Skip to content

Commit

Permalink
UI - Ability to highlight text and have it offered as a ignore-text o…
Browse files Browse the repository at this point in the history
…ption, really nice easy way to set ignores on changing text (#1746)
  • Loading branch information
dgtlmoon authored Aug 24, 2023
1 parent 087d21c commit 52df3b1
Show file tree
Hide file tree
Showing 7 changed files with 174 additions and 7 deletions.
21 changes: 21 additions & 0 deletions changedetectionio/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -1430,6 +1430,27 @@ def form_share_put_watch():
# paste in etc
return redirect(url_for('index'))

@app.route("/highlight_submit_ignore_url", methods=['POST'])
def highlight_submit_ignore_url():
import re
mode = request.form.get('mode')
selection = request.form.get('selection')

uuid = request.args.get('uuid','')
if datastore.data["watching"].get(uuid):
if mode == 'exact':
for l in selection.splitlines():
datastore.data["watching"][uuid]['ignore_text'].append(l.strip())
elif mode == 'digit-regex':
for l in selection.splitlines():
# Replace any series of numbers with a regex
s = re.escape(l.strip())
s = re.sub(r'[0-9]+', r'\\d+', s)
datastore.data["watching"][uuid]['ignore_text'].append('/' + s + '/')

return f"<a href={url_for('preview_page', uuid=uuid)}>Click to preview</a>"


import changedetectionio.blueprint.browser_steps as browser_steps
app.register_blueprint(browser_steps.construct_blueprint(datastore), url_prefix='/browser-steps')

Expand Down
73 changes: 71 additions & 2 deletions changedetectionio/static/js/diff-overview.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,13 @@
$(document).ready(function () {
var csrftoken = $('input[name=csrf_token]').val();
$.ajaxSetup({
beforeSend: function (xhr, settings) {
if (!/^(GET|HEAD|OPTIONS|TRACE)$/i.test(settings.type) && !this.crossDomain) {
xhr.setRequestHeader("X-CSRFToken", csrftoken)
}
}
})

// Load it when the #screenshot tab is in use, so we dont give a slow experience when waiting for the text diff to load
window.addEventListener('hashchange', function (e) {
toggle(location.hash);
Expand All @@ -15,11 +24,71 @@ $(document).ready(function () {
$("#settings").hide();
} else if (hash_name === '#extract') {
$("#settings").hide();
} else {
$("#settings").show();
}
}

const article = $('.highlightable-filter')[0];

// We could also add the 'touchend' event for touch devices, but since
// most iOS/Android browsers already show a dialog when you select
// text (often with a Share option) we'll skip that
article.addEventListener('mouseup', dragTextHandler, false);
article.addEventListener('mousedown', clean, false);

function clean(event) {
$("#highlightSnippet").remove();
}


function dragTextHandler(event) {
console.log('mouseupped');

// Check if any text was selected
if (window.getSelection().toString().length > 0) {

// Find out how much (if any) user has scrolled
var scrollTop = (window.pageYOffset !== undefined) ? window.pageYOffset : (document.documentElement || document.body.parentNode || document.body).scrollTop;

// Get cursor position
const posX = event.clientX;
const posY = event.clientY + 20 + scrollTop;

// Append HTML to the body, create the "Tweet Selection" dialog
document.body.insertAdjacentHTML('beforeend', '<div id="highlightSnippet" style="position: absolute; top: ' + posY + 'px; left: ' + posX + 'px;"><div class="pure-form-message-inline" style="font-size: 70%">Ignore any change on any line which contains the selected text.</div><br><a data-mode="exact" href="javascript:void(0);" class="pure-button button-secondary button-xsmall">Ignore exact text</a>&nbsp;</div>');

if (/\d/.test(window.getSelection().toString())) {
// Offer regex replacement
document.getElementById("highlightSnippet").insertAdjacentHTML('beforeend', '<a data-mode="digit-regex" href="javascript:void(0);" class="pure-button button-secondary button-xsmall">Ignore text including number changes</a>');
}

$('#highlightSnippet a').bind('click', function (e) {
if(!window.getSelection().toString().trim().length) {
alert('Oops no text selected!');
return;
}

$.ajax({
type: "POST",
url: highlight_submit_ignore_url,
data: {'mode': $(this).data('mode'), 'selection': window.getSelection().toString()},
statusCode: {
400: function () {
// More than likely the CSRF token was lost when the server restarted
alert("There was a problem processing the request, please reload the page.");
}
}
}).done(function (data) {
$("#highlightSnippet").append(data)
}).fail(function (data) {
console.log(data);
alert('There was an error communicating with the server.');
});
});

else {
$("#settings").show();
}
}


});
7 changes: 7 additions & 0 deletions changedetectionio/static/styles/diff.css
Original file line number Diff line number Diff line change
Expand Up @@ -218,3 +218,10 @@ td#diff-col div {
text-align: center; }
.tab-pane-inner#screenshot img {
max-width: 99%; }

#highlightSnippet {
background: var(--color-background);
padding: 1em;
border-radius: 5px;
background: var(--color-background);
box-shadow: 1px 1px 4px var(--color-shadow-jump); }
8 changes: 8 additions & 0 deletions changedetectionio/static/styles/scss/diff.scss
Original file line number Diff line number Diff line change
Expand Up @@ -119,3 +119,11 @@ td#diff-col div {
max-width: 99%;
}
}

#highlightSnippet {
background: var(--color-background);
padding: 1em;
border-radius: 5px;
background: var(--color-background);
box-shadow: 1px 1px 4px var(--color-shadow-jump);
}
7 changes: 5 additions & 2 deletions changedetectionio/templates/diff.html
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@
{% if last_error_screenshot %}
const error_screenshot_url="{{url_for('static_content', group='screenshot', filename=uuid, error_screenshot=1) }}";
{% endif %}

const highlight_submit_ignore_url="{{url_for('highlight_submit_ignore_url', uuid=uuid)}}";

</script>
<script src="{{url_for('static_content', group='js', filename='diff-overview.js')}}" defer></script>

Expand Down Expand Up @@ -76,7 +79,7 @@ <h1>Differences</h1>
</div>

<div class="tab-pane-inner" id="text">
<div class="tip">Pro-tip: Use <strong>show current snapshot</strong> tab to visualise what will be ignored.</div>
<div class="tip">Pro-tip: Use <strong>show current snapshot</strong> tab to visualise what will be ignored, highlight text to add to ignore filters</div>

{% if password_enabled_and_share_is_off %}
<div class="tip">Pro-tip: You can enable <strong>"share access when password is enabled"</strong> from settings</div>
Expand All @@ -91,7 +94,7 @@ <h1>Differences</h1>
<td id="a" style="display: none;">{{previous}}</td>
<td id="b" style="display: none;">{{newest}}</td>
<td id="diff-col">
<span id="result"></span>
<span id="result" class="highlightable-filter"></span>
</td>
</tr>
</tbody>
Expand Down
8 changes: 5 additions & 3 deletions changedetectionio/templates/preview.html
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
{% if last_error_screenshot %}
const error_screenshot_url="{{url_for('static_content', group='screenshot', filename=uuid, error_screenshot=1) }}";
{% endif %}
const highlight_submit_ignore_url="{{url_for('highlight_submit_ignore_url', uuid=uuid)}}";
</script>
<script src="{{url_for('static_content', group='js', filename='diff-overview.js')}}" defer></script>

Expand All @@ -20,7 +21,7 @@
{% endif %}
</ul>
</div>

<form><input type="hidden" name="csrf_token" value="{{ csrf_token() }}"></form>
<div id="diff-ui">
<div class="tab-pane-inner" id="error-text">
<div class="snapshot-age error">{{watch.error_text_ctime|format_seconds_ago}} seconds ago</div>
Expand All @@ -36,11 +37,12 @@

<div class="tab-pane-inner" id="text">
<div class="snapshot-age">{{watch.snapshot_text_ctime|format_timestamp_timeago}}</div>
<span class="ignored">Grey lines are ignored</span> <span class="triggered">Blue lines are triggers</span>
<span class="ignored">Grey lines are ignored</span> <span class="triggered">Blue lines are triggers</span> <span class="tip"><strong>Pro-tip</strong>: Highlight text to add to ignore filters</span>

<table>
<tbody>
<tr>
<td id="diff-col">
<td id="diff-col" class="highlightable-filter">
{% for row in content %}
<div class="{{row.classes}}">{{row.line}}</div>
{% endfor %}
Expand Down
57 changes: 57 additions & 0 deletions changedetectionio/tests/test_ignorehighlighter.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
#!/usr/bin/python3

import time
from flask import url_for
from .util import live_server_setup, wait_for_all_checks
from changedetectionio import html_tools
from . util import extract_UUID_from_client

def set_original_ignore_response():
test_return_data = """<html>
<body>
Some initial text<br>
<p>Which is across multiple lines</p>
<br>
So let's see what happens. <br>
<p>oh yeah 456</p>
</body>
</html>
"""

with open("test-datastore/endpoint-content.txt", "w") as f:
f.write(test_return_data)


def test_highlight_ignore(client, live_server):
live_server_setup(live_server)
set_original_ignore_response()
test_url = url_for('test_endpoint', _external=True)
res = client.post(
url_for("import_page"),
data={"urls": test_url},
follow_redirects=True
)
assert b"1 Imported" in res.data

# Give the thread time to pick it up
wait_for_all_checks(client)
uuid = extract_UUID_from_client(client)
# use the highlighter endpoint
res = client.post(
url_for("highlight_submit_ignore_url", uuid=uuid),
data={"mode": 'digit-regex', 'selection': 'oh yeah 123'},
follow_redirects=True
)

res = client.get(url_for("edit_page", uuid=uuid))

# should be a regex now
assert b'/oh\ yeah\ \d+/' in res.data

# Should return a link
assert b'href' in res.data

# And it should register in the preview page
res = client.get(url_for("preview_page", uuid=uuid))
assert b'<div class="ignored">oh yeah 456' in res.data

0 comments on commit 52df3b1

Please sign in to comment.