Add [diff] mechanism

pull/1/head
Leigh Morresi 4 years ago
parent 43c7ccb3fe
commit 81534d9367

@ -10,7 +10,9 @@
# @todo on change detected, config for calling some API # @todo on change detected, config for calling some API
# @todo make tables responsive! # @todo make tables responsive!
# @todo fetch title into json # @todo fetch title into json
# https://distill.io/features
# proxy per check
#i
import json import json
import eventlet import eventlet
import eventlet.wsgi import eventlet.wsgi
@ -34,6 +36,7 @@ ticker_thread = None
datastore = store.ChangeDetectionStore() datastore = store.ChangeDetectionStore()
messages = [] messages = []
extra_stylesheets = []
running_update_threads = {} running_update_threads = {}
app = Flask(__name__, static_url_path='/static') app = Flask(__name__, static_url_path='/static')
@ -149,6 +152,31 @@ def import_page():
return output return output
@app.route("/diff/<string:uuid>", methods=['GET'])
def diff_history_page(uuid):
global messages
global extra_stylesheets
extra_stylesheets.append('/static/css/diff.css')
watch = datastore.data['watching'][uuid]
dates = list(watch['history'].keys())
dates = [int(i) for i in dates]
dates.sort(reverse=True)
left_file_contents = right_file_contents = ""
l_file = watch['history'][str(dates[-1])]
with open(l_file, 'r') as f:
left_file_contents = f.read()
r_file = watch['history'][str(dates[-2])]
with open(r_file, 'r') as f:
right_file_contents = f.read()
output = render_template("diff.html", watch_a=watch, messages=messages, left=left_file_contents,
right=right_file_contents, extra_stylesheets=extra_stylesheets)
return output
@app.route("/favicon.ico", methods=['GET']) @app.route("/favicon.ico", methods=['GET'])
def favicon(): def favicon():
return send_from_directory("/app/static/images", filename="favicon.ico") return send_from_directory("/app/static/images", filename="favicon.ico")

@ -127,7 +127,7 @@ class perform_site_check(Thread):
# attempt because 'self.current_md5 != fetched_md5' (current_md5 will be None when not run) # attempt because 'self.current_md5 != fetched_md5' (current_md5 will be None when not run)
# need to learn more about attr/setters/getters # need to learn more about attr/setters/getters
history = self.datastore.get_val(self.uuid, 'history') history = self.datastore.get_val(self.uuid, 'history')
history.update(dict([(self.timestamp, output_filepath)])) history.update(dict([(str(self.timestamp), output_filepath)]))
self.datastore.update_watch(self.uuid, 'history', history) self.datastore.update_watch(self.uuid, 'history', history)
self.datastore.update_watch(self.uuid, 'last_checked', int(time.time())) self.datastore.update_watch(self.uuid, 'last_checked', int(time.time()))

@ -0,0 +1,61 @@
table {
table-layout: fixed;
width: 100%;
}
td {
width: 33%;
padding: 3px 4px;
border: 1px solid transparent;
vertical-align: top;
font: 1em monospace;
text-align: left;
white-space: pre-wrap;
}
h1 {
display: inline;
font-size: 100%;
}
del {
text-decoration: none;
color: #b30000;
background: #fadad7;
}
ins {
background: #eaf2c2;
color: #406619;
text-decoration: none;
}
#result {
white-space: pre-wrap;
}
#settings {
line-height: 2em;
}
#settings label {
margin-left: 1em;
}
.source {
position: absolute;
right: 1%;
top: .2em;
}
@-moz-document url-prefix() {
body {
height: 99%; /* Hide scroll bar in Firefox */
}
}
#diff-ui {
background: #fff;
padding: 2em;
margin: 1em;
border-radius: 5px;
font-size: 9px;
}

@ -48,6 +48,7 @@ section.content {
} }
.watch-tag-list { .watch-tag-list {
color: #e70069; color: #e70069;
white-space: nowrap;
} }
.box { .box {

File diff suppressed because it is too large Load Diff

@ -12,6 +12,7 @@ class ChangeDetectionStore:
self.needs_write = False self.needs_write = False
self.__data = { self.__data = {
'note' : "Hello! If you change this file manually, please be sure to restart your changedetection.io instance!",
'watching': {}, 'watching': {},
'settings': { 'settings': {
'headers': { 'headers': {
@ -126,7 +127,6 @@ class ChangeDetectionStore:
def sync_to_json(self): def sync_to_json(self):
print ("Saving index....")
with open('/datastore/url-watches.json', 'w') as json_file: with open('/datastore/url-watches.json', 'w') as json_file:
json.dump(self.data, json_file, indent=4) json.dump(self.data, json_file, indent=4)
self.needs_write = False self.needs_write = False

@ -7,6 +7,11 @@
<title>Change Detection</title> <title>Change Detection</title>
<link rel="stylesheet" href="/static/css/pure-min.css"> <link rel="stylesheet" href="/static/css/pure-min.css">
<link rel="stylesheet" href="/static/css/styles.css"> <link rel="stylesheet" href="/static/css/styles.css">
{% if extra_stylesheets %}
{% for m in extra_stylesheets %}
<link rel="stylesheet" href="{{ m }}">
{% endfor %}
{% endif %}
</head> </head>
<body> <body>

@ -0,0 +1,98 @@
{% extends 'base.html' %}
{% block content %}
<div id="diff-ui">
<del>Removed text</del>
<ins>Inserted Text</ins>
<div id="settings">
<h3>Diff</h3>
<label><input type="radio" name="diff_type" value="diffChars"> Chars</label>
<label><input type="radio" name="diff_type" value="diffWords" > Words</label>
<label><input type="radio" name="diff_type" value="diffLines" checked=""> Lines</label>
</div>
<table>
<tbody>
<tr>
<!-- just proof of concept copied straight from github.com/kpdecker/jsdiff -->
<td id="a" style="display: none;">{{left}}</td>
<td id="b" style="display: none;">{{right}}</td>
<td>
<pre id="result"></pre>
</td>
</tr>
</tbody>
</table>
Diff algorithm from the amazing <a href="https://github.com/kpdecker/jsdiff" >github.com/kpdecker/jsdiff</a>
</div>
<script src="/static/js/diff.js"></script>
<script defer="">
var a = document.getElementById('a');
var b = document.getElementById('b');
var result = document.getElementById('result');
function changed() {
var diff = JsDiff[window.diffType](a.textContent, b.textContent);
var fragment = document.createDocumentFragment();
for (var i=0; i < diff.length; i++) {
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.appendChild(document.createTextNode(diff[i].value));
} else if (diff[i].added) {
node = document.createElement('ins');
node.appendChild(document.createTextNode(diff[i].value));
} else {
node = document.createTextNode(diff[i].value);
}
fragment.appendChild(node);
}
result.textContent = '';
result.appendChild(fragment);
}
window.onload = function() {
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;
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();
}
}
</script>
{% endblock %}

@ -15,7 +15,7 @@
white-space: pre; white-space: pre;
overflow-wrap: normal; overflow-wrap: normal;
overflow-x: scroll;" rows="25">{{ remaining }}</textarea> overflow-x: scroll;" rows="25">{{ remaining }}</textarea>
</fieldset> </fieldset>
<button type="submit" class="pure-button pure-input-1-2 pure-button-primary">Import</button> <button type="submit" class="pure-button pure-input-1-2 pure-button-primary">Import</button>
</form> </form>

@ -26,6 +26,7 @@
</div> </div>
<div id="watch-table-wrapper"> <div id="watch-table-wrapper">
<table class="pure-table pure-table-striped watch-table"> <table class="pure-table pure-table-striped watch-table">
<thead> <thead>
<tr> <tr>
@ -56,6 +57,9 @@
<td>{{watch.last_changed|format_timestamp_timeago}}</td> <td>{{watch.last_changed|format_timestamp_timeago}}</td>
<td><a href="/api/checknow?uuid={{ watch.uuid}}" class="pure-button button-small pure-button-primary">Recheck</a> <td><a href="/api/checknow?uuid={{ watch.uuid}}" class="pure-button button-small pure-button-primary">Recheck</a>
<a href="/edit?uuid={{ watch.uuid}}" class="pure-button button-small pure-button-primary">Edit</a> <a href="/edit?uuid={{ watch.uuid}}" class="pure-button button-small pure-button-primary">Edit</a>
{% if watch.history|length >= 2 %}
<a href="/diff/{{ watch.uuid}}" class="pure-button button-small pure-button-primary">Diff</a>
{% endif %}
</td> </td>
</tr> </tr>
{% endfor %} {% endfor %}

Loading…
Cancel
Save