Merge pull request #445 from dod-ccpo/filter-by-member-status

Filter by all member statuses
This commit is contained in:
patricksmithdds 2018-11-13 13:29:31 -05:00 committed by GitHub
commit bd353ab1f6
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 55 additions and 30 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
@ -123,7 +123,8 @@ def workspace_members(workspace_id):
return render_template( return render_template(
"workspaces/members/index.html", "workspaces/members/index.html",
workspace=workspace, workspace=workspace,
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
) )
} }
} }
@ -51,7 +53,8 @@ export default {
props: { props: {
members: Array, members: Array,
choices: Array, role_choices: Array,
status_choices: Array,
}, },
data: function () { data: function () {
@ -90,8 +93,9 @@ export default {
return { return {
searchValue: '', searchValue: '',
status: '', status: '',
statusesByDisplayName: indexBy(prop('display_name'), this.status_choices),
role: '', role: '',
rolesByDisplayName: indexBy(prop('display_name'), this.choices), rolesByDisplayName: indexBy(prop('display_name'), this.role_choices),
sortInfo: { sortInfo: {
columnName: '', columnName: '',
isAscending: true, isAscending: true,
@ -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

@ -27,6 +27,8 @@
flex-basis: 100%; flex-basis: 100%;
.usa-input { .usa-input {
flex-basis: 100%;
@media (min-width:1000px) { @media (min-width:1000px) {
margin-top: 0; margin-top: 0;
} }

View File

@ -47,7 +47,12 @@
{% endif %} {% endif %}
<members-list inline-template id="search-template" v-bind:members='{{ members | tojson}}' v-bind:choices='{{ 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'>
@ -56,26 +61,28 @@
<button type="button"></button> <button type="button"></button>
</div> </div>
<div class='usa-input filter-input'> <div class="search-bar__filters">
<label for='filter-status'>Filter members by status</label> <div class='usa-input'>
<select v-model="status" id="filter-status" name="filter-status"> <label for='filter-status'>Filter members by status</label>
<option value="" selected disabled>Filter by status</option> <select v-model="status" id="filter-status" name="filter-status">
<option value="all">View All</option> <option value="" selected disabled>Filter by status</option>
<option value="active">Active</option> <option value="all">View All</option>
<option value="pending">Pending</option> {% for status in status_choices %}
<option value="denied">Denied</option> <option value='{{ status.name }}'>{{ status.display_name }}</option>
</select> {% endfor %}
</div> </select>
</div>
<div class='usa-input filter-input'> <div class='usa-input'>
<label for='filter-role'>Filter members by role</label> <label for='filter-role'>Filter members by role</label>
<select v-model="role" id="filter-role" name="filter-role"> <select v-model="role" id="filter-role" name="filter-role">
<option value="" selected disabled>Filter by role</option> <option value="" selected disabled>Filter by role</option>
<option value="all">View All</option> <option value="all">View All</option>
{% for role in choices %} {% for role in role_choices %}
<option value='{{ role.name }}'>{{ role.display_name }}</option> <option value='{{ role.name }}'>{{ role.display_name }}</option>
{% endfor %} {% endfor %}
</select> </select>
</div>
</div> </div>
</form> </form>