From 5f28e145c48ddf20b3e279c2f7157fa4ce2965e6 Mon Sep 17 00:00:00 2001 From: Elio Struyf Date: Thu, 30 Sep 2021 16:26:21 +0200 Subject: [PATCH] #124 - Add support to specify preview image --- package.json | 4 +++ src/commands/Dashboard.ts | 3 ++- .../components/Contents/Item.tsx | 13 ++++++--- src/dashboardWebView/models/Settings.ts | 2 ++ src/hooks/useContentType.tsx | 27 +++++++++++++++++++ src/models/PanelSettings.ts | 1 + src/panelWebView/components/Metadata.tsx | 14 ++-------- 7 files changed, 47 insertions(+), 17 deletions(-) create mode 100644 src/hooks/useContentType.tsx diff --git a/package.json b/package.json index 714409e2..b908bd39 100644 --- a/package.json +++ b/package.json @@ -294,6 +294,10 @@ "multiSelect": { "type": "boolean", "description": "Do you allow to select multiple values?" + }, + "isPreviewImage": { + "type": "boolean", + "description": "Specify if the image field can be used as preview. Be aware, you can only have one preview image per content type." } }, "additionalProperties": false, diff --git a/src/commands/Dashboard.ts b/src/commands/Dashboard.ts index 17190abf..27dc32a8 100644 --- a/src/commands/Dashboard.ts +++ b/src/commands/Dashboard.ts @@ -1,4 +1,4 @@ -import { SETTINGS_CONTENT_STATIC_FOLDERS, SETTING_DATE_FIELD, SETTING_SEO_DESCRIPTION_FIELD, SETTINGS_DASHBOARD_OPENONSTART, SETTINGS_DASHBOARD_MEDIA_SNIPPET } from './../constants/settings'; +import { SETTINGS_CONTENT_STATIC_FOLDERS, SETTING_DATE_FIELD, SETTING_SEO_DESCRIPTION_FIELD, SETTINGS_DASHBOARD_OPENONSTART, SETTINGS_DASHBOARD_MEDIA_SNIPPET, SETTING_TAXONOMY_CONTENT_TYPES } from './../constants/settings'; import { ArticleHelper } from './../helpers/ArticleHelper'; import { basename, dirname, extname, join, parse } from "path"; import { existsSync, renameSync, statSync, unlinkSync, writeFileSync } from "fs"; @@ -239,6 +239,7 @@ export class Dashboard { versionInfo: ext.getVersion(), pageViewType: await ext.getState(EXTENSION_STATE_PAGES_VIEW), mediaSnippet: SettingsHelper.get(SETTINGS_DASHBOARD_MEDIA_SNIPPET) || [], + contentTypes: SettingsHelper.get(SETTING_TAXONOMY_CONTENT_TYPES) || [], } as Settings }); } diff --git a/src/dashboardWebView/components/Contents/Item.tsx b/src/dashboardWebView/components/Contents/Item.tsx index a68ee036..31488d7c 100644 --- a/src/dashboardWebView/components/Contents/Item.tsx +++ b/src/dashboardWebView/components/Contents/Item.tsx @@ -3,15 +3,20 @@ import { useRecoilValue } from 'recoil'; import { MarkdownIcon } from '../../../panelWebView/components/Icons/MarkdownIcon'; import { DashboardMessage } from '../../DashboardMessage'; import { Page } from '../../models/Page'; -import { ViewSelector, ViewType } from '../../state'; +import { SettingsSelector, ViewSelector, ViewType } from '../../state'; import { DateField } from '../DateField'; import { Status } from '../Status'; import { Messenger } from '@estruyf/vscode/dist/client'; +import useContentType from '../../../hooks/useContentType'; export interface IItemProps extends Page {} -export const Item: React.FunctionComponent = ({ fmFilePath, date, title, draft, description, preview }: React.PropsWithChildren) => { +export const Item: React.FunctionComponent = ({ fmFilePath, date, title, draft, description, type, ...pageData }: React.PropsWithChildren) => { const view = useRecoilValue(ViewSelector); + const settings = useRecoilValue(SettingsSelector); + const contentType = useContentType(settings, { type }); + + const previewField = contentType.fields.find(field => field.isPreviewImage && field.type === "image")?.name || "preview"; const openFile = () => { Messenger.send(DashboardMessage.openFile, fmFilePath); @@ -24,8 +29,8 @@ export const Item: React.FunctionComponent = ({ fmFilePath, date, ti onClick={openFile}>
{ - preview ? ( - {title} + previewField && pageData[previewField] ? ( + {title} ) : (
diff --git a/src/dashboardWebView/models/Settings.ts b/src/dashboardWebView/models/Settings.ts index 59ddaa31..5f17a019 100644 --- a/src/dashboardWebView/models/Settings.ts +++ b/src/dashboardWebView/models/Settings.ts @@ -1,6 +1,7 @@ import { VersionInfo } from '../../models/VersionInfo'; import { ViewType } from '../state'; import { ContentFolder } from '../../models/ContentFolder'; +import { ContentType } from '../../models'; export interface Settings { beta: boolean; @@ -14,4 +15,5 @@ export interface Settings { versionInfo: VersionInfo; pageViewType: ViewType | undefined; mediaSnippet: string[]; + contentTypes: ContentType[]; } \ No newline at end of file diff --git a/src/hooks/useContentType.tsx b/src/hooks/useContentType.tsx new file mode 100644 index 00000000..27b2975a --- /dev/null +++ b/src/hooks/useContentType.tsx @@ -0,0 +1,27 @@ +import { useState, useEffect } from 'react'; +import { DEFAULT_CONTENT_TYPE, DEFAULT_CONTENT_TYPE_NAME } from '../constants/ContentType'; +import { Settings } from '../dashboardWebView/models'; +import { ContentType, PanelSettings } from '../models'; + +export default function useContentType(settings: PanelSettings | Settings | undefined | null, metadata: any) { + const [contentType, setContentType] = useState(DEFAULT_CONTENT_TYPE); + + useEffect(() => { + if (settings) { + const contentTypeName = metadata.type as string || DEFAULT_CONTENT_TYPE_NAME; + let ct = settings.contentTypes.find(ct => ct.name === contentTypeName); + + if (!ct) { + ct = settings.contentTypes.find(ct => ct.name === DEFAULT_CONTENT_TYPE_NAME); + } + + if (!ct || !ct.fields) { + ct = DEFAULT_CONTENT_TYPE; + } + + setContentType(ct || DEFAULT_CONTENT_TYPE) + } + }, [settings?.contentTypes, metadata?.data]); + + return contentType; +} \ No newline at end of file diff --git a/src/models/PanelSettings.ts b/src/models/PanelSettings.ts index aadb9a49..7693e5bb 100644 --- a/src/models/PanelSettings.ts +++ b/src/models/PanelSettings.ts @@ -31,6 +31,7 @@ export interface Field { choices?: string[] | Choice[]; single?: boolean; multiSelect?: boolean; + isPreviewImage?: boolean; } export interface DateInfo { diff --git a/src/panelWebView/components/Metadata.tsx b/src/panelWebView/components/Metadata.tsx index d81c0c3b..a7d7be57 100644 --- a/src/panelWebView/components/Metadata.tsx +++ b/src/panelWebView/components/Metadata.tsx @@ -13,10 +13,10 @@ import { DateTimeField } from './Fields/DateTimeField'; import { TextField } from './Fields/TextField'; import "react-datepicker/dist/react-datepicker.css"; import { PreviewImageField } from './Fields/PreviewImageField'; -import { DEFAULT_CONTENT_TYPE, DEFAULT_CONTENT_TYPE_NAME } from '../../constants/ContentType'; import { ListUnorderedIcon } from './Icons/ListUnorderedIcon'; import { NumberField } from './Fields/NumberField'; import { ChoiceField } from './Fields/ChoiceField'; +import useContentType from '../../hooks/useContentType'; export interface IMetadataProps { settings: PanelSettings | undefined; @@ -26,6 +26,7 @@ export interface IMetadataProps { } export const Metadata: React.FunctionComponent = ({settings, metadata, focusElm, unsetFocus}: React.PropsWithChildren) => { + const contentType = useContentType(settings, metadata); const sendUpdate = (field: string | undefined, value: any) => { if (!field) { @@ -49,17 +50,6 @@ export const Metadata: React.FunctionComponent = ({settings, met return null; } - const contentTypeName = metadata.type as string || DEFAULT_CONTENT_TYPE_NAME; - let contentType = settings.contentTypes.find(ct => ct.name === contentTypeName); - - if (!contentType) { - contentType = settings.contentTypes.find(ct => ct.name === DEFAULT_CONTENT_TYPE_NAME); - } - - if (!contentType || !contentType.fields) { - contentType = DEFAULT_CONTENT_TYPE; - } - const renderFields = (ctFields: Field[]) => { if (!ctFields) { return;