mirror of
https://github.com/galaxyproject/galaxy.git
synced 2026-09-24 16:30:27 +08:00
Remove unused legacy grid column types
This commit is contained in:
@@ -129,13 +129,6 @@ class GridColumn:
|
||||
return query
|
||||
|
||||
|
||||
class ReverseSortColumn(GridColumn):
|
||||
"""Column that reverses sorting; this is useful when the natural sort is descending."""
|
||||
|
||||
def sort(self, trans, query, ascending, column_name=None):
|
||||
return GridColumn.sort(self, trans, query, (not ascending), column_name=column_name)
|
||||
|
||||
|
||||
class TextColumn(GridColumn):
|
||||
"""Generic column that employs freetext and, hence, supports freetext, case-independent filtering."""
|
||||
|
||||
@@ -182,495 +175,6 @@ class TextColumn(GridColumn):
|
||||
return query
|
||||
|
||||
|
||||
class DateTimeColumn(TextColumn):
|
||||
def sort(self, trans, query, ascending, column_name=None):
|
||||
"""Sort query using this column."""
|
||||
return GridColumn.sort(self, trans, query, ascending, column_name=column_name)
|
||||
|
||||
|
||||
class BooleanColumn(TextColumn):
|
||||
def sort(self, trans, query, ascending, column_name=None):
|
||||
"""Sort query using this column."""
|
||||
return GridColumn.sort(self, trans, query, ascending, column_name=column_name)
|
||||
|
||||
def get_single_filter(self, user, a_filter):
|
||||
if self.key.find(".") > -1:
|
||||
a_key = self.key.split(".")[1]
|
||||
else:
|
||||
a_key = self.key
|
||||
model_class_key_field = getattr(self.model_class, a_key)
|
||||
return model_class_key_field == a_filter
|
||||
|
||||
|
||||
class IntegerColumn(TextColumn):
|
||||
"""
|
||||
Integer column that employs freetext, but checks that the text is an integer,
|
||||
so support filtering on integer values.
|
||||
|
||||
IMPORTANT NOTE: grids that use this column type should not include the column
|
||||
in the cols_to_filter list of MulticolFilterColumn ( i.e., searching on this
|
||||
column type should not be performed in the grid's standard search - it won't
|
||||
throw exceptions, but it also will not find what you're looking for ). Grids
|
||||
that search on this column should use 'filterable="advanced"' so that searching
|
||||
is only performed in the advanced search component, restricting the search to
|
||||
the specific column.
|
||||
|
||||
This is useful for searching on object ids or other integer columns. See the
|
||||
JobIdColumn column in the SpecifiedDateListGrid class in the jobs controller of
|
||||
the reports webapp for an example.
|
||||
"""
|
||||
|
||||
def get_single_filter(self, user, a_filter):
|
||||
model_class_key_field = getattr(self.model_class, self.key)
|
||||
assert int(a_filter), "The search entry must be an integer"
|
||||
return model_class_key_field == int(a_filter)
|
||||
|
||||
def sort(self, trans, query, ascending, column_name=None):
|
||||
"""Sort query using this column."""
|
||||
return GridColumn.sort(self, trans, query, ascending, column_name=column_name)
|
||||
|
||||
|
||||
class CommunityRatingColumn(GridColumn, UsesItemRatings):
|
||||
"""Column that displays community ratings for an item."""
|
||||
|
||||
def get_value(self, trans, grid, item):
|
||||
if not hasattr(item, "average_rating"):
|
||||
# No prefetched column property, generate it on the fly.
|
||||
ave_item_rating, num_ratings = self.get_ave_item_rating_data(
|
||||
trans.sa_session, item, webapp_model=trans.model
|
||||
)
|
||||
else:
|
||||
ave_item_rating = item.average_rating
|
||||
num_ratings = 2 # just used for pluralization
|
||||
if not ave_item_rating:
|
||||
ave_item_rating = 0
|
||||
return trans.fill_template(
|
||||
"tool_shed_rating.mako",
|
||||
ave_item_rating=ave_item_rating,
|
||||
num_ratings=num_ratings,
|
||||
item_id=trans.security.encode_id(item.id),
|
||||
)
|
||||
|
||||
def sort(self, trans, query, ascending, column_name=None):
|
||||
# Get the columns that connect item's table and item's rating association table.
|
||||
item_rating_assoc_class = getattr(trans.model, f"{self.model_class.__name__}RatingAssociation")
|
||||
foreign_key = get_foreign_key(item_rating_assoc_class, self.model_class)
|
||||
fk_col = foreign_key.parent
|
||||
referent_col = foreign_key.get_referent(self.model_class.table)
|
||||
# Do sorting using a subquery.
|
||||
# Subquery to get average rating for each item.
|
||||
ave_rating_subquery = (
|
||||
trans.sa_session.query(fk_col, func.avg(item_rating_assoc_class.table.c.rating).label("avg_rating"))
|
||||
.group_by(fk_col)
|
||||
.subquery()
|
||||
)
|
||||
# Integrate subquery into main query.
|
||||
query = query.outerjoin((ave_rating_subquery, referent_col == ave_rating_subquery.columns[fk_col.name]))
|
||||
# Sort using subquery results; use coalesce to avoid null values.
|
||||
if (
|
||||
not ascending
|
||||
): # TODO: for now, reverse sorting b/c first sort is ascending, and that should be the natural sort.
|
||||
query = query.order_by(func.coalesce(ave_rating_subquery.c.avg_rating, 0).asc())
|
||||
else:
|
||||
query = query.order_by(func.coalesce(ave_rating_subquery.c.avg_rating, 0).desc())
|
||||
return query
|
||||
|
||||
|
||||
class OwnerAnnotationColumn(TextColumn, UsesAnnotations):
|
||||
"""Column that displays and filters item owner's annotations."""
|
||||
|
||||
def __init__(self, col_name, key, model_class=None, model_annotation_association_class=None, filterable=None):
|
||||
GridColumn.__init__(self, col_name, key=key, model_class=model_class, filterable=filterable)
|
||||
self.sortable = False
|
||||
self.model_annotation_association_class = model_annotation_association_class
|
||||
|
||||
def get_value(self, trans, grid, item):
|
||||
"""Returns first 150 characters of annotation."""
|
||||
annotation = self.get_item_annotation_str(trans.sa_session, item.user, item)
|
||||
if annotation:
|
||||
ann_snippet = annotation[:155]
|
||||
if len(annotation) > 155:
|
||||
ann_snippet = ann_snippet[: ann_snippet.rfind(" ")]
|
||||
ann_snippet += "..."
|
||||
else:
|
||||
ann_snippet = ""
|
||||
return escape(ann_snippet)
|
||||
|
||||
def get_single_filter(self, user, a_filter):
|
||||
"""Filter by annotation and annotation owner."""
|
||||
return self.model_class.annotations.any(
|
||||
and_(
|
||||
func.lower(self.model_annotation_association_class.annotation).like(f"%{a_filter.lower()}%"),
|
||||
# TODO: not sure why, to filter by owner's annotations, we have to do this rather than
|
||||
# 'self.model_class.user==self.model_annotation_association_class.user'
|
||||
self.model_annotation_association_class.table.c.user_id == self.model_class.table.c.user_id,
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
class CommunityTagsColumn(TextColumn):
|
||||
"""Column that supports community tags."""
|
||||
|
||||
def __init__(
|
||||
self, col_name, key, model_class=None, model_tag_association_class=None, filterable=None, grid_name=None
|
||||
):
|
||||
GridColumn.__init__(
|
||||
self, col_name, key=key, model_class=model_class, nowrap=True, filterable=filterable, sortable=False
|
||||
)
|
||||
self.model_tag_association_class = model_tag_association_class
|
||||
# Column-specific attributes.
|
||||
self.grid_name = grid_name
|
||||
|
||||
def get_value(self, trans, grid, item):
|
||||
return trans.fill_template(
|
||||
"/tagging_common.mako",
|
||||
tag_type="community",
|
||||
trans=trans,
|
||||
user=trans.get_user(),
|
||||
tagged_item=item,
|
||||
elt_context=self.grid_name,
|
||||
tag_click_fn="add_tag_to_grid_filter",
|
||||
use_toggle_link=True,
|
||||
)
|
||||
|
||||
def filter(self, trans, user, query, column_filter):
|
||||
"""Modify query to filter model_class by tag. Multiple filters are ANDed."""
|
||||
if column_filter == "All":
|
||||
pass
|
||||
elif column_filter:
|
||||
query = query.filter(self.get_filter(trans, user, column_filter))
|
||||
return query
|
||||
|
||||
def get_filter(self, trans, user, column_filter):
|
||||
# Parse filter to extract multiple tags.
|
||||
if isinstance(column_filter, list):
|
||||
# Collapse list of tags into a single string; this is redundant but effective. TODO: fix this by iterating over tags.
|
||||
column_filter = ",".join(column_filter)
|
||||
raw_tags = trans.app.tag_handler.parse_tags(column_filter)
|
||||
clause_list = []
|
||||
for name, value in raw_tags:
|
||||
if name:
|
||||
# Filter by all tags.
|
||||
clause_list.append(
|
||||
self.model_class.tags.any(
|
||||
func.lower(self.model_tag_association_class.user_tname).like(f"%{name.lower()}%")
|
||||
)
|
||||
)
|
||||
if value:
|
||||
# Filter by all values.
|
||||
clause_list.append(
|
||||
self.model_class.tags.any(
|
||||
func.lower(self.model_tag_association_class.user_value).like(f"%{value.lower()}%")
|
||||
)
|
||||
)
|
||||
return and_(*clause_list)
|
||||
|
||||
|
||||
class IndividualTagsColumn(CommunityTagsColumn):
|
||||
"""Column that supports individual tags."""
|
||||
|
||||
def get_value(self, trans, grid, item):
|
||||
return trans.fill_template(
|
||||
"/tagging_common.mako",
|
||||
tag_type="individual",
|
||||
user=trans.user,
|
||||
tagged_item=item,
|
||||
elt_context=self.grid_name,
|
||||
tag_click_fn="add_tag_to_grid_filter",
|
||||
use_toggle_link=True,
|
||||
)
|
||||
|
||||
def get_filter(self, trans, user, column_filter):
|
||||
# Parse filter to extract multiple tags.
|
||||
if isinstance(column_filter, list):
|
||||
# Collapse list of tags into a single string; this is redundant but effective. TODO: fix this by iterating over tags.
|
||||
column_filter = ",".join(column_filter)
|
||||
raw_tags = trans.app.tag_handler.parse_tags(column_filter)
|
||||
clause_list = []
|
||||
for name, value in raw_tags:
|
||||
if name:
|
||||
# Filter by individual's tag names.
|
||||
clause_list.append(
|
||||
self.model_class.tags.any(
|
||||
and_(
|
||||
func.lower(self.model_tag_association_class.user_tname).like(f"%{name.lower()}%"),
|
||||
self.model_tag_association_class.user == user,
|
||||
)
|
||||
)
|
||||
)
|
||||
if value:
|
||||
# Filter by individual's tag values.
|
||||
clause_list.append(
|
||||
self.model_class.tags.any(
|
||||
and_(
|
||||
func.lower(self.model_tag_association_class.user_value).like(f"%{value.lower()}%"),
|
||||
self.model_tag_association_class.user == user,
|
||||
)
|
||||
)
|
||||
)
|
||||
return and_(*clause_list)
|
||||
|
||||
|
||||
class MulticolFilterColumn(TextColumn):
|
||||
"""Column that performs multicolumn filtering."""
|
||||
|
||||
def __init__(self, col_name, cols_to_filter, key, visible, filterable="default"):
|
||||
GridColumn.__init__(self, col_name, key=key, visible=visible, filterable=filterable)
|
||||
self.cols_to_filter = cols_to_filter
|
||||
|
||||
def filter(self, trans, user, query, column_filter):
|
||||
"""Modify query to filter model_class by tag. Multiple filters are ANDed."""
|
||||
if column_filter == "All":
|
||||
return query
|
||||
if isinstance(column_filter, list):
|
||||
clause_list = []
|
||||
for filter in column_filter:
|
||||
part_clause_list = []
|
||||
for column in self.cols_to_filter:
|
||||
part_clause_list.append(column.get_filter(trans, user, filter))
|
||||
clause_list.append(or_(*part_clause_list))
|
||||
complete_filter = and_(*clause_list)
|
||||
else:
|
||||
clause_list = []
|
||||
for column in self.cols_to_filter:
|
||||
clause_list.append(column.get_filter(trans, user, column_filter))
|
||||
complete_filter = or_(*clause_list)
|
||||
return query.filter(complete_filter)
|
||||
|
||||
|
||||
class OwnerColumn(TextColumn):
|
||||
"""Column that lists item's owner."""
|
||||
|
||||
def get_value(self, trans, grid, item):
|
||||
return item.user.username
|
||||
|
||||
def sort(self, trans, query, ascending, column_name=None):
|
||||
"""Sort column using case-insensitive alphabetical sorting on item's username."""
|
||||
if ascending:
|
||||
query = query.order_by(func.lower(self.model_class.username).asc())
|
||||
else:
|
||||
query = query.order_by(func.lower(self.model_class.username).desc())
|
||||
return query
|
||||
|
||||
|
||||
class PublicURLColumn(TextColumn):
|
||||
"""Column displays item's public URL based on username and slug."""
|
||||
|
||||
def get_link(self, trans, grid, item):
|
||||
if item.user.username and item.slug:
|
||||
return dict(action="display_by_username_and_slug", username=item.user.username, slug=item.slug)
|
||||
elif not item.user.username:
|
||||
# TODO: provide link to set username.
|
||||
return None
|
||||
elif not item.user.slug:
|
||||
# TODO: provide link to set slug.
|
||||
return None
|
||||
|
||||
|
||||
class DeletedColumn(GridColumn):
|
||||
"""Column that tracks and filters for items with deleted attribute."""
|
||||
|
||||
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(GridColumnFilter(label, args))
|
||||
return accepted_filters
|
||||
|
||||
def filter(self, trans, user, query, column_filter):
|
||||
"""Modify query to filter self.model_class by state."""
|
||||
if column_filter == "All":
|
||||
pass
|
||||
elif column_filter in ["True", "False"]:
|
||||
query = query.filter(self.model_class.deleted == (column_filter == "True"))
|
||||
return query
|
||||
|
||||
|
||||
class PurgedColumn(GridColumn):
|
||||
"""Column that tracks and filters for items with purged attribute."""
|
||||
|
||||
def get_accepted_filters(self):
|
||||
"""Returns a list of accepted filters for this column."""
|
||||
accepted_filter_labels_and_vals = {"nonpurged": "False", "purged": "True", "all": "All"}
|
||||
accepted_filters = []
|
||||
for label, val in accepted_filter_labels_and_vals.items():
|
||||
args = {self.key: val}
|
||||
accepted_filters.append(GridColumnFilter(label, args))
|
||||
return accepted_filters
|
||||
|
||||
def filter(self, trans, user, query, column_filter):
|
||||
"""Modify query to filter self.model_class by state."""
|
||||
if column_filter == "All":
|
||||
pass
|
||||
elif column_filter in ["True", "False"]:
|
||||
query = query.filter(self.model_class.purged == (column_filter == "True"))
|
||||
return query
|
||||
|
||||
|
||||
class StateColumn(GridColumn):
|
||||
"""
|
||||
Column that tracks and filters for items with state attribute.
|
||||
|
||||
IMPORTANT NOTE: self.model_class must have a states Bunch or dict if
|
||||
this column type is used in the grid.
|
||||
"""
|
||||
|
||||
def get_value(self, trans, grid, item):
|
||||
return item.state
|
||||
|
||||
def filter(self, trans, user, query, column_filter):
|
||||
"""Modify query to filter self.model_class by state."""
|
||||
if column_filter == "All":
|
||||
pass
|
||||
elif column_filter in [v for k, v in self.model_class.states.items()]:
|
||||
query = query.filter(self.model_class.state == column_filter)
|
||||
return query
|
||||
|
||||
def get_accepted_filters(self):
|
||||
"""Returns a list of accepted filters for this column."""
|
||||
all = GridColumnFilter("all", {self.key: "All"})
|
||||
accepted_filters = [all]
|
||||
for v in self.model_class.states.values():
|
||||
args = {self.key: v}
|
||||
accepted_filters.append(GridColumnFilter(v, args))
|
||||
return accepted_filters
|
||||
|
||||
|
||||
class SharingStatusColumn(GridColumn):
|
||||
"""Grid column to indicate sharing status."""
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
self.use_shared_with_count = kwargs.pop("use_shared_with_count", False)
|
||||
super().__init__(*args, **kwargs)
|
||||
|
||||
def get_value(self, trans, grid, item):
|
||||
# Delete items cannot be shared.
|
||||
if item.deleted:
|
||||
return ""
|
||||
# Build a list of sharing for this item.
|
||||
sharing_statuses = []
|
||||
if self._is_shared(item):
|
||||
sharing_statuses.append("Shared")
|
||||
if item.importable:
|
||||
sharing_statuses.append("Accessible")
|
||||
if item.published:
|
||||
sharing_statuses.append("Published")
|
||||
return ", ".join(sharing_statuses)
|
||||
|
||||
def _is_shared(self, item):
|
||||
if self.use_shared_with_count:
|
||||
# optimization to skip join for users_shared_with and loading in that data.
|
||||
return item.users_shared_with_count > 0
|
||||
|
||||
return item.users_shared_with
|
||||
|
||||
def filter(self, trans, user, query, column_filter):
|
||||
"""Modify query to filter histories by sharing status."""
|
||||
if column_filter == "All":
|
||||
pass
|
||||
elif column_filter:
|
||||
if column_filter == "private":
|
||||
query = query.filter(self.model_class.users_shared_with == null())
|
||||
query = query.filter(self.model_class.importable == false())
|
||||
elif column_filter == "shared":
|
||||
query = query.filter(self.model_class.users_shared_with != null())
|
||||
elif column_filter == "accessible":
|
||||
query = query.filter(self.model_class.importable == true())
|
||||
elif column_filter == "published":
|
||||
query = query.filter(self.model_class.published == true())
|
||||
return query
|
||||
|
||||
def get_accepted_filters(self):
|
||||
"""Returns a list of accepted filters for this column."""
|
||||
accepted_filter_labels_and_vals = {}
|
||||
accepted_filter_labels_and_vals["private"] = "private"
|
||||
accepted_filter_labels_and_vals["shared"] = "shared"
|
||||
accepted_filter_labels_and_vals["accessible"] = "accessible"
|
||||
accepted_filter_labels_and_vals["published"] = "published"
|
||||
accepted_filter_labels_and_vals["all"] = "All"
|
||||
accepted_filters = []
|
||||
for label, val in accepted_filter_labels_and_vals.items():
|
||||
args = {self.key: val}
|
||||
accepted_filters.append(GridColumnFilter(label, args))
|
||||
return accepted_filters
|
||||
|
||||
|
||||
class GridOperation:
|
||||
def __init__(
|
||||
self,
|
||||
label,
|
||||
key=None,
|
||||
condition=None,
|
||||
allow_multiple=True,
|
||||
allow_popup=True,
|
||||
target=None,
|
||||
url_args=None,
|
||||
async_compatible=False,
|
||||
confirm=None,
|
||||
global_operation=None,
|
||||
):
|
||||
self.label = label
|
||||
self.key = key
|
||||
self.allow_multiple = allow_multiple
|
||||
self.allow_popup = allow_popup
|
||||
self.condition = condition
|
||||
self.target = target
|
||||
self.url_args = url_args
|
||||
self.async_compatible = async_compatible
|
||||
# if 'confirm' is set, then ask before completing the operation
|
||||
self.confirm = confirm
|
||||
# specify a general operation that acts on the full grid
|
||||
# this should be a function returning a dictionary with parameters
|
||||
# to pass to the URL, similar to GridColumn links:
|
||||
# global_operation=(lambda: dict(operation="download")
|
||||
self.global_operation = global_operation
|
||||
|
||||
def get_url_args(self, item):
|
||||
if self.url_args:
|
||||
if callable(self.url_args):
|
||||
url_args = self.url_args(item)
|
||||
else:
|
||||
url_args = dict(self.url_args)
|
||||
url_args["id"] = item.id
|
||||
return url_args
|
||||
else:
|
||||
return dict(operation=self.label, id=item.id)
|
||||
|
||||
def allowed(self, item):
|
||||
if self.condition:
|
||||
return bool(self.condition(item))
|
||||
else:
|
||||
return True
|
||||
|
||||
|
||||
class DisplayByUsernameAndSlugGridOperation(GridOperation):
|
||||
"""Operation to display an item by username and slug."""
|
||||
|
||||
def get_url_args(self, item):
|
||||
return {"action": "display_by_username_and_slug", "username": item.user.username, "slug": item.slug}
|
||||
|
||||
|
||||
class GridAction:
|
||||
def __init__(self, label=None, url_args=None, target=None):
|
||||
self.label = label
|
||||
self.url_args = url_args
|
||||
self.target = target
|
||||
|
||||
|
||||
class GridColumnFilter:
|
||||
def __init__(self, label, args=None):
|
||||
self.label = label
|
||||
self.args = args
|
||||
|
||||
def get_url_args(self):
|
||||
rval = {}
|
||||
for k, v in self.args.items():
|
||||
rval[f"f-{k}"] = v
|
||||
return rval
|
||||
|
||||
|
||||
class GridData:
|
||||
"""
|
||||
Specifies the content a grid (data table).
|
||||
|
||||
@@ -245,7 +245,7 @@ class GroupListGrid(grids.GridData):
|
||||
grids.GridColumn("Name", key="name"),
|
||||
UsersColumn("Users", key="users"),
|
||||
RolesColumn("Roles", key="roles"),
|
||||
grids.DeletedColumn("Deleted", key="deleted", escape=False),
|
||||
grids.GridColumn("Deleted", key="deleted", escape=False),
|
||||
grids.GridColumn("Last Updated", key="update_time"),
|
||||
]
|
||||
|
||||
|
||||
Reference in New Issue
Block a user