From 448d442a0ba05bc26d413ccfb5f4ef0581a7b355 Mon Sep 17 00:00:00 2001 From: Ashish Dhama <16203333+AshishDhama@users.noreply.github.com> Date: Tue, 14 Nov 2023 00:50:35 +0530 Subject: [PATCH] [MM-40384]: Channel notification settings modal UX revamp (#24984) * Move notification preferences modal to new UI * fix lint issue * fix i18n * fix unit test * fix type issue and lint errors * fix test case * move common components to widget modals dir * fix css issue * feedback changes * fix lint and i18n issues * more feedback changes * fix issue with mobile notification ui * fix test * clean up * remove name * fix test --------- Co-authored-by: Mattermost Build --- .../channels/channel/channel_info_rhs_spec.js | 4 +- .../channel_notifications_spec.js | 101 +- .../desktop_notifications_2_spec.js | 6 +- .../ignore_channel_mentions_spec.js | 21 +- .../channels/src/components/alert_banner.tsx | 7 +- .../channel_notifications_modal.test.tsx.snap | 2697 +++++++++++++++-- .../channel_notifications_modal.scss | 139 + .../channel_notifications_modal.test.tsx | 484 +-- .../channel_notifications_modal.tsx | 816 ++--- .../__snapshots__/collapse_view.test.tsx.snap | 61 - .../__snapshots__/describe.test.tsx.snap | 59 - .../__snapshots__/expand_view.test.tsx.snap | 942 ------ .../__snapshots__/extra_info.test.tsx.snap | 28 - .../notification_section.test.jsx.snap | 91 - .../__snapshots__/section_title.test.tsx.snap | 30 - .../components/collapse_view.test.tsx | 44 - .../components/collapse_view.tsx | 38 - .../components/describe.test.tsx | 61 - .../components/describe.tsx | 139 - .../components/expand_view.test.tsx | 96 - .../components/expand_view.tsx | 437 --- .../components/extra_info.test.tsx | 41 - .../components/extra_info.tsx | 64 - .../components/notification_section.jsx | 182 -- .../components/notification_section.test.jsx | 121 - .../components/section_title.scss | 15 - .../components/section_title.test.tsx | 41 - .../components/section_title.tsx | 71 - .../channel_notifications_modal/index.ts | 4 + .../channel_notifications_modal/utils.tsx | 276 ++ .../modals/components/base_setting_item.scss | 152 + .../modals/components/base_setting_item.tsx | 45 + .../components/checkbox_setting_item.tsx | 60 + .../modals/components/modal_header.scss | 84 + .../modals/components/modal_header.tsx | 42 + .../modals/components/modal_section.scss | 50 + .../modals/components/modal_section.tsx | 59 + .../modals/components/modal_sidebar.scss | 35 + .../modals/components/modal_sidebar.tsx | 60 + .../modals/components/radio_setting_item.tsx | 72 + .../modals/components/react_select_item.tsx | 65 + .../modals/components/save_changes_panel.scss | 68 + .../modals/components/save_changes_panel.tsx | 50 + webapp/channels/src/i18n/en.json | 65 +- .../mattermost-redux/test/test_helper.ts | 8 +- webapp/platform/types/src/channels.ts | 2 + 46 files changed, 4274 insertions(+), 3759 deletions(-) create mode 100644 webapp/channels/src/components/channel_notifications_modal/channel_notifications_modal.scss delete mode 100644 webapp/channels/src/components/channel_notifications_modal/components/__snapshots__/collapse_view.test.tsx.snap delete mode 100644 webapp/channels/src/components/channel_notifications_modal/components/__snapshots__/describe.test.tsx.snap delete mode 100644 webapp/channels/src/components/channel_notifications_modal/components/__snapshots__/expand_view.test.tsx.snap delete mode 100644 webapp/channels/src/components/channel_notifications_modal/components/__snapshots__/extra_info.test.tsx.snap delete mode 100644 webapp/channels/src/components/channel_notifications_modal/components/__snapshots__/notification_section.test.jsx.snap delete mode 100644 webapp/channels/src/components/channel_notifications_modal/components/__snapshots__/section_title.test.tsx.snap delete mode 100644 webapp/channels/src/components/channel_notifications_modal/components/collapse_view.test.tsx delete mode 100644 webapp/channels/src/components/channel_notifications_modal/components/collapse_view.tsx delete mode 100644 webapp/channels/src/components/channel_notifications_modal/components/describe.test.tsx delete mode 100644 webapp/channels/src/components/channel_notifications_modal/components/describe.tsx delete mode 100644 webapp/channels/src/components/channel_notifications_modal/components/expand_view.test.tsx delete mode 100644 webapp/channels/src/components/channel_notifications_modal/components/expand_view.tsx delete mode 100644 webapp/channels/src/components/channel_notifications_modal/components/extra_info.test.tsx delete mode 100644 webapp/channels/src/components/channel_notifications_modal/components/extra_info.tsx delete mode 100644 webapp/channels/src/components/channel_notifications_modal/components/notification_section.jsx delete mode 100644 webapp/channels/src/components/channel_notifications_modal/components/notification_section.test.jsx delete mode 100644 webapp/channels/src/components/channel_notifications_modal/components/section_title.scss delete mode 100644 webapp/channels/src/components/channel_notifications_modal/components/section_title.test.tsx delete mode 100644 webapp/channels/src/components/channel_notifications_modal/components/section_title.tsx create mode 100644 webapp/channels/src/components/channel_notifications_modal/utils.tsx create mode 100644 webapp/channels/src/components/widgets/modals/components/base_setting_item.scss create mode 100644 webapp/channels/src/components/widgets/modals/components/base_setting_item.tsx create mode 100644 webapp/channels/src/components/widgets/modals/components/checkbox_setting_item.tsx create mode 100644 webapp/channels/src/components/widgets/modals/components/modal_header.scss create mode 100644 webapp/channels/src/components/widgets/modals/components/modal_header.tsx create mode 100644 webapp/channels/src/components/widgets/modals/components/modal_section.scss create mode 100644 webapp/channels/src/components/widgets/modals/components/modal_section.tsx create mode 100644 webapp/channels/src/components/widgets/modals/components/modal_sidebar.scss create mode 100644 webapp/channels/src/components/widgets/modals/components/modal_sidebar.tsx create mode 100644 webapp/channels/src/components/widgets/modals/components/radio_setting_item.tsx create mode 100644 webapp/channels/src/components/widgets/modals/components/react_select_item.tsx create mode 100644 webapp/channels/src/components/widgets/modals/components/save_changes_panel.scss create mode 100644 webapp/channels/src/components/widgets/modals/components/save_changes_panel.tsx diff --git a/e2e-tests/cypress/tests/integration/channels/channel/channel_info_rhs_spec.js b/e2e-tests/cypress/tests/integration/channels/channel/channel_info_rhs_spec.js index c95695a866..f7da2c6c78 100644 --- a/e2e-tests/cypress/tests/integration/channels/channel/channel_info_rhs_spec.js +++ b/e2e-tests/cypress/tests/integration/channels/channel/channel_info_rhs_spec.js @@ -211,7 +211,7 @@ describe('Channel Info RHS', () => { cy.uiGetRHS().findByText('Notification Preferences').should('be.visible').click(); // * Ensures the modal is there - cy.get('.settings-modal').should('be.visible'); + cy.get('.channel-notifications-settings-modal').should('be.visible'); }); it('should be able to view files and come back', () => { // # Go to test channel @@ -373,7 +373,7 @@ describe('Channel Info RHS', () => { cy.uiGetRHS().findByText('Notification Preferences').should('be.visible').click(); // * Ensures the modal is there - cy.get('.settings-modal').should('be.visible'); + cy.get('.channel-notifications-settings-modal').should('be.visible'); }); }); }); diff --git a/e2e-tests/cypress/tests/integration/channels/collapsed_reply_threads/channel_notifications_spec.js b/e2e-tests/cypress/tests/integration/channels/collapsed_reply_threads/channel_notifications_spec.js index b54a9d8121..c34cb4022d 100644 --- a/e2e-tests/cypress/tests/integration/channels/collapsed_reply_threads/channel_notifications_spec.js +++ b/e2e-tests/cypress/tests/integration/channels/collapsed_reply_threads/channel_notifications_spec.js @@ -52,11 +52,46 @@ describe('CRT Desktop notifications', () => { // # Visit channel cy.visit(testChannelUrl); + cy.uiOpenChannelMenu('Notification Preferences'); + cy.get('[data-testid="muteChannel"]').click().then(() => { + cy.get('.AlertBanner--app').should('be.visible'); + }); + cy.get('.channel-notifications-settings-modal__save-btn').should('be.visible').click(); + // Setup notification spy spyNotificationAs('notifySpy', 'granted'); // # Set users notification settings - setCRTDesktopNotification('ALL'); + cy.uiOpenChannelMenu('Notification Preferences'); + + // # click on Mute Channel to Unmute Channel + cy.get('[data-testid="muteChannel"]').click(); + + // # Click "Desktop Notifications" + cy.findByText('Desktop Notifications').should('be.visible'); + + cy.get('.channel-notifications-settings-modal__body').scrollTo('center').get('#desktopNotification-all').should('be.visible').click(); + cy.get('.channel-notifications-settings-modal__body').get('#desktopNotification-all').should('be.checked'); + + cy.get('#desktopNotification-mention').should('be.visible').click().then(() => { + cy.get('[data-testid="desktopReplyThreads"]').should('be.checked'); + cy.get('[data-testid="desktopReplyThreads"]').should('be.visible').click(); + cy.get('[data-testid="desktopReplyThreads"]').should('not.be.checked'); + }); + cy.get('.channel-notifications-settings-modal__body').scrollTo('center').get('#desktopNotification-mention').should('be.checked'); + + cy.get('.channel-notifications-settings-modal__body').scrollTo('center').get('#desktopNotification-none').should('be.visible').click(); + cy.get('.channel-notifications-settings-modal__body').get('#desktopNotification-none').should('be.checked'); + + // # click on Save button + cy.get('.channel-notifications-settings-modal__save-btn').should('be.visible').click(); + + // # Set users notification settings + cy.uiOpenChannelMenu('Notification Preferences'); + cy.get('.channel-notifications-settings-modal__body').scrollTo('center').get('#desktopNotification-none').should('be.checked'); + cy.get('.channel-notifications-settings-modal__body').get('#desktopNotification-all').scrollIntoView().should('be.visible').click(); + + cy.get('.channel-notifications-settings-modal__save-btn').should('be.visible').click(); // # Post a root message as other user cy.postMessageAs({sender, message: 'This is a not followed root message', channelId: testChannelId, rootId: ''}).then(({id: postId}) => { @@ -99,14 +134,41 @@ describe('CRT Desktop notifications', () => { }); }); - it('MM-T4417_2 Trigger notifications only on mention replies when channel setting is unchecked', () => { + it('MM-T4417_2 Click on sameMobileSettingsDesktop and check if additional settings still appears', () => { + cy.visit(testChannelUrl); + cy.uiOpenChannelMenu('Notification Preferences'); + cy.get('.channel-notifications-settings-modal__body').scrollTo('center').get('#desktopNotification-mention').should('be.visible').click().then(() => { + cy.get('[data-testid="desktopReplyThreads"]').should('be.visible').click(); + }); + cy.get('.channel-notifications-settings-modal__body').scrollTo('center').get('[data-testid="desktopReplyThreads"]').should('be.visible').click(); + cy.get('.channel-notifications-settings-modal__body').get('[data-testid="sameMobileSettingsDesktop"]').scrollIntoView().click().should('be.checked').then(() => { + cy.findByText('Notify me about…').should('not.be.visible'); + }); + + // check the box to see if the additional settings appears + cy.get('.channel-notifications-settings-modal__body').get('[data-testid="sameMobileSettingsDesktop"]').scrollIntoView().click(); + cy.get('.mm-modal-generic-section-item__title').should('be.visible').and('contain', 'Notify me about'); + + cy.get('#MobileNotification-all').should('be.visible').click(); + cy.get('#MobileNotification-mention').should('be.visible').click().then(() => { + cy.get('[data-testid="mobileReplyThreads"]').should('be.visible').click(); + }); + cy.get('#MobileNotification-none').should('be.visible').click(); + + cy.get('[data-testid="autoFollowThreads"]').should('be.visible').click(); + + // # click on Save button + cy.get('.channel-notifications-settings-modal__save-btn').should('be.visible').click(); + }); + + it('MM-T4417_3 Trigger notifications only on mention replies when channel setting is unchecked', () => { cy.visit(testChannelUrl); // Setup notification spy spyNotificationAs('notifySpy', 'granted'); - - // # Set users notification settings - setCRTDesktopNotification('MENTION'); + cy.uiOpenChannelMenu('Notification Preferences'); + cy.get('.channel-notifications-settings-modal__body').scrollTo('center').get('#desktopNotification-mention').should('be.visible').click(); + cy.get('.channel-notifications-settings-modal__save-btn').should('be.visible').click(); // # Post a root message as other user cy.postMessageAs({sender, message: 'This is a not followed root message', channelId: testChannelId, rootId: ''}).then(({id: postId}) => { @@ -232,32 +294,3 @@ describe('CRT Desktop notifications', () => { }); }); }); - -function setCRTDesktopNotification(type) { - if (['ALL', 'MENTION'].indexOf(type) === -1) { - throw new Error(`${type} is invalid`); - } - - // # Open settings modal - cy.uiOpenChannelMenu('Notification Preferences'); - - // # Click "Desktop Notifications" - cy.get('#desktopTitle'). - scrollIntoView(). - should('be.visible'). - and('contain', 'Desktop notifications').click(); - - // # Select mentions category for messages. - cy.get('#channelNotificationMentions').scrollIntoView().check(); - - if (type === 'ALL') { - // # Check notify for all replies. - cy.get('#desktopThreadsNotificationAllActivity').scrollIntoView().check().should('be.checked'); - } else if (type === 'MENTION') { - // # Check notify only for mentions. - cy.get('#desktopThreadsNotificationAllActivity').scrollIntoView().uncheck().should('not.be.checked'); - } - - // # Click "Save" and close the modal - cy.uiSaveAndClose(); -} diff --git a/e2e-tests/cypress/tests/integration/channels/notifications/desktop_notifications_2_spec.js b/e2e-tests/cypress/tests/integration/channels/notifications/desktop_notifications_2_spec.js index a4986b7ad0..12d9e3a4d3 100644 --- a/e2e-tests/cypress/tests/integration/channels/notifications/desktop_notifications_2_spec.js +++ b/e2e-tests/cypress/tests/integration/channels/notifications/desktop_notifications_2_spec.js @@ -53,9 +53,9 @@ describe('Desktop notifications', () => { // # Set channel notifications to show on mention only cy.uiOpenChannelMenu('Notification Preferences'); - cy.findByText('Desktop notifications').click(); - cy.findByRole('radio', {name: 'Only for mentions'}).click(); - cy.uiSaveAndClose(); + cy.findByText('Desktop Notifications').should('be.visible'); + cy.findByRole('radio', {name: 'Mentions, direct messages, and keywords only'}).click().should('be.checked'); + cy.uiSave(); // # Visit off-topic cy.uiClickSidebarItem('off-topic'); diff --git a/e2e-tests/cypress/tests/integration/channels/notifications/ignore_channel_mentions_spec.js b/e2e-tests/cypress/tests/integration/channels/notifications/ignore_channel_mentions_spec.js index 22c60ee93d..11395b4528 100644 --- a/e2e-tests/cypress/tests/integration/channels/notifications/ignore_channel_mentions_spec.js +++ b/e2e-tests/cypress/tests/integration/channels/notifications/ignore_channel_mentions_spec.js @@ -109,26 +109,15 @@ function addNumberOfUsersToChannel(num = 1) { } function setIgnoreMentions(toSet) { - let stringToSet = 'Off'; - if (toSet) { - stringToSet = 'On'; - } - // # Open channel menu and click Notification Preferences cy.uiOpenChannelMenu('Notification Preferences'); - // # Click on the edit button for ignore channel mentions - cy.get('#ignoreChannelMentionsEdit').should('exist').click(); + // # find mute or ignore section + cy.findByText('Mute or ignore').should('be.visible'); - // # Click on selected option - cy.get(`#ignoreChannelMentions${stringToSet}`).should('exist').click(); + // # find Ignore mentions checkbox, set value accordingly + cy.findByRole('checkbox', {name: 'Ignore mentions for @channel, @here and @all'}).click().should(toSet ? 'be.checked' : 'not.be.checked'); // # Click on save to save the configuration - cy.get('#saveSetting').should('exist').click(); - - // * Assert that the option selected is reflected - cy.get('#ignoreChannelMentionsDesc').should('contain', stringToSet); - - // # Click on the X button to close the modal - cy.get('#channelNotificationModalLabel').siblings('.close').click(); + cy.uiSave(); } diff --git a/webapp/channels/src/components/alert_banner.tsx b/webapp/channels/src/components/alert_banner.tsx index 3e2dde3827..82a0e47483 100644 --- a/webapp/channels/src/components/alert_banner.tsx +++ b/webapp/channels/src/components/alert_banner.tsx @@ -25,6 +25,7 @@ export type AlertBannerProps = { id?: string; mode: ModeType; title?: React.ReactNode; + customIcon?: React.ReactNode; message?: React.ReactNode; children?: React.ReactNode; className?: string; @@ -41,6 +42,7 @@ const AlertBanner = ({ id, mode, title, + customIcon, message, className, variant = 'sys', @@ -57,6 +59,9 @@ const AlertBanner = ({ const [tooltipId] = useState(`alert_banner_close_btn_tooltip_${Math.random()}`); const bannerIcon = useCallback(() => { + if (customIcon) { + return customIcon; + } if (mode === 'danger' || mode === 'warning') { return ( ); - }, [mode]); + }, [mode, customIcon]); return (
- - - - - channel_display_name - - - -