unisi 0.1.16__py3-none-any.whl → 0.1.18__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 +2 -2
- unisi/autotest.py +4 -4
- unisi/common.py +2 -2
- unisi/containers.py +8 -9
- unisi/{dbelements.py → dbunits.py} +73 -34
- unisi/kdb.py +19 -25
- unisi/llmrag.py +44 -26
- unisi/server.py +4 -1
- unisi/tables.py +59 -73
- unisi/{guielements.py → units.py} +21 -21
- unisi/users.py +49 -28
- unisi/web/css/{440.824522cf.css → 885.880242b5.css} +1 -1
- unisi/web/index.html +1 -1
- unisi/web/js/885.90550ab6.js +1 -0
- unisi/web/js/{app.c4786556.js → app.3ca810a2.js} +1 -1
- {unisi-0.1.16.dist-info → unisi-0.1.18.dist-info}/METADATA +35 -46
- {unisi-0.1.16.dist-info → unisi-0.1.18.dist-info}/RECORD +19 -19
- unisi/web/js/440.970b3f89.js +0 -2
- {unisi-0.1.16.dist-info → unisi-0.1.18.dist-info}/WHEEL +0 -0
- {unisi-0.1.16.dist-info → unisi-0.1.18.dist-info}/licenses/LICENSE +0 -0
unisi/tables.py
CHANGED
@@ -1,8 +1,9 @@
|
|
1
|
-
from .
|
1
|
+
from .units import Unit
|
2
2
|
from .common import *
|
3
|
-
from .
|
3
|
+
from .dbunits import Dblist, dbupdates
|
4
4
|
from .llmrag import get_property
|
5
5
|
import asyncio
|
6
|
+
from collections import OrderedDict
|
6
7
|
|
7
8
|
relation_mark = 'Ⓡ'
|
8
9
|
exclude_mark = '✘'
|
@@ -10,14 +11,9 @@ max_len_rows4llm = 30
|
|
10
11
|
|
11
12
|
def get_chunk(obj, start_index):
|
12
13
|
delta, data = obj.rows.get_delta_chunk(start_index)
|
13
|
-
return {'
|
14
|
+
return {'update': 'updates', 'index': delta, 'data': data}
|
14
15
|
|
15
|
-
def
|
16
|
-
for i, val in enumerate(iter):
|
17
|
-
if i == times:
|
18
|
-
return val
|
19
|
-
|
20
|
-
def accept_cell_value(table, dval):
|
16
|
+
def accept_cell_value(table, dval):
|
21
17
|
value = dval['value']
|
22
18
|
if not isinstance(value, bool):
|
23
19
|
try:
|
@@ -25,21 +21,15 @@ def accept_cell_value(table, dval):
|
|
25
21
|
except:
|
26
22
|
pass
|
27
23
|
if hasattr(table,'id'):
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
row_id = table.rows[dval['delta']][len(dbt.table_fields)]
|
33
|
-
else:
|
34
|
-
table_id = table.__link__[2]
|
35
|
-
row_id = dval['id']
|
36
|
-
dbt.db.update_row(table_id, row_id, {field: value}, in_node)
|
37
|
-
table.rows[dval['delta']][dval['cell']] = value
|
24
|
+
dval['value'] = value
|
25
|
+
table.rows.update_cell(**dval)['exclude'] = True
|
26
|
+
else:
|
27
|
+
table.rows[dval['delta']][dval['cell']] = value
|
38
28
|
|
39
29
|
def delete_table_row(table, value):
|
40
30
|
if table.selected_list:
|
41
31
|
if hasattr(table, 'link') and table.filter:
|
42
|
-
link_table, rel_props, rel_name = table.
|
32
|
+
link_table, rel_props, rel_name = table.rows.link
|
43
33
|
if not isinstance(value, list):
|
44
34
|
value = [value]
|
45
35
|
table.rows.dbtable.delete_links(link_table.id, link_ids = value, index_name = rel_name)
|
@@ -61,7 +51,7 @@ def append_table_row(table, search_str):
|
|
61
51
|
id = table.rows.dbtable.list.append(new_row)
|
62
52
|
new_row.append(id)
|
63
53
|
if hasattr(table, 'link') and table.filter:
|
64
|
-
link_table, _, rel_name = table.
|
54
|
+
link_table, _, rel_name = table.rows.link
|
65
55
|
for linked_id in link_table.selected_list:
|
66
56
|
relation = table.rows.dbtable.add_link(id, link_table.id, linked_id, link_index_name = rel_name)
|
67
57
|
new_row.extend(relation)
|
@@ -69,7 +59,7 @@ def append_table_row(table, search_str):
|
|
69
59
|
table.rows.append(new_row)
|
70
60
|
return new_row
|
71
61
|
|
72
|
-
class Table(
|
62
|
+
class Table(Unit):
|
73
63
|
def __init__(self, *args, panda = None, **kwargs):
|
74
64
|
if panda is not None:
|
75
65
|
self.mutate(PandaTable(*args, panda=panda, **kwargs))
|
@@ -77,10 +67,9 @@ class Table(Gui):
|
|
77
67
|
super().__init__(*args, **kwargs)
|
78
68
|
set_defaults(self, dict(headers = [], type = 'table', value = None, rows = [], editing = False, dense = True))
|
79
69
|
self.__headers__ = self.headers[:]
|
80
|
-
if
|
81
|
-
|
82
|
-
|
83
|
-
db.set_db_list(self)
|
70
|
+
if hasattr(self,'id'):
|
71
|
+
if Unishare.db:
|
72
|
+
Unishare.db.set_db_list(self)
|
84
73
|
else:
|
85
74
|
raise AssertionError('Config db_dir is not defined!')
|
86
75
|
self.get = get_chunk
|
@@ -96,10 +85,10 @@ class Table(Gui):
|
|
96
85
|
rel_name, rel_fields = self.rows.dbtable.get_rel_fields2(link_table.id, prop_types, rel_name)
|
97
86
|
if not hasattr(link_table, 'id'):
|
98
87
|
raise AttributeError('Linked table has to be persistent!')
|
99
|
-
self.
|
88
|
+
self.rows.link = link_table, list(prop_types.keys()), rel_name
|
100
89
|
self.link = rel_fields
|
101
90
|
|
102
|
-
@
|
91
|
+
@Unishare.handle(link_table,'changed')
|
103
92
|
def link_table_selection_changed(master_table, val, init = False):
|
104
93
|
lstvalue = val if isinstance(val, list) else [val] if val != None else []
|
105
94
|
if lstvalue:
|
@@ -112,24 +101,23 @@ class Table(Gui):
|
|
112
101
|
self.rows = link_rows
|
113
102
|
else:
|
114
103
|
selected_ids = [link_rows[i][-1] for i in range(len(link_rows))]
|
115
|
-
self.value = selected_ids
|
116
|
-
#restore table rows if they are not rows
|
104
|
+
self.value = selected_ids
|
117
105
|
if self.rows.cache is not None:
|
118
|
-
|
106
|
+
self.rows = self.rows.dbtable.list
|
119
107
|
if not init:
|
120
108
|
master_table.accept(val)
|
121
109
|
return self
|
122
110
|
link_table_selection_changed(link_table, link_table.value, True)
|
123
111
|
self.__link_table_selection_changed__ = link_table_selection_changed
|
124
112
|
|
125
|
-
@
|
113
|
+
@Unishare.handle(self,'filter')
|
126
114
|
def filter_status_changed(table, value):
|
127
115
|
self.filter = value
|
128
116
|
link_table_selection_changed(link_table, link_table.value, True)
|
129
117
|
self.calc_headers()
|
130
118
|
return self
|
131
119
|
|
132
|
-
@
|
120
|
+
@Unishare.handle(self,'changed')
|
133
121
|
def changed_selection_causes__changing_links(self, new_value):
|
134
122
|
if link_table.value is not None and link_table.value != []:
|
135
123
|
#if link table is in multi mode, links are not editable
|
@@ -146,8 +134,8 @@ class Table(Gui):
|
|
146
134
|
else:
|
147
135
|
return Warning('The linked table is not in edit mode', self)
|
148
136
|
return self.accept(new_value)
|
149
|
-
|
150
|
-
@
|
137
|
+
"""
|
138
|
+
@Unishare.handle(self,'search')
|
151
139
|
def search_changed(table, value):
|
152
140
|
self.search = value
|
153
141
|
if has_link:
|
@@ -155,7 +143,7 @@ class Table(Gui):
|
|
155
143
|
else:
|
156
144
|
self.rows = self.rows.dbtable.get_init_list(self.search)
|
157
145
|
return self
|
158
|
-
|
146
|
+
"""
|
159
147
|
self.calc_headers()
|
160
148
|
|
161
149
|
elif hasattr(self,'ids'):
|
@@ -165,15 +153,13 @@ class Table(Gui):
|
|
165
153
|
set_defaults(self,{'delete': delete_table_row, 'append': append_table_row, 'modify': accept_cell_value})
|
166
154
|
|
167
155
|
@property
|
168
|
-
def compact_view(self):
|
156
|
+
def compact_view(self) -> str:
|
169
157
|
"""only selected are sended to llm"""
|
170
|
-
selected = self.selected_list
|
171
|
-
result = []
|
158
|
+
selected = self.selected_list
|
172
159
|
if not selected and len(self.rows) < max_len_rows4llm:
|
173
|
-
selected = range(len(self.rows))
|
174
|
-
for index in selected
|
175
|
-
|
176
|
-
return {'name': self.name, 'value': result}
|
160
|
+
selected = range(len(self.rows))
|
161
|
+
str_rows = ';'.join(','.join(f'{field}: {value}' for field, value in zip(self.headers, self.rows[index])) for index in selected)
|
162
|
+
return f'{self.name} : {str_rows}'
|
177
163
|
|
178
164
|
@property
|
179
165
|
def selected_list(self):
|
@@ -181,7 +167,7 @@ class Table(Gui):
|
|
181
167
|
|
182
168
|
def clean_selection(self):
|
183
169
|
self.value = [] if isinstance(self.value,tuple | list) else None
|
184
|
-
return self
|
170
|
+
return self
|
185
171
|
|
186
172
|
def calc_headers(self):
|
187
173
|
"""only for persistent"""
|
@@ -197,45 +183,45 @@ class Table(Gui):
|
|
197
183
|
self.headers.extend([relation_mark + pretty4(link_field) for link_field in self.link])
|
198
184
|
if self.ids:
|
199
185
|
self.headers.append(relation_mark + 'ID')
|
200
|
-
|
201
|
-
def index2node_relation(self, cell_index):
|
202
|
-
"""calculate delta to property of node or link for persistent"""
|
203
|
-
table_fields = self.rows.dbtable.table_fields
|
204
|
-
delta = cell_index - len(table_fields)
|
205
|
-
if delta < 0:
|
206
|
-
return True, iterate(table_fields, cell_index)
|
207
|
-
delta -= 1 #ID field
|
208
|
-
return False, iterate(self.link, delta)
|
209
186
|
|
210
187
|
async def emit(self, *_):
|
211
188
|
"""calcute llm field values for selected rows if they are None"""
|
212
|
-
if
|
189
|
+
if Unishare.llm_model and getattr(self, 'llm', None) is not None:
|
213
190
|
tasks = []
|
214
191
|
for index in self.selected_list:
|
215
|
-
values = {field: value for field, value in zip(self.headers, self.rows[index])
|
216
|
-
if value is not None and value != ''}
|
192
|
+
values = {field: value for field, value in zip(self.headers, self.rows[index]) if value}
|
217
193
|
for fld, deps in self.__llm_dependencies__.items():
|
218
|
-
if fld not in values:
|
219
|
-
|
220
|
-
|
221
|
-
|
222
|
-
|
223
|
-
|
224
|
-
|
225
|
-
|
226
|
-
|
227
|
-
|
228
|
-
|
229
|
-
|
230
|
-
|
231
|
-
|
194
|
+
if fld not in values:
|
195
|
+
if deps is True:
|
196
|
+
context = values
|
197
|
+
else:
|
198
|
+
context = OrderedDict()
|
199
|
+
for dep in deps:
|
200
|
+
value = values.get(dep, None)
|
201
|
+
if value is None:
|
202
|
+
if self.llm: #exact
|
203
|
+
continue #not all fields
|
204
|
+
else:
|
205
|
+
if isinstance(dep, str):
|
206
|
+
context[dep] = value
|
207
|
+
elif isinstance(dep, Unit):
|
208
|
+
context[dep.name] = dep.value
|
209
|
+
else:
|
210
|
+
raise AttributeError(f'Invalid llm parameter {dep} in {self.name} element!')
|
232
211
|
if context:
|
233
|
-
async def assign(index, fld,
|
234
|
-
self.rows[index][self.headers.index(fld)] = await get_property(fld,
|
235
|
-
|
212
|
+
async def assign(index, fld, context):
|
213
|
+
self.rows[index][self.headers.index(fld)] = await get_property(fld, context)
|
214
|
+
context = ','.join(f'{fld}:{val}' for fld, val in context.items())
|
215
|
+
tasks.append(asyncio.create_task(assign(index, fld, context)))
|
236
216
|
if tasks:
|
237
217
|
await asyncio.gather(*tasks)
|
238
218
|
return self
|
219
|
+
@property
|
220
|
+
def is_base_table_list(self):
|
221
|
+
"""is table in basic view mode"""
|
222
|
+
if hasattr(self, 'id'):
|
223
|
+
dbtable = self.rows.dbtable
|
224
|
+
return dbtable.list is self.rows
|
239
225
|
|
240
226
|
def delete_panda_row(table, row_num):
|
241
227
|
df = table.__panda__
|
@@ -1,7 +1,7 @@
|
|
1
1
|
from .common import *
|
2
2
|
from .llmrag import get_property
|
3
3
|
|
4
|
-
class
|
4
|
+
class Unit:
|
5
5
|
def __init__(self, name, *args, **kwargs):
|
6
6
|
self.name = name
|
7
7
|
la = len(args)
|
@@ -24,20 +24,20 @@ class Gui:
|
|
24
24
|
self.value = value
|
25
25
|
|
26
26
|
@property
|
27
|
-
def compact_view(self):
|
27
|
+
def compact_view(self) -> str:
|
28
28
|
"""reduce for external (llm) using if required"""
|
29
|
-
return {self.name : self.value}
|
29
|
+
return f'{self.name} : {self.value}'
|
30
30
|
|
31
31
|
async def emit(self, *_ ):
|
32
32
|
"""calcute value by system llm, can be used as a handler"""
|
33
|
-
if
|
33
|
+
if Unishare.llm_model and (exactly := getattr(self, 'llm', None)) is not None:
|
34
34
|
elems = [e.compact_view for e in self.__llm_dependencies__ if e.value != '' and e.value is not None]
|
35
35
|
#exactly is requirment that all elements have to have valid value
|
36
36
|
if not exactly or len(elems) == len(self.__llm_dependencies__):
|
37
|
-
context =
|
37
|
+
context = ','.join(elems)
|
38
38
|
self.value = await get_property(self.name, context, self.type, options = getattr(self, 'options', None))
|
39
39
|
return self
|
40
|
-
|
40
|
+
|
41
41
|
def add_changed_handler(self, handler):
|
42
42
|
changed_handler = getattr(self, 'changed', None)
|
43
43
|
if not changed_handler:
|
@@ -45,7 +45,7 @@ class Gui:
|
|
45
45
|
obj.value = value
|
46
46
|
self.changed = compose_handlers(changed_handler, handler)
|
47
47
|
|
48
|
-
Line =
|
48
|
+
Line = Unit("__Line__", type = 'line')
|
49
49
|
|
50
50
|
def smart_complete(lst, min_input_length = 0, max_output_length = 20):
|
51
51
|
di = {it: it.lower() for it in lst}
|
@@ -60,7 +60,7 @@ def smart_complete(lst, min_input_length = 0, max_output_length = 20):
|
|
60
60
|
return [e[1] for e in arr]
|
61
61
|
return complete
|
62
62
|
|
63
|
-
class Edit(
|
63
|
+
class Edit(Unit):
|
64
64
|
def __init__(self, name, *args, **kwargs):
|
65
65
|
super().__init__(name, *args, **kwargs)
|
66
66
|
has_value = hasattr(self,'value')
|
@@ -70,18 +70,18 @@ class Edit(Gui):
|
|
70
70
|
if type_value == int or type_value == float:
|
71
71
|
self.type = 'number'
|
72
72
|
return
|
73
|
-
self.type =
|
73
|
+
self.type = 'string'
|
74
74
|
if not has_value:
|
75
75
|
self.value = '' if self.type != 'number' else 0
|
76
76
|
|
77
|
-
class Text(
|
77
|
+
class Text(Unit):
|
78
78
|
def __init__(self, name, *args, **kwargs):
|
79
79
|
super().__init__(name, *args, **kwargs)
|
80
80
|
self.value = self.name
|
81
81
|
self.type = 'string'
|
82
82
|
self.edit = False
|
83
83
|
|
84
|
-
class Range(
|
84
|
+
class Range(Unit):
|
85
85
|
def __init__(self, name, *args, **kwargs):
|
86
86
|
super().__init__(name, *args, **kwargs)
|
87
87
|
if not hasattr(self, 'value'):
|
@@ -90,7 +90,7 @@ class Range(Gui):
|
|
90
90
|
if 'options' not in kwargs:
|
91
91
|
self.options = [self.value - 10, self.value + 10, 1]
|
92
92
|
|
93
|
-
class Button(
|
93
|
+
class Button(Unit):
|
94
94
|
def __init__(self, name, handler = None, **kwargs):
|
95
95
|
self.name = name
|
96
96
|
self.value = None
|
@@ -110,7 +110,7 @@ def UploadButton(name, handler = None,**kwargs):
|
|
110
110
|
kwargs['width'] = 250.0
|
111
111
|
return Button(name, handler, **kwargs)
|
112
112
|
|
113
|
-
class Image(
|
113
|
+
class Image(Unit):
|
114
114
|
'''name is file name or url, label is optional text to draw on the image'''
|
115
115
|
def __init__(self, name, value = False, handler = None, label = '', width = 300, **kwargs):
|
116
116
|
super().__init__(name, [], **kwargs)
|
@@ -126,7 +126,7 @@ class Image(Gui):
|
|
126
126
|
if self.url[1] == ':':
|
127
127
|
self.url = f'/{self.url}'
|
128
128
|
|
129
|
-
class Video(
|
129
|
+
class Video(Unit):
|
130
130
|
'''has to contain src parameter'''
|
131
131
|
def __init__(self,name, *args, **kwargs):
|
132
132
|
super().__init__(name, *args, **kwargs)
|
@@ -134,7 +134,7 @@ class Video(Gui):
|
|
134
134
|
set_defaults(self, {'url': self.name, 'ratio' : None})
|
135
135
|
|
136
136
|
class Node:
|
137
|
-
def __init__(self, name = '',
|
137
|
+
def __init__(self, name = '',id = '', color = '', size = 0):
|
138
138
|
if name:
|
139
139
|
self.name = name
|
140
140
|
if color:
|
@@ -145,7 +145,7 @@ class Node:
|
|
145
145
|
self.id = id
|
146
146
|
|
147
147
|
class Edge:
|
148
|
-
def __init__(self, source, target, name = '',
|
148
|
+
def __init__(self, source, target, name = '', id = '', color = '', size = 0):
|
149
149
|
self.source = source
|
150
150
|
self.target = target
|
151
151
|
if name:
|
@@ -159,32 +159,32 @@ class Edge:
|
|
159
159
|
|
160
160
|
graph_default_value = {'nodes' : [], 'edges' : []}
|
161
161
|
|
162
|
-
class Graph(
|
162
|
+
class Graph(Unit):
|
163
163
|
'''has to contain nodes, edges, see Readme'''
|
164
164
|
def __init__(self, name, *args, **kwargs):
|
165
165
|
super().__init__(name, *args, **kwargs)
|
166
166
|
self.type='graph'
|
167
167
|
set_defaults(self,{'value': graph_default_value, 'nodes': [], 'edges': []})
|
168
168
|
|
169
|
-
class Switch(
|
169
|
+
class Switch(Unit):
|
170
170
|
def __init__(self,name, *args, **kwargs):
|
171
171
|
super().__init__(name, *args, **kwargs)
|
172
172
|
set_defaults(self,{'value': False, 'type': 'switch'})
|
173
173
|
|
174
|
-
class Select(
|
174
|
+
class Select(Unit):
|
175
175
|
def __init__(self,name, *args, **kwargs):
|
176
176
|
super().__init__(name, *args, **kwargs)
|
177
177
|
set_defaults(self,{'options': [], 'value': None})
|
178
178
|
if not hasattr(self, 'type'):
|
179
179
|
self.type = 'select' if len(self.options) > 3 else 'radio'
|
180
180
|
|
181
|
-
class Tree(
|
181
|
+
class Tree(Unit):
|
182
182
|
def __init__(self,name, *args, **kwargs):
|
183
183
|
super().__init__(name, *args, **kwargs)
|
184
184
|
self.type = 'tree'
|
185
185
|
set_defaults(self,{'options': [], 'value': None})
|
186
186
|
|
187
|
-
class TextArea(
|
187
|
+
class TextArea(Unit):
|
188
188
|
def __init__(self,name, *args, **kwargs):
|
189
189
|
super().__init__(name, *args, **kwargs)
|
190
190
|
self.type = 'text'
|
unisi/users.py
CHANGED
@@ -1,20 +1,17 @@
|
|
1
1
|
from .utils import *
|
2
|
-
from .
|
2
|
+
from .units import *
|
3
3
|
from .common import *
|
4
4
|
from .containers import Dialog, Screen
|
5
5
|
from .multimon import notify_monitor, logging_lock, run_external_process
|
6
6
|
from .kdb import Database
|
7
|
+
from .dbunits import dbshare, dbupdates
|
7
8
|
import sys, asyncio, logging, importlib
|
8
|
-
from collections import defaultdict
|
9
9
|
|
10
10
|
class User:
|
11
11
|
last_user = None
|
12
|
-
toolbar = []
|
13
|
-
sessions = {}
|
12
|
+
toolbar = []
|
14
13
|
count = 0
|
15
|
-
|
16
|
-
dbshare = defaultdict(lambda: defaultdict(lambda: []))
|
17
|
-
|
14
|
+
|
18
15
|
def __init__(self, session: str, share = None):
|
19
16
|
self.session = session
|
20
17
|
self.active_dialog = None
|
@@ -53,7 +50,7 @@ class User:
|
|
53
50
|
await asyncio.gather(*[user.send(message)
|
54
51
|
for user in self.reflections
|
55
52
|
if user is not self and screen is user.screen_module])
|
56
|
-
|
53
|
+
|
57
54
|
async def reflect(self, message, result):
|
58
55
|
if self.reflections and not is_screen_switch(message):
|
59
56
|
if result:
|
@@ -92,7 +89,7 @@ class User:
|
|
92
89
|
return module
|
93
90
|
|
94
91
|
async def delete(self):
|
95
|
-
uss =
|
92
|
+
uss = Unishare.sessions
|
96
93
|
if uss and uss.get(self.session):
|
97
94
|
del uss[self.session]
|
98
95
|
|
@@ -124,7 +121,7 @@ class User:
|
|
124
121
|
if self.screens:
|
125
122
|
self.screens.sort(key=lambda s: s.screen.order)
|
126
123
|
main = self.screens[0]
|
127
|
-
if 'prepare'
|
124
|
+
if hasattr(main, 'prepare'):
|
128
125
|
main.prepare()
|
129
126
|
self.screen_module = main
|
130
127
|
self.update_menu()
|
@@ -146,6 +143,7 @@ class User:
|
|
146
143
|
|
147
144
|
def set_screen(self,name):
|
148
145
|
return asyncio.run(self.process(ArgObject(block = 'root', element = None, value = name)))
|
146
|
+
|
149
147
|
async def result4message(self, message):
|
150
148
|
result = None
|
151
149
|
self.last_message = message
|
@@ -211,21 +209,21 @@ class User:
|
|
211
209
|
else:
|
212
210
|
if isinstance(raw, Message):
|
213
211
|
raw.fill_paths4(self)
|
214
|
-
elif isinstance(raw,
|
212
|
+
elif isinstance(raw,Unit):
|
215
213
|
raw = Message(raw, user = self)
|
216
214
|
elif isinstance(raw, (list, tuple)):
|
217
215
|
raw = Message(*raw, user = self)
|
218
216
|
return raw
|
219
217
|
|
220
218
|
async def process(self, message):
|
221
|
-
screen_change_message =
|
222
|
-
if is_screen_switch(message)
|
219
|
+
screen_change_message = message.screen and self.screen.name != message.screen
|
220
|
+
if screen_change_message or is_screen_switch(message):
|
223
221
|
for s in self.screens:
|
224
222
|
if s.name == message.value:
|
225
223
|
self.screen_module = s
|
226
224
|
if screen_change_message:
|
227
225
|
break
|
228
|
-
if getattr(s.screen,'prepare',
|
226
|
+
if getattr(s.screen,'prepare', None):
|
229
227
|
s.screen.prepare()
|
230
228
|
return True
|
231
229
|
else:
|
@@ -285,6 +283,33 @@ class User:
|
|
285
283
|
logging.info(str)
|
286
284
|
func(level = logging.WARNING)
|
287
285
|
|
286
|
+
def calc_dbsharing(self):
|
287
|
+
"""calc connections db and units"""
|
288
|
+
dbshare.clear()
|
289
|
+
for module in self.screens:
|
290
|
+
screen = module.screen
|
291
|
+
for block in flatten(screen.blocks):
|
292
|
+
for elem in flatten(block.value):
|
293
|
+
if hasattr(elem, 'id'):
|
294
|
+
dbshare[elem.id][screen.name].append({'element': elem.name, 'block': block.name})
|
295
|
+
|
296
|
+
async def sync_dbupdates(self):
|
297
|
+
sync_calls = []
|
298
|
+
for id, updates in dbupdates.items():
|
299
|
+
for update in updates:
|
300
|
+
if update:
|
301
|
+
screen2el_bl = dbshare[id]
|
302
|
+
exclude = update.get('exclude', False)
|
303
|
+
for user in Unishare.sessions.values():
|
304
|
+
if not exclude or user is not self:
|
305
|
+
scr_name = user.screen.name
|
306
|
+
if scr_name in screen2el_bl:
|
307
|
+
for elem_block in screen2el_bl[scr_name]:
|
308
|
+
update4user = {**update, **elem_block}
|
309
|
+
sync_calls.append(user.send(update4user))
|
310
|
+
dbupdates.clear()
|
311
|
+
await asyncio.gather(*sync_calls)
|
312
|
+
|
288
313
|
def context_user():
|
289
314
|
return context_object(User)
|
290
315
|
|
@@ -296,16 +321,17 @@ def message_logger(str, type = 'error'):
|
|
296
321
|
user = context_user()
|
297
322
|
user.log(str, type)
|
298
323
|
|
299
|
-
|
300
|
-
|
301
|
-
|
302
|
-
User.db = Database(config.db_dir, message_logger) if config.db_dir else None
|
324
|
+
Unishare.context_user = context_user
|
325
|
+
Unishare.message_logger = message_logger
|
303
326
|
User.type = User
|
304
327
|
|
328
|
+
if config.db_dir:
|
329
|
+
Unishare.db = Database(config.db_dir, message_logger)
|
330
|
+
|
305
331
|
def make_user(request):
|
306
332
|
session = f'{request.remote}-{User.count}'
|
307
333
|
if requested_connect := request.query_string if config.share else None:
|
308
|
-
user =
|
334
|
+
user = Unishare.sessions.get(requested_connect, None)
|
309
335
|
if not user:
|
310
336
|
error = f'Session id "{requested_connect}" is unknown. Connection refused!'
|
311
337
|
with logging_lock:
|
@@ -319,16 +345,11 @@ def make_user(request):
|
|
319
345
|
else:
|
320
346
|
user = User.type(session)
|
321
347
|
ok = user.load()
|
322
|
-
#register
|
348
|
+
#register shared db map once
|
323
349
|
if not user.count:
|
324
|
-
|
325
|
-
screen = module.screen
|
326
|
-
for block in flatten(screen.blocks):
|
327
|
-
for elem in flatten(block.value):
|
328
|
-
if hasattr(elem, 'id'):
|
329
|
-
User.dbshare[elem.id][screen.name].append([elem.name, block.name])
|
350
|
+
user.calc_dbsharing()
|
330
351
|
User.count += 1
|
331
|
-
|
352
|
+
Unishare.sessions[session] = user
|
332
353
|
return user, ok
|
333
354
|
|
334
355
|
def handle(elem, event):
|
@@ -343,4 +364,4 @@ def handle(elem, event):
|
|
343
364
|
return fn
|
344
365
|
return h
|
345
366
|
|
346
|
-
|
367
|
+
Unishare.handle = handle
|
@@ -1 +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)}body[data-v-
|
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)}body[data-v-763052dd]{display:flex;justify-content:center}.custom-caption[data-v-763052dd]{padding:5px!important}.web-camera-container[data-v-763052dd]{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-763052dd]{margin-bottom:2rem}.web-camera-container .camera-box .camera-shutter[data-v-763052dd]{background-color:#fff;height:337.5px;opacity:0;position:absolute;width:450px}.web-camera-container .camera-box .camera-shutter.flash[data-v-763052dd]{opacity:1}.web-camera-container .camera-shoot[data-v-763052dd]{margin:1rem 0}.web-camera-container .camera-shoot button[data-v-763052dd]{align-items:center;border-radius:100%;display:flex;height:60px;justify-content:center;width:60px}.web-camera-container .camera-shoot button img[data-v-763052dd]{height:35px;object-fit:cover}.web-camera-container .camera-loading[data-v-763052dd]{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-763052dd]{height:100%;margin:0;position:absolute;width:100%;z-index:999999}.web-camera-container .camera-loading .loader-circle[data-v-763052dd]{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-763052dd]{animation:preload-763052dd 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-763052dd]:nth-child(2){animation-delay:.2s}.web-camera-container .camera-loading .loader-circle li[data-v-763052dd]:nth-child(3){animation-delay:.4s}@keyframes preload-763052dd{0%{opacity:1}50%{opacity:.4}to{opacity:1}}.q-tab__label{font-size:16px;font-weight:700}
|
unisi/web/index.html
CHANGED
@@ -1 +1 @@
|
|
1
|
-
<!DOCTYPE html><html><head><base href=/ ><title>UNISI</title><meta charset=utf-8><meta name=description content="UNISI on Quasar"><meta name=format-detection content="telephone=no"><meta name=msapplication-tap-highlight content=no><meta name=viewport content="user-scalable=no,initial-scale=1,maximum-scale=1,minimum-scale=1,width=device-width"><link rel=icon type=image/png sizes=128x128 href=icons/favicon-128x128.png><link rel=icon type=image/png sizes=96x96 href=icons/favicon-96x96.png><link rel=icon type=image/png sizes=32x32 href=icons/favicon-32x32.png><link rel=icon type=image/png sizes=16x16 href=icons/favicon-16x16.png><link rel=icon type=image/ico href=favicon.ico><script defer src=/js/vendor.eab68489.js></script><script defer src=/js/app.
|
1
|
+
<!DOCTYPE html><html><head><base href=/ ><title>UNISI</title><meta charset=utf-8><meta name=description content="UNISI on Quasar"><meta name=format-detection content="telephone=no"><meta name=msapplication-tap-highlight content=no><meta name=viewport content="user-scalable=no,initial-scale=1,maximum-scale=1,minimum-scale=1,width=device-width"><link rel=icon type=image/png sizes=128x128 href=icons/favicon-128x128.png><link rel=icon type=image/png sizes=96x96 href=icons/favicon-96x96.png><link rel=icon type=image/png sizes=32x32 href=icons/favicon-32x32.png><link rel=icon type=image/png sizes=16x16 href=icons/favicon-16x16.png><link rel=icon type=image/ico href=favicon.ico><script defer src=/js/vendor.eab68489.js></script><script defer src=/js/app.3ca810a2.js></script><link href=/css/vendor.9ed7638d.css rel=stylesheet><link href=/css/app.31d6cfe0.css rel=stylesheet></head><body><div id=q-app></div></body></html>
|