parent
1f5bf604e1
commit
3ea2fcc520
10 changed files with 751 additions and 0 deletions
@ -0,0 +1,287 @@ |
||||
import { Grid, menuClasses as muiMenuClasses } from '@mui/material'; |
||||
import { FC, useMemo } from 'react'; |
||||
import { v4 as uuidv4 } from 'uuid'; |
||||
|
||||
import ActionGroup from '../ActionGroup'; |
||||
import api from '../../lib/api'; |
||||
import FlexBox from '../FlexBox'; |
||||
import FormSummary from '../FormSummary'; |
||||
import handleAPIError from '../../lib/handleAPIError'; |
||||
import mailRecipientListSchema from './schema'; |
||||
import ManageAlertOverride from './ManageAlertOverride'; |
||||
import MessageGroup from '../MessageGroup'; |
||||
import OutlinedInputWithLabel from '../OutlinedInputWithLabel'; |
||||
import SelectWithLabel from '../SelectWithLabel'; |
||||
import { BodyText, SmallText } from '../Text'; |
||||
import UncontrolledInput from '../UncontrolledInput'; |
||||
import useFormikUtils from '../../hooks/useFormikUtils'; |
||||
|
||||
/** |
||||
* TODO: add descriptions to each item: |
||||
* |
||||
=head4 1 / critical |
||||
|
||||
Alerts at this level will go to all recipients, except for those ignoring the source system entirely. |
||||
|
||||
This is reserved for alerts that could lead to imminent service interruption or unexpected loss of redundancy. |
||||
|
||||
Alerts at this level should trigger alarm systems for all administrators as well as management who may be impacted by service interruptions. |
||||
|
||||
=head4 2 / warning |
||||
|
||||
This is used for alerts that require attention from administrators. Examples include intentional loss of redundancy caused by load shedding, hardware in pre-failure, loss of input power, temperature anomalies, etc. |
||||
|
||||
Alerts at this level should trigger alarm systems for administrative staff. |
||||
|
||||
=head4 3 / notice |
||||
|
||||
This is used for alerts that are generally safe to ignore, but might provide early warnings of developing issues or insight into system behaviour.
|
||||
|
||||
Alerts at this level should not trigger alarm systems. Periodic review is sufficient. |
||||
|
||||
=head4 4 / info |
||||
|
||||
This is used for alerts that are almost always safe to ignore, but may be useful in testing and debugging.
|
||||
*
|
||||
*/ |
||||
const LEVEL_OPTIONS: SelectItem<number>[] = [ |
||||
{ |
||||
displayValue: ( |
||||
<FlexBox spacing={0}> |
||||
<BodyText inheritColour fontWeight="inherit"> |
||||
Critical |
||||
</BodyText> |
||||
<SmallText inheritColour whiteSpace="normal"> |
||||
Alerts that could lead to imminent service interruption or unexpected |
||||
loss of redundancy. |
||||
</SmallText> |
||||
</FlexBox> |
||||
), |
||||
value: 1, |
||||
}, |
||||
{ |
||||
displayValue: ( |
||||
<FlexBox spacing={0}> |
||||
<BodyText inheritColour fontWeight="inherit"> |
||||
Warning |
||||
</BodyText> |
||||
<SmallText inheritColour whiteSpace="normal"> |
||||
Alerts that require attention from administrators, such as redundancy |
||||
loss due to load shedding, hardware in pre-failure, input power loss, |
||||
temperature anomalies, etc. |
||||
</SmallText> |
||||
</FlexBox> |
||||
), |
||||
value: 2, |
||||
}, |
||||
{ |
||||
displayValue: ( |
||||
<FlexBox spacing={0}> |
||||
<BodyText inheritColour fontWeight="inherit"> |
||||
Notice |
||||
</BodyText> |
||||
<SmallText inheritColour whiteSpace="normal"> |
||||
Alerts that are generally safe to ignore, but might provide early |
||||
warnings of developing issues or insight into system behaviour. |
||||
</SmallText> |
||||
</FlexBox> |
||||
), |
||||
value: 3, |
||||
}, |
||||
{ |
||||
displayValue: ( |
||||
<FlexBox spacing={0}> |
||||
<BodyText inheritColour fontWeight="inherit"> |
||||
Info |
||||
</BodyText> |
||||
<SmallText inheritColour whiteSpace="normal"> |
||||
Alerts that are almost always safe to ignore, but may be useful in |
||||
testing and debugging. |
||||
</SmallText> |
||||
</FlexBox> |
||||
), |
||||
value: 4, |
||||
}, |
||||
]; |
||||
|
||||
const MAP_TO_LEVEL_LABEL: Record<number, string> = { |
||||
1: 'Critical', |
||||
2: 'Warning', |
||||
3: 'Notice', |
||||
4: 'Info', |
||||
}; |
||||
|
||||
const AddMailRecipientForm: FC<AddMailRecipientFormProps> = (props) => { |
||||
const { |
||||
alertOverrideTargetOptions, |
||||
mailRecipientUuid, |
||||
previousFormikValues, |
||||
tools, |
||||
} = props; |
||||
|
||||
const mrUuid = useMemo<string>( |
||||
() => mailRecipientUuid ?? uuidv4(), |
||||
[mailRecipientUuid], |
||||
); |
||||
|
||||
const formikUtils = useFormikUtils<MailRecipientFormikValues>({ |
||||
initialValues: previousFormikValues ?? { |
||||
[mrUuid]: { |
||||
alertOverrides: {}, |
||||
email: '', |
||||
language: 'en_CA', |
||||
level: 2, |
||||
name: '', |
||||
uuid: mrUuid, |
||||
}, |
||||
}, |
||||
onSubmit: (values, { setSubmitting }) => { |
||||
const { [mrUuid]: mailRecipient } = values; |
||||
const { confirm } = tools; |
||||
|
||||
let actionProceedText: string = 'Add'; |
||||
let errorMessage: React.ReactNode = <>Failed to add mail recipient.</>; |
||||
let method: 'post' | 'put' = 'post'; |
||||
let successMessage: React.ReactNode = <>Mail recipient added.</>; |
||||
let titleText: string = `Add mail recipient with the following?`; |
||||
let url: string = '/mail-recipient'; |
||||
|
||||
if (previousFormikValues) { |
||||
actionProceedText = 'Update'; |
||||
errorMessage = <>Failed to update mail server.</>; |
||||
method = 'put'; |
||||
successMessage = <>Mail recipient updated.</>; |
||||
titleText = `Update ${mailRecipient.name} with the following?`; |
||||
url += `/${mrUuid}`; |
||||
} |
||||
|
||||
const { alertOverrides, uuid, ...mrBody } = mailRecipient; |
||||
|
||||
confirm.prepare({ |
||||
actionProceedText, |
||||
content: <FormSummary entries={mrBody} />, |
||||
onCancelAppend: () => setSubmitting(false), |
||||
onProceedAppend: () => { |
||||
confirm.loading(true); |
||||
|
||||
api[method](url, mrBody) |
||||
.then(() => confirm.finish('Success', { children: successMessage })) |
||||
.catch((error) => { |
||||
const emsg = handleAPIError(error); |
||||
|
||||
emsg.children = ( |
||||
<> |
||||
{errorMessage} {emsg.children} |
||||
</> |
||||
); |
||||
|
||||
confirm.finish('Error', emsg); |
||||
}) |
||||
.finally(() => setSubmitting(false)); |
||||
}, |
||||
titleText, |
||||
}); |
||||
|
||||
confirm.open(true); |
||||
}, |
||||
validationSchema: mailRecipientListSchema, |
||||
}); |
||||
|
||||
const { disabledSubmit, formik, formikErrors, handleChange } = formikUtils; |
||||
|
||||
const emailChain = useMemo<string>(() => `${mrUuid}.email`, [mrUuid]); |
||||
const levelChain = useMemo<string>(() => `${mrUuid}.level`, [mrUuid]); |
||||
const nameChain = useMemo<string>(() => `${mrUuid}.name`, [mrUuid]); |
||||
|
||||
return ( |
||||
<Grid |
||||
columns={{ xs: 1, sm: 2 }} |
||||
component="form" |
||||
container |
||||
onSubmit={(event) => { |
||||
event.preventDefault(); |
||||
|
||||
formik.submitForm(); |
||||
}} |
||||
spacing="1em" |
||||
> |
||||
<Grid item xs={1}> |
||||
<UncontrolledInput |
||||
input={ |
||||
<OutlinedInputWithLabel |
||||
id={nameChain} |
||||
label="Recipient name" |
||||
name={nameChain} |
||||
onChange={handleChange} |
||||
required |
||||
value={formik.values[mrUuid].name} |
||||
/> |
||||
} |
||||
/> |
||||
</Grid> |
||||
<Grid item xs={1}> |
||||
<UncontrolledInput |
||||
input={ |
||||
<OutlinedInputWithLabel |
||||
id={emailChain} |
||||
label="Recipient email" |
||||
name={emailChain} |
||||
onChange={handleChange} |
||||
required |
||||
value={formik.values[mrUuid].email} |
||||
/> |
||||
} |
||||
/> |
||||
</Grid> |
||||
<Grid item xs={1}> |
||||
<UncontrolledInput |
||||
input={ |
||||
<SelectWithLabel |
||||
id={levelChain} |
||||
label="Alert level" |
||||
name={levelChain} |
||||
onChange={formik.handleChange} |
||||
required |
||||
selectItems={LEVEL_OPTIONS} |
||||
selectProps={{ |
||||
MenuProps: { |
||||
sx: { |
||||
[`& .${muiMenuClasses.paper}`]: { |
||||
maxWidth: { md: '60%', lg: '40%' }, |
||||
}, |
||||
}, |
||||
}, |
||||
renderValue: (value) => MAP_TO_LEVEL_LABEL[value], |
||||
}} |
||||
value={formik.values[mrUuid].level} |
||||
/> |
||||
} |
||||
/> |
||||
</Grid> |
||||
<Grid item width="100%"> |
||||
<ManageAlertOverride |
||||
alertOverrideTargetOptions={alertOverrideTargetOptions} |
||||
formikUtils={formikUtils} |
||||
mailRecipientUuid={mrUuid} |
||||
/> |
||||
</Grid> |
||||
<Grid item width="100%"> |
||||
<MessageGroup count={1} messages={formikErrors} /> |
||||
</Grid> |
||||
<Grid item width="100%"> |
||||
<ActionGroup |
||||
actions={[ |
||||
{ |
||||
background: 'blue', |
||||
children: previousFormikValues ? 'Update' : 'Add', |
||||
disabled: disabledSubmit, |
||||
type: 'submit', |
||||
}, |
||||
]} |
||||
/> |
||||
</Grid> |
||||
</Grid> |
||||
); |
||||
}; |
||||
|
||||
export default AddMailRecipientForm; |
@ -0,0 +1,117 @@ |
||||
import { Grid } from '@mui/material'; |
||||
import { FC, useMemo } from 'react'; |
||||
import { v4 as uuidv4 } from 'uuid'; |
||||
|
||||
import Autocomplete from '../Autocomplete'; |
||||
import FlexBox from '../FlexBox'; |
||||
import IconButton from '../IconButton'; |
||||
import SelectWithLabel from '../SelectWithLabel'; |
||||
import { BodyText, SmallText } from '../Text'; |
||||
import UncontrolledInput from '../UncontrolledInput'; |
||||
|
||||
const LEVEL_OPTIONS: SelectItem<number>[] = [ |
||||
{ displayValue: 'Critical', value: 1 }, |
||||
{ displayValue: 'Warning', value: 2 }, |
||||
{ displayValue: 'Notice', value: 3 }, |
||||
{ displayValue: 'Info', value: 4 }, |
||||
]; |
||||
|
||||
const AlertOverrideInputGroup: FC<AlertOverrideInputGroupProps> = (props) => { |
||||
const { |
||||
alertOverrideTargetOptions, |
||||
alertOverrideUuid, |
||||
mailRecipientUuid: mrUuid, |
||||
formikUtils, |
||||
} = props; |
||||
|
||||
const aoUuid = useMemo<string>( |
||||
() => alertOverrideUuid ?? uuidv4(), |
||||
[alertOverrideUuid], |
||||
); |
||||
|
||||
const { formik } = formikUtils; |
||||
const { |
||||
values: { [mrUuid]: mailRecipient }, |
||||
} = formik; |
||||
const { |
||||
alertOverrides: { [aoUuid]: alertOverride }, |
||||
} = mailRecipient; |
||||
|
||||
const overrideChain = useMemo<string>( |
||||
() => `${mrUuid}.alertOverrides.${aoUuid}`, |
||||
[aoUuid, mrUuid], |
||||
); |
||||
const targetChain = useMemo<string>( |
||||
() => `${overrideChain}.target`, |
||||
[overrideChain], |
||||
); |
||||
const levelChain = useMemo<string>( |
||||
() => `${overrideChain}.level`, |
||||
[overrideChain], |
||||
); |
||||
|
||||
return ( |
||||
<Grid |
||||
alignItems="center" |
||||
columns={{ xs: 1, sm: 10 }} |
||||
container |
||||
justifyContent="stretch" |
||||
spacing="1em" |
||||
> |
||||
<Grid item xs={6}> |
||||
<Autocomplete |
||||
getOptionLabel={(option) => option.name} |
||||
id={targetChain} |
||||
isOptionEqualToValue={(option, value) => option.uuid === value.uuid} |
||||
label="Target" |
||||
noOptionsText="No node or subnode found." |
||||
onChange={(event, value) => |
||||
formik.setFieldValue(targetChain, value, true) |
||||
} |
||||
openOnFocus |
||||
options={alertOverrideTargetOptions} |
||||
renderOption={(optionProps, option) => ( |
||||
<li {...optionProps} key={`${option.node}-${option.uuid}`}> |
||||
{option.type === 'node' ? ( |
||||
<FlexBox spacing={0}> |
||||
<BodyText inheritColour>{option.name}</BodyText> |
||||
<SmallText inheritColour>{option.description}</SmallText> |
||||
</FlexBox> |
||||
) : ( |
||||
<BodyText inheritColour paddingLeft=".6em"> |
||||
{option.name} |
||||
</BodyText> |
||||
)} |
||||
</li> |
||||
)} |
||||
value={alertOverride.target} |
||||
/> |
||||
</Grid> |
||||
<Grid item flexGrow={1}> |
||||
<UncontrolledInput |
||||
input={ |
||||
<SelectWithLabel |
||||
id={levelChain} |
||||
label="Alert level" |
||||
name={levelChain} |
||||
onChange={formik.handleChange} |
||||
selectItems={LEVEL_OPTIONS} |
||||
value={alertOverride.level} |
||||
/> |
||||
} |
||||
/> |
||||
</Grid> |
||||
<Grid item width="min-content"> |
||||
<IconButton |
||||
mapPreset="delete" |
||||
onClick={() => { |
||||
formik.setFieldValue(overrideChain, undefined, true); |
||||
}} |
||||
size="small" |
||||
/> |
||||
</Grid> |
||||
</Grid> |
||||
); |
||||
}; |
||||
|
||||
export default AlertOverrideInputGroup; |
@ -0,0 +1,9 @@ |
||||
import { FC } from 'react'; |
||||
|
||||
import AddMailRecipientForm from './AddMailRecipientForm'; |
||||
|
||||
const EditMailRecipientForm: FC<EditMailRecipientFormProps> = (props) => ( |
||||
<AddMailRecipientForm {...props} /> |
||||
); |
||||
|
||||
export default EditMailRecipientForm; |
@ -0,0 +1,58 @@ |
||||
import { FC } from 'react'; |
||||
import { v4 as uuidv4 } from 'uuid'; |
||||
|
||||
import AlertOverrideInputGroup from './AlertOverrideInputGroup'; |
||||
import List from '../List'; |
||||
import useChecklist from '../../hooks/useChecklist'; |
||||
|
||||
const ManageAlertOverride: FC<ManageAlertOverrideProps> = (props) => { |
||||
const { |
||||
alertOverrideTargetOptions, |
||||
formikUtils, |
||||
mailRecipientUuid: mrUuid, |
||||
} = props; |
||||
|
||||
const { formik } = formikUtils; |
||||
const { |
||||
values: { [mrUuid]: mailRecipient }, |
||||
} = formik; |
||||
const { alertOverrides } = mailRecipient; |
||||
|
||||
const { hasChecks } = useChecklist(alertOverrides); |
||||
|
||||
return ( |
||||
<List |
||||
allowAddItem |
||||
disableDelete={!hasChecks} |
||||
edit |
||||
header="Alert override rules" |
||||
listEmpty="No alert overrides(s)" |
||||
listItems={alertOverrides} |
||||
onAdd={() => { |
||||
const aoUuid = uuidv4(); |
||||
|
||||
formik.setValues((previous) => { |
||||
const current = { ...previous }; |
||||
|
||||
current[mrUuid].alertOverrides[aoUuid] = { |
||||
level: 2, |
||||
target: null, |
||||
uuid: aoUuid, |
||||
}; |
||||
|
||||
return current; |
||||
}); |
||||
}} |
||||
renderListItem={(uuid) => ( |
||||
<AlertOverrideInputGroup |
||||
alertOverrideTargetOptions={alertOverrideTargetOptions} |
||||
alertOverrideUuid={uuid} |
||||
formikUtils={formikUtils} |
||||
mailRecipientUuid={mrUuid} |
||||
/> |
||||
)} |
||||
/> |
||||
); |
||||
}; |
||||
|
||||
export default ManageAlertOverride; |
@ -0,0 +1,160 @@ |
||||
import { FC, useMemo, useState } from 'react'; |
||||
|
||||
import AddMailRecipientForm from './AddMailRecipientForm'; |
||||
import { toAnvilOverviewList } from '../../lib/api_converters'; |
||||
import CrudList from '../CrudList'; |
||||
import EditMailRecipientForm from './EditMailRecipientForm'; |
||||
import { BodyText } from '../Text'; |
||||
import useActiveFetch from '../../hooks/useActiveFetch'; |
||||
import useFetch from '../../hooks/useFetch'; |
||||
|
||||
const ManageMailRecipient: FC = () => { |
||||
const [alertOverrides, setAlertOverrides] = useState< |
||||
APIAlertOverrideOverviewList | undefined |
||||
>(); |
||||
|
||||
const { altData: nodes, loading: loadingNodes } = useFetch< |
||||
APIAnvilOverviewArray, |
||||
APIAnvilOverviewList |
||||
>('/anvil', { mod: toAnvilOverviewList }); |
||||
|
||||
const alertOverrideTargetOptions = useMemo<AlertOverrideTarget[] | undefined>( |
||||
() => |
||||
nodes && |
||||
Object.values(nodes) |
||||
.sort((a, b) => a.name.localeCompare(b.name)) |
||||
.reduce<AlertOverrideTarget[]>((options, node) => { |
||||
options.push({ |
||||
description: node.description, |
||||
name: node.name, |
||||
node: node.uuid, |
||||
type: 'node', |
||||
uuid: node.uuid, |
||||
}); |
||||
|
||||
Object.values(node.hosts) |
||||
.sort((a, b) => a.name.localeCompare(b.name)) |
||||
.forEach((subnode) => { |
||||
if (subnode.type === 'dr') return; |
||||
|
||||
options.push({ |
||||
name: subnode.name, |
||||
node: node.uuid, |
||||
type: 'subnode', |
||||
uuid: subnode.uuid, |
||||
}); |
||||
}); |
||||
|
||||
return options; |
||||
}, []), |
||||
[nodes], |
||||
); |
||||
|
||||
const { fetch: getAlertOverrides, loading: loadingAlertOverrides } = |
||||
useActiveFetch<APIAlertOverrideOverviewList>({ |
||||
onData: (data) => setAlertOverrides(data), |
||||
url: '/alert-override', |
||||
}); |
||||
|
||||
const formikAlertOverrides = useMemo< |
||||
AlertOverrideFormikValues | undefined |
||||
>(() => { |
||||
if (!alertOverrides) return undefined; |
||||
|
||||
const groups: Record<string, number> = {}; |
||||
|
||||
return Object.values(alertOverrides).reduce<AlertOverrideFormikValues>( |
||||
(previous, value) => { |
||||
const { level, node, subnode, uuid } = value; |
||||
|
||||
groups[node.uuid] = groups[node.uuid] ? groups[node.uuid] + 1 : 1; |
||||
|
||||
previous[uuid] = { |
||||
level, |
||||
target: |
||||
groups[node.uuid] > 1 |
||||
? { |
||||
name: node.name, |
||||
node: node.uuid, |
||||
type: 'node', |
||||
uuid: node.uuid, |
||||
} |
||||
: { |
||||
name: subnode.name, |
||||
node: node.uuid, |
||||
type: 'subnode', |
||||
uuid: subnode.uuid, |
||||
}, |
||||
uuid, |
||||
}; |
||||
|
||||
return previous; |
||||
}, |
||||
{}, |
||||
); |
||||
}, [alertOverrides]); |
||||
|
||||
return ( |
||||
<> |
||||
<CrudList<APIMailRecipientOverview, APIMailRecipientDetail> |
||||
addHeader="Add mail recipient" |
||||
editHeader={(entry) => `Update ${entry?.name}`} |
||||
entriesUrl="/mail-recipient" |
||||
getAddLoading={(previous) => previous || loadingNodes} |
||||
getDeleteErrorMessage={({ children, ...rest }) => ({ |
||||
...rest, |
||||
children: <>Failed to delete mail recipient(s). {children}</>, |
||||
})} |
||||
getDeleteHeader={(count) => |
||||
`Delete the following ${count} mail recipient(s)?` |
||||
} |
||||
getDeleteSuccessMessage={() => ({ |
||||
children: <>Successfully deleted mail recipient(s).</>, |
||||
})} |
||||
getEditLoading={(previous) => previous || loadingAlertOverrides} |
||||
onItemClick={(base, ...args) => { |
||||
const [, mailRecipientUuid] = args; |
||||
|
||||
base(...args); |
||||
|
||||
getAlertOverrides(undefined, { |
||||
params: { 'mail-recipient': mailRecipientUuid }, |
||||
}); |
||||
}} |
||||
renderAddForm={(tools) => |
||||
alertOverrideTargetOptions && ( |
||||
<AddMailRecipientForm |
||||
alertOverrideTargetOptions={alertOverrideTargetOptions} |
||||
tools={tools} |
||||
/> |
||||
) |
||||
} |
||||
renderDeleteItem={(mailRecipientList, { key }) => { |
||||
const mr = mailRecipientList?.[key]; |
||||
|
||||
return <BodyText>{mr?.name}</BodyText>; |
||||
}} |
||||
renderEditForm={(tools, mailRecipient) => |
||||
alertOverrideTargetOptions && |
||||
mailRecipient && |
||||
formikAlertOverrides && ( |
||||
<EditMailRecipientForm |
||||
alertOverrideTargetOptions={alertOverrideTargetOptions} |
||||
mailRecipientUuid={mailRecipient.uuid} |
||||
previousFormikValues={{ |
||||
[mailRecipient.uuid]: { |
||||
alertOverrides: formikAlertOverrides, |
||||
...mailRecipient, |
||||
}, |
||||
}} |
||||
tools={tools} |
||||
/> |
||||
) |
||||
} |
||||
renderListItem={(uuid, { name }) => <BodyText>{name}</BodyText>} |
||||
/> |
||||
</> |
||||
); |
||||
}; |
||||
|
||||
export default ManageMailRecipient; |
@ -0,0 +1,4 @@ |
||||
import AddMailRecipientForm from './AddMailRecipientForm'; |
||||
import ManageMailRecipient from './ManageMailRecipient'; |
||||
|
||||
export { AddMailRecipientForm, ManageMailRecipient }; |
@ -0,0 +1,33 @@ |
||||
import * as yup from 'yup'; |
||||
|
||||
import buildYupDynamicObject from '../../lib/buildYupDynamicObject'; |
||||
|
||||
const alertLevelSchema = yup.number().oneOf([1, 2, 3, 4]); |
||||
|
||||
const alertOverrideSchema = yup.object({ |
||||
level: alertLevelSchema.required(), |
||||
target: yup.object({ |
||||
type: yup.string().oneOf(['node', 'subnode']).required(), |
||||
uuid: yup.string().uuid().required(), |
||||
}), |
||||
uuid: yup.string().uuid().required(), |
||||
}); |
||||
|
||||
const alertOverrideListSchema = yup.lazy((entries) => |
||||
yup.object(buildYupDynamicObject(entries, alertOverrideSchema)), |
||||
); |
||||
|
||||
const mailRecipientSchema = yup.object({ |
||||
alertOverrides: alertOverrideListSchema, |
||||
email: yup.string().email().required(), |
||||
language: yup.string().oneOf(['en_CA']).optional(), |
||||
level: alertLevelSchema.required(), |
||||
name: yup.string().required(), |
||||
uuid: yup.string().uuid().required(), |
||||
}); |
||||
|
||||
const mailRecipientListSchema = yup.lazy((entries) => |
||||
yup.object(buildYupDynamicObject(entries, mailRecipientSchema)), |
||||
); |
||||
|
||||
export default mailRecipientListSchema; |
@ -0,0 +1,11 @@ |
||||
type APIAlertOverrideOverview = { |
||||
level: number; |
||||
mailRecipient: APIMailRecipientOverview; |
||||
node: { name: string; uuid: string }; |
||||
subnode: { name: string; short: string; uuid: string }; |
||||
uuid: string; |
||||
}; |
||||
|
||||
type APIAlertOverrideOverviewList = { |
||||
[uuid: string]: APIAlertOverrideOverview; |
||||
}; |
@ -0,0 +1,11 @@ |
||||
type APIMailRecipientOverview = { name: string; uuid: string }; |
||||
|
||||
type APIMailRecipientOverviewList = { |
||||
[uuid: string]: APIMailRecipientOverview; |
||||
}; |
||||
|
||||
type APIMailRecipientDetail = APIMailRecipientOverview & { |
||||
email: string; |
||||
language: string; |
||||
level: number; |
||||
}; |
@ -0,0 +1,61 @@ |
||||
type AlertOverrideTarget = { |
||||
description?: string; |
||||
name: string; |
||||
node: string; |
||||
type: 'node' | 'subnode'; |
||||
uuid: string; |
||||
}; |
||||
|
||||
type AlertOverrideFormikAlertOverride = { |
||||
level: number; |
||||
target: AlertOverrideTarget | null; |
||||
uuid: string; |
||||
}; |
||||
|
||||
type AlertOverrideFormikValues = { |
||||
[uuid: string]: AlertOverrideFormikAlertOverride; |
||||
}; |
||||
|
||||
type MailRecipientFormikMailRecipient = APIMailRecipientDetail & { |
||||
alertOverrides: AlertOverrideFormikValues; |
||||
}; |
||||
|
||||
type MailRecipientFormikValues = { |
||||
[uuid: string]: MailRecipientFormikMailRecipient; |
||||
}; |
||||
|
||||
/** AddMailRecipientForm */ |
||||
|
||||
type AddMailRecipientFormOptionalProps = { |
||||
mailRecipientUuid?: string; |
||||
previousFormikValues?: MailRecipientFormikValues; |
||||
}; |
||||
|
||||
type AddMailRecipientFormProps = AddMailRecipientFormOptionalProps & { |
||||
alertOverrideTargetOptions: AlertOverrideTarget[]; |
||||
tools: CrudListFormTools; |
||||
}; |
||||
|
||||
/** EditMailRecipientForm */ |
||||
|
||||
type EditMailRecipientFormProps = Required<AddMailRecipientFormProps>; |
||||
|
||||
/** ManageAlertOverride */ |
||||
|
||||
type ManageAlertOverrideProps = Required< |
||||
Pick< |
||||
AddMailRecipientFormProps, |
||||
'alertOverrideTargetOptions' | 'mailRecipientUuid' |
||||
> |
||||
> & { |
||||
formikUtils: FormikUtils<MailRecipientFormikValues>; |
||||
}; |
||||
|
||||
/** AlertOverrideInputGroup */ |
||||
|
||||
type AlertOverrideInputGroupOptionalProps = { |
||||
alertOverrideUuid?: string; |
||||
}; |
||||
|
||||
type AlertOverrideInputGroupProps = AlertOverrideInputGroupOptionalProps & |
||||
ManageAlertOverrideProps; |
Loading…
Reference in new issue