#108 - Choice field support added

This commit is contained in:
Elio Struyf
2021-09-17 14:04:06 +02:00
parent ed460fde4f
commit 78db3d0b96
7 changed files with 91 additions and 3 deletions
+2 -1
View File
@@ -7,7 +7,8 @@
- [#103](https://github.com/estruyf/vscode-front-matter/issues/103): Added title and description field to the metadata section
- [#104](https://github.com/estruyf/vscode-front-matter/issues/104): Allow to set images in front matter from the metadata panel section
- [#105](https://github.com/estruyf/vscode-front-matter/issues/105): Content Type support with backwards compatibility
- [#107](https://github.com/estruyf/vscode-front-matter/issues/107): Number field support added in content types fields
- [#107](https://github.com/estruyf/vscode-front-matter/issues/107): Number field support added in content type fields
- [#108](https://github.com/estruyf/vscode-front-matter/issues/108): Choice field support added in content type fields
## [3.1.0] - 2021-09-10
+13
View File
@@ -451,6 +451,19 @@ input:checked + .field__toggle__slider:before {
outline: none !important;
}
.metadata_field__choice {
border: 1px solid var(--vscode-inputValidation-infoBorder) !important;
outline: none !important;
width: 100%;
padding: var(--input-padding-vertical) var(--input-padding-horizontal);
color: var(--vscode-input-foreground);
background-color: var(--vscode-input-background);
}
.metadata_field__choice::placeholde {
color: var(--vscode-input-placeholderForeground);
}
.metadata_field__datetime {
display: flex;
justify-content: space-between;
+10
View File
@@ -175,9 +175,19 @@ Front Matter its metadata section supports the following fields:
- `datetime`
- `boolean`
- `image`
- `choice`
- `tags`: mapped to the tags defined in your settings.
- `categories`: mapped to the categories defined in your settings.
### Field properties
A field consists out of the following properties:
- `title`: The title to show in the metadata section (optional);
- `name`: The name of your field, will be used to set in the front matter of your Markdown file;
- `type`: One of the above supported types;
- `choices`: When you picked the `choice` field type, you need to return an array of choices: `["Choice 1", "Choice 2", "Choice 3"]`.
## Creating a template
To make sure that your type of content is already defined when creating a new Markdown file. It will be easier to set the type of content within a template.
+8
View File
@@ -337,6 +337,7 @@
"datetime",
"boolean",
"image",
"choice",
"tags",
"categories"
],
@@ -349,6 +350,13 @@
"title": {
"type": "string",
"description": "Title to show in the UI"
},
"choices": {
"type": "array",
"description": "Define your choices",
"items": {
"type": "string"
}
}
},
"additionalProperties": false,
+2 -1
View File
@@ -26,7 +26,8 @@ export interface ContentType {
export interface Field {
title?: string;
name: string;
type: "string" | "number" | "datetime" | "boolean" | "image" | "tags" | "categories";
type: "string" | "number" | "datetime" | "boolean" | "image" | "choice" | "tags" | "categories";
choices?: string[];
}
export interface DateInfo {
@@ -0,0 +1,42 @@
import { CheckIcon } from '@heroicons/react/outline';
import * as React from 'react';
import { VsLabel } from '../VscodeComponents';
export interface IChoiceFieldProps {
label: string;
selected: string;
choices: string[];
onChange: (value: string) => void;
}
export const ChoiceField: React.FunctionComponent<IChoiceFieldProps> = ({label, selected, choices, onChange}: React.PropsWithChildren<IChoiceFieldProps>) => {
const [ crntSelected, setCrntSelected ] = React.useState<string | null>(selected);
const onValueChange = (txtValue: string) => {
setCrntSelected(txtValue);
onChange(txtValue);
};
const containsSelected = selected && choices.indexOf(selected) !== -1;
return (
<div className={`metadata_field`}>
<VsLabel>
<div className={`metadata_field__label`}>
<CheckIcon style={{ width: "16px", height: "16px" }} /> <span style={{ lineHeight: "16px"}}>{label}</span>
</div>
</VsLabel>
<select
value={crntSelected || ""}
placeholder={`Select from your ${label}`}
className={`metadata_field__choice`}
onChange={(e) => onValueChange(e.currentTarget.value)}>
{ !containsSelected && <option value='' disabled hidden></option> }
{choices.map((choice, index) => (
<option key={index} value={choice} selected={crntSelected === selected}>{choice}</option>
))}
</select>
</div>
);
};
+14 -1
View File
@@ -11,12 +11,13 @@ import { TagPicker } from './TagPicker';
import { parseJSON } from 'date-fns';
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';
export interface IMetadataProps {
settings: PanelSettings | undefined;
metadata: { [prop: string]: string[] | string | null };
@@ -127,6 +128,18 @@ export const Metadata: React.FunctionComponent<IMetadataProps> = ({settings, met
value={metadata[field.name] as string}
onChange={(value => sendUpdate(field.name, value))} />
);
} else if (field.type === 'choice') {
const choices = field.choices || [];
const choiceValue = metadata[field.name];
return (
<ChoiceField
key={field.name}
label={field.title || field.name}
selected={choiceValue as string}
choices={choices}
onChange={(value => sendUpdate(field.name, value))} />
);
} else if (field.type === 'tags') {
return (
<TagPicker