Skip to content

Commit

Permalink
Feature/add search box to org users tab (#5158)
Browse files Browse the repository at this point in the history
* init SearchBox in OrganizationAffiliations

* prevent reload error on search

* add search and orderBy options to query

* change AffiliationUserOrder to UserOrder

* add orderBy options to org affiliations

* add role priority to orderBy permission

* update tests

* default orderBy permission

* update faker schema

* fix adminpage test

* add translations

* conditionally render glossary toggle button
  • Loading branch information
lcampbell2 committed Mar 12, 2024
1 parent dbb13de commit 3ef26ec
Show file tree
Hide file tree
Showing 20 changed files with 533 additions and 317 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -530,7 +530,7 @@ describe('given the load affiliations by org id function', () => {
permission: 'user',
})
})
describe('ordering by USER_USERNAME', () => {
describe('ordering by USERNAME', () => {
describe('direction is set to ASC', () => {
it('returns affiliation', async () => {
const expectedAffiliation = await loadAffiliationByKey({
Expand All @@ -552,7 +552,7 @@ describe('given the load affiliations by org id function', () => {
after: toGlobalId('affiliation', affOne._key),
before: toGlobalId('affiliation', affThree._key),
orderBy: {
field: 'user-username',
field: 'username',
direction: 'ASC',
},
}
Expand Down Expand Up @@ -601,7 +601,7 @@ describe('given the load affiliations by org id function', () => {
after: toGlobalId('affiliation', affThree._key),
before: toGlobalId('affiliation', affOne._key),
orderBy: {
field: 'user-username',
field: 'username',
direction: 'DESC',
},
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,15 @@ export const loadAffiliationConnectionsByOrgId =

let affiliationField, documentField
/* istanbul ignore else */
if (orderBy.field === 'user-username') {
if (orderBy.field === 'username') {
affiliationField = aql`DOCUMENT(users, PARSE_IDENTIFIER(affiliation._to).key).userName`
documentField = aql`DOCUMENT(users, PARSE_IDENTIFIER(DOCUMENT(affiliations, ${afterId})._to).key).userName`
} else if (orderBy.field === 'display_name') {
affiliationField = aql`DOCUMENT(users, PARSE_IDENTIFIER(affiliation._to).key).displayName`
documentField = aql`DOCUMENT(users, PARSE_IDENTIFIER(DOCUMENT(affiliations, ${afterId})._to).key).displayName`
} else if (orderBy.field === 'permission') {
affiliationField = aql`rolePriority[affiliation.permission]`
documentField = aql`rolePriority[DOCUMENT(affiliations, ${afterId}).permission]`
}

afterTemplate = aql`
Expand All @@ -48,9 +54,15 @@ export const loadAffiliationConnectionsByOrgId =

let affiliationField, documentField
/* istanbul ignore else */
if (orderBy.field === 'user-username') {
if (orderBy.field === 'username') {
affiliationField = aql`DOCUMENT(users, PARSE_IDENTIFIER(affiliation._to).key).userName`
documentField = aql`DOCUMENT(users, PARSE_IDENTIFIER(DOCUMENT(affiliations, ${beforeId})._to).key).userName`
} else if (orderBy.field === 'display_name') {
affiliationField = aql`DOCUMENT(users, PARSE_IDENTIFIER(affiliation._to).key).displayName`
documentField = aql`DOCUMENT(users, PARSE_IDENTIFIER(DOCUMENT(affiliations, ${beforeId})._to).key).displayName`
} else if (orderBy.field === 'permission') {
affiliationField = aql`rolePriority[affiliation.permission]`
documentField = aql`rolePriority[DOCUMENT(affiliations, ${beforeId}).permission]`
}

beforeTemplate = aql`
Expand Down Expand Up @@ -124,10 +136,18 @@ export const loadAffiliationConnectionsByOrgId =

let affField, hasNextPageDocument, hasPreviousPageDocument
/* istanbul ignore else */
if (orderBy.field === 'user-username') {
if (orderBy.field === 'username') {
affField = aql`DOCUMENT(users, PARSE_IDENTIFIER(affiliation._to).key).userName`
hasNextPageDocument = aql`DOCUMENT(users, PARSE_IDENTIFIER(LAST(retrievedAffiliations)._to).key).userName`
hasPreviousPageDocument = aql`DOCUMENT(users, PARSE_IDENTIFIER(FIRST(retrievedAffiliations)._to).key).userName`
} else if (orderBy.field === 'display_name') {
affField = aql`DOCUMENT(users, PARSE_IDENTIFIER(affiliation._to).key).displayName`
hasNextPageDocument = aql`DOCUMENT(users, PARSE_IDENTIFIER(LAST(retrievedAffiliations)._to).key).displayName`
hasPreviousPageDocument = aql`DOCUMENT(users, PARSE_IDENTIFIER(FIRST(retrievedAffiliations)._to).key).displayName`
} else if (orderBy.field === 'permission') {
affField = aql`rolePriority[affiliation.permission]`
hasNextPageDocument = aql`rolePriority[LAST(retrievedAffiliations).permission]`
hasPreviousPageDocument = aql`FIRST(retrievedAffiliations).permission`
}

hasNextPageFilter = aql`
Expand All @@ -146,8 +166,12 @@ export const loadAffiliationConnectionsByOrgId =
let sortByField = aql``
if (typeof orderBy !== 'undefined') {
/* istanbul ignore else */
if (orderBy.field === 'user-username') {
if (orderBy.field === 'username') {
sortByField = aql`DOCUMENT(users, PARSE_IDENTIFIER(affiliation._to).key).userName ${orderBy.direction},`
} else if (orderBy.field === 'display_name') {
sortByField = aql`DOCUMENT(users, PARSE_IDENTIFIER(affiliation._to).key).displayName ${orderBy.direction},`
} else if (orderBy.field === 'permission') {
sortByField = aql`rolePriority[affiliation.permission] ${orderBy.direction},`
}
}

Expand Down Expand Up @@ -196,6 +220,14 @@ export const loadAffiliationConnectionsByOrgId =
RETURN e._key
)
LET rolePriority = {
"pending": 0,
"owner": 1,
"super_admin": 2,
"admin": 3,
"user": 4
}
LET retrievedAffiliations = (
FOR affiliation IN affiliations
FILTER affiliation._key IN affiliationKeys
Expand Down
28 changes: 10 additions & 18 deletions api/src/enums/affiliation-user-order-field.js
Original file line number Diff line number Diff line change
@@ -1,28 +1,20 @@
import {GraphQLEnumType} from 'graphql'
import { GraphQLEnumType } from 'graphql'

export const AffiliationUserOrderField = new GraphQLEnumType({
name: 'AffiliationUserOrderField',
description: 'Properties by which affiliation connections can be ordered.',
values: {
USER_USERNAME: {
value: 'user-username',
description: 'Order affiliation edges by username.',
USERNAME: {
value: 'username',
description: 'Order affiliations by username.',
},
USER_DISPLAYNAME: {
value: 'user-displayName',
description: 'Order affiliation edges by displayName.',
DISPLAY_NAME: {
value: 'display_name',
description: 'Order affiliations by display name.',
},
USER_EMAIL_VALIDATED: {
value: 'user-emailValidated',
description: 'Order affiliation edges by user verification status.',
},
USER_INSIDER: {
value: 'user-insider',
description: 'Order affiliation edges by user insider status.',
},
USER_AFFILIATIONS_COUNT: {
value: 'user-affiliations-totalCount',
description: 'Order affiliation edges by amount of total affiliations.',
PERMISSION: {
value: 'permission',
description: 'Order affiliations by permission.',
},
},
})
1 change: 1 addition & 0 deletions api/src/enums/index.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
export * from './affiliation-org-order-field'
export * from './affiliation-user-order-field'
export * from './user-order-field'
export * from './dkim-order-field'
export * from './dkim-result-order-field'
export * from './dmarc-order-field'
Expand Down
28 changes: 28 additions & 0 deletions api/src/enums/user-order-field.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import { GraphQLEnumType } from 'graphql'

export const UserOrderField = new GraphQLEnumType({
name: 'UserOrderField',
description: 'Properties by which affiliation connections can be ordered.',
values: {
USER_USERNAME: {
value: 'user-username',
description: 'Order affiliation edges by username.',
},
USER_DISPLAYNAME: {
value: 'user-displayName',
description: 'Order affiliation edges by displayName.',
},
USER_EMAIL_VALIDATED: {
value: 'user-emailValidated',
description: 'Order affiliation edges by user verification status.',
},
USER_INSIDER: {
value: 'user-insider',
description: 'Order affiliation edges by user insider status.',
},
USER_AFFILIATIONS_COUNT: {
value: 'user-affiliations-totalCount',
description: 'Order affiliation edges by amount of total affiliations.',
},
},
})
1 change: 1 addition & 0 deletions api/src/user/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,4 @@ export * from './mutations'
export * from './objects'
export * from './queries'
export * from './unions'
export * from './inputs'
21 changes: 21 additions & 0 deletions api/src/user/inputs/__tests__/user-order.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import { GraphQLNonNull } from 'graphql'

import { userOrder } from '../user-order'
import { OrderDirection, UserOrderField } from '../../../enums'

describe('given the affiliationOrder input object', () => {
describe('testing fields', () => {
it('has a direction field', () => {
const demoType = userOrder.getFields()

expect(demoType).toHaveProperty('direction')
expect(demoType.direction.type).toMatchObject(new GraphQLNonNull(OrderDirection))
})
it('has a field field', () => {
const demoType = userOrder.getFields()

expect(demoType).toHaveProperty('field')
expect(demoType.field.type).toMatchObject(new GraphQLNonNull(UserOrderField))
})
})
})
1 change: 1 addition & 0 deletions api/src/user/inputs/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from './user-order'
18 changes: 18 additions & 0 deletions api/src/user/inputs/user-order.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import { GraphQLInputObjectType, GraphQLNonNull } from 'graphql'

import { OrderDirection, UserOrderField } from '../../enums'

export const userOrder = new GraphQLInputObjectType({
name: 'UserOrder',
description: 'Ordering options for affiliation connections.',
fields: () => ({
field: {
type: new GraphQLNonNull(UserOrderField),
description: 'The field to order affiliations by.',
},
direction: {
type: new GraphQLNonNull(OrderDirection),
description: 'The ordering direction.',
},
}),
})
23 changes: 9 additions & 14 deletions api/src/user/queries/find-my-users.js
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
import {GraphQLString} from 'graphql'
import {connectionArgs} from 'graphql-relay'
import { GraphQLString } from 'graphql'
import { connectionArgs } from 'graphql-relay'

import {affiliationUserOrder} from '../../affiliation/inputs'
import {userConnection} from '../objects/user-connection'
import { userOrder } from '../../user/inputs'
import { userConnection } from '../objects/user-connection'

export const findMyUsers = {
type: userConnection.connectionType,
description: 'Select users an admin has access to.',
args: {
orderBy: {
type: affiliationUserOrder,
type: userOrder,
description: 'Ordering options for user affiliation',
},
search: {
Expand All @@ -23,20 +23,15 @@ export const findMyUsers = {
args,
{
userKey,
auth: {
checkSuperAdmin,
userRequired,
verifiedRequired,
superAdminRequired,
},
loaders: {loadUserConnectionsByUserId},
auth: { checkSuperAdmin, userRequired, verifiedRequired, superAdminRequired },
loaders: { loadUserConnectionsByUserId },
},
) => {
const user = await userRequired()
verifiedRequired({user})
verifiedRequired({ user })

const isSuperAdmin = await checkSuperAdmin()
superAdminRequired({user, isSuperAdmin})
superAdminRequired({ user, isSuperAdmin })

const userConnections = await loadUserConnectionsByUserId({
isSuperAdmin,
Expand Down
69 changes: 52 additions & 17 deletions frontend/mocking/faked_schema.js
Original file line number Diff line number Diff line change
Expand Up @@ -324,7 +324,7 @@ export const getTypeNames = () => gql`
"""
Ordering options for user affiliation
"""
orderBy: AffiliationUserOrder
orderBy: UserOrder
"""
String used to search for users.
Expand Down Expand Up @@ -2232,29 +2232,19 @@ export const getTypeNames = () => gql`
"""
enum AffiliationUserOrderField {
"""
Order affiliation edges by username.
Order affiliations by username.
"""
USER_USERNAME
USERNAME
"""
Order affiliation edges by displayName.
"""
USER_DISPLAYNAME
Order affiliations by display name.
"""
Order affiliation edges by user verification status.
"""
USER_EMAIL_VALIDATED
"""
Order affiliation edges by user insider status.
"""
USER_INSIDER
DISPLAY_NAME
"""
Order affiliation edges by amount of total affiliations.
Order affiliations by permission.
"""
USER_AFFILIATIONS_COUNT
PERMISSION
}
"""
Expand Down Expand Up @@ -4388,6 +4378,51 @@ export const getTypeNames = () => gql`
cursor: String!
}
"""
Ordering options for affiliation connections.
"""
input UserOrder {
"""
The field to order affiliations by.
"""
field: UserOrderField!
"""
The ordering direction.
"""
direction: OrderDirection!
}
"""
Properties by which affiliation connections can be ordered.
"""
enum UserOrderField {
"""
Order affiliation edges by username.
"""
USER_USERNAME
"""
Order affiliation edges by displayName.
"""
USER_DISPLAYNAME
"""
Order affiliation edges by user verification status.
"""
USER_EMAIL_VALIDATED
"""
Order affiliation edges by user insider status.
"""
USER_INSIDER
"""
Order affiliation edges by amount of total affiliations.
"""
USER_AFFILIATIONS_COUNT
}
"""
Domain object containing information for a given domain.
"""
Expand Down
7 changes: 6 additions & 1 deletion frontend/src/admin/UserList.js
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,12 @@ export function UserList({ includePending, permission, orgSlug, orgId }) {
usePaginatedCollection({
fetchForward: FORWARD,
recordsPerPage: usersPerPage,
variables: { orgSlug, search: debouncedSearchUser, includePending },
variables: {
orgSlug,
search: debouncedSearchUser,
includePending,
orderBy: { field: 'PERMISSION', direction: 'ASC' },
},
relayRoot: 'findOrganizationBySlug.affiliations',
fetchPolicy: 'cache-and-network',
nextFetchPolicy: 'cache-first',
Expand Down

0 comments on commit 3ef26ec

Please sign in to comment.