From f3943bd8468109d1a99bf65634e1c440fe41c3dd Mon Sep 17 00:00:00 2001 From: Elio Struyf Date: Wed, 17 Nov 2021 09:07:47 +0100 Subject: [PATCH 01/25] 5.6.0 --- package-lock.json | 2 +- package.json | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/package-lock.json b/package-lock.json index c2c7d87f..f317c3c3 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "vscode-front-matter-beta", - "version": "5.5.0", + "version": "5.6.0", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/package.json b/package.json index b209ecce..9d8966a1 100644 --- a/package.json +++ b/package.json @@ -3,7 +3,7 @@ "displayName": "Front Matter", "description": "An essential Visual Studio Code extension when you want to manage the markdown pages of your static site like: Hugo, Jekyll, Hexo, NextJs, Gatsby, and many more...", "icon": "assets/frontmatter-teal-128x128.png", - "version": "5.5.0", + "version": "5.6.0", "preview": false, "publisher": "eliostruyf", "galleryBanner": { @@ -839,4 +839,4 @@ "dependencies": { "@docsearch/js": "^3.0.0-alpha.40" } -} \ No newline at end of file +} From e6a7a9aae77cbbce0717df6af51c7ce409b0d83c Mon Sep 17 00:00:00 2001 From: Elio Struyf Date: Wed, 17 Nov 2021 10:03:19 +0100 Subject: [PATCH 02/25] #179 - New open dashboard icon --- CHANGELOG.md | 8 +++++ assets/icons/frontmatter-small-dark.svg | 11 +++++++ assets/icons/frontmatter-small-light.svg | 11 +++++++ assets/icons/frontmatter-small-teal.svg | 11 +++++++ assets/icons/media-dark.svg | 3 ++ assets/icons/media-light.svg | 3 ++ package.json | 30 +++++++++++++++++-- src/commands/Dashboard.ts | 15 ++++++++-- src/constants/Extension.ts | 1 + src/constants/context.ts | 3 +- .../components/Media/Item.tsx | 4 +-- src/extension.ts | 4 +++ 12 files changed, 95 insertions(+), 9 deletions(-) create mode 100644 assets/icons/frontmatter-small-dark.svg create mode 100644 assets/icons/frontmatter-small-light.svg create mode 100644 assets/icons/frontmatter-small-teal.svg create mode 100644 assets/icons/media-dark.svg create mode 100644 assets/icons/media-light.svg diff --git a/CHANGELOG.md b/CHANGELOG.md index f692c820..defc7e09 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,13 @@ # Change Log +## [5.6.0] - 2021-11-xx + +### 🎨 Enhancements + +- Updated camera icon from VS Code to media icon +- Updated `check` icon on media inserts to `plus` icon +- [#179](https://github.com/estruyf/vscode-front-matter/issues/179): Updated the `open dashboard` icon to make it easier to spot it + ## [5.5.0] - 2021-11-15 As from this version onwards, the extension will be published to [open-vsx.org](https://open-vsx.org/). diff --git a/assets/icons/frontmatter-small-dark.svg b/assets/icons/frontmatter-small-dark.svg new file mode 100644 index 00000000..4154f969 --- /dev/null +++ b/assets/icons/frontmatter-small-dark.svg @@ -0,0 +1,11 @@ + + + + + + diff --git a/assets/icons/frontmatter-small-light.svg b/assets/icons/frontmatter-small-light.svg new file mode 100644 index 00000000..30527cad --- /dev/null +++ b/assets/icons/frontmatter-small-light.svg @@ -0,0 +1,11 @@ + + + + + + diff --git a/assets/icons/frontmatter-small-teal.svg b/assets/icons/frontmatter-small-teal.svg new file mode 100644 index 00000000..61c61bd9 --- /dev/null +++ b/assets/icons/frontmatter-small-teal.svg @@ -0,0 +1,11 @@ + + + + + + diff --git a/assets/icons/media-dark.svg b/assets/icons/media-dark.svg new file mode 100644 index 00000000..65377af6 --- /dev/null +++ b/assets/icons/media-dark.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/assets/icons/media-light.svg b/assets/icons/media-light.svg new file mode 100644 index 00000000..a382f5cc --- /dev/null +++ b/assets/icons/media-light.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/package.json b/package.json index 9d8966a1..73f5e6ed 100644 --- a/package.json +++ b/package.json @@ -660,7 +660,10 @@ "command": "frontMatter.insertImage", "title": "Insert image into your content", "category": "Front matter", - "icon": "$(device-camera)" + "icon": { + "dark": "/assets/icons/media-dark.svg", + "light": "/assets/icons/media-light.svg" + } }, { "command": "frontMatter.insertTags", @@ -676,7 +679,19 @@ "command": "frontMatter.dashboard", "title": "Open dashboard", "category": "Front matter", - "icon": "$(preview)" + "icon": { + "dark": "/assets/icons/frontmatter-small-dark.svg", + "light": "/assets/icons/frontmatter-small-light.svg" + } + }, + { + "command": "frontMatter.dashboard.close", + "title": "Close dashboard", + "category": "Front matter", + "icon": { + "dark": "/assets/icons/frontmatter-small-teal.svg", + "light": "/assets/icons/frontmatter-small-teal.svg" + } }, { "command": "frontMatter.preview", @@ -709,7 +724,12 @@ { "command": "frontMatter.dashboard", "group": "navigation@-98", - "when": "frontMatter:enabled == true" + "when": "frontMatter:enabled == true && frontMatter:dashboard:open == false" + }, + { + "command": "frontMatter.dashboard.close", + "group": "navigation@-98", + "when": "frontMatter:enabled == true && frontMatter:dashboard:open == true" } ], "explorer/context": [ @@ -757,6 +777,10 @@ { "command": "frontMatter.createFromTemplate", "when": "false" + }, + { + "command": "frontMatter.dashboard.close", + "when": "false" } ], "view/title": [ diff --git a/src/commands/Dashboard.ts b/src/commands/Dashboard.ts index ff31c1c3..91c3290c 100644 --- a/src/commands/Dashboard.ts +++ b/src/commands/Dashboard.ts @@ -1,4 +1,4 @@ -import { SETTINGS_CONTENT_STATIC_FOLDER, SETTING_DATE_FIELD, SETTING_SEO_DESCRIPTION_FIELD, SETTINGS_DASHBOARD_OPENONSTART, SETTINGS_DASHBOARD_MEDIA_SNIPPET, SETTING_TAXONOMY_CONTENT_TYPES, DefaultFields, HOME_PAGE_NAVIGATION_ID, ExtensionState, COMMAND_NAME, SETTINGS_FRAMEWORK_ID, SETTINGS_CONTENT_DRAFT_FIELD, SETTINGS_CONTENT_SORTING } from '../constants'; +import { SETTINGS_CONTENT_STATIC_FOLDER, SETTING_DATE_FIELD, SETTING_SEO_DESCRIPTION_FIELD, SETTINGS_DASHBOARD_OPENONSTART, SETTINGS_DASHBOARD_MEDIA_SNIPPET, SETTING_TAXONOMY_CONTENT_TYPES, DefaultFields, HOME_PAGE_NAVIGATION_ID, ExtensionState, COMMAND_NAME, SETTINGS_FRAMEWORK_ID, SETTINGS_CONTENT_DRAFT_FIELD, SETTINGS_CONTENT_SORTING, CONTEXT } from '../constants'; import { ArticleHelper } from './../helpers/ArticleHelper'; import { basename, dirname, extname, join, parse } from "path"; import { existsSync, readdirSync, statSync, unlinkSync, writeFileSync } from "fs"; @@ -62,6 +62,8 @@ export class Dashboard { } else { Dashboard.create(); } + + await commands.executeCommand('setContext', CONTEXT.isDashboardOpen, true); } /** @@ -79,6 +81,10 @@ export class Dashboard { Dashboard.webview.reveal(); } } + + public static close() { + Dashboard.webview?.dispose(); + } /** * Create the dashboard webview @@ -105,19 +111,22 @@ export class Dashboard { Dashboard.webview.webview.html = Dashboard.getWebviewContent(Dashboard.webview.webview, extensionUri); - Dashboard.webview.onDidChangeViewState(() => { + Dashboard.webview.onDidChangeViewState(async () => { if (!this.webview?.visible) { Dashboard._viewData = undefined; const panel = ExplorerView.getInstance(extensionUri); panel.getMediaSelection(); } + + await commands.executeCommand('setContext', CONTEXT.isDashboardOpen, this.webview?.visible); }); - Dashboard.webview.onDidDispose(() => { + Dashboard.webview.onDidDispose(async () => { Dashboard.isDisposed = true; Dashboard._viewData = undefined; const panel = ExplorerView.getInstance(extensionUri); panel.getMediaSelection(); + await commands.executeCommand('setContext', CONTEXT.isDashboardOpen, false); }); SettingsHelper.onConfigChange((global?: any) => { diff --git a/src/constants/Extension.ts b/src/constants/Extension.ts index 05c71422..49ce954d 100644 --- a/src/constants/Extension.ts +++ b/src/constants/Extension.ts @@ -28,6 +28,7 @@ export const COMMAND_NAME = { collapseSections: getCommandName("collapseSections"), preview: getCommandName("preview"), dashboard: getCommandName("dashboard"), + dashboardClose: getCommandName("dashboard.close"), promote: getCommandName("promoteSettings"), insertImage: getCommandName("insertImage"), createFolder: getCommandName("createFolder"), diff --git a/src/constants/context.ts b/src/constants/context.ts index 3adfb320..a8754720 100644 --- a/src/constants/context.ts +++ b/src/constants/context.ts @@ -2,5 +2,6 @@ export const CONTEXT = { canInit: "frontMatterCanInit", canOpenPreview: "frontMatterCanOpenPreview", canOpenDashboard: "frontMatterCanOpenDashboard", - isEnabled: "frontMatter:enabled" + isEnabled: "frontMatter:enabled", + isDashboardOpen: "frontMatter:dashboard:open", }; \ No newline at end of file diff --git a/src/dashboardWebView/components/Media/Item.tsx b/src/dashboardWebView/components/Media/Item.tsx index 98295957..51718098 100644 --- a/src/dashboardWebView/components/Media/Item.tsx +++ b/src/dashboardWebView/components/Media/Item.tsx @@ -1,5 +1,5 @@ import { Messenger } from '@estruyf/vscode/dist/client'; -import { CheckCircleIcon, ClipboardCopyIcon, CodeIcon, PencilIcon, PhotographIcon, TrashIcon } from '@heroicons/react/outline'; +import { ClipboardCopyIcon, CodeIcon, PencilIcon, PhotographIcon, PlusCircleIcon, TrashIcon } from '@heroicons/react/outline'; import { basename, dirname } from 'path'; import * as React from 'react'; import { useEffect } from 'react'; @@ -199,7 +199,7 @@ export const Item: React.FunctionComponent = ({media}: React.PropsWi title={`Insert into your content`} className={`hover:text-teal-900 focus:outline-none`} onClick={insertToArticle}> - + Insert into your content { diff --git a/src/extension.ts b/src/extension.ts index 6d416d32..3995918a 100644 --- a/src/extension.ts +++ b/src/extension.ts @@ -45,6 +45,10 @@ export async function activate(context: vscode.ExtensionContext) { subscriptions.push(vscode.commands.registerCommand(COMMAND_NAME.dashboard, (data?: DashboardData) => { Dashboard.open(data); })); + + subscriptions.push(vscode.commands.registerCommand(COMMAND_NAME.dashboardClose, (data?: DashboardData) => { + Dashboard.close(); + })); if (!extension.getVersion().usedVersion) { vscode.commands.executeCommand(COMMAND_NAME.dashboard); From 8a0d308ceb784dac85e8e2025e644272ba9391f6 Mon Sep 17 00:00:00 2001 From: Elio Struyf Date: Wed, 17 Nov 2021 14:18:04 +0100 Subject: [PATCH 03/25] #178 - Sorting for media files --- CHANGELOG.md | 1 + src/commands/Dashboard.ts | 44 +++++++++++++++---- src/constants/ExtensionState.ts | 7 ++- .../components/Contents/Contents.tsx | 8 ++-- src/dashboardWebView/components/Dashboard.tsx | 7 ++- .../components/Header/Breadcrumb.tsx | 10 ++++- .../components/Header/Header.tsx | 22 ++++++---- .../components/Header/Sorting.tsx | 28 ++++++++---- .../components/Media/Pagination.tsx | 18 ++++++-- src/dashboardWebView/hooks/useMessages.tsx | 5 ++- src/dashboardWebView/hooks/usePages.tsx | 2 +- src/dashboardWebView/models/Settings.ts | 5 +++ src/dashboardWebView/models/ViewType.ts | 4 ++ src/dashboardWebView/models/index.ts | 2 + .../state/atom/DashboardViewAtom.ts | 5 ++- 15 files changed, 126 insertions(+), 42 deletions(-) create mode 100644 src/dashboardWebView/models/ViewType.ts diff --git a/CHANGELOG.md b/CHANGELOG.md index defc7e09..6f6ad5ec 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,7 @@ - Updated camera icon from VS Code to media icon - Updated `check` icon on media inserts to `plus` icon +- [#178](https://github.com/estruyf/vscode-front-matter/issues/178): Sorting added to the media dashboard - [#179](https://github.com/estruyf/vscode-front-matter/issues/179): Updated the `open dashboard` icon to make it easier to spot it ## [5.5.0] - 2021-11-15 diff --git a/src/commands/Dashboard.ts b/src/commands/Dashboard.ts index 91c3290c..f7ce1ebd 100644 --- a/src/commands/Dashboard.ts +++ b/src/commands/Dashboard.ts @@ -4,7 +4,7 @@ import { basename, dirname, extname, join, parse } from "path"; import { existsSync, readdirSync, statSync, unlinkSync, writeFileSync } from "fs"; import { commands, Uri, ViewColumn, Webview, WebviewPanel, window, workspace, env, Position } from "vscode"; import { Settings as SettingsHelper } from '../helpers'; -import { DraftField, Framework, SortingSetting, TaxonomyType } from '../models'; +import { DraftField, Framework, SortingSetting, SortOrder, TaxonomyType } from '../models'; import { Folders } from './Folders'; import { DashboardCommand } from '../dashboardWebView/DashboardCommand'; import { DashboardMessage } from '../dashboardWebView/DashboardMessage'; @@ -26,6 +26,7 @@ import { parseWinPath } from '../helpers/parseWinPath'; import { DateHelper } from '../helpers/DateHelper'; import { FrameworkDetector } from '../helpers/FrameworkDetector'; import { ContentType } from '../helpers/ContentType'; +import { SortingOption } from '../dashboardWebView/models'; export class Dashboard { private static webview: WebviewPanel | null = null; @@ -174,7 +175,7 @@ export class Dashboard { Extension.getInstance().setState(ExtensionState.PagesView, msg.data, "workspace"); break; case DashboardMessage.getMedia: - Dashboard.getMedia(msg?.data?.page, msg?.data?.folder); + Dashboard.getMedia(msg?.data?.page, msg?.data?.folder, msg?.data?.sorting); break; case DashboardMessage.copyToClipboard: env.clipboard.writeText(msg.data); @@ -299,7 +300,12 @@ export class Dashboard { crntFramework: SettingsHelper.get(SETTINGS_FRAMEWORK_ID), framework: (!isInitialized && wsFolder) ? FrameworkDetector.get(wsFolder.fsPath) : null, dashboardState: { - sorting: await ext.getState(ExtensionState.Dashboard.Sorting, "workspace") + contents: { + sorting: await ext.getState(ExtensionState.Dashboard.Contents.Sorting, "workspace") + }, + media: { + sorting: await ext.getState(ExtensionState.Dashboard.Media.Sorting, "workspace") + } } } as Settings }); @@ -334,16 +340,19 @@ export class Dashboard { /** * Retrieve all media files */ - private static async getMedia(page: number = 0, requestedFolder: string = '') { + private static async getMedia(page: number = 0, requestedFolder: string = '', sort: SortingOption | null = null) { const wsFolder = Folders.getWorkspaceFolder(); const staticFolder = SettingsHelper.get(SETTINGS_CONTENT_STATIC_FOLDER); const contentFolders = Folders.get(); const viewData = Dashboard.viewData; let selectedFolder = requestedFolder; + const ext = Extension.getInstance(); + const crntSort = sort === null ? await ext.getState(ExtensionState.Dashboard.Media.Sorting, "workspace") : sort; + // If the static folder is not set, retreive the last opened location if (!selectedFolder) { - const stateValue = await Extension.getInstance().getState(ExtensionState.SelectedFolder, "workspace"); + const stateValue = await ext.getState(ExtensionState.SelectedFolder, "workspace"); if (stateValue !== HOME_PAGE_NAVIGATION_ID) { // Support for page bundles @@ -400,15 +409,19 @@ export class Dashboard { } allMedia = allMedia.sort((a, b) => { - if (b.fsPath < a.fsPath) { + if (a.fsPath.toLowerCase() < b.fsPath.toLowerCase()) { return -1; } - if (b.fsPath > a.fsPath) { + if (a.fsPath.toLowerCase() > b.fsPath.toLowerCase()) { return 1; } return 0; }); + if (crntSort?.order === SortOrder.desc) { + allMedia = allMedia.reverse(); + } + Dashboard.media = Object.assign([], allMedia); let files: MediaInfo[] = Dashboard.media; @@ -459,13 +472,28 @@ export class Dashboard { // Store the last opened folder await Extension.getInstance().setState(ExtensionState.SelectedFolder, requestedFolder === HOME_PAGE_NAVIGATION_ID ? HOME_PAGE_NAVIGATION_ID : selectedFolder, "workspace"); + + let sortedFolders = [...allContentFolders, ...allFolders]; + sortedFolders = sortedFolders.sort((a, b) => { + if (a.toLowerCase() < b.toLowerCase()) { + return -1; + } + if (a.toLowerCase() > b.toLowerCase()) { + return 1; + } + return 0; + }); + + if (crntSort?.order === SortOrder.desc) { + sortedFolders = sortedFolders.reverse(); + } Dashboard.postWebviewMessage({ command: DashboardCommand.media, data: { media: files, total: total, - folders: [...allContentFolders, ...allFolders], + folders: sortedFolders, selectedFolder } as MediaPaths }); diff --git a/src/constants/ExtensionState.ts b/src/constants/ExtensionState.ts index d486d45a..36139f50 100644 --- a/src/constants/ExtensionState.ts +++ b/src/constants/ExtensionState.ts @@ -7,6 +7,11 @@ export const ExtensionState = { MoveTemplatesFolder: `frontMatter:Templates:Move`, Dashboard: { - Sorting: `frontMatter:Dashboard:Sorting`, + Contents: { + Sorting: `frontMatter:Dashboard:Contents:Sorting`, + }, + Media: { + Sorting: `frontMatter:Dashboard:Media:Sorting`, + } } }; \ No newline at end of file diff --git a/src/dashboardWebView/components/Contents/Contents.tsx b/src/dashboardWebView/components/Contents/Contents.tsx index 5817d556..b2450786 100644 --- a/src/dashboardWebView/components/Contents/Contents.tsx +++ b/src/dashboardWebView/components/Contents/Contents.tsx @@ -6,6 +6,7 @@ import { Header } from '../Header'; import { Overview } from './Overview'; import { Spinner } from '../Spinner'; import { SponsorMsg } from '../SponsorMsg'; +import usePages from '../../hooks/usePages'; export interface IContentsProps { pages: Page[]; @@ -14,19 +15,20 @@ export interface IContentsProps { export const Contents: React.FunctionComponent = ({pages, loading}: React.PropsWithChildren) => { const settings = useRecoilValue(SettingsSelector); + const { pageItems } = usePages(pages); - const pageFolders = [...new Set(pages.map(page => page.fmFolder))]; + const pageFolders = [...new Set(pageItems.map(page => page.fmFolder))]; return (
- { loading ? : } + { loading ? : }
diff --git a/src/dashboardWebView/components/Dashboard.tsx b/src/dashboardWebView/components/Dashboard.tsx index c48071b3..b4519d0a 100644 --- a/src/dashboardWebView/components/Dashboard.tsx +++ b/src/dashboardWebView/components/Dashboard.tsx @@ -2,12 +2,12 @@ import * as React from 'react'; import { Spinner } from './Spinner'; import useMessages from '../hooks/useMessages'; import useDarkMode from '../../hooks/useDarkMode'; -import usePages from '../hooks/usePages'; import { WelcomeScreen } from './WelcomeScreen'; import { useRecoilValue } from 'recoil'; import { DashboardViewSelector } from '../state'; import { Contents } from './Contents/Contents'; import { Media } from './Media/Media'; +import { ViewType } from '../models'; export interface IDashboardProps { showWelcome: boolean; @@ -15,7 +15,6 @@ export interface IDashboardProps { export const Dashboard: React.FunctionComponent = ({showWelcome}: React.PropsWithChildren) => { const { loading, pages, settings } = useMessages(); - const { pageItems } = usePages(pages); const view = useRecoilValue(DashboardViewSelector); useDarkMode(); @@ -31,9 +30,9 @@ export const Dashboard: React.FunctionComponent = ({showWelcome return ; } - if (view === 'media') { + if (view === ViewType.Media) { return ; } - return ; + return ; }; \ No newline at end of file diff --git a/src/dashboardWebView/components/Header/Breadcrumb.tsx b/src/dashboardWebView/components/Header/Breadcrumb.tsx index 3675354c..86486725 100644 --- a/src/dashboardWebView/components/Header/Breadcrumb.tsx +++ b/src/dashboardWebView/components/Header/Breadcrumb.tsx @@ -2,8 +2,10 @@ import { CollectionIcon } from '@heroicons/react/outline'; import { basename, join } from 'path'; import * as React from 'react'; import { useRecoilState, useRecoilValue } from 'recoil'; +import { Sorting } from '.'; import { HOME_PAGE_NAVIGATION_ID } from '../../../constants'; import { parseWinPath } from '../../../helpers/parseWinPath'; +import { ViewType } from '../../models'; import { SelectedMediaFolderAtom, SettingsAtom } from '../../state'; export interface IBreadcrumbProps {} @@ -63,8 +65,8 @@ export const Breadcrumb: React.FunctionComponent = (props: Rea }, [selectedFolder]); return ( -