Allow filtering by all member statuses in member list view

This commit is contained in:
Patrick Smith 2018-11-12 17:11:45 -05:00
parent 947106a5b1
commit 990c24b802
5 changed files with 32 additions and 11 deletions

View File

@ -9,6 +9,16 @@ from .users import Users
from .exceptions import NotFoundError from .exceptions import NotFoundError
MEMBER_STATUSES = [
{"name": "active", "display_name": "Active"},
{"name": "revoked", "display_name": "Revoked"},
{"name": "expired", "display_name": "Invite expired"},
{"name": "error", "display_name": "Error on invite"},
{"name": "pending", "display_name": "Pending"},
{"name": "unknown", "display_name": "Unknown errors"},
]
class WorkspaceRoles(object): class WorkspaceRoles(object):
@classmethod @classmethod
def get(cls, workspace_id, user_id): def get(cls, workspace_id, user_id):

View File

@ -53,11 +53,12 @@ class WorkspaceRole(Base, mixins.TimestampsMixin, mixins.AuditableMixin):
elif self.latest_invitation: elif self.latest_invitation:
if self.latest_invitation.is_revoked: if self.latest_invitation.is_revoked:
return "Revoked" return "Revoked"
elif self.latest_invitation.is_rejected_expired:
return "Invite expired"
elif self.latest_invitation.is_rejected_wrong_user: elif self.latest_invitation.is_rejected_wrong_user:
return "Error on invite" return "Error on invite"
elif self.latest_invitation.is_expired: elif (
self.latest_invitation.is_rejected_expired
or self.latest_invitation.is_expired
):
return "Invite expired" return "Invite expired"
else: else:
return "Pending" return "Pending"

View File

@ -14,7 +14,7 @@ from atst.domain.exceptions import UnauthorizedError, AlreadyExistsError
from atst.domain.projects import Projects from atst.domain.projects import Projects
from atst.domain.reports import Reports from atst.domain.reports import Reports
from atst.domain.workspaces import Workspaces from atst.domain.workspaces import Workspaces
from atst.domain.workspace_roles import WorkspaceRoles from atst.domain.workspace_roles import WorkspaceRoles, MEMBER_STATUSES
from atst.domain.environments import Environments from atst.domain.environments import Environments
from atst.domain.environment_roles import EnvironmentRoles from atst.domain.environment_roles import EnvironmentRoles
from atst.forms.project import NewProjectForm, ProjectForm from atst.forms.project import NewProjectForm, ProjectForm
@ -124,6 +124,7 @@ def workspace_members(workspace_id):
"workspaces/members/index.html", "workspaces/members/index.html",
workspace=workspace, workspace=workspace,
role_choices=WORKSPACE_ROLE_DEFINITIONS, role_choices=WORKSPACE_ROLE_DEFINITIONS,
status_choices=MEMBER_STATUSES,
members=members_list, members=members_list,
new_member=new_member, new_member=new_member,
) )

View File

@ -11,12 +11,14 @@ const search = (query, members) => {
} }
} }
const filterByStatus = (status, members) => { const filterByStatus = (status, statusesByDisplayName, members) => {
const getStatusFromDisplayName = (_status) => statusesByDisplayName[_status].name
if (status === '' || status === 'all') { if (status === '' || status === 'all') {
return members return members
} else { } else {
return members.filter( return members.filter(
(member) => member.status.toLowerCase() === status (member) => getStatusFromDisplayName(member.status) === status
) )
} }
} }
@ -52,6 +54,7 @@ export default {
props: { props: {
members: Array, members: Array,
role_choices: Array, role_choices: Array,
status_choices: Array,
}, },
data: function () { data: function () {
@ -90,6 +93,7 @@ export default {
return { return {
searchValue: '', searchValue: '',
status: '', status: '',
statusesByDisplayName: indexBy(prop('display_name'), this.status_choices),
role: '', role: '',
rolesByDisplayName: indexBy(prop('display_name'), this.role_choices), rolesByDisplayName: indexBy(prop('display_name'), this.role_choices),
sortInfo: { sortInfo: {
@ -104,7 +108,7 @@ export default {
searchedList: function () { searchedList: function () {
return pipe( return pipe(
partial(search, [this.searchValue]), partial(search, [this.searchValue]),
partial(filterByStatus, [this.status]), partial(filterByStatus, [this.status, this.statusesByDisplayName]),
partial(filterByRole, [this.role, this.rolesByDisplayName]), partial(filterByRole, [this.role, this.rolesByDisplayName]),
partial(sort, [this.sortInfo]) partial(sort, [this.sortInfo])
)(this.members) )(this.members)

View File

@ -47,7 +47,12 @@
{% endif %} {% endif %}
<members-list inline-template id="search-template" v-bind:members='{{ members | tojson}}' v-bind:role_choices='{{ role_choices | tojson}}'> <members-list
inline-template
id="search-template"
v-bind:members='{{ members | tojson}}'
v-bind:role_choices='{{ role_choices | tojson}}'
v-bind:status_choices='{{ status_choices | tojson}}'>
<div> <div>
<form class='search-bar' @submit.prevent> <form class='search-bar' @submit.prevent>
<div class='usa-input search-input'> <div class='usa-input search-input'>
@ -61,9 +66,9 @@
<select v-model="status" id="filter-status" name="filter-status"> <select v-model="status" id="filter-status" name="filter-status">
<option value="" selected disabled>Filter by status</option> <option value="" selected disabled>Filter by status</option>
<option value="all">View All</option> <option value="all">View All</option>
<option value="active">Active</option> {% for status in status_choices %}
<option value="pending">Pending</option> <option value='{{ status.name }}'>{{ status.display_name }}</option>
<option value="denied">Denied</option> {% endfor %}
</select> </select>
</div> </div>