refactor: Deduplicate delete modal (#1734)

This commit is contained in:
Philip Molares 2022-02-14 00:44:17 +01:00 committed by GitHub
parent 6a6f6105b9
commit 5f228b1bf2
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 62 additions and 36 deletions

View file

@ -11,36 +11,58 @@ 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 DeleteHistoryNoteModalProps {
modalTitleI18nKey?: string
modalQuestionI18nKey?: string
modalWarningI18nKey?: string
modalButtonI18nKey?: string
}
export interface DeleteNoteModalProps extends ModalVisibilityProps {
optionalNoteTitle?: string
onConfirm: () => void
}
/**
* A modal that asks the user if they really want to delete the current note.
*
* @param optionalNoteTitle optional note title
* @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
* @param modalTitleI18nKey optional i18nKey for the title
* @param modalQuestionI18nKey optional i18nKey for the question
* @param modalWarningI18nKey optional i18nKey for the warning
* @param modalButtonI18nKey optional i18nKey for the button
*/
export const DeleteNoteModal: React.FC<DeleteNoteModalProps> = ({ show, onHide, onConfirm }) => {
export const DeleteNoteModal: React.FC<DeleteNoteModalProps & DeleteHistoryNoteModalProps> = ({
optionalNoteTitle,
show,
onHide,
onConfirm,
modalTitleI18nKey,
modalQuestionI18nKey,
modalWarningI18nKey,
modalButtonI18nKey
}) => {
const noteTitle = useApplicationState((state) => state.noteDetails.noteTitle)
return (
<DeletionModal
{...cypressId('sidebar.deleteNote.modal')}
onConfirm={onConfirm}
deletionButtonI18nKey={'editor.modal.deleteNote.button'}
deletionButtonI18nKey={modalButtonI18nKey ?? 'editor.modal.deleteNote.button'}
show={show}
onHide={onHide}
title={'editor.modal.deleteNote.title'}>
title={modalTitleI18nKey ?? 'editor.modal.deleteNote.title'}>
<h5>
<Trans i18nKey={'editor.modal.deleteNote.question'} />
<Trans i18nKey={modalQuestionI18nKey ?? 'editor.modal.deleteNote.question'} />
</h5>
<ul>
<li {...cypressId('sidebar.deleteNote.modal.noteTitle')}>&nbsp;{noteTitle}</li>
<li {...cypressId('sidebar.deleteNote.modal.noteTitle')}>{optionalNoteTitle ?? noteTitle}</li>
</ul>
<h6>
<Trans i18nKey={'editor.modal.deleteNote.warning'} />
<Trans i18nKey={modalWarningI18nKey ?? 'editor.modal.deleteNote.warning'} />
</h6>
</DeletionModal>
)

View file

@ -17,11 +17,7 @@ export const DeleteNoteItem: React.FC<DeleteNoteItemProps> = ({ noteTitle, onCon
<DropdownItemWithDeletionModal
onConfirm={onConfirm}
itemI18nKey={'landing.history.menu.deleteNote'}
modalButtonI18nKey={'editor.modal.deleteNote.button'}
modalIcon={'trash'}
modalTitleI18nKey={'editor.modal.deleteNote.title'}
modalQuestionI18nKey={'editor.modal.deleteNote.question'}
modalWarningI18nKey={'editor.modal.deleteNote.warning'}
noteTitle={noteTitle}
/>
)

View file

@ -4,26 +4,38 @@
* SPDX-License-Identifier: AGPL-3.0-only
*/
import React, { Fragment, useState } from 'react'
import React, { Fragment, useCallback, useState } from 'react'
import { Dropdown } from 'react-bootstrap'
import { Trans, useTranslation } from 'react-i18next'
import { ForkAwesomeIcon } from '../../common/fork-awesome/fork-awesome-icon'
import type { IconName } from '../../common/fork-awesome/types'
import { DeletionModal } from '../../common/modals/deletion-modal'
import type { DeleteHistoryNoteModalProps } from '../../editor-page/sidebar/delete-note-sidebar-entry/delete-note-modal'
import { DeleteNoteModal } from '../../editor-page/sidebar/delete-note-sidebar-entry/delete-note-modal'
export interface DropdownItemWithDeletionModalProps {
onConfirm: () => void
itemI18nKey: string
modalButtonI18nKey: string
modalIcon: IconName
modalTitleI18nKey: string
modalQuestionI18nKey: string
modalWarningI18nKey: string
noteTitle: string
className?: string
}
export const DropdownItemWithDeletionModal: React.FC<DropdownItemWithDeletionModalProps> = ({
/**
* Renders a dropdown item and the corresponding deletion modal
*
* @param onConfirm A callback that fires if the user confirmed the request
* @param noteTitle The note title to be displayed
* @param modalTitleI18nKey The i18nKey for title to be shown in the modal
* @param modalButtonI18nKey The i18nKey for button to be shown in the modal
* @param itemI18nKey The i18nKey for the dropdown item
* @param modalIcon The icon for the dropdown item
* @param modalQuestionI18nKey The i18nKey for question to be shown in the modal
* @param modalWarningI18nKey The i18nKey for warning to be shown in the modal
* @param className Additional classes given to the dropdown item
*/
export const DropdownItemWithDeletionModal: React.FC<
DropdownItemWithDeletionModalProps & DeleteHistoryNoteModalProps
> = ({
onConfirm,
noteTitle,
modalTitleI18nKey,
@ -36,6 +48,11 @@ export const DropdownItemWithDeletionModal: React.FC<DropdownItemWithDeletionMod
}) => {
useTranslation()
const [showDialog, setShowDialog] = useState(false)
const handleConfirm = useCallback(() => {
setShowDialog(false)
onConfirm()
}, [onConfirm])
const onHide = useCallback(() => setShowDialog(false), [])
return (
<Fragment>
@ -43,25 +60,16 @@ export const DropdownItemWithDeletionModal: React.FC<DropdownItemWithDeletionMod
<ForkAwesomeIcon icon={modalIcon} fixedWidth={true} className='mx-2' />
<Trans i18nKey={itemI18nKey} />
</Dropdown.Item>
<DeletionModal
onConfirm={() => {
setShowDialog(false)
onConfirm()
}}
deletionButtonI18nKey={modalButtonI18nKey}
<DeleteNoteModal
optionalNoteTitle={noteTitle}
onConfirm={handleConfirm}
show={showDialog}
onHide={() => setShowDialog(false)}
title={modalTitleI18nKey}>
<h5>
<Trans i18nKey={modalQuestionI18nKey} />
</h5>
<ul>
<li>{noteTitle}</li>
</ul>
<h6>
<Trans i18nKey={modalWarningI18nKey} />
</h6>
</DeletionModal>
onHide={onHide}
modalTitleI18nKey={modalTitleI18nKey}
modalButtonI18nKey={modalButtonI18nKey}
modalQuestionI18nKey={modalQuestionI18nKey}
modalWarningI18nKey={modalWarningI18nKey}
/>
</Fragment>
)
}

View file

@ -72,7 +72,7 @@ export const HistoryCard: React.FC<HistoryEntryProps & HistoryEventHandlers> = (
<div className={'d-flex flex-column'}>
<EntryMenu
id={entry.identifier}
title={entry.title}
title={entryTitle}
origin={entry.origin}
isDark={false}
onRemove={onRemove}