Skip to content
This repository has been archived by the owner on Nov 23, 2022. It is now read-only.

Commit

Permalink
Refactor metadata input and redux action for replacement
Browse files Browse the repository at this point in the history
Signed-off-by: Tilman Vatteroth <[email protected]>
  • Loading branch information
mrdrogdrog committed Mar 17, 2021
1 parent facd55b commit 1e8d355
Show file tree
Hide file tree
Showing 11 changed files with 180 additions and 112 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -4,38 +4,41 @@
* SPDX-License-Identifier: AGPL-3.0-only
*/

import React from 'react'
import React, { useCallback } from 'react'
import { ToggleButton, ToggleButtonGroup } from 'react-bootstrap'
import { Trans, useTranslation } from 'react-i18next'
import { MetadataInputFieldProps } from './metadata-editor'

enum ButtonState {
ON,
OFF
ON = 1,
OFF = 0
}

export const BreaksMetadataInput: React.FC<MetadataInputFieldProps<boolean>> = ({ id, content, onContentChange }) => {
export const BreaksMetadataInput: React.FC<MetadataInputFieldProps<boolean>> = ({ frontmatterKey, content, onContentChange }) => {
const { t } = useTranslation()

const toggleButtonClick = useCallback((value: ButtonState) => {
onContentChange({ breaks: value === ButtonState.ON })
}, [onContentChange])

return (
<ToggleButtonGroup
type="radio"
name={ id }
id={ id }
name={ frontmatterKey }
id={ frontmatterKey }
value={ content ? ButtonState.ON : ButtonState.OFF }
className={ 'd-block' }>
className={ 'd-block' }
onChange={ toggleButtonClick }>
<ToggleButton
value={ ButtonState.ON }
variant="outline-secondary"
title={ t('editor.modal.metadataEditor.labels.breaksOn') }
onChange={ () => onContentChange(true) }>
title={ t('editor.modal.metadataEditor.labels.breaksOn') }>
<Trans i18nKey={ 'editor.modal.metadataEditor.labels.breaksOn' }/>
</ToggleButton>
<ToggleButton
value={ ButtonState.OFF }
variant="outline-secondary"
title={ t('editor.modal.metadataEditor.labels.breaksOff') }
onChange={ () => onContentChange(false) }>
title={ t('editor.modal.metadataEditor.labels.breaksOff') }>
<Trans i18nKey={ 'editor.modal.metadataEditor.labels.breaksOff' }/>
</ToggleButton>
</ToggleButtonGroup>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,26 +4,36 @@
* SPDX-License-Identifier: AGPL-3.0-only
*/

import React, { Fragment, useCallback } from 'react'
import React, { useCallback } from 'react'
import { MetadataInputFieldProps, SelectMetadataOptions } from './metadata-editor'
import { Dropdown, DropdownButton } from 'react-bootstrap'

export const DatalistMetadataInput: React.FC<MetadataInputFieldProps<string> & SelectMetadataOptions<string>> = ({ id, content, onContentChange, options }) => {
const onChange = useCallback((event: React.ChangeEvent<HTMLInputElement>) => {
onContentChange(event.currentTarget.value)
}, [onContentChange])
export const DatalistMetadataInput: React.FC<MetadataInputFieldProps<string> & SelectMetadataOptions<string>> = ({ frontmatterKey, content, onContentChange, options }) => {
const onSelect = useCallback((eventKey: string | null) => {
if (eventKey === null) {
return
}
onContentChange({ [frontmatterKey]: eventKey })
}, [frontmatterKey, onContentChange])

return (
<Fragment>
<input list={ id } onChange={ onChange } value={ content } className={ 'form-control' }/>
<datalist id={ id }>
{ options.map(option => {
return (
<option value={ option }>
{ option }
</option>
)
}) }
</datalist>
</Fragment>
<DropdownButton onSelect={ onSelect } id={ frontmatterKey } title={ content }>
{
options.map((option) => <Dropdown.Item eventKey={ option } key={ option }>{ option }</Dropdown.Item>)
}
</DropdownButton>
)
}
/*
<!--<Fragment>
<input list={ frontmatterKey } onChange={ onChange } value={ content } className={ 'form-control' }/>
<datalist id={ frontmatterKey }>
{ options.map(option => (
<option key={ option } value={ option }>
{ option }
</option>
)) }
</datalist>
</Fragment>-->
*/
58 changes: 29 additions & 29 deletions src/components/editor-page/metadata-editor/metadata-editor.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,9 @@ import { Col, Modal, Row } from 'react-bootstrap'
import { useTranslation } from 'react-i18next'
import { useSelector } from 'react-redux'
import { ApplicationState } from '../../../redux'
import { setNoteFrontmatter } from '../../../redux/note-details/methods'
import { replaceFrontmatterInMarkdownContentAction } from '../../../redux/note-details/methods'
import { CommonModal } from '../../common/modals/common-modal'
import { NoteFrontmatter, NoteType } from '../note-frontmatter/note-frontmatter'
import { NoteType, RawNoteFrontmatter } from '../note-frontmatter/note-frontmatter'
import { BreaksMetadataInput } from './breaks-metadata-input'
import { DatalistMetadataInput } from './datalist-metadata-input'
import { InputLabel } from './input-label'
Expand All @@ -27,9 +27,9 @@ export interface MetadataEditorProps {
}

export interface MetadataInputFieldProps<T> {
id: string
content: T
onContentChange: (newContent: T) => void
frontmatterKey: keyof RawNoteFrontmatter
onContentChange: (frontmatter: RawNoteFrontmatter) => void
}

export interface SelectMetadataOptions<T> {
Expand All @@ -54,11 +54,9 @@ export const MetadataEditor: React.FC<MetadataEditorProps> = ({ show, onHide })
deprecatedTagsSyntax: false
})*/

const setMarkdown = useCallback((changes: Partial<NoteFrontmatter>) => {
const newMetadata = Object.assign(yamlMetadata, changes)

// setnoteDetails(noteDetails)
}, [noteDetails])
const updateFrontmatter = useCallback((frontmatter: RawNoteFrontmatter): void => {
replaceFrontmatterInMarkdownContentAction(frontmatter)
}, [])

return (
<CommonModal
Expand All @@ -71,46 +69,48 @@ export const MetadataEditor: React.FC<MetadataEditorProps> = ({ show, onHide })
<Row>
<Col lg={ 6 }>
<InputLabel id={ 'title' } label={ t('editor.modal.metadataEditor.labels.title') }>
<StringMetadataInput id={ 'title' } content={ yamlMetadata.title }
onContentChange={ title => setNoteFrontmatter({ ...yamlMetadata, title }) }/>
<StringMetadataInput frontmatterKey={ 'title' } content={ yamlMetadata.title }
onContentChange={ updateFrontmatter }/>
</InputLabel>
<InputLabel id={ 'type' } label={ t('editor.modal.metadataEditor.labels.type') }>
<DatalistMetadataInput id={ 'type' } options={ Object.values(NoteType) } content={ yamlMetadata.type }
onContentChange={ type => setNoteFrontmatter({ ...yamlMetadata, type: (type as NoteType) }) }/>
<DatalistMetadataInput frontmatterKey={ 'type' } options={ Object.values(NoteType) }
content={ yamlMetadata.type }
onContentChange={ updateFrontmatter }/>
</InputLabel>
<InputLabel id={ 'dir' } label={ t('editor.modal.metadataEditor.labels.dir') }>
<TextDirectionMetadataInput id={ 'dir' } content={ yamlMetadata.dir }
onContentChange={ dir => setNoteFrontmatter({ ...yamlMetadata, dir }) }/>
<TextDirectionMetadataInput frontmatterKey={ 'dir' } content={ yamlMetadata.dir }
onContentChange={ updateFrontmatter }/>
</InputLabel>
<InputLabel id={ 'description' } label={ t('editor.modal.metadataEditor.labels.description') }>
<StringMetadataTextarea id={ 'description' } content={ yamlMetadata.description }
onContentChange={ description => setNoteFrontmatter({ ...yamlMetadata, description }) }/>
<StringMetadataTextarea frontmatterKey={ 'description' } content={ yamlMetadata.description }
onContentChange={ updateFrontmatter }/>
</InputLabel>
<InputLabel id={ 'disqus' } label={ t('editor.modal.metadataEditor.labels.disqus') }>
<StringMetadataInput id={ 'disqus' } content={ yamlMetadata.disqus }
onContentChange={ disqus => setNoteFrontmatter({ ...yamlMetadata, disqus }) }/>
<StringMetadataInput frontmatterKey={ 'disqus' } content={ yamlMetadata.disqus }
onContentChange={ updateFrontmatter }/>
</InputLabel>
</Col>
<Col lg={ 6 }>
<InputLabel id={ 'lang' } label={ t('editor.modal.metadataEditor.labels.lang') }>
<DatalistMetadataInput id={ 'lang' } options={ ISO.getAllCodes() } content={ yamlMetadata.lang }
onContentChange={ lang => setNoteFrontmatter({ ...yamlMetadata, lang }) }/>
<DatalistMetadataInput frontmatterKey={ 'lang' } options={ ISO.getAllCodes() }
content={ yamlMetadata.lang }
onContentChange={ updateFrontmatter }/>
</InputLabel>
<InputLabel id={ 'robots' } label={ t('editor.modal.metadataEditor.labels.robots') }>
<StringMetadataInput id={ 'robots' } content={ yamlMetadata.robots }
onContentChange={ robots => setNoteFrontmatter({ ...yamlMetadata, robots }) }/>
<StringMetadataInput frontmatterKey={ 'robots' } content={ yamlMetadata.robots }
onContentChange={ updateFrontmatter }/>
</InputLabel>
<InputLabel id={ 'breaks' } label={ t('editor.modal.metadataEditor.labels.breaks') }>
<BreaksMetadataInput id={ 'breaks' } content={ yamlMetadata.breaks }
onContentChange={ breaks => setNoteFrontmatter({ ...yamlMetadata, breaks }) }/>
<BreaksMetadataInput frontmatterKey={ 'breaks' } content={ yamlMetadata.breaks }
onContentChange={ updateFrontmatter }/>
</InputLabel>
<InputLabel id={ 'tags' } label={ t('editor.modal.metadataEditor.labels.tags') }>
<TagsMetadataInput id={ 'tags' } content={ yamlMetadata.tags }
onContentChange={ tags => setNoteFrontmatter({ ...yamlMetadata, tags }) }/>
<TagsMetadataInput frontmatterKey={ 'tags' } content={ yamlMetadata.tags }
onContentChange={ updateFrontmatter }/>
</InputLabel>
<InputLabel id={ 'GA' } label={ t('editor.modal.metadataEditor.labels.GA') }>
<StringMetadataInput id={ 'GA' } content={ yamlMetadata.GA }
onContentChange={ GA => setNoteFrontmatter({ ...yamlMetadata, GA }) }/>
<StringMetadataInput frontmatterKey={ 'GA' } content={ yamlMetadata.GA }
onContentChange={ updateFrontmatter }/>
</InputLabel>
</Col>
</Row>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,14 @@
import React, { useCallback } from 'react'
import { MetadataInputFieldProps } from './metadata-editor'

export const StringMetadataInput: React.FC<MetadataInputFieldProps<string>> = ({ id, content, onContentChange }) => {
export const StringMetadataInput: React.FC<MetadataInputFieldProps<string>> = ({ content, onContentChange, frontmatterKey }) => {
const onChange = useCallback((event: React.ChangeEvent<HTMLInputElement>) => {
onContentChange(event.currentTarget.value)
}, [onContentChange])
onContentChange({ [frontmatterKey]: event.currentTarget.value })
}, [frontmatterKey, onContentChange])

return (
<input
id={ id }
id={ frontmatterKey }
type="text"
className={ 'form-control' }
value={ content }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,14 @@
import React, { useCallback } from 'react'
import { MetadataInputFieldProps } from './metadata-editor'

export const StringMetadataTextarea: React.FC<MetadataInputFieldProps<string>> = ({ id, content, onContentChange }) => {
export const StringMetadataTextarea: React.FC<MetadataInputFieldProps<string>> = ({ frontmatterKey, content, onContentChange }) => {
const onChange = useCallback((event: React.ChangeEvent<HTMLTextAreaElement>) => {
onContentChange(event.currentTarget.value)
onContentChange({ [frontmatterKey]: event.currentTarget.value })
}, [onContentChange])

return (
<textarea
id={ id }
id={ frontmatterKey }
className={ 'form-control' }
value={ content }
onChange={ onChange }
Expand Down
32 changes: 17 additions & 15 deletions src/components/editor-page/metadata-editor/tags-metadata-input.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,18 +4,18 @@
* SPDX-License-Identifier: AGPL-3.0-only
*/

import React, { Fragment, useCallback, useState } from 'react'
import React, { Fragment, useCallback, useMemo, useState } from 'react'
import { ForkAwesomeIcon } from '../../common/fork-awesome/fork-awesome-icon'
import { MetadataInputFieldProps } from './metadata-editor'
import './tags-metadata-input.scss'

export const TagsMetadataInput: React.FC<MetadataInputFieldProps<string[]>> = ({ id, content, onContentChange }) => {
export const TagsMetadataInput: React.FC<MetadataInputFieldProps<string[]>> = ({ frontmatterKey, content, onContentChange }) => {

const [newTag, setNewTag] = useState<string>('')

const addTag = useCallback(() => {
if (!/^\s*$/.test(newTag)) {
onContentChange([...content, newTag])
onContentChange({ tags: [...content, newTag] })
setNewTag('')
}
}, [content, newTag, onContentChange])
Expand All @@ -31,26 +31,28 @@ export const TagsMetadataInput: React.FC<MetadataInputFieldProps<string[]>> = ({
}, [])

const dismissTag = useCallback((clickedTag: string) => {
onContentChange(content.filter(tag => tag !== clickedTag))
onContentChange({ 'tags': content.filter(tag => tag !== clickedTag) })
}, [content, onContentChange])

const tags = useMemo(() => {
return content.map((tag, index) => {
return (
<div className='rounded-pill mr-1 px-2 bg-primary tag-bubble' key={ index }>
<span className={ 'user-select-none' }>{ tag }</span>
<ForkAwesomeIcon icon={ 'times' } className='pl-1 cursor-pointer' onClick={ () => dismissTag(tag) }/>
</div>
)
})
}, [content, dismissTag])

return (
<Fragment>
<div className='d-flex flex-row mb-2 mt-1 overflow-x-scroll'>
{
content.map(tag => {
return (
<div className='rounded-pill mr-1 px-2 bg-primary tag-bubble' key={ tag }>
<span className={ 'user-select-none' }>{ tag }</span>
<ForkAwesomeIcon icon={ 'times' } className='pl-1 cursor-pointer' onClick={ () => dismissTag(tag) }/>
</div>
)
})
}
{ tags }
</div>
<input
type="text"
id={ id }
id={ frontmatterKey }
className='form-control'
value={ newTag }
onKeyDown={ onKeyDown }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,38 +4,41 @@
* SPDX-License-Identifier: AGPL-3.0-only
*/

import React from 'react'
import React, { useCallback } from 'react'
import { ToggleButton, ToggleButtonGroup } from 'react-bootstrap'
import { Trans, useTranslation } from 'react-i18next'
import { ForkAwesomeIcon } from '../../common/fork-awesome/fork-awesome-icon'
import { TextDirection } from '../note-frontmatter/note-frontmatter'
import { MetadataInputFieldProps } from './metadata-editor'
import { NoteTextDirection } from '../note-frontmatter/note-frontmatter'


export const TextDirectionMetadataInput: React.FC<MetadataInputFieldProps<TextDirection>> = ({ id, content, onContentChange }) => {
export const TextDirectionMetadataInput: React.FC<MetadataInputFieldProps<NoteTextDirection>> = ({ frontmatterKey, content, onContentChange }) => {
const { t } = useTranslation()

const toggleButtonSelect = useCallback((value: NoteTextDirection) => {
onContentChange({ dir: value })
}, [onContentChange])

return (
<ToggleButtonGroup
className={ 'd-block' }
type="radio"
name={ id }
id={ id }
value={ content }>
name={ frontmatterKey }
id={ frontmatterKey }
value={ content }
onChange={ toggleButtonSelect }>
<ToggleButton
value={ TextDirection.LTR }
value={ NoteTextDirection.LTR }
variant="outline-secondary"
title={ t('editor.modal.metadataEditor.labels.LTR') }
onChange={ () => onContentChange(TextDirection.LTR) }>
title={ t('editor.modal.metadataEditor.labels.LTR') }>
<ForkAwesomeIcon icon={ 'align-left' }/>
&nbsp;
<Trans i18nKey={ 'editor.modal.metadataEditor.labels.LTR' }/>
</ToggleButton>
<ToggleButton
value={ TextDirection.RTL }
value={ NoteTextDirection.RTL }
variant="outline-secondary"
title={ t('editor.modal.metadataEditor.labels.RTL') }
onChange={ () => onContentChange(TextDirection.RTL) }>
title={ t('editor.modal.metadataEditor.labels.RTL') }>
<ForkAwesomeIcon icon={ 'align-right' }/>
&nbsp;
<Trans i18nKey={ 'editor.modal.metadataEditor.labels.RTL' }/>
Expand Down
Loading

0 comments on commit 1e8d355

Please sign in to comment.