diff --git a/frontend/src/webparts/approvalAdmin/components/app/AdminApp.tsx b/frontend/src/webparts/approvalAdmin/components/app/AdminApp.tsx index 0db5ee1..1fb17ab 100644 --- a/frontend/src/webparts/approvalAdmin/components/app/AdminApp.tsx +++ b/frontend/src/webparts/approvalAdmin/components/app/AdminApp.tsx @@ -14,6 +14,7 @@ import { texts } from '../../texts'; import { useLocalStorageState } from '../../hooks/useLocalStorageState'; import { DashboardScreen } from '../screens/DashboardScreen'; import { RequestTypesScreen } from '../screens/RequestTypesScreen'; +import { RequestTypeAccessScreen } from '../screens/RequestTypeAccessScreen'; import { RoutesScreen } from '../screens/RoutesScreen'; import { RouteStepsScreen } from '../screens/RouteStepsScreen'; import { ResolveScreen } from '../screens/ResolveScreen'; @@ -27,6 +28,7 @@ import { ManageByUserScreen } from '../screens/ManageByUserScreen'; const NAV_ITEMS: ISidebarItem[] = [ { id: 'dashboard', title: texts.nav.dashboard, icon: 'chart' }, { id: 'requestTypes', title: texts.nav.requestTypes, icon: 'document' }, + { id: 'requestTypeAccess', title: texts.nav.requestTypeAccess, icon: 'people' }, { id: 'routes', title: texts.nav.routes, icon: 'send' }, { id: 'resolve', title: texts.nav.resolve, icon: 'search' }, { id: 'manageRequests', title: texts.nav.manageRequests, icon: 'clipboard' }, @@ -147,6 +149,7 @@ export const AdminApp: React.FC = ({ api, dictionary, sharePoint
{route.tab === 'dashboard' && } {route.tab === 'requestTypes' && } + {route.tab === 'requestTypeAccess' && } {route.tab === 'routes' && !route.routeId && ( = ({ api, dictionary }) => { + const requestTypes = useRequestTypes(api); + const access = useRequestTypeAccess(api); + const employees = usePortalEmployees(dictionary); + + const [showForm, setShowForm] = React.useState(false); + const [requestTypeId, setRequestTypeId] = React.useState(''); + const [email, setEmail] = React.useState(''); + const submit = useAsyncSubmit(); + + const deleteTarget = useDeleteTarget(item => api.requestTypeAccess.remove(item.id), access.reload); + + const requestTypeName = (id: number): string => requestTypes.items.find(rt => rt.id === id)?.name ?? `#${id}`; + + const openCreate = (): void => { + setRequestTypeId(''); + setEmail(''); + setShowForm(true); + }; + + const submitForm = (): void => { + if (!requestTypeId) { + submit.fail(texts.requestTypeAccess.validationRequestType); + return; + } + if (!email.trim()) { + submit.fail(texts.requestTypeAccess.validationEmail); + return; + } + + submit.run(() => + api.requestTypeAccess.create({ requestTypeId: Number(requestTypeId), email: email.trim() }).then(() => { + setShowForm(false); + access.reload(); + }) + ); + }; + + return ( +
+ + {texts.requestTypeAccess.add}} + /> + + {access.error && {access.error}} + {deleteTarget.error && {deleteTarget.error}} + + {requestTypeName(r.requestTypeId)} }, + { key: 'email', header: texts.requestTypeAccess.columnEmail, render: r => r.email }, + { + key: 'actions', + header: '', + width: '100px', + align: 'right', + sticky: true, + render: r => ( + + deleteTarget.ask(r)} /> + + ) + } + ]} + rows={access.items} + keyOf={r => r.id} + emptyMessage={access.isLoading ? texts.common.loading : texts.requestTypeAccess.emptyList} + /> + + {showForm && ( + setShowForm(false)} + > + + +