From 49ba2b0f6956159794de407b371e131bc72fd9a9 Mon Sep 17 00:00:00 2001 From: Joshen Lim Date: Wed, 28 Sep 2022 12:32:06 +0800 Subject: [PATCH 01/13] Update SelectEditor to use Listbox component from Ui library --- .../grid/components/editor/SelectEditor.tsx | 32 ++++++++++++------- studio/components/grid/utils/gridColumns.tsx | 8 ++++- studio/styles/grid.scss | 5 ++- 3 files changed, 32 insertions(+), 13 deletions(-) diff --git a/studio/components/grid/components/editor/SelectEditor.tsx b/studio/components/grid/components/editor/SelectEditor.tsx index cdbbd2a547c..fd41a84c46a 100644 --- a/studio/components/grid/components/editor/SelectEditor.tsx +++ b/studio/components/grid/components/editor/SelectEditor.tsx @@ -1,6 +1,8 @@ -import * as React from 'react' +import { Listbox } from '@supabase/ui' import { EditorProps } from '@supabase/react-data-grid' +import { useTrackedState } from 'components/grid/store' + interface SelectEditorProps extends EditorProps { options: { label: string; value: string }[] } @@ -12,10 +14,12 @@ export function SelectEditor({ onClose, options, }: SelectEditorProps) { + const state = useTrackedState() + const gridColumn = state.gridColumns.find((x) => x.name == column.key) + const value = row[column.key as keyof TRow] as unknown as string - function onChange(event: React.ChangeEvent) { - const value = event.target.value + function onChange(value: string) { if (!value || value == '') { onRowChange({ ...row, [column.key]: null }, true) } else { @@ -28,19 +32,25 @@ export function SelectEditor({ } return ( - + ) } diff --git a/studio/components/grid/utils/gridColumns.tsx b/studio/components/grid/utils/gridColumns.tsx index 049f9066e68..0d815aaab1c 100644 --- a/studio/components/grid/utils/gridColumns.tsx +++ b/studio/components/grid/utils/gridColumns.tsx @@ -91,6 +91,8 @@ function getColumnEditor(columnDefinition: SupaColumn, columnType: ColumnType) { return } + console.log('getColumnEditor', columnType, columnDefinition) + switch (columnType) { case 'boolean': { return columnDefinition.isNullable ? NullableBooleanEditor : BooleanEditor @@ -108,7 +110,11 @@ function getColumnEditor(columnDefinition: SupaColumn, columnType: ColumnType) { const options = columnDefinition.enum!.map((x) => { return { label: x, value: x } }) - return (p: any) => + if (columnDefinition.dataType === 'ARRAY') { + // MultiSelectEditor + } else { + return (p: any) => + } } case 'array': case 'json': { diff --git a/studio/styles/grid.scss b/studio/styles/grid.scss index 51af1b7e0e9..7da30942b20 100644 --- a/studio/styles/grid.scss +++ b/studio/styles/grid.scss @@ -386,7 +386,10 @@ */ .sb-grid-select-editor { - @apply h-full w-full; + button { + @apply border-none rounded-none shadow-none; + box-shadow: none !important + } } /* From 0df9a7a39dd1daf6b40171f19c71079823e16128 Mon Sep 17 00:00:00 2001 From: Joshen Lim Date: Wed, 28 Sep 2022 15:36:35 +0800 Subject: [PATCH 02/13] Midway implementing MultiSelectEditor --- .../components/editor/MultiSelectEditor.tsx | 76 +++++++++++++++++++ .../grid/components/editor/index.ts | 1 + studio/components/grid/utils/gridColumns.tsx | 13 ++-- studio/components/ui/MultiSelect/index.tsx | 3 +- 4 files changed, 84 insertions(+), 9 deletions(-) create mode 100644 studio/components/grid/components/editor/MultiSelectEditor.tsx diff --git a/studio/components/grid/components/editor/MultiSelectEditor.tsx b/studio/components/grid/components/editor/MultiSelectEditor.tsx new file mode 100644 index 00000000000..c8f316acd30 --- /dev/null +++ b/studio/components/grid/components/editor/MultiSelectEditor.tsx @@ -0,0 +1,76 @@ +import { Listbox } from '@supabase/ui' +import { EditorProps } from '@supabase/react-data-grid' + +import { useTrackedState } from 'components/grid/store' +import MultiSelect from 'components/ui/MultiSelect' + +interface MultiSelectEditorProps + extends EditorProps { + options?: { label: string; value: string }[] +} + +// Mainly for arrays (specifically enums) +// Array elements are not unique, so this supports selecting an option more than once +export function MultiSelectEditor({ + row, + column, + onRowChange, + onClose, +}: MultiSelectEditorProps) { + const state = useTrackedState() + const gridColumn = state.gridColumns.find((x) => x.name == column.key) + + // Hardcoded options for now + const options = [ + { label: 'Apple', value: 'apple' }, + { label: 'Orange', value: 'orange' }, + ] + + const value = row[column.key as keyof TRow] as unknown as string + console.log('value', value) + + function onChange(value: string) { + if (!value || value == '') { + onRowChange({ ...row, [column.key]: null }, true) + } else { + onRowChange({ ...row, [column.key]: value }, true) + } + } + + function onBlur() { + onClose(false) + } + + // return ( + // + // ) + + return ( + + + NULL + + {options.map(({ label, value }) => ( + + {label} + + ))} + + ) +} diff --git a/studio/components/grid/components/editor/index.ts b/studio/components/grid/components/editor/index.ts index af37e035773..d11ccfedb78 100644 --- a/studio/components/grid/components/editor/index.ts +++ b/studio/components/grid/components/editor/index.ts @@ -5,5 +5,6 @@ export * from './JsonEditor' export * from './NullableBooleanEditor' export * from './NumberEditor' export * from './SelectEditor' +export * from './MultiSelectEditor' export * from './TextEditor' export * from './TimeEditor' diff --git a/studio/components/grid/utils/gridColumns.tsx b/studio/components/grid/utils/gridColumns.tsx index 0d815aaab1c..33ed4bda265 100644 --- a/studio/components/grid/utils/gridColumns.tsx +++ b/studio/components/grid/utils/gridColumns.tsx @@ -19,6 +19,7 @@ import { DateTimeEditor, DateTimeWithTimezoneEditor, JsonEditor, + MultiSelectEditor, NullableBooleanEditor, NumberEditor, SelectEditor, @@ -91,8 +92,6 @@ function getColumnEditor(columnDefinition: SupaColumn, columnType: ColumnType) { return } - console.log('getColumnEditor', columnType, columnDefinition) - switch (columnType) { case 'boolean': { return columnDefinition.isNullable ? NullableBooleanEditor : BooleanEditor @@ -110,13 +109,11 @@ function getColumnEditor(columnDefinition: SupaColumn, columnType: ColumnType) { const options = columnDefinition.enum!.map((x) => { return { label: x, value: x } }) - if (columnDefinition.dataType === 'ARRAY') { - // MultiSelectEditor - } else { - return (p: any) => - } + return (p: any) => + } + case 'array': { + return MultiSelectEditor } - case 'array': case 'json': { return JsonEditor } diff --git a/studio/components/ui/MultiSelect/index.tsx b/studio/components/ui/MultiSelect/index.tsx index a3a85005d46..67c102f1e49 100644 --- a/studio/components/ui/MultiSelect/index.tsx +++ b/studio/components/ui/MultiSelect/index.tsx @@ -12,14 +12,15 @@ export interface MultiSelectOption { } interface Props { - options: MultiSelectOption[] value: string[] + options: MultiSelectOption[] label?: string placeholder?: string | ReactNode searchPlaceholder?: string descriptionText?: string | ReactNode emptyMessage?: string | ReactNode disabled?: boolean + allowDuplicateSelection?: boolean onChange?(x: string[]): void } From 105833d6221e37ab2e35ece61824b6fb5b385744 Mon Sep 17 00:00:00 2001 From: Joshen Lim Date: Wed, 28 Sep 2022 17:40:54 +0800 Subject: [PATCH 03/13] Implement MultiSelectEditor for grid, for an enum array column --- .../components/editor/MultiSelectEditor.tsx | 140 ++++++++++++------ studio/components/grid/utils/gridColumns.tsx | 9 +- studio/components/ui/MultiSelect/index.tsx | 3 +- 3 files changed, 100 insertions(+), 52 deletions(-) diff --git a/studio/components/grid/components/editor/MultiSelectEditor.tsx b/studio/components/grid/components/editor/MultiSelectEditor.tsx index c8f316acd30..cf6d0eb9691 100644 --- a/studio/components/grid/components/editor/MultiSelectEditor.tsx +++ b/studio/components/grid/components/editor/MultiSelectEditor.tsx @@ -1,14 +1,28 @@ -import { Listbox } from '@supabase/ui' +import { useState } from 'react' +import { Popover, IconX, IconPlus } from '@supabase/ui' import { EditorProps } from '@supabase/react-data-grid' import { useTrackedState } from 'components/grid/store' -import MultiSelect from 'components/ui/MultiSelect' +import { tryParseJson } from 'lib/helpers' -interface MultiSelectEditorProps - extends EditorProps { +interface Props extends EditorProps { options?: { label: string; value: string }[] } +const convertPgArrayToJsArray = (value: string): string[] => { + const valueArray = value + .slice(1, value.length - 1) + .split(',') + .map((x) => `"${x}"`) + const formattedValue = `[${valueArray.join(',')}]` + return tryParseJson(formattedValue) ?? [] +} + +const convertJsArraytoPgArray = (value: string[]) => { + if (value.length === 0) return null + else return `{${value.join(',')}}` +} + // Mainly for arrays (specifically enums) // Array elements are not unique, so this supports selecting an option more than once export function MultiSelectEditor({ @@ -16,61 +30,89 @@ export function MultiSelectEditor({ column, onRowChange, onClose, -}: MultiSelectEditorProps) { + options = [], +}: Props) { const state = useTrackedState() const gridColumn = state.gridColumns.find((x) => x.name == column.key) - // Hardcoded options for now - const options = [ - { label: 'Apple', value: 'apple' }, - { label: 'Orange', value: 'orange' }, - ] + const originalValue = row[column.key as keyof TRow] as string + const [selectedValues, setSelectedValues] = useState(convertPgArrayToJsArray(originalValue)) - const value = row[column.key as keyof TRow] as unknown as string - console.log('value', value) - - function onChange(value: string) { - if (!value || value == '') { - onRowChange({ ...row, [column.key]: null }, true) - } else { - onRowChange({ ...row, [column.key]: value }, true) + const onOpenChange = (open: boolean) => { + if (!open) { + const updatedValue = convertJsArraytoPgArray(selectedValues) + if (updatedValue === originalValue) { + onClose() + } else { + onRowChange({ ...row, [column.key]: updatedValue }, true) + } } } - function onBlur() { - onClose(false) + const handleAdd = (option: { label: string; value: string }) => { + const updatedValues = selectedValues.concat([option.value]) + setSelectedValues(updatedValues) } - // return ( - // - // ) + const handleRemove = (idx: number) => { + const updatedValues = selectedValues.filter((x, index) => index !== idx) + setSelectedValues(updatedValues) + } return ( - - - NULL - - {options.map(({ label, value }) => ( - - {label} - - ))} - + +
+ {selectedValues.map((value, idx) => ( +
+ {value} + { + e.preventDefault() + handleRemove(idx) + }} + /> +
+ ))} +
+
+ {options.map((option) => ( +
handleAdd(option)} + > +

{option.label}

+
+ +

Add value

+
+
+ ))} +
+ + } + /> ) } diff --git a/studio/components/grid/utils/gridColumns.tsx b/studio/components/grid/utils/gridColumns.tsx index 33ed4bda265..7789f664774 100644 --- a/studio/components/grid/utils/gridColumns.tsx +++ b/studio/components/grid/utils/gridColumns.tsx @@ -112,7 +112,14 @@ function getColumnEditor(columnDefinition: SupaColumn, columnType: ColumnType) { return (p: any) => } case 'array': { - return MultiSelectEditor + if ((columnDefinition?.enum ?? []).length > 0) { + const options = columnDefinition.enum!.map((x) => { + return { label: x, value: x } + }) + return (p: any) => + } else { + return JsonEditor + } } case 'json': { return JsonEditor diff --git a/studio/components/ui/MultiSelect/index.tsx b/studio/components/ui/MultiSelect/index.tsx index 67c102f1e49..5a649240349 100644 --- a/studio/components/ui/MultiSelect/index.tsx +++ b/studio/components/ui/MultiSelect/index.tsx @@ -8,7 +8,7 @@ export interface MultiSelectOption { id: string | number value: string name: string - disabled: boolean + disabled?: boolean } interface Props { @@ -20,7 +20,6 @@ interface Props { descriptionText?: string | ReactNode emptyMessage?: string | ReactNode disabled?: boolean - allowDuplicateSelection?: boolean onChange?(x: string[]): void } From ee7754fbdc6da7870e3d8852104ac8727ed802d1 Mon Sep 17 00:00:00 2001 From: Joshen Lim Date: Thu, 29 Sep 2022 14:42:14 +0800 Subject: [PATCH 04/13] Update MultiSelect component to support selecting duplicate value --- .../components/editor/MultiSelectEditor.tsx | 16 +--- .../SidePanelEditor/RowEditor/InputField.tsx | 79 ++++++++++++++----- .../SidePanelEditor/RowEditor/RowEditor.tsx | 2 +- studio/components/ui/MultiSelect/index.tsx | 61 +++++++++----- studio/lib/helpers.ts | 48 +++++++---- 5 files changed, 135 insertions(+), 71 deletions(-) diff --git a/studio/components/grid/components/editor/MultiSelectEditor.tsx b/studio/components/grid/components/editor/MultiSelectEditor.tsx index cf6d0eb9691..5d444eed758 100644 --- a/studio/components/grid/components/editor/MultiSelectEditor.tsx +++ b/studio/components/grid/components/editor/MultiSelectEditor.tsx @@ -3,26 +3,12 @@ import { Popover, IconX, IconPlus } from '@supabase/ui' import { EditorProps } from '@supabase/react-data-grid' import { useTrackedState } from 'components/grid/store' -import { tryParseJson } from 'lib/helpers' +import { convertPgArrayToJsArray, convertJsArraytoPgArray } from 'lib/helpers' interface Props extends EditorProps { options?: { label: string; value: string }[] } -const convertPgArrayToJsArray = (value: string): string[] => { - const valueArray = value - .slice(1, value.length - 1) - .split(',') - .map((x) => `"${x}"`) - const formattedValue = `[${valueArray.join(',')}]` - return tryParseJson(formattedValue) ?? [] -} - -const convertJsArraytoPgArray = (value: string[]) => { - if (value.length === 0) return null - else return `{${value.join(',')}}` -} - // Mainly for arrays (specifically enums) // Array elements are not unique, so this supports selecting an option more than once export function MultiSelectEditor({ diff --git a/studio/components/interfaces/TableGridEditor/SidePanelEditor/RowEditor/InputField.tsx b/studio/components/interfaces/TableGridEditor/SidePanelEditor/RowEditor/InputField.tsx index 7fb90d8e9d5..f72b4eec940 100644 --- a/studio/components/interfaces/TableGridEditor/SidePanelEditor/RowEditor/InputField.tsx +++ b/studio/components/interfaces/TableGridEditor/SidePanelEditor/RowEditor/InputField.tsx @@ -5,6 +5,8 @@ import { Button, Select, Input, IconLink, IconArrowRight, IconEdit2 } from '@sup import { RowField } from './RowEditor.types' import DateTimeInput from './DateTimeInput' import { TEXT_TYPES, JSON_TYPES, DATETIME_TYPES } from '../SidePanelEditor.constants' +import MultiSelect from 'components/ui/MultiSelect' +import { convertPgArrayToJsArray, convertJsArraytoPgArray, uuidv4 } from 'lib/helpers' interface Props { field: RowField @@ -23,29 +25,68 @@ const InputField: FC = ({ onEditJson = () => {}, onViewForeignKey = () => {}, }) => { - if (field.enums.length > 0) { + // Hardcode for now + if (field.name === 'test') { + const formattedValue = convertPgArrayToJsArray(field.value) + const options = [ + { id: uuidv4(), value: 'VALUE_0', name: 'VALUE_0', disabled: false }, + { id: uuidv4(), value: 'VALUE_1', name: 'VALUE_1', disabled: false }, + { id: uuidv4(), value: 'VALUE_2', name: 'VALUE_2', disabled: false }, + ] return ( - +
+
+ + + {field.format} + +
+
+ { + const formattedValues = convertJsArraytoPgArray(values) + onUpdateField({ [field.name]: formattedValues }) + }} + /> +
+
) } + if (field.enums.length > 0) { + const isArray = field.format[0] === '_' + + if (isArray) { + console.log('Render') + } else { + return ( + + ) + } + } + if (!isUndefined(field.foreignKey)) { return ( = ({ return ( = ({ isEditingJson || isViewingReferenceRow ? ' mr-32' : '' }`} onCancel={closePanel} - hideFooter onInteractOutside={(event) => { const isToast = (event.target as Element)?.closest('#toast') if (isToast) { diff --git a/studio/components/ui/MultiSelect/index.tsx b/studio/components/ui/MultiSelect/index.tsx index 5a649240349..871eac8b8c1 100644 --- a/studio/components/ui/MultiSelect/index.tsx +++ b/studio/components/ui/MultiSelect/index.tsx @@ -1,6 +1,6 @@ import { useRef, useEffect, useState, FormEvent, KeyboardEvent, ReactNode } from 'react' import { orderBy, filter, without } from 'lodash' -import { Popover, IconCheck, IconAlertCircle, IconSearch } from '@supabase/ui' +import { Popover, IconCheck, IconAlertCircle, IconSearch, IconPlus } from '@supabase/ui' import { BadgeDisabled, BadgeSelected } from './Badges' @@ -8,7 +8,7 @@ export interface MultiSelectOption { id: string | number value: string name: string - disabled?: boolean + disabled: boolean } interface Props { @@ -20,6 +20,7 @@ interface Props { descriptionText?: string | ReactNode emptyMessage?: string | ReactNode disabled?: boolean + allowDuplicateSelection?: boolean onChange?(x: string[]): void } @@ -37,6 +38,7 @@ export default function MultiSelect({ searchPlaceholder = 'Search for option', emptyMessage, disabled, + allowDuplicateSelection = false, onChange = () => {}, }: Props) { const ref = useRef(null) @@ -51,7 +53,7 @@ export default function MultiSelect({ // Calculate width of the Popover useEffect(() => { setInputWidth(ref.current ? (ref.current as any).offsetWidth : inputWidth) - }, []) + }, [ref.current]) const width = `${inputWidth}px` @@ -69,11 +71,19 @@ export default function MultiSelect({ return isOptionSelected !== undefined } + const handleRemove = (idx: number) => { + const updatedSelected = selected.filter((x, index) => index !== idx) + setSelected(updatedSelected) + onChange(updatedSelected) + } + const handleChange = (option: MultiSelectOption) => { const _selected = selectedOptions const isActive = checkIfActive(option) - const updatedPayload = isActive + const updatedPayload = allowDuplicateSelection + ? [..._selected.concat([option.value])] + : isActive ? [...without(_selected, option.value)] : [..._selected.concat([option.value])] @@ -81,7 +91,10 @@ export default function MultiSelect({ const compulsoryOptions = options .filter((option) => option.disabled) .map((option) => option.name) - const formattedPayload = [...new Set(updatedPayload.concat(compulsoryOptions))] + + const formattedPayload = allowDuplicateSelection + ? updatedPayload.concat(compulsoryOptions) + : [...new Set(updatedPayload.concat(compulsoryOptions))] setSelected(formattedPayload) onChange(formattedPayload) @@ -131,6 +144,7 @@ export default function MultiSelect({ {filteredOptions.length >= 1 ? ( filteredOptions.map((option) => { const active = + !allowDuplicateSelection && selectedOptions && selectedOptions.find((selected) => { return selected === option.value @@ -140,11 +154,11 @@ export default function MultiSelect({ return (
handleChange(option)} className={[ 'text-typography-body-light dark:text-typography-body-dark', - 'flex cursor-pointer items-center justify-between transition', + 'group flex cursor-pointer items-center justify-between transition', 'space-x-1 rounded bg-transparent p-2 px-4 text-sm hover:bg-gray-600', `${active ? ' dark:bg-green-600 dark:bg-opacity-25' : ''}`, ].join(' ')} @@ -159,6 +173,12 @@ export default function MultiSelect({ }`} /> )} + {allowDuplicateSelection && ( +
+ +

Add value

+
+ )}
) }) @@ -207,21 +227,22 @@ export default function MultiSelect({ {selectedOptions.length === 0 && placeholder && (
{placeholder}
)} - {formattedOptions.map((option) => { - const active = - selectedOptions && - selectedOptions.find((selected) => { - return selected === option.value - }) - - if (option.disabled) { - return - } else if (active) { + {selectedOptions.map((value, idx) => { + const id = `${value}-${idx}` + const option = formattedOptions.find((x) => x.value === value) + const isDisabled = option?.disabled ?? false + if (!option) { + return <> + } else if (isDisabled) { + return + } else { return ( handleChange(option)} + key={id} + name={value} + handleRemove={() => + allowDuplicateSelection ? handleRemove(idx) : handleChange(option) + } /> ) } diff --git a/studio/lib/helpers.ts b/studio/lib/helpers.ts index 7797cce3830..1883401f9b8 100644 --- a/studio/lib/helpers.ts +++ b/studio/lib/helpers.ts @@ -168,31 +168,33 @@ export async function passwordStrength(value: string) { let strength = 0 if (value && value !== '') { - if(value.length > 99){ + if (value.length > 99) { message = `${PASSWORD_STRENGTH[0]} Maximum length of password exceeded` warning = `Password should be less than 100 characters` } else { - const response = await post(`${API_URL}/profile/password-check`, { password: value }) - if (!response.error) { - const { result } = response - const score = (PASSWORD_STRENGTH as any)[result.score] - const suggestions = result.feedback?.suggestions ? result.feedback.suggestions.join(' ') : '' + const response = await post(`${API_URL}/profile/password-check`, { password: value }) + if (!response.error) { + const { result } = response + const score = (PASSWORD_STRENGTH as any)[result.score] + const suggestions = result.feedback?.suggestions + ? result.feedback.suggestions.join(' ') + : '' - // set message :string - message = `${score} ${suggestions}` + // set message :string + message = `${score} ${suggestions}` - // set strength :number - strength = result.score + // set strength :number + strength = result.score - // warning message for anything below 4 strength :string - if (result.score < DEFAULT_MINIMUM_PASSWORD_STRENGTH) { - warning = `${ - result?.feedback?.warning ? result?.feedback?.warning + '.' : '' - } You need a stronger password.` + // warning message for anything below 4 strength :string + if (result.score < DEFAULT_MINIMUM_PASSWORD_STRENGTH) { + warning = `${ + result?.feedback?.warning ? result?.feedback?.warning + '.' : '' + } You need a stronger password.` + } } } } -} return { message, @@ -212,3 +214,17 @@ export const detectBrowser = () => { return 'Safari' } } + +export const convertPgArrayToJsArray = (value: string): string[] => { + const valueArray = value + .slice(1, value.length - 1) + .split(',') + .map((x) => `"${x}"`) + const formattedValue = `[${valueArray.join(',')}]` + return tryParseJson(formattedValue) ?? [] +} + +export const convertJsArraytoPgArray = (value: string[]) => { + if (value.length === 0) return null + else return `{${value.join(',')}}` +} From 465d1c752e0c262d6510699b85e6ecc59174a74b Mon Sep 17 00:00:00 2001 From: Joshen Lim Date: Thu, 29 Sep 2022 14:58:55 +0800 Subject: [PATCH 05/13] Remove hardcoded stuff --- .../SidePanelEditor/RowEditor/InputField.tsx | 62 +++++++++---------- .../RowEditor/RowEditor.utils.ts | 17 ++--- studio/components/ui/MultiSelect/index.tsx | 4 ++ studio/lib/helpers.ts | 2 + 4 files changed, 38 insertions(+), 47 deletions(-) diff --git a/studio/components/interfaces/TableGridEditor/SidePanelEditor/RowEditor/InputField.tsx b/studio/components/interfaces/TableGridEditor/SidePanelEditor/RowEditor/InputField.tsx index f72b4eec940..ce96a02b2f0 100644 --- a/studio/components/interfaces/TableGridEditor/SidePanelEditor/RowEditor/InputField.tsx +++ b/studio/components/interfaces/TableGridEditor/SidePanelEditor/RowEditor/InputField.tsx @@ -25,44 +25,38 @@ const InputField: FC = ({ onEditJson = () => {}, onViewForeignKey = () => {}, }) => { - // Hardcode for now - if (field.name === 'test') { - const formattedValue = convertPgArrayToJsArray(field.value) - const options = [ - { id: uuidv4(), value: 'VALUE_0', name: 'VALUE_0', disabled: false }, - { id: uuidv4(), value: 'VALUE_1', name: 'VALUE_1', disabled: false }, - { id: uuidv4(), value: 'VALUE_2', name: 'VALUE_2', disabled: false }, - ] - return ( -
-
- - - {field.format} - -
-
- { - const formattedValues = convertJsArraytoPgArray(values) - onUpdateField({ [field.name]: formattedValues }) - }} - /> -
-
- ) - } - if (field.enums.length > 0) { const isArray = field.format[0] === '_' if (isArray) { - console.log('Render') + const formattedValue = convertPgArrayToJsArray(field.value) + const options = field.enums.map((value: string) => { + return { id: uuidv4(), value, name: value, disabled: false } + }) + return ( +
+
+ + + {field.format} + +
+
+ { + const formattedValues = convertJsArraytoPgArray(values) + onUpdateField({ [field.name]: formattedValues }) + }} + /> +
+
+ ) } else { return (