From 4602389376d469331c77fdd9fe443cf6acd87fa7 Mon Sep 17 00:00:00 2001 From: Mathieu Suen Date: Tue, 20 Jun 2023 16:58:04 +0200 Subject: [PATCH] SONAR-19613 Migrate project notification to new UI --- .../design-system/src/components/Checkbox.tsx | 1 + .../notifications/ProjectNotifications.tsx | 110 +++++++++--------- .../__tests__/ProjectNotifications-test.tsx | 4 +- .../resources/org/sonar/l10n/core.properties | 9 +- 4 files changed, 70 insertions(+), 54 deletions(-) diff --git a/server/sonar-web/design-system/src/components/Checkbox.tsx b/server/sonar-web/design-system/src/components/Checkbox.tsx index 6b4a77a3c98..238a52cba6e 100644 --- a/server/sonar-web/design-system/src/components/Checkbox.tsx +++ b/server/sonar-web/design-system/src/components/Checkbox.tsx @@ -140,6 +140,7 @@ export const AccessibleCheckbox = styled.input` padding: 0; white-space: nowrap; width: 1px; + appearance: none; &:focus, &:active { diff --git a/server/sonar-web/src/main/js/apps/projectInformation/notifications/ProjectNotifications.tsx b/server/sonar-web/src/main/js/apps/projectInformation/notifications/ProjectNotifications.tsx index d0ddd4fd9fc..760cc32b7d2 100644 --- a/server/sonar-web/src/main/js/apps/projectInformation/notifications/ProjectNotifications.tsx +++ b/server/sonar-web/src/main/js/apps/projectInformation/notifications/ProjectNotifications.tsx @@ -17,16 +17,16 @@ * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ +import { Checkbox, FlagMessage, SubTitle } from 'design-system'; import * as React from 'react'; import { - withNotifications, WithNotificationsProps, + withNotifications, } from '../../../components/hoc/withNotifications'; -import { Alert } from '../../../components/ui/Alert'; import DeferredSpinner from '../../../components/ui/DeferredSpinner'; -import { translate } from '../../../helpers/l10n'; +import { hasMessage, translate, translateWithParameters } from '../../../helpers/l10n'; +import { NotificationProjectType } from '../../../types/notifications'; import { Component } from '../../../types/types'; -import NotificationsList from '../../account/notifications/NotificationsList'; interface Props { component: Component; @@ -34,70 +34,76 @@ interface Props { export function ProjectNotifications(props: WithNotificationsProps & Props) { const { channels, component, loading, notifications, perProjectTypes } = props; - const heading = React.useRef(null); - React.useEffect(() => { - if (heading.current) { - // a11y: provide focus to the heading when the info drawer page is opened. - heading.current.focus(); + const handleCheck = (type: NotificationProjectType, channel: string, checked: boolean) => { + if (checked) { + props.addNotification({ project: component.key, channel, type }); + } else { + props.removeNotification({ + project: component.key, + channel, + type, + }); } - }, [heading]); + }; - const handleAddNotification = ({ channel, type }: { channel: string; type: string }) => { - props.addNotification({ project: component.key, channel, type }); + const getCheckboxId = (type: string, channel: string) => { + return `project-notification-${component.key}-${type}-${channel}`; }; - const handleRemoveNotification = ({ channel, type }: { channel: string; type: string }) => { - props.removeNotification({ - project: component.key, - channel, - type, - }); + const getDispatcherLabel = (dispatcher: string) => { + const globalMessageKey = ['notification.dispatcher', dispatcher]; + const projectMessageKey = [...globalMessageKey, 'project']; + const shouldUseProjectMessage = hasMessage(...projectMessageKey); + return shouldUseProjectMessage + ? translate(...projectMessageKey) + : translate(...globalMessageKey); }; - const getCheckboxId = (type: string, channel: string) => { - return `project-notification-${component.key}-${type}-${channel}`; + const isEnabled = (type: string, channel: string) => { + return !!notifications.find( + (notification) => + notification.type === type && + notification.channel === channel && + notification.project === component.key + ); }; - const projectNotifications = notifications.filter( - (n) => n.project && n.project === component.key - ); + const emailChannel = channels[0]; return ( -
-

- {translate('project.info.notifications')} -

+
+ {translate('project.info.notifications')} - + {translate('notification.dispatcher.information')} - + - - - - - ))} - - - - -
- {channels.map((channel) => ( - -

{translate('notification.channel', channel)}

-
+

+ {translate('project_information.project_notifications.title')} +

+
    + {perProjectTypes.map((type) => ( +
  • + handleCheck(type, emailChannel, checked)} + > + {getDispatcherLabel(type)} + +
  • + ))} +
-
+ ); } diff --git a/server/sonar-web/src/main/js/apps/projectInformation/notifications/__tests__/ProjectNotifications-test.tsx b/server/sonar-web/src/main/js/apps/projectInformation/notifications/__tests__/ProjectNotifications-test.tsx index e7d187c574f..73cd0028e2c 100644 --- a/server/sonar-web/src/main/js/apps/projectInformation/notifications/__tests__/ProjectNotifications-test.tsx +++ b/server/sonar-web/src/main/js/apps/projectInformation/notifications/__tests__/ProjectNotifications-test.tsx @@ -49,7 +49,9 @@ it('should render correctly', async () => { const user = userEvent.setup(); renderProjectNotifications(); - expect(await screen.findByText('notification.channel.channel1')).toBeInTheDocument(); + expect( + await screen.findByText('project_information.project_notifications.title') + ).toBeInTheDocument(); expect( screen.getByLabelText( 'notification.dispatcher.descrption_x.notification.dispatcher.NewAlerts.project' diff --git a/sonar-core/src/main/resources/org/sonar/l10n/core.properties b/sonar-core/src/main/resources/org/sonar/l10n/core.properties index 99d7d002a8a..76613b49e15 100644 --- a/sonar-core/src/main/resources/org/sonar/l10n/core.properties +++ b/sonar-core/src/main/resources/org/sonar/l10n/core.properties @@ -1828,7 +1828,7 @@ application.info.title=Application Information project.info.description=Description project.info.quality_gate=Quality Gate used project.info.to_notifications=Set notifications -project.info.notifications=Set notifications +project.info.notifications=Notifications project.info.main_branch=Main branch project.info.see_more_info_on_x_locs=See more information on your {0} lines of code @@ -3416,6 +3416,13 @@ project_dump.failed_import=The last import has failed. Please try once again. project_dump.import_form_description=A dump has been found on the file system for this project. You can import it by clicking on the button below. project_dump.import_form_description_disabled=Projects cannot be imported. This feature is only available starting from Enterprise Edition. +#------------------------------------------------------------------------------ +# +# Project Information +# +#------------------------------------------------------------------------------ +project_information.project_notifications.title=Send me an email when: + #------------------------------------------------------------------------------ # # SYSTEM -- 2.39.5