diff options
author | Mathieu Suen <mathieu.suen@sonarsource.com> | 2023-06-20 16:58:04 +0200 |
---|---|---|
committer | sonartech <sonartech@sonarsource.com> | 2023-06-26 20:03:55 +0000 |
commit | 4602389376d469331c77fdd9fe443cf6acd87fa7 (patch) | |
tree | 320437390372102d796da395336e0b3679c80bb3 /server | |
parent | 6a8eba1b0a016b92f5b57d294c33d0c4b18f0367 (diff) | |
download | sonarqube-4602389376d469331c77fdd9fe443cf6acd87fa7.tar.gz sonarqube-4602389376d469331c77fdd9fe443cf6acd87fa7.zip |
SONAR-19613 Migrate project notification to new UI
Diffstat (limited to 'server')
3 files changed, 62 insertions, 53 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<HTMLHeadingElement>(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 ( - <div> - <h3 tabIndex={-1} ref={heading}> - {translate('project.info.notifications')} - </h3> + <form aria-labelledby="notifications-update-title"> + <SubTitle>{translate('project.info.notifications')}</SubTitle> - <Alert className="spacer-top" variant="info"> + <FlagMessage className="spacer-top" variant="info"> {translate('notification.dispatcher.information')} - </Alert> + </FlagMessage> <DeferredSpinner loading={loading}> - <table className="data zebra notifications-table"> - <thead> - <tr> - <th aria-label={translate('project')} /> - {channels.map((channel) => ( - <th className="text-center" key={channel}> - <h4>{translate('notification.channel', channel)}</h4> - </th> - ))} - </tr> - </thead> - - <NotificationsList - channels={channels} - checkboxId={getCheckboxId} - notifications={projectNotifications} - onAdd={handleAddNotification} - onRemove={handleRemoveNotification} - project - types={perProjectTypes} - /> - </table> + <h3 id="notifications-update-title" className="sw-mt-6"> + {translate('project_information.project_notifications.title')} + </h3> + <ul className="sw-list-none sw-mt-4 sw-pl-0"> + {perProjectTypes.map((type) => ( + <li className="sw-pl-0 sw-p-2" key={type}> + <Checkbox + right + className="sw-flex sw-justify-between" + label={translateWithParameters( + 'notification.dispatcher.descrption_x', + getDispatcherLabel(type) + )} + checked={isEnabled(type, emailChannel)} + id={getCheckboxId(type, emailChannel)} + onCheck={(checked: boolean) => handleCheck(type, emailChannel, checked)} + > + {getDispatcherLabel(type)} + </Checkbox> + </li> + ))} + </ul> </DeferredSpinner> - </div> + </form> ); } 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' |