Restructure repository (#426)

organized repository 

Signed-off-by: Tilman Vatteroth <tilman.vatteroth@tu-dortmund.de>
Co-authored-by: Tilman Vatteroth <tilman.vatteroth@tu-dortmund.de>
Co-authored-by: Philip Molares <git@molar.es>
This commit is contained in:
mrdrogdrog 2020-08-16 16:02:26 +02:00 committed by GitHub
parent 66258ca615
commit 0fadc09f2b
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
254 changed files with 384 additions and 403 deletions

View file

@ -1,6 +1,5 @@
import { RegisterError } from '../components/landing/pages/register/register'
import { expectResponseCode, getApiUrl } from '../utils/apiUtils'
import { defaultFetchConfig } from './default'
import { RegisterError } from '../../components/register-page/register-page'
import { expectResponseCode, getApiUrl, defaultFetchConfig } from '../utils'
export const doInternalLogin = async (username: string, password: string): Promise<void> => {
const response = await fetch(getApiUrl() + '/auth/internal', {

View file

@ -1,5 +1,4 @@
import { expectResponseCode, getApiUrl } from '../../utils/apiUtils'
import { defaultFetchConfig } from '../default'
import { expectResponseCode, getApiUrl, defaultFetchConfig } from '../utils'
import { Config } from './types'
export const getConfig = async (): Promise<Config> => {

View file

@ -1,10 +0,0 @@
export const defaultFetchConfig: Partial<RequestInit> = {
mode: 'cors',
cache: 'no-cache',
credentials: 'same-origin',
headers: {
'Content-Type': 'application/json'
},
redirect: 'follow',
referrerPolicy: 'no-referrer'
}

View file

@ -1,6 +1,6 @@
import { HistoryEntry } from '../components/landing/pages/history/history'
import { expectResponseCode, getApiUrl } from '../utils/apiUtils'
import { defaultFetchConfig } from './default'
import { expectResponseCode, getApiUrl, defaultFetchConfig } from '../utils'
import { HistoryEntry } from '../../components/history-page/history-page'
export const getHistory = async (): Promise<HistoryEntry[]> => {
const response = await fetch(getApiUrl() + '/history')

View file

@ -1,6 +1,5 @@
import { LoginProvider } from '../redux/user/types'
import { expectResponseCode, getApiUrl } from '../utils/apiUtils'
import { defaultFetchConfig } from './default'
import { LoginProvider } from '../../redux/user/types'
import { expectResponseCode, getApiUrl, defaultFetchConfig } from '../utils'
export const getMe = async (): Promise<meResponse> => {
const response = await fetch(getApiUrl() + '/me', {

View file

@ -1,6 +1,5 @@
import { ImageProxyResponse } from '../components/editor/markdown-renderer/replace-components/image/types'
import { expectResponseCode, getApiUrl } from '../utils/apiUtils'
import { defaultFetchConfig } from './default'
import { ImageProxyResponse } from '../../components/markdown-renderer/replace-components/image/types'
import { expectResponseCode, getApiUrl, defaultFetchConfig } from '../utils'
export const getProxiedUrl = async (imageUrl: string): Promise<ImageProxyResponse> => {
const response = await fetch(getApiUrl() + '/media/proxy', {

View file

@ -1,5 +1,4 @@
import { expectResponseCode, getApiUrl } from '../utils/apiUtils'
import { defaultFetchConfig } from './default'
import { defaultFetchConfig, expectResponseCode, getApiUrl } from '../utils'
interface LastChange {
userId: string

22
src/api/utils.ts Normal file
View file

@ -0,0 +1,22 @@
import { store } from '../redux'
export const defaultFetchConfig: Partial<RequestInit> = {
mode: 'cors',
cache: 'no-cache',
credentials: 'same-origin',
headers: {
'Content-Type': 'application/json'
},
redirect: 'follow',
referrerPolicy: 'no-referrer'
}
export const getApiUrl = (): string => {
return store.getState().apiUrl.apiUrl
}
export const expectResponseCode = (response: Response, code = 200): void => {
if (response.status !== code) {
throw new Error(`response code is not ${code}`)
}
}

View file

@ -2,7 +2,7 @@ import { getConfig } from '../../../api/config'
import { setApiUrl } from '../../../redux/api-url/methods'
import { setBanner } from '../../../redux/banner/methods'
import { setConfig } from '../../../redux/config/methods'
import { getAndSetUser } from '../../../utils/apiUtils'
import { getAndSetUser } from '../../login-page/auth/utils'
export const loadAllConfig: (baseUrl: string) => Promise<void> = async (baseUrl) => {
setApiUrl({

View file

@ -1,28 +0,0 @@
import React, { Fragment } from 'react'
import { ShowIf } from '../show-if/show-if'
export interface ElementSeparatorProps {
separator: React.ReactElement
}
export const ElementSeparator: React.FC<ElementSeparatorProps> = ({ children, separator }) => {
return (
<Fragment>
{
React.Children
.toArray(children)
.filter(child => child !== null)
.map((child, index) => {
return (
<Fragment>
<ShowIf condition={index > 0}>
{separator}
</ShowIf>
{child}
</Fragment>
)
})
}
</Fragment>
)
}

View file

@ -1,11 +1,17 @@
.btn-icon {
padding: 0.375rem 0.375rem;
border-right: 1px solid rgba(0, 0, 0, 0.2);
display: flex;
&.with-border {
.icon-part {
border-right: 1px solid rgba(0, 0, 0, 0.2);
}
.text-part {
padding: 0.375rem 0.75rem;
}
}
.icon-part {
padding: 0.375rem 0.375rem;
border-right: 1px solid rgba(0, 0, 0, 0.2);
display: flex;
.social-icon {
@ -14,7 +20,7 @@
}
.text-part {
padding: 0.375rem 0.75rem;
padding: 0.375rem 0.75rem 0.375rem 0;
}
}

View file

@ -3,15 +3,15 @@ import { Button, ButtonProps } from 'react-bootstrap'
import { ForkAwesomeIcon, IconName } from '../fork-awesome/fork-awesome-icon'
import './icon-button.scss'
export interface SocialButtonProps extends ButtonProps {
export interface IconButtonProps extends ButtonProps {
icon: IconName
onClick?: () => void
border?: boolean
}
export const IconButton: React.FC<SocialButtonProps> = ({ icon, children, variant, onClick }) => {
export const IconButton: React.FC<IconButtonProps> = ({ icon, children, border = false, ...props }) => {
return (
<Button variant={variant} className={'btn-icon p-0 d-inline-flex align-items-stretch'}
onClick={() => onClick?.()}>
<Button {...props} className={`btn-icon p-0 d-inline-flex align-items-stretch ${border ? 'with-border' : ''}`}>
<span className="icon-part d-flex align-items-center">
<ForkAwesomeIcon icon={icon} className={'icon'}/>
</span>

View file

@ -0,0 +1,16 @@
import React from 'react'
import { Trans } from 'react-i18next'
import './icon-button.scss'
import { IconButton, IconButtonProps } from './icon-button'
export interface TranslatedIconButton extends IconButtonProps {
i18nKey: string
}
export const TranslatedIconButton: React.FC<TranslatedIconButton> = ({ i18nKey, ...props }) => {
return (
<IconButton {...props}>
<Trans i18nKey={i18nKey}/>
</IconButton>
)
}

View file

@ -4,10 +4,10 @@ import { Link } from 'react-router-dom'
import { ApplicationState } from '../../../redux'
import { Alert, Button } from 'react-bootstrap'
import { setBanner } from '../../../redux/banner/methods'
import { ForkAwesomeIcon } from '../../common/fork-awesome/fork-awesome-icon'
import { ShowIf } from '../../common/show-if/show-if'
import { ForkAwesomeIcon } from '../fork-awesome/fork-awesome-icon'
import { ShowIf } from '../show-if/show-if'
export const InfoBanner: React.FC = () => {
export const MotdBanner: React.FC = () => {
const bannerState = useSelector((state: ApplicationState) => state.banner)
const dismissBanner = () => {

View file

@ -1,7 +1,7 @@
import React from 'react'
import { LandingLayout } from '../landing/landing-layout'
import { LandingLayout } from '../../landing-layout/landing-layout'
export const NotFound: React.FC = () => {
export const NotFoundErrorScreen: React.FC = () => {
return (
<LandingLayout>
<div className='text-white d-flex align-items-center justify-content-center my-5'>

View file

@ -1,8 +1,8 @@
import React, { useEffect, useState } from 'react'
import { Redirect } from 'react-router'
import { useParams } from 'react-router-dom'
import { getNote } from '../../api/note'
import { NotFound } from '../error/not-found'
import { getNote } from '../../../api/notes'
import { NotFoundErrorScreen } from './not-found-error-screen'
interface RouteParameters {
id: string
@ -19,7 +19,7 @@ export const Redirector: React.FC = () => {
}, [id])
if (error) {
return (<NotFound/>)
return (<NotFoundErrorScreen/>)
} else if (!error && error != null) {
return (<Redirect to={`/n/${id}`}/>)
} else {

View file

@ -1,6 +1,6 @@
import React from 'react'
import { useTranslation } from 'react-i18next'
import { ShowIf } from '../../../common/show-if/show-if'
import { ShowIf } from '../show-if/show-if'
import './user-avatar.scss'
export interface UserAvatarProps {

View file

@ -5,17 +5,17 @@ import { useSelector } from 'react-redux'
import { useParams } from 'react-router'
import { Link } from 'react-router-dom'
import { ApplicationState } from '../../../redux'
import { Branding } from '../../common/branding/branding'
import { ForkAwesomeIcon } from '../../common/fork-awesome/fork-awesome-icon'
import { ShowIf } from '../../common/show-if/show-if'
import { SignInButton } from '../../landing/layout/navigation/sign-in-button'
import { UserDropdown } from '../../landing/layout/navigation/user-dropdown/user-dropdown'
import { SignInButton } from '../../landing-layout/navigation/sign-in-button'
import { UserDropdown } from '../../landing-layout/navigation/user-dropdown'
import { EditorPathParams } from '../editor'
import { DarkModeButton } from './dark-mode-button'
import { EditorViewMode } from './editor-view-mode'
import { HelpButton } from './help-button'
import { NavbarBranding } from './navbar-branding'
export const TaskBar: React.FC = () => {
export const AppBar: React.FC = () => {
const { t } = useTranslation()
const { id } = useParams<EditorPathParams>()
const user = useSelector((state: ApplicationState) => state.user)
@ -23,13 +23,7 @@ export const TaskBar: React.FC = () => {
return (
<Navbar bg={'light'}>
<Nav className="mr-auto d-flex align-items-center">
<Navbar.Brand>
<Link to="/intro" className="text-secondary text-decoration-none d-flex align-items-center">
<ForkAwesomeIcon icon="file-text" className={'mr-2'}/>
<span>CodiMD</span>
<Branding inline={true}/>
</Link>
</Navbar.Brand>
<NavbarBranding/>
<EditorViewMode/>
<DarkModeButton/>
<Link to={`/p/${id}`} target='_blank'>

View file

@ -0,0 +1,17 @@
import React from 'react'
import { Navbar } from 'react-bootstrap'
import { Link } from 'react-router-dom'
import { Branding } from '../../common/branding/branding'
import { ForkAwesomeIcon } from '../../common/fork-awesome/fork-awesome-icon'
export const NavbarBranding: React.FC = () => {
return (
<Navbar.Brand>
<Link to="/intro" className="text-secondary text-decoration-none d-flex align-items-center">
<ForkAwesomeIcon icon="file-text" className={'mr-2'}/>
<span>CodiMD</span>
<Branding inline={true}/>
</Link>
</Navbar.Brand>
)
}

View file

@ -1,18 +1,14 @@
import React, { Fragment, useState } from 'react'
import { Trans } from 'react-i18next'
import { ForkAwesomeIcon } from '../../common/fork-awesome/fork-awesome-icon'
import { Button, Modal } from 'react-bootstrap'
import { CommonModal } from '../../common/modals/common-modal'
import { Modal } from 'react-bootstrap'
import { CommonModal } from '../../../common/modals/common-modal'
import { TranslatedIconButton } from '../../../common/icon-button/translated-icon-button'
export const PermissionButton: React.FC = () => {
const [showReadOnly, setShowReadOnly] = useState(false)
return (
<Fragment>
<Button variant={'light'} className={'mx-1'} size={'sm'} onClick={() => setShowReadOnly(true)}>
<ForkAwesomeIcon icon={'lock'} className={'mx-1'}/>
<Trans i18nKey={'editor.documentBar.permissions'}/>
</Button>
<TranslatedIconButton size={'sm'} className={'mx-1'} icon={'lock'} variant={'light'} onClick={() => setShowReadOnly(true)} i18nKey={'editor.documentBar.permissions'}/>
<CommonModal
show={showReadOnly}
onHide={() => setShowReadOnly(false)}

View file

@ -0,0 +1,12 @@
import React from 'react'
import { useTranslation } from 'react-i18next'
import { TranslatedIconButton } from '../../../common/icon-button/translated-icon-button'
export const PinToHistoryButton: React.FC = () => {
useTranslation()
const isPinned = true
const i18nKey = isPinned ? 'editor.documentBar.pinNoteToHistory' : 'editor.documentBar.pinnedToHistory'
return <TranslatedIconButton size={'sm'} className={'mx-1'} icon={'thumb-tack'} variant={'light'} i18nKey={i18nKey}/>
}

View file

@ -0,0 +1,6 @@
import React from 'react'
import { TranslatedIconButton } from '../../../common/icon-button/translated-icon-button'
export const RevisionButton: React.FC = () => {
return <TranslatedIconButton size={'sm'} className={'mx-1'} icon={'history'} variant={'light'} i18nKey={'editor.documentBar.revision'}/>
}

View file

@ -1,19 +1,16 @@
import React, { Fragment, useState } from 'react'
import { Button, Modal } from 'react-bootstrap'
import { Modal } from 'react-bootstrap'
import { Trans } from 'react-i18next'
import { CopyableField } from '../../common/copyable-field/copyable-field'
import { ForkAwesomeIcon } from '../../common/fork-awesome/fork-awesome-icon'
import { CommonModal } from '../../common/modals/common-modal'
import { CopyableField } from '../../../common/copyable-field/copyable-field'
import { CommonModal } from '../../../common/modals/common-modal'
import { TranslatedIconButton } from '../../../common/icon-button/translated-icon-button'
export const ShareLinkButton: React.FC = () => {
const [showReadOnly, setShowReadOnly] = useState(false)
return (
<Fragment>
<Button variant={'light'} className={'mx-1'} size={'sm'} onClick={() => setShowReadOnly(true)}>
<ForkAwesomeIcon icon={'share'} className={'mx-1'}/>
<Trans i18nKey={'editor.documentBar.shareLink'}/>
</Button>
<TranslatedIconButton size={'sm'} className={'mx-1'} icon={'share'} variant={'light'} onClick={() => setShowReadOnly(true)} i18nKey={'editor.documentBar.shareLink'}/>
<CommonModal
show={showReadOnly}
onHide={() => setShowReadOnly(false)}

View file

@ -1,5 +1,5 @@
import React, { Fragment } from 'react'
import { UserAvatar } from '../../../landing/layout/user-avatar/user-avatar'
import { UserAvatar } from '../../../common/user-avatar/user-avatar'
import { ActiveIndicator, ActiveIndicatorStatus } from './active-indicator'
import './user-line.scss'

View file

@ -1,14 +1,14 @@
import React from 'react'
import { useTranslation } from 'react-i18next'
import { ConnectionIndicator } from './connection-indicator/connection-indicator'
import { DocumentInfoButton } from './document-info-button'
import { EditorMenu } from './editor-menu'
import { ExportMenu } from './export-menu'
import { ImportMenu } from './import-menu'
import { PermissionButton } from './permission-button'
import { PinToHistoryButton } from './pin-to-history-button'
import { ShareLinkButton } from './share-link-button'
import { RevisionButton } from './revision-button'
import { DocumentInfoButton } from './document-info/document-info-button'
import { EditorMenu } from './menus/editor-menu'
import { ExportMenu } from './menus/export-menu'
import { ImportMenu } from './menus/import-menu'
import { PermissionButton } from './buttons/permission-button'
import { PinToHistoryButton } from './buttons/pin-to-history-button'
import { ShareLinkButton } from './buttons/share-link-button'
import { RevisionButton } from './buttons/revision-button'
export interface DocumentBarProps {
title: string

View file

@ -1,3 +0,0 @@
.font-style-normal {
font-style: normal;
}

View file

@ -1,10 +0,0 @@
import React from 'react'
import './unitalic-bold-text.scss'
export interface BoldTextProps {
text: string ;
}
export const UnitalicBoldText: React.FC<BoldTextProps> = ({ text }) => {
return <b className={'font-style-normal mr-1'}>{text}</b>
}

View file

@ -1,12 +1,12 @@
import moment from 'moment'
import React, { Fragment, useState } from 'react'
import { Button, ListGroup, Modal } from 'react-bootstrap'
import { ListGroup, Modal } from 'react-bootstrap'
import { Trans, useTranslation } from 'react-i18next'
import { ForkAwesomeIcon } from '../../common/fork-awesome/fork-awesome-icon'
import { CommonModal } from '../../common/modals/common-modal'
import { CommonModal } from '../../../common/modals/common-modal'
import { DocumentInfoLine } from './document-info-line'
import { DocumentInfoLineWithTimeMode, DocumentInfoTimeLine } from './document-info-time-line'
import { UnitalicBoldText } from './document-info-time-line-helper/unitalic-bold-text'
import { UnitalicBoldText } from './unitalic-bold-text'
import { TranslatedIconButton } from '../../../common/icon-button/translated-icon-button'
export const DocumentInfoButton: React.FC = () => {
const [showModal, setShowModal] = useState(false)
@ -14,10 +14,7 @@ export const DocumentInfoButton: React.FC = () => {
return (
<Fragment>
<Button variant={'light'} className={'mx-1'} size={'sm'} onClick={() => setShowModal(true)}>
<ForkAwesomeIcon icon={'line-chart'} className={'mx-1'}/>
<Trans i18nKey={'editor.documentBar.documentInfo'}/>
</Button>
<TranslatedIconButton size={'sm'} className={'mx-1'} icon={'line-chart'} variant={'light'} onClick={() => setShowModal(true)} i18nKey={'editor.documentBar.documentInfo'}/>
<CommonModal
show={showModal}
onHide={() => setShowModal(false)}

View file

@ -1,5 +1,5 @@
import React from 'react'
import { ForkAwesomeIcon, IconName } from '../../common/fork-awesome/fork-awesome-icon'
import { ForkAwesomeIcon, IconName } from '../../../common/fork-awesome/fork-awesome-icon'
export interface DocumentInfoLineProps {
icon: IconName

View file

@ -1,11 +1,11 @@
import { Moment } from 'moment'
import React from 'react'
import { Trans, useTranslation } from 'react-i18next'
import { IconName } from '../../common/fork-awesome/fork-awesome-icon'
import { IconName } from '../../../common/fork-awesome/fork-awesome-icon'
import { DocumentInfoLine } from './document-info-line'
import './document-info-time-line.scss'
import { TimeFromNow } from './document-info-time-line-helper/time-from-now'
import { UserAvatar } from '../../landing/layout/user-avatar/user-avatar'
import { TimeFromNow } from './time-from-now'
import { UserAvatar } from '../../../common/user-avatar/user-avatar'
export interface DocumentInfoLineWithTimeProps {
time: Moment,

View file

@ -1,11 +1,11 @@
import { Moment } from 'moment'
import React from 'react'
export interface ItalicTime {
export interface TimeFromNowProps {
time: Moment
}
export const TimeFromNow: React.FC<ItalicTime> = ({ time }) => {
export const TimeFromNow: React.FC<TimeFromNowProps> = ({ time }) => {
return (
<time className={'mx-1'} title={time.format('LLLL')} dateTime={time.format()}>{time.fromNow(true)}</time>
)

View file

@ -0,0 +1,9 @@
import React from 'react'
export interface UnitalicBoldTextProps {
text: string ;
}
export const UnitalicBoldText: React.FC<UnitalicBoldTextProps> = ({ text }) => {
return <b className={'font-style-normal mr-1'}>{text}</b>
}

View file

@ -1,7 +1,7 @@
import React from 'react'
import { Dropdown } from 'react-bootstrap'
import { Trans, useTranslation } from 'react-i18next'
import { DropdownItemWithDeletionModal } from '../../landing/pages/history/common/entry-menu/dropdown-item-with-deletion-modal'
import { DropdownItemWithDeletionModal } from '../../../history-page/entry-menu/dropdown-item-with-deletion-modal'
export interface EditorMenuProps {
noteTitle: string

View file

@ -1,8 +1,8 @@
import React from 'react'
import { Dropdown } from 'react-bootstrap'
import { Trans, useTranslation } from 'react-i18next'
import { ForkAwesomeIcon } from '../../common/fork-awesome/fork-awesome-icon'
import { TranslatedExternalLink } from '../../common/links/translated-external-link'
import { ForkAwesomeIcon } from '../../../common/fork-awesome/fork-awesome-icon'
import { TranslatedExternalLink } from '../../../common/links/translated-external-link'
const ExportMenu: React.FC = () => {
useTranslation()

View file

@ -1,7 +1,7 @@
import React from 'react'
import { Dropdown } from 'react-bootstrap'
import { Trans } from 'react-i18next'
import { ForkAwesomeIcon } from '../../common/fork-awesome/fork-awesome-icon'
import { ForkAwesomeIcon } from '../../../common/fork-awesome/fork-awesome-icon'
export const ImportMenu: React.FC = () => {
return (

View file

@ -1,18 +0,0 @@
import React from 'react'
import { Button } from 'react-bootstrap'
import { Trans, useTranslation } from 'react-i18next'
import { ForkAwesomeIcon } from '../../common/fork-awesome/fork-awesome-icon'
export const PinToHistoryButton: React.FC = () => {
useTranslation()
const isPinned = true
const i18nKey = isPinned ? 'editor.documentBar.pinNoteToHistory' : 'editor.documentBar.pinnedToHistory'
return (
<Button variant={'light'} className={'mx-1'} size={'sm'}>
<ForkAwesomeIcon icon={'thumb-tack'} className={'mx-1'}/>
<Trans i18nKey={i18nKey}/>
</Button>
)
}

View file

@ -1,13 +0,0 @@
import React from 'react'
import { Button } from 'react-bootstrap'
import { Trans } from 'react-i18next'
import { ForkAwesomeIcon } from '../../common/fork-awesome/fork-awesome-icon'
export const RevisionButton: React.FC = () => {
return (
<Button variant={'light'} className={'mx-1'} size={'sm'}>
<ForkAwesomeIcon icon={'history'} className={'mx-1'}/>
<Trans i18nKey={'editor.documentBar.revision'}/>
</Button>
)
}

View file

@ -4,18 +4,18 @@ import useResizeObserver from 'use-resize-observer'
import { TocAst } from '../../../external-types/markdown-it-toc-done-right/interface'
import { ForkAwesomeIcon } from '../../common/fork-awesome/fork-awesome-icon'
import { ShowIf } from '../../common/show-if/show-if'
import { MarkdownRenderer } from '../markdown-renderer/markdown-renderer'
import { MarkdownToc } from '../markdown-toc/markdown-toc'
import { MarkdownRenderer } from '../../markdown-renderer/markdown-renderer'
import { YAMLMetaData } from '../yaml-metadata/yaml-metadata'
import { TableOfContents } from '../table-of-contents/table-of-contents'
interface RenderWindowProps {
interface DocumentRenderPaneProps {
content: string
onMetadataChange: (metaData: YAMLMetaData | undefined) => void
onFirstHeadingChange: (firstHeading: string | undefined) => void
wide?: boolean
}
export const MarkdownRenderWindow: React.FC<RenderWindowProps> = ({ content, onMetadataChange, onFirstHeadingChange, wide }) => {
export const DocumentRenderPane: React.FC<DocumentRenderPaneProps> = ({ content, onMetadataChange, onFirstHeadingChange, wide }) => {
const [tocAst, setTocAst] = useState<TocAst>()
const renderer = useRef<HTMLDivElement>(null)
const { width } = useResizeObserver({ ref: renderer })
@ -36,7 +36,7 @@ export const MarkdownRenderWindow: React.FC<RenderWindowProps> = ({ content, onM
<div className={'col-md'}>
<ShowIf condition={realWidth >= 1280 && !!tocAst}>
<MarkdownToc ast={tocAst as TocAst} sticky={true}/>
<TableOfContents ast={tocAst as TocAst} sticky={true}/>
</ShowIf>
<ShowIf condition={realWidth < 1280 && !!tocAst}>
<div className={'markdown-toc-sidebar-button'}>
@ -46,7 +46,7 @@ export const MarkdownRenderWindow: React.FC<RenderWindowProps> = ({ content, onM
</Dropdown.Toggle>
<Dropdown.Menu>
<div className={'p-2'}>
<MarkdownToc ast={tocAst as TocAst}/>
<TableOfContents ast={tocAst as TocAst}/>
</div>
</Dropdown.Menu>
</Dropdown>

View file

@ -23,19 +23,19 @@ import 'codemirror/mode/gfm/gfm'
import React, { useCallback, useMemo, useState } from 'react'
import { Controlled as ControlledCodeMirror } from 'react-codemirror2'
import { useTranslation } from 'react-i18next'
import './editor-window.scss'
import { emojiHints, emojiWordRegex, findWordAtCursor } from './hints/emoji'
import './editor-pane.scss'
import { generateEmojiHints, emojiWordRegex, findWordAtCursor } from './hints/emoji'
import { defaultKeyMap } from './key-map'
import { createStatusInfo, defaultState, StatusBar, StatusBarInfo } from './status-bar/status-bar'
import { ToolBar } from './tool-bar/tool-bar'
export interface EditorWindowProps {
export interface EditorPaneProps {
onContentChange: (content: string) => void
content: string
}
const hintOptions = {
hint: emojiHints,
hint: generateEmojiHints,
completeSingle: false,
completeOnSingleClick: false,
alignWithWord: true
@ -48,7 +48,7 @@ const onChange = (editor: Editor) => {
}
}
export const EditorWindow: React.FC<EditorWindowProps> = ({ onContentChange, content }) => {
export const EditorPane: React.FC<EditorPaneProps> = ({ onContentChange, content }) => {
const { t } = useTranslation()
const [editor, setEditor] = useState<Editor>()
const [statusBarInfo, setStatusBarInfo] = useState<StatusBarInfo>(defaultState)

View file

@ -1,7 +1,7 @@
import { Editor, Hint, Hints, Pos } from 'codemirror'
import { Data, EmojiData, NimbleEmojiIndex } from 'emoji-mart'
import data from 'emoji-mart/data/twitter.json'
import { getEmojiIcon, getEmojiShortCode } from '../../../../utils/emoji'
import { getEmojiIcon, getEmojiShortCode } from '../tool-bar/utils/emojiUtils'
import { customEmojis } from '../tool-bar/emoji-picker/emoji-picker'
interface findWordAtCursorResponse {
@ -12,7 +12,6 @@ interface findWordAtCursorResponse {
const allowedCharsInEmojiCodeRegex = /(:|\w|-|_|\+)/
const emojiIndex = new NimbleEmojiIndex(data as unknown as Data)
export const emojiWordRegex = /^:((\w|-|_|\+)+)$/
export const findWordAtCursor = (editor: Editor): findWordAtCursorResponse => {
@ -34,7 +33,7 @@ export const findWordAtCursor = (editor: Editor): findWordAtCursorResponse => {
}
}
export const emojiHints = (editor: Editor): Promise< Hints| null > => {
export const generateEmojiHints = (editor: Editor): Promise< Hints| null > => {
return new Promise((resolve) => {
const searchTerm = findWordAtCursor(editor)
const searchResult = emojiWordRegex.exec(searchTerm.text)

View file

@ -5,7 +5,7 @@ import {
markSelection,
strikeThroughSelection,
underlineSelection
} from './tool-bar/utils'
} from './tool-bar/utils/toolbarButtonUtils'
const isMac = navigator.platform.toLowerCase().includes('mac')

View file

@ -2,9 +2,9 @@ import CodeMirror from 'codemirror'
import React, { Fragment, useState } from 'react'
import { Button } from 'react-bootstrap'
import { useTranslation } from 'react-i18next'
import { ForkAwesomeIcon } from '../../../common/fork-awesome/fork-awesome-icon'
import { EmojiPicker } from './emoji-picker/emoji-picker'
import { addEmoji } from './utils'
import { ForkAwesomeIcon } from '../../../../common/fork-awesome/fork-awesome-icon'
import { EmojiPicker } from './emoji-picker'
import { addEmoji } from '../utils/toolbarButtonUtils'
export interface EmojiPickerButtonProps {
editor: CodeMirror.Editor

View file

@ -6,6 +6,7 @@ import { useClickAway } from 'react-use'
import { ShowIf } from '../../../../common/show-if/show-if'
import './emoji-picker.scss'
import { ForkAwesomeIcons } from './icon-names'
import forkawesomeIcon from './forkawesome.png'
export interface EmojiPickerProps {
show: boolean
@ -19,7 +20,7 @@ export const customEmojis: CustomEmoji[] = Object.keys(ForkAwesomeIcons).map((na
text: '',
emoticons: [],
keywords: ['fork awesome'],
imageUrl: '/img/forkawesome.png',
imageUrl: forkawesomeIcon,
customCategory: 'ForkAwesome'
}))

View file

Before

Width:  |  Height:  |  Size: 32 KiB

After

Width:  |  Height:  |  Size: 32 KiB

View file

@ -4,7 +4,7 @@ import { Button, ButtonGroup, ButtonToolbar } from 'react-bootstrap'
import { useTranslation } from 'react-i18next'
import { ForkAwesomeIcon } from '../../../common/fork-awesome/fork-awesome-icon'
import { EditorPreferences } from './editor-preferences/editor-preferences'
import { EmojiPickerButton } from './emoji-picker-button'
import { EmojiPickerButton } from './emoji-picker/emoji-picker-button'
import './tool-bar.scss'
import {
addCodeFences,
@ -24,7 +24,7 @@ import {
subscriptSelection,
superscriptSelection,
underlineSelection
} from './utils'
} from './utils/toolbarButtonUtils'
export interface ToolBarProps {
editor: Editor | undefined

View file

@ -21,7 +21,7 @@ import {
subscriptSelection,
superscriptSelection,
underlineSelection
} from './utils'
} from './toolbarButtonUtils'
Mock.configure('jest')

View file

@ -1,6 +1,6 @@
import { Editor } from 'codemirror'
import { EmojiData } from 'emoji-mart'
import { getEmojiShortCode } from '../../../../utils/emoji'
import { getEmojiShortCode } from './emojiUtils'
export const makeSelectionBold = (editor: Editor): void => wrapTextWith(editor, '**')
export const makeSelectionItalic = (editor: Editor): void => wrapTextWith(editor, '*')

View file

@ -5,15 +5,15 @@ import useMedia from 'use-media'
import { ApplicationState } from '../../redux'
import { setEditorModeConfig } from '../../redux/editor/methods'
import { DocumentTitle } from '../common/document-title/document-title'
import { Splitter } from '../common/splitter/splitter'
import { InfoBanner } from '../landing/layout/info-banner'
import { DocumentRenderPane } from './document-renderer-pane/document-render-pane'
import { EditorPane } from './editor-pane/editor-pane'
import { Splitter } from './splitter/splitter'
import { MotdBanner } from '../common/motd-banner/motd-banner'
import { DocumentBar } from './document-bar/document-bar'
import { EditorWindow } from './editor-window/editor-window'
import { editorTestContent } from './editorTestContent'
import { MarkdownRenderWindow } from './renderer-window/markdown-render-window'
import { EditorMode } from './task-bar/editor-view-mode'
import { TaskBar } from './task-bar/task-bar'
import { YAMLMetaData } from './yaml-metadata/yaml-metadata'
import { AppBar } from './app-bar/app-bar'
import { EditorMode } from './app-bar/editor-view-mode'
export interface EditorPathParams {
id: string
@ -62,21 +62,21 @@ export const Editor: React.FC = () => {
return (
<Fragment>
<InfoBanner/>
<MotdBanner/>
<DocumentTitle title={documentTitle}/>
<div className={'d-flex flex-column vh-100'}>
<TaskBar/>
<AppBar/>
<DocumentBar title={documentTitle}/>
<Splitter
showLeft={editorMode === EditorMode.EDITOR || editorMode === EditorMode.BOTH}
left={
<EditorWindow
<EditorPane
onContentChange={content => setMarkdownContent(content)}
content={markdownContent}/>
}
showRight={editorMode === EditorMode.PREVIEW || (editorMode === EditorMode.BOTH)}
right={
<MarkdownRenderWindow
<DocumentRenderPane
content={markdownContent}
wide={editorMode === EditorMode.PREVIEW}
onMetadataChange={onMetadataChange}

View file

@ -1,6 +1,6 @@
import React, { ReactElement, useRef, useState } from 'react'
import { ShowIf } from '../show-if/show-if'
import { SplitDivider } from '../split-divider/split-divider'
import { ShowIf } from '../../common/show-if/show-if'
import { SplitDivider } from './split-divider/split-divider'
import './splitter.scss'
export interface SplitterProps {

View file

@ -1,15 +1,18 @@
import React, { Fragment, ReactElement, useMemo } from 'react'
import { TocAst } from '../../../external-types/markdown-it-toc-done-right/interface'
import { slugify } from '../../../utils/slugify'
import { ShowIf } from '../../common/show-if/show-if'
import './markdown-toc.scss'
import './table-of-contents.scss'
export interface MarkdownTocProps {
export interface TableOfContentsProps {
ast: TocAst
maxDepth?: number
sticky?: boolean
}
export const slugify = (content:string) => {
return encodeURIComponent(String(content).trim().toLowerCase().replace(/\s+/g, '-'))
}
const convertLevel = (toc: TocAst, levelsToShowUnderThis: number, headerCounts: Map<string, number>, wrapInListItem: boolean): ReactElement | null => {
if (levelsToShowUnderThis < 0) {
return null
@ -48,7 +51,7 @@ const convertLevel = (toc: TocAst, levelsToShowUnderThis: number, headerCounts:
}
}
export const MarkdownToc: React.FC<MarkdownTocProps> = ({ ast, maxDepth = 3, sticky }) => {
export const TableOfContents: React.FC<TableOfContentsProps> = ({ ast, maxDepth = 3, sticky }) => {
const tocTree = useMemo(() => convertLevel(ast, maxDepth, new Map<string, number>(), false), [ast, maxDepth])
return (

View file

@ -1,8 +1,8 @@
import React, { Fragment, useState } from 'react'
import { Dropdown } from 'react-bootstrap'
import { Trans, useTranslation } from 'react-i18next'
import { ForkAwesomeIcon, IconName } from '../../../../../common/fork-awesome/fork-awesome-icon'
import { DeletionModal } from '../../../../../common/modals/deletion-modal'
import { ForkAwesomeIcon, IconName } from '../../common/fork-awesome/fork-awesome-icon'
import { DeletionModal } from '../../common/modals/deletion-modal'
export interface DropdownItemWithDeletionModalProps {
onConfirm: () => void

View file

@ -1,9 +1,9 @@
import React from 'react'
import { Dropdown } from 'react-bootstrap'
import { Trans, useTranslation } from 'react-i18next'
import { ForkAwesomeIcon } from '../../../../../common/fork-awesome/fork-awesome-icon'
import { ShowIf } from '../../../../../common/show-if/show-if'
import { HistoryEntryOrigin } from '../../history'
import { ForkAwesomeIcon } from '../../common/fork-awesome/fork-awesome-icon'
import { ShowIf } from '../../common/show-if/show-if'
import { HistoryEntryOrigin } from '../history-page'
import './entry-menu.scss'
import { DeleteNoteItem } from './delete-note-item'
import { RemoveNoteEntryItem } from './remove-note-entry-item'

View file

@ -1,6 +1,6 @@
import React from 'react'
import { Row } from 'react-bootstrap'
import { Pager } from '../../../../common/pagination/pager'
import { Pager } from '../../common/pagination/pager'
import { HistoryEntriesProps } from '../history-content/history-content'
import { HistoryCard } from './history-card'

View file

@ -2,10 +2,10 @@ import moment from 'moment'
import React from 'react'
import { Badge, Card } from 'react-bootstrap'
import { Link } from 'react-router-dom'
import { formatHistoryDate } from '../../../../../utils/historyUtils'
import { ForkAwesomeIcon } from '../../../../common/fork-awesome/fork-awesome-icon'
import { EntryMenu } from '../common/entry-menu/entry-menu'
import { PinButton } from '../common/pin-button'
import { formatHistoryDate } from '../utils'
import { ForkAwesomeIcon } from '../../common/fork-awesome/fork-awesome-icon'
import { EntryMenu } from '../entry-menu/entry-menu'
import { PinButton } from '../pin-button/pin-button'
import { HistoryEntryProps } from '../history-content/history-content'
import './history-card.scss'

View file

@ -1,8 +1,8 @@
import React, { Fragment, useState } from 'react'
import { Alert, Row } from 'react-bootstrap'
import { Trans, useTranslation } from 'react-i18next'
import { PagerPagination } from '../../../../common/pagination/pager-pagination'
import { HistoryEntryOrigin, LocatedHistoryEntry } from '../history'
import { PagerPagination } from '../../common/pagination/pager-pagination'
import { HistoryEntryOrigin, LocatedHistoryEntry } from '../history-page'
import { HistoryCardList } from '../history-card/history-card-list'
import { HistoryTable } from '../history-table/history-table'
import { ViewStateEnum } from '../history-toolbar/history-toolbar'

View file

@ -2,9 +2,9 @@ import React, { Fragment, useCallback, useEffect, useMemo, useState } from 'reac
import { Row } from 'react-bootstrap'
import { Trans, useTranslation } from 'react-i18next'
import { useSelector } from 'react-redux'
import { deleteHistory, deleteHistoryEntry, getHistory, setHistory, updateHistoryEntry } from '../../../../api/history'
import { deleteNote } from '../../../../api/note'
import { ApplicationState } from '../../../../redux'
import { deleteHistory, deleteHistoryEntry, getHistory, setHistory, updateHistoryEntry } from '../../api/history'
import { deleteNote } from '../../api/notes'
import { ApplicationState } from '../../redux'
import {
collectEntries,
downloadHistory,
@ -12,8 +12,8 @@ import {
mergeEntryArrays,
setHistoryToLocalStore,
sortAndFilterEntries
} from '../../../../utils/historyUtils'
import { ErrorModal } from '../../../common/modals/error-modal'
} from './utils'
import { ErrorModal } from '../common/modals/error-modal'
import { HistoryContent } from './history-content/history-content'
import { HistoryToolbar, HistoryToolbarState, initState as toolbarInitState } from './history-toolbar/history-toolbar'
@ -41,7 +41,7 @@ export enum HistoryEntryOrigin {
REMOTE = 'remote'
}
export const History: React.FC = () => {
export const HistoryPage: React.FC = () => {
useTranslation()
const [localHistoryEntries, setLocalHistoryEntries] = useState<HistoryEntry[]>(loadHistoryFromLocalStore)
const [remoteHistoryEntries, setRemoteHistoryEntries] = useState<HistoryEntry[]>([])

View file

@ -1,9 +1,9 @@
import React from 'react'
import { Badge } from 'react-bootstrap'
import { Link } from 'react-router-dom'
import { formatHistoryDate } from '../../../../../utils/historyUtils'
import { EntryMenu } from '../common/entry-menu/entry-menu'
import { PinButton } from '../common/pin-button'
import { formatHistoryDate } from '../utils'
import { EntryMenu } from '../entry-menu/entry-menu'
import { PinButton } from '../pin-button/pin-button'
import { HistoryEntryProps } from '../history-content/history-content'
export const HistoryTableRow: React.FC<HistoryEntryProps> = ({ entry, onPinClick, onRemoveClick, onDeleteClick }) => {

View file

@ -1,7 +1,7 @@
import React from 'react'
import { Table } from 'react-bootstrap'
import { Trans, useTranslation } from 'react-i18next'
import { Pager } from '../../../../common/pagination/pager'
import { Pager } from '../../common/pagination/pager'
import { HistoryEntriesProps } from '../history-content/history-content'
import { HistoryTableRow } from './history-table-row'
import './history-table.scss'

View file

@ -1,8 +1,8 @@
import React, { Fragment, useState } from 'react'
import { Button } from 'react-bootstrap'
import { Trans, useTranslation } from 'react-i18next'
import { ForkAwesomeIcon } from '../../../../common/fork-awesome/fork-awesome-icon'
import { DeletionModal } from '../../../../common/modals/deletion-modal'
import { ForkAwesomeIcon } from '../../common/fork-awesome/fork-awesome-icon'
import { DeletionModal } from '../../common/modals/deletion-modal'
export interface ClearHistoryButtonProps {
onClearHistory: () => void

View file

@ -1,7 +1,7 @@
import React from 'react'
import { Button } from 'react-bootstrap'
import { useTranslation } from 'react-i18next'
import { ForkAwesomeIcon } from '../../../../common/fork-awesome/fork-awesome-icon'
import { ForkAwesomeIcon } from '../../common/fork-awesome/fork-awesome-icon'
export interface ExportHistoryButtonProps {
onExportHistory: () => void

View file

@ -3,11 +3,11 @@ import { Button, Form, FormControl, InputGroup, ToggleButton, ToggleButtonGroup
import { Typeahead } from 'react-bootstrap-typeahead'
import { Trans, useTranslation } from 'react-i18next'
import { useSelector } from 'react-redux'
import { ApplicationState } from '../../../../../redux'
import { ForkAwesomeIcon } from '../../../../common/fork-awesome/fork-awesome-icon'
import { ShowIf } from '../../../../common/show-if/show-if'
import { SortButton, SortModeEnum } from '../../../../common/sort-button/sort-button'
import { HistoryEntry } from '../history'
import { ApplicationState } from '../../../redux'
import { ForkAwesomeIcon } from '../../common/fork-awesome/fork-awesome-icon'
import { ShowIf } from '../../common/show-if/show-if'
import { SortButton, SortModeEnum } from '../sort-button/sort-button'
import { HistoryEntry } from '../history-page'
import { ClearHistoryButton } from './clear-history-button'
import { ExportHistoryButton } from './export-history-button'
import { ImportHistoryButton } from './import-history-button'

View file

@ -1,10 +1,10 @@
import React, { useRef, useState } from 'react'
import { Button } from 'react-bootstrap'
import { Trans, useTranslation } from 'react-i18next'
import { convertV1History, V1HistoryEntry } from '../../../../../utils/historyUtils'
import { ErrorModal } from '../../../../common/modals/error-modal'
import { ForkAwesomeIcon } from '../../../../common/fork-awesome/fork-awesome-icon'
import { HistoryEntry, HistoryJson } from '../history'
import { convertV1History, V1HistoryEntry } from '../utils'
import { ErrorModal } from '../../common/modals/error-modal'
import { ForkAwesomeIcon } from '../../common/fork-awesome/fork-awesome-icon'
import { HistoryEntry, HistoryJson } from '../history-page'
export interface ImportHistoryButtonProps {
onImportHistory: (entries: HistoryEntry[]) => void

View file

@ -1,5 +1,4 @@
.history-pin {
.fa {
opacity: 0.2;
transition: opacity 0.2s ease-in-out, color 0.2s ease-in-out;

View file

@ -1,6 +1,6 @@
import React from 'react'
import { Button } from 'react-bootstrap'
import { ForkAwesomeIcon } from '../../../../common/fork-awesome/fork-awesome-icon'
import { ForkAwesomeIcon } from '../../common/fork-awesome/fork-awesome-icon'
import './pin-button.scss'
export interface PinButtonProps {

View file

@ -1,7 +1,7 @@
import React from 'react'
import { ButtonProps } from 'react-bootstrap'
import { IconName } from '../fork-awesome/fork-awesome-icon'
import { IconButton } from '../icon-button/icon-button'
import { IconName } from '../../common/fork-awesome/fork-awesome-icon'
import { IconButton } from '../../common/icon-button/icon-button'
export enum SortModeEnum {
up = 1,
@ -43,5 +43,5 @@ export const SortButton: React.FC<SortButtonProps> = ({ children, variant, onDir
onDirectionChange(toggleDirection(direction))
}
return <IconButton onClick={toggleSort} variant={variant} icon={getIcon(direction)}>{children}</IconButton>
return <IconButton onClick={toggleSort} variant={variant} icon={getIcon(direction)} border={true}>{children}</IconButton>
}

View file

@ -1,12 +1,12 @@
import moment from 'moment'
import { SortModeEnum } from '../components/common/sort-button/sort-button'
import { SortModeEnum } from './sort-button/sort-button'
import {
HistoryEntry,
HistoryEntryOrigin,
HistoryJson,
LocatedHistoryEntry
} from '../components/landing/pages/history/history'
import { HistoryToolbarState } from '../components/landing/pages/history/history-toolbar/history-toolbar'
} from './history-page'
import { HistoryToolbarState } from './history-toolbar/history-toolbar'
export function collectEntries (localEntries: HistoryEntry[], remoteEntries: HistoryEntry[]): LocatedHistoryEntry[] {
const locatedLocalEntries = locateEntries(localEntries, HistoryEntryOrigin.LOCAL)

View file

@ -3,10 +3,10 @@ import { Button } from 'react-bootstrap'
import { Trans, useTranslation } from 'react-i18next'
import { useSelector } from 'react-redux'
import { Link } from 'react-router-dom'
import { ApplicationState } from '../../../../../redux'
import { ShowIf } from '../../../../common/show-if/show-if'
import { SignInButton } from '../../../layout/navigation/sign-in-button'
import { ApplicationState } from '../../../redux'
import { ShowIf } from '../../common/show-if/show-if'
import './cover-buttons.scss'
import { SignInButton } from '../../landing-layout/navigation/sign-in-button'
export const CoverButtons: React.FC = () => {
useTranslation()

View file

@ -2,7 +2,7 @@ import React from 'react'
import { Col, Row } from 'react-bootstrap'
import { Trans, useTranslation } from 'react-i18next'
import { Link } from 'react-router-dom'
import { ForkAwesomeIcon } from '../../../common/fork-awesome/fork-awesome-icon'
import { ForkAwesomeIcon } from '../common/fork-awesome/fork-awesome-icon'
export const FeatureLinks: React.FC = () => {
useTranslation()

View file

Before

Width:  |  Height:  |  Size: 222 KiB

After

Width:  |  Height:  |  Size: 222 KiB

View file

@ -1,12 +1,12 @@
import React, { Fragment } from 'react'
import { Trans, useTranslation } from 'react-i18next'
import { Branding } from '../../../common/branding/branding'
import { ForkAwesomeIcon } from '../../../common/fork-awesome/fork-awesome-icon'
import { Branding } from '../common/branding/branding'
import { ForkAwesomeIcon } from '../common/fork-awesome/fork-awesome-icon'
import { CoverButtons } from './cover-buttons/cover-buttons'
import { FeatureLinks } from './feature-links'
import screenshot from './img/screenshot.png'
const Intro: React.FC = () => {
const IntroPage: React.FC = () => {
const { t } = useTranslation()
return (
@ -28,4 +28,4 @@ const Intro: React.FC = () => {
)
}
export { Intro }
export { IntroPage }

Some files were not shown because too many files have changed in this diff Show more