From 5e539a3d144cef85aa6f472b53e61fe72cddb429 Mon Sep 17 00:00:00 2001 From: Elio Struyf Date: Tue, 24 Aug 2021 10:30:23 +0200 Subject: [PATCH] #64 - Toggle implementation --- CHANGELOG.md | 1 + assets/media/styles.css | 69 +++++++++++++++++++ src/viewpanel/components/Fields/Toggle.tsx | 28 ++++++++ src/viewpanel/components/Icons/RocketIcon.tsx | 9 +++ src/viewpanel/components/Metadata.tsx | 15 +++- src/viewpanel/components/TagPicker.tsx | 9 ++- src/webview/ExplorerView.ts | 25 +++++++ 7 files changed, 153 insertions(+), 3 deletions(-) create mode 100644 src/viewpanel/components/Fields/Toggle.tsx create mode 100644 src/viewpanel/components/Icons/RocketIcon.tsx diff --git a/CHANGELOG.md b/CHANGELOG.md index 0e66424a..353476e3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,7 @@ ## [2.6.0] - [#61](https://github.com/estruyf/vscode-front-matter/issues/61): List of recently modified files +- [#64](https://github.com/estruyf/vscode-front-matter/issues/64): Publish toggle for easier publishing an article ## [2.5.1] - 2020-08-23 diff --git a/assets/media/styles.css b/assets/media/styles.css index 3999bf84..10f0ac03 100644 --- a/assets/media/styles.css +++ b/assets/media/styles.css @@ -359,6 +359,75 @@ color: #E6AF2E; } +/* Fields */ +.field__toggle { + position: relative; + display: inline-block; + width: 50px; + height: 24px; +} + +.field__toggle input { + opacity: 0; + width: 0; + height: 0; +} + +.field__toggle__slider { + position: absolute; + cursor: pointer; + top: 0; + left: 0; + right: 0; + bottom: 0; + background-color: var(--vscode-button-secondaryBackground); + -webkit-transition: .4s; + transition: .4s; + border-radius: 34px; +} + +.field__toggle__slider:before { + position: absolute; + content: ""; + height: 16px; + width: 16px; + left: 4px; + bottom: 4px; + background-color: white; + -webkit-transition: .4s; + transition: .4s; + border-radius: 50%; +} + +input:checked + .field__toggle__slider { + background-color: var(--vscode-button-background); +} + +input:focus + .field__toggle__slider { + box-shadow: 0 0 1px var(--vscode-button-background); +} + +input:checked + .field__toggle__slider:before { + -webkit-transform: translateX(26px); + -ms-transform: translateX(26px); + transform: translateX(26px); +} + +/* Metadata */ +.metadata_field { + margin-bottom: 1rem; +} + +.metadata_field__label { + display: flex; + align-items: center; + margin-bottom: .5rem; +} + +.metadata_field__label svg { + margin-right: .5rem; +} + /* File list */ .file_list vscode-label { border-bottom: 1px solid var(--vscode-foreground); diff --git a/src/viewpanel/components/Fields/Toggle.tsx b/src/viewpanel/components/Fields/Toggle.tsx new file mode 100644 index 00000000..6b70a3ed --- /dev/null +++ b/src/viewpanel/components/Fields/Toggle.tsx @@ -0,0 +1,28 @@ +import * as React from 'react'; + +export interface IToggleProps { + checked: boolean; + onChanged: (checked: boolean) => void; +} + +export const Toggle: React.FunctionComponent = ({checked, onChanged}: React.PropsWithChildren) => { + const [ isChecked, setIsChecked ] = React.useState(checked); + + const onChange = (event: React.ChangeEvent) => { + setIsChecked(!isChecked); + onChanged(!isChecked); + }; + + React.useEffect(() => { + if (isChecked !== checked) { + setIsChecked(checked); + } + }, [ checked ]); + + return ( + + ); +}; \ No newline at end of file diff --git a/src/viewpanel/components/Icons/RocketIcon.tsx b/src/viewpanel/components/Icons/RocketIcon.tsx new file mode 100644 index 00000000..b5a3dffe --- /dev/null +++ b/src/viewpanel/components/Icons/RocketIcon.tsx @@ -0,0 +1,9 @@ +import * as React from 'react'; + +export interface IRocketIconProps {} + +export const RocketIcon: React.FunctionComponent = (props: React.PropsWithChildren) => { + return ( + + ); +}; \ No newline at end of file diff --git a/src/viewpanel/components/Metadata.tsx b/src/viewpanel/components/Metadata.tsx index 4c3d9879..23225f61 100644 --- a/src/viewpanel/components/Metadata.tsx +++ b/src/viewpanel/components/Metadata.tsx @@ -4,10 +4,13 @@ import { CommandToCode } from '../CommandToCode'; import { MessageHelper } from '../helper/MessageHelper'; import { TagType } from '../TagType'; import { Collapsible } from './Collapsible'; +import { Toggle } from './Fields/Toggle'; import { ListUnorderedIcon } from './Icons/ListUnorderedIcon'; +import { RocketIcon } from './Icons/RocketIcon'; import { SymbolKeywordIcon } from './Icons/SymbolKeywordIcon'; import { TagIcon } from './Icons/TagIcon'; import { TagPicker } from './TagPicker'; +import { VsCheckbox, VsLabel } from './VscodeComponents'; export interface IMetadataProps { settings: PanelSettings | undefined; @@ -18,7 +21,7 @@ export interface IMetadataProps { export const Metadata: React.FunctionComponent = ({settings, metadata, focusElm, unsetFocus}: React.PropsWithChildren) => { - const sendUpdate = (field: string, value: string) => { + const sendUpdate = (field: string, value: any) => { MessageHelper.sendMessage(CommandToCode.updateMetadata, { field, value @@ -27,6 +30,16 @@ export const Metadata: React.FunctionComponent = ({settings, met return ( + +
+ +
+ Published +
+
+ sendUpdate("draft", !checked)} /> +
+ { } diff --git a/src/viewpanel/components/TagPicker.tsx b/src/viewpanel/components/TagPicker.tsx index 64b2a872..4de2e939 100644 --- a/src/viewpanel/components/TagPicker.tsx +++ b/src/viewpanel/components/TagPicker.tsx @@ -6,6 +6,7 @@ import { TagType } from '../TagType'; import { MessageHelper } from '../helper/MessageHelper'; import Downshift from 'downshift'; import { AddIcon } from './Icons/AddIcon'; +import { VsLabel } from './VscodeComponents'; export interface ITagPickerProps { type: string; @@ -126,8 +127,12 @@ export const TagPicker: React.FunctionComponent = (props: React }, [crntSelected]); return ( -
-

{icon} {type}

+
+ +
+ {icon} {type} +
+
onSelect(selected || "")} diff --git a/src/webview/ExplorerView.ts b/src/webview/ExplorerView.ts index f29b0919..7864207c 100644 --- a/src/webview/ExplorerView.ts +++ b/src/webview/ExplorerView.ts @@ -172,6 +172,9 @@ export class ExplorerView implements WebviewViewProvider, Disposable { case CommandToCode.openInEditor: this.openFileInEditor(msg.data); break; + case CommandToCode.updateMetadata: + this.updateMetadata(msg.data); + break; } }); @@ -228,6 +231,28 @@ export class ExplorerView implements WebviewViewProvider, Disposable { this.postWebviewMessage({ command: Command.closeSections }); } + /** + * Update the metadata of the article + */ + private updateMetadata({field, value}: { field: string, value: string }) { + if (!field) { + return; + } + + const editor = window.activeTextEditor; + if (!editor) { + return; + } + + const article = ArticleHelper.getFrontMatter(editor); + if (!article) { + return; + } + + article.data[field] = value; + ArticleHelper.update(editor, article); + } + /** * Open the file via its path */