From 2e69e371f5cccf381ca5f4aa692c774383d09d1e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Patrik=20Matias=CC=8Cko?= Date: Wed, 8 May 2024 10:54:37 +0200 Subject: [PATCH] FormGenerator update --- src/components/Atomic/Editor/Editor.tsx | 2 + src/components/Atomic/Editor/Editor.types.ts | 1 + .../Atomic/Headline/Headline.types.ts | 3 +- src/components/Atomic/Switch/Switch.styles.ts | 2 +- src/components/Atomic/Switch/Switch.tsx | 2 +- .../Switch/__snapshots__/Switch.test.tsx.snap | 26 +++- .../__snapshots__/TileToggle.test.tsx.snap | 17 ++- .../DevicesResourcesModal.tsx | 2 + .../FormGenerator/FormGenerator.tsx | 122 ++++++++++++++---- 9 files changed, 140 insertions(+), 37 deletions(-) diff --git a/src/components/Atomic/Editor/Editor.tsx b/src/components/Atomic/Editor/Editor.tsx index d42e01cd..52aa0090 100644 --- a/src/components/Atomic/Editor/Editor.tsx +++ b/src/components/Atomic/Editor/Editor.tsx @@ -24,6 +24,7 @@ const Editor = forwardRef((props, ref) => { onChange, onError, onResize, + onValidation, onViewChange, schema, style, @@ -89,6 +90,7 @@ const Editor = forwardRef((props, ref) => { statusBar: false, onChangeText, onValidationError: onValidationError, + onValidate: onValidation, schema, } diff --git a/src/components/Atomic/Editor/Editor.types.ts b/src/components/Atomic/Editor/Editor.types.ts index f85d2966..550766d7 100644 --- a/src/components/Atomic/Editor/Editor.types.ts +++ b/src/components/Atomic/Editor/Editor.types.ts @@ -20,6 +20,7 @@ export type Props = { onChange?: (json: any) => void onError?: (error: any) => void onResize?: (width: number, height: number, callback: () => void) => void + onValidation?: (data: any) => void onViewChange?: (fullview: boolean) => void schema?: [] | object style?: CSSProperties diff --git a/src/components/Atomic/Headline/Headline.types.ts b/src/components/Atomic/Headline/Headline.types.ts index e569543f..e70e5bd8 100644 --- a/src/components/Atomic/Headline/Headline.types.ts +++ b/src/components/Atomic/Headline/Headline.types.ts @@ -1,4 +1,4 @@ -import { ReactNode } from 'react' +import { CSSProperties, ReactNode } from 'react' export type HeadlineType = 'h1' | 'h2' | 'h3' | 'h4' | 'h5' | 'h6' @@ -7,6 +7,7 @@ export type Props = { children: ReactNode dataTestId?: string id?: string + style?: CSSProperties type?: HeadlineType } diff --git a/src/components/Atomic/Switch/Switch.styles.ts b/src/components/Atomic/Switch/Switch.styles.ts index 25f4c407..5e83ef4e 100644 --- a/src/components/Atomic/Switch/Switch.styles.ts +++ b/src/components/Atomic/Switch/Switch.styles.ts @@ -5,7 +5,7 @@ import styled from '@emotion/styled' import { ThemeType, get } from '../_theme' export const switchC = css` - display: flex; + display: inline-flex; align-items: center; ` diff --git a/src/components/Atomic/Switch/Switch.tsx b/src/components/Atomic/Switch/Switch.tsx index e6ae6a2a..b4754575 100644 --- a/src/components/Atomic/Switch/Switch.tsx +++ b/src/components/Atomic/Switch/Switch.tsx @@ -17,7 +17,7 @@ const Switch = forwardRef((props, ref) => { ref={ref} type='checkbox' /> - + {label &&
{label}
} diff --git a/src/components/Atomic/Switch/__snapshots__/Switch.test.tsx.snap b/src/components/Atomic/Switch/__snapshots__/Switch.test.tsx.snap index ca40ede2..e9e4148e 100644 --- a/src/components/Atomic/Switch/__snapshots__/Switch.test.tsx.snap +++ b/src/components/Atomic/Switch/__snapshots__/Switch.test.tsx.snap @@ -3,10 +3,10 @@ exports[` render correctly - snapshot 1`] = ` .emotion-0 { - display: -webkit-box; - display: -webkit-flex; - display: -ms-flexbox; - display: flex; + display: -webkit-inline-box; + display: -webkit-inline-flex; + display: -ms-inline-flexbox; + display: inline-flex; -webkit-align-items: center; -webkit-box-align: center; -ms-flex-align: center; @@ -45,6 +45,10 @@ exports[` render correctly - snapshot 1`] = ` bottom: 0; -webkit-transition: 0.4s; transition: 0.4s; + width: 24px; + height: 16px; + border-radius: 20px; + overflow: hidden; } .emotion-3:before { @@ -60,6 +64,11 @@ exports[` render correctly - snapshot 1`] = ` height: 12px; } +.emotion-3:before { + width: 12px; + height: 12px; +} + .emotion-6 { width: 32px; height: 20px; @@ -92,6 +101,10 @@ exports[` render correctly - snapshot 1`] = ` bottom: 0; -webkit-transition: 0.4s; transition: 0.4s; + width: 32px; + height: 20px; + border-radius: 26.6667px; + overflow: hidden; } .emotion-8:before { @@ -107,6 +120,11 @@ exports[` render correctly - snapshot 1`] = ` height: 16px; } +.emotion-8:before { + width: 16px; + height: 16px; +} + .emotion-25 { font-size: 14px; padding-left: 8px; diff --git a/src/components/Atomic/TileToggle/__snapshots__/TileToggle.test.tsx.snap b/src/components/Atomic/TileToggle/__snapshots__/TileToggle.test.tsx.snap index ab6f7568..89a37ad8 100644 --- a/src/components/Atomic/TileToggle/__snapshots__/TileToggle.test.tsx.snap +++ b/src/components/Atomic/TileToggle/__snapshots__/TileToggle.test.tsx.snap @@ -35,10 +35,10 @@ exports[` render correctly - snapshot 1`] = ` } .emotion-2 { - display: -webkit-box; - display: -webkit-flex; - display: -ms-flexbox; - display: flex; + display: -webkit-inline-box; + display: -webkit-inline-flex; + display: -ms-inline-flexbox; + display: inline-flex; -webkit-align-items: center; -webkit-box-align: center; -ms-flex-align: center; @@ -77,6 +77,10 @@ exports[` render correctly - snapshot 1`] = ` bottom: 0; -webkit-transition: 0.4s; transition: 0.4s; + width: 32px; + height: 20px; + border-radius: 26.6667px; + overflow: hidden; } .emotion-5:before { @@ -92,6 +96,11 @@ exports[` render correctly - snapshot 1`] = ` height: 16px; } +.emotion-5:before { + width: 16px; + height: 16px; +} +
= (props) => { const dataForSend = typeof jsonData === 'string' && jsonData.startsWith('"') && jsonData.endsWith('"') ? jsonData.replace(/"/g, '') : jsonData if (isUpdateModal) { + console.log('!!!') + console.log(dataForSend) updateResource(params, dataForSend) } else { createResource(params, dataForSend) diff --git a/src/components/Organisms/GeneratedResourceForm/FormGenerator/FormGenerator.tsx b/src/components/Organisms/GeneratedResourceForm/FormGenerator/FormGenerator.tsx index aaa82f23..b2650919 100644 --- a/src/components/Organisms/GeneratedResourceForm/FormGenerator/FormGenerator.tsx +++ b/src/components/Organisms/GeneratedResourceForm/FormGenerator/FormGenerator.tsx @@ -4,6 +4,7 @@ import { Controller, useForm } from 'react-hook-form' import get from 'lodash/get' import isObject from 'lodash/isObject' import isFunction from 'lodash/isFunction' +import set from 'lodash/set' import { PropertiesType, Property } from '../GeneratedResourceForm.types' import FormInput from '../../../Atomic/FormInput' @@ -15,14 +16,24 @@ import { ModalStrippedLine } from '../../../Atomic/Modal' import FormGroup from '../../../Atomic/FormGroup' import { Props } from './FormGenerator.types' import { knownResourceHref } from '../constants' +import Editor from '../../../Atomic/Editor' export const sortProperties = (properties: PropertiesType) => properties - ? Object.keys(properties).map((href: string) => { - // @ts-ignore - const property = properties[href] as Property - return { ...property, href } - }) + ? Object.keys(properties) + .map((href: string) => { + // @ts-ignore + const property = properties[href] as Property + return { ...property, href } + }) + .sort((a, b) => (a.href || a.href).localeCompare(b.href || b.href)) + .sort((a, b) => + a.hasOwnProperty('properties') && !b.hasOwnProperty('properties') + ? 1 + : b.hasOwnProperty('properties') && !a.hasOwnProperty('properties') + ? -1 + : 0 + ) : [] export const getHref = (parentHref: string, href: string) => `${parentHref !== '' ? parentHref + '/' : parentHref}${href}` @@ -35,6 +46,7 @@ const FormGenerator: FC = (props) => { const isSingleValueMode = useMemo(() => !isObject(values), [values]) const formDefaultValues = useMemo(() => (isSingleValueMode ? values : { [topHref]: values }), [isSingleValueMode, topHref, values]) const [hasError, setHasError] = useState(false) + const [editorErrors, setEditorErrors] = useState([]) const { control, @@ -47,30 +59,49 @@ const FormGenerator: FC = (props) => { }, [reset, resetFormKey]) const getDefaultValue = useCallback( - (href: string) => (isSingleValueMode ? values : get(values, href.replace(topHref, '').substring(1), '')), + (href: string) => (isSingleValueMode ? values : get(values, href.replace(topHref, '').substring(1).replace('/', '.'), '')), [isSingleValueMode, topHref, values] ) const handleValueChange = useCallback( - (value: any) => { + (value: any, href?: string) => { if (isFunction(onChange)) { if (isSingleValueMode) { onChange(value === undefined ? '' : value) + } else if (href) { + onChange(set(values, href, value === undefined ? '' : value)) } } }, - [onChange, isSingleValueMode] + [onChange, isSingleValueMode, values] + ) + + const handleEditorChange = useCallback( + (value: any, href: string) => { + try { + handleValueChange(JSON.parse(value), href) + setEditorErrors(editorErrors.filter((error) => error !== href)) + } catch (e) { + setEditorErrors([...editorErrors, href]) + } + }, + [editorErrors, handleValueChange] ) useEffect(() => { - if (isValid && hasError) { - setHasError(false) - isFunction(setFormError) && setFormError(false) - } else if (!isValid && !hasError) { + if (editorErrors.length > 0) { setHasError(true) isFunction(setFormError) && setFormError(true) + } else { + if (isValid && editorErrors.length === 0 && hasError) { + setHasError(false) + isFunction(setFormError) && setFormError(false) + } else if (!isValid && !hasError) { + setHasError(true) + isFunction(setFormError) && setFormError(true) + } } - }, [hasError, isValid, setFormError]) + }, [editorErrors, hasError, isValid, setFormError]) useEffect(() => { const buildProperties: any = (properties: PropertiesType, parentHref = '', readOnly = false, depth = 1) => @@ -111,7 +142,7 @@ const FormGenerator: FC = (props) => { name={field.name} onChange={(e) => { field.onChange(formatValue(e.target.value)) - handleValueChange(formatValue(e.target.value)) + handleValueChange(formatValue(e.target.value), property.href) }} readOnly={readOnlyP} rightContent={property.unit} @@ -138,33 +169,72 @@ const FormGenerator: FC = (props) => { smallPadding component={
- + { + field.onChange(e) + handleValueChange(e.target.checked, property.href) + }} + />
} - label={property.title} + label={property.title || property.href} /> )} /> ) - } else if (property.type === 'object' && property.properties) { - return ( - - - {property.title || property.href} + } else if (property.type === 'object') { + if (property.properties) { + return ( + + + + {property.title || property.href} + + + {buildProperties(property.properties, href, readOnlyP, depth + 1)} - {buildProperties(property.properties, href, readOnlyP, depth + 1)} - - ) + ) + } else { + return ( + ( + { + field.onChange(value) + handleEditorChange(value, property.href) + }} + /> + } + label={property.title || property.href} + /> + )} + /> + ) + } } else { return
} }) if (properties) { - console.log(properties) setComponents(buildProperties(properties)) } - }, [control, errors, getDefaultValue, handleValueChange, properties]) + }, [control, errors, getDefaultValue, handleEditorChange, handleValueChange, properties]) return <>{components} }