mirror of
https://github.com/hedgedoc/hedgedoc.git
synced 2025-03-24 01:01:20 +00:00
The History PR: III - Editor integration (#1158)
* Update history on editor load and title change Signed-off-by: Erik Michelson <github@erik.michelson.eu> * Add pinning to history from sidebar Signed-off-by: Erik Michelson <github@erik.michelson.eu> * Add CHANGELOG entry Signed-off-by: Erik Michelson <github@erik.michelson.eu> * Only update local history entries Signed-off-by: Erik Michelson <github@erik.michelson.eu> * Update property names to match backend ones Signed-off-by: Erik Michelson <github@erik.michelson.eu> * Show error notification on failure Signed-off-by: Erik Michelson <github@erik.michelson.eu> * Apply requested changes from review - rename use hook to reflect the situation that only local entries will be updated - extract the update ready check from the hook - rename vars to make comparison more clear Signed-off-by: Erik Michelson <github@erik.michelson.eu>
This commit is contained in:
parent
726b084509
commit
3887de4309
5 changed files with 85 additions and 6 deletions
|
@ -72,6 +72,7 @@ SPDX-License-Identifier: CC-BY-SA-4.0
|
|||
- The intro page content can be changed by editing `public/intro.md`.
|
||||
- When pasting tables (e.g. from LibreOffice Calc or MS Excel) they get reformatted to markdown tables.
|
||||
- The history page supports URL parameters that allow bookmarking of a specific search of tags filter.
|
||||
- Users can change the pinning state of a note directly from the editor.
|
||||
|
||||
### Changed
|
||||
|
||||
|
|
|
@ -35,6 +35,7 @@ import { useEditorModeFromUrl } from './hooks/useEditorModeFromUrl'
|
|||
import { UiNotifications } from '../notifications/ui-notifications'
|
||||
import { useNotificationTest } from './use-notification-test'
|
||||
import { IframeCommunicatorContextProvider } from './render-context/iframe-communicator-context-provider'
|
||||
import { useUpdateLocalHistoryEntry } from './hooks/useUpdateLocalHistoryEntry'
|
||||
|
||||
export interface EditorPagePathParams {
|
||||
id: string
|
||||
|
@ -77,6 +78,8 @@ export const EditorPage: React.FC = () => {
|
|||
|
||||
const [error, loading] = useLoadNoteFromServer()
|
||||
|
||||
useUpdateLocalHistoryEntry(!error && !loading)
|
||||
|
||||
const setRendererToScrollSource = useCallback(() => {
|
||||
scrollSource.current = ScrollSource.RENDERER
|
||||
}, [])
|
||||
|
|
|
@ -0,0 +1,51 @@
|
|||
/*
|
||||
* SPDX-FileCopyrightText: 2021 The HedgeDoc developers (see AUTHORS file)
|
||||
*
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
|
||||
import equal from 'fast-deep-equal'
|
||||
import { useEffect, useRef } from 'react'
|
||||
import { useSelector } from 'react-redux'
|
||||
import { ApplicationState, store } from '../../../redux'
|
||||
import { useParams } from 'react-router-dom'
|
||||
import { EditorPagePathParams } from '../editor-page'
|
||||
import { HistoryEntry, HistoryEntryOrigin } from '../../../redux/history/types'
|
||||
import { updateLocalHistoryEntry } from '../../../redux/history/methods'
|
||||
|
||||
export const useUpdateLocalHistoryEntry = (updateReady: boolean): void => {
|
||||
const { id } = useParams<EditorPagePathParams>()
|
||||
const userExists = useSelector((state: ApplicationState) => !!state.user)
|
||||
const currentNoteTitle = useSelector((state: ApplicationState) => state.noteDetails.noteTitle)
|
||||
const currentNoteTags = useSelector((state: ApplicationState) => state.noteDetails.frontmatter.tags)
|
||||
|
||||
const lastNoteTitle = useRef('')
|
||||
const lastNoteTags = useRef<string[]>([])
|
||||
|
||||
useEffect(() => {
|
||||
if (!updateReady || userExists) {
|
||||
return
|
||||
}
|
||||
if (currentNoteTitle === lastNoteTitle.current && equal(currentNoteTags, lastNoteTags.current)) {
|
||||
return
|
||||
}
|
||||
const history = store.getState().history
|
||||
const entry: HistoryEntry = history.find(entry => entry.identifier === id) ?? {
|
||||
identifier: id,
|
||||
title: '',
|
||||
pinStatus: false,
|
||||
lastVisited: '',
|
||||
tags: [],
|
||||
origin: HistoryEntryOrigin.LOCAL
|
||||
}
|
||||
if (entry.origin === HistoryEntryOrigin.REMOTE) {
|
||||
return
|
||||
}
|
||||
entry.title = currentNoteTitle
|
||||
entry.tags = currentNoteTags
|
||||
entry.lastVisited = new Date().toISOString()
|
||||
updateLocalHistoryEntry(id, entry)
|
||||
lastNoteTitle.current = currentNoteTitle
|
||||
lastNoteTags.current = currentNoteTags
|
||||
}, [updateReady, id, userExists, currentNoteTitle, currentNoteTags])
|
||||
}
|
|
@ -4,20 +4,40 @@
|
|||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
|
||||
import React from 'react'
|
||||
import React, { useCallback, useMemo } from 'react'
|
||||
import { Trans, useTranslation } from 'react-i18next'
|
||||
import { SidebarButton } from './sidebar-button'
|
||||
import { SpecificSidebarEntryProps } from './types'
|
||||
import { useParams } from 'react-router-dom'
|
||||
import { EditorPagePathParams } from '../editor-page'
|
||||
import { useSelector } from 'react-redux'
|
||||
import { ApplicationState } from '../../../redux'
|
||||
import { toggleHistoryEntryPinning } from '../../../redux/history/methods'
|
||||
import { showErrorNotification } from '../../../redux/ui-notifications/methods'
|
||||
|
||||
export const PinNoteSidebarEntry: React.FC<SpecificSidebarEntryProps> = ({ className, hide }) => {
|
||||
useTranslation()
|
||||
const { t } = useTranslation()
|
||||
const { id } = useParams<EditorPagePathParams>()
|
||||
const history = useSelector((state: ApplicationState) => state.history)
|
||||
|
||||
const isPinned = true
|
||||
const i18nKey = isPinned ? 'editor.documentBar.pinNoteToHistory' : 'editor.documentBar.pinnedToHistory'
|
||||
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(t('landing.history.error.updateEntry.text'))
|
||||
)
|
||||
}, [id, t])
|
||||
|
||||
return (
|
||||
<SidebarButton icon={ 'thumb-tack' } className={ className } hide={ hide }>
|
||||
<Trans i18nKey={ i18nKey }/>
|
||||
<SidebarButton icon={ 'thumb-tack' } hide={ hide } onClick={ onPinClicked }
|
||||
className={ `${ className ?? '' } ${ isPinned ? 'icon-highlighted' : '' }` }>
|
||||
<Trans i18nKey={ isPinned ? 'editor.documentBar.pinnedToHistory' : 'editor.documentBar.pinNoteToHistory' }/>
|
||||
</SidebarButton>
|
||||
)
|
||||
}
|
||||
|
|
|
@ -33,6 +33,10 @@
|
|||
background: $entry-hover-bg;
|
||||
}
|
||||
}
|
||||
|
||||
&.icon-highlighted > .sidebar-icon {
|
||||
color: $orange
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue