[2] | 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 ) |
---|