mirror of
https://github.com/hedgedoc/hedgedoc.git
synced 2025-05-22 19:25:18 -04:00
refactor: Deduplicate delete modal (#1734)
This commit is contained in:
parent
6a6f6105b9
commit
5f228b1bf2
4 changed files with 62 additions and 36 deletions
|
@ -11,36 +11,58 @@ import { DeletionModal } from '../../../common/modals/deletion-modal'
|
||||||
import { useApplicationState } from '../../../../hooks/common/use-application-state'
|
import { useApplicationState } from '../../../../hooks/common/use-application-state'
|
||||||
import type { ModalVisibilityProps } from '../../../common/modals/common-modal'
|
import type { ModalVisibilityProps } from '../../../common/modals/common-modal'
|
||||||
|
|
||||||
|
export interface DeleteHistoryNoteModalProps {
|
||||||
|
modalTitleI18nKey?: string
|
||||||
|
modalQuestionI18nKey?: string
|
||||||
|
modalWarningI18nKey?: string
|
||||||
|
modalButtonI18nKey?: string
|
||||||
|
}
|
||||||
|
|
||||||
export interface DeleteNoteModalProps extends ModalVisibilityProps {
|
export interface DeleteNoteModalProps extends ModalVisibilityProps {
|
||||||
|
optionalNoteTitle?: string
|
||||||
onConfirm: () => void
|
onConfirm: () => void
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A modal that asks the user if they really want to delete the current note.
|
* 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 show Defines if the modal should be shown
|
||||||
* @param onHide A callback that fires if the modal should be hidden without confirmation
|
* @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 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)
|
const noteTitle = useApplicationState((state) => state.noteDetails.noteTitle)
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<DeletionModal
|
<DeletionModal
|
||||||
{...cypressId('sidebar.deleteNote.modal')}
|
{...cypressId('sidebar.deleteNote.modal')}
|
||||||
onConfirm={onConfirm}
|
onConfirm={onConfirm}
|
||||||
deletionButtonI18nKey={'editor.modal.deleteNote.button'}
|
deletionButtonI18nKey={modalButtonI18nKey ?? 'editor.modal.deleteNote.button'}
|
||||||
show={show}
|
show={show}
|
||||||
onHide={onHide}
|
onHide={onHide}
|
||||||
title={'editor.modal.deleteNote.title'}>
|
title={modalTitleI18nKey ?? 'editor.modal.deleteNote.title'}>
|
||||||
<h5>
|
<h5>
|
||||||
<Trans i18nKey={'editor.modal.deleteNote.question'} />
|
<Trans i18nKey={modalQuestionI18nKey ?? 'editor.modal.deleteNote.question'} />
|
||||||
</h5>
|
</h5>
|
||||||
<ul>
|
<ul>
|
||||||
<li {...cypressId('sidebar.deleteNote.modal.noteTitle')}> {noteTitle}</li>
|
<li {...cypressId('sidebar.deleteNote.modal.noteTitle')}>{optionalNoteTitle ?? noteTitle}</li>
|
||||||
</ul>
|
</ul>
|
||||||
<h6>
|
<h6>
|
||||||
<Trans i18nKey={'editor.modal.deleteNote.warning'} />
|
<Trans i18nKey={modalWarningI18nKey ?? 'editor.modal.deleteNote.warning'} />
|
||||||
</h6>
|
</h6>
|
||||||
</DeletionModal>
|
</DeletionModal>
|
||||||
)
|
)
|
||||||
|
|
|
@ -17,11 +17,7 @@ export const DeleteNoteItem: React.FC<DeleteNoteItemProps> = ({ noteTitle, onCon
|
||||||
<DropdownItemWithDeletionModal
|
<DropdownItemWithDeletionModal
|
||||||
onConfirm={onConfirm}
|
onConfirm={onConfirm}
|
||||||
itemI18nKey={'landing.history.menu.deleteNote'}
|
itemI18nKey={'landing.history.menu.deleteNote'}
|
||||||
modalButtonI18nKey={'editor.modal.deleteNote.button'}
|
|
||||||
modalIcon={'trash'}
|
modalIcon={'trash'}
|
||||||
modalTitleI18nKey={'editor.modal.deleteNote.title'}
|
|
||||||
modalQuestionI18nKey={'editor.modal.deleteNote.question'}
|
|
||||||
modalWarningI18nKey={'editor.modal.deleteNote.warning'}
|
|
||||||
noteTitle={noteTitle}
|
noteTitle={noteTitle}
|
||||||
/>
|
/>
|
||||||
)
|
)
|
||||||
|
|
|
@ -4,26 +4,38 @@
|
||||||
* SPDX-License-Identifier: AGPL-3.0-only
|
* 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 { Dropdown } from 'react-bootstrap'
|
||||||
import { Trans, useTranslation } from 'react-i18next'
|
import { Trans, useTranslation } from 'react-i18next'
|
||||||
import { ForkAwesomeIcon } from '../../common/fork-awesome/fork-awesome-icon'
|
import { ForkAwesomeIcon } from '../../common/fork-awesome/fork-awesome-icon'
|
||||||
import type { IconName } from '../../common/fork-awesome/types'
|
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 {
|
export interface DropdownItemWithDeletionModalProps {
|
||||||
onConfirm: () => void
|
onConfirm: () => void
|
||||||
itemI18nKey: string
|
itemI18nKey: string
|
||||||
modalButtonI18nKey: string
|
|
||||||
modalIcon: IconName
|
modalIcon: IconName
|
||||||
modalTitleI18nKey: string
|
|
||||||
modalQuestionI18nKey: string
|
|
||||||
modalWarningI18nKey: string
|
|
||||||
noteTitle: string
|
noteTitle: string
|
||||||
className?: 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,
|
onConfirm,
|
||||||
noteTitle,
|
noteTitle,
|
||||||
modalTitleI18nKey,
|
modalTitleI18nKey,
|
||||||
|
@ -36,6 +48,11 @@ export const DropdownItemWithDeletionModal: React.FC<DropdownItemWithDeletionMod
|
||||||
}) => {
|
}) => {
|
||||||
useTranslation()
|
useTranslation()
|
||||||
const [showDialog, setShowDialog] = useState(false)
|
const [showDialog, setShowDialog] = useState(false)
|
||||||
|
const handleConfirm = useCallback(() => {
|
||||||
|
setShowDialog(false)
|
||||||
|
onConfirm()
|
||||||
|
}, [onConfirm])
|
||||||
|
const onHide = useCallback(() => setShowDialog(false), [])
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Fragment>
|
<Fragment>
|
||||||
|
@ -43,25 +60,16 @@ export const DropdownItemWithDeletionModal: React.FC<DropdownItemWithDeletionMod
|
||||||
<ForkAwesomeIcon icon={modalIcon} fixedWidth={true} className='mx-2' />
|
<ForkAwesomeIcon icon={modalIcon} fixedWidth={true} className='mx-2' />
|
||||||
<Trans i18nKey={itemI18nKey} />
|
<Trans i18nKey={itemI18nKey} />
|
||||||
</Dropdown.Item>
|
</Dropdown.Item>
|
||||||
<DeletionModal
|
<DeleteNoteModal
|
||||||
onConfirm={() => {
|
optionalNoteTitle={noteTitle}
|
||||||
setShowDialog(false)
|
onConfirm={handleConfirm}
|
||||||
onConfirm()
|
|
||||||
}}
|
|
||||||
deletionButtonI18nKey={modalButtonI18nKey}
|
|
||||||
show={showDialog}
|
show={showDialog}
|
||||||
onHide={() => setShowDialog(false)}
|
onHide={onHide}
|
||||||
title={modalTitleI18nKey}>
|
modalTitleI18nKey={modalTitleI18nKey}
|
||||||
<h5>
|
modalButtonI18nKey={modalButtonI18nKey}
|
||||||
<Trans i18nKey={modalQuestionI18nKey} />
|
modalQuestionI18nKey={modalQuestionI18nKey}
|
||||||
</h5>
|
modalWarningI18nKey={modalWarningI18nKey}
|
||||||
<ul>
|
/>
|
||||||
<li>{noteTitle}</li>
|
|
||||||
</ul>
|
|
||||||
<h6>
|
|
||||||
<Trans i18nKey={modalWarningI18nKey} />
|
|
||||||
</h6>
|
|
||||||
</DeletionModal>
|
|
||||||
</Fragment>
|
</Fragment>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
@ -72,7 +72,7 @@ export const HistoryCard: React.FC<HistoryEntryProps & HistoryEventHandlers> = (
|
||||||
<div className={'d-flex flex-column'}>
|
<div className={'d-flex flex-column'}>
|
||||||
<EntryMenu
|
<EntryMenu
|
||||||
id={entry.identifier}
|
id={entry.identifier}
|
||||||
title={entry.title}
|
title={entryTitle}
|
||||||
origin={entry.origin}
|
origin={entry.origin}
|
||||||
isDark={false}
|
isDark={false}
|
||||||
onRemove={onRemove}
|
onRemove={onRemove}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue