FEATURE displaying data tree
diff --git a/backend/connections.py b/backend/connections.py
index 6c32a7d..596d1a5 100644
--- a/backend/connections.py
+++ b/backend/connections.py
@@ -15,6 +15,7 @@
from .inventory import INVENTORY
from .devices import devices_get
from .error import NetopeerException
+from .data import *
sessions = {}
@@ -85,6 +86,8 @@
if not 'key' in req:
return(json.dumps({'success': False, 'error-msg': 'Missing session key.'}))
+ if not 'recursive' in req:
+ return(json.dumps({'success': False, 'error-msg': 'Missing recursive flag.'}))
if not user.username in sessions:
sessions[user.username] = {}
@@ -102,7 +105,10 @@
reply['error'].append(json.loads(str(err)))
return(json.dumps(reply))
- return(json.dumps({'success': True, 'data': json.loads(data.print_mem(ly.LYD_JSON, ly.LYP_WITHSIBLINGS))}))
+ if not 'path' in req:
+ return(dataInfoRoots(data, True if req['recursive'] == 'true' else False))
+ else:
+ return(dataInfoSubtree(data, req['path'], True if req['recursive'] == 'true' else False))
@auth.required()
diff --git a/backend/data.py b/backend/data.py
new file mode 100644
index 0000000..ba866ca
--- /dev/null
+++ b/backend/data.py
@@ -0,0 +1,78 @@
+"""
+NETCONF data helper functions
+File: data.py
+Author: Radek Krejci <rkrejci@cesnet.cz>
+"""
+
+import json
+import os
+
+import libyang as ly
+import netconf2 as nc
+
+def dataInfoNode(node, recursion=False):
+ schema = node.schema()
+ casted = node.subtype()
+
+ if node.dflt():
+ return None
+
+ info = {}
+ info["type"] = schema.nodetype()
+ info["module"] = schema.module().name()
+ info["name"] = schema.name()
+ info["dsc"] = schema.dsc()
+ info["config"] = True if schema.flags() & ly.LYS_CONFIG_W else False
+
+ result = {}
+ if info["type"] == ly.LYS_LEAF or info["type"] == ly.LYS_LEAFLIST:
+ result["value"] = casted.value_str()
+ elif recursion:
+ result["children"] = []
+ if node.child():
+ for child in node.child().tree_for():
+ childNode = dataInfoNode(child, True)
+ if not childNode:
+ continue
+ if not child.next():
+ childNode["last"] = True
+ result["children"].append(childNode)
+ result["info"] = info
+ result["path"] = node.path()
+
+ return result
+
+def dataInfoSubtree(data, path, recursion=False):
+ try:
+ node = data.find_path(path).data()[0]
+ except:
+ return(json.dumps({'success': False, 'error-msg': 'Invalid data path.'}))
+
+ result = dataInfoNode(node)
+ if not result:
+ return(json.dumps({'success': False, 'error-msg': 'Path refers to a default node.'}))
+
+ result["children"] = []
+ if node.child():
+ for child in node.child().tree_for():
+ childNode = dataInfoNode(child, recursion)
+ if not childNode:
+ continue
+ if not child.next():
+ childNode["last"] = True
+ result["children"].append(childNode)
+
+ return(json.dumps({'success': True, 'data': result}))
+
+
+def dataInfoRoots(data, recursion=False):
+ result = []
+ for root in data.tree_for():
+ rootNode = dataInfoNode(root, recursion)
+ if not rootNode:
+ continue
+ if not root.next():
+ rootNode["last"] = True
+ result.append(rootNode)
+
+ return(json.dumps({'success': True, 'data': result}))
\ No newline at end of file
diff --git a/config.json b/config.json
index 3737762..56f7407 100644
--- a/config.json
+++ b/config.json
@@ -1,8 +1,10 @@
{
"module": {
- "file": "netopeer.module.ts",
+ "name" : "netopeer",
+ "file" : "netopeer.module.ts",
"class" : "NetopeerModule",
"frontend" : "frontend",
- "backend" : "backend"
+ "backend" : "backend",
+ "assets" : "frontend-assets"
}
}
diff --git a/frontend-assets/icons/add.svg b/frontend-assets/icons/add.svg
new file mode 100644
index 0000000..1675388
--- /dev/null
+++ b/frontend-assets/icons/add.svg
@@ -0,0 +1,69 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ version="1.1"
+ id="svg2"
+ inkscape:version="0.91+devel r14491"
+ width="32"
+ height="32"
+ viewBox="0 0 32 32"
+ sodipodi:docname="add.svg">
+ <metadata
+ id="metadata8">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ <dc:title></dc:title>
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <defs
+ id="defs6" />
+ <sodipodi:namedview
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1"
+ objecttolerance="10"
+ gridtolerance="10"
+ guidetolerance="10"
+ inkscape:pageopacity="0"
+ inkscape:pageshadow="2"
+ inkscape:window-width="1764"
+ inkscape:window-height="1171"
+ inkscape:document-units="px"
+ id="namedview4"
+ showgrid="false"
+ width="32"
+ inkscape:zoom="10.429825"
+ inkscape:cx="0.096465403"
+ inkscape:cy="2.0739103"
+ inkscape:window-x="1920"
+ inkscape:window-y="0"
+ inkscape:window-maximized="1"
+ inkscape:current-layer="svg2">
+ <inkscape:grid
+ type="xygrid"
+ id="grid29" />
+ </sodipodi:namedview>
+ <path
+ style="fill:none;fill-opacity:1;stroke:#000000;stroke-width:4.57085705;stroke-linecap:round;stroke-opacity:1"
+ d="m 7.3319965,15.973932 17.1964165,1e-6"
+ id="path2991"
+ inkscape:connector-curvature="0" />
+ <path
+ style="fill:#a65400;fill-opacity:1;stroke:#000000;stroke-width:4.57085705;stroke-linecap:round;stroke-opacity:1"
+ d="m 15.930205,7.3757241 0,17.1964169"
+ id="path2993"
+ inkscape:connector-curvature="0" />
+</svg>
diff --git a/frontend-assets/icons/add_active.svg b/frontend-assets/icons/add_active.svg
new file mode 100644
index 0000000..a2f485f
--- /dev/null
+++ b/frontend-assets/icons/add_active.svg
@@ -0,0 +1,69 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ version="1.1"
+ id="svg2"
+ inkscape:version="0.91+devel r14491"
+ width="32"
+ height="32"
+ viewBox="0 0 32 32"
+ sodipodi:docname="add_active.svg">
+ <metadata
+ id="metadata8">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ <dc:title></dc:title>
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <defs
+ id="defs6" />
+ <sodipodi:namedview
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1"
+ objecttolerance="10"
+ gridtolerance="10"
+ guidetolerance="10"
+ inkscape:pageopacity="0"
+ inkscape:pageshadow="2"
+ inkscape:window-width="1764"
+ inkscape:window-height="1171"
+ inkscape:document-units="px"
+ id="namedview4"
+ showgrid="false"
+ width="32"
+ inkscape:zoom="10.429825"
+ inkscape:cx="0.096465403"
+ inkscape:cy="2.0739103"
+ inkscape:window-x="1920"
+ inkscape:window-y="0"
+ inkscape:window-maximized="1"
+ inkscape:current-layer="svg2">
+ <inkscape:grid
+ type="xygrid"
+ id="grid29" />
+ </sodipodi:namedview>
+ <path
+ style="fill:none;fill-opacity:1;stroke:#00a654;stroke-width:4.57085705;stroke-linecap:round;stroke-opacity:1"
+ d="m 7.3319965,15.973932 17.1964165,1e-6"
+ id="path2991"
+ inkscape:connector-curvature="0" />
+ <path
+ style="fill:#a65400;fill-opacity:1;stroke:#00a654;stroke-width:4.57085705;stroke-linecap:round;stroke-opacity:1"
+ d="m 15.930205,7.3757241 0,17.1964169"
+ id="path2993"
+ inkscape:connector-curvature="0" />
+</svg>
diff --git a/frontend-assets/icons/close.svg b/frontend-assets/icons/close.svg
new file mode 100644
index 0000000..74514c3
--- /dev/null
+++ b/frontend-assets/icons/close.svg
@@ -0,0 +1,69 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ version="1.1"
+ id="svg2"
+ inkscape:version="0.91+devel r14491"
+ width="32"
+ height="32"
+ viewBox="0 0 32 32"
+ sodipodi:docname="close.svg">
+ <metadata
+ id="metadata8">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ <dc:title></dc:title>
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <defs
+ id="defs6" />
+ <sodipodi:namedview
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1"
+ objecttolerance="10"
+ gridtolerance="10"
+ guidetolerance="10"
+ inkscape:pageopacity="0"
+ inkscape:pageshadow="2"
+ inkscape:window-width="1764"
+ inkscape:window-height="1171"
+ inkscape:document-units="px"
+ id="namedview4"
+ showgrid="false"
+ width="32"
+ inkscape:zoom="10.429825"
+ inkscape:cx="0.096465403"
+ inkscape:cy="2.0739103"
+ inkscape:window-x="1920"
+ inkscape:window-y="0"
+ inkscape:window-maximized="1"
+ inkscape:current-layer="svg2">
+ <inkscape:grid
+ type="xygrid"
+ id="grid29" />
+ </sodipodi:namedview>
+ <path
+ style="fill:none;fill-opacity:1;stroke:#000000;stroke-width:4.57085705;stroke-linecap:round;stroke-opacity:1"
+ d="M 9.8503536,9.8940808 22.010056,22.053784"
+ id="path2991"
+ inkscape:connector-curvature="0" />
+ <path
+ style="fill:#a65400;fill-opacity:1;stroke:#000000;stroke-width:4.57085705;stroke-linecap:round;stroke-opacity:1"
+ d="M 22.010056,9.8940808 9.8503536,22.053784"
+ id="path2993"
+ inkscape:connector-curvature="0" />
+</svg>
diff --git a/frontend-assets/icons/close_active.svg b/frontend-assets/icons/close_active.svg
new file mode 100644
index 0000000..ffe8618
--- /dev/null
+++ b/frontend-assets/icons/close_active.svg
@@ -0,0 +1,69 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ version="1.1"
+ id="svg2"
+ inkscape:version="0.91+devel r14491"
+ width="32"
+ height="32"
+ viewBox="0 0 32 32"
+ sodipodi:docname="close_active.svg">
+ <metadata
+ id="metadata8">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ <dc:title></dc:title>
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <defs
+ id="defs6" />
+ <sodipodi:namedview
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1"
+ objecttolerance="10"
+ gridtolerance="10"
+ guidetolerance="10"
+ inkscape:pageopacity="0"
+ inkscape:pageshadow="2"
+ inkscape:window-width="1764"
+ inkscape:window-height="1171"
+ inkscape:document-units="px"
+ id="namedview4"
+ showgrid="false"
+ width="32"
+ inkscape:zoom="10.429825"
+ inkscape:cx="0.096465403"
+ inkscape:cy="2.0739103"
+ inkscape:window-x="1920"
+ inkscape:window-y="0"
+ inkscape:window-maximized="1"
+ inkscape:current-layer="svg2">
+ <inkscape:grid
+ type="xygrid"
+ id="grid29" />
+ </sodipodi:namedview>
+ <path
+ style="fill:none;fill-opacity:1;stroke:#c80000;stroke-width:4.57085705;stroke-linecap:round;stroke-opacity:1"
+ d="M 9.8503536,9.8940808 22.010056,22.053784"
+ id="path2991"
+ inkscape:connector-curvature="0" />
+ <path
+ style="fill:#a65400;fill-opacity:1;stroke:#c80000;stroke-width:4.57085705;stroke-linecap:round;stroke-opacity:1"
+ d="M 22.010056,9.8940808 9.8503536,22.053784"
+ id="path2993"
+ inkscape:connector-curvature="0" />
+</svg>
diff --git a/frontend-assets/icons/collapse.svg b/frontend-assets/icons/collapse.svg
new file mode 100644
index 0000000..9a0066f
--- /dev/null
+++ b/frontend-assets/icons/collapse.svg
@@ -0,0 +1,92 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ version="1.1"
+ id="svg2"
+ inkscape:version="0.91+devel r14491"
+ width="32"
+ height="32"
+ viewBox="0 0 32 32"
+ sodipodi:docname="collapse.svg">
+ <metadata
+ id="metadata8">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ <dc:title></dc:title>
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <defs
+ id="defs6" />
+ <sodipodi:namedview
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1"
+ objecttolerance="10"
+ gridtolerance="10"
+ guidetolerance="10"
+ inkscape:pageopacity="0"
+ inkscape:pageshadow="2"
+ inkscape:window-width="1764"
+ inkscape:window-height="1171"
+ inkscape:document-units="px"
+ id="namedview4"
+ showgrid="true"
+ width="32"
+ inkscape:zoom="14.75"
+ inkscape:cx="15.701475"
+ inkscape:cy="26.322461"
+ inkscape:window-x="1920"
+ inkscape:window-y="0"
+ inkscape:window-maximized="1"
+ inkscape:current-layer="svg2">
+ <inkscape:grid
+ type="xygrid"
+ id="grid29" />
+ </sodipodi:namedview>
+ <path
+ style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:medium;line-height:normal;font-family:sans-serif;font-variant-ligatures:normal;font-variant-position:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-alternates:normal;font-feature-settings:normal;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:normal;word-spacing:normal;text-transform:none;writing-mode:lr-tb;direction:ltr;text-orientation:mixed;dominant-baseline:auto;baseline-shift:baseline;text-anchor:start;white-space:normal;shape-padding:0;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
+ d="M 4.5,8.7265625 V 27 l 1,-0.5 V 8.7265625 Z"
+ id="path31"
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="ccccc" />
+ <path
+ style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1"
+ d="M 5,12 V 27"
+ id="path33"
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="cc" />
+ <g
+ id="g110-6"
+ transform="matrix(0.55555556,0,0,0.55555556,-5.2441368,-0.56587432)">
+ <path
+ sodipodi:nodetypes="ccccc"
+ inkscape:connector-curvature="0"
+ id="path99-7"
+ d="m 19,14 4,-2 V 7 l -4,2 z"
+ style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.01;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+ <path
+ sodipodi:nodetypes="ccccc"
+ inkscape:connector-curvature="0"
+ id="path103-5"
+ d="M 18,14 V 9 L 14,7 v 5 z"
+ style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.01;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+ <path
+ inkscape:connector-curvature="0"
+ id="path105-3"
+ d="m 14.514613,6 4,2 4,-2 -4,-2 z"
+ style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.01;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+ </g>
+</svg>
diff --git a/frontend-assets/icons/collapse_active.svg b/frontend-assets/icons/collapse_active.svg
new file mode 100644
index 0000000..01c1c9c
--- /dev/null
+++ b/frontend-assets/icons/collapse_active.svg
@@ -0,0 +1,92 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ version="1.1"
+ id="svg2"
+ inkscape:version="0.91+devel r14491"
+ width="32"
+ height="32"
+ viewBox="0 0 32 32"
+ sodipodi:docname="collapse_active.svg">
+ <metadata
+ id="metadata8">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ <dc:title></dc:title>
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <defs
+ id="defs6" />
+ <sodipodi:namedview
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1"
+ objecttolerance="10"
+ gridtolerance="10"
+ guidetolerance="10"
+ inkscape:pageopacity="0"
+ inkscape:pageshadow="2"
+ inkscape:window-width="1920"
+ inkscape:window-height="1131"
+ inkscape:document-units="px"
+ id="namedview4"
+ showgrid="true"
+ width="32"
+ inkscape:zoom="10.429825"
+ inkscape:cx="-19.888321"
+ inkscape:cy="11.767916"
+ inkscape:window-x="0"
+ inkscape:window-y="0"
+ inkscape:window-maximized="1"
+ inkscape:current-layer="svg2">
+ <inkscape:grid
+ type="xygrid"
+ id="grid29" />
+ </sodipodi:namedview>
+ <path
+ style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:medium;line-height:normal;font-family:sans-serif;font-variant-ligatures:normal;font-variant-position:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-alternates:normal;font-feature-settings:normal;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:normal;word-spacing:normal;text-transform:none;writing-mode:lr-tb;direction:ltr;text-orientation:mixed;dominant-baseline:auto;baseline-shift:baseline;text-anchor:start;white-space:normal;shape-padding:0;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
+ d="M 4.5,8.7265625 V 27 l 1,-0.5 V 8.7265625 Z"
+ id="path31"
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="ccccc" />
+ <path
+ style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1"
+ d="M 5,12 V 27"
+ id="path33"
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="cc" />
+ <g
+ id="g124"
+ transform="matrix(1.2,0,0,1.2,-1.0064532,-0.88696403)">
+ <path
+ sodipodi:nodetypes="ccccc"
+ inkscape:connector-curvature="0"
+ id="path99-7"
+ d="M 5.3114188,7.2119035 7.5336411,6.1007924 V 3.3230146 L 5.3114188,4.4341257 Z"
+ style="fill:#ffb400;fill-opacity:1;fill-rule:evenodd;stroke:#ffb400;stroke-width:0.00005556;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+ <path
+ sodipodi:nodetypes="ccccc"
+ inkscape:connector-curvature="0"
+ id="path103-5"
+ d="M 4.7558633,7.2119035 V 4.4341257 L 2.533641,3.3230146 v 2.7777778 z"
+ style="fill:#ffb400;fill-opacity:1;fill-rule:evenodd;stroke:#ffb400;stroke-width:0.00555556;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+ <path
+ inkscape:connector-curvature="0"
+ id="path105-3"
+ d="M 2.8195372,2.767459 5.0417594,3.8785702 7.2639816,2.767459 5.0417594,1.6563479 Z"
+ style="fill:#ffb400;fill-opacity:1;fill-rule:evenodd;stroke:#ffb400;stroke-width:0.00555556;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+ </g>
+</svg>
diff --git a/frontend-assets/icons/container.svg b/frontend-assets/icons/container.svg
new file mode 100644
index 0000000..07d678c
--- /dev/null
+++ b/frontend-assets/icons/container.svg
@@ -0,0 +1,80 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ version="1.1"
+ id="svg2"
+ inkscape:version="0.91+devel r14491"
+ width="32"
+ height="32"
+ viewBox="0 0 32 32"
+ sodipodi:docname="container.svg">
+ <metadata
+ id="metadata8">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ <dc:title></dc:title>
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <defs
+ id="defs6" />
+ <sodipodi:namedview
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1"
+ objecttolerance="10"
+ gridtolerance="10"
+ guidetolerance="10"
+ inkscape:pageopacity="0"
+ inkscape:pageshadow="2"
+ inkscape:window-width="1764"
+ inkscape:window-height="1171"
+ inkscape:document-units="px"
+ id="namedview4"
+ showgrid="false"
+ width="32"
+ inkscape:zoom="10.429825"
+ inkscape:cx="21.291731"
+ inkscape:cy="8.4274412"
+ inkscape:window-x="1920"
+ inkscape:window-y="0"
+ inkscape:window-maximized="1"
+ inkscape:current-layer="svg2">
+ <inkscape:grid
+ type="xygrid"
+ id="grid29" />
+ </sodipodi:namedview>
+ <g
+ id="g110-6"
+ transform="matrix(2.5279623,0,0,2.5279623,-30.450997,-6.7186552)">
+ <path
+ sodipodi:nodetypes="ccccc"
+ inkscape:connector-curvature="0"
+ id="path99-7"
+ d="m 19,14 4,-2 V 7 l -4,2 z"
+ style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.01;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+ <path
+ sodipodi:nodetypes="ccccc"
+ inkscape:connector-curvature="0"
+ id="path103-5"
+ d="M 18,14 V 9 L 14,7 v 5 z"
+ style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.01;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+ <path
+ inkscape:connector-curvature="0"
+ id="path105-3"
+ d="m 14.514613,6 4,2 4,-2 -4,-2 z"
+ style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.01;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+ </g>
+</svg>
diff --git a/frontend-assets/icons/info.svg b/frontend-assets/icons/info.svg
new file mode 100644
index 0000000..055c329
--- /dev/null
+++ b/frontend-assets/icons/info.svg
@@ -0,0 +1,77 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ version="1.1"
+ id="svg2"
+ inkscape:version="0.91+devel r14491"
+ width="32"
+ height="32"
+ viewBox="0 0 32 32"
+ sodipodi:docname="info.svg">
+ <metadata
+ id="metadata8">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ <dc:title></dc:title>
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <defs
+ id="defs6" />
+ <sodipodi:namedview
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1"
+ objecttolerance="10"
+ gridtolerance="10"
+ guidetolerance="10"
+ inkscape:pageopacity="0"
+ inkscape:pageshadow="2"
+ inkscape:window-width="1764"
+ inkscape:window-height="1171"
+ inkscape:document-units="px"
+ id="namedview4"
+ showgrid="true"
+ width="32"
+ inkscape:zoom="14.75"
+ inkscape:cx="14.722117"
+ inkscape:cy="13.579493"
+ inkscape:window-x="1920"
+ inkscape:window-y="0"
+ inkscape:window-maximized="1"
+ inkscape:current-layer="svg2">
+ <inkscape:grid
+ type="xygrid"
+ id="grid29" />
+ </sodipodi:namedview>
+ <ellipse
+ style="fill:#000000;fill-opacity:1;stroke-width:0.01;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none"
+ id="path197"
+ cy="16.042376"
+ cx="16.059322"
+ rx="13.059322"
+ ry="13.025427" />
+ <text
+ xml:space="preserve"
+ style="font-style:normal;font-variant:normal;font-weight:600;font-stretch:normal;font-size:20px;line-height:125%;font-family:'Latin Modern Roman Demi';-inkscape-font-specification:'Latin Modern Roman Demi Semi-Bold';letter-spacing:0px;word-spacing:0px;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ x="13.149323"
+ y="22.912376"
+ id="text201"
+ sodipodi:linespacing="125%"><tspan
+ sodipodi:role="line"
+ id="tspan199"
+ x="13.149323"
+ y="22.912376">i</tspan></text>
+</svg>
diff --git a/frontend-assets/icons/info_active.svg b/frontend-assets/icons/info_active.svg
new file mode 100644
index 0000000..73992c5
--- /dev/null
+++ b/frontend-assets/icons/info_active.svg
@@ -0,0 +1,77 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ version="1.1"
+ id="svg2"
+ inkscape:version="0.91+devel r14491"
+ width="32"
+ height="32"
+ viewBox="0 0 32 32"
+ sodipodi:docname="info_active.svg">
+ <metadata
+ id="metadata8">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ <dc:title></dc:title>
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <defs
+ id="defs6" />
+ <sodipodi:namedview
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1"
+ objecttolerance="10"
+ gridtolerance="10"
+ guidetolerance="10"
+ inkscape:pageopacity="0"
+ inkscape:pageshadow="2"
+ inkscape:window-width="1764"
+ inkscape:window-height="1171"
+ inkscape:document-units="px"
+ id="namedview4"
+ showgrid="true"
+ width="32"
+ inkscape:zoom="14.75"
+ inkscape:cx="14.722117"
+ inkscape:cy="13.579493"
+ inkscape:window-x="1920"
+ inkscape:window-y="0"
+ inkscape:window-maximized="1"
+ inkscape:current-layer="svg2">
+ <inkscape:grid
+ type="xygrid"
+ id="grid29" />
+ </sodipodi:namedview>
+ <ellipse
+ style="fill:#0054a6;fill-opacity:1;stroke-width:0.01;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none"
+ id="path197"
+ cy="16.042376"
+ cx="16.059322"
+ rx="13.059322"
+ ry="13.025427" />
+ <text
+ xml:space="preserve"
+ style="font-style:normal;font-variant:normal;font-weight:600;font-stretch:normal;font-size:20px;line-height:125%;font-family:'Latin Modern Roman Demi';-inkscape-font-specification:'Latin Modern Roman Demi Semi-Bold';letter-spacing:0px;word-spacing:0px;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ x="13.149323"
+ y="22.912376"
+ id="text201"
+ sodipodi:linespacing="125%"><tspan
+ sodipodi:role="line"
+ id="tspan199"
+ x="13.149323"
+ y="22.912376">i</tspan></text>
+</svg>
diff --git a/frontend-assets/icons/leaf.svg b/frontend-assets/icons/leaf.svg
new file mode 100644
index 0000000..4077cae
--- /dev/null
+++ b/frontend-assets/icons/leaf.svg
@@ -0,0 +1,65 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ version="1.1"
+ id="svg2"
+ inkscape:version="0.91+devel r14491"
+ width="32"
+ height="32"
+ viewBox="0 0 32 32"
+ sodipodi:docname="leaf.svg">
+ <metadata
+ id="metadata8">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ <dc:title></dc:title>
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <defs
+ id="defs6" />
+ <sodipodi:namedview
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1"
+ objecttolerance="10"
+ gridtolerance="10"
+ guidetolerance="10"
+ inkscape:pageopacity="0"
+ inkscape:pageshadow="2"
+ inkscape:window-width="1764"
+ inkscape:window-height="1171"
+ inkscape:document-units="px"
+ id="namedview4"
+ showgrid="false"
+ width="32"
+ inkscape:zoom="10.429825"
+ inkscape:cx="21.291731"
+ inkscape:cy="8.4274412"
+ inkscape:window-x="1920"
+ inkscape:window-y="0"
+ inkscape:window-maximized="1"
+ inkscape:current-layer="svg2">
+ <inkscape:grid
+ type="xygrid"
+ id="grid29" />
+ </sodipodi:namedview>
+ <path
+ style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.01697966;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ d="M 7.1364998,26.743276 C 8.6016888,20.963913 10.729376,15.949998 17.882651,10.903229 10.540343,13.233635 8.2760938,17.642961 8.2760938,17.642961 2.7240748,8.0318159 17.692006,3.2566891 26.48314,7.5301562 26.605246,15.547998 20.114443,28.612861 12.463166,21.707935 c -1.530934,2.18212 -1.798413,3.476478 -2.345216,5.663685 z"
+ id="path82-3"
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="ccccccc" />
+</svg>
diff --git a/frontend-assets/icons/leaflist.svg b/frontend-assets/icons/leaflist.svg
new file mode 100644
index 0000000..469c795
--- /dev/null
+++ b/frontend-assets/icons/leaflist.svg
@@ -0,0 +1,75 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ version="1.1"
+ id="svg2"
+ inkscape:version="0.91+devel r14491"
+ width="32"
+ height="32"
+ viewBox="0 0 32 32"
+ sodipodi:docname="leaflist.svg">
+ <metadata
+ id="metadata8">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ <dc:title></dc:title>
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <defs
+ id="defs6" />
+ <sodipodi:namedview
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1"
+ objecttolerance="10"
+ gridtolerance="10"
+ guidetolerance="10"
+ inkscape:pageopacity="0"
+ inkscape:pageshadow="2"
+ inkscape:window-width="1764"
+ inkscape:window-height="1171"
+ inkscape:document-units="px"
+ id="namedview4"
+ showgrid="false"
+ width="32"
+ inkscape:zoom="10.429825"
+ inkscape:cx="3.5852856"
+ inkscape:cy="18.397605"
+ inkscape:window-x="1920"
+ inkscape:window-y="0"
+ inkscape:window-maximized="1"
+ inkscape:current-layer="svg2">
+ <inkscape:grid
+ type="xygrid"
+ id="grid29" />
+ </sodipodi:namedview>
+ <g
+ id="g321"
+ transform="matrix(0.87723565,0,0,0.87723565,3.6055513,3.6675193)">
+ <path
+ sodipodi:nodetypes="ccccccc"
+ inkscape:connector-curvature="0"
+ id="path82-3-5"
+ d="M 13.824203,9.8131899 C 12.396744,8.1135289 10.574231,6.4395596 8.1964063,4.76196 11.868403,5.9274305 14.270302,7.6128695 15.754072,9.0066876 16.995426,8.4971039 18.04143,8.2948117 18.973034,8.153974 19.733964,0.84443103 7.2957293,-2.3540764 -0.40408302,1.388887 -0.50356084,7.9208958 3.7860165,17.802663 9.5164397,17.507246 9.0636018,14.416943 9.7412253,11.915797 13.824203,9.8131899 Z"
+ style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.01697966;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+ <path
+ sodipodi:nodetypes="ccccccc"
+ inkscape:connector-curvature="0"
+ id="path82-3"
+ d="M 10.012866,29.236127 C 11.478055,23.456764 13.605743,18.442849 20.759018,13.39608 13.41671,15.726486 11.15246,20.135812 11.15246,20.135812 5.6004414,10.524667 20.568373,5.7495401 29.359507,10.023007 c 0.122106,8.017842 -6.368697,21.082705 -14.019974,14.177779 -1.530934,2.18212 -1.798413,3.476478 -2.345216,5.663685 z"
+ style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.01697966;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+ </g>
+</svg>
diff --git a/frontend-assets/icons/reload.svg b/frontend-assets/icons/reload.svg
new file mode 100644
index 0000000..c571248
--- /dev/null
+++ b/frontend-assets/icons/reload.svg
@@ -0,0 +1,420 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ version="1.1"
+ id="svg2"
+ inkscape:version="0.91+devel r14491"
+ width="32"
+ height="32"
+ viewBox="0 0 32 32"
+ sodipodi:docname="reload.svg">
+ <metadata
+ id="metadata8">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ <dc:title></dc:title>
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <defs
+ id="defs6">
+ <linearGradient
+ id="linearGradient4225"
+ inkscape:collect="always">
+ <stop
+ id="stop4227"
+ offset="0"
+ style="stop-color:#00ff00;stop-opacity:1;" />
+ <stop
+ id="stop4229"
+ offset="1"
+ style="stop-color:#00ff00;stop-opacity:0;" />
+ </linearGradient>
+ <linearGradient
+ id="imagebot_37">
+ <stop
+ id="imagebot_44"
+ offset="0"
+ stop-color="#ffffff" />
+ <stop
+ id="imagebot_43"
+ offset="1"
+ stop-opacity="0"
+ stop-color="#ffffff" />
+ </linearGradient>
+ <linearGradient
+ id="imagebot_21"
+ y2="21.876775"
+ x2="13.814828"
+ y1="10.965213"
+ x1="12.042996"
+ gradientTransform="scale(1.1419004,0.87573313)"
+ gradientUnits="userSpaceOnUse">
+ <stop
+ id="imagebot_42"
+ offset="0"
+ stop-color="#707070" />
+ <stop
+ style="stop-color:#4d4d4d;stop-opacity:1"
+ id="imagebot_41"
+ offset="0.33333"
+ stop-color="#5b86be" />
+ <stop
+ id="imagebot_40"
+ offset="1"
+ stop-opacity="0"
+ stop-color="#83a8d8" />
+ </linearGradient>
+ <linearGradient
+ id="imagebot_22"
+ y2="22.923376"
+ x2="8.8634028"
+ y1="18.385699"
+ x1="8.8058708"
+ gradientTransform="scale(1.1419004,0.87573313)"
+ gradientUnits="userSpaceOnUse">
+ <stop
+ style="stop-color:#4d4d4d;stop-opacity:1"
+ id="imagebot_39"
+ offset="0"
+ stop-color="#707070" />
+ <stop
+ id="imagebot_38"
+ offset="1"
+ stop-opacity="0"
+ stop-color="#707070" />
+ </linearGradient>
+ <linearGradient
+ id="imagebot_6"
+ y2="26.499712"
+ xlink:href="#imagebot_37"
+ x2="51.063529"
+ y1="26.499712"
+ x1="4.6650344"
+ gradientTransform="scale(1.0486647,0.95359363)"
+ gradientUnits="userSpaceOnUse" />
+ <linearGradient
+ id="imagebot_12"
+ y2="1.01508"
+ x2="0.83337"
+ y1="0.89452"
+ x1="0.86549">
+ <stop
+ id="imagebot_36"
+ offset="0"
+ stop-color="#707070" />
+ <stop
+ id="imagebot_35"
+ offset="1"
+ stop-color="#707070" />
+ </linearGradient>
+ <radialGradient
+ id="imagebot_24"
+ gradientUnits="userSpaceOnUse"
+ cy="36.421"
+ cx="24.837"
+ gradientTransform="matrix(1,0,0,0.53672,0,16.873)"
+ r="15.645">
+ <stop
+ id="imagebot_34"
+ offset="0"
+ stop-color="#707070" />
+ <stop
+ id="imagebot_33"
+ offset="1"
+ stop-opacity="0"
+ stop-color="#707070" />
+ </radialGradient>
+ <linearGradient
+ id="imagebot_18"
+ y2="0.37082"
+ x2="0.15148"
+ y1="0.69903"
+ x1="0.99444">
+ <stop
+ id="imagebot_32"
+ offset="0"
+ stop-color="#b9cfe7" />
+ <stop
+ id="imagebot_31"
+ offset="1"
+ stop-color="#729fcf" />
+ </linearGradient>
+ <linearGradient
+ id="imagebot_11"
+ y2="0.49999"
+ x2="0.83223"
+ y1="0.43678"
+ x1="0.20248">
+ <stop
+ id="imagebot_30"
+ offset="0"
+ stop-color="#729fcf" />
+ <stop
+ id="imagebot_29"
+ offset="1"
+ stop-color="#528ac5" />
+ </linearGradient>
+ <linearGradient
+ id="imagebot_16"
+ y2="27.96628"
+ x2="32.728516"
+ y1="36.263326"
+ x1="32.355118"
+ gradientTransform="scale(1.1430281,0.87486911)"
+ gradientUnits="userSpaceOnUse">
+ <stop
+ style="stop-color:#1a1a1a;stop-opacity:1"
+ id="imagebot_28"
+ offset="0"
+ stop-color="#3977c3" />
+ <stop
+ id="imagebot_27"
+ offset="1"
+ stop-opacity="0"
+ stop-color="#89aedc" />
+ </linearGradient>
+ <linearGradient
+ id="imagebot_15"
+ y2="27.96628"
+ x2="32.728516"
+ y1="35.376378"
+ x1="28.651658"
+ gradientTransform="scale(1.1430281,0.87486911)"
+ gradientUnits="userSpaceOnUse">
+ <stop
+ style="stop-color:#333333;stop-opacity:1"
+ id="imagebot_26"
+ offset="0"
+ stop-color="#c4d7eb" />
+ <stop
+ id="imagebot_25"
+ offset="1"
+ stop-opacity="0"
+ stop-color="#c4d7eb" />
+ </linearGradient>
+ <linearGradient
+ gradientUnits="userSpaceOnUse"
+ y2="30.563"
+ x2="20.062"
+ y1="30.563"
+ x1="7.0625"
+ id="linearGradient4231"
+ xlink:href="#linearGradient4225"
+ inkscape:collect="always" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#imagebot_12"
+ id="linearGradient220"
+ x1="48.895984"
+ y1="44.737763"
+ x2="47.338499"
+ y2="50.583657"
+ gradientTransform="scale(0.96652103,1.0346386)"
+ gradientUnits="userSpaceOnUse" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#imagebot_12"
+ id="linearGradient222"
+ x1="48.669812"
+ y1="44.233604"
+ x2="47.125967"
+ y2="50.028298"
+ gradientTransform="scale(0.97148753,1.0293493)"
+ gradientUnits="userSpaceOnUse" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#imagebot_12"
+ id="linearGradient224"
+ x1="48.669812"
+ y1="44.233604"
+ x2="47.125967"
+ y2="50.028298"
+ gradientTransform="scale(0.97148753,1.0293493)"
+ gradientUnits="userSpaceOnUse" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#imagebot_37"
+ id="linearGradient226"
+ x1="4.5632353"
+ y1="27.739821"
+ x2="52.450109"
+ y2="27.739821"
+ gradientTransform="scale(1.0266686,0.97402418)"
+ gradientUnits="userSpaceOnUse" />
+ </defs>
+ <sodipodi:namedview
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1"
+ objecttolerance="10"
+ gridtolerance="10"
+ guidetolerance="10"
+ inkscape:pageopacity="0"
+ inkscape:pageshadow="2"
+ inkscape:window-width="1764"
+ inkscape:window-height="1171"
+ inkscape:document-units="px"
+ id="namedview4"
+ showgrid="false"
+ width="32"
+ inkscape:zoom="10.429825"
+ inkscape:cx="18.070421"
+ inkscape:cy="3.8319753"
+ inkscape:window-x="1920"
+ inkscape:window-y="0"
+ inkscape:window-maximized="1"
+ inkscape:current-layer="layer2">
+ <inkscape:grid
+ type="xygrid"
+ id="grid29" />
+ </sodipodi:namedview>
+ <g
+ inkscape:groupmode="layer"
+ id="layer1"
+ inkscape:label="Layer 1"
+ style="display:none"
+ sodipodi:insensitive="true">
+ <g
+ style="display:inline"
+ id="imagebot_2"
+ label="Layer 1"
+ transform="matrix(0.53168626,-0.21005051,0.21005051,0.53168626,-37.875177,1.6574228)">
+ <g
+ inkscape:export-ydpi="772.32001"
+ inkscape:export-xdpi="772.32001"
+ style="fill:#ff0000;stroke:#707070"
+ id="imagebot_17"
+ transform="matrix(-0.57905,-0.48923,-0.48923,0.57905,60.95052,28.909)"
+ label="Layer 1">
+ <path
+ inkscape:connector-curvature="0"
+ style="fill:#ff0000;stroke:url(#linearGradient220);stroke-width:1.31916833;stroke-miterlimit:4;stroke-dasharray:none"
+ id="imagebot_19"
+ d="M 44.307,50.23 C 62.821,35.819 49.665,13.412 22.462,12.498 l -0.348,-9.3465 -14.49,17.346 15.09,12.721 c 0,0 -0.252,-9.881 -0.252,-9.881 18.83,0.999 32.982,14.072 21.845,26.892 z" />
+ </g>
+ <path
+ inkscape:export-ydpi="772.32001"
+ inkscape:export-xdpi="772.32001"
+ transform="translate(4.03452,15.538)"
+ style="fill:url(#imagebot_15);stroke:url(#imagebot_16)"
+ inkscape:connector-curvature="0"
+ id="imagebot_14"
+ d="m 28.375,33.438 c 0,0 8.937,0.624 6.187,-9.876 h 7.776 c 0,1.503 -0.588,11.876 -13.963,9.876 z"
+ label="Layer 1" />
+ <g
+ inkscape:export-ydpi="772.32001"
+ inkscape:export-xdpi="772.32001"
+ style="display:block;fill:#00ff00;stroke:url(#linearGradient224);stroke-width:1.31920004"
+ id="imagebot_10"
+ transform="matrix(0.57905,0.48923,0.48923,-0.57905,-3.88648,46.074)"
+ display="block"
+ label="Layer 1">
+ <path
+ inkscape:connector-curvature="0"
+ style="fill:#00ff00;stroke:url(#linearGradient222);stroke-width:1.31920004"
+ id="imagebot_13"
+ d="M 44.307,50.23 C 62.821,35.819 49.665,13.412 22.462,12.498 L 22.399,3.069 7.794,20.424 22.462,33.006 v -9.668 c 18.83,0.999 32.982,14.072 21.845,26.892 z" />
+ </g>
+ <path
+ inkscape:export-ydpi="772.32001"
+ inkscape:export-xdpi="772.32001"
+ transform="translate(4.03452,15.538)"
+ inkscape:connector-curvature="0"
+ style="opacity:0.27221997;fill:url(#linearGradient4231)"
+ id="imagebot_9"
+ d="m 7.0625,38.188 0.0625,-14.876 12.937,-0.374 -4.388,5.178 3.867,2.374 c -3,2.25 -4.55,2.422 -5.55,4.984 l -2.817,-2.11 z"
+ label="Layer 1" />
+ <g
+ inkscape:export-ydpi="772.32001"
+ inkscape:export-xdpi="772.32001"
+ style="opacity:0.5;fill:#ff0000;stroke:#ffffff"
+ id="imagebot_4"
+ transform="matrix(-0.50854,-0.42965,-0.42965,0.50854,57.08352,28.903)"
+ label="Layer 1">
+ <path
+ inkscape:connector-curvature="0"
+ style="fill:#ff0000;stroke:url(#linearGradient226);stroke-width:1.50209999"
+ id="imagebot_5"
+ d="M 51.39,46.506 C 60.51,31.286 47.051,12.432 19.628,12.07 l -0.285,-8.0193 -13.002,15.328 13.468,11.386 -0.182,-9.454 c 18.245,0.382 34.784,10.926 31.763,25.195 z" />
+ </g>
+ <path
+ inkscape:export-ydpi="772.32001"
+ inkscape:export-xdpi="772.32001"
+ transform="matrix(-1.4897,0,0,-1.0013,61.209,75.282)"
+ style="opacity:0.38332998;fill:url(#imagebot_24);fill-rule:evenodd"
+ inkscape:connector-curvature="0"
+ id="imagebot_23"
+ d="m 40.482,36.421 a 15.645,8.3969 0 1 1 -31.29,0 15.645,8.3969 0 1 1 31.29,0 z"
+ label="Layer 1" />
+ <path
+ inkscape:export-ydpi="772.32001"
+ inkscape:export-xdpi="772.32001"
+ transform="translate(4.03452,15.538)"
+ style="fill:url(#imagebot_21);stroke:url(#imagebot_22)"
+ inkscape:connector-curvature="0"
+ id="imagebot_20"
+ d="m 20.153,10.41 c 0,0 -8.938,-0.6251 -6.188,9.875 H 6.2779 c 0,0 0.5,-11.875 13.875,-9.875 z"
+ label="Layer 1" />
+ <g
+ inkscape:export-ydpi="772.32001"
+ inkscape:export-xdpi="772.32001"
+ style="opacity:0.5;fill:#008000;stroke:#ffffff"
+ id="imagebot_7"
+ transform="matrix(0.50854,0.42965,0.42965,-0.50854,0.06132,46.079)"
+ label="Layer 1">
+ <path
+ inkscape:connector-curvature="0"
+ style="fill:#4d4d4d;fill-opacity:0;stroke:url(#imagebot_6);stroke-width:1.50209999"
+ id="imagebot_8"
+ d="M 51.09,45.944 C 60.21,30.724 46.632,12.201 19.485,11.949 l 0.028,-8.2457 -12.979,15.594 12.834,10.972 c 0,0 0.055,-9.007 0.055,-9.007 17.528,-0.224 35.195,10.103 31.667,24.682 z" />
+ </g>
+ <path
+ inkscape:export-ydpi="772.32001"
+ inkscape:export-xdpi="772.32001"
+ transform="translate(4.03452,15.538)"
+ style="opacity:0.27221997;fill:#ffffff"
+ inkscape:connector-curvature="0"
+ id="imagebot_3"
+ d="m 6.8125,16.5 c 3.5935,-10.441 16.444,-6.145 20.188,-4.5 4.175,0.211 5.675,-2.835 9,-3 -14.05,-9.79 -28.812,-6.5 -29.188,7.5 z"
+ label="Layer 1" />
+ <title
+ id="title3383">Layer 1</title>
+ </g>
+ </g>
+ <g
+ inkscape:groupmode="layer"
+ id="layer2"
+ inkscape:label="Layer 2">
+ <g
+ id="g264"
+ transform="translate(29.818333,1.5340622)"
+ style="fill:#000000;fill-opacity:1">
+ <path
+ sodipodi:nodetypes="ccccccccccc"
+ inkscape:connector-curvature="0"
+ id="path245"
+ d="M -9.1043636,5.4317128 C -20.071956,1.5799989 -28.140748,8.4097214 -23.851037,16.911708 c 0.165977,0.316076 0.262711,0.276139 0.176752,-0.06412 -1.589079,-5.636891 4.80164,-9.6564127 13.06879,-6.9647826 L -11.7666,13.05608 c -0.17051,0.448594 -0.0062,0.76274 0.459668,0.545923 l 6.7320004,-2.651057 c 0.318792,-0.139897 0.347196,-0.38647 0.224026,-0.779766 l -3.034243,-7.8041187 c -0.157643,-0.4035438 -0.386428,-0.4137624 -0.550099,-0.018088 z"
+ style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.01;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+ <path
+ sodipodi:nodetypes="ccccccccccc"
+ inkscape:connector-curvature="0"
+ id="path245-3"
+ d="m -17.77505,23.27118 c 10.9675944,3.851714 19.0363864,-2.978008 14.7466754,-11.479995 -0.165977,-0.316076 -0.262711,-0.276139 -0.176752,0.06412 1.589079,5.636891 -4.801641,9.656413 -13.0687924,6.964783 l 1.161105,-3.173275 c 0.17051,-0.448594 0.0062,-0.76274 -0.459668,-0.545923 l -6.732,2.651057 c -0.318791,0.139897 -0.347195,0.38647 -0.224026,0.779766 l 3.034244,7.804119 c 0.157643,0.403544 0.386428,0.413762 0.550099,0.01809 z"
+ style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.01;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+ </g>
+ </g>
+</svg>
diff --git a/frontend-assets/icons/reload_active.svg b/frontend-assets/icons/reload_active.svg
new file mode 100644
index 0000000..14e20be
--- /dev/null
+++ b/frontend-assets/icons/reload_active.svg
@@ -0,0 +1,419 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ version="1.1"
+ id="svg2"
+ inkscape:version="0.91+devel r14491"
+ width="32"
+ height="32"
+ viewBox="0 0 32 32"
+ sodipodi:docname="reload_active.svg">
+ <metadata
+ id="metadata8">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ <dc:title></dc:title>
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <defs
+ id="defs6">
+ <linearGradient
+ id="linearGradient4225"
+ inkscape:collect="always">
+ <stop
+ id="stop4227"
+ offset="0"
+ style="stop-color:#00ff00;stop-opacity:1;" />
+ <stop
+ id="stop4229"
+ offset="1"
+ style="stop-color:#00ff00;stop-opacity:0;" />
+ </linearGradient>
+ <linearGradient
+ id="imagebot_37">
+ <stop
+ id="imagebot_44"
+ offset="0"
+ stop-color="#ffffff" />
+ <stop
+ id="imagebot_43"
+ offset="1"
+ stop-opacity="0"
+ stop-color="#ffffff" />
+ </linearGradient>
+ <linearGradient
+ id="imagebot_21"
+ y2="21.876775"
+ x2="13.814828"
+ y1="10.965213"
+ x1="12.042996"
+ gradientTransform="scale(1.1419004,0.87573313)"
+ gradientUnits="userSpaceOnUse">
+ <stop
+ id="imagebot_42"
+ offset="0"
+ stop-color="#707070" />
+ <stop
+ style="stop-color:#4d4d4d;stop-opacity:1"
+ id="imagebot_41"
+ offset="0.33333"
+ stop-color="#5b86be" />
+ <stop
+ id="imagebot_40"
+ offset="1"
+ stop-opacity="0"
+ stop-color="#83a8d8" />
+ </linearGradient>
+ <linearGradient
+ id="imagebot_22"
+ y2="22.923376"
+ x2="8.8634028"
+ y1="18.385699"
+ x1="8.8058708"
+ gradientTransform="scale(1.1419004,0.87573313)"
+ gradientUnits="userSpaceOnUse">
+ <stop
+ style="stop-color:#4d4d4d;stop-opacity:1"
+ id="imagebot_39"
+ offset="0"
+ stop-color="#707070" />
+ <stop
+ id="imagebot_38"
+ offset="1"
+ stop-opacity="0"
+ stop-color="#707070" />
+ </linearGradient>
+ <linearGradient
+ id="imagebot_6"
+ y2="26.499712"
+ xlink:href="#imagebot_37"
+ x2="51.063529"
+ y1="26.499712"
+ x1="4.6650344"
+ gradientTransform="scale(1.0486647,0.95359363)"
+ gradientUnits="userSpaceOnUse" />
+ <linearGradient
+ id="imagebot_12"
+ y2="1.01508"
+ x2="0.83337"
+ y1="0.89452"
+ x1="0.86549">
+ <stop
+ id="imagebot_36"
+ offset="0"
+ stop-color="#707070" />
+ <stop
+ id="imagebot_35"
+ offset="1"
+ stop-color="#707070" />
+ </linearGradient>
+ <radialGradient
+ id="imagebot_24"
+ gradientUnits="userSpaceOnUse"
+ cy="36.421"
+ cx="24.837"
+ gradientTransform="matrix(1,0,0,0.53672,0,16.873)"
+ r="15.645">
+ <stop
+ id="imagebot_34"
+ offset="0"
+ stop-color="#707070" />
+ <stop
+ id="imagebot_33"
+ offset="1"
+ stop-opacity="0"
+ stop-color="#707070" />
+ </radialGradient>
+ <linearGradient
+ id="imagebot_18"
+ y2="0.37082"
+ x2="0.15148"
+ y1="0.69903"
+ x1="0.99444">
+ <stop
+ id="imagebot_32"
+ offset="0"
+ stop-color="#b9cfe7" />
+ <stop
+ id="imagebot_31"
+ offset="1"
+ stop-color="#729fcf" />
+ </linearGradient>
+ <linearGradient
+ id="imagebot_11"
+ y2="0.49999"
+ x2="0.83223"
+ y1="0.43678"
+ x1="0.20248">
+ <stop
+ id="imagebot_30"
+ offset="0"
+ stop-color="#729fcf" />
+ <stop
+ id="imagebot_29"
+ offset="1"
+ stop-color="#528ac5" />
+ </linearGradient>
+ <linearGradient
+ id="imagebot_16"
+ y2="27.96628"
+ x2="32.728516"
+ y1="36.263326"
+ x1="32.355118"
+ gradientTransform="scale(1.1430281,0.87486911)"
+ gradientUnits="userSpaceOnUse">
+ <stop
+ style="stop-color:#1a1a1a;stop-opacity:1"
+ id="imagebot_28"
+ offset="0"
+ stop-color="#3977c3" />
+ <stop
+ id="imagebot_27"
+ offset="1"
+ stop-opacity="0"
+ stop-color="#89aedc" />
+ </linearGradient>
+ <linearGradient
+ id="imagebot_15"
+ y2="27.96628"
+ x2="32.728516"
+ y1="35.376378"
+ x1="28.651658"
+ gradientTransform="scale(1.1430281,0.87486911)"
+ gradientUnits="userSpaceOnUse">
+ <stop
+ style="stop-color:#333333;stop-opacity:1"
+ id="imagebot_26"
+ offset="0"
+ stop-color="#c4d7eb" />
+ <stop
+ id="imagebot_25"
+ offset="1"
+ stop-opacity="0"
+ stop-color="#c4d7eb" />
+ </linearGradient>
+ <linearGradient
+ gradientUnits="userSpaceOnUse"
+ y2="30.563"
+ x2="20.062"
+ y1="30.563"
+ x1="7.0625"
+ id="linearGradient4231"
+ xlink:href="#linearGradient4225"
+ inkscape:collect="always" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#imagebot_12"
+ id="linearGradient220"
+ x1="48.895984"
+ y1="44.737763"
+ x2="47.338499"
+ y2="50.583657"
+ gradientTransform="scale(0.96652103,1.0346386)"
+ gradientUnits="userSpaceOnUse" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#imagebot_12"
+ id="linearGradient222"
+ x1="48.669812"
+ y1="44.233604"
+ x2="47.125967"
+ y2="50.028298"
+ gradientTransform="scale(0.97148753,1.0293493)"
+ gradientUnits="userSpaceOnUse" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#imagebot_12"
+ id="linearGradient224"
+ x1="48.669812"
+ y1="44.233604"
+ x2="47.125967"
+ y2="50.028298"
+ gradientTransform="scale(0.97148753,1.0293493)"
+ gradientUnits="userSpaceOnUse" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#imagebot_37"
+ id="linearGradient226"
+ x1="4.5632353"
+ y1="27.739821"
+ x2="52.450109"
+ y2="27.739821"
+ gradientTransform="scale(1.0266686,0.97402418)"
+ gradientUnits="userSpaceOnUse" />
+ </defs>
+ <sodipodi:namedview
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1"
+ objecttolerance="10"
+ gridtolerance="10"
+ guidetolerance="10"
+ inkscape:pageopacity="0"
+ inkscape:pageshadow="2"
+ inkscape:window-width="1764"
+ inkscape:window-height="1171"
+ inkscape:document-units="px"
+ id="namedview4"
+ showgrid="false"
+ width="32"
+ inkscape:zoom="10.429825"
+ inkscape:cx="18.070421"
+ inkscape:cy="3.8319753"
+ inkscape:window-x="1920"
+ inkscape:window-y="0"
+ inkscape:window-maximized="1"
+ inkscape:current-layer="svg2">
+ <inkscape:grid
+ type="xygrid"
+ id="grid29" />
+ </sodipodi:namedview>
+ <g
+ inkscape:groupmode="layer"
+ id="layer1"
+ inkscape:label="Layer 1"
+ style="display:none"
+ sodipodi:insensitive="true">
+ <g
+ style="display:inline"
+ id="imagebot_2"
+ label="Layer 1"
+ transform="matrix(0.53168626,-0.21005051,0.21005051,0.53168626,-37.875177,1.6574228)">
+ <g
+ inkscape:export-ydpi="772.32001"
+ inkscape:export-xdpi="772.32001"
+ style="fill:#ff0000;stroke:#707070"
+ id="imagebot_17"
+ transform="matrix(-0.57905,-0.48923,-0.48923,0.57905,60.95052,28.909)"
+ label="Layer 1">
+ <path
+ inkscape:connector-curvature="0"
+ style="fill:#ff0000;stroke:url(#linearGradient220);stroke-width:1.31916833;stroke-miterlimit:4;stroke-dasharray:none"
+ id="imagebot_19"
+ d="M 44.307,50.23 C 62.821,35.819 49.665,13.412 22.462,12.498 l -0.348,-9.3465 -14.49,17.346 15.09,12.721 c 0,0 -0.252,-9.881 -0.252,-9.881 18.83,0.999 32.982,14.072 21.845,26.892 z" />
+ </g>
+ <path
+ inkscape:export-ydpi="772.32001"
+ inkscape:export-xdpi="772.32001"
+ transform="translate(4.03452,15.538)"
+ style="fill:url(#imagebot_15);stroke:url(#imagebot_16)"
+ inkscape:connector-curvature="0"
+ id="imagebot_14"
+ d="m 28.375,33.438 c 0,0 8.937,0.624 6.187,-9.876 h 7.776 c 0,1.503 -0.588,11.876 -13.963,9.876 z"
+ label="Layer 1" />
+ <g
+ inkscape:export-ydpi="772.32001"
+ inkscape:export-xdpi="772.32001"
+ style="display:block;fill:#00ff00;stroke:url(#linearGradient224);stroke-width:1.31920004"
+ id="imagebot_10"
+ transform="matrix(0.57905,0.48923,0.48923,-0.57905,-3.88648,46.074)"
+ display="block"
+ label="Layer 1">
+ <path
+ inkscape:connector-curvature="0"
+ style="fill:#00ff00;stroke:url(#linearGradient222);stroke-width:1.31920004"
+ id="imagebot_13"
+ d="M 44.307,50.23 C 62.821,35.819 49.665,13.412 22.462,12.498 L 22.399,3.069 7.794,20.424 22.462,33.006 v -9.668 c 18.83,0.999 32.982,14.072 21.845,26.892 z" />
+ </g>
+ <path
+ inkscape:export-ydpi="772.32001"
+ inkscape:export-xdpi="772.32001"
+ transform="translate(4.03452,15.538)"
+ inkscape:connector-curvature="0"
+ style="opacity:0.27221997;fill:url(#linearGradient4231)"
+ id="imagebot_9"
+ d="m 7.0625,38.188 0.0625,-14.876 12.937,-0.374 -4.388,5.178 3.867,2.374 c -3,2.25 -4.55,2.422 -5.55,4.984 l -2.817,-2.11 z"
+ label="Layer 1" />
+ <g
+ inkscape:export-ydpi="772.32001"
+ inkscape:export-xdpi="772.32001"
+ style="opacity:0.5;fill:#ff0000;stroke:#ffffff"
+ id="imagebot_4"
+ transform="matrix(-0.50854,-0.42965,-0.42965,0.50854,57.08352,28.903)"
+ label="Layer 1">
+ <path
+ inkscape:connector-curvature="0"
+ style="fill:#ff0000;stroke:url(#linearGradient226);stroke-width:1.50209999"
+ id="imagebot_5"
+ d="M 51.39,46.506 C 60.51,31.286 47.051,12.432 19.628,12.07 l -0.285,-8.0193 -13.002,15.328 13.468,11.386 -0.182,-9.454 c 18.245,0.382 34.784,10.926 31.763,25.195 z" />
+ </g>
+ <path
+ inkscape:export-ydpi="772.32001"
+ inkscape:export-xdpi="772.32001"
+ transform="matrix(-1.4897,0,0,-1.0013,61.209,75.282)"
+ style="opacity:0.38332998;fill:url(#imagebot_24);fill-rule:evenodd"
+ inkscape:connector-curvature="0"
+ id="imagebot_23"
+ d="m 40.482,36.421 a 15.645,8.3969 0 1 1 -31.29,0 15.645,8.3969 0 1 1 31.29,0 z"
+ label="Layer 1" />
+ <path
+ inkscape:export-ydpi="772.32001"
+ inkscape:export-xdpi="772.32001"
+ transform="translate(4.03452,15.538)"
+ style="fill:url(#imagebot_21);stroke:url(#imagebot_22)"
+ inkscape:connector-curvature="0"
+ id="imagebot_20"
+ d="m 20.153,10.41 c 0,0 -8.938,-0.6251 -6.188,9.875 H 6.2779 c 0,0 0.5,-11.875 13.875,-9.875 z"
+ label="Layer 1" />
+ <g
+ inkscape:export-ydpi="772.32001"
+ inkscape:export-xdpi="772.32001"
+ style="opacity:0.5;fill:#008000;stroke:#ffffff"
+ id="imagebot_7"
+ transform="matrix(0.50854,0.42965,0.42965,-0.50854,0.06132,46.079)"
+ label="Layer 1">
+ <path
+ inkscape:connector-curvature="0"
+ style="fill:#4d4d4d;fill-opacity:0;stroke:url(#imagebot_6);stroke-width:1.50209999"
+ id="imagebot_8"
+ d="M 51.09,45.944 C 60.21,30.724 46.632,12.201 19.485,11.949 l 0.028,-8.2457 -12.979,15.594 12.834,10.972 c 0,0 0.055,-9.007 0.055,-9.007 17.528,-0.224 35.195,10.103 31.667,24.682 z" />
+ </g>
+ <path
+ inkscape:export-ydpi="772.32001"
+ inkscape:export-xdpi="772.32001"
+ transform="translate(4.03452,15.538)"
+ style="opacity:0.27221997;fill:#ffffff"
+ inkscape:connector-curvature="0"
+ id="imagebot_3"
+ d="m 6.8125,16.5 c 3.5935,-10.441 16.444,-6.145 20.188,-4.5 4.175,0.211 5.675,-2.835 9,-3 -14.05,-9.79 -28.812,-6.5 -29.188,7.5 z"
+ label="Layer 1" />
+ <title
+ id="title3383">Layer 1</title>
+ </g>
+ </g>
+ <g
+ inkscape:groupmode="layer"
+ id="layer2"
+ inkscape:label="Layer 2">
+ <g
+ id="g264"
+ transform="translate(29.818333,1.5340622)">
+ <path
+ sodipodi:nodetypes="ccccccccccc"
+ inkscape:connector-curvature="0"
+ id="path245"
+ d="M -9.1043636,5.4317128 C -20.071956,1.5799989 -28.140748,8.4097214 -23.851037,16.911708 c 0.165977,0.316076 0.262711,0.276139 0.176752,-0.06412 -1.589079,-5.636891 4.80164,-9.6564127 13.06879,-6.9647826 L -11.7666,13.05608 c -0.17051,0.448594 -0.0062,0.76274 0.459668,0.545923 l 6.7320004,-2.651057 c 0.318792,-0.139897 0.347196,-0.38647 0.224026,-0.779766 l -3.034243,-7.8041187 c -0.157643,-0.4035438 -0.386428,-0.4137624 -0.550099,-0.018088 z"
+ style="fill:#0054a6;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.01;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+ <path
+ sodipodi:nodetypes="ccccccccccc"
+ inkscape:connector-curvature="0"
+ id="path245-3"
+ d="m -17.77505,23.27118 c 10.9675944,3.851714 19.0363864,-2.978008 14.7466754,-11.479995 -0.165977,-0.316076 -0.262711,-0.276139 -0.176752,0.06412 1.589079,5.636891 -4.801641,9.656413 -13.0687924,6.964783 l 1.161105,-3.173275 c 0.17051,-0.448594 0.0062,-0.76274 -0.459668,-0.545923 l -6.732,2.651057 c -0.318791,0.139897 -0.347195,0.38647 -0.224026,0.779766 l 3.034244,7.804119 c 0.157643,0.403544 0.386428,0.413762 0.550099,0.01809 z"
+ style="fill:#0054a6;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.01;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+ </g>
+ </g>
+</svg>
diff --git a/frontend-assets/icons/show.svg b/frontend-assets/icons/show.svg
new file mode 100644
index 0000000..367bc94
--- /dev/null
+++ b/frontend-assets/icons/show.svg
@@ -0,0 +1,83 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ version="1.1"
+ id="svg2"
+ inkscape:version="0.91+devel r14491"
+ width="32"
+ height="32"
+ viewBox="0 0 32 32"
+ sodipodi:docname="show.svg">
+ <metadata
+ id="metadata8">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ <dc:title />
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <defs
+ id="defs6" />
+ <sodipodi:namedview
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1"
+ objecttolerance="10"
+ gridtolerance="10"
+ guidetolerance="10"
+ inkscape:pageopacity="0"
+ inkscape:pageshadow="2"
+ inkscape:window-width="1764"
+ inkscape:window-height="1171"
+ inkscape:document-units="px"
+ id="namedview4"
+ showgrid="false"
+ width="32"
+ inkscape:zoom="22.627417"
+ inkscape:cx="13.117851"
+ inkscape:cy="13.743637"
+ inkscape:window-x="1920"
+ inkscape:window-y="0"
+ inkscape:window-maximized="1"
+ inkscape:current-layer="svg2">
+ <inkscape:grid
+ type="xygrid"
+ id="grid29" />
+ </sodipodi:namedview>
+ <path
+ inkscape:connector-curvature="0"
+ d="m 0.39229996,15.370659 c 0,0 7.01437074,9.874507 15.66702204,9.874507 8.652652,0 15.667023,-9.874507 15.667023,-9.874507 0,0 -6.54505,-9.8138114 -15.822111,-9.8138114 -9.2770602,0 -15.51193404,9.8138114 -15.51193404,9.8138114 z"
+ id="path184-3"
+ style="fill:#000000;fill-opacity:1;stroke-width:0.01452594"
+ sodipodi:nodetypes="csczc" />
+ <path
+ inkscape:connector-curvature="0"
+ d="m 3.135374,15.375972 c 0,0 5.7862538,8.145621 12.923948,8.145621 7.137695,0 12.923949,-8.145621 12.923949,-8.145621 0,0 -5.399104,-8.0955511 -13.051883,-8.0955511 -7.652778,0 -12.796014,8.0955511 -12.796014,8.0955511 z"
+ id="path184-3-6"
+ style="fill:#ffffff;fill-opacity:1;stroke-width:0.01198266"
+ sodipodi:nodetypes="csczc" />
+ <path
+ style="fill:#000000;fill-opacity:1;stroke:#ffff00;stroke-width:0.00005556;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ id="path377"
+ sodipodi:type="arc"
+ sodipodi:cx="16.05957"
+ sodipodi:cy="15.075125"
+ sodipodi:rx="6.1650872"
+ sodipodi:ry="6.1650872"
+ sodipodi:start="0"
+ sodipodi:end="6.0503933"
+ sodipodi:open="true"
+ d="M 22.224658,15.075125 A 6.1650872,6.1650872 0 0 1 16.418164,21.229774 6.1650872,6.1650872 0 0 1 9.9361984,15.791097 6.1650872,6.1650872 0 0 1 14.988643,9.0037644 6.1650872,6.1650872 0 0 1 22.058361,13.652869" />
+</svg>
diff --git a/frontend-assets/icons/show_active.svg b/frontend-assets/icons/show_active.svg
new file mode 100644
index 0000000..36d5eaa
--- /dev/null
+++ b/frontend-assets/icons/show_active.svg
@@ -0,0 +1,83 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ version="1.1"
+ id="svg2"
+ inkscape:version="0.91+devel r14491"
+ width="32"
+ height="32"
+ viewBox="0 0 32 32"
+ sodipodi:docname="show_active.svg">
+ <metadata
+ id="metadata8">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ <dc:title></dc:title>
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <defs
+ id="defs6" />
+ <sodipodi:namedview
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1"
+ objecttolerance="10"
+ gridtolerance="10"
+ guidetolerance="10"
+ inkscape:pageopacity="0"
+ inkscape:pageshadow="2"
+ inkscape:window-width="1764"
+ inkscape:window-height="1171"
+ inkscape:document-units="px"
+ id="namedview4"
+ showgrid="false"
+ width="32"
+ inkscape:zoom="22.627417"
+ inkscape:cx="13.117851"
+ inkscape:cy="13.743637"
+ inkscape:window-x="1920"
+ inkscape:window-y="0"
+ inkscape:window-maximized="1"
+ inkscape:current-layer="svg2">
+ <inkscape:grid
+ type="xygrid"
+ id="grid29" />
+ </sodipodi:namedview>
+ <path
+ inkscape:connector-curvature="0"
+ d="m 0.39229996,15.370659 c 0,0 7.01437074,9.874507 15.66702204,9.874507 8.652652,0 15.667023,-9.874507 15.667023,-9.874507 0,0 -6.54505,-9.8138114 -15.822111,-9.8138114 -9.2770602,0 -15.51193404,9.8138114 -15.51193404,9.8138114 z"
+ id="path184-3"
+ style="fill:#000000;fill-opacity:1;stroke-width:0.01452594"
+ sodipodi:nodetypes="csczc" />
+ <path
+ inkscape:connector-curvature="0"
+ d="m 3.135374,15.375972 c 0,0 5.7862538,8.145621 12.923948,8.145621 7.137695,0 12.923949,-8.145621 12.923949,-8.145621 0,0 -5.399104,-8.0955511 -13.051883,-8.0955511 -7.652778,0 -12.796014,8.0955511 -12.796014,8.0955511 z"
+ id="path184-3-6"
+ style="fill:#ffffff;fill-opacity:1;stroke-width:0.01198266"
+ sodipodi:nodetypes="csczc" />
+ <path
+ style="fill:#0054a6;fill-opacity:1;stroke:#ffff00;stroke-width:0.00005556;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ id="path377"
+ sodipodi:type="arc"
+ sodipodi:cx="16.05957"
+ sodipodi:cy="15.075125"
+ sodipodi:rx="6.1650872"
+ sodipodi:ry="6.1650872"
+ sodipodi:start="0"
+ sodipodi:end="6.0503933"
+ sodipodi:open="true"
+ d="M 22.224658,15.075125 A 6.1650872,6.1650872 0 0 1 16.418164,21.229774 6.1650872,6.1650872 0 0 1 9.9361984,15.791097 6.1650872,6.1650872 0 0 1 14.988643,9.0037644 6.1650872,6.1650872 0 0 1 22.058361,13.652869" />
+</svg>
diff --git a/frontend-assets/icons/show_all.svg b/frontend-assets/icons/show_all.svg
new file mode 100644
index 0000000..f63d86b
--- /dev/null
+++ b/frontend-assets/icons/show_all.svg
@@ -0,0 +1,130 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ version="1.1"
+ id="svg2"
+ inkscape:version="0.91+devel r14491"
+ width="32"
+ height="32"
+ viewBox="0 0 32 32"
+ sodipodi:docname="show_all.svg">
+ <metadata
+ id="metadata8">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ <dc:title></dc:title>
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <defs
+ id="defs6" />
+ <sodipodi:namedview
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1"
+ objecttolerance="10"
+ gridtolerance="10"
+ guidetolerance="10"
+ inkscape:pageopacity="0"
+ inkscape:pageshadow="2"
+ inkscape:window-width="1764"
+ inkscape:window-height="1171"
+ inkscape:document-units="px"
+ id="namedview4"
+ showgrid="false"
+ width="32"
+ inkscape:zoom="10.429825"
+ inkscape:cx="21.291731"
+ inkscape:cy="8.4274412"
+ inkscape:window-x="1920"
+ inkscape:window-y="0"
+ inkscape:window-maximized="1"
+ inkscape:current-layer="svg2">
+ <inkscape:grid
+ type="xygrid"
+ id="grid29" />
+ </sodipodi:namedview>
+ <path
+ style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:medium;line-height:normal;font-family:sans-serif;font-variant-ligatures:normal;font-variant-position:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-alternates:normal;font-feature-settings:normal;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:normal;word-spacing:normal;text-transform:none;writing-mode:lr-tb;direction:ltr;text-orientation:mixed;dominant-baseline:auto;baseline-shift:baseline;text-anchor:start;white-space:normal;shape-padding:0;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
+ d="M 4.5,8.7265625 V 27 c 2.76e-5,0.276131 0.2238691,0.499972 0.5,0.5 h 5 c 0.676161,0.0096 0.676161,-1.009563 0,-1 H 5.5 V 8.7265625 Z"
+ id="path31"
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="cccccccc" />
+ <path
+ style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1"
+ d="M 5.5130359,12 H 10"
+ id="path33"
+ inkscape:connector-curvature="0" />
+ <path
+ style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:medium;line-height:normal;font-family:sans-serif;font-variant-ligatures:normal;font-variant-position:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-alternates:normal;font-feature-settings:normal;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:normal;word-spacing:normal;text-transform:none;writing-mode:lr-tb;direction:ltr;text-orientation:mixed;dominant-baseline:auto;baseline-shift:baseline;text-anchor:start;white-space:normal;shape-padding:0;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
+ d="m 14.5,17 v 5 c 2.8e-5,0.276131 0.223869,0.499972 0.5,0.5 h 5 c 0.676161,0.0096 0.676161,-1.009563 0,-1 H 15.5 V 17 Z"
+ id="path35"
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="cccccccc" />
+ <path
+ style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.00407575;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ d="m 11.820891,30.003208 c 0.3517,-1.387262 0.862424,-2.590788 2.579476,-3.8022 -1.762427,0.559384 -2.305931,1.617786 -2.305931,1.617786 -1.332691,-2.307032 2.260169,-3.45324 4.370368,-2.427449 0.02931,1.92458 -1.528724,5.060633 -3.365315,3.403194 -0.367481,0.52379 -0.431686,0.834484 -0.562939,1.359495 z"
+ id="path82"
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="ccccccc" />
+ <path
+ style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.00407575;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ d="m 22.038725,25.214932 c 0.3517,-1.387262 0.862424,-2.590788 2.579476,-3.8022 -1.762427,0.559384 -2.305931,1.617786 -2.305931,1.617786 -1.332691,-2.307032 2.260169,-3.45324 4.370368,-2.427449 0.02931,1.92458 -1.528724,5.060633 -3.365315,3.403194 -0.367481,0.52379 -0.431686,0.834484 -0.562939,1.359495 z"
+ id="path82-3"
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="ccccccc" />
+ <g
+ id="g110"
+ transform="matrix(0.55555556,0,0,0.55555556,4.749556,7.0456966)">
+ <path
+ sodipodi:nodetypes="ccccc"
+ inkscape:connector-curvature="0"
+ id="path99"
+ d="m 19,14 4,-2 V 7 l -4,2 z"
+ style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.01;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+ <path
+ sodipodi:nodetypes="ccccc"
+ inkscape:connector-curvature="0"
+ id="path103"
+ d="M 18,14 V 9 L 14,7 v 5 z"
+ style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.01;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+ <path
+ inkscape:connector-curvature="0"
+ id="path105"
+ d="m 14.514613,6 4,2 4,-2 -4,-2 z"
+ style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.01;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+ </g>
+ <g
+ id="g110-6"
+ transform="matrix(0.55555556,0,0,0.55555556,-5.2441368,-0.56587432)">
+ <path
+ sodipodi:nodetypes="ccccc"
+ inkscape:connector-curvature="0"
+ id="path99-7"
+ d="m 19,14 4,-2 V 7 l -4,2 z"
+ style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.01;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+ <path
+ sodipodi:nodetypes="ccccc"
+ inkscape:connector-curvature="0"
+ id="path103-5"
+ d="M 18,14 V 9 L 14,7 v 5 z"
+ style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.01;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+ <path
+ inkscape:connector-curvature="0"
+ id="path105-3"
+ d="m 14.514613,6 4,2 4,-2 -4,-2 z"
+ style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.01;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+ </g>
+</svg>
diff --git a/frontend-assets/icons/show_all_active.svg b/frontend-assets/icons/show_all_active.svg
new file mode 100644
index 0000000..71041a8
--- /dev/null
+++ b/frontend-assets/icons/show_all_active.svg
@@ -0,0 +1,132 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ version="1.1"
+ id="svg2"
+ inkscape:version="0.91+devel r14491"
+ width="32"
+ height="32"
+ viewBox="0 0 32 32"
+ sodipodi:docname="show_all_active.svg">
+ <metadata
+ id="metadata8">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ <dc:title></dc:title>
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <defs
+ id="defs6" />
+ <sodipodi:namedview
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1"
+ objecttolerance="10"
+ gridtolerance="10"
+ guidetolerance="10"
+ inkscape:pageopacity="0"
+ inkscape:pageshadow="2"
+ inkscape:window-width="1920"
+ inkscape:window-height="1131"
+ inkscape:document-units="px"
+ id="namedview4"
+ showgrid="false"
+ width="32"
+ inkscape:zoom="10.429825"
+ inkscape:cx="4.081471"
+ inkscape:cy="8.4274412"
+ inkscape:window-x="0"
+ inkscape:window-y="0"
+ inkscape:window-maximized="1"
+ inkscape:current-layer="svg2">
+ <inkscape:grid
+ type="xygrid"
+ id="grid29" />
+ </sodipodi:namedview>
+ <path
+ style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:medium;line-height:normal;font-family:sans-serif;font-variant-ligatures:normal;font-variant-position:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-alternates:normal;font-feature-settings:normal;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:normal;word-spacing:normal;text-transform:none;writing-mode:lr-tb;direction:ltr;text-orientation:mixed;dominant-baseline:auto;baseline-shift:baseline;text-anchor:start;white-space:normal;shape-padding:0;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
+ d="M 4.5,8.7265625 V 27 c 2.76e-5,0.276131 0.2238691,0.499972 0.5,0.5 h 5 c 0.676161,0.0096 0.676161,-1.009563 0,-1 H 5.5 V 8.7265625 Z"
+ id="path31"
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="cccccccc" />
+ <path
+ style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1"
+ d="M 5.5130359,12 H 10"
+ id="path33"
+ inkscape:connector-curvature="0" />
+ <path
+ style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:medium;line-height:normal;font-family:sans-serif;font-variant-ligatures:normal;font-variant-position:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-alternates:normal;font-feature-settings:normal;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:normal;word-spacing:normal;text-transform:none;writing-mode:lr-tb;direction:ltr;text-orientation:mixed;dominant-baseline:auto;baseline-shift:baseline;text-anchor:start;white-space:normal;shape-padding:0;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
+ d="m 14.5,17 v 5 c 2.8e-5,0.276131 0.223869,0.499972 0.5,0.5 h 5 c 0.676161,0.0096 0.676161,-1.009563 0,-1 H 15.5 V 17 Z"
+ id="path35"
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="cccccccc" />
+ <path
+ style="fill:#00b400;fill-opacity:1;fill-rule:evenodd;stroke:#00b400;stroke-width:0.0048909;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ d="m 11.357989,30.487069 c 0.42204,-1.664714 1.034908,-3.108946 3.095371,-4.56264 -2.114913,0.671261 -2.767117,1.941343 -2.767117,1.941343 -1.59923,-2.768438 2.712202,-4.143888 5.244441,-2.912939 0.03517,2.309496 -1.834469,6.07276 -4.038378,4.083833 -0.440977,0.628548 -0.518023,1.001381 -0.675527,1.631394 z"
+ id="path82"
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="ccccccc" />
+ <path
+ style="fill:#00b400;fill-opacity:1;fill-rule:evenodd;stroke:#00b400;stroke-width:0.0048909;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ d="m 21.575823,25.698793 c 0.42204,-1.664714 1.034908,-3.108946 3.095371,-4.56264 -2.114913,0.671261 -2.767117,1.941343 -2.767117,1.941343 -1.59923,-2.768438 2.712202,-4.143888 5.244441,-2.912939 0.03517,2.309496 -1.834469,6.07276 -4.038378,4.083833 -0.440977,0.628548 -0.518023,1.001381 -0.675527,1.631394 z"
+ id="path82-3"
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="ccccccc" />
+ <g
+ id="g110"
+ transform="matrix(0.66666667,0,0,0.66666667,2.6940004,6.0455577)"
+ style="fill:#ffb400;fill-opacity:1;stroke:#ffb400;stroke-opacity:1">
+ <path
+ sodipodi:nodetypes="ccccc"
+ inkscape:connector-curvature="0"
+ id="path99"
+ d="m 19,14 4,-2 V 7 l -4,2 z"
+ style="fill:#ffb400;fill-opacity:1;fill-rule:evenodd;stroke:#ffb400;stroke-width:0.01;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+ <path
+ sodipodi:nodetypes="ccccc"
+ inkscape:connector-curvature="0"
+ id="path103"
+ d="M 18,14 V 9 L 14,7 v 5 z"
+ style="fill:#ffb400;fill-opacity:1;fill-rule:evenodd;stroke:#ffb400;stroke-width:0.01;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+ <path
+ inkscape:connector-curvature="0"
+ id="path105"
+ d="m 14.514613,6 4,2 4,-2 -4,-2 z"
+ style="fill:#ffb400;fill-opacity:1;fill-rule:evenodd;stroke:#ffb400;stroke-width:0.01;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+ </g>
+ <g
+ id="g110-6"
+ transform="matrix(0.66666667,0,0,0.66666667,-7.2996924,-1.5660132)"
+ style="fill:#ffb400;fill-opacity:1;stroke:#ffb400;stroke-opacity:1">
+ <path
+ sodipodi:nodetypes="ccccc"
+ inkscape:connector-curvature="0"
+ id="path99-7"
+ d="m 19,14 4,-2 V 7 l -4,2 z"
+ style="fill:#ffb400;fill-opacity:1;fill-rule:evenodd;stroke:#ffb400;stroke-width:0.01;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+ <path
+ sodipodi:nodetypes="ccccc"
+ inkscape:connector-curvature="0"
+ id="path103-5"
+ d="M 18,14 V 9 L 14,7 v 5 z"
+ style="fill:#ffb400;fill-opacity:1;fill-rule:evenodd;stroke:#ffb400;stroke-width:0.01;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+ <path
+ inkscape:connector-curvature="0"
+ id="path105-3"
+ d="m 14.514613,6 4,2 4,-2 -4,-2 z"
+ style="fill:#ffb400;fill-opacity:1;fill-rule:evenodd;stroke:#ffb400;stroke-width:0.01;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+ </g>
+</svg>
diff --git a/frontend-assets/icons/show_children.svg b/frontend-assets/icons/show_children.svg
new file mode 100644
index 0000000..8f9a754
--- /dev/null
+++ b/frontend-assets/icons/show_children.svg
@@ -0,0 +1,118 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ version="1.1"
+ id="svg2"
+ inkscape:version="0.91+devel r14491"
+ width="32"
+ height="32"
+ viewBox="0 0 32 32"
+ sodipodi:docname="show_children.svg">
+ <metadata
+ id="metadata8">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ <dc:title></dc:title>
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <defs
+ id="defs6" />
+ <sodipodi:namedview
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1"
+ objecttolerance="10"
+ gridtolerance="10"
+ guidetolerance="10"
+ inkscape:pageopacity="0"
+ inkscape:pageshadow="2"
+ inkscape:window-width="1764"
+ inkscape:window-height="1171"
+ inkscape:document-units="px"
+ id="namedview4"
+ showgrid="false"
+ width="32"
+ inkscape:zoom="10.429825"
+ inkscape:cx="21.291731"
+ inkscape:cy="8.4274412"
+ inkscape:window-x="1920"
+ inkscape:window-y="0"
+ inkscape:window-maximized="1"
+ inkscape:current-layer="svg2">
+ <inkscape:grid
+ type="xygrid"
+ id="grid29" />
+ </sodipodi:namedview>
+ <path
+ style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:medium;line-height:normal;font-family:sans-serif;font-variant-ligatures:normal;font-variant-position:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-alternates:normal;font-feature-settings:normal;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:normal;word-spacing:normal;text-transform:none;writing-mode:lr-tb;direction:ltr;text-orientation:mixed;dominant-baseline:auto;baseline-shift:baseline;text-anchor:start;white-space:normal;shape-padding:0;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
+ d="M 4.5,8.7265625 V 27 c 2.76e-5,0.276131 0.2238691,0.499972 0.5,0.5 h 5 c 0.676161,0.0096 0.676161,-1.009563 0,-1 H 5.5 V 8.7265625 Z"
+ id="path31"
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="cccccccc" />
+ <path
+ style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1"
+ d="M 5.5130359,12 H 10"
+ id="path33"
+ inkscape:connector-curvature="0" />
+ <path
+ style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.00407575;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ d="m 11.820891,30.003208 c 0.3517,-1.387262 0.862424,-2.590788 2.579476,-3.8022 -1.762427,0.559384 -2.305931,1.617786 -2.305931,1.617786 -1.332691,-2.307032 2.260169,-3.45324 4.370368,-2.427449 0.02931,1.92458 -1.528724,5.060633 -3.365315,3.403194 -0.367481,0.52379 -0.431686,0.834484 -0.562939,1.359495 z"
+ id="path82"
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="ccccccc" />
+ <g
+ id="g110"
+ transform="matrix(0.55555556,0,0,0.55555556,4.749556,7.0456966)">
+ <path
+ sodipodi:nodetypes="ccccc"
+ inkscape:connector-curvature="0"
+ id="path99"
+ d="m 19,14 4,-2 V 7 l -4,2 z"
+ style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.01;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+ <path
+ sodipodi:nodetypes="ccccc"
+ inkscape:connector-curvature="0"
+ id="path103"
+ d="M 18,14 V 9 L 14,7 v 5 z"
+ style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.01;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+ <path
+ inkscape:connector-curvature="0"
+ id="path105"
+ d="m 14.514613,6 4,2 4,-2 -4,-2 z"
+ style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.01;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+ </g>
+ <g
+ id="g110-6"
+ transform="matrix(0.55555556,0,0,0.55555556,-5.2441368,-0.56587432)">
+ <path
+ sodipodi:nodetypes="ccccc"
+ inkscape:connector-curvature="0"
+ id="path99-7"
+ d="m 19,14 4,-2 V 7 l -4,2 z"
+ style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.01;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+ <path
+ sodipodi:nodetypes="ccccc"
+ inkscape:connector-curvature="0"
+ id="path103-5"
+ d="M 18,14 V 9 L 14,7 v 5 z"
+ style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.01;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+ <path
+ inkscape:connector-curvature="0"
+ id="path105-3"
+ d="m 14.514613,6 4,2 4,-2 -4,-2 z"
+ style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.01;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+ </g>
+</svg>
diff --git a/frontend-assets/icons/show_children_active.svg b/frontend-assets/icons/show_children_active.svg
new file mode 100644
index 0000000..c8a27df
--- /dev/null
+++ b/frontend-assets/icons/show_children_active.svg
@@ -0,0 +1,120 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ version="1.1"
+ id="svg2"
+ inkscape:version="0.91+devel r14491"
+ width="32"
+ height="32"
+ viewBox="0 0 32 32"
+ sodipodi:docname="show_children_active.svg">
+ <metadata
+ id="metadata8">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ <dc:title></dc:title>
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <defs
+ id="defs6" />
+ <sodipodi:namedview
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1"
+ objecttolerance="10"
+ gridtolerance="10"
+ guidetolerance="10"
+ inkscape:pageopacity="0"
+ inkscape:pageshadow="2"
+ inkscape:window-width="1920"
+ inkscape:window-height="1131"
+ inkscape:document-units="px"
+ id="namedview4"
+ showgrid="false"
+ width="32"
+ inkscape:zoom="10.429825"
+ inkscape:cx="4.081471"
+ inkscape:cy="8.4274412"
+ inkscape:window-x="0"
+ inkscape:window-y="0"
+ inkscape:window-maximized="1"
+ inkscape:current-layer="svg2">
+ <inkscape:grid
+ type="xygrid"
+ id="grid29" />
+ </sodipodi:namedview>
+ <path
+ style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:medium;line-height:normal;font-family:sans-serif;font-variant-ligatures:normal;font-variant-position:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-alternates:normal;font-feature-settings:normal;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:normal;word-spacing:normal;text-transform:none;writing-mode:lr-tb;direction:ltr;text-orientation:mixed;dominant-baseline:auto;baseline-shift:baseline;text-anchor:start;white-space:normal;shape-padding:0;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
+ d="M 4.5,8.7265625 V 27 c 2.76e-5,0.276131 0.2238691,0.499972 0.5,0.5 h 5 c 0.676161,0.0096 0.676161,-1.009563 0,-1 H 5.5 V 8.7265625 Z"
+ id="path31"
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="cccccccc" />
+ <path
+ style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1"
+ d="M 5.5130359,12 H 10"
+ id="path33"
+ inkscape:connector-curvature="0" />
+ <path
+ style="fill:#00b400;fill-opacity:1;fill-rule:evenodd;stroke:#00b400;stroke-width:0.0048909;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ d="m 11.357989,30.487069 c 0.42204,-1.664714 1.034908,-3.108946 3.095371,-4.56264 -2.114913,0.671261 -2.767117,1.941343 -2.767117,1.941343 -1.59923,-2.768438 2.712202,-4.143888 5.244441,-2.912939 0.03517,2.309496 -1.834469,6.07276 -4.038378,4.083833 -0.440977,0.628548 -0.518023,1.001381 -0.675527,1.631394 z"
+ id="path82"
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="ccccccc" />
+ <g
+ id="g110"
+ transform="matrix(0.66666667,0,0,0.66666667,2.6940004,6.0455577)"
+ style="fill:#ffb400;fill-opacity:1;stroke:#ffb400;stroke-opacity:1">
+ <path
+ sodipodi:nodetypes="ccccc"
+ inkscape:connector-curvature="0"
+ id="path99"
+ d="m 19,14 4,-2 V 7 l -4,2 z"
+ style="fill:#ffb400;fill-opacity:1;fill-rule:evenodd;stroke:#ffb400;stroke-width:0.01;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+ <path
+ sodipodi:nodetypes="ccccc"
+ inkscape:connector-curvature="0"
+ id="path103"
+ d="M 18,14 V 9 L 14,7 v 5 z"
+ style="fill:#ffb400;fill-opacity:1;fill-rule:evenodd;stroke:#ffb400;stroke-width:0.01;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+ <path
+ inkscape:connector-curvature="0"
+ id="path105"
+ d="m 14.514613,6 4,2 4,-2 -4,-2 z"
+ style="fill:#ffb400;fill-opacity:1;fill-rule:evenodd;stroke:#ffb400;stroke-width:0.01;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+ </g>
+ <g
+ id="g110-6"
+ transform="matrix(0.66666667,0,0,0.66666667,-7.2996924,-1.5660132)"
+ style="fill:#ffb400;fill-opacity:1;stroke:#ffb400;stroke-opacity:1">
+ <path
+ sodipodi:nodetypes="ccccc"
+ inkscape:connector-curvature="0"
+ id="path99-7"
+ d="m 19,14 4,-2 V 7 l -4,2 z"
+ style="fill:#ffb400;fill-opacity:1;fill-rule:evenodd;stroke:#ffb400;stroke-width:0.01;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+ <path
+ sodipodi:nodetypes="ccccc"
+ inkscape:connector-curvature="0"
+ id="path103-5"
+ d="M 18,14 V 9 L 14,7 v 5 z"
+ style="fill:#ffb400;fill-opacity:1;fill-rule:evenodd;stroke:#ffb400;stroke-width:0.01;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+ <path
+ inkscape:connector-curvature="0"
+ id="path105-3"
+ d="m 14.514613,6 4,2 4,-2 -4,-2 z"
+ style="fill:#ffb400;fill-opacity:1;fill-rule:evenodd;stroke:#ffb400;stroke-width:0.01;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+ </g>
+</svg>
diff --git a/frontend-assets/icons/tree_branch.svg b/frontend-assets/icons/tree_branch.svg
new file mode 100644
index 0000000..f45dea6
--- /dev/null
+++ b/frontend-assets/icons/tree_branch.svg
@@ -0,0 +1,78 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ version="1.1"
+ id="svg2"
+ inkscape:version="0.91+devel r14491"
+ width="32"
+ height="32"
+ viewBox="0 0 32 32"
+ sodipodi:docname="tree_branch.svg">
+ <metadata
+ id="metadata8">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ <dc:title />
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <defs
+ id="defs6" />
+ <sodipodi:namedview
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1"
+ objecttolerance="10"
+ gridtolerance="10"
+ guidetolerance="10"
+ inkscape:pageopacity="0"
+ inkscape:pageshadow="2"
+ inkscape:window-width="1764"
+ inkscape:window-height="1171"
+ inkscape:document-units="px"
+ id="namedview4"
+ showgrid="true"
+ width="32"
+ inkscape:zoom="20.85965"
+ inkscape:cx="4.734334"
+ inkscape:cy="10.548157"
+ inkscape:window-x="1920"
+ inkscape:window-y="0"
+ inkscape:window-maximized="1"
+ inkscape:current-layer="svg2">
+ <inkscape:grid
+ type="xygrid"
+ id="grid29" />
+ </sodipodi:namedview>
+ <rect
+ style="fill:none;fill-opacity:1;stroke:#000000;stroke-width:0.02;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ id="rect221"
+ width="32"
+ height="32"
+ x="0"
+ y="0" />
+ <path
+ style="fill:none;fill-rule:evenodd;stroke:#d2d2d2;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ d="M 13,0 V 32.071488"
+ id="path219"
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="cc" />
+ <path
+ style="fill:none;fill-rule:evenodd;stroke:#d2d2d2;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ d="M 13,16 H 32.035744"
+ id="path219-3"
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="cc" />
+</svg>
diff --git a/frontend-assets/icons/tree_cont.svg b/frontend-assets/icons/tree_cont.svg
new file mode 100644
index 0000000..ebd1237
--- /dev/null
+++ b/frontend-assets/icons/tree_cont.svg
@@ -0,0 +1,72 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ version="1.1"
+ id="svg2"
+ inkscape:version="0.91+devel r14491"
+ width="32"
+ height="32"
+ viewBox="0 0 32 32"
+ sodipodi:docname="tree_cont.svg">
+ <metadata
+ id="metadata8">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ <dc:title />
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <defs
+ id="defs6" />
+ <sodipodi:namedview
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1"
+ objecttolerance="10"
+ gridtolerance="10"
+ guidetolerance="10"
+ inkscape:pageopacity="0"
+ inkscape:pageshadow="2"
+ inkscape:window-width="1764"
+ inkscape:window-height="1171"
+ inkscape:document-units="px"
+ id="namedview4"
+ showgrid="true"
+ width="32"
+ inkscape:zoom="20.85965"
+ inkscape:cx="4.734334"
+ inkscape:cy="10.548157"
+ inkscape:window-x="1920"
+ inkscape:window-y="0"
+ inkscape:window-maximized="1"
+ inkscape:current-layer="svg2">
+ <inkscape:grid
+ type="xygrid"
+ id="grid29" />
+ </sodipodi:namedview>
+ <rect
+ style="fill:none;fill-opacity:1;stroke:#000000;stroke-width:0.02;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ id="rect221"
+ width="32"
+ height="32"
+ x="0"
+ y="0" />
+ <path
+ style="fill:none;fill-rule:evenodd;stroke:#d2d2d2;stroke-width:2;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ d="m 13,0 v 16.035744 16"
+ id="path219"
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="ccc" />
+</svg>
diff --git a/frontend-assets/icons/tree_empty.svg b/frontend-assets/icons/tree_empty.svg
new file mode 100644
index 0000000..a7808d1
--- /dev/null
+++ b/frontend-assets/icons/tree_empty.svg
@@ -0,0 +1,66 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ version="1.1"
+ id="svg2"
+ inkscape:version="0.91+devel r14491"
+ width="32"
+ height="32"
+ viewBox="0 0 32 32"
+ sodipodi:docname="tree_empty.svg">
+ <metadata
+ id="metadata8">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ <dc:title></dc:title>
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <defs
+ id="defs6" />
+ <sodipodi:namedview
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1"
+ objecttolerance="10"
+ gridtolerance="10"
+ guidetolerance="10"
+ inkscape:pageopacity="0"
+ inkscape:pageshadow="2"
+ inkscape:window-width="1920"
+ inkscape:window-height="1131"
+ inkscape:document-units="px"
+ id="namedview4"
+ showgrid="true"
+ width="32"
+ inkscape:zoom="20.85965"
+ inkscape:cx="13.339464"
+ inkscape:cy="10.068763"
+ inkscape:window-x="0"
+ inkscape:window-y="0"
+ inkscape:window-maximized="1"
+ inkscape:current-layer="svg2">
+ <inkscape:grid
+ type="xygrid"
+ id="grid29" />
+ </sodipodi:namedview>
+ <rect
+ style="fill:none;fill-opacity:1;stroke:#000000;stroke-width:0.02;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ id="rect221"
+ width="32"
+ height="32"
+ x="0"
+ y="0" />
+</svg>
diff --git a/frontend-assets/icons/tree_last_branch.svg b/frontend-assets/icons/tree_last_branch.svg
new file mode 100644
index 0000000..efb8e20
--- /dev/null
+++ b/frontend-assets/icons/tree_last_branch.svg
@@ -0,0 +1,72 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ version="1.1"
+ id="svg2"
+ inkscape:version="0.91+devel r14491"
+ width="32"
+ height="32"
+ viewBox="0 0 32 32"
+ sodipodi:docname="tree_last_branch.svg">
+ <metadata
+ id="metadata8">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ <dc:title />
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <defs
+ id="defs6" />
+ <sodipodi:namedview
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1"
+ objecttolerance="10"
+ gridtolerance="10"
+ guidetolerance="10"
+ inkscape:pageopacity="0"
+ inkscape:pageshadow="2"
+ inkscape:window-width="1764"
+ inkscape:window-height="1171"
+ inkscape:document-units="px"
+ id="namedview4"
+ showgrid="true"
+ width="32"
+ inkscape:zoom="20.85965"
+ inkscape:cx="13.339464"
+ inkscape:cy="10.548157"
+ inkscape:window-x="1920"
+ inkscape:window-y="0"
+ inkscape:window-maximized="1"
+ inkscape:current-layer="svg2">
+ <inkscape:grid
+ type="xygrid"
+ id="grid29" />
+ </sodipodi:namedview>
+ <rect
+ style="fill:none;fill-opacity:1;stroke:#000000;stroke-width:0.02;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ id="rect221"
+ width="32"
+ height="32"
+ x="0"
+ y="0" />
+ <path
+ style="fill:none;fill-rule:evenodd;stroke:#d2d2d2;stroke-width:2;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ d="M 13,0 V 16.035744 L 32,16"
+ id="path219"
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="ccc" />
+</svg>
diff --git a/frontend/config/config.component.css b/frontend/config/config.component.css
index 30ccea5..c2336b0 100644
--- a/frontend/config/config.component.css
+++ b/frontend/config/config.component.css
@@ -13,6 +13,15 @@
padding-right: 0.5em;
}
+.tab-icon {
+ vertical-align: middle;
+ height: 1em;
+}
+
+.tab-add {
+ filter: invert(100%);
+}
+
.tab-add:hover {
color: green;
}
@@ -23,14 +32,14 @@
color: blue;
}
-nav {
+#confignav {
position: fixed;
width: 100%;
background-color: #3B4257;
padding-left: 1em;
}
-nav a {
+#confignav a {
cursor: pointer;
text-decoration: none;
display: inline-block;
@@ -38,16 +47,18 @@
color: #FAFAFA;
}
-nav a:visited, a:link {
+#confignav a:visited,
+#confignav a:link {
color: inherited;
}
-nav a:hover, nav a.active {
+#confignav a:hover,
+#confignav a.active {
background-color: #FAFAFA;
- color: #000
+ color: #000;
}
-nav a.active:hover {
+#confignav a.active:hover {
cursor: default;
}
@@ -67,11 +78,14 @@
}
#config-data {
- padding-left: 11em;
- display: inline-block;
width: 100%;
}
+.item_action_expand,
+.item_action_collapse {
+ height: 1em;
+}
+
.item_action_collapse:hover {
color:red;
}
diff --git a/frontend/config/config.component.html b/frontend/config/config.component.html
index 654b94c..8b398e5 100644
--- a/frontend/config/config.component.html
+++ b/frontend/config/config.component.html
@@ -1,20 +1,34 @@
-<nav #navbar>
- <a *ngFor="let session of sessionsService.sessions" [class.active]="session.key==activeSession.key"
- (click)="changeActiveSession(session.key)">{{session.device.hostname}}:{{session.device.port}}
- <span *ngIf="session.key==activeSession.key" class="tab-reload tab-action-first" (click)="reloadData(session.key)">o</span>
- <span class="tab-close tab-action-last" (click)="disconnect(session.key)">x</span>
- </a><a (click)="addSession()"><span class="tab-add tab-action-first tab-action-last">+</span></a>
+<nav #confignav id="confignav">
+ <a *ngFor="let session of sessionsService.sessions" [class.active]="session.key==activeSession.key"
+ (click)="changeActiveSession(session.key)">{{session.device.hostname}}:{{session.device.port}}
+ <!--<span *ngIf="session.key==activeSession.key" class="tab-reload tab-action-first" (click)="reloadData(session.key)">o</span>-->
+ <img *ngIf="session.key==activeSession.key" class="tab-icon tab-reload tab-action-first" src="assets/netopeer/icons/reload.svg" alt="o" title="reload"
+ onmouseover="this.src='assets/netopeer/icons/reload_active.svg'"
+ onmouseout="this.src='assets/netopeer/icons/reload.svg'" (click)="reloadData()"/>
+ <img class="tab-icon tab-close tab-action-last" src="assets/netopeer/icons/close.svg" alt="x" title="disconnect"
+ onmouseover="this.src='assets/netopeer/icons/close_active.svg'"
+ onmouseout="this.src='assets/netopeer/icons/close.svg'" (click)="disconnect(session.key)"/>
+ </a><a (click)="addSession()" onmouseout="getElementById('tabadd').style.filter='invert(100%)'" onmouseover="getElementById('tabadd').style.filter='invert(0%)'">
+ <img id="tabadd" class="tab-icon tab-add tab-action-last" src="assets/netopeer/icons/add.svg" alt="+" title="add connection"
+ onmouseover="this.src='assets/netopeer/icons/add_active.svg'"
+ onmouseout="this.src='assets/netopeer/icons/add.svg'"/>
+ </a>
</nav>
-<div class="netopeer-content" [style.padding-top]="'calc(' + navbar.offsetHeight + 'px - -0.7em)'">
+<div class="netopeer-content" [style.padding-top]="'calc(' + confignav.offsetHeight + 'px - -0.7em)'">
<div *ngIf="sessionsService.activeSession">
- <p class="msg-failure msg-rounded" *ngIf="err_msg"><span class="msg-close" (click)="err_msg=''">x</span>{{err_msg}}</p>
-
+ <p class="msg-failure msg-rounded" *ngIf="err_msg"><img class="msg-close" (click)="err_msg=''" src="assets/netopeer/icons/close_active.svg" alt="x" title="close"/>{{err_msg}}</p>
<table class="items">
<tr class="item_header">
<th class="item_left item_actions" [ngSwitch]="activeSession.cpbltsVisibility">
- <span *ngSwitchCase="false" class="item_action_expand" (click)="getCapabilities(activeSession.key);activeSession.cpbltsVisibility=true">v</span>
- <span *ngSwitchCase="true" class="item_action_collapse" (click)="activeSession.cpbltsVisibility=false">x</span>
+ <img *ngSwitchCase="false" class="item_action_expand" (click)="getCapabilities(activeSession.key);activeSession.cpbltsVisibility=true"
+ src="assets/netopeer/icons/show.svg" alt="v" title="show"
+ onmouseover="this.src='assets/netopeer/icons/show_active.svg'"
+ onmouseout="this.src='assets/netopeer/icons/show.svg'"/>
+ <img *ngSwitchCase="true" class="item_action_collapse" (click)="activeSession.cpbltsVisibility=false"
+ src="assets/netopeer/icons/close.svg" alt="x" title="close"
+ onmouseover="this.src='assets/netopeer/icons/close_active.svg'"
+ onmouseout="this.src='assets/netopeer/icons/close.svg'"/>
</th>
<th>Capability / Module</th>
<th class="item_right">Version</th>
@@ -30,24 +44,29 @@
<table class="items">
<tr class="item_header">
- <th class="item_left item_actions" [ngSwitch]="activeSession.dataVisibility">
- <span *ngSwitchCase="false" class="item_action_expand" (click)="rpcGet(activeSession.key);activeSession.dataVisibility=true">v</span>
- <span *ngSwitchCase="true" class="item_action_collapse" (click)="activeSession.dataVisibility=false">x</span>
- </th>
- <th class="item_right">Data</th>
+ <th class="item_left item_actions" style="cursor: default;"> </th>
+ <th class="item_right" >Data</th>
</tr>
</table>
- <ng-container *ngIf="activeSession.dataVisibility==true && activeSession.data">
-<!--
- <div id="config-toc">
- <div class="config-toc-item" [ngSwitch]="activeSession.dataVisibility">
- <a *ngSwitchCase="false" (click)="rpcGet(activeSession.key);activeSession.dataVisibility=true">show data</a>
- <a *ngSwitchCase="true" (click)="activeSession.dataVisibility=false">hide data</a>
- </div>
- </div>
--->
+ <div>
+ <img *ngIf="activeSession.dataVisibility!='root'" class="icon_action" (click)="rpcGet(false);activeSession.dataVisibility='root'"
+ src="assets/netopeer/icons/show_children.svg" alt="v" title="expand roots"
+ onmouseover="this.src='assets/netopeer/icons/show_children_active.svg'"
+ onmouseout="this.src='assets/netopeer/icons/show_children.svg'"/>
+ <img *ngIf="activeSession.dataVisibility!='all'" class="icon_action" (click)="rpcGet(true);activeSession.dataVisibility='all'"
+ src="assets/netopeer/icons/show_all.svg" alt="w" title="expand all"
+ onmouseover="this.src='assets/netopeer/icons/show_all_active.svg'"
+ onmouseout="this.src='assets/netopeer/icons/show_all.svg'"/>
+ <img *ngIf="activeSession.dataVisibility!='none'" class="icon_action" (click)="activeSession.dataVisibility='none'"
+ src="assets/netopeer/icons/close.svg" alt="x" title="close"
+ onmouseover="this.src='assets/netopeer/icons/close_active.svg'"
+ onmouseout="this.src='assets/netopeer/icons/close.svg'"/>
+ <span><input type="checkbox" name="statusVisibility" [checked]="activeSession.statusVisibility" (change)="activeSession.statusVisibility = !activeSession.statusVisibility"/> include status data</span>
+ </div><br/>
+ <ng-container *ngIf="activeSession.dataVisibility!='none' && activeSession.data">
<div id="config-data">
- <pre >{{activeSession.data | json}}</pre>
+ <tree-view [treeData]="activeSession.data"></tree-view>
+ <!--<pre>{{activeSession.data | json}}</pre>-->
</div>
</ng-container>
</div>
diff --git a/frontend/config/config.component.ts b/frontend/config/config.component.ts
index 0618771..7adf96d 100644
--- a/frontend/config/config.component.ts
+++ b/frontend/config/config.component.ts
@@ -3,12 +3,11 @@
import {SessionsService} from './sessions.service';
import {Session} from './session';
-import {Device} from '../inventory/device';
@Component({
selector: 'netopeer-config',
templateUrl: './config.component.html',
- styleUrls: ['../netopeer.css', './config.component.css', '../inventory/inventory.component.css']
+ styleUrls: ['../netopeer.css', './config.component.css', './tree.component.css', '../inventory/inventory.component.css']
})
export class ConfigComponent implements OnInit, OnDestroy {
@@ -16,15 +15,20 @@
activeSession: Session;
err_msg = "";
+ objectKeys = Object.keys;
constructor(private sessionsService: SessionsService, private router: Router) {}
addSession() {
this.router.navigateByUrl('/netopeer/inventory/devices');
}
- reloadData(key: string) {
+ reloadData() {
this.activeSession.data = null;
- this.rpcGet(key);
+ if (this.activeSession.dataVisibility == 'all') {
+ this.rpcGet(true);
+ } else if(this.activeSession.dataVisibility == 'root') {
+ this.rpcGet(false);
+ }
}
disconnect(key: string) {
@@ -45,9 +49,10 @@
}
this.sessionsService.getCpblts(key).subscribe(result => {
if (result['success']) {
- this.activeSession.cpblts = result['capabilities']
+ this.activeSession.cpblts = result['capabilities'];
} else {
- this.err_msg = result['error-msg']
+ this.activeSession.cpbltsVisibility = false;
+ this.err_msg = result['error-msg'];
}
});
}
@@ -105,17 +110,23 @@
return version;
}
- rpcGet(key: string) {
+ rpcGet(all: boolean) {
if (this.activeSession.data) {
- return;
+ if ((all && this.activeSession.dataVisibility == 'all') ||
+ (!all && this.activeSession.dataVisibility == 'root')) {
+ return;
+ }
}
- this.sessionsService.rpcGet(key).subscribe(result => {
+ this.sessionsService.rpcGetSubtree(this.activeSession.key, all).subscribe(result => {
if (result['success']) {
- this.activeSession.data = result['data']
- } else if ('error-msg' in result) {
- this.err_msg = result['error-msg']
+ this.activeSession.data = result['data'];
} else {
- this.err_msg = result['error'][0]['message']
+ this.activeSession.dataVisibility = 'none';
+ if ('error-msg' in result) {
+ this.err_msg = result['error-msg'];
+ } else {
+ this.err_msg = result['error'][0]['message'];
+ }
}
});
}
diff --git a/frontend/config/session.ts b/frontend/config/session.ts
index 1ca2c3c..9f56289 100644
--- a/frontend/config/session.ts
+++ b/frontend/config/session.ts
@@ -4,9 +4,10 @@
constructor (
public key: string,
public device: Device,
- public data: string = "",
+ public data = null,
public cpblts: string = "",
- public dataVisibility: boolean = false,
- public cpbltsVisibility: boolean = false
+ public dataVisibility: string = 'none',
+ public statusVisibility: boolean = true,
+ public cpbltsVisibility: boolean = false,
) {}
}
diff --git a/frontend/config/sessions.service.ts b/frontend/config/sessions.service.ts
index a947a4f..83d99f9 100644
--- a/frontend/config/sessions.service.ts
+++ b/frontend/config/sessions.service.ts
@@ -84,9 +84,13 @@
.catch((err: Response | any) => Observable.throw(err));
}
- rpcGet(key: string): Observable<string[]> {
+ rpcGetSubtree(key: string, all: boolean, path: string = ""): Observable<string[]> {
let params = new URLSearchParams();
params.set('key', key);
+ params.set('recursive', String(all));
+ if (path.length) {
+ params.set('path', path);
+ }
let options = new RequestOptions({ search: params });
return this.http.get('/netopeer/session/rpcGet', options)
.map((resp: Response) => resp.json())
@@ -127,7 +131,7 @@
.map((resp: Response) => resp.json())
.do(resp => {
if (resp['success']) {
- this.sessions.push(new Session(resp['session-key'], dev, "", "", false, false));
+ this.sessions.push(new Session(resp['session-key'], dev));
this.activeSession = resp['session-key'];
localStorage.setItem('sessions', JSON.stringify(this.sessions));
localStorage.setItem('activeSession', this.activeSession);
diff --git a/frontend/config/tree.component.css b/frontend/config/tree.component.css
new file mode 100644
index 0000000..9534da8
--- /dev/null
+++ b/frontend/config/tree.component.css
@@ -0,0 +1,46 @@
+.subtree {
+ cursor: default;
+ display: block;
+ width: 100%;
+}
+
+.node {
+ width: 100%;
+}
+.node:hover {
+ background-color: #e1e1e1
+}
+.node div {
+ display: inline-block;
+}
+
+.status {
+ color: grey;
+}
+
+.icon,
+.icon_action {
+ font-size: xx-small;
+ height: 2em;
+}
+
+.icon_action {
+ cursor: pointer;
+}
+
+.module_name {
+ float: right;
+}
+
+.children {
+ padding-left: 0em;
+}
+
+.value {
+ display: inline-block;
+ padding-left: 1.5em;
+}
+
+.indentation {
+ height: 1.7em;
+}
\ No newline at end of file
diff --git a/frontend/config/tree.component.html b/frontend/config/tree.component.html
new file mode 100644
index 0000000..22e7b75
--- /dev/null
+++ b/frontend/config/tree.component.html
@@ -0,0 +1,44 @@
+<ng-container *ngFor="let node of treeData">
+<div class="subtree" *ngIf="node['info']['config'] || activeSession.statusVisibility" [class.status]="!node['info']['config']">
+ <div class="node">
+ <ng-container *ngFor="let indent of indentation">
+ <img *ngIf="!indent" class="indentation" src="assets/netopeer/icons/tree_cont.svg"/>
+ <img *ngIf="indent" class="indentation" src="assets/netopeer/icons/tree_empty.svg"/>
+ </ng-container>
+ <img *ngIf="node['last']" class="indentation" src="assets/netopeer/icons/tree_last_branch.svg"/>
+ <img *ngIf="!node['last']" class="indentation" src="assets/netopeer/icons/tree_branch.svg"/>
+ <ng-container [ngSwitch]="node['info']['type']">
+ <img *ngSwitchCase="1" class="icon" src="assets/netopeer/icons/container.svg" alt="container" title="container"/>
+ <img *ngSwitchCase="4" class="icon" src="assets/netopeer/icons/leaf.svg" alt="leaf" title="leaf"/>
+ <img *ngSwitchCase="8" class="icon" src="assets/netopeer/icons/leaflist.svg" alt="leaf-list" title="leaf-list"/>
+ <img *ngSwitchCase="16" class="icon" src="assets/netopeer/icons/container.svg" alt="list" title="list"/>
+ <img *ngSwitchCase="32800" class="icon" src="assets/netopeer/icons/anydata.svg" alt="anydata" title="anydata"/>
+ </ng-container>
+ <img class="icon" src="assets/netopeer/icons/info.svg"
+ onmouseover="this.src='assets/netopeer/icons/info_active.svg'"
+ onmouseout="this.src='assets/netopeer/icons/info.svg'" alt="info" title="{{node['info']['dsc']}}"/>
+ <ng-container *ngIf="expandable(node)">
+ <img *ngIf="hasHiddenChild(node)" (click)="getSubtree(node, true)"
+ class="icon_action" src="assets/netopeer/icons/show_all.svg"
+ onmouseover="this.src='assets/netopeer/icons/show_all_active.svg'"
+ onmouseout="this.src='assets/netopeer/icons/show_all.svg'" alt="show-all" title="expand subtree"/>
+ <img *ngIf="!node['children']" (click)="getSubtree(node, false)"
+ class="icon_action" src="assets/netopeer/icons/show_children.svg"
+ onmouseover="this.src='assets/netopeer/icons/show_children_active.svg'"
+ onmouseout="this.src='assets/netopeer/icons/show_children.svg'" alt="show-children" title="expand children"/>
+ <img *ngIf="node['children']" (click)="collapse(node)"
+ class="icon_action" src="assets/netopeer/icons/collapse.svg" alt="collapse" title="collapse"
+ onmouseover="this.src='assets/netopeer/icons/collapse_active.svg'"
+ onmouseout="this.src='assets/netopeer/icons/collapse.svg'"/>
+ </ng-container>
+ <div>{{node['info']['name']}}</div>
+ <ng-container *ngIf="node['value']">
+ :<div class="value" >{{node['value']}}</div>
+ </ng-container>
+ <div class="module_name">{{node['info']['module']}}</div>
+ </div>
+ <div class="children" *ngIf="node['children']">
+ <tree-view [treeData]="node['children']" [indentation]="inheritIndentation(node)"></tree-view>
+ </div>
+</div>
+</ng-container>
\ No newline at end of file
diff --git a/frontend/config/tree.component.ts b/frontend/config/tree.component.ts
new file mode 100644
index 0000000..99b6cec
--- /dev/null
+++ b/frontend/config/tree.component.ts
@@ -0,0 +1,92 @@
+import {Component, Input, OnInit} from '@angular/core';
+
+import {Session} from './session';
+import {SessionsService} from './sessions.service';
+
+@Component({
+ selector: 'tree-view',
+ templateUrl: './tree.component.html',
+ styleUrls: ['../netopeer.css', './tree.component.css']
+})
+
+export class TreeView implements OnInit {
+ @Input() treeData;
+ @Input() indentation;
+ c = 1; i = 1;
+ activeSession: Session;
+ objectKeys = Object.keys;
+ constructor(private sessionsService: SessionsService) {}
+
+ ngOnInit(): void {
+ this.activeSession = this.sessionsService.getActiveSession(this.sessionsService.activeSession);
+ }
+
+ getSubtree(node, all: boolean) {
+ this.sessionsService.rpcGetSubtree(this.activeSession.key, all, node['path']).subscribe(result => {
+ if (result['success']) {
+ node['children'] = result['data']['children'];
+ }
+ });
+ }
+
+ getType(object) {
+ let result = 'data';
+ if (typeof object == 'object') {
+ if (object instanceof Array) {
+ result = 'array';
+ } else {
+ result = 'object';
+ }
+ }
+ return result;
+ }
+
+ expandable(node): boolean {
+ if (node['info']['type'] == 1 || /* container */
+ node['info']['type'] == 16) { /* list */
+ return true;
+ }
+ return false;
+ }
+
+ hasHiddenChild(node, clean=false): boolean {
+ if (!clean && 'hasHiddenChild' in node) {
+ return node['hasHiddenChild'];
+ }
+ node['hasHiddenChild'] = false;
+ if (!node['children']) {
+ node['hasHiddenChild'] = true;
+ } else {
+ for (let child of node['children']) {
+ if (!('children' in child) || this.hasHiddenChild(child, clean)) {
+ node['hasHiddenChild'] = true;
+ break;
+ }
+ }
+ }
+ return node['hasHiddenChild'];
+ }
+
+ inheritIndentation(node) {
+ let newIndent;
+ if (node['last']) {
+ newIndent = [true];
+ } else {
+ newIndent = [false];
+ }
+
+ if (!this.indentation) {
+ return newIndent;
+ } else {
+ return this.indentation.concat(newIndent);
+ }
+ }
+
+ collapse(node) {
+ node['children'] = null;
+ this.activeSession.dataVisibility = 'mixed';
+ for (let iter of this.activeSession.data) {
+ this.hasHiddenChild(iter, true);
+ }
+ }
+}
diff --git a/frontend/netopeer.component.html b/frontend/netopeer.component.html
index 1e4000e..97c3072 100644
--- a/frontend/netopeer.component.html
+++ b/frontend/netopeer.component.html
@@ -1,7 +1,7 @@
<div id="netopeer-header" #header>
<h1><span routerLink="/netopeer">Netopeer</span> {{componentTitle}}</h1>
- <nav>
+ <nav id="mainnav">
<a *ngFor="let component of netopeerComponents"
routerLink="{{component.route}}" routerLinkActive="active">{{component.name}}</a>
</nav>
diff --git a/frontend/netopeer.css b/frontend/netopeer.css
index 32b950b..0b6b864 100644
--- a/frontend/netopeer.css
+++ b/frontend/netopeer.css
@@ -23,28 +23,35 @@
color: #000;
}
-nav {
+#mainnav {
with: 100%;
padding-left: 1em;
}
-nav a {
+#mainnav a:visited,
+#mainnav a:link {
+ color: inherit;
+}
+
+#mainnav a:hover {
+ border-top-color: #3B4257;
+ background-color: #3B4257;
+}
+
+#mainnav a.active {
+ border-top-color: #BAE4F0;
+ background-color: #3B4257;
+}
+#mainnav a.active:hover {
+ cursor: default;
+}
+
+#mainnav a {
text-decoration: none;
display: inline-block;
padding: 0.5em 1em 0.5em 0.5em;
color: #FAFAFA;
-}
-
-nav a:visited, a:link {
- color: inherited;
-}
-
-nav a:hover, a.active {
- background-color: #3B4257;
-}
-
-nav a.active:hover {
- cursor: default;
+ border-top: 0.2em solid #313747;
}
.msg-rounded {
@@ -58,6 +65,7 @@
font-family: monospace;
font-size: large;
cursor: pointer;
+ height: 1em;
}
.msg-success {
@@ -76,6 +84,6 @@
padding: 5px 1em 5px 0em;
}
-.msg-failure.msg-close {
+.msg-failure .msg-close {
color: red;
}
\ No newline at end of file
diff --git a/frontend/netopeer.module.ts b/frontend/netopeer.module.ts
index b97e9b6..24e0685 100644
--- a/frontend/netopeer.module.ts
+++ b/frontend/netopeer.module.ts
@@ -15,6 +15,7 @@
import { InventorySchemasComponent } from './inventory/schemas.component';
import { InventoryDevicesComponent } from './inventory/devices.component';
import { ConfigComponent } from './config/config.component';
+import { TreeView } from './config/tree.component';
import { YANGComponent } from './yang/yang.component';
import { MonitoringComponent } from './monitoring/monitoring.component';
import { PluginsComponent } from './plugins/plugins.component';
@@ -57,6 +58,7 @@
InventorySchemasComponent,
InventoryDevicesComponent,
ConfigComponent,
+ TreeView,
YANGComponent,
MonitoringComponent,
PluginsComponent