mirror of
https://github.com/hedgedoc/hedgedoc.git
synced 2024-11-25 11:16:31 -05:00
Add boolean state hook
Signed-off-by: Tilman Vatteroth <git@tilmanvatteroth.de>
This commit is contained in:
parent
311d37b16f
commit
50d2dee9d2
15 changed files with 114 additions and 118 deletions
|
@ -1,20 +1,20 @@
|
|||
/*
|
||||
* SPDX-FileCopyrightText: 2021 The HedgeDoc developers (see AUTHORS file)
|
||||
* SPDX-FileCopyrightText: 2022 The HedgeDoc developers (see AUTHORS file)
|
||||
*
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
|
||||
import React, { Fragment, useCallback, useState } from 'react'
|
||||
import React, { Fragment } from 'react'
|
||||
import { Button } from 'react-bootstrap'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import { ForkAwesomeIcon } from '../../../common/fork-awesome/fork-awesome-icon'
|
||||
import { HelpModal } from './help-modal'
|
||||
import { cypressId } from '../../../../utils/cypress-attribute'
|
||||
import { useBooleanState } from '../../../../hooks/common/use-boolean-state'
|
||||
|
||||
export const HelpButton: React.FC = () => {
|
||||
const { t } = useTranslation()
|
||||
const [show, setShow] = useState(false)
|
||||
const onHide = useCallback(() => setShow(false), [])
|
||||
const [modalVisibility, showModal, closeModal] = useBooleanState()
|
||||
|
||||
return (
|
||||
<Fragment>
|
||||
|
@ -24,10 +24,10 @@ export const HelpButton: React.FC = () => {
|
|||
className='ml-2 text-secondary'
|
||||
size='sm'
|
||||
variant='outline-light'
|
||||
onClick={() => setShow(true)}>
|
||||
onClick={showModal}>
|
||||
<ForkAwesomeIcon icon='question-circle' />
|
||||
</Button>
|
||||
<HelpModal show={show} onHide={onHide} />
|
||||
<HelpModal show={modalVisibility} onHide={closeModal} />
|
||||
</Fragment>
|
||||
)
|
||||
}
|
||||
|
|
|
@ -1,33 +1,33 @@
|
|||
/*
|
||||
* SPDX-FileCopyrightText: 2021 The HedgeDoc developers (see AUTHORS file)
|
||||
* SPDX-FileCopyrightText: 2022 The HedgeDoc developers (see AUTHORS file)
|
||||
*
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
|
||||
import React, { useCallback, useEffect, useRef, useState } from 'react'
|
||||
import React, { useEffect, useRef } from 'react'
|
||||
import { MaxLengthWarningModal } from './max-length-warning-modal'
|
||||
import { useNoteMarkdownContent } from '../../../../hooks/common/use-note-markdown-content'
|
||||
import { useApplicationState } from '../../../../hooks/common/use-application-state'
|
||||
import { useBooleanState } from '../../../../hooks/common/use-boolean-state'
|
||||
|
||||
/**
|
||||
* Watches the length of the document and shows a warning modal to the user if the document length exceeds the configured value.
|
||||
*/
|
||||
export const MaxLengthWarning: React.FC = () => {
|
||||
const [showMaxLengthWarningModal, setShowMaxLengthWarningModal] = useState(false)
|
||||
const [modalVisibility, showModal, closeModal] = useBooleanState()
|
||||
const maxLengthWarningAlreadyShown = useRef(false)
|
||||
const maxDocumentLength = useApplicationState((state) => state.config.maxDocumentLength)
|
||||
const hideWarning = useCallback(() => setShowMaxLengthWarningModal(false), [])
|
||||
const markdownContent = useNoteMarkdownContent()
|
||||
|
||||
useEffect(() => {
|
||||
if (markdownContent.length > maxDocumentLength && !maxLengthWarningAlreadyShown.current) {
|
||||
setShowMaxLengthWarningModal(true)
|
||||
showModal()
|
||||
maxLengthWarningAlreadyShown.current = true
|
||||
}
|
||||
if (markdownContent.length <= maxDocumentLength) {
|
||||
maxLengthWarningAlreadyShown.current = false
|
||||
}
|
||||
}, [markdownContent, maxDocumentLength])
|
||||
}, [markdownContent, maxDocumentLength, showModal])
|
||||
|
||||
return <MaxLengthWarningModal show={showMaxLengthWarningModal} onHide={hideWarning} />
|
||||
return <MaxLengthWarningModal show={modalVisibility} onHide={closeModal} />
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* SPDX-FileCopyrightText: 2021 The HedgeDoc developers (see AUTHORS file)
|
||||
* SPDX-FileCopyrightText: 2022 The HedgeDoc developers (see AUTHORS file)
|
||||
*
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
|
@ -12,30 +12,27 @@ import type {
|
|||
} from '../../render-page/window-post-message-communicator/rendering-message'
|
||||
import { CommunicationMessageType } from '../../render-page/window-post-message-communicator/rendering-message'
|
||||
import { useEditorReceiveHandler } from '../../render-page/window-post-message-communicator/hooks/use-editor-receive-handler'
|
||||
import { useBooleanState } from '../../../hooks/common/use-boolean-state'
|
||||
|
||||
export const CommunicatorImageLightbox: React.FC = () => {
|
||||
const [lightboxDetails, setLightboxDetails] = useState<ImageDetails | undefined>(undefined)
|
||||
const [show, setShow] = useState<boolean>(false)
|
||||
const [modalVisibility, showModal, closeModal] = useBooleanState()
|
||||
|
||||
useEditorReceiveHandler(
|
||||
CommunicationMessageType.IMAGE_CLICKED,
|
||||
useCallback(
|
||||
(values: ImageClickedMessage) => {
|
||||
setLightboxDetails?.(values.details)
|
||||
setShow(true)
|
||||
showModal()
|
||||
},
|
||||
[setLightboxDetails]
|
||||
[showModal]
|
||||
)
|
||||
)
|
||||
|
||||
const hideLightbox = useCallback(() => {
|
||||
setShow(false)
|
||||
}, [])
|
||||
|
||||
return (
|
||||
<ImageLightboxModal
|
||||
show={show}
|
||||
onHide={hideLightbox}
|
||||
show={modalVisibility}
|
||||
onHide={closeModal}
|
||||
src={lightboxDetails?.src}
|
||||
alt={lightboxDetails?.alt}
|
||||
title={lightboxDetails?.title}
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
/*
|
||||
* SPDX-FileCopyrightText: 2021 The HedgeDoc developers (see AUTHORS file)
|
||||
* SPDX-FileCopyrightText: 2022 The HedgeDoc developers (see AUTHORS file)
|
||||
*
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
|
||||
import type { PropsWithChildren } from 'react'
|
||||
import React, { Fragment, useCallback, useState } from 'react'
|
||||
import React, { Fragment, useCallback } from 'react'
|
||||
import { Trans, useTranslation } from 'react-i18next'
|
||||
import { SidebarButton } from '../sidebar-button/sidebar-button'
|
||||
import type { SpecificSidebarEntryProps } from '../types'
|
||||
|
@ -14,7 +14,7 @@ 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'
|
||||
import { useBooleanState } from '../../../../hooks/common/use-boolean-state'
|
||||
|
||||
/**
|
||||
* Sidebar entry that can be used to delete the current note.
|
||||
|
@ -24,15 +24,11 @@ import { ShowIf } from '../../../common/show-if/show-if'
|
|||
*/
|
||||
export const DeleteNoteSidebarEntry: React.FC<PropsWithChildren<SpecificSidebarEntryProps>> = ({ 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 [modalVisibility, showModal, closeModal] = useBooleanState()
|
||||
const deleteNoteAndCloseDialog = useCallback(() => {
|
||||
deleteNote(noteId)
|
||||
.catch(showErrorNotification('landing.history.error.deleteNote.text'))
|
||||
.finally(() => setShowDialog(false))
|
||||
}, [noteId])
|
||||
deleteNote(noteId).catch(showErrorNotification('landing.history.error.deleteNote.text')).finally(closeModal)
|
||||
}, [closeModal, noteId])
|
||||
|
||||
return (
|
||||
<Fragment>
|
||||
|
@ -41,12 +37,10 @@ export const DeleteNoteSidebarEntry: React.FC<PropsWithChildren<SpecificSidebarE
|
|||
icon={'trash'}
|
||||
className={className}
|
||||
hide={hide}
|
||||
onClick={openDialog}>
|
||||
onClick={showModal}>
|
||||
<Trans i18nKey={'landing.history.menu.deleteNote'} />
|
||||
</SidebarButton>
|
||||
<ShowIf condition={showDialog}>
|
||||
<DeleteNoteModal onHide={closeDialog} onConfirm={deleteNoteAndCloseDialog} show={showDialog} />
|
||||
</ShowIf>
|
||||
<DeleteNoteModal onHide={closeModal} onConfirm={deleteNoteAndCloseDialog} show={modalVisibility} />
|
||||
</Fragment>
|
||||
)
|
||||
}
|
||||
|
|
|
@ -1,18 +1,19 @@
|
|||
/*
|
||||
* SPDX-FileCopyrightText: 2021 The HedgeDoc developers (see AUTHORS file)
|
||||
* SPDX-FileCopyrightText: 2022 The HedgeDoc developers (see AUTHORS file)
|
||||
*
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
|
||||
import React, { Fragment, useState } from 'react'
|
||||
import React, { Fragment } from 'react'
|
||||
import { Trans, useTranslation } from 'react-i18next'
|
||||
import { NoteInfoModal } from '../../document-bar/note-info/note-info-modal'
|
||||
import { SidebarButton } from '../sidebar-button/sidebar-button'
|
||||
import type { SpecificSidebarEntryProps } from '../types'
|
||||
import { cypressId } from '../../../../utils/cypress-attribute'
|
||||
import { useBooleanState } from '../../../../hooks/common/use-boolean-state'
|
||||
|
||||
export const NoteInfoSidebarEntry: React.FC<SpecificSidebarEntryProps> = ({ className, hide }) => {
|
||||
const [showModal, setShowModal] = useState(false)
|
||||
const [modalVisibility, showModal, closeModal] = useBooleanState()
|
||||
useTranslation()
|
||||
|
||||
return (
|
||||
|
@ -21,11 +22,11 @@ export const NoteInfoSidebarEntry: React.FC<SpecificSidebarEntryProps> = ({ clas
|
|||
hide={hide}
|
||||
className={className}
|
||||
icon={'line-chart'}
|
||||
onClick={() => setShowModal(true)}
|
||||
onClick={showModal}
|
||||
{...cypressId('sidebar-btn-document-info')}>
|
||||
<Trans i18nKey={'editor.modal.documentInfo.title'} />
|
||||
</SidebarButton>
|
||||
<NoteInfoModal show={showModal} onHide={() => setShowModal(false)} />
|
||||
<NoteInfoModal show={modalVisibility} onHide={closeModal} />
|
||||
</Fragment>
|
||||
)
|
||||
}
|
||||
|
|
|
@ -1,25 +1,26 @@
|
|||
/*
|
||||
* SPDX-FileCopyrightText: 2021 The HedgeDoc developers (see AUTHORS file)
|
||||
* SPDX-FileCopyrightText: 2022 The HedgeDoc developers (see AUTHORS file)
|
||||
*
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
|
||||
import React, { Fragment, useState } from 'react'
|
||||
import React, { Fragment } from 'react'
|
||||
import { Trans, useTranslation } from 'react-i18next'
|
||||
import { PermissionModal } from '../../document-bar/permissions/permission-modal'
|
||||
import { SidebarButton } from '../sidebar-button/sidebar-button'
|
||||
import type { SpecificSidebarEntryProps } from '../types'
|
||||
import { useBooleanState } from '../../../../hooks/common/use-boolean-state'
|
||||
|
||||
export const PermissionsSidebarEntry: React.FC<SpecificSidebarEntryProps> = ({ className, hide }) => {
|
||||
const [showModal, setShowModal] = useState(false)
|
||||
const [modalVisibility, showModal, closeModal] = useBooleanState()
|
||||
useTranslation()
|
||||
|
||||
return (
|
||||
<Fragment>
|
||||
<SidebarButton hide={hide} className={className} icon={'lock'} onClick={() => setShowModal(true)}>
|
||||
<SidebarButton hide={hide} className={className} icon={'lock'} onClick={showModal}>
|
||||
<Trans i18nKey={'editor.modal.permissions.title'} />
|
||||
</SidebarButton>
|
||||
<PermissionModal show={showModal} onHide={() => setShowModal(false)} />
|
||||
<PermissionModal show={modalVisibility} onHide={closeModal} />
|
||||
</Fragment>
|
||||
)
|
||||
}
|
||||
|
|
|
@ -1,30 +1,25 @@
|
|||
/*
|
||||
* SPDX-FileCopyrightText: 2021 The HedgeDoc developers (see AUTHORS file)
|
||||
* SPDX-FileCopyrightText: 2022 The HedgeDoc developers (see AUTHORS file)
|
||||
*
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
|
||||
import React, { Fragment, useCallback, useState } from 'react'
|
||||
import React, { Fragment } from 'react'
|
||||
import { Trans } from 'react-i18next'
|
||||
import { RevisionModal } from '../../document-bar/revisions/revision-modal'
|
||||
import { SidebarButton } from '../sidebar-button/sidebar-button'
|
||||
import type { SpecificSidebarEntryProps } from '../types'
|
||||
import { useBooleanState } from '../../../../hooks/common/use-boolean-state'
|
||||
|
||||
export const RevisionSidebarEntry: React.FC<SpecificSidebarEntryProps> = ({ className, hide }) => {
|
||||
const [showModal, setShowModal] = useState(false)
|
||||
const onHide = useCallback(() => {
|
||||
setShowModal(false)
|
||||
}, [])
|
||||
const onShow = useCallback(() => {
|
||||
setShowModal(true)
|
||||
}, [])
|
||||
const [modalVisibility, showModal, closeModal] = useBooleanState()
|
||||
|
||||
return (
|
||||
<Fragment>
|
||||
<SidebarButton hide={hide} className={className} icon={'history'} onClick={onShow}>
|
||||
<SidebarButton hide={hide} className={className} icon={'history'} onClick={showModal}>
|
||||
<Trans i18nKey={'editor.modal.revision.title'} />
|
||||
</SidebarButton>
|
||||
<RevisionModal show={showModal} onHide={onHide} />
|
||||
<RevisionModal show={modalVisibility} onHide={closeModal} />
|
||||
</Fragment>
|
||||
)
|
||||
}
|
||||
|
|
|
@ -1,25 +1,26 @@
|
|||
/*
|
||||
* SPDX-FileCopyrightText: 2021 The HedgeDoc developers (see AUTHORS file)
|
||||
* SPDX-FileCopyrightText: 2022 The HedgeDoc developers (see AUTHORS file)
|
||||
*
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
|
||||
import React, { Fragment, useState } from 'react'
|
||||
import React, { Fragment } from 'react'
|
||||
import { Trans, useTranslation } from 'react-i18next'
|
||||
import { ShareModal } from '../../document-bar/share/share-modal'
|
||||
import { SidebarButton } from '../sidebar-button/sidebar-button'
|
||||
import type { SpecificSidebarEntryProps } from '../types'
|
||||
import { useBooleanState } from '../../../../hooks/common/use-boolean-state'
|
||||
|
||||
export const ShareSidebarEntry: React.FC<SpecificSidebarEntryProps> = ({ className, hide }) => {
|
||||
const [showModal, setShowModal] = useState(false)
|
||||
const [modalVisibility, showModal, closeModal] = useBooleanState()
|
||||
useTranslation()
|
||||
|
||||
return (
|
||||
<Fragment>
|
||||
<SidebarButton hide={hide} className={className} icon={'share'} onClick={() => setShowModal(true)}>
|
||||
<SidebarButton hide={hide} className={className} icon={'share'} onClick={showModal}>
|
||||
<Trans i18nKey={'editor.modal.shareLink.title'} />
|
||||
</SidebarButton>
|
||||
<ShareModal show={showModal} onHide={() => setShowModal(false)} />
|
||||
<ShareModal show={modalVisibility} onHide={closeModal} />
|
||||
</Fragment>
|
||||
)
|
||||
}
|
||||
|
|
|
@ -1,16 +1,17 @@
|
|||
/*
|
||||
* SPDX-FileCopyrightText: 2021 The HedgeDoc developers (see AUTHORS file)
|
||||
* SPDX-FileCopyrightText: 2022 The HedgeDoc developers (see AUTHORS file)
|
||||
*
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
|
||||
import React, { Fragment, useCallback, useState } from 'react'
|
||||
import React, { Fragment, useCallback } 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 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'
|
||||
import { useBooleanState } from '../../../hooks/common/use-boolean-state'
|
||||
|
||||
export interface DropdownItemWithDeletionModalProps {
|
||||
onConfirm: () => void
|
||||
|
@ -47,24 +48,24 @@ export const DropdownItemWithDeletionModal: React.FC<
|
|||
className
|
||||
}) => {
|
||||
useTranslation()
|
||||
const [showDialog, setShowDialog] = useState(false)
|
||||
const [modalVisibility, showModal, closeModal] = useBooleanState()
|
||||
|
||||
const handleConfirm = useCallback(() => {
|
||||
setShowDialog(false)
|
||||
closeModal()
|
||||
onConfirm()
|
||||
}, [onConfirm])
|
||||
const onHide = useCallback(() => setShowDialog(false), [])
|
||||
}, [closeModal, onConfirm])
|
||||
|
||||
return (
|
||||
<Fragment>
|
||||
<Dropdown.Item onClick={() => setShowDialog(true)} className={className}>
|
||||
<Dropdown.Item onClick={showModal} className={className}>
|
||||
<ForkAwesomeIcon icon={modalIcon} fixedWidth={true} className='mx-2' />
|
||||
<Trans i18nKey={itemI18nKey} />
|
||||
</Dropdown.Item>
|
||||
<DeleteNoteModal
|
||||
optionalNoteTitle={noteTitle}
|
||||
onConfirm={handleConfirm}
|
||||
show={showDialog}
|
||||
onHide={onHide}
|
||||
show={modalVisibility}
|
||||
onHide={closeModal}
|
||||
modalTitleI18nKey={modalTitleI18nKey}
|
||||
modalButtonI18nKey={modalButtonI18nKey}
|
||||
modalQuestionI18nKey={modalQuestionI18nKey}
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
/*
|
||||
* SPDX-FileCopyrightText: 2021 The HedgeDoc developers (see AUTHORS file)
|
||||
* SPDX-FileCopyrightText: 2022 The HedgeDoc developers (see AUTHORS file)
|
||||
*
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
|
||||
import React, { Fragment, useCallback, useState } from 'react'
|
||||
import React, { Fragment, useCallback } from 'react'
|
||||
import { Button } from 'react-bootstrap'
|
||||
import { Trans, useTranslation } from 'react-i18next'
|
||||
import { ForkAwesomeIcon } from '../../common/fork-awesome/fork-awesome-icon'
|
||||
|
@ -12,36 +12,34 @@ import { DeletionModal } from '../../common/modals/deletion-modal'
|
|||
import { deleteAllHistoryEntries, safeRefreshHistoryState } from '../../../redux/history/methods'
|
||||
import { showErrorNotification } from '../../../redux/ui-notifications/methods'
|
||||
import { cypressId } from '../../../utils/cypress-attribute'
|
||||
import { useBooleanState } from '../../../hooks/common/use-boolean-state'
|
||||
|
||||
export const ClearHistoryButton: React.FC = () => {
|
||||
const { t } = useTranslation()
|
||||
const [show, setShow] = useState(false)
|
||||
|
||||
const handleShow = () => setShow(true)
|
||||
const handleClose = () => setShow(false)
|
||||
const [modalVisibility, showModal, closeModal] = useBooleanState()
|
||||
|
||||
const onConfirm = useCallback(() => {
|
||||
deleteAllHistoryEntries().catch((error: Error) => {
|
||||
showErrorNotification('landing.history.error.deleteEntry.text')(error)
|
||||
safeRefreshHistoryState()
|
||||
})
|
||||
handleClose()
|
||||
}, [])
|
||||
closeModal()
|
||||
}, [closeModal])
|
||||
|
||||
return (
|
||||
<Fragment>
|
||||
<Button
|
||||
variant={'light'}
|
||||
title={t('landing.history.toolbar.clear')}
|
||||
onClick={handleShow}
|
||||
onClick={showModal}
|
||||
{...cypressId('history-clear-button')}>
|
||||
<ForkAwesomeIcon icon={'trash'} />
|
||||
</Button>
|
||||
<DeletionModal
|
||||
onConfirm={onConfirm}
|
||||
deletionButtonI18nKey={'landing.history.toolbar.clear'}
|
||||
show={show}
|
||||
onHide={handleClose}
|
||||
show={modalVisibility}
|
||||
onHide={closeModal}
|
||||
title={'landing.history.modal.clearHistory.title'}>
|
||||
<h5>
|
||||
<Trans i18nKey={'landing.history.modal.clearHistory.question'} />
|
||||
|
|
|
@ -1,25 +1,24 @@
|
|||
/*
|
||||
* SPDX-FileCopyrightText: 2021 The HedgeDoc developers (see AUTHORS file)
|
||||
* SPDX-FileCopyrightText: 2022 The HedgeDoc developers (see AUTHORS file)
|
||||
*
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
|
||||
import React, { Fragment, useCallback, useState } from 'react'
|
||||
import React, { Fragment } from 'react'
|
||||
import { Trans } from 'react-i18next'
|
||||
import { VersionInfoModal } from './version-info-modal'
|
||||
import { cypressId } from '../../../../utils/cypress-attribute'
|
||||
import { useBooleanState } from '../../../../hooks/common/use-boolean-state'
|
||||
|
||||
export const VersionInfoLink: React.FC = () => {
|
||||
const [show, setShow] = useState(false)
|
||||
const closeModal = useCallback(() => setShow(false), [])
|
||||
const showModal = useCallback(() => setShow(true), [])
|
||||
const [modalVisibility, showModal, closeModal] = useBooleanState()
|
||||
|
||||
return (
|
||||
<Fragment>
|
||||
<a {...cypressId('show-version-modal')} href={'#'} className={'text-light'} onClick={showModal}>
|
||||
<Trans i18nKey={'landing.versionInfo.versionInfo'} />
|
||||
</a>
|
||||
<VersionInfoModal onHide={closeModal} show={show} />
|
||||
<VersionInfoModal onHide={closeModal} show={modalVisibility} />
|
||||
</Fragment>
|
||||
)
|
||||
}
|
||||
|
|
|
@ -37,11 +37,7 @@ export const AccessTokenDeletionModal: React.FC<AccessTokenDeletionModalProps> =
|
|||
)
|
||||
})
|
||||
.catch(showErrorNotification('profile.modal.deleteAccessToken.failed'))
|
||||
.finally(() => {
|
||||
if (onHide) {
|
||||
onHide()
|
||||
}
|
||||
})
|
||||
.finally(() => onHide?.())
|
||||
}, [token, onHide])
|
||||
|
||||
return (
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
/*
|
||||
* SPDX-FileCopyrightText: 2021 The HedgeDoc developers (see AUTHORS file)
|
||||
* SPDX-FileCopyrightText: 2022 The HedgeDoc developers (see AUTHORS file)
|
||||
*
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
|
||||
import React, { useCallback, useMemo, useState } from 'react'
|
||||
import React, { useCallback, useMemo } from 'react'
|
||||
import { Col, ListGroup, Row } from 'react-bootstrap'
|
||||
import { cypressId } from '../../../utils/cypress-attribute'
|
||||
import { Trans, useTranslation } from 'react-i18next'
|
||||
|
@ -13,6 +13,7 @@ import { IconButton } from '../../common/icon-button/icon-button'
|
|||
import type { AccessToken } from '../../../api/tokens/types'
|
||||
import { AccessTokenDeletionModal } from './access-token-deletion-modal'
|
||||
import type { AccessTokenUpdateProps } from './profile-access-tokens'
|
||||
import { useBooleanState } from '../../../hooks/common/use-boolean-state'
|
||||
|
||||
export interface AccessTokenListEntryProps {
|
||||
token: AccessToken
|
||||
|
@ -28,16 +29,12 @@ export const AccessTokenListEntry: React.FC<AccessTokenListEntryProps & AccessTo
|
|||
onUpdateList
|
||||
}) => {
|
||||
useTranslation()
|
||||
const [showDeletionModal, setShowDeletionModal] = useState(false)
|
||||
|
||||
const onShowDeletionModal = useCallback(() => {
|
||||
setShowDeletionModal(true)
|
||||
}, [])
|
||||
const [modalVisibility, showModal, closeModal] = useBooleanState()
|
||||
|
||||
const onHideDeletionModal = useCallback(() => {
|
||||
setShowDeletionModal(false)
|
||||
closeModal()
|
||||
onUpdateList()
|
||||
}, [onUpdateList])
|
||||
}, [closeModal, onUpdateList])
|
||||
|
||||
const lastUsed = useMemo(() => {
|
||||
if (!token.lastUsedAt) {
|
||||
|
@ -66,12 +63,12 @@ export const AccessTokenListEntry: React.FC<AccessTokenListEntryProps & AccessTo
|
|||
<IconButton
|
||||
icon='trash-o'
|
||||
variant='danger'
|
||||
onClick={onShowDeletionModal}
|
||||
onClick={showModal}
|
||||
{...cypressId('access-token-delete-button')}
|
||||
/>
|
||||
</Col>
|
||||
</Row>
|
||||
<AccessTokenDeletionModal token={token} show={showDeletionModal} onHide={onHideDeletionModal} />
|
||||
<AccessTokenDeletionModal token={token} show={modalVisibility} onHide={onHideDeletionModal} />
|
||||
</ListGroup.Item>
|
||||
)
|
||||
}
|
||||
|
|
|
@ -1,30 +1,23 @@
|
|||
/*
|
||||
* SPDX-FileCopyrightText: 2021 The HedgeDoc developers (see AUTHORS file)
|
||||
* SPDX-FileCopyrightText: 2022 The HedgeDoc developers (see AUTHORS file)
|
||||
*
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
|
||||
import React, { Fragment, useCallback, useState } from 'react'
|
||||
import React, { Fragment } from 'react'
|
||||
import { Button, Card } from 'react-bootstrap'
|
||||
import { Trans, useTranslation } from 'react-i18next'
|
||||
import { ForkAwesomeIcon } from '../../common/fork-awesome/fork-awesome-icon'
|
||||
import { AccountDeletionModal } from './account-deletion-modal'
|
||||
import { apiUrl } from '../../../utils/api-url'
|
||||
import { useBooleanState } from '../../../hooks/common/use-boolean-state'
|
||||
|
||||
/**
|
||||
* Profile page section that allows to export all data from the account or to delete the account.
|
||||
*/
|
||||
export const ProfileAccountManagement: React.FC = () => {
|
||||
useTranslation()
|
||||
const [showDeleteModal, setShowDeleteModal] = useState(false)
|
||||
|
||||
const onShowDeletionModal = useCallback(() => {
|
||||
setShowDeleteModal(true)
|
||||
}, [])
|
||||
|
||||
const onHideDeletionModal = useCallback(() => {
|
||||
setShowDeleteModal(false)
|
||||
}, [])
|
||||
const [modalVisibility, showModal, closeModal] = useBooleanState()
|
||||
|
||||
return (
|
||||
<Fragment>
|
||||
|
@ -37,13 +30,13 @@ export const ProfileAccountManagement: React.FC = () => {
|
|||
<ForkAwesomeIcon icon='cloud-download' fixedWidth={true} className='mx-2' />
|
||||
<Trans i18nKey='profile.exportUserData' />
|
||||
</Button>
|
||||
<Button variant='danger' block onClick={onShowDeletionModal}>
|
||||
<Button variant='danger' block onClick={showModal}>
|
||||
<ForkAwesomeIcon icon='trash' fixedWidth={true} className='mx-2' />
|
||||
<Trans i18nKey='profile.deleteUser' />
|
||||
</Button>
|
||||
</Card.Body>
|
||||
</Card>
|
||||
<AccountDeletionModal show={showDeleteModal} onHide={onHideDeletionModal} />
|
||||
<AccountDeletionModal show={modalVisibility} onHide={closeModal} />
|
||||
</Fragment>
|
||||
)
|
||||
}
|
||||
|
|
23
src/hooks/common/use-boolean-state.ts
Normal file
23
src/hooks/common/use-boolean-state.ts
Normal file
|
@ -0,0 +1,23 @@
|
|||
/*
|
||||
* SPDX-FileCopyrightText: 2022 The HedgeDoc developers (see AUTHORS file)
|
||||
*
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
|
||||
import { useCallback, useState } from 'react'
|
||||
|
||||
/**
|
||||
* Provides a boolean state and two functions that set the boolean to true or false.
|
||||
*
|
||||
* @param initialState The initial value of the state
|
||||
* @return An array containing the state, and two functions that set the state value to true or false.
|
||||
*/
|
||||
export const useBooleanState = (
|
||||
initialState: boolean | (() => boolean) = false
|
||||
): [state: boolean, setToTrue: () => void, setToFalse: () => void] => {
|
||||
const [state, setState] = useState(initialState)
|
||||
const setToFalse = useCallback(() => setState(false), [])
|
||||
const setToTrue = useCallback(() => setState(true), [])
|
||||
|
||||
return [state, setToTrue, setToFalse]
|
||||
}
|
Loading…
Reference in a new issue