mirror of
https://github.com/estruyf/vscode-front-matter.git
synced 2026-06-23 03:24:59 +02:00
#101 - Date picker added to metadata
This commit is contained in:
@@ -506,4 +506,22 @@ input:checked + .field__toggle__slider:before {
|
||||
|
||||
.sponsor a > span {
|
||||
margin-right: .25rem;
|
||||
}
|
||||
|
||||
/* Timepicker */
|
||||
.react-datepicker button:hover {
|
||||
background-color: none !important;
|
||||
}
|
||||
|
||||
.react-datepicker__triangle {
|
||||
transform: translate3d(15px, 0px, 0px) !important;
|
||||
}
|
||||
|
||||
.react-datepicker-time__input {
|
||||
background: transparent !important;
|
||||
color: #000 !important;
|
||||
}
|
||||
|
||||
.react-datepicker-time__input input {
|
||||
border: 1px solid #aeaeae !important;
|
||||
}
|
||||
Generated
+69
@@ -262,6 +262,12 @@
|
||||
"fastq": "^1.6.0"
|
||||
}
|
||||
},
|
||||
"@popperjs/core": {
|
||||
"version": "2.10.1",
|
||||
"resolved": "https://registry.npmjs.org/@popperjs/core/-/core-2.10.1.tgz",
|
||||
"integrity": "sha512-HnUhk1Sy9IuKrxEMdIRCxpIqPw6BFsbYSEUO9p/hNw5sMld/+3OLMWQP80F8/db9qsv3qUjs7ZR5bS/R+iinXw==",
|
||||
"dev": true
|
||||
},
|
||||
"@tailwindcss/forms": {
|
||||
"version": "0.3.3",
|
||||
"resolved": "https://registry.npmjs.org/@tailwindcss/forms/-/forms-0.3.3.tgz",
|
||||
@@ -375,6 +381,18 @@
|
||||
"csstype": "^3.0.2"
|
||||
}
|
||||
},
|
||||
"@types/react-datepicker": {
|
||||
"version": "4.1.7",
|
||||
"resolved": "https://registry.npmjs.org/@types/react-datepicker/-/react-datepicker-4.1.7.tgz",
|
||||
"integrity": "sha512-8FZt62redGDsO/Dptb8/kdu/JZsAD17lsU3E8OwJqxhtNk4EsdVT0v2ArP8efDGkmtonIKVF2usoPzF6ZeL8zw==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@popperjs/core": "^2.9.2",
|
||||
"@types/react": "*",
|
||||
"date-fns": "^2.0.1",
|
||||
"react-popper": "^2.2.5"
|
||||
}
|
||||
},
|
||||
"@types/react-dom": {
|
||||
"version": "17.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-17.0.0.tgz",
|
||||
@@ -1360,6 +1378,12 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"classnames": {
|
||||
"version": "2.3.1",
|
||||
"resolved": "https://registry.npmjs.org/classnames/-/classnames-2.3.1.tgz",
|
||||
"integrity": "sha512-OlQdbZ7gLfGarSqxesMesDa5uz7KFbID8Kpq/SxIoNGDqY8lSYs0D+hhtBXhcdB3rcbXArFr7vlHheLk1voeNA==",
|
||||
"dev": true
|
||||
},
|
||||
"clean-css": {
|
||||
"version": "4.2.3",
|
||||
"resolved": "https://registry.npmjs.org/clean-css/-/clean-css-4.2.3.tgz",
|
||||
@@ -4808,6 +4832,20 @@
|
||||
"object-assign": "^4.1.1"
|
||||
}
|
||||
},
|
||||
"react-datepicker": {
|
||||
"version": "4.2.1",
|
||||
"resolved": "https://registry.npmjs.org/react-datepicker/-/react-datepicker-4.2.1.tgz",
|
||||
"integrity": "sha512-0gcvHMnX8rS1fV90PjjsB7MQdsWNU77JeVHf6bbwK9HnFxgwjVflTx40ebKmHV+leqe+f+FgUP9Nvqbe5RGyfA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@popperjs/core": "^2.9.2",
|
||||
"classnames": "^2.2.6",
|
||||
"date-fns": "^2.0.1",
|
||||
"prop-types": "^15.7.2",
|
||||
"react-onclickoutside": "^6.10.0",
|
||||
"react-popper": "^2.2.5"
|
||||
}
|
||||
},
|
||||
"react-dom": {
|
||||
"version": "17.0.1",
|
||||
"resolved": "https://registry.npmjs.org/react-dom/-/react-dom-17.0.1.tgz",
|
||||
@@ -4830,12 +4868,34 @@
|
||||
"prop-types": "^15.7.2"
|
||||
}
|
||||
},
|
||||
"react-fast-compare": {
|
||||
"version": "3.2.0",
|
||||
"resolved": "https://registry.npmjs.org/react-fast-compare/-/react-fast-compare-3.2.0.tgz",
|
||||
"integrity": "sha512-rtGImPZ0YyLrscKI9xTpV8psd6I8VAtjKCzQDlzyDvqJA8XOW78TXYQwNRNd8g8JZnDu8q9Fu/1v4HPAVwVdHA==",
|
||||
"dev": true
|
||||
},
|
||||
"react-is": {
|
||||
"version": "16.13.1",
|
||||
"resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz",
|
||||
"integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==",
|
||||
"dev": true
|
||||
},
|
||||
"react-onclickoutside": {
|
||||
"version": "6.12.0",
|
||||
"resolved": "https://registry.npmjs.org/react-onclickoutside/-/react-onclickoutside-6.12.0.tgz",
|
||||
"integrity": "sha512-oPlOTYcISLHfpMog2lUZMFSbqOs4LFcA4+vo7fpfevB5v9Z0D5VBDBkfeO5lv+hpEcGoaGk67braLT+QT+eICA==",
|
||||
"dev": true
|
||||
},
|
||||
"react-popper": {
|
||||
"version": "2.2.5",
|
||||
"resolved": "https://registry.npmjs.org/react-popper/-/react-popper-2.2.5.tgz",
|
||||
"integrity": "sha512-kxGkS80eQGtLl18+uig1UIf9MKixFSyPxglsgLBxlYnyDf65BiY9B3nZSc6C9XUNDgStROB0fMQlTEz1KxGddw==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"react-fast-compare": "^3.0.1",
|
||||
"warning": "^4.0.2"
|
||||
}
|
||||
},
|
||||
"readable-stream": {
|
||||
"version": "2.3.7",
|
||||
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz",
|
||||
@@ -6161,6 +6221,15 @@
|
||||
"integrity": "sha512-2ham8XPWTONajOR0ohOKOHXkm3+gaBmGut3SRuu75xLd/RRaY6vqgh8NBYYk7+RW3u5AtzPQZG8F10LHkl0lAQ==",
|
||||
"dev": true
|
||||
},
|
||||
"warning": {
|
||||
"version": "4.0.3",
|
||||
"resolved": "https://registry.npmjs.org/warning/-/warning-4.0.3.tgz",
|
||||
"integrity": "sha512-rpJyN222KWIvHJ/F53XSZv0Zl/accqHR8et1kpaMTD/fLCRxtV8iX8czMzY7sVZupTI3zcUTg8eycS2kNF9l6w==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"loose-envify": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"watchpack": {
|
||||
"version": "1.7.5",
|
||||
"resolved": "https://registry.npmjs.org/watchpack/-/watchpack-1.7.5.tgz",
|
||||
|
||||
@@ -407,6 +407,7 @@
|
||||
"@types/mocha": "^5.2.6",
|
||||
"@types/node": "10.17.48",
|
||||
"@types/react": "17.0.0",
|
||||
"@types/react-datepicker": "^4.1.7",
|
||||
"@types/react-dom": "17.0.0",
|
||||
"@types/vscode": "1.51.0",
|
||||
"@vscode/codicons": "0.0.20",
|
||||
@@ -424,6 +425,7 @@
|
||||
"postcss": "^8.3.6",
|
||||
"postcss-loader": "4.3.0",
|
||||
"react": "17.0.1",
|
||||
"react-datepicker": "4.2.1",
|
||||
"react-dom": "17.0.1",
|
||||
"react-dropzone": "^11.3.4",
|
||||
"recoil": "^0.4.1",
|
||||
|
||||
+24
-20
@@ -7,6 +7,7 @@ import { ArticleHelper, SettingsHelper, SlugHelper } from '../helpers';
|
||||
import matter = require('gray-matter');
|
||||
import { Notifications } from '../helpers/Notifications';
|
||||
import { extname, basename } from 'path';
|
||||
import { DefaultFields } from '../constants';
|
||||
|
||||
|
||||
export class Article {
|
||||
@@ -102,12 +103,11 @@ export class Article {
|
||||
*/
|
||||
public static updateDate(article: matter.GrayMatterFile<string>, forceCreate: boolean = false) {
|
||||
const config = SettingsHelper.getConfig();
|
||||
const dateFormat = config.get(SETTING_DATE_FORMAT) as string;
|
||||
const dateField = config.get(SETTING_DATE_FIELD) as string || "date";
|
||||
const modField = config.get(SETTING_MODIFIED_FIELD) as string || "date";
|
||||
const dateField = config.get(SETTING_DATE_FIELD) as string || DefaultFields.PublishingDate;
|
||||
const modField = config.get(SETTING_MODIFIED_FIELD) as string || DefaultFields.PublishingDate;
|
||||
|
||||
article = this.articleDate(article, dateFormat, dateField, forceCreate);
|
||||
article = this.articleDate(article, dateFormat, modField, false);
|
||||
article = this.articleDate(article, dateField, forceCreate);
|
||||
article = this.articleDate(article, modField, false);
|
||||
|
||||
return article;
|
||||
}
|
||||
@@ -128,19 +128,13 @@ export class Article {
|
||||
}
|
||||
|
||||
const cloneArticle = Object.assign({}, article);
|
||||
const dateFormat = config.get(SETTING_DATE_FORMAT) as string;
|
||||
const dateField = config.get(SETTING_MODIFIED_FIELD) as string || "lastmod";
|
||||
const dateField = config.get(SETTING_MODIFIED_FIELD) as string || DefaultFields.LastModified;
|
||||
try {
|
||||
if (dateFormat && typeof dateFormat === "string") {
|
||||
cloneArticle.data[dateField] = format(new Date(), dateFormat);
|
||||
} else {
|
||||
cloneArticle.data[dateField] = new Date().toISOString();
|
||||
}
|
||||
cloneArticle.data[dateField] = Article.formatDate(new Date());
|
||||
|
||||
ArticleHelper.update(editor, cloneArticle);
|
||||
} catch (e) {
|
||||
} catch (e: any) {
|
||||
Notifications.error(`Something failed while parsing the date format. Check your "${CONFIG_KEY}${SETTING_DATE_FORMAT}" setting.`);
|
||||
console.log(e.message);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -250,6 +244,20 @@ export class Article {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Format the date to the defined format
|
||||
*/
|
||||
public static formatDate(dateValue: Date) {
|
||||
const config = SettingsHelper.getConfig();
|
||||
const dateFormat = config.get(SETTING_DATE_FORMAT) as string;
|
||||
|
||||
if (dateFormat && typeof dateFormat === "string") {
|
||||
return format(dateValue, dateFormat);
|
||||
} else {
|
||||
return dateValue.toISOString();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the current article
|
||||
*/
|
||||
@@ -274,13 +282,9 @@ export class Article {
|
||||
* @param field
|
||||
* @param forceCreate
|
||||
*/
|
||||
private static articleDate(article: matter.GrayMatterFile<string>, dateFormat: string, field: string, forceCreate: boolean) {
|
||||
private static articleDate(article: matter.GrayMatterFile<string>, field: string, forceCreate: boolean) {
|
||||
if (typeof article.data[field] !== "undefined" || forceCreate) {
|
||||
if (dateFormat && typeof dateFormat === "string") {
|
||||
article.data[field] = format(new Date(), dateFormat);
|
||||
} else {
|
||||
article.data[field] = new Date().toISOString();
|
||||
}
|
||||
article.data[field] = Article.formatDate(new Date());
|
||||
}
|
||||
return article;
|
||||
}
|
||||
|
||||
@@ -20,6 +20,7 @@ import { ViewType } from '../pagesView/state';
|
||||
import { WebviewHelper } from '@estruyf/vscode';
|
||||
import { MediaInfo, MediaPaths } from './../models/MediaPaths';
|
||||
import { decodeBase64Image } from '../helpers/decodeBase64Image';
|
||||
import { DefaultFields } from '../constants';
|
||||
|
||||
|
||||
export class Dashboard {
|
||||
@@ -280,8 +281,8 @@ export class Dashboard {
|
||||
const config = SettingsHelper.getConfig();
|
||||
const wsFolder = Folders.getWorkspaceFolder();
|
||||
|
||||
const descriptionField = config.get(SETTING_SEO_DESCRIPTION_FIELD) as string || "description";
|
||||
const dateField = config.get(SETTING_DATE_FIELD) as string || "date";
|
||||
const descriptionField = config.get(SETTING_SEO_DESCRIPTION_FIELD) as string || DefaultFields.Description;
|
||||
const dateField = config.get(SETTING_DATE_FIELD) as string || DefaultFields.PublishingDate;
|
||||
const staticFolder = config.get<string>(SETTINGS_CONTENT_STATIC_FOLDERS);
|
||||
|
||||
const folderInfo = await Folders.getInfo();
|
||||
|
||||
@@ -2,6 +2,7 @@ import { SETTING_SEO_DESCRIPTION_FIELD, SETTING_SEO_DESCRIPTION_LENGTH, SETTING_
|
||||
import * as vscode from 'vscode';
|
||||
import { ArticleHelper, SeoHelper, SettingsHelper } from '../helpers';
|
||||
import { ExplorerView } from '../webview/ExplorerView';
|
||||
import { DefaultFields } from '../constants';
|
||||
|
||||
export class StatusListener {
|
||||
|
||||
@@ -39,7 +40,7 @@ export class StatusListener {
|
||||
const config = SettingsHelper.getConfig();
|
||||
const titleLength = config.get(SETTING_SEO_TITLE_LENGTH) as number || -1;
|
||||
const descLength = config.get(SETTING_SEO_DESCRIPTION_LENGTH) as number || -1;
|
||||
const fieldName = config.get(SETTING_SEO_DESCRIPTION_FIELD) as string || "description";
|
||||
const fieldName = config.get(SETTING_SEO_DESCRIPTION_FIELD) as string || DefaultFields.Description;
|
||||
|
||||
if (article.data.title && titleLength > -1) {
|
||||
SeoHelper.checkLength(editor, collection, article, "title", titleLength);
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
|
||||
export const DefaultFields = {
|
||||
PublishingDate: `date`,
|
||||
LastModified: `lastmod`,
|
||||
Description: `description`
|
||||
};
|
||||
@@ -1 +1,7 @@
|
||||
export * from './DefaultFields';
|
||||
export * from './Extension';
|
||||
export * from './Links';
|
||||
export * from './charMap';
|
||||
export * from './context';
|
||||
export * from './settings';
|
||||
export * from './stopwords-en';
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import * as vscode from 'vscode';
|
||||
import * as matter from "gray-matter";
|
||||
import * as fs from "fs";
|
||||
import { CONFIG_KEY, SETTING_DATE_FIELD, SETTING_DATE_FORMAT, SETTING_INDENT_ARRAY, SETTING_REMOVE_QUOTES } from '../constants';
|
||||
import { CONFIG_KEY, DefaultFields, SETTING_DATE_FIELD, SETTING_DATE_FORMAT, SETTING_INDENT_ARRAY, SETTING_REMOVE_QUOTES } from '../constants';
|
||||
import { DumpOptions } from 'js-yaml';
|
||||
import { TomlEngine, getFmLanguage, getFormatOpts } from './TomlEngine';
|
||||
import { SettingsHelper } from '.';
|
||||
@@ -117,7 +117,7 @@ export class ArticleHelper {
|
||||
|
||||
const config = SettingsHelper.getConfig();
|
||||
const dateFormat = config.get(SETTING_DATE_FORMAT) as string;
|
||||
const dateField = config.get(SETTING_DATE_FIELD) as string || "date";
|
||||
const dateField = config.get(SETTING_DATE_FIELD) as string || DefaultFields.PublishingDate;
|
||||
|
||||
if (typeof article.data[dateField] !== "undefined") {
|
||||
if (dateFormat && typeof dateFormat === "string") {
|
||||
|
||||
@@ -4,6 +4,7 @@ export interface PanelSettings {
|
||||
seo: SEO;
|
||||
slug: Slug;
|
||||
tags: string[];
|
||||
date: DateInfo;
|
||||
categories: string[];
|
||||
freeform: boolean;
|
||||
scripts: CustomScript[];
|
||||
@@ -14,6 +15,12 @@ export interface PanelSettings {
|
||||
preview: PreviewSettings;
|
||||
}
|
||||
|
||||
export interface DateInfo {
|
||||
format: string;
|
||||
pubDate: string;
|
||||
modDate: string;
|
||||
}
|
||||
|
||||
export interface SEO {
|
||||
title: number;
|
||||
description: number;
|
||||
|
||||
@@ -0,0 +1,56 @@
|
||||
import * as React from 'react';
|
||||
import { VsLabel } from '../VscodeComponents';
|
||||
import { ClockIcon } from '@heroicons/react/outline';
|
||||
import DatePicker from 'react-datepicker';
|
||||
import { forwardRef } from 'react';
|
||||
|
||||
export interface IDateTimeProps {
|
||||
label: string;
|
||||
date: Date | null;
|
||||
format?: string;
|
||||
onChange: (date: Date) => void;
|
||||
}
|
||||
|
||||
type InputProps = JSX.IntrinsicElements["input"];
|
||||
|
||||
const CustomInput = forwardRef<HTMLInputElement, InputProps>(({ value, onClick }, ref) => {
|
||||
return (
|
||||
<button className="example-custom-input" onClick={onClick as any} ref={ref as any}>
|
||||
{value || "Pick your date"}
|
||||
</button>
|
||||
)
|
||||
});
|
||||
|
||||
export const DateTime: React.FunctionComponent<IDateTimeProps> = ({label, date, format, onChange}: React.PropsWithChildren<IDateTimeProps>) => {
|
||||
const [ dateValue, setDateValue ] = React.useState<Date | null>(date);
|
||||
|
||||
const onDateChange = (date: Date) => {
|
||||
setDateValue(date);
|
||||
onChange(date);
|
||||
};
|
||||
|
||||
React.useEffect(() => {
|
||||
if (dateValue?.toISOString() !== date?.toISOString()) {
|
||||
setDateValue(date);
|
||||
}
|
||||
}, [ date ]);
|
||||
|
||||
return (
|
||||
<div className={`metadata_field`}>
|
||||
<VsLabel>
|
||||
<div className={`metadata_field__label`}>
|
||||
<ClockIcon style={{ width: "16px", height: "16px" }} /> <span style={{ lineHeight: "16px"}}>{label}</span>
|
||||
</div>
|
||||
</VsLabel>
|
||||
|
||||
<DatePicker
|
||||
selected={dateValue as Date}
|
||||
onChange={onDateChange}
|
||||
timeInputLabel="Time:"
|
||||
dateFormat={format || "MM/dd/yyyy HH:mm"}
|
||||
customInput={(<CustomInput />)}
|
||||
showTimeInput
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
@@ -10,40 +10,84 @@ import { RocketIcon } from './Icons/RocketIcon';
|
||||
import { SymbolKeywordIcon } from './Icons/SymbolKeywordIcon';
|
||||
import { TagIcon } from './Icons/TagIcon';
|
||||
import { TagPicker } from './TagPicker';
|
||||
import { VsCheckbox, VsLabel } from './VscodeComponents';
|
||||
import { VsLabel } from './VscodeComponents';
|
||||
import { useState } from 'react';
|
||||
|
||||
import "react-datepicker/dist/react-datepicker.css";
|
||||
import { parseJSON } from 'date-fns';
|
||||
import { DateTime } from './Fields/DateTime';
|
||||
|
||||
export interface IMetadataProps {
|
||||
settings: PanelSettings | undefined;
|
||||
metadata: { [prop: string]: string[] | null };
|
||||
metadata: { [prop: string]: string[] | string | null };
|
||||
focusElm: TagType | null;
|
||||
unsetFocus: () => void;
|
||||
}
|
||||
|
||||
export const Metadata: React.FunctionComponent<IMetadataProps> = ({settings, metadata, focusElm, unsetFocus}: React.PropsWithChildren<IMetadataProps>) => {
|
||||
|
||||
const sendUpdate = (field: string, value: any) => {
|
||||
const sendUpdate = (field: string | undefined, value: any) => {
|
||||
if (!field) {
|
||||
return;
|
||||
}
|
||||
|
||||
MessageHelper.sendMessage(CommandToCode.updateMetadata, {
|
||||
field,
|
||||
value
|
||||
});
|
||||
};
|
||||
|
||||
const getDate = (date: string | Date) => {
|
||||
if (typeof date === 'string') {
|
||||
return parseJSON(date);
|
||||
}
|
||||
return date;
|
||||
}
|
||||
|
||||
let publishing: Date | null = null;
|
||||
let modifying: Date | null = null;
|
||||
|
||||
if (settings?.date) {
|
||||
const { modDate, pubDate } = settings.date;
|
||||
publishing = metadata[pubDate] ? getDate(metadata[pubDate] as string) : null;
|
||||
modifying = metadata[modDate] ? getDate(metadata[modDate] as string) : null;
|
||||
}
|
||||
|
||||
return (
|
||||
<Collapsible id={`tags`} title="Metadata" className={`inherit z-20`}>
|
||||
|
||||
<DateTime
|
||||
label={`Article date`}
|
||||
date={publishing}
|
||||
format={settings?.date?.format}
|
||||
onChange={(date => sendUpdate(settings?.date?.pubDate, date))} />
|
||||
|
||||
{
|
||||
modifying && (
|
||||
<DateTime
|
||||
label={`Modified date`}
|
||||
date={modifying}
|
||||
format={settings?.date?.format}
|
||||
onChange={(date => sendUpdate(settings?.date?.modDate, date))} />
|
||||
)
|
||||
}
|
||||
|
||||
<div className={`metadata_field`}>
|
||||
<VsLabel>
|
||||
<div className={`metadata_field__label`}>
|
||||
<RocketIcon /> <span style={{ lineHeight: "16px"}}>Published</span>
|
||||
</div>
|
||||
</VsLabel>
|
||||
<Toggle checked={!metadata.draft as any} onChanged={(checked) => sendUpdate("draft", !checked)} />
|
||||
|
||||
<Toggle
|
||||
checked={!metadata.draft as any}
|
||||
onChanged={(checked) => sendUpdate("draft", !checked)} />
|
||||
</div>
|
||||
|
||||
{
|
||||
<TagPicker type={TagType.keywords}
|
||||
icon={<SymbolKeywordIcon />}
|
||||
crntSelected={metadata.keywords || []}
|
||||
crntSelected={metadata.keywords as string[] || []}
|
||||
options={[]}
|
||||
freeform={true}
|
||||
focussed={focusElm === TagType.keywords}
|
||||
@@ -54,7 +98,7 @@ export const Metadata: React.FunctionComponent<IMetadataProps> = ({settings, met
|
||||
(settings && settings.tags && settings.tags.length > 0) && (
|
||||
<TagPicker type={TagType.tags}
|
||||
icon={<TagIcon />}
|
||||
crntSelected={metadata.tags || []}
|
||||
crntSelected={metadata.tags as string[] || []}
|
||||
options={settings.tags}
|
||||
freeform={settings.freeform}
|
||||
focussed={focusElm === TagType.tags}
|
||||
@@ -65,7 +109,7 @@ export const Metadata: React.FunctionComponent<IMetadataProps> = ({settings, met
|
||||
(settings && settings.categories && settings.categories.length > 0) && (
|
||||
<TagPicker type={TagType.categories}
|
||||
icon={<ListUnorderedIcon />}
|
||||
crntSelected={metadata.categories || []}
|
||||
crntSelected={metadata.categories as string[] || []}
|
||||
options={settings.categories}
|
||||
freeform={settings.freeform}
|
||||
focussed={focusElm === TagType.categories}
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import { Template } from './../commands/Template';
|
||||
import { SETTINGS_CONTENT_FRONTMATTER_HIGHLIGHT, SETTING_AUTO_UPDATE_DATE, SETTING_CUSTOM_SCRIPTS, SETTING_SEO_CONTENT_MIN_LENGTH, SETTING_SEO_DESCRIPTION_FIELD, SETTING_SLUG_UPDATE_FILE_NAME, SETTING_PREVIEW_HOST } from './../constants/settings';
|
||||
import { SETTINGS_CONTENT_FRONTMATTER_HIGHLIGHT, SETTING_AUTO_UPDATE_DATE, SETTING_CUSTOM_SCRIPTS, SETTING_SEO_CONTENT_MIN_LENGTH, SETTING_SEO_DESCRIPTION_FIELD, SETTING_SLUG_UPDATE_FILE_NAME, SETTING_PREVIEW_HOST, SETTING_DATE_FORMAT, SETTING_DATE_FIELD, SETTING_MODIFIED_FIELD } from './../constants/settings';
|
||||
import * as os from 'os';
|
||||
import { PanelSettings, CustomScript } from './../models/PanelSettings';
|
||||
import { CancellationToken, Disposable, Uri, Webview, WebviewView, WebviewViewProvider, WebviewViewResolveContext, window, workspace, commands, env as vscodeEnv } from "vscode";
|
||||
import { SETTING_PANEL_FREEFORM, SETTING_SEO_DESCRIPTION_LENGTH, SETTING_SEO_TITLE_LENGTH, SETTING_SLUG_PREFIX, SETTING_SLUG_SUFFIX, SETTING_TAXONOMY_CATEGORIES, SETTING_TAXONOMY_TAGS } from "../constants";
|
||||
import { DefaultFields, SETTING_PANEL_FREEFORM, SETTING_SEO_DESCRIPTION_LENGTH, SETTING_SEO_TITLE_LENGTH, SETTING_SLUG_PREFIX, SETTING_SLUG_SUFFIX, SETTING_TAXONOMY_CATEGORIES, SETTING_TAXONOMY_TAGS } from "../constants";
|
||||
import { ArticleHelper, SettingsHelper } from "../helpers";
|
||||
import { Command } from "../viewpanel/Command";
|
||||
import { CommandToCode } from '../viewpanel/CommandToCode';
|
||||
@@ -242,6 +242,10 @@ export class ExplorerView implements WebviewViewProvider, Disposable {
|
||||
* Update the metadata of the article
|
||||
*/
|
||||
private updateMetadata({field, value}: { field: string, value: string }) {
|
||||
const config = SettingsHelper.getConfig();
|
||||
const pubDate = config.get(SETTING_DATE_FIELD) as string || DefaultFields.PublishingDate;
|
||||
const modDate = config.get(SETTING_MODIFIED_FIELD) as string || DefaultFields.LastModified;
|
||||
|
||||
if (!field) {
|
||||
return;
|
||||
}
|
||||
@@ -256,8 +260,12 @@ export class ExplorerView implements WebviewViewProvider, Disposable {
|
||||
return;
|
||||
}
|
||||
|
||||
article.data[field] = value;
|
||||
ArticleHelper.update(editor, article);
|
||||
if ((field === pubDate || field === modDate) && value) {
|
||||
article.data[field] = Article.formatDate(new Date(value));
|
||||
} else {
|
||||
article.data[field] = value;
|
||||
}
|
||||
ArticleHelper.update(editor, article);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -315,13 +323,18 @@ export class ExplorerView implements WebviewViewProvider, Disposable {
|
||||
title: config.get(SETTING_SEO_TITLE_LENGTH) as number || -1,
|
||||
description: config.get(SETTING_SEO_DESCRIPTION_LENGTH) as number || -1,
|
||||
content: config.get(SETTING_SEO_CONTENT_MIN_LENGTH) as number || -1,
|
||||
descriptionField: config.get(SETTING_SEO_DESCRIPTION_FIELD) as string || "description"
|
||||
descriptionField: config.get(SETTING_SEO_DESCRIPTION_FIELD) as string || DefaultFields.Description
|
||||
},
|
||||
slug: {
|
||||
prefix: config.get(SETTING_SLUG_PREFIX) || "",
|
||||
suffix: config.get(SETTING_SLUG_SUFFIX) || "",
|
||||
updateFileName: !!config.get<boolean>(SETTING_SLUG_UPDATE_FILE_NAME),
|
||||
},
|
||||
date: {
|
||||
format: config.get(SETTING_DATE_FORMAT),
|
||||
pubDate: config.get(SETTING_DATE_FIELD) as string || DefaultFields.PublishingDate,
|
||||
modDate: config.get(SETTING_MODIFIED_FIELD) as string || DefaultFields.LastModified
|
||||
},
|
||||
tags: config.get(SETTING_TAXONOMY_TAGS) || [],
|
||||
categories: config.get(SETTING_TAXONOMY_CATEGORIES) || [],
|
||||
freeform: config.get(SETTING_PANEL_FREEFORM),
|
||||
|
||||
@@ -56,6 +56,10 @@ const config = [
|
||||
use: [{
|
||||
loader: 'ts-loader'
|
||||
}]
|
||||
},
|
||||
{
|
||||
test: /\.css$/,
|
||||
use: ['style-loader', 'css-loader']
|
||||
}
|
||||
]
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user