#406 - Single data entries

This commit is contained in:
Elio Struyf
2022-09-27 13:16:44 +02:00
parent cb2194bc48
commit 2b8f08c03c
7 changed files with 84 additions and 41 deletions
+12
View File
@@ -1,5 +1,17 @@
# Change Log
## [8.2.0] - 2022-xx-xx
### ✨ New features
### 🎨 Enhancements
- [#406](https://github.com/estruyf/vscode-front-matter/issues/406): Added support for single data entries in the data dashboard
### ⚡️ Optimizations
### 🐞 Fixes
## [8.1.1] - 2022-09-23
### 🐞 Fixes
+10
View File
@@ -550,6 +550,11 @@
"type": "string",
"default": "content",
"description": "If you are using data types, you can specify your type ID."
},
"singleEntry": {
"type": "boolean",
"description": "If you want to use a single entry for your data file.",
"default": false
}
},
"additionalProperties": false,
@@ -601,6 +606,11 @@
"type": "string",
"default": "content",
"description": "If you are using data types, you can specify your type ID."
},
"singleEntry": {
"type": "boolean",
"description": "If you want to use a single entry for your data files in the folder.",
"default": false
}
},
"additionalProperties": false,
@@ -3,7 +3,7 @@ import { Header } from '../Header';
import { useRecoilValue } from 'recoil';
import { SettingsSelector } from '../../state';
import { DataForm } from './DataForm';
import { useCallback, useEffect, useState } from 'react';
import { useCallback, useEffect, useMemo, useState } from 'react';
import { DataFile } from '../../../models/DataFile';
import { Messenger } from '@estruyf/vscode/dist/client';
import { DashboardMessage } from '../../DashboardMessage';
@@ -27,7 +27,7 @@ export interface IDataViewProps {}
export const DataView: React.FunctionComponent<IDataViewProps> = (props: React.PropsWithChildren<IDataViewProps>) => {
const [ selectedData, setSelectedData ] = useState<DataFile | null>(null);
const [ selectedIndex, setSelectedIndex ] = useState<number | null>(null);
const [ dataEntries, setDataEntries ] = useState<any[] | null>(null);
const [ dataEntries, setDataEntries ] = useState<any | any[] | null>(null);
const settings = useRecoilValue(SettingsSelector);
const setSchema = (dataFile: DataFile) => {
@@ -57,6 +57,12 @@ export const DataView: React.FunctionComponent<IDataViewProps> = (props: React.P
const onSubmit = useCallback((data: any) => {
if (selectedData?.singleEntry) {
// Needs to add a single entry
updateData(data);
return;
}
const dataClone: any[] = Object.assign([], dataEntries);
if (selectedIndex !== null && selectedIndex !== undefined) {
dataClone[selectedIndex] = data;
@@ -102,6 +108,14 @@ export const DataView: React.FunctionComponent<IDataViewProps> = (props: React.P
});
}, [selectedData]);
const dataEntry = useMemo(() => {
if (selectedData?.singleEntry) {
return dataEntries || {};
}
return (dataEntries && selectedIndex !== null && selectedIndex !== undefined) ? dataEntries[selectedIndex] : null;
}, [selectedData, , dataEntries, selectedIndex]);
useEffect(() => {
Messenger.listen(messageListener);
@@ -171,49 +185,53 @@ export const DataView: React.FunctionComponent<IDataViewProps> = (props: React.P
{
selectedData ? (
<>
<div className={`w-1/3 py-6 px-4 flex-1 border-r border-gray-200 dark:border-vulcan-300 overflow-auto`}>
<h2 className={`text-lg text-gray-500 dark:text-whisper-900`}>Your {selectedData?.title?.toLowerCase() || ""} data items</h2>
{
!selectedData.singleEntry && (
<div className={`w-1/3 py-6 px-4 flex-1 border-r border-gray-200 dark:border-vulcan-300 overflow-auto`}>
<h2 className={`text-lg text-gray-500 dark:text-whisper-900`}>Your {selectedData?.title?.toLowerCase() || ""} data items</h2>
<div className='py-4'>
{
(dataEntries && dataEntries.length > 0) ? (
<>
<Container onSortEnd={onSortEnd} useDragHandle>
{
(dataEntries || []).map((dataEntry, idx) => (
<SortableItem
key={dataEntry[selectedData.labelField] || `entry-${idx}`}
value={dataEntry[selectedData.labelField] || `Entry ${idx+1}`}
index={idx}
crntIndex={idx}
selectedIndex={selectedIndex}
onSelectedIndexChange={(index: number) => setSelectedIndex(index)}
onDeleteItem={deleteItem}
/>
))
}
</Container>
<Button
className='mt-4'
onClick={() => setSelectedIndex(null)}>
Add a new entry
</Button>
</>
) : (
<div className={`flex flex-col items-center justify-center`}>
<p className={`text-gray-500 dark:text-whisper-900`}>No {selectedData.title.toLowerCase()} data entries found</p>
</div>
)
}
</div>
</div>
<div className={`w-2/3 py-6 px-4 overflow-auto`}>
<div className='py-4'>
{
(dataEntries && dataEntries.length > 0) ? (
<>
<Container onSortEnd={onSortEnd} useDragHandle>
{
(dataEntries as any[] || []).map((dataEntry, idx) => (
<SortableItem
key={dataEntry[selectedData.labelField] || `entry-${idx}`}
value={dataEntry[selectedData.labelField] || `Entry ${idx+1}`}
index={idx}
crntIndex={idx}
selectedIndex={selectedIndex}
onSelectedIndexChange={(index: number) => setSelectedIndex(index)}
onDeleteItem={deleteItem}
/>
))
}
</Container>
<Button
className='mt-4'
onClick={() => setSelectedIndex(null)}>
Add a new entry
</Button>
</>
) : (
<div className={`flex flex-col items-center justify-center`}>
<p className={`text-gray-500 dark:text-whisper-900`}>No {selectedData.title.toLowerCase()} data entries found</p>
</div>
)
}
</div>
</div>
)
}
<div className={`${selectedData.singleEntry ? "w-full" : "w-2/3"} py-6 px-4 overflow-auto`}>
<h2 className={`text-lg text-gray-500 dark:text-whisper-900`}>Create or modify your {selectedData.title.toLowerCase()} data</h2>
{
selectedData ? (
<DataForm
schema={selectedData?.schema}
model={(dataEntries && selectedIndex !== null && selectedIndex !== undefined) ? dataEntries[selectedIndex] : null}
model={dataEntry}
onSubmit={onSubmit}
onClear={() => setSelectedIndex(null)} />
) : (
+2 -1
View File
@@ -113,7 +113,8 @@ export class DashboardSettings {
fileType: dataFile.fsPath.endsWith('.json') ? 'json' : 'yaml',
labelField: folder.labelField,
schema: folder.schema,
type: folder.type
type: folder.type,
singleEntry: typeof folder.singleEntry === 'boolean' ? folder.singleEntry : false,
} as DataFile)
}
}
+1 -1
View File
@@ -36,7 +36,7 @@ export class DataListener extends BaseListener {
* @param msgData
*/
private static processDataUpdate(msgData: any) {
const { file, fileType, entries } = msgData as { file: string, fileType: string, entries: any[] };
const { file, fileType, entries } = msgData as { file: string, fileType: string, entries: unknown | unknown[] };
const absPath = Folders.getAbsFilePath(file);
if (!existsSync(absPath)) {
+1
View File
@@ -6,4 +6,5 @@ export interface DataFile {
labelField: string;
schema?: any;
type?: string;
singleEntry?: boolean;
}
+1
View File
@@ -6,4 +6,5 @@ export interface DataFolder {
labelField: string;
schema?: any;
type?: string;
singleEntry?: boolean;
}