From b9e57453316969a2d03c31f3da899a091a5eadb7 Mon Sep 17 00:00:00 2001 From: iou1name Date: Thu, 13 Jun 2019 10:46:59 -0400 Subject: [PATCH] added edit_field functionality --- juice.py | 57 ++++++++++++++++++++++++++++--- static/fontawesome-webfont.woff2 | Bin 0 -> 2596 bytes static/juice.css | 36 ++++++++++++++++--- static/juice.js | 54 ++++++++++++++++++++++++++++- templates/index.html | 8 ++--- 5 files changed, 142 insertions(+), 13 deletions(-) create mode 100644 static/fontawesome-webfont.woff2 diff --git a/juice.py b/juice.py index 0852125..fd29590 100644 --- a/juice.py +++ b/juice.py @@ -7,7 +7,7 @@ import copy import json import requests -from flask import Flask, render_template, request, abort +from flask import Flask, render_template, request, abort, jsonify class RelayDevice: @@ -55,7 +55,7 @@ class RelayDevice: ).groups()[0] == 'High' sub_dev.state = state - return json.dumps({sub_dev_id: state}) + return json.dumps({'ok': True, sub_dev_id: state}) def from_dict(self, data): """ @@ -151,13 +151,62 @@ def toggle(): if device.id == device_id: break else: - abort(404) + return make_error(404, "device_id not found") res = device.toggle(sub_dev_id) if not res: - abort(404) + return make_error(404, "sub_dev_id not found") save_network() return res +@app.route('/edit') +def edit(): + """ + Edits the text of a particular field. + """ + device_id = request.args.get('device_id') + sub_dev_id = request.args.get('sub_dev_id') + field = request.args.get('field') + value = request.args.get('value') + + for device in sum(network.values(), []): + if device.id == device_id: + break + else: + return make_error(404, "device_id not found") + + if sub_dev_id: + for sub_dev in sum(device.sub_devices.values(), []): + if sub_dev.id == sub_dev_id: + break + else: + return make_error(404, "sub_dev_id not found") + if hasattr(sub_dev, field): + setattr(sub_dev, field, value) + else: + return make_error(404, "sub_device field not found") + else: + if hasattr(device, field): + setattr(device, field, value) + else: + return make_error(404, "device field not found") + + data = { + 'ok': True, + 'field': field, + 'value': value + } + save_network() + return json.dumps(data) + + +def make_error(code, message): + """ + Returns a JSON error. + """ + res = jsonify(ok=False, status=code, message=message) + res.status_code = code + return res + if __name__ == '__main__': app.run(host='0.0.0.0', port=5300) diff --git a/static/fontawesome-webfont.woff2 b/static/fontawesome-webfont.woff2 new file mode 100644 index 0000000000000000000000000000000000000000..d2a3f9905d29978e97b80c7c54a8ecf9e4123886 GIT binary patch literal 2596 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 GB>`XooatWx literal 0 HcmV?d00001 diff --git a/static/juice.css b/static/juice.css index 4ada69c..637c48f 100644 --- a/static/juice.css +++ b/static/juice.css @@ -2,15 +2,26 @@ body { padding: 5%; display: flex; justify-content: center; + font-family: Helvetica,sans-serif; + background-color: lightblue; } .device { - border: 1px solid #ccc; - padding: 3%; - margin: 3%; + border: 2px solid darkgray; + border-radius: 0.5em; + padding: 3em; + margin: 3em; display: flex; flex-direction: column; align-items: center; + background-color: whitesmoke; +} + + +.ip_address { + font-size: 0.8em; + color: darkgray; + margin: 0.2em; } .sub_devices { @@ -18,7 +29,8 @@ body { } .sub_device { - border: 1px solid #ccc; + border: 2px solid darkgray; + border-radius: 0.5em; padding: 1em; margin: 1em; display: flex; @@ -42,3 +54,19 @@ path { .off { stroke: black; } + +@font-face { + font-family: FontAwesome; + src: url("/static/fontawesome-webfont.woff2"); +} + +.edit, .save { + font-family: FontAwesome; + font-size: 0.8em; + color: dimgrey; +} + +.edit:hover, .save:hover { + color: red; + cursor: pointer; +} diff --git a/static/juice.js b/static/juice.js index 5f98600..41995a9 100644 --- a/static/juice.js +++ b/static/juice.js @@ -9,10 +9,10 @@ function toggle_outlet(svg) { .join('&'); fetch(window.location.href + 'toggle?' + query) .then(function(response) { - if (!response.ok) { throw new Error('HTTP error, status = ' + response.status); } return response.json(); }) .then(function(json) { + if (!json.ok) { throw new Error('HTTP error, status = ' + json.status + ', message = ' + json.message); } if (json[sub_dev.id]) { svg.classList.remove('off'); svg.classList.add('on'); @@ -22,3 +22,55 @@ function toggle_outlet(svg) { } }); } + +function edit_field(field) { + let value = field.firstElementChild.innerText; + let input = document.createElement('input'); + input.value = value; + field.firstElementChild.replaceWith(input); + + let save = document.createElement('span'); + save.innerHTML = ''; + save.className = 'save'; + save.setAttribute('onclick', 'save_field(this.parentElement)'); + field.children[1].replaceWith(save); +} + +function save_field(field) { + let value = field.firstElementChild.value; + let device_id = field.parentElement.id; + let sub_dev_id; + if (field.parentElement.className.includes('sub_device')) { + sub_dev_id = device_id; + device_id = field.parentElement.parentElement.parentElement.id; + } else { + sub_dev_id = ''; + } + let params = { + device_id: device_id, + sub_dev_id: sub_dev_id, + field: field.className, + value: value + }; + let query = Object.keys(params) + .map(k => encodeURIComponent(k) + '=' + encodeURIComponent(params[k])) + .join('&'); + + fetch(window.location.href + 'edit?' + query) + .then(function(response) { + return response.json(); + }) + .then(function(json) { + if (!json.ok) { throw new Error('HTTP error, status = ' + json.status + ', message = ' + json.message); } + let span = document.createElement('span'); + span.innerText = json['value']; + span.className = 'field_value'; + field.firstElementChild.replaceWith(span); + + let edit = document.createElement('span'); + edit.innerHTML = ''; + edit.className = 'edit'; + edit.setAttribute('onclick', 'edit_field(this.parentElement)'); + field.children[1].replaceWith(edit); + }); +} diff --git a/templates/index.html b/templates/index.html index ea076b3..41272e4 100644 --- a/templates/index.html +++ b/templates/index.html @@ -10,9 +10,9 @@ {% for device in devices %}
{{ device.id }}
-
{{ device.description }}
-
{{ device.location }}
-
{{ device.ip_address }}
+
{{ device.description }}
+
{{ device.location }}
+
{{ device.ip_address }}
{% for sub_dev_type, sub_devs in device.sub_devices.items() %} {% for sub_dev in sub_devs %} @@ -24,7 +24,7 @@ -
{{ sub_dev.description }}
+
{{ sub_dev.description }}
{% endfor %} {% endfor %}