mirror of
https://github.com/estruyf/vscode-front-matter.git
synced 2026-03-28 17:42:40 +01:00
#64 - Toggle implementation
This commit is contained in:
@@ -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
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
28
src/viewpanel/components/Fields/Toggle.tsx
Normal file
28
src/viewpanel/components/Fields/Toggle.tsx
Normal file
@@ -0,0 +1,28 @@
|
||||
import * as React from 'react';
|
||||
|
||||
export interface IToggleProps {
|
||||
checked: boolean;
|
||||
onChanged: (checked: boolean) => void;
|
||||
}
|
||||
|
||||
export const Toggle: React.FunctionComponent<IToggleProps> = ({checked, onChanged}: React.PropsWithChildren<IToggleProps>) => {
|
||||
const [ isChecked, setIsChecked ] = React.useState(checked);
|
||||
|
||||
const onChange = (event: React.ChangeEvent<HTMLInputElement>) => {
|
||||
setIsChecked(!isChecked);
|
||||
onChanged(!isChecked);
|
||||
};
|
||||
|
||||
React.useEffect(() => {
|
||||
if (isChecked !== checked) {
|
||||
setIsChecked(checked);
|
||||
}
|
||||
}, [ checked ]);
|
||||
|
||||
return (
|
||||
<label className="field__toggle">
|
||||
<input type="checkbox" checked={isChecked} onChange={onChange} />
|
||||
<span className="field__toggle__slider"></span>
|
||||
</label>
|
||||
);
|
||||
};
|
||||
9
src/viewpanel/components/Icons/RocketIcon.tsx
Normal file
9
src/viewpanel/components/Icons/RocketIcon.tsx
Normal file
@@ -0,0 +1,9 @@
|
||||
import * as React from 'react';
|
||||
|
||||
export interface IRocketIconProps {}
|
||||
|
||||
export const RocketIcon: React.FunctionComponent<IRocketIconProps> = (props: React.PropsWithChildren<IRocketIconProps>) => {
|
||||
return (
|
||||
<svg width="16" height="16" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg" fill="currentColor"><path fillRule="evenodd" clipRule="evenodd" d="M14.491 1c-3.598.004-6.654 1.983-8.835 4H1.5l-.5.5v3l.147.354.991.991.001.009 4 4 .009.001.999.999L7.5 15h3l.5-.5v-4.154c2.019-2.178 3.996-5.233 3.992-8.846l-.501-.5zM2 6h2.643a23.828 23.828 0 0 0-2.225 2.71L2 8.294V6zm5.7 8l-.42-.423a23.59 23.59 0 0 0 2.715-2.216V14H7.7zm-1.143-1.144L3.136 9.437C4.128 8 8.379 2.355 13.978 2.016c-.326 5.612-5.987 9.853-7.421 10.84zM4 15v-1H2v-2H1v3h3zm6.748-7.667a1.5 1.5 0 1 0-2.496-1.666 1.5 1.5 0 0 0 2.495 1.666z"/></svg>
|
||||
);
|
||||
};
|
||||
@@ -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<IMetadataProps> = ({settings, metadata, focusElm, unsetFocus}: React.PropsWithChildren<IMetadataProps>) => {
|
||||
|
||||
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<IMetadataProps> = ({settings, met
|
||||
|
||||
return (
|
||||
<Collapsible id={`tags`} title="Metadata" className={`inherit z-20`}>
|
||||
|
||||
<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)} />
|
||||
</div>
|
||||
|
||||
{
|
||||
<TagPicker type={TagType.keywords}
|
||||
icon={<SymbolKeywordIcon />}
|
||||
|
||||
@@ -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<ITagPickerProps> = (props: React
|
||||
}, [crntSelected]);
|
||||
|
||||
return (
|
||||
<div className={`article__tags`}>
|
||||
<h3>{icon} {type}</h3>
|
||||
<div className={`article__tags`}>
|
||||
<VsLabel>
|
||||
<div className={`metadata_field__label`}>
|
||||
{icon} <span style={{ lineHeight: "16px"}}>{type}</span>
|
||||
</div>
|
||||
</VsLabel>
|
||||
|
||||
<Downshift ref={dsRef}
|
||||
onChange={(selected) => onSelect(selected || "")}
|
||||
|
||||
@@ -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
|
||||
*/
|
||||
|
||||
Reference in New Issue
Block a user