From 4089f0c6ed9a59892eb17768704991efa922988d Mon Sep 17 00:00:00 2001 From: Philip Molares Date: Thu, 30 Dec 2021 18:40:52 +0100 Subject: [PATCH] fix: use actual noteTitle in DeleteNoteSidebarEntry (#1729) fixes #1728 Signed-off-by: Philip Molares Co-Authored-by: Philip Molares Signed-off-by: Tilman Vatteroth --- cypress/integration/deleteNote.spec.ts | 50 ++++++++++++++++++ .../common/modals/deletion-modal.tsx | 3 +- .../delete-note-modal.tsx | 47 +++++++++++++++++ .../delete-note-sidebar-entry.tsx | 51 +++++++++++++++++++ .../editor-page/sidebar/sidebar.tsx | 2 +- .../delete-note-sidebar-entry.tsx | 40 --------------- 6 files changed, 151 insertions(+), 42 deletions(-) create mode 100644 cypress/integration/deleteNote.spec.ts create mode 100644 src/components/editor-page/sidebar/delete-note-sidebar-entry/delete-note-modal.tsx create mode 100644 src/components/editor-page/sidebar/delete-note-sidebar-entry/delete-note-sidebar-entry.tsx delete mode 100644 src/components/editor-page/sidebar/specific-sidebar-entries/delete-note-sidebar-entry.tsx diff --git a/cypress/integration/deleteNote.spec.ts b/cypress/integration/deleteNote.spec.ts new file mode 100644 index 000000000..f87de889e --- /dev/null +++ b/cypress/integration/deleteNote.spec.ts @@ -0,0 +1,50 @@ +/* + * SPDX-FileCopyrightText: 2021 The HedgeDoc developers (see AUTHORS file) + * + * SPDX-License-Identifier: AGPL-3.0-only + */ + +describe('Delete note', () => { + beforeEach(() => { + cy.visitTestEditor() + }) + + it('correctly deletes a note', () => { + cy.intercept('DELETE', '/mock-backend/api/private/notes/mock_note_id', { + statusCode: 200 + }) + cy.getByCypressId('sidebar.deleteNote.button').click() + cy.getByCypressId('sidebar.deleteNote.modal').should('be.visible') + cy.getByCypressId('sidebar.deleteNote.modal.noteTitle').should('be.visible').text().should('eq', '') + cy.getByCypressId('deletionModal.confirmButton').should('be.visible').click() + cy.getByCypressId('sidebar.deleteNote.modal').should('not.be.exist') + cy.getByCypressId('notification-toast').should('not.exist') + }) + + it('displays an error notification if something goes wrong', () => { + cy.getByCypressId('sidebar.deleteNote.button').click() + cy.getByCypressId('sidebar.deleteNote.modal').should('be.visible') + cy.getByCypressId('sidebar.deleteNote.modal.noteTitle').should('be.visible').text().should('eq', '') + cy.getByCypressId('deletionModal.confirmButton').should('be.visible').click() + cy.getByCypressId('sidebar.deleteNote.modal').should('not.exist') + cy.getByCypressId('notification-toast').should('be.visible') + }) + + describe('displays the note title coming from', () => { + const title = 'mock_title' + it('yaml metadata', () => { + cy.setCodemirrorContent(`---\ntitle: ${title}\n---`) + }) + it('opengraph', () => { + cy.setCodemirrorContent(`---\nopengraph:\n title: ${title}\n---`) + }) + it('just first heading', () => { + cy.setCodemirrorContent(`# ${title}`) + }) + afterEach(() => { + cy.getByCypressId('sidebar.deleteNote.button').click() + cy.getByCypressId('sidebar.deleteNote.modal').should('be.visible') + cy.getByCypressId('sidebar.deleteNote.modal.noteTitle').should('be.visible').text().should('eq', title) + }) + }) +}) diff --git a/src/components/common/modals/deletion-modal.tsx b/src/components/common/modals/deletion-modal.tsx index bde4070c7..94e0ee4a6 100644 --- a/src/components/common/modals/deletion-modal.tsx +++ b/src/components/common/modals/deletion-modal.tsx @@ -9,6 +9,7 @@ import { Button, Modal } from 'react-bootstrap' import { Trans, useTranslation } from 'react-i18next' import type { CommonModalProps } from './common-modal' import { CommonModal } from './common-modal' +import { cypressId } from '../../../utils/cypress-attribute' export interface DeletionModalProps extends CommonModalProps { onConfirm: () => void @@ -31,7 +32,7 @@ export const DeletionModal: React.FC = ({ {children} - diff --git a/src/components/editor-page/sidebar/delete-note-sidebar-entry/delete-note-modal.tsx b/src/components/editor-page/sidebar/delete-note-sidebar-entry/delete-note-modal.tsx new file mode 100644 index 000000000..06c78ff6f --- /dev/null +++ b/src/components/editor-page/sidebar/delete-note-sidebar-entry/delete-note-modal.tsx @@ -0,0 +1,47 @@ +/* + * SPDX-FileCopyrightText: 2021 The HedgeDoc developers (see AUTHORS file) + * + * SPDX-License-Identifier: AGPL-3.0-only + */ + +import React from 'react' +import { cypressId } from '../../../../utils/cypress-attribute' +import { Trans } from 'react-i18next' +import { DeletionModal } from '../../../common/modals/deletion-modal' +import { useApplicationState } from '../../../../hooks/common/use-application-state' +import type { ModalVisibilityProps } from '../../../common/modals/common-modal' + +export interface DeleteNoteModalProps extends ModalVisibilityProps { + onConfirm: () => void +} + +/** + * A modal that asks the user if they really want to delete the current note. + * + * @param show Defines if the modal should be shown + * @param onHide A callback that fires if the modal should be hidden without confirmation + * @param onConfirm A callback that fires if the user confirmed the request + */ +export const DeleteNoteModal: React.FC = ({ show, onHide, onConfirm }) => { + const noteTitle = useApplicationState((state) => state.noteDetails.noteTitle) + + return ( + +
+ +
+
    +
  •  {noteTitle}
  • +
+
+ +
+
+ ) +} diff --git a/src/components/editor-page/sidebar/delete-note-sidebar-entry/delete-note-sidebar-entry.tsx b/src/components/editor-page/sidebar/delete-note-sidebar-entry/delete-note-sidebar-entry.tsx new file mode 100644 index 000000000..97c44a068 --- /dev/null +++ b/src/components/editor-page/sidebar/delete-note-sidebar-entry/delete-note-sidebar-entry.tsx @@ -0,0 +1,51 @@ +/* + * SPDX-FileCopyrightText: 2021 The HedgeDoc developers (see AUTHORS file) + * + * SPDX-License-Identifier: AGPL-3.0-only + */ + +import React, { Fragment, useCallback, useState } from 'react' +import { Trans, useTranslation } from 'react-i18next' +import { SidebarButton } from '../sidebar-button/sidebar-button' +import type { SpecificSidebarEntryProps } from '../types' +import { useApplicationState } from '../../../../hooks/common/use-application-state' +import { cypressId } from '../../../../utils/cypress-attribute' +import { showErrorNotification } from '../../../../redux/ui-notifications/methods' +import { deleteNote } from '../../../../api/notes' +import { DeleteNoteModal } from './delete-note-modal' +import { ShowIf } from '../../../common/show-if/show-if' + +/** + * Sidebar entry that can be used to delete the current note. + * + * @param hide {@code true} if the entry shouldn't be visible + * @param className Additional css class names for the sidebar entry + */ +export const DeleteNoteSidebarEntry: React.FC = ({ hide, className }) => { + useTranslation() + const [showDialog, setShowDialog] = useState(false) + const noteId = useApplicationState((state) => state.noteDetails.id) + const openDialog = useCallback(() => setShowDialog(true), []) + const closeDialog = useCallback(() => setShowDialog(false), []) + const deleteNoteAndCloseDialog = useCallback(() => { + deleteNote(noteId) + .catch(showErrorNotification('landing.history.error.deleteNote.text')) + .finally(() => setShowDialog(false)) + }, [noteId]) + + return ( + + + + + + + + + ) +} diff --git a/src/components/editor-page/sidebar/sidebar.tsx b/src/components/editor-page/sidebar/sidebar.tsx index a22b61f66..4f2a35b7e 100644 --- a/src/components/editor-page/sidebar/sidebar.tsx +++ b/src/components/editor-page/sidebar/sidebar.tsx @@ -6,7 +6,7 @@ import React, { useCallback, useRef, useState } from 'react' import { useClickAway } from 'react-use' -import { DeleteNoteSidebarEntry } from './specific-sidebar-entries/delete-note-sidebar-entry' +import { DeleteNoteSidebarEntry } from './delete-note-sidebar-entry/delete-note-sidebar-entry' import { DocumentInfoSidebarEntry } from './specific-sidebar-entries/document-info-sidebar-entry' import { ExportMenuSidebarMenu } from './specific-sidebar-entries/export-menu-sidebar-menu' import { ImportMenuSidebarMenu } from './specific-sidebar-entries/import-menu-sidebar-menu' diff --git a/src/components/editor-page/sidebar/specific-sidebar-entries/delete-note-sidebar-entry.tsx b/src/components/editor-page/sidebar/specific-sidebar-entries/delete-note-sidebar-entry.tsx deleted file mode 100644 index ddeb3b6ff..000000000 --- a/src/components/editor-page/sidebar/specific-sidebar-entries/delete-note-sidebar-entry.tsx +++ /dev/null @@ -1,40 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2021 The HedgeDoc developers (see AUTHORS file) - * - * SPDX-License-Identifier: AGPL-3.0-only - */ - -import React, { Fragment, useState } from 'react' -import { Trans, useTranslation } from 'react-i18next' -import { DeletionModal } from '../../../common/modals/deletion-modal' -import { SidebarButton } from '../sidebar-button/sidebar-button' -import type { SpecificSidebarEntryProps } from '../types' - -export const DeleteNoteSidebarEntry: React.FC = ({ hide, className }) => { - useTranslation() - const [showDialog, setShowDialog] = useState(false) - - return ( - - setShowDialog(true)}> - - - setShowDialog(false)} - deletionButtonI18nKey={'editor.modal.deleteNote.button'} - show={showDialog} - onHide={() => setShowDialog(false)} - title={'editor.modal.deleteNote.title'}> -
- -
-
    -
  • noteTitle
  • -
-
- -
-
-
- ) -}