Skip to content

Commit

Permalink
move RoleSelect into a separate file
Browse files Browse the repository at this point in the history
  • Loading branch information
nl0 committed Jun 11, 2024
1 parent fa08866 commit bc98967
Show file tree
Hide file tree
Showing 2 changed files with 250 additions and 230 deletions.
234 changes: 234 additions & 0 deletions catalog/app/containers/Admin/UsersAndRoles/RoleSelect.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,234 @@
import cx from 'classnames'

Check warning on line 1 in catalog/app/containers/Admin/UsersAndRoles/RoleSelect.tsx

View check run for this annotation

Codecov / codecov/patch/informational

catalog/app/containers/Admin/UsersAndRoles/RoleSelect.tsx#L1

Added line #L1 was not covered by tests
import * as FF from 'final-form'
import * as R from 'ramda'
import * as React from 'react'

Check warning on line 4 in catalog/app/containers/Admin/UsersAndRoles/RoleSelect.tsx

View check run for this annotation

Codecov / codecov/patch/informational

catalog/app/containers/Admin/UsersAndRoles/RoleSelect.tsx#L3-L4

Added lines #L3 - L4 were not covered by tests
import * as RF from 'react-final-form'
import * as M from '@material-ui/core'

Check warning on line 6 in catalog/app/containers/Admin/UsersAndRoles/RoleSelect.tsx

View check run for this annotation

Codecov / codecov/patch/informational

catalog/app/containers/Admin/UsersAndRoles/RoleSelect.tsx#L6

Added line #L6 was not covered by tests

export interface Role {
id: string
name: string
}

export interface Value {
selected: readonly Role[]
active: Role | null
}

export const EMPTY_VALUE: Value = { selected: [], active: null }

Check warning on line 18 in catalog/app/containers/Admin/UsersAndRoles/RoleSelect.tsx

View check run for this annotation

Codecov / codecov/patch/informational

catalog/app/containers/Admin/UsersAndRoles/RoleSelect.tsx#L18

Added line #L18 was not covered by tests

export const validate: FF.FieldValidator<Value> = (v) => {

Check warning on line 20 in catalog/app/containers/Admin/UsersAndRoles/RoleSelect.tsx

View check run for this annotation

Codecov / codecov/patch/informational

catalog/app/containers/Admin/UsersAndRoles/RoleSelect.tsx#L20

Added line #L20 was not covered by tests
if (!v.selected.length) return 'required'
if (!v.active) return 'active'
}

export const ROLE_NAME_ASC = R.ascend((r: Role) => r.name)

Check warning on line 25 in catalog/app/containers/Admin/UsersAndRoles/RoleSelect.tsx

View check run for this annotation

Codecov / codecov/patch/informational

catalog/app/containers/Admin/UsersAndRoles/RoleSelect.tsx#L25

Added line #L25 was not covered by tests

const useRoleSelectStyles = M.makeStyles((t) => ({

Check warning on line 27 in catalog/app/containers/Admin/UsersAndRoles/RoleSelect.tsx

View check run for this annotation

Codecov / codecov/patch/informational

catalog/app/containers/Admin/UsersAndRoles/RoleSelect.tsx#L27

Added line #L27 was not covered by tests
grid: {
alignItems: 'center',
display: 'grid',
gap: t.spacing(1),
grid: 'auto-flow / 1fr auto 1fr',
marginTop: t.spacing(2),
},
list: ({ roles }: { roles: number }) => ({

Check warning on line 35 in catalog/app/containers/Admin/UsersAndRoles/RoleSelect.tsx

View check run for this annotation

Codecov / codecov/patch/informational

catalog/app/containers/Admin/UsersAndRoles/RoleSelect.tsx#L35

Added line #L35 was not covered by tests
height: `${46 * R.clamp(3, 4.5, roles)}px`,
overflowY: 'auto',
}),
listEmpty: {
alignItems: 'center',
display: 'flex',
flexDirection: 'column',
paddingTop: t.spacing(3),
},
availableRole: {
paddingBottom: '5px',
paddingTop: '5px',
},
defaultRole: {
fontWeight: t.typography.fontWeightMedium,
'&::after': {
content: '"*"',
},
},
}))

interface RoleSelectProps extends RF.FieldRenderProps<Value> {
roles: readonly Role[]
defaultRole: Role | null
}

export function RoleSelect({
roles,
defaultRole,
input: { value, onChange },
meta,
}: RoleSelectProps) {
const classes = useRoleSelectStyles({ roles: roles.length })

Check warning on line 68 in catalog/app/containers/Admin/UsersAndRoles/RoleSelect.tsx

View check run for this annotation

Codecov / codecov/patch/informational

catalog/app/containers/Admin/UsersAndRoles/RoleSelect.tsx#L62-L68

Added lines #L62 - L68 were not covered by tests

const error = meta.submitFailed && meta.error
const disabled = meta.submitting || meta.submitSucceeded

const { active, selected } = value ?? EMPTY_VALUE

const available = React.useMemo(
() => roles.filter((r) => !selected.find((r2) => r2.id === r.id)).sort(ROLE_NAME_ASC),

Check warning on line 76 in catalog/app/containers/Admin/UsersAndRoles/RoleSelect.tsx

View check run for this annotation

Codecov / codecov/patch/informational

catalog/app/containers/Admin/UsersAndRoles/RoleSelect.tsx#L75-L76

Added lines #L75 - L76 were not covered by tests
[roles, selected],
)

const add = (r: Role) =>
onChange({

Check warning on line 81 in catalog/app/containers/Admin/UsersAndRoles/RoleSelect.tsx

View check run for this annotation

Codecov / codecov/patch/informational

catalog/app/containers/Admin/UsersAndRoles/RoleSelect.tsx#L80-L81

Added lines #L80 - L81 were not covered by tests
selected: selected.concat(r).sort(ROLE_NAME_ASC),
active: active ?? r,
})

const remove = (r: Role) => {
const newSelected = selected.filter((r2) => r2.id !== r.id)

Check warning on line 87 in catalog/app/containers/Admin/UsersAndRoles/RoleSelect.tsx

View check run for this annotation

Codecov / codecov/patch/informational

catalog/app/containers/Admin/UsersAndRoles/RoleSelect.tsx#L86-L87

Added lines #L86 - L87 were not covered by tests
let newActive: Role | null
if (newSelected.length === 1) {
// select the only available role
newActive = newSelected[0]

Check warning on line 91 in catalog/app/containers/Admin/UsersAndRoles/RoleSelect.tsx

View check run for this annotation

Codecov / codecov/patch/informational

catalog/app/containers/Admin/UsersAndRoles/RoleSelect.tsx#L91

Added line #L91 was not covered by tests
} else if (newSelected.find((r2) => r2.id === active?.id)) {
// keep the active role if it's still available
newActive = active
} else {
newActive = null

Check warning on line 96 in catalog/app/containers/Admin/UsersAndRoles/RoleSelect.tsx

View check run for this annotation

Codecov / codecov/patch/informational

catalog/app/containers/Admin/UsersAndRoles/RoleSelect.tsx#L94-L96

Added lines #L94 - L96 were not covered by tests
}
onChange({ selected: newSelected, active: newActive })

Check warning on line 98 in catalog/app/containers/Admin/UsersAndRoles/RoleSelect.tsx

View check run for this annotation

Codecov / codecov/patch/informational

catalog/app/containers/Admin/UsersAndRoles/RoleSelect.tsx#L98

Added line #L98 was not covered by tests
}

const activate = (r: Role) => onChange({ selected, active: r })

Check warning on line 101 in catalog/app/containers/Admin/UsersAndRoles/RoleSelect.tsx

View check run for this annotation

Codecov / codecov/patch/informational

catalog/app/containers/Admin/UsersAndRoles/RoleSelect.tsx#L101

Added line #L101 was not covered by tests

const clear = () => onChange({ selected: [], active: null })

Check warning on line 103 in catalog/app/containers/Admin/UsersAndRoles/RoleSelect.tsx

View check run for this annotation

Codecov / codecov/patch/informational

catalog/app/containers/Admin/UsersAndRoles/RoleSelect.tsx#L103

Added line #L103 was not covered by tests

function roleNameDisplay(r: Role) {

Check warning on line 105 in catalog/app/containers/Admin/UsersAndRoles/RoleSelect.tsx

View check run for this annotation

Codecov / codecov/patch/informational

catalog/app/containers/Admin/UsersAndRoles/RoleSelect.tsx#L105

Added line #L105 was not covered by tests
if (r.id !== defaultRole?.id) return r.name
return (

Check warning on line 107 in catalog/app/containers/Admin/UsersAndRoles/RoleSelect.tsx

View check run for this annotation

Codecov / codecov/patch/informational

catalog/app/containers/Admin/UsersAndRoles/RoleSelect.tsx#L107

Added line #L107 was not covered by tests
<M.Tooltip title="Default role">
<span className={classes.defaultRole}>{r.name}</span>
</M.Tooltip>
)
}

return (

Check warning on line 114 in catalog/app/containers/Admin/UsersAndRoles/RoleSelect.tsx

View check run for this annotation

Codecov / codecov/patch/informational

catalog/app/containers/Admin/UsersAndRoles/RoleSelect.tsx#L114

Added line #L114 was not covered by tests
<M.FormControl error={!!error} margin="normal" fullWidth>
{error ? (
<M.Typography variant="body2" color="error">

Check warning on line 117 in catalog/app/containers/Admin/UsersAndRoles/RoleSelect.tsx

View check run for this annotation

Codecov / codecov/patch/informational

catalog/app/containers/Admin/UsersAndRoles/RoleSelect.tsx#L117

Added line #L117 was not covered by tests
{error === 'required' ? 'Assign at least one role' : 'Select an active role'}
</M.Typography>
) : (
<M.Typography variant="body2" color="textSecondary">

Check warning on line 121 in catalog/app/containers/Admin/UsersAndRoles/RoleSelect.tsx

View check run for this annotation

Codecov / codecov/patch/informational

catalog/app/containers/Admin/UsersAndRoles/RoleSelect.tsx#L121

Added line #L121 was not covered by tests
User can assume any of the assigned roles
</M.Typography>
)}

<div className={classes.grid}>
<M.Card variant="outlined">
<M.ListItem component="div" ContainerComponent="div" dense divider>
<M.ListItemText
primary="Assigned roles"
secondary={`${selected.length} / ${roles.length} roles`}
primaryTypographyProps={{ color: error ? 'error' : undefined }}
/>
<M.ListItemSecondaryAction>
<M.Tooltip title="Unassign all roles">
<M.IconButton
onClick={clear}
edge="end"
size="small"
disabled={disabled || selected.length === 0}
>
<M.Icon>clear_all</M.Icon>
</M.IconButton>
</M.Tooltip>
</M.ListItemSecondaryAction>
</M.ListItem>
{selected.length ? (
<M.List dense disablePadding className={classes.list}>
{selected.map((r) => (

Check warning on line 149 in catalog/app/containers/Admin/UsersAndRoles/RoleSelect.tsx

View check run for this annotation

Codecov / codecov/patch/informational

catalog/app/containers/Admin/UsersAndRoles/RoleSelect.tsx#L148-L149

Added lines #L148 - L149 were not covered by tests
<M.ListItem
key={r.id}
selected={active?.id === r.id}
disabled={disabled}
button
onClick={() => activate(r)}

Check warning on line 155 in catalog/app/containers/Admin/UsersAndRoles/RoleSelect.tsx

View check run for this annotation

Codecov / codecov/patch/informational

catalog/app/containers/Admin/UsersAndRoles/RoleSelect.tsx#L155

Added line #L155 was not covered by tests
>
<M.Tooltip
title={active?.id === r.id ? 'Active role' : 'Set active role'}
>
<M.Radio
checked={active?.id === r.id}
tabIndex={-1}
edge="start"
size="small"
disableRipple
/>
</M.Tooltip>
<M.ListItemText primaryTypographyProps={{ noWrap: true }}>
{roleNameDisplay(r)}
</M.ListItemText>
<M.ListItemSecondaryAction>
<M.Tooltip title="Unassign role">
<M.IconButton edge="end" size="small" onClick={() => remove(r)}>

Check warning on line 173 in catalog/app/containers/Admin/UsersAndRoles/RoleSelect.tsx

View check run for this annotation

Codecov / codecov/patch/informational

catalog/app/containers/Admin/UsersAndRoles/RoleSelect.tsx#L173

Added line #L173 was not covered by tests
<M.Icon>close</M.Icon>
</M.IconButton>
</M.Tooltip>
</M.ListItemSecondaryAction>
</M.ListItem>
))}
</M.List>
) : (
<div className={cx(classes.list, classes.listEmpty)}>

Check warning on line 182 in catalog/app/containers/Admin/UsersAndRoles/RoleSelect.tsx

View check run for this annotation

Codecov / codecov/patch/informational

catalog/app/containers/Admin/UsersAndRoles/RoleSelect.tsx#L182

Added line #L182 was not covered by tests
<M.Typography color={error ? 'error' : 'textSecondary'}>
No roles assigned
</M.Typography>
{!!defaultRole && (
<>

Check warning on line 187 in catalog/app/containers/Admin/UsersAndRoles/RoleSelect.tsx

View check run for this annotation

Codecov / codecov/patch/informational

catalog/app/containers/Admin/UsersAndRoles/RoleSelect.tsx#L187

Added line #L187 was not covered by tests
<M.Box pt={2} />
<M.Button
variant="contained"
color="primary"
onClick={() => add(defaultRole)}

Check warning on line 192 in catalog/app/containers/Admin/UsersAndRoles/RoleSelect.tsx

View check run for this annotation

Codecov / codecov/patch/informational

catalog/app/containers/Admin/UsersAndRoles/RoleSelect.tsx#L192

Added line #L192 was not covered by tests
disabled={disabled}
>
Assign default role
</M.Button>
</>
)}
</div>
)}
</M.Card>

<M.Icon color="action">sync_alt</M.Icon>

<M.Card variant="outlined">
<M.ListItem component="div" ContainerComponent="div" dense divider>
<M.ListItemText
primary="Available roles"
secondary={`${roles.length - selected.length} / ${roles.length} roles`}
/>
</M.ListItem>
{available.length ? (
<M.List dense disablePadding className={classes.list}>
{available.map((r) => (
<M.ListItem key={r.id} disabled={disabled} button onClick={() => add(r)}>

Check warning on line 215 in catalog/app/containers/Admin/UsersAndRoles/RoleSelect.tsx

View check run for this annotation

Codecov / codecov/patch/informational

catalog/app/containers/Admin/UsersAndRoles/RoleSelect.tsx#L213-L215

Added lines #L213 - L215 were not covered by tests
<M.ListItemText
className={classes.availableRole}
primaryTypographyProps={{ noWrap: true }}
>
{roleNameDisplay(r)}
</M.ListItemText>
</M.ListItem>
))}
</M.List>
) : (
<div className={cx(classes.list, classes.listEmpty)}>

Check warning on line 226 in catalog/app/containers/Admin/UsersAndRoles/RoleSelect.tsx

View check run for this annotation

Codecov / codecov/patch/informational

catalog/app/containers/Admin/UsersAndRoles/RoleSelect.tsx#L226

Added line #L226 was not covered by tests
<M.Typography color="textSecondary">All roles assigned</M.Typography>
</div>
)}
</M.Card>
</div>
</M.FormControl>
)
}
Loading

0 comments on commit bc98967

Please sign in to comment.