diff --git a/react/assets/forus-platform/scss/_common/includes/common.scss b/react/assets/forus-platform/scss/_common/includes/common.scss index 935667024..4f27569df 100644 --- a/react/assets/forus-platform/scss/_common/includes/common.scss +++ b/react/assets/forus-platform/scss/_common/includes/common.scss @@ -93,6 +93,10 @@ img { text-decoration: line-through; } +.text-white-space-normal { + white-space: normal; +} + .text-pre { white-space: pre; } @@ -178,10 +182,6 @@ img { color: #e63b3b !important; } -.text-danger-dark { - color: #8b0f0f !important; -} - .text-dim { color: #454545 !important; } diff --git a/react/src/dashboard/components/pages/implementation-notifications/ImplementationNotificationEdit.tsx b/react/src/dashboard/components/pages/implementation-notifications/ImplementationNotificationEdit.tsx index 818fb6343..b99dfce6e 100644 --- a/react/src/dashboard/components/pages/implementation-notifications/ImplementationNotificationEdit.tsx +++ b/react/src/dashboard/components/pages/implementation-notifications/ImplementationNotificationEdit.tsx @@ -8,8 +8,6 @@ import SystemNotification from '../../../props/models/SystemNotification'; import { useParams } from 'react-router'; import StateNavLink from '../../../modules/state_router/StateNavLink'; import SystemNotificationEditor from './elements/SystemNotificationEditor'; -import { useFundService } from '../../../services/FundService'; -import Fund from '../../../props/models/Fund'; import useTranslate from '../../../hooks/useTranslate'; import useSetProgress from '../../../hooks/useSetProgress'; import usePushApiError from '../../../hooks/usePushApiError'; @@ -23,13 +21,9 @@ export default function ImplementationNotificationEdit() { const pushApiError = usePushApiError(); const activeOrganization = useActiveOrganization(); - const fundService = useFundService(); const implementationService = useImplementationService(); const implementationNotificationsService = useImplementationNotificationService(); - const [fund, setFund] = useState>(null); - const [funds, setFunds] = useState>>(null); - const [notification, setNotification] = useState(null); const [implementation, setImplementation] = useState(null); @@ -47,35 +41,11 @@ export default function ImplementationNotificationEdit() { setProgress(0); implementationNotificationsService - .read(activeOrganization.id, parseInt(implementationId), parseInt(id), { fund_id: fund?.id }) + .read(activeOrganization.id, parseInt(implementationId), parseInt(id)) .then((res) => setNotification(res.data.data)) .catch(pushApiError) .finally(() => setProgress(100)); - }, [ - id, - fund?.id, - setProgress, - pushApiError, - implementationId, - activeOrganization.id, - implementationNotificationsService, - ]); - - const fetchFunds = useCallback(() => { - if (implementation.allow_per_fund_notification_templates) { - setProgress(0); - - fundService - .list(activeOrganization.id, { - implementation_id: implementation.id, - with_archived: 1, - stats: 'min', - }) - .then((res) => setFunds([{ id: null, name: 'Alle fondsen' }, ...res.data.data])) - .catch(pushApiError) - .finally(() => setProgress(100)); - } - }, [setProgress, implementation, fundService, activeOrganization.id, pushApiError]); + }, [id, setProgress, pushApiError, implementationId, activeOrganization.id, implementationNotificationsService]); useEffect(() => { fetchImplementation(); @@ -85,13 +55,7 @@ export default function ImplementationNotificationEdit() { fetchNotification(); }, [fetchNotification]); - useEffect(() => { - if (implementation) { - fetchFunds(); - } - }, [fetchFunds, implementation]); - - if (!implementation || !notification || (implementation?.allow_per_fund_notification_templates && !funds)) { + if (!implementation || !notification) { return ; } @@ -112,9 +76,6 @@ export default function ImplementationNotificationEdit() { >(['mail', 'push', 'database']); const [notifications, setNotifications] = useState>(null); const [implementation, setImplementation] = useState(null); @@ -52,7 +52,6 @@ export default function ImplementationNotifications() { const list = notifications?.data?.map((notification) => ({ ...notification, - state: implementationNotificationsService.notificationToStateLabel(notification), title: translate(`system_notifications.notifications.${notification.key}.title`), description: translate(`system_notifications.notifications.${notification.key}.description`), })); @@ -63,67 +62,7 @@ export default function ImplementationNotifications() { .map((group) => ({ group, groupLabel: groupLabels[group], notifications: grouped[group] })) .map((item) => ({ ...item, notifications: item.notifications.sort((a, b) => a.order - b.order) })) .sort((a, b) => groupOrder.indexOf(a.group) - groupOrder.indexOf(b.group)); - }, [translate, groupLabels, notifications, implementationNotificationsService]); - - const notificationIconColor = useCallback( - (notification: SystemNotification, type: 'database' | 'mail' | 'push') => { - const templateChanged = notification.templates.filter((item) => item.type == type).length > 0; - - if (!notification.channels.includes(type)) { - return 'text-muted-light'; - } - - if (!notification.enable_all || !notification['enable_' + type]) { - return 'text-danger-dark'; - } - - return templateChanged ? 'text-primary-dark' : 'text-success-dark'; - }, - [], - ); - - const notificationIcon = useCallback((notification: SystemNotification, type: 'database' | 'mail' | 'push') => { - const iconOff = { - mail: 'email-off-outline', - push: 'cellphone-off', - database: 'bell-off-outline', - }[type]; - - const iconsOn = { - mail: 'email', - push: 'cellphone', - database: 'bell', - }[type]; - - if (!notification.channels.includes(type) || !notification.enable_all || !notification['enable_' + type]) { - return iconOff; - } - - return iconsOn; - }, []); - - const notificationIconTooltip = useCallback( - (notification: SystemNotification, type: 'database' | 'mail' | 'push') => { - const heading = translate(`system_notifications.types.${type}.title`); - const templateChanged = notification.templates.filter((item) => item.type == type).length > 0; - - if (!notification.channels.includes(type)) { - return { heading, text: translate(`system_notifications.tooltips.channel_not_available`) }; - } - - if (!notification.enable_all || !notification[`enable_${type}`]) { - return { heading, text: translate(`system_notifications.tooltips.disabled_by_you`) }; - } - - return { - heading, - text: translate( - 'system_notifications.tooltips.' + (templateChanged ? 'enabled_edited' : 'enabled_default'), - ), - }; - }, - [translate], - ); + }, [translate, groupLabels, notifications]); const fetchImplementationNotifications = useCallback(() => { implementationNotificationsService @@ -214,7 +153,7 @@ export default function ImplementationNotifications() { customElement={'tr'} className={'tr-clickable'}> -
+
{notification.editable ? ( ) : ( @@ -222,46 +161,17 @@ export default function ImplementationNotifications() { )} {notification.title}
- {notification.description} +
+ {notification.description} +
+ {notification.optional ? 'Nee' : 'Ja'} -
- {channels.map((channel, index) => ( - -
-
- {notificationIconTooltip(notification, channel).heading} -
-
- {notificationIconTooltip(notification, channel).text} -
-
-
- ))} -
+ - {notification.state?.state === 'active' && ( - - )} - - {notification.state?.state === 'inactive' && ( - - )} - - {notification.state?.state === 'active_partly' && ( - - )} - - {!['active', 'inactive', 'active_partly'].includes(notification.state?.state) && ( - - )} + diff --git a/react/src/dashboard/components/pages/implementation-notifications/elements/SystemNotificationChannelIcon.tsx b/react/src/dashboard/components/pages/implementation-notifications/elements/SystemNotificationChannelIcon.tsx new file mode 100644 index 000000000..8955efc34 --- /dev/null +++ b/react/src/dashboard/components/pages/implementation-notifications/elements/SystemNotificationChannelIcon.tsx @@ -0,0 +1,124 @@ +import React, { useMemo } from 'react'; +import classNames from 'classnames'; +import useTranslate from '../../../../hooks/useTranslate'; +import SystemNotification from '../../../../props/models/SystemNotification'; + +export default function SystemNotificationChannelIcon({ + notification, + type, +}: { + notification: SystemNotification; + type: 'database' | 'mail' | 'push'; +}) { + const translate = useTranslate(); + + const hasAnyFundChannelDisabled = useMemo(() => { + return Boolean( + notification.funds?.some((fund) => { + const enabled = { + database: fund.enable_database, + mail: fund.enable_mail, + push: fund.enable_push, + }[type]; + + return !fund.enable_all || !enabled; + }), + ); + }, [notification.funds, type]); + + const hasAllFundsChannelDisabled = useMemo(() => { + return Boolean( + notification.funds?.length && + notification.funds.every((fund) => { + const enabled = { + database: fund.enable_database, + mail: fund.enable_mail, + push: fund.enable_push, + }[type]; + + return !fund.enable_all || !enabled; + }), + ); + }, [notification.funds, type]); + + const templateChanged = useMemo(() => { + return notification.templates.filter((item) => item.type == type).length > 0; + }, [notification.templates, type]); + + const icon = useMemo(() => { + const iconOff = { + mail: 'email-off-outline', + push: 'cellphone-off', + database: 'bell-off-outline', + }[type]; + + const iconOn = { + mail: 'email', + push: 'cellphone', + database: 'bell', + }[type]; + + if ( + !notification.channels.includes(type) || + !notification.enable_all || + !notification['enable_' + type] || + hasAllFundsChannelDisabled + ) { + return iconOff; + } + + return iconOn; + }, [hasAllFundsChannelDisabled, notification, type]); + + const color = useMemo(() => { + if (!notification.channels.includes(type)) { + return classNames('text-muted-light'); + } + + if (!notification.enable_all || !notification['enable_' + type] || hasAllFundsChannelDisabled) { + return classNames('text-danger'); + } + + if (hasAnyFundChannelDisabled) { + return classNames('text-warning'); + } + + return classNames(templateChanged ? 'text-primary-dark' : 'text-success-dark'); + }, [hasAllFundsChannelDisabled, hasAnyFundChannelDisabled, notification, templateChanged, type]); + + const tooltip = useMemo(() => { + const heading = translate(`system_notifications.types.${type}.title`); + + if (!notification.channels.includes(type)) { + return { heading, text: translate(`system_notifications.tooltips.channel_not_available`) }; + } + + if (!notification.enable_all || !notification[`enable_${type}`]) { + return { heading, text: translate(`system_notifications.tooltips.disabled_by_you`) }; + } + + if (hasAllFundsChannelDisabled) { + return { heading, text: 'Voor alle fondsen uitgeschakeld.' }; + } + + if (hasAnyFundChannelDisabled) { + return { heading, text: 'Voor een of meer fondsen uitgeschakeld.' }; + } + + return { + heading, + text: translate( + 'system_notifications.tooltips.' + (templateChanged ? 'enabled_edited' : 'enabled_default'), + ), + }; + }, [hasAllFundsChannelDisabled, hasAnyFundChannelDisabled, notification, templateChanged, translate, type]); + + return ( + +
+
{tooltip.heading}
+
{tooltip.text}
+
+
+ ); +} diff --git a/react/src/dashboard/components/pages/implementation-notifications/elements/SystemNotificationChannelIcons.tsx b/react/src/dashboard/components/pages/implementation-notifications/elements/SystemNotificationChannelIcons.tsx new file mode 100644 index 000000000..2208f5735 --- /dev/null +++ b/react/src/dashboard/components/pages/implementation-notifications/elements/SystemNotificationChannelIcons.tsx @@ -0,0 +1,15 @@ +import React from 'react'; +import SystemNotification from '../../../../props/models/SystemNotification'; +import SystemNotificationChannelIcon from './SystemNotificationChannelIcon'; + +export default function SystemNotificationChannelIcons({ notification }: { notification: SystemNotification }) { + const channels: Array<'mail' | 'push' | 'database'> = ['mail', 'push', 'database']; + + return ( +
+ {channels.map((channel) => ( + + ))} +
+ ); +} diff --git a/react/src/dashboard/components/pages/implementation-notifications/elements/SystemNotificationEditor.tsx b/react/src/dashboard/components/pages/implementation-notifications/elements/SystemNotificationEditor.tsx index 0457fa03e..4022c6e43 100644 --- a/react/src/dashboard/components/pages/implementation-notifications/elements/SystemNotificationEditor.tsx +++ b/react/src/dashboard/components/pages/implementation-notifications/elements/SystemNotificationEditor.tsx @@ -1,4 +1,4 @@ -import React, { useCallback, useMemo, useState } from 'react'; +import React, { useCallback, useEffect, useMemo, useState } from 'react'; import classNames from 'classnames'; import ToggleControl from '../../../elements/forms/controls/ToggleControl'; import useImplementationNotificationService from '../../../../services/ImplementationNotificationService'; @@ -14,20 +14,15 @@ import LoadingCard from '../../../elements/loading-card/LoadingCard'; import useTranslate from '../../../../hooks/useTranslate'; import useSetProgress from '../../../../hooks/useSetProgress'; import TableEmptyValue from '../../../elements/table-empty-value/TableEmptyValue'; -import Label from '../../../elements/label/Label'; +import SystemNotificationFundState from '../../../../props/models/SystemNotificationFundState'; +import SystemNotificationStatusLabel from './SystemNotificationStatusLabel'; export default function SystemNotificationEditor({ - fund, - funds, - setFund, notification, organization, implementation, setNotifications, }: { - fund: Partial; - funds?: Array>; - setFund?: React.Dispatch>>; notification: SystemNotification; organization: Organization; implementation: Implementation; @@ -39,12 +34,47 @@ export default function SystemNotificationEditor({ const implementationNotificationsService = useImplementationNotificationService(); + const [fund, setFund] = useState>(null); const [notificationToggleLabels] = useState({ disabled: `Uitgezet, alle kanalen zijn uitgezet.`, enabled_all: 'Aangezet, alle kanalen zijn aangezet.', enabled_partial: 'Aangezet, sommige kanalen staan afzonderlijk uit.', }); + const funds = useMemo>>(() => { + if (!implementation.allow_per_fund_notification_templates) { + return []; + } + + return [ + { id: null, name: 'Alle fondsen' }, + ...(notification.funds || []).map((fundState) => ({ + id: fundState.id, + name: fundState.name, + })), + ]; + }, [implementation.allow_per_fund_notification_templates, notification.funds]); + + const fundState = useMemo(() => { + return notification.funds?.find((fundState) => fundState.id === fund?.id) || null; + }, [fund?.id, notification.funds]); + + const currentNotification = useMemo(() => { + if (!fundState) { + return notification; + } + + return { + ...notification, + enable_all: notification.enable_all && fundState.enable_all, + enable_mail: notification.enable_mail && fundState.enable_mail, + enable_push: notification.enable_push && fundState.enable_push, + enable_database: notification.enable_database && fundState.enable_database, + last_sent_date: fundState.last_sent_date, + last_sent_date_locale: fundState.last_sent_date_locale, + }; + }, [fundState, notification]); + const templates = useMemo(() => { const channels: { mail?: boolean; @@ -89,15 +119,16 @@ export default function SystemNotificationEditor({ notification.templates_default, ]); - const state = useMemo(() => { - return implementationNotificationsService.notificationToStateLabel(notification); - }, [implementationNotificationsService, notification]); + useEffect(() => { + setFund(null); + }, [notification.id]); const toggleSwitched = useCallback(() => { setProgress(0); - const data = { enable_all: !notification.enable_all }; - const hasDisabledChannels = implementationNotificationsService.notificationHasDisabledChannels(notification); + const data = { enable_all: fundState ? !fundState.enable_all : !notification.enable_all }; + const hasDisabledChannels = + implementationNotificationsService.notificationHasDisabledChannels(currentNotification); const message = data.enable_all ? hasDisabledChannels @@ -106,7 +137,10 @@ export default function SystemNotificationEditor({ : notificationToggleLabels.disabled; implementationNotificationsService - .update(organization.id, implementation.id, notification.id, data) + .update(organization.id, implementation.id, notification.id, { + ...data, + ...(fund?.id ? { fund_id: fund.id } : {}), + }) .then((res) => { setNotifications(res.data.data); pushSuccess('Opgeslagen', message); @@ -119,6 +153,9 @@ export default function SystemNotificationEditor({ notification, organization.id, implementation.id, + fund?.id, + fundState, + currentNotification, implementationNotificationsService, notificationToggleLabels.disabled, notificationToggleLabels.enabled_all, @@ -132,36 +169,54 @@ export default function SystemNotificationEditor({ return (
-
+
- {notification.title} {translate(`system_notifications.notifications.${notification.key}.title`)}
- {notification.editable && ( -
-
- -
+
+
+
- )} +
{funds && funds.length > 0 && ( -
+
@@ -184,20 +239,18 @@ export default function SystemNotificationEditor({
)} -
+
Status
- {state?.state === 'active' && } - {state?.state === 'inactive' && } - {state?.state === 'active_partly' && } - - {!['active', 'inactive', 'active_partly'].includes(state?.state) && ( - - )} +
@@ -223,7 +276,7 @@ export default function SystemNotificationEditor({
Laatste datum
- {notification?.last_sent_date_locale || } + {currentNotification?.last_sent_date_locale || }
)} @@ -237,7 +290,9 @@ export default function SystemNotificationEditor({ fund={fund} implementation={implementation} organization={organization} - notification={notification} + notification={currentNotification} + implementationNotification={notification} + fundState={fundState} template={templates.mail} onChange={(data) => setNotifications({ ...notification, ...data })} /> @@ -249,7 +304,9 @@ export default function SystemNotificationEditor({ implementation={implementation} organization={organization} fund={fund} - notification={notification} + notification={currentNotification} + implementationNotification={notification} + fundState={fundState} template={templates.push} onChange={(data) => setNotifications({ ...notification, ...data })} /> @@ -261,7 +318,9 @@ export default function SystemNotificationEditor({ implementation={implementation} organization={organization} fund={fund} - notification={notification} + notification={currentNotification} + implementationNotification={notification} + fundState={fundState} template={templates.database} onChange={(data) => setNotifications({ ...notification, ...data })} /> diff --git a/react/src/dashboard/components/pages/implementation-notifications/elements/SystemNotificationStatusLabel.tsx b/react/src/dashboard/components/pages/implementation-notifications/elements/SystemNotificationStatusLabel.tsx new file mode 100644 index 000000000..2bb7624f3 --- /dev/null +++ b/react/src/dashboard/components/pages/implementation-notifications/elements/SystemNotificationStatusLabel.tsx @@ -0,0 +1,85 @@ +import React, { useMemo } from 'react'; +import Label from '../../../elements/label/Label'; +import useImplementationNotificationService from '../../../../services/ImplementationNotificationService'; +import SystemNotification from '../../../../props/models/SystemNotification'; +import SystemNotificationFundState from '../../../../props/models/SystemNotificationFundState'; + +export default function SystemNotificationStatusLabel({ + notification, + fundState = null, +}: { + notification: SystemNotification; + fundState?: SystemNotificationFundState; +}) { + const implementationNotificationsService = useImplementationNotificationService(); + + const state = useMemo(() => { + const notificationStateLabel = { + inactive: `Inactief`, + active: 'Actief', + active_partly: 'Gedeeltelijk', + }; + + if (fundState) { + const currentNotification = { + ...notification, + enable_all: notification.enable_all && fundState.enable_all, + enable_mail: notification.enable_mail && fundState.enable_mail, + enable_push: notification.enable_push && fundState.enable_push, + enable_database: notification.enable_database && fundState.enable_database, + }; + + const hasDisabledChannels = + implementationNotificationsService.notificationHasDisabledChannels(currentNotification); + const state = currentNotification.enable_all + ? hasDisabledChannels + ? 'active_partly' + : 'active' + : 'inactive'; + + return { state, stateLabel: notificationStateLabel[state] }; + } + + const funds = notification.funds; + const hasDisabledChannels = implementationNotificationsService.notificationHasDisabledChannels(notification); + const hasAnyFundDisabled = Boolean(funds?.some((fund) => !fund.enable_all)); + const hasAllFundsDisabled = Boolean(funds?.length && funds.every((fund) => !fund.enable_all)); + + const hasAnyFundDisabledChannels = notification.channels.some((type) => + Boolean( + funds?.some((fund) => { + const enabled = { + database: fund.enable_database, + mail: fund.enable_mail, + push: fund.enable_push, + }[type]; + + return !fund.enable_all || !enabled; + }), + ), + ); + + const state = + !notification.enable_all || hasAllFundsDisabled + ? 'inactive' + : hasDisabledChannels || hasAnyFundDisabled || hasAnyFundDisabledChannels + ? 'active_partly' + : 'active'; + + return { state, stateLabel: notificationStateLabel[state] }; + }, [fundState, implementationNotificationsService, notification]); + + if (state?.state === 'active') { + return ; + } + + if (state?.state === 'inactive') { + return ; + } + + if (state?.state === 'active_partly') { + return ; + } + + return ; +} diff --git a/react/src/dashboard/components/pages/implementation-notifications/elements/SystemNotificationTemplateEditor.tsx b/react/src/dashboard/components/pages/implementation-notifications/elements/SystemNotificationTemplateEditor.tsx index b86ea175a..c8b927cba 100644 --- a/react/src/dashboard/components/pages/implementation-notifications/elements/SystemNotificationTemplateEditor.tsx +++ b/react/src/dashboard/components/pages/implementation-notifications/elements/SystemNotificationTemplateEditor.tsx @@ -22,6 +22,7 @@ import NotificationTemplate from '../../../../props/models/NotificationTemplate' import { uniqueId } from 'lodash'; import useSetProgress from '../../../../hooks/useSetProgress'; import usePushApiError from '../../../../hooks/usePushApiError'; +import SystemNotificationFundState from '../../../../props/models/SystemNotificationFundState'; type Variables = { [key: string]: string }; @@ -33,10 +34,12 @@ export default function SystemNotificationTemplateEditor({ onChange, template, notification, + implementationNotification, organization, onEditUpdated, implementation, variableValues, + fundState, }: { type: string; fund?: Partial; @@ -46,9 +49,11 @@ export default function SystemNotificationTemplateEditor({ template: NotificationTemplate; organization: Organization; notification: SystemNotification; + implementationNotification?: SystemNotification; implementation: Implementation; onEditUpdated?: (editing: boolean) => void; variableValues?: Variables; + fundState?: SystemNotificationFundState; }) { const translate = useTranslate(); const openModal = useOpenModal(); @@ -66,17 +71,25 @@ export default function SystemNotificationTemplateEditor({ const [contentPreview, setContentPreview] = useState(null); const insertMarkdownTextRef = useRef<(text: string) => void>(null); - const [header] = useState({ - icon: translate(`system_notifications.types.${type}.icon`), - title: translate(`system_notifications.types.${type}.title`), - }); - - const [disabledNotes] = useState({ - enable: `${header.title} staat nu aan.`, - disabled: `${header.title} staat nu uit.`, - }); - - const [variables] = useState(() => { + const header = useMemo(() => { + return { + icon: translate(`system_notifications.types.${type}.icon`), + title: translate(`system_notifications.types.${type}.title`), + }; + }, [translate, type]); + + const disabledNotes = useMemo(() => { + return { + enable: `${header.title} staat nu aan.`, + disabled: `${header.title} staat nu uit.`, + }; + }, [header.title]); + + const implementationChannelEnabled = + implementationNotification?.['enable_' + type] ?? notification['enable_' + type]; + const implementationNotificationEnabled = implementationNotification?.enable_all ?? notification.enable_all; + + const variables = useMemo(() => { return notification.variables.map((variable) => ({ id: variable, key: variablesMap[`:${variable}`], @@ -85,7 +98,7 @@ export default function SystemNotificationTemplateEditor({ ? ['mail'] : ['mail', 'push', 'database'], })); - }); + }, [implementationNotificationsService, notification.variables]); const titleId = useMemo(() => uniqueId('template_title_'), []); const descriptionId = useMemo(() => uniqueId('template_description_'), []); @@ -141,7 +154,10 @@ export default function SystemNotificationTemplateEditor({ const shouldReset = isSameTitle && isSameContent; data = { - ...(shouldReset ? { templates_remove: [{ formal, type: type }] } : { templates: [newTemplate] }), + ...(fund?.id ? { fund_id: fund.id } : {}), + ...(shouldReset + ? { templates_remove: [{ formal, type: type, fund_id: fund?.id }] } + : { templates: [newTemplate] }), }; } @@ -179,9 +195,10 @@ export default function SystemNotificationTemplateEditor({ } setProgress(0); + const requestData = fund?.id ? { fund_id: fund.id, ...data } : data; implementationNotificationsService - .update(organization.id, implementation.id, notification.id, data) + .update(organization.id, implementation.id, notification.id, requestData) .then((res) => { setFormErrors(null); onChange(res.data.data); @@ -215,6 +232,7 @@ export default function SystemNotificationTemplateEditor({ organization.id, notification.id, implementation.id, + fund?.id, cancelTemplateEdit, implementationNotificationsService, ], @@ -298,7 +316,10 @@ export default function SystemNotificationTemplateEditor({ const data = { ['enable_' + type]: enable }; implementationNotificationsService - .update(organization.id, implementation.id, notification.id, data) + .update(organization.id, implementation.id, notification.id, { + ...data, + ...(fund?.id ? { fund_id: fund.id } : {}), + }) .then((res) => { onChange(res.data.data); pushSuccess('Opgeslagen', `${header.title} is nu ${enable ? 'ingeschakeld.' : 'uitgeschakeld.'}`); @@ -312,6 +333,7 @@ export default function SystemNotificationTemplateEditor({ header.title, organization.id, implementation.id, + fund?.id, implementationNotificationsService, ], ); @@ -339,6 +361,10 @@ export default function SystemNotificationTemplateEditor({ updateTemplatePreview(template); }, [template, updateTemplatePreview, variableValues]); + useEffect(() => { + setEnable(notification['enable_' + type]); + }, [notification, type]); + if (!template) { return ; } @@ -375,7 +401,10 @@ export default function SystemNotificationTemplateEditor({
) : (
+ className={classNames( + 'card-header', + notification.optional && !(enable && notification.enable_all) && 'card-header-danger', + )}>
{header.title} @@ -383,23 +412,39 @@ export default function SystemNotificationTemplateEditor({ {fund && ({fund.name})}
- {notification.editable && !edit && ( + {!edit && (
{ - if (notification.enable_all) { + if ( + notification.editable && + notification.optional && + implementationNotificationEnabled && + !(fundState && !implementationChannelEnabled) + ) { setEnable(!enable); - toggleSwitched(!enable); + toggleSwitched(fundState ? !fundState['enable_' + type] : !enable); } }} /> @@ -432,7 +477,7 @@ export default function SystemNotificationTemplateEditor({
{!compose && notification.editable && !edit && ( diff --git a/react/src/dashboard/i18n/nl/pages/implementation-notifications.js b/react/src/dashboard/i18n/nl/pages/implementation-notifications.js index f8b0a9c60..14fbcb0fa 100644 --- a/react/src/dashboard/i18n/nl/pages/implementation-notifications.js +++ b/react/src/dashboard/i18n/nl/pages/implementation-notifications.js @@ -1,11 +1,14 @@ export default { labels: { description: 'Omschrijving', + required: 'Staat vast', channels: 'Kanalen', status: 'Status', }, tooltips: { description: 'Beschrijving van het systeembericht.', + required: + 'Geeft aan of de mail individueel per regeling uit te zetten is. Ja betekent dat het systeembericht vaststaat en niet individueel per regeling uit te zetten is. Staat er Nee, dan kan het systeembericht per regeling worden uitgezet.', channels: 'Beschikbare verzendkanalen (e-mail, push, web).', status: 'Actieve of inactieve status van het bericht.', }, diff --git a/react/src/dashboard/props/models/SystemNotification.tsx b/react/src/dashboard/props/models/SystemNotification.tsx index d1adcecf3..73bc11ff0 100644 --- a/react/src/dashboard/props/models/SystemNotification.tsx +++ b/react/src/dashboard/props/models/SystemNotification.tsx @@ -1,4 +1,5 @@ import NotificationTemplate from './NotificationTemplate'; +import SystemNotificationFundState from './SystemNotificationFundState'; export default interface SystemNotification { id?: number; @@ -16,6 +17,7 @@ export default interface SystemNotification { channels?: Array<'database' | 'mail' | 'push'>; last_sent_date?: string; last_sent_date_locale?: string; + funds?: Array | null; templates?: Array; templates_default?: Array; } diff --git a/react/src/dashboard/props/models/SystemNotificationFundState.tsx b/react/src/dashboard/props/models/SystemNotificationFundState.tsx new file mode 100644 index 000000000..1422d2a4e --- /dev/null +++ b/react/src/dashboard/props/models/SystemNotificationFundState.tsx @@ -0,0 +1,10 @@ +export default interface SystemNotificationFundState { + id?: number; + name?: string; + enable_all?: boolean; + enable_mail?: boolean; + enable_push?: boolean; + enable_database?: boolean; + last_sent_date?: string; + last_sent_date_locale?: string; +} diff --git a/react/src/dashboard/services/ImplementationNotificationService.tsx b/react/src/dashboard/services/ImplementationNotificationService.tsx index c1fd6fa05..ee10f6a03 100644 --- a/react/src/dashboard/services/ImplementationNotificationService.tsx +++ b/react/src/dashboard/services/ImplementationNotificationService.tsx @@ -180,22 +180,8 @@ export class ImplementationNotificationService { }); } - public notificationToStateLabel(notification: SystemNotification) { - const notificationStateLabel = { - inactive: `Inactief`, - active: 'Actief', - active_partly: 'Gedeeltelijk', - }; - const hasDisabledChannels = this.notificationHasDisabledChannels(notification); - - const state = notification.enable_all ? (hasDisabledChannels ? 'active_partly' : 'active') : 'inactive'; - const stateLabel = notificationStateLabel[state]; - - return { state, stateLabel }; - } - public getColumns(): Array { - const list = ['description', 'channels', 'status'].filter((item) => item); + const list = ['description', 'required', 'channels', 'status'].filter((item) => item); return list.map((key) => ({ key,