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:
Erik Michelson 2021-05-04 20:35:08 +02:00 committed by GitHub
parent 726b084509
commit 3887de4309
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 85 additions and 6 deletions

View file

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

View file

@ -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
}, [])

View file

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

View file

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

View file

@ -33,6 +33,10 @@
background: $entry-hover-bg;
}
}
&.icon-highlighted > .sidebar-icon {
color: $orange
}
}
}