You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
216 lines
6.6 KiB
216 lines
6.6 KiB
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) => { |
|
const nodeTarget: AlertOverrideTarget = { |
|
description: node.description, |
|
name: node.name, |
|
node: node.uuid, |
|
subnodes: [], |
|
type: 'node', |
|
uuid: node.uuid, |
|
}; |
|
|
|
const subnodeTargets = Object.values(node.hosts) |
|
.sort((a, b) => a.name.localeCompare(b.name)) |
|
.reduce<AlertOverrideTarget[]>((previous, subnode) => { |
|
if (subnode.type === 'dr') return previous; |
|
|
|
previous.push({ |
|
name: subnode.name, |
|
node: node.uuid, |
|
type: 'subnode', |
|
uuid: subnode.uuid, |
|
}); |
|
|
|
nodeTarget.subnodes?.push(subnode.uuid); |
|
|
|
return previous; |
|
}, []); |
|
|
|
// Append the options in sequence: node followed by its subnode(s). |
|
options.push(nodeTarget, ...subnodeTargets); |
|
|
|
return options; |
|
}, []), |
|
[nodes], |
|
); |
|
|
|
const { fetch: getAlertOverrides, loading: loadingAlertOverrides } = |
|
useActiveFetch<APIAlertOverrideOverviewList>({ |
|
onData: (data) => setAlertOverrides(data), |
|
url: '/alert-override', |
|
}); |
|
|
|
const formikAlertOverrides = useMemo< |
|
AlertOverrideFormikValues | undefined |
|
>(() => { |
|
if (!nodes || !alertOverrides) return undefined; |
|
|
|
/** |
|
* Group alert override rules based on node UUID. The groups will be used |
|
* for comparison to see whether the subnodes are assigned the same alert |
|
* level. |
|
* |
|
* If subnodes have the same level, they will be consolidated into a single |
|
* target for display. Otherwise, every subnode will get its own visual. |
|
*/ |
|
const groups = Object.values(alertOverrides).reduce< |
|
Record<string, APIAlertOverrideOverview[]> |
|
>((previous, override) => { |
|
const { |
|
node: { uuid: nodeUuid }, |
|
} = override; |
|
|
|
if (previous[nodeUuid]) { |
|
previous[nodeUuid].push(override); |
|
} else { |
|
previous[nodeUuid] = [override]; |
|
} |
|
|
|
return previous; |
|
}, {}); |
|
|
|
return Object.entries(groups).reduce<AlertOverrideFormikValues>( |
|
(previous, pair) => { |
|
const [nodeUuid, overrides] = pair; |
|
const [firstOverride, ...restOverrides] = overrides; |
|
|
|
const sameLevel = |
|
overrides.length > 1 && |
|
restOverrides.every(({ level }) => level === firstOverride.level); |
|
|
|
if (sameLevel) { |
|
const { |
|
0: { level }, |
|
} = overrides; |
|
|
|
const { [nodeUuid]: node } = nodes; |
|
|
|
previous[nodeUuid] = { |
|
level, |
|
target: { |
|
description: node.description, |
|
name: node.name, |
|
node: node.uuid, |
|
subnodes: overrides.map<string>(({ subnode: { uuid } }) => uuid), |
|
type: 'node', |
|
uuid: node.uuid, |
|
}, |
|
uuids: overrides.reduce<Record<string, string>>( |
|
(uuids, { subnode, uuid: overrideUuid }) => { |
|
uuids[overrideUuid] = subnode.uuid; |
|
|
|
return uuids; |
|
}, |
|
{}, |
|
), |
|
}; |
|
} else { |
|
overrides.forEach(({ level, node, subnode, uuid: overrideUuid }) => { |
|
previous[subnode.uuid] = { |
|
level, |
|
target: { |
|
name: subnode.name, |
|
node: node.uuid, |
|
type: 'subnode', |
|
uuid: subnode.uuid, |
|
}, |
|
uuids: { [overrideUuid]: subnode.uuid }, |
|
}; |
|
}); |
|
} |
|
|
|
return previous; |
|
}, |
|
{}, |
|
); |
|
}, [alertOverrides, nodes]); |
|
|
|
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} |
|
listEmpty="No mail recipient(s) found." |
|
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;
|
|
|