mirror of
https://github.com/estruyf/vscode-front-matter.git
synced 2026-08-07 09:23:00 +02:00
#586 - Allow to specify the content card fields
This commit is contained in:
+2
-1
@@ -9,9 +9,10 @@
|
||||
|
||||
### 🎨 Enhancements
|
||||
|
||||
- [#558](https://github.com/estruyf/vscode-front-matter/issues/558): Moved the tags and categories to a `.frontmatter/database/taxonomyDb.json` file
|
||||
- [#566](https://github.com/estruyf/vscode-front-matter/issues/566): Keep the panel context on the live preview
|
||||
- [#568](https://github.com/estruyf/vscode-front-matter/issues/568): Update the preview URL if the slug changes
|
||||
- [#558](https://github.com/estruyf/vscode-front-matter/issues/558): Moved the tags and categories to a `.frontmatter/database/taxonomyDb.json` file
|
||||
- [#586](https://github.com/estruyf/vscode-front-matter/issues/586): Allow to specify the content card fields
|
||||
|
||||
### ⚡️ Optimizations
|
||||
|
||||
|
||||
@@ -573,6 +573,26 @@
|
||||
"markdownDescription": "Specify the name of the metadata field that will be used to show the tags on the content card. When empty or null, it will hide the tags from the card. [Check in the docs](https://frontmatter.codes/docs/settings/overview#frontMatter.dashboard.content.cardTags)",
|
||||
"scope": "Dashboard"
|
||||
},
|
||||
"frontMatter.dashboard.content.card.fields.state": {
|
||||
"type": "boolean",
|
||||
"default": true,
|
||||
"markdownDescription": "Specify if you want to show the state/draft status on the content card view. [Check in the docs](https://frontmatter.codes/docs/settings/overview#frontMatter.dashboard.content.card.fields.state)"
|
||||
},
|
||||
"frontMatter.dashboard.content.card.fields.date": {
|
||||
"type": "boolean",
|
||||
"default": true,
|
||||
"markdownDescription": "Specify if you want to show the date on the content card view. [Check in the docs](https://frontmatter.codes/docs/settings/overview#frontMatter.dashboard.content.card.fields.date)"
|
||||
},
|
||||
"frontMatter.dashboard.content.card.fields.description": {
|
||||
"type": ["null", "string"],
|
||||
"default": "",
|
||||
"markdownDescription": "Specify the name of the metadata field that will be used to show the description on the content card. [Check in the docs](https://frontmatter.codes/docs/settings/overview#frontMatter.dashboard.content.card.fields.description)"
|
||||
},
|
||||
"frontMatter.dashboard.content.card.fields.title": {
|
||||
"type": ["null", "string"],
|
||||
"default": "",
|
||||
"markdownDescription": "Specify the name of the metadata field that will be used to show the title on the content card. [Check in the docs](https://frontmatter.codes/docs/settings/overview#frontMatter.dashboard.content.card.fields.title)"
|
||||
},
|
||||
"frontMatter.dashboard.mediaSnippet": {
|
||||
"type": "array",
|
||||
"default": [],
|
||||
|
||||
@@ -76,6 +76,13 @@ export const SETTING_DASHBOARD_OPENONSTART = 'dashboard.openOnStart';
|
||||
export const SETTING_DASHBOARD_CONTENT_TAGS = 'dashboard.content.cardTags';
|
||||
export const SETTING_DASHBOARD_CONTENT_PAGINATION = 'dashboard.content.pagination';
|
||||
|
||||
// Content cards
|
||||
export const SETTING_DASHBOARD_CONTENT_CARD_STATE = 'dashboard.content.card.fields.state';
|
||||
export const SETTING_DASHBOARD_CONTENT_CARD_DATE = 'dashboard.content.card.fields.date';
|
||||
export const SETTING_DASHBOARD_CONTENT_CARD_TITLE = 'dashboard.content.card.fields.title';
|
||||
export const SETTING_DASHBOARD_CONTENT_CARD_DESCRIPTION =
|
||||
'dashboard.content.card.fields.description';
|
||||
|
||||
export const SETTING_DATA_FILES = 'data.files';
|
||||
export const SETTING_DATA_FOLDERS = 'data.folders';
|
||||
export const SETTING_DATA_TYPES = 'data.types';
|
||||
|
||||
@@ -11,7 +11,6 @@ import { useEffect, useMemo, useState } from 'react';
|
||||
import useThemeColors from '../../hooks/useThemeColors';
|
||||
import { Status } from './Status';
|
||||
import * as React from 'react';
|
||||
import { messageHandler } from '@estruyf/vscode/dist/client';
|
||||
|
||||
export interface IItemProps extends Page { }
|
||||
|
||||
@@ -28,25 +27,51 @@ export const Item: React.FunctionComponent<IItemProps> = ({
|
||||
const view = useRecoilValue(ViewSelector);
|
||||
const settings = useRecoilValue(SettingsSelector);
|
||||
const draftField = useMemo(() => settings?.draftField, [settings]);
|
||||
const cardFields = useMemo(() => settings?.dashboardState?.contents?.cardFields, [settings?.dashboardState?.contents?.cardFields]);
|
||||
const [imageHtml, setImageHtml] = useState<string | undefined>(undefined);
|
||||
const [footerHtml, setFooterHtml] = useState<string | undefined>(undefined);
|
||||
const { getColors } = useThemeColors();
|
||||
|
||||
const escapedTitle = useMemo(() => {
|
||||
if (title && typeof title !== 'string') {
|
||||
console.log('escapedTitle', title, cardFields?.title, pageData);
|
||||
let value = title;
|
||||
|
||||
if (cardFields?.title) {
|
||||
if (cardFields.title === "description") {
|
||||
value = description;
|
||||
} else if (cardFields?.title !== "title") {
|
||||
value = pageData[cardFields?.title] || title;
|
||||
}
|
||||
} else if (cardFields?.title === null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (value && typeof value !== 'string') {
|
||||
return '<invalid title>';
|
||||
}
|
||||
|
||||
return title;
|
||||
}, [title]);
|
||||
return value;
|
||||
}, [title, description, cardFields?.title, pageData]);
|
||||
|
||||
const escapedDescription = useMemo(() => {
|
||||
if (description && typeof description !== 'string') {
|
||||
let value = description;
|
||||
|
||||
if (cardFields?.description) {
|
||||
if (cardFields.description === "title") {
|
||||
value = title;
|
||||
} else if (cardFields?.description !== "description") {
|
||||
value = pageData[cardFields?.description] || description;
|
||||
}
|
||||
} else if (cardFields?.description === null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (value && typeof value !== 'string') {
|
||||
return '<invalid description>';
|
||||
}
|
||||
|
||||
return description;
|
||||
}, [description]);
|
||||
return value;
|
||||
}, [description, title, cardFields?.description, pageData]);
|
||||
|
||||
const openFile = () => {
|
||||
Messenger.send(DashboardMessage.openFile, fmFilePath);
|
||||
@@ -77,6 +102,10 @@ export const Item: React.FunctionComponent<IItemProps> = ({
|
||||
return [];
|
||||
}, [settings, pageData]);
|
||||
|
||||
const hasDraftOrDate = useMemo(() => {
|
||||
return cardFields && (cardFields.state || cardFields.date);
|
||||
}, [cardFields]);
|
||||
|
||||
useEffect(() => {
|
||||
if (window.fmExternal && window.fmExternal.getCardFooter) {
|
||||
window.fmExternal.getCardFooter(fmFilePath, {
|
||||
@@ -137,7 +166,7 @@ export const Item: React.FunctionComponent<IItemProps> = ({
|
||||
pageData[PREVIEW_IMAGE_FIELD] ? (
|
||||
<img
|
||||
src={`${pageData[PREVIEW_IMAGE_FIELD]}`}
|
||||
alt={escapedTitle}
|
||||
alt={escapedTitle || ""}
|
||||
className="absolute inset-0 h-full w-full object-cover group-hover:brightness-75"
|
||||
loading="lazy"
|
||||
/>
|
||||
@@ -160,21 +189,27 @@ export const Item: React.FunctionComponent<IItemProps> = ({
|
||||
</button>
|
||||
|
||||
<div className="relative p-4 w-full grow">
|
||||
<div className={`flex justify-between items-center`}>
|
||||
{draftField && draftField.name && <Status draft={pageData[draftField.name]} />}
|
||||
<div className={`flex justify-between items-center ${hasDraftOrDate ? `mb-2` : ``}`}>
|
||||
{
|
||||
cardFields?.state && draftField && draftField.name && <Status draft={pageData[draftField.name]} />
|
||||
}
|
||||
|
||||
<DateField className={`mr-4`} value={date} />
|
||||
|
||||
<ContentActions
|
||||
title={title}
|
||||
path={fmFilePath}
|
||||
scripts={settings?.scripts}
|
||||
onOpen={openFile}
|
||||
/>
|
||||
{
|
||||
cardFields?.date && <DateField className={`mr-4`} value={date} />
|
||||
}
|
||||
</div>
|
||||
|
||||
<ContentActions
|
||||
title={title}
|
||||
path={fmFilePath}
|
||||
scripts={settings?.scripts}
|
||||
onOpen={openFile}
|
||||
/>
|
||||
|
||||
<button onClick={openFile} className={`text-left block`}>
|
||||
<h2 className="mt-2 mb-2 font-bold">{escapedTitle}</h2>
|
||||
<h2 className="mb-2 font-bold">
|
||||
{escapedTitle}
|
||||
</h2>
|
||||
</button>
|
||||
|
||||
<button onClick={openFile} className={`text-left block`}>
|
||||
@@ -226,7 +261,7 @@ export const Item: React.FunctionComponent<IItemProps> = ({
|
||||
</button>
|
||||
|
||||
<ContentActions
|
||||
title={escapedTitle}
|
||||
title={escapedTitle || ""}
|
||||
path={fmFilePath}
|
||||
scripts={settings?.scripts}
|
||||
onOpen={openFile}
|
||||
|
||||
@@ -58,6 +58,14 @@ export interface ContentsViewState {
|
||||
tags: string | null | undefined;
|
||||
templatesEnabled: boolean | null | undefined;
|
||||
pagination: boolean | number | null | undefined;
|
||||
cardFields: CardFields;
|
||||
}
|
||||
|
||||
export interface CardFields {
|
||||
state: boolean | undefined;
|
||||
date: boolean | undefined;
|
||||
title: string | null | undefined;
|
||||
description: string | null | undefined;
|
||||
}
|
||||
|
||||
export interface MediaViewState extends ContentsViewState {
|
||||
|
||||
@@ -25,7 +25,11 @@ import {
|
||||
SETTING_TEMPLATES_ENABLED,
|
||||
SETTING_GIT_ENABLED,
|
||||
SETTING_DASHBOARD_CONTENT_PAGINATION,
|
||||
SETTING_SNIPPETS_WRAPPER
|
||||
SETTING_SNIPPETS_WRAPPER,
|
||||
SETTING_DASHBOARD_CONTENT_CARD_DATE,
|
||||
SETTING_DASHBOARD_CONTENT_CARD_TITLE,
|
||||
SETTING_DASHBOARD_CONTENT_CARD_STATE,
|
||||
SETTING_DASHBOARD_CONTENT_CARD_DESCRIPTION
|
||||
} from '../constants';
|
||||
import {
|
||||
DashboardViewType,
|
||||
@@ -99,7 +103,13 @@ export class DashboardSettings {
|
||||
defaultSorting: Settings.get<string>(SETTING_CONTENT_SORTING_DEFAULT),
|
||||
tags: Settings.get<string>(SETTING_DASHBOARD_CONTENT_TAGS),
|
||||
templatesEnabled: Settings.get<boolean>(SETTING_TEMPLATES_ENABLED),
|
||||
pagination: pagination !== undefined ? pagination : true
|
||||
pagination: pagination !== undefined ? pagination : true,
|
||||
cardFields: {
|
||||
state: Settings.get<string>(SETTING_DASHBOARD_CONTENT_CARD_STATE),
|
||||
date: Settings.get<string>(SETTING_DASHBOARD_CONTENT_CARD_DATE),
|
||||
title: Settings.get<string>(SETTING_DASHBOARD_CONTENT_CARD_TITLE),
|
||||
description: Settings.get<string>(SETTING_DASHBOARD_CONTENT_CARD_DESCRIPTION)
|
||||
}
|
||||
},
|
||||
media: {
|
||||
sorting: await ext.getState<SortingOption | undefined>(
|
||||
|
||||
@@ -3,11 +3,16 @@ import { basename } from 'path';
|
||||
import { commands, FileSystemWatcher, RelativePattern, TextDocument, Uri, workspace } from 'vscode';
|
||||
import { Dashboard } from '../../commands/Dashboard';
|
||||
import { Folders } from '../../commands/Folders';
|
||||
import { COMMAND_NAME, ExtensionState } from '../../constants';
|
||||
import {
|
||||
COMMAND_NAME,
|
||||
ExtensionState,
|
||||
SETTING_DASHBOARD_CONTENT_CARD_DESCRIPTION,
|
||||
SETTING_DASHBOARD_CONTENT_CARD_TITLE
|
||||
} from '../../constants';
|
||||
import { DashboardCommand } from '../../dashboardWebView/DashboardCommand';
|
||||
import { DashboardMessage } from '../../dashboardWebView/DashboardMessage';
|
||||
import { Page } from '../../dashboardWebView/models';
|
||||
import { ArticleHelper, Extension, Logger } from '../../helpers';
|
||||
import { ArticleHelper, Extension, Logger, Settings } from '../../helpers';
|
||||
import { BaseListener } from './BaseListener';
|
||||
import { DataListener } from '../panel';
|
||||
import Fuse from 'fuse.js';
|
||||
@@ -219,13 +224,24 @@ export class PagesListener extends BaseListener {
|
||||
* Search the pages
|
||||
*/
|
||||
private static async searchPages(data: { query: string }) {
|
||||
const fieldKeys = [
|
||||
{ name: 'title', weight: 1 },
|
||||
{ name: 'fmBody', weight: 1 },
|
||||
{ name: 'slug', weight: 0.5 },
|
||||
{ name: 'description', weight: 0.5 }
|
||||
];
|
||||
|
||||
const cardTitle = Settings.get(SETTING_DASHBOARD_CONTENT_CARD_TITLE);
|
||||
if (cardTitle) {
|
||||
fieldKeys.push({ name: cardTitle as string, weight: 1 });
|
||||
}
|
||||
const cardDescription = Settings.get(SETTING_DASHBOARD_CONTENT_CARD_DESCRIPTION);
|
||||
if (cardTitle) {
|
||||
fieldKeys.push({ name: cardDescription as string, weight: 0.5 });
|
||||
}
|
||||
|
||||
const fuseOptions: Fuse.IFuseOptions<Page> = {
|
||||
keys: [
|
||||
{ name: 'title', weight: 1 },
|
||||
{ name: 'fmBody', weight: 1 },
|
||||
{ name: 'slug', weight: 0.5 },
|
||||
{ name: 'description', weight: 0.5 }
|
||||
],
|
||||
keys: fieldKeys,
|
||||
includeScore: true,
|
||||
ignoreLocation: true,
|
||||
threshold: 0.1
|
||||
|
||||
Reference in New Issue
Block a user