diff --git a/front/src/components/Form.jsx b/front/src/components/Form.jsx index 4e97a913f..0cf2831f9 100644 --- a/front/src/components/Form.jsx +++ b/front/src/components/Form.jsx @@ -7,7 +7,6 @@ import { Translation } from 'react-i18next' import basicUiSchema from '../schemas/ui-schema-basic-override.json' import defaultUiSchema from '../schemas/ui-schema-editor.json' import defaultSchema from '../schemas/data-schema.json' -import { toYaml } from './Write/metadata/yaml' // REMIND: use a custom SelectWidget to support "ui:emptyValue" // remove once fixed in https://github.com/rjsf-team/react-jsonschema-form/issues/1041 @@ -256,7 +255,7 @@ export default function SchemaForm ({ const path = id.replace('root_', '').replace('_', '.') setFormData((state) => { const newFormData = set(state, path, value) - onChange(toYaml(newFormData)) + onChange(newFormData) return newFormData }) }, @@ -282,7 +281,7 @@ export default function SchemaForm ({ const handleUpdate = useCallback((event) => { const formData = event.formData setFormData(formData) - onChange(toYaml(formData)) + onChange(formData) }, [setFormData, onChange]) // noinspection JSValidateTypes diff --git a/front/src/components/Write/yamleditor/YamlEditor.jsx b/front/src/components/Write/yamleditor/YamlEditor.jsx index 2ed7e56e5..ac64b8978 100644 --- a/front/src/components/Write/yamleditor/YamlEditor.jsx +++ b/front/src/components/Write/yamleditor/YamlEditor.jsx @@ -1,28 +1,15 @@ -import React from 'react' +import React, { useCallback } from 'react' import PropTypes from 'prop-types' import YAML from 'js-yaml' import Form from '../../Form' +import { toYaml } from "../metadata/yaml.js"; +import { convertLegacyValues } from "../../metadata/MetadataValues.js"; -export default function YamlEditor ({ yaml = '', basicMode = false, onChange }) { +export default function YamlEditor({ yaml = '', basicMode = false, onChange = () => {} }) { const [parsed = {}] = YAML.loadAll(yaml) - - // we convert YYYY/MM/DD dates into ISO YYYY-MM-DD - if (parsed.date) { - parsed.date = parsed.date.replace(/\//g, '-') - } - - // we array-ify legacy string keywords - if (parsed.keywords) { - parsed.keywords = parsed.keywords.map(block => { - if (typeof block.list_f === 'string') { - block.list_f = block.list_f.split(',').map(word => word.trim()) - } - - return block - }) - } - - return
+ const formData = convertLegacyValues(parsed) + const handleChange = useCallback((newFormData) => onChange(toYaml(newFormData)), [onChange]) + return } YamlEditor.propTypes = { diff --git a/front/src/components/corpus/Corpus.graphql b/front/src/components/corpus/Corpus.graphql index 5d5ed6432..b725408b7 100644 --- a/front/src/components/corpus/Corpus.graphql +++ b/front/src/components/corpus/Corpus.graphql @@ -9,6 +9,7 @@ query getCorpus($filter: FilterCorpusInput, $includeArticles: Boolean = false) { username email } + metadata articles @include(if: $includeArticles) { article { _id @@ -45,6 +46,14 @@ mutation deleteCorpus($corpusId: ID!) { } } +mutation updateMetadata($corpusId: ID!, $metadata: String!) { + corpus(corpusId: $corpusId) { + updateMetadata(metadata: $metadata) { + _id + } + } +} + mutation updateCorpus($corpusId: ID!, $updateCorpusInput: UpdateCorpusInput!) { corpus(corpusId: $corpusId) { update(updateCorpusInput: $updateCorpusInput) { diff --git a/front/src/components/corpus/CorpusItem.jsx b/front/src/components/corpus/CorpusItem.jsx index 6cd0f7e68..7dd27fd81 100644 --- a/front/src/components/corpus/CorpusItem.jsx +++ b/front/src/components/corpus/CorpusItem.jsx @@ -18,7 +18,7 @@ import { deleteCorpus } from './Corpus.graphql' import styles from './corpusItem.module.scss' -export default function CorpusItem ({ corpus }) { +export default function CorpusItem({ corpus }) { const { t } = useTranslation() const { setToast } = useToasts() const dispatch = useDispatch() @@ -86,7 +86,7 @@ export default function CorpusItem ({ corpus }) {

{expanded &&
{corpus.description &&

{corpus.description}

} - +
} @@ -115,16 +116,18 @@ export default function CorpusItem ({ corpus }) { {t('corpus.deleteModal.confirmMessage')} - setDeleteCorpusVisible(false)}>{t('modal.cancelButton.text')} + setDeleteCorpusVisible(false)}>{t('modal.cancelButton.text')} {t('modal.confirmButton.text')}

{t('corpus.exportModal.title')}

- + - setExportCorpusVisible(false)}>{t('modal.cancelButton.text')} + setExportCorpusVisible(false)}>{t('modal.cancelButton.text')}
@@ -132,7 +135,8 @@ export default function CorpusItem ({ corpus }) { - setEditCorpusVisible(false)}>{t('modal.cancelButton.text')} + setEditCorpusVisible(false)}>{t('modal.cancelButton.text')} ) diff --git a/front/src/components/metadata/MetadataForm.jsx b/front/src/components/metadata/MetadataForm.jsx new file mode 100644 index 000000000..b9d3facdb --- /dev/null +++ b/front/src/components/metadata/MetadataForm.jsx @@ -0,0 +1,25 @@ +import React from "react"; +import PropTypes from "prop-types"; + +import Form from "../Form.jsx"; +import { convertLegacyValues } from "./MetadataValues.js"; + +/** + * @param data Values in JSON format + * @param templates List of template names + * @param onChange Function that return the values in YAML format + * @returns {Element} + * @constructor + */ +export default function MetadataForm({ data, templates, onChange }) { + const formData = convertLegacyValues(data) + const basicMode = templates.includes('basic') + return +} + +MetadataForm.propTypes = { + data: PropTypes.object, + templates: PropTypes.array, + onChange: PropTypes.func, +} + diff --git a/front/src/components/metadata/MetadataValues.js b/front/src/components/metadata/MetadataValues.js new file mode 100644 index 000000000..3ff8175a9 --- /dev/null +++ b/front/src/components/metadata/MetadataValues.js @@ -0,0 +1,23 @@ +/** + * Convert legacy values. + * @param {object} data + * @returns {*} + */ +export function convertLegacyValues(data) { + // we convert YYYY/MM/DD dates into ISO YYYY-MM-DD + if (data.date) { + data.date = data.date.replace(/\//g, '-') + } + + // we array-ify legacy string keywords + if (data.keywords) { + data.keywords = data.keywords.map(block => { + if (typeof block.list_f === 'string') { + block.list_f = block.list_f.split(',').map(word => word.trim()) + } + return block + }) + } + + return data +} diff --git a/front/src/schemas/corpus-journal-metadata.schema.json b/front/src/schemas/corpus-journal-metadata.schema.json new file mode 100644 index 000000000..c5a545ad2 --- /dev/null +++ b/front/src/schemas/corpus-journal-metadata.schema.json @@ -0,0 +1,29 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://stylo.huma-num.fr/schemas/corpus-journal-metadata.schema.json", + "title": "Journal metadata", + "type": "object", + "properties": { + "type": { + "type": "string", + "const": "journal" + }, + "name": { + "type": "string" + }, + "issue": { + "type": "object", + "properties": { + "title": { + "type": "string" + }, + "identifier": { + "type": "string" + }, + "number": { + "type": "string" + } + } + } + } +} diff --git a/graphql/package.json b/graphql/package.json index f793ec33a..323cab1f0 100644 --- a/graphql/package.json +++ b/graphql/package.json @@ -61,4 +61,4 @@ "node": "18.20.4", "npm": "10.9.0" } -} \ No newline at end of file +}