UI - Ability to select between any difference date ( from / to ) and minor UI cleanup for differences page (#1855)

1857-edit-page-title
dgtlmoon 1 year ago committed by GitHub
parent 3e2b55a46f
commit da421fe110
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -912,21 +912,29 @@ def changedetection_app(config=None, datastore_o=None):
# Read as binary and force decode as UTF-8 # Read as binary and force decode as UTF-8
# Windows may fail decode in python if we just use 'r' mode (chardet decode exception) # Windows may fail decode in python if we just use 'r' mode (chardet decode exception)
from_version = request.args.get('from_version')
from_version_index = -2 # second newest
if from_version and from_version in dates:
from_version_index = dates.index(from_version)
else:
from_version = dates[from_version_index]
try: try:
newest_version_file_contents = watch.get_history_snapshot(dates[-1]) from_version_file_contents = watch.get_history_snapshot(dates[from_version_index])
except Exception as e: except Exception as e:
newest_version_file_contents = "Unable to read {}.\n".format(dates[-1]) from_version_file_contents = "Unable to read to-version at index{}.\n".format(dates[from_version_index])
previous_version = request.args.get('previous_version') to_version = request.args.get('to_version')
previous_timestamp = dates[-2] to_version_index = -1
if previous_version: if to_version and to_version in dates:
previous_timestamp = previous_version to_version_index = dates.index(to_version)
else:
to_version = dates[to_version_index]
try: try:
previous_version_file_contents = watch.get_history_snapshot(previous_timestamp) to_version_file_contents = watch.get_history_snapshot(dates[to_version_index])
except Exception as e: except Exception as e:
previous_version_file_contents = "Unable to read {}.\n".format(previous_timestamp) to_version_file_contents = "Unable to read to-version at index{}.\n".format(dates[to_version_index])
screenshot_url = watch.get_screenshot() screenshot_url = watch.get_screenshot()
@ -942,7 +950,8 @@ def changedetection_app(config=None, datastore_o=None):
output = render_template("diff.html", output = render_template("diff.html",
current_diff_url=watch['url'], current_diff_url=watch['url'],
current_previous_version=str(previous_version), from_version=str(from_version),
to_version=str(to_version),
extra_stylesheets=extra_stylesheets, extra_stylesheets=extra_stylesheets,
extra_title=" - Diff - {}".format(watch['title'] if watch['title'] else watch['url']), extra_title=" - Diff - {}".format(watch['title'] if watch['title'] else watch['url']),
extract_form=extract_form, extract_form=extract_form,
@ -951,13 +960,14 @@ def changedetection_app(config=None, datastore_o=None):
last_error_screenshot=watch.get_error_snapshot(), last_error_screenshot=watch.get_error_snapshot(),
last_error_text=watch.get_error_text(), last_error_text=watch.get_error_text(),
left_sticky=True, left_sticky=True,
newest=newest_version_file_contents, newest=to_version_file_contents,
newest_version_timestamp=dates[-1], newest_version_timestamp=dates[-1],
password_enabled_and_share_is_off=password_enabled_and_share_is_off, password_enabled_and_share_is_off=password_enabled_and_share_is_off,
previous=previous_version_file_contents, from_version_file_contents=from_version_file_contents,
to_version_file_contents=to_version_file_contents,
screenshot=screenshot_url, screenshot=screenshot_url,
uuid=uuid, uuid=uuid,
versions=dates[:-1], # All except current/last versions=dates, # All except current/last
watch_a=watch watch_a=watch
) )

@ -1,110 +1,105 @@
var a = document.getElementById("a"); $(document).ready(function () {
var b = document.getElementById("b"); var a = document.getElementById("a");
var result = document.getElementById("result"); var b = document.getElementById("b");
var result = document.getElementById("result");
function changed() { var inputs = document.getElementsByClassName("change");
// https://github.com/kpdecker/jsdiff/issues/389 inputs.current = 0;
// I would love to use `{ignoreWhitespace: true}` here but it breaks the formatting
options = { function changed() {
ignoreWhitespace: document.getElementById("ignoreWhitespace").checked, // https://github.com/kpdecker/jsdiff/issues/389
}; // I would love to use `{ignoreWhitespace: true}` here but it breaks the formatting
options = {
var diff = Diff[window.diffType](a.textContent, b.textContent, options); ignoreWhitespace: document.getElementById("ignoreWhitespace").checked,
var fragment = document.createDocumentFragment(); };
for (var i = 0; i < diff.length; i++) {
if (diff[i].added && diff[i + 1] && diff[i + 1].removed) { var diff = Diff[window.diffType](a.textContent, b.textContent, options);
var swap = diff[i]; var fragment = document.createDocumentFragment();
diff[i] = diff[i + 1]; for (var i = 0; i < diff.length; i++) {
diff[i + 1] = swap; if (diff[i].added && diff[i + 1] && diff[i + 1].removed) {
var swap = diff[i];
diff[i] = diff[i + 1];
diff[i + 1] = swap;
}
var node;
if (diff[i].removed) {
node = document.createElement("del");
node.classList.add("change");
const wrapper = node.appendChild(document.createElement("span"));
wrapper.appendChild(document.createTextNode(diff[i].value));
} else if (diff[i].added) {
node = document.createElement("ins");
node.classList.add("change");
const wrapper = node.appendChild(document.createElement("span"));
wrapper.appendChild(document.createTextNode(diff[i].value));
} else {
node = document.createTextNode(diff[i].value);
}
fragment.appendChild(node);
}
result.textContent = "";
result.appendChild(fragment);
// Jump at start
inputs.current = 0;
next_diff();
} }
var node; $('.needs-localtime').each(function () {
if (diff[i].removed) { for (var option of this.options) {
node = document.createElement("del"); var dateObject = new Date(option.value * 1000);
node.classList.add("change"); option.label = dateObject.toLocaleString(undefined, {dateStyle: "full", timeStyle: "medium"});
const wrapper = node.appendChild(document.createElement("span")); }
wrapper.appendChild(document.createTextNode(diff[i].value)); })
} else if (diff[i].added) { onDiffTypeChange(
node = document.createElement("ins"); document.querySelector('#settings [name="diff_type"]:checked'),
node.classList.add("change"); );
const wrapper = node.appendChild(document.createElement("span")); changed();
wrapper.appendChild(document.createTextNode(diff[i].value));
a.onpaste = a.onchange = b.onpaste = b.onchange = changed;
if ("oninput" in a) {
a.oninput = b.oninput = changed;
} else { } else {
node = document.createTextNode(diff[i].value); a.onkeyup = b.onkeyup = changed;
} }
fragment.appendChild(node);
} function onDiffTypeChange(radio) {
window.diffType = radio.value;
result.textContent = ""; // Not necessary
result.appendChild(fragment); // document.title = "Diff " + radio.value.slice(4);
// Jump at start
inputs.current = 0;
next_diff();
}
window.onload = function () {
/* Convert what is options from UTC time.time() to local browser time */
var diffList = document.getElementById("diff-version");
if (typeof diffList != "undefined" && diffList != null) {
for (var option of diffList.options) {
var dateObject = new Date(option.value * 1000);
option.label = dateObject.toLocaleString();
} }
}
/* Set current version date as local time in the browser also */
var current_v = document.getElementById("current-v-date");
var dateObject = new Date(newest_version_timestamp * 1000);
current_v.innerHTML = dateObject.toLocaleString();
onDiffTypeChange(
document.querySelector('#settings [name="diff_type"]:checked'),
);
changed();
};
a.onpaste = a.onchange = b.onpaste = b.onchange = changed;
if ("oninput" in a) {
a.oninput = b.oninput = changed;
} else {
a.onkeyup = b.onkeyup = changed;
}
function onDiffTypeChange(radio) {
window.diffType = radio.value;
// Not necessary
// document.title = "Diff " + radio.value.slice(4);
}
var radio = document.getElementsByName("diff_type");
for (var i = 0; i < radio.length; i++) {
radio[i].onchange = function (e) {
onDiffTypeChange(e.target);
changed();
};
}
document.getElementById("ignoreWhitespace").onchange = function (e) { var radio = document.getElementsByName("diff_type");
changed(); for (var i = 0; i < radio.length; i++) {
}; radio[i].onchange = function (e) {
onDiffTypeChange(e.target);
changed();
};
}
var inputs = document.getElementsByClassName("change"); document.getElementById("ignoreWhitespace").onchange = function (e) {
inputs.current = 0; changed();
};
function next_diff() {
var element = inputs[inputs.current];
var headerOffset = 80;
var elementPosition = element.getBoundingClientRect().top;
var offsetPosition = elementPosition - headerOffset + window.scrollY;
window.scrollTo({ function next_diff() {
top: offsetPosition, var element = inputs[inputs.current];
behavior: "smooth", var headerOffset = 80;
}); var elementPosition = element.getBoundingClientRect().top;
var offsetPosition = elementPosition - headerOffset + window.scrollY;
window.scrollTo({
top: offsetPosition,
behavior: "smooth",
});
inputs.current++;
if (inputs.current >= inputs.length) {
inputs.current = 0;
}
}
});
inputs.current++;
if (inputs.current >= inputs.length) {
inputs.current = 0;
}
}

@ -187,6 +187,10 @@ ins {
padding: 0.5em; } padding: 0.5em; }
#settings ins { #settings ins {
padding: 0.5em; } padding: 0.5em; }
#settings option:checked {
font-weight: bold; }
#settings [type=radio], #settings [type=checkbox] {
vertical-align: middle; }
.source { .source {
position: absolute; position: absolute;

@ -77,6 +77,13 @@ ins {
ins { ins {
padding: 0.5em; padding: 0.5em;
} }
option:checked {
font-weight: bold;
}
[type=radio],[type=checkbox] {
vertical-align: middle;
}
} }
.source { .source {

@ -13,10 +13,31 @@
<script src="{{url_for('static_content', group='js', filename='diff-overview.js')}}" defer></script> <script src="{{url_for('static_content', group='js', filename='diff-overview.js')}}" defer></script>
<div id="settings"> <div id="settings">
<h1>Differences</h1>
<form class="pure-form " action="" method="GET"> <form class="pure-form " action="" method="GET">
<fieldset> <fieldset>
{% if versions|length >= 1 %}
<strong>Compare</strong>
<del class="change"><span>from</span></del>
<select id="diff-version" name="from_version" class="needs-localtime">
{% for version in versions|reverse %}
<option value="{{ version }}" {% if version== from_version %} selected="" {% endif %}>
{{ version }}
</option>
{% endfor %}
</select>
<ins class="change"><span>to</span></ins>
<select id="current-version" name="to_version" class="needs-localtime">
{% for version in versions|reverse %}
<option value="{{ version }}" {% if version== to_version %} selected="" {% endif %}>
{{ version }}
</option>
{% endfor %}
</select>
<button type="submit" class="pure-button pure-button-primary">Go</button>
{% endif %}
</fieldset>
<fieldset>
<strong>Style</strong>
<label for="diffWords" class="pure-checkbox"> <label for="diffWords" class="pure-checkbox">
<input type="radio" name="diff_type" id="diffWords" value="diffWords"> Words</label> <input type="radio" name="diff_type" id="diffWords" value="diffWords"> Words</label>
<label for="diffLines" class="pure-checkbox"> <label for="diffLines" class="pure-checkbox">
@ -26,28 +47,16 @@
<input type="radio" name="diff_type" id="diffChars" value="diffChars"> Chars</label> <input type="radio" name="diff_type" id="diffChars" value="diffChars"> Chars</label>
<!-- @todo - when mimetype is JSON, select this by default? --> <!-- @todo - when mimetype is JSON, select this by default? -->
<label for="diffJson" class="pure-checkbox"> <label for="diffJson" class="pure-checkbox">
<input type="radio" name="diff_type" id="diffJson" value="diffJson" > JSON</label> <input type="radio" name="diff_type" id="diffJson" value="diffJson"> JSON</label>
{% if versions|length >= 1 %} <span>
<label for="diff-version">Compare newest (<span id="current-v-date"></span>) with</label>
<select id="diff-version" name="previous_version">
{% for version in versions|reverse %}
<option value="{{version}}" {% if version== current_previous_version %} selected="" {% endif %}>
{{version}}
</option>
{% endfor %}
</select>
<button type="submit" class="pure-button pure-button-primary">Go</button>
{% endif %}
</fieldset>
</form>
<del>Removed text</del>
<ins>Inserted Text</ins>
<span>
<!-- https://github.com/kpdecker/jsdiff/issues/389 ? --> <!-- https://github.com/kpdecker/jsdiff/issues/389 ? -->
<label for="ignoreWhitespace" class="pure-checkbox" id="label-diff-ignorewhitespace"> <label for="ignoreWhitespace" class="pure-checkbox" id="label-diff-ignorewhitespace">
<input type="checkbox" id="ignoreWhitespace" name="ignoreWhitespace" > Ignore Whitespace</label> <input type="checkbox" id="ignoreWhitespace" name="ignoreWhitespace"> Ignore Whitespace</label>
</span> </span>
</fieldset>
</form>
</div> </div>
<div id="diff-jump"> <div id="diff-jump">
@ -91,8 +100,8 @@
<tbody> <tbody>
<tr> <tr>
<!-- just proof of concept copied straight from github.com/kpdecker/jsdiff --> <!-- just proof of concept copied straight from github.com/kpdecker/jsdiff -->
<td id="a" style="display: none;">{{previous}}</td> <td id="a" style="display: none;">{{from_version_file_contents}}</td>
<td id="b" style="display: none;">{{newest}}</td> <td id="b" style="display: none;">{{to_version_file_contents}}</td>
<td id="diff-col"> <td id="diff-col">
<span id="result" class="highlightable-filter"></span> <span id="result" class="highlightable-filter"></span>
</td> </td>

@ -89,7 +89,7 @@ def test_check_basic_change_detection_functionality(client, live_server):
# Following the 'diff' link, it should no longer display as 'unviewed' even after we recheck it a few times # Following the 'diff' link, it should no longer display as 'unviewed' even after we recheck it a few times
res = client.get(url_for("diff_history_page", uuid="first")) res = client.get(url_for("diff_history_page", uuid="first"))
assert b'Compare newest' in res.data assert b'selected=""' in res.data, "Confirm diff history page loaded"
# Check the [preview] pulls the right one # Check the [preview] pulls the right one
res = client.get( res = client.get(

Loading…
Cancel
Save