diff --git a/src/panelWebView/components/DataBlock/DataBlockField.tsx b/src/panelWebView/components/DataBlock/DataBlockField.tsx index ae60272f..13e3e943 100644 --- a/src/panelWebView/components/DataBlock/DataBlockField.tsx +++ b/src/panelWebView/components/DataBlock/DataBlockField.tsx @@ -7,7 +7,6 @@ import { DataBlockRecords, DataBlockSelector } from '.'; import { SortEnd } from 'react-sortable-hoc'; import { arrayMoveImmutable } from 'array-move'; import { IMetadata } from '../Metadata'; -import { MessageHelper } from '../../../helpers/MessageHelper'; export interface IDataBlockFieldProps { label: string; @@ -21,17 +20,21 @@ export interface IDataBlockFieldProps { parent: IMetadata, parentFields?: string[], blockData?: BlockFieldData, - onFieldUpdate?: (field: string | undefined, value: any, parents: string[]) => void + onFieldUpdate?: (field: string | undefined, value: any, parents: string[]) => void, + parentBlock?: string | null ) => (JSX.Element | null)[] | undefined onSubmit: (data: any) => void; + parentBlock: string | null | undefined; } -export const DataBlockField: React.FunctionComponent = ({ label, filePath, settings, field, parentFields = [], value, fieldsRenderer, onSubmit }: React.PropsWithChildren) => { +export const DataBlockField: React.FunctionComponent = ({ label, filePath, settings, field, parentFields = [], value, fieldsRenderer, onSubmit, parentBlock }: React.PropsWithChildren) => { const [ selectedIndex, setSelectedIndex ] = useState(null); const [ selectedGroup, setSelectedGroup ] = useState(null); const [ selectedBlockData, setSelectedBlockData ] = useState(null); + const [ hideSubBlock, setHideSubBlock ] = useState(true); - const stateKey = useMemo(() => `${filePath}-data_block-${field.name}`, [filePath, field.name]); + const SELECTION_STATE_KEY = useMemo(() => `${filePath}-data-selection-${field.name}`, [filePath, field.name]); + const DATA_STATE_KEY = useMemo(() => `${filePath}-data-state-${field.name}`, [filePath, field.name]); const onFieldUpdate = useCallback((crntField: string | undefined, crntValue: any, parents: string[]) => { const dataClone: any[] = Object.assign([], value); @@ -40,40 +43,21 @@ export const DataBlockField: React.FunctionComponent = ({ return; } + let data: any = {}; if (selectedIndex !== null && selectedIndex !== undefined) { - const data = Object.assign({}, dataClone[selectedIndex]); + data = Object.assign({}, dataClone[selectedIndex]); + } - let parentObj: any = data; - if (parents.length > 1) { - parents.shift(); - for (const parent of parents) { - if (!data[parent]) { - data[parent] = {}; - } + let parentObj: any = data; + parentObj[crntField] = crntValue; - parentObj = data[parent]; - } - } - - parentObj[crntField] = crntValue; + if (selectedIndex !== null && selectedIndex !== undefined) { dataClone[selectedIndex] = { ...data, fieldGroup: selectedGroup?.id }; } else { - const data: any = {}; - let parentObj: any = data; - if (parents.length > 1) { - parents.shift(); - for (const parent of parents) { - data[parent] = {}; - parentObj = data[parent]; - } - } - - parentObj[crntField] = crntValue; - dataClone.push({ ...data, fieldGroup: selectedGroup?.id @@ -81,7 +65,7 @@ export const DataBlockField: React.FunctionComponent = ({ const newIndex = dataClone.length - 1; setSelectedIndex(newIndex); - updateState(newIndex); + updateSelectionState(newIndex); } onSubmit(dataClone); @@ -96,6 +80,7 @@ export const DataBlockField: React.FunctionComponent = ({ dataClone.splice(index, 1); onSubmit(dataClone); + onAdd(); }, [value, selectedIndex, onSubmit]); const onGroupChange = (group: FieldGroup | null | undefined) => { @@ -107,19 +92,53 @@ export const DataBlockField: React.FunctionComponent = ({ } } + /** + * Store the current state + show the form + */ + const onShowForm = () => { + const dataClone = Object.assign([], value); + localStorage.setItem(DATA_STATE_KEY, JSON.stringify(dataClone)); + setHideSubBlock(false); + }; + + /** + * Reset the state back to the state before editing + */ + const onCancelForm = () => { + const prevState = localStorage.getItem(DATA_STATE_KEY); + if (prevState) { + const dataClone = JSON.parse(prevState); + onSubmit(dataClone); + } + setHideSubBlock(true); + onAdd(); + }; + + /** + * Remove the previous state and hide the form + */ + const onSaveForm = () => { + localStorage.removeItem(DATA_STATE_KEY); + setHideSubBlock(true); + onAdd(); + }; + + const onAdd = useCallback(() => { setSelectedIndex(null); setSelectedGroup(null); setSelectedBlockData({}); - updateState(undefined); + updateSelectionState(undefined); }, [setSelectedIndex, setSelectedGroup, setSelectedBlockData]); const onEdit = useCallback((index: number) => { - updateState(index); - + updateSelectionState(index); setSelectedIndex(index); + // Show the form + onShowForm(); + const fieldData = value[index]; if (index !== null && settings?.fieldGroups) { const fieldGroup = fieldData?.fieldGroup; @@ -143,15 +162,16 @@ export const DataBlockField: React.FunctionComponent = ({ }, [value, selectedIndex]); // Retrieving the state from local storage (does not need to be persistent) - const retrieveState = useCallback(() => { - const prevState = localStorage.getItem(stateKey); - return prevState ? parseInt(prevState) : undefined; - }, [stateKey]); + const retrieveSelectionState = useCallback(() => { + const prevState = localStorage.getItem(SELECTION_STATE_KEY); + const prevStateValue = prevState ? parseInt(prevState) : null; + return prevStateValue === null || isNaN(prevStateValue) ? undefined : prevStateValue; + }, [SELECTION_STATE_KEY]); // Storing the state to local storage (does not need to be persistent) - const updateState = useCallback((value: number | undefined) => { - localStorage.setItem(stateKey, value as any); - }, [stateKey]); + const updateSelectionState = useCallback((value: number | undefined) => { + localStorage.setItem(SELECTION_STATE_KEY, value as any); + }, [SELECTION_STATE_KEY]); useEffect(() => { if (selectedIndex !== null) { @@ -161,11 +181,21 @@ export const DataBlockField: React.FunctionComponent = ({ } , [selectedIndex, value, setSelectedBlockData]); useEffect(() => { - const stateIdx = retrieveState(); + if (parentBlock) { + onAdd(); + } + }, [parentBlock]); + + useEffect(() => { + const stateIdx = retrieveSelectionState(); if (stateIdx !== undefined) { onEdit(stateIdx); } }, []); + + if (parentBlock === null) { + return null; + } return (
@@ -176,33 +206,55 @@ export const DataBlockField: React.FunctionComponent = ({
- - { - selectedGroup?.fields && ( + (!hideSubBlock) ? (

- {selectedIndex !== null ? `Editing: ${selectedGroup.id} ${selectedIndex + 1}` : `Create a new ${selectedGroup?.id}`} + { + selectedGroup?.id ? ( + selectedIndex !== null ? `Editing: ${selectedGroup.id} ${selectedIndex + 1}` : `Create a new ${selectedGroup?.id}` + ) : ( + `Select a group` + ) + }

+ + { - fieldsRenderer( - selectedGroup?.fields, - selectedBlockData || {}, - [...parentFields, field.name], - { - parentFields: [...parentFields, field.name], - blockType: selectedGroup?.id || undefined, - selectedIndex: selectedIndex === null ? undefined : selectedIndex - }, - onFieldUpdate - ) + selectedGroup?.fields && ( + fieldsRenderer( + selectedGroup?.fields, + selectedBlockData || {}, + [...parentFields, field.name], + { + parentFields: [...parentFields, field.name], + blockType: selectedGroup?.id || undefined, + selectedIndex: selectedIndex === null ? undefined : selectedIndex + }, + onFieldUpdate, + selectedIndex === null ? null : `${field.name}-${selectedGroup?.id}-${selectedIndex}` + ) + ) } + +
+ + +
+ ) : ( + ) } diff --git a/src/panelWebView/components/Metadata.tsx b/src/panelWebView/components/Metadata.tsx index a075ab80..468035b9 100644 --- a/src/panelWebView/components/Metadata.tsx +++ b/src/panelWebView/components/Metadata.tsx @@ -63,6 +63,7 @@ const Metadata: React.FunctionComponent = ({settings, metadata, parentFields: string[] = [], blockData?: BlockFieldData, onFieldUpdate?: (field: string | undefined, value: any, parents: string[]) => void, + parentBlock?: string | null ) => { if (!ctFields) { return; @@ -106,6 +107,8 @@ const Metadata: React.FunctionComponent = ({settings, metadata, } else if (field.type === 'string') { const textValue = parent[field.name]; + console.log(textValue, parent, field) + let limit = -1; if (field.name === 'title') { limit = settings?.seo.title; @@ -284,6 +287,7 @@ const Metadata: React.FunctionComponent = ({settings, metadata, fieldsRenderer={renderFields} parentFields={parentFields} filePath={metadata.filePath as string} + parentBlock={parentBlock} onSubmit={(value) => onSendUpdate(field.name, value, parentFields)} /> ); diff --git a/src/panelWebView/styles.css b/src/panelWebView/styles.css index 60cef643..11228c25 100644 --- a/src/panelWebView/styles.css +++ b/src/panelWebView/styles.css @@ -5,6 +5,42 @@ padding: 1rem; } +.block_field__form__buttons { + display: flex; + justify-content: space-between; + margin-top: 1rem; + + button { + margin: 0 1rem; + + &:first-child { + margin-left: 0; + } + + &:last-child { + margin-right: 0; + } + } +} + +.block_field__form__button__save { + background-color: var(--vscode-button-background); + color: var(--vscode-button-foreground); + + &:hover { + background-color: var(--vscode-button-hoverBackground); + } +} + +.block_field__form__button__cancel { + background-color: var(--vscode-button-secondaryBackground); + color: var(--vscode-button-secondaryForeground); + + &:hover { + background-color: var(--vscode-button-secondaryHoverBackground); + } +} + .json_data__field { border: 1px dashed var(--vscode-button-secondaryBackground); color: var(--vscode--settings-headerForeground);