Reorganize redux and hooks (1/4) (#985)

Signed-off-by: Tilman Vatteroth <tilman.vatteroth@tu-dortmund.de>
This commit is contained in:
Tilman Vatteroth 2021-02-01 22:55:49 +01:00 committed by GitHub
parent bdf8110676
commit 1b7abf9f27
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
61 changed files with 898 additions and 986 deletions

View file

@ -0,0 +1,57 @@
/*
* SPDX-FileCopyrightText: 2021 The HedgeDoc developers (see AUTHORS file)
*
* SPDX-License-Identifier: AGPL-3.0-only
*/
import { store } from '..'
import { Note } from '../../api/notes'
import { NoteFrontmatter } from '../../components/editor/note-frontmatter/note-frontmatter'
import { initialState } from './reducers'
import {
NoteDetailsActionType,
SetCheckboxInMarkdownContentAction,
SetNoteDetailsAction,
SetNoteDetailsFromServerAction,
SetNoteFrontmatterFromRenderingAction,
UpdateNoteTitleByFirstHeadingAction
} from './types'
export const setNoteMarkdownContent = (content: string): void => {
store.dispatch({
type: NoteDetailsActionType.SET_DOCUMENT_CONTENT,
content
} as SetNoteDetailsAction)
}
export const setNoteDataFromServer = (apiResponse: Note): void => {
store.dispatch({
type: NoteDetailsActionType.SET_NOTE_DATA_FROM_SERVER,
note: apiResponse
} as SetNoteDetailsFromServerAction)
}
export const updateNoteTitleByFirstHeading = (firstHeading?: string): void => {
store.dispatch({
type: NoteDetailsActionType.UPDATE_NOTE_TITLE_BY_FIRST_HEADING,
firstHeading: firstHeading ?? ''
} as UpdateNoteTitleByFirstHeadingAction)
}
export const setNoteFrontmatter = (frontmatter: NoteFrontmatter | undefined): void => {
if (!frontmatter) {
frontmatter = initialState.frontmatter
}
store.dispatch({
type: NoteDetailsActionType.SET_NOTE_FRONTMATTER,
frontmatter: frontmatter
} as SetNoteFrontmatterFromRenderingAction)
}
export const SetCheckboxInMarkdownContent = (lineInMarkdown: number, checked: boolean): void => {
store.dispatch({
type: NoteDetailsActionType.SET_CHECKBOX_IN_MARKDOWN_CONTENT,
checked: checked,
lineInMarkdown: lineInMarkdown
} as SetCheckboxInMarkdownContentAction)
}

View file

@ -0,0 +1,127 @@
/*
* SPDX-FileCopyrightText: 2021 The HedgeDoc developers (see AUTHORS file)
*
* SPDX-License-Identifier: AGPL-3.0-only
*/
import { DateTime } from 'luxon'
import { Reducer } from 'redux'
import { Note } from '../../api/notes'
import { NoteFrontmatter } from '../../components/editor/note-frontmatter/note-frontmatter'
import {
NoteDetails,
NoteDetailsAction,
NoteDetailsActionType,
SetCheckboxInMarkdownContentAction,
SetNoteDetailsAction,
SetNoteDetailsFromServerAction,
SetNoteFrontmatterFromRenderingAction,
UpdateNoteTitleByFirstHeadingAction
} from './types'
export const initialState: NoteDetails = {
markdownContent: '',
id: '',
createTime: DateTime.fromSeconds(0),
lastChange: {
timestamp: DateTime.fromSeconds(0),
userId: ''
},
alias: '',
preVersionTwoNote: false,
viewCount: 0,
authorship: [],
noteTitle: '',
firstHeading: '',
frontmatter: {
title: '',
description: '',
tags: [],
deprecatedTagsSyntax: false,
robots: '',
lang: 'en',
dir: 'ltr',
breaks: true,
GA: '',
disqus: '',
type: '',
opengraph: new Map<string, string>()
}
}
export const NoteDetailsReducer: Reducer<NoteDetails, NoteDetailsAction> = (state: NoteDetails = initialState, action: NoteDetailsAction) => {
switch (action.type) {
case NoteDetailsActionType.SET_DOCUMENT_CONTENT:
return {
...state,
markdownContent: (action as SetNoteDetailsAction).content
}
case NoteDetailsActionType.UPDATE_NOTE_TITLE_BY_FIRST_HEADING:
return {
...state,
firstHeading: (action as UpdateNoteTitleByFirstHeadingAction).firstHeading,
noteTitle: generateNoteTitle(state.frontmatter, (action as UpdateNoteTitleByFirstHeadingAction).firstHeading)
}
case NoteDetailsActionType.SET_NOTE_DATA_FROM_SERVER:
return convertNoteToNoteDetails((action as SetNoteDetailsFromServerAction).note)
case NoteDetailsActionType.SET_NOTE_FRONTMATTER:
return {
...state,
frontmatter: (action as SetNoteFrontmatterFromRenderingAction).frontmatter,
noteTitle: generateNoteTitle((action as SetNoteFrontmatterFromRenderingAction).frontmatter, state.firstHeading)
}
case NoteDetailsActionType.SET_CHECKBOX_IN_MARKDOWN_CONTENT:
return {
...state,
markdownContent: setCheckboxInMarkdownContent(
state.markdownContent,
(action as SetCheckboxInMarkdownContentAction).lineInMarkdown,
(action as SetCheckboxInMarkdownContentAction).checked
)
}
default:
return state
}
}
const TASK_REGEX = /(\s*[-*] )(\[[ xX]])( .*)/
const setCheckboxInMarkdownContent = (markdownContent: string, lineInMarkdown: number, checked: boolean): string => {
const lines = markdownContent.split('\n')
const results = TASK_REGEX.exec(lines[lineInMarkdown])
if (results) {
const before = results[1]
const after = results[3]
lines[lineInMarkdown] = `${before}[${checked ? 'x' : ' '}]${after}`
return lines.join('\n')
}
return markdownContent
}
const generateNoteTitle = (frontmatter: NoteFrontmatter, firstHeading?: string) => {
if (frontmatter?.title && frontmatter?.title !== '') {
return frontmatter.title.trim()
} else if (frontmatter?.opengraph && frontmatter?.opengraph.get('title') && frontmatter?.opengraph.get('title') !== '') {
return (frontmatter?.opengraph.get('title') ?? firstHeading ?? '').trim()
} else {
return (firstHeading ?? firstHeading ?? '').trim()
}
}
const convertNoteToNoteDetails = (note: Note): NoteDetails => {
return {
markdownContent: note.content,
frontmatter: initialState.frontmatter,
id: note.id,
noteTitle: initialState.noteTitle,
createTime: DateTime.fromSeconds(note.createTime),
lastChange: {
userId: note.lastChange.userId,
timestamp: DateTime.fromSeconds(note.lastChange.timestamp)
},
firstHeading: initialState.firstHeading,
preVersionTwoNote: note.preVersionTwoNote,
viewCount: note.viewCount,
alias: note.alias,
authorship: note.authorship
}
}

View file

@ -0,0 +1,67 @@
/*
* SPDX-FileCopyrightText: 2021 The HedgeDoc developers (see AUTHORS file)
*
* SPDX-License-Identifier: AGPL-3.0-only
*/
import { DateTime } from 'luxon'
import { Action } from 'redux'
import { Note } from '../../api/notes'
import { NoteFrontmatter } from '../../components/editor/note-frontmatter/note-frontmatter'
export enum NoteDetailsActionType {
SET_DOCUMENT_CONTENT = 'note-details/set',
SET_NOTE_DATA_FROM_SERVER = 'note-details/data/server/set',
SET_NOTE_FRONTMATTER = 'note-details/frontmatter/set',
UPDATE_NOTE_TITLE_BY_FIRST_HEADING = 'note-details/update-note-title-by-first-heading',
SET_CHECKBOX_IN_MARKDOWN_CONTENT = 'note-details/toggle-checkbox-in-markdown-content'
}
interface LastChange {
userId: string
timestamp: DateTime
}
export interface NoteDetails {
markdownContent: string
id: string
createTime: DateTime
lastChange: LastChange
preVersionTwoNote: boolean
viewCount: number
alias: string
authorship: number[]
noteTitle: string
firstHeading: string
frontmatter: NoteFrontmatter
}
export interface NoteDetailsAction extends Action<NoteDetailsActionType> {
type: NoteDetailsActionType
}
export interface SetNoteDetailsAction extends NoteDetailsAction {
type: NoteDetailsActionType.SET_DOCUMENT_CONTENT
content: string
}
export interface SetNoteDetailsFromServerAction extends NoteDetailsAction {
type: NoteDetailsActionType.SET_NOTE_DATA_FROM_SERVER
note: Note
}
export interface UpdateNoteTitleByFirstHeadingAction extends NoteDetailsAction {
type: NoteDetailsActionType.UPDATE_NOTE_TITLE_BY_FIRST_HEADING
firstHeading: string
}
export interface SetNoteFrontmatterFromRenderingAction extends NoteDetailsAction {
type: NoteDetailsActionType.SET_NOTE_FRONTMATTER
frontmatter: NoteFrontmatter
}
export interface SetCheckboxInMarkdownContentAction extends NoteDetailsAction {
type: NoteDetailsActionType.SET_CHECKBOX_IN_MARKDOWN_CONTENT,
lineInMarkdown: number,
checked: boolean
}