From 13a7e752d5264d63bb73c73c94eb05c7446c09b7 Mon Sep 17 00:00:00 2001 From: ilkin-overleaf <100852799+ilkin-overleaf@users.noreply.github.com> Date: Mon, 10 Jul 2023 15:12:22 +0300 Subject: [PATCH] Merge pull request #13710 from overleaf/ii-review-panel-migration-bulk-actions-entry [web] Create bulk actions entry and bulk actions modal GitOrigin-RevId: c88ce6213304a110ee7410529813310b863178c1 --- .../web/frontend/extracted-translations.json | 4 + .../review-panel/current-file-container.tsx | 11 ++- .../entries/bulk-actions-entry.tsx | 7 -- .../bulk-actions-entry/bulk-actions-entry.tsx | 66 ++++++++++++++ .../bulk-actions-entry/bulk-actions.tsx | 24 +++++ .../entries/bulk-actions-entry/modal.tsx | 87 +++++++++++++++++++ .../hooks/use-angular-review-panel-state.ts | 13 +++ .../review-panel/types/review-panel-state.ts | 3 + .../controllers/ReviewPanelController.js | 8 +- .../review-panel/review-panel.spec.tsx | 11 +++ services/web/types/review-panel/entry.ts | 3 +- 11 files changed, 223 insertions(+), 14 deletions(-) delete mode 100644 services/web/frontend/js/features/source-editor/components/review-panel/entries/bulk-actions-entry.tsx create mode 100644 services/web/frontend/js/features/source-editor/components/review-panel/entries/bulk-actions-entry/bulk-actions-entry.tsx create mode 100644 services/web/frontend/js/features/source-editor/components/review-panel/entries/bulk-actions-entry/bulk-actions.tsx create mode 100644 services/web/frontend/js/features/source-editor/components/review-panel/entries/bulk-actions-entry/modal.tsx diff --git a/services/web/frontend/extracted-translations.json b/services/web/frontend/extracted-translations.json index 8410af827e..88ca9f218f 100644 --- a/services/web/frontend/extracted-translations.json +++ b/services/web/frontend/extracted-translations.json @@ -14,6 +14,7 @@ "about_to_leave_projects": "", "about_to_trash_projects": "", "accept": "", + "accept_all": "", "accept_invitation": "", "accepted_invite": "", "access_denied": "", @@ -87,6 +88,8 @@ "blank_project": "", "blocked_filename": "", "browser": "", + "bulk_accept_confirm": "", + "bulk_reject_confirm": "", "by_subscribing_you_agree_to_our_terms_of_service": "", "can_edit": "", "can_link_institution_email_acct_to_institution_acct": "", @@ -809,6 +812,7 @@ "refreshing": "", "regards": "", "reject": "", + "reject_all": "", "relink_your_account": "", "remote_service_error": "", "remove": "", diff --git a/services/web/frontend/js/features/source-editor/components/review-panel/current-file-container.tsx b/services/web/frontend/js/features/source-editor/components/review-panel/current-file-container.tsx index da4fbd0aee..d7373fdd02 100644 --- a/services/web/frontend/js/features/source-editor/components/review-panel/current-file-container.tsx +++ b/services/web/frontend/js/features/source-editor/components/review-panel/current-file-container.tsx @@ -7,7 +7,7 @@ import ChangeEntry from './entries/change-entry' import AggregateChangeEntry from './entries/aggregate-change-entry' import CommentEntry from './entries/comment-entry' import AddCommentEntry from './entries/add-comment-entry' -import BulkActionsEntry from './entries/bulk-actions-entry' +import BulkActionsEntry from './entries/bulk-actions-entry/bulk-actions-entry' import { useReviewPanelUpdaterFnsContext, useReviewPanelValueContext, @@ -24,6 +24,7 @@ function CurrentFileContainer() { permissions, loadingThreads, users, + nVisibleSelectedChanges: nChanges, toggleReviewPanel, } = useReviewPanelValueContext() const { setEntryHover } = useReviewPanelUpdaterFnsContext() @@ -114,7 +115,13 @@ function CurrentFileContainer() { } if (entry.type === 'bulk-actions') { - return + return ( + + ) } return null diff --git a/services/web/frontend/js/features/source-editor/components/review-panel/entries/bulk-actions-entry.tsx b/services/web/frontend/js/features/source-editor/components/review-panel/entries/bulk-actions-entry.tsx deleted file mode 100644 index bb9fc52b90..0000000000 --- a/services/web/frontend/js/features/source-editor/components/review-panel/entries/bulk-actions-entry.tsx +++ /dev/null @@ -1,7 +0,0 @@ -import EntryContainer from './entry-container' - -function BulkActionsEntry() { - return Bulk actions entry -} - -export default BulkActionsEntry diff --git a/services/web/frontend/js/features/source-editor/components/review-panel/entries/bulk-actions-entry/bulk-actions-entry.tsx b/services/web/frontend/js/features/source-editor/components/review-panel/entries/bulk-actions-entry/bulk-actions-entry.tsx new file mode 100644 index 0000000000..71261bba8b --- /dev/null +++ b/services/web/frontend/js/features/source-editor/components/review-panel/entries/bulk-actions-entry/bulk-actions-entry.tsx @@ -0,0 +1,66 @@ +import { useTranslation } from 'react-i18next' +import EntryContainer from '../entry-container' +import EntryCallout from '../entry-callout' +import Icon from '../../../../../../shared/components/icon' +import BulkActions from './bulk-actions' +import Modal, { useBulkActionsModal } from './modal' +import { ReviewPanelBulkActionsEntry } from '../../../../../../../../types/review-panel/entry' + +type BulkActionsEntryProps = { + entry: ReviewPanelBulkActionsEntry + nChanges: number +} + +function BulkActionsEntry({ entry, nChanges }: BulkActionsEntryProps) { + const { t } = useTranslation() + const { + show, + setShow, + isAccept, + handleShowBulkAcceptDialog, + handleShowBulkRejectDialog, + handleConfirmDialog, + } = useBulkActionsModal() + + return ( + <> + + {nChanges > 1 && ( + <> + + + + {t('reject_all')} ({nChanges}) + + + {t('accept_all')} ({nChanges}) + + + + )} + + + + ) +} + +export default BulkActionsEntry diff --git a/services/web/frontend/js/features/source-editor/components/review-panel/entries/bulk-actions-entry/bulk-actions.tsx b/services/web/frontend/js/features/source-editor/components/review-panel/entries/bulk-actions-entry/bulk-actions.tsx new file mode 100644 index 0000000000..f8201e479e --- /dev/null +++ b/services/web/frontend/js/features/source-editor/components/review-panel/entries/bulk-actions-entry/bulk-actions.tsx @@ -0,0 +1,24 @@ +import classnames from 'classnames' + +function BulkActions({ + className, + ...rest +}: React.ComponentPropsWithoutRef<'div'>) { + return ( +
+ ) +} + +BulkActions.Button = function BulkActionsButton({ + className, + ...rest +}: React.ComponentPropsWithoutRef<'button'>) { + return ( + + + + + ) +} + +export function useBulkActionsModal() { + const [show, setShow] = useState(false) + const [isAccept, setIsAccept] = useState(false) + const { bulkAcceptActions, bulkRejectActions } = useReviewPanelValueContext() + + const handleShowBulkAcceptDialog = useCallback(() => { + setIsAccept(true) + setShow(true) + }, []) + + const handleShowBulkRejectDialog = useCallback(() => { + setIsAccept(false) + setShow(true) + }, []) + + const handleConfirmDialog = useCallback(() => { + if (isAccept) { + bulkAcceptActions() + } else { + bulkRejectActions() + } + + setShow(false) + }, [bulkAcceptActions, bulkRejectActions, isAccept]) + + return { + show, + setShow, + isAccept, + handleShowBulkAcceptDialog, + handleShowBulkRejectDialog, + handleConfirmDialog, + } +} + +export default Modal diff --git a/services/web/frontend/js/features/source-editor/context/review-panel/hooks/use-angular-review-panel-state.ts b/services/web/frontend/js/features/source-editor/context/review-panel/hooks/use-angular-review-panel-state.ts index 849c99d6af..a7414f9b61 100644 --- a/services/web/frontend/js/features/source-editor/context/review-panel/hooks/use-angular-review-panel-state.ts +++ b/services/web/frontend/js/features/source-editor/context/review-panel/hooks/use-angular-review-panel-state.ts @@ -16,6 +16,9 @@ function useAngularReviewPanelState(): ReviewPanelState { const [loading] = useScopeValue>( 'reviewPanel.overview.loading' ) + const [nVisibleSelectedChanges] = useScopeValue< + ReviewPanel.Value<'nVisibleSelectedChanges'> + >('reviewPanel.nVisibleSelectedChanges') const [collapsed, setCollapsed] = useScopeValue< ReviewPanel.Value<'collapsed'> >('reviewPanel.overview.docsCollapsedState') @@ -97,6 +100,10 @@ function useAngularReviewPanelState(): ReviewPanelState { useScopeValue>('acceptChanges') const [rejectChanges] = useScopeValue>('rejectChanges') + const [bulkAcceptActions] = + useScopeValue>('bulkAcceptActions') + const [bulkRejectActions] = + useScopeValue>('bulkRejectActions') const handleSetSubview = useCallback( (subView: SubView) => { @@ -132,6 +139,7 @@ function useAngularReviewPanelState(): ReviewPanelState { gotoEntry, handleLayoutChange, loadingThreads, + nVisibleSelectedChanges, permissions, users, resolveComment, @@ -152,6 +160,8 @@ function useAngularReviewPanelState(): ReviewPanelState { trackChangesForGuestsAvailable, formattedProjectMembers, toggleReviewPanel, + bulkAcceptActions, + bulkRejectActions, unresolveComment, deleteThread, refreshResolvedCommentsDropdown, @@ -169,6 +179,7 @@ function useAngularReviewPanelState(): ReviewPanelState { gotoEntry, handleLayoutChange, loadingThreads, + nVisibleSelectedChanges, permissions, users, resolveComment, @@ -189,6 +200,8 @@ function useAngularReviewPanelState(): ReviewPanelState { trackChangesForGuestsAvailable, formattedProjectMembers, toggleReviewPanel, + bulkAcceptActions, + bulkRejectActions, unresolveComment, deleteThread, refreshResolvedCommentsDropdown, diff --git a/services/web/frontend/js/features/source-editor/context/review-panel/types/review-panel-state.ts b/services/web/frontend/js/features/source-editor/context/review-panel/types/review-panel-state.ts index 9c8bf61deb..4bd1698538 100644 --- a/services/web/frontend/js/features/source-editor/context/review-panel/types/review-panel-state.ts +++ b/services/web/frontend/js/features/source-editor/context/review-panel/types/review-panel-state.ts @@ -24,6 +24,7 @@ export interface ReviewPanelState { gotoEntry: (docId: DocId, entryOffset: number) => void handleLayoutChange: () => void loadingThreads: boolean + nVisibleSelectedChanges: number permissions: ReviewPanelPermissions users: ReviewPanelUsers resolveComment: (docId: DocId, entryId: ThreadId) => void @@ -54,6 +55,8 @@ export interface ReviewPanelState { } > toggleReviewPanel: () => void + bulkAcceptActions: () => void + bulkRejectActions: () => void unresolveComment: (threadId: ThreadId) => void deleteThread: (_entryId: unknown, docId: DocId, threadId: ThreadId) => void refreshResolvedCommentsDropdown: () => Promise diff --git a/services/web/frontend/js/ide/review-panel/controllers/ReviewPanelController.js b/services/web/frontend/js/ide/review-panel/controllers/ReviewPanelController.js index 3b6e402e93..b0ebbdbabe 100644 --- a/services/web/frontend/js/ide/review-panel/controllers/ReviewPanelController.js +++ b/services/web/frontend/js/ide/review-panel/controllers/ReviewPanelController.js @@ -688,7 +688,7 @@ export default App.controller( dispatchReviewPanelEvent('changes:reject', change_ids) } - const bulkAccept = function () { + ide.$scope.bulkAcceptActions = function () { _doAcceptChanges(ide.$scope.reviewPanel.selectedEntryIds.slice()) eventTracking.sendMB('rp-bulk-accept', { view: $scope.ui.reviewPanelOpen @@ -698,7 +698,7 @@ export default App.controller( }) } - const bulkReject = function () { + ide.$scope.bulkRejectActions = function () { _doRejectChanges(ide.$scope.reviewPanel.selectedEntryIds.slice()) eventTracking.sendMB('rp-bulk-reject', { view: $scope.ui.reviewPanelOpen @@ -729,9 +729,9 @@ export default App.controller( }) .result.then(function (isAccept) { if (isAccept) { - return bulkAccept() + return ide.$scope.bulkAcceptActions() } else { - return bulkReject() + return ide.$scope.bulkRejectActions() } }) diff --git a/services/web/test/frontend/features/review-panel/review-panel.spec.tsx b/services/web/test/frontend/features/review-panel/review-panel.spec.tsx index 257867acf6..273c25be18 100644 --- a/services/web/test/frontend/features/review-panel/review-panel.spec.tsx +++ b/services/web/test/frontend/features/review-panel/review-panel.spec.tsx @@ -232,6 +232,17 @@ describe('', function () { it.skip('adds comment', function () {}) }) + describe('bulk actions entry', function () { + // eslint-disable-next-line mocha/no-skipped-tests + it.skip('renders the reject and accept all buttons`', function () {}) + + // eslint-disable-next-line mocha/no-skipped-tests + it.skip('accepts all changes', function () {}) + + // eslint-disable-next-line mocha/no-skipped-tests + it.skip('rejects all changes', function () {}) + }) + describe('overview mode', function () { // eslint-disable-next-line mocha/no-skipped-tests it.skip('shows list of files changed', function () {}) diff --git a/services/web/types/review-panel/entry.ts b/services/web/types/review-panel/entry.ts index faf78a308d..fb430d41a5 100644 --- a/services/web/types/review-panel/entry.ts +++ b/services/web/types/review-panel/entry.ts @@ -57,8 +57,9 @@ export interface ReviewPanelAddCommentEntry extends ReviewPanelBaseEntry { type: 'add-comment' } -interface ReviewPanelBulkActionsEntry extends ReviewPanelBaseEntry { +export interface ReviewPanelBulkActionsEntry extends ReviewPanelBaseEntry { type: 'bulk-actions' + length: number } export type ReviewPanelEntry =