From f36c87b301a741e0a9922115f6992d58c8dbd64c Mon Sep 17 00:00:00 2001 From: Domagoj Kriskovic Date: Wed, 2 Apr 2025 12:27:11 +0200 Subject: [PATCH] Update share modal dropdown with a description for reviewers in a free project (#24571) * Update collaborator select dropdown with a description for reviewers in free project * Update share-project-modal test * Fix saas-e2e tests * fix server pro tests * fix cypress multiple inputs selection * fix testid case GitOrigin-RevId: 5369828334596d80988aba168385f0a51eea998f --- .../test/create-and-compile-project.spec.ts | 4 +- server-ce/test/git-bridge.spec.ts | 4 +- server-ce/test/helpers/project.ts | 14 +++-- server-ce/test/project-sharing.spec.ts | 6 +- .../web/frontend/extracted-translations.json | 5 +- .../components/add-collaborators.jsx | 58 +++++++++++++------ .../components/member-privileges.jsx | 6 +- .../components/select-collaborators.jsx | 1 + .../frontend/js/shared/components/select.tsx | 4 ++ .../bootstrap-5/pages/editor/share.scss | 11 ++++ services/web/locales/en.json | 5 +- .../components/share-project-modal.test.jsx | 36 ++++++++---- 12 files changed, 103 insertions(+), 51 deletions(-) diff --git a/server-ce/test/create-and-compile-project.spec.ts b/server-ce/test/create-and-compile-project.spec.ts index afee2072b5..20f8f0dd6d 100644 --- a/server-ce/test/create-and-compile-project.spec.ts +++ b/server-ce/test/create-and-compile-project.spec.ts @@ -95,7 +95,9 @@ describe('Project creation and compilation', function () { cy.findByText('Share').click() cy.findByRole('dialog').within(() => { - cy.get('input').type('collaborator@example.com,') + cy.findByTestId('collaborator-email-input').type( + 'collaborator@example.com,' + ) cy.findByText('Invite').click({ force: true }) cy.findByText('Invite not yet accepted.') }) diff --git a/server-ce/test/git-bridge.spec.ts b/server-ce/test/git-bridge.spec.ts index 010b8ccf74..071091bdfd 100644 --- a/server-ce/test/git-bridge.spec.ts +++ b/server-ce/test/git-bridge.spec.ts @@ -136,7 +136,7 @@ describe('git-bridge', function () { shareProjectByEmailAndAcceptInviteViaDash( projectName, 'collaborator-rw@example.com', - 'Can edit' + 'Editor' ) maybeClearAllTokens() openProjectByName(projectName) @@ -147,7 +147,7 @@ describe('git-bridge', function () { shareProjectByEmailAndAcceptInviteViaDash( projectName, 'collaborator-ro@example.com', - 'Can view' + 'Viewer' ) maybeClearAllTokens() openProjectByName(projectName) diff --git a/server-ce/test/helpers/project.ts b/server-ce/test/helpers/project.ts index 3b43e3d959..662327d6f2 100644 --- a/server-ce/test/helpers/project.ts +++ b/server-ce/test/helpers/project.ts @@ -100,7 +100,7 @@ export function openProjectViaInviteNotification(projectName: string) { function shareProjectByEmail( projectName: string, email: string, - level: 'Can view' | 'Can edit' + level: 'Viewer' | 'Editor' ) { openProjectByName(projectName) cy.findByText('Share').click() @@ -108,7 +108,13 @@ function shareProjectByEmail( cy.findByLabelText('Add people', { selector: 'input' }).type(`${email},`) cy.findByLabelText('Add people', { selector: 'input' }) .parents('form') - .within(() => cy.findByText('Can edit').parent().select(level)) + .within(() => { + cy.findByTestId('add-collaborator-select') + .click() + .then(() => { + cy.findByText(level).click() + }) + }) cy.findByText('Invite').click({ force: true }) cy.findByText('Invite not yet accepted.') }) @@ -117,7 +123,7 @@ function shareProjectByEmail( export function shareProjectByEmailAndAcceptInviteViaDash( projectName: string, email: string, - level: 'Can view' | 'Can edit' + level: 'Viewer' | 'Editor' ) { shareProjectByEmail(projectName, email, level) @@ -128,7 +134,7 @@ export function shareProjectByEmailAndAcceptInviteViaDash( export function shareProjectByEmailAndAcceptInviteViaEmail( projectName: string, email: string, - level: 'Can view' | 'Can edit' + level: 'Viewer' | 'Editor' ) { shareProjectByEmail(projectName, email, level) diff --git a/server-ce/test/project-sharing.spec.ts b/server-ce/test/project-sharing.spec.ts index 44887f2fd2..e26439264b 100644 --- a/server-ce/test/project-sharing.spec.ts +++ b/server-ce/test/project-sharing.spec.ts @@ -154,7 +154,7 @@ describe('Project Sharing', function () { beforeEach(function () { login('user@example.com') - shareProjectByEmailAndAcceptInviteViaEmail(projectName, email, 'Can view') + shareProjectByEmailAndAcceptInviteViaEmail(projectName, email, 'Viewer') }) it('should grant the collaborator read access', () => { @@ -169,7 +169,7 @@ describe('Project Sharing', function () { beforeWithReRunOnTestRetry(function () { login('user@example.com') - shareProjectByEmailAndAcceptInviteViaDash(projectName, email, 'Can view') + shareProjectByEmailAndAcceptInviteViaDash(projectName, email, 'Viewer') }) it('should grant the collaborator read access', () => { @@ -186,7 +186,7 @@ describe('Project Sharing', function () { beforeWithReRunOnTestRetry(function () { login('user@example.com') - shareProjectByEmailAndAcceptInviteViaDash(projectName, email, 'Can edit') + shareProjectByEmailAndAcceptInviteViaDash(projectName, email, 'Editor') }) it('should grant the collaborator write access', () => { diff --git a/services/web/frontend/extracted-translations.json b/services/web/frontend/extracted-translations.json index 058e8e77bf..12f86f93eb 100644 --- a/services/web/frontend/extracted-translations.json +++ b/services/web/frontend/extracted-translations.json @@ -183,13 +183,10 @@ "blog": "", "browser": "", "by_subscribing_you_agree_to_our_terms_of_service": "", - "can_edit": "", "can_edit_content": "", "can_link_institution_email_acct_to_institution_acct": "", "can_link_your_institution_acct_2": "", "can_now_relink_dropbox": "", - "can_review": "", - "can_view": "", "can_view_content": "", "cancel": "", "cancel_add_on": "", @@ -268,6 +265,7 @@ "column_width_is_x_click_to_resize": "", "comment": "", "comment_only": "", + "comment_only_upgrade_for_track_changes": "", "common": "", "common_causes_of_compile_timeouts_include": "", "commons_plan_tooltip": "", @@ -1273,7 +1271,6 @@ "read_lines_from_path": "", "read_more": "", "read_more_about_free_compile_timeouts_servers": "", - "read_only": "", "read_only_token": "", "read_write_token": "", "ready_to_join_x": "", diff --git a/services/web/frontend/js/features/share-project-modal/components/add-collaborators.jsx b/services/web/frontend/js/features/share-project-modal/components/add-collaborators.jsx index 9e86d5dcac..aa5948cb6f 100644 --- a/services/web/frontend/js/features/share-project-modal/components/add-collaborators.jsx +++ b/services/web/frontend/js/features/share-project-modal/components/add-collaborators.jsx @@ -12,7 +12,7 @@ import ClickableElementEnhancer from '@/shared/components/clickable-element-enha import PropTypes from 'prop-types' import OLForm from '@/features/ui/components/ol/ol-form' import OLFormGroup from '@/features/ui/components/ol/ol-form-group' -import OLFormSelect from '@/features/ui/components/ol/ol-form-select' +import { Select } from '@/shared/components/select' import OLButton from '@/features/ui/components/ol/ol-button' import getMeta from '@/utils/meta' @@ -27,7 +27,7 @@ export default function AddCollaborators({ readOnly }) { const { updateProject, setInFlight, setError } = useShareProjectContext() - const { _id: projectId, members, invites } = useProjectContext() + const { _id: projectId, members, invites, features } = useProjectContext() const currentMemberEmails = useMemo( () => (members || []).map(member => member.email).sort(), @@ -149,6 +149,32 @@ export default function AddCollaborators({ readOnly }) { updateProject, ]) + const privilegeOptions = useMemo(() => { + const options = [ + { + key: 'readAndWrite', + label: t('editor'), + }, + ] + + if (getMeta('ol-isReviewerRoleEnabled')) { + options.push({ + key: 'review', + label: t('reviewer'), + description: !features.trackChanges + ? t('comment_only_upgrade_for_track_changes') + : null, + }) + } + + options.push({ + key: 'readOnly', + label: t('viewer'), + }) + + return options + }, [features.trackChanges, t]) + return ( @@ -161,23 +187,19 @@ export default function AddCollaborators({ readOnly }) { -
- setPrivileges(event.target.value)} - > - - {getMeta('ol-isReviewerRoleEnabled') && ( - +
+