-
Notifications
You must be signed in to change notification settings - Fork 0
/
manual_tests.py
337 lines (255 loc) · 15.3 KB
/
manual_tests.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
# -*- coding: utf-8 -*-
import html,sys,os,time
from htag import Tag,expose,Runner
def r(o):
x=o.__class__.__name__
if o.attrs.get("name"):
x+=f"[{o['name']}]"
return x
#=================================================================================
if __name__ == "__main__":
# import logging
# logging.basicConfig(format='[%(levelname)-5s] %(name)s: %(message)s',level=logging.INFO)
# logging.getLogger("htag.tag").setLevel( logging.INFO )
base=sys.argv[1] if len(sys.argv)>1 else "basics"
if base == "bulma":
import htagui.bulma as ui
elif base == "shoelace":
import htagui.shoelace as ui
elif base == "md":
import htagui.md as ui
elif base == "fluent":
import htagui.fluent as ui
else:
import htagui.basics as ui
class TestInputs(Tag.div):
def init(self, root, dynamic=False):
self.output=root.output
self.dynamic=dynamic
OPTS = {1:"v1",2:"v2",3:"v3"}
if dynamic:
self.objects=[
ui.IText("itext", onchange=self.onchange_dynamic,_label="itext"),
ui.ITextarea("itextarea", onchange=self.onchange_dynamic,_label="itextarea"),
ui.IBool(True, onchange=self.onchange_dynamic),
ui.IRange(42, onchange=self.onchange_dynamic),
ui.ISelect(2,OPTS, onchange=self.onchange_dynamic),
ui.IRadios(3,OPTS, onchange=self.onchange_dynamic),
]
else:
self.objects=[
ui.Input(_value="input", _onchange=self.bind( self.onchange_static, b"this.value"),_name="myinput",_label="myinput"),
ui.Textarea("textarea", _onchange=self.bind( self.onchange_static, b"this.value"),_name="mytextarea" ,_label="mytextarea"),
ui.Input(_type="checkbox",_checked=True, _onchange=self.bind( self.onchange_static, b"this.checked || this.selected"),_name="mycheckbox"), # selected for "MD" !!!!
ui.Input(_type="range",_value=42, _onchange=self.bind( self.onchange_static, b"this.value"),_name="myrange"),
ui.Select(OPTS,_value=2, _onchange=self.bind( self.onchange_static, b"this.value"),_name="myselect"),
ui.Radios(OPTS,_value=2, _onchange=self.bind( self.onchange_static, b"this.value"),_name="myradios"),
# more Specialized input types
ui.Input(_type="search",_onchange=self.bind( self.onchange_static, b"this.value"),_name="mysearch",_label="mysearch"),
ui.Input(_type="password",_onchange=self.bind( self.onchange_static, b"this.value"),_name="mypassword",_label="mypassword"),
ui.Input(_type="color",_onchange=self.bind( self.onchange_static, b"this.value"),_name="mycolor"),
# ui.Input(_type="date",_name="mydate"),
# ui.Input(_type="month",_name="mymonth"),
# ui.Input(_type="time",_name="mytime"),
# ui.Input(_type="week",_name="myweek"),
]
self.omain=Tag.div()
self <= self.omain
self.generate()
def generate(self):
self.output() # clean if real
HBox=ui.hflex("0 0 200px","*")
if self.dynamic:
self.omain.clear( Tag.h1( "Dynamics" ))
self.omain <= [HBox( i.__class__.__name__,i) for i in self.objects]
self.omain <= ui.Button("save",_onclick=lambda ev: self.dyn_save(self.objects))
self.omain <= ui.Button("load",_onclick=lambda ev: self.dyn_load(self.objects))
else:
self.omain.clear( Tag.h1( "Statics" ))
def onsubmit(d):
self.output(f"form/dict submitted: {d}")
self.omain <= ui.Form( onsubmit ) <= [HBox( r(i),i) for i in self.objects] + ui.Button("submit") + ui.Button("reset",_type="reset")
def dyn_save(self,liste):
for i in liste:
i.saved_value=i.value
self.output(f"getter {r(i)} -> {i.value} ({type(i.value)})")
def dyn_load(self,liste):
for i in liste:
i.value = i.saved_value
self.output(f"setter {r(i)} <- {i.value} ({type(i.value)})")
def onchange_static(self,v):
self.output( f"_onchange static : {v}")
def onchange_dynamic(self,ev):
o = ev.target
self.output( f"onchange dynamic on {r(o)} : {o.value} ({type(o.value)})")
class TestTabs(Tag.div):
def init(self,root):
output = root.output
#================================================
self<=Tag.h2("Test TABS features")
#================================================
t1=Tag.div("hello1",name="tab1")
t2=Tag.div("hello2",name="tab2")
t3=Tag.div("hello3",name="tab3")
t=ui.Tabs( t1,t2,t3,onchange = lambda x: output("tab changed"+str(x.selected)))
self <= t
def force_select(nb):
t.selected=nb
self <= ui.Button("Select 1",_onclick=lambda ev: force_select(0) )
self <= ui.Button("Select 2",_onclick=lambda ev: force_select(1) )
self <= ui.Button("add a tab",_onclick=lambda ev: t.add_tab(Tag.div("Fresh",name="fresh") ) )
class TestDialogs(Tag.div):
statics="window.error = alert"
imports=ui.ALL
def init(self,root):
self.ui=root.ui
#================================================
self<=Tag.h2("Test UI features")
#================================================
entries={
"menu1": lambda: self.ui.notify("menu1"),
"menu2": lambda: self.ui.notify("menu2"),
"menu3": lambda: self.ui.notify("menu3"),
}
content="fdsfd sgfdg g gfds ggfds g"*1000
self <= ui.Button("notify", _onclick=lambda ev: self.ui.notify("kkkk"))
self<= Tag.hr()+"dialog alert & cousins"
self <= ui.Button("alert", _onclick=lambda ev: self.ui.alert(content))
self <= ui.Button("alert size=.1", _onclick=lambda ev: self.ui.alert("kkkk",size=0.1))
self <= ui.Button("alert size=.5", _onclick=lambda ev: self.ui.alert("kkkk",size=0.5))
self <= ui.Button("alert size=.9", _onclick=lambda ev: self.ui.alert("kkkk",size=0.9))
self <= ui.Button("alert size=1", _onclick=lambda ev: self.ui.alert("kkkk",size=1))
self <= ui.Button("confirm", _onclick=lambda ev: self.ui.confirm("kkkk", self.ui.notify))
self <= ui.Button("prompt", _onclick=lambda ev: self.ui.prompt("What's your name?","value", self.ui.notify) )
self<= Tag.hr()+"dialog drawers"
self <= ui.Button("drawer left", _onclick=lambda ev: self.ui.drawer( ui.Menu(entries) + "click on the menu should auto-close the dialog","left" ) )
self <= ui.Button("drawer right", _onclick=lambda ev: self.ui.drawer( "yo","right" ))
self <= ui.Button("drawer top", _onclick=lambda ev: self.ui.drawer( "yo","top" ))
self <= ui.Button("drawer bottom", _onclick=lambda ev: self.ui.drawer( "yo","bottom" ))
self<= Tag.hr()+"dialog blockers"
def block(ev):
self.ui.block( Tag.div(ui.Spinner()+ui.Button("unblock",_onclick=lambda ev: self.ui.close() ) + ui.Menu(entries)) + "click on the menu should auto-close the dialog" )
def page(ev):
self.ui.page( "click on the menu shouldn't close the dialog !!!"+ui.Menu(entries) + ui.Button("alert",_onclick=lambda ev: self.ui.alert('yo'))+ Tag.h3("Click the image to quit")+Tag.img(_src="https://picsum.photos/501/501",_onclick=lambda ev: self.ui.page()) )
self <= ui.Button("block", _onclick=block)
self <= ui.Button("page", _onclick=page)
self <= Tag.hr()
async def atest_yield(v):
self.ui.block( Tag.div(f"yield({v})"+ui.Button("unblock",_onclick=lambda ev: self.ui.close())) )
yield
import time;time.sleep(0.5)
self.ui.close()
def test_yield(v):
self.ui.block( Tag.div(f"yield({v})"+ui.Button("unblock",_onclick=lambda ev: self.ui.close())) )
yield
import time;time.sleep(0.5)
self.ui.close()
self <= ui.Button("test cb (async) yield", _onclick=lambda ev: self.ui.prompt("value","?", atest_yield))
self <= ui.Button("test cb yield", _onclick=lambda ev: self.ui.prompt("value","?", test_yield))
self <= Tag.hr() + "specials"
def copy(ev):
self.ui.clipboard_copy(str(time.time()))
self.ui.notify("copied")
self <= ui.Button("copy into clipboard", _onclick=copy)
self <= ui.Button("paste from clipboard", _onclick=lambda ev: self.ui.clipboard_paste(lambda content: self.ui.notify(f'Content from clipboard {content}')))
self <= ui.Button("download", _onclick=lambda ev: self.ui.download("myfile.txt",b"my content"))
self<= Tag.hr()+"dialog poppers"
def pop_in_dialog(ev):
o=Tag.div("hello")
o<=ui.Button("pop",_onclick = lambda ev: self.ui.pop( ui.Menu(entries) ,(ev.clientX,ev.clientY)) )
self.ui.alert(o)
self <= ui.Button("pop in dialog", _onclick=pop_in_dialog)
self <= ui.Button("pop", _onclick=lambda ev: self.ui.pop("kkkk",(ev.clientX,ev.clientY)) )
self <= ui.Button("pop menu", _onclick=lambda ev: self.ui.pop( ui.Menu(entries) ,(ev.clientX,ev.clientY)) )
class TestOthers(Tag.div):
def init(self,root):
self.output=root.output
h=ui.HSplit( Tag.div("A"), Tag.div("B"),_style="height:100px;border:1px solid black", onchange = lambda o: self.output( f"h sizes: {o.sizes}" ))
v=ui.VSplit( Tag.div("A"), Tag.div("B"),minSize=10)
self <= h
self<= ui.Button("50,50",_onclick=lambda ev: h.setSizes([50,50]))
self<= ui.Button("70,30",_onclick=lambda ev: h.setSizes([70,30]))
self <= ui.HSplit( Tag.div("A"), Tag.div("B"), v, sizes=[20,20,60],minSize=20,_style="height:100px;border:1px solid black")
def doit(name:str,content:bytes):
self.output( f'uploaded {name} ({len(content)} bytes)')
self <= Tag.div("Simple:") <= ui.FileUpload( doit )
self <= Tag.div("Multiple:") <= ui.FileUpload( doit, _multiple=True )
class TestSortable(Tag.div):
def init(self,root):
self.output=root.output
ll=[Tag.div(f"Item {i} (drag me)",value=i) for i in range(10)]
def onchange(o:ui.Sortable):
self.output( str([i.value for i in o.values]) )
self <= ui.Sortable(ll,onchange=onchange)
class TestVscroll(Tag.div):
def init(self,root):
self.output=root.output
#=====================================================================
def feed():
yield [Tag.div(i) for i in range(20) ]
self <= Tag.h3("Unlimited scrolling")
self <= Tag.div(_style="height:200px; border:1px solid red;" ) <= ui.VScroll( feed )
#=====================================================================
#=====================================================================
class O(Tag.div):
def init(self,x):
self <= x
self["style"]="display:inline-block;width:100px;height:100px;border:1px solid black"
# scrolling on demand in a defined list (of lambda())
self <= Tag.h3("On-demand vertical scroll")
self <= Tag.div(_style="height:200px; border:1px solid red;" ) <= ui.VScrollPager([lambda i=i: O(i) for i in range(1,200)])
#=====================================================================
class TestView(Tag.div):
def init(self,root):
self.output=root.output
default_view=Tag.div("Default view")
v = ui.View( default_view, _style="border:1px solid red;width:100%;height:400px" )
self <= v
self <= ui.Button("p1", _onclick = lambda ev: v.go( Tag.div("p1") ))
self <= ui.Button("p2", _onclick = lambda ev: v.go( Tag.div("p2") ))
class App(ui.App):
statics="""
my {cursor:pointer;padding:4px;margin:4px;display:inline-block;text-decoration:underline}
my.selected {color:red;}
hr {padding:0px !important;margin:4px !important;}
"""
imports=ui.ALL
def init(self):
self["class"]="content" # for bulma
self.omain = Tag.div( )
self.oresult = Tag.div(_style="display:flex;flex-flow:column nowrap;flex-direction: column-reverse;")
f = lambda x: "selected" if base==x else ''
self <= Tag.my("basics",_onclick=lambda ev: self.restart_with("basics"),_class=f("basics"))
self <= Tag.my("bulma",_onclick=lambda ev: self.restart_with("bulma"),_class=f("bulma"))
self <= Tag.my("shoelace",_onclick=lambda ev: self.restart_with("shoelace"),_class=f("shoelace"))
self <= Tag.my("fluent",_onclick=lambda ev: self.restart_with("fluent"),_class=f("fluent"))
self <= Tag.my("md (the worst)",_onclick=lambda ev: self.restart_with("md"),_class=f("md"))
def setter(o,testobject):
for i in o.parent.childs:
i["class"].remove("selected")
o["class"].add("selected")
self.omain.clear(testobject)
with Tag.div() as menu:
menu <= Tag.my("Dialogs",_onclick=lambda ev: setter(ev.target,TestDialogs( self )),_class="selected" )
menu <= Tag.my("Tabs",_onclick=lambda ev: setter(ev.target,TestTabs( self )) )
menu <= Tag.my("Inputs statics",_onclick=lambda ev: setter(ev.target,TestInputs(self)) )
menu <= Tag.my("I-fields dynamics",_onclick=lambda ev: setter(ev.target,TestInputs(self,True)) )
menu <= Tag.my("others",_onclick=lambda ev: setter(ev.target,TestOthers(self)) )
menu <= Tag.my("Sortable",_onclick=lambda ev: setter(ev.target,TestSortable(self)) )
menu <= Tag.my("VScroll",_onclick=lambda ev: setter(ev.target,TestVscroll(self)) )
menu <= Tag.my("View",_onclick=lambda ev: setter(ev.target,TestView(self)) )
self <= menu
self <= Tag.hr()
self <= self.omain
self <= self.oresult
self.omain<= TestDialogs( self )
def restart_with(self,mode):
self.call("window.close()")
yield
os.execv(sys.executable, ["python3"]+[os.path.abspath(sys.argv[0]), mode])
def output(self,x=None):
if x:
self.oresult <= Tag.li( html.escape(x) )
else:
self.oresult.clear()
Runner(App).run()