From e16c83ea0c49e6795095f00297864bc2f77abebc Mon Sep 17 00:00:00 2001 From: Alf Eaton Date: Tue, 18 Apr 2023 09:14:07 +0100 Subject: [PATCH] Merge pull request #12621 from overleaf/ii-history-react-delete-labels [web] Delete history tags GitOrigin-RevId: 0a2846bbb3e99ef632b9192a9f8c04f702645506 --- .../web/frontend/extracted-translations.json | 3 + .../change-list/history-version.tsx | 5 +- .../components/change-list/label-badges.tsx | 0 .../components/change-list/labels-list.tsx | 6 +- .../components/change-list/tag-tooltip.tsx | 136 ++++++++++-- .../history/context/history-context.tsx | 7 + .../context/types/history-context-value.ts | 4 + .../js/features/history/utils/label.ts | 4 + .../frontend/js/shared/components/badge.tsx | 6 +- .../web/frontend/stories/badge.stories.tsx | 53 +++++ .../history/components/change-list.spec.tsx | 197 ++++++++++++++++++ .../history/components/chnage-list.spec.tsx | 35 ---- .../features/history/fixtures/labels.ts | 44 ++++ .../features/history/fixtures/updates.ts | 93 +++++++++ 14 files changed, 536 insertions(+), 57 deletions(-) delete mode 100644 services/web/frontend/js/features/history/components/change-list/label-badges.tsx create mode 100644 services/web/frontend/stories/badge.stories.tsx create mode 100644 services/web/test/frontend/features/history/components/change-list.spec.tsx delete mode 100644 services/web/test/frontend/features/history/components/chnage-list.spec.tsx create mode 100644 services/web/test/frontend/features/history/fixtures/labels.ts create mode 100644 services/web/test/frontend/features/history/fixtures/updates.ts diff --git a/services/web/frontend/extracted-translations.json b/services/web/frontend/extracted-translations.json index 0f5a27b8f2..0071efe7f9 100644 --- a/services/web/frontend/extracted-translations.json +++ b/services/web/frontend/extracted-translations.json @@ -353,6 +353,9 @@ "hide_document_preamble": "", "hide_outline": "", "history": "", + "history_are_you_sure_delete_label": "", + "history_delete_label": "", + "history_deleting_label": "", "history_entry_origin_dropbox": "", "history_entry_origin_git": "", "history_entry_origin_github": "", diff --git a/services/web/frontend/js/features/history/components/change-list/history-version.tsx b/services/web/frontend/js/features/history/components/change-list/history-version.tsx index 57a9a8a768..0cbf457e50 100644 --- a/services/web/frontend/js/features/history/components/change-list/history-version.tsx +++ b/services/web/frontend/js/features/history/components/change-list/history-version.tsx @@ -22,7 +22,10 @@ function HistoryVersion({ update }: HistoryEntryProps) { {relativeDate(update.meta.end_ts)} )} -
+
diff --git a/services/web/frontend/js/features/history/components/change-list/label-badges.tsx b/services/web/frontend/js/features/history/components/change-list/label-badges.tsx deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/services/web/frontend/js/features/history/components/change-list/labels-list.tsx b/services/web/frontend/js/features/history/components/change-list/labels-list.tsx index 30bb777182..e3320a5bb0 100644 --- a/services/web/frontend/js/features/history/components/change-list/labels-list.tsx +++ b/services/web/frontend/js/features/history/components/change-list/labels-list.tsx @@ -27,7 +27,11 @@ function LabelsList() { return ( <> {versionWithLabels.map(({ version, labels }) => ( -
+
{labels.map(label => ( { + const showConfirmationModal = (e: React.MouseEvent) => { e.stopPropagation() + setShowDeleteModal(true) + } + + const handleModalExited = () => { + if (!isSuccess) return + + const tempUpdates = [...updates] + for (const [i, update] of tempUpdates.entries()) { + if (update.toV === label.version) { + tempUpdates[i] = { + ...update, + labels: update.labels.filter(({ id }) => id !== label.id), + } + break + } + } + + setUpdates(tempUpdates) + + if (labels) { + const nonPseudoLabels = labels.filter(isLabel) + const filteredLabels = nonPseudoLabels.filter(({ id }) => id !== label.id) + setLabels(loadLabels(filteredLabels, tempUpdates[0].toV)) + } + + setShowDeleteModal(false) + + // TODO _handleHistoryUIStateChange + } + + const localDeleteHandler = () => { + runAsync(deleteJSON(`/project/${projectId}/labels/${label.id}`)) + .then(() => { + setShowDeleteModal(false) + }) + .catch(console.error) + } + + const responseError = error as unknown as { + response: Response + data?: { + message?: string + } } return ( - } - onClose={e => handleDelete(e, label)} - showCloseButton={Boolean( - isOwnedByCurrentUser && !isPseudoCurrentStateLabel + <> + } + onClose={showConfirmationModal} + closeButton={Boolean( + isOwnedByCurrentUser && !isPseudoCurrentStateLabel + )} + closeBtnProps={{ 'aria-label': t('delete') }} + className="history-version-badge" + data-testid="history-version-badge" + {...props} + > + {isPseudoCurrentStateLabel + ? t('history_label_project_current_state') + : label.comment} + + {!isPseudoCurrentStateLabel && ( + setShowDeleteModal(false)} + id="delete-history-label" + > + + {t('history_delete_label')} + + + {isError ? ( + responseError.response.status === 400 && + responseError?.data?.message ? ( + {responseError.data.message} + ) : ( + + {t('generic_something_went_wrong')} + + ) + ) : null} +

+ {t('history_are_you_sure_delete_label')}  + "{label.comment}"? +

+
+ + + + +
)} - closeBtnProps={{ 'aria-label': t('delete') }} - className="history-version-badge" - {...props} - > - {isPseudoCurrentStateLabel - ? t('history_label_project_current_state') - : label.comment} -
+ ) } @@ -60,7 +163,6 @@ function TagTooltip({ label, currentUserId, showTooltip }: LabelBadgesProps) { return showTooltip && !isPseudoCurrentStateLabel ? (
diff --git a/services/web/frontend/js/features/history/context/history-context.tsx b/services/web/frontend/js/features/history/context/history-context.tsx index b37325bd6c..0a6c23e554 100644 --- a/services/web/frontend/js/features/history/context/history-context.tsx +++ b/services/web/frontend/js/features/history/context/history-context.tsx @@ -97,6 +97,9 @@ function useHistory() { setUpdates(updates.concat(loadedUpdates)) // TODO first load + // if (firstLoad) { + // _handleHistoryUIStateChange() + // } } if (atEnd) return @@ -192,9 +195,11 @@ function useHistory() { isLoading, freeHistoryLimitHit, labels, + setLabels, loadingFileTree, nextBeforeTimestamp, updates, + setUpdates, userHasFullFeature, projectId, fileSelection, @@ -208,9 +213,11 @@ function useHistory() { isLoading, freeHistoryLimitHit, labels, + setLabels, loadingFileTree, nextBeforeTimestamp, updates, + setUpdates, userHasFullFeature, projectId, fileSelection, diff --git a/services/web/frontend/js/features/history/context/types/history-context-value.ts b/services/web/frontend/js/features/history/context/types/history-context-value.ts index 48e8537cd2..9917d85d8b 100644 --- a/services/web/frontend/js/features/history/context/types/history-context-value.ts +++ b/services/web/frontend/js/features/history/context/types/history-context-value.ts @@ -5,6 +5,9 @@ import { FileSelection } from '../../services/types/file' export type HistoryContextValue = { updates: LoadedUpdate[] + setUpdates: React.Dispatch< + React.SetStateAction + > nextBeforeTimestamp: number | undefined atEnd: boolean userHasFullFeature: boolean | undefined @@ -12,6 +15,7 @@ export type HistoryContextValue = { isLoading: boolean error: Nullable labels: Nullable + setLabels: React.Dispatch> loadingFileTree: boolean projectId: string fileSelection: FileSelection | null diff --git a/services/web/frontend/js/features/history/utils/label.ts b/services/web/frontend/js/features/history/utils/label.ts index dd1db5e7ff..5ca8c7513d 100644 --- a/services/web/frontend/js/features/history/utils/label.ts +++ b/services/web/frontend/js/features/history/utils/label.ts @@ -12,6 +12,10 @@ export const isPseudoLabel = ( return (label as PseudoCurrentStateLabel).isPseudoCurrentStateLabel === true } +export const isLabel = (label: LoadedLabel): label is Label => { + return !isPseudoLabel(label) +} + const sortLabelsByVersionAndDate = (labels: LoadedLabel[]) => { return orderBy( labels, diff --git a/services/web/frontend/js/shared/components/badge.tsx b/services/web/frontend/js/shared/components/badge.tsx index 2b841f0083..94456525d8 100644 --- a/services/web/frontend/js/shared/components/badge.tsx +++ b/services/web/frontend/js/shared/components/badge.tsx @@ -7,7 +7,7 @@ type BadgeProps = MergeAndOverride< prepend?: React.ReactNode children: React.ReactNode className?: string - showCloseButton?: boolean + closeButton?: boolean onClose?: (e: React.MouseEvent) => void closeBtnProps?: React.ComponentProps<'button'> } @@ -17,7 +17,7 @@ function Badge({ prepend, children, className, - showCloseButton = false, + closeButton = false, onClose, closeBtnProps, ...rest @@ -26,7 +26,7 @@ function Badge({ {prepend} {children} - {showCloseButton && ( + {closeButton && (