mirror of
https://github.com/estruyf/vscode-front-matter.git
synced 2026-08-06 00:43:17 +02:00
#124 - Add support to specify preview image
This commit is contained in:
@@ -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,
|
||||
|
||||
@@ -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<ViewType | undefined>(EXTENSION_STATE_PAGES_VIEW),
|
||||
mediaSnippet: SettingsHelper.get<string[]>(SETTINGS_DASHBOARD_MEDIA_SNIPPET) || [],
|
||||
contentTypes: SettingsHelper.get(SETTING_TAXONOMY_CONTENT_TYPES) || [],
|
||||
} as Settings
|
||||
});
|
||||
}
|
||||
|
||||
@@ -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<IItemProps> = ({ fmFilePath, date, title, draft, description, preview }: React.PropsWithChildren<IItemProps>) => {
|
||||
export const Item: React.FunctionComponent<IItemProps> = ({ fmFilePath, date, title, draft, description, type, ...pageData }: React.PropsWithChildren<IItemProps>) => {
|
||||
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<IItemProps> = ({ fmFilePath, date, ti
|
||||
onClick={openFile}>
|
||||
<div className="relative h-36 w-full overflow-hidden border-b border-gray-100 dark:border-vulcan-100 dark:group-hover:border-vulcan-200">
|
||||
{
|
||||
preview ? (
|
||||
<img src={`${preview}`} alt={title} className="absolute inset-0 h-full w-full object-cover" loading="lazy" />
|
||||
previewField && pageData[previewField] ? (
|
||||
<img src={`${pageData[previewField]}`} alt={title} className="absolute inset-0 h-full w-full object-cover" loading="lazy" />
|
||||
) : (
|
||||
<div className={`flex items-center justify-center bg-whisper-500 dark:bg-vulcan-200 dark:group-hover:bg-vulcan-100`}>
|
||||
<MarkdownIcon className={`h-32 text-vulcan-100 dark:text-whisper-100`} />
|
||||
|
||||
@@ -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[];
|
||||
}
|
||||
@@ -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<ContentType>(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;
|
||||
}
|
||||
@@ -31,6 +31,7 @@ export interface Field {
|
||||
choices?: string[] | Choice[];
|
||||
single?: boolean;
|
||||
multiSelect?: boolean;
|
||||
isPreviewImage?: boolean;
|
||||
}
|
||||
|
||||
export interface DateInfo {
|
||||
|
||||
@@ -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<IMetadataProps> = ({settings, metadata, focusElm, unsetFocus}: React.PropsWithChildren<IMetadataProps>) => {
|
||||
const contentType = useContentType(settings, metadata);
|
||||
|
||||
const sendUpdate = (field: string | undefined, value: any) => {
|
||||
if (!field) {
|
||||
@@ -49,17 +50,6 @@ export const Metadata: React.FunctionComponent<IMetadataProps> = ({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;
|
||||
|
||||
Reference in New Issue
Block a user