#51 - Default panel actions

This commit is contained in:
Elio Struyf
2021-08-06 14:41:39 +02:00
parent 0780842365
commit cefbf74582
13 changed files with 144 additions and 31 deletions
+1
View File
@@ -7,6 +7,7 @@
- [#48](https://github.com/estruyf/vscode-front-matter/issues/48): Added new folder registration message + notification helper
- [#49](https://github.com/estruyf/vscode-front-matter/issues/49): New initialize project command
- [#50](https://github.com/estruyf/vscode-front-matter/issues/50): Fix in the table rendering of rows
- [#51](https://github.com/estruyf/vscode-front-matter/issues/51): Panel actions base view enhanced to show project actions and information
## [2.1.0] - 2020-08-04
+7 -1
View File
@@ -53,7 +53,13 @@ Initially, this panel has been created to make it easier to add tags and categor
To leverage most of the capabilities of the extension. SEO information and everyday actions like slug optimization, updating the date, and publish/drafting the article.
The panel consists of the following sections:
When the panel opens on a none markdown file, it will contain the following sections:
<p align="center">
<img src="./assets/v2.2.0/baseview.png" alt="Base view" style="display: inline-block" />
</p>
When you open the Front Matter panel on a Markdown file, you get to see the following sections:
**SEO Status**
+3 -1
View File
@@ -248,7 +248,9 @@
filter: contrast(60%);
}
.article__actions > * + * {
.article__actions > * + *,
.base__actions > * + *,
.base__information > * + * {
--tw-space-y-reverse: 0;
margin-top: calc(1rem * calc(1 - var(--tw-space-y-reverse)));
margin-bottom: calc(1rem * var(--tw-space-y-reverse));
Binary file not shown.

After

Width:  |  Height:  |  Size: 27 KiB

+30 -2
View File
@@ -1,7 +1,7 @@
import { commands, Uri, workspace, window } from "vscode";
import { CONFIG_KEY, EXTENSION_NAME, SETTINGS_CONTENT_FOLDERS } from "../constants";
import { CONFIG_KEY, SETTINGS_CONTENT_FOLDERS } from "../constants";
import { basename } from "path";
import { ContentFolder } from "../models";
import { ContentFolder, FolderInfo } from "../models";
import uniqBy = require("lodash.uniqby");
import { Template } from "./Template";
import { Notifications } from "../helpers/Notifications";
@@ -118,6 +118,34 @@ export class Folders {
return folderPath;
}
/**
* Get the registered folders information
*/
public static async getInfo(): Promise<FolderInfo[] | null> {
const folders = Folders.get();
if (folders && folders.length > 0) {
let folderInfo: FolderInfo[] = [];
for (const folder of folders) {
try {
const files = await workspace.fs.readDirectory(Uri.file(folder.fsPath));
if (files) {
folderInfo.push({
title: folder.title,
files: files.length
});
}
} catch (e) {
// Skip the current folder
}
}
return folderInfo;
}
return null;
}
/**
* Get the folder settings
* @returns
+1 -1
View File
@@ -17,7 +17,7 @@ export class StatusListener {
const publishMsg = "to publish";
let editor = vscode.window.activeTextEditor;
if (editor && editor.document && (editor.document.languageId.toLowerCase() === "markdown" || editor.document.languageId.toLowerCase() === "mdx")) {
if (editor && ArticleHelper.isMarkdownDile()) {
try {
const article = ArticleHelper.getFrontMatter(editor);
+12 -6
View File
@@ -15,24 +15,30 @@ export class Template {
* Check if the template folder is available
*/
public static async init() {
const isInitialized = await Template.isInitialized();
await vscode.commands.executeCommand('setContext', CONTEXT.canInit, !isInitialized);
}
/**
* Check if the project is already initialized
*/
public static async isInitialized() {
const config = vscode.workspace.getConfiguration(CONFIG_KEY);
const folder = config.get<string>(SETTING_TEMPLATES_FOLDER);
const workspaceFolders = vscode.workspace.workspaceFolders;
if (!folder || !workspaceFolders || workspaceFolders.length === 0) {
vscode.commands.executeCommand('setContext', CONTEXT.canInit, true);
return;
return false;
}
const workspaceFolder = workspaceFolders[0];
const templatePath = vscode.Uri.file(path.join(workspaceFolder.uri.fsPath, folder));
try {
await vscode.workspace.fs.stat(templatePath);
vscode.commands.executeCommand('setContext', CONTEXT.canInit, false);
return true;
} catch (e) {
vscode.commands.executeCommand('setContext', CONTEXT.canInit, true);
return false;
}
}
+8
View File
@@ -96,4 +96,12 @@ export class ArticleHelper {
indent: spaces || 2
} as DumpOptions as any));
}
/**
* Checks if the current file is a markdown file
*/
public static isMarkdownDile() {
const editor = vscode.window.activeTextEditor;
return (editor && editor.document && (editor.document.languageId.toLowerCase() === "markdown" || editor.document.languageId.toLowerCase() === "mdx"));
}
}
+7
View File
@@ -6,6 +6,8 @@ export interface PanelSettings {
categories: string[];
freeform: boolean;
scripts: CustomScript[];
isInitialized: boolean;
contentInfo: FolderInfo[] | null;
}
export interface SEO {
@@ -20,6 +22,11 @@ export interface Slug {
suffix: number;
}
export interface FolderInfo {
title: string;
files: number;
}
export interface CustomScript {
title: string;
script: string;
+3 -1
View File
@@ -12,5 +12,7 @@ export enum CommandToCode {
openSettings = "open-settings",
openFile = "open-file",
openProject = "open-project",
runCustomScript = "custom-script"
runCustomScript = "custom-script",
initProject = "init-project",
createContent = "create-content",
}
+1 -1
View File
@@ -31,7 +31,7 @@ export const ViewPanel: React.FunctionComponent<IViewPanelProps> = (props: React
if (!metadata || Object.keys(metadata).length === 0) {
return (
<BaseView />
<BaseView settings={settings} />
);
}
+41 -3
View File
@@ -1,11 +1,49 @@
import * as React from 'react';
import { PanelSettings } from '../../models';
import { CommandToCode } from '../CommandToCode';
import { MessageHelper } from '../helper/MessageHelper';
import { Collapsible } from './Collapsible';
export interface IBaseViewProps {}
export interface IBaseViewProps {
settings: PanelSettings | undefined;
}
export const BaseView: React.FunctionComponent<IBaseViewProps> = ({settings}: React.PropsWithChildren<IBaseViewProps>) => {
const initProject = () => {
MessageHelper.sendMessage(CommandToCode.initProject);
};
const createContent = () => {
MessageHelper.sendMessage(CommandToCode.createContent);
};
export const BaseView: React.FunctionComponent<IBaseViewProps> = (props: React.PropsWithChildren<IBaseViewProps>) => {
return (
<div className="frontmatter">
<div className={`ext_actions`}>
<Collapsible title="Actions">
<div className={`base__actions`}>
<button onClick={initProject} disabled={settings?.isInitialized}>Initialize project</button>
<button onClick={createContent} disabled={!settings?.isInitialized}>Create new content</button>
</div>
</Collapsible>
{
settings?.contentInfo && (
<Collapsible title="Content information">
<div className="base__information">
{
settings.contentInfo.map(folder => (
<div key={folder.title}>
{folder.title}: {folder.files} file{folder.files > 1 ? 's' : ''}
</div>
))
}
</div>
</Collapsible>
)
}
</div>
</div>
);
};
+30 -15
View File
@@ -1,3 +1,4 @@
import { Template } from './../commands/Template';
import { SETTING_CUSTOM_SCRIPTS, SETTING_SEO_CONTENT_MIN_LENGTH, SETTING_SEO_DESCRIPTION_FIELD, SETTING_SLUG_UPDATE_FILE_NAME } from './../constants/settings';
import * as os from 'os';
import { PanelSettings, CustomScript } from './../models/PanelSettings';
@@ -14,6 +15,8 @@ import * as path from 'path';
import { fromMarkdown } from 'mdast-util-from-markdown';
import { Content } from 'mdast';
import { Notifications } from '../helpers/Notifications';
import { COMMAND_NAME } from '../constants/Extension';
import { Folders } from '../commands/Folders';
export class ExplorerView implements WebviewViewProvider, Disposable {
@@ -75,7 +78,7 @@ export class ExplorerView implements WebviewViewProvider, Disposable {
webviewView.onDidDispose(() => { webviewView.webview.html = ""; }, this),
);
webviewView.webview.onDidReceiveMessage(msg => {
webviewView.webview.onDidReceiveMessage(async (msg) => {
switch(msg.command) {
case CommandToCode.getData:
this.getSettings();
@@ -136,6 +139,13 @@ export class ExplorerView implements WebviewViewProvider, Disposable {
}
}
break;
case CommandToCode.initProject:
await commands.executeCommand(COMMAND_NAME.init);
this.getSettings();
break;
case CommandToCode.createContent:
await commands.executeCommand(COMMAND_NAME.createContent);
break;
}
});
@@ -162,10 +172,15 @@ export class ExplorerView implements WebviewViewProvider, Disposable {
* @param metadata
*/
public pushMetadata(metadata: any) {
const articleDetails = this.getArticleDetails();
if (articleDetails) {
metadata.articleDetails = articleDetails;
}
this.postWebviewMessage({ command: Command.metadata, data: {
...metadata,
articleDetails: this.getArticleDetails()
} });
...metadata
}});
}
/**
@@ -225,7 +240,7 @@ export class ExplorerView implements WebviewViewProvider, Disposable {
/**
* Retrieve the extension settings
*/
private getSettings() {
private async getSettings() {
const config = workspace.getConfiguration(CONFIG_KEY);
this.postWebviewMessage({
@@ -245,7 +260,9 @@ export class ExplorerView implements WebviewViewProvider, Disposable {
tags: config.get(SETTING_TAXONOMY_TAGS) || [],
categories: config.get(SETTING_TAXONOMY_CATEGORIES) || [],
freeform: config.get(SETTING_PANEL_FREEFORM),
scripts: config.get(SETTING_CUSTOM_SCRIPTS)
scripts: config.get(SETTING_CUSTOM_SCRIPTS),
isInitialized: await Template.isInitialized(),
contentInfo: await Folders.getInfo() || null
} as PanelSettings
});
}
@@ -260,10 +277,7 @@ export class ExplorerView implements WebviewViewProvider, Disposable {
}
const article = ArticleHelper.getFrontMatter(editor);
this.postWebviewMessage({ command: Command.metadata, data: {
...article!.data,
articleDetails: this.getArticleDetails()
}});
this.pushMetadata(article!.data);
}
/**
@@ -281,10 +295,7 @@ export class ExplorerView implements WebviewViewProvider, Disposable {
if (article && article.data) {
article.data[tagType.toLowerCase()] = values || [];
ArticleHelper.update(editor, article);
this.postWebviewMessage({ command: Command.metadata, data: {
...article.data,
articleDetails: this.getArticleDetails()
}});
this.pushMetadata(article!.data);
}
}
@@ -314,7 +325,11 @@ export class ExplorerView implements WebviewViewProvider, Disposable {
private getArticleDetails() {
const editor = window.activeTextEditor;
if (!editor) {
return "";
return null;
}
if (!ArticleHelper.isMarkdownDile()) {
return null;
}
const article = ArticleHelper.getFrontMatter(editor);