-
+
-
- Copy media path
-
-
-
- Delete media
-
+ onClick={insertToArticle}>
+
+ Insert into your article
+
+ {
+ (viewData?.data?.position && settings?.mediaSnippet && settings?.mediaSnippet.length > 0) && (
+
+
+ Insert your media snippet
+
+ )
+ }
+ >
+ ) : (
+ <>
+
+
+ Copy media path
+
+
+
+ Delete media
+
+ >
+ )
+ }
{basename(parseWinPath(media.fsPath) || "")}
diff --git a/src/pagesView/components/Media/Lightbox.tsx b/src/dashboardWebView/components/Media/Lightbox.tsx
similarity index 100%
rename from src/pagesView/components/Media/Lightbox.tsx
rename to src/dashboardWebView/components/Media/Lightbox.tsx
diff --git a/src/pagesView/components/Media/List.tsx b/src/dashboardWebView/components/Media/List.tsx
similarity index 100%
rename from src/pagesView/components/Media/List.tsx
rename to src/dashboardWebView/components/Media/List.tsx
diff --git a/src/pagesView/components/Media/Media.tsx b/src/dashboardWebView/components/Media/Media.tsx
similarity index 87%
rename from src/pagesView/components/Media/Media.tsx
rename to src/dashboardWebView/components/Media/Media.tsx
index e18a5eab..4069b10d 100644
--- a/src/pagesView/components/Media/Media.tsx
+++ b/src/dashboardWebView/components/Media/Media.tsx
@@ -5,7 +5,7 @@ import * as React from 'react';
import { useRecoilState, useRecoilValue } from 'recoil';
import { MediaInfo, MediaPaths } from '../../../models/MediaPaths';
import { DashboardCommand } from '../../DashboardCommand';
-import { LoadingAtom, MediaFoldersAtom, MediaTotalAtom, SelectedMediaFolderSelector, SettingsSelector } from '../../state';
+import { LoadingAtom, MediaFoldersAtom, MediaTotalAtom, SelectedMediaFolderSelector, SettingsSelector, ViewDataSelector } from '../../state';
import { Header } from '../Header';
import { Spinner } from '../Spinner';
import { SponsorMsg } from '../SponsorMsg';
@@ -27,6 +27,7 @@ export const Media: React.FunctionComponent = (props: React.PropsWi
const [ , setTotal ] = useRecoilState(MediaTotalAtom);
const [ , setFolders ] = useRecoilState(MediaFoldersAtom);
const [ loading, setLoading ] = useRecoilState(LoadingAtom);
+ const viewData = useRecoilValue(ViewDataSelector);
const onDrop = useCallback((acceptedFiles: File[]) => {
acceptedFiles.forEach((file) => {
@@ -73,6 +74,15 @@ export const Media: React.FunctionComponent = (props: React.PropsWi
+
+ {
+ viewData?.data?.filePath && (
+
+
Select the image you want to use for your article.
+
You can also drag and drop images from your desktop and select that once uploaded.
+
+ )
+ }
{
isDragActive && (
diff --git a/src/pagesView/components/Media/Pagination.tsx b/src/dashboardWebView/components/Media/Pagination.tsx
similarity index 100%
rename from src/pagesView/components/Media/Pagination.tsx
rename to src/dashboardWebView/components/Media/Pagination.tsx
diff --git a/src/pagesView/components/Media/PaginationButton.tsx b/src/dashboardWebView/components/Media/PaginationButton.tsx
similarity index 100%
rename from src/pagesView/components/Media/PaginationButton.tsx
rename to src/dashboardWebView/components/Media/PaginationButton.tsx
diff --git a/src/pagesView/components/Menu/MenuButton.tsx b/src/dashboardWebView/components/Menu/MenuButton.tsx
similarity index 100%
rename from src/pagesView/components/Menu/MenuButton.tsx
rename to src/dashboardWebView/components/Menu/MenuButton.tsx
diff --git a/src/pagesView/components/Menu/MenuItem.tsx b/src/dashboardWebView/components/Menu/MenuItem.tsx
similarity index 100%
rename from src/pagesView/components/Menu/MenuItem.tsx
rename to src/dashboardWebView/components/Menu/MenuItem.tsx
diff --git a/src/pagesView/components/Menu/MenuItems.tsx b/src/dashboardWebView/components/Menu/MenuItems.tsx
similarity index 100%
rename from src/pagesView/components/Menu/MenuItems.tsx
rename to src/dashboardWebView/components/Menu/MenuItems.tsx
diff --git a/src/pagesView/components/Menu/index.ts b/src/dashboardWebView/components/Menu/index.ts
similarity index 100%
rename from src/pagesView/components/Menu/index.ts
rename to src/dashboardWebView/components/Menu/index.ts
diff --git a/src/pagesView/components/Modals/Alert.tsx b/src/dashboardWebView/components/Modals/Alert.tsx
similarity index 100%
rename from src/pagesView/components/Modals/Alert.tsx
rename to src/dashboardWebView/components/Modals/Alert.tsx
diff --git a/src/pagesView/components/Navigation.tsx b/src/dashboardWebView/components/Navigation.tsx
similarity index 100%
rename from src/pagesView/components/Navigation.tsx
rename to src/dashboardWebView/components/Navigation.tsx
diff --git a/src/pagesView/components/Spinner.tsx b/src/dashboardWebView/components/Spinner.tsx
similarity index 100%
rename from src/pagesView/components/Spinner.tsx
rename to src/dashboardWebView/components/Spinner.tsx
diff --git a/src/pagesView/components/SponsorMsg.tsx b/src/dashboardWebView/components/SponsorMsg.tsx
similarity index 100%
rename from src/pagesView/components/SponsorMsg.tsx
rename to src/dashboardWebView/components/SponsorMsg.tsx
diff --git a/src/pagesView/components/Startup.tsx b/src/dashboardWebView/components/Startup.tsx
similarity index 100%
rename from src/pagesView/components/Startup.tsx
rename to src/dashboardWebView/components/Startup.tsx
diff --git a/src/pagesView/components/Status.tsx b/src/dashboardWebView/components/Status.tsx
similarity index 100%
rename from src/pagesView/components/Status.tsx
rename to src/dashboardWebView/components/Status.tsx
diff --git a/src/pagesView/components/Steps/Step.tsx b/src/dashboardWebView/components/Steps/Step.tsx
similarity index 100%
rename from src/pagesView/components/Steps/Step.tsx
rename to src/dashboardWebView/components/Steps/Step.tsx
diff --git a/src/pagesView/components/Steps/StepsToGetStarted.tsx b/src/dashboardWebView/components/Steps/StepsToGetStarted.tsx
similarity index 100%
rename from src/pagesView/components/Steps/StepsToGetStarted.tsx
rename to src/dashboardWebView/components/Steps/StepsToGetStarted.tsx
diff --git a/src/pagesView/components/WelcomeScreen.tsx b/src/dashboardWebView/components/WelcomeScreen.tsx
similarity index 96%
rename from src/pagesView/components/WelcomeScreen.tsx
rename to src/dashboardWebView/components/WelcomeScreen.tsx
index aecb321c..ef5cdd1f 100644
--- a/src/pagesView/components/WelcomeScreen.tsx
+++ b/src/dashboardWebView/components/WelcomeScreen.tsx
@@ -2,8 +2,8 @@ import { HeartIcon, StarIcon } from '@heroicons/react/outline';
import * as React from 'react';
import { GITHUB_LINK, REVIEW_LINK, SPONSOR_LINK } from '../../constants/Links';
import { Messenger } from '@estruyf/vscode/dist/client';
-import { FrontMatterIcon } from '../../viewpanel/components/Icons/FrontMatterIcon';
-import { GitHubIcon } from '../../viewpanel/components/Icons/GitHubIcon';
+import { FrontMatterIcon } from '../../panelWebView/components/Icons/FrontMatterIcon';
+import { GitHubIcon } from '../../panelWebView/components/Icons/GitHubIcon';
import { DashboardMessage } from '../DashboardMessage';
import { Settings } from '../models/Settings';
import { StepsToGetStarted } from './Steps/StepsToGetStarted';
diff --git a/src/pagesView/constants/GroupOption.ts b/src/dashboardWebView/constants/GroupOption.ts
similarity index 100%
rename from src/pagesView/constants/GroupOption.ts
rename to src/dashboardWebView/constants/GroupOption.ts
diff --git a/src/pagesView/constants/SortOption.ts b/src/dashboardWebView/constants/SortOption.ts
similarity index 100%
rename from src/pagesView/constants/SortOption.ts
rename to src/dashboardWebView/constants/SortOption.ts
diff --git a/src/pagesView/constants/Storage.ts b/src/dashboardWebView/constants/Storage.ts
similarity index 100%
rename from src/pagesView/constants/Storage.ts
rename to src/dashboardWebView/constants/Storage.ts
diff --git a/src/pagesView/constants/Tab.ts b/src/dashboardWebView/constants/Tab.ts
similarity index 100%
rename from src/pagesView/constants/Tab.ts
rename to src/dashboardWebView/constants/Tab.ts
diff --git a/src/pagesView/hooks/useMessages.tsx b/src/dashboardWebView/hooks/useMessages.tsx
similarity index 71%
rename from src/pagesView/hooks/useMessages.tsx
rename to src/dashboardWebView/hooks/useMessages.tsx
index e20bf0c1..2f7fcccb 100644
--- a/src/pagesView/hooks/useMessages.tsx
+++ b/src/dashboardWebView/hooks/useMessages.tsx
@@ -3,7 +3,7 @@ import { useRecoilState } from 'recoil';
import { DashboardCommand } from '../DashboardCommand';
import { DashboardMessage } from '../DashboardMessage';
import { Page } from '../models/Page';
-import { SettingsAtom } from '../state';
+import { DashboardViewAtom, SettingsAtom, ViewDataAtom } from '../state';
import { Messenger } from '@estruyf/vscode/dist/client';
import { EventData } from '@estruyf/vscode/dist/models';
@@ -11,12 +11,20 @@ export default function useMessages() {
const [loading, setLoading] = useState
(false);
const [pages, setPages] = useState([]);
const [settings, setSettings] = useRecoilState(SettingsAtom);
+ const [viewData, setViewData] = useRecoilState(ViewDataAtom);
+ const [, setView] = useRecoilState(DashboardViewAtom);
Messenger.listen((message: MessageEvent>) => {
switch (message.data.command) {
case DashboardCommand.loading:
setLoading(message.data.data);
break;
+ case DashboardCommand.viewData:
+ setViewData(message.data.data);
+ if (message.data.data?.type === 'media') {
+ setView('media');
+ }
+ break;
case DashboardCommand.settings:
setSettings(message.data.data);
break;
@@ -27,8 +35,9 @@ export default function useMessages() {
}
});
- useEffect(() => {
+ useEffect(() => {
setLoading(true);
+ Messenger.send(DashboardMessage.getViewType);
Messenger.send(DashboardMessage.getTheme);
Messenger.send(DashboardMessage.getData);
}, ['']);
@@ -36,6 +45,7 @@ export default function useMessages() {
return {
loading,
pages,
+ viewData,
settings
};
}
\ No newline at end of file
diff --git a/src/pagesView/hooks/usePages.tsx b/src/dashboardWebView/hooks/usePages.tsx
similarity index 100%
rename from src/pagesView/hooks/usePages.tsx
rename to src/dashboardWebView/hooks/usePages.tsx
diff --git a/src/pagesView/index.tsx b/src/dashboardWebView/index.tsx
similarity index 100%
rename from src/pagesView/index.tsx
rename to src/dashboardWebView/index.tsx
diff --git a/src/pagesView/models/Page.ts b/src/dashboardWebView/models/Page.ts
similarity index 100%
rename from src/pagesView/models/Page.ts
rename to src/dashboardWebView/models/Page.ts
diff --git a/src/pagesView/models/Settings.ts b/src/dashboardWebView/models/Settings.ts
similarity index 81%
rename from src/pagesView/models/Settings.ts
rename to src/dashboardWebView/models/Settings.ts
index e3335b15..59ddaa31 100644
--- a/src/pagesView/models/Settings.ts
+++ b/src/dashboardWebView/models/Settings.ts
@@ -1,6 +1,6 @@
import { VersionInfo } from '../../models/VersionInfo';
import { ViewType } from '../state';
-import { ContentFolder } from './../../models/ContentFolder';
+import { ContentFolder } from '../../models/ContentFolder';
export interface Settings {
beta: boolean;
@@ -13,4 +13,5 @@ export interface Settings {
openOnStart: boolean | null;
versionInfo: VersionInfo;
pageViewType: ViewType | undefined;
+ mediaSnippet: string[];
}
\ No newline at end of file
diff --git a/src/pagesView/models/Status.ts b/src/dashboardWebView/models/Status.ts
similarity index 100%
rename from src/pagesView/models/Status.ts
rename to src/dashboardWebView/models/Status.ts
diff --git a/src/pagesView/models/index.ts b/src/dashboardWebView/models/index.ts
similarity index 100%
rename from src/pagesView/models/index.ts
rename to src/dashboardWebView/models/index.ts
diff --git a/src/pagesView/state/atom/CategoryAtom.ts b/src/dashboardWebView/state/atom/CategoryAtom.ts
similarity index 100%
rename from src/pagesView/state/atom/CategoryAtom.ts
rename to src/dashboardWebView/state/atom/CategoryAtom.ts
diff --git a/src/pagesView/state/atom/DashboardViewAtom.ts b/src/dashboardWebView/state/atom/DashboardViewAtom.ts
similarity index 100%
rename from src/pagesView/state/atom/DashboardViewAtom.ts
rename to src/dashboardWebView/state/atom/DashboardViewAtom.ts
diff --git a/src/pagesView/state/atom/FolderAtom.ts b/src/dashboardWebView/state/atom/FolderAtom.ts
similarity index 100%
rename from src/pagesView/state/atom/FolderAtom.ts
rename to src/dashboardWebView/state/atom/FolderAtom.ts
diff --git a/src/pagesView/state/atom/GroupingAtom.ts b/src/dashboardWebView/state/atom/GroupingAtom.ts
similarity index 100%
rename from src/pagesView/state/atom/GroupingAtom.ts
rename to src/dashboardWebView/state/atom/GroupingAtom.ts
diff --git a/src/pagesView/state/atom/LightboxAtom.ts b/src/dashboardWebView/state/atom/LightboxAtom.ts
similarity index 100%
rename from src/pagesView/state/atom/LightboxAtom.ts
rename to src/dashboardWebView/state/atom/LightboxAtom.ts
diff --git a/src/pagesView/state/atom/LoadingAtom.ts b/src/dashboardWebView/state/atom/LoadingAtom.ts
similarity index 100%
rename from src/pagesView/state/atom/LoadingAtom.ts
rename to src/dashboardWebView/state/atom/LoadingAtom.ts
diff --git a/src/pagesView/state/atom/MediaFoldersAtom.ts b/src/dashboardWebView/state/atom/MediaFoldersAtom.ts
similarity index 100%
rename from src/pagesView/state/atom/MediaFoldersAtom.ts
rename to src/dashboardWebView/state/atom/MediaFoldersAtom.ts
diff --git a/src/pagesView/state/atom/MediaTotalAtom.ts b/src/dashboardWebView/state/atom/MediaTotalAtom.ts
similarity index 100%
rename from src/pagesView/state/atom/MediaTotalAtom.ts
rename to src/dashboardWebView/state/atom/MediaTotalAtom.ts
diff --git a/src/pagesView/state/atom/PageAtom.ts b/src/dashboardWebView/state/atom/PageAtom.ts
similarity index 100%
rename from src/pagesView/state/atom/PageAtom.ts
rename to src/dashboardWebView/state/atom/PageAtom.ts
diff --git a/src/pagesView/state/atom/SearchAtom.ts b/src/dashboardWebView/state/atom/SearchAtom.ts
similarity index 100%
rename from src/pagesView/state/atom/SearchAtom.ts
rename to src/dashboardWebView/state/atom/SearchAtom.ts
diff --git a/src/pagesView/state/atom/SelectedMediaFolderAtom.ts b/src/dashboardWebView/state/atom/SelectedMediaFolderAtom.ts
similarity index 100%
rename from src/pagesView/state/atom/SelectedMediaFolderAtom.ts
rename to src/dashboardWebView/state/atom/SelectedMediaFolderAtom.ts
diff --git a/src/pagesView/state/atom/SettingsAtom.ts b/src/dashboardWebView/state/atom/SettingsAtom.ts
similarity index 100%
rename from src/pagesView/state/atom/SettingsAtom.ts
rename to src/dashboardWebView/state/atom/SettingsAtom.ts
diff --git a/src/pagesView/state/atom/SortingAtom.ts b/src/dashboardWebView/state/atom/SortingAtom.ts
similarity index 100%
rename from src/pagesView/state/atom/SortingAtom.ts
rename to src/dashboardWebView/state/atom/SortingAtom.ts
diff --git a/src/pagesView/state/atom/TabAtom.ts b/src/dashboardWebView/state/atom/TabAtom.ts
similarity index 100%
rename from src/pagesView/state/atom/TabAtom.ts
rename to src/dashboardWebView/state/atom/TabAtom.ts
diff --git a/src/pagesView/state/atom/TagAtom.ts b/src/dashboardWebView/state/atom/TagAtom.ts
similarity index 100%
rename from src/pagesView/state/atom/TagAtom.ts
rename to src/dashboardWebView/state/atom/TagAtom.ts
diff --git a/src/pagesView/state/atom/ViewAtom.ts b/src/dashboardWebView/state/atom/ViewAtom.ts
similarity index 100%
rename from src/pagesView/state/atom/ViewAtom.ts
rename to src/dashboardWebView/state/atom/ViewAtom.ts
diff --git a/src/dashboardWebView/state/atom/ViewDataAtom.ts b/src/dashboardWebView/state/atom/ViewDataAtom.ts
new file mode 100644
index 00000000..c05bad0d
--- /dev/null
+++ b/src/dashboardWebView/state/atom/ViewDataAtom.ts
@@ -0,0 +1,7 @@
+import { atom } from 'recoil';
+import { DashboardData } from '../../../models/DashboardData';
+
+export const ViewDataAtom = atom({
+ key: 'ViewDataAtom',
+ default: undefined
+});
\ No newline at end of file
diff --git a/src/pagesView/state/atom/index.ts b/src/dashboardWebView/state/atom/index.ts
similarity index 94%
rename from src/pagesView/state/atom/index.ts
rename to src/dashboardWebView/state/atom/index.ts
index a8d30209..2dcf5824 100644
--- a/src/pagesView/state/atom/index.ts
+++ b/src/dashboardWebView/state/atom/index.ts
@@ -14,3 +14,4 @@ export * from './SortingAtom';
export * from './TabAtom';
export * from './TagAtom';
export * from './ViewAtom';
+export * from './ViewDataAtom';
diff --git a/src/pagesView/state/index.ts b/src/dashboardWebView/state/index.ts
similarity index 100%
rename from src/pagesView/state/index.ts
rename to src/dashboardWebView/state/index.ts
diff --git a/src/pagesView/state/selectors/CategorySelector.ts b/src/dashboardWebView/state/selectors/CategorySelector.ts
similarity index 100%
rename from src/pagesView/state/selectors/CategorySelector.ts
rename to src/dashboardWebView/state/selectors/CategorySelector.ts
diff --git a/src/pagesView/state/selectors/DashboardViewSelector.ts b/src/dashboardWebView/state/selectors/DashboardViewSelector.ts
similarity index 100%
rename from src/pagesView/state/selectors/DashboardViewSelector.ts
rename to src/dashboardWebView/state/selectors/DashboardViewSelector.ts
diff --git a/src/pagesView/state/selectors/FolderSelector.ts b/src/dashboardWebView/state/selectors/FolderSelector.ts
similarity index 100%
rename from src/pagesView/state/selectors/FolderSelector.ts
rename to src/dashboardWebView/state/selectors/FolderSelector.ts
diff --git a/src/pagesView/state/selectors/GroupingSelector.ts b/src/dashboardWebView/state/selectors/GroupingSelector.ts
similarity index 100%
rename from src/pagesView/state/selectors/GroupingSelector.ts
rename to src/dashboardWebView/state/selectors/GroupingSelector.ts
diff --git a/src/pagesView/state/selectors/LoadingSelector.ts b/src/dashboardWebView/state/selectors/LoadingSelector.ts
similarity index 100%
rename from src/pagesView/state/selectors/LoadingSelector.ts
rename to src/dashboardWebView/state/selectors/LoadingSelector.ts
diff --git a/src/pagesView/state/selectors/MediaFoldersSelector.ts b/src/dashboardWebView/state/selectors/MediaFoldersSelector.ts
similarity index 100%
rename from src/pagesView/state/selectors/MediaFoldersSelector.ts
rename to src/dashboardWebView/state/selectors/MediaFoldersSelector.ts
diff --git a/src/pagesView/state/selectors/MediaTotalSelector.ts b/src/dashboardWebView/state/selectors/MediaTotalSelector.ts
similarity index 100%
rename from src/pagesView/state/selectors/MediaTotalSelector.ts
rename to src/dashboardWebView/state/selectors/MediaTotalSelector.ts
diff --git a/src/pagesView/state/selectors/SearchSelector.ts b/src/dashboardWebView/state/selectors/SearchSelector.ts
similarity index 100%
rename from src/pagesView/state/selectors/SearchSelector.ts
rename to src/dashboardWebView/state/selectors/SearchSelector.ts
diff --git a/src/pagesView/state/selectors/SelectedMediaFolderSelector.ts b/src/dashboardWebView/state/selectors/SelectedMediaFolderSelector.ts
similarity index 100%
rename from src/pagesView/state/selectors/SelectedMediaFolderSelector.ts
rename to src/dashboardWebView/state/selectors/SelectedMediaFolderSelector.ts
diff --git a/src/pagesView/state/selectors/SettingsSelector.ts b/src/dashboardWebView/state/selectors/SettingsSelector.ts
similarity index 100%
rename from src/pagesView/state/selectors/SettingsSelector.ts
rename to src/dashboardWebView/state/selectors/SettingsSelector.ts
diff --git a/src/pagesView/state/selectors/SortingSelector.ts b/src/dashboardWebView/state/selectors/SortingSelector.ts
similarity index 100%
rename from src/pagesView/state/selectors/SortingSelector.ts
rename to src/dashboardWebView/state/selectors/SortingSelector.ts
diff --git a/src/pagesView/state/selectors/TabSelector.ts b/src/dashboardWebView/state/selectors/TabSelector.ts
similarity index 100%
rename from src/pagesView/state/selectors/TabSelector.ts
rename to src/dashboardWebView/state/selectors/TabSelector.ts
diff --git a/src/pagesView/state/selectors/TagSelector.ts b/src/dashboardWebView/state/selectors/TagSelector.ts
similarity index 100%
rename from src/pagesView/state/selectors/TagSelector.ts
rename to src/dashboardWebView/state/selectors/TagSelector.ts
diff --git a/src/dashboardWebView/state/selectors/ViewDataSelector.ts b/src/dashboardWebView/state/selectors/ViewDataSelector.ts
new file mode 100644
index 00000000..b1596594
--- /dev/null
+++ b/src/dashboardWebView/state/selectors/ViewDataSelector.ts
@@ -0,0 +1,9 @@
+import { selector } from 'recoil';
+import { ViewDataAtom } from '..';
+
+export const ViewDataSelector = selector({
+ key: 'ViewDataSelector',
+ get: ({get}) => {
+ return get(ViewDataAtom);
+ }
+});
\ No newline at end of file
diff --git a/src/pagesView/state/selectors/ViewSelector.ts b/src/dashboardWebView/state/selectors/ViewSelector.ts
similarity index 100%
rename from src/pagesView/state/selectors/ViewSelector.ts
rename to src/dashboardWebView/state/selectors/ViewSelector.ts
diff --git a/src/pagesView/state/selectors/index.ts b/src/dashboardWebView/state/selectors/index.ts
similarity index 93%
rename from src/pagesView/state/selectors/index.ts
rename to src/dashboardWebView/state/selectors/index.ts
index 3c52ec37..a694a579 100644
--- a/src/pagesView/state/selectors/index.ts
+++ b/src/dashboardWebView/state/selectors/index.ts
@@ -11,4 +11,5 @@ export * from './SettingsSelector';
export * from './SortingSelector';
export * from './TabSelector';
export * from './TagSelector';
+export * from './ViewDataSelector';
export * from './ViewSelector';
diff --git a/src/pagesView/styles.css b/src/dashboardWebView/styles.css
similarity index 100%
rename from src/pagesView/styles.css
rename to src/dashboardWebView/styles.css
diff --git a/src/webview/ExplorerView.ts b/src/explorerView/ExplorerView.ts
similarity index 72%
rename from src/webview/ExplorerView.ts
rename to src/explorerView/ExplorerView.ts
index 29695cc8..30ecfa11 100644
--- a/src/webview/ExplorerView.ts
+++ b/src/explorerView/ExplorerView.ts
@@ -1,14 +1,14 @@
-import { Template } from './../commands/Template';
-import { SETTINGS_CONTENT_FRONTMATTER_HIGHLIGHT, SETTING_AUTO_UPDATE_DATE, SETTING_CUSTOM_SCRIPTS, SETTING_SEO_CONTENT_MIN_LENGTH, SETTING_SEO_DESCRIPTION_FIELD, SETTING_SLUG_UPDATE_FILE_NAME, SETTING_PREVIEW_HOST } from './../constants/settings';
+import { DashboardData } from '../models/DashboardData';
+import { Template } from '../commands/Template';
+import { DefaultFields, SETTINGS_CONTENT_FRONTMATTER_HIGHLIGHT, SETTING_AUTO_UPDATE_DATE, SETTING_CUSTOM_SCRIPTS, SETTING_SEO_CONTENT_MIN_LENGTH, SETTING_SEO_DESCRIPTION_FIELD, SETTING_SLUG_UPDATE_FILE_NAME, SETTING_PREVIEW_HOST, SETTING_DATE_FORMAT, SETTING_COMMA_SEPARATED_FIELDS, SETTINGS_CONTENT_STATIC_FOLDERS, SETTING_TAXONOMY_CONTENT_TYPES, SETTING_PANEL_FREEFORM, SETTING_SEO_DESCRIPTION_LENGTH, SETTING_SEO_TITLE_LENGTH, SETTING_SLUG_PREFIX, SETTING_SLUG_SUFFIX, SETTING_TAXONOMY_CATEGORIES, SETTING_TAXONOMY_TAGS } from '../constants';
import * as os from 'os';
-import { PanelSettings, CustomScript } from './../models/PanelSettings';
+import { PanelSettings, CustomScript } from '../models/PanelSettings';
import { CancellationToken, Disposable, Uri, Webview, WebviewView, WebviewViewProvider, WebviewViewResolveContext, window, workspace, commands, env as vscodeEnv } from "vscode";
-import { SETTING_PANEL_FREEFORM, SETTING_SEO_DESCRIPTION_LENGTH, SETTING_SEO_TITLE_LENGTH, SETTING_SLUG_PREFIX, SETTING_SLUG_SUFFIX, SETTING_TAXONOMY_CATEGORIES, SETTING_TAXONOMY_TAGS } from "../constants";
-import { ArticleHelper, SettingsHelper } from "../helpers";
-import { Command } from "../viewpanel/Command";
-import { CommandToCode } from '../viewpanel/CommandToCode';
+import { ArticleHelper, Settings } from "../helpers";
+import { Command } from "../panelWebView/Command";
+import { CommandToCode } from '../panelWebView/CommandToCode';
import { Article } from '../commands';
-import { TagType } from '../viewpanel/TagType';
+import { TagType } from '../panelWebView/TagType';
import { TaxonomyType } from '../models';
import { exec } from 'child_process';
import * as path from 'path';
@@ -21,6 +21,9 @@ import { Preview } from '../commands/Preview';
import { openFileInEditor } from '../helpers/openFileInEditor';
import { WebviewHelper } from '@estruyf/vscode';
import { Extension } from '../helpers/Extension';
+import { dirname, join } from 'path';
+import { existsSync } from 'fs';
+import { Dashboard } from '../commands/Dashboard';
const FILE_LIMIT = 10;
@@ -73,8 +76,7 @@ export class ExplorerView implements WebviewViewProvider, Disposable {
webviewView.webview.options = {
enableScripts: true,
- enableCommandUris: true,
- localResourceRoots: [this.extPath]
+ enableCommandUris: true
};
webviewView.webview.html = this.getWebviewContent(webviewView.webview);
@@ -93,9 +95,6 @@ export class ExplorerView implements WebviewViewProvider, Disposable {
case CommandToCode.updateSlug:
Article.generateSlug();
break;
- case CommandToCode.updateDate:
- Article.setDate();
- break;
case CommandToCode.updateLastMod:
Article.setLastModifiedDate();
break;
@@ -182,6 +181,13 @@ export class ExplorerView implements WebviewViewProvider, Disposable {
case CommandToCode.updateMetadata:
this.updateMetadata(msg.data);
break;
+ case CommandToCode.selectImage:
+ await commands.executeCommand(COMMAND_NAME.dashboard, {
+ type: "media",
+ data: msg.data
+ } as DashboardData);
+ this.getMediaSelection();
+ break;
}
});
@@ -198,7 +204,7 @@ export class ExplorerView implements WebviewViewProvider, Disposable {
}
}, this);
- workspace.onDidChangeConfiguration(() => {
+ Settings.onConfigChange((global?: any) => {
this.getSettings();
});
}
@@ -208,14 +214,62 @@ export class ExplorerView implements WebviewViewProvider, Disposable {
* @param metadata
*/
public pushMetadata(metadata: any) {
+ const wsFolder = Folders.getWorkspaceFolder();
+ const filePath = window.activeTextEditor?.document.uri.fsPath;
+ const commaSeparated = Settings.get(SETTING_COMMA_SEPARATED_FIELDS);
+ const staticFolder = Settings.get(SETTINGS_CONTENT_STATIC_FOLDERS);
+ const contentTypes = Settings.get(SETTING_TAXONOMY_CONTENT_TYPES);
+
const articleDetails = this.getArticleDetails();
if (articleDetails) {
metadata.articleDetails = articleDetails;
}
+ let updatedMetadata = Object.assign({}, metadata);
+ if (commaSeparated) {
+ for (const key of commaSeparated) {
+ if (updatedMetadata[key] && typeof updatedMetadata[key] === "string") {
+ updatedMetadata[key] = updatedMetadata[key].split(",").map((s: string) => s.trim());
+ }
+ }
+ }
+
+ const keys = Object.keys(updatedMetadata);
+ if (keys.length > 0) {
+ updatedMetadata.filePath = filePath;
+ }
+
+ if (keys.length > 0 && contentTypes && wsFolder) {
+ // Get the current content type
+ const contentType = ArticleHelper.getContentType(updatedMetadata);
+ if (contentType) {
+ const imageFields = contentType.fields.filter((field) => field.type === "image");
+ for (const field of imageFields) {
+ if (updatedMetadata[field.name]) {
+ const staticPath = join(wsFolder.fsPath, staticFolder || "", updatedMetadata[field.name]);
+ const contentFolderPath = filePath ? join(dirname(filePath), updatedMetadata[field.name]) : null;
+
+ let previewUri = null;
+ if (existsSync(staticPath)) {
+ previewUri = Uri.file(staticPath);
+ } else if (contentFolderPath && existsSync(contentFolderPath)) {
+ previewUri = Uri.file(contentFolderPath);
+ }
+
+ if (previewUri) {
+ const preview = this.panel?.webview.asWebviewUri(previewUri);
+ updatedMetadata[field.name]= preview?.toString() || "";
+ } else {
+ updatedMetadata[field.name] = "";
+ }
+ }
+ }
+ }
+ }
+
this.postWebviewMessage({ command: Command.metadata, data: {
- ...metadata
+ ...updatedMetadata
}});
}
@@ -241,7 +295,7 @@ export class ExplorerView implements WebviewViewProvider, Disposable {
/**
* Update the metadata of the article
*/
- private updateMetadata({field, value}: { field: string, value: string }) {
+ public async updateMetadata({field, value}: { field: string, value: string }) {
if (!field) {
return;
}
@@ -256,8 +310,19 @@ export class ExplorerView implements WebviewViewProvider, Disposable {
return;
}
- article.data[field] = value;
+ const contentType = ArticleHelper.getContentType(article.data);
+ const dateFields = contentType.fields.filter((field) => field.type === "datetime");
+
+ for (const dateField of dateFields) {
+ if ((field === dateField.name) && value) {
+ article.data[field] = Article.formatDate(new Date(value));
+ } else {
+ article.data[field] = value;
+ }
+ }
+
ArticleHelper.update(editor, article);
+ this.pushMetadata(article.data);
}
/**
@@ -265,8 +330,7 @@ export class ExplorerView implements WebviewViewProvider, Disposable {
* @param msg
*/
private runCustomScript(msg: { command: string, data: any}) {
- const config = SettingsHelper.getConfig();
- const scripts: CustomScript[] | undefined = config.get(SETTING_CUSTOM_SCRIPTS);
+ const scripts: CustomScript[] | undefined = Settings.get(SETTING_CUSTOM_SCRIPTS);
if (msg?.data?.title && msg?.data?.script && scripts) {
const customScript = scripts.find((s: CustomScript) => s.title === msg.data.title);
@@ -302,35 +366,49 @@ export class ExplorerView implements WebviewViewProvider, Disposable {
}
}
+ /**
+ * Return the media selection
+ */
+ public async getMediaSelection() {
+ this.postWebviewMessage({
+ command: Command.mediaSelectionData,
+ data: Dashboard.viewData
+ });
+ }
+
/**
* Retrieve the extension settings
*/
public async getSettings() {
- const config = SettingsHelper.getConfig();
-
this.postWebviewMessage({
command: Command.settings,
data: {
seo: {
- title: config.get(SETTING_SEO_TITLE_LENGTH) as number || -1,
- description: config.get(SETTING_SEO_DESCRIPTION_LENGTH) as number || -1,
- content: config.get(SETTING_SEO_CONTENT_MIN_LENGTH) as number || -1,
- descriptionField: config.get(SETTING_SEO_DESCRIPTION_FIELD) as string || "description"
+ title: Settings.get(SETTING_SEO_TITLE_LENGTH) as number || -1,
+ description: Settings.get(SETTING_SEO_DESCRIPTION_LENGTH) as number || -1,
+ content: Settings.get(SETTING_SEO_CONTENT_MIN_LENGTH) as number || -1,
+ descriptionField: Settings.get(SETTING_SEO_DESCRIPTION_FIELD) as string || DefaultFields.Description
},
slug: {
- prefix: config.get(SETTING_SLUG_PREFIX) || "",
- suffix: config.get(SETTING_SLUG_SUFFIX) || "",
- updateFileName: !!config.get(SETTING_SLUG_UPDATE_FILE_NAME),
+ prefix: Settings.get(SETTING_SLUG_PREFIX) || "",
+ suffix: Settings.get(SETTING_SLUG_SUFFIX) || "",
+ updateFileName: !!Settings.get(SETTING_SLUG_UPDATE_FILE_NAME),
},
- tags: config.get(SETTING_TAXONOMY_TAGS) || [],
- categories: config.get(SETTING_TAXONOMY_CATEGORIES) || [],
- freeform: config.get(SETTING_PANEL_FREEFORM),
- scripts: config.get(SETTING_CUSTOM_SCRIPTS),
+ date: {
+ format: Settings.get(SETTING_DATE_FORMAT)
+ },
+ tags: Settings.get(SETTING_TAXONOMY_TAGS, true) || [],
+ categories: Settings.get(SETTING_TAXONOMY_CATEGORIES, true) || [],
+ freeform: Settings.get(SETTING_PANEL_FREEFORM),
+ scripts: Settings.get(SETTING_CUSTOM_SCRIPTS),
isInitialized: await Template.isInitialized(),
- modifiedDateUpdate: config.get(SETTING_AUTO_UPDATE_DATE) || false,
+ modifiedDateUpdate: Settings.get(SETTING_AUTO_UPDATE_DATE) || false,
writingSettingsEnabled: this.isWritingSettingsEnabled() || false,
- fmHighlighting: config.get(SETTINGS_CONTENT_FRONTMATTER_HIGHLIGHT),
+ fmHighlighting: Settings.get(SETTINGS_CONTENT_FRONTMATTER_HIGHLIGHT),
preview: Preview.getSettings(),
+ commaSeparatedFields: Settings.get(SETTING_COMMA_SEPARATED_FIELDS) || [],
+ contentTypes: Settings.get(SETTING_TAXONOMY_CONTENT_TYPES) || [],
+ dashboardViewData: Dashboard.viewData
} as PanelSettings
});
}
@@ -384,8 +462,7 @@ export class ExplorerView implements WebviewViewProvider, Disposable {
*/
private async addTags(tagType: TagType, value: string) {
if (value) {
- const config = SettingsHelper.getConfig();
- let options = tagType === TagType.tags ? config.get(SETTING_TAXONOMY_TAGS) : config.get(SETTING_TAXONOMY_CATEGORIES);
+ let options = tagType === TagType.tags ? Settings.get(SETTING_TAXONOMY_TAGS, true) : Settings.get(SETTING_TAXONOMY_CATEGORIES, true);
if (!options) {
options = [];
@@ -393,7 +470,7 @@ export class ExplorerView implements WebviewViewProvider, Disposable {
options.push(value);
const taxType = tagType === TagType.tags ? TaxonomyType.Tag : TaxonomyType.Category;
- await SettingsHelper.update(taxType, options);
+ await Settings.updateTaxonomy(taxType, options);
}
}
@@ -492,8 +569,7 @@ export class ExplorerView implements WebviewViewProvider, Disposable {
* Update the preview URL
*/
private async updatePreviewUrl(previewUrl: string) {
- const config = SettingsHelper.getConfig();
- await config.update(SETTING_PREVIEW_HOST, previewUrl);
+ await Settings.update(SETTING_PREVIEW_HOST, previewUrl);
this.getSettings();
}
@@ -501,8 +577,7 @@ export class ExplorerView implements WebviewViewProvider, Disposable {
* Toggle the Front Matter highlighting
*/
private async updateFmHighlight(autoUpdate: boolean) {
- const config = SettingsHelper.getConfig();
- await config.update(SETTINGS_CONTENT_FRONTMATTER_HIGHLIGHT, autoUpdate);
+ await Settings.update(SETTINGS_CONTENT_FRONTMATTER_HIGHLIGHT, autoUpdate);
this.getSettings();
}
@@ -510,8 +585,7 @@ export class ExplorerView implements WebviewViewProvider, Disposable {
* Toggle the modified auto-update setting
*/
private async updateModifiedUpdating(autoUpdate: boolean) {
- const config = SettingsHelper.getConfig();
- await config.update(SETTING_AUTO_UPDATE_DATE, autoUpdate);
+ await Settings.update(SETTING_AUTO_UPDATE_DATE, autoUpdate);
this.getSettings();
}
@@ -541,7 +615,7 @@ export class ExplorerView implements WebviewViewProvider, Disposable {
-
+
@@ -559,4 +633,4 @@ export class ExplorerView implements WebviewViewProvider, Disposable {
`;
}
-}
\ No newline at end of file
+}
diff --git a/src/extension.ts b/src/extension.ts
index 750118c2..a5bde400 100644
--- a/src/extension.ts
+++ b/src/extension.ts
@@ -5,14 +5,14 @@ import { Folders } from './commands/Folders';
import { Preview } from './commands/Preview';
import { Project } from './commands/Project';
import { Template } from './commands/Template';
-import { COMMAND_NAME, EXTENSION_BETA_ID, EXTENSION_ID } from './constants/Extension';
+import { COMMAND_NAME } from './constants/Extension';
import { TaxonomyType } from './models';
import { MarkdownFoldingProvider } from './providers/MarkdownFoldingProvider';
-import { TagType } from './viewpanel/TagType';
-import { ExplorerView } from './webview/ExplorerView';
+import { TagType } from './panelWebView/TagType';
+import { ExplorerView } from './explorerView/ExplorerView';
import { Extension } from './helpers/Extension';
-import { basename } from 'path';
-import { Notifications } from './helpers/Notifications';
+import { DashboardData } from './models/DashboardData';
+import { Settings as SettingsHelper } from './helpers';
let frontMatterStatusBar: vscode.StatusBarItem;
let statusDebouncer: { (fnc: any, time: number): void; };
@@ -29,15 +29,16 @@ export async function activate(context: vscode.ExtensionContext) {
if (!extension.checkIfExtensionCanRun()) {
return undefined;
}
-
- extension.migrateSettings()
+
+ SettingsHelper.init();
+ extension.migrateSettings();
collection = vscode.languages.createDiagnosticCollection('frontMatter');
// Pages dashboard
Dashboard.init();
- subscriptions.push(vscode.commands.registerCommand(COMMAND_NAME.dashboard, () => {
- Dashboard.open();
+ subscriptions.push(vscode.commands.registerCommand(COMMAND_NAME.dashboard, (data?: DashboardData) => {
+ Dashboard.open(data);
}));
if (!extension.getVersion().usedVersion) {
@@ -79,8 +80,6 @@ export async function activate(context: vscode.ExtensionContext) {
let remap = vscode.commands.registerCommand(COMMAND_NAME.remap, Settings.remap);
- let setDate = vscode.commands.registerCommand(COMMAND_NAME.setDate, Article.setDate);
-
let setLastModifiedDate = vscode.commands.registerCommand(COMMAND_NAME.setLastModifiedDate, Article.setLastModifiedDate);
let generateSlug = vscode.commands.registerCommand(COMMAND_NAME.generateSlug, Article.generateSlug);
@@ -117,17 +116,20 @@ export async function activate(context: vscode.ExtensionContext) {
}
});
+ // Settings promotion command
+ subscriptions.push(vscode.commands.registerCommand(COMMAND_NAME.promote, () => { console.log('promote'); SettingsHelper.promote(); }));
+
// Collapse all sections in the webview
const collapseAll = vscode.commands.registerCommand(COMMAND_NAME.collapseSections, () => {
ExplorerView.getInstance()?.collapseAll();
});
// Things to do when configuration changes
- vscode.workspace.onDidChangeConfiguration(() => {
+ SettingsHelper.onConfigChange((global?: any) => {
Template.init();
Preview.init();
- const exView = ExplorerView.getInstance();
+ const exView = ExplorerView.getInstance();
exView.getSettings();
exView.getFoldersAndFiles();
MarkdownFoldingProvider.triggerHighlighting();
@@ -162,6 +164,9 @@ export async function activate(context: vscode.ExtensionContext) {
Preview.init();
subscriptions.push(vscode.commands.registerCommand(COMMAND_NAME.preview, () => Preview.open(extensionPath) ));
+ // Inserting an image in Markdown
+ subscriptions.push(vscode.commands.registerCommand(COMMAND_NAME.insertImage, Article.insertImage));
+
// Subscribe all commands
subscriptions.push(
insertTags,
@@ -171,7 +176,6 @@ export async function activate(context: vscode.ExtensionContext) {
createCategory,
exportTaxonomy,
remap,
- setDate,
setLastModifiedDate,
generateSlug,
createFromTemplate,
diff --git a/src/helpers/ArticleHelper.ts b/src/helpers/ArticleHelper.ts
index 9e4408be..83a1fcde 100644
--- a/src/helpers/ArticleHelper.ts
+++ b/src/helpers/ArticleHelper.ts
@@ -1,11 +1,15 @@
+import { DEFAULT_CONTENT_TYPE, DEFAULT_CONTENT_TYPE_NAME } from './../constants/ContentType';
+import { ContentType } from './../models/PanelSettings';
import * as vscode from 'vscode';
import * as matter from "gray-matter";
import * as fs from "fs";
-import { CONFIG_KEY, SETTING_DATE_FIELD, SETTING_DATE_FORMAT, SETTING_INDENT_ARRAY, SETTING_REMOVE_QUOTES } from '../constants';
+import { DefaultFields, SETTING_COMMA_SEPARATED_FIELDS, SETTING_DATE_FIELD, SETTING_DATE_FORMAT, SETTING_INDENT_ARRAY, SETTING_REMOVE_QUOTES, SETTING_TAXONOMY_CONTENT_TYPES } from '../constants';
import { DumpOptions } from 'js-yaml';
import { TomlEngine, getFmLanguage, getFormatOpts } from './TomlEngine';
-import { SettingsHelper } from '.';
+import { Settings } from '.';
import { parse } from 'date-fns';
+import { Notifications } from './Notifications';
+import { Article } from '../commands';
export class ArticleHelper {
@@ -14,18 +18,9 @@ export class ArticleHelper {
*
* @param editor
*/
- public static getFrontMatter(editor: vscode.TextEditor) {
- const language: string = getFmLanguage();
- const langOpts = getFormatOpts(language);
- let article: matter.GrayMatterFile | null = matter(editor.document.getText(), {
- ...TomlEngine,
- ...langOpts
- });
-
- if (article && article.data) {
- return article;
- }
- return null;
+ public static getFrontMatter(editor: vscode.TextEditor) {
+ const fileContents = editor.document.getText();
+ return ArticleHelper.parseFile(fileContents);
}
/**
@@ -34,19 +29,7 @@ export class ArticleHelper {
*/
public static getFrontMatterByPath(filePath: string) {
const file = fs.readFileSync(filePath, { encoding: "utf-8" });
- if (file) {
- const language: string = getFmLanguage();
- const langOpts = getFormatOpts(language);
- let article: matter.GrayMatterFile | null = matter(file, {
- ...TomlEngine,
- ...langOpts
- });
-
- if (article && article.data) {
- return article;
- }
- }
- return null;
+ return ArticleHelper.parseFile(file);
}
/**
@@ -56,17 +39,23 @@ export class ArticleHelper {
* @param article
*/
public static async update(editor: vscode.TextEditor, article: matter.GrayMatterFile) {
- const config = SettingsHelper.getConfig();
- const removeQuotes = config.get(SETTING_REMOVE_QUOTES) as string[];
+ const removeQuotes = Settings.get(SETTING_REMOVE_QUOTES) as string[];
+ const commaSeparated = Settings.get(SETTING_COMMA_SEPARATED_FIELDS);
- let newMarkdown = this.stringifyFrontMatter(article.content, article.data);
+ let newMarkdown = this.stringifyFrontMatter(article.content, Object.assign({}, article.data));
// Check for field where quotes need to be removed
if (removeQuotes && removeQuotes.length) {
for (const toRemove of removeQuotes) {
if (article && article.data && article.data[toRemove]) {
- newMarkdown = newMarkdown.replace(`'${article.data[toRemove]}'`, article.data[toRemove]);
- newMarkdown = newMarkdown.replace(`"${article.data[toRemove]}"`, article.data[toRemove]);
+ if (commaSeparated?.includes(toRemove)) {
+ const textToReplace = article.data[toRemove].join(", ");
+ newMarkdown = newMarkdown.replace(`'${textToReplace}'`, textToReplace);
+ newMarkdown = newMarkdown.replace(`"${textToReplace}"`, textToReplace);
+ } else {
+ newMarkdown = newMarkdown.replace(`'${article.data[toRemove]}'`, article.data[toRemove]);
+ newMarkdown = newMarkdown.replace(`"${article.data[toRemove]}"`, article.data[toRemove]);
+ }
}
}
}
@@ -82,14 +71,22 @@ export class ArticleHelper {
* @param data
*/
public static stringifyFrontMatter(content: string, data: any) {
- const config = SettingsHelper.getConfig();
- const indentArray = config.get(SETTING_INDENT_ARRAY) as boolean;
+ const indentArray = Settings.get(SETTING_INDENT_ARRAY) as boolean;
+ const commaSeparated = Settings.get(SETTING_COMMA_SEPARATED_FIELDS);
const language = getFmLanguage();
const langOpts = getFormatOpts(language);
const spaces = vscode.window.activeTextEditor?.options?.tabSize;
+ if (commaSeparated) {
+ for (const key of commaSeparated) {
+ if (data[key] && typeof data[key] === "object") {
+ data[key] = data[key].join(", ");
+ }
+ }
+ }
+
return matter.stringify(content, data, ({
...TomlEngine,
...langOpts,
@@ -115,9 +112,8 @@ export class ArticleHelper {
return;
}
- const config = SettingsHelper.getConfig();
- const dateFormat = config.get(SETTING_DATE_FORMAT) as string;
- const dateField = config.get(SETTING_DATE_FIELD) as string || "date";
+ const dateFormat = Settings.get(SETTING_DATE_FORMAT) as string;
+ const dateField = Settings.get(SETTING_DATE_FIELD) as string || DefaultFields.PublishingDate;
if (typeof article.data[dateField] !== "undefined") {
if (dateFormat && typeof dateFormat === "string") {
@@ -130,4 +126,74 @@ export class ArticleHelper {
}
return;
}
+
+ /**
+ * Retrieve the content type of the current file
+ * @param updatedMetadata
+ */
+ public static getContentType(metadata: { [field: string]: string; }): ContentType {
+ const contentTypes = Settings.get(SETTING_TAXONOMY_CONTENT_TYPES);
+
+ if (!contentTypes || !metadata) {
+ return DEFAULT_CONTENT_TYPE;
+ }
+
+ let contentType = contentTypes.find(ct => ct.name === (metadata.type || DEFAULT_CONTENT_TYPE_NAME));
+ if (!contentType) {
+ contentType = contentTypes.find(ct => ct.name === DEFAULT_CONTENT_TYPE_NAME);
+ }
+ return contentType || DEFAULT_CONTENT_TYPE;
+ }
+
+ /**
+ * Update all dates in the metadata
+ * @param metadata
+ */
+ public static updateDates(metadata: { [field: string]: string; }) {
+ const contentType = ArticleHelper.getContentType(metadata);
+ const dateFields = contentType.fields.filter((field) => field.type === "datetime");
+
+ for (const dateField of dateFields) {
+ if (typeof metadata[dateField.name] !== "undefined") {
+ metadata[dateField.name] = Article.formatDate(new Date());
+ }
+ }
+
+ return metadata;
+ }
+
+ /**
+ * Parse a markdown file and its front matter
+ * @param fileContents
+ * @returns
+ */
+ private static parseFile(fileContents: string): matter.GrayMatterFile | null {
+ try {
+ const commaSeparated = Settings.get(SETTING_COMMA_SEPARATED_FIELDS);
+
+ if (fileContents) {
+ const language: string = getFmLanguage();
+ const langOpts = getFormatOpts(language);
+ let article: matter.GrayMatterFile | null = matter(fileContents, {
+ ...TomlEngine,
+ ...langOpts
+ });
+
+ if (article?.data) {
+ if (commaSeparated) {
+ for (const key of commaSeparated) {
+ if (article?.data[key] && typeof article.data[key] === "string") {
+ article.data[key] = article.data[key].split(",").map((s: string) => s.trim());
+ }
+ }
+ }
+
+ return article;
+ }
+ }
+ } catch (error: any) {
+ Notifications.error(`There seems to be an issue parsing your Front Matter. ERROR: ${error.message || error}`);
+ }
+ return null;
+ }
}
\ No newline at end of file
diff --git a/src/helpers/Extension.ts b/src/helpers/Extension.ts
index 2236dad1..2f5f0e93 100644
--- a/src/helpers/Extension.ts
+++ b/src/helpers/Extension.ts
@@ -1,10 +1,12 @@
import { basename } from "path";
import { extensions, Uri, ExtensionContext } from "vscode";
import { Folders, WORKSPACE_PLACEHOLDER } from "../commands/Folders";
-import { SETTINGS_CONTENT_FOLDERS, SETTINGS_CONTENT_PAGE_FOLDERS } from "../constants";
+import { SETTINGS_CONTENT_FOLDERS, SETTINGS_CONTENT_PAGE_FOLDERS, SETTING_DATE_FIELD, SETTING_MODIFIED_FIELD, SETTING_SEO_DESCRIPTION_FIELD, SETTING_TAXONOMY_CONTENT_TYPES } from "../constants";
+import { DEFAULT_CONTENT_TYPE_NAME } from "../constants/ContentType";
import { EXTENSION_BETA_ID, EXTENSION_ID, EXTENSION_STATE_VERSION } from "../constants/Extension";
+import { ContentType } from "../models";
import { Notifications } from "./Notifications";
-import { SettingsHelper } from "./SettingsHelper";
+import { Settings } from "./SettingsHelper";
export class Extension {
@@ -36,9 +38,10 @@ export class Extension {
installedVersion = `${installedVersion}-beta`;
}
- if (!usedVersion) {
+ if (usedVersion !== installedVersion) {
+ Notifications.info(`Find out what is new at [v${installedVersion} release notes](https://${this.isBetaVersion() ? 'beta.' : ''}frontmatter.codes/updates)`);
this.setVersion(installedVersion);
- };
+ }
return {
usedVersion,
@@ -64,8 +67,8 @@ export class Extension {
* Migrate old settings to new settings
*/
public async migrateSettings(): Promise {
- const config = SettingsHelper.getConfig();
- const folders = config.get(SETTINGS_CONTENT_FOLDERS);
+ // Migration to version 3.1.0
+ const folders = Settings.get(SETTINGS_CONTENT_FOLDERS);
if (folders && folders.length > 0) {
const workspace = Folders.getWorkspaceFolder();
const projectFolder = basename(workspace?.fsPath || "");
@@ -75,7 +78,56 @@ export class Extension {
path: `${WORKSPACE_PLACEHOLDER}${folder.fsPath.split(projectFolder).slice(1).join('')}`.split('\\').join('/')
}));
- await config.update(`${SETTINGS_CONTENT_PAGE_FOLDERS}`, paths);
+ await Settings.update(SETTINGS_CONTENT_PAGE_FOLDERS, paths);
+ }
+
+ // Create team settings
+ if (Settings.hasSettings()) {
+ Settings.createTeamSettings();
+ }
+
+ // Migration to version 4.0.0
+ const dateField = Settings.get(SETTING_DATE_FIELD);
+ const lastModField = Settings.get(SETTING_MODIFIED_FIELD);
+ const description = Settings.get(SETTING_SEO_DESCRIPTION_FIELD);
+ const contentTypes = Settings.get(SETTING_TAXONOMY_CONTENT_TYPES);
+
+ if (contentTypes) {
+ let needsUpdate = false;
+ let defaultContentType = contentTypes.find(ct => ct.name === DEFAULT_CONTENT_TYPE_NAME);
+
+ if (defaultContentType) {
+ if (dateField && dateField !== "date") {
+ defaultContentType.fields = defaultContentType.fields.filter(f => f.name !== "date");
+ defaultContentType.fields.push({
+ name: dateField,
+ type: "datetime"
+ });
+ needsUpdate = true;
+ }
+
+ if (lastModField && lastModField !== "lastmod") {
+ defaultContentType.fields = defaultContentType.fields.filter(f => f.name !== "lastmod");
+ defaultContentType.fields.push({
+ name: lastModField,
+ type: "datetime"
+ });
+ needsUpdate = true;
+ }
+
+ if (description && description !== "description") {
+ defaultContentType.fields = defaultContentType.fields.filter(f => f.name !== "lastmod");
+ defaultContentType.fields.push({
+ name: description,
+ type: "string"
+ });
+ needsUpdate = true;
+ }
+
+ if (needsUpdate) {
+ await Settings.update(SETTING_TAXONOMY_CONTENT_TYPES, contentTypes);
+ }
+ }
}
}
@@ -103,4 +155,9 @@ export class Extension {
return true;
}
+
+ public get packageJson() {
+ const frontMatter = extensions.getExtension(this.isBetaVersion() ? EXTENSION_BETA_ID : EXTENSION_ID)!;
+ return frontMatter.packageJSON;
+ }
}
\ No newline at end of file
diff --git a/src/helpers/MessageHelper.ts b/src/helpers/MessageHelper.ts
index d95e8936..64597d19 100644
--- a/src/helpers/MessageHelper.ts
+++ b/src/helpers/MessageHelper.ts
@@ -1,5 +1,5 @@
-import { DashboardMessage } from './../pagesView/DashboardMessage';
-import { CommandToCode } from "../viewpanel/CommandToCode";
+import { DashboardMessage } from '../dashboardWebView/DashboardMessage';
+import { CommandToCode } from "../panelWebView/CommandToCode";
interface ClientVsCode {
diff --git a/src/helpers/SettingsHelper.ts b/src/helpers/SettingsHelper.ts
index 20dee8fb..2c328535 100644
--- a/src/helpers/SettingsHelper.ts
+++ b/src/helpers/SettingsHelper.ts
@@ -1,16 +1,137 @@
+import { Notifications } from './Notifications';
+import { workspace } from 'vscode';
import * as vscode from 'vscode';
import { TaxonomyType } from '../models';
import { SETTING_TAXONOMY_TAGS, SETTING_TAXONOMY_CATEGORIES, CONFIG_KEY } from '../constants';
+import { Folders } from '../commands/Folders';
+import { join, basename } from 'path';
+import { existsSync, readFileSync, writeFileSync } from 'fs';
+import { Extension } from './Extension';
-export class SettingsHelper {
+export class Settings {
+ private static config: vscode.WorkspaceConfiguration;
+ private static globalFile = "frontmatter.json";
+ private static globalConfig: any;
+
+ public static init() {
+ const fmConfig = Settings.projectConfigPath;
+ if (fmConfig && existsSync(fmConfig)) {
+ const localConfig = readFileSync(fmConfig, 'utf8');
+ Settings.globalConfig = JSON.parse(localConfig);
+ } else {
+ Settings.globalConfig = undefined;
+ }
- public static getConfig(): vscode.WorkspaceConfiguration {
- return vscode.workspace.getConfiguration(CONFIG_KEY);
+ Settings.config = vscode.workspace.getConfiguration(CONFIG_KEY);
+
+ Settings.onConfigChange((global?: any) => {
+ if (global) {
+ Settings.globalConfig = Object.assign({}, global);
+ } else {
+ Settings.config = vscode.workspace.getConfiguration(CONFIG_KEY);
+ }
+ });
}
- public static async updateSetting(name: string, value: any) {
- const config = vscode.workspace.getConfiguration(CONFIG_KEY);
- await config.update(name, value);
+ /**
+ * Check for config changes on global and local settings
+ * @param callback
+ */
+ public static onConfigChange(callback: (global?: any) => void) {
+ workspace.onDidChangeConfiguration(() => {
+ callback();
+ });
+
+ workspace.onDidSaveTextDocument(async (e) => {
+ const filename = e.uri.fsPath;
+ if (Settings.checkProjectConfig(filename)) {
+ const file = await workspace.openTextDocument(e.uri);
+ if (file) {
+ const fileContents = file.getText();
+ const json = JSON.parse(fileContents);
+ callback(json);
+ }
+ }
+ });
+
+ workspace.onDidDeleteFiles((e) => {
+ const needCallback = e?.files.find(f => Settings.checkProjectConfig(f.fsPath));
+ if (needCallback) {
+ callback();
+ }
+ });
+ }
+
+ /**
+ * Retrieve a setting from global and local config
+ */
+ public static get(name: string, merging: boolean = false): T | undefined{
+ const configInpection = Settings.config.inspect(name);
+
+ let setting = undefined;
+ const settingKey = `${CONFIG_KEY}.${name}`;
+
+ if (Settings.globalConfig && typeof Settings.globalConfig[settingKey] !== "undefined") {
+ setting = Settings.globalConfig[settingKey];
+ }
+
+ // Local overrides global
+ if (configInpection && typeof configInpection.workspaceValue !== "undefined") {
+ if (merging && setting && typeof setting === "object") {
+ setting = Object.assign([], setting, configInpection.workspaceValue);
+ } else {
+ setting = configInpection.workspaceValue;
+ }
+ }
+
+ if (setting === undefined) {
+ setting = Settings.config.get(name);
+ }
+
+ return setting;
+ }
+
+ /**
+ * String update config setting
+ * @param name
+ * @param value
+ */
+ public static async update(name: string, value: T, updateGlobal: boolean = false) {
+ const fmConfig = Settings.projectConfigPath;
+
+ if (updateGlobal) {
+ if (fmConfig && existsSync(fmConfig)) {
+ const localConfig = readFileSync(fmConfig, 'utf8');
+ Settings.globalConfig = JSON.parse(localConfig);
+ Settings.globalConfig[`${CONFIG_KEY}.${name}`] = value;
+ writeFileSync(fmConfig, JSON.stringify(Settings.globalConfig, null, 2), 'utf8');
+ return;
+ }
+ } else {
+ await Settings.config.update(name, value);
+ return;
+ }
+
+ // Fallback to the local settings
+ await Settings.config.update(name, value);
+ }
+
+ /**
+ * Create team settings
+ */
+ public static createTeamSettings() {
+ const wsFolder = Folders.getWorkspaceFolder();
+
+ const initialConfig = {
+ "$schema": `https://${Extension.getInstance().isBetaVersion() ? `beta.` : ``}frontmatter.codes/frontmatter.schema.json`
+ };
+
+ if (wsFolder) {
+ const configPath = join(wsFolder.fsPath, Settings.globalFile);
+ if (!existsSync(configPath)) {
+ writeFileSync(configPath, JSON.stringify(initialConfig, null, 2), 'utf8');
+ }
+ }
}
/**
@@ -19,10 +140,9 @@ export class SettingsHelper {
* @param type
*/
public static getTaxonomy(type: TaxonomyType): string[] {
- const config = vscode.workspace.getConfiguration(CONFIG_KEY);
// Add all the known options to the selection list
const configSetting = type === TaxonomyType.Tag ? SETTING_TAXONOMY_TAGS : SETTING_TAXONOMY_CATEGORIES;
- const crntOptions = config.get(configSetting) as string[];
+ const crntOptions = Settings.get(configSetting, true) as string[];
if (crntOptions && crntOptions.length > 0) {
return crntOptions;
}
@@ -36,11 +156,86 @@ export class SettingsHelper {
* @param type
* @param options
*/
- static async update(type: TaxonomyType, options: string[]) {
- const config = vscode.workspace.getConfiguration(CONFIG_KEY);
+ public static async updateTaxonomy(type: TaxonomyType, options: string[]) {
const configSetting = type === TaxonomyType.Tag ? SETTING_TAXONOMY_TAGS : SETTING_TAXONOMY_CATEGORIES;
options = [...new Set(options)];
options = options.sort().filter(o => !!o);
- await config.update(configSetting, options);
+ await Settings.update(configSetting, options, true);
+ }
+
+ /**
+ * Promote settings from local to team level
+ */
+ public static async promote() {
+ const pkg = Extension.getInstance().packageJson;
+ if (pkg?.contributes?.configuration?.properties) {
+ const settingNames = Object.keys(pkg.contributes.configuration.properties);
+
+ for (const name of settingNames) {
+ const settingName = name.replace(`${CONFIG_KEY}.`, '');
+ const setting = Settings.config.inspect(settingName);
+
+ if (setting && typeof setting.workspaceValue !== "undefined") {
+ await Settings.update(settingName, setting.workspaceValue, true);
+ await Settings.update(settingName, undefined);
+ }
+ }
+ }
+
+ Notifications.info(`All settings promoted to team level.`);
+ }
+
+ /**
+ * Check if there are any Front Matter settings in the workspace
+ * @returns
+ */
+ public static hasSettings() {
+ let hasSetting = false;
+
+ const pkg = Extension.getInstance().packageJson;
+ if (pkg?.contributes?.configuration?.properties) {
+ const settingNames = Object.keys(pkg.contributes.configuration.properties);
+
+ for (const name of settingNames) {
+ const settingName = name.replace(`${CONFIG_KEY}.`, '');
+ const setting = Settings.config.inspect(settingName);
+
+ if (setting && typeof setting.workspaceValue !== "undefined") {
+ hasSetting = true;
+ }
+ }
+ }
+
+ return hasSetting;
+ }
+
+
+ /**
+ * Check if its the project config
+ * @param filePath
+ * @returns
+ */
+ private static checkProjectConfig(filePath: string) {
+ const fmConfig = Settings.projectConfigPath;
+ if (fmConfig && existsSync(fmConfig)) {
+ return filePath &&
+ basename(filePath).toLowerCase() === Settings.globalFile.toLowerCase() &&
+ fmConfig.toLowerCase() === filePath.toLowerCase();
+ }
+
+ return false;
+ }
+
+ /**
+ * Get the project config path
+ * @returns
+ */
+ private static get projectConfigPath() {
+ const wsFolder = Folders.getWorkspaceFolder();
+ if (wsFolder) {
+ const fmConfig = join(wsFolder.fsPath, Settings.globalFile);
+ return fmConfig;
+ }
+ return undefined;
}
}
\ No newline at end of file
diff --git a/src/helpers/TomlEngine.ts b/src/helpers/TomlEngine.ts
index f0bcc240..99839e6d 100644
--- a/src/helpers/TomlEngine.ts
+++ b/src/helpers/TomlEngine.ts
@@ -1,11 +1,9 @@
-import * as vscode from 'vscode';
import * as toml from '@iarna/toml';
import { SETTING_FRONTMATTER_TYPE } from '../constants';
-import { SettingsHelper } from '.';
+import { Settings } from './SettingsHelper';
export const getFmLanguage = (): string => {
- const config = SettingsHelper.getConfig();
- const language = config.get(SETTING_FRONTMATTER_TYPE) as string || "YAML";
+ const language = Settings.get(SETTING_FRONTMATTER_TYPE) as string || "YAML";
return language.toLowerCase();
};
diff --git a/src/models/DashboardData.ts b/src/models/DashboardData.ts
new file mode 100644
index 00000000..27318fea
--- /dev/null
+++ b/src/models/DashboardData.ts
@@ -0,0 +1,4 @@
+export interface DashboardData {
+ type: "contents" | "media";
+ data?: any;
+}
\ No newline at end of file
diff --git a/src/models/PanelSettings.ts b/src/models/PanelSettings.ts
index b40da5e4..51043dfb 100644
--- a/src/models/PanelSettings.ts
+++ b/src/models/PanelSettings.ts
@@ -1,9 +1,11 @@
import { FileType } from "vscode";
+import { DashboardData } from "./DashboardData";
export interface PanelSettings {
seo: SEO;
slug: Slug;
tags: string[];
+ date: DateInfo;
categories: string[];
freeform: boolean;
scripts: CustomScript[];
@@ -12,6 +14,24 @@ export interface PanelSettings {
writingSettingsEnabled: boolean;
fmHighlighting: boolean;
preview: PreviewSettings;
+ contentTypes: ContentType[];
+ dashboardViewData: DashboardData | undefined;
+}
+
+export interface ContentType {
+ name: string;
+ fields: Field[];
+}
+
+export interface Field {
+ title?: string;
+ name: string;
+ type: "string" | "number" | "datetime" | "boolean" | "image" | "choice" | "tags" | "categories";
+ choices?: string[];
+}
+
+export interface DateInfo {
+ format: string;
}
export interface SEO {
diff --git a/src/viewpanel/Command.ts b/src/panelWebView/Command.ts
similarity index 83%
rename from src/viewpanel/Command.ts
rename to src/panelWebView/Command.ts
index 7e4145c1..7236f776 100644
--- a/src/viewpanel/Command.ts
+++ b/src/panelWebView/Command.ts
@@ -6,4 +6,5 @@ export enum Command {
focusOnCategories = "focusOnCategories",
closeSections = "closeSections",
folderInfo = "folderInfo",
+ mediaSelectionData = "mediaSelectionData"
}
\ No newline at end of file
diff --git a/src/viewpanel/CommandToCode.ts b/src/panelWebView/CommandToCode.ts
similarity index 96%
rename from src/viewpanel/CommandToCode.ts
rename to src/panelWebView/CommandToCode.ts
index 80fbcb3a..46fb32f1 100644
--- a/src/viewpanel/CommandToCode.ts
+++ b/src/panelWebView/CommandToCode.ts
@@ -25,4 +25,5 @@ export enum CommandToCode {
openInEditor = "open-in-editor",
updateMetadata = "update-metadata",
openDashboard = "open-dashboard",
+ selectImage = "select-image",
}
\ No newline at end of file
diff --git a/src/viewpanel/TagType.ts b/src/panelWebView/TagType.ts
similarity index 100%
rename from src/viewpanel/TagType.ts
rename to src/panelWebView/TagType.ts
diff --git a/src/viewpanel/ViewPanel.tsx b/src/panelWebView/ViewPanel.tsx
similarity index 80%
rename from src/viewpanel/ViewPanel.tsx
rename to src/panelWebView/ViewPanel.tsx
index 17744abb..fdcab7da 100644
--- a/src/viewpanel/ViewPanel.tsx
+++ b/src/panelWebView/ViewPanel.tsx
@@ -14,7 +14,15 @@ export interface IViewPanelProps {
}
export const ViewPanel: React.FunctionComponent = (props: React.PropsWithChildren) => {
- const { loading, metadata, settings, folderAndFiles, focusElm, unsetFocus } = useMessages();
+ const { loading, mediaSelecting, metadata, settings, folderAndFiles, focusElm, unsetFocus } = useMessages();
+
+ if (mediaSelecting) {
+ return (
+
+
Continue in the media dashboard to select the image you want to insert.
+
+ );
+ }
if (loading) {
return (
@@ -22,7 +30,7 @@ export const ViewPanel: React.FunctionComponent = (props: React
);
}
- if (!metadata || Object.keys(metadata).length === 0) {
+ if (!metadata || Object.keys(metadata || {}).length === 0) {
return (
);
diff --git a/src/viewpanel/components/ActionButton.tsx b/src/panelWebView/components/ActionButton.tsx
similarity index 100%
rename from src/viewpanel/components/ActionButton.tsx
rename to src/panelWebView/components/ActionButton.tsx
diff --git a/src/viewpanel/components/Actions.tsx b/src/panelWebView/components/Actions.tsx
similarity index 84%
rename from src/viewpanel/components/Actions.tsx
rename to src/panelWebView/components/Actions.tsx
index 07e86888..1d0d511e 100644
--- a/src/viewpanel/components/Actions.tsx
+++ b/src/panelWebView/components/Actions.tsx
@@ -2,9 +2,7 @@ import * as React from 'react';
import { PanelSettings } from '../../models/PanelSettings';
import { Collapsible } from './Collapsible';
import { CustomScript } from './CustomScript';
-import { DateAction } from './DateAction';
import { Preview } from './Preview';
-import { PublishAction } from './PublishAction';
import { SlugAction } from './SlugAction';
export interface IActionsProps {
@@ -27,10 +25,6 @@ export const Actions: React.FunctionComponent = (props: React.Pro
{ settings?.preview?.host && }
-
-
- { metadata && typeof metadata.draft !== undefined && }
-
{
(settings && settings.scripts && settings.scripts.length > 0) && (
settings.scripts.map((value) => (
diff --git a/src/viewpanel/components/ArticleDetails.tsx b/src/panelWebView/components/ArticleDetails.tsx
similarity index 100%
rename from src/viewpanel/components/ArticleDetails.tsx
rename to src/panelWebView/components/ArticleDetails.tsx
diff --git a/src/viewpanel/components/BaseView.tsx b/src/panelWebView/components/BaseView.tsx
similarity index 99%
rename from src/viewpanel/components/BaseView.tsx
rename to src/panelWebView/components/BaseView.tsx
index c1a2b73a..6371bfbf 100644
--- a/src/viewpanel/components/BaseView.tsx
+++ b/src/panelWebView/components/BaseView.tsx
@@ -29,7 +29,6 @@ export const BaseView: React.FunctionComponent = ({settings, fol
MessageHelper.sendMessage(CommandToCode.createContent);
};
-
return (
diff --git a/src/viewpanel/components/Collapsible.tsx b/src/panelWebView/components/Collapsible.tsx
similarity index 100%
rename from src/viewpanel/components/Collapsible.tsx
rename to src/panelWebView/components/Collapsible.tsx
diff --git a/src/viewpanel/components/CustomScript.tsx b/src/panelWebView/components/CustomScript.tsx
similarity index 100%
rename from src/viewpanel/components/CustomScript.tsx
rename to src/panelWebView/components/CustomScript.tsx
diff --git a/src/panelWebView/components/Fields/ChoiceField.tsx b/src/panelWebView/components/Fields/ChoiceField.tsx
new file mode 100644
index 00000000..85bd3a6e
--- /dev/null
+++ b/src/panelWebView/components/Fields/ChoiceField.tsx
@@ -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
= ({label, selected, choices, onChange}: React.PropsWithChildren) => {
+ const [ crntSelected, setCrntSelected ] = React.useState(selected);
+
+ const onValueChange = (txtValue: string) => {
+ setCrntSelected(txtValue);
+ onChange(txtValue);
+ };
+
+ const containsSelected = crntSelected && choices.indexOf(crntSelected) !== -1;
+
+ return (
+
+
+
+ {label}
+
+
+
+
onValueChange(e.currentTarget.value)}>
+ { !containsSelected && }
+ {choices.map((choice, index) => (
+ {choice}
+ ))}
+
+
+ );
+};
\ No newline at end of file
diff --git a/src/panelWebView/components/Fields/DateTimeField.tsx b/src/panelWebView/components/Fields/DateTimeField.tsx
new file mode 100644
index 00000000..b18b0c65
--- /dev/null
+++ b/src/panelWebView/components/Fields/DateTimeField.tsx
@@ -0,0 +1,62 @@
+import * as React from 'react';
+import { VsLabel } from '../VscodeComponents';
+import { ClockIcon } from '@heroicons/react/outline';
+import DatePicker from 'react-datepicker';
+import { forwardRef } from 'react';
+
+export interface IDateTimeFieldProps {
+ label: string;
+ date: Date | null;
+ format?: string;
+ onChange: (date: Date) => void;
+}
+
+type InputProps = JSX.IntrinsicElements["input"];
+
+const CustomInput = forwardRef(({ value, onClick }, ref) => {
+ return (
+
+ {value || "Pick your date"}
+
+ )
+});
+
+export const DateTimeField: React.FunctionComponent = ({label, date, format, onChange}: React.PropsWithChildren) => {
+ const [ dateValue, setDateValue ] = React.useState(date);
+
+ const onDateChange = (date: Date) => {
+ setDateValue(date);
+ onChange(date);
+ };
+
+ React.useEffect(() => {
+ if (dateValue?.toISOString() !== date?.toISOString()) {
+ setDateValue(date);
+ }
+ }, [ date ]);
+
+ return (
+
+
+
+ {label}
+
+
+
+
+ )}
+ showTimeInput
+ />
+
+ onDateChange(new Date())}>
+ now
+
+
+
+ );
+};
\ No newline at end of file
diff --git a/src/panelWebView/components/Fields/NumberField.tsx b/src/panelWebView/components/Fields/NumberField.tsx
new file mode 100644
index 00000000..5f140501
--- /dev/null
+++ b/src/panelWebView/components/Fields/NumberField.tsx
@@ -0,0 +1,35 @@
+import { CalculatorIcon } from '@heroicons/react/outline';
+import * as React from 'react';
+import { VsLabel } from '../VscodeComponents';
+
+export interface INumberFieldProps {
+ label: string;
+ value: number | null;
+ onChange: (nrValue: number | null) => void;
+}
+
+export const NumberField: React.FunctionComponent = ({label, value, onChange}: React.PropsWithChildren) => {
+ const [ nrValue, setNrValue ] = React.useState(value);
+
+ const onValueChange = (txtValue: string) => {
+ let newValue: number | null = parseInt(txtValue);
+ if (isNaN(newValue)) {
+ newValue = null;
+ }
+
+ setNrValue(newValue);
+ onChange(newValue);
+ };
+
+ return (
+
+
+
+ {label}
+
+
+
+
onValueChange(e.target.value)} />
+
+ );
+};
\ No newline at end of file
diff --git a/src/panelWebView/components/Fields/PreviewImageField.tsx b/src/panelWebView/components/Fields/PreviewImageField.tsx
new file mode 100644
index 00000000..b70f472f
--- /dev/null
+++ b/src/panelWebView/components/Fields/PreviewImageField.tsx
@@ -0,0 +1,47 @@
+import { PhotographIcon } from '@heroicons/react/outline';
+import * as React from 'react';
+import { MessageHelper } from '../../../helpers/MessageHelper';
+import { CommandToCode } from '../../CommandToCode';
+import { VsLabel } from '../VscodeComponents';
+
+export interface IPreviewImageFieldProps {
+ label: string;
+ fieldName: string;
+ value: string | null;
+ filePath: string | null;
+ onChange: (value: string | null) => void;
+}
+
+export const PreviewImageField: React.FunctionComponent = ({label, fieldName, onChange, value, filePath}: React.PropsWithChildren) => {
+
+ const selectImage = () => {
+ MessageHelper.sendMessage(CommandToCode.selectImage, {
+ filePath,
+ fieldName
+ });
+ };
+
+ return (
+
+
+
+
+
+
+ {
+ value ? (
+
+
+
+
onChange(null)} className={`metadata_field__preview_image__remove`}>Remove image
+
+ ) : (
+
Select image
+ )
+ }
+
+
+ );
+};
\ No newline at end of file
diff --git a/src/panelWebView/components/Fields/TextField.tsx b/src/panelWebView/components/Fields/TextField.tsx
new file mode 100644
index 00000000..8339e301
--- /dev/null
+++ b/src/panelWebView/components/Fields/TextField.tsx
@@ -0,0 +1,57 @@
+import { PencilIcon } from '@heroicons/react/outline';
+import * as React from 'react';
+import { VsLabel } from '../VscodeComponents';
+
+export interface ITextFieldProps {
+ label: string;
+ value: string | null;
+ limit: number | undefined;
+ rows?: number;
+ onChange: (txtValue: string) => void;
+}
+
+export const TextField: React.FunctionComponent = ({limit, label, value, rows, onChange}: React.PropsWithChildren) => {
+ const [ text, setText ] = React.useState(value);
+
+ const onTextChange = (txtValue: string) => {
+ setText(txtValue);
+ onChange(txtValue);
+ };
+
+ React.useEffect(() => {
+ if (text !== value) {
+ setText(value);
+ }
+ }, [ value ]);
+
+ let isValid = true;
+ if (limit && limit !== -1) {
+ isValid = ((text || "").length < limit);
+ }
+
+ return (
+
+ );
+};
\ No newline at end of file
diff --git a/src/panelWebView/components/Fields/Toggle.tsx b/src/panelWebView/components/Fields/Toggle.tsx
new file mode 100644
index 00000000..c572f27a
--- /dev/null
+++ b/src/panelWebView/components/Fields/Toggle.tsx
@@ -0,0 +1,40 @@
+import * as React from 'react';
+import { RocketIcon } from '../Icons/RocketIcon';
+import { VsLabel } from '../VscodeComponents';
+
+export interface IToggleProps {
+ label: string;
+ checked: boolean;
+ onChanged: (checked: boolean) => void;
+}
+
+export const Toggle: React.FunctionComponent = ({label, 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 (
+
+
+
+ {label}
+
+
+
+
+
+
+
+
+
+ );
+};
\ No newline at end of file
diff --git a/src/viewpanel/components/FileList.tsx b/src/panelWebView/components/FileList.tsx
similarity index 100%
rename from src/viewpanel/components/FileList.tsx
rename to src/panelWebView/components/FileList.tsx
diff --git a/src/viewpanel/components/FolderAndFiles.tsx b/src/panelWebView/components/FolderAndFiles.tsx
similarity index 100%
rename from src/viewpanel/components/FolderAndFiles.tsx
rename to src/panelWebView/components/FolderAndFiles.tsx
diff --git a/src/viewpanel/components/GlobalSettings.tsx b/src/panelWebView/components/GlobalSettings.tsx
similarity index 100%
rename from src/viewpanel/components/GlobalSettings.tsx
rename to src/panelWebView/components/GlobalSettings.tsx
diff --git a/src/viewpanel/components/Icon.tsx b/src/panelWebView/components/Icon.tsx
similarity index 100%
rename from src/viewpanel/components/Icon.tsx
rename to src/panelWebView/components/Icon.tsx
diff --git a/src/viewpanel/components/Icons/AddIcon.tsx b/src/panelWebView/components/Icons/AddIcon.tsx
similarity index 100%
rename from src/viewpanel/components/Icons/AddIcon.tsx
rename to src/panelWebView/components/Icons/AddIcon.tsx
diff --git a/src/viewpanel/components/Icons/ArchiveIcon.tsx b/src/panelWebView/components/Icons/ArchiveIcon.tsx
similarity index 100%
rename from src/viewpanel/components/Icons/ArchiveIcon.tsx
rename to src/panelWebView/components/Icons/ArchiveIcon.tsx
diff --git a/src/viewpanel/components/Icons/BugIcon.tsx b/src/panelWebView/components/Icons/BugIcon.tsx
similarity index 100%
rename from src/viewpanel/components/Icons/BugIcon.tsx
rename to src/panelWebView/components/Icons/BugIcon.tsx
diff --git a/src/viewpanel/components/Icons/CenterIcon.tsx b/src/panelWebView/components/Icons/CenterIcon.tsx
similarity index 100%
rename from src/viewpanel/components/Icons/CenterIcon.tsx
rename to src/panelWebView/components/Icons/CenterIcon.tsx
diff --git a/src/viewpanel/components/Icons/CheckIcon.tsx b/src/panelWebView/components/Icons/CheckIcon.tsx
similarity index 100%
rename from src/viewpanel/components/Icons/CheckIcon.tsx
rename to src/panelWebView/components/Icons/CheckIcon.tsx
diff --git a/src/viewpanel/components/Icons/FileIcon.tsx b/src/panelWebView/components/Icons/FileIcon.tsx
similarity index 100%
rename from src/viewpanel/components/Icons/FileIcon.tsx
rename to src/panelWebView/components/Icons/FileIcon.tsx
diff --git a/src/viewpanel/components/Icons/FolderOpenedIcon.tsx b/src/panelWebView/components/Icons/FolderOpenedIcon.tsx
similarity index 100%
rename from src/viewpanel/components/Icons/FolderOpenedIcon.tsx
rename to src/panelWebView/components/Icons/FolderOpenedIcon.tsx
diff --git a/src/viewpanel/components/Icons/FrontMatterIcon.tsx b/src/panelWebView/components/Icons/FrontMatterIcon.tsx
similarity index 100%
rename from src/viewpanel/components/Icons/FrontMatterIcon.tsx
rename to src/panelWebView/components/Icons/FrontMatterIcon.tsx
diff --git a/src/viewpanel/components/Icons/GitHubIcon.tsx b/src/panelWebView/components/Icons/GitHubIcon.tsx
similarity index 100%
rename from src/viewpanel/components/Icons/GitHubIcon.tsx
rename to src/panelWebView/components/Icons/GitHubIcon.tsx
diff --git a/src/viewpanel/components/Icons/HeartIcon.tsx b/src/panelWebView/components/Icons/HeartIcon.tsx
similarity index 100%
rename from src/viewpanel/components/Icons/HeartIcon.tsx
rename to src/panelWebView/components/Icons/HeartIcon.tsx
diff --git a/src/viewpanel/components/Icons/ListUnorderedIcon.tsx b/src/panelWebView/components/Icons/ListUnorderedIcon.tsx
similarity index 100%
rename from src/viewpanel/components/Icons/ListUnorderedIcon.tsx
rename to src/panelWebView/components/Icons/ListUnorderedIcon.tsx
diff --git a/src/viewpanel/components/Icons/MarkdownIcon.tsx b/src/panelWebView/components/Icons/MarkdownIcon.tsx
similarity index 100%
rename from src/viewpanel/components/Icons/MarkdownIcon.tsx
rename to src/panelWebView/components/Icons/MarkdownIcon.tsx
diff --git a/src/viewpanel/components/Icons/RocketIcon.tsx b/src/panelWebView/components/Icons/RocketIcon.tsx
similarity index 100%
rename from src/viewpanel/components/Icons/RocketIcon.tsx
rename to src/panelWebView/components/Icons/RocketIcon.tsx
diff --git a/src/viewpanel/components/Icons/SettingsIcon.tsx b/src/panelWebView/components/Icons/SettingsIcon.tsx
similarity index 100%
rename from src/viewpanel/components/Icons/SettingsIcon.tsx
rename to src/panelWebView/components/Icons/SettingsIcon.tsx
diff --git a/src/viewpanel/components/Icons/SymbolKeywordIcon.tsx b/src/panelWebView/components/Icons/SymbolKeywordIcon.tsx
similarity index 100%
rename from src/viewpanel/components/Icons/SymbolKeywordIcon.tsx
rename to src/panelWebView/components/Icons/SymbolKeywordIcon.tsx
diff --git a/src/viewpanel/components/Icons/TagIcon.tsx b/src/panelWebView/components/Icons/TagIcon.tsx
similarity index 100%
rename from src/viewpanel/components/Icons/TagIcon.tsx
rename to src/panelWebView/components/Icons/TagIcon.tsx
diff --git a/src/viewpanel/components/Icons/TemplateIcon.tsx b/src/panelWebView/components/Icons/TemplateIcon.tsx
similarity index 100%
rename from src/viewpanel/components/Icons/TemplateIcon.tsx
rename to src/panelWebView/components/Icons/TemplateIcon.tsx
diff --git a/src/viewpanel/components/Icons/WarningIcon.tsx b/src/panelWebView/components/Icons/WarningIcon.tsx
similarity index 100%
rename from src/viewpanel/components/Icons/WarningIcon.tsx
rename to src/panelWebView/components/Icons/WarningIcon.tsx
diff --git a/src/viewpanel/components/Icons/WritingIcon.tsx b/src/panelWebView/components/Icons/WritingIcon.tsx
similarity index 100%
rename from src/viewpanel/components/Icons/WritingIcon.tsx
rename to src/panelWebView/components/Icons/WritingIcon.tsx
diff --git a/src/panelWebView/components/Metadata.tsx b/src/panelWebView/components/Metadata.tsx
new file mode 100644
index 00000000..5bfdc4f7
--- /dev/null
+++ b/src/panelWebView/components/Metadata.tsx
@@ -0,0 +1,192 @@
+import * as React from 'react';
+import { Field, PanelSettings } from '../../models';
+import { CommandToCode } from '../CommandToCode';
+import { MessageHelper } from '../../helpers/MessageHelper';
+import { TagType } from '../TagType';
+import { Collapsible } from './Collapsible';
+import { Toggle } from './Fields/Toggle';
+import { SymbolKeywordIcon } from './Icons/SymbolKeywordIcon';
+import { TagIcon } from './Icons/TagIcon';
+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 };
+ focusElm: TagType | null;
+ unsetFocus: () => void;
+}
+
+export const Metadata: React.FunctionComponent = ({settings, metadata, focusElm, unsetFocus}: React.PropsWithChildren) => {
+
+ const sendUpdate = (field: string | undefined, value: any) => {
+ if (!field) {
+ return;
+ }
+
+ MessageHelper.sendMessage(CommandToCode.updateMetadata, {
+ field,
+ value
+ });
+ };
+
+ const getDate = (date: string | Date) => {
+ if (typeof date === 'string') {
+ return parseJSON(date);
+ }
+ return date;
+ }
+
+ if (!settings) {
+ return null;
+ }
+
+ const contentTypeName = metadata.type as string || DEFAULT_CONTENT_TYPE_NAME;
+ let contentType = settings.contentTypes.find(ct => ct.name === contentTypeName);
+
+ if (!contentType) {
+ contentType = settings.contentTypes.find(ct => ct.name === DEFAULT_CONTENT_TYPE_NAME);
+ }
+
+ if (!contentType || !contentType.fields) {
+ contentType = DEFAULT_CONTENT_TYPE;
+ }
+
+ const renderFields = (ctFields: Field[]) => {
+ if (!ctFields) {
+ return;
+ }
+
+ return ctFields.map(field => {
+ if (field.type === 'datetime') {
+ const dateValue = metadata[field.name] ? getDate(metadata[field.name] as string) : null;
+
+ return (
+ sendUpdate(field.name, date))} />
+ );
+ } else if (field.type === 'boolean') {
+ return (
+ sendUpdate(field.name, checked)} />
+ );
+ } else if (field.type === 'string') {
+ const textValue = metadata[field.name];
+
+ let limit = -1;
+ if (field.name === 'title') {
+ limit = settings?.seo.title;
+ } else if (field.name === settings.seo.descriptionField) {
+ limit = settings?.seo.description;
+ }
+
+ return (
+ sendUpdate(field.name, value)}
+ value={textValue as string || null} />
+ );
+ } else if (field.type === 'number') {
+ const fieldValue = metadata[field.name];
+ let nrValue: number | null = parseInt(fieldValue as string);
+ if (isNaN(nrValue)) {
+ nrValue = null;
+ }
+
+ return (
+ sendUpdate(field.name, value)}
+ value={nrValue} />
+ );
+ } else if (field.type === 'image') {
+ return (
+ sendUpdate(field.name, value))} />
+ );
+ } else if (field.type === 'choice') {
+ const choices = field.choices || [];
+ const choiceValue = metadata[field.name];
+
+ return (
+ sendUpdate(field.name, value))} />
+ );
+ } else if (field.type === 'tags') {
+ return (
+ }
+ crntSelected={metadata[field.name] as string[] || []}
+ options={settings?.tags || []}
+ freeform={settings.freeform}
+ focussed={focusElm === TagType.tags}
+ unsetFocus={unsetFocus} />
+ );
+ } else if (field.type === 'categories') {
+ return (
+ }
+ crntSelected={metadata.categories as string[] || []}
+ options={settings.categories}
+ freeform={settings.freeform}
+ focussed={focusElm === TagType.categories}
+ unsetFocus={unsetFocus} />
+ );
+ }
+ });
+ };
+
+ return (
+
+
+ {
+ renderFields(contentType?.fields)
+ }
+
+ {
+ }
+ crntSelected={metadata.keywords as string[] || []}
+ options={[]}
+ freeform={true}
+ focussed={focusElm === TagType.keywords}
+ unsetFocus={unsetFocus}
+ disableConfigurable />
+ }
+
+ );
+};
\ No newline at end of file
diff --git a/src/viewpanel/components/OtherActionButton.tsx b/src/panelWebView/components/OtherActionButton.tsx
similarity index 100%
rename from src/viewpanel/components/OtherActionButton.tsx
rename to src/panelWebView/components/OtherActionButton.tsx
diff --git a/src/viewpanel/components/OtherActions.tsx b/src/panelWebView/components/OtherActions.tsx
similarity index 100%
rename from src/viewpanel/components/OtherActions.tsx
rename to src/panelWebView/components/OtherActions.tsx
diff --git a/src/viewpanel/components/Preview.tsx b/src/panelWebView/components/Preview.tsx
similarity index 100%
rename from src/viewpanel/components/Preview.tsx
rename to src/panelWebView/components/Preview.tsx
diff --git a/src/viewpanel/components/PublishAction.tsx b/src/panelWebView/components/PublishAction.tsx
similarity index 100%
rename from src/viewpanel/components/PublishAction.tsx
rename to src/panelWebView/components/PublishAction.tsx
diff --git a/src/viewpanel/components/SeoDetails.tsx b/src/panelWebView/components/SeoDetails.tsx
similarity index 100%
rename from src/viewpanel/components/SeoDetails.tsx
rename to src/panelWebView/components/SeoDetails.tsx
diff --git a/src/viewpanel/components/SeoFieldInfo.tsx b/src/panelWebView/components/SeoFieldInfo.tsx
similarity index 100%
rename from src/viewpanel/components/SeoFieldInfo.tsx
rename to src/panelWebView/components/SeoFieldInfo.tsx
diff --git a/src/viewpanel/components/SeoKeywordInfo.tsx b/src/panelWebView/components/SeoKeywordInfo.tsx
similarity index 100%
rename from src/viewpanel/components/SeoKeywordInfo.tsx
rename to src/panelWebView/components/SeoKeywordInfo.tsx
diff --git a/src/viewpanel/components/SeoKeywords.tsx b/src/panelWebView/components/SeoKeywords.tsx
similarity index 100%
rename from src/viewpanel/components/SeoKeywords.tsx
rename to src/panelWebView/components/SeoKeywords.tsx
diff --git a/src/viewpanel/components/SeoStatus.tsx b/src/panelWebView/components/SeoStatus.tsx
similarity index 100%
rename from src/viewpanel/components/SeoStatus.tsx
rename to src/panelWebView/components/SeoStatus.tsx
diff --git a/src/viewpanel/components/SlugAction.tsx b/src/panelWebView/components/SlugAction.tsx
similarity index 100%
rename from src/viewpanel/components/SlugAction.tsx
rename to src/panelWebView/components/SlugAction.tsx
diff --git a/src/viewpanel/components/Spinner.tsx b/src/panelWebView/components/Spinner.tsx
similarity index 100%
rename from src/viewpanel/components/Spinner.tsx
rename to src/panelWebView/components/Spinner.tsx
diff --git a/src/viewpanel/components/SponsorMsg.tsx b/src/panelWebView/components/SponsorMsg.tsx
similarity index 100%
rename from src/viewpanel/components/SponsorMsg.tsx
rename to src/panelWebView/components/SponsorMsg.tsx
diff --git a/src/viewpanel/components/Tag.tsx b/src/panelWebView/components/Tag.tsx
similarity index 100%
rename from src/viewpanel/components/Tag.tsx
rename to src/panelWebView/components/Tag.tsx
diff --git a/src/viewpanel/components/TagPicker.tsx b/src/panelWebView/components/TagPicker.tsx
similarity index 95%
rename from src/viewpanel/components/TagPicker.tsx
rename to src/panelWebView/components/TagPicker.tsx
index 0d19e065..877515e5 100644
--- a/src/viewpanel/components/TagPicker.tsx
+++ b/src/panelWebView/components/TagPicker.tsx
@@ -11,6 +11,7 @@ import { MessageHelper } from '../../helpers/MessageHelper';
export interface ITagPickerProps {
type: string;
icon: JSX.Element;
+ label?: string;
crntSelected: string[];
options: string[];
freeform: boolean;
@@ -20,7 +21,7 @@ export interface ITagPickerProps {
}
export const TagPicker: React.FunctionComponent = (props: React.PropsWithChildren) => {
- const { icon, type, crntSelected, options, freeform, focussed, unsetFocus, disableConfigurable } = props;
+ const { label, icon, type, crntSelected, options, freeform, focussed, unsetFocus, disableConfigurable } = props;
const [ selected, setSelected ] = React.useState([]);
const [ inputValue, setInputValue ] = React.useState("");
const prevSelected = usePrevious(crntSelected);
@@ -130,7 +131,7 @@ export const TagPicker: React.FunctionComponent = (props: React
- {icon} {type}
+ {icon} {label || type}
@@ -157,7 +158,7 @@ export const TagPicker: React.FunctionComponent
= (props: React
}
})
}
- placeholder={`Pick your ${type.toLowerCase()}`} />
+ placeholder={`Pick your ${label || type.toLowerCase()}`} />
{
freeform && (
diff --git a/src/viewpanel/components/Tags.tsx b/src/panelWebView/components/Tags.tsx
similarity index 100%
rename from src/viewpanel/components/Tags.tsx
rename to src/panelWebView/components/Tags.tsx
diff --git a/src/viewpanel/components/ValidInfo.tsx b/src/panelWebView/components/ValidInfo.tsx
similarity index 100%
rename from src/viewpanel/components/ValidInfo.tsx
rename to src/panelWebView/components/ValidInfo.tsx
diff --git a/src/viewpanel/components/VscodeComponents.ts b/src/panelWebView/components/VscodeComponents.ts
similarity index 100%
rename from src/viewpanel/components/VscodeComponents.ts
rename to src/panelWebView/components/VscodeComponents.ts
diff --git a/src/viewpanel/hooks/useMessages.tsx b/src/panelWebView/hooks/useMessages.tsx
similarity index 85%
rename from src/viewpanel/hooks/useMessages.tsx
rename to src/panelWebView/hooks/useMessages.tsx
index 3490a824..fd53af91 100644
--- a/src/viewpanel/hooks/useMessages.tsx
+++ b/src/panelWebView/hooks/useMessages.tsx
@@ -1,5 +1,6 @@
import { useState, useEffect } from 'react';
import { MessageHelper } from '../../helpers/MessageHelper';
+import { DashboardData } from '../../models/DashboardData';
import { FolderInfo, PanelSettings } from '../../models/PanelSettings';
import { Command } from '../Command';
import { CommandToCode } from '../CommandToCode';
@@ -13,6 +14,7 @@ export default function useMessages() {
const [loading, setLoading] = useState(false);
const [focusElm, setFocus] = useState(null);
const [folderAndFiles, setFolderAndFiles] = useState(undefined);
+ const [mediaSelecting, setMediaSelecting] = useState(undefined);
window.addEventListener('message', event => {
const message = event.data;
@@ -38,6 +40,9 @@ export default function useMessages() {
case Command.focusOnCategories:
setFocus(TagType.categories);
break;
+ case Command.mediaSelectionData:
+ setMediaSelecting(message.data);
+ break;
}
});
@@ -52,6 +57,7 @@ export default function useMessages() {
folderAndFiles,
focusElm,
loading,
+ mediaSelecting,
unsetFocus: () => { setFocus(null) }
};
}
\ No newline at end of file
diff --git a/src/viewpanel/hooks/usePrevious.tsx b/src/panelWebView/hooks/usePrevious.tsx
similarity index 100%
rename from src/viewpanel/hooks/usePrevious.tsx
rename to src/panelWebView/hooks/usePrevious.tsx
diff --git a/src/viewpanel/index.tsx b/src/panelWebView/index.tsx
similarity index 100%
rename from src/viewpanel/index.tsx
rename to src/panelWebView/index.tsx
diff --git a/src/providers/MarkdownFoldingProvider.ts b/src/providers/MarkdownFoldingProvider.ts
index 7e69beac..17d0fb1f 100644
--- a/src/providers/MarkdownFoldingProvider.ts
+++ b/src/providers/MarkdownFoldingProvider.ts
@@ -1,7 +1,7 @@
import { TextEditorDecorationType } from 'vscode';
import { CancellationToken, FoldingContext, FoldingRange, FoldingRangeKind, FoldingRangeProvider, Range, TextDocument, window, Position } from 'vscode';
import { SETTINGS_CONTENT_FRONTMATTER_HIGHLIGHT } from '../constants';
-import { SettingsHelper } from '../helpers';
+import { Settings } from '../helpers';
import { FrontMatterDecorationProvider } from './FrontMatterDecorationProvider';
export class MarkdownFoldingProvider implements FoldingRangeProvider {
@@ -44,8 +44,7 @@ export class MarkdownFoldingProvider implements FoldingRangeProvider {
}
public static triggerHighlighting() {
- const config = SettingsHelper.getConfig();
- const fmHighlight = config.get(SETTINGS_CONTENT_FRONTMATTER_HIGHLIGHT);
+ const fmHighlight = Settings.get(SETTINGS_CONTENT_FRONTMATTER_HIGHLIGHT);
if (MarkdownFoldingProvider.start !== null && MarkdownFoldingProvider.end !== null && MarkdownFoldingProvider.endLine !== null) {
const range = new Range(new Position(MarkdownFoldingProvider.start, 0), new Position(MarkdownFoldingProvider.end, MarkdownFoldingProvider.endLine));
diff --git a/src/viewpanel/components/DateAction.tsx b/src/viewpanel/components/DateAction.tsx
deleted file mode 100644
index adecf71b..00000000
--- a/src/viewpanel/components/DateAction.tsx
+++ /dev/null
@@ -1,24 +0,0 @@
-import * as React from 'react';
-import { CommandToCode } from '../CommandToCode';
-import { MessageHelper } from '../../helpers/MessageHelper';
-import { ActionButton } from './ActionButton';
-
-export interface IDateActionProps {}
-
-export const DateAction: React.FunctionComponent = (props: React.PropsWithChildren) => {
-
- const setDate = () => {
- MessageHelper.sendMessage(CommandToCode.updateDate);
- };
-
- const setLastMod = () => {
- MessageHelper.sendMessage(CommandToCode.updateLastMod);
- };
-
- return (
- <>
-
-
- >
- );
-};
\ No newline at end of file
diff --git a/src/viewpanel/components/Fields/Toggle.tsx b/src/viewpanel/components/Fields/Toggle.tsx
deleted file mode 100644
index 6b70a3ed..00000000
--- a/src/viewpanel/components/Fields/Toggle.tsx
+++ /dev/null
@@ -1,28 +0,0 @@
-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/Metadata.tsx b/src/viewpanel/components/Metadata.tsx
deleted file mode 100644
index 75e04952..00000000
--- a/src/viewpanel/components/Metadata.tsx
+++ /dev/null
@@ -1,77 +0,0 @@
-import * as React from 'react';
-import { PanelSettings } from '../../models';
-import { CommandToCode } from '../CommandToCode';
-import { MessageHelper } from '../../helpers/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;
- metadata: { [prop: string]: string[] | null };
- focusElm: TagType | null;
- unsetFocus: () => void;
-}
-
-export const Metadata: React.FunctionComponent = ({settings, metadata, focusElm, unsetFocus}: React.PropsWithChildren) => {
-
- const sendUpdate = (field: string, value: any) => {
- MessageHelper.sendMessage(CommandToCode.updateMetadata, {
- field,
- value
- });
- };
-
- return (
-
-
-
-
-
- Published
-
-
-
sendUpdate("draft", !checked)} />
-
-
- {
- }
- crntSelected={metadata.keywords || []}
- options={[]}
- freeform={true}
- focussed={focusElm === TagType.keywords}
- unsetFocus={unsetFocus}
- disableConfigurable />
- }
- {
- (settings && settings.tags && settings.tags.length > 0) && (
- }
- crntSelected={metadata.tags || []}
- options={settings.tags}
- freeform={settings.freeform}
- focussed={focusElm === TagType.tags}
- unsetFocus={unsetFocus} />
- )
- }
- {
- (settings && settings.categories && settings.categories.length > 0) && (
- }
- crntSelected={metadata.categories || []}
- options={settings.categories}
- freeform={settings.freeform}
- focussed={focusElm === TagType.categories}
- unsetFocus={unsetFocus} />
- )
- }
-
- );
-};
\ No newline at end of file
diff --git a/webpack.config.js b/webpack.config.js
index ee1b632f..a03bd92e 100644
--- a/webpack.config.js
+++ b/webpack.config.js
@@ -37,9 +37,9 @@ const config = [
}
},
{
- name: 'viewpanel',
+ name: 'panelWebView',
target: 'web',
- entry: './src/viewpanel/index.tsx',
+ entry: './src/panelWebView/index.tsx',
output: {
path: path.resolve(__dirname, 'dist'),
filename: 'viewpanel.js'
@@ -56,6 +56,10 @@ const config = [
use: [{
loader: 'ts-loader'
}]
+ },
+ {
+ test: /\.css$/,
+ use: ['style-loader', 'css-loader']
}
]
},
@@ -65,9 +69,9 @@ const config = [
}
},
{
- name: 'pagesView',
+ name: 'dashboardWebView',
target: 'web',
- entry: './src/pagesView/index.tsx',
+ entry: './src/dashboardWebView/index.tsx',
output: {
path: path.resolve(__dirname, 'dist'),
filename: 'pages.js'