| 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 ) | 
|---|