@bsol-oss/react-datatable5 8.0.1 → 8.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.ts +2 -0
- package/dist/index.js +242 -261
- package/dist/index.mjs +243 -262
- package/dist/types/components/Form/Form.d.ts +2 -0
- package/dist/types/components/Form/SchemaFormContext.d.ts +4 -2
- package/dist/types/components/Form/components/IdViewer.d.ts +3 -1
- package/dist/types/components/Form/components/StringInputField.d.ts +8 -5
- package/dist/types/components/Form/useSchemaContext.d.ts +4 -2
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -2,7 +2,7 @@ import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
|
|
|
2
2
|
import { Button as Button$1, AbsoluteCenter, Spinner, Span, IconButton, Portal, Dialog, RadioGroup as RadioGroup$1, Grid, Box, Slider as Slider$1, HStack, For, Flex, Text, Tag as Tag$1, Input, useDisclosure, DialogBackdrop, CheckboxCard as CheckboxCard$1, Menu, createRecipeContext, createContext as createContext$1, Pagination, usePaginationContext, Image, Card, DataList, Checkbox as Checkbox$1, Table as Table$1, Tooltip as Tooltip$1, Icon, MenuRoot as MenuRoot$1, MenuTrigger as MenuTrigger$1, EmptyState as EmptyState$2, VStack, List, Alert, Group, InputElement, Popover, Field as Field$1, NumberInput, Accordion, Show, RadioCard, CheckboxGroup, Heading, Center } from '@chakra-ui/react';
|
|
3
3
|
import { AiOutlineColumnWidth } from 'react-icons/ai';
|
|
4
4
|
import * as React from 'react';
|
|
5
|
-
import React__default, { createContext, useContext, useState, useEffect, useRef
|
|
5
|
+
import React__default, { createContext, useContext, useState, useEffect, useRef } from 'react';
|
|
6
6
|
import { MdFilterAlt, MdArrowUpward, MdArrowDownward, MdOutlineMoveDown, MdOutlineSort, MdOutlineViewColumn, MdFilterListAlt, MdPushPin, MdCancel, MdClear, MdOutlineChecklist, MdClose, MdSearch } from 'react-icons/md';
|
|
7
7
|
import { LuX, LuCheck, LuChevronRight, LuChevronDown } from 'react-icons/lu';
|
|
8
8
|
import Dayzed from '@bsol-oss/dayzed-react19';
|
|
@@ -3540,16 +3540,17 @@ const Field = React.forwardRef(function Field(props, ref) {
|
|
|
3540
3540
|
});
|
|
3541
3541
|
|
|
3542
3542
|
const useSchemaContext = () => {
|
|
3543
|
-
const { schema, serverUrl, order, ignore, onSubmit,
|
|
3543
|
+
const { schema, serverUrl, order, ignore, onSubmit, rowNumber, displayText, idMap, setIdMap, } = useContext(SchemaFormContext);
|
|
3544
3544
|
return {
|
|
3545
3545
|
schema,
|
|
3546
3546
|
serverUrl,
|
|
3547
3547
|
order,
|
|
3548
3548
|
ignore,
|
|
3549
3549
|
onSubmit,
|
|
3550
|
-
preLoadedValues,
|
|
3551
3550
|
rowNumber,
|
|
3552
3551
|
displayText,
|
|
3552
|
+
idMap,
|
|
3553
|
+
setIdMap,
|
|
3553
3554
|
};
|
|
3554
3555
|
};
|
|
3555
3556
|
|
|
@@ -3587,7 +3588,7 @@ const getTableData = async ({ serverUrl, in_table, searching = "", where = [], l
|
|
|
3587
3588
|
|
|
3588
3589
|
const IdPicker = ({ column, isMultiple = false }) => {
|
|
3589
3590
|
const { watch, formState: { errors }, setValue, } = useFormContext();
|
|
3590
|
-
const { schema, serverUrl, displayText } = useSchemaContext();
|
|
3591
|
+
const { schema, serverUrl, displayText, idMap, setIdMap } = useSchemaContext();
|
|
3591
3592
|
const { fieldRequired } = displayText;
|
|
3592
3593
|
const { required } = schema;
|
|
3593
3594
|
const isRequired = required?.some((columnId) => columnId === column);
|
|
@@ -3597,21 +3598,20 @@ const IdPicker = ({ column, isMultiple = false }) => {
|
|
|
3597
3598
|
const { total, showing, typeToSearch } = displayText;
|
|
3598
3599
|
const { gridColumn, gridRow, title, renderDisplay, foreign_key } = schema
|
|
3599
3600
|
.properties[column];
|
|
3600
|
-
const { table
|
|
3601
|
+
const { table, column: column_ref, display_column, } = foreign_key;
|
|
3601
3602
|
const [searchText, setSearchText] = useState();
|
|
3602
3603
|
const [limit, setLimit] = useState(10);
|
|
3603
3604
|
const [openSearchResult, setOpenSearchResult] = useState();
|
|
3604
3605
|
const [page, setPage] = useState(0);
|
|
3605
|
-
const [idMap, setIdMap] = useState({});
|
|
3606
3606
|
const ref = useRef(null);
|
|
3607
3607
|
const selectedIds = watch(column) ?? [];
|
|
3608
3608
|
const query = useQuery({
|
|
3609
|
-
queryKey: [`idpicker`, { searchText, limit, page }],
|
|
3609
|
+
queryKey: [`idpicker`, { column, searchText, limit, page }],
|
|
3610
3610
|
queryFn: async () => {
|
|
3611
3611
|
const data = await getTableData({
|
|
3612
3612
|
serverUrl,
|
|
3613
3613
|
searching: searchText ?? "",
|
|
3614
|
-
in_table:
|
|
3614
|
+
in_table: table,
|
|
3615
3615
|
limit: limit,
|
|
3616
3616
|
offset: page * 10,
|
|
3617
3617
|
});
|
|
@@ -3631,33 +3631,8 @@ const IdPicker = ({ column, isMultiple = false }) => {
|
|
|
3631
3631
|
enabled: (searchText ?? "")?.length > 0,
|
|
3632
3632
|
staleTime: 300000,
|
|
3633
3633
|
});
|
|
3634
|
-
useQuery({
|
|
3635
|
-
queryKey: [`idpicker`, { selectedIds }],
|
|
3636
|
-
queryFn: async () => {
|
|
3637
|
-
const data = await getTableData({
|
|
3638
|
-
serverUrl,
|
|
3639
|
-
in_table: in_table,
|
|
3640
|
-
limit: 1,
|
|
3641
|
-
where: [{ id: column_ref, value: watchId }],
|
|
3642
|
-
});
|
|
3643
|
-
const newMap = Object.fromEntries((data ?? { data: [] }).data.map((item) => {
|
|
3644
|
-
return [
|
|
3645
|
-
item[column_ref],
|
|
3646
|
-
{
|
|
3647
|
-
...item,
|
|
3648
|
-
},
|
|
3649
|
-
];
|
|
3650
|
-
}));
|
|
3651
|
-
setIdMap((state) => {
|
|
3652
|
-
return { ...state, ...newMap };
|
|
3653
|
-
});
|
|
3654
|
-
return data;
|
|
3655
|
-
},
|
|
3656
|
-
enabled: (selectedIds ?? []).length > 0,
|
|
3657
|
-
staleTime: 300000,
|
|
3658
|
-
});
|
|
3659
3634
|
const { isLoading, isFetching, data, isPending, isError } = query;
|
|
3660
|
-
const dataList =
|
|
3635
|
+
const dataList = data?.data ?? [];
|
|
3661
3636
|
const count = data?.count ?? 0;
|
|
3662
3637
|
const isDirty = (searchText?.length ?? 0) > 0;
|
|
3663
3638
|
const onSearchChange = async (event) => {
|
|
@@ -3733,32 +3708,16 @@ const DataListItem = React.forwardRef(function DataListItem(props, ref) {
|
|
|
3733
3708
|
return (jsxs(DataList.Item, { ref: ref, ...rest, children: [jsxs(DataList.ItemLabel, { flex: grow ? "1" : undefined, children: [label, info && jsx(InfoTip, { children: info })] }), jsx(DataList.ItemValue, { flex: grow ? "1" : undefined, children: value }), children] }));
|
|
3734
3709
|
});
|
|
3735
3710
|
|
|
3736
|
-
const IdViewer = ({ value, column }) => {
|
|
3737
|
-
const { schema,
|
|
3711
|
+
const IdViewer = ({ value, column, dataListItemProps, }) => {
|
|
3712
|
+
const { schema, idMap } = useSchemaContext();
|
|
3738
3713
|
if (schema.properties == undefined) {
|
|
3739
3714
|
throw new Error("schema properties when using DatePicker");
|
|
3740
3715
|
}
|
|
3741
3716
|
const { title, foreign_key } = schema.properties[column];
|
|
3742
3717
|
if (foreign_key === undefined) {
|
|
3743
|
-
throw new Error(
|
|
3718
|
+
throw new Error("foreign_key when variant is id-picker");
|
|
3744
3719
|
}
|
|
3745
|
-
const {
|
|
3746
|
-
const query = useQuery({
|
|
3747
|
-
queryKey: [`idpicker`, table, value],
|
|
3748
|
-
queryFn: async () => {
|
|
3749
|
-
return await getTableData({
|
|
3750
|
-
serverUrl,
|
|
3751
|
-
in_table: foreginKeyColumn ?? '',
|
|
3752
|
-
where: [
|
|
3753
|
-
{
|
|
3754
|
-
id: column,
|
|
3755
|
-
value: value,
|
|
3756
|
-
},
|
|
3757
|
-
],
|
|
3758
|
-
});
|
|
3759
|
-
},
|
|
3760
|
-
staleTime: 10000,
|
|
3761
|
-
});
|
|
3720
|
+
const { display_column } = foreign_key;
|
|
3762
3721
|
const getDataListProps = (value) => {
|
|
3763
3722
|
if (value == undefined || value.length <= 0) {
|
|
3764
3723
|
return {
|
|
@@ -3770,7 +3729,10 @@ const IdViewer = ({ value, column }) => {
|
|
|
3770
3729
|
value: value,
|
|
3771
3730
|
};
|
|
3772
3731
|
};
|
|
3773
|
-
|
|
3732
|
+
if (value === undefined) {
|
|
3733
|
+
return jsx(Fragment, { children: "undefined" });
|
|
3734
|
+
}
|
|
3735
|
+
return (jsx(DataListItem, { label: `${title ?? snakeToLabel(column)}`, ...getDataListProps(idMap[value][display_column]), ...dataListItemProps }));
|
|
3774
3736
|
};
|
|
3775
3737
|
|
|
3776
3738
|
const NumberInputRoot = React.forwardRef(function NumberInput$1(props, ref) {
|
|
@@ -3928,156 +3890,71 @@ const DatePicker = ({ column }) => {
|
|
|
3928
3890
|
} })] }) })] }), errors[`${column}`] && (jsx(Text, { color: "red.400", children: fieldRequired ?? "The field is requried" }))] }));
|
|
3929
3891
|
};
|
|
3930
3892
|
|
|
3931
|
-
|
|
3932
|
-
|
|
3893
|
+
function filterArray(array, searchTerm) {
|
|
3894
|
+
// Convert the search term to lower case for case-insensitive comparison
|
|
3895
|
+
const lowerCaseSearchTerm = searchTerm.toLowerCase();
|
|
3896
|
+
// Use the filter method to return an array of matching items
|
|
3897
|
+
return array.filter((item) => {
|
|
3898
|
+
// Convert each item to a string and check if it includes the search term
|
|
3899
|
+
return item.toString().toLowerCase().includes(lowerCaseSearchTerm);
|
|
3900
|
+
});
|
|
3901
|
+
}
|
|
3902
|
+
|
|
3903
|
+
const EnumPicker = ({ column, isMultiple = false }) => {
|
|
3904
|
+
const { watch, formState: { errors }, setValue, } = useFormContext();
|
|
3933
3905
|
const { schema, displayText } = useSchemaContext();
|
|
3934
|
-
const {
|
|
3906
|
+
const { fieldRequired, total, showing, typeToSearch } = displayText;
|
|
3935
3907
|
const { required } = schema;
|
|
3936
3908
|
const isRequired = required?.some((columnId) => columnId === column);
|
|
3937
|
-
const entries = Object.entries(getValues(column) ?? {});
|
|
3938
|
-
const [showNewEntries, setShowNewEntries] = useState(false);
|
|
3939
|
-
const [newKey, setNewKey] = useState();
|
|
3940
|
-
const [newValue, setNewValue] = useState();
|
|
3941
3909
|
if (schema.properties == undefined) {
|
|
3942
3910
|
throw new Error("schema properties when using DatePicker");
|
|
3943
3911
|
}
|
|
3944
|
-
const { gridColumn, gridRow, title } = schema.properties[column];
|
|
3945
|
-
|
|
3946
|
-
|
|
3947
|
-
|
|
3948
|
-
|
|
3949
|
-
|
|
3950
|
-
|
|
3951
|
-
|
|
3952
|
-
|
|
3953
|
-
|
|
3954
|
-
|
|
3955
|
-
|
|
3956
|
-
|
|
3957
|
-
|
|
3958
|
-
|
|
3959
|
-
|
|
3960
|
-
|
|
3961
|
-
|
|
3962
|
-
|
|
3963
|
-
|
|
3964
|
-
|
|
3965
|
-
|
|
3966
|
-
|
|
3967
|
-
|
|
3968
|
-
|
|
3969
|
-
|
|
3970
|
-
|
|
3971
|
-
|
|
3972
|
-
|
|
3973
|
-
|
|
3974
|
-
|
|
3975
|
-
|
|
3976
|
-
|
|
3977
|
-
|
|
3978
|
-
|
|
3979
|
-
|
|
3980
|
-
|
|
3981
|
-
|
|
3982
|
-
|
|
3983
|
-
|
|
3984
|
-
|
|
3985
|
-
|
|
3986
|
-
|
|
3987
|
-
|
|
3988
|
-
|
|
3989
|
-
|
|
3990
|
-
const hasContent = label || description || icon;
|
|
3991
|
-
const ContentWrapper = indicator ? RadioCard.ItemContent : React.Fragment;
|
|
3992
|
-
return (jsxs(RadioCard.Item, { ...rest, children: [jsx(RadioCard.ItemHiddenInput, { ref: ref, ...inputProps }), jsxs(RadioCard.ItemControl, { children: [indicatorPlacement === "start" && indicator, hasContent && (jsxs(ContentWrapper, { children: [icon, label && jsx(RadioCard.ItemText, { children: label }), description && (jsx(RadioCard.ItemDescription, { children: description })), indicatorPlacement === "inside" && indicator] })), indicatorPlacement === "end" && indicator] }), addon && jsx(RadioCard.ItemAddon, { children: addon })] }));
|
|
3993
|
-
});
|
|
3994
|
-
const RadioCardRoot = RadioCard.Root;
|
|
3995
|
-
RadioCard.Label;
|
|
3996
|
-
RadioCard.ItemIndicator;
|
|
3997
|
-
|
|
3998
|
-
const TagPicker = ({ column }) => {
|
|
3999
|
-
const { watch, formState: { errors }, setValue, } = useFormContext();
|
|
4000
|
-
const { schema, serverUrl } = useSchemaContext();
|
|
4001
|
-
if (schema.properties == undefined) {
|
|
4002
|
-
throw new Error("schema properties undefined when using DatePicker");
|
|
4003
|
-
}
|
|
4004
|
-
const { gridColumn, gridRow, in_table, object_id_column } = schema.properties[column];
|
|
4005
|
-
if (in_table === undefined) {
|
|
4006
|
-
throw new Error("in_table is undefined when using TagPicker");
|
|
4007
|
-
}
|
|
4008
|
-
if (object_id_column === undefined) {
|
|
4009
|
-
throw new Error("object_id_column is undefined when using TagPicker");
|
|
4010
|
-
}
|
|
4011
|
-
const query = useQuery({
|
|
4012
|
-
queryKey: [`tagpicker`, in_table],
|
|
4013
|
-
queryFn: async () => {
|
|
4014
|
-
return await getTableData({
|
|
4015
|
-
serverUrl,
|
|
4016
|
-
in_table: "tables_tags_view",
|
|
4017
|
-
where: [
|
|
4018
|
-
{
|
|
4019
|
-
id: "table_name",
|
|
4020
|
-
value: [in_table],
|
|
4021
|
-
},
|
|
4022
|
-
],
|
|
4023
|
-
limit: 100,
|
|
4024
|
-
});
|
|
4025
|
-
},
|
|
4026
|
-
staleTime: 10000,
|
|
4027
|
-
});
|
|
4028
|
-
const object_id = watch(object_id_column);
|
|
4029
|
-
const existingTagsQuery = useQuery({
|
|
4030
|
-
queryKey: [`existing`, in_table, object_id_column, object_id],
|
|
4031
|
-
queryFn: async () => {
|
|
4032
|
-
return await getTableData({
|
|
4033
|
-
serverUrl,
|
|
4034
|
-
in_table: in_table,
|
|
4035
|
-
where: [
|
|
4036
|
-
{
|
|
4037
|
-
id: object_id_column,
|
|
4038
|
-
value: object_id[0],
|
|
4039
|
-
},
|
|
4040
|
-
],
|
|
4041
|
-
limit: 100,
|
|
4042
|
-
});
|
|
4043
|
-
},
|
|
4044
|
-
enabled: object_id != undefined,
|
|
4045
|
-
staleTime: 10000,
|
|
4046
|
-
});
|
|
4047
|
-
const { isLoading, isFetching, data, isPending, isError } = query;
|
|
4048
|
-
const dataList = data?.data ?? [];
|
|
4049
|
-
const existingTagList = existingTagsQuery.data?.data ?? [];
|
|
4050
|
-
if (!!object_id === false) {
|
|
4051
|
-
return jsx(Fragment, {});
|
|
4052
|
-
}
|
|
4053
|
-
return (jsxs(Flex, { flexFlow: "column", gap: 4, gridColumn,
|
|
4054
|
-
gridRow, children: [isFetching && jsx(Fragment, { children: "isFetching" }), isLoading && jsx(Fragment, { children: "isLoading" }), isPending && jsx(Fragment, { children: "isPending" }), isError && jsx(Fragment, { children: "isError" }), dataList.map(({ parent_tag_name, all_tags, is_mutually_exclusive }) => {
|
|
4055
|
-
return (jsxs(Flex, { flexFlow: "column", gap: 2, children: [jsx(Text, { children: parent_tag_name }), is_mutually_exclusive && (jsx(RadioCardRoot, { defaultValue: "next", variant: "surface", onValueChange: (tagIds) => {
|
|
4056
|
-
const existedTags = Object.values(all_tags)
|
|
4057
|
-
.filter(({ id }) => {
|
|
4058
|
-
return existingTagList.some(({ tag_id }) => tag_id === id);
|
|
4059
|
-
})
|
|
4060
|
-
.map(({ id }) => {
|
|
4061
|
-
return id;
|
|
4062
|
-
});
|
|
4063
|
-
setValue(`${column}.${parent_tag_name}.current`, [
|
|
4064
|
-
tagIds.value,
|
|
4065
|
-
]);
|
|
4066
|
-
setValue(`${column}.${parent_tag_name}.old`, existedTags);
|
|
4067
|
-
}, children: jsx(Flex, { flexFlow: "wrap", gap: 2, children: Object.entries(all_tags).map(([tagName, { id }]) => {
|
|
4068
|
-
if (existingTagList.some(({ tag_id }) => tag_id === id)) {
|
|
4069
|
-
return (jsx(RadioCardItem, { label: tagName, value: id, flex: "0 0 0%", disabled: true }, `${tagName}-${id}`));
|
|
4070
|
-
}
|
|
4071
|
-
return (jsx(RadioCardItem, { label: tagName, value: id, flex: "0 0 0%", colorPalette: "blue" }, `${tagName}-${id}`));
|
|
4072
|
-
}) }) })), !is_mutually_exclusive && (jsx(CheckboxGroup, { onValueChange: (tagIds) => {
|
|
4073
|
-
setValue(`${column}.${parent_tag_name}.current`, tagIds);
|
|
4074
|
-
}, children: jsx(Flex, { flexFlow: "wrap", gap: 2, children: Object.entries(all_tags).map(([tagName, { id }]) => {
|
|
4075
|
-
if (existingTagList.some(({ tag_id }) => tag_id === id)) {
|
|
4076
|
-
return (jsx(CheckboxCard, { label: tagName, value: id, flex: "0 0 0%", disabled: true, colorPalette: "blue" }, `${tagName}-${id}`));
|
|
4077
|
-
}
|
|
4078
|
-
return (jsx(CheckboxCard, { label: tagName, value: id, flex: "0 0 0%" }, `${tagName}-${id}`));
|
|
4079
|
-
}) }) }))] }, `tag-${parent_tag_name}`));
|
|
4080
|
-
}), errors[`${column}`] && (jsx(Text, { color: "red.400", children: (errors[`${column}`]?.message ?? "No error message") }))] }));
|
|
3912
|
+
const { gridColumn, gridRow, title, renderDisplay } = schema.properties[column];
|
|
3913
|
+
const [searchText, setSearchText] = useState();
|
|
3914
|
+
const [limit, setLimit] = useState(10);
|
|
3915
|
+
const [openSearchResult, setOpenSearchResult] = useState();
|
|
3916
|
+
const ref = useRef(null);
|
|
3917
|
+
const watchEnum = watch(column);
|
|
3918
|
+
const watchEnums = (watch(column) ?? []);
|
|
3919
|
+
const properties = (schema.properties[column] ?? {});
|
|
3920
|
+
const dataList = properties.enum ?? [];
|
|
3921
|
+
const count = properties.enum?.length ?? 0;
|
|
3922
|
+
const isDirty = (searchText?.length ?? 0) > 0;
|
|
3923
|
+
const onSearchChange = async (event) => {
|
|
3924
|
+
setSearchText(event.target.value);
|
|
3925
|
+
setLimit(10);
|
|
3926
|
+
};
|
|
3927
|
+
return (jsxs(Field, { label: `${title ?? snakeToLabel(column)}`, required: isRequired, alignItems: "stretch", gridColumn,
|
|
3928
|
+
gridRow, children: [isMultiple && (jsxs(Flex, { flexFlow: "wrap", gap: 1, children: [watchEnums.map((enumValue) => {
|
|
3929
|
+
const item = enumValue;
|
|
3930
|
+
if (item === undefined) {
|
|
3931
|
+
return jsx(Fragment, { children: "undefined" });
|
|
3932
|
+
}
|
|
3933
|
+
return (jsx(Tag, { closable: true, onClick: () => {
|
|
3934
|
+
setSelectedEnums((state) => state.filter((id) => id != item));
|
|
3935
|
+
setValue(column, watchEnums.filter((id) => id != item));
|
|
3936
|
+
}, children: !!renderDisplay === true ? renderDisplay(item) : item }));
|
|
3937
|
+
}), jsx(Tag, { cursor: "pointer", onClick: () => {
|
|
3938
|
+
setOpenSearchResult(true);
|
|
3939
|
+
}, children: "Add" })] })), !isMultiple && (jsx(Button, { variant: "outline", onClick: () => {
|
|
3940
|
+
setOpenSearchResult(true);
|
|
3941
|
+
}, children: watchEnum })), jsxs(PopoverRoot, { open: openSearchResult, onOpenChange: (e) => setOpenSearchResult(e.open), closeOnInteractOutside: true, initialFocusEl: () => ref.current, positioning: { placement: "bottom-start" }, children: [jsx(PopoverTrigger, {}), jsx(PopoverContent, { children: jsxs(PopoverBody, { display: "grid", gap: 1, children: [jsx(Input, { placeholder: typeToSearch ?? "Type to search", onChange: (event) => {
|
|
3942
|
+
onSearchChange(event);
|
|
3943
|
+
setOpenSearchResult(true);
|
|
3944
|
+
}, autoComplete: "off", ref: ref }), jsx(PopoverTitle, {}), jsx(Text, { children: `${total ?? "Total"}: ${count}, ${showing ?? "Showing"} ${limit}` }), jsxs(Grid, { gridTemplateColumns: "repeat(auto-fit, minmax(15rem, 1fr))", overflow: "auto", maxHeight: "50vh", children: [jsx(Flex, { flexFlow: "column wrap", children: filterArray(dataList, searchText ?? "").map((item) => {
|
|
3945
|
+
const selected = isMultiple
|
|
3946
|
+
? watchEnums.some((enumValue) => item === enumValue)
|
|
3947
|
+
: watchEnum == item;
|
|
3948
|
+
return (jsx(Box, { cursor: "pointer", onClick: () => {
|
|
3949
|
+
if (!isMultiple) {
|
|
3950
|
+
setOpenSearchResult(false);
|
|
3951
|
+
setValue(column, item);
|
|
3952
|
+
return;
|
|
3953
|
+
}
|
|
3954
|
+
const newSet = new Set([...(watchEnums ?? []), item]);
|
|
3955
|
+
setValue(column, [...newSet]);
|
|
3956
|
+
}, ...(selected ? { color: "gray.400/50" } : {}), children: !!renderDisplay === true ? renderDisplay(item) : item }, `${column}-${item}`));
|
|
3957
|
+
}) }), isDirty && (jsxs(Fragment, { children: [dataList.length <= 0 && jsx(Fragment, { children: "Empty Search Result" }), " "] }))] })] }) })] }), errors[`${column}`] && (jsx(Text, { color: "red.400", children: fieldRequired ?? "The field is requried" }))] }));
|
|
4081
3958
|
};
|
|
4082
3959
|
|
|
4083
3960
|
function isEnteringWindow(_ref) {
|
|
@@ -4455,71 +4332,156 @@ const FilePicker = ({ column }) => {
|
|
|
4455
4332
|
}) }), errors[`${column}`] && (jsx(Text, { color: "red.400", children: fieldRequired ?? "The field is requried" }))] }));
|
|
4456
4333
|
};
|
|
4457
4334
|
|
|
4458
|
-
|
|
4459
|
-
|
|
4460
|
-
const lowerCaseSearchTerm = searchTerm.toLowerCase();
|
|
4461
|
-
// Use the filter method to return an array of matching items
|
|
4462
|
-
return array.filter((item) => {
|
|
4463
|
-
// Convert each item to a string and check if it includes the search term
|
|
4464
|
-
return item.toString().toLowerCase().includes(lowerCaseSearchTerm);
|
|
4465
|
-
});
|
|
4466
|
-
}
|
|
4467
|
-
|
|
4468
|
-
const EnumPicker = ({ column, isMultiple = false }) => {
|
|
4469
|
-
const { watch, formState: { errors }, setValue, } = useFormContext();
|
|
4335
|
+
const ObjectInput = ({ column }) => {
|
|
4336
|
+
const { formState: { errors }, setValue, getValues, } = useFormContext();
|
|
4470
4337
|
const { schema, displayText } = useSchemaContext();
|
|
4471
|
-
const {
|
|
4338
|
+
const { addNew, fieldRequired, save } = displayText;
|
|
4472
4339
|
const { required } = schema;
|
|
4473
4340
|
const isRequired = required?.some((columnId) => columnId === column);
|
|
4341
|
+
const entries = Object.entries(getValues(column) ?? {});
|
|
4342
|
+
const [showNewEntries, setShowNewEntries] = useState(false);
|
|
4343
|
+
const [newKey, setNewKey] = useState();
|
|
4344
|
+
const [newValue, setNewValue] = useState();
|
|
4474
4345
|
if (schema.properties == undefined) {
|
|
4475
4346
|
throw new Error("schema properties when using DatePicker");
|
|
4476
4347
|
}
|
|
4477
|
-
const { gridColumn, gridRow, title
|
|
4478
|
-
|
|
4479
|
-
|
|
4480
|
-
|
|
4481
|
-
|
|
4482
|
-
|
|
4483
|
-
|
|
4484
|
-
|
|
4485
|
-
|
|
4486
|
-
|
|
4487
|
-
|
|
4488
|
-
|
|
4489
|
-
|
|
4490
|
-
|
|
4491
|
-
|
|
4492
|
-
|
|
4493
|
-
|
|
4494
|
-
|
|
4495
|
-
|
|
4496
|
-
|
|
4497
|
-
|
|
4498
|
-
|
|
4499
|
-
|
|
4500
|
-
|
|
4501
|
-
|
|
4502
|
-
|
|
4503
|
-
|
|
4504
|
-
|
|
4505
|
-
|
|
4506
|
-
|
|
4507
|
-
|
|
4508
|
-
|
|
4509
|
-
|
|
4510
|
-
|
|
4511
|
-
|
|
4512
|
-
|
|
4513
|
-
|
|
4514
|
-
|
|
4515
|
-
|
|
4516
|
-
|
|
4517
|
-
|
|
4518
|
-
|
|
4519
|
-
|
|
4520
|
-
|
|
4521
|
-
|
|
4522
|
-
|
|
4348
|
+
const { gridColumn, gridRow, title } = schema.properties[column];
|
|
4349
|
+
return (jsxs(Field, { label: `${title ?? snakeToLabel(column)}`, required: isRequired, alignItems: "stretch", gridColumn, gridRow, children: [entries.map(([key, value]) => {
|
|
4350
|
+
return (jsxs(Grid, { templateColumns: "1fr 1fr auto", gap: 1, children: [jsx(Input, { value: key, onChange: (e) => {
|
|
4351
|
+
const filtered = entries.filter(([target]) => {
|
|
4352
|
+
return target !== key;
|
|
4353
|
+
});
|
|
4354
|
+
setValue(column, Object.fromEntries([...filtered, [e.target.value, value]]));
|
|
4355
|
+
}, autoComplete: "off" }), jsx(Input, { value: value, onChange: (e) => {
|
|
4356
|
+
setValue(column, {
|
|
4357
|
+
...getValues(column),
|
|
4358
|
+
[key]: e.target.value,
|
|
4359
|
+
});
|
|
4360
|
+
}, autoComplete: "off" }), jsx(IconButton, { variant: "ghost", onClick: () => {
|
|
4361
|
+
const filtered = entries.filter(([target]) => {
|
|
4362
|
+
return target !== key;
|
|
4363
|
+
});
|
|
4364
|
+
setValue(column, Object.fromEntries([...filtered]));
|
|
4365
|
+
}, children: jsx(CgClose, {}) })] }));
|
|
4366
|
+
}), jsx(Show, { when: showNewEntries, children: jsxs(Card.Root, { children: [jsx(Card.Body, { gap: "2", children: jsxs(Grid, { templateColumns: "1fr 1fr auto", gap: 1, children: [jsx(Input, { value: newKey, onChange: (e) => {
|
|
4367
|
+
setNewKey(e.target.value);
|
|
4368
|
+
}, autoComplete: "off" }), jsx(Input, { value: newValue, onChange: (e) => {
|
|
4369
|
+
setNewValue(e.target.value);
|
|
4370
|
+
}, autoComplete: "off" })] }) }), jsxs(Card.Footer, { justifyContent: "flex-end", children: [jsx(IconButton, { variant: "subtle", onClick: () => {
|
|
4371
|
+
setShowNewEntries(false);
|
|
4372
|
+
setNewKey(undefined);
|
|
4373
|
+
setNewValue(undefined);
|
|
4374
|
+
}, children: jsx(CgClose, {}) }), jsx(Button, { onClick: () => {
|
|
4375
|
+
if (!!newKey === false) {
|
|
4376
|
+
setShowNewEntries(false);
|
|
4377
|
+
setNewKey(undefined);
|
|
4378
|
+
setNewValue(undefined);
|
|
4379
|
+
return;
|
|
4380
|
+
}
|
|
4381
|
+
setValue(column, Object.fromEntries([...entries, [newKey, newValue]]));
|
|
4382
|
+
setShowNewEntries(false);
|
|
4383
|
+
setNewKey(undefined);
|
|
4384
|
+
setNewValue(undefined);
|
|
4385
|
+
}, children: save ?? "Save" })] })] }) }), jsx(Button, { onClick: () => {
|
|
4386
|
+
setShowNewEntries(true);
|
|
4387
|
+
setNewKey(undefined);
|
|
4388
|
+
setNewValue(undefined);
|
|
4389
|
+
}, children: addNew ?? "Add New" }), errors[`${column}`] && (jsx(Text, { color: "red.400", children: fieldRequired ?? "The field is requried" }))] }));
|
|
4390
|
+
};
|
|
4391
|
+
|
|
4392
|
+
const RadioCardItem = React.forwardRef(function RadioCardItem(props, ref) {
|
|
4393
|
+
const { inputProps, label, description, addon, icon, indicator = jsx(RadioCard.ItemIndicator, {}), indicatorPlacement = "end", ...rest } = props;
|
|
4394
|
+
const hasContent = label || description || icon;
|
|
4395
|
+
const ContentWrapper = indicator ? RadioCard.ItemContent : React.Fragment;
|
|
4396
|
+
return (jsxs(RadioCard.Item, { ...rest, children: [jsx(RadioCard.ItemHiddenInput, { ref: ref, ...inputProps }), jsxs(RadioCard.ItemControl, { children: [indicatorPlacement === "start" && indicator, hasContent && (jsxs(ContentWrapper, { children: [icon, label && jsx(RadioCard.ItemText, { children: label }), description && (jsx(RadioCard.ItemDescription, { children: description })), indicatorPlacement === "inside" && indicator] })), indicatorPlacement === "end" && indicator] }), addon && jsx(RadioCard.ItemAddon, { children: addon })] }));
|
|
4397
|
+
});
|
|
4398
|
+
const RadioCardRoot = RadioCard.Root;
|
|
4399
|
+
RadioCard.Label;
|
|
4400
|
+
RadioCard.ItemIndicator;
|
|
4401
|
+
|
|
4402
|
+
const TagPicker = ({ column }) => {
|
|
4403
|
+
const { watch, formState: { errors }, setValue, } = useFormContext();
|
|
4404
|
+
const { schema, serverUrl } = useSchemaContext();
|
|
4405
|
+
if (schema.properties == undefined) {
|
|
4406
|
+
throw new Error("schema properties undefined when using DatePicker");
|
|
4407
|
+
}
|
|
4408
|
+
const { gridColumn, gridRow, in_table, object_id_column } = schema.properties[column];
|
|
4409
|
+
if (in_table === undefined) {
|
|
4410
|
+
throw new Error("in_table is undefined when using TagPicker");
|
|
4411
|
+
}
|
|
4412
|
+
if (object_id_column === undefined) {
|
|
4413
|
+
throw new Error("object_id_column is undefined when using TagPicker");
|
|
4414
|
+
}
|
|
4415
|
+
const query = useQuery({
|
|
4416
|
+
queryKey: [`tagpicker`, in_table],
|
|
4417
|
+
queryFn: async () => {
|
|
4418
|
+
return await getTableData({
|
|
4419
|
+
serverUrl,
|
|
4420
|
+
in_table: "tables_tags_view",
|
|
4421
|
+
where: [
|
|
4422
|
+
{
|
|
4423
|
+
id: "table_name",
|
|
4424
|
+
value: [in_table],
|
|
4425
|
+
},
|
|
4426
|
+
],
|
|
4427
|
+
limit: 100,
|
|
4428
|
+
});
|
|
4429
|
+
},
|
|
4430
|
+
staleTime: 10000,
|
|
4431
|
+
});
|
|
4432
|
+
const object_id = watch(object_id_column);
|
|
4433
|
+
const existingTagsQuery = useQuery({
|
|
4434
|
+
queryKey: [`existing`, in_table, object_id_column, object_id],
|
|
4435
|
+
queryFn: async () => {
|
|
4436
|
+
return await getTableData({
|
|
4437
|
+
serverUrl,
|
|
4438
|
+
in_table: in_table,
|
|
4439
|
+
where: [
|
|
4440
|
+
{
|
|
4441
|
+
id: object_id_column,
|
|
4442
|
+
value: object_id[0],
|
|
4443
|
+
},
|
|
4444
|
+
],
|
|
4445
|
+
limit: 100,
|
|
4446
|
+
});
|
|
4447
|
+
},
|
|
4448
|
+
enabled: object_id != undefined,
|
|
4449
|
+
staleTime: 10000,
|
|
4450
|
+
});
|
|
4451
|
+
const { isLoading, isFetching, data, isPending, isError } = query;
|
|
4452
|
+
const dataList = data?.data ?? [];
|
|
4453
|
+
const existingTagList = existingTagsQuery.data?.data ?? [];
|
|
4454
|
+
if (!!object_id === false) {
|
|
4455
|
+
return jsx(Fragment, {});
|
|
4456
|
+
}
|
|
4457
|
+
return (jsxs(Flex, { flexFlow: "column", gap: 4, gridColumn,
|
|
4458
|
+
gridRow, children: [isFetching && jsx(Fragment, { children: "isFetching" }), isLoading && jsx(Fragment, { children: "isLoading" }), isPending && jsx(Fragment, { children: "isPending" }), isError && jsx(Fragment, { children: "isError" }), dataList.map(({ parent_tag_name, all_tags, is_mutually_exclusive }) => {
|
|
4459
|
+
return (jsxs(Flex, { flexFlow: "column", gap: 2, children: [jsx(Text, { children: parent_tag_name }), is_mutually_exclusive && (jsx(RadioCardRoot, { defaultValue: "next", variant: "surface", onValueChange: (tagIds) => {
|
|
4460
|
+
const existedTags = Object.values(all_tags)
|
|
4461
|
+
.filter(({ id }) => {
|
|
4462
|
+
return existingTagList.some(({ tag_id }) => tag_id === id);
|
|
4463
|
+
})
|
|
4464
|
+
.map(({ id }) => {
|
|
4465
|
+
return id;
|
|
4466
|
+
});
|
|
4467
|
+
setValue(`${column}.${parent_tag_name}.current`, [
|
|
4468
|
+
tagIds.value,
|
|
4469
|
+
]);
|
|
4470
|
+
setValue(`${column}.${parent_tag_name}.old`, existedTags);
|
|
4471
|
+
}, children: jsx(Flex, { flexFlow: "wrap", gap: 2, children: Object.entries(all_tags).map(([tagName, { id }]) => {
|
|
4472
|
+
if (existingTagList.some(({ tag_id }) => tag_id === id)) {
|
|
4473
|
+
return (jsx(RadioCardItem, { label: tagName, value: id, flex: "0 0 0%", disabled: true }, `${tagName}-${id}`));
|
|
4474
|
+
}
|
|
4475
|
+
return (jsx(RadioCardItem, { label: tagName, value: id, flex: "0 0 0%", colorPalette: "blue" }, `${tagName}-${id}`));
|
|
4476
|
+
}) }) })), !is_mutually_exclusive && (jsx(CheckboxGroup, { onValueChange: (tagIds) => {
|
|
4477
|
+
setValue(`${column}.${parent_tag_name}.current`, tagIds);
|
|
4478
|
+
}, children: jsx(Flex, { flexFlow: "wrap", gap: 2, children: Object.entries(all_tags).map(([tagName, { id }]) => {
|
|
4479
|
+
if (existingTagList.some(({ tag_id }) => tag_id === id)) {
|
|
4480
|
+
return (jsx(CheckboxCard, { label: tagName, value: id, flex: "0 0 0%", disabled: true, colorPalette: "blue" }, `${tagName}-${id}`));
|
|
4481
|
+
}
|
|
4482
|
+
return (jsx(CheckboxCard, { label: tagName, value: id, flex: "0 0 0%" }, `${tagName}-${id}`));
|
|
4483
|
+
}) }) }))] }, `tag-${parent_tag_name}`));
|
|
4484
|
+
}), errors[`${column}`] && (jsx(Text, { color: "red.400", children: (errors[`${column}`]?.message ?? "No error message") }))] }));
|
|
4523
4485
|
};
|
|
4524
4486
|
|
|
4525
4487
|
const idPickerSanityCheck = (column, foreign_key) => {
|
|
@@ -4538,7 +4500,7 @@ const idPickerSanityCheck = (column, foreign_key) => {
|
|
|
4538
4500
|
}
|
|
4539
4501
|
};
|
|
4540
4502
|
const FormInternal = () => {
|
|
4541
|
-
const { schema, serverUrl, displayText, order, ignore, onSubmit, rowNumber } = useSchemaContext();
|
|
4503
|
+
const { schema, serverUrl, displayText, order, ignore, onSubmit, rowNumber, idMap, } = useSchemaContext();
|
|
4542
4504
|
const { title, submit, empty, cancel, submitSuccess, submitAgain, confirm } = displayText;
|
|
4543
4505
|
const methods = useFormContext();
|
|
4544
4506
|
const [isSuccess, setIsSuccess] = useState(false);
|
|
@@ -4645,8 +4607,7 @@ const FormInternal = () => {
|
|
|
4645
4607
|
if (variant === "id-picker") {
|
|
4646
4608
|
idPickerSanityCheck(column, foreign_key);
|
|
4647
4609
|
return (jsx(IdViewer, { value: (validatedData ?? {})[column], column,
|
|
4648
|
-
gridColumn,
|
|
4649
|
-
gridRow }, `form-${key}`));
|
|
4610
|
+
dataListItemProps: { gridColumn, gridRow } }, `form-${key}`));
|
|
4650
4611
|
}
|
|
4651
4612
|
if (variant === "date-picker") {
|
|
4652
4613
|
const value = (validatedData ?? {})[column];
|
|
@@ -4684,6 +4645,22 @@ const FormInternal = () => {
|
|
|
4684
4645
|
});
|
|
4685
4646
|
return (jsx(DataListItem, { gridColumn: gridColumn ?? "span 4", gridRow: gridRow ?? "span 4", label: `${snakeToLabel(column)}`, ...getDataListProps(JSON.stringify(fileNames)) }, `form-${key}`));
|
|
4686
4647
|
}
|
|
4648
|
+
if (variant === "id-picker") {
|
|
4649
|
+
const value = (validatedData ?? {})[column];
|
|
4650
|
+
if (schema.properties == undefined) {
|
|
4651
|
+
throw new Error("schema properties when using DatePicker");
|
|
4652
|
+
}
|
|
4653
|
+
const { foreign_key } = schema.properties[column];
|
|
4654
|
+
if (foreign_key === undefined) {
|
|
4655
|
+
throw new Error("foreign_key when variant is id-picker");
|
|
4656
|
+
}
|
|
4657
|
+
const { display_column } = foreign_key;
|
|
4658
|
+
const mapped = value.map((item) => {
|
|
4659
|
+
return idMap[item][display_column];
|
|
4660
|
+
});
|
|
4661
|
+
return (jsxs(Grid, { flexFlow: "column", gridColumn,
|
|
4662
|
+
gridRow, children: [jsx(Text, { children: snakeToLabel(column) }), jsx(RecordDisplay, { object: mapped })] }, `form-${key}`));
|
|
4663
|
+
}
|
|
4687
4664
|
const objectString = JSON.stringify((validatedData ?? {})[column]);
|
|
4688
4665
|
return (jsx(DataListItem, { gridColumn: gridColumn ?? "span 4", gridRow: gridRow ?? "span 4", label: `${snakeToLabel(column)}`, ...getDataListProps(objectString) }, `form-${key}`));
|
|
4689
4666
|
}
|
|
@@ -4710,8 +4687,9 @@ const FormInternal = () => {
|
|
|
4710
4687
|
return jsx(Fragment, {});
|
|
4711
4688
|
}
|
|
4712
4689
|
//@ts-expect-error TODO: add more fields to support form-creation
|
|
4713
|
-
const { type, variant,
|
|
4690
|
+
const { type, variant, foreign_key } = values;
|
|
4714
4691
|
if (type === "string") {
|
|
4692
|
+
// @ts-expect-error enum should exists
|
|
4715
4693
|
if ((values.enum ?? []).length > 0) {
|
|
4716
4694
|
return jsx(EnumPicker, { column: key }, `form-${key}`);
|
|
4717
4695
|
}
|
|
@@ -4757,6 +4735,7 @@ const FormInternal = () => {
|
|
|
4757
4735
|
const Form = ({ schema, serverUrl, order = [], ignore = [], onSubmit = undefined, preLoadedValues = {}, rowNumber = undefined, displayText = {}, }) => {
|
|
4758
4736
|
const queryClient = new QueryClient();
|
|
4759
4737
|
const methods = useForm({ values: preLoadedValues });
|
|
4738
|
+
const [idMap, setIdMap] = useState({});
|
|
4760
4739
|
const { properties } = schema;
|
|
4761
4740
|
idListSanityCheck("order", order, properties);
|
|
4762
4741
|
idListSanityCheck("ignore", ignore, properties);
|
|
@@ -4770,6 +4749,8 @@ const Form = ({ schema, serverUrl, order = [], ignore = [], onSubmit = undefined
|
|
|
4770
4749
|
// @ts-expect-error TODO: find appropriate types
|
|
4771
4750
|
onSubmit,
|
|
4772
4751
|
rowNumber,
|
|
4752
|
+
idMap,
|
|
4753
|
+
setIdMap,
|
|
4773
4754
|
}, children: jsx(FormProvider, { ...methods, children: jsx(FormInternal, {}) }) }) }));
|
|
4774
4755
|
};
|
|
4775
4756
|
|