From 442261e6557e21c3a0cd997faf2816e3c776adab Mon Sep 17 00:00:00 2001 From: Elio Struyf Date: Mon, 14 Feb 2022 16:07:59 -0800 Subject: [PATCH] #176 - Taxonomy field support added to block field --- assets/media/styles.css | 1 + src/listeners/panel/DataListener.ts | 74 ++++++++++++++--------- src/listeners/panel/TaxonomyListener.ts | 22 +++---- src/models/CustomTaxonomyData.ts | 2 + src/panelWebView/components/Metadata.tsx | 9 ++- src/panelWebView/components/TagPicker.tsx | 14 +++-- 6 files changed, 70 insertions(+), 52 deletions(-) diff --git a/assets/media/styles.css b/assets/media/styles.css index 4f839e5d..ec9f85d4 100644 --- a/assets/media/styles.css +++ b/assets/media/styles.css @@ -143,6 +143,7 @@ } .article__tags { + position: relative; margin-bottom: 1rem; } diff --git a/src/listeners/panel/DataListener.ts b/src/listeners/panel/DataListener.ts index b7902b6c..33f301b2 100644 --- a/src/listeners/panel/DataListener.ts +++ b/src/listeners/panel/DataListener.ts @@ -8,6 +8,7 @@ import { commands, ThemeIcon, window } from 'vscode'; import { ArticleHelper, Settings } from "../../helpers"; import { COMMAND_NAME, DefaultFields, SETTING_COMMA_SEPARATED_FIELDS, SETTING_TAXONOMY_CONTENT_TYPES } from "../../constants"; import { Article } from '../../commands'; +import { ParsedFrontMatter } from '../../parsers'; const FILE_LIMIT = 10; @@ -133,8 +134,50 @@ export class DataListener extends BaseListener { const imageFields = contentType.fields.filter((f) => f.type === "image" && f.multiple); // Support multi-level fields - let parentObj = article.data; + const parentObj = DataListener.getParentObject(article.data, article, parents, blockData); + + for (const dateField of dateFields) { + if ((field === dateField.name) && value) { + parentObj[field] = Article.formatDate(new Date(value)); + } else if (!imageFields.find(f => f.name === field)) { + // Only override the field data if it is not an multiselect image field + parentObj[field] = value; + } + } + + for (const imageField of imageFields) { + if (field === imageField.name) { + // If value is an array, it means it comes from the explorer view itself (deletion) + if (Array.isArray(value)) { + parentObj[field] = value || []; + } else { // Otherwise it is coming from the media dashboard (addition) + let fieldValue = parentObj[field]; + if (fieldValue && !Array.isArray(fieldValue)) { + fieldValue = [fieldValue]; + } + const crntData = Object.assign([], fieldValue); + const allRelPaths = [...(crntData || []), value]; + parentObj[field] = [...new Set(allRelPaths)].filter(f => f); + } + } + } + + ArticleHelper.update(editor, article); + this.pushMetadata(article.data); + } + + /** + * Retrieve the parent object to update + * @param data + * @param article + * @param parents + * @param blockData + * @returns + */ + public static getParentObject(data: any, article: ParsedFrontMatter, parents: string[] | undefined, blockData?: BlockFieldData) { + let parentObj = data; let allParents = Object.assign([], parents); + const contentType = ArticleHelper.getContentType(article.data); // Add support for block fields if (blockData?.parentFields) { @@ -188,34 +231,7 @@ export class DataListener extends BaseListener { } } - for (const dateField of dateFields) { - if ((field === dateField.name) && value) { - parentObj[field] = Article.formatDate(new Date(value)); - } else if (!imageFields.find(f => f.name === field)) { - // Only override the field data if it is not an multiselect image field - parentObj[field] = value; - } - } - - for (const imageField of imageFields) { - if (field === imageField.name) { - // If value is an array, it means it comes from the explorer view itself (deletion) - if (Array.isArray(value)) { - parentObj[field] = value || []; - } else { // Otherwise it is coming from the media dashboard (addition) - let fieldValue = parentObj[field]; - if (fieldValue && !Array.isArray(fieldValue)) { - fieldValue = [fieldValue]; - } - const crntData = Object.assign([], fieldValue); - const allRelPaths = [...(crntData || []), value]; - parentObj[field] = [...new Set(allRelPaths)].filter(f => f); - } - } - } - - ArticleHelper.update(editor, article); - this.pushMetadata(article.data); + return parentObj; } /** diff --git a/src/listeners/panel/TaxonomyListener.ts b/src/listeners/panel/TaxonomyListener.ts index 6b1fa5de..675f3c88 100644 --- a/src/listeners/panel/TaxonomyListener.ts +++ b/src/listeners/panel/TaxonomyListener.ts @@ -3,7 +3,7 @@ import { TagType } from "../../panelWebView/TagType"; import { BaseListener } from "./BaseListener"; import { window } from "vscode"; import { ArticleHelper, Settings } from "../../helpers"; -import { CustomTaxonomyData, TaxonomyType } from "../../models"; +import { BlockFieldData, CustomTaxonomyData, TaxonomyType } from "../../models"; import { DataListener } from "."; import { SETTING_TAXONOMY_CATEGORIES, SETTING_TAXONOMY_TAGS } from "../../constants"; @@ -19,13 +19,13 @@ export class TaxonomyListener extends BaseListener { switch(msg.command) { case CommandToCode.updateTags: - this.updateTags(TagType.tags, msg.data?.values || [], msg.data?.parents || []); + this.updateTags(TagType.tags, msg.data?.values || [], msg.data?.parents || [], msg.data?.blockData); break; case CommandToCode.updateCategories: - this.updateTags(TagType.categories, msg.data?.values || [], msg.data?.parents || []); + this.updateTags(TagType.categories, msg.data?.values || [], msg.data?.parents || [], msg.data?.blockData); break; case CommandToCode.updateKeywords: - this.updateTags(TagType.keywords, msg.data?.values || [], msg.data?.parents || []); + this.updateTags(TagType.keywords, msg.data?.values || [], msg.data?.parents || [], msg.data?.blockData); break; case CommandToCode.updateCustomTaxonomy: this.updateCustomTaxonomy(msg.data); @@ -47,7 +47,7 @@ export class TaxonomyListener extends BaseListener { * @param tagType * @param values */ - private static updateTags(tagType: TagType, values: string[], parents: string[]) { + private static updateTags(tagType: TagType, values: string[], parents: string[], blockData?: BlockFieldData) { const editor = window.activeTextEditor; if (!editor) { return ""; @@ -56,11 +56,7 @@ export class TaxonomyListener extends BaseListener { const article = ArticleHelper.getFrontMatter(editor); if (article && article.data) { - // Support multi-level fields - let parentObj = article.data; - for (const parent of parents || []) { - parentObj = parentObj[parent]; - } + const parentObj = DataListener.getParentObject(article.data, article, parents, blockData); parentObj[tagType.toLowerCase()] = values || []; ArticleHelper.update(editor, article); @@ -85,11 +81,7 @@ export class TaxonomyListener extends BaseListener { const article = ArticleHelper.getFrontMatter(editor); if (article && article.data) { - // Support multi-level fields - let parentObj = article.data; - for (const parent of data.parents || []) { - parentObj = parentObj[parent]; - } + const parentObj = DataListener.getParentObject(article.data, article, data.parents, data.blockData); parentObj[data.name] = data.options || []; ArticleHelper.update(editor, article); diff --git a/src/models/CustomTaxonomyData.ts b/src/models/CustomTaxonomyData.ts index f9b9f1b1..5862eecd 100644 --- a/src/models/CustomTaxonomyData.ts +++ b/src/models/CustomTaxonomyData.ts @@ -1,3 +1,4 @@ +import { BlockFieldData } from './BlockFieldData'; export interface CustomTaxonomyData { id: string | undefined; @@ -5,4 +6,5 @@ export interface CustomTaxonomyData { options?: string[] | undefined; option?: string | undefined; parents?: string[]; + blockData?: BlockFieldData; } \ No newline at end of file diff --git a/src/panelWebView/components/Metadata.tsx b/src/panelWebView/components/Metadata.tsx index a1940d7c..a075ab80 100644 --- a/src/panelWebView/components/Metadata.tsx +++ b/src/panelWebView/components/Metadata.tsx @@ -180,7 +180,8 @@ const Metadata: React.FunctionComponent = ({settings, metadata, freeform={settings.freeform || false} focussed={focusElm === TagType.tags} unsetFocus={unsetFocus} - parents={parentFields} /> + parents={parentFields} + blockData={blockData} /> ); } else if (field.type === 'taxonomy') { @@ -200,7 +201,8 @@ const Metadata: React.FunctionComponent = ({settings, metadata, unsetFocus={unsetFocus} fieldName={field.name} taxonomyId={field.taxonomyId} - parents={parentFields} /> + parents={parentFields} + blockData={blockData} /> ); } else if (field.type === 'categories') { @@ -215,7 +217,8 @@ const Metadata: React.FunctionComponent = ({settings, metadata, freeform={settings.freeform || false} focussed={focusElm === TagType.categories} unsetFocus={unsetFocus} - parents={parentFields} /> + parents={parentFields} + blockData={blockData} /> ); } else if (field.type === 'draft') { diff --git a/src/panelWebView/components/TagPicker.tsx b/src/panelWebView/components/TagPicker.tsx index 3ce29307..7040e025 100644 --- a/src/panelWebView/components/TagPicker.tsx +++ b/src/panelWebView/components/TagPicker.tsx @@ -7,7 +7,7 @@ import Downshift from 'downshift'; import { AddIcon } from './Icons/AddIcon'; import { VsLabel } from './VscodeComponents'; import { MessageHelper } from '../../helpers/MessageHelper'; -import { CustomTaxonomyData } from '../../models'; +import { BlockFieldData, CustomTaxonomyData } from '../../models'; export interface ITagPickerProps { type: TagType; @@ -19,6 +19,7 @@ export interface ITagPickerProps { unsetFocus: () => void; parents?: string[]; + blockData?: BlockFieldData; label?: string; disableConfigurable?: boolean; fieldName?: string; @@ -26,7 +27,7 @@ export interface ITagPickerProps { } const TagPicker: React.FunctionComponent = (props: React.PropsWithChildren) => { - const { label, icon, type, crntSelected, options, freeform, focussed, unsetFocus, disableConfigurable, fieldName, taxonomyId, parents } = props; + const { label, icon, type, crntSelected, options, freeform, focussed, unsetFocus, disableConfigurable, fieldName, taxonomyId, parents, blockData } = props; const [ selected, setSelected ] = React.useState([]); const [ inputValue, setInputValue ] = React.useState(""); const prevSelected = usePrevious(crntSelected); @@ -69,12 +70,14 @@ const TagPicker: React.FunctionComponent = (props: React.PropsW if (type === TagType.tags) { MessageHelper.sendMessage(CommandToCode.updateTags, { values, - parents + parents, + blockData }); } else if (type === TagType.categories) { MessageHelper.sendMessage(CommandToCode.updateCategories, { values, - parents + parents, + blockData }); } else if (type === TagType.keywords) { MessageHelper.sendMessage(CommandToCode.updateKeywords, { @@ -86,7 +89,8 @@ const TagPicker: React.FunctionComponent = (props: React.PropsW id: taxonomyId, name: fieldName, options: values, - parents + parents, + blockData } as CustomTaxonomyData); } };