def render_title(context): context.caller_stack._push_frame() try: _import_ns = {} _mako_get_namespace(context, '__anon_0x7f313c4cda10')._populate( _import_ns, [u'*']) _mako_get_namespace(context, '__anon_0x7f313c4cd310')._populate( _import_ns, [ u'render_individual_tagging_element', u'render_community_tagging_element' ]) item = _import_ns.get('item', context.get('item', UNDEFINED)) get_class_display_name = _import_ns.get( 'get_class_display_name', context.get('get_class_display_name', UNDEFINED)) get_item_name = _import_ns.get('get_item_name', context.get('get_item_name', UNDEFINED)) __M_writer = context.writer() # SOURCE LINE 19 __M_writer(u'\n Galaxy | ') # SOURCE LINE 20 __M_writer( unicode( iff( item.published, "Published ", iff(item.importable, "Accessible ", iff(item.users_shared_with, "Shared ", "Private "))) + get_class_display_name(item.__class__))) __M_writer(u' | ') __M_writer(filters.html_escape(unicode(get_item_name(item)))) __M_writer(u'\n') return '' finally: context.caller_stack._pop_frame()
class FormsGrid( grids.Grid ): # Custom column types class NameColumn( grids.TextColumn ): def get_value(self, trans, grid, form): return form.latest_form.name class DescriptionColumn( grids.TextColumn ): def get_value(self, trans, grid, form): return form.latest_form.desc class TypeColumn( grids.TextColumn ): def get_value(self, trans, grid, form): return form.latest_form.type class DeletedColumn( grids.GridColumn ): def get_accepted_filters( self ): """ Returns a list of accepted filters for this column. """ accepted_filter_labels_and_vals = { "active" : "False", "deleted" : "True", "all": "All" } accepted_filters = [] for label, val in accepted_filter_labels_and_vals.items(): args = { self.key: val } accepted_filters.append( grids.GridColumnFilter( label, args) ) return accepted_filters # Grid definition title = "Forms" template = "admin/forms/grid.mako" model_class = model.FormDefinitionCurrent default_sort_key = "-create_time" num_rows_per_page = 50 preserve_state = True use_paging = True default_filter = dict( deleted="False" ) columns = [ NameColumn( "Name", key="name", model_class=model.FormDefinition, link=( lambda item: iff( item.deleted, None, dict( operation="view", id=item.id ) ) ), attach_popup=True, filterable="advanced" ), DescriptionColumn( "Description", key='desc', model_class=model.FormDefinition, filterable="advanced" ), TypeColumn( "Type" ), DeletedColumn( "Deleted", key="deleted", visible=False, filterable="advanced" ) ] columns.append( grids.MulticolFilterColumn( "Search", cols_to_filter=[ columns[0], columns[1] ], key="free-text-search", visible=False, filterable="standard" ) ) operations = [ grids.GridOperation( "Edit", allow_multiple=False, condition=( lambda item: not item.deleted ) ), grids.GridOperation( "Delete", allow_multiple=True, condition=( lambda item: not item.deleted ) ), grids.GridOperation( "Undelete", condition=( lambda item: item.deleted ) ), ] global_actions = [ grids.GridAction( "Create new form", dict( controller='forms', action='new' ) ) ]
def _list_undelete(self, trans, histories): """Undelete histories""" n_undeleted = 0 n_already_purged = 0 for history in histories: if history.purged: n_already_purged += 1 if history.deleted: history.deleted = False if not history.default_permissions: # For backward compatibility - for a while we were deleting all DefaultHistoryPermissions on # the history when we deleted the history. We are no longer doing this. # Need to add default DefaultHistoryPermissions in case they were deleted when the history was deleted default_action = trans.app.security_agent.permitted_actions.DATASET_MANAGE_PERMISSIONS private_user_role = trans.app.security_agent.get_private_user_role(history.user) default_permissions = {} default_permissions[default_action] = [private_user_role] trans.app.security_agent.history_set_default_permissions(history, default_permissions) n_undeleted += 1 trans.log_event("History (%s) %d marked as undeleted" % (history.name, history.id)) status = SUCCESS message_parts = [] if n_undeleted: message_parts.append("Undeleted %d %s. " % (n_undeleted, iff(n_undeleted != 1, "histories", "history"))) if n_already_purged: message_parts.append("%d histories have already been purged and cannot be undeleted." % n_already_purged) status = WARNING return status, "".join(message_parts)
class FormsGrid(grids.Grid): # Custom column types class NameColumn(grids.TextColumn): def get_value(self, trans, grid, form): return escape(form.latest_form.name) class DescriptionColumn(grids.TextColumn): def get_value(self, trans, grid, form): return escape(form.latest_form.desc) class TypeColumn(grids.TextColumn): def get_value(self, trans, grid, form): return form.latest_form.type # Grid definition title = "Forms" template = "admin/forms/grid.mako" model_class = model.FormDefinitionCurrent default_sort_key = "-create_time" num_rows_per_page = 50 preserve_state = True use_paging = True default_filter = dict(deleted="False") columns = [ NameColumn("Name", key="name", model_class=model.FormDefinition, link=(lambda item: iff(item.deleted, None, dict(operation="view_latest_form_definition", id=item.id))), attach_popup=True, filterable="advanced"), DescriptionColumn("Description", key='desc', model_class=model.FormDefinition, filterable="advanced"), TypeColumn("Type"), grids.DeletedColumn("Deleted", key="deleted", visible=False, filterable="advanced") ] columns.append(grids.MulticolFilterColumn("Search", cols_to_filter=[columns[0], columns[1]], key="free-text-search", visible=False, filterable="standard")) operations = [ grids.GridOperation("Edit", allow_multiple=False, condition=(lambda item: not item.deleted)), grids.GridOperation("Delete", allow_multiple=True, condition=(lambda item: not item.deleted)), grids.GridOperation("Undelete", condition=(lambda item: item.deleted)), ] global_actions = [ grids.GridAction("Create new form", dict(controller='forms', action='create_form_definition')) ] def build_initial_query(self, trans, **kwargs): return trans.sa_session.query(self.model_class).join(model.FormDefinition, self.model_class.latest_form_id == model.FormDefinition.id)
def render_title(context): context.caller_stack._push_frame() try: _import_ns = {} _mako_get_namespace(context, '__anon_0x1135ad290')._populate(_import_ns, [u'render_individual_tagging_element', u'render_community_tagging_element', u'community_tag_js']) _mako_get_namespace(context, '__anon_0x1135ad890')._populate(_import_ns, [u'*']) item = _import_ns.get('item', context.get('item', UNDEFINED)) get_class_display_name = _import_ns.get('get_class_display_name', context.get('get_class_display_name', UNDEFINED)) get_item_name = _import_ns.get('get_item_name', context.get('get_item_name', UNDEFINED)) __M_writer = context.writer() # SOURCE LINE 19 __M_writer(u'\n Galaxy | ') # SOURCE LINE 20 __M_writer(unicode(iff( item.published, "Published ", iff( item.importable , "Accessible ", iff( item.users_shared_with, "Shared ", "Private " ) ) ) + get_class_display_name( item.__class__ ))) __M_writer(u' | ') __M_writer(filters.html_escape(unicode(get_item_name( item ) ))) __M_writer(u'\n') return '' finally: context.caller_stack._pop_frame()
def _list_delete(self, trans, histories, purge=False): """Delete histories""" n_deleted = 0 deleted_current = False message_parts = [] status = SUCCESS current_history = trans.get_history() for history in histories: try: if history.users_shared_with: raise exceptions.ObjectAttributeInvalidException( f"History ({history.name}) has been shared with others, unshare it before deleting it." ) if purge: self.history_manager.purge(history) else: self.history_manager.delete(history) if history == current_history: deleted_current = True except Exception as e: message_parts.append(unicodify(e)) status = ERROR else: trans.log_event(f"History ({history.name}) marked as deleted") n_deleted += 1 if n_deleted: part = "Deleted %d %s" % (n_deleted, iff(n_deleted != 1, "histories", "history")) if purge and trans.app.config.allow_user_dataset_purge: part += f" and removed {iff(n_deleted != 1, 'their', 'its')} dataset{iff(n_deleted != 1, 's', '')} from disk" elif purge: part += " but the datasets were not removed from disk because that feature is not enabled in this Galaxy instance" message_parts.append(f"{part}. ") if deleted_current: # if this history is the current history for this session, # - attempt to find the most recently used, undeleted history and switch to it. # - If no suitable recent history is found, create a new one and switch # note: this needs to come after commits above or will use an empty history that was deleted above not_deleted_or_purged = [model.History.deleted == false(), model.History.purged == false()] most_recent_history = self.history_manager.most_recent(user=trans.user, filters=not_deleted_or_purged) if most_recent_history: self.history_manager.set_current(trans, most_recent_history) else: trans.get_or_create_default_history() message_parts.append("Your active history was deleted, a new empty history is now active. ") status = INFO return (status, " ".join(message_parts))
def render_render_tagging_element_html(context,elt_id=None,tags=None,editable=True,use_toggle_link=True,input_size='15',in_form=False,tag_type='individual',render_add_tag_button=True): context.caller_stack._push_frame() try: h = context.get('h', UNDEFINED) unicode = context.get('unicode', UNDEFINED) isinstance = context.get('isinstance', UNDEFINED) len = context.get('len', UNDEFINED) str = context.get('str', UNDEFINED) __M_writer = context.writer() # SOURCE LINE 20 __M_writer(u'\n') # SOURCE LINE 22 __M_writer(u' ') num_tags = len( tags ) # SOURCE LINE 24 __M_writer(u'\n <div class="tag-element"\n') # SOURCE LINE 26 if elt_id: # SOURCE LINE 27 __M_writer(u' id="') __M_writer(unicode(elt_id)) __M_writer(u'"\n') pass # SOURCE LINE 30 if num_tags == 0 and not editable: # SOURCE LINE 31 __M_writer(u' style="display: none"\n') pass # SOURCE LINE 33 __M_writer(u' >\n') # SOURCE LINE 34 if use_toggle_link: # SOURCE LINE 35 __M_writer(u' <a class="toggle-link" href="#">') __M_writer(unicode(num_tags)) __M_writer(u' Tag') __M_writer(unicode(iff( num_tags == 1, "", "s"))) __M_writer(u'</a>\n') pass # SOURCE LINE 37 __M_writer(u' <div class="tag-area \n') # SOURCE LINE 38 if tag_type == 'individual': # SOURCE LINE 39 __M_writer(u' individual-tag-area\n') pass # SOURCE LINE 41 __M_writer(u' ">\n\n') # SOURCE LINE 44 for tag in tags: # SOURCE LINE 45 __M_writer(u' ') ## Handle both Tag and ItemTagAssociation objects. if isinstance( tag, Tag ): tag_name = tag.name tag_value = None elif isinstance( tag, ItemTagAssociation ): tag_name = tag.user_tname tag_value = tag.user_value ## Convert tag name, value to unicode. if isinstance( tag_name, str ): tag_name = unicode( escape( tag_name ), 'utf-8' ) if tag_value: tag_value = unicode( escape( tag_value ), 'utf-8' ) if tag_value: tag_str = tag_name + ":" + tag_value else: tag_str = tag_name # SOURCE LINE 62 __M_writer(u'\n <span class="tag-button">\n <span class="tag-name">') # SOURCE LINE 64 __M_writer(unicode(tag_str)) __M_writer(u'</span>\n') # SOURCE LINE 65 if editable: # SOURCE LINE 66 __M_writer(u' <img class="delete-tag-img" src="') __M_writer(unicode(h.url_for('/static/images/delete_tag_icon_gray.png'))) __M_writer(u'"/>\n') pass # SOURCE LINE 68 __M_writer(u' </span>\n') pass # SOURCE LINE 70 __M_writer(u' \n') # SOURCE LINE 72 if editable: # SOURCE LINE 73 if in_form: # SOURCE LINE 74 __M_writer(u' <textarea class="tag-input" rows=\'1\' cols=\'') __M_writer(unicode(input_size)) __M_writer(u"'></textarea>\n") # SOURCE LINE 75 else: # SOURCE LINE 76 __M_writer(u' <input class="tag-input" type=\'text\' size=\'') __M_writer(unicode(input_size)) __M_writer(u"'/>\n") pass # SOURCE LINE 79 if render_add_tag_button: # SOURCE LINE 80 __M_writer(u" <img src='") __M_writer(unicode(h.url_for('/static/images/fugue/tag--plus.png'))) __M_writer(u'\' class="add-tag-button tooltip" title="Add tags"/>\n') pass pass # SOURCE LINE 83 __M_writer(u' </div>\n </div>\n') return '' finally: context.caller_stack._pop_frame()
def __call__(self, trans, **kwargs): status = kwargs.get('status', None) message = kwargs.get('message', None) session = trans.sa_session # Build a base filter and sort key that is the combination of the saved state and defaults. Saved state takes preference over defaults. base_filter = {} if self.default_filter: base_filter = self.default_filter.copy() base_sort_key = self.default_sort_key if self.preserve_state: pref_name = unicode(self.__class__.__name__ + self.cur_filter_pref_name) if pref_name in trans.get_user().preferences: saved_filter = from_json_string( trans.get_user().preferences[pref_name]) base_filter.update(saved_filter) pref_name = unicode(self.__class__.__name__ + self.cur_sort_key_pref_name) if pref_name in trans.get_user().preferences: base_sort_key = from_json_string( trans.get_user().preferences[pref_name]) # Build initial query query = self.build_initial_query(session) query = self.apply_default_filter(trans, query, **kwargs) # Maintain sort state in generated urls extra_url_args = {} # Determine whether use_default_filter flag is set. use_default_filter_str = kwargs.get('use_default_filter') use_default_filter = False if use_default_filter_str: use_default_filter = (use_default_filter_str.lower() == 'true') # Process filtering arguments to (a) build a query that represents the filter and (b) builds a # dictionary that denotes the current filter. cur_filter_dict = {} for column in self.columns: if column.key: # Get the filter criterion for the column. Precedence is (a) if using default filter, only look there; otherwise, # (b) look in kwargs; and (c) look in base filter. column_filter = None if use_default_filter: if self.default_filter: column_filter = self.default_filter.get(column.key) elif "f-" + column.key in kwargs: column_filter = kwargs.get("f-" + column.key) elif column.key in base_filter: column_filter = base_filter.get(column.key) # Method (1) combines a mix of strings and lists of strings into a single string and (2) attempts to de-jsonify all strings. def from_json_string_recurse(item): decoded_list = [] if isinstance(item, basestring): try: # Not clear what we're decoding, so recurse to ensure that we catch everything. decoded_item = from_json_string(item) if isinstance(decoded_item, list): decoded_list = from_json_string_recurse( decoded_item) else: decoded_list = [unicode(decoded_item)] except ValueError: decoded_list = [unicode(item)] elif isinstance(item, list): return_val = [] for element in item: a_list = from_json_string_recurse(element) decoded_list = decoded_list + a_list return decoded_list # If column filter found, apply it. if column_filter is not None: # TextColumns may have a mix of json and strings. if isinstance(column, TextColumn): column_filter = from_json_string_recurse(column_filter) if len(column_filter) == 1: column_filter = column_filter[0] # If filter criterion is empty, do nothing. if column_filter == '': continue # Update query. query = column.filter(trans.sa_session, query, column_filter) # Upate current filter dict. cur_filter_dict[column.key] = column_filter # Carry filter along to newly generated urls; make sure filter is a string so # that we can encode to UTF-8 and thus handle user input to filters. if isinstance(column_filter, list): # Filter is a list; process each item. for filter in column_filter: if not isinstance(filter, basestring): filter = unicode(filter).encode("utf-8") extra_url_args["f-" + column.key] = to_json_string( column_filter) else: # Process singleton filter. if not isinstance(column_filter, basestring): column_filter = unicode(column_filter) extra_url_args[ "f-" + column.key] = column_filter.encode("utf-8") # Process sort arguments. sort_key = sort_order = None if 'sort' in kwargs: sort_key = kwargs['sort'] elif base_sort_key: sort_key = base_sort_key encoded_sort_key = sort_key if sort_key: if sort_key.startswith("-"): sort_key = sort_key[1:] sort_order = 'desc' query = query.order_by( self.model_class.table.c.get(sort_key).desc()) else: sort_order = 'asc' query = query.order_by( self.model_class.table.c.get(sort_key).asc()) extra_url_args['sort'] = encoded_sort_key # There might be a current row current_item = self.get_current_item(trans) # Process page number. if self.use_paging: if 'page' in kwargs: if kwargs['page'] == 'all': page_num = 0 else: page_num = int(kwargs['page']) else: page_num = 1 if page_num == 0: # Show all rows in page. total_num_rows = query.count() page_num = 1 num_pages = 1 else: # Show a limited number of rows. Before modifying query, get the total number of rows that query # returns so that the total number of pages can be computed. total_num_rows = query.count() query = query.limit(self.num_rows_per_page).offset( (page_num - 1) * self.num_rows_per_page) num_pages = int( math.ceil(float(total_num_rows) / self.num_rows_per_page)) else: # Defaults. page_num = 1 num_pages = 1 # Preserve grid state: save current filter and sort key. if self.preserve_state: pref_name = unicode(self.__class__.__name__ + self.cur_filter_pref_name) trans.get_user().preferences[pref_name] = unicode( to_json_string(cur_filter_dict)) if sort_key: pref_name = unicode(self.__class__.__name__ + self.cur_sort_key_pref_name) trans.get_user().preferences[pref_name] = unicode( to_json_string(sort_key)) trans.sa_session.flush() # Log grid view. context = unicode(self.__class__.__name__) params = cur_filter_dict.copy() params['sort'] = sort_key params['async'] = ('async' in kwargs) trans.log_action(unicode("grid.view"), context, params) # Render grid. def url(*args, **kwargs): # Only include sort/filter arguments if not linking to another # page. This is a bit of a hack. if 'action' in kwargs: new_kwargs = dict() else: new_kwargs = dict(extra_url_args) # Extend new_kwargs with first argument if found if len(args) > 0: new_kwargs.update(args[0]) new_kwargs.update(kwargs) # We need to encode item ids if 'id' in new_kwargs: id = new_kwargs['id'] if isinstance(id, list): new_args['id'] = [trans.security.encode_id(i) for i in id] else: new_kwargs['id'] = trans.security.encode_id(id) return url_for(**new_kwargs) async_request = ((self.use_async) and ('async' in kwargs) and (kwargs['async'] in ['True', 'true'])) return trans.fill_template( iff(async_request, self.async_template, self.template), grid=self, query=query, cur_page_num=page_num, num_pages=num_pages, default_filter_dict=self.default_filter, cur_filter_dict=cur_filter_dict, sort_key=sort_key, encoded_sort_key=encoded_sort_key, sort_order=sort_order, current_item=current_item, ids=kwargs.get('id', []), url=url, message_type=status, message=message, # Pass back kwargs so that grid template can set and use args without grid explicitly having to pass them. kwargs=kwargs)
class InstalledRepositoryGrid(grids.Grid): class ToolShedStatusColumn(grids.TextColumn): def get_value(self, trans, grid, tool_shed_repository): if tool_shed_repository.tool_shed_status: tool_shed_status_str = '' if tool_shed_repository.is_deprecated_in_tool_shed: tool_shed_status_str += generate_deprecated_repository_img_str( include_mouse_over=True) if tool_shed_repository.is_latest_installable_revision: tool_shed_status_str += generate_latest_revision_img_str( include_mouse_over=True) if tool_shed_repository.revision_update_available: tool_shed_status_str += generate_revision_updates_img_str( include_mouse_over=True) if tool_shed_repository.upgrade_available: tool_shed_status_str += generate_revision_upgrades_img_str( include_mouse_over=True) if tool_shed_repository.includes_workflows: tool_shed_status_str += generate_includes_workflows_img_str( include_mouse_over=True) else: tool_shed_status_str = generate_unknown_img_str( include_mouse_over=True) return tool_shed_status_str class NameColumn(grids.TextColumn): def get_value(self, trans, grid, tool_shed_repository): return str(tool_shed_repository.name) class DescriptionColumn(grids.TextColumn): def get_value(self, trans, grid, tool_shed_repository): return util.unicodify(tool_shed_repository.description) class OwnerColumn(grids.TextColumn): def get_value(self, trans, grid, tool_shed_repository): return str(tool_shed_repository.owner) class RevisionColumn(grids.TextColumn): def get_value(self, trans, grid, tool_shed_repository): return str(tool_shed_repository.changeset_revision) class StatusColumn(grids.TextColumn): def get_value(self, trans, grid, tool_shed_repository): return suc.get_tool_shed_repository_status_label( trans.app, tool_shed_repository) class ToolShedColumn(grids.TextColumn): def get_value(self, trans, grid, tool_shed_repository): return tool_shed_repository.tool_shed class DeletedColumn(grids.DeletedColumn): def get_accepted_filters(self): """ Returns a list of accepted filters for this column. """ accepted_filter_labels_and_vals = { "Active": "False", "Deactivated or uninstalled": "True", "All": "All" } accepted_filters = [] for label, val in accepted_filter_labels_and_vals.items(): args = {self.key: val} accepted_filters.append(grids.GridColumnFilter(label, args)) return accepted_filters # Grid definition title = "Installed tool shed repositories" model_class = tool_shed_install.ToolShedRepository template = '/admin/tool_shed_repository/grid.mako' default_sort_key = "name" columns = [ ToolShedStatusColumn(label=""), NameColumn( label="Name", key="name", link=(lambda item: iff( item.status in [ tool_shed_install.ToolShedRepository.installation_status. CLONING ], None, dict(operation="manage_repository", id=item.id))), attach_popup=True), DescriptionColumn(label="Description"), OwnerColumn(label="Owner"), RevisionColumn(label="Revision"), StatusColumn(label="Installation Status", filterable="advanced"), ToolShedColumn(label="Tool shed"), # Columns that are valid for filtering but are not visible. DeletedColumn(label="Status", key="deleted", visible=False, filterable="advanced") ] columns.append( grids.MulticolFilterColumn("Search repository name", cols_to_filter=[columns[1]], key="free-text-search", visible=False, filterable="standard")) global_actions = [ grids.GridAction( label="Update tool shed status", url_args=dict( controller='admin_toolshed', action='update_tool_shed_status_for_installed_repository', all_installed_repositories=True), inbound=False) ] operations = [ grids.GridOperation( label="Update tool shed status", condition=( lambda item: not item.deleted ), allow_multiple=False, url_args=dict( controller='admin_toolshed', action='browse_repositories', operation='update tool shed status' ) ), grids.GridOperation( label="Get updates", condition=( lambda item: \ not item.deleted and \ item.revision_update_available and \ item.status not in \ [ tool_shed_install.ToolShedRepository.installation_status.ERROR, tool_shed_install.ToolShedRepository.installation_status.NEW ] ), allow_multiple=False, url_args=dict( controller='admin_toolshed', action='browse_repositories', operation='get updates' ) ), grids.GridOperation( label="Install latest revision", condition=( lambda item: item.upgrade_available ), allow_multiple=False, url_args=dict( controller='admin_toolshed', action='browse_repositories', operation='install latest revision' ) ), grids.GridOperation( label="Install", condition=( lambda item: \ not item.deleted and \ item.status == tool_shed_install.ToolShedRepository.installation_status.NEW ), allow_multiple=False, url_args=dict( controller='admin_toolshed', action='manage_repository', operation='install' ) ), grids.GridOperation( label="Deactivate or uninstall", condition=( lambda item: \ not item.deleted and \ item.status != tool_shed_install.ToolShedRepository.installation_status.NEW ), allow_multiple=False, url_args=dict( controller='admin_toolshed', action='browse_repositories', operation='deactivate or uninstall' ) ), grids.GridOperation( label="Reset to install", condition=( lambda item: \ ( item.status == tool_shed_install.ToolShedRepository.installation_status.ERROR ) ), allow_multiple=False, url_args=dict( controller='admin_toolshed', action='browse_repositories', operation='reset to install' ) ), grids.GridOperation( label="Activate or reinstall", condition=( lambda item: item.deleted ), allow_multiple=False, target=None, url_args=dict( controller='admin_toolshed', action='browse_repositories', operation='activate or reinstall' ) ), grids.GridOperation( label="Purge", condition=( lambda item: item.is_new ), allow_multiple=False, target=None, url_args=dict( controller='admin_toolshed', action='browse_repositories', operation='purge' ) ) ] standard_filters = [] default_filter = dict(deleted="False") num_rows_per_page = 50 preserve_state = False use_paging = False def build_initial_query(self, trans, **kwd): return trans.install_model.context.query( self.model_class ) \ .order_by( self.model_class.table.c.tool_shed, self.model_class.table.c.name, self.model_class.table.c.owner, self.model_class.table.c.ctx_rev ) @property def legend(self): legend_str = '%s Updates are available in the Tool Shed for this revision<br/>' % generate_revision_updates_img_str( ) legend_str += '%s A newer installable revision is available for this repository<br/>' % generate_revision_upgrades_img_str( ) legend_str += '%s This is the latest installable revision of this repository<br/>' % generate_latest_revision_img_str( ) legend_str += '%s This repository is deprecated in the Tool Shed<br/>' % generate_deprecated_repository_img_str( ) legend_str += '%s This repository contains exported workflows<br/>' % generate_includes_workflows_img_str( ) legend_str += '%s Unable to get information from the Tool Shed<br/>' % generate_unknown_img_str( ) return legend_str
class RepositoryInstallationGrid(grids.Grid): class NameColumn(grids.TextColumn): def get_value(self, trans, grid, tool_shed_repository): return tool_shed_repository.name class DescriptionColumn(grids.TextColumn): def get_value(self, trans, grid, tool_shed_repository): return tool_shed_repository.description class OwnerColumn(grids.TextColumn): def get_value(self, trans, grid, tool_shed_repository): return tool_shed_repository.owner class RevisionColumn(grids.TextColumn): def get_value(self, trans, grid, tool_shed_repository): return tool_shed_repository.changeset_revision class StatusColumn(grids.TextColumn): def get_value(self, trans, grid, tool_shed_repository): status_label = tool_shed_repository.status if tool_shed_repository.status in [ trans.install_model.ToolShedRepository.installation_status. CLONING, trans.install_model.ToolShedRepository. installation_status.SETTING_TOOL_VERSIONS, trans.install_model.ToolShedRepository.installation_status. INSTALLING_TOOL_DEPENDENCIES, trans.install_model.ToolShedRepository.installation_status. LOADING_PROPRIETARY_DATATYPES ]: bgcolor = trans.install_model.ToolShedRepository.states.INSTALLING elif tool_shed_repository.status in [ trans.install_model.ToolShedRepository.installation_status. NEW, trans.install_model.ToolShedRepository. installation_status.UNINSTALLED ]: bgcolor = trans.install_model.ToolShedRepository.states.UNINSTALLED elif tool_shed_repository.status in [ trans.install_model.ToolShedRepository.installation_status. ERROR ]: bgcolor = trans.install_model.ToolShedRepository.states.ERROR elif tool_shed_repository.status in [ trans.install_model.ToolShedRepository.installation_status. DEACTIVATED ]: bgcolor = trans.install_model.ToolShedRepository.states.WARNING elif tool_shed_repository.status in [ trans.install_model.ToolShedRepository.installation_status. INSTALLED ]: if tool_shed_repository.missing_tool_dependencies or tool_shed_repository.missing_repository_dependencies: bgcolor = trans.install_model.ToolShedRepository.states.WARNING if tool_shed_repository.missing_tool_dependencies and not tool_shed_repository.missing_repository_dependencies: status_label = '%s, missing tool dependencies' % status_label if tool_shed_repository.missing_repository_dependencies and not tool_shed_repository.missing_tool_dependencies: status_label = '%s, missing repository dependencies' % status_label if tool_shed_repository.missing_tool_dependencies and tool_shed_repository.missing_repository_dependencies: status_label = '%s, missing both tool and repository dependencies' % status_label if not tool_shed_repository.missing_tool_dependencies and not tool_shed_repository.missing_repository_dependencies: bgcolor = trans.install_model.ToolShedRepository.states.OK else: bgcolor = trans.install_model.ToolShedRepository.states.ERROR rval = '<div class="count-box state-color-%s" id="RepositoryStatus-%s">%s</div>' % \ ( bgcolor, trans.security.encode_id( tool_shed_repository.id ), status_label ) return rval title = "Monitor installing tool shed repositories" template = "admin/tool_shed_repository/repository_installation_grid.mako" model_class = tool_shed_install.ToolShedRepository default_sort_key = "-create_time" num_rows_per_page = 50 preserve_state = True use_paging = False columns = [ NameColumn( "Name", link=( lambda item: iff( item.status in \ [ tool_shed_install.ToolShedRepository.installation_status.NEW, tool_shed_install.ToolShedRepository.installation_status.CLONING, tool_shed_install.ToolShedRepository.installation_status.SETTING_TOOL_VERSIONS, tool_shed_install.ToolShedRepository.installation_status.INSTALLING_REPOSITORY_DEPENDENCIES, tool_shed_install.ToolShedRepository.installation_status.INSTALLING_TOOL_DEPENDENCIES, tool_shed_install.ToolShedRepository.installation_status.LOADING_PROPRIETARY_DATATYPES, tool_shed_install.ToolShedRepository.installation_status.UNINSTALLED ], \ None, dict( action="manage_repository", id=item.id ) ) ), filterable="advanced" ), DescriptionColumn( "Description", filterable="advanced" ), OwnerColumn( "Owner", filterable="advanced" ), RevisionColumn( "Revision", filterable="advanced" ), StatusColumn( "Installation Status", filterable="advanced", label_id_prefix="RepositoryStatus-" ) ] operations = [] def build_initial_query(self, trans, **kwd): clause_list = [] tool_shed_repository_ids = util.listify( kwd.get('tool_shed_repository_ids', None)) if tool_shed_repository_ids: for tool_shed_repository_id in tool_shed_repository_ids: clause_list.append(self.model_class.table.c.id == trans. security.decode_id(tool_shed_repository_id)) if clause_list: return trans.install_model.context.query( self.model_class ) \ .filter( or_( *clause_list ) ) for tool_shed_repository in trans.install_model.context.query( self.model_class ) \ .filter( self.model_class.table.c.deleted == False ): if tool_shed_repository.status in [ trans.install_model.ToolShedRepository.installation_status. NEW, trans.install_model.ToolShedRepository. installation_status.CLONING, trans.install_model.ToolShedRepository.installation_status. SETTING_TOOL_VERSIONS, trans.install_model.ToolShedRepository.installation_status. INSTALLING_TOOL_DEPENDENCIES, trans.install_model.ToolShedRepository.installation_status. LOADING_PROPRIETARY_DATATYPES ]: clause_list.append( self.model_class.table.c.id == tool_shed_repository.id) if clause_list: return trans.install_model.context.query( self.model_class ) \ .filter( or_( *clause_list ) ) return trans.install_model.context.query( self.model_class ) \ .filter( self.model_class.table.c.status == trans.install_model.ToolShedRepository.installation_status.NEW ) def apply_query_filter(self, trans, query, **kwd): tool_shed_repository_id = kwd.get('tool_shed_repository_id', None) if tool_shed_repository_id: return query.filter_by(tool_shed_repository_id=trans.security. decode_id(tool_shed_repository_id)) return query
def __call__(self, trans, **kwargs): # Get basics. webapp = kwargs.get('webapp', 'galaxy') status = kwargs.get('status', None) message = kwargs.get('message', None) # Build a base filter and sort key that is the combination of the saved state and defaults. # Saved state takes preference over defaults. base_filter = {} if self.default_filter: # default_filter is a dictionary that provides a default set of filters based on the grid's columns. base_filter = self.default_filter.copy() base_sort_key = self.default_sort_key if self.preserve_state: pref_name = unicode(self.__class__.__name__ + self.cur_filter_pref_name) if pref_name in trans.get_user().preferences: saved_filter = from_json_string( trans.get_user().preferences[pref_name]) base_filter.update(saved_filter) pref_name = unicode(self.__class__.__name__ + self.cur_sort_key_pref_name) if pref_name in trans.get_user().preferences: base_sort_key = from_json_string( trans.get_user().preferences[pref_name]) # Build initial query query = self.build_initial_query(trans, **kwargs) query = self.apply_query_filter(trans, query, **kwargs) # Maintain sort state in generated urls extra_url_args = {} # Determine whether use_default_filter flag is set. use_default_filter_str = kwargs.get('use_default_filter') use_default_filter = False if use_default_filter_str: use_default_filter = (use_default_filter_str.lower() == 'true') # Process filtering arguments to (a) build a query that represents the filter and (b) build a # dictionary that denotes the current filter. cur_filter_dict = {} for column in self.columns: if column.key: # Get the filter criterion for the column. Precedence is (a) if using default filter, only look there; otherwise, # (b) look in kwargs; and (c) look in base filter. column_filter = None if use_default_filter: if self.default_filter: column_filter = self.default_filter.get(column.key) elif "f-" + column.model_class.__name__ + ".%s" % column.key in kwargs: # Queries that include table joins cannot guarantee unique column names. This problem is # handled by setting the column_filter value to <TableName>.<ColumnName>. column_filter = kwargs.get("f-" + column.model_class.__name__ + ".%s" % column.key) elif "f-" + column.key in kwargs: column_filter = kwargs.get("f-" + column.key) elif column.key in base_filter: column_filter = base_filter.get(column.key) # Method (1) combines a mix of strings and lists of strings into a single string and (2) attempts to de-jsonify all strings. def from_json_string_recurse(item): decoded_list = [] if isinstance(item, basestring): try: # Not clear what we're decoding, so recurse to ensure that we catch everything. decoded_item = from_json_string(item) if isinstance(decoded_item, list): decoded_list = from_json_string_recurse( decoded_item) else: decoded_list = [unicode(decoded_item)] except ValueError: decoded_list = [unicode(item)] elif isinstance(item, list): return_val = [] for element in item: a_list = from_json_string_recurse(element) decoded_list = decoded_list + a_list return decoded_list # If column filter found, apply it. if column_filter is not None: # TextColumns may have a mix of json and strings. if isinstance(column, TextColumn): column_filter = from_json_string_recurse(column_filter) if len(column_filter) == 1: column_filter = column_filter[0] # Interpret ',' as a separator for multiple terms. if isinstance( column_filter, basestring) and column_filter.find(',') != -1: column_filter = column_filter.split(',') # If filter criterion is empty, do nothing. if column_filter == '': continue # Update query. query = column.filter(trans, trans.user, query, column_filter) # Upate current filter dict. cur_filter_dict[column.key] = column_filter # Carry filter along to newly generated urls; make sure filter is a string so # that we can encode to UTF-8 and thus handle user input to filters. if isinstance(column_filter, list): # Filter is a list; process each item. for filter in column_filter: if not isinstance(filter, basestring): filter = unicode(filter).encode("utf-8") extra_url_args["f-" + column.key] = to_json_string( column_filter) else: # Process singleton filter. if not isinstance(column_filter, basestring): column_filter = unicode(column_filter) extra_url_args[ "f-" + column.key] = column_filter.encode("utf-8") # Process sort arguments. sort_key = None if 'sort' in kwargs: sort_key = kwargs['sort'] elif base_sort_key: sort_key = base_sort_key if sort_key: ascending = not (sort_key.startswith("-")) # Queries that include table joins cannot guarantee unique column names. This problem is # handled by setting the column_filter value to <TableName>.<ColumnName>. table_name = None if sort_key.find('.') > -1: a_list = sort_key.split('.') if ascending: table_name = a_list[0] else: table_name = a_list[0][1:] column_name = a_list[1] elif ascending: column_name = sort_key else: column_name = sort_key[1:] # Sort key is a column key. for column in self.columns: if column.key and column.key.find('.') > -1: column_key = column.key.split('.')[1] else: column_key = column.key if (table_name is None or table_name == column.model_class.__name__ ) and column_key == column_name: query = column.sort(trans, query, ascending, column_name=column_name) break extra_url_args['sort'] = sort_key # There might be a current row current_item = self.get_current_item(trans, **kwargs) # Process page number. if self.use_paging: if 'page' in kwargs: if kwargs['page'] == 'all': page_num = 0 else: page_num = int(kwargs['page']) else: page_num = 1 if page_num == 0: # Show all rows in page. total_num_rows = query.count() page_num = 1 num_pages = 1 else: # Show a limited number of rows. Before modifying query, get the total number of rows that query # returns so that the total number of pages can be computed. total_num_rows = query.count() query = query.limit(self.num_rows_per_page).offset( (page_num - 1) * self.num_rows_per_page) num_pages = int( math.ceil(float(total_num_rows) / self.num_rows_per_page)) else: # Defaults. page_num = 1 num_pages = 1 # There are some places in grid templates where it's useful for a grid # to have its current filter. self.cur_filter_dict = cur_filter_dict # Preserve grid state: save current filter and sort key. if self.preserve_state: pref_name = unicode(self.__class__.__name__ + self.cur_filter_pref_name) trans.get_user().preferences[pref_name] = unicode( to_json_string(cur_filter_dict)) if sort_key: pref_name = unicode(self.__class__.__name__ + self.cur_sort_key_pref_name) trans.get_user().preferences[pref_name] = unicode( to_json_string(sort_key)) trans.sa_session.flush() # Log grid view. context = unicode(self.__class__.__name__) params = cur_filter_dict.copy() params['sort'] = sort_key params['async'] = ('async' in kwargs) params['webapp'] = webapp trans.log_action(trans.get_user(), unicode("grid.view"), context, params) # Render grid. def url(*args, **kwargs): # Only include sort/filter arguments if not linking to another # page. This is a bit of a hack. if 'action' in kwargs: new_kwargs = dict() else: new_kwargs = dict(extra_url_args) # Extend new_kwargs with first argument if found if len(args) > 0: new_kwargs.update(args[0]) new_kwargs.update(kwargs) # We need to encode item ids if 'id' in new_kwargs: id = new_kwargs['id'] if isinstance(id, list): new_args['id'] = [trans.security.encode_id(i) for i in id] else: new_kwargs['id'] = trans.security.encode_id(id) return url_for(**new_kwargs) self.use_panels = (kwargs.get('use_panels', False) in [True, 'True', 'true']) async_request = ((self.use_async) and (kwargs.get('async', False) in [True, 'True', 'true'])) # Currently, filling the template returns a str object; this requires decoding the string into a # unicode object within mako templates. What probably should be done is to return the template as # utf-8 unicode; however, this would require encoding the object as utf-8 before returning the grid # results via a controller method, which is require substantial changes. Hence, for now, return grid # as str. return trans.fill_template( iff(async_request, self.async_template, self.template), grid=self, query=query, cur_page_num=page_num, num_pages=num_pages, num_page_links=self.num_page_links, default_filter_dict=self.default_filter, cur_filter_dict=cur_filter_dict, sort_key=sort_key, current_item=current_item, ids=kwargs.get('id', []), url=url, status=status, message=message, use_panels=self.use_panels, webapp=webapp, show_item_checkboxes=(kwargs.get('show_item_checkboxes', '') in ['True', 'true']), # Pass back kwargs so that grid template can set and use args without # grid explicitly having to pass them. kwargs=kwargs)
class RequestTypeGrid(grids.Grid): # Custom column types class NameColumn(grids.TextColumn): def get_value(self, trans, grid, request_type): return escape(request_type.name) class DescriptionColumn(grids.TextColumn): def get_value(self, trans, grid, request_type): return escape(request_type.desc) class RequestFormColumn(grids.TextColumn): def get_value(self, trans, grid, request_type): return escape(request_type.request_form.name) class SampleFormColumn(grids.TextColumn): def get_value(self, trans, grid, request_type): return escape(request_type.sample_form.name) class ExternalServiceColumn(grids.IntegerColumn): def get_value(self, trans, grid, request_type): if request_type.external_services: return len(request_type.external_services) return 'No external service assigned' # Grid definition title = "Request Types" template = "admin/request_type/grid.mako" model_class = model.RequestType default_sort_key = "-create_time" num_rows_per_page = 50 preserve_state = True use_paging = True default_filter = dict(deleted="False") columns = [ NameColumn("Name", key="name", link=(lambda item: iff( item.deleted, None, dict(operation="view_request_type", id=item.id))), attach_popup=True, filterable="advanced"), DescriptionColumn("Description", key='desc', filterable="advanced"), RequestFormColumn("Request Form", link=(lambda item: iff( item.deleted, None, dict(operation="view_form_definition", id=item.request_form.id)))), SampleFormColumn( "Sample Form", link=(lambda item: iff( item.deleted, None, dict(operation="view_form_definition", id=item.sample_form.id)) )), ExternalServiceColumn("External Services"), grids.DeletedColumn("Deleted", key="deleted", visible=False, filterable="advanced") ] columns.append( grids.MulticolFilterColumn("Search", cols_to_filter=[columns[0], columns[1]], key="free-text-search", visible=False, filterable="standard")) operations = [ grids.GridOperation("Edit request type", allow_multiple=False, condition=(lambda item: not item.deleted)), grids.GridOperation("Edit permissions", allow_multiple=False, condition=(lambda item: not item.deleted)), grids.GridOperation( "Use run details template", allow_multiple=False, condition=( lambda item: not item.deleted and not item.run_details)), grids.GridOperation("Delete", allow_multiple=True, condition=(lambda item: not item.deleted)), grids.GridOperation("Undelete", condition=(lambda item: item.deleted)), ] global_actions = [ grids.GridAction( "Create new request type", dict(controller='request_type', action='create_request_type')) ]
def render_render_grid_column_filter(context, grid, column): context.caller_stack._push_frame() try: basestring = context.get('basestring', UNDEFINED) cur_filter_dict = context.get('cur_filter_dict', UNDEFINED) url = context.get('url', UNDEFINED) h = context.get('h', UNDEFINED) list = context.get('list', UNDEFINED) len = context.get('len', UNDEFINED) dict = context.get('dict', UNDEFINED) enumerate = context.get('enumerate', UNDEFINED) isinstance = context.get('isinstance', UNDEFINED) __M_writer = context.writer() # SOURCE LINE 7 __M_writer(u'\n <tr>\n ') # SOURCE LINE 9 column_label = column.label if column.filterable == "advanced": column_label = column_label.lower() # SOURCE LINE 13 __M_writer(u'\n') # SOURCE LINE 14 if column.filterable == "advanced": # SOURCE LINE 15 __M_writer( u' <td align="left" style="padding-left: 10px">') __M_writer(unicode(column_label)) __M_writer(u':</td>\n') # SOURCE LINE 17 __M_writer(u' <td style="padding: 0;">\n') # SOURCE LINE 18 if isinstance(column, TextColumn): # SOURCE LINE 19 __M_writer( u' <form class="text-filter-form" column_key="') __M_writer(unicode(column.key)) __M_writer(u'" action="') __M_writer(unicode(url(dict()))) __M_writer(u'" method="get" >\n') # SOURCE LINE 21 for temp_column in grid.columns: # SOURCE LINE 22 if temp_column.key in cur_filter_dict: # SOURCE LINE 23 __M_writer(u' ') value = cur_filter_dict[temp_column.key] __M_writer(u'\n') # SOURCE LINE 24 if value != "All": # SOURCE LINE 25 __M_writer(u' ') if isinstance(temp_column, TextColumn): value = h.to_json_string(value) # SOURCE LINE 28 __M_writer( u'\n <input type="hidden" id="' ) # SOURCE LINE 29 __M_writer(unicode(temp_column.key)) __M_writer(u'" name="f-') __M_writer(unicode(temp_column.key)) __M_writer(u'" value=\'') __M_writer(unicode(value)) __M_writer(u"'/>\n") # SOURCE LINE 33 __M_writer(u' \n') # SOURCE LINE 35 __M_writer(u' <span id="') __M_writer(unicode(column.key)) __M_writer(u'-filtering-criteria">\n') # SOURCE LINE 36 if column.key in cur_filter_dict: # SOURCE LINE 37 __M_writer(u' ') column_filter = cur_filter_dict[column.key] __M_writer(u'\n') # SOURCE LINE 38 if isinstance(column_filter, basestring): # SOURCE LINE 39 if column_filter != "All": # SOURCE LINE 40 __M_writer( u" <span class='text-filter-val'>\n " ) # SOURCE LINE 41 __M_writer(unicode(cur_filter_dict[column.key])) __M_writer( u'\n ') # SOURCE LINE 42 filter_all = GridColumnFilter("", {column.key: "All"}) __M_writer( u'\n <a href="' ) # SOURCE LINE 43 __M_writer(unicode(url(filter_all.get_url_args()))) __M_writer( u'"><span class="delete-search-icon" /></a> \n </span>\n' ) # SOURCE LINE 46 elif isinstance(column_filter, list): # SOURCE LINE 47 for i, filter in enumerate(column_filter): # SOURCE LINE 48 if i > 0: # SOURCE LINE 49 __M_writer( u' ,\n') # SOURCE LINE 51 __M_writer( u" <span class='text-filter-val'>" ) __M_writer(unicode(filter)) __M_writer( u'\n ') # SOURCE LINE 52 new_filter = list(column_filter) del new_filter[i] new_column_filter = GridColumnFilter( "", {column.key: h.to_json_string(new_filter)}) # SOURCE LINE 56 __M_writer( u'\n <a href="' ) # SOURCE LINE 57 __M_writer( unicode(url(new_column_filter.get_url_args()))) __M_writer( u'"><span class="delete-search-icon" /></a>\n </span>\n' ) # SOURCE LINE 62 __M_writer(u' </span>\n') # SOURCE LINE 64 __M_writer( u' <span class="search-box">\n ' ) # SOURCE LINE 65 # Set value, size of search input field. Minimum size is 20 characters. value = iff(column.filterable == "standard", column.label.lower(), "") size = len(value) if size < 20: size = 20 # +4 to account for search icon/button. size = size + 4 # SOURCE LINE 73 __M_writer( u'\n <input class="search-box-input" id="input-' ) # SOURCE LINE 74 __M_writer(unicode(column.key)) __M_writer(u'-filter" name="f-') __M_writer(unicode(column.key)) __M_writer(u'" type="text" value="') __M_writer(unicode(value)) __M_writer(u'" size="') __M_writer(unicode(size)) __M_writer( u'"/>\n <button class="submit-image" type="submit" title=\'Search\'><span style="display: none;"></button>\n </span>\n </form>\n' ) # SOURCE LINE 78 else: # SOURCE LINE 79 __M_writer(u' <span id="') __M_writer(unicode(column.key)) __M_writer(u'-filtering-criteria">\n') # SOURCE LINE 80 for i, filter in enumerate(column.get_accepted_filters()): # SOURCE LINE 81 __M_writer(u' ') # HACK: we know that each filter will have only a single argument, so get that single argument. for key, arg in filter.args.items(): filter_key = key filter_arg = arg # SOURCE LINE 86 __M_writer(u'\n') # SOURCE LINE 87 if i > 0: # SOURCE LINE 88 __M_writer(u' |\n') # SOURCE LINE 90 if column.key in cur_filter_dict and column.key in filter.args and cur_filter_dict[ column.key] == filter.args[column.key]: # SOURCE LINE 91 __M_writer( u' <span class="categorical-filter ' ) __M_writer(unicode(column.key)) __M_writer(u'-filter current-filter">') __M_writer(unicode(filter.label)) __M_writer(u'</span>\n') # SOURCE LINE 92 else: # SOURCE LINE 93 __M_writer( u' <span class="categorical-filter ' ) __M_writer(unicode(column.key)) __M_writer( u'-filter">\n <a href="' ) # SOURCE LINE 94 __M_writer(unicode(url(filter.get_url_args()))) __M_writer(u'" filter_key="') __M_writer(unicode(filter_key)) __M_writer(u'" filter_val="') __M_writer(unicode(filter_arg)) __M_writer(u'">') __M_writer(unicode(filter.label)) __M_writer(u'</a>\n </span>\n') # SOURCE LINE 98 __M_writer(u' </span>\n') # SOURCE LINE 100 __M_writer(u' </td>\n </tr>\n') return '' finally: context.caller_stack._pop_frame()
class ExternalServiceGrid(grids.Grid): # Custom column types class NameColumn(grids.TextColumn): def get_value(self, trans, grid, external_service): return external_service.name class ExternalServiceTypeColumn(grids.TextColumn): def get_value(self, trans, grid, external_service): try: return trans.app.external_service_types.all_external_service_types[ external_service.external_service_type_id].name except KeyError: return 'Error in loading external_service type: %s' % external_service.external_service_type_id # Grid definition title = "External Services" template = "admin/external_service/grid.mako" model_class = model.ExternalService default_sort_key = "-create_time" num_rows_per_page = 50 preserve_state = True use_paging = True default_filter = dict(deleted="False") columns = [ NameColumn("Name", key="name", link=(lambda item: iff(item.deleted, None, dict(operation="view", id=item.id))), attach_popup=True, filterable="advanced"), grids.TextColumn("Description", key='description', filterable="advanced"), ExternalServiceTypeColumn("External Service Type"), grids.GridColumn("Last Updated", key="update_time", format=time_ago), grids.DeletedColumn("Deleted", key="deleted", visible=False, filterable="advanced") ] columns.append( grids.MulticolFilterColumn("Search", cols_to_filter=[columns[0], columns[1]], key="free-text-search", visible=False, filterable="standard")) operations = [ grids.GridOperation("Edit", allow_multiple=False, condition=(lambda item: not item.deleted)), grids.GridOperation("Delete", allow_multiple=True, condition=(lambda item: not item.deleted)), grids.GridOperation("Undelete", condition=(lambda item: item.deleted)), ] global_actions = [ grids.GridAction( "Reload external service types", dict(controller='external_service', action='reload_external_service_types')), grids.GridAction( "Create new external service", dict(controller='external_service', action='create_external_service')) ]
except KeyError, e: return 'Error in loading external_service type: %s' % external_service.external_service_type_id # Grid definition title = "External Services" template = "admin/external_service/grid.mako" model_class = model.ExternalService default_sort_key = "-create_time" num_rows_per_page = 50 preserve_state = True use_paging = True default_filter = dict( deleted="False" ) columns = [ NameColumn( "Name", key="name", link=( lambda item: iff( item.deleted, None, dict( operation="view", id=item.id ) ) ), attach_popup=True, filterable="advanced" ), grids.TextColumn( "Description", key='description', filterable="advanced" ), ExternalServiceTypeColumn( "External Service Type" ), grids.GridColumn( "Last Updated", key="update_time", format=time_ago ), grids.DeletedColumn( "Deleted", key="deleted", visible=False, filterable="advanced" ) ] columns.append( grids.MulticolFilterColumn( "Search",
def render_render_individual_tagging_element(context,user=None,tagged_item=None,elt_context=None,use_toggle_link=True,in_form=False,input_size='15',tag_click_fn='default_tag_click_fn',get_toggle_link_text_fn='default_get_toggle_link_text_fn',editable=True,render_add_tag_button=True): context.caller_stack._push_frame() try: isinstance = context.get('isinstance', UNDEFINED) unicode = context.get('unicode', UNDEFINED) int = context.get('int', UNDEFINED) h = context.get('h', UNDEFINED) self = context.get('self', UNDEFINED) dict = context.get('dict', UNDEFINED) str = context.get('str', UNDEFINED) trans = context.get('trans', UNDEFINED) __M_writer = context.writer() # SOURCE LINE 122 __M_writer(u'\n') # SOURCE LINE 124 __M_writer(u' ') # Useful ids. tagged_item_id = str( trans.security.encode_id ( tagged_item.id ) ) elt_id = int ( floor ( random()*maxint ) ) # Get list of user's item tags. TODO: implement owner_tags for all taggable objects and use here. item_tags = [ tag for tag in tagged_item.tags if ( tag.user == user ) ] # SOURCE LINE 131 __M_writer(u'\n \n') # SOURCE LINE 134 __M_writer(u' ') __M_writer(unicode(self.render_tagging_element_html(elt_id=elt_id, tags=item_tags, editable=editable, use_toggle_link=use_toggle_link, input_size=input_size, in_form=in_form, render_add_tag_button=render_add_tag_button))) __M_writer(u'\n \n') # SOURCE LINE 137 __M_writer(u' <script type="text/javascript">\n //\n // Set up autocomplete tagger.\n //\n\n //\n // Default function get text to display on the toggle link.\n //\n var default_get_toggle_link_text_fn = function(tags)\n {\n var text = "";\n var num_tags = obj_length(tags);\n if (num_tags != 0)\n {\n text = num_tags + (num_tags != 1 ? " Tags" : " Tag");\n /*\n // Show first N tags; hide the rest.\n var max_to_show = 1;\n \n // Build tag string.\n var tag_strs = new Array();\n var count = 0;\n for (tag_name in tags)\n {\n tag_value = tags[tag_name];\n tag_strs[tag_strs.length] = build_tag_str(tag_name, tag_value);\n if (++count == max_to_show)\n break;\n }\n tag_str = tag_strs.join(", ");\n \n // Finalize text.\n var num_tags_hiding = num_tags - max_to_show;\n text = "Tags: " + tag_str + \n (num_tags_hiding != 0 ? " and " + num_tags_hiding + " more" : "");\n */\n }\n else\n {\n // No tags.\n text = "Add tags";\n }\n return text;\n };\n \n // Default function to handle a tag click.\n var default_tag_click_fn = function(tag_name, tag_value) { };\n \n ') # SOURCE LINE 185 ## Build dict of tag name, values. tag_names_and_values = dict() for tag in item_tags: tag_name = tag.user_tname tag_value = "" if tag.value is not None: tag_value = tag.user_value ## Tag names and values may be string or unicode object. if isinstance( tag_name, str ): tag_names_and_values[unicode(tag_name, 'utf-8')] = unicode(tag_value, 'utf-8') else: ## isInstance( tag_name, unicode ): tag_names_and_values[tag_name] = tag_value # SOURCE LINE 198 __M_writer(u'\n var options =\n {\n tags : ') # SOURCE LINE 201 __M_writer(unicode(h.to_json_string(tag_names_and_values))) __M_writer(u',\n editable : ') # SOURCE LINE 202 __M_writer(unicode(iff( editable, 'true', 'false' ))) __M_writer(u',\n get_toggle_link_text_fn: ') # SOURCE LINE 203 __M_writer(unicode(get_toggle_link_text_fn)) __M_writer(u',\n tag_click_fn: ') # SOURCE LINE 204 __M_writer(unicode(tag_click_fn)) __M_writer(u',\n') # SOURCE LINE 206 __M_writer(u' ajax_autocomplete_tag_url: "') __M_writer(unicode(h.url_for( controller='/tag', action='tag_autocomplete_data', item_id=tagged_item_id, item_class=tagged_item.__class__.__name__ ))) __M_writer(u'",\n ajax_add_tag_url: "') # SOURCE LINE 207 __M_writer(unicode(h.url_for( controller='/tag', action='add_tag_async', item_id=tagged_item_id, item_class=tagged_item.__class__.__name__, context=elt_context ))) __M_writer(u'",\n ajax_delete_tag_url: "') # SOURCE LINE 208 __M_writer(unicode(h.url_for( controller='/tag', action='remove_tag_async', item_id=tagged_item_id, item_class=tagged_item.__class__.__name__, context=elt_context ))) __M_writer(u'",\n delete_tag_img: "') # SOURCE LINE 209 __M_writer(unicode(h.url_for('/static/images/delete_tag_icon_gray.png'))) __M_writer(u'",\n delete_tag_img_rollover: "') # SOURCE LINE 210 __M_writer(unicode(h.url_for('/static/images/delete_tag_icon_white.png'))) __M_writer(u'",\n use_toggle_link: ') # SOURCE LINE 211 __M_writer(unicode(iff( use_toggle_link, 'true', 'false' ))) __M_writer(u"\n };\n \n $('#") # SOURCE LINE 214 __M_writer(unicode(elt_id)) __M_writer(u"').autocomplete_tagging(options);\n </script>\n \n") # SOURCE LINE 218 __M_writer(u' <style>\n .tag-area {\n display: ') # SOURCE LINE 220 __M_writer(unicode(iff( use_toggle_link, "none", "block" ))) __M_writer(u';\n }\n </style>\n\n <noscript>\n <style>\n .tag-area {\n display: block;\n }\n </style>\n </noscript>\n') return '' finally: context.caller_stack._pop_frame()
class InstalledRepositoryGrid(grids.Grid): class NameColumn(grids.TextColumn): def get_value(self, trans, grid, tool_shed_repository): if tool_shed_repository.update_available: return '<div class="count-box state-color-running">%s</div>' % tool_shed_repository.name return tool_shed_repository.name class DescriptionColumn(grids.TextColumn): def get_value(self, trans, grid, tool_shed_repository): return tool_shed_repository.description class OwnerColumn(grids.TextColumn): def get_value(self, trans, grid, tool_shed_repository): return tool_shed_repository.owner class RevisionColumn(grids.TextColumn): def get_value(self, trans, grid, tool_shed_repository): return tool_shed_repository.changeset_revision class StatusColumn(grids.TextColumn): def get_value(self, trans, grid, tool_shed_repository): status_label = tool_shed_repository.status if tool_shed_repository.status in [ trans.model.ToolShedRepository.installation_status.CLONING, trans.model.ToolShedRepository.installation_status. SETTING_TOOL_VERSIONS, trans.model.ToolShedRepository. installation_status.INSTALLING_REPOSITORY_DEPENDENCIES, trans.model.ToolShedRepository.installation_status. INSTALLING_TOOL_DEPENDENCIES, trans.model.ToolShedRepository.installation_status. LOADING_PROPRIETARY_DATATYPES ]: bgcolor = trans.model.ToolShedRepository.states.INSTALLING elif tool_shed_repository.status in [ trans.model.ToolShedRepository.installation_status.NEW, trans.model.ToolShedRepository.installation_status. UNINSTALLED ]: bgcolor = trans.model.ToolShedRepository.states.UNINSTALLED elif tool_shed_repository.status in [ trans.model.ToolShedRepository.installation_status.ERROR ]: bgcolor = trans.model.ToolShedRepository.states.ERROR elif tool_shed_repository.status in [ trans.model.ToolShedRepository.installation_status. DEACTIVATED ]: bgcolor = trans.model.ToolShedRepository.states.WARNING elif tool_shed_repository.status in [ trans.model.ToolShedRepository.installation_status. INSTALLED ]: if tool_shed_repository.missing_repository_dependencies: bgcolor = trans.model.ToolShedRepository.states.WARNING status_label = '%s, missing repository dependencies' % status_label elif tool_shed_repository.missing_tool_dependencies: bgcolor = trans.model.ToolShedRepository.states.WARNING status_label = '%s, missing tool dependencies' % status_label else: bgcolor = trans.model.ToolShedRepository.states.OK else: bgcolor = trans.model.ToolShedRepository.states.ERROR rval = '<div class="count-box state-color-%s">%s</div>' % ( bgcolor, status_label) return rval class ToolShedColumn(grids.TextColumn): def get_value(self, trans, grid, tool_shed_repository): return tool_shed_repository.tool_shed class DeletedColumn(grids.DeletedColumn): def get_accepted_filters(self): """ Returns a list of accepted filters for this column. """ accepted_filter_labels_and_vals = { "Active": "False", "Deactivated or uninstalled": "True", "All": "All" } accepted_filters = [] for label, val in accepted_filter_labels_and_vals.items(): args = {self.key: val} accepted_filters.append(grids.GridColumnFilter(label, args)) return accepted_filters # Grid definition title = "Installed tool shed repositories" model_class = model.ToolShedRepository template = '/admin/tool_shed_repository/grid.mako' default_sort_key = "name" columns = [ NameColumn("Name", key="name", link=(lambda item: iff( item.status in [model.ToolShedRepository.installation_status.CLONING], None, dict(operation="manage_repository", id=item.id))), attach_popup=True), DescriptionColumn("Description"), OwnerColumn("Owner"), RevisionColumn("Revision"), StatusColumn("Installation Status", filterable="advanced"), ToolShedColumn("Tool shed"), # Columns that are valid for filtering but are not visible. DeletedColumn("Status", key="deleted", visible=False, filterable="advanced") ] columns.append( grids.MulticolFilterColumn("Search repository name", cols_to_filter=[columns[0]], key="free-text-search", visible=False, filterable="standard")) global_actions = [] operations = [ grids.GridOperation( "Get updates", allow_multiple=False, condition=( lambda item: not item.deleted and item.status not in \ [ model.ToolShedRepository.installation_status.ERROR, model.ToolShedRepository.installation_status.NEW ] ), async_compatible=False, url_args=dict( controller='admin_toolshed', action='browse_repositories', operation='get updates' ) ), grids.GridOperation( "Install", allow_multiple=False, condition=( lambda item: not item.deleted and item.status == model.ToolShedRepository.installation_status.NEW ), async_compatible=False, url_args=dict( controller='admin_toolshed', action='manage_repository', operation='install' ) ), grids.GridOperation( "Deactivate or uninstall", allow_multiple=False, condition=( lambda item: not item.deleted and item.status not in \ [ model.ToolShedRepository.installation_status.ERROR, model.ToolShedRepository.installation_status.NEW ] ), async_compatible=False, url_args=dict( controller='admin_toolshed', action='browse_repositories', operation='deactivate or uninstall' ) ), grids.GridOperation( "Reset to install", allow_multiple=False, condition=( lambda item: ( item.status == model.ToolShedRepository.installation_status.ERROR ) ), async_compatible=False, url_args=dict( controller='admin_toolshed', action='browse_repositories', operation='reset to install' ) ), grids.GridOperation( "Activate or reinstall", allow_multiple=False, condition=( lambda item: item.deleted ), async_compatible=False, url_args=dict( controller='admin_toolshed', action='browse_repositories', operation='activate or reinstall' ) ) ] standard_filters = [] default_filter = dict(deleted="False") num_rows_per_page = 50 preserve_state = False use_paging = False def build_initial_query(self, trans, **kwd): return trans.sa_session.query(self.model_class)
class HistoryDatasetAssociationListGrid(grids.Grid): # Custom columns for grid. class HistoryColumn(grids.GridColumn): def get_value(self, trans, grid, hda): return hda.history.name class StatusColumn(grids.GridColumn): def get_value(self, trans, grid, hda): if hda.deleted: return "deleted" return "" def get_accepted_filters(self): """ Returns a list of accepted filters for this column. """ accepted_filter_labels_and_vals = { "Active": "False", "Deleted": "True", "All": "All" } accepted_filters = [] for label, val in accepted_filter_labels_and_vals.items(): args = {self.key: val} accepted_filters.append(grids.GridColumnFilter(label, args)) return accepted_filters # Grid definition title = "Saved Datasets" model_class = model.HistoryDatasetAssociation template = '/dataset/grid.mako' default_sort_key = "-create_time" columns = [ grids.TextColumn( "Name", key="name", model_class=model.HistoryDatasetAssociation, # Link name to dataset's history. link=(lambda item: iff(item.history.deleted, None, dict(operation="switch", id=item.id))), filterable="advanced"), HistoryColumn("History", key="history", link=(lambda item: iff( item.history.deleted, None, dict(operation="switch_history", id=item.id)))), grids.TagsColumn("Tags", "tags", model.HistoryDatasetAssociation, model.HistoryDatasetAssociationTagAssociation, filterable="advanced", grid_name="HistoryDatasetAssocationListGrid"), StatusColumn("Status", key="deleted", attach_popup=False), grids.GridColumn("Created", key="create_time", format=time_ago), grids.GridColumn("Last Updated", key="update_time", format=time_ago), ] columns.append( grids.MulticolFilterColumn("Search", cols_to_filter=[columns[0], columns[2]], key="free-text-search", visible=False, filterable="standard")) operations = [] standard_filters = [] default_filter = dict(name="All", deleted="False", tags="All") preserve_state = False use_paging = True num_rows_per_page = 50 def apply_default_filter(self, trans, query, **kwargs): # This is a somewhat obtuse way to join the History and HDA tables. However, it's necessary # because the initial query in build_initial_query is specificied on the HDA table (this is reasonable) # and there's no simple property in the HDA to do the join. return query.select_from( model.HistoryDatasetAssociation.table.join( model.History.table)).filter(model.History.user == trans.user)
def render_render_grid_column_filter(context,grid,column): context.caller_stack._push_frame() try: basestring = context.get('basestring', UNDEFINED) cur_filter_dict = context.get('cur_filter_dict', UNDEFINED) url = context.get('url', UNDEFINED) h = context.get('h', UNDEFINED) list = context.get('list', UNDEFINED) len = context.get('len', UNDEFINED) dict = context.get('dict', UNDEFINED) enumerate = context.get('enumerate', UNDEFINED) isinstance = context.get('isinstance', UNDEFINED) __M_writer = context.writer() # SOURCE LINE 7 __M_writer(u'\n <tr>\n ') # SOURCE LINE 9 column_label = column.label if column.filterable == "advanced": column_label = column_label.lower() # SOURCE LINE 13 __M_writer(u'\n') # SOURCE LINE 14 if column.filterable == "advanced": # SOURCE LINE 15 __M_writer(u' <td align="left" style="padding-left: 10px">') __M_writer(unicode(column_label)) __M_writer(u':</td>\n') pass # SOURCE LINE 17 __M_writer(u' <td style="padding: 0;">\n') # SOURCE LINE 18 if isinstance(column, TextColumn): # SOURCE LINE 19 __M_writer(u' <form class="text-filter-form" column_key="') __M_writer(unicode(column.key)) __M_writer(u'" action="') __M_writer(unicode(url(dict()))) __M_writer(u'" method="get" >\n') # SOURCE LINE 21 for temp_column in grid.columns: # SOURCE LINE 22 if temp_column.key in cur_filter_dict: # SOURCE LINE 23 __M_writer(u' ') value = cur_filter_dict[ temp_column.key ] __M_writer(u'\n') # SOURCE LINE 24 if value != "All": # SOURCE LINE 25 __M_writer(u' ') if isinstance( temp_column, TextColumn ): value = h.to_json_string( value ) # SOURCE LINE 28 __M_writer(u'\n <input type="hidden" id="') # SOURCE LINE 29 __M_writer(unicode(temp_column.key)) __M_writer(u'" name="f-') __M_writer(unicode(temp_column.key)) __M_writer(u'" value=\'') __M_writer(unicode(value)) __M_writer(u"'/>\n") pass pass pass # SOURCE LINE 34 __M_writer(u' <span id="') __M_writer(unicode(column.key)) __M_writer(u'-filtering-criteria">\n') # SOURCE LINE 35 if column.key in cur_filter_dict: # SOURCE LINE 36 __M_writer(u' ') column_filter = cur_filter_dict[column.key] __M_writer(u'\n') # SOURCE LINE 37 if isinstance( column_filter, basestring ): # SOURCE LINE 38 if column_filter != "All": # SOURCE LINE 39 __M_writer(u" <span class='text-filter-val'>\n ") # SOURCE LINE 40 __M_writer(unicode(cur_filter_dict[column.key])) __M_writer(u'\n ') # SOURCE LINE 41 filter_all = GridColumnFilter( "", { column.key : "All" } ) __M_writer(u'\n <a href="') # SOURCE LINE 42 __M_writer(unicode(url(filter_all.get_url_args()))) __M_writer(u'"><span class="delete-search-icon" /></a>\n </span>\n') pass # SOURCE LINE 45 elif isinstance( column_filter, list ): # SOURCE LINE 46 for i, filter in enumerate( column_filter ): # SOURCE LINE 47 if i > 0: # SOURCE LINE 48 __M_writer(u' ,\n') pass # SOURCE LINE 50 __M_writer(u" <span class='text-filter-val'>") __M_writer(unicode(filter)) __M_writer(u'\n ') # SOURCE LINE 51 new_filter = list( column_filter ) del new_filter[ i ] new_column_filter = GridColumnFilter( "", { column.key : h.to_json_string( new_filter ) } ) # SOURCE LINE 55 __M_writer(u'\n <a href="') # SOURCE LINE 56 __M_writer(unicode(url(new_column_filter.get_url_args()))) __M_writer(u'"><span class="delete-search-icon" /></a>\n </span>\n') pass pass pass # SOURCE LINE 61 __M_writer(u' </span>\n') # SOURCE LINE 63 __M_writer(u' <span class="search-box">\n ') # SOURCE LINE 64 # Set value, size of search input field. Minimum size is 20 characters. value = iff( column.filterable == "standard", column.label.lower(), "") size = len( value ) if size < 20: size = 20 # +4 to account for search icon/button. size = size + 4 # SOURCE LINE 72 __M_writer(u'\n <input class="search-box-input" id="input-') # SOURCE LINE 73 __M_writer(unicode(column.key)) __M_writer(u'-filter" name="f-') __M_writer(unicode(column.key)) __M_writer(u'" type="text" value="') __M_writer(unicode(value)) __M_writer(u'" size="') __M_writer(unicode(size)) __M_writer(u'"/>\n <button class="submit-image" type="submit" title=\'Search\'><span style="display: none;"></button>\n </span>\n </form>\n') # SOURCE LINE 77 else: # SOURCE LINE 78 __M_writer(u' <span id="') __M_writer(unicode(column.key)) __M_writer(u'-filtering-criteria">\n') # SOURCE LINE 79 for i, filter in enumerate( column.get_accepted_filters() ): # SOURCE LINE 80 __M_writer(u' ') # HACK: we know that each filter will have only a single argument, so get that single argument. for key, arg in filter.args.items(): filter_key = key filter_arg = arg # SOURCE LINE 85 __M_writer(u'\n') # SOURCE LINE 86 if i > 0: # SOURCE LINE 87 __M_writer(u' |\n') pass # SOURCE LINE 89 if column.key in cur_filter_dict and column.key in filter.args and cur_filter_dict[column.key] == filter.args[column.key]: # SOURCE LINE 90 __M_writer(u' <span class="categorical-filter ') __M_writer(unicode(column.key)) __M_writer(u'-filter current-filter">') __M_writer(unicode(filter.label)) __M_writer(u'</span>\n') # SOURCE LINE 91 else: # SOURCE LINE 92 __M_writer(u' <span class="categorical-filter ') __M_writer(unicode(column.key)) __M_writer(u'-filter">\n <a href="') # SOURCE LINE 93 __M_writer(unicode(url(filter.get_url_args()))) __M_writer(u'" filter_key="') __M_writer(unicode(filter_key)) __M_writer(u'" filter_val="') __M_writer(unicode(filter_arg)) __M_writer(u'">') __M_writer(unicode(filter.label)) __M_writer(u'</a>\n </span>\n') pass pass # SOURCE LINE 97 __M_writer(u' </span>\n') pass # SOURCE LINE 99 __M_writer(u' </td>\n </tr>\n') return '' finally: context.caller_stack._pop_frame()
def __call__(self, trans, **kwargs): # Get basics. # FIXME: pretty sure this is only here to pass along, can likely be eliminated status = kwargs.get('status', None) message = kwargs.get('message', None) # Build a base filter and sort key that is the combination of the saved state and defaults. # Saved state takes preference over defaults. base_filter = {} if self.default_filter: # default_filter is a dictionary that provides a default set of filters based on the grid's columns. base_filter = self.default_filter.copy() base_sort_key = self.default_sort_key # Build initial query query = self.build_initial_query(trans, **kwargs) query = self.apply_query_filter(trans, query, **kwargs) # Maintain sort state in generated urls extra_url_args = {} # Determine whether use_default_filter flag is set. use_default_filter_str = kwargs.get('use_default_filter') use_default_filter = False if use_default_filter_str: use_default_filter = (use_default_filter_str.lower() == 'true') # Process filtering arguments to (a) build a query that represents the filter and (b) build a # dictionary that denotes the current filter. cur_filter_dict = {} for column in self.columns: if column.key: # Get the filter criterion for the column. Precedence is (a) if using default filter, only look there; otherwise, # (b) look in kwargs; and (c) look in base filter. column_filter = None if use_default_filter: if self.default_filter: column_filter = self.default_filter.get(column.key) elif f"f-{column.model_class.__name__}.{column.key}" in kwargs: # Queries that include table joins cannot guarantee unique column names. This problem is # handled by setting the column_filter value to <TableName>.<ColumnName>. column_filter = kwargs.get(f"f-{column.model_class.__name__}.{column.key}") elif f"f-{column.key}" in kwargs: column_filter = kwargs.get(f"f-{column.key}") elif column.key in base_filter: column_filter = base_filter.get(column.key) # Method (1) combines a mix of strings and lists of strings into a single string and (2) attempts to de-jsonify all strings. def loads_recurse(item): decoded_list = [] if isinstance(item, str): try: # Not clear what we're decoding, so recurse to ensure that we catch everything. decoded_item = loads(item) if isinstance(decoded_item, list): decoded_list = loads_recurse(decoded_item) else: decoded_list = [str(decoded_item)] except ValueError: decoded_list = [str(item)] elif isinstance(item, list): for element in item: a_list = loads_recurse(element) decoded_list = decoded_list + a_list return decoded_list # If column filter found, apply it. if column_filter is not None: # TextColumns may have a mix of json and strings. if isinstance(column, TextColumn): column_filter = loads_recurse(column_filter) if len(column_filter) == 1: column_filter = column_filter[0] # Interpret ',' as a separator for multiple terms. if isinstance(column_filter, str) and column_filter.find(',') != -1: column_filter = column_filter.split(',') # Check if filter is empty if isinstance(column_filter, list): # Remove empty strings from filter list column_filter = [x for x in column_filter if x != ''] if len(column_filter) == 0: continue elif isinstance(column_filter, str): # If filter criterion is empty, do nothing. if column_filter == '': continue # Update query. query = column.filter(trans, trans.user, query, column_filter) # Upate current filter dict. # Column filters are rendered in various places, sanitize them all here. cur_filter_dict[column.key] = sanitize_text(column_filter) # Carry filter along to newly generated urls; make sure filter is a string so # that we can encode to UTF-8 and thus handle user input to filters. if isinstance(column_filter, list): # Filter is a list; process each item. column_filter = [str(_).encode('utf-8') if not isinstance(_, str) else _ for _ in column_filter] extra_url_args[f"f-{column.key}"] = dumps(column_filter) else: # Process singleton filter. if not isinstance(column_filter, str): column_filter = str(column_filter) extra_url_args[f"f-{column.key}"] = column_filter.encode("utf-8") # Process sort arguments. sort_key = None if 'sort' in kwargs: sort_key = kwargs['sort'] elif base_sort_key: sort_key = base_sort_key if sort_key: ascending = not(sort_key.startswith("-")) # Queries that include table joins cannot guarantee unique column names. This problem is # handled by setting the column_filter value to <TableName>.<ColumnName>. table_name = None if sort_key.find('.') > -1: a_list = sort_key.split('.') if ascending: table_name = a_list[0] else: table_name = a_list[0][1:] column_name = a_list[1] elif ascending: column_name = sort_key else: column_name = sort_key[1:] # Sort key is a column key. for column in self.columns: if column.key and column.key.find('.') > -1: column_key = column.key.split('.')[1] else: column_key = column.key if (table_name is None or table_name == column.model_class.__name__) and column_key == column_name: query = column.sort(trans, query, ascending, column_name=column_name) break extra_url_args['sort'] = sort_key # There might be a current row current_item = self.get_current_item(trans, **kwargs) # Process page number. if self.use_paging: if 'page' in kwargs: if kwargs['page'] == 'all': page_num = 0 if self.allow_fetching_all_results: page_num = 0 else: # Should make it harder to return all results at once page_num = 1 else: page_num = int(kwargs['page']) else: page_num = 1 if page_num == 0: # Show all rows in page. total_num_rows = query.count() page_num = 1 num_pages = 1 else: # Show a limited number of rows. Before modifying query, get the total number of rows that query # returns so that the total number of pages can be computed. total_num_rows = query.count() query = query.limit(self.num_rows_per_page).offset((page_num - 1) * self.num_rows_per_page) num_pages = int(math.ceil(float(total_num_rows) / self.num_rows_per_page)) else: # Defaults. page_num = 1 num_pages = 1 # There are some places in grid templates where it's useful for a grid # to have its current filter. self.cur_filter_dict = cur_filter_dict # Log grid view. context = str(self.__class__.__name__) params = cur_filter_dict.copy() params['sort'] = sort_key params['async'] = ('async' in kwargs) # TODO:?? # commenting this out; when this fn calls session.add( action ) and session.flush the query from this fn # is effectively 'wiped' out. Nate believes it has something to do with our use of session( autocommit=True ) # in mapping.py. If you change that to False, the log_action doesn't affect the query # Below, I'm rendering the template first (that uses query), then calling log_action, then returning the page # trans.log_action( trans.get_user(), text_type( "grid.view" ), context, params ) # Render grid. def url(*args, **kwargs): route_name = kwargs.pop('__route_name__', None) # Only include sort/filter arguments if not linking to another # page. This is a bit of a hack. if 'action' in kwargs: new_kwargs = dict() else: new_kwargs = dict(extra_url_args) # Extend new_kwargs with first argument if found if len(args) > 0: new_kwargs.update(args[0]) new_kwargs.update(kwargs) # We need to encode item ids if 'id' in new_kwargs: id = new_kwargs['id'] if isinstance(id, list): new_kwargs['id'] = [trans.security.encode_id(i) for i in id] else: new_kwargs['id'] = trans.security.encode_id(id) # The url_for invocation *must* include a controller and action. if 'controller' not in new_kwargs: new_kwargs['controller'] = trans.controller if 'action' not in new_kwargs: new_kwargs['action'] = trans.action if route_name: return url_for(route_name, **new_kwargs) return url_for(**new_kwargs) self.use_panels = (kwargs.get('use_panels', False) in [True, 'True', 'true']) self.advanced_search = (kwargs.get('advanced_search', False) in [True, 'True', 'true']) async_request = ((self.use_async) and (kwargs.get('async', False) in [True, 'True', 'true'])) # Currently, filling the template returns a str object; this requires decoding the string into a # unicode object within mako templates. What probably should be done is to return the template as # utf-8 unicode; however, this would require encoding the object as utf-8 before returning the grid # results via a controller method, which is require substantial changes. Hence, for now, return grid # as str. page = trans.fill_template(iff(async_request, self.async_template, self.template), grid=self, query=query, cur_page_num=page_num, num_pages=num_pages, num_page_links=self.num_page_links, allow_fetching_all_results=self.allow_fetching_all_results, default_filter_dict=self.default_filter, cur_filter_dict=cur_filter_dict, sort_key=sort_key, current_item=current_item, ids=kwargs.get('id', []), url=url, status=status, message=message, info_text=self.info_text, use_panels=self.use_panels, use_hide_message=self.use_hide_message, advanced_search=self.advanced_search, show_item_checkboxes=(self.show_item_checkboxes or kwargs.get('show_item_checkboxes', '') in ['True', 'true']), # Pass back kwargs so that grid template can set and use args without # grid explicitly having to pass them. kwargs=kwargs) trans.log_action(trans.get_user(), "grid.view", context, params) return page
class ToolDependencyGrid(grids.Grid): class NameColumn(grids.TextColumn): def get_value(self, trans, grid, tool_dependency): return tool_dependency.name class VersionColumn(grids.TextColumn): def get_value(self, trans, grid, tool_dependency): return tool_dependency.version class TypeColumn(grids.TextColumn): def get_value(self, trans, grid, tool_dependency): return tool_dependency.type class StatusColumn(grids.TextColumn): def get_value(self, trans, grid, tool_dependency): if tool_dependency.status in [ trans.install_model.ToolDependency.installation_status. INSTALLING ]: bgcolor = trans.install_model.ToolDependency.states.INSTALLING elif tool_dependency.status in [ trans.install_model.ToolDependency.installation_status. NEVER_INSTALLED, trans.install_model.ToolDependency. installation_status.UNINSTALLED ]: bgcolor = trans.install_model.ToolDependency.states.UNINSTALLED elif tool_dependency.status in [ trans.install_model.ToolDependency.installation_status. ERROR ]: bgcolor = trans.install_model.ToolDependency.states.ERROR elif tool_dependency.status in [ trans.install_model.ToolDependency.installation_status. INSTALLED ]: bgcolor = trans.install_model.ToolDependency.states.OK rval = '<div class="count-box state-color-%s" id="ToolDependencyStatus-%s">%s</div>' % \ ( bgcolor, trans.security.encode_id( tool_dependency.id ), tool_dependency.status ) return rval title = "Tool Dependencies" template = "admin/tool_shed_repository/tool_dependencies_grid.mako" model_class = tool_shed_install.ToolDependency default_sort_key = "-create_time" num_rows_per_page = 50 preserve_state = True use_paging = False columns = [ NameColumn("Name", link=(lambda item: iff( item.status in [ tool_shed_install.ToolDependency.installation_status .NEVER_INSTALLED, tool_shed_install.ToolDependency. installation_status.INSTALLING, tool_shed_install. ToolDependency.installation_status.UNINSTALLED ], None, dict(action="manage_tool_dependencies", operation='browse', id=item.id))), filterable="advanced"), VersionColumn("Version", filterable="advanced"), TypeColumn("Type", filterable="advanced"), StatusColumn("Installation Status", filterable="advanced"), ] def build_initial_query(self, trans, **kwd): tool_dependency_ids = tool_dependency_util.get_tool_dependency_ids( as_string=False, **kwd) if tool_dependency_ids: clause_list = [] for tool_dependency_id in tool_dependency_ids: clause_list.append(self.model_class.table.c.id == trans. security.decode_id(tool_dependency_id)) return trans.install_model.context.query( self.model_class ) \ .filter( or_( *clause_list ) ) return trans.install_model.context.query(self.model_class) def apply_query_filter(self, trans, query, **kwd): tool_dependency_id = kwd.get('tool_dependency_id', None) if tool_dependency_id: return query.filter_by(tool_dependency_id=trans.security.decode_id( tool_dependency_id)) return query
def __call__(self, trans, **kwargs): # Get basics. # FIXME: pretty sure this is only here to pass along, can likely be eliminated status = kwargs.get('status', None) message = kwargs.get('message', None) dict_format = kwargs.get('dict_format', False) # Build a base filter and sort key that is the combination of the saved state and defaults. # Saved state takes preference over defaults. base_filter = {} if self.default_filter: # default_filter is a dictionary that provides a default set of filters based on the grid's columns. base_filter = self.default_filter.copy() base_sort_key = self.default_sort_key if self.preserve_state: pref_name = text_type(self.__class__.__name__ + self.cur_filter_pref_name) if pref_name in trans.get_user().preferences: saved_filter = loads(trans.get_user().preferences[pref_name]) base_filter.update(saved_filter) pref_name = text_type(self.__class__.__name__ + self.cur_sort_key_pref_name) if pref_name in trans.get_user().preferences: base_sort_key = loads(trans.get_user().preferences[pref_name]) # Build initial query query = self.build_initial_query(trans, **kwargs) query = self.apply_query_filter(trans, query, **kwargs) # Maintain sort state in generated urls extra_url_args = {} # Determine whether use_default_filter flag is set. use_default_filter_str = kwargs.get('use_default_filter') use_default_filter = False if use_default_filter_str: use_default_filter = (use_default_filter_str.lower() == 'true') # Process filtering arguments to (a) build a query that represents the filter and (b) build a # dictionary that denotes the current filter. cur_filter_dict = {} for column in self.columns: if column.key: # Get the filter criterion for the column. Precedence is (a) if using default filter, only look there; otherwise, # (b) look in kwargs; and (c) look in base filter. column_filter = None if use_default_filter: if self.default_filter: column_filter = self.default_filter.get(column.key) elif "f-" + column.model_class.__name__ + ".%s" % column.key in kwargs: # Queries that include table joins cannot guarantee unique column names. This problem is # handled by setting the column_filter value to <TableName>.<ColumnName>. column_filter = kwargs.get("f-" + column.model_class.__name__ + ".%s" % column.key) elif "f-" + column.key in kwargs: column_filter = kwargs.get("f-" + column.key) elif column.key in base_filter: column_filter = base_filter.get(column.key) # Method (1) combines a mix of strings and lists of strings into a single string and (2) attempts to de-jsonify all strings. def loads_recurse(item): decoded_list = [] if isinstance(item, string_types): try: # Not clear what we're decoding, so recurse to ensure that we catch everything. decoded_item = loads(item) if isinstance(decoded_item, list): decoded_list = loads_recurse(decoded_item) else: decoded_list = [text_type(decoded_item)] except ValueError: decoded_list = [text_type(item)] elif isinstance(item, list): for element in item: a_list = loads_recurse(element) decoded_list = decoded_list + a_list return decoded_list # If column filter found, apply it. if column_filter is not None: # TextColumns may have a mix of json and strings. if isinstance(column, TextColumn): column_filter = loads_recurse(column_filter) if len(column_filter) == 1: column_filter = column_filter[0] # Interpret ',' as a separator for multiple terms. if isinstance( column_filter, string_types) and column_filter.find(',') != -1: column_filter = column_filter.split(',') # Check if filter is empty if isinstance(column_filter, list): # Remove empty strings from filter list column_filter = [x for x in column_filter if x != ''] if len(column_filter) == 0: continue elif isinstance(column_filter, string_types): # If filter criterion is empty, do nothing. if column_filter == '': continue # Update query. query = column.filter(trans, trans.user, query, column_filter) # Upate current filter dict. # Column filters are rendered in various places, sanitize them all here. cur_filter_dict[column.key] = sanitize_text(column_filter) # Carry filter along to newly generated urls; make sure filter is a string so # that we can encode to UTF-8 and thus handle user input to filters. if isinstance(column_filter, list): # Filter is a list; process each item. column_filter = [ text_type(_).encode('utf-8') if not isinstance(_, string_types) else _ for _ in column_filter ] extra_url_args["f-" + column.key] = dumps(column_filter) else: # Process singleton filter. if not isinstance(column_filter, string_types): column_filter = text_type(column_filter) extra_url_args[ "f-" + column.key] = column_filter.encode("utf-8") # Process sort arguments. sort_key = None if 'sort' in kwargs: sort_key = kwargs['sort'] elif base_sort_key: sort_key = base_sort_key if sort_key: ascending = not (sort_key.startswith("-")) # Queries that include table joins cannot guarantee unique column names. This problem is # handled by setting the column_filter value to <TableName>.<ColumnName>. table_name = None if sort_key.find('.') > -1: a_list = sort_key.split('.') if ascending: table_name = a_list[0] else: table_name = a_list[0][1:] column_name = a_list[1] elif ascending: column_name = sort_key else: column_name = sort_key[1:] # Sort key is a column key. for column in self.columns: if column.key and column.key.find('.') > -1: column_key = column.key.split('.')[1] else: column_key = column.key if (table_name is None or table_name == column.model_class.__name__ ) and column_key == column_name: query = column.sort(trans, query, ascending, column_name=column_name) break extra_url_args['sort'] = sort_key # There might be a current row current_item = self.get_current_item(trans, **kwargs) # Process page number. if self.use_paging: if 'page' in kwargs: if kwargs['page'] == 'all': page_num = 0 else: page_num = int(kwargs['page']) else: page_num = 1 if page_num == 0: # Show all rows in page. total_num_rows = query.count() page_num = 1 num_pages = 1 else: # Show a limited number of rows. Before modifying query, get the total number of rows that query # returns so that the total number of pages can be computed. total_num_rows = query.count() query = query.limit(self.num_rows_per_page).offset( (page_num - 1) * self.num_rows_per_page) num_pages = int( math.ceil(float(total_num_rows) / self.num_rows_per_page)) else: # Defaults. page_num = 1 num_pages = 1 # There are some places in grid templates where it's useful for a grid # to have its current filter. self.cur_filter_dict = cur_filter_dict # Preserve grid state: save current filter and sort key. if self.preserve_state: pref_name = text_type(self.__class__.__name__ + self.cur_filter_pref_name) trans.get_user().preferences[pref_name] = text_type( dumps(cur_filter_dict)) if sort_key: pref_name = text_type(self.__class__.__name__ + self.cur_sort_key_pref_name) trans.get_user().preferences[pref_name] = text_type( dumps(sort_key)) trans.sa_session.flush() # Log grid view. context = text_type(self.__class__.__name__) params = cur_filter_dict.copy() params['sort'] = sort_key params['async'] = ('async' in kwargs) # TODO:?? # commenting this out; when this fn calls session.add( action ) and session.flush the query from this fn # is effectively 'wiped' out. Nate believes it has something to do with our use of session( autocommit=True ) # in mapping.py. If you change that to False, the log_action doesn't affect the query # Below, I'm rendering the template first (that uses query), then calling log_action, then returning the page # trans.log_action( trans.get_user(), text_type( "grid.view" ), context, params ) # Render grid. def url(*args, **kwargs): route_name = kwargs.pop('__route_name__', None) # Only include sort/filter arguments if not linking to another # page. This is a bit of a hack. if 'action' in kwargs: new_kwargs = dict() else: new_kwargs = dict(extra_url_args) # Extend new_kwargs with first argument if found if len(args) > 0: new_kwargs.update(args[0]) new_kwargs.update(kwargs) # We need to encode item ids if 'id' in new_kwargs: id = new_kwargs['id'] if isinstance(id, list): new_kwargs['id'] = [ trans.security.encode_id(i) for i in id ] else: new_kwargs['id'] = trans.security.encode_id(id) # The url_for invocation *must* include a controller and action. if 'controller' not in new_kwargs: new_kwargs['controller'] = trans.controller if 'action' not in new_kwargs: new_kwargs['action'] = trans.action if route_name: return url_for(route_name, **new_kwargs) return url_for(**new_kwargs) self.use_panels = (kwargs.get('use_panels', False) in [True, 'True', 'true']) self.advanced_search = (kwargs.get('advanced_search', False) in [True, 'True', 'true']) async_request = ((self.use_async) and (kwargs.get('async', False) in [True, 'True', 'true'])) # Currently, filling the template returns a str object; this requires decoding the string into a # unicode object within mako templates. What probably should be done is to return the template as # utf-8 unicode; however, this would require encoding the object as utf-8 before returning the grid # results via a controller method, which is require substantial changes. Hence, for now, return grid # as str. if not dict_format: page = trans.fill_template( iff(async_request, self.async_template, self.template), grid=self, query=query, cur_page_num=page_num, num_pages=num_pages, num_page_links=self.num_page_links, default_filter_dict=self.default_filter, cur_filter_dict=cur_filter_dict, sort_key=sort_key, current_item=current_item, ids=kwargs.get('id', []), url=url, status=status, message=message, info_text=self.info_text, use_panels=self.use_panels, use_hide_message=self.use_hide_message, advanced_search=self.advanced_search, show_item_checkboxes=(self.show_item_checkboxes or kwargs.get( 'show_item_checkboxes', '') in ['True', 'true']), # Pass back kwargs so that grid template can set and use args without # grid explicitly having to pass them. kwargs=kwargs) trans.log_action(trans.get_user(), text_type("grid.view"), context, params) return page grid_config = { 'title': self.title, 'url_base': trans.request.path_url, 'async': self.use_async, 'async_ops': [], 'categorical_filters': {}, 'filters': cur_filter_dict, 'sort_key': sort_key, 'show_item_checkboxes': self.show_item_checkboxes or kwargs.get('show_item_checkboxes', '') in ['True', 'true'], 'cur_page_num': page_num, 'num_pages': num_pages, 'num_page_links': self.num_page_links, 'status': status, 'message': restore_text(message), 'global_actions': [], 'operations': [], 'items': [], 'columns': [], 'model_class': str(self.model_class), 'use_paging': self.use_paging, 'legend': self.legend, 'current_item_id': False, 'use_hide_message': self.use_hide_message, 'default_filter_dict': self.default_filter, 'advanced_search': self.advanced_search, 'info_text': self.info_text, 'url': url(dict()), 'refresh_frames': kwargs.get('refresh_frames', []) } if current_item: grid_config['current_item_id'] = current_item.id for column in self.columns: href = None extra = '' if column.sortable: if sort_key.endswith(column.key): if not sort_key.startswith("-"): href = url(sort=("-" + column.key)) extra = "↓" else: href = url(sort=(column.key)) extra = "↑" else: href = url(sort=column.key) grid_config['columns'].append({ 'key': column.key, 'visible': column.visible, 'nowrap': column.nowrap, 'attach_popup': column.attach_popup, 'label_id_prefix': column.label_id_prefix, 'sortable': column.sortable, 'label': column.label, 'filterable': column.filterable, 'is_text': isinstance(column, TextColumn), 'href': href, 'extra': extra }) for operation in self.operations: grid_config['operations'].append({ 'allow_multiple': operation.allow_multiple, 'allow_popup': operation.allow_popup, 'target': operation.target, 'label': operation.label, 'confirm': operation.confirm, 'href': url(**operation.url_args) if isinstance( operation.url_args, dict) else None, 'global_operation': False }) if operation.allow_multiple: grid_config['show_item_checkboxes'] = True if operation.global_operation: grid_config['global_operation'] = url( **(operation.global_operation())) for action in self.global_actions: grid_config['global_actions'].append({ 'url_args': url(**action.url_args), 'label': action.label, 'target': action.target }) for operation in [op for op in self.operations if op.async_compatible]: grid_config['async_ops'].append(operation.label.lower()) for column in self.columns: if column.filterable is not None and not isinstance( column, TextColumn): grid_config['categorical_filters'][column.key] = dict([ (filter.label, filter.args) for filter in column.get_accepted_filters() ]) for i, item in enumerate(query): item_dict = { 'id': item.id, 'encode_id': trans.security.encode_id(item.id), 'link': [], 'operation_config': {}, 'column_config': {} } for column in self.columns: if column.visible: link = column.get_link(trans, self, item) if link: link = url(**link) else: link = None target = column.target value = column.get_value(trans, self, item) if isinstance(value, str): value = text_type(value, 'utf-8') value = value.replace('/', '//') item_dict['column_config'][column.label] = { 'link': link, 'value': value, 'target': target } for operation in self.operations: item_dict['operation_config'][operation.label] = { 'allowed': operation.allowed(item), 'url_args': url(**operation.get_url_args(item)), 'target': operation.target } grid_config['items'].append(item_dict) trans.log_action(trans.get_user(), text_type("grid.view"), context, params) return grid_config
def __call__( self, trans, **kwargs ): # Get basics. # FIXME: pretty sure this is only here to pass along, can likely be eliminated status = kwargs.get( 'status', None ) message = kwargs.get( 'message', None ) # Build a base filter and sort key that is the combination of the saved state and defaults. # Saved state takes preference over defaults. base_filter = {} if self.default_filter: # default_filter is a dictionary that provides a default set of filters based on the grid's columns. base_filter = self.default_filter.copy() base_sort_key = self.default_sort_key if self.preserve_state: pref_name = unicode( self.__class__.__name__ + self.cur_filter_pref_name ) if pref_name in trans.get_user().preferences: saved_filter = loads( trans.get_user().preferences[pref_name] ) base_filter.update( saved_filter ) pref_name = unicode( self.__class__.__name__ + self.cur_sort_key_pref_name ) if pref_name in trans.get_user().preferences: base_sort_key = loads( trans.get_user().preferences[pref_name] ) # Build initial query query = self.build_initial_query( trans, **kwargs ) query = self.apply_query_filter( trans, query, **kwargs ) # Maintain sort state in generated urls extra_url_args = {} # Determine whether use_default_filter flag is set. use_default_filter_str = kwargs.get( 'use_default_filter' ) use_default_filter = False if use_default_filter_str: use_default_filter = ( use_default_filter_str.lower() == 'true' ) # Process filtering arguments to (a) build a query that represents the filter and (b) build a # dictionary that denotes the current filter. cur_filter_dict = {} for column in self.columns: if column.key: # Get the filter criterion for the column. Precedence is (a) if using default filter, only look there; otherwise, # (b) look in kwargs; and (c) look in base filter. column_filter = None if use_default_filter: if self.default_filter: column_filter = self.default_filter.get( column.key ) elif "f-" + column.model_class.__name__ + ".%s" % column.key in kwargs: # Queries that include table joins cannot guarantee unique column names. This problem is # handled by setting the column_filter value to <TableName>.<ColumnName>. column_filter = kwargs.get( "f-" + column.model_class.__name__ + ".%s" % column.key ) elif "f-" + column.key in kwargs: column_filter = kwargs.get( "f-" + column.key ) elif column.key in base_filter: column_filter = base_filter.get( column.key ) # Method (1) combines a mix of strings and lists of strings into a single string and (2) attempts to de-jsonify all strings. def loads_recurse(item): decoded_list = [] if isinstance( item, basestring): try: # Not clear what we're decoding, so recurse to ensure that we catch everything. decoded_item = loads( item ) if isinstance( decoded_item, list): decoded_list = loads_recurse( decoded_item ) else: decoded_list = [ unicode( decoded_item ) ] except ValueError: decoded_list = [ unicode( item ) ] elif isinstance( item, list): for element in item: a_list = loads_recurse( element ) decoded_list = decoded_list + a_list return decoded_list # If column filter found, apply it. if column_filter is not None: # TextColumns may have a mix of json and strings. if isinstance( column, TextColumn ): column_filter = loads_recurse( column_filter ) if len( column_filter ) == 1: column_filter = column_filter[0] # Interpret ',' as a separator for multiple terms. if isinstance( column_filter, basestring ) and column_filter.find(',') != -1: column_filter = column_filter.split(',') # Check if filter is empty if isinstance( column_filter, list ): # Remove empty strings from filter list column_filter = [x for x in column_filter if x != ''] if len(column_filter) == 0: continue elif isinstance(column_filter, basestring): # If filter criterion is empty, do nothing. if column_filter == '': continue # Update query. query = column.filter( trans, trans.user, query, column_filter ) # Upate current filter dict. # Column filters are rendered in various places, sanitize them all here. cur_filter_dict[ column.key ] = sanitize_text(column_filter) # Carry filter along to newly generated urls; make sure filter is a string so # that we can encode to UTF-8 and thus handle user input to filters. if isinstance( column_filter, list ): # Filter is a list; process each item. for filter in column_filter: if not isinstance( filter, basestring ): filter = unicode( filter ).encode("utf-8") extra_url_args[ "f-" + column.key ] = dumps( column_filter ) else: # Process singleton filter. if not isinstance( column_filter, basestring ): column_filter = unicode(column_filter) extra_url_args[ "f-" + column.key ] = column_filter.encode("utf-8") # Process sort arguments. sort_key = None if 'sort' in kwargs: sort_key = kwargs['sort'] elif base_sort_key: sort_key = base_sort_key if sort_key: ascending = not( sort_key.startswith( "-" ) ) # Queries that include table joins cannot guarantee unique column names. This problem is # handled by setting the column_filter value to <TableName>.<ColumnName>. table_name = None if sort_key.find( '.' ) > -1: a_list = sort_key.split( '.' ) if ascending: table_name = a_list[0] else: table_name = a_list[0][1:] column_name = a_list[1] elif ascending: column_name = sort_key else: column_name = sort_key[1:] # Sort key is a column key. for column in self.columns: if column.key and column.key.find( '.' ) > -1: column_key = column.key.split( '.' )[1] else: column_key = column.key if ( table_name is None or table_name == column.model_class.__name__ ) and column_key == column_name: query = column.sort( trans, query, ascending, column_name=column_name ) break extra_url_args['sort'] = sort_key # There might be a current row current_item = self.get_current_item( trans, **kwargs ) # Process page number. if self.use_paging: if 'page' in kwargs: if kwargs['page'] == 'all': page_num = 0 else: page_num = int( kwargs['page'] ) else: page_num = 1 if page_num == 0: # Show all rows in page. total_num_rows = query.count() page_num = 1 num_pages = 1 else: # Show a limited number of rows. Before modifying query, get the total number of rows that query # returns so that the total number of pages can be computed. total_num_rows = query.count() query = query.limit( self.num_rows_per_page ).offset( ( page_num - 1 ) * self.num_rows_per_page ) num_pages = int( math.ceil( float( total_num_rows ) / self.num_rows_per_page ) ) else: # Defaults. page_num = 1 num_pages = 1 # There are some places in grid templates where it's useful for a grid # to have its current filter. self.cur_filter_dict = cur_filter_dict # Preserve grid state: save current filter and sort key. if self.preserve_state: pref_name = unicode( self.__class__.__name__ + self.cur_filter_pref_name ) trans.get_user().preferences[pref_name] = unicode( dumps( cur_filter_dict ) ) if sort_key: pref_name = unicode( self.__class__.__name__ + self.cur_sort_key_pref_name ) trans.get_user().preferences[pref_name] = unicode( dumps( sort_key ) ) trans.sa_session.flush() # Log grid view. context = unicode( self.__class__.__name__ ) params = cur_filter_dict.copy() params['sort'] = sort_key params['async'] = ( 'async' in kwargs ) # TODO:?? # commenting this out; when this fn calls session.add( action ) and session.flush the query from this fn # is effectively 'wiped' out. Nate believes it has something to do with our use of session( autocommit=True ) # in mapping.py. If you change that to False, the log_action doesn't affect the query # Below, I'm rendering the template first (that uses query), then calling log_action, then returning the page # trans.log_action( trans.get_user(), unicode( "grid.view" ), context, params ) # Render grid. def url( *args, **kwargs ): # Only include sort/filter arguments if not linking to another # page. This is a bit of a hack. if 'action' in kwargs: new_kwargs = dict() else: new_kwargs = dict( extra_url_args ) # Extend new_kwargs with first argument if found if len(args) > 0: new_kwargs.update( args[0] ) new_kwargs.update( kwargs ) # We need to encode item ids if 'id' in new_kwargs: id = new_kwargs[ 'id' ] if isinstance( id, list ): new_kwargs[ 'id' ] = [ trans.security.encode_id( i ) for i in id ] else: new_kwargs[ 'id' ] = trans.security.encode_id( id ) # The url_for invocation *must* include a controller and action. if 'controller' not in new_kwargs: new_kwargs['controller'] = trans.controller if 'action' not in new_kwargs: new_kwargs['action'] = trans.action return url_for( **new_kwargs) self.use_panels = ( kwargs.get( 'use_panels', False ) in [ True, 'True', 'true' ] ) self.advanced_search = ( kwargs.get( 'advanced_search', False ) in [ True, 'True', 'true' ] ) async_request = ( ( self.use_async ) and ( kwargs.get( 'async', False ) in [ True, 'True', 'true'] ) ) # Currently, filling the template returns a str object; this requires decoding the string into a # unicode object within mako templates. What probably should be done is to return the template as # utf-8 unicode; however, this would require encoding the object as utf-8 before returning the grid # results via a controller method, which is require substantial changes. Hence, for now, return grid # as str. page = trans.fill_template( iff( async_request, self.async_template, self.template ), grid=self, query=query, cur_page_num=page_num, num_pages=num_pages, num_page_links=self.num_page_links, default_filter_dict=self.default_filter, cur_filter_dict=cur_filter_dict, sort_key=sort_key, current_item=current_item, ids=kwargs.get( 'id', [] ), url=url, status=status, message=message, info_text=self.info_text, use_panels=self.use_panels, use_hide_message=self.use_hide_message, advanced_search=self.advanced_search, show_item_checkboxes=( self.show_item_checkboxes or kwargs.get( 'show_item_checkboxes', '' ) in [ 'True', 'true' ] ), # Pass back kwargs so that grid template can set and use args without # grid explicitly having to pass them. kwargs=kwargs ) trans.log_action( trans.get_user(), unicode( "grid.view" ), context, params ) return page