unisi 0.2.5__py3-none-any.whl → 0.2.7__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- unisi/__init__.py +1 -0
- unisi/autotest.py +4 -7
- unisi/containers.py +0 -180
- unisi/graphs.py +169 -0
- unisi/server.py +2 -4
- unisi/units.py +22 -0
- unisi/users.py +16 -5
- unisi/web/css/882.d3c09c5d.css +1 -0
- unisi/web/css/vendor.f7e3cefe.css +6 -0
- unisi/web/index.html +1 -1
- unisi/web/js/609.35dc13d3.js +1 -0
- unisi/web/js/882.aa6d1721.js +1 -0
- unisi/web/js/935.cc0c012c.js +1 -0
- unisi/web/js/app.57a98df1.js +1 -0
- unisi/web/js/vendor.1bb14e9d.js +45 -0
- {unisi-0.2.5.dist-info → unisi-0.2.7.dist-info}/METADATA +1 -1
- {unisi-0.2.5.dist-info → unisi-0.2.7.dist-info}/RECORD +20 -19
- unisi/web/css/328.b849c5e5.css +0 -1
- unisi/web/css/vendor.9ed7638d.css +0 -6
- unisi/web/js/193.283445be.js +0 -1
- unisi/web/js/328.f2a89803.js +0 -1
- unisi/web/js/430.591e9a73.js +0 -1
- unisi/web/js/app.2b81b997.js +0 -1
- unisi/web/js/vendor.2875b6c7.js +0 -45
- {unisi-0.2.5.dist-info → unisi-0.2.7.dist-info}/WHEEL +0 -0
- {unisi-0.2.5.dist-info → unisi-0.2.7.dist-info}/entry_points.txt +0 -0
- {unisi-0.2.5.dist-info → unisi-0.2.7.dist-info}/licenses/LICENSE +0 -0
unisi/__init__.py
CHANGED
unisi/autotest.py
CHANGED
@@ -96,6 +96,8 @@ test_name = Edit('Name test file', '', focus = True)
|
|
96
96
|
rewrite = Switch('Overwrite existing', False, type = 'check')
|
97
97
|
|
98
98
|
def button_clicked(_,__):
|
99
|
+
if not os.path.exists(testdir):
|
100
|
+
os.makedirs(testdir)
|
99
101
|
test_name.value = User.last_user.screen.name
|
100
102
|
test_name.complete = smart_complete(os.listdir(testdir))
|
101
103
|
return Dialog('Create autotest..', ask_create_test, test_name, rewrite)
|
@@ -176,11 +178,7 @@ def check_module(module):
|
|
176
178
|
errors.insert(0, f"\nErrors in screen {screen.name}, file name {module.__file__}:")
|
177
179
|
return errors
|
178
180
|
|
179
|
-
def run_tests():
|
180
|
-
if not os.path.exists(testdir):
|
181
|
-
os.makedirs(testdir)
|
182
|
-
user = User.type(testdir)
|
183
|
-
user.load()
|
181
|
+
def run_tests(user):
|
184
182
|
errors = []
|
185
183
|
for module in user.screens:
|
186
184
|
errors += check_module(module)
|
@@ -200,8 +198,7 @@ def run_tests():
|
|
200
198
|
if not test(file,user):
|
201
199
|
ok = False
|
202
200
|
if process and ok:
|
203
|
-
print('\n-----Autotests successfully passed.-----\n')
|
204
|
-
User.last_user = None
|
201
|
+
print('\n-----Autotests successfully passed.-----\n')
|
205
202
|
User.toolbar.append(button)
|
206
203
|
|
207
204
|
|
unisi/containers.py
CHANGED
@@ -1,186 +1,6 @@
|
|
1
1
|
from .units import *
|
2
|
-
from .tables import Table
|
3
2
|
from .common import pretty4, flatten
|
4
3
|
from numbers import Number
|
5
|
-
from collections import defaultdict
|
6
|
-
from collections.abc import Iterable
|
7
|
-
|
8
|
-
class Node:
|
9
|
-
def __init__(self, name , color = '', size = 0, image = ''):
|
10
|
-
if name:
|
11
|
-
self.name = name
|
12
|
-
if image:
|
13
|
-
self.type = 'image'
|
14
|
-
self.image = image
|
15
|
-
else:
|
16
|
-
self.type = ''
|
17
|
-
if color:
|
18
|
-
self.color = color
|
19
|
-
if size:
|
20
|
-
self.size = size
|
21
|
-
|
22
|
-
class Edge:
|
23
|
-
def __init__(self, source, target, name = '', color = '', size = 0, property = None):
|
24
|
-
self.source = source
|
25
|
-
self.target = target
|
26
|
-
if name:
|
27
|
-
self.name = name
|
28
|
-
if color:
|
29
|
-
self.color = color
|
30
|
-
if size:
|
31
|
-
self.size = size
|
32
|
-
if property is not None:
|
33
|
-
self.property = property
|
34
|
-
def __str__(self):
|
35
|
-
return f"Edge({self.source}->{self.target})"
|
36
|
-
def __repr__(self):
|
37
|
-
return f"Edge({self.source}->{self.target})"
|
38
|
-
|
39
|
-
graph_default_value = {'nodes' : [], 'edges' : []}
|
40
|
-
|
41
|
-
class Graph(Unit):
|
42
|
-
'''has to contain nodes, edges, see Readme'''
|
43
|
-
def __init__(self, name, *args, **kwargs):
|
44
|
-
super().__init__(name, *args, **kwargs)
|
45
|
-
set_defaults(self, dict(type ='graph', value = graph_default_value, nodes = [], edges = []))
|
46
|
-
|
47
|
-
Topology = lambda: defaultdict(lambda: defaultdict(lambda: {}))
|
48
|
-
|
49
|
-
def unit2image(unit):
|
50
|
-
match unit:
|
51
|
-
case Block():
|
52
|
-
return 'https://img.icons8.com/fluency/48/object.png'
|
53
|
-
case Button():
|
54
|
-
return 'https://img.icons8.com/ios-filled/50/doorbell.png'
|
55
|
-
case Edit() | Text():
|
56
|
-
return 'https://img.icons8.com/fluency-systems-filled/50/123.png' if unit.type == 'number'\
|
57
|
-
else 'https://img.icons8.com/sf-regular/48/abc.png'
|
58
|
-
case Switch():
|
59
|
-
return 'https://img.icons8.com/ios/50/toggle-on--v1.png'
|
60
|
-
case TextArea():
|
61
|
-
return 'https://img.icons8.com/color/48/align-cell-content-left.png'
|
62
|
-
case Table():
|
63
|
-
return 'https://img.icons8.com/color/48/day-view.png' if unit.type == 'table'\
|
64
|
-
else 'https://img.icons8.com/ultraviolet/40/combo-chart.png'
|
65
|
-
case Tree():
|
66
|
-
return 'https://img.icons8.com/external-flatart-icons-outline-flatarticons/64/external-tree-nature-flatart-icons-outline-flatarticons-3.png'
|
67
|
-
case Select():
|
68
|
-
return 'https://img.icons8.com/cotton/64/list--v2.png'
|
69
|
-
case Graph():
|
70
|
-
return 'https://img.icons8.com/external-vitaliy-gorbachev-blue-vitaly-gorbachev/50/external-nodes-cryptocurrency-vitaliy-gorbachev-blue-vitaly-gorbachev.png'
|
71
|
-
case Range():
|
72
|
-
return 'https://img.icons8.com/ios/50/slider-control.png'
|
73
|
-
case Unit():
|
74
|
-
return 'https://img.icons8.com/ios-filled/50/link--v1.png'
|
75
|
-
case _:
|
76
|
-
return ''
|
77
|
-
|
78
|
-
class Net(Graph):
|
79
|
-
"""Graph of Units"""
|
80
|
-
def __init__(self, name, topology = Topology(), *args, **kwargs):
|
81
|
-
super().__init__(name, *args, **kwargs)
|
82
|
-
self.type = 'graph'
|
83
|
-
self.topology = topology
|
84
|
-
changed_handler = getattr(self, 'changed', None)
|
85
|
-
|
86
|
-
def changed_converter(_, value):
|
87
|
-
mark_changed = self._mark_changed
|
88
|
-
self._mark_changed = None #turn off for 'value' diff reaction
|
89
|
-
self._value = value
|
90
|
-
narray = self._narray
|
91
|
-
value = dict(nodes = [self._narray[i] for i in value['nodes']], edges =
|
92
|
-
[Edge(narray[self._edges[i].source], narray[self._edges[i].target]) for i in value['edges']])
|
93
|
-
if changed_handler:
|
94
|
-
result = changed_handler(_, value)
|
95
|
-
else:
|
96
|
-
result = None
|
97
|
-
self.value = value
|
98
|
-
self._mark_changed = mark_changed #turn on
|
99
|
-
return result
|
100
|
-
self.changed = changed_converter
|
101
|
-
|
102
|
-
def specific_changed_register(self, property = None, value = None):
|
103
|
-
""" mark serial info as invalid """
|
104
|
-
if property:
|
105
|
-
if property.startswith('_'):
|
106
|
-
return False
|
107
|
-
else:
|
108
|
-
self.delattr('_nodes')
|
109
|
-
self.delattr('_value')
|
110
|
-
return True
|
111
|
-
|
112
|
-
def elements(self, stubs=True):
|
113
|
-
if not hasattr(self, '_nodes'):
|
114
|
-
self.__getstate__()
|
115
|
-
return self.narray
|
116
|
-
|
117
|
-
def __getstate__(self):
|
118
|
-
if not hasattr(self, '_nodes'):
|
119
|
-
nodes = []
|
120
|
-
narray = []
|
121
|
-
earray = []
|
122
|
-
for sunit, links in self.topology.items():
|
123
|
-
sindex = index_of(narray,sunit)
|
124
|
-
if sindex == -1:
|
125
|
-
sindex = len(narray)
|
126
|
-
narray.append(sunit)
|
127
|
-
nodes.append(Node(sunit.name, image = unit2image(sunit),
|
128
|
-
color = 'white', size = 15))
|
129
|
-
for dunit in links:
|
130
|
-
dindex = index_of(narray,dunit)
|
131
|
-
if dindex == -1:
|
132
|
-
dindex = len(narray)
|
133
|
-
narray.append(dunit)
|
134
|
-
nodes.append(Node(dunit.name, image = unit2image(dunit),
|
135
|
-
color = 'white', size = 15))
|
136
|
-
earray.append(Edge(sindex, dindex))
|
137
|
-
self._nodes = nodes
|
138
|
-
self._edges = earray
|
139
|
-
self._narray = narray
|
140
|
-
|
141
|
-
if not hasattr(self, '_value'):
|
142
|
-
self._value = dict(nodes = [index_of(self._narray,unit) for unit in self.value['nodes']],
|
143
|
-
edges = [Edge(index_of(self._narray, e.source), index_of(self._narray, e.target)) for e in self.value['edges']])
|
144
|
-
return dict(name = self.name, type = self.type, nodes = self._nodes, edges = self._edges, value = self._value)
|
145
|
-
|
146
|
-
def make_topology(self, unit: Unit | Iterable):
|
147
|
-
topo = Topology()
|
148
|
-
def dive(unit):
|
149
|
-
match unit:
|
150
|
-
case Iterable():
|
151
|
-
node = Unit('Union', type = 'union')
|
152
|
-
for obj in unit:
|
153
|
-
if obj:
|
154
|
-
topo[node][dive(obj)] = {}
|
155
|
-
return node
|
156
|
-
case Block():
|
157
|
-
for obj in unit.value:
|
158
|
-
if obj:
|
159
|
-
topo[unit][dive(obj)] = {}
|
160
|
-
case _: ...
|
161
|
-
return unit
|
162
|
-
dive(unit)
|
163
|
-
self.topology = topo
|
164
|
-
self.specific_changed_register()
|
165
|
-
|
166
|
-
class ContentScaler(Range):
|
167
|
-
def __init__(self, *args, **kwargs):
|
168
|
-
name = args[0] if args else 'Scale content'
|
169
|
-
super().__init__(name, *args, **kwargs)
|
170
|
-
if 'options' not in kwargs:
|
171
|
-
self.options = [0.25, 3.0, 0.25]
|
172
|
-
self.changed = self.scaler
|
173
|
-
|
174
|
-
def scaler(self, _, val):
|
175
|
-
prev = self.value
|
176
|
-
elements = self.elements()
|
177
|
-
self.value = val
|
178
|
-
if elements:
|
179
|
-
prev /= val
|
180
|
-
for element in elements:
|
181
|
-
element.width /= prev
|
182
|
-
element.height /= prev
|
183
|
-
return elements
|
184
4
|
|
185
5
|
class Block(Unit):
|
186
6
|
def __init__(self, name, *elems, **options):
|
unisi/graphs.py
ADDED
@@ -0,0 +1,169 @@
|
|
1
|
+
from .units import *
|
2
|
+
from .tables import Table
|
3
|
+
from .containers import Block
|
4
|
+
from collections import defaultdict
|
5
|
+
from collections.abc import Iterable
|
6
|
+
|
7
|
+
class Node:
|
8
|
+
def __init__(self, name , color = '', size = 0, image = ''):
|
9
|
+
if name:
|
10
|
+
self.name = name
|
11
|
+
if image:
|
12
|
+
self.type = 'image'
|
13
|
+
self.image = image
|
14
|
+
else:
|
15
|
+
self.type = ''
|
16
|
+
if color:
|
17
|
+
self.color = color
|
18
|
+
if size:
|
19
|
+
self.size = size
|
20
|
+
|
21
|
+
class Edge:
|
22
|
+
def __init__(self, source, target, name = '', color = '', size = 0, property = None):
|
23
|
+
self.source = source
|
24
|
+
self.target = target
|
25
|
+
if name:
|
26
|
+
self.name = name
|
27
|
+
if color:
|
28
|
+
self.color = color
|
29
|
+
if size:
|
30
|
+
self.size = size
|
31
|
+
if property is not None:
|
32
|
+
self.property = property
|
33
|
+
def __str__(self):
|
34
|
+
return f"Edge({self.source}->{self.target})"
|
35
|
+
def __repr__(self):
|
36
|
+
return f"Edge({self.source}->{self.target})"
|
37
|
+
|
38
|
+
graph_default_value = {'nodes' : [], 'edges' : []}
|
39
|
+
|
40
|
+
class Graph(Unit):
|
41
|
+
'''has to contain nodes, edges, see Readme'''
|
42
|
+
def __init__(self, name, *args, **kwargs):
|
43
|
+
super().__init__(name, *args, **kwargs)
|
44
|
+
set_defaults(self, dict(type ='graph', value = graph_default_value, nodes = [], edges = []))
|
45
|
+
|
46
|
+
Topology = lambda: defaultdict(lambda: defaultdict(lambda: None))
|
47
|
+
|
48
|
+
def unit2image(unit):
|
49
|
+
match unit:
|
50
|
+
case Block():
|
51
|
+
return 'https://img.icons8.com/fluency/48/object.png'
|
52
|
+
case Button():
|
53
|
+
return 'https://img.icons8.com/ios-filled/50/doorbell.png'
|
54
|
+
case Edit() | Text():
|
55
|
+
return 'https://img.icons8.com/fluency-systems-filled/50/123.png' if unit.type == 'number'\
|
56
|
+
else 'https://img.icons8.com/sf-regular/48/abc.png'
|
57
|
+
case Switch():
|
58
|
+
return 'https://img.icons8.com/ios/50/toggle-on--v1.png'
|
59
|
+
case TextArea():
|
60
|
+
return 'https://img.icons8.com/color/48/align-cell-content-left.png'
|
61
|
+
case Table():
|
62
|
+
return 'https://img.icons8.com/color/48/day-view.png' if unit.type == 'table'\
|
63
|
+
else 'https://img.icons8.com/ultraviolet/40/combo-chart.png'
|
64
|
+
case Tree():
|
65
|
+
return 'https://img.icons8.com/external-flatart-icons-outline-flatarticons/64/external-tree-nature-flatart-icons-outline-flatarticons-3.png'
|
66
|
+
case Select():
|
67
|
+
return 'https://img.icons8.com/cotton/64/list--v2.png'
|
68
|
+
case Graph():
|
69
|
+
return 'https://img.icons8.com/external-vitaliy-gorbachev-blue-vitaly-gorbachev/50/external-nodes-cryptocurrency-vitaliy-gorbachev-blue-vitaly-gorbachev.png'
|
70
|
+
case Range():
|
71
|
+
return 'https://img.icons8.com/ios/50/slider-control.png'
|
72
|
+
case Unit():
|
73
|
+
return 'https://img.icons8.com/ios-filled/50/link--v1.png'
|
74
|
+
case _:
|
75
|
+
return ''
|
76
|
+
|
77
|
+
class Net(Graph):
|
78
|
+
"""Graph of Units"""
|
79
|
+
replace4state = dict(nodes = '_nodes', edges = '_edges', value = '_value')
|
80
|
+
def __init__(self, name, topology = Topology(), **kwargs):
|
81
|
+
Unit.__init__(self, name, **kwargs)
|
82
|
+
if not hasattr(self, 'value'):
|
83
|
+
self.value = graph_default_value
|
84
|
+
self.type = 'graph'
|
85
|
+
self.topology = topology
|
86
|
+
self._inside_converter = False
|
87
|
+
changed_handler = getattr(self, 'changed', None)
|
88
|
+
|
89
|
+
def changed_converter(_, value):
|
90
|
+
self._inside_converter = True
|
91
|
+
self._value = value
|
92
|
+
narray = self._narray
|
93
|
+
value = dict(nodes = [self._narray[i] for i in value['nodes']], edges =
|
94
|
+
[Edge(narray[self._edges[i].source], narray[self._edges[i].target]) for i in value['edges']])
|
95
|
+
if changed_handler:
|
96
|
+
result = changed_handler(_, value)
|
97
|
+
else:
|
98
|
+
result = None
|
99
|
+
self.value = value
|
100
|
+
self._inside_converter = False
|
101
|
+
return result
|
102
|
+
self.changed = changed_converter
|
103
|
+
|
104
|
+
def specific_changed_register(self, property = None, value = None):
|
105
|
+
""" mark serial info as invalid """
|
106
|
+
if property:
|
107
|
+
if property.startswith('_'):
|
108
|
+
return False
|
109
|
+
elif property == 'value' and self._inside_converter:
|
110
|
+
return False
|
111
|
+
else:
|
112
|
+
self.delattr('_nodes')
|
113
|
+
self.delattr('_value')
|
114
|
+
return True
|
115
|
+
|
116
|
+
def elements(self, stubs=True):
|
117
|
+
if not hasattr(self, '_nodes'):
|
118
|
+
self.__getstate__()
|
119
|
+
return self.narray
|
120
|
+
|
121
|
+
def __getstate__(self):
|
122
|
+
if not hasattr(self, '_nodes'):
|
123
|
+
nodes = []
|
124
|
+
narray = []
|
125
|
+
earray = []
|
126
|
+
for sunit, links in self.topology.items():
|
127
|
+
sindex = index_of(narray,sunit)
|
128
|
+
if sindex == -1:
|
129
|
+
sindex = len(narray)
|
130
|
+
narray.append(sunit)
|
131
|
+
nodes.append(Node(sunit.name, image = unit2image(sunit),
|
132
|
+
color = 'white', size = 15))
|
133
|
+
for dunit in links:
|
134
|
+
dindex = index_of(narray,dunit)
|
135
|
+
if dindex == -1:
|
136
|
+
dindex = len(narray)
|
137
|
+
narray.append(dunit)
|
138
|
+
nodes.append(Node(dunit.name, image = unit2image(dunit),
|
139
|
+
color = 'white', size = 15))
|
140
|
+
earray.append(Edge(sindex, dindex))
|
141
|
+
self._nodes = nodes
|
142
|
+
self._edges = earray
|
143
|
+
self._narray = narray
|
144
|
+
|
145
|
+
if not hasattr(self, '_value'):
|
146
|
+
self._value = dict(nodes = [index_of(self._narray,unit) for unit in self.value['nodes']],
|
147
|
+
edges = [Edge(index_of(self._narray, e.source), index_of(self._narray, e.target)) for e in self.value['edges']])
|
148
|
+
return {name: getattr(self,Net.replace4state.get(name, name)) for name in ['nodes', 'edges', *self.__dict__.keys()]
|
149
|
+
if name != 'topology' and name[0] != '_'}
|
150
|
+
|
151
|
+
def make_topology(self, unit: Unit | Iterable):
|
152
|
+
topo = Topology()
|
153
|
+
def dive(unit):
|
154
|
+
match unit:
|
155
|
+
case Iterable():
|
156
|
+
node = Unit('Union', type = 'union')
|
157
|
+
for obj in unit:
|
158
|
+
if obj:
|
159
|
+
topo[node][dive(obj)] = {}
|
160
|
+
return node
|
161
|
+
case Block():
|
162
|
+
for obj in unit.value:
|
163
|
+
if obj:
|
164
|
+
topo[unit][dive(obj)] = {}
|
165
|
+
case _: ...
|
166
|
+
return unit
|
167
|
+
dive(unit)
|
168
|
+
self.topology = topo
|
169
|
+
self.specific_changed_register()
|
unisi/server.py
CHANGED
@@ -105,10 +105,8 @@ def start(appname = None, user_type = User, http_handlers = []):
|
|
105
105
|
if appname:
|
106
106
|
config.appname = appname
|
107
107
|
|
108
|
-
User.type = user_type
|
109
|
-
|
110
|
-
if config.autotest:
|
111
|
-
run_tests()
|
108
|
+
User.type = user_type
|
109
|
+
run_tests(User.init_user())
|
112
110
|
|
113
111
|
http_handlers.insert(0, web.get('/ws', websocket_handler))
|
114
112
|
http_handlers += [web.static(f'/{config.upload_dir}', upload_dir),
|
unisi/units.py
CHANGED
@@ -125,6 +125,9 @@ class Unit:
|
|
125
125
|
def changed_handler(obj, value):
|
126
126
|
obj.value = value
|
127
127
|
self.changed = compose_handlers(changed_handler, handler)
|
128
|
+
|
129
|
+
def __getstate__(self):
|
130
|
+
return {n: v for n, v in self.__dict__.items() if n[0] != '_'}
|
128
131
|
|
129
132
|
def __str__(self):
|
130
133
|
return f'{type(self).__name__}({self.name})'
|
@@ -177,6 +180,25 @@ class Range(Unit):
|
|
177
180
|
if 'options' not in kwargs:
|
178
181
|
self.options = [self.value - 10, self.value + 10, 1]
|
179
182
|
|
183
|
+
class ContentScaler(Range):
|
184
|
+
def __init__(self, *args, **kwargs):
|
185
|
+
name = args[0] if args else 'Scale content'
|
186
|
+
super().__init__(name, *args, **kwargs)
|
187
|
+
if 'options' not in kwargs:
|
188
|
+
self.options = [0.25, 3.0, 0.25]
|
189
|
+
self.changed = self.scaler
|
190
|
+
|
191
|
+
def scaler(self, _, val):
|
192
|
+
prev = self.value
|
193
|
+
elements = self.elements()
|
194
|
+
self.value = val
|
195
|
+
if elements:
|
196
|
+
prev /= val
|
197
|
+
for element in elements:
|
198
|
+
element.width /= prev
|
199
|
+
element.height /= prev
|
200
|
+
return elements
|
201
|
+
|
180
202
|
class Button(Unit):
|
181
203
|
def __init__(self, name, handler = None, **kwargs):
|
182
204
|
self._mark_changed = None
|
unisi/users.py
CHANGED
@@ -285,7 +285,7 @@ class User:
|
|
285
285
|
self.log(error)
|
286
286
|
return Error(error)
|
287
287
|
|
288
|
-
def monitor(self, session, share):
|
288
|
+
def monitor(self, session, share = None):
|
289
289
|
if config.share and session != testdir:
|
290
290
|
self.log(f'User is connected, session: {session}, share: {share.session if share else None}', type = 'info')
|
291
291
|
|
@@ -306,6 +306,14 @@ class User:
|
|
306
306
|
logging.info(str)
|
307
307
|
func(level = logging.WARNING)
|
308
308
|
|
309
|
+
def init_user():
|
310
|
+
"""make initial user for autotest and evaluating dbsharing"""
|
311
|
+
user = User.type(testdir)
|
312
|
+
user.load()
|
313
|
+
#register shared db map once
|
314
|
+
user.calc_dbsharing()
|
315
|
+
return user
|
316
|
+
|
309
317
|
def calc_dbsharing(self):
|
310
318
|
"""calc connections db and units"""
|
311
319
|
dbshare.clear()
|
@@ -362,15 +370,18 @@ def make_user(request):
|
|
362
370
|
return None, Error(error)
|
363
371
|
user = User.type(session, user)
|
364
372
|
ok = user.screens
|
365
|
-
elif config.mirror and User.
|
373
|
+
elif config.mirror and User.count:
|
366
374
|
user = User.type(session, User.last_user)
|
367
375
|
ok = user.screens
|
376
|
+
elif not User.count:
|
377
|
+
user = User.last_user
|
378
|
+
user.session = session
|
379
|
+
user.monitor(session)
|
380
|
+
ok = True
|
368
381
|
else:
|
369
382
|
user = User.type(session)
|
370
383
|
ok = user.load()
|
371
|
-
|
372
|
-
if not user.count:
|
373
|
-
user.calc_dbsharing()
|
384
|
+
|
374
385
|
User.count += 1
|
375
386
|
Unishare.sessions[session] = user
|
376
387
|
return user, ok
|
@@ -0,0 +1 @@
|
|
1
|
+
thead tr:first-child th{-webkit-backdrop-filter:blur(10px);backdrop-filter:blur(10px);position:sticky;top:0;z-index:1000}:root{--scrollbar-width-height:10px;--scrollbar-thumb-hover:#2176d2;--scrollbar-thumb-dark:#2176d2;--scrollbar-thumb-hover-dark:#2176d2}::-webkit-scrollbar{height:var(--scrollbar-width-height);width:var(--scrollbar-width-height)}::-webkit-scrollbar-track{box-shadow:inset 0 0 4px var(--scrollbar-track-dark)}::-webkit-scrollbar-corner{background:var(--scrollbar-track-dark)}::-webkit-scrollbar-thumb{background:var(--scrollbar-thumb-dark);border-radius:5px}::-webkit-scrollbar-thumb:hover{background:var(--scrollbar-thumb-hover-dark)}#header[data-v-419ab6c8]{font-size:16px;font-weight:700;left:10px;pointer-events:none;position:absolute;top:10px;z-index:2}#graph[data-v-419ab6c8]{border:1px solid #ccc;height:600px;position:relative;width:100%}body[data-v-0f5a7837]{display:flex;justify-content:center}.custom-caption[data-v-0f5a7837]{padding:5px!important}.web-camera-container[data-v-0f5a7837]{align-items:center;border:1px solid #ccc;border-radius:4px;display:flex;flex-direction:column;justify-content:center;margin-bottom:2rem;margin-top:2rem;padding:2rem;width:500px}.web-camera-container .camera-button[data-v-0f5a7837]{margin-bottom:2rem}.web-camera-container .camera-box .camera-shutter[data-v-0f5a7837]{background-color:#fff;height:337.5px;opacity:0;position:absolute;width:450px}.web-camera-container .camera-box .camera-shutter.flash[data-v-0f5a7837]{opacity:1}.web-camera-container .camera-shoot[data-v-0f5a7837]{margin:1rem 0}.web-camera-container .camera-shoot button[data-v-0f5a7837]{align-items:center;border-radius:100%;display:flex;height:60px;justify-content:center;width:60px}.web-camera-container .camera-shoot button img[data-v-0f5a7837]{height:35px;object-fit:cover}.web-camera-container .camera-loading[data-v-0f5a7837]{height:100%;margin:3rem 0 0 -1.2rem;min-height:150px;overflow:hidden;position:absolute;width:100%}.web-camera-container .camera-loading ul[data-v-0f5a7837]{height:100%;margin:0;position:absolute;width:100%;z-index:999999}.web-camera-container .camera-loading .loader-circle[data-v-0f5a7837]{display:block;height:14px;left:100%;margin:0 auto;padding:0;position:absolute;top:50%;transform:translateY(-50%);transform:translateX(-50%);width:100%}.web-camera-container .camera-loading .loader-circle li[data-v-0f5a7837]{animation:preload-0f5a7837 1s infinite;background:#999;border-radius:100%;display:block;float:left;height:10px;line-height:10px;margin:0 0 0 4px;padding:0;position:relative;top:-50%;width:10px}.web-camera-container .camera-loading .loader-circle li[data-v-0f5a7837]:nth-child(2){animation-delay:.2s}.web-camera-container .camera-loading .loader-circle li[data-v-0f5a7837]:nth-child(3){animation-delay:.4s}@keyframes preload-0f5a7837{0%{opacity:1}50%{opacity:.4}to{opacity:1}}.container[data-v-0f5a7837]{position:relative}.frame[data-v-0f5a7837]{border:2px solid #573497;border-radius:8px;height:100%;left:0;pointer-events:none;position:absolute;top:0;width:100%;z-index:10}.container{position:relative}.frame{border:2px solid #573497;border-radius:8px;height:100%;left:0;pointer-events:none;position:absolute;top:0;width:100%;z-index:10}.q-tab__label{font-size:16px;font-weight:700}
|