class RepositoriesReviewedByMeGrid(RepositoriesWithReviewsGrid):
    # This grid filters out repositories that have been marked as either deprecated or deleted.

    columns = [
        RepositoriesWithReviewsGrid.NameColumn(
            "Repository name",
            key="name",
            link=(lambda item: dict(operation="view_or_manage_repository",
                                    id=item.id)),
            attach_popup=True),
        RepositoriesWithReviewsGrid.UserColumn("Owner", attach_popup=False),
        RepositoriesWithReviewsGrid.WithReviewsRevisionColumn(
            "Reviewed revisions"),
        RepositoriesWithReviewsGrid.ReviewersColumn("Reviewers",
                                                    attach_popup=False),
        RepositoriesWithReviewsGrid.RatingColumn("Rating", attach_popup=False),
        RepositoriesWithReviewsGrid.ApprovedColumn("Approved",
                                                   attach_popup=False)
    ]
    columns.append(
        grids.MulticolFilterColumn("Search repository name",
                                   cols_to_filter=[columns[0]],
                                   key="free-text-search",
                                   visible=False,
                                   filterable="standard"))

    def build_initial_query(self, trans, **kwd):
        return trans.sa_session.query(model.Repository) \
                               .filter(and_(model.Repository.table.c.deleted == false(),
                                            model.Repository.table.c.deprecated == false())) \
                               .join((model.RepositoryReview.table, model.RepositoryReview.table.c.repository_id == model.Repository.table.c.id)) \
                               .filter(model.RepositoryReview.table.c.user_id == trans.user.id) \
                               .join((model.User.table, model.User.table.c.id == model.RepositoryReview.table.c.user_id)) \
                               .outerjoin((model.ComponentReview.table, model.ComponentReview.table.c.repository_review_id == model.RepositoryReview.table.c.id)) \
                               .outerjoin((model.Component.table, model.Component.table.c.id == model.ComponentReview.table.c.component_id))
class AdminRepositoryGrid(RepositoryGrid):
    class DeletedColumn(grids.BooleanColumn):
        def get_value(self, trans, grid, repository):
            if repository.deleted:
                return 'yes'
            return ''

    columns = [
        RepositoryGrid.NameColumn(
            "Name",
            key="name",
            link=(lambda item: dict(operation="view_or_manage_repository",
                                    id=item.id)),
            attach_popup=True),
        RepositoryGrid.HeadsColumn("Heads"),
        RepositoryGrid.UserColumn(
            "Owner",
            model_class=model.User,
            link=(lambda item: dict(operation="repositories_by_user",
                                    id=item.id)),
            attach_popup=False,
            key="User.username"),
        RepositoryGrid.DeprecatedColumn("Deprecated",
                                        key="deprecated",
                                        attach_popup=False),
        # Columns that are valid for filtering but are not visible.
        DeletedColumn("Deleted", key="deleted", attach_popup=False)
    ]
    columns.append(
        grids.MulticolFilterColumn("Search repository name",
                                   cols_to_filter=[columns[0]],
                                   key="free-text-search",
                                   visible=False,
                                   filterable="standard"))
    operations = [operation for operation in RepositoryGrid.operations]
    operations.append(
        grids.GridOperation("Delete",
                            allow_multiple=False,
                            condition=(lambda item: not item.deleted),
                            async_compatible=False))
    operations.append(
        grids.GridOperation("Undelete",
                            allow_multiple=False,
                            condition=(lambda item: item.deleted),
                            async_compatible=False))
    standard_filters = []
    default_filter = {}

    def build_initial_query(self, trans, **kwd):
        return trans.sa_session.query(model.Repository) \
                               .join(model.User.table)
class RepositoriesReadyForReviewGrid(RepositoriesWithoutReviewsGrid):
    # Repositories that are ready for human review are those that either:
    # 1) Have no tools
    # 2) Have tools that have been proven to be functionally correct within Galaxy.
    # This grid filters out repositories that have been marked as either deprecated or deleted.
    title = "Repositories ready for review"
    columns = [
        RepositoriesWithoutReviewsGrid.NameColumn(
            "Repository name",
            key="name",
            link=(lambda item: dict(operation="view_or_manage_repository",
                                    id=item.id)),
            attach_popup=True),
        RepositoriesWithoutReviewsGrid.DescriptionColumn("Synopsis",
                                                         key="description",
                                                         attach_popup=False),
        RepositoriesWithoutReviewsGrid.WithoutReviewsRevisionColumn(
            "Revisions for review"),
        RepositoriesWithoutReviewsGrid.UserColumn("Owner",
                                                  model_class=model.User,
                                                  attach_popup=False,
                                                  key="User.username")
    ]
    columns.append(
        grids.MulticolFilterColumn("Search repository name, description",
                                   cols_to_filter=[columns[0], columns[1]],
                                   key="free-text-search",
                                   visible=False,
                                   filterable="standard"))
    operations = [
        grids.GridOperation("Inspect repository revisions",
                            allow_multiple=False,
                            condition=(lambda item: not item.deleted),
                            async_compatible=False)
    ]

    def build_initial_query(self, trans, **kwd):
        return trans.sa_session.query(model.Repository) \
                               .filter(and_(model.Repository.table.c.deleted == false(),
                                            model.Repository.table.c.deprecated == false(),
                                            model.Repository.reviews == null())) \
                               .join(model.RepositoryMetadata.table) \
                               .filter(and_(model.RepositoryMetadata.table.c.downloadable == true(),
                                            or_(model.RepositoryMetadata.table.c.includes_tools == false(),
                                                and_(model.RepositoryMetadata.table.c.includes_tools == true(),
                                                     model.RepositoryMetadata.table.c.tools_functionally_correct == true())))) \
                               .join(model.User.table)
class RepositoriesWithoutReviewsGrid(RepositoriesWithReviewsGrid):
    # This grid filters out repositories that have been marked as either deprecated or deleted.
    title = "Repositories with no reviews"
    columns = [
        RepositoriesWithReviewsGrid.NameColumn(
            "Repository name",
            key="name",
            link=(lambda item: dict(operation="view_or_manage_repository",
                                    id=item.id)),
            attach_popup=True),
        RepositoriesWithReviewsGrid.DescriptionColumn("Synopsis",
                                                      key="description",
                                                      attach_popup=False),
        RepositoriesWithReviewsGrid.WithoutReviewsRevisionColumn(
            "Revisions for review"),
        RepositoriesWithReviewsGrid.UserColumn("Owner",
                                               model_class=model.User,
                                               attach_popup=False,
                                               key="User.username")
    ]
    columns.append(
        grids.MulticolFilterColumn("Search repository name, description",
                                   cols_to_filter=[columns[0], columns[1]],
                                   key="free-text-search",
                                   visible=False,
                                   filterable="standard"))
    operations = [
        grids.GridOperation("Inspect repository revisions",
                            allow_multiple=False,
                            condition=(lambda item: not item.deleted),
                            async_compatible=False)
    ]

    def build_initial_query(self, trans, **kwd):
        return trans.sa_session.query(model.Repository) \
                               .filter(and_(model.Repository.table.c.deleted == false(),
                                            model.Repository.table.c.deprecated == false(),
                                            model.Repository.reviews == null())) \
                               .join(model.User.table)
class ReviewedRepositoriesIOwnGrid(RepositoriesWithReviewsGrid):
    title = "Reviewed repositories I own"
    columns = [
        RepositoriesWithReviewsGrid.NameColumn(
            "Repository name",
            key="name",
            link=(lambda item: dict(operation="view_or_manage_repository",
                                    id=item.id)),
            attach_popup=True),
        RepositoriesWithReviewsGrid.WithReviewsRevisionColumn(
            "Reviewed revisions"),
        RepositoriesWithReviewsGrid.WithoutReviewsRevisionColumn(
            "Revisions for review"),
        RepositoriesWithReviewsGrid.ReviewersColumn("Reviewers",
                                                    attach_popup=False),
        RepositoryGrid.DeprecatedColumn("Deprecated")
    ]
    columns.append(
        grids.MulticolFilterColumn("Search repository name",
                                   cols_to_filter=[columns[0]],
                                   key="free-text-search",
                                   visible=False,
                                   filterable="standard"))
    operations = [
        grids.GridOperation("Inspect repository revisions",
                            allow_multiple=False,
                            condition=(lambda item: not item.deleted),
                            async_compatible=False)
    ]

    def build_initial_query(self, trans, **kwd):
        return trans.sa_session.query(model.Repository) \
                               .join((model.RepositoryReview.table, model.RepositoryReview.table.c.repository_id == model.Repository.table.c.id)) \
                               .filter(model.Repository.table.c.user_id == trans.user.id) \
                               .join((model.User.table, model.User.table.c.id == model.RepositoryReview.table.c.user_id)) \
                               .outerjoin((model.ComponentReview.table, model.ComponentReview.table.c.repository_review_id == model.RepositoryReview.table.c.id)) \
                               .outerjoin((model.Component.table, model.Component.table.c.id == model.ComponentReview.table.c.component_id))
class RepositoriesWithReviewsGrid(RepositoryGrid):
    # This grid filters out repositories that have been marked as either deprecated or deleted.

    class WithReviewsRevisionColumn(grids.GridColumn):
        def get_value(self, trans, grid, repository):
            # Restrict to revisions that have been reviewed.
            if repository.reviews:
                rval = ''
                repo = hg_util.get_repo_for_repository(trans.app,
                                                       repository=repository,
                                                       repo_path=None,
                                                       create=False)
                for review in repository.reviews:
                    changeset_revision = review.changeset_revision
                    rev, label = hg_util.get_rev_label_from_changeset_revision(
                        repo, changeset_revision)
                    rval += '<a href="manage_repository_reviews_of_revision?id=%s&changeset_revision=%s">%s</a><br/>' % \
                        (trans.security.encode_id(repository.id), changeset_revision, label)
                return rval
            return ''

    class WithoutReviewsRevisionColumn(grids.GridColumn):
        def get_value(self, trans, grid, repository):
            # Restrict the options to revisions that have not yet been reviewed.
            repository_metadata_revisions = metadata_util.get_repository_metadata_revisions_for_review(
                repository, reviewed=False)
            if repository_metadata_revisions:
                rval = ''
                for repository_metadata in repository_metadata_revisions:
                    rev, label, changeset_revision = \
                        hg_util.get_rev_label_changeset_revision_from_repository_metadata(trans.app,
                                                                                          repository_metadata,
                                                                                          repository=repository,
                                                                                          include_date=True,
                                                                                          include_hash=False)
                    rval += '<a href="manage_repository_reviews_of_revision?id=%s&changeset_revision=%s">%s</a><br/>' % \
                        (trans.security.encode_id(repository.id), changeset_revision, label)
                return rval
            return ''

    class ReviewersColumn(grids.TextColumn):
        def get_value(self, trans, grid, repository):
            rval = ''
            if repository.reviewers:
                for user in repository.reviewers:
                    rval += '<a class="view-info" href="repository_reviews_by_user?id=%s">' % trans.security.encode_id(
                        user.id)
                    rval += '%s</a> | ' % user.username
                rval = rval.rstrip(' | ')
            return rval

    class RatingColumn(grids.TextColumn):
        def get_value(self, trans, grid, repository):
            rval = ''
            for review in repository.reviews:
                if review.rating:
                    for index in range(1, 6):
                        rval += '<input '
                        rval += 'name="star1-%s" ' % trans.security.encode_id(
                            review.id)
                        rval += 'type="radio" '
                        rval += 'class="community_rating_star star" '
                        rval += 'disabled="disabled" '
                        rval += 'value="%s" ' % str(review.rating)
                        if review.rating > (index - 0.5) and review.rating < (
                                index + 0.5):
                            rval += 'checked="checked" '
                        rval += '/>'
                rval += '<br/>'
            return rval

    class ApprovedColumn(grids.TextColumn):
        def get_value(self, trans, grid, repository):
            rval = ''
            for review in repository.reviews:
                if review.approved:
                    rval += '%s<br/>' % review.approved
            return rval

    title = "All reviewed repositories"
    model_class = model.Repository
    template = '/webapps/tool_shed/repository_review/grid.mako'
    default_sort_key = "Repository.name"
    columns = [
        RepositoryGrid.NameColumn(
            "Repository name",
            key="name",
            link=(lambda item: dict(operation="view_or_manage_repository",
                                    id=item.id)),
            attach_popup=True),
        RepositoryGrid.UserColumn("Owner",
                                  model_class=model.User,
                                  attach_popup=False,
                                  key="User.username"),
        WithReviewsRevisionColumn("Reviewed revisions"),
        ReviewersColumn("Reviewers", attach_popup=False),
        RatingColumn("Rating", attach_popup=False),
        ApprovedColumn("Approved", attach_popup=False)
    ]
    columns.append(
        grids.MulticolFilterColumn("Search repository name",
                                   cols_to_filter=[columns[0]],
                                   key="free-text-search",
                                   visible=False,
                                   filterable="standard"))
    operations = [
        grids.GridOperation("Inspect repository revisions",
                            allow_multiple=False,
                            condition=(lambda item: not item.deleted),
                            async_compatible=False)
    ]

    def build_initial_query(self, trans, **kwd):
        return trans.sa_session.query(model.Repository) \
                               .filter(and_(model.Repository.table.c.deleted == false(),
                                            model.Repository.table.c.deprecated == false())) \
                               .join((model.RepositoryReview.table, model.RepositoryReview.table.c.repository_id == model.Repository.table.c.id)) \
                               .join((model.User.table, model.User.table.c.id == model.Repository.table.c.user_id)) \
                               .outerjoin((model.ComponentReview.table, model.ComponentReview.table.c.repository_review_id == model.RepositoryReview.table.c.id)) \
                               .outerjoin((model.Component.table, model.Component.table.c.id == model.ComponentReview.table.c.component_id))
示例#7
0
class SpecifiedDateListGrid(grids.Grid):

    class WorkflowNameColumn(grids.TextColumn):

        def get_value(self, trans, grid, stored_workflow):
            return escape(stored_workflow.name)

    class CreateTimeColumn(grids.DateTimeColumn):

        def get_value(self, trans, grid, stored_workflow):
            return stored_workflow.create_time

    class UserColumn(grids.TextColumn):

        def get_value(self, trans, grid, stored_workflow):
            if stored_workflow.user:
                return escape(stored_workflow.user.email)
            return 'unknown'

    class EmailColumn(grids.GridColumn):

        def filter(self, trans, user, query, column_filter):
            if column_filter == 'All':
                return query
            return query.filter(and_(model.StoredWorkflow.table.c.user_id == model.User.table.c.id,
                                     model.User.table.c.email == column_filter))

    class SpecifiedDateColumn(grids.GridColumn):

        def filter(self, trans, user, query, column_filter):
            if column_filter == 'All':
                return query
            # We are either filtering on a date like YYYY-MM-DD or on a month like YYYY-MM,
            # so we need to figure out which type of date we have
            if column_filter.count('-') == 2:
                # We are filtering on a date like YYYY-MM-DD
                year, month, day = map(int, column_filter.split("-"))
                start_date = date(year, month, day)
                end_date = start_date + timedelta(days=1)
                return query.filter(and_(self.model_class.table.c.create_time >= start_date,
                                         self.model_class.table.c.create_time < end_date))
            if column_filter.count('-') == 1:
                # We are filtering on a month like YYYY-MM
                year, month = map(int, column_filter.split("-"))
                start_date = date(year, month, 1)
                end_date = start_date + timedelta(days=calendar.monthrange(year, month)[1])
                return query.filter(and_(self.model_class.table.c.create_time >= start_date,
                                         self.model_class.table.c.create_time < end_date))

    # Grid definition
    use_async = False
    model_class = model.StoredWorkflow
    title = "Workflows"
    default_sort_key = "name"
    columns = [
        WorkflowNameColumn("Name",
                           key="name",
                           attach_popup=False,
                           filterable="advanced"),
        CreateTimeColumn("Creation Time",
                         key="create_time",
                         attach_popup=False),
        UserColumn("User",
                   key="email",
                   model_class=model.User,
                   link=(lambda item: dict(operation="user_per_month", id=item.id, webapp="reports")),
                   attach_popup=False),
        # Columns that are valid for filtering but are not visible.
        SpecifiedDateColumn("Specified Date",
                            key="specified_date",
                            visible=False),
        EmailColumn("Email",
                    key="email",
                    model_class=model.User,
                    visible=False),
    ]
    columns.append(grids.MulticolFilterColumn("Search",
                                              cols_to_filter=[columns[0], columns[2]],
                                              key="free-text-search",
                                              visible=False,
                                              filterable="standard"))
    standard_filters = []
    default_filter = {'specified_date': 'All'}
    num_rows_per_page = 50
    use_paging = True

    def build_initial_query(self, trans, **kwd):
        return trans.sa_session.query(self.model_class) \
                               .join(model.User) \
                               .enable_eagerloads(False)
示例#8
0
class SpecifiedDateListGrid(grids.Grid):
    class JobIdColumn(grids.IntegerColumn):
        def get_value(self, trans, grid, job):
            return job.id

    class StateColumn(grids.TextColumn):
        def get_value(self, trans, grid, job):
            return '<div class="count-box state-color-%s">%s</div>' % (
                job.state, job.state)

        def filter(self, trans, user, query, column_filter):
            if column_filter == 'Unfinished':
                return query.filter(
                    not_(
                        or_(
                            model.Job.table.c.state == model.Job.states.OK,
                            model.Job.table.c.state == model.Job.states.ERROR,
                            model.Job.table.c.state ==
                            model.Job.states.DELETED)))
            return query

    class ToolColumn(grids.TextColumn):
        def get_value(self, trans, grid, job):
            return job.tool_id

        def filter(self, trans, user, query, column_filter):
            if column_filter is not None:
                query = query.filter(
                    model.Job.table.c.tool_id == column_filter)

            return query

    class CreateTimeColumn(grids.DateTimeColumn):
        def get_value(self, trans, grid, job):
            return job.create_time.strftime("%b %d, %Y, %H:%M:%S")

    class UserColumn(grids.GridColumn):
        def get_value(self, trans, grid, job):
            if job.user:
                return escape(job.user.email)
            return 'anonymous'

    class EmailColumn(grids.GridColumn):
        def filter(self, trans, user, query, column_filter):
            if column_filter == 'All':
                return query
            return query.filter(
                and_(model.Job.table.c.user_id == model.User.table.c.id,
                     model.User.table.c.email == column_filter))

    class SpecifiedDateColumn(grids.GridColumn):
        def filter(self, trans, user, query, column_filter):
            if column_filter == 'All':
                return query
            # We are either filtering on a date like YYYY-MM-DD or on a month like YYYY-MM,
            # so we need to figure out which type of date we have
            if column_filter.count(
                    '-') == 2:  # We are filtering on a date like YYYY-MM-DD
                year, month, day = map(int, column_filter.split("-"))
                start_date = date(year, month, day)
                end_date = start_date + timedelta(days=1)
            if column_filter.count(
                    '-') == 1:  # We are filtering on a month like YYYY-MM
                year, month = map(int, column_filter.split("-"))
                start_date = date(year, month, 1)
                end_date = start_date + timedelta(
                    days=calendar.monthrange(year, month)[1])

            return query.filter(
                and_(self.model_class.table.c.create_time >= start_date,
                     self.model_class.table.c.create_time < end_date))

    # Grid definition
    use_async = False
    model_class = model.Job
    title = "Jobs"
    default_sort_key = "id"
    columns = [
        JobIdColumn("Id",
                    key="id",
                    link=(lambda item: dict(
                        operation="job_info", id=item.id, webapp="reports")),
                    attach_popup=False,
                    filterable="advanced"),
        StateColumn("State", key="state", attach_popup=False),
        ToolColumn(
            "Tool Id",
            key="tool_id",
            link=(lambda item: dict(
                operation="tool_per_month", id=item.id, webapp="reports")),
            attach_popup=False),
        CreateTimeColumn("Creation Time",
                         key="create_time",
                         attach_popup=False),
        UserColumn(
            "User",
            key="email",
            model_class=model.User,
            link=(lambda item: dict(
                operation="user_per_month", id=item.id, webapp="reports")),
            attach_popup=False),
        # Columns that are valid for filtering but are not visible.
        SpecifiedDateColumn("Specified Date",
                            key="specified_date",
                            visible=False),
        EmailColumn("Email",
                    key="email",
                    model_class=model.User,
                    visible=False),
        grids.StateColumn("State",
                          key="state",
                          visible=False,
                          filterable="advanced")
    ]
    columns.append(
        grids.MulticolFilterColumn("Search",
                                   cols_to_filter=[columns[1], columns[2]],
                                   key="free-text-search",
                                   visible=False,
                                   filterable="standard"))
    standard_filters = []
    default_filter = {'specified_date': 'All'}
    num_rows_per_page = 50
    use_paging = True

    def build_initial_query(self, trans, **kwd):
        params = util.Params(kwd)
        monitor_email = params.get('monitor_email', '*****@*****.**')
        monitor_user_id = get_monitor_id(trans, monitor_email)
        return trans.sa_session.query(self.model_class) \
                               .join(model.User) \
                               .filter(model.Job.table.c.user_id != monitor_user_id)\
                               .enable_eagerloads(False)
class RepositoryMetadataGrid(grids.Grid):
    class IdColumn(grids.IntegerColumn):
        def get_value(self, trans, grid, repository_metadata):
            return repository_metadata.id

    class NameColumn(grids.TextColumn):
        def get_value(self, trans, grid, repository_metadata):
            return escape(repository_metadata.repository.name)

    class OwnerColumn(grids.TextColumn):
        def get_value(self, trans, grid, repository_metadata):
            return escape(repository_metadata.repository.user.username)

    class RevisionColumn(grids.TextColumn):
        def get_value(self, trans, grid, repository_metadata):
            repository = repository_metadata.repository
            return hg_util.get_revision_label(
                trans.app,
                repository,
                repository_metadata.changeset_revision,
                include_date=True,
                include_hash=True)

    class ToolsColumn(grids.TextColumn):
        def get_value(self, trans, grid, repository_metadata):
            tools_str = '0'
            if repository_metadata:
                metadata = repository_metadata.metadata
                if metadata:
                    if 'tools' in metadata:
                        # We used to display the following, but grid was too cluttered.
                        # for tool_metadata_dict in metadata[ 'tools' ]:
                        #    tools_str += '%s <b>%s</b><br/>' % ( tool_metadata_dict[ 'id' ], tool_metadata_dict[ 'version' ] )
                        return '%d' % len(metadata['tools'])
            return tools_str

    class DatatypesColumn(grids.TextColumn):
        def get_value(self, trans, grid, repository_metadata):
            datatypes_str = '0'
            if repository_metadata:
                metadata = repository_metadata.metadata
                if metadata:
                    if 'datatypes' in metadata:
                        # We used to display the following, but grid was too cluttered.
                        # for datatype_metadata_dict in metadata[ 'datatypes' ]:
                        #    datatypes_str += '%s<br/>' % datatype_metadata_dict[ 'extension' ]
                        return '%d' % len(metadata['datatypes'])
            return datatypes_str

    class WorkflowsColumn(grids.TextColumn):
        def get_value(self, trans, grid, repository_metadata):
            workflows_str = '0'
            if repository_metadata:
                metadata = repository_metadata.metadata
                if metadata:
                    if 'workflows' in metadata:
                        # We used to display the following, but grid was too cluttered.
                        # workflows_str += '<b>Workflows:</b><br/>'
                        # metadata[ 'workflows' ] is a list of tuples where each contained tuple is
                        # [ <relative path to the .ga file in the repository>, <exported workflow dict> ]
                        # workflow_tups = metadata[ 'workflows' ]
                        # workflow_metadata_dicts = [ workflow_tup[1] for workflow_tup in workflow_tups ]
                        # for workflow_metadata_dict in workflow_metadata_dicts:
                        #    workflows_str += '%s<br/>' % workflow_metadata_dict[ 'name' ]
                        return '%d' % len(metadata['workflows'])
            return workflows_str

    class DeletedColumn(grids.BooleanColumn):
        def get_value(self, trans, grid, repository_metadata):
            if repository_metadata.repository.deleted:
                return 'yes'
            return ''

    class DeprecatedColumn(grids.BooleanColumn):
        def get_value(self, trans, grid, repository_metadata):
            if repository_metadata.repository.deprecated:
                return 'yes'
            return ''

    class MaliciousColumn(grids.BooleanColumn):
        def get_value(self, trans, grid, repository_metadata):
            if repository_metadata.malicious:
                return 'yes'
            return ''

    # Grid definition
    title = "Repository Metadata"
    model_class = model.RepositoryMetadata
    default_sort_key = "name"
    use_hide_message = False
    columns = [
        IdColumn("Id", visible=False, attach_popup=False),
        NameColumn(
            "Name",
            key="name",
            model_class=model.Repository,
            link=(lambda item: dict(
                operation="view_or_manage_repository_revision", id=item.id)),
            attach_popup=True),
        OwnerColumn("Owner", attach_popup=False),
        RevisionColumn("Revision", attach_popup=False),
        ToolsColumn("Tools", attach_popup=False),
        DatatypesColumn("Datatypes", attach_popup=False),
        WorkflowsColumn("Workflows", attach_popup=False),
        DeletedColumn("Deleted", attach_popup=False),
        DeprecatedColumn("Deprecated", attach_popup=False),
        MaliciousColumn("Malicious", attach_popup=False)
    ]
    columns.append(
        grids.MulticolFilterColumn("Search repository name",
                                   cols_to_filter=[columns[1]],
                                   key="free-text-search",
                                   visible=False,
                                   filterable="standard"))
    operations = [
        grids.GridOperation(
            "Delete",
            allow_multiple=False,
            allow_popup=True,
            async_compatible=False,
            confirm=
            "Repository metadata records cannot be recovered after they are deleted. Click OK to delete the selected items."
        )
    ]
    standard_filters = []
    default_filter = {}
    use_paging = False

    def build_initial_query(self, trans, **kwd):
        return trans.sa_session.query(model.RepositoryMetadata) \
                               .join(model.Repository.table)
class GroupGrid(grids.Grid):
    class NameColumn(grids.TextColumn):
        def get_value(self, trans, grid, group):
            return str(group.name)

    class StatusColumn(grids.GridColumn):
        def get_value(self, trans, grid, group):
            if group.deleted:
                return "deleted"
            return ""

    class RolesColumn(grids.GridColumn):
        def get_value(self, trans, grid, group):
            if group.roles:
                return len(group.roles)
            return 0

    class UsersColumn(grids.GridColumn):
        def get_value(self, trans, grid, group):
            if group.members:
                return len(group.members)
            return 0

    title = "Groups"
    model_class = model.Group
    default_sort_key = "name"
    columns = [
        NameColumn("Name",
                   key="name",
                   link=(lambda item: dict(operation="Manage users and roles",
                                           id=item.id)),
                   attach_popup=True),
        UsersColumn("Users", attach_popup=False),
        RolesColumn("Roles", attach_popup=False),
        StatusColumn("Status", attach_popup=False),
        # Columns that are valid for filtering but are not visible.
        grids.DeletedColumn("Deleted",
                            key="deleted",
                            visible=False,
                            filterable="advanced")
    ]
    columns.append(
        grids.MulticolFilterColumn("Search",
                                   cols_to_filter=[columns[0]],
                                   key="free-text-search",
                                   visible=False,
                                   filterable="standard"))
    global_actions = [
        grids.GridAction(
            "Add new group",
            dict(controller='admin', action='groups', operation='create'))
    ]
    operations = [
        grids.GridOperation("Rename",
                            condition=(lambda item: not item.deleted),
                            allow_multiple=False,
                            url_args=dict(action="rename_group")),
        grids.GridOperation("Delete",
                            condition=(lambda item: not item.deleted),
                            allow_multiple=True,
                            url_args=dict(action="mark_group_deleted")),
        grids.GridOperation("Undelete",
                            condition=(lambda item: item.deleted),
                            allow_multiple=True,
                            url_args=dict(action="undelete_group")),
        grids.GridOperation("Purge",
                            condition=(lambda item: item.deleted),
                            allow_multiple=True,
                            url_args=dict(action="purge_group"))
    ]
    standard_filters = [
        grids.GridColumnFilter("Active", args=dict(deleted=False)),
        grids.GridColumnFilter("Deleted", args=dict(deleted=True)),
        grids.GridColumnFilter("All", args=dict(deleted='All'))
    ]

    use_paging = False
class UserGrid(grids.Grid):
    class UserLoginColumn(grids.TextColumn):
        def get_value(self, trans, grid, user):
            return escape(user.email)

    class UserNameColumn(grids.TextColumn):
        def get_value(self, trans, grid, user):
            if user.username:
                return escape(user.username)
            return 'not set'

    class GroupsColumn(grids.GridColumn):
        def get_value(self, trans, grid, user):
            if user.groups:
                return len(user.groups)
            return 0

    class RolesColumn(grids.GridColumn):
        def get_value(self, trans, grid, user):
            if user.roles:
                return len(user.roles)
            return 0

    class ExternalColumn(grids.GridColumn):
        def get_value(self, trans, grid, user):
            if user.external:
                return 'yes'
            return 'no'

    class LastLoginColumn(grids.GridColumn):
        def get_value(self, trans, grid, user):
            if user.galaxy_sessions:
                return self.format(user.galaxy_sessions[0].update_time)
            return 'never'

    class StatusColumn(grids.GridColumn):
        def get_value(self, trans, grid, user):
            if user.purged:
                return "purged"
            elif user.deleted:
                return "deleted"
            return ""

    class EmailColumn(grids.GridColumn):
        def filter(self, trans, user, query, column_filter):
            if column_filter == 'All':
                return query
            return query.filter(
                and_(model.Tool.table.c.user_id == model.User.table.c.id,
                     model.User.table.c.email == column_filter))

    title = "Users"
    model_class = model.User
    default_sort_key = "email"
    columns = [
        UserLoginColumn(
            "Email",
            key="email",
            link=(lambda item: dict(operation="information", id=item.id)),
            attach_popup=True,
            filterable="advanced"),
        UserNameColumn("User Name",
                       key="username",
                       attach_popup=False,
                       filterable="advanced"),
        GroupsColumn("Groups", attach_popup=False),
        RolesColumn("Roles", attach_popup=False),
        ExternalColumn("External", attach_popup=False),
        LastLoginColumn("Last Login", format=time_ago),
        StatusColumn("Status", attach_popup=False),
        # Columns that are valid for filtering but are not visible.
        EmailColumn("Email", key="email", visible=False)
    ]
    columns.append(
        grids.MulticolFilterColumn("Search",
                                   cols_to_filter=[columns[0], columns[1]],
                                   key="free-text-search",
                                   visible=False,
                                   filterable="standard"))
    global_actions = [
        grids.GridAction(
            "Create new user",
            dict(controller='admin', action='users', operation='create'))
    ]
    operations = [
        grids.GridOperation(
            "Manage Roles and Groups",
            condition=(lambda item: not item.deleted),
            allow_multiple=False,
            url_args=dict(action="manage_roles_and_groups_for_user")),
        grids.GridOperation("Reset Password",
                            condition=(lambda item: not item.deleted),
                            allow_multiple=True,
                            allow_popup=False,
                            url_args=dict(action="reset_user_password"))
    ]
    standard_filters = [
        grids.GridColumnFilter("Active", args=dict(deleted=False)),
        grids.GridColumnFilter("Deleted",
                               args=dict(deleted=True, purged=False)),
        grids.GridColumnFilter("Purged", args=dict(purged=True)),
        grids.GridColumnFilter("All", args=dict(deleted='All'))
    ]

    use_paging = False

    def get_current_item(self, trans, **kwargs):
        return trans.user
class RoleGrid(grids.Grid):
    class NameColumn(grids.TextColumn):
        def get_value(self, trans, grid, role):
            return escape(str(role.name))

    class DescriptionColumn(grids.TextColumn):
        def get_value(self, trans, grid, role):
            if role.description:
                return str(role.description)
            return ''

    class TypeColumn(grids.TextColumn):
        def get_value(self, trans, grid, role):
            return str(role.type)

    class StatusColumn(grids.GridColumn):
        def get_value(self, trans, grid, role):
            if role.deleted:
                return "deleted"
            return ""

    class GroupsColumn(grids.GridColumn):
        def get_value(self, trans, grid, role):
            if role.groups:
                return len(role.groups)
            return 0

    class RepositoriesColumn(grids.GridColumn):
        def get_value(self, trans, grid, role):
            if role.repositories:
                return len(role.repositories)
            return 0

    class UsersColumn(grids.GridColumn):
        def get_value(self, trans, grid, role):
            if role.users:
                return len(role.users)
            return 0

    title = "Roles"
    model_class = model.Role
    default_sort_key = "name"
    columns = [
        NameColumn("Name",
                   key="name",
                   link=(lambda item: dict(
                       operation="Manage role associations", id=item.id)),
                   attach_popup=True,
                   filterable="advanced"),
        DescriptionColumn("Description",
                          key='description',
                          attach_popup=False,
                          filterable="advanced"),
        GroupsColumn("Groups", attach_popup=False),
        RepositoriesColumn("Repositories", attach_popup=False),
        UsersColumn("Users", attach_popup=False),
        # Columns that are valid for filtering but are not visible.
        grids.DeletedColumn("Deleted",
                            key="deleted",
                            visible=False,
                            filterable="advanced")
    ]
    columns.append(
        grids.MulticolFilterColumn("Search",
                                   cols_to_filter=[columns[0]],
                                   key="free-text-search",
                                   visible=False,
                                   filterable="standard"))
    global_actions = [
        grids.GridAction(
            "Add new role",
            dict(controller='admin', action='roles', operation='create'))
    ]
    # Repository admin roles currently do not have any operations since they are managed automatically based
    # on other events.  For example, if a repository is renamed, its associated admin role is automatically
    # renamed accordingly and if a repository is deleted its associated admin role is automatically deleted.
    operations = [
        grids.GridOperation("Rename",
                            condition=(lambda item: not item.deleted and
                                       not item.is_repository_admin_role),
                            allow_multiple=False,
                            url_args=dict(action="rename_role")),
        grids.GridOperation("Delete",
                            condition=(lambda item: not item.deleted and
                                       not item.is_repository_admin_role),
                            allow_multiple=True,
                            url_args=dict(action="mark_role_deleted")),
        grids.GridOperation("Undelete",
                            condition=(lambda item: item.deleted and not item.
                                       is_repository_admin_role),
                            allow_multiple=True,
                            url_args=dict(action="undelete_role")),
        grids.GridOperation("Purge",
                            condition=(lambda item: item.deleted and not item.
                                       is_repository_admin_role),
                            allow_multiple=True,
                            url_args=dict(action="purge_role"))
    ]
    standard_filters = [
        grids.GridColumnFilter("Active", args=dict(deleted=False)),
        grids.GridColumnFilter("Deleted", args=dict(deleted=True)),
        grids.GridColumnFilter("All", args=dict(deleted='All'))
    ]

    use_paging = False

    def apply_query_filter(self, trans, query, **kwd):
        return query.filter(model.Role.type != model.Role.types.PRIVATE)