Passing error messages for notebooks
This commit is contained in:
@ -45,24 +45,15 @@ type NoteSectionProps = {
|
|||||||
targetId: string
|
targetId: string
|
||||||
|
|
||||||
placeHolder: string
|
placeHolder: string
|
||||||
mode: 'edit' | 'preview'
|
|
||||||
|
|
||||||
setEditMode: (set: 'edit' | 'preview') => void
|
|
||||||
|
|
||||||
text: string | undefined
|
text: string | undefined
|
||||||
saveText: (text: string, completed: (success: boolean) => void) => void
|
saveText: (text: string) => void
|
||||||
}
|
}
|
||||||
|
|
||||||
export function ArticleNotes(props: NoteSectionProps): JSX.Element {
|
export function ArticleNotes(props: NoteSectionProps): JSX.Element {
|
||||||
const [lastSaved, setLastSaved] = useState<Date | undefined>(undefined)
|
|
||||||
|
|
||||||
const saveText = useCallback(
|
const saveText = useCallback(
|
||||||
(text, updateTime) => {
|
(text) => {
|
||||||
props.saveText(text, (success) => {
|
props.saveText(text)
|
||||||
if (success) {
|
|
||||||
setLastSaved(updateTime)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
},
|
},
|
||||||
[props]
|
[props]
|
||||||
)
|
)
|
||||||
@ -73,7 +64,6 @@ export function ArticleNotes(props: NoteSectionProps): JSX.Element {
|
|||||||
placeHolder={props.placeHolder}
|
placeHolder={props.placeHolder}
|
||||||
text={props.text}
|
text={props.text}
|
||||||
saveText={saveText}
|
saveText={saveText}
|
||||||
lastSaved={lastSaved}
|
|
||||||
fillBackground={false}
|
fillBackground={false}
|
||||||
/>
|
/>
|
||||||
)
|
)
|
||||||
@ -97,14 +87,14 @@ export function HighlightViewNote(props: HighlightViewNoteProps): JSX.Element {
|
|||||||
const [lastSaved, setLastSaved] = useState<Date | undefined>(undefined)
|
const [lastSaved, setLastSaved] = useState<Date | undefined>(undefined)
|
||||||
|
|
||||||
const saveText = useCallback(
|
const saveText = useCallback(
|
||||||
(text, updateTime) => {
|
(text) => {
|
||||||
;(async () => {
|
;(async () => {
|
||||||
const success = await updateHighlightMutation({
|
const success = await updateHighlightMutation({
|
||||||
annotation: text,
|
annotation: text,
|
||||||
highlightId: props.highlight?.id,
|
highlightId: props.highlight?.id,
|
||||||
})
|
})
|
||||||
if (success) {
|
if (success) {
|
||||||
setLastSaved(updateTime)
|
// setLastSaved(updateTime)
|
||||||
props.highlight.annotation = text
|
props.highlight.annotation = text
|
||||||
props.updateHighlight(props.highlight)
|
props.updateHighlight(props.highlight)
|
||||||
}
|
}
|
||||||
@ -119,7 +109,6 @@ export function HighlightViewNote(props: HighlightViewNoteProps): JSX.Element {
|
|||||||
placeHolder={props.placeHolder}
|
placeHolder={props.placeHolder}
|
||||||
text={props.text}
|
text={props.text}
|
||||||
saveText={saveText}
|
saveText={saveText}
|
||||||
lastSaved={lastSaved}
|
|
||||||
fillBackground={true}
|
fillBackground={true}
|
||||||
/>
|
/>
|
||||||
)
|
)
|
||||||
@ -133,27 +122,22 @@ type MarkdownNote = {
|
|||||||
text: string | undefined
|
text: string | undefined
|
||||||
fillBackground: boolean | undefined
|
fillBackground: boolean | undefined
|
||||||
|
|
||||||
lastSaved: Date | undefined
|
saveText: (text: string) => void
|
||||||
saveText: (text: string, updateTime: Date) => void
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export function MarkdownNote(props: MarkdownNote): JSX.Element {
|
export function MarkdownNote(props: MarkdownNote): JSX.Element {
|
||||||
const editorRef = useRef<MdEditor | null>(null)
|
const editorRef = useRef<MdEditor | null>(null)
|
||||||
const [lastChanged, setLastChanged] = useState<Date | undefined>(undefined)
|
|
||||||
const [errorSaving, setErrorSaving] = useState<string | undefined>(undefined)
|
|
||||||
const isDark = isDarkTheme()
|
const isDark = isDarkTheme()
|
||||||
|
|
||||||
const saveRef = useRef(props.saveText)
|
const saveRef = useRef(props.saveText)
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
saveRef.current = props.saveText
|
saveRef.current = props.saveText
|
||||||
}, [props.lastSaved, lastChanged])
|
}, [props])
|
||||||
|
|
||||||
const debouncedSave = useMemo<
|
const debouncedSave = useMemo<(text: string) => void>(() => {
|
||||||
(text: string, updateTime: Date) => void
|
const func = (text: string) => {
|
||||||
>(() => {
|
saveRef.current?.(text)
|
||||||
const func = (text: string, updateTime: Date) => {
|
|
||||||
saveRef.current?.(text, updateTime)
|
|
||||||
}
|
}
|
||||||
return throttle(func, 3000)
|
return throttle(func, 3000)
|
||||||
}, [])
|
}, [])
|
||||||
@ -167,19 +151,16 @@ export function MarkdownNote(props: MarkdownNote): JSX.Element {
|
|||||||
event.preventDefault()
|
event.preventDefault()
|
||||||
}
|
}
|
||||||
|
|
||||||
const updateTime = new Date()
|
debouncedSave(data.text)
|
||||||
setLastChanged(updateTime)
|
|
||||||
localStorage.setItem(`note-${props.targetId}`, JSON.stringify(data))
|
|
||||||
debouncedSave(data.text, updateTime)
|
|
||||||
},
|
},
|
||||||
[props.lastSaved, lastChanged]
|
[]
|
||||||
)
|
)
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const saveMarkdownNote = () => {
|
const saveMarkdownNote = () => {
|
||||||
const md = editorRef.current?.getMdValue()
|
const md = editorRef.current?.getMdValue()
|
||||||
if (md) {
|
if (md) {
|
||||||
props.saveText(md, new Date())
|
props.saveText(md)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
document.addEventListener('saveMarkdownNote', saveMarkdownNote)
|
document.addEventListener('saveMarkdownNote', saveMarkdownNote)
|
||||||
@ -238,38 +219,6 @@ export function MarkdownNote(props: MarkdownNote): JSX.Element {
|
|||||||
renderHTML={(text: string) => mdParser.render(text)}
|
renderHTML={(text: string) => mdParser.render(text)}
|
||||||
onChange={handleEditorChange}
|
onChange={handleEditorChange}
|
||||||
/>
|
/>
|
||||||
<HStack
|
|
||||||
css={{
|
|
||||||
minHeight: '15px',
|
|
||||||
width: '100%',
|
|
||||||
fontSize: '9px',
|
|
||||||
mt: '5px',
|
|
||||||
color: '$thTextSubtle',
|
|
||||||
}}
|
|
||||||
alignment="start"
|
|
||||||
distribution="start"
|
|
||||||
>
|
|
||||||
{errorSaving && (
|
|
||||||
<SpanBox
|
|
||||||
css={{
|
|
||||||
width: '100%',
|
|
||||||
fontSize: '9px',
|
|
||||||
mt: '5px',
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
{errorSaving}
|
|
||||||
</SpanBox>
|
|
||||||
)}
|
|
||||||
{props.lastSaved !== undefined ? (
|
|
||||||
<>
|
|
||||||
{lastChanged === props.lastSaved
|
|
||||||
? 'Saved'
|
|
||||||
: `Last saved ${formattedShortTime(
|
|
||||||
props.lastSaved.toISOString()
|
|
||||||
)}`}
|
|
||||||
</>
|
|
||||||
) : null}
|
|
||||||
</HStack>
|
|
||||||
</VStack>
|
</VStack>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@ -18,13 +18,6 @@ import throttle from 'lodash/throttle'
|
|||||||
import { updateHighlightMutation } from '../../lib/networking/mutations/updateHighlightMutation'
|
import { updateHighlightMutation } from '../../lib/networking/mutations/updateHighlightMutation'
|
||||||
import { Highlight } from '../../lib/networking/fragments/highlightFragment'
|
import { Highlight } from '../../lib/networking/fragments/highlightFragment'
|
||||||
import { Button } from '../elements/Button'
|
import { Button } from '../elements/Button'
|
||||||
import {
|
|
||||||
ModalContent,
|
|
||||||
ModalOverlay,
|
|
||||||
ModalRoot,
|
|
||||||
} from '../elements/ModalPrimitives'
|
|
||||||
import { CloseButton } from '../elements/CloseButton'
|
|
||||||
import { StyledText } from '../elements/StyledText'
|
|
||||||
import remarkGfm from 'remark-gfm'
|
import remarkGfm from 'remark-gfm'
|
||||||
import { RcEditorStyles } from './RcEditorStyles'
|
import { RcEditorStyles } from './RcEditorStyles'
|
||||||
import { isDarkTheme } from '../../lib/themeUpdater'
|
import { isDarkTheme } from '../../lib/themeUpdater'
|
||||||
@ -36,46 +29,6 @@ MdEditor.use(Plugins.TabInsert, {
|
|||||||
tabMapValue: 1, // note that 1 means a '\t' instead of ' '.
|
tabMapValue: 1, // note that 1 means a '\t' instead of ' '.
|
||||||
})
|
})
|
||||||
|
|
||||||
type NoteSectionProps = {
|
|
||||||
targetId: string
|
|
||||||
|
|
||||||
placeHolder: string
|
|
||||||
mode: 'edit' | 'preview'
|
|
||||||
|
|
||||||
setEditMode: (set: 'edit' | 'preview') => void
|
|
||||||
|
|
||||||
text: string | undefined
|
|
||||||
saveText: (text: string, completed: (success: boolean) => void) => void
|
|
||||||
}
|
|
||||||
|
|
||||||
export function HighlightNoteBox(props: NoteSectionProps): JSX.Element {
|
|
||||||
const [lastSaved, setLastSaved] = useState<Date | undefined>(undefined)
|
|
||||||
|
|
||||||
const saveText = useCallback(
|
|
||||||
(text, updateTime) => {
|
|
||||||
props.saveText(text, (success) => {
|
|
||||||
if (success) {
|
|
||||||
setLastSaved(updateTime)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
},
|
|
||||||
[props]
|
|
||||||
)
|
|
||||||
|
|
||||||
return (
|
|
||||||
<MarkdownNote
|
|
||||||
targetId={props.targetId}
|
|
||||||
placeHolder={props.placeHolder}
|
|
||||||
mode={props.mode}
|
|
||||||
setEditMode={props.setEditMode}
|
|
||||||
text={props.text}
|
|
||||||
saveText={saveText}
|
|
||||||
lastSaved={lastSaved}
|
|
||||||
fillBackground={false}
|
|
||||||
/>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
type HighlightViewNoteProps = {
|
type HighlightViewNoteProps = {
|
||||||
targetId: string
|
targetId: string
|
||||||
|
|
||||||
@ -92,9 +45,10 @@ type HighlightViewNoteProps = {
|
|||||||
|
|
||||||
export function HighlightViewNote(props: HighlightViewNoteProps): JSX.Element {
|
export function HighlightViewNote(props: HighlightViewNoteProps): JSX.Element {
|
||||||
const [lastSaved, setLastSaved] = useState<Date | undefined>(undefined)
|
const [lastSaved, setLastSaved] = useState<Date | undefined>(undefined)
|
||||||
|
const [errorSaving, setErrorSaving] = useState<string | undefined>(undefined)
|
||||||
|
|
||||||
const saveText = useCallback(
|
const saveText = useCallback(
|
||||||
(text, updateTime) => {
|
(text, updateTime, interactive) => {
|
||||||
;(async () => {
|
;(async () => {
|
||||||
const success = await updateHighlightMutation({
|
const success = await updateHighlightMutation({
|
||||||
annotation: text,
|
annotation: text,
|
||||||
@ -104,13 +58,13 @@ export function HighlightViewNote(props: HighlightViewNoteProps): JSX.Element {
|
|||||||
setLastSaved(updateTime)
|
setLastSaved(updateTime)
|
||||||
props.highlight.annotation = text
|
props.highlight.annotation = text
|
||||||
props.updateHighlight(props.highlight)
|
props.updateHighlight(props.highlight)
|
||||||
showSuccessToast('Note saved.', {
|
if (interactive) {
|
||||||
position: 'bottom-right',
|
showSuccessToast('Note saved', {
|
||||||
})
|
position: 'bottom-right',
|
||||||
|
})
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
showErrorToast('Error saving note.', {
|
setErrorSaving('Error saving note.')
|
||||||
position: 'bottom-right',
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
})()
|
})()
|
||||||
},
|
},
|
||||||
@ -126,6 +80,7 @@ export function HighlightViewNote(props: HighlightViewNoteProps): JSX.Element {
|
|||||||
text={props.text}
|
text={props.text}
|
||||||
saveText={saveText}
|
saveText={saveText}
|
||||||
lastSaved={lastSaved}
|
lastSaved={lastSaved}
|
||||||
|
errorSaving={errorSaving}
|
||||||
fillBackground={true}
|
fillBackground={true}
|
||||||
/>
|
/>
|
||||||
)
|
)
|
||||||
@ -143,14 +98,47 @@ type MarkdownNote = {
|
|||||||
fillBackground: boolean | undefined
|
fillBackground: boolean | undefined
|
||||||
|
|
||||||
lastSaved: Date | undefined
|
lastSaved: Date | undefined
|
||||||
saveText: (text: string, updateTime: Date) => void
|
errorSaving: string | undefined
|
||||||
|
|
||||||
|
saveText: (text: string, updateTime: Date, interactive: boolean) => void
|
||||||
}
|
}
|
||||||
|
|
||||||
export function MarkdownNote(props: MarkdownNote): JSX.Element {
|
export function MarkdownNote(props: MarkdownNote): JSX.Element {
|
||||||
const editorRef = useRef<MdEditor | null>(null)
|
const editorRef = useRef<MdEditor | null>(null)
|
||||||
const [lastChanged, setLastChanged] = useState<Date | undefined>(undefined)
|
|
||||||
const [errorSaving, setErrorSaving] = useState<string | undefined>(undefined)
|
|
||||||
const isDark = isDarkTheme()
|
const isDark = isDarkTheme()
|
||||||
|
const [lastChanged, setLastChanged] = useState<Date | undefined>(undefined)
|
||||||
|
|
||||||
|
const saveRef = useRef(props.saveText)
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
saveRef.current = props.saveText
|
||||||
|
}, [props])
|
||||||
|
|
||||||
|
const debouncedSave = useMemo<
|
||||||
|
(text: string, updateTime: Date) => void
|
||||||
|
>(() => {
|
||||||
|
const func = (text: string, updateTime: Date) => {
|
||||||
|
saveRef.current?.(text, updateTime, false)
|
||||||
|
}
|
||||||
|
return throttle(func, 3000)
|
||||||
|
}, [])
|
||||||
|
|
||||||
|
const handleEditorChange = useCallback(
|
||||||
|
(
|
||||||
|
data: { text: string; html: string },
|
||||||
|
event?: ChangeEvent<HTMLTextAreaElement> | undefined
|
||||||
|
) => {
|
||||||
|
if (event) {
|
||||||
|
event.preventDefault()
|
||||||
|
}
|
||||||
|
|
||||||
|
const updateTime = new Date()
|
||||||
|
setLastChanged(updateTime)
|
||||||
|
|
||||||
|
debouncedSave(data.text, updateTime)
|
||||||
|
},
|
||||||
|
[]
|
||||||
|
)
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
@ -201,6 +189,7 @@ export function MarkdownNote(props: MarkdownNote): JSX.Element {
|
|||||||
height: '160px',
|
height: '160px',
|
||||||
}}
|
}}
|
||||||
renderHTML={(text: string) => mdParser.render(text)}
|
renderHTML={(text: string) => mdParser.render(text)}
|
||||||
|
onChange={handleEditorChange}
|
||||||
/>
|
/>
|
||||||
<HStack
|
<HStack
|
||||||
css={{
|
css={{
|
||||||
@ -213,7 +202,7 @@ export function MarkdownNote(props: MarkdownNote): JSX.Element {
|
|||||||
alignment="start"
|
alignment="start"
|
||||||
distribution="start"
|
distribution="start"
|
||||||
>
|
>
|
||||||
{errorSaving && (
|
{props.errorSaving && (
|
||||||
<SpanBox
|
<SpanBox
|
||||||
css={{
|
css={{
|
||||||
width: '100%',
|
width: '100%',
|
||||||
@ -222,9 +211,18 @@ export function MarkdownNote(props: MarkdownNote): JSX.Element {
|
|||||||
color: 'red',
|
color: 'red',
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{errorSaving}
|
{props.errorSaving}
|
||||||
</SpanBox>
|
</SpanBox>
|
||||||
)}
|
)}
|
||||||
|
{props.lastSaved !== undefined ? (
|
||||||
|
<>
|
||||||
|
{lastChanged === props.lastSaved
|
||||||
|
? 'Saved'
|
||||||
|
: `Last saved ${formattedShortTime(
|
||||||
|
props.lastSaved.toISOString()
|
||||||
|
)}`}
|
||||||
|
</>
|
||||||
|
) : null}
|
||||||
<SpanBox
|
<SpanBox
|
||||||
css={{
|
css={{
|
||||||
fontSize: '9px',
|
fontSize: '9px',
|
||||||
@ -238,7 +236,9 @@ export function MarkdownNote(props: MarkdownNote): JSX.Element {
|
|||||||
onClick={(event) => {
|
onClick={(event) => {
|
||||||
const value = editorRef.current?.getMdValue()
|
const value = editorRef.current?.getMdValue()
|
||||||
if (value) {
|
if (value) {
|
||||||
props.saveText(value, new Date())
|
const updateTime = new Date()
|
||||||
|
setLastChanged(updateTime)
|
||||||
|
props.saveText(value, updateTime, true)
|
||||||
props.setEditMode('preview')
|
props.setEditMode('preview')
|
||||||
} else {
|
} else {
|
||||||
showErrorToast('Error saving note.', {
|
showErrorToast('Error saving note.', {
|
||||||
|
|||||||
@ -30,5 +30,11 @@ export const RcEditorStyles = (isDark: boolean, shadow: boolean) => {
|
|||||||
border: '1px solid $thBorderSubtle',
|
border: '1px solid $thBorderSubtle',
|
||||||
backgroundColor: isDark ? '#2A2A2A' : 'white',
|
backgroundColor: isDark ? '#2A2A2A' : 'white',
|
||||||
},
|
},
|
||||||
|
'.rc-md-editor:focus-within': {
|
||||||
|
outline: '2px solid $omnivoreCtaYellow',
|
||||||
|
borderRadius: '5px',
|
||||||
|
border: 'unset',
|
||||||
|
boxShadow: 'unset',
|
||||||
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -36,6 +36,8 @@ import { SetHighlightLabelsModalPresenter } from './SetLabelsModalPresenter'
|
|||||||
import { Button } from '../../elements/Button'
|
import { Button } from '../../elements/Button'
|
||||||
import { ArticleNotes } from '../../patterns/ArticleNotes'
|
import { ArticleNotes } from '../../patterns/ArticleNotes'
|
||||||
import { useGetArticleQuery } from '../../../lib/networking/queries/useGetArticleQuery'
|
import { useGetArticleQuery } from '../../../lib/networking/queries/useGetArticleQuery'
|
||||||
|
import { formattedShortTime } from '../../../lib/dateFormatting'
|
||||||
|
import { isDarkTheme } from '../../../lib/themeUpdater'
|
||||||
|
|
||||||
type NotebookContentProps = {
|
type NotebookContentProps = {
|
||||||
viewer: UserBasicData
|
viewer: UserBasicData
|
||||||
@ -64,6 +66,8 @@ type NoteState = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export function NotebookContent(props: NotebookContentProps): JSX.Element {
|
export function NotebookContent(props: NotebookContentProps): JSX.Element {
|
||||||
|
const isDark = isDarkTheme()
|
||||||
|
|
||||||
const { articleData, mutate } = useGetArticleQuery({
|
const { articleData, mutate } = useGetArticleQuery({
|
||||||
slug: props.item.slug,
|
slug: props.item.slug,
|
||||||
username: props.viewer.profile.username,
|
username: props.viewer.profile.username,
|
||||||
@ -74,9 +78,6 @@ export function NotebookContent(props: NotebookContentProps): JSX.Element {
|
|||||||
const [labelsTarget, setLabelsTarget] = useState<Highlight | undefined>(
|
const [labelsTarget, setLabelsTarget] = useState<Highlight | undefined>(
|
||||||
undefined
|
undefined
|
||||||
)
|
)
|
||||||
const [notesEditMode, setNotesEditMode] = useState<'edit' | 'preview'>(
|
|
||||||
'preview'
|
|
||||||
)
|
|
||||||
const noteState = useRef<NoteState>({
|
const noteState = useRef<NoteState>({
|
||||||
isCreating: false,
|
isCreating: false,
|
||||||
note: undefined,
|
note: undefined,
|
||||||
@ -87,14 +88,22 @@ export function NotebookContent(props: NotebookContentProps): JSX.Element {
|
|||||||
return uuidv4()
|
return uuidv4()
|
||||||
}, [])
|
}, [])
|
||||||
|
|
||||||
const updateNote = useCallback((note: Highlight, text: string) => {
|
const updateNote = useCallback(
|
||||||
;(async () => {
|
(note: Highlight, text: string, startTime: Date) => {
|
||||||
const result = await updateHighlightMutation({
|
;(async () => {
|
||||||
highlightId: note.id,
|
const result = await updateHighlightMutation({
|
||||||
annotation: text,
|
highlightId: note.id,
|
||||||
})
|
annotation: text,
|
||||||
})()
|
})
|
||||||
}, [])
|
if (result) {
|
||||||
|
setLastSaved(startTime)
|
||||||
|
} else {
|
||||||
|
setErrorSaving('Error saving')
|
||||||
|
}
|
||||||
|
})()
|
||||||
|
},
|
||||||
|
[]
|
||||||
|
)
|
||||||
|
|
||||||
const createNote = useCallback((text: string) => {
|
const createNote = useCallback((text: string) => {
|
||||||
console.log('creating note: ', newNoteId, noteState.current.isCreating)
|
console.log('creating note: ', newNoteId, noteState.current.isCreating)
|
||||||
@ -112,10 +121,13 @@ export function NotebookContent(props: NotebookContentProps): JSX.Element {
|
|||||||
if (success) {
|
if (success) {
|
||||||
noteState.current.note = success
|
noteState.current.note = success
|
||||||
noteState.current.isCreating = false
|
noteState.current.isCreating = false
|
||||||
|
} else {
|
||||||
|
setErrorSaving('Error creating note')
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('error creating note: ', error)
|
console.error('error creating note: ', error)
|
||||||
noteState.current.isCreating = false
|
noteState.current.isCreating = false
|
||||||
|
setErrorSaving('Error creating note')
|
||||||
}
|
}
|
||||||
})()
|
})()
|
||||||
}, [])
|
}, [])
|
||||||
@ -167,10 +179,12 @@ export function NotebookContent(props: NotebookContentProps): JSX.Element {
|
|||||||
}, [highlights])
|
}, [highlights])
|
||||||
|
|
||||||
const handleSaveNoteText = useCallback(
|
const handleSaveNoteText = useCallback(
|
||||||
(text, cb: (success: boolean) => void) => {
|
(text) => {
|
||||||
console.log('handleSaveNoteText', noteState.current)
|
const changeTime = new Date()
|
||||||
|
|
||||||
|
setLastChanged(changeTime)
|
||||||
if (noteState.current.note) {
|
if (noteState.current.note) {
|
||||||
updateNote(noteState.current.note, text)
|
updateNote(noteState.current.note, text, changeTime)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if (noteState.current.isCreating) {
|
if (noteState.current.isCreating) {
|
||||||
@ -195,6 +209,9 @@ export function NotebookContent(props: NotebookContentProps): JSX.Element {
|
|||||||
|
|
||||||
const [articleNotesCollapsed, setArticleNotesCollapsed] = useState(false)
|
const [articleNotesCollapsed, setArticleNotesCollapsed] = useState(false)
|
||||||
const [highlightsCollapsed, setHighlightsCollapsed] = useState(false)
|
const [highlightsCollapsed, setHighlightsCollapsed] = useState(false)
|
||||||
|
const [errorSaving, setErrorSaving] = useState<string | undefined>(undefined)
|
||||||
|
const [lastChanged, setLastChanged] = useState<Date | undefined>(undefined)
|
||||||
|
const [lastSaved, setLastSaved] = useState<Date | undefined>(undefined)
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<VStack
|
<VStack
|
||||||
@ -203,6 +220,7 @@ export function NotebookContent(props: NotebookContentProps): JSX.Element {
|
|||||||
height: '100%',
|
height: '100%',
|
||||||
width: '100%',
|
width: '100%',
|
||||||
p: '20px',
|
p: '20px',
|
||||||
|
bg: '$readerMargin',
|
||||||
'@mdDown': { p: '15px' },
|
'@mdDown': { p: '15px' },
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
@ -212,20 +230,50 @@ export function NotebookContent(props: NotebookContentProps): JSX.Element {
|
|||||||
setCollapsed={setArticleNotesCollapsed}
|
setCollapsed={setArticleNotesCollapsed}
|
||||||
/>
|
/>
|
||||||
{!articleNotesCollapsed && (
|
{!articleNotesCollapsed && (
|
||||||
<HStack
|
<>
|
||||||
alignment="start"
|
<HStack
|
||||||
distribution="start"
|
alignment="start"
|
||||||
css={{ width: '100%', mt: '10px', gap: '10px' }}
|
distribution="start"
|
||||||
>
|
css={{ width: '100%', mt: '10px', gap: '10px' }}
|
||||||
<ArticleNotes
|
>
|
||||||
mode={notesEditMode}
|
<ArticleNotes
|
||||||
targetId={props.item.id}
|
targetId={props.item.id}
|
||||||
setEditMode={setNotesEditMode}
|
text={noteState.current.note?.annotation}
|
||||||
text={noteState.current.note?.annotation}
|
placeHolder="Add notes to this document..."
|
||||||
placeHolder="Add notes to this document..."
|
saveText={handleSaveNoteText}
|
||||||
saveText={handleSaveNoteText}
|
/>
|
||||||
/>
|
</HStack>
|
||||||
</HStack>
|
<HStack
|
||||||
|
css={{
|
||||||
|
minHeight: '15px',
|
||||||
|
width: '100%',
|
||||||
|
fontSize: '9px',
|
||||||
|
mt: '5px',
|
||||||
|
color: '$thTextSubtle',
|
||||||
|
}}
|
||||||
|
alignment="start"
|
||||||
|
distribution="start"
|
||||||
|
>
|
||||||
|
{errorSaving && (
|
||||||
|
<SpanBox
|
||||||
|
css={{
|
||||||
|
width: '100%',
|
||||||
|
fontSize: '9px',
|
||||||
|
mt: '5px',
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{errorSaving}
|
||||||
|
</SpanBox>
|
||||||
|
)}
|
||||||
|
{lastSaved !== undefined ? (
|
||||||
|
<>
|
||||||
|
{lastChanged === lastSaved
|
||||||
|
? 'Saved'
|
||||||
|
: `Last saved ${formattedShortTime(lastSaved.toISOString())}`}
|
||||||
|
</>
|
||||||
|
) : null}
|
||||||
|
</HStack>
|
||||||
|
</>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
<SpanBox css={{ mt: '10px', mb: '25px' }} />
|
<SpanBox css={{ mt: '10px', mb: '25px' }} />
|
||||||
@ -250,16 +298,14 @@ export function NotebookContent(props: NotebookContentProps): JSX.Element {
|
|||||||
setShowConfirmDeleteHighlightId
|
setShowConfirmDeleteHighlightId
|
||||||
}
|
}
|
||||||
updateHighlight={() => {
|
updateHighlight={() => {
|
||||||
// dispatchAnnotations({
|
mutate()
|
||||||
// type: 'UPDATE_HIGHLIGHT',
|
|
||||||
// updateHighlight: highlight,
|
|
||||||
// })
|
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
))}
|
))}
|
||||||
{sortedHighlights.length === 0 && (
|
{sortedHighlights.length === 0 && (
|
||||||
<Box
|
<Box
|
||||||
css={{
|
css={{
|
||||||
|
p: '10px',
|
||||||
mt: '15px',
|
mt: '15px',
|
||||||
width: '100%',
|
width: '100%',
|
||||||
fontSize: '9px',
|
fontSize: '9px',
|
||||||
@ -267,6 +313,10 @@ export function NotebookContent(props: NotebookContentProps): JSX.Element {
|
|||||||
alignItems: 'center',
|
alignItems: 'center',
|
||||||
justifyContent: 'center',
|
justifyContent: 'center',
|
||||||
mb: '100px',
|
mb: '100px',
|
||||||
|
|
||||||
|
bg: isDark ? '#3D3D3D' : '$thBackground',
|
||||||
|
borderRadius: '6px',
|
||||||
|
boxShadow: '0px 4px 4px rgba(33, 33, 33, 0.1)',
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
You have not added any highlights to this document.
|
You have not added any highlights to this document.
|
||||||
|
|||||||
Reference in New Issue
Block a user