From bff19228e1e572b44eff2e449a4246752ec0f476 Mon Sep 17 00:00:00 2001 From: "Sinan Sonmez (Chaush)" <37421564+sinansonmez@users.noreply.github.com> Date: Tue, 20 Feb 2024 23:46:35 +0100 Subject: [PATCH] MM-41586: Team setting modal UI update (#25729) * add new sections * remove section related code * add some todos * convert team setting to functional component * remove unused props from main_menu * remove unused collapseModal * create 2 sections files * clean info section * cleanup access tab * further clean team info setting component * fix input fields * fix description input field * reorganize files * add team icon when there is no team image * improve layout * fix autofocus * delete empty file * add note related to learna bout teams link * add edit icon * add upload functionality * finish image upload * implement logic for handle save * add remove icon button * fix remove button color * fix styling on image remove and upload * fix image remove feature * show remove image button dynamically * fix height * update haveImageChanges on handleTeamIconRemove cl * fix spacing inside input * fix cursor point * access tab basis * add some todo * add baseline for client error * handle desc and image client errors * move folders * rename section to tab * move the name section to new file * dedicated description component * dedicated image section * convert to functional component * remove unnecessary fetchTeam * remove havechanges state * remove not needed folder * rename from section to tab * convert access tab to FC * fix invite section input * finalize team invite code section * add checkbox * add select_text_input * finish allowed domains * fix save changes panel style * convert open_invite * add logic for show save changes panel globally * handle server errors * combine client errors * fix save changes issue * clean colors used in css * fix style * fix type issues * fix another type * fix allowed domains * fix type error * add save changes panel to access tab * add success state to save changes panel * remove unused prop * cleanup css * fix save changes modal position * fix title font size * remove not used prop * fix mobile view width * fix mobile view * add group constraint text * handle invite code error * update snapshots * fix input height * fix tests * write tests for open_invite * write tests for team_info_tab * write tests for team_access_tab * Refactor setTeamIcon test in teams.test.ts * Refactor team access and team info tabs for save changes panel * Add useEffect hook to set inviteId in AccessTab component * fix lint * fix lint * fix i18 * remove old todo * fix text * fix css * fix css * fix padding * fix mobile view * update snapshot * performance improvements * fix type * improve translation passing to components * fix lint * rename saving to editing * fix empty allowed domains * complete renaming of saving * seperate AllowedDomainsSelect * seperate InviteSectionInput * fix i18n * capitalize translation id * final fix for i18n * remove empty file * fix lint and test * fix rgb values * remove action related types from index file * add last_team_icon_update to Team type * fix unnecessary null check operator * fix more types * add new features for text selector * update text for select text input * fix style issues on save changes * fix lint check * add animation for save changes panel * remove unused type * fix test * fix theming issues * fix MM-T385 * fix MM-T388 * fix MM-T387 and MM-T2341 * fix MM-T391 * Fix MM-T2318, MM-T2317, MM-T2312, MM-T2322, MM-T2335 * fix top padding --------- Co-authored-by: Mattermost Build --- .../closed_team_invite_by_email_spec.js | 11 +- .../invite_user_to_closed_team_spec.js | 12 +- ...closed_team_with_not_allowed_email_spec.js | 44 +- .../team_settings/remove_team_icon_spec.js | 60 +- .../channels/team_settings/teams_spec.js | 46 +- .../channel_name_form_field.tsx | 2 +- .../channel_notifications_modal.test.tsx.snap | 82 +- .../select_text_input/select_text_input.scss | 9 + .../select_text_input/select_text_input.tsx | 126 ++++ .../src/components/main_menu/index.tsx | 5 +- .../components/main_menu/main_menu.test.tsx | 5 - .../src/components/main_menu/main_menu.tsx | 5 - .../components/payment_form/address_form.tsx | 2 +- .../components/payment_form/payment_form.tsx | 2 +- .../channels/src/components/signup/signup.tsx | 2 +- .../__snapshots__/open_invite.test.tsx.snap | 129 ---- .../team_general_tab.test.tsx.snap | 361 --------- .../team_general_tab/open_invite.test.tsx | 60 -- .../team_general_tab/open_invite.tsx | 160 ---- .../team_general_tab/team_general_tab.scss | 17 - .../team_general_tab.test.tsx | 213 ------ .../team_general_tab/team_general_tab.tsx | 702 ------------------ .../allowed_domains_select.tsx | 83 +++ .../team_settings/team_access_tab/index.ts | 38 + .../team_access_tab/invite_section_input.tsx | 103 +++ .../team_access_tab/open_invite.test.tsx | 53 ++ .../team_access_tab/open_invite.tsx | 76 ++ .../team_access_tab/team_access_tab.scss | 34 + .../team_access_tab/team_access_tab.test.tsx | 123 +++ .../team_access_tab/team_access_tab.tsx | 161 ++++ .../team_info_tab}/index.ts | 25 +- .../team_description_section.tsx | 58 ++ .../team_info_tab/team_info_tab.scss | 26 + .../team_info_tab/team_info_tab.test.tsx | 183 +++++ .../team_info_tab/team_info_tab.tsx | 236 ++++++ .../team_info_tab/team_name_section.tsx | 59 ++ .../team_info_tab/team_picture_section.scss | 61 ++ .../team_info_tab/team_picture_section.tsx | 180 +++++ .../team_settings/team_settings.tsx | 50 +- .../team_settings_modal.test.tsx.snap | 93 --- .../components/team_settings_modal/index.ts | 3 - .../team_settings_modal.test.tsx | 24 +- .../team_settings_modal.tsx | 183 ++--- .../widgets/inputs/input/input.scss | 8 + .../components/widgets/inputs/input/input.tsx | 65 +- .../widgets/inputs/url_input/url_input.tsx | 8 +- .../modals/components/base_setting_item.scss | 29 +- .../modals/components/base_setting_item.tsx | 54 +- .../components/checkbox_setting_item.tsx | 6 + .../modals/components/modal_section.scss | 1 - .../modals/components/modal_section.tsx | 23 +- .../modals/components/save_changes_panel.scss | 114 ++- .../modals/components/save_changes_panel.tsx | 113 ++- webapp/channels/src/i18n/en.json | 39 +- .../src/sass/components/_settings-modal.scss | 2 + .../channels/src/sass/responsive/_mobile.scss | 3 + .../channels/src/sass/routes/_settings.scss | 8 +- webapp/channels/src/utils/utils.tsx | 2 +- webapp/platform/types/src/teams.ts | 1 + 59 files changed, 2254 insertions(+), 2129 deletions(-) create mode 100644 webapp/channels/src/components/common/select_text_input/select_text_input.scss create mode 100644 webapp/channels/src/components/common/select_text_input/select_text_input.tsx delete mode 100644 webapp/channels/src/components/team_general_tab/__snapshots__/open_invite.test.tsx.snap delete mode 100644 webapp/channels/src/components/team_general_tab/__snapshots__/team_general_tab.test.tsx.snap delete mode 100644 webapp/channels/src/components/team_general_tab/open_invite.test.tsx delete mode 100644 webapp/channels/src/components/team_general_tab/open_invite.tsx delete mode 100644 webapp/channels/src/components/team_general_tab/team_general_tab.scss delete mode 100644 webapp/channels/src/components/team_general_tab/team_general_tab.test.tsx delete mode 100644 webapp/channels/src/components/team_general_tab/team_general_tab.tsx create mode 100644 webapp/channels/src/components/team_settings/team_access_tab/allowed_domains_select.tsx create mode 100644 webapp/channels/src/components/team_settings/team_access_tab/index.ts create mode 100644 webapp/channels/src/components/team_settings/team_access_tab/invite_section_input.tsx create mode 100644 webapp/channels/src/components/team_settings/team_access_tab/open_invite.test.tsx create mode 100644 webapp/channels/src/components/team_settings/team_access_tab/open_invite.tsx create mode 100644 webapp/channels/src/components/team_settings/team_access_tab/team_access_tab.scss create mode 100644 webapp/channels/src/components/team_settings/team_access_tab/team_access_tab.test.tsx create mode 100644 webapp/channels/src/components/team_settings/team_access_tab/team_access_tab.tsx rename webapp/channels/src/components/{team_general_tab => team_settings/team_info_tab}/index.ts (56%) create mode 100644 webapp/channels/src/components/team_settings/team_info_tab/team_description_section.tsx create mode 100644 webapp/channels/src/components/team_settings/team_info_tab/team_info_tab.scss create mode 100644 webapp/channels/src/components/team_settings/team_info_tab/team_info_tab.test.tsx create mode 100644 webapp/channels/src/components/team_settings/team_info_tab/team_info_tab.tsx create mode 100644 webapp/channels/src/components/team_settings/team_info_tab/team_name_section.tsx create mode 100644 webapp/channels/src/components/team_settings/team_info_tab/team_picture_section.scss create mode 100644 webapp/channels/src/components/team_settings/team_info_tab/team_picture_section.tsx delete mode 100644 webapp/channels/src/components/team_settings_modal/__snapshots__/team_settings_modal.test.tsx.snap diff --git a/e2e-tests/cypress/tests/integration/channels/team_settings/closed_team_invite_by_email_spec.js b/e2e-tests/cypress/tests/integration/channels/team_settings/closed_team_invite_by_email_spec.js index 2e1c148b05..f42dd3ccc7 100644 --- a/e2e-tests/cypress/tests/integration/channels/team_settings/closed_team_invite_by_email_spec.js +++ b/e2e-tests/cypress/tests/integration/channels/team_settings/closed_team_invite_by_email_spec.js @@ -59,13 +59,16 @@ describe('Team Settings', () => { // * Check that the 'Team Settings' modal was opened cy.get('#teamSettingsModal').should('exist').within(() => { - cy.get('#open_inviteDesc').should('have.text', 'No'); + // # Go to Access section + cy.get('#accessButton').click(); - // # Click on the 'Allow only users with a specific email domain to join this team' edit button - cy.get('#allowed_domainsEdit').should('be.visible').click(); + cy.get('.access-allowed-domains-section').should('exist').within(() => { + // # Click on the 'Allow only users with a specific email domain to join this team' checkbox + cy.get('.mm-modal-generic-section-item__input-checkbox').should('not.be.checked').click(); + }); // * Verify that the '#allowedDomains' input field is empty - cy.get('#allowedDomains').should('be.empty'); + cy.get('#allowedDomains').should('have.text', 'corp.mattermost.com, mattermost.com'); // # Close the modal cy.get('#teamSettingsModalLabel').find('button').should('be.visible').click(); diff --git a/e2e-tests/cypress/tests/integration/channels/team_settings/invite_user_to_closed_team_spec.js b/e2e-tests/cypress/tests/integration/channels/team_settings/invite_user_to_closed_team_spec.js index 19cbc1ceff..d9577a58d8 100644 --- a/e2e-tests/cypress/tests/integration/channels/team_settings/invite_user_to_closed_team_spec.js +++ b/e2e-tests/cypress/tests/integration/channels/team_settings/invite_user_to_closed_team_spec.js @@ -38,12 +38,16 @@ describe('Team Settings', () => { // * Check that the 'Team Settings' modal was opened cy.get('#teamSettingsModal').should('exist').within(() => { - // # Click on the 'Allow only users with a specific email domain to join this team' edit button - cy.get('#allowed_domainsEdit').should('be.visible').click(); + // # Go to Access section + cy.get('#accessButton').click(); + + cy.get('.access-allowed-domains-section').should('exist').within(() => { + // # Click on the 'Allow only users with a specific email domain to join this team' checkbox + cy.get('.mm-modal-generic-section-item__input-checkbox').should('not.be.checked').click(); + }); // # Set 'sample.mattermost.com' as the only allowed email domain and save - cy.wait(TIMEOUTS.HALF_SEC); - cy.focused().type(emailDomain); + cy.get('#allowedDomains').click().type(emailDomain).type(' '); cy.findByText('Save').should('be.visible').click(); // # Close the modal diff --git a/e2e-tests/cypress/tests/integration/channels/team_settings/join_closed_team_with_not_allowed_email_spec.js b/e2e-tests/cypress/tests/integration/channels/team_settings/join_closed_team_with_not_allowed_email_spec.js index 3753e85dee..894f7daf1e 100644 --- a/e2e-tests/cypress/tests/integration/channels/team_settings/join_closed_team_with_not_allowed_email_spec.js +++ b/e2e-tests/cypress/tests/integration/channels/team_settings/join_closed_team_with_not_allowed_email_spec.js @@ -11,7 +11,6 @@ // Group: @channels @team_settings import {getRandomId, stubClipboard} from '../../../utils'; -import * as TIMEOUTS from '../../../fixtures/timeouts'; describe('Team Settings', () => { const randomId = getRandomId(); @@ -47,15 +46,22 @@ describe('Team Settings', () => { // * Check that the 'Team Settings' modal was opened cy.get('#teamSettingsModal').should('exist').within(() => { - // # Click on the 'Allow only users with a specific email domain to join this team' edit button - cy.get('#allowed_domainsEdit').should('be.visible').click(); + // # Go to Access section + cy.get('#accessButton').click(); - // # Set 'sample.mattermost.com' as the only allowed email domain, save then close - cy.wait(TIMEOUTS.HALF_SEC); - cy.focused().type(emailDomain); - cy.uiSaveAndClose(); + // # Click on the 'Allow only users with a specific email domain to join this team' edit button + cy.get('.access-allowed-domains-section').should('exist').within(() => { + // # Click on the 'Allow only users with a specific email domain to join this team' checkbox + cy.get('.mm-modal-generic-section-item__input-checkbox').should('not.be.checked').click(); + }); + + // # Set 'sample.mattermost.com' as the only allowed email domain and save + cy.get('#allowedDomains').click().type(emailDomain).type(' '); + cy.findByText('Save').should('be.visible').click(); }); + cy.uiClose(); + // # Open team menu and click 'Invite People' cy.uiOpenTeamMenu('Invite People'); @@ -92,26 +98,26 @@ describe('Team Settings', () => { // * Check that the 'Team Settings' modal was opened cy.get('#teamSettingsModal').should('exist').within(() => { - // # Click on the 'Allow any user with an account on this server to join this team' edit button - cy.get('#open_inviteEdit').should('be.visible').click(); + // # Go to Access section + cy.get('#accessButton').click(); - // # Enable any user with an account on the server to join the team - cy.get('#teamOpenInvite').should('be.visible').check(); - - // # Save and verify it took effect - cy.uiSave(); - cy.get('#open_inviteDesc').should('be.visible').and('have.text', 'Yes'); + cy.get('.access-invite-domains-section').should('exist').within(() => { + // # Enable any user with an account on the server to join the team + cy.get('.mm-modal-generic-section-item__input-checkbox').should('not.be.checked').click(); + }); // # Click on the 'Allow only users with a specific email domain to join this team' edit button - cy.get('#allowed_domainsEdit').should('be.visible').click(); + cy.get('.access-allowed-domains-section').should('exist').within(() => { + // # Click on the 'Allow only users with a specific email domain to join this team' checkbox + cy.get('.mm-modal-generic-section-item__input-checkbox').should('not.be.checked').click(); + }); // # Set 'sample.mattermost.com' as the only allowed email domain and save - cy.wait(TIMEOUTS.HALF_SEC); - cy.findByRole('textbox', {name: 'Allowed Domains'}).should('be.visible').and('be.focused').type(emailDomain); + cy.get('#allowedDomains').click().type(emailDomain).type(' '); + cy.findByText('Save').should('be.visible').click(); // # Save and verify it took effect cy.uiSave(); - cy.get('#allowed_domainsDesc').should('be.visible').and('have.text', emailDomain); // # Close the modal cy.uiClose(); diff --git a/e2e-tests/cypress/tests/integration/channels/team_settings/remove_team_icon_spec.js b/e2e-tests/cypress/tests/integration/channels/team_settings/remove_team_icon_spec.js index ba1c0a0389..ca9fb8547e 100644 --- a/e2e-tests/cypress/tests/integration/channels/team_settings/remove_team_icon_spec.js +++ b/e2e-tests/cypress/tests/integration/channels/team_settings/remove_team_icon_spec.js @@ -28,56 +28,34 @@ describe('Teams Settings', () => { // # Open team settings dialog openTeamSettingsDialog(); - // * Verify the settings picture button is visible to click - cy.findByTestId('inputSettingPictureButton').should('be.visible').click(); - - // * Before uploading the picture the save button must be disabled - cy.uiSaveButton().should('be.disabled'); - // # Upload a file on center view cy.findByTestId('uploadPicture').attachFile('mattermost-icon.png'); - // * Save then close - cy.uiSaveAndClose(); + // * Save + cy.uiSave(); // * Verify team icon - cy.get(`#${testTeam.name}TeamButton`).within(() => { - cy.findByTestId('teamIconImage').should('be.visible'); - cy.findByTestId('teamIconInitial').should('not.exist'); - }); - - // # Open the team settings dialog - openTeamSettingsDialog(); - - // # Click on 'X' icon to remove the image - cy.findByTestId('removeSettingPicture').should('be.visible').click(); - - // # Click on the cancel button - cy.findByTestId('cancelSettingPicture').should('be.visible').click(); + cy.get('#teamIconImage').should('be.visible'); + cy.get('#teamIconInitial').should('not.exist'); // # Close the team settings dialog cy.uiClose(); - // * Verify the team icon image is visible and initial team holder is not visible - cy.get(`#${testTeam.name}TeamButton`).within(() => { - cy.findByTestId('teamIconImage').should('be.visible'); - cy.findByTestId('teamIconInitial').should('not.exist'); - }); - - // # Open team settings dialog + // # Open the team settings dialog openTeamSettingsDialog(); - // # Click on 'X' icon to remove the image - cy.findByTestId('removeSettingPicture').should('be.visible').click(); + // # Click on 'Remove Image' button to remove the image + cy.findByTestId('removeImageButton').should('be.visible').click(); - // # Save and close the modal - cy.uiSaveAndClose(); + // # Close the modal + cy.uiClose(); + + // # Open the team settings dialog + openTeamSettingsDialog(); // * After removing the team icon initial team holder is visible but not team icon holder - cy.get(`#${testTeam.name}TeamButton`).within(() => { - cy.findByTestId('teamIconImage').should('not.exist'); - cy.findByTestId('teamIconInitial').should('be.visible'); - }); + cy.get('#teamIconImage').should('not.exist'); + cy.get('#teamIconInitial').should('be.visible'); }); }); @@ -88,9 +66,11 @@ function openTeamSettingsDialog() { // * Verify the team settings dialog is open cy.get('#teamSettingsModalLabel').should('be.visible').and('contain', 'Team Settings'); - // * Verify the edit icon is visible - cy.get('#team_iconEdit').should('be.visible'); + cy.get('.team-picture-section').within(() => { + // * Verify the edit icon is visible + cy.get('.icon-pencil-outline').should('be.visible'); - // # Click on edit button - cy.get('#team_iconEdit').click(); + // # Click on edit button + cy.get('.icon-pencil-outline').click(); + }); } diff --git a/e2e-tests/cypress/tests/integration/channels/team_settings/teams_spec.js b/e2e-tests/cypress/tests/integration/channels/team_settings/teams_spec.js index 02d53bcc52..00fae8e087 100644 --- a/e2e-tests/cypress/tests/integration/channels/team_settings/teams_spec.js +++ b/e2e-tests/cypress/tests/integration/channels/team_settings/teams_spec.js @@ -186,6 +186,9 @@ describe('Teams Suite', () => { // # Open team menu and click "Team Settings" cy.uiOpenTeamMenu('Team Settings'); + // # Go to Access section + cy.get('#accessButton').click(); + // # Open edit settings for invite code cy.findByText('Invite Code').should('be.visible').click(); @@ -213,11 +216,8 @@ describe('Teams Suite', () => { // # Change team name in the input cy.get('#teamName').should('be.visible').clear().type(teamName); - // Save new team name - cy.findByText(/save/i).click(); - - // # Close the team settings - cy.get('body').typeWithForce('{esc}'); + // Save new team name annd close< + cy.uiSaveAndClose(); // Team display name shows as "Testing Team" at top of team menu cy.uiGetLHSHeader().findByText(teamName); @@ -238,9 +238,6 @@ describe('Teams Suite', () => { // # Open team menu and click "Team Settings" cy.uiOpenTeamMenu('Team Settings'); - // # Click on the team description menu item - cy.findByText('Team Description').should('be.visible').click(); - // # Change team description in the input cy.get('#teamDescription').should('be.visible').clear().type(teamDescription); cy.get('#teamDescription').should('have.value', teamDescription); @@ -252,7 +249,7 @@ describe('Teams Suite', () => { cy.uiOpenTeamMenu('Team Settings'); // * Verify team description is updated - cy.get('#descriptionDesc').should('have.text', teamDescription); + cy.get('#teamDescription').should('have.text', teamDescription); }); it('MM-T2318 Allow anyone to join this team', () => { @@ -262,17 +259,16 @@ describe('Teams Suite', () => { // # Open team menu and click "Team Settings" cy.uiOpenTeamMenu('Team Settings'); - // # Click on the team description menu item - cy.findByText('Allow any user with an account on this server to join this team').should('be.visible').click(); + // # Go to Access section + cy.get('#accessButton').click(); - // # Change team description in the input - cy.get('#teamOpenInvite').click(); + cy.get('.access-invite-domains-section').should('exist').within(() => { + // # Click on the 'Allow any user with an account on this server to join this team' checkbox + cy.get('.mm-modal-generic-section-item__input-checkbox').should('not.be.checked').click(); + }); - // Save new team description - cy.findByText(/save/i).click(); - - // # Close the team settings - cy.get('body').typeWithForce('{esc}'); + // # Save and close + cy.uiSaveAndClose(); // # Login as new user cy.apiLogin(newUser); @@ -302,14 +298,16 @@ describe('Teams Suite', () => { // # Open team menu and click "Team Settings" cy.uiOpenTeamMenu('Team Settings'); - // # Click on the team description menu item - cy.findByText('Allow any user with an account on this server to join this team').should('be.visible').click(); + // # Go to Access section + cy.get('#accessButton').click(); - // # Change team description in the input - cy.get('#teamOpenInviteNo').click(); + cy.get('.access-invite-domains-section').should('exist').within(() => { + // # Click on the 'Allow any user with an account on this server to join this team' checkbox + cy.get('.mm-modal-generic-section-item__input-checkbox').should('not.be.checked'); + }); - // Save new team description and close team settings - cy.uiSaveAndClose(); + // # Save and close + cy.uiClose(); // # Login as new user cy.apiLogin(testUser); diff --git a/webapp/channels/src/components/channel_name_form_field/channel_name_form_field.tsx b/webapp/channels/src/components/channel_name_form_field/channel_name_form_field.tsx index ae9d9f7fe9..6d208aa017 100644 --- a/webapp/channels/src/components/channel_name_form_field/channel_name_form_field.tsx +++ b/webapp/channels/src/components/channel_name_form_field/channel_name_form_field.tsx @@ -96,7 +96,7 @@ const ChannelNameFormField = (props: Props): JSX.Element => { } }, [props.onURLChange, displayName.current, url, displayNameModified]); - const handleOnURLChange = useCallback((e: React.ChangeEvent) => { + const handleOnURLChange = useCallback((e: React.ChangeEvent) => { e.preventDefault(); const {target: {value: url}} = e; diff --git a/webapp/channels/src/components/channel_notifications_modal/__snapshots__/channel_notifications_modal.test.tsx.snap b/webapp/channels/src/components/channel_notifications_modal/__snapshots__/channel_notifications_modal.test.tsx.snap index d66b237494..d00414fa8d 100644 --- a/webapp/channels/src/components/channel_notifications_modal/__snapshots__/channel_notifications_modal.test.tsx.snap +++ b/webapp/channels/src/components/channel_notifications_modal/__snapshots__/channel_notifications_modal.test.tsx.snap @@ -76,7 +76,7 @@ Object { class="mm-modal-generic-section" >