mirror of
https://github.com/hedgedoc/hedgedoc.git
synced 2025-05-29 14:25:38 -04:00
fix: Move content into to frontend directory
Doing this BEFORE the merge prevents a lot of merge conflicts. Signed-off-by: Tilman Vatteroth <git@tilmanvatteroth.de>
This commit is contained in:
parent
4e18ce38f3
commit
762a0a850e
1051 changed files with 0 additions and 35 deletions
|
@ -0,0 +1,32 @@
|
|||
/*
|
||||
* SPDX-FileCopyrightText: 2022 The HedgeDoc developers (see AUTHORS file)
|
||||
*
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
|
||||
import React, { Fragment } from 'react'
|
||||
import { Trans, useTranslation } from 'react-i18next'
|
||||
import type { SpecificSidebarEntryProps } from '../types'
|
||||
import { SidebarButton } from '../sidebar-button/sidebar-button'
|
||||
import { AliasesModal } from '../../document-bar/aliases/aliases-modal'
|
||||
import { useBooleanState } from '../../../../hooks/common/use-boolean-state'
|
||||
|
||||
/**
|
||||
* Component that shows a button in the editor sidebar for opening the aliases modal.
|
||||
*
|
||||
* @param className Additional CSS classes that should be added to the sidebar button.
|
||||
* @param hide True when the sidebar button should be hidden, False otherwise.
|
||||
*/
|
||||
export const AliasesSidebarEntry: React.FC<SpecificSidebarEntryProps> = ({ className, hide }) => {
|
||||
useTranslation()
|
||||
const [showModal, setShowModal, setHideModal] = useBooleanState(false)
|
||||
|
||||
return (
|
||||
<Fragment>
|
||||
<SidebarButton hide={hide} className={className} icon={'tags'} onClick={setShowModal}>
|
||||
<Trans i18nKey={'editor.modal.aliases.title'} />
|
||||
</SidebarButton>
|
||||
<AliasesModal show={showModal} onHide={setHideModal} />
|
||||
</Fragment>
|
||||
)
|
||||
}
|
|
@ -0,0 +1,32 @@
|
|||
/*
|
||||
* SPDX-FileCopyrightText: 2021 The HedgeDoc developers (see AUTHORS file)
|
||||
*
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
|
||||
import React, { useCallback } from 'react'
|
||||
import sanitize from 'sanitize-filename'
|
||||
import { getGlobalState } from '../../../../redux'
|
||||
import { Trans, useTranslation } from 'react-i18next'
|
||||
import { download } from '../../../common/download/download'
|
||||
import { SidebarButton } from '../sidebar-button/sidebar-button'
|
||||
import { useNoteMarkdownContent } from '../../../../hooks/common/use-note-markdown-content'
|
||||
import { cypressId } from '../../../../utils/cypress-attribute'
|
||||
|
||||
/**
|
||||
* Editor sidebar entry for exporting the markdown content into a local file.
|
||||
*/
|
||||
export const ExportMarkdownSidebarEntry: React.FC = () => {
|
||||
const { t } = useTranslation()
|
||||
const markdownContent = useNoteMarkdownContent()
|
||||
const onClick = useCallback(() => {
|
||||
const sanitized = sanitize(getGlobalState().noteDetails.title)
|
||||
download(markdownContent, `${sanitized !== '' ? sanitized : t('editor.untitledNote')}.md`, 'text/markdown')
|
||||
}, [markdownContent, t])
|
||||
|
||||
return (
|
||||
<SidebarButton {...cypressId('menu-export-markdown')} onClick={onClick} icon={'file-text'}>
|
||||
<Trans i18nKey={'editor.export.markdown-file'} />
|
||||
</SidebarButton>
|
||||
)
|
||||
}
|
|
@ -0,0 +1,61 @@
|
|||
/*
|
||||
* SPDX-FileCopyrightText: 2022 The HedgeDoc developers (see AUTHORS file)
|
||||
*
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
|
||||
import React, { Fragment, useCallback } from 'react'
|
||||
import { Trans, useTranslation } from 'react-i18next'
|
||||
import { ExportMarkdownSidebarEntry } from './export-markdown-sidebar-entry'
|
||||
import { SidebarButton } from '../sidebar-button/sidebar-button'
|
||||
import { SidebarMenu } from '../sidebar-menu/sidebar-menu'
|
||||
import type { SpecificSidebarMenuProps } from '../types'
|
||||
import { DocumentSidebarMenuSelection } from '../types'
|
||||
import { cypressId } from '../../../../utils/cypress-attribute'
|
||||
|
||||
/**
|
||||
* Renders the export menu for the sidebar.
|
||||
*
|
||||
* @param className Additional class names given to the menu button
|
||||
* @param menuId The id of the menu
|
||||
* @param onClick The callback, that should be called when the menu button is pressed
|
||||
* @param selectedMenuId The currently selected menu id
|
||||
*/
|
||||
export const ExportMenuSidebarMenu: React.FC<SpecificSidebarMenuProps> = ({
|
||||
className,
|
||||
menuId,
|
||||
onClick,
|
||||
selectedMenuId
|
||||
}) => {
|
||||
useTranslation()
|
||||
|
||||
const hide = selectedMenuId !== DocumentSidebarMenuSelection.NONE && selectedMenuId !== menuId
|
||||
const expand = selectedMenuId === menuId
|
||||
const onClickHandler = useCallback(() => {
|
||||
onClick(menuId)
|
||||
}, [menuId, onClick])
|
||||
|
||||
return (
|
||||
<Fragment>
|
||||
<SidebarButton
|
||||
{...cypressId('menu-export')}
|
||||
hide={hide}
|
||||
icon={expand ? 'arrow-left' : 'cloud-download'}
|
||||
className={className}
|
||||
onClick={onClickHandler}>
|
||||
<Trans i18nKey={'editor.documentBar.export'} />
|
||||
</SidebarButton>
|
||||
<SidebarMenu expand={expand}>
|
||||
<SidebarButton icon={'github'}>Gist</SidebarButton>
|
||||
<SidebarButton icon={'gitlab'}>Gitlab Snippet</SidebarButton>
|
||||
|
||||
<ExportMarkdownSidebarEntry />
|
||||
|
||||
<SidebarButton icon={'file-code-o'}>HTML</SidebarButton>
|
||||
<SidebarButton icon={'file-code-o'}>
|
||||
<Trans i18nKey='editor.export.rawHtml' />
|
||||
</SidebarButton>
|
||||
</SidebarMenu>
|
||||
</Fragment>
|
||||
)
|
||||
}
|
|
@ -0,0 +1,67 @@
|
|||
/*
|
||||
* SPDX-FileCopyrightText: 2022 The HedgeDoc developers (see AUTHORS file)
|
||||
*
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
|
||||
import React, { Fragment, useCallback, useRef } from 'react'
|
||||
import { Trans, useTranslation } from 'react-i18next'
|
||||
import { SidebarButton } from '../sidebar-button/sidebar-button'
|
||||
import { UploadInput } from '../upload-input'
|
||||
import { cypressId } from '../../../../utils/cypress-attribute'
|
||||
import { useChangeEditorContentCallback } from '../../change-content-context/use-change-editor-content-callback'
|
||||
import { ShowIf } from '../../../common/show-if/show-if'
|
||||
import { FileContentFormat, readFile } from '../../../../utils/read-file'
|
||||
|
||||
/**
|
||||
* Renders a sidebar entry that allows to import the content of markdown files into the currently opened note.
|
||||
*/
|
||||
export const ImportMarkdownSidebarEntry: React.FC = () => {
|
||||
useTranslation()
|
||||
const changeEditorContent = useChangeEditorContentCallback()
|
||||
|
||||
const onImportMarkdown = useCallback(
|
||||
async (file: File): Promise<void> => {
|
||||
const content = await readFile(file, FileContentFormat.TEXT)
|
||||
changeEditorContent?.(({ markdownContent }) => {
|
||||
const newContent = (markdownContent.length === 0 ? '' : '\n') + content
|
||||
return [
|
||||
[
|
||||
{
|
||||
from: markdownContent.length,
|
||||
to: markdownContent.length,
|
||||
insert: newContent
|
||||
}
|
||||
],
|
||||
undefined
|
||||
]
|
||||
})
|
||||
},
|
||||
[changeEditorContent]
|
||||
)
|
||||
|
||||
const clickRef = useRef<() => void>()
|
||||
const buttonClick = useCallback(() => {
|
||||
clickRef.current?.()
|
||||
}, [])
|
||||
|
||||
return (
|
||||
<Fragment>
|
||||
<SidebarButton
|
||||
{...cypressId('menu-import-markdown-button')}
|
||||
icon={'file-text-o'}
|
||||
onClick={buttonClick}
|
||||
disabled={!changeEditorContent}>
|
||||
<Trans i18nKey={'editor.import.file'} />
|
||||
</SidebarButton>
|
||||
<ShowIf condition={!!changeEditorContent}>
|
||||
<UploadInput
|
||||
onLoad={onImportMarkdown}
|
||||
{...cypressId('menu-import-markdown-input')}
|
||||
allowedFileTypes={'.md, text/markdown, text/plain'}
|
||||
onClickRef={clickRef}
|
||||
/>
|
||||
</ShowIf>
|
||||
</Fragment>
|
||||
)
|
||||
}
|
|
@ -0,0 +1,58 @@
|
|||
/*
|
||||
* SPDX-FileCopyrightText: 2022 The HedgeDoc developers (see AUTHORS file)
|
||||
*
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
|
||||
import React, { Fragment, useCallback } from 'react'
|
||||
import { Trans, useTranslation } from 'react-i18next'
|
||||
import { ImportMarkdownSidebarEntry } from './import-markdown-sidebar-entry'
|
||||
import { SidebarButton } from '../sidebar-button/sidebar-button'
|
||||
import { SidebarMenu } from '../sidebar-menu/sidebar-menu'
|
||||
import type { SpecificSidebarMenuProps } from '../types'
|
||||
import { DocumentSidebarMenuSelection } from '../types'
|
||||
import { cypressId } from '../../../../utils/cypress-attribute'
|
||||
|
||||
/**
|
||||
* Renders the import menu for the sidebar.
|
||||
*
|
||||
* @param className Additional class names given to the menu button
|
||||
* @param menuId The id of the menu
|
||||
* @param onClick The callback, that should be called when the menu button is pressed
|
||||
* @param selectedMenuId The currently selected menu id
|
||||
*/
|
||||
export const ImportMenuSidebarMenu: React.FC<SpecificSidebarMenuProps> = ({
|
||||
className,
|
||||
menuId,
|
||||
onClick,
|
||||
selectedMenuId
|
||||
}) => {
|
||||
useTranslation()
|
||||
|
||||
const hide = selectedMenuId !== DocumentSidebarMenuSelection.NONE && selectedMenuId !== menuId
|
||||
const expand = selectedMenuId === menuId
|
||||
const onClickHandler = useCallback(() => {
|
||||
onClick(menuId)
|
||||
}, [menuId, onClick])
|
||||
|
||||
return (
|
||||
<Fragment>
|
||||
<SidebarButton
|
||||
{...cypressId('menu-import')}
|
||||
hide={hide}
|
||||
icon={expand ? 'arrow-left' : 'cloud-upload'}
|
||||
className={className}
|
||||
onClick={onClickHandler}>
|
||||
<Trans i18nKey={'editor.documentBar.import'} />
|
||||
</SidebarButton>
|
||||
<SidebarMenu expand={expand}>
|
||||
<SidebarButton icon={'github'}>Gist</SidebarButton>
|
||||
<SidebarButton icon={'gitlab'}>Gitlab Snippet</SidebarButton>
|
||||
<SidebarButton icon={'clipboard'}>
|
||||
<Trans i18nKey={'editor.import.clipboard'} />
|
||||
</SidebarButton>
|
||||
<ImportMarkdownSidebarEntry />
|
||||
</SidebarMenu>
|
||||
</Fragment>
|
||||
)
|
||||
}
|
|
@ -0,0 +1,38 @@
|
|||
/*
|
||||
* SPDX-FileCopyrightText: 2022 The HedgeDoc developers (see AUTHORS file)
|
||||
*
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
|
||||
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'
|
||||
|
||||
/**
|
||||
* Sidebar entry that allows to open the {@link NoteInfoModal} containing information about the current note.
|
||||
*
|
||||
* @param className CSS classes to add to the sidebar button
|
||||
* @param hide true when the sidebar button should be hidden, false otherwise
|
||||
*/
|
||||
export const NoteInfoSidebarEntry: React.FC<SpecificSidebarEntryProps> = ({ className, hide }) => {
|
||||
const [modalVisibility, showModal, closeModal] = useBooleanState()
|
||||
useTranslation()
|
||||
|
||||
return (
|
||||
<Fragment>
|
||||
<SidebarButton
|
||||
hide={hide}
|
||||
className={className}
|
||||
icon={'line-chart'}
|
||||
onClick={showModal}
|
||||
{...cypressId('sidebar-btn-document-info')}>
|
||||
<Trans i18nKey={'editor.modal.documentInfo.title'} />
|
||||
</SidebarButton>
|
||||
<NoteInfoModal show={modalVisibility} onHide={closeModal} />
|
||||
</Fragment>
|
||||
)
|
||||
}
|
|
@ -0,0 +1,32 @@
|
|||
/*
|
||||
* SPDX-FileCopyrightText: 2022 The HedgeDoc developers (see AUTHORS file)
|
||||
*
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
|
||||
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'
|
||||
|
||||
/**
|
||||
* Renders a button to open the permission modal for the sidebar.
|
||||
*
|
||||
* @param className Additional classes directly given to the button
|
||||
* @param hide If the button should be hidden
|
||||
*/
|
||||
export const PermissionsSidebarEntry: React.FC<SpecificSidebarEntryProps> = ({ className, hide }) => {
|
||||
const [modalVisibility, showModal, closeModal] = useBooleanState()
|
||||
useTranslation()
|
||||
|
||||
return (
|
||||
<Fragment>
|
||||
<SidebarButton hide={hide} className={className} icon={'lock'} onClick={showModal}>
|
||||
<Trans i18nKey={'editor.modal.permissions.title'} />
|
||||
</SidebarButton>
|
||||
<PermissionModal show={modalVisibility} onHide={closeModal} />
|
||||
</Fragment>
|
||||
)
|
||||
}
|
|
@ -0,0 +1,9 @@
|
|||
/*
|
||||
* SPDX-FileCopyrightText: 2022 The HedgeDoc developers (see AUTHORS file)
|
||||
*
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
|
||||
.highlighted {
|
||||
color: #b51f08 !important;
|
||||
}
|
|
@ -0,0 +1,49 @@
|
|||
/*
|
||||
* SPDX-FileCopyrightText: 2022 The HedgeDoc developers (see AUTHORS file)
|
||||
*
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
|
||||
import React, { useCallback, useMemo } from 'react'
|
||||
import { Trans, useTranslation } from 'react-i18next'
|
||||
import { SidebarButton } from '../sidebar-button/sidebar-button'
|
||||
import type { SpecificSidebarEntryProps } from '../types'
|
||||
import { toggleHistoryEntryPinning } from '../../../../redux/history/methods'
|
||||
import { useApplicationState } from '../../../../hooks/common/use-application-state'
|
||||
import styles from './pin-note-sidebar-entry.module.css'
|
||||
import { useUiNotifications } from '../../../notifications/ui-notification-boundary'
|
||||
|
||||
/**
|
||||
* Sidebar entry button that toggles the pinned status of the current note in the history.
|
||||
*
|
||||
* @param className CSS classes to add to the sidebar button
|
||||
* @param hide true when the sidebar button should be hidden, false otherwise
|
||||
*/
|
||||
export const PinNoteSidebarEntry: React.FC<SpecificSidebarEntryProps> = ({ className, hide }) => {
|
||||
useTranslation()
|
||||
const id = useApplicationState((state) => state.noteDetails.id)
|
||||
const history = useApplicationState((state) => state.history)
|
||||
const { showErrorNotification } = useUiNotifications()
|
||||
|
||||
const isPinned = useMemo(() => {
|
||||
const entry = history.find((entry) => entry.identifier === id)
|
||||
if (!entry) {
|
||||
return false
|
||||
}
|
||||
return entry.pinStatus
|
||||
}, [id, history])
|
||||
|
||||
const onPinClicked = useCallback(() => {
|
||||
toggleHistoryEntryPinning(id).catch(showErrorNotification('landing.history.error.updateEntry.text'))
|
||||
}, [id, showErrorNotification])
|
||||
|
||||
return (
|
||||
<SidebarButton
|
||||
icon={'thumb-tack'}
|
||||
hide={hide}
|
||||
onClick={onPinClicked}
|
||||
className={`${className ?? ''} ${isPinned ? styles['highlighted'] : ''}`}>
|
||||
<Trans i18nKey={isPinned ? 'editor.documentBar.pinnedToHistory' : 'editor.documentBar.pinNoteToHistory'} />
|
||||
</SidebarButton>
|
||||
)
|
||||
}
|
|
@ -0,0 +1,31 @@
|
|||
/*
|
||||
* SPDX-FileCopyrightText: 2022 The HedgeDoc developers (see AUTHORS file)
|
||||
*
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
|
||||
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'
|
||||
|
||||
/**
|
||||
* Renders a button to open the revision modal for the sidebar.
|
||||
*
|
||||
* @param className Additional classes directly given to the button
|
||||
* @param hide If the button should be hidden
|
||||
*/
|
||||
export const RevisionSidebarEntry: React.FC<SpecificSidebarEntryProps> = ({ className, hide }) => {
|
||||
const [modalVisibility, showModal, closeModal] = useBooleanState()
|
||||
|
||||
return (
|
||||
<Fragment>
|
||||
<SidebarButton hide={hide} className={className} icon={'history'} onClick={showModal}>
|
||||
<Trans i18nKey={'editor.modal.revision.title'} />
|
||||
</SidebarButton>
|
||||
<RevisionModal show={modalVisibility} onHide={closeModal} />
|
||||
</Fragment>
|
||||
)
|
||||
}
|
|
@ -0,0 +1,32 @@
|
|||
/*
|
||||
* SPDX-FileCopyrightText: 2022 The HedgeDoc developers (see AUTHORS file)
|
||||
*
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
|
||||
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'
|
||||
|
||||
/**
|
||||
* Renders a button to open the share modal for the sidebar.
|
||||
*
|
||||
* @param className Additional classes directly given to the button
|
||||
* @param hide If the button should be hidden
|
||||
*/
|
||||
export const ShareSidebarEntry: React.FC<SpecificSidebarEntryProps> = ({ className, hide }) => {
|
||||
const [modalVisibility, showModal, closeModal] = useBooleanState()
|
||||
useTranslation()
|
||||
|
||||
return (
|
||||
<Fragment>
|
||||
<SidebarButton hide={hide} className={className} icon={'share'} onClick={showModal}>
|
||||
<Trans i18nKey={'editor.modal.shareLink.title'} />
|
||||
</SidebarButton>
|
||||
<ShareModal show={modalVisibility} onHide={closeModal} />
|
||||
</Fragment>
|
||||
)
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue