1 | from galaxy.web.base.controller import * |
---|
2 | from galaxy.model.orm import * |
---|
3 | from galaxy.datatypes import sniff |
---|
4 | from galaxy import model, util |
---|
5 | import logging, os, sys |
---|
6 | from galaxy.web.form_builder import * |
---|
7 | from galaxy.tools.parameters.basic import parameter_types |
---|
8 | from elementtree.ElementTree import XML, Element |
---|
9 | from galaxy.util.odict import odict |
---|
10 | import copy |
---|
11 | from galaxy.web.framework.helpers import time_ago, iff, grids |
---|
12 | |
---|
13 | log = logging.getLogger( __name__ ) |
---|
14 | |
---|
15 | class FormsGrid( grids.Grid ): |
---|
16 | # Custom column types |
---|
17 | class NameColumn( grids.TextColumn ): |
---|
18 | def get_value(self, trans, grid, form): |
---|
19 | return form.latest_form.name |
---|
20 | class DescriptionColumn( grids.TextColumn ): |
---|
21 | def get_value(self, trans, grid, form): |
---|
22 | return form.latest_form.desc |
---|
23 | class TypeColumn( grids.TextColumn ): |
---|
24 | def get_value(self, trans, grid, form): |
---|
25 | return form.latest_form.type |
---|
26 | # Grid definition |
---|
27 | title = "Forms" |
---|
28 | template = "admin/forms/grid.mako" |
---|
29 | model_class = model.FormDefinitionCurrent |
---|
30 | default_sort_key = "-create_time" |
---|
31 | num_rows_per_page = 50 |
---|
32 | preserve_state = True |
---|
33 | use_paging = True |
---|
34 | default_filter = dict( deleted="False" ) |
---|
35 | columns = [ |
---|
36 | NameColumn( "Name", |
---|
37 | key="name", |
---|
38 | model_class=model.FormDefinition, |
---|
39 | link=( lambda item: iff( item.deleted, None, dict( operation="view", id=item.id ) ) ), |
---|
40 | attach_popup=True, |
---|
41 | filterable="advanced" ), |
---|
42 | DescriptionColumn( "Description", |
---|
43 | key='desc', |
---|
44 | model_class=model.FormDefinition, |
---|
45 | filterable="advanced" ), |
---|
46 | TypeColumn( "Type" ), |
---|
47 | grids.DeletedColumn( "Deleted", |
---|
48 | key="deleted", |
---|
49 | visible=False, |
---|
50 | filterable="advanced" ) |
---|
51 | ] |
---|
52 | columns.append( grids.MulticolFilterColumn( "Search", |
---|
53 | cols_to_filter=[ columns[0], columns[1] ], |
---|
54 | key="free-text-search", |
---|
55 | visible=False, |
---|
56 | filterable="standard" ) ) |
---|
57 | operations = [ |
---|
58 | grids.GridOperation( "Edit", allow_multiple=False, condition=( lambda item: not item.deleted ) ), |
---|
59 | grids.GridOperation( "Delete", allow_multiple=True, condition=( lambda item: not item.deleted ) ), |
---|
60 | grids.GridOperation( "Undelete", condition=( lambda item: item.deleted ) ), |
---|
61 | ] |
---|
62 | global_actions = [ |
---|
63 | grids.GridAction( "Create new form", dict( controller='forms', action='create_form' ) ) |
---|
64 | ] |
---|
65 | |
---|
66 | class Forms( BaseController ): |
---|
67 | # Empty form field |
---|
68 | empty_field = { 'label': '', |
---|
69 | 'helptext': '', |
---|
70 | 'visible': True, |
---|
71 | 'required': False, |
---|
72 | 'type': BaseField.form_field_types()[0], |
---|
73 | 'selectlist': [], |
---|
74 | 'layout': 'none', |
---|
75 | 'default': '' } |
---|
76 | forms_grid = FormsGrid() |
---|
77 | |
---|
78 | @web.expose |
---|
79 | @web.require_admin |
---|
80 | def manage( self, trans, **kwd ): |
---|
81 | if 'operation' in kwd: |
---|
82 | operation = kwd['operation'].lower() |
---|
83 | if not kwd.get( 'id', None ): |
---|
84 | return trans.response.send_redirect( web.url_for( controller='forms', |
---|
85 | action='manage', |
---|
86 | status='error', |
---|
87 | message="Invalid form ID") ) |
---|
88 | if operation == "view": |
---|
89 | return self.__view( trans, **kwd ) |
---|
90 | elif operation == "delete": |
---|
91 | return self.__delete( trans, **kwd ) |
---|
92 | elif operation == "undelete": |
---|
93 | return self.__undelete( trans, **kwd ) |
---|
94 | elif operation == "edit": |
---|
95 | return self.edit( trans, **kwd ) |
---|
96 | return self.forms_grid( trans, **kwd ) |
---|
97 | def __view(self, trans, **kwd): |
---|
98 | try: |
---|
99 | fdc = trans.sa_session.query( trans.app.model.FormDefinitionCurrent )\ |
---|
100 | .get( trans.security.decode_id(kwd['id']) ) |
---|
101 | except: |
---|
102 | return trans.response.send_redirect( web.url_for( controller='forms', |
---|
103 | action='manage', |
---|
104 | message='Invalid form', |
---|
105 | status='error' ) ) |
---|
106 | return trans.fill_template( '/admin/forms/show_form_read_only.mako', |
---|
107 | form_definition=fdc.latest_form ) |
---|
108 | def __form_types_widget(self, trans, selected='none'): |
---|
109 | form_type_selectbox = SelectField( 'form_type_selectbox' ) |
---|
110 | if selected == 'none': |
---|
111 | form_type_selectbox.add_option('Select one', 'none', selected=True) |
---|
112 | else: |
---|
113 | form_type_selectbox.add_option('Select one', 'none') |
---|
114 | fd_types = trans.app.model.FormDefinition.types.items() |
---|
115 | fd_types.sort() |
---|
116 | for ft in fd_types: |
---|
117 | if selected == ft[1]: |
---|
118 | form_type_selectbox.add_option(ft[1], ft[1], selected=True) |
---|
119 | else: |
---|
120 | form_type_selectbox.add_option(ft[1], ft[1]) |
---|
121 | return form_type_selectbox |
---|
122 | |
---|
123 | @web.expose |
---|
124 | @web.require_admin |
---|
125 | def create_form( self, trans, **kwd ): |
---|
126 | params = util.Params( kwd ) |
---|
127 | message = util.restore_text( params.get( 'message', '' ) ) |
---|
128 | status = params.get( 'status', 'done' ) |
---|
129 | self.__imported_from_file = False |
---|
130 | if params.get( 'create_form_button', False ): |
---|
131 | fd, message = self.__save_form( trans, fdc_id=None, **kwd ) |
---|
132 | if not fd: |
---|
133 | return trans.response.send_redirect( web.url_for( controller='forms', |
---|
134 | action='create_form', |
---|
135 | message=message, |
---|
136 | status='error', |
---|
137 | name=util.restore_text( params.get( 'name', '' ) ), |
---|
138 | description=util.restore_text( params.get( 'description', '' ) ) )) |
---|
139 | self.__get_saved_form( fd ) |
---|
140 | if self.__imported_from_file: |
---|
141 | return trans.response.send_redirect( web.url_for( controller='forms', |
---|
142 | action='edit', |
---|
143 | id=trans.security.encode_id(fd.current.id)) ) |
---|
144 | else: |
---|
145 | return trans.response.send_redirect( web.url_for( controller='forms', |
---|
146 | action='edit', |
---|
147 | id=trans.security.encode_id(fd.current.id), |
---|
148 | add_field_button='Add field', |
---|
149 | name=fd.name, |
---|
150 | description=fd.desc, |
---|
151 | form_type_selectbox=fd.type ) ) |
---|
152 | inputs = [ ( 'Name', TextField( 'name', 40, util.restore_text( params.get( 'name', '' ) ) ) ), |
---|
153 | ( 'Description', TextField( 'description', 40, util.restore_text( params.get( 'description', '' ) ) ) ), |
---|
154 | ( 'Type', self.__form_types_widget(trans, selected=params.get( 'form_type', 'none' )) ), |
---|
155 | ( 'Import from csv file (Optional)', FileField( 'file_data', 40, '' ) ) ] |
---|
156 | return trans.fill_template( '/admin/forms/create_form.mako', |
---|
157 | inputs=inputs, |
---|
158 | message=message, |
---|
159 | status=status ) |
---|
160 | def __delete( self, trans, **kwd ): |
---|
161 | id_list = util.listify( kwd['id'] ) |
---|
162 | delete_failed = [] |
---|
163 | for id in id_list: |
---|
164 | try: |
---|
165 | fdc = trans.sa_session.query( trans.app.model.FormDefinitionCurrent ).get( trans.security.decode_id(id) ) |
---|
166 | except: |
---|
167 | return trans.response.send_redirect( web.url_for( controller='forms', |
---|
168 | action='manage', |
---|
169 | message='Invalid form', |
---|
170 | status='error' ) ) |
---|
171 | fdc.deleted = True |
---|
172 | trans.sa_session.add( fdc ) |
---|
173 | trans.sa_session.flush() |
---|
174 | return trans.response.send_redirect( web.url_for( controller='forms', |
---|
175 | action='manage', |
---|
176 | message='%i forms have been deleted.' % len(id_list), |
---|
177 | status='done') ) |
---|
178 | def __undelete( self, trans, **kwd ): |
---|
179 | id_list = util.listify( kwd['id'] ) |
---|
180 | delete_failed = [] |
---|
181 | for id in id_list: |
---|
182 | try: |
---|
183 | fdc = trans.sa_session.query( trans.app.model.FormDefinitionCurrent ).get( trans.security.decode_id(id) ) |
---|
184 | except: |
---|
185 | return trans.response.send_redirect( web.url_for( controller='forms', |
---|
186 | action='manage', |
---|
187 | message='Invalid form', |
---|
188 | status='error' ) ) |
---|
189 | fdc.deleted = False |
---|
190 | trans.sa_session.add( fdc ) |
---|
191 | trans.sa_session.flush() |
---|
192 | return trans.response.send_redirect( web.url_for( controller='forms', |
---|
193 | action='manage', |
---|
194 | message='%i forms have been undeleted.' % len(id_list), |
---|
195 | status='done') ) |
---|
196 | @web.expose |
---|
197 | def edit( self, trans, response_redirect=None, **kwd ): |
---|
198 | ''' |
---|
199 | This callback method is for handling form editing. The value of response_redirect |
---|
200 | should be an URL that is defined by the caller. This allows for redirecting as desired |
---|
201 | when the form changes have been saved. For an example of how this works, see the |
---|
202 | edit_template() method in the library_common controller. |
---|
203 | ''' |
---|
204 | params = util.Params( kwd ) |
---|
205 | message = util.restore_text( params.get( 'message', '' ) ) |
---|
206 | status = params.get( 'status', 'done' ) |
---|
207 | try: |
---|
208 | fdc = trans.sa_session.query( trans.app.model.FormDefinitionCurrent ).get( trans.security.decode_id(kwd['id']) ) |
---|
209 | except: |
---|
210 | return trans.response.send_redirect( web.url_for( controller='forms', |
---|
211 | action='manage', |
---|
212 | message='Invalid form', |
---|
213 | status='error' ) ) |
---|
214 | fd = fdc.latest_form |
---|
215 | # |
---|
216 | # Save changes |
---|
217 | # |
---|
218 | if params.get( 'save_changes_button', False ): |
---|
219 | fd_new, message = self.__save_form( trans, fdc_id=fd.form_definition_current.id, **kwd ) |
---|
220 | # if validation error encountered while saving the form, show the |
---|
221 | # unsaved form, with the error message |
---|
222 | if not fd_new: |
---|
223 | current_form = self.__get_form( trans, **kwd ) |
---|
224 | return self.__show( trans=trans, form=fd, current_form=current_form, |
---|
225 | message=message, status='error', response_redirect=response_redirect, **kwd ) |
---|
226 | # everything went fine. form saved successfully. Show the saved form or redirect |
---|
227 | # to response_redirect if appropriate. |
---|
228 | if response_redirect: |
---|
229 | return trans.response.send_redirect( response_redirect ) |
---|
230 | fd = fd_new |
---|
231 | current_form = self.__get_saved_form( fd ) |
---|
232 | message = "The form '%s' has been updated with the changes." % fd.name |
---|
233 | return self.__show( trans=trans, form=fd, current_form=current_form, |
---|
234 | message=message, status=status, response_redirect=response_redirect, **kwd ) |
---|
235 | # |
---|
236 | # Add a layout grid |
---|
237 | # |
---|
238 | elif params.get( 'add_layout_grid', False ): |
---|
239 | current_form = self.__get_form( trans, **kwd ) |
---|
240 | current_form['layout'].append('') |
---|
241 | # show the form again |
---|
242 | return self.__show( trans=trans, form=fd, current_form=current_form, |
---|
243 | message=message, status=status, response_redirect=response_redirect, **kwd ) |
---|
244 | # |
---|
245 | # Delete a layout grid |
---|
246 | # |
---|
247 | elif params.get( 'remove_layout_grid_button', False ): |
---|
248 | current_form = self.__get_form( trans, **kwd ) |
---|
249 | index = int( kwd[ 'remove_layout_grid_button' ].split( ' ' )[2] ) - 1 |
---|
250 | del current_form['layout'][index] |
---|
251 | return self.__show( trans=trans, form=fd, current_form=current_form, |
---|
252 | message=message, status=status, response_redirect=response_redirect, **kwd ) |
---|
253 | # |
---|
254 | # Add a field |
---|
255 | # |
---|
256 | elif params.get( 'add_field_button', False ): |
---|
257 | current_form = self.__get_form( trans, **kwd ) |
---|
258 | current_form['fields'].append( self.empty_field ) |
---|
259 | # show the form again with one empty field |
---|
260 | return self.__show( trans=trans, form=fd, current_form=current_form, |
---|
261 | message=message, status=status, response_redirect=response_redirect, **kwd ) |
---|
262 | # |
---|
263 | # Delete a field |
---|
264 | # |
---|
265 | elif params.get( 'remove_button', False ): |
---|
266 | current_form = self.__get_form( trans, **kwd ) |
---|
267 | # find the index of the field to be removed from the remove button label |
---|
268 | index = int( kwd[ 'remove_button' ].split( ' ' )[2] ) - 1 |
---|
269 | del current_form['fields'][index] |
---|
270 | return self.__show( trans=trans, form=fd, current_form=current_form, |
---|
271 | message=message, status=status, response_redirect=response_redirect, **kwd ) |
---|
272 | # |
---|
273 | # Add SelectField option |
---|
274 | # |
---|
275 | elif 'Add' in kwd.values(): |
---|
276 | return self.__add_selectbox_option(trans, fd, message, status, response_redirect=response_redirect, **kwd) |
---|
277 | # |
---|
278 | # Remove SelectField option |
---|
279 | # |
---|
280 | elif 'Remove' in kwd.values(): |
---|
281 | return self.__remove_selectbox_option(trans, fd, message, status, response_redirect=response_redirect, **kwd) |
---|
282 | # |
---|
283 | # Refresh page |
---|
284 | # |
---|
285 | elif params.get( 'refresh', False ): |
---|
286 | current_form = self.__get_form( trans, **kwd ) |
---|
287 | return self.__show( trans=trans, form=fd, current_form=current_form, |
---|
288 | message=message, status=status, response_redirect=response_redirect, **kwd ) |
---|
289 | # |
---|
290 | # Show the form for editing |
---|
291 | # |
---|
292 | else: |
---|
293 | current_form = self.__get_saved_form( fd ) |
---|
294 | return self.__show( trans=trans, form=fd, current_form=current_form, |
---|
295 | message=message, status=status, response_redirect=response_redirect, **kwd ) |
---|
296 | |
---|
297 | def __add_selectbox_option( self, trans, fd, message, status, response_redirect=None, **kwd ): |
---|
298 | ''' |
---|
299 | This method adds a selectbox option. The kwd dict searched for |
---|
300 | the field index which needs to be removed |
---|
301 | ''' |
---|
302 | current_form = self.__get_form( trans, **kwd ) |
---|
303 | index = -1 |
---|
304 | for k, v in kwd.items(): |
---|
305 | if v == 'Add': |
---|
306 | # extract the field index from the |
---|
307 | # button name of format: 'addoption_<field>' |
---|
308 | index = int(k.split('_')[1]) |
---|
309 | break |
---|
310 | if index == -1: |
---|
311 | # something wrong happened |
---|
312 | return self.__show( trans=trans, form=fd, current_form=current_form, |
---|
313 | message='Error in adding selectfield option', |
---|
314 | status='error', response_redirect=response_redirect, **kwd ) |
---|
315 | # add an empty option |
---|
316 | current_form[ 'fields' ][ index ][ 'selectlist' ].append( '' ) |
---|
317 | return self.__show( trans=trans, form=fd, current_form=current_form, |
---|
318 | message=message, status=status, response_redirect=response_redirect, **kwd ) |
---|
319 | def __remove_selectbox_option( self, trans, fd, message, status, response_redirect=None, **kwd ): |
---|
320 | ''' |
---|
321 | This method removes a selectbox option. The kwd dict searched for |
---|
322 | the field index and option index which needs to be removed |
---|
323 | ''' |
---|
324 | current_form = self.__get_form( trans, **kwd ) |
---|
325 | option = -1 |
---|
326 | for k, v in kwd.items(): |
---|
327 | if v == 'Remove': |
---|
328 | # extract the field & option indices from the |
---|
329 | # button name of format: 'removeoption_<field>_<option>' |
---|
330 | index = int(k.split('_')[1]) |
---|
331 | option = int(k.split('_')[2]) |
---|
332 | break |
---|
333 | if option == -1: |
---|
334 | # something wrong happened |
---|
335 | return self.__show( trans=trans, form=fd, current_form=current_form, |
---|
336 | message='Error in removing selectfield option', |
---|
337 | status='error', response_redirect=response_redirect, **kwd ) |
---|
338 | # remove the option |
---|
339 | del current_form[ 'fields' ][ index ][ 'selectlist' ][ option ] |
---|
340 | return self.__show( trans=trans, form=fd, current_form=current_form, |
---|
341 | message=message, status=status, response_redirect=response_redirect, **kwd ) |
---|
342 | |
---|
343 | |
---|
344 | def __get_field(self, index, **kwd): |
---|
345 | ''' |
---|
346 | This method retrieves all the user-entered details of a field and |
---|
347 | returns a dict. |
---|
348 | ''' |
---|
349 | params = util.Params( kwd ) |
---|
350 | name = util.restore_text( params.get( 'field_name_%i' % index, '' ) ) |
---|
351 | helptext = util.restore_text( params.get( 'field_helptext_%i' % index, '' ) ) |
---|
352 | required = params.get( 'field_required_%i' % index, False ) |
---|
353 | field_type = util.restore_text( params.get( 'field_type_%i' % index, '' ) ) |
---|
354 | layout = params.get( 'field_layout_%i' % index, '' ) |
---|
355 | default = params.get( 'field_default_%i' % index, '' ) |
---|
356 | if field_type == 'SelectField': |
---|
357 | selectlist = self.__get_selectbox_options(index, **kwd) |
---|
358 | return {'label': name, |
---|
359 | 'helptext': helptext, |
---|
360 | 'visible': True, |
---|
361 | 'required': required, |
---|
362 | 'type': field_type, |
---|
363 | 'selectlist': selectlist, |
---|
364 | 'layout': layout, |
---|
365 | 'default': default } |
---|
366 | return {'label': name, |
---|
367 | 'helptext': helptext, |
---|
368 | 'visible': True, |
---|
369 | 'required': required, |
---|
370 | 'type': field_type, |
---|
371 | 'layout': layout, |
---|
372 | 'default': default} |
---|
373 | def __get_selectbox_options(self, index, **kwd): |
---|
374 | ''' |
---|
375 | This method gets all the options entered by the user for field when |
---|
376 | the fieldtype is SelectField |
---|
377 | ''' |
---|
378 | params = util.Params( kwd ) |
---|
379 | ctr=0 |
---|
380 | sb_options = [] |
---|
381 | while True: |
---|
382 | if kwd.has_key( 'field_'+str(index)+'_option_'+str(ctr) ): |
---|
383 | option = params.get( 'field_'+str(index)+'_option_'+str(ctr), None ) |
---|
384 | sb_options.append(util.restore_text(option)) |
---|
385 | ctr = ctr+1 |
---|
386 | else: |
---|
387 | return sb_options |
---|
388 | def __get_saved_form(self, fd): |
---|
389 | ''' |
---|
390 | This retrieves the saved form and returns a dictionary containing the name, |
---|
391 | desc, type, layout & fields of the form |
---|
392 | ''' |
---|
393 | return dict(name = fd.name, |
---|
394 | desc = fd.desc, |
---|
395 | type = fd.type, |
---|
396 | layout = list(copy.deepcopy(fd.layout)), |
---|
397 | fields = list(copy.deepcopy(fd.fields))) |
---|
398 | def __get_form(self, trans, **kwd): |
---|
399 | ''' |
---|
400 | This method gets all the user-entered form details and returns a |
---|
401 | dictionary containing the name, desc, type, layout & fields of the form |
---|
402 | ''' |
---|
403 | params = util.Params( kwd ) |
---|
404 | name = util.restore_text( params.name ) |
---|
405 | desc = util.restore_text( params.description ) or "" |
---|
406 | form_type = util.restore_text( params.form_type_selectbox ) |
---|
407 | # get the user entered layout grids |
---|
408 | layout = [] |
---|
409 | index = 0 |
---|
410 | while True: |
---|
411 | if kwd.has_key( 'grid_layout%i' % index ): |
---|
412 | grid_name = util.restore_text( params.get( 'grid_layout%i' % index, '' ) ) |
---|
413 | layout.append( grid_name ) |
---|
414 | index = index + 1 |
---|
415 | else: |
---|
416 | break |
---|
417 | # for csv file import |
---|
418 | csv_file = params.get( 'file_data', '' ) |
---|
419 | fields = [] |
---|
420 | if csv_file == '': |
---|
421 | # get the user entered fields |
---|
422 | index = 0 |
---|
423 | while True: |
---|
424 | if kwd.has_key( 'field_name_%i' % index ): |
---|
425 | fields.append( self.__get_field( index, **kwd ) ) |
---|
426 | index = index + 1 |
---|
427 | else: |
---|
428 | break |
---|
429 | fields = fields |
---|
430 | else: |
---|
431 | fields, layout = self.__import_fields(trans, csv_file, form_type) |
---|
432 | return dict(name = name, |
---|
433 | desc = desc, |
---|
434 | type = form_type, |
---|
435 | layout = layout, |
---|
436 | fields = fields) |
---|
437 | |
---|
438 | def __import_fields(self, trans, csv_file, form_type): |
---|
439 | ''' |
---|
440 | "company","name of the company", "True", "required", "TextField",, |
---|
441 | "due date","turnaround time", "True", "optional", "SelectField","24 hours, 1 week, 1 month" |
---|
442 | ''' |
---|
443 | import csv |
---|
444 | fields = [] |
---|
445 | layouts = set() |
---|
446 | try: |
---|
447 | reader = csv.reader(csv_file.file) |
---|
448 | for row in reader: |
---|
449 | if len(row) < 7: # ignore bogus rows |
---|
450 | continue |
---|
451 | options = row[5].split(',') |
---|
452 | if len(row) >= 8: |
---|
453 | fields.append({'label': row[0], |
---|
454 | 'helptext': row[1], |
---|
455 | 'visible': row[2], |
---|
456 | 'required': row[3], |
---|
457 | 'type': row[4], |
---|
458 | 'selectlist': options, |
---|
459 | 'layout':row[6], |
---|
460 | 'default': row[7]}) |
---|
461 | layouts.add(row[6]) |
---|
462 | else: |
---|
463 | fields.append({'label': row[0], |
---|
464 | 'helptext': row[1], |
---|
465 | 'visible': row[2], |
---|
466 | 'required': row[3], |
---|
467 | 'type': row[4], |
---|
468 | 'selectlist': options, |
---|
469 | 'default': row[6]}) |
---|
470 | except: |
---|
471 | return trans.response.send_redirect( web.url_for( controller='forms', |
---|
472 | action='create_form', |
---|
473 | status='error', |
---|
474 | message='Error in importing <b>%s</b> file' % csv_file.file)) |
---|
475 | self.__imported_from_file = True |
---|
476 | return fields, list(layouts) |
---|
477 | def __validate_form(self, **kwd): |
---|
478 | ''' |
---|
479 | This method checks the following text inputs are filled out by the user |
---|
480 | - the name of form |
---|
481 | - form type |
---|
482 | ''' |
---|
483 | params = util.Params( kwd ) |
---|
484 | # form name |
---|
485 | if not util.restore_text( params.name ): |
---|
486 | return None, 'Form name must be filled.' |
---|
487 | # form type |
---|
488 | if util.restore_text( params.form_type_selectbox ) == 'none': |
---|
489 | return None, 'Form type must be selected.' |
---|
490 | return True, '' |
---|
491 | def __save_form(self, trans, fdc_id=None, **kwd): |
---|
492 | ''' |
---|
493 | This method saves the current form |
---|
494 | ''' |
---|
495 | # check the form for invalid inputs |
---|
496 | flag, message = self.__validate_form(**kwd) |
---|
497 | if not flag: |
---|
498 | return None, message |
---|
499 | current_form = self.__get_form( trans, **kwd ) |
---|
500 | # validate fields |
---|
501 | for field in current_form[ 'fields' ]: |
---|
502 | if not field[ 'label' ]: |
---|
503 | return None, "All the field labels must be completed." |
---|
504 | # create a new form definition |
---|
505 | fd = trans.app.model.FormDefinition(name=current_form[ 'name' ], |
---|
506 | desc=current_form[ 'desc' ], |
---|
507 | fields=current_form[ 'fields' ], |
---|
508 | form_definition_current=None, |
---|
509 | form_type=current_form[ 'type' ], |
---|
510 | layout=current_form[ 'layout' ] ) |
---|
511 | if fdc_id: # save changes to the existing form |
---|
512 | # change the pointer in the form_definition_current table to point |
---|
513 | # to this new record |
---|
514 | fdc = trans.sa_session.query( trans.app.model.FormDefinitionCurrent ).get( fdc_id ) |
---|
515 | else: # create a new form |
---|
516 | fdc = trans.app.model.FormDefinitionCurrent() |
---|
517 | # create corresponding row in the form_definition_current table |
---|
518 | fd.form_definition_current = fdc |
---|
519 | fdc.latest_form = fd |
---|
520 | trans.sa_session.add( fdc ) |
---|
521 | trans.sa_session.flush() |
---|
522 | message = "The new form named '%s' has been created. " % (fd.name) |
---|
523 | return fd, message |
---|
524 | |
---|
525 | class FieldUI(object): |
---|
526 | def __init__(self, trans, layout_grids, index, field=None, field_type=None, form_type=None): |
---|
527 | ''' |
---|
528 | This method returns a list of widgets which describes a field. This |
---|
529 | includes label, helptext, type, & required/optional |
---|
530 | ''' |
---|
531 | self.index = index |
---|
532 | self.label = TextField('field_name_'+str(index), 40, '') |
---|
533 | self.helptext = TextField('field_helptext_'+str(index), 40, '') |
---|
534 | self.fieldtype = SelectField('field_type_'+str(index), |
---|
535 | refresh_on_change=True, |
---|
536 | refresh_on_change_values=['SelectField']) |
---|
537 | self.selectbox_options = [] |
---|
538 | # if the form is for defining samples, then use the sample field types |
---|
539 | # which does not include TextArea & AddressField |
---|
540 | if form_type == trans.app.model.FormDefinition.types.SAMPLE: |
---|
541 | for ft in BaseField.sample_field_types(): |
---|
542 | self.fieldtype.add_option(ft, ft) |
---|
543 | else: |
---|
544 | for ft in BaseField.form_field_types(): |
---|
545 | self.fieldtype.add_option(ft, ft) |
---|
546 | self.required = SelectField('field_required_'+str(index), display='radio') |
---|
547 | self.required.add_option('Required', 'required') |
---|
548 | self.required.add_option('Optional', 'optional', selected=True) |
---|
549 | self.layout_grids = layout_grids |
---|
550 | if layout_grids: |
---|
551 | self.layout_selectbox = SelectField('field_layout_'+str(index)) |
---|
552 | for index, grid_name in enumerate(layout_grids): |
---|
553 | self.layout_selectbox.add_option("%i. %s" %(index+1, grid_name), index) |
---|
554 | # default value |
---|
555 | self.default = TextField('field_default_'+str(index), 40, '') |
---|
556 | if field: |
---|
557 | self.fill(trans, field, field_type, form_type) |
---|
558 | def fill(self, trans, field, field_type=None, form_type=None): |
---|
559 | # label |
---|
560 | self.label.value = field['label'] |
---|
561 | # helptext |
---|
562 | self.helptext.value = field['helptext'] |
---|
563 | # default value |
---|
564 | self.default.value = field.get('default', '') |
---|
565 | # type |
---|
566 | self.fieldtype = SelectField('field_type_'+str(self.index), |
---|
567 | refresh_on_change=True, |
---|
568 | refresh_on_change_values=['SelectField']) |
---|
569 | if field_type: |
---|
570 | field['type'] = unicode(field_type) |
---|
571 | if field_type == 'SelectField' and not field['selectlist']: |
---|
572 | field['selectlist'] = ['', ''] |
---|
573 | # if the form is for defining samples, then use the sample field types |
---|
574 | # which does not include TextArea & AddressField |
---|
575 | if form_type == trans.app.model.FormDefinition.types.SAMPLE: |
---|
576 | for ft in BaseField.sample_field_types(): |
---|
577 | if ft == field['type']: |
---|
578 | self.fieldtype.add_option(ft, ft, selected=True) |
---|
579 | if ft == 'SelectField': |
---|
580 | self.selectbox_ui(field) |
---|
581 | else: |
---|
582 | self.fieldtype.add_option(ft, ft) |
---|
583 | else: |
---|
584 | for ft in BaseField.form_field_types(): |
---|
585 | if ft == field['type']: |
---|
586 | self.fieldtype.add_option(ft, ft, selected=True) |
---|
587 | if ft == 'SelectField': |
---|
588 | self.selectbox_ui(field) |
---|
589 | else: |
---|
590 | self.fieldtype.add_option(ft, ft) |
---|
591 | # required/optional |
---|
592 | if field['required'] == 'required': |
---|
593 | self.required = SelectField('field_required_'+str(self.index), display='radio') |
---|
594 | self.required.add_option('Required', 'required', selected=True) |
---|
595 | self.required.add_option('Optional', 'optional') |
---|
596 | # layout |
---|
597 | if self.layout_grids: |
---|
598 | self.layout_selectbox = SelectField('field_layout_'+str(self.index)) |
---|
599 | for i, grid_name in enumerate(self.layout_grids): |
---|
600 | if field['layout'] == str(i): |
---|
601 | self.layout_selectbox.add_option("%i. %s" %(i+1, grid_name), i, selected=True) |
---|
602 | else: |
---|
603 | self.layout_selectbox.add_option("%i. %s" %(i+1, grid_name), i) |
---|
604 | def selectbox_ui(self, field): |
---|
605 | self.selectbox_options = [] |
---|
606 | if field['selectlist']: |
---|
607 | for ctr, option in enumerate(field['selectlist']): |
---|
608 | self.selectbox_options.append(('Option '+str(ctr+1), |
---|
609 | TextField('field_'+str(self.index)+'_option_'+str(ctr), |
---|
610 | 40, option))) |
---|
611 | def get(self): |
---|
612 | if self.layout_grids: |
---|
613 | return [( 'Label', self.label ), |
---|
614 | ( 'Help text', self.helptext ), |
---|
615 | ( 'Type', self.fieldtype, self.selectbox_options), |
---|
616 | ( 'Default value', self.default ), |
---|
617 | ( '', self.required), |
---|
618 | ( 'Select the grid layout to place this field', self.layout_selectbox)] |
---|
619 | return [( 'Label', self.label ), |
---|
620 | ( 'Help text', self.helptext ), |
---|
621 | ( 'Type', self.fieldtype, self.selectbox_options), |
---|
622 | ( 'Default value', self.default ), |
---|
623 | ( '', self.required)] |
---|
624 | def __repr__(self): |
---|
625 | return str(self.index)+'.'+self.label |
---|
626 | def label(self): |
---|
627 | return str(self.index)+'.'+self.label |
---|
628 | |
---|
629 | def __show( self, trans, form, current_form, message='', status='done', response_redirect=None, **kwd ): |
---|
630 | ''' |
---|
631 | This method displays the form and any of the changes made to it, |
---|
632 | The empty_form param allows for this method to simulate clicking |
---|
633 | the "add_field_button" on the edit_form.mako page so that the page |
---|
634 | is displayed with the first field to be added, saving a mouse click. |
---|
635 | ''' |
---|
636 | params = util.Params( kwd ) |
---|
637 | # name & description |
---|
638 | # TODO: RC, I've changed Type to be a hidden field since it should not be displayed on the edit_form.mako |
---|
639 | # template. Make sure this is the optimal solution for this problem. See my additional TODO in edit_form.mako. |
---|
640 | form_details = [ ( 'Name', TextField( 'name', 40, current_form[ 'name' ] ) ), |
---|
641 | ( 'Description', TextField( 'description', 40, current_form[ 'desc' ] ) ), |
---|
642 | ( 'Type', HiddenField( 'form_type_selectbox', current_form['type']) ) ] |
---|
643 | form_layout = [] |
---|
644 | if current_form[ 'type' ] == trans.app.model.FormDefinition.types.SAMPLE: |
---|
645 | for index, lg in enumerate(current_form[ 'layout' ]): |
---|
646 | form_layout.append( TextField( 'grid_layout%i' % index, 40, lg )) |
---|
647 | # fields |
---|
648 | field_details = [] |
---|
649 | for index, field in enumerate( current_form[ 'fields' ] ): |
---|
650 | if current_form['type'] == trans.app.model.FormDefinition.types.SAMPLE: |
---|
651 | field_ui = self.FieldUI( trans, current_form['layout'], index, field, form_type=current_form['type'] ) |
---|
652 | else: |
---|
653 | field_ui = self.FieldUI( trans, None, index, field, form_type=current_form['type'] ) |
---|
654 | field_details.append( field_ui.get() ) |
---|
655 | return trans.fill_template( '/admin/forms/edit_form.mako', |
---|
656 | form_details=form_details, |
---|
657 | field_details=field_details, |
---|
658 | form=form, |
---|
659 | field_types=BaseField.form_field_types(), |
---|
660 | message=message, |
---|
661 | status=status, |
---|
662 | current_form_type=current_form[ 'type' ], |
---|
663 | layout_grids=form_layout, |
---|
664 | response_redirect=response_redirect ) |
---|