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:
Tilman Vatteroth 2022-11-11 11:16:18 +01:00
parent 4e18ce38f3
commit 762a0a850e
No known key found for this signature in database
GPG key ID: B97799103358209B
1051 changed files with 0 additions and 35 deletions

View file

@ -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>
)
}

View file

@ -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>
)
}

View file

@ -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>
)
}

View file

@ -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>
)
}

View file

@ -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>
)
}

View file

@ -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>
)
}

View file

@ -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>
)
}

View file

@ -0,0 +1,9 @@
/*
* SPDX-FileCopyrightText: 2022 The HedgeDoc developers (see AUTHORS file)
*
* SPDX-License-Identifier: AGPL-3.0-only
*/
.highlighted {
color: #b51f08 !important;
}

View file

@ -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>
)
}

View file

@ -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>
)
}

View file

@ -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>
)
}