summaryrefslogtreecommitdiffstats
path: root/ogcp
diff options
context:
space:
mode:
authorDaniel GarcĂ­a Moreno <danigm@soleta.eu>2021-07-07 10:27:59 +0200
committerOpenGnSys Support Team <soporte-og@soleta.eu>2021-07-07 11:27:28 +0200
commit4e519590af6484cc05a91f102a0a3765408b5e72 (patch)
treefcd40d47e79beb94f1e1602d37ba8cbd6585e664 /ogcp
parentaf938c328011f942258091276a150c6810970dd4 (diff)
Update scopes tree dynamically
This patch adds a javascript function to update the scope tree (on/off) state. This javacript function is called every second, does a call to the new backend endpoint `/scopes/status` and updates the tree classes depending on the current data. The new `/scopes/status` endpoint just returns the scopes tree as json. This patch also adds an icon in the tree leafs, a filled green circle when the state is `on`, and a empty red circle when the state is `off`. There's also a new javascript function to unfold all collapses in the scope tree.
Diffstat (limited to 'ogcp')
-rw-r--r--ogcp/static/js/ogcp.js54
-rw-r--r--ogcp/templates/macros.html20
-rw-r--r--ogcp/views.py8
3 files changed, 79 insertions, 3 deletions
diff --git a/ogcp/static/js/ogcp.js b/ogcp/static/js/ogcp.js
new file mode 100644
index 0000000..ab06dfc
--- /dev/null
+++ b/ogcp/static/js/ogcp.js
@@ -0,0 +1,54 @@
+const Endpoint = '/scopes/status';
+const Interval = 1000;
+let updateTimeoutId = null;
+
+function updateScopeState() {
+ if (updateTimeoutId) {
+ clearTimeout(updateTimeoutId);
+ }
+
+ updateTimeoutId = setTimeout(() => {
+ updateTimeoutId = null;
+ fetch(Endpoint)
+ .then(response => response.json())
+ .then((data) => {
+ updateScopes(data.scope);
+ })
+ .catch((error) => { console.error(error); })
+ .finally(() => {
+ updateScopeState();
+ });
+ }, Interval);
+}
+
+function updateScopes(scopes) {
+ scopes.forEach((scope) => {
+ if (scope.state) {
+ const scopeId = `${scope.name}_${scope.id}`;
+ const scopeEl = document.querySelector(`#${scopeId}`);
+ const stateCls = ['state--on', 'state--off'];
+ scopeEl.classList.remove(...stateCls);
+ const stateClass = `state--${scope.state}`;
+ scopeEl.classList.add(stateClass);
+
+ const iconEl = document.querySelector(`#${scopeId} .nav-icon`);
+ const iconCls = ['fas', 'far', 'text-danger', 'text-success'];
+ iconEl.classList.remove(...iconCls);
+ let newIconCls = [];
+ if (scope.state === 'on') {
+ newIconCls.push('fas', 'text-success');
+ } else {
+ newIconCls.push('far', 'text-danger');
+ }
+ iconEl.classList.add(...newIconCls);
+ }
+ if (scope.scope) {
+ // This is a level so we should update all childs
+ updateScopes(scope.scope);
+ }
+ });
+}
+
+function unfoldAll() {
+ $('#scopes .collapse').collapse('show');
+}
diff --git a/ogcp/templates/macros.html b/ogcp/templates/macros.html
index 60b26a7..93c7380 100644
--- a/ogcp/templates/macros.html
+++ b/ogcp/templates/macros.html
@@ -20,15 +20,28 @@
{% macro scopes_tree_collapse(scopes) -%}
-<ul class="nav flex-column nav-pills">
+<ul id="scopes" class="nav flex-column nav-pills">
{{ scopes_tree_collapse_level(scopes["scope"], 1) }}
</ul>
+<script>
+ // Launch the javascript on document ready, so all the global functions exists
+ // in the scope
+ document.addEventListener('readystatechange', () => {
+ if (document.readyState === 'complete') {
+ updateScopeState();
+ unfoldAll();
+ }
+ });
+</script>
{% endmacro %}
{% macro scopes_tree_collapse_level(scopes, i) -%}
{% for scope in scopes %}
-<li class="nav-item {% if scope["state"] %}state--{{scope["state"] | lower}}{% endif %}">
+ <li
+ id="{{ scope["name"] }}_{{ scope["id"] }}"
+ class="nav-item {% if scope["state"] %}state--{{scope["state"] | lower}}{% endif %}"
+ >
{% if " ".join(scope["ip"]) %}
<input class="form-check-input" type="checkbox" form="scopesForm"
value="{{ " ".join(scope["ip"]) }}"
@@ -37,6 +50,9 @@
{% endif %}
<a class="nav-link {% if not scope["scope"] %}disabled{% endif %}" href="#level{{i}}-{{loop.index}}"
{% if scope["scope"] %}data-toggle="collapse"{% endif %}>
+ {% if not scope["scope"] %}
+ <i class="nav-icon fa-circle {% if scope['state'] == 'on' %}fas text-success{% else %}far text-danger{% endif %}"></i>
+ {% endif %}
{{ scope["name"] }}
</a>
{% if scope["scope"] %}
diff --git a/ogcp/views.py b/ogcp/views.py
index 1221478..ad5a8cb 100644
--- a/ogcp/views.py
+++ b/ogcp/views.py
@@ -113,7 +113,7 @@ def add_state_and_ips(scope, clients, ips):
if client:
scope['state'] = client['state']
else:
- scope['state'] = 'OFF'
+ scope['state'] = 'off'
scope['ip'] = [scope['ip']]
scope['selected'] = set(scope['ip']).issubset(ips)
else:
@@ -191,6 +191,12 @@ def logout():
logout_user()
return redirect(url_for('index'))
+@app.route('/scopes/status')
+@login_required
+def scopes_status():
+ scopes, _clients = get_scopes()
+ return jsonify(scopes)
+
@app.route('/scopes/')
@login_required
def scopes():