mirror of
https://github.com/estruyf/vscode-front-matter.git
synced 2026-03-28 17:42:40 +01:00
Enhancement: Ability to create new data files for a folder #834
This commit is contained in:
@@ -6,6 +6,8 @@
|
||||
|
||||
### 🎨 Enhancements
|
||||
|
||||
- [#834](https://github.com/estruyf/vscode-front-matter/issues/834): Added the ability to create new data files for a data folder
|
||||
|
||||
### 🐞 Fixes
|
||||
|
||||
## [10.3.0] - 2024-08-13 - [Release notes](https://beta.frontmatter.codes/updates/v10.3.0)
|
||||
|
||||
@@ -140,6 +140,9 @@
|
||||
"dashboard.dataView.dataView.noDataFiles": "No data files found",
|
||||
"dashboard.dataView.dataView.getStarted.link": "Read more to get started using data files",
|
||||
"dashboard.dataView.dataView.update.message": "Updated your data entries",
|
||||
"dashboard.dataView.dataView.createNew": "Create new data file",
|
||||
"dashboard.dataView.dataView.selectDataFolder": "Select data folder",
|
||||
"dashboard.dataView.dataView.closeSelectedDataFile": "Close data file",
|
||||
|
||||
"dashboard.dataView.emptyView.heading": "Select your date type first",
|
||||
|
||||
@@ -783,6 +786,9 @@
|
||||
"listeners.panel.dataListener.aiSuggestTaxonomy.noData.error": "No article data",
|
||||
"listeners.panel.dataListener.getDataFileEntries.noDataFiles.error": "Couldn't find data file entries",
|
||||
"listeners.panel.dataListener.pushMetadata.frontMatter.error": "Something went wrong while parsing your front matter. Please check the contents of your file.",
|
||||
"listeners.panel.dataListener.createDataFile.inputTitle": "What is the name of the data file?",
|
||||
"listeners.panel.dataListener.createDataFile.error": "No data file id or path defined.",
|
||||
"listeners.panel.dataListener.createDataFile.noFileName": "No filename provided.",
|
||||
|
||||
|
||||
"listeners.panel.taxonomyListener.aiSuggestTaxonomy.noEditor.error": "No active editor",
|
||||
|
||||
347
package.json
347
package.json
@@ -10,8 +10,7 @@
|
||||
"color": "#0e131f",
|
||||
"theme": "dark"
|
||||
},
|
||||
"badges": [
|
||||
{
|
||||
"badges": [{
|
||||
"description": "version",
|
||||
"url": "https://img.shields.io/github/package-json/v/estruyf/vscode-front-matter?color=green&label=vscode-front-matter&style=flat-square",
|
||||
"href": "https://github.com/estruyf/vscode-front-matter"
|
||||
@@ -71,8 +70,7 @@
|
||||
"**/.frontmatter/config/*.json": "jsonc"
|
||||
}
|
||||
},
|
||||
"keybindings": [
|
||||
{
|
||||
"keybindings": [{
|
||||
"command": "frontMatter.dashboard",
|
||||
"key": "alt+d"
|
||||
},
|
||||
@@ -96,23 +94,19 @@
|
||||
}
|
||||
],
|
||||
"viewsContainers": {
|
||||
"activitybar": [
|
||||
{
|
||||
"id": "frontmatter-explorer",
|
||||
"title": "FM",
|
||||
"icon": "$(fm-logo)"
|
||||
}
|
||||
]
|
||||
"activitybar": [{
|
||||
"id": "frontmatter-explorer",
|
||||
"title": "FM",
|
||||
"icon": "$(fm-logo)"
|
||||
}]
|
||||
},
|
||||
"views": {
|
||||
"frontmatter-explorer": [
|
||||
{
|
||||
"id": "frontMatter.explorer",
|
||||
"name": "Front Matter",
|
||||
"icon": "$(fm-logo)",
|
||||
"type": "webview"
|
||||
}
|
||||
]
|
||||
"frontmatter-explorer": [{
|
||||
"id": "frontMatter.explorer",
|
||||
"name": "Front Matter",
|
||||
"icon": "$(fm-logo)",
|
||||
"type": "webview"
|
||||
}]
|
||||
},
|
||||
"configuration": {
|
||||
"title": "%settings.configuration.title%",
|
||||
@@ -180,8 +174,7 @@
|
||||
"frontMatter.content.defaultFileType": {
|
||||
"type": "string",
|
||||
"default": "md",
|
||||
"oneOf": [
|
||||
{
|
||||
"oneOf": [{
|
||||
"enum": [
|
||||
"md",
|
||||
"mdx"
|
||||
@@ -197,8 +190,7 @@
|
||||
"frontMatter.content.defaultSorting": {
|
||||
"type": "string",
|
||||
"default": "",
|
||||
"oneOf": [
|
||||
{
|
||||
"oneOf": [{
|
||||
"enum": [
|
||||
"LastModifiedAsc",
|
||||
"LastModifiedDesc",
|
||||
@@ -550,8 +542,7 @@
|
||||
"categories"
|
||||
],
|
||||
"markdownDescription": "%setting.frontMatter.content.filters.markdownDescription%",
|
||||
"items": [
|
||||
{
|
||||
"items": [{
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"contentFolders",
|
||||
@@ -625,8 +616,7 @@
|
||||
"command": {
|
||||
"$id": "#scriptCommand",
|
||||
"type": "string",
|
||||
"anyOf": [
|
||||
{
|
||||
"anyOf": [{
|
||||
"enum": [
|
||||
"node",
|
||||
"bash",
|
||||
@@ -822,8 +812,7 @@
|
||||
"title",
|
||||
"file"
|
||||
],
|
||||
"anyOf": [
|
||||
{
|
||||
"anyOf": [{
|
||||
"required": [
|
||||
"schema"
|
||||
]
|
||||
@@ -870,6 +859,20 @@
|
||||
"type": "boolean",
|
||||
"description": "%setting.frontMatter.data.folders.items.properties.singleEntry.description%",
|
||||
"default": false
|
||||
},
|
||||
"enableFileCreation": {
|
||||
"type": "boolean",
|
||||
"description": "%setting.frontMatter.data.folders.items.properties.enableFileCreation.description%",
|
||||
"default": false
|
||||
},
|
||||
"fileType": {
|
||||
"type": "string",
|
||||
"default": "json",
|
||||
"enum": [
|
||||
"json",
|
||||
"yaml"
|
||||
],
|
||||
"description": "%setting.frontMatter.data.folders.items.properties.fileType.description%"
|
||||
}
|
||||
},
|
||||
"additionalProperties": false,
|
||||
@@ -877,8 +880,7 @@
|
||||
"id",
|
||||
"path"
|
||||
],
|
||||
"anyOf": [
|
||||
{
|
||||
"anyOf": [{
|
||||
"required": [
|
||||
"schema"
|
||||
]
|
||||
@@ -1119,29 +1121,26 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"default": [
|
||||
{
|
||||
"name": "default",
|
||||
"fileTypes": null,
|
||||
"fields": [
|
||||
{
|
||||
"title": "Title",
|
||||
"name": "title",
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"title": "Caption",
|
||||
"name": "caption",
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"title": "Alt text",
|
||||
"name": "alt",
|
||||
"type": "string"
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"default": [{
|
||||
"name": "default",
|
||||
"fileTypes": null,
|
||||
"fields": [{
|
||||
"title": "Title",
|
||||
"name": "title",
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"title": "Caption",
|
||||
"name": "caption",
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"title": "Alt text",
|
||||
"name": "alt",
|
||||
"type": "string"
|
||||
}
|
||||
]
|
||||
}],
|
||||
"scope": "Media"
|
||||
},
|
||||
"frontMatter.media.supportedMimeTypes": {
|
||||
@@ -1244,8 +1243,7 @@
|
||||
"fileType": {
|
||||
"type": "string",
|
||||
"default": "",
|
||||
"oneOf": [
|
||||
{
|
||||
"oneOf": [{
|
||||
"enum": [
|
||||
"md",
|
||||
"mdx"
|
||||
@@ -1384,8 +1382,7 @@
|
||||
"default": "",
|
||||
"description": "%setting.frontMatter.taxonomy.contentTypes.items.properties.fields.items.properties.taxonomyId.description%",
|
||||
"not": {
|
||||
"anyOf": [
|
||||
{
|
||||
"anyOf": [{
|
||||
"const": ""
|
||||
},
|
||||
{
|
||||
@@ -1586,8 +1583,7 @@
|
||||
"type",
|
||||
"name"
|
||||
],
|
||||
"allOf": [
|
||||
{
|
||||
"allOf": [{
|
||||
"if": {
|
||||
"properties": {
|
||||
"type": {
|
||||
@@ -1799,51 +1795,48 @@
|
||||
"fields"
|
||||
]
|
||||
},
|
||||
"default": [
|
||||
{
|
||||
"name": "default",
|
||||
"pageBundle": false,
|
||||
"fields": [
|
||||
{
|
||||
"title": "Title",
|
||||
"name": "title",
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"title": "Description",
|
||||
"name": "description",
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"title": "Publishing date",
|
||||
"name": "date",
|
||||
"type": "datetime",
|
||||
"default": "{{now}}",
|
||||
"isPublishDate": true
|
||||
},
|
||||
{
|
||||
"title": "Content preview",
|
||||
"name": "preview",
|
||||
"type": "image"
|
||||
},
|
||||
{
|
||||
"title": "Is in draft",
|
||||
"name": "draft",
|
||||
"type": "boolean"
|
||||
},
|
||||
{
|
||||
"title": "Tags",
|
||||
"name": "tags",
|
||||
"type": "tags"
|
||||
},
|
||||
{
|
||||
"title": "Categories",
|
||||
"name": "categories",
|
||||
"type": "categories"
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"default": [{
|
||||
"name": "default",
|
||||
"pageBundle": false,
|
||||
"fields": [{
|
||||
"title": "Title",
|
||||
"name": "title",
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"title": "Description",
|
||||
"name": "description",
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"title": "Publishing date",
|
||||
"name": "date",
|
||||
"type": "datetime",
|
||||
"default": "{{now}}",
|
||||
"isPublishDate": true
|
||||
},
|
||||
{
|
||||
"title": "Content preview",
|
||||
"name": "preview",
|
||||
"type": "image"
|
||||
},
|
||||
{
|
||||
"title": "Is in draft",
|
||||
"name": "draft",
|
||||
"type": "boolean"
|
||||
},
|
||||
{
|
||||
"title": "Tags",
|
||||
"name": "tags",
|
||||
"type": "tags"
|
||||
},
|
||||
{
|
||||
"title": "Categories",
|
||||
"name": "categories",
|
||||
"type": "categories"
|
||||
}
|
||||
]
|
||||
}],
|
||||
"scope": "Taxonomy"
|
||||
},
|
||||
"frontMatter.taxonomy.customTaxonomy": {
|
||||
@@ -1856,8 +1849,7 @@
|
||||
"type": "string",
|
||||
"description": "%setting.frontMatter.taxonomy.customTaxonomy.items.properties.id.description%",
|
||||
"not": {
|
||||
"anyOf": [
|
||||
{
|
||||
"anyOf": [{
|
||||
"const": ""
|
||||
},
|
||||
{
|
||||
@@ -2052,8 +2044,7 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"commands": [
|
||||
{
|
||||
"commands": [{
|
||||
"command": "frontMatter.project.switch",
|
||||
"title": "%command.frontMatter.project.switch%",
|
||||
"category": "Front Matter",
|
||||
@@ -2385,21 +2376,16 @@
|
||||
}
|
||||
}
|
||||
],
|
||||
"submenus": [
|
||||
{
|
||||
"id": "frontmatter.submenu",
|
||||
"label": "Front Matter"
|
||||
}
|
||||
],
|
||||
"submenus": [{
|
||||
"id": "frontmatter.submenu",
|
||||
"label": "Front Matter"
|
||||
}],
|
||||
"menus": {
|
||||
"webview/context": [
|
||||
{
|
||||
"command": "workbench.action.webview.openDeveloperTools",
|
||||
"when": "frontMatter:isDevelopment"
|
||||
}
|
||||
],
|
||||
"editor/title": [
|
||||
{
|
||||
"webview/context": [{
|
||||
"command": "workbench.action.webview.openDeveloperTools",
|
||||
"when": "frontMatter:isDevelopment"
|
||||
}],
|
||||
"editor/title": [{
|
||||
"command": "frontMatter.markup.heading",
|
||||
"group": "navigation@-133",
|
||||
"when": "frontMatter:file:isValid == true && frontMatter:markdown:wysiwyg"
|
||||
@@ -2485,14 +2471,11 @@
|
||||
"when": "resourceFilename == 'frontmatter.json'"
|
||||
}
|
||||
],
|
||||
"explorer/context": [
|
||||
{
|
||||
"submenu": "frontmatter.submenu",
|
||||
"group": "frontmatter@1"
|
||||
}
|
||||
],
|
||||
"frontmatter.submenu": [
|
||||
{
|
||||
"explorer/context": [{
|
||||
"submenu": "frontmatter.submenu",
|
||||
"group": "frontmatter@1"
|
||||
}],
|
||||
"frontmatter.submenu": [{
|
||||
"command": "frontMatter.createFromTemplate",
|
||||
"when": "explorerResourceIsFolder",
|
||||
"group": "frontmatter@1"
|
||||
@@ -2508,8 +2491,7 @@
|
||||
"group": "frontmatter@3"
|
||||
}
|
||||
],
|
||||
"commandPalette": [
|
||||
{
|
||||
"commandPalette": [{
|
||||
"command": "frontMatter.init",
|
||||
"when": "frontMatterCanInit"
|
||||
},
|
||||
@@ -2686,8 +2668,7 @@
|
||||
"when": "frontMatter:file:isValid == true"
|
||||
}
|
||||
],
|
||||
"view/title": [
|
||||
{
|
||||
"view/title": [{
|
||||
"command": "frontMatter.docs",
|
||||
"group": "navigation@-1",
|
||||
"when": "view == frontMatter.explorer"
|
||||
@@ -2724,16 +2705,13 @@
|
||||
}
|
||||
]
|
||||
},
|
||||
"languages": [
|
||||
{
|
||||
"id": "frontmatter.project.output",
|
||||
"mimetypes": [
|
||||
"text/x-code-output"
|
||||
]
|
||||
}
|
||||
],
|
||||
"grammars": [
|
||||
{
|
||||
"languages": [{
|
||||
"id": "frontmatter.project.output",
|
||||
"mimetypes": [
|
||||
"text/x-code-output"
|
||||
]
|
||||
}],
|
||||
"grammars": [{
|
||||
"path": "./syntaxes/hugo.tmLanguage.json",
|
||||
"scopeName": "frontmatter.markdown.hugo",
|
||||
"injectTo": [
|
||||
@@ -2746,48 +2724,45 @@
|
||||
"path": "./syntaxes/frontmatter-output.tmLanguage.json"
|
||||
}
|
||||
],
|
||||
"walkthroughs": [
|
||||
{
|
||||
"id": "frontmatter.welcome",
|
||||
"title": "Get started with Front Matter",
|
||||
"description": "Discover the features of Front Matter and learn how to use the CMS for your SSG or static site.",
|
||||
"steps": [
|
||||
{
|
||||
"id": "frontmatter.welcome.init",
|
||||
"title": "Get started",
|
||||
"description": "Initial steps to get started.\n[Open dashboard](command:frontMatter.dashboard)",
|
||||
"media": {
|
||||
"markdown": "assets/walkthrough/get-started.md"
|
||||
},
|
||||
"completionEvents": [
|
||||
"onContext:frontMatterInitialized"
|
||||
]
|
||||
"walkthroughs": [{
|
||||
"id": "frontmatter.welcome",
|
||||
"title": "Get started with Front Matter",
|
||||
"description": "Discover the features of Front Matter and learn how to use the CMS for your SSG or static site.",
|
||||
"steps": [{
|
||||
"id": "frontmatter.welcome.init",
|
||||
"title": "Get started",
|
||||
"description": "Initial steps to get started.\n[Open dashboard](command:frontMatter.dashboard)",
|
||||
"media": {
|
||||
"markdown": "assets/walkthrough/get-started.md"
|
||||
},
|
||||
{
|
||||
"id": "frontmatter.welcome.documentation",
|
||||
"title": "Documentation",
|
||||
"description": "Check out the documentation for Front Matter.\n[View our documentation](https://frontmatter.codes/docs)",
|
||||
"media": {
|
||||
"markdown": "assets/walkthrough/documentation.md"
|
||||
},
|
||||
"completionEvents": [
|
||||
"onLink:https://frontmatter.codes/docs"
|
||||
]
|
||||
"completionEvents": [
|
||||
"onContext:frontMatterInitialized"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "frontmatter.welcome.documentation",
|
||||
"title": "Documentation",
|
||||
"description": "Check out the documentation for Front Matter.\n[View our documentation](https://frontmatter.codes/docs)",
|
||||
"media": {
|
||||
"markdown": "assets/walkthrough/documentation.md"
|
||||
},
|
||||
{
|
||||
"id": "frontmatter.welcome.supporter",
|
||||
"title": "Support the project",
|
||||
"description": "Become a supporter.\n[Support the project](https://github.com/sponsors/estruyf)",
|
||||
"media": {
|
||||
"markdown": "assets/walkthrough/support-the-project.md"
|
||||
},
|
||||
"completionEvents": [
|
||||
"onLink:https://github.com/sponsors/estruyf"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
"completionEvents": [
|
||||
"onLink:https://frontmatter.codes/docs"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "frontmatter.welcome.supporter",
|
||||
"title": "Support the project",
|
||||
"description": "Become a supporter.\n[Support the project](https://github.com/sponsors/estruyf)",
|
||||
"media": {
|
||||
"markdown": "assets/walkthrough/support-the-project.md"
|
||||
},
|
||||
"completionEvents": [
|
||||
"onLink:https://github.com/sponsors/estruyf"
|
||||
]
|
||||
}
|
||||
]
|
||||
}]
|
||||
},
|
||||
"scripts": {
|
||||
"dev:ext": "npm run clean && npm run localization:generate && npm-run-all --parallel watch:*",
|
||||
@@ -2915,4 +2890,4 @@
|
||||
"dependencies": {
|
||||
"@radix-ui/react-dropdown-menu": "^2.0.6"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -145,6 +145,8 @@
|
||||
"setting.frontMatter.data.folders.items.properties.path.description": "Path to the folder to load files.",
|
||||
"setting.frontMatter.data.folders.items.properties.type.description": "If you are using data types, you can specify your type ID.",
|
||||
"setting.frontMatter.data.folders.items.properties.singleEntry.description": "If you want to use a single entry for your data files in the folder.",
|
||||
"setting.frontMatter.data.folders.items.properties.enableFileCreation.description": "Enable the creation of new data files in the folder.",
|
||||
"setting.frontMatter.data.folders.items.properties.fileType.description": "Defines the file type for when the file creation is enabled. JSON is the default.",
|
||||
"setting.frontMatter.data.types.markdownDescription": "Specify the data types. These types can be used in for your data files. [Docs](https://frontmatter.codes/docs/settings/overview#frontmatter.data.types) - [View in VS Code](command:simpleBrowser.show?%5B%22https://frontmatter.codes/docs/settings/overview%23frontmatter.data.types%22%5D)",
|
||||
"setting.frontMatter.data.types.items.properties.id.description": "Your unique ID you want to use for your data type.",
|
||||
"setting.frontMatter.file.preserveCasing.markdownDescription": "Specify if you want to preserve the casing of your file names from the title. [Docs](https://frontmatter.codes/docs/settings/overview#frontmatter.file.preservecasing) - [View in VS Code](command:simpleBrowser.show?%5B%22https://frontmatter.codes/docs/settings/overview%23frontmatter.file.preservecasing%22%5D)",
|
||||
|
||||
@@ -557,6 +557,22 @@ export class Folders {
|
||||
return parseWinPath(absPath);
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts a given file path to a workspace-relative path.
|
||||
*
|
||||
* @param path - The file path to convert.
|
||||
* @returns The workspace-relative path.
|
||||
*/
|
||||
public static wsPath(path: string) {
|
||||
const wsFolder = Folders.getWorkspaceFolder();
|
||||
let absPath = parseWinPath(path).replace(
|
||||
parseWinPath(wsFolder?.fsPath || ''),
|
||||
WORKSPACE_PLACEHOLDER
|
||||
);
|
||||
absPath = isWindows() ? absPath.split('\\').join('/') : absPath;
|
||||
return absPath;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate relative folder path
|
||||
* @param folder
|
||||
|
||||
@@ -50,6 +50,7 @@ export enum DashboardMessage {
|
||||
// Data dashboard
|
||||
getDataEntries = 'getDataEntries',
|
||||
putDataEntries = 'putDataEntries',
|
||||
createDataFile = 'createDataFile',
|
||||
|
||||
// Snippets dashboard
|
||||
insertSnippet = 'insertSnippet',
|
||||
|
||||
@@ -5,7 +5,7 @@ import { SettingsSelector } from '../../state';
|
||||
import { DataForm } from './DataForm';
|
||||
import { useCallback, useEffect, useMemo, useState } from 'react';
|
||||
import { DataFile } from '../../../models/DataFile';
|
||||
import { Messenger } from '@estruyf/vscode/dist/client';
|
||||
import { messageHandler, Messenger } from '@estruyf/vscode/dist/client';
|
||||
import { DashboardMessage } from '../../DashboardMessage';
|
||||
import { SponsorMsg } from '../Layout/SponsorMsg';
|
||||
import { EventData } from '@estruyf/vscode';
|
||||
@@ -15,15 +15,18 @@ import { arrayMoveImmutable } from 'array-move';
|
||||
import { EmptyView } from './EmptyView';
|
||||
import { Container } from './SortableContainer';
|
||||
import { SortableItem } from './SortableItem';
|
||||
import { ChevronRightIcon, CircleStackIcon } from '@heroicons/react/24/outline';
|
||||
import { ChevronRightIcon, CircleStackIcon, EyeIcon, XMarkIcon } from '@heroicons/react/24/outline';
|
||||
import { DataType } from '../../../models/DataType';
|
||||
import { GeneralCommands, WEBSITE_LINKS } from '../../../constants';
|
||||
import { NavigationItem } from '../Layout';
|
||||
import * as l10n from '@vscode/l10n';
|
||||
import { LocalizationKey } from '../../../localization';
|
||||
import { LocalizationKey, localize } from '../../../localization';
|
||||
import { DropdownMenu, DropdownMenuContent } from '../../../components/shadcn/Dropdown';
|
||||
import { MenuButton, MenuItem } from '../Menu';
|
||||
import { Transition } from '@headlessui/react';
|
||||
import { DataFolder } from '../../../models';
|
||||
import { ActionsBarItem } from '../Header/ActionsBarItem';
|
||||
import { Spinner } from '../Common/Spinner';
|
||||
import { openFile } from '../../utils/MessageHandlers';
|
||||
|
||||
export interface IDataViewProps { }
|
||||
|
||||
@@ -33,6 +36,7 @@ export const DataView: React.FunctionComponent<IDataViewProps> = (
|
||||
const [selectedData, setSelectedData] = useState<DataFile | null>(null);
|
||||
const [selectedIndex, setSelectedIndex] = useState<number | null>(null);
|
||||
const [dataEntries, setDataEntries] = useState<any | any[] | null>(null);
|
||||
const [loading, setLoading] = useState<boolean>(false);
|
||||
const settings = useRecoilValue(SettingsSelector);
|
||||
|
||||
const setSchema = (dataFile: DataFile) => {
|
||||
@@ -71,6 +75,7 @@ export const DataView: React.FunctionComponent<IDataViewProps> = (
|
||||
return;
|
||||
}
|
||||
|
||||
debugger
|
||||
const dataClone: any[] = Object.assign([], dataEntries);
|
||||
if (selectedIndex !== null && selectedIndex !== undefined) {
|
||||
dataClone[selectedIndex] = data;
|
||||
@@ -110,11 +115,23 @@ export const DataView: React.FunctionComponent<IDataViewProps> = (
|
||||
entries: data
|
||||
});
|
||||
|
||||
Messenger.send(DashboardMessage.showNotification, l10n.t(LocalizationKey.dashboardDataViewDataViewUpdateMessage));
|
||||
Messenger.send(DashboardMessage.showNotification, localize(LocalizationKey.dashboardDataViewDataViewUpdateMessage));
|
||||
},
|
||||
[selectedData]
|
||||
);
|
||||
|
||||
const createDataFile = (folder: DataFolder) => {
|
||||
setLoading(true);
|
||||
messageHandler.request<DataFile>(DashboardMessage.createDataFile, folder).then(dataFile => {
|
||||
if (dataFile) {
|
||||
setSchema(dataFile);
|
||||
}
|
||||
setLoading(false);
|
||||
}).catch((_: any) => {
|
||||
setLoading(false);
|
||||
});
|
||||
}
|
||||
|
||||
const dataEntry = useMemo(() => {
|
||||
if (selectedData?.singleEntry) {
|
||||
return dataEntries || {};
|
||||
@@ -125,10 +142,40 @@ export const DataView: React.FunctionComponent<IDataViewProps> = (
|
||||
: null;
|
||||
}, [selectedData, , dataEntries, selectedIndex]);
|
||||
|
||||
// Retrieve the data files, check if they have a schema or ID, if not, they shouldn't be shown
|
||||
const dataFiles = useMemo(() => {
|
||||
return (settings?.dataFiles || [])
|
||||
.map((dataFile: DataFile) => {
|
||||
if (!dataFile.schema && !dataFile.id) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const clonedFile = Object.assign({}, dataFile);
|
||||
|
||||
if (clonedFile.type) {
|
||||
const dataType = settings?.dataTypes?.find(
|
||||
(dataType: DataType) => dataType.id === clonedFile.type
|
||||
);
|
||||
if (!dataType) {
|
||||
return null;
|
||||
}
|
||||
clonedFile.schema = Object.assign({}, dataType.schema);
|
||||
}
|
||||
|
||||
return clonedFile;
|
||||
})
|
||||
.filter((d) => d !== null) as DataFile[];
|
||||
}, [settings?.dataFiles]);
|
||||
|
||||
const fileCreationFolders = useMemo(() => {
|
||||
return (settings?.dataFolders || [])
|
||||
.filter((folder) => folder.enableFileCreation);
|
||||
}, [settings?.dataFolders]);
|
||||
|
||||
useEffect(() => {
|
||||
Messenger.listen(messageListener);
|
||||
|
||||
Messenger.send(DashboardMessage.setTitle, l10n.t(LocalizationKey.dashboardHeaderTabsData));
|
||||
Messenger.send(DashboardMessage.setTitle, localize(LocalizationKey.dashboardHeaderTabsData));
|
||||
|
||||
Messenger.send(GeneralCommands.toVSCode.logging.info, {
|
||||
message: 'Data view loaded',
|
||||
@@ -140,29 +187,6 @@ export const DataView: React.FunctionComponent<IDataViewProps> = (
|
||||
};
|
||||
}, []);
|
||||
|
||||
// Retrieve the data files, check if they have a schema or ID, if not, they shouldn't be shown
|
||||
const dataFiles = (settings?.dataFiles || [])
|
||||
.map((dataFile: DataFile) => {
|
||||
if (!dataFile.schema && !dataFile.id) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const clonedFile = Object.assign({}, dataFile);
|
||||
|
||||
if (clonedFile.type) {
|
||||
const dataType = settings?.dataTypes?.find(
|
||||
(dataType: DataType) => dataType.id === clonedFile.type
|
||||
);
|
||||
if (!dataType) {
|
||||
return null;
|
||||
}
|
||||
clonedFile.schema = Object.assign({}, dataType.schema);
|
||||
}
|
||||
|
||||
return clonedFile;
|
||||
})
|
||||
.filter((d) => d !== null) as DataFile[];
|
||||
|
||||
return (
|
||||
<div className="flex flex-col h-full overflow-auto inset-y-0">
|
||||
<Header settings={settings} />
|
||||
@@ -176,7 +200,7 @@ export const DataView: React.FunctionComponent<IDataViewProps> = (
|
||||
className={`flex flex-col flex-grow overflow-y-auto border-r py-6 px-4 overflow-auto border-[var(--frontmatter-border)]`}
|
||||
>
|
||||
<h2 className={`text-lg text-[var(--frontmatter-text)]`}>
|
||||
{l10n.t(LocalizationKey.dashboardDataViewDataViewSelect)}
|
||||
{localize(LocalizationKey.dashboardDataViewDataViewSelect)}
|
||||
</h2>
|
||||
|
||||
<nav className={`flex-1 py-4 -mx-4`}>
|
||||
@@ -209,24 +233,70 @@ export const DataView: React.FunctionComponent<IDataViewProps> = (
|
||||
enterTo="opacity-100">
|
||||
<div className={`w-full px-4 py-2 border-b border-[var(--frontmatter-border)]`}>
|
||||
{selectedData && (
|
||||
<DropdownMenu>
|
||||
<MenuButton
|
||||
label={l10n.t(LocalizationKey.dashboardDataViewDataViewSelect)}
|
||||
title={selectedData.title}
|
||||
/>
|
||||
|
||||
<DropdownMenuContent>
|
||||
{dataFiles.map((dataFile) => (
|
||||
<MenuItem
|
||||
key={dataFile.id}
|
||||
title={dataFile.title}
|
||||
value={dataFile}
|
||||
isCurrent={selectedData.id === dataFile.id}
|
||||
onClick={() => setSchema(dataFile)}
|
||||
<div className={`flex justify-between`}>
|
||||
<div className={`flex gap-4`}>
|
||||
<DropdownMenu>
|
||||
<MenuButton
|
||||
label={localize(LocalizationKey.dashboardDataViewDataViewSelect)}
|
||||
title={selectedData.title}
|
||||
/>
|
||||
))}
|
||||
</DropdownMenuContent>
|
||||
</DropdownMenu>
|
||||
|
||||
<DropdownMenuContent>
|
||||
{dataFiles.map((dataFile) => (
|
||||
<MenuItem
|
||||
key={dataFile.id}
|
||||
title={dataFile.title}
|
||||
value={dataFile}
|
||||
isCurrent={selectedData.id === dataFile.id}
|
||||
onClick={() => setSchema(dataFile)}
|
||||
/>
|
||||
))}
|
||||
</DropdownMenuContent>
|
||||
</DropdownMenu>
|
||||
|
||||
{
|
||||
fileCreationFolders && fileCreationFolders.length > 0 && (
|
||||
<DropdownMenu>
|
||||
<MenuButton
|
||||
label={localize(LocalizationKey.dashboardDataViewDataViewCreateNew)}
|
||||
title={localize(LocalizationKey.dashboardDataViewDataViewSelectDataFolder)}
|
||||
/>
|
||||
|
||||
<DropdownMenuContent>
|
||||
{fileCreationFolders.map((folder) => (
|
||||
<MenuItem
|
||||
key={folder.id}
|
||||
title={folder.id}
|
||||
value={folder}
|
||||
onClick={() => createDataFile(folder)}
|
||||
/>
|
||||
))}
|
||||
</DropdownMenuContent>
|
||||
</DropdownMenu>
|
||||
)
|
||||
}
|
||||
</div>
|
||||
|
||||
<div className={`flex gap-2`}>
|
||||
<ActionsBarItem
|
||||
className='flex items-center'
|
||||
onClick={() => openFile(selectedData.file)}
|
||||
title={localize(LocalizationKey.commonView)}
|
||||
>
|
||||
<EyeIcon className="w-4 h-4 mr-1" aria-hidden="true" />
|
||||
<span>{localize(LocalizationKey.commonView)}</span>
|
||||
</ActionsBarItem>
|
||||
|
||||
<ActionsBarItem
|
||||
className='flex items-center hover:text-[var(--vscode-statusBarItem-warningBackground)]'
|
||||
onClick={() => setSelectedData(null)}
|
||||
title={localize(LocalizationKey.dashboardDataViewDataViewCloseSelectedDataFile)}
|
||||
>
|
||||
<XMarkIcon className="w-4 h-4 mr-1" aria-hidden="true" />
|
||||
<span>{localize(LocalizationKey.dashboardDataViewDataViewCloseSelectedDataFile)}</span>
|
||||
</ActionsBarItem>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</Transition>
|
||||
@@ -239,7 +309,7 @@ export const DataView: React.FunctionComponent<IDataViewProps> = (
|
||||
className={`w-1/3 py-6 px-4 flex-1 border-r overflow-auto border-[var(--frontmatter-border)]`}
|
||||
>
|
||||
<h2 className={`text-lg text-[var(--frontmatter-text)]`}>
|
||||
{l10n.t(LocalizationKey.dashboardDataViewDataViewTitle, selectedData?.title?.toLowerCase() || '')}
|
||||
{localize(LocalizationKey.dashboardDataViewDataViewTitle, selectedData?.title?.toLowerCase() || '')}
|
||||
</h2>
|
||||
|
||||
<div className="py-4">
|
||||
@@ -259,13 +329,13 @@ export const DataView: React.FunctionComponent<IDataViewProps> = (
|
||||
))}
|
||||
</Container>
|
||||
<Button className="mt-4" onClick={() => setSelectedIndex(null)}>
|
||||
{l10n.t(LocalizationKey.dashboardDataViewDataViewAdd)}
|
||||
{localize(LocalizationKey.dashboardDataViewDataViewAdd)}
|
||||
</Button>
|
||||
</>
|
||||
) : (
|
||||
<div className={`flex flex-col items-center justify-center`}>
|
||||
<p className={`text-[var(--frontmatter-text)]`}>
|
||||
{l10n.t(LocalizationKey.dashboardDataViewDataViewEmpty, selectedData.title.toLowerCase())}
|
||||
{localize(LocalizationKey.dashboardDataViewDataViewEmpty, selectedData.title.toLowerCase())}
|
||||
</p>
|
||||
</div>
|
||||
)}
|
||||
@@ -277,7 +347,7 @@ export const DataView: React.FunctionComponent<IDataViewProps> = (
|
||||
} py-6 px-4 overflow-auto`}
|
||||
>
|
||||
<h2 className={`text-lg text-[var(--frontmatter-text)]`}>
|
||||
{l10n.t(LocalizationKey.dashboardDataViewDataViewCreateOrModify, selectedData.title.toLowerCase())}
|
||||
{localize(LocalizationKey.dashboardDataViewDataViewCreateOrModify, selectedData.title.toLowerCase())}
|
||||
</h2>
|
||||
{selectedData ? (
|
||||
<DataForm
|
||||
@@ -287,12 +357,14 @@ export const DataView: React.FunctionComponent<IDataViewProps> = (
|
||||
onClear={() => setSelectedIndex(null)}
|
||||
/>
|
||||
) : (
|
||||
<p>{l10n.t(LocalizationKey.dashboardDataViewDataViewGetStarted)}</p>
|
||||
<p>{localize(LocalizationKey.dashboardDataViewDataViewGetStarted)}</p>
|
||||
)}
|
||||
</div>
|
||||
</>
|
||||
) : (
|
||||
<EmptyView />
|
||||
<EmptyView
|
||||
folders={fileCreationFolders}
|
||||
onCreate={createDataFile} />
|
||||
)}
|
||||
</section>
|
||||
</div>
|
||||
@@ -300,14 +372,14 @@ export const DataView: React.FunctionComponent<IDataViewProps> = (
|
||||
<div className="w-full h-full flex items-center justify-center">
|
||||
<div className={`flex flex-col items-center text-[var(--frontmatter-text)]`}>
|
||||
<CircleStackIcon className="w-32 h-32" />
|
||||
<p className="text-3xl mt-2">{l10n.t(LocalizationKey.dashboardDataViewDataViewNoDataFiles)}</p>
|
||||
<p className="text-3xl mt-2">{localize(LocalizationKey.dashboardDataViewDataViewNoDataFiles)}</p>
|
||||
<p className="text-xl mt-4">
|
||||
<a
|
||||
className={`text-[var(--frontmatter-link)] hover:text-[var(--frontmatter-link-hover)]`}
|
||||
href={WEBSITE_LINKS.docs.dataDashboard}
|
||||
title={l10n.t(LocalizationKey.dashboardDataViewDataViewGetStartedLink)}
|
||||
title={localize(LocalizationKey.dashboardDataViewDataViewGetStartedLink)}
|
||||
>
|
||||
{l10n.t(LocalizationKey.dashboardDataViewDataViewGetStartedLink)}
|
||||
{localize(LocalizationKey.dashboardDataViewDataViewGetStartedLink)}
|
||||
</a>
|
||||
</p>
|
||||
</div>
|
||||
@@ -315,6 +387,8 @@ export const DataView: React.FunctionComponent<IDataViewProps> = (
|
||||
)
|
||||
}
|
||||
|
||||
{loading && <Spinner />}
|
||||
|
||||
<SponsorMsg
|
||||
beta={settings?.beta}
|
||||
version={settings?.versionInfo}
|
||||
|
||||
@@ -1,12 +1,18 @@
|
||||
import { ExclamationCircleIcon } from '@heroicons/react/24/outline';
|
||||
import * as React from 'react';
|
||||
import * as l10n from '@vscode/l10n';
|
||||
import { LocalizationKey } from '../../../localization';
|
||||
import { LocalizationKey, localize } from '../../../localization';
|
||||
import { DataFolder } from '../../../models';
|
||||
import { DropdownMenu, DropdownMenuContent } from '../../../components/shadcn/Dropdown';
|
||||
import { MenuButton, MenuItem } from '../Menu';
|
||||
|
||||
export interface IEmptyViewProps { }
|
||||
export interface IEmptyViewProps {
|
||||
folders: DataFolder[];
|
||||
onCreate: (folder: DataFolder) => void;
|
||||
}
|
||||
|
||||
export const EmptyView: React.FunctionComponent<IEmptyViewProps> = (
|
||||
props: React.PropsWithChildren<IEmptyViewProps>
|
||||
{ folders, onCreate }: React.PropsWithChildren<IEmptyViewProps>
|
||||
) => {
|
||||
|
||||
return (
|
||||
@@ -15,6 +21,32 @@ export const EmptyView: React.FunctionComponent<IEmptyViewProps> = (
|
||||
<h2 className={`text-xl text-[var(--frontmatter-secondary-text)]`}>
|
||||
{l10n.t(LocalizationKey.dashboardDataViewEmptyViewHeading)}
|
||||
</h2>
|
||||
|
||||
{
|
||||
onCreate && folders && folders.length > 0 && (
|
||||
<div className='mt-4'>
|
||||
<DropdownMenu>
|
||||
<MenuButton
|
||||
label={localize(LocalizationKey.dashboardDataViewDataViewCreateNew)}
|
||||
title={localize(LocalizationKey.dashboardDataViewDataViewSelectDataFolder)}
|
||||
className={`text-lg`}
|
||||
labelClass={`font-normal text-[var(--frontmatter-secondary-text)]`}
|
||||
/>
|
||||
|
||||
<DropdownMenuContent>
|
||||
{folders.map((folder) => (
|
||||
<MenuItem
|
||||
key={folder.id}
|
||||
title={folder.id}
|
||||
value={folder}
|
||||
onClick={() => onCreate(folder)}
|
||||
/>
|
||||
))}
|
||||
</DropdownMenuContent>
|
||||
</DropdownMenu>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -1,26 +1,33 @@
|
||||
import { ChevronDownIcon } from '@heroicons/react/24/solid';
|
||||
import * as React from 'react';
|
||||
import { DropdownMenuTrigger } from '../../../components/shadcn/Dropdown';
|
||||
import { cn } from '../../../utils/cn';
|
||||
|
||||
export interface IMenuButtonProps {
|
||||
label: string | JSX.Element;
|
||||
title: string;
|
||||
disabled?: boolean;
|
||||
className?: string;
|
||||
labelClass?: string;
|
||||
buttonClass?: string;
|
||||
}
|
||||
|
||||
export const MenuButton: React.FunctionComponent<IMenuButtonProps> = ({
|
||||
label,
|
||||
title,
|
||||
disabled
|
||||
disabled,
|
||||
className,
|
||||
labelClass,
|
||||
buttonClass,
|
||||
}: React.PropsWithChildren<IMenuButtonProps>) => {
|
||||
return (
|
||||
<div className={`group flex items-center shrink-0 ${disabled ? 'opacity-50' : ''}`}>
|
||||
<div className={`mr-2 font-medium flex items-center text-[var(--vscode-tab-inactiveForeground)]`}>
|
||||
<div className={cn(`group flex items-center shrink-0 ${disabled ? 'opacity-50' : ''} ${className || ""}`)}>
|
||||
<div className={cn(`mr-2 font-medium flex items-center text-[var(--vscode-tab-inactiveForeground)] ${labelClass || ""}`)}>
|
||||
{label}:
|
||||
</div>
|
||||
|
||||
<DropdownMenuTrigger
|
||||
className='text-[var(--vscode-textLink-foreground)] hover:text-[var(--vscode-textLink-activeForeground)] flex items-center focus:outline-none'
|
||||
className={cn(`text-[var(--vscode-textLink-foreground)] hover:text-[var(--vscode-textLink-activeForeground)] flex items-center focus:outline-none ${buttonClass || ""}`)}
|
||||
disabled={disabled}>
|
||||
<span>{title}</span>
|
||||
<ChevronDownIcon className={`-mr-1 ml-1 h-4 w-4`} aria-hidden="true" />
|
||||
|
||||
@@ -5,6 +5,7 @@ import {
|
||||
ContentType,
|
||||
CustomScript,
|
||||
CustomTaxonomy,
|
||||
DataFolder,
|
||||
DraftField,
|
||||
FilterType,
|
||||
Framework,
|
||||
@@ -43,6 +44,7 @@ export interface Settings {
|
||||
dashboardState: DashboardState;
|
||||
scripts: CustomScript[];
|
||||
dataFiles: DataFile[] | undefined;
|
||||
dataFolders: DataFolder[];
|
||||
dataTypes: DataType[] | undefined;
|
||||
isBacker: boolean | undefined;
|
||||
snippets: Snippets | undefined;
|
||||
|
||||
@@ -58,6 +58,7 @@ import { parseWinPath } from './parseWinPath';
|
||||
import { TaxonomyHelper } from './TaxonomyHelper';
|
||||
import { ContentType } from './ContentType';
|
||||
import { Logger } from './Logger';
|
||||
import { DataListener } from '../listeners/dashboard';
|
||||
|
||||
export class DashboardSettings {
|
||||
private static cachedSettings: ISettings | undefined = undefined;
|
||||
@@ -158,6 +159,7 @@ export class DashboardSettings {
|
||||
}
|
||||
},
|
||||
dataFiles: await this.getDataFiles(),
|
||||
dataFolders: Settings.get<DataFolder[]>(SETTING_DATA_FOLDERS) || [],
|
||||
dataTypes: Settings.get<DataType[]>(SETTING_DATA_TYPES),
|
||||
snippets: Settings.get<Snippets>(SETTING_CONTENT_SNIPPETS),
|
||||
snippetsWrapper: Settings.get<boolean>(SETTING_SNIPPETS_WRAPPER),
|
||||
@@ -217,16 +219,7 @@ export class DashboardSettings {
|
||||
|
||||
const dataFiles = [...dataJsonFiles, ...dataYmlFiles, ...dataYamlFiles];
|
||||
for (let dataFile of dataFiles) {
|
||||
clonedFiles.push({
|
||||
id: basename(dataFile.fsPath),
|
||||
title: basename(dataFile.fsPath),
|
||||
file: dataFile.fsPath,
|
||||
fileType: dataFile.fsPath.endsWith('.json') ? 'json' : 'yaml',
|
||||
labelField: folder.labelField,
|
||||
schema: folder.schema,
|
||||
type: folder.type,
|
||||
singleEntry: typeof folder.singleEntry === 'boolean' ? folder.singleEntry : false
|
||||
} as DataFile);
|
||||
clonedFiles.push(DataListener.createDataFileObject(dataFile.fsPath, folder));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,9 +3,14 @@ import { Logger } from './Logger';
|
||||
import { Notifications } from './Notifications';
|
||||
import * as l10n from '@vscode/l10n';
|
||||
import { LocalizationKey } from '../localization';
|
||||
import { Folders, WORKSPACE_PLACEHOLDER } from '../commands';
|
||||
|
||||
export const openFileInEditor = async (filePath: string) => {
|
||||
if (filePath) {
|
||||
if (filePath.startsWith(WORKSPACE_PLACEHOLDER)) {
|
||||
filePath = Folders.getAbsFilePath(filePath);
|
||||
}
|
||||
|
||||
try {
|
||||
const doc = await workspace.openTextDocument(Uri.file(filePath));
|
||||
await window.showTextDocument(doc, 1, false);
|
||||
|
||||
@@ -1,15 +1,17 @@
|
||||
import { workspace } from 'vscode';
|
||||
import { workspace, window } from 'vscode';
|
||||
import { DataFile } from './../../models/DataFile';
|
||||
import { DashboardMessage } from '../../dashboardWebView/DashboardMessage';
|
||||
import { BaseListener } from './BaseListener';
|
||||
import { DashboardCommand } from '../../dashboardWebView/DashboardCommand';
|
||||
import { Folders } from '../../commands/Folders';
|
||||
import { dirname } from 'path';
|
||||
import { basename, dirname, join } from 'path';
|
||||
import * as yaml from 'js-yaml';
|
||||
import { DataFileHelper, Logger } from '../../helpers';
|
||||
import { existsAsync, readFileAsync, writeFileAsync } from '../../utils';
|
||||
import { mkdirAsync } from '../../utils/mkdirAsync';
|
||||
import { PostMessageData } from '../../models';
|
||||
import { DataFolder, PostMessageData } from '../../models';
|
||||
import { LocalizationKey, localize } from '../../localization';
|
||||
import { SettingsListener } from './SettingsListener';
|
||||
|
||||
export class DataListener extends BaseListener {
|
||||
public static process(msg: PostMessageData) {
|
||||
@@ -26,11 +28,35 @@ export class DataListener extends BaseListener {
|
||||
case DashboardMessage.putDataEntries:
|
||||
this.processDataUpdate(msg?.payload);
|
||||
break;
|
||||
case DashboardMessage.createDataFile:
|
||||
this.createDataFile(msg.command, msg.requestId || '', msg.payload);
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a DataFile object based on the provided path and folder.
|
||||
*
|
||||
* @param path - The path of the file.
|
||||
* @param folder - The DataFolder object.
|
||||
* @returns The created DataFile object.
|
||||
*/
|
||||
public static createDataFileObject(path: string, folder: DataFolder): DataFile {
|
||||
const filePath = Folders.wsPath(path);
|
||||
return {
|
||||
id: basename(path),
|
||||
title: basename(path),
|
||||
file: filePath,
|
||||
fileType: path.endsWith('.json') ? 'json' : 'yaml',
|
||||
labelField: folder.labelField,
|
||||
schema: folder.schema,
|
||||
type: folder.type,
|
||||
singleEntry: typeof folder.singleEntry === 'boolean' ? folder.singleEntry : false
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Process the data update
|
||||
* @param msgData
|
||||
@@ -81,4 +107,57 @@ export class DataListener extends BaseListener {
|
||||
const entries = await DataFileHelper.process(msgData);
|
||||
this.sendMsg(DashboardCommand.dataFileEntries, entries);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new data file
|
||||
* @param command
|
||||
* @param requestId
|
||||
* @param data
|
||||
*/
|
||||
private static async createDataFile(command: string, requestId: string, dataFolder: DataFolder) {
|
||||
if (!command || !requestId || !dataFolder) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!dataFolder.id || !dataFolder.path) {
|
||||
this.sendError(
|
||||
command as DashboardCommand,
|
||||
requestId,
|
||||
localize(LocalizationKey.listenersPanelDataListenerCreateDataFileError)
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
const fileName = await window.showInputBox({
|
||||
title: localize(LocalizationKey.listenersPanelDataListenerCreateDataFileInputTitle),
|
||||
prompt: localize(LocalizationKey.listenersPanelDataListenerCreateDataFileInputTitle),
|
||||
ignoreFocusOut: true
|
||||
});
|
||||
|
||||
if (!fileName || fileName.trim() === '') {
|
||||
this.sendError(
|
||||
command as DashboardCommand,
|
||||
requestId,
|
||||
localize(LocalizationKey.listenersPanelDataListenerCreateDataFileNoFileName)
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
const absPath = Folders.getAbsFilePath(dataFolder.path);
|
||||
if (!(await existsAsync(absPath))) {
|
||||
const dirPath = dirname(absPath);
|
||||
if (!(await existsAsync(dirPath))) {
|
||||
await mkdirAsync(dirPath, { recursive: true });
|
||||
}
|
||||
}
|
||||
|
||||
// Check the file type and create the file
|
||||
const filePath = join(absPath, `${fileName}.${dataFolder.fileType || 'json'}`);
|
||||
await writeFileAsync(filePath, dataFolder.fileType === 'json' ? '{}' : '', 'utf8');
|
||||
|
||||
// Update the settings
|
||||
await SettingsListener.getSettings(true);
|
||||
const dataFile = DataListener.createDataFileObject(filePath, dataFolder);
|
||||
this.sendRequest(command as DashboardCommand, requestId, dataFile);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -479,6 +479,18 @@ export enum LocalizationKey {
|
||||
* Updated your data entries
|
||||
*/
|
||||
dashboardDataViewDataViewUpdateMessage = 'dashboard.dataView.dataView.update.message',
|
||||
/**
|
||||
* Create new data file
|
||||
*/
|
||||
dashboardDataViewDataViewCreateNew = 'dashboard.dataView.dataView.createNew',
|
||||
/**
|
||||
* Select data folder
|
||||
*/
|
||||
dashboardDataViewDataViewSelectDataFolder = 'dashboard.dataView.dataView.selectDataFolder',
|
||||
/**
|
||||
* Close data file
|
||||
*/
|
||||
dashboardDataViewDataViewCloseSelectedDataFile = 'dashboard.dataView.dataView.closeSelectedDataFile',
|
||||
/**
|
||||
* Select your date type first
|
||||
*/
|
||||
@@ -2592,6 +2604,18 @@ export enum LocalizationKey {
|
||||
* Something went wrong while parsing your front matter. Please check the contents of your file.
|
||||
*/
|
||||
listenersPanelDataListenerPushMetadataFrontMatterError = 'listeners.panel.dataListener.pushMetadata.frontMatter.error',
|
||||
/**
|
||||
* What is the name of the data file?
|
||||
*/
|
||||
listenersPanelDataListenerCreateDataFileInputTitle = 'listeners.panel.dataListener.createDataFile.inputTitle',
|
||||
/**
|
||||
* No data file id or path defined.
|
||||
*/
|
||||
listenersPanelDataListenerCreateDataFileError = 'listeners.panel.dataListener.createDataFile.error',
|
||||
/**
|
||||
* No filename provided.
|
||||
*/
|
||||
listenersPanelDataListenerCreateDataFileNoFileName = 'listeners.panel.dataListener.createDataFile.noFileName',
|
||||
/**
|
||||
* No active editor
|
||||
*/
|
||||
|
||||
@@ -5,4 +5,6 @@ export interface DataFolder {
|
||||
schema?: any;
|
||||
type?: string;
|
||||
singleEntry?: boolean;
|
||||
enableFileCreation?: boolean;
|
||||
fileType?: 'json' | 'yaml';
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user