Skip to content
Snippets Groups Projects
Commit 920f01ea authored by Tore.Brede's avatar Tore.Brede
Browse files

GREG-255: Doing some changes on the edit role screen

parent 2673b853
No related branches found
No related tags found
1 merge request!325GREG-255: Doing some changes on the edit role screen
...@@ -56,6 +56,7 @@ export type Role = { ...@@ -56,6 +56,7 @@ export type Role = {
contact_person_unit: string | null contact_person_unit: string | null
comments: string | null comments: string | null
sponsor_name: string sponsor_name: string
ou_id: number
} }
export type FetchedRole = { export type FetchedRole = {
...@@ -70,6 +71,7 @@ export type FetchedRole = { ...@@ -70,6 +71,7 @@ export type FetchedRole = {
contact_person_unit: string | null contact_person_unit: string | null
comments: string | null comments: string | null
sponsor_name: string sponsor_name: string
ou_id: number
} }
export type ConsentType = { export type ConsentType = {
......
...@@ -5,7 +5,8 @@ import { LocalizationProvider } from '@mui/lab' ...@@ -5,7 +5,8 @@ import { LocalizationProvider } from '@mui/lab'
// eslint-disable-next-line import/no-extraneous-dependencies // eslint-disable-next-line import/no-extraneous-dependencies
import { Guest } from 'interfaces' import { Guest } from 'interfaces'
import parse from 'date-fns/parse' import parse from 'date-fns/parse'
import { BrowserRouter } from 'react-router-dom' import { MemoryRouter, Route, Routes } from 'react-router-dom'
import { addDays } from 'date-fns/fp'
import GuestRoleInfo from './index' import GuestRoleInfo from './index'
import { waitFor } from '../../../../test-utils' import { waitFor } from '../../../../test-utils'
...@@ -30,11 +31,12 @@ const guest: Guest = { ...@@ -30,11 +31,12 @@ const guest: Guest = {
name_en: 'Guest role', name_en: 'Guest role',
name_nb: 'Gjesterolle', name_nb: 'Gjesterolle',
start_date: parse('2021-08-10', 'yyyy-MM-dd', new Date()), start_date: parse('2021-08-10', 'yyyy-MM-dd', new Date()),
end_date: parse('2021-08-16', 'yyyy-MM-dd', new Date()), end_date: addDays(10)(new Date()),
contact_person_unit: 'Test contact person', contact_person_unit: 'Test contact person',
max_days: 100, max_days: 100,
comments: 'Test comment', comments: 'Test comment',
sponsor_name: 'Test', sponsor_name: 'Test',
ou_id: 1,
}, },
{ {
id: '201', id: '201',
...@@ -43,22 +45,41 @@ const guest: Guest = { ...@@ -43,22 +45,41 @@ const guest: Guest = {
name_en: 'Test role', name_en: 'Test role',
name_nb: 'Testrolle', name_nb: 'Testrolle',
start_date: parse('2021-09-06', 'yyyy-MM-dd', new Date()), start_date: parse('2021-09-06', 'yyyy-MM-dd', new Date()),
end_date: parse('2021-09-20', 'yyyy-MM-dd', new Date()), end_date: addDays(10)(new Date()),
contact_person_unit: 'Test contact person', contact_person_unit: 'Test contact person',
max_days: 100, max_days: 100,
comments: 'Test comment', comments: 'Test comment',
sponsor_name: 'Test', sponsor_name: 'Test',
ou_id: 2,
}, },
], ],
} }
test('Button state correct on load', async () => { // Mock useOus so that it looks like the user is a sponsor for
// the unit with ID 1
jest.mock('hooks/useOus', () => () => ({
ous: [
{
id: 1,
nb: 'Test',
en: 'Test2',
},
],
loading: false,
}))
test('End now enabled for role that is not expired and in unit where user is host', async () => {
render( render(
<BrowserRouter> <MemoryRouter initialEntries={['/sponsor/guest/1/roles/200']}>
<LocalizationProvider dateAdapter={AdapterDateFns}> <LocalizationProvider dateAdapter={AdapterDateFns}>
<GuestRoleInfo guest={guest} reloadGuest={() => {}} /> <Routes>
<Route
path="sponsor/guest/:pid/roles/:id"
element={<GuestRoleInfo guest={guest} reloadGuest={() => {}} />}
/>
</Routes>
</LocalizationProvider> </LocalizationProvider>
</BrowserRouter> </MemoryRouter>
) )
await waitFor( await waitFor(
...@@ -69,3 +90,26 @@ test('Button state correct on load', async () => { ...@@ -69,3 +90,26 @@ test('Button state correct on load', async () => {
{ timeout: 5000 } { timeout: 5000 }
) )
}, 10000) }, 10000)
test('End now disabled for role that is not expired and in unit where user is not host', async () => {
render(
<MemoryRouter initialEntries={['/sponsor/guest/1/roles/201']}>
<LocalizationProvider dateAdapter={AdapterDateFns}>
<Routes>
<Route
path="sponsor/guest/:pid/roles/:id"
element={<GuestRoleInfo guest={guest} reloadGuest={() => {}} />}
/>
</Routes>
</LocalizationProvider>
</MemoryRouter>
)
await waitFor(
() => {
expect(screen.getByText('button.save')).toBeDisabled()
expect(screen.getByText('sponsor.endNow')).toBeDisabled()
},
{ timeout: 5000 }
)
}, 10000)
...@@ -18,6 +18,7 @@ import { Controller, SubmitHandler, useForm } from 'react-hook-form' ...@@ -18,6 +18,7 @@ import { Controller, SubmitHandler, useForm } from 'react-hook-form'
import { getRoleName, getRoleOuName, submitJsonOpts } from 'utils' import { getRoleName, getRoleOuName, submitJsonOpts } from 'utils'
import { useFeatureContext } from 'contexts/featureContext' import { useFeatureContext } from 'contexts/featureContext'
import ConfirmDialog from '../../../../components/confirmDialog' import ConfirmDialog from '../../../../components/confirmDialog'
import useOus from '../../../../hooks/useOus'
interface GuestRoleInfoProps { interface GuestRoleInfoProps {
guest: Guest guest: Guest
...@@ -101,6 +102,7 @@ export default function GuestRoleInfo({ ...@@ -101,6 +102,7 @@ export default function GuestRoleInfo({
reloadGuest, reloadGuest,
}: GuestRoleInfoProps) { }: GuestRoleInfoProps) {
const { pid, id } = useParams<GuestRoleInfoParams>() const { pid, id } = useParams<GuestRoleInfoParams>()
const { ous } = useOus()
const [t] = useTranslation('common') const [t] = useTranslation('common')
const { displayContactAtUnit, displayComment } = useFeatureContext() const { displayContactAtUnit, displayComment } = useFeatureContext()
const navigate = useNavigate() const navigate = useNavigate()
...@@ -116,6 +118,7 @@ export default function GuestRoleInfo({ ...@@ -116,6 +118,7 @@ export default function GuestRoleInfo({
contact_person_unit: null, contact_person_unit: null,
comments: null, comments: null,
sponsor_name: '', sponsor_name: '',
ou_id: -1,
}) })
// Prepare min and max date values // Prepare min and max date values
const today = new Date() const today = new Date()
...@@ -141,6 +144,13 @@ export default function GuestRoleInfo({ ...@@ -141,6 +144,13 @@ export default function GuestRoleInfo({
formState: { isDirty, isValid }, formState: { isDirty, isValid },
} = useForm<RoleFormData>({ mode: 'onChange' }) } = useForm<RoleFormData>({ mode: 'onChange' })
// A sponsor can only edit roles belonging to departments where he is a sponsor.
// Look at the unit where the role is registered and see if that unit is present
// in the list of units where a sponsor can assign roles to determine if
// he can edit this role
const allowEdit =
ous === undefined ? false : ous.some((value) => value.id === role.ou_id)
// Submit function for the save button // Submit function for the save button
const submit: SubmitHandler<RoleFormData> = (data) => { const submit: SubmitHandler<RoleFormData> = (data) => {
const payload: { start_date?: string; end_date: string } = { const payload: { start_date?: string; end_date: string } = {
...@@ -198,12 +208,16 @@ export default function GuestRoleInfo({ ...@@ -198,12 +208,16 @@ export default function GuestRoleInfo({
to={`/sponsor/guest/${pid}`} to={`/sponsor/guest/${pid}`}
name={`${guest.first} ${guest.last}`} name={`${guest.first} ${guest.last}`}
/> />
<Typography sx={{ marginBottom: '1rem' }} variant="h2"> {allowEdit && (
{t('sponsor.roleInfoHead')} <>
</Typography> <Typography sx={{ marginBottom: '1rem' }} variant="h2">
<Typography sx={{ marginBottom: '1rem' }} variant="body1"> {t('sponsor.roleInfoHead')}
{t('sponsor.roleInfoText')} </Typography>
</Typography> <Typography sx={{ marginBottom: '1rem' }} variant="body1">
{t('sponsor.roleInfoText')}
</Typography>
</>
)}
<form onSubmit={onSubmit}> <form onSubmit={onSubmit}>
<TableContainer> <TableContainer>
<Table sx={{ minWidth: 650 }} aria-label="simple table"> <Table sx={{ minWidth: 650 }} aria-label="simple table">
...@@ -239,6 +253,7 @@ export default function GuestRoleInfo({ ...@@ -239,6 +253,7 @@ export default function GuestRoleInfo({
inputFormat="yyyy-MM-dd" inputFormat="yyyy-MM-dd"
onChange={onChange} onChange={onChange}
renderInput={(params) => <TextField {...params} />} renderInput={(params) => <TextField {...params} />}
disabled={!allowEdit}
/> />
)} )}
/> />
...@@ -257,6 +272,7 @@ export default function GuestRoleInfo({ ...@@ -257,6 +272,7 @@ export default function GuestRoleInfo({
inputFormat="yyyy-MM-dd" inputFormat="yyyy-MM-dd"
onChange={onChange} onChange={onChange}
renderInput={(params) => <TextField {...params} />} renderInput={(params) => <TextField {...params} />}
disabled={!allowEdit}
/> />
)} )}
/> />
...@@ -301,7 +317,7 @@ export default function GuestRoleInfo({ ...@@ -301,7 +317,7 @@ export default function GuestRoleInfo({
variant="contained" variant="contained"
color="success" color="success"
type="submit" type="submit"
disabled={!isDirty || !isValid} disabled={!isDirty || !isValid || !allowEdit}
> >
{t('button.save')} {t('button.save')}
</Button>{' '} </Button>{' '}
...@@ -309,7 +325,7 @@ export default function GuestRoleInfo({ ...@@ -309,7 +325,7 @@ export default function GuestRoleInfo({
<Button <Button
aria-label={t('sponsor.endNow')} aria-label={t('sponsor.endNow')}
color="primary" color="primary"
disabled={role.end_date < today} disabled={role.end_date < today || !allowEdit}
onClick={() => setShowEndRoleConfirmationDialog(true)} onClick={() => setShowEndRoleConfirmationDialog(true)}
> >
{t('sponsor.endNow')} {t('sponsor.endNow')}
......
...@@ -150,6 +150,7 @@ export function parseRole(role: FetchedRole): Role { ...@@ -150,6 +150,7 @@ export function parseRole(role: FetchedRole): Role {
contact_person_unit: role.contact_person_unit, contact_person_unit: role.contact_person_unit,
comments: role.comments, comments: role.comments,
sponsor_name: role.sponsor_name, sponsor_name: role.sponsor_name,
ou_id: role.ou_id
} }
} }
......
...@@ -104,6 +104,7 @@ class ExtendedRoleSerializer(serializers.ModelSerializer): ...@@ -104,6 +104,7 @@ class ExtendedRoleSerializer(serializers.ModelSerializer):
ou_en = SerializerMethodField(source="orgunit") ou_en = SerializerMethodField(source="orgunit")
max_days = SerializerMethodField(source="type") max_days = SerializerMethodField(source="type")
sponsor_name = SerializerMethodField(source="sponsor") sponsor_name = SerializerMethodField(source="sponsor")
ou_id = SerializerMethodField(source="orgunit")
def get_name_nb(self, obj): def get_name_nb(self, obj):
return obj.type.name_nb return obj.type.name_nb
...@@ -123,6 +124,9 @@ class ExtendedRoleSerializer(serializers.ModelSerializer): ...@@ -123,6 +124,9 @@ class ExtendedRoleSerializer(serializers.ModelSerializer):
def get_sponsor_name(self, obj): def get_sponsor_name(self, obj):
return f"{obj.sponsor.first_name} {obj.sponsor.last_name}" return f"{obj.sponsor.first_name} {obj.sponsor.last_name}"
def get_ou_id(self, obj):
return obj.orgunit.id
class Meta: class Meta:
model = Role model = Role
fields = [ fields = [
...@@ -137,5 +141,6 @@ class ExtendedRoleSerializer(serializers.ModelSerializer): ...@@ -137,5 +141,6 @@ class ExtendedRoleSerializer(serializers.ModelSerializer):
"contact_person_unit", "contact_person_unit",
"comments", "comments",
"sponsor_name", "sponsor_name",
"ou_id",
] ]
read_only_fields = ["contact_person_unit", "sponsor_name"] read_only_fields = ["contact_person_unit", "sponsor_name"]
...@@ -35,6 +35,7 @@ def test_serialize_guest(invited_person): ...@@ -35,6 +35,7 @@ def test_serialize_guest(invited_person):
"contact_person_unit": "", "contact_person_unit": "",
"comments": "", "comments": "",
"sponsor_name": "Sponsor Bar", "sponsor_name": "Sponsor Bar",
"ou_id": 1,
}, },
], ],
"verified": False, "verified": False,
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment