3from flask_wtf
import FlaskForm, recaptcha
4from flask_wtf.recaptcha
import RecaptchaField
6from wtforms
import RadioField, SelectField, StringField, PasswordField, BooleanField, SubmitField, IntegerField, TextAreaField, \
7 SelectMultipleField, FieldList, FileField, MultipleFileField, widgets, HiddenField, DateField, SearchField, FormField, Form
8from wtforms.widgets
import core
9from wtforms.validators
import InputRequired, Email, Optional, EqualTo, NumberRange, ReadOnly, Length
14sys.path.append(os.path.abspath(
'../TVDatabase'))
21 Renders a select field.
23 If `multiple` is True, then the `size` property should be specified on
24 rendering to make the field useful.
26 The field must provide an `iter_choices()` method which the widget will
27 call on rendering; this method must yield tuples of
28 `(value, label, selected)`.
30 def __init__(self, multiple=False):
33 def __call__(self, field, **kwargs):
34 kwargs.setdefault(
'id', field.id)
36 kwargs[
'multiple'] =
True
37 if 'required' not in kwargs
and 'required' in getattr(field,
'flags', []):
38 kwargs[
'required'] =
True
41 for val, label, selected, _
in field.iter_choices():
42 suggestion_list.append(val)
43 suggestion_list.append(label)
44 html = [
'<select %s style="width:1300px">' % core.html_params(name=field.name, **kwargs)]
47 for val, label, selected, _
in field.iter_choices():
49 html.append(
'</select>')
51 html.append(
'</br><div id=search_'+field.id+
'>'+field.description+
'</br>')
52 html.append(
'<label for=filter_'+field.id+
'>Search in all your list and press Go : </label></br>')
53 html.append(
'<input id=filter_'+field.id+
' type=text class="ui-autocomplete-input" autocomplete="off" style="width:1000px;" > ')
54 html.append(
'<button class="btn btn-default" type="button" id="Valid_'+field.id+
'">Go</button>')
56 html.append(
'<script type="text/javascript">\n')
57 html.append(
' var suggestion_list'+field.id+
'='+str(suggestion_list)+
';\n')
58 html.append(
' $("#search_'+field.id+
'").off("autocompleteselect").on( "autocompleteselect", \n')
59 html.append(
' function( event, ui ) {\n')
60 html.append(
' document.getElementById("filter_'+field.id+
'").value = ui.item.value})\n')
61 html.append(
' .on("keypress", function( e ) {\n')
62 html.append(
' if (e.which == 13 ) { \n')
63 html.append(
' var searchval=$("#filter_'+field.id+
'").val().toLowerCase();\n var ioption=0;\n')
64 html.append(
' for (var sugesstr in suggestion_list'+field.id+
') {\n')
65 html.append(
' if ( suggestion_list'+field.id+
'[sugesstr].toLowerCase().includes(searchval) ) {\n ')
66 html.append(
' ioption=2*Math.floor(sugesstr/2);\n')
67 html.append(
' break}}\n')
68 html.append(
' $("#'+field.id+
'").val(suggestion_list'+field.id+
'[ioption]); } })\n')
69 html.append(
' $("#filter_'+field.id+
'").autocomplete({\n')
70 html.append(
' source: suggestion_list'+field.id+
'});\n')
71 html.append(
' $("#Valid_'+field.id+
'").on("click", function() {\n')
72 html.append(
' var searchval=$("#filter_'+field.id+
'").val();\n var ioption=0;\n')
73 html.append(
' for (var sugesstr in suggestion_list'+field.id+
') {\n')
74 html.append(
' if ( suggestion_list'+field.id+
'[sugesstr] == searchval ) {\n ')
75 html.append(
' ioption=2*Math.floor(sugesstr/2);\n')
76 html.append(
' break}}\n')
77 html.append(
' $("#'+field.id+
'").val(suggestion_list'+field.id+
'[ioption]);\n')
79 html.append(
'</script>')
80 return markupsafe.Markup(
''.join(html))
83 def render_option(cls, value, label, selected, **kwargs):
86 value = text_type(value)
88 options = dict(kwargs, value=value)
90 options[
'selected'] =
True
91 return markupsafe.Markup(
'<option %s>%s</option>' % (core.html_params(**options), markupsafe.escape(label)))
98 username = StringField(
'Username',
99 validators=[Optional(),
101 message=(
'not too short (<6), not too long (>16)...'))
103 iseditor = BooleanField(
"Role editor",default=
False,
104 validators=[Optional()])
106def BuildRegisterForm(Username=None,Useremail=None,Usercomp=None,Usermanager=None):
107 class RegisterForm(FlaskForm):
109 RegisterForm.username = StringField(
"Username", default=Username, validators=[InputRequired()])
110 RegisterForm.email = StringField(
"E-mail adress", default=Useremail, validators=[InputRequired(), Email()])
111 RegisterForm.compagny = StringField(
"Compagny name", default=Usercomp, validators=[InputRequired()])
112 RegisterForm.manager = StringField(
"Manager name", default=Usermanager, validators=[InputRequired()])
113 RegisterForm.password = PasswordField(
"Password", validators=[
115 EqualTo(
'confirm', message=
'Passwords must match')])
116 RegisterForm.confirm = PasswordField(
"Confirm password", validators=[InputRequired()])
117 RegisterForm.remember_me = BooleanField(
"Remember me")
118 RegisterForm.newpassword = BooleanField(
"Change password (must be logged in) ",default=Username
is not None)
119 RegisterForm.choice_project = RadioField(
"About the project :",choices=[(
"create",
"Create a new one ?"),
120 (
"connect",
"Connect to an existing one ?")],
122 RegisterForm.submit = SubmitField(
"Sign In")
125def BuildLoginForm(session):
126 class LoginForm(FlaskForm):
130 default_username = session.get(
"username",
"Anonymous")
132 default_username =
"Anonymous"
133 LoginForm.username = StringField(
"Username", default=default_username,validators=[InputRequired()])
134 LoginForm.password = PasswordField(
"Password", validators=[InputRequired()])
136 LoginForm.remember_me = BooleanField(
"Remember me")
137 LoginForm.newuser = BooleanField(
"Change password ?")
139 LoginForm.choice_project = RadioField(
140 label=
"Action with the project :",
141 choices=[(
"create",
"Create a new one ?"), (
"connect",
"Connect to an existing one ?")],
145 LoginForm.submit = SubmitField(
"Next step")
148def Build2FAForm(session,myusername):
149 class Form2FA(FlaskForm):
153 Form2FA.username = StringField(
"Username", default=myusername,validators=[InputRequired()])
155 Form2FA.code = IntegerField(
"Code received by mail for 2FA security check",validators=[InputRequired(),NumberRange(min=100000, max=999999)])
157 Form2FA.submit = SubmitField(
"Next step")
160def BuildNewProjectForm(listprojects):
161 class NewProjectForm(FlaskForm):
163 NewProjectForm.projectname = StringField(
"New Project name", validators=[Optional()])
164 NewProjectForm.description = StringField(
"Description of this project", validators=[Optional()])
165 NewProjectForm.chosen_project=myFixedSelectField(description=
'Or choose one of your old projects in this list (with its sessions) :',choices=listprojects,validators=[Optional()])
167 choices=[(
"use",
"Use an existing session for the grid"),
168 (
"create",
"Create new session")]
169 NewProjectForm.action_sessions = RadioField(description=
"Action with the sessions of this project :",default=
"create",
171 validators=[Optional()])
172 NewProjectForm.submit = SubmitField(
"Next step")
173 return NewProjectForm
176def BuildAdminForm(list_myprojects,list_myprojects_sessions,list_user_connections,list_all_users=None,list_all_projects=None,list_all_sessions=None,list_all_connections=None):
178 class AdminForm(FlaskForm):
181 AdminForm.chosen_project=myFixedSelectField(description=
'Choose one of your own project.',choices=list_myprojects,validators=[Optional()])
182 AdminForm.chosen_project_session=myFixedSelectField(description=
'Choose one of your own project / sessions.',choices=list_myprojects_sessions,validators=[Optional()])
184 AdminForm.chosen_user_connection=myFixedSelectField(description=
'OR one of your connections.',choices=list_user_connections,validators=[Optional()])
185 if (list_all_connections
is not None):
186 AdminForm.chosen_connections=myFixedSelectField(description=
'OR one of all other connections.',choices=list_all_connections,validators=[Optional()])
188 if (list_all_users
is not None):
189 AdminForm.all_users=myFixedSelectField(description=
'Choose one user. !! This will remove all projects/sessions of this user !!',choices=list_all_users,validators=[Optional()])
192 if (list_all_projects
is not None):
193 AdminForm.all_projects=myFixedSelectField(description=
'Choose one project.',choices=list_all_projects,validators=[Optional()])
195 if (list_all_sessions
is not None):
196 AdminForm.all_sessions=myFixedSelectField(description=
'Choose one project.',choices=list_all_sessions,validators=[Optional()])
198 if (list_all_connections
is not None):
199 AdminForm.all_connections=myFixedSelectField(description=
'Choose one connection.',choices=list_all_connections,validators=[Optional()])
201 AdminForm.suppressSelected = SubmitField(
"Delete SELECTIONS.")
202 AdminForm.suppressAllMyConnections = SubmitField(
"Delete all MY CONNECTIONS.")
204 if (list_all_users
is not None):
205 AdminForm.suprressfreetiles = SubmitField(
"Delete all FREE TILES.")
206 AdminForm.suprressUnusedTilesets = SubmitField(
"Delete all UNUSED TILESETS.")
208 if (list_all_connections
is not None):
209 AdminForm.suppressAllConnections = SubmitField(
"Delete ALL CONNECTIONS.")
210 AdminForm.submit = SubmitField(
"Help")
214def BuildAllProjectSessionForm(list_myprojects_sessions,list_invite_sessions):
215 class AllProjectSessionForm(FlaskForm):
218 AllProjectSessionForm.chosen_project_session=myFixedSelectField(description=
'Choose one of your own project / sessions.',choices=list_myprojects_sessions,validators=[Optional()])
219 AllProjectSessionForm.chosen_session_invited=myFixedSelectField(description=
'OR choose one of your collaboration sessions.',choices=list_invite_sessions,validators=[Optional()])
220 AllProjectSessionForm.edit = SubmitField(
"Edit session before grid")
221 AllProjectSessionForm.submit = SubmitField(
"Next step")
222 return AllProjectSessionForm
225def BuildOldProjectForm(thisproject,listsessions, session):
226 class OldProjectForm(FlaskForm):
229 can_manage_members=session.get(
"can_manage_members",
False)
230 can_edit_session=session.get(
"can_edit_session",
False)
231 if (can_edit_session):
232 choices=[(
"use",
"Use a session"),
233 (
"copy",
"Duplicate a session")]
235 choices=[(
"use",
"Use a session")]
237 OldProjectForm.projectname=StringField(label=
"Project name", default=thisproject[
"name"],validators=[Optional()])
238 OldProjectForm.description=StringField(label=
"Description of this project", default=thisproject[
"description"],validators=[Optional()])
239 OldProjectForm.from_session = RadioField(label=
'Action on session (required)',
240 description=
'Choose which action with old session you want :',
243 validators=[InputRequired()])
244 OldProjectForm.chosen_session=RadioField(label=
'List of sessions for project '+thisproject[
"name"]+
' :',choices=listsessions)
245 OldProjectForm.submit = SubmitField(
"Next step")
246 return OldProjectForm
248def BuildNewSessionForm():
249 class NewSessionForm(FlaskForm):
251 NewSessionForm.submit1 = SubmitField(
"Next step")
252 NewSessionForm.sessionname = StringField(
"Session name", validators=[InputRequired()])
253 NewSessionForm.description = StringField(
"Description of this session", validators=[InputRequired()])
254 NewSessionForm.users = FieldList(description=
"Add users",
255 unbound_field=FormField(UserField),
256 min_entries=5,max_entries=10)
257 NewSessionForm.add_users = SubmitField(
'Add more users')
258 NewSessionForm.Session_config = SubmitField(
"Edit configuration of the session")
259 NewSessionForm.submit = SubmitField(
"Next step")
260 return NewSessionForm
262def BuildEditsessionform(oldsession, session, edit=True):
263 class editsessionform(FlaskForm):
265 editsessionform.submit1 = SubmitField(
"Next step")
266 editsessionform.sessionname = StringField(
"New session name", default=oldsession.name, validators=[InputRequired()])
267 editsessionform.description = StringField(
"Description of this session", default=oldsession.description, validators=[InputRequired()])
268 ListAllTileSet_ThisSession=[ (str(thistileset.id), thistileset.name)
for thistileset
in oldsession.tile_sets]
274 can_manage_members=session.get(
"can_manage_members",
False)
275 can_edit_session=session.get(
"can_edit_session",
False)
282 json_tiles_nbClusters = 2
284 if (len(ListAllTileSet_ThisSession) > 0):
289 editsessionform.tilesetchoice = RadioField(label=
'listtilesets',
290 description=
'List all tilesets for this session',
291 choices=ListAllTileSet_ThisSession,
292 default=ListAllTileSet_ThisSession[0][0],
300 editsessionform.edit = SubmitField(
"View or edit selected tileset.")
301 editsessionform.tilesetaction = RadioField(label=
'tilesetaction',
302 description=
'Choose to create and add a new tileset or just use all existing ones.',
303 choices=[(
"create",
"Add a new tileset."),
304 (
"copy",
"Copy an old tileset into a new one."),
305 (
"search",
"Search another tileset for Session."),
306 (
"remove",
"Remove an old tileset in Session."),
307 (
"useold",
"Use existing tilesets and go to grid.")],
309 render_kw={
'label_class':
'text-decoration-underline',
'radio_class':
'text-decoration-none'},
312 editsessionform.tilesetaction = RadioField(label=
'tilesetaction',
313 description=
'Choose to create and add a new tileset or just use all existing ones.',
314 choices=[(
"create",
"Add a new tileset."),
315 (
"copy",
"Copy an old tileset into a new one."),
316 (
"search",
"Search another tileset for Session."),
317 (
"useold",
"Use existing tilesets and go to grid.")],
319 render_kw={
'label_class':
'text-decoration-underline',
'radio_class':
'text-decoration-none'},
323 editsessionform.has_pca = RadioField(label=
'- Principal Component Analysis :',
324 description=
'Would you like to perform automatically Principal Component Analysis (PCA) on all your tilesets? <br/>\
325 This option will perform clustering and thus add tags corresponding to groups.',
326 choices=[(
"YES",
"yes"),
333 # Add the number of cluster field
334 editsessionform.json_tiles_nbClusters = IntegerField("Number of wanted clusters ", default=json_tiles_nbClusters,
335 validators = [NumberRange(min=2)])
337 editsessionform.tilesetchoice = RadioField(label='listtilesetsforpca',
338 description='List of tilesets for this session : check all the desired ones ',
339 choices=ListAllTileSet_ThisSession,
340 default=ListAllTileSet_ThisSession[0][0],
341 validators=[Optional()])
350 editsessionform.tilesetaction = RadioField(label=
'tilesetaction',
351 description=
'No old tilesets. Create a first tileset.',
352 choices=[(
"create",
"Add a new tileset."),
353 (
"search",
"Search another tileset for Session.")],
357 editsessionform.has_pca=HiddenField(
"no PCA if no TileSet.",default=
False,validators=valid)
359 myproject=oldsession.projects
360 myUsers=oldsession.users
361 printstr=
"{0:\xa0<20.20}\xa0|\xa0{1:\xa0<18.18}"
362 ListAllUsers_ThisSession=[(
'NoChoice',printstr.format(
"User name",
"role"))]
364 for projm
in user.project_members_user:
365 if projm.project_id == myproject.id:
366 ListAllUsers_ThisSession.append((user.id,printstr.format(user.name,projm.role_type)))
367 labelUsers=
'All users in this session and their roles : '
368 editsessionform.allusers=myFixedSelectField(label=labelUsers,
369 choices=ListAllUsers_ThisSession,
370 validators=[Optional()])
372 editsessionform.editusers = SubmitField(
"Edit users in project members page.")
374 if can_manage_members:
375 editsessionform.users = FieldList(label=
"Add new users : ",
376 unbound_field=FormField(UserField),
377 min_entries=2,max_entries=10)
378 editsessionform.add_users = SubmitField(
'Add more users')
380 editsessionform.Session_config = SubmitField(
"Edit configuration of the session")
381 editsessionform.submit = SubmitField(
"Next step")
382 return editsessionform
384def BuildOldTileSetForm(username,listtilesets):
385 class OldTileSetForm(FlaskForm):
388 OldTileSetForm.chosen_tileset=myFixedSelectField(description=
'List of Tileset for user '+username+
' :',choices=listtilesets,validators=[Optional()])
389 OldTileSetForm.submit = SubmitField(
"Next step")
390 return OldTileSetForm
392def BuildConfigSessionForm(oldConfig,json_configs_text):
393 class ConfigForm(FlaskForm):
395 ConfigForm.jsonConfig={}
397 ConfigForm.json_config_text = TextAreaField(
"Past json object for configuration of Session ",
398 default=json_configs_text,
399 validators=[Optional()])
400 ConfigForm.editjson = SubmitField(
"Use Json editor for this configuration.")
401 ConfigForm.submit = SubmitField(
"Next step")
413def BuildTilesSetForm(oldtileset=None,json_tiles_text=None,onlycopy=False,editconnection=False):
414 class TilesSetForm(FlaskForm):
416 if (oldtileset==
None):
419 type_of_tiles=
"PICTURE"
423 dataset_path=oldtileset.Dataset_path
424 type_of_tiles=oldtileset.type_of_tiles
426 if (json_tiles_text==
None):
427 json_tiles_text=tvdb.decode_tileset(oldtileset)
433 TilesSetForm.submit1 = SubmitField(
"Next step")
434 TilesSetForm.name = StringField(
"Tiles Set name (required)", default=name, validators=[InputRequired()])
437 TilesSetForm.type_of_tiles = RadioField(label=
'Type of the tiles',
438 description=
'Connection with some pictures or web pages or remote VMs.',
439 choices=[(
"PICTURE",
"a set of pictures on the web or locally"),
440 (
"URL",
"a set of web links in html"),
441 (
"CONNECTION",
"Use a connection to a remote machine")
443 default=type_of_tiles,
444 validators=[Optional()])
445 TilesSetForm.json_tiles_text = TextAreaField(
"Paste json object for tileset ",default=json_tiles_text,
446 validators=[Optional()])
447 TilesSetForm.json_tiles_file = FileField(
"File json object for tileset ",
448 validators=[Optional()])
450 TilesSetForm.editjson = SubmitField(
"Use Json editor for this tileset.")
452 TilesSetForm.dataset_path = StringField(
"Path or main URL of dataset (add to tiles)", default=dataset_path, validators=[Optional()])
453 TilesSetForm.script_launch_file = FileField(
454 u'python script for Connection machine to launch the TileSet',
455 validators=[Optional()])
461 TilesSetForm.configfiles = MultipleFileField(label=
"ConfigFiles",
462 description=
"Configuration files placed in connection dir and upload in CASE dir on HPC frontend.",
463 validators=[Optional()])
466 TilesSetForm.createconnection = SubmitField(label=
"createconnection",description=
"Create Connection")
467 TilesSetForm.editconnection = SubmitField(label=
"editconnection",description=
"Edit Connection")
468 TilesSetForm.shellconnection = SubmitField(label=
"shellconnection",description=
"Direct shell Connection")
469 TilesSetForm.manage_connection= RadioField(label=
'Connections',
470 description=
'Manage Connection for this tileset.',
471 choices=[(
"Use",
"Use an old one."),
472 (
"Quit",
"Quit running connection."),
473 (
"reNew",
"Create a new one."),
476 validators=[Optional()])
485 TilesSetForm.has_pca = RadioField(label=
'- Principal Component Analysis :',
486 description=
'Would you like to perform automatically Principal Component Analysis (PCA) on your data? <br/>\
487 This option will perform clustering and thus add tags corresponding to groups.',
488 choices=[(
"YES",
"yes"),
492 validators=[Optional()])
495 TilesSetForm.goback = SubmitField(
"Go back")
496 TilesSetForm.submit = SubmitField(
"Next step")
501def BuildConnectionsForm(is_admin=False,authchoice="ssh",oldconnection=None):
502 class ConnectionForm(FlaskForm):
505 if (oldconnection==
None):
508 container=
"docker_swarm"
511 host_address=oldconnection.host_address
512 auth_type=oldconnection.auth_type
513 container=oldconnection.container
514 scheduler=oldconnection.scheduler
516 ConnectionForm.submit1 = SubmitField(
"Next step")
517 ConnectionForm.host_address = StringField(
"Name or IP of the machine (required)", default=host_address, validators=[InputRequired()])
519 ConnectionForm.debug = BooleanField(
"Debug mode",default=
False)
521 ConnectionForm.debug =
False
524 ConnectionForm.configfiles = MultipleFileField(label=
"Connection configuration files (required for connection). ",
525 description=
"Configuration files placed in connection dir and upload in CASE dir on HPC frontend.",
526 validators=[Optional()],default=
None)
530 print(f
"authchoices inside {authchoice}")
532 ConnectionForm.auth_type = RadioField(label=
'Authentication type',
533 description=
'Connection to the machine :',
534 choices=[(
"ssh",
"Direct ssh connection"),
535 (
"rebound",
"ssh through gateway(s)")
538 validators=[Optional()])
542 ConnectionForm.container = HiddenField(default=container)
545 ConnectionForm.scheduler = HiddenField(default=scheduler)
554 ConnectionForm.scheduler_file = HiddenField(default=
None)
559 ConnectionForm.submit = SubmitField(
"Next step")
560 return ConnectionForm
564 name = StringField(
"Tiles Set name", validators=[InputRequired()])
565 sessionname = StringField(
"Project name", validators=[InputRequired()])
576def BuildRetreiveSessionForm():
577 class RetreiveSessionForm(FlaskForm):
580 RetreiveSessionForm.session_file = FileField(
"Session file for TiledViz ",
581 validators=[InputRequired()])
584 RetreiveSessionForm.goback = SubmitField(
"Go back")
585 RetreiveSessionForm.submit = SubmitField(
"Next step")
587 return RetreiveSessionForm
590 client_type = RadioField(
'Client Type',
591 choices=[(
'active',
'Active'), (
'passive',
'Passive')],
593 max_uses = IntegerField(
'Maximum Uses', validators=[NumberRange(min=1)], default=1)
594 submit = SubmitField(
'Generate Invitation Link')
595 cancel = SubmitField(
'Cancel')