mirror of
https://github.com/hedgedoc/hedgedoc.git
synced 2025-05-15 15:44:45 -04:00
Improvement/move document content into redux (#691)
This commit is contained in:
parent
0750695e2f
commit
1690a7bdcf
15 changed files with 101 additions and 51 deletions
|
@ -6,7 +6,7 @@ import { ConnectionIndicator } from './connection-indicator/connection-indicator
|
|||
import { DocumentInfoButton } from './document-info/document-info-button'
|
||||
import { EditorMenu } from './menus/editor-menu'
|
||||
import { ExportMenu } from './menus/export-menu'
|
||||
import { ImportMenu, ImportProps } from './menus/import-menu'
|
||||
import { ImportMenu } from './menus/import-menu'
|
||||
import { PermissionButton } from './permissions/permission-button'
|
||||
import { RevisionButton } from './revisions/revision-button'
|
||||
|
||||
|
@ -14,7 +14,7 @@ export interface DocumentBarProps {
|
|||
title: string
|
||||
}
|
||||
|
||||
export const DocumentBar: React.FC<DocumentBarProps & ImportProps> = ({ title, noteContent, updateNoteContent }) => {
|
||||
export const DocumentBar: React.FC<DocumentBarProps> = ({ title }) => {
|
||||
useTranslation()
|
||||
|
||||
return (
|
||||
|
@ -22,13 +22,13 @@ export const DocumentBar: React.FC<DocumentBarProps & ImportProps> = ({ title, n
|
|||
<div className="navbar-nav">
|
||||
<ShareLinkButton/>
|
||||
<DocumentInfoButton/>
|
||||
<RevisionButton noteContent={noteContent}/>
|
||||
<RevisionButton/>
|
||||
<PinToHistoryButton/>
|
||||
<PermissionButton/>
|
||||
</div>
|
||||
<div className="ml-auto navbar-nav">
|
||||
<ImportMenu updateNoteContent={updateNoteContent} noteContent={noteContent}/>
|
||||
<ExportMenu title={title} noteContent={noteContent}/>
|
||||
<ImportMenu/>
|
||||
<ExportMenu title={title}/>
|
||||
<EditorMenu noteTitle={title}/>
|
||||
<ConnectionIndicator/>
|
||||
</div>
|
||||
|
|
|
@ -1,10 +1,14 @@
|
|||
import React, { Fragment, useCallback, useRef } from 'react'
|
||||
import { Dropdown } from 'react-bootstrap'
|
||||
import { Trans } from 'react-i18next'
|
||||
import { useSelector } from 'react-redux'
|
||||
import { ApplicationState } from '../../../../redux'
|
||||
import { setDocumentContent } from '../../../../redux/document-content/methods'
|
||||
import { ForkAwesomeIcon } from '../../../common/fork-awesome/fork-awesome-icon'
|
||||
import { ImportProps } from '../menus/import-menu'
|
||||
|
||||
export const ImportFile: React.FC<ImportProps> = ({ noteContent, updateNoteContent }) => {
|
||||
export const ImportFile: React.FC = () => {
|
||||
const markdownContent = useSelector((state: ApplicationState) => state.documentContent.content)
|
||||
|
||||
const fileInputReference = useRef<HTMLInputElement>(null)
|
||||
const doImport = useCallback(() => {
|
||||
const fileInput = fileInputReference.current
|
||||
|
@ -19,10 +23,10 @@ export const ImportFile: React.FC<ImportProps> = ({ noteContent, updateNoteConte
|
|||
const fileReader = new FileReader()
|
||||
fileReader.addEventListener('load', () => {
|
||||
const newContent = fileReader.result as string
|
||||
if (noteContent.length === 0) {
|
||||
updateNoteContent(newContent)
|
||||
if (markdownContent.length === 0) {
|
||||
setDocumentContent(newContent)
|
||||
} else {
|
||||
updateNoteContent(noteContent + '\n' + newContent)
|
||||
setDocumentContent(markdownContent + '\n' + newContent)
|
||||
}
|
||||
})
|
||||
fileReader.addEventListener('loadend', () => {
|
||||
|
@ -31,7 +35,7 @@ export const ImportFile: React.FC<ImportProps> = ({ noteContent, updateNoteConte
|
|||
fileReader.readAsText(file)
|
||||
})
|
||||
fileInput.click()
|
||||
}, [fileInputReference, noteContent, updateNoteContent])
|
||||
}, [markdownContent])
|
||||
|
||||
return (
|
||||
<Fragment>
|
||||
|
|
|
@ -7,10 +7,9 @@ import { MarkdownExportDropdownItem } from './export/markdown'
|
|||
|
||||
export interface ExportMenuProps {
|
||||
title: string
|
||||
noteContent: string
|
||||
}
|
||||
|
||||
export const ExportMenu: React.FC<ExportMenuProps> = ({ title, noteContent }) => {
|
||||
export const ExportMenu: React.FC<ExportMenuProps> = ({ title }) => {
|
||||
useTranslation()
|
||||
return (
|
||||
<Dropdown className='small mx-1' alignRight={true}>
|
||||
|
@ -40,10 +39,7 @@ export const ExportMenu: React.FC<ExportMenuProps> = ({ title, noteContent }) =>
|
|||
<Dropdown.Header>
|
||||
<Trans i18nKey='editor.documentBar.download'/>
|
||||
</Dropdown.Header>
|
||||
<MarkdownExportDropdownItem
|
||||
title={title}
|
||||
noteContent={noteContent}
|
||||
/>
|
||||
<MarkdownExportDropdownItem title={title} />
|
||||
<Dropdown.Item className='small'>
|
||||
<ForkAwesomeIcon icon='file-code-o' className={'mx-2'}/>
|
||||
HTML
|
||||
|
|
|
@ -1,16 +1,19 @@
|
|||
import React from 'react'
|
||||
import { Dropdown } from 'react-bootstrap'
|
||||
import { useSelector } from 'react-redux'
|
||||
import { ApplicationState } from '../../../../../redux'
|
||||
import { download } from '../../../../common/download/download'
|
||||
import { ForkAwesomeIcon } from '../../../../common/fork-awesome/fork-awesome-icon'
|
||||
|
||||
export interface MarkdownExportDropdownItemProps {
|
||||
title: string
|
||||
noteContent: string
|
||||
}
|
||||
|
||||
export const MarkdownExportDropdownItem: React.FC<MarkdownExportDropdownItemProps> = ({ title, noteContent }) => {
|
||||
export const MarkdownExportDropdownItem: React.FC<MarkdownExportDropdownItemProps> = ({ title }) => {
|
||||
const markdownContent = useSelector((state: ApplicationState) => state.documentContent.content)
|
||||
|
||||
return (
|
||||
<Dropdown.Item className='small' onClick={() => download(noteContent, `${title}.md`, 'text/markdown')}>
|
||||
<Dropdown.Item className='small' onClick={() => download(markdownContent, `${title}.md`, 'text/markdown')}>
|
||||
<ForkAwesomeIcon icon='file-text' className={'mx-2'}/>
|
||||
Markdown
|
||||
</Dropdown.Item>
|
||||
|
|
|
@ -4,12 +4,7 @@ import { Trans } from 'react-i18next'
|
|||
import { ForkAwesomeIcon } from '../../../common/fork-awesome/fork-awesome-icon'
|
||||
import { ImportFile } from '../import/import-file'
|
||||
|
||||
export interface ImportProps {
|
||||
noteContent: string
|
||||
updateNoteContent: (content: string) => void
|
||||
}
|
||||
|
||||
export const ImportMenu: React.FC<ImportProps> = ({ updateNoteContent, noteContent }) => {
|
||||
export const ImportMenu: React.FC = () => {
|
||||
return (
|
||||
<Dropdown className='small mx-1' alignRight={true}>
|
||||
<Dropdown.Toggle variant='light' size='sm' id='editor-menu-import' className=''>
|
||||
|
@ -33,7 +28,7 @@ export const ImportMenu: React.FC<ImportProps> = ({ updateNoteContent, noteConte
|
|||
<ForkAwesomeIcon icon='clipboard' className={'mx-2'}/>
|
||||
<Trans i18nKey='editor.import.clipboard'/>
|
||||
</Dropdown.Item>
|
||||
<ImportFile updateNoteContent={updateNoteContent} noteContent={noteContent}/>
|
||||
<ImportFile/>
|
||||
</Dropdown.Menu>
|
||||
</Dropdown>
|
||||
)
|
||||
|
|
|
@ -2,17 +2,13 @@ import React, { Fragment, useState } from 'react'
|
|||
import { TranslatedIconButton } from '../../../common/icon-button/translated-icon-button'
|
||||
import { RevisionModal } from './revision-modal'
|
||||
|
||||
export interface RevisionButtonProps {
|
||||
noteContent: string
|
||||
}
|
||||
|
||||
export const RevisionButton: React.FC<RevisionButtonProps> = ({ noteContent }) => {
|
||||
export const RevisionButton: React.FC = () => {
|
||||
const [show, setShow] = useState(false)
|
||||
|
||||
return (
|
||||
<Fragment>
|
||||
<TranslatedIconButton size={'sm'} className={'mx-1'} icon={'history'} variant={'light'} i18nKey={'editor.documentBar.revision'} onClick={() => setShow(true)}/>
|
||||
<RevisionModal show={show} onHide={() => setShow(false)} titleI18nKey={'editor.modal.revision.title'} icon={'history'} noteContent={noteContent}/>
|
||||
<RevisionModal show={show} onHide={() => setShow(false)} titleI18nKey={'editor.modal.revision.title'} icon={'history'}/>
|
||||
</Fragment>
|
||||
)
|
||||
}
|
||||
|
|
|
@ -10,12 +10,11 @@ import { UserResponse } from '../../../../api/users/types'
|
|||
import { ApplicationState } from '../../../../redux'
|
||||
import { CommonModal, CommonModalProps } from '../../../common/modals/common-modal'
|
||||
import { ShowIf } from '../../../common/show-if/show-if'
|
||||
import { RevisionButtonProps } from './revision-button'
|
||||
import { RevisionModalListEntry } from './revision-modal-list-entry'
|
||||
import './revision-modal.scss'
|
||||
import { downloadRevision, getUserDataForRevision } from './utils'
|
||||
|
||||
export const RevisionModal: React.FC<CommonModalProps & RevisionButtonProps> = ({ show, onHide, icon, titleI18nKey, noteContent }) => {
|
||||
export const RevisionModal: React.FC<CommonModalProps> = ({ show, onHide, icon, titleI18nKey }) => {
|
||||
useTranslation()
|
||||
const [revisions, setRevisions] = useState<RevisionListEntry[]>([])
|
||||
const [selectedRevisionTimestamp, setSelectedRevisionTimestamp] = useState<number | null>(null)
|
||||
|
@ -47,6 +46,8 @@ export const RevisionModal: React.FC<CommonModalProps & RevisionButtonProps> = (
|
|||
}).catch(() => setError(true))
|
||||
}, [selectedRevisionTimestamp, id])
|
||||
|
||||
const markdownContent = useSelector((state: ApplicationState) => state.documentContent.content)
|
||||
|
||||
return (
|
||||
<CommonModal show={show} onHide={onHide} titleI18nKey={titleI18nKey} icon={icon} closeButton={true} size={'xl'} additionalClasses='revision-modal'>
|
||||
<Modal.Body>
|
||||
|
@ -75,7 +76,7 @@ export const RevisionModal: React.FC<CommonModalProps & RevisionButtonProps> = (
|
|||
<ShowIf condition={!error && !!selectedRevision}>
|
||||
<ReactDiffViewer
|
||||
oldValue={selectedRevision?.content}
|
||||
newValue={noteContent}
|
||||
newValue={markdownContent}
|
||||
splitView={false}
|
||||
compareMethod={DiffMethod.WORDS}
|
||||
useDarkTheme={darkModeEnabled}
|
||||
|
|
|
@ -1,7 +1,9 @@
|
|||
import React, { RefObject, useState } from 'react'
|
||||
import { Dropdown } from 'react-bootstrap'
|
||||
import { useSelector } from 'react-redux'
|
||||
import useResizeObserver from 'use-resize-observer'
|
||||
import { TocAst } from '../../../external-types/markdown-it-toc-done-right/interface'
|
||||
import { ApplicationState } from '../../../redux'
|
||||
import { ForkAwesomeIcon } from '../../common/fork-awesome/fork-awesome-icon'
|
||||
import { ShowIf } from '../../common/show-if/show-if'
|
||||
import { LineMarkerPosition } from '../../markdown-renderer/types'
|
||||
|
@ -10,7 +12,6 @@ import { TableOfContents } from '../table-of-contents/table-of-contents'
|
|||
import { YAMLMetaData } from '../yaml-metadata/yaml-metadata'
|
||||
|
||||
export interface DocumentRenderPaneProps {
|
||||
content: string
|
||||
extraClasses?: string
|
||||
onFirstHeadingChange: (firstHeading: string | undefined) => void
|
||||
onLineMarkerPositionChanged?: (lineMarkerPosition: LineMarkerPosition[]) => void
|
||||
|
@ -23,7 +24,6 @@ export interface DocumentRenderPaneProps {
|
|||
}
|
||||
|
||||
export const DocumentRenderPane: React.FC<DocumentRenderPaneProps> = ({
|
||||
content,
|
||||
extraClasses,
|
||||
onFirstHeadingChange,
|
||||
onLineMarkerPositionChanged,
|
||||
|
@ -37,6 +37,7 @@ export const DocumentRenderPane: React.FC<DocumentRenderPaneProps> = ({
|
|||
const [tocAst, setTocAst] = useState<TocAst>()
|
||||
const { width } = useResizeObserver(rendererReference ? { ref: rendererReference } : undefined)
|
||||
const realWidth = width || 0
|
||||
const markdownContent = useSelector((state: ApplicationState) => state.documentContent.content)
|
||||
|
||||
return (
|
||||
<div className={`bg-light flex-fill pb-5 flex-row d-flex w-100 h-100 ${extraClasses ?? ''}`}
|
||||
|
@ -45,7 +46,7 @@ export const DocumentRenderPane: React.FC<DocumentRenderPaneProps> = ({
|
|||
<div className={'bg-light flex-fill'}>
|
||||
<FullMarkdownRenderer
|
||||
className={'flex-fill mb-3'}
|
||||
content={content}
|
||||
content={markdownContent}
|
||||
onFirstHeadingChange={onFirstHeadingChange}
|
||||
onLineMarkerPositionChanged={onLineMarkerPositionChanged}
|
||||
onMetaDataChange={onMetadataChange}
|
||||
|
|
|
@ -1,4 +1,6 @@
|
|||
import React, { useMemo, useRef, useState } from 'react'
|
||||
import { useSelector } from 'react-redux'
|
||||
import { ApplicationState } from '../../../redux'
|
||||
import { LineMarkerPosition } from '../../markdown-renderer/types'
|
||||
import { useScrollToLineMark } from '../scroll/hooks/use-scroll-to-line-mark'
|
||||
import { useUserScroll } from '../scroll/hooks/use-user-scroll'
|
||||
|
@ -6,7 +8,6 @@ import { ScrollProps } from '../scroll/scroll-props'
|
|||
import { DocumentRenderPane, DocumentRenderPaneProps } from './document-render-pane'
|
||||
|
||||
export const ScrollingDocumentRenderPane: React.FC<DocumentRenderPaneProps & ScrollProps> = ({
|
||||
content,
|
||||
scrollState,
|
||||
wide,
|
||||
onFirstHeadingChange,
|
||||
|
@ -15,16 +16,16 @@ export const ScrollingDocumentRenderPane: React.FC<DocumentRenderPaneProps & Scr
|
|||
onScroll,
|
||||
onTaskCheckedChange
|
||||
}) => {
|
||||
const markdownContent = useSelector((state: ApplicationState) => state.documentContent.content)
|
||||
const renderer = useRef<HTMLDivElement>(null)
|
||||
const [lineMarks, setLineMarks] = useState<LineMarkerPosition[]>()
|
||||
|
||||
const contentLineCount = useMemo(() => content.split('\n').length, [content])
|
||||
const contentLineCount = useMemo(() => markdownContent.split('\n').length, [markdownContent])
|
||||
useScrollToLineMark(scrollState, lineMarks, contentLineCount, renderer)
|
||||
const userScroll = useUserScroll(lineMarks, renderer, onScroll)
|
||||
|
||||
return (
|
||||
<DocumentRenderPane
|
||||
content={content}
|
||||
extraClasses={'overflow-y-scroll'}
|
||||
rendererReference={renderer}
|
||||
wide={wide}
|
||||
|
|
|
@ -5,6 +5,7 @@ import useMedia from 'use-media'
|
|||
import { useApplyDarkMode } from '../../hooks/common/use-apply-dark-mode'
|
||||
import { useDocumentTitle } from '../../hooks/common/use-document-title'
|
||||
import { ApplicationState } from '../../redux'
|
||||
import { setDocumentContent } from '../../redux/document-content/methods'
|
||||
import { setEditorMode } from '../../redux/editor/methods'
|
||||
import { extractNoteTitle } from '../common/document-title/note-title-extractor'
|
||||
import { MotdBanner } from '../common/motd-banner/motd-banner'
|
||||
|
@ -34,7 +35,7 @@ const TASK_REGEX = /(\s*[-*] )(\[[ xX]])( .*)/
|
|||
export const Editor: React.FC = () => {
|
||||
const { t } = useTranslation()
|
||||
const untitledNote = t('editor.untitledNote')
|
||||
const [markdownContent, setMarkdownContent] = useState(editorTestContent)
|
||||
const markdownContent = useSelector((state: ApplicationState) => state.documentContent.content)
|
||||
const isWide = useMedia({ minWidth: 576 })
|
||||
const [documentTitle, setDocumentTitle] = useState(untitledNote)
|
||||
const noteMetadata = useRef<YAMLMetaData>()
|
||||
|
@ -49,6 +50,10 @@ export const Editor: React.FC = () => {
|
|||
rendererScrollState: { firstLineInView: 1, scrolledPercentage: 0 }
|
||||
}))
|
||||
|
||||
useEffect(() => {
|
||||
setDocumentContent(editorTestContent)
|
||||
}, [])
|
||||
|
||||
const updateDocumentTitle = useCallback(() => {
|
||||
const noteTitle = extractNoteTitle(untitledNote, noteMetadata.current, firstHeading.current)
|
||||
setDocumentTitle(noteTitle)
|
||||
|
@ -71,9 +76,9 @@ export const Editor: React.FC = () => {
|
|||
const before = results[1]
|
||||
const after = results[3]
|
||||
lines[lineInMarkdown] = `${before}[${checked ? 'x' : ' '}]${after}`
|
||||
setMarkdownContent(lines.join('\n'))
|
||||
setDocumentContent(lines.join('\n'))
|
||||
}
|
||||
}, [markdownContent, setMarkdownContent])
|
||||
}, [markdownContent])
|
||||
|
||||
useViewModeShortcuts()
|
||||
|
||||
|
@ -105,12 +110,12 @@ export const Editor: React.FC = () => {
|
|||
<MotdBanner/>
|
||||
<div className={'d-flex flex-column vh-100'}>
|
||||
<AppBar mode={AppBarMode.EDITOR}/>
|
||||
<DocumentBar title={documentTitle} noteContent={markdownContent} updateNoteContent={(newContent) => setMarkdownContent(newContent)}/>
|
||||
<DocumentBar title={documentTitle}/>
|
||||
<Splitter
|
||||
showLeft={editorMode === EditorMode.EDITOR || editorMode === EditorMode.BOTH}
|
||||
left={
|
||||
<EditorPane
|
||||
onContentChange={content => setMarkdownContent(content)}
|
||||
onContentChange={setDocumentContent}
|
||||
content={markdownContent}
|
||||
scrollState={scrollState.editorScrollState}
|
||||
onScroll={onEditorScroll}
|
||||
|
@ -120,7 +125,6 @@ export const Editor: React.FC = () => {
|
|||
showRight={editorMode === EditorMode.PREVIEW || (editorMode === EditorMode.BOTH)}
|
||||
right={
|
||||
<ScrollingDocumentRenderPane
|
||||
content={markdownContent}
|
||||
onFirstHeadingChange={onFirstHeadingChange}
|
||||
onMakeScrollSource={() => {
|
||||
scrollSource.current = ScrollSource.RENDERER
|
||||
|
|
|
@ -5,6 +5,7 @@ import { useParams } from 'react-router'
|
|||
import { getNote, Note } from '../../api/notes'
|
||||
import { useApplyDarkMode } from '../../hooks/common/use-apply-dark-mode'
|
||||
import { useDocumentTitle } from '../../hooks/common/use-document-title'
|
||||
import { setDocumentContent } from '../../redux/document-content/methods'
|
||||
import { extractNoteTitle } from '../common/document-title/note-title-extractor'
|
||||
import { MotdBanner } from '../common/motd-banner/motd-banner'
|
||||
import { ShowIf } from '../common/show-if/show-if'
|
||||
|
@ -42,7 +43,10 @@ export const PadViewOnly: React.FC = () => {
|
|||
|
||||
useEffect(() => {
|
||||
getNote(id)
|
||||
.then(note => setNoteData(note))
|
||||
.then(note => {
|
||||
setNoteData(note)
|
||||
setDocumentContent(note.content)
|
||||
})
|
||||
.catch(() => setError(true))
|
||||
.finally(() => setLoading(false))
|
||||
}, [id])
|
||||
|
@ -80,7 +84,6 @@ export const PadViewOnly: React.FC = () => {
|
|||
viewCount={noteData?.viewcount ?? 0}
|
||||
/>
|
||||
<DocumentRenderPane
|
||||
content={noteData?.content ?? ''}
|
||||
onFirstHeadingChange={onFirstHeadingChange}
|
||||
onMetadataChange={onMetadataChange}
|
||||
onTaskCheckedChange={() => false}
|
||||
|
|
10
src/redux/document-content/methods.ts
Normal file
10
src/redux/document-content/methods.ts
Normal file
|
@ -0,0 +1,10 @@
|
|||
import { store } from '..'
|
||||
import { DocumentContentActionType, SetDocumentContentAction } from './types'
|
||||
|
||||
export const setDocumentContent = (content: string): void => {
|
||||
const action: SetDocumentContentAction = {
|
||||
type: DocumentContentActionType.SET_DOCUMENT_CONTENT,
|
||||
content: content
|
||||
}
|
||||
store.dispatch(action)
|
||||
}
|
15
src/redux/document-content/reducers.ts
Normal file
15
src/redux/document-content/reducers.ts
Normal file
|
@ -0,0 +1,15 @@
|
|||
import { Reducer } from 'redux'
|
||||
import { DocumentContent, DocumentContentAction, DocumentContentActionType, SetDocumentContentAction } from './types'
|
||||
|
||||
export const initialState: DocumentContent = {
|
||||
content: ''
|
||||
}
|
||||
|
||||
export const DocumentContentReducer: Reducer<DocumentContent, DocumentContentAction> = (state: DocumentContent = initialState, action: DocumentContentAction) => {
|
||||
switch (action.type) {
|
||||
case DocumentContentActionType.SET_DOCUMENT_CONTENT:
|
||||
return { content: (action as SetDocumentContentAction).content }
|
||||
default:
|
||||
return state
|
||||
}
|
||||
}
|
17
src/redux/document-content/types.ts
Normal file
17
src/redux/document-content/types.ts
Normal file
|
@ -0,0 +1,17 @@
|
|||
import { Action } from 'redux'
|
||||
|
||||
export enum DocumentContentActionType {
|
||||
SET_DOCUMENT_CONTENT = 'document-content/set',
|
||||
}
|
||||
|
||||
export interface DocumentContent {
|
||||
content: string
|
||||
}
|
||||
|
||||
export interface DocumentContentAction extends Action<DocumentContentActionType> {
|
||||
type: DocumentContentActionType
|
||||
}
|
||||
|
||||
export interface SetDocumentContentAction extends DocumentContentAction {
|
||||
content: string
|
||||
}
|
|
@ -7,6 +7,8 @@ import { BannerState } from './banner/types'
|
|||
import { ConfigReducer } from './config/reducers'
|
||||
import { DarkModeConfigReducer } from './dark-mode/reducers'
|
||||
import { DarkModeConfig } from './dark-mode/types'
|
||||
import { DocumentContentReducer } from './document-content/reducers'
|
||||
import { DocumentContent } from './document-content/types'
|
||||
import { EditorConfigReducer } from './editor/reducers'
|
||||
import { EditorConfig } from './editor/types'
|
||||
import { UserReducer } from './user/reducers'
|
||||
|
@ -19,6 +21,7 @@ export interface ApplicationState {
|
|||
apiUrl: ApiUrlObject;
|
||||
editorConfig: EditorConfig;
|
||||
darkMode: DarkModeConfig;
|
||||
documentContent: DocumentContent;
|
||||
}
|
||||
|
||||
export const allReducers: Reducer<ApplicationState> = combineReducers<ApplicationState>({
|
||||
|
@ -27,7 +30,8 @@ export const allReducers: Reducer<ApplicationState> = combineReducers<Applicatio
|
|||
banner: BannerReducer,
|
||||
apiUrl: ApiUrlReducer,
|
||||
editorConfig: EditorConfigReducer,
|
||||
darkMode: DarkModeConfigReducer
|
||||
darkMode: DarkModeConfigReducer,
|
||||
documentContent: DocumentContentReducer
|
||||
})
|
||||
|
||||
export const store = createStore(allReducers)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue