@bsol-oss/react-datatable5 13.0.1-beta.1 → 13.0.1-beta.3
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 +33 -3
- package/dist/index.js +92 -168
- package/dist/index.mjs +92 -168
- package/dist/types/components/Form/SchemaFormContext.d.ts +0 -1
- package/dist/types/components/Form/components/core/FormRoot.d.ts +1 -2
- package/dist/types/components/Form/components/fields/TagPicker.d.ts +1 -1
- package/dist/types/components/Form/components/fields/useIdPickerData.d.ts +3 -23
- package/dist/types/components/Form/components/types/CustomJSONSchema7.d.ts +32 -0
- package/dist/types/components/Form/components/viewers/TagViewer.d.ts +1 -1
- package/dist/types/components/Form/utils/getTableData.d.ts +1 -2
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -817,12 +817,25 @@ interface TimePickerLabels {
|
|
|
817
817
|
placeholder?: string;
|
|
818
818
|
emptyMessage?: string;
|
|
819
819
|
}
|
|
820
|
+
interface LoadInitialValuesParams {
|
|
821
|
+
ids: string[];
|
|
822
|
+
foreign_key: ForeignKeyProps;
|
|
823
|
+
setIdMap: React__default.Dispatch<React__default.SetStateAction<Record<string, object>>>;
|
|
824
|
+
}
|
|
825
|
+
interface LoadInitialValuesResult {
|
|
826
|
+
data: {
|
|
827
|
+
data: Record<string, any>[];
|
|
828
|
+
count: number;
|
|
829
|
+
};
|
|
830
|
+
idMap: Record<string, object>;
|
|
831
|
+
}
|
|
820
832
|
interface CustomJSONSchema7 extends JSONSchema7 {
|
|
821
833
|
gridColumn?: string;
|
|
822
834
|
gridRow?: string;
|
|
823
835
|
foreign_key?: ForeignKeyProps;
|
|
824
836
|
variant?: string;
|
|
825
837
|
renderDisplay?: (item: unknown) => ReactNode;
|
|
838
|
+
loadInitialValues?: (params: LoadInitialValuesParams) => Promise<LoadInitialValuesResult>;
|
|
826
839
|
inputRender?: (props: {
|
|
827
840
|
column: string;
|
|
828
841
|
schema: CustomJSONSchema7;
|
|
@@ -844,6 +857,24 @@ interface CustomJSONSchema7 extends JSONSchema7 {
|
|
|
844
857
|
numberStorageType?: 'string' | 'number';
|
|
845
858
|
errorMessages?: Partial<Record<ValidationErrorType | string, string>>;
|
|
846
859
|
filePicker?: FilePickerProps;
|
|
860
|
+
tagPicker?: {
|
|
861
|
+
queryFn?: (params: {
|
|
862
|
+
in_table: string;
|
|
863
|
+
where?: {
|
|
864
|
+
id: string;
|
|
865
|
+
value: string[];
|
|
866
|
+
}[];
|
|
867
|
+
limit?: number;
|
|
868
|
+
offset?: number;
|
|
869
|
+
searching?: string;
|
|
870
|
+
}) => Promise<{
|
|
871
|
+
data: {
|
|
872
|
+
data: any[];
|
|
873
|
+
count: number;
|
|
874
|
+
};
|
|
875
|
+
idMap?: Record<string, object>;
|
|
876
|
+
}>;
|
|
877
|
+
};
|
|
847
878
|
}
|
|
848
879
|
declare const defaultRenderDisplay: (item: unknown) => ReactNode;
|
|
849
880
|
interface TagPickerProps {
|
|
@@ -869,7 +900,6 @@ interface FilePickerProps {
|
|
|
869
900
|
|
|
870
901
|
interface FormRootProps<TData extends FieldValues> {
|
|
871
902
|
schema: CustomJSONSchema7;
|
|
872
|
-
serverUrl: string;
|
|
873
903
|
requestUrl?: string;
|
|
874
904
|
idMap: Record<string, object>;
|
|
875
905
|
setIdMap: Dispatch<SetStateAction<Record<string, object>>>;
|
|
@@ -913,7 +943,7 @@ declare const idPickerSanityCheck: (column: string, foreign_key?: {
|
|
|
913
943
|
table?: string | undefined;
|
|
914
944
|
column?: string | undefined;
|
|
915
945
|
} | undefined) => void;
|
|
916
|
-
declare const FormRoot: <TData extends FieldValues>({ schema, idMap, setIdMap, form,
|
|
946
|
+
declare const FormRoot: <TData extends FieldValues>({ schema, idMap, setIdMap, form, translate, children, order, ignore, include, onSubmit, rowNumber, requestOptions, getUpdatedData, customErrorRenderer, customSuccessRenderer, displayConfig, requireConfirmation, dateTimePickerLabels, idPickerLabels, enumPickerLabels, filePickerLabels, formButtonLabels, timePickerLabels, insideDialog, }: FormRootProps<TData>) => react_jsx_runtime.JSX.Element;
|
|
917
947
|
|
|
918
948
|
interface DefaultFormProps<TData extends FieldValues> {
|
|
919
949
|
formConfig: Omit<FormRootProps<TData>, "children">;
|
|
@@ -1388,4 +1418,4 @@ declare module '@tanstack/react-table' {
|
|
|
1388
1418
|
}
|
|
1389
1419
|
}
|
|
1390
1420
|
|
|
1391
|
-
export { CalendarDisplay, type CalendarDisplayProps, type CalendarEvent, type CalendarProps, CardHeader, type CardHeaderProps, type CustomJSONSchema7, type CustomJSONSchema7Definition, DataDisplay, type DataDisplayProps, type DataResponse, DataTable, type DataTableDefaultState, type DataTableProps, DataTableServer, type DataTableServerProps, DatePickerInput, type DatePickerInputProps, type DatePickerLabels, type DatePickerProps, type DateTimePickerLabels, DefaultCardTitle, DefaultForm, type DefaultFormProps, DefaultTable, type DefaultTableProps, DefaultTableServer, type DefaultTableServerProps, DensityToggleButton, type DensityToggleButtonProps, type EditFilterButtonProps, EditSortingButton, type EditSortingButtonProps, type EditViewButtonProps, EmptyState, type EmptyStateProps, type EnumPickerLabels, ErrorAlert, type ErrorAlertProps, type ErrorMessageConfig, type ErrorMessageResult, type FieldErrorConfig, type FilePickerLabels, type FilePickerMediaFile, type FilePickerProps, FilterDialog, FormBody, type FormButtonLabels, FormRoot, type FormRootProps, FormTitle, type GetColumnsConfigs, type GetDateColorProps, type GetMultiDatesProps, type GetRangeDatesProps, type GetStyleProps, type GetVariantProps, GlobalFilter, type IdPickerLabels, MediaLibraryBrowser, type MediaLibraryBrowserProps, PageSizeControl, type PageSizeControlProps, Pagination, type QueryParams, type RangeCalendarProps, type RangeDatePickerLabels, type RangeDatePickerProps, RecordDisplay, type RecordDisplayProps, ReloadButton, type ReloadButtonProps, ResetFilteringButton, ResetSelectionButton, ResetSortingButton, type Result, RowCountText, SelectAllRowsToggle, type SelectAllRowsToggleProps, Table, TableBody, type TableBodyProps, TableCardContainer, type TableCardContainerProps, TableCards, type TableCardsProps, TableComponent, TableControls, type TableControlsProps, TableDataDisplay, type TableDataDisplayProps, TableFilter, TableFilterTags, TableFooter, type TableFooterProps, TableHeader, type TableHeaderProps, type TableHeaderTexts, TableLoadingComponent, type TableLoadingComponentProps, type TableProps, type TableRendererProps, type TableRowSelectorProps, TableSelector, TableSorter, TableViewer, type TagPickerProps, TextCell, type TextCellProps, type TimePickerLabels, type Translate, type UseDataTableProps, type UseDataTableReturn, type UseDataTableServerProps, type UseDataTableServerReturn, type UseFormProps, type ValidationErrorType, ViewDialog, buildErrorMessages, buildFieldErrors, buildRequiredErrors, convertToAjvErrorsFormat, createErrorMessage, defaultRenderDisplay, getColumns, getMultiDates, getRangeDates, idPickerSanityCheck, useDataTable, useDataTableContext, useDataTableServer, useForm, widthSanityCheck };
|
|
1421
|
+
export { CalendarDisplay, type CalendarDisplayProps, type CalendarEvent, type CalendarProps, CardHeader, type CardHeaderProps, type CustomJSONSchema7, type CustomJSONSchema7Definition, DataDisplay, type DataDisplayProps, type DataResponse, DataTable, type DataTableDefaultState, type DataTableProps, DataTableServer, type DataTableServerProps, DatePickerInput, type DatePickerInputProps, type DatePickerLabels, type DatePickerProps, type DateTimePickerLabels, DefaultCardTitle, DefaultForm, type DefaultFormProps, DefaultTable, type DefaultTableProps, DefaultTableServer, type DefaultTableServerProps, DensityToggleButton, type DensityToggleButtonProps, type EditFilterButtonProps, EditSortingButton, type EditSortingButtonProps, type EditViewButtonProps, EmptyState, type EmptyStateProps, type EnumPickerLabels, ErrorAlert, type ErrorAlertProps, type ErrorMessageConfig, type ErrorMessageResult, type FieldErrorConfig, type FilePickerLabels, type FilePickerMediaFile, type FilePickerProps, FilterDialog, FormBody, type FormButtonLabels, FormRoot, type FormRootProps, FormTitle, type GetColumnsConfigs, type GetDateColorProps, type GetMultiDatesProps, type GetRangeDatesProps, type GetStyleProps, type GetVariantProps, GlobalFilter, type IdPickerLabels, type LoadInitialValuesParams, type LoadInitialValuesResult, MediaLibraryBrowser, type MediaLibraryBrowserProps, PageSizeControl, type PageSizeControlProps, Pagination, type QueryParams, type RangeCalendarProps, type RangeDatePickerLabels, type RangeDatePickerProps, RecordDisplay, type RecordDisplayProps, ReloadButton, type ReloadButtonProps, ResetFilteringButton, ResetSelectionButton, ResetSortingButton, type Result, RowCountText, SelectAllRowsToggle, type SelectAllRowsToggleProps, Table, TableBody, type TableBodyProps, TableCardContainer, type TableCardContainerProps, TableCards, type TableCardsProps, TableComponent, TableControls, type TableControlsProps, TableDataDisplay, type TableDataDisplayProps, TableFilter, TableFilterTags, TableFooter, type TableFooterProps, TableHeader, type TableHeaderProps, type TableHeaderTexts, TableLoadingComponent, type TableLoadingComponentProps, type TableProps, type TableRendererProps, type TableRowSelectorProps, TableSelector, TableSorter, TableViewer, type TagPickerProps, TextCell, type TextCellProps, type TimePickerLabels, type Translate, type UseDataTableProps, type UseDataTableReturn, type UseDataTableServerProps, type UseDataTableServerReturn, type UseFormProps, type ValidationErrorType, ViewDialog, buildErrorMessages, buildFieldErrors, buildRequiredErrors, convertToAjvErrorsFormat, createErrorMessage, defaultRenderDisplay, getColumns, getMultiDates, getRangeDates, idPickerSanityCheck, useDataTable, useDataTableContext, useDataTableServer, useForm, widthSanityCheck };
|
package/dist/index.js
CHANGED
|
@@ -3714,7 +3714,7 @@ const TextWithCopy = ({ text, globalFilter, highlightedText, }) => {
|
|
|
3714
3714
|
const displayText = highlightedText !== undefined
|
|
3715
3715
|
? highlightedText
|
|
3716
3716
|
: highlightText$1(textValue, globalFilter);
|
|
3717
|
-
return (jsxRuntime.jsxs(react.HStack, { gap: 2, alignItems: "center", children: [jsxRuntime.jsx(react.Text, { as: "span", children: displayText }), jsxRuntime.jsx(react.Clipboard.Root, { value: textValue, children: jsxRuntime.jsx(react.Clipboard.Trigger, { asChild: true, children: jsxRuntime.jsx(react.IconButton, { size: "
|
|
3717
|
+
return (jsxRuntime.jsxs(react.HStack, { gap: 2, alignItems: "center", children: [jsxRuntime.jsx(react.Text, { as: "span", children: displayText }), jsxRuntime.jsx(react.Clipboard.Root, { value: textValue, children: jsxRuntime.jsx(react.Clipboard.Trigger, { asChild: true, children: jsxRuntime.jsx(react.IconButton, { size: "2xs", variant: "ghost", "aria-label": "Copy", fontSize: "1em", children: jsxRuntime.jsx(react.Clipboard.Indicator, { copied: jsxRuntime.jsx(lu.LuCheck, {}), children: jsxRuntime.jsx(lu.LuCopy, {}) }) }) }) })] }));
|
|
3718
3718
|
};
|
|
3719
3719
|
|
|
3720
3720
|
// Helper function to highlight matching text
|
|
@@ -4036,7 +4036,6 @@ const getColumns = ({ schema, include = [], ignore = [], width = [], meta = {},
|
|
|
4036
4036
|
//@ts-expect-error TODO: find appropriate type
|
|
4037
4037
|
const SchemaFormContext = React.createContext({
|
|
4038
4038
|
schema: {},
|
|
4039
|
-
serverUrl: '',
|
|
4040
4039
|
requestUrl: '',
|
|
4041
4040
|
order: [],
|
|
4042
4041
|
ignore: [],
|
|
@@ -4276,7 +4275,7 @@ const idPickerSanityCheck = (column, foreign_key) => {
|
|
|
4276
4275
|
throw new Error(`The key column does not exist in properties of column ${column} when using id-picker.`);
|
|
4277
4276
|
}
|
|
4278
4277
|
};
|
|
4279
|
-
const FormRoot = ({ schema, idMap, setIdMap, form,
|
|
4278
|
+
const FormRoot = ({ schema, idMap, setIdMap, form, translate, children, order = [], ignore = [], include = [], onSubmit = undefined, rowNumber = undefined, requestOptions = {}, getUpdatedData = () => { }, customErrorRenderer, customSuccessRenderer, displayConfig = {
|
|
4280
4279
|
showSubmitButton: true,
|
|
4281
4280
|
showResetButton: true,
|
|
4282
4281
|
showTitle: true,
|
|
@@ -4317,9 +4316,11 @@ const FormRoot = ({ schema, idMap, setIdMap, form, serverUrl, translate, childre
|
|
|
4317
4316
|
}
|
|
4318
4317
|
};
|
|
4319
4318
|
const defaultSubmitPromise = (data) => {
|
|
4319
|
+
if (!requestOptions.url) {
|
|
4320
|
+
throw new Error('requestOptions.url is required when onSubmit is not provided');
|
|
4321
|
+
}
|
|
4320
4322
|
const options = {
|
|
4321
4323
|
method: 'POST',
|
|
4322
|
-
url: `${serverUrl}`,
|
|
4323
4324
|
data: clearEmptyString(data),
|
|
4324
4325
|
...requestOptions,
|
|
4325
4326
|
};
|
|
@@ -4337,7 +4338,6 @@ const FormRoot = ({ schema, idMap, setIdMap, form, serverUrl, translate, childre
|
|
|
4337
4338
|
};
|
|
4338
4339
|
return (jsxRuntime.jsx(SchemaFormContext.Provider, { value: {
|
|
4339
4340
|
schema,
|
|
4340
|
-
serverUrl,
|
|
4341
4341
|
order,
|
|
4342
4342
|
ignore,
|
|
4343
4343
|
include,
|
|
@@ -5618,106 +5618,20 @@ const FormMediaLibraryBrowser = ({ column, schema, prefix, }) => {
|
|
|
5618
5618
|
}) })] }));
|
|
5619
5619
|
};
|
|
5620
5620
|
|
|
5621
|
-
const getTableData = async ({ serverUrl, in_table, searching = "", where = [], limit = 10, offset = 0, }) => {
|
|
5622
|
-
if (serverUrl === undefined || serverUrl.length == 0) {
|
|
5623
|
-
throw new Error("The serverUrl is missing");
|
|
5624
|
-
}
|
|
5625
|
-
if (in_table === undefined || in_table.length == 0) {
|
|
5626
|
-
throw new Error("The in_table is missing");
|
|
5627
|
-
}
|
|
5628
|
-
const options = {
|
|
5629
|
-
method: "GET",
|
|
5630
|
-
url: `${serverUrl}/api/g/${in_table}`,
|
|
5631
|
-
params: {
|
|
5632
|
-
searching,
|
|
5633
|
-
where,
|
|
5634
|
-
limit,
|
|
5635
|
-
offset
|
|
5636
|
-
},
|
|
5637
|
-
};
|
|
5638
|
-
try {
|
|
5639
|
-
const { data } = await axios.request(options);
|
|
5640
|
-
console.log(data);
|
|
5641
|
-
return data;
|
|
5642
|
-
}
|
|
5643
|
-
catch (error) {
|
|
5644
|
-
console.error(error);
|
|
5645
|
-
throw error;
|
|
5646
|
-
}
|
|
5647
|
-
};
|
|
5648
|
-
|
|
5649
5621
|
// Default renderDisplay function that stringifies JSON
|
|
5650
5622
|
const defaultRenderDisplay = (item) => {
|
|
5651
5623
|
return JSON.stringify(item);
|
|
5652
5624
|
};
|
|
5653
5625
|
|
|
5654
|
-
/**
|
|
5655
|
-
* Load initial values for IdPicker fields into idMap
|
|
5656
|
-
* Uses customQueryFn if available, otherwise falls back to getTableData
|
|
5657
|
-
*
|
|
5658
|
-
* @param params - Configuration for loading initial values
|
|
5659
|
-
* @returns Promise with fetched data and idMap
|
|
5660
|
-
*/
|
|
5661
|
-
const loadInitialValues = async ({ ids, foreign_key, serverUrl, setIdMap, }) => {
|
|
5662
|
-
if (!ids || ids.length === 0) {
|
|
5663
|
-
return { data: { data: [], count: 0 }, idMap: {} };
|
|
5664
|
-
}
|
|
5665
|
-
const { table, column: column_ref, customQueryFn } = foreign_key;
|
|
5666
|
-
// Filter out IDs that are already in idMap (optional optimization)
|
|
5667
|
-
// For now, we'll fetch all requested IDs to ensure consistency
|
|
5668
|
-
if (customQueryFn) {
|
|
5669
|
-
const { data, idMap: returnedIdMap } = await customQueryFn({
|
|
5670
|
-
searching: '',
|
|
5671
|
-
limit: ids.length,
|
|
5672
|
-
offset: 0,
|
|
5673
|
-
where: [
|
|
5674
|
-
{
|
|
5675
|
-
id: column_ref,
|
|
5676
|
-
value: ids.length === 1 ? ids[0] : ids, // CustomQueryFn accepts string | string[]
|
|
5677
|
-
},
|
|
5678
|
-
],
|
|
5679
|
-
});
|
|
5680
|
-
// Update idMap with returned values
|
|
5681
|
-
if (returnedIdMap && Object.keys(returnedIdMap).length > 0) {
|
|
5682
|
-
setIdMap((state) => {
|
|
5683
|
-
return { ...state, ...returnedIdMap };
|
|
5684
|
-
});
|
|
5685
|
-
}
|
|
5686
|
-
return { data, idMap: returnedIdMap || {} };
|
|
5687
|
-
}
|
|
5688
|
-
// Fallback to default getTableData
|
|
5689
|
-
const data = await getTableData({
|
|
5690
|
-
serverUrl,
|
|
5691
|
-
searching: '',
|
|
5692
|
-
in_table: table,
|
|
5693
|
-
limit: ids.length,
|
|
5694
|
-
offset: 0,
|
|
5695
|
-
where: [
|
|
5696
|
-
{
|
|
5697
|
-
id: column_ref,
|
|
5698
|
-
value: ids, // Always pass as array
|
|
5699
|
-
},
|
|
5700
|
-
],
|
|
5701
|
-
});
|
|
5702
|
-
// Build idMap from fetched data
|
|
5703
|
-
const newMap = Object.fromEntries((data ?? { data: [] }).data.map((item) => {
|
|
5704
|
-
return [
|
|
5705
|
-
item[column_ref],
|
|
5706
|
-
{
|
|
5707
|
-
...item,
|
|
5708
|
-
},
|
|
5709
|
-
];
|
|
5710
|
-
}));
|
|
5711
|
-
// Update idMap state
|
|
5712
|
-
setIdMap((state) => {
|
|
5713
|
-
return { ...state, ...newMap };
|
|
5714
|
-
});
|
|
5715
|
-
return { data: data, idMap: newMap };
|
|
5716
|
-
};
|
|
5717
5626
|
const useIdPickerData = ({ column, schema, prefix, isMultiple, }) => {
|
|
5718
5627
|
const { watch, getValues, formState: { errors }, setValue, } = reactHookForm.useFormContext();
|
|
5719
|
-
const {
|
|
5720
|
-
const { renderDisplay, foreign_key } = schema;
|
|
5628
|
+
const { idMap, setIdMap, idPickerLabels, insideDialog } = useSchemaContext();
|
|
5629
|
+
const { renderDisplay, loadInitialValues, foreign_key, variant } = schema;
|
|
5630
|
+
// loadInitialValues must be provided in schema for id-picker fields
|
|
5631
|
+
// It's used to load the record of the id so the display is human-readable
|
|
5632
|
+
if (variant === 'id-picker' && !loadInitialValues) {
|
|
5633
|
+
throw new Error(`loadInitialValues is required in schema for IdPicker field '${column}'. Please provide loadInitialValues function in the schema to load records for human-readable display.`);
|
|
5634
|
+
}
|
|
5721
5635
|
const { table, column: column_ref, customQueryFn, } = foreign_key;
|
|
5722
5636
|
const [searchText, setSearchText] = React.useState('');
|
|
5723
5637
|
const [debouncedSearchText, setDebouncedSearchText] = React.useState('');
|
|
@@ -5762,60 +5676,57 @@ const useIdPickerData = ({ column, schema, prefix, isMultiple, }) => {
|
|
|
5762
5676
|
const missingIdsKey = React.useMemo(() => {
|
|
5763
5677
|
return JSON.stringify([...missingIds].sort());
|
|
5764
5678
|
}, [missingIds]);
|
|
5679
|
+
// Include idMap state in query key to force refetch when idMap is reset (e.g., on remount from another page)
|
|
5680
|
+
// This ensures the query runs even if React Query has cached data for the same missing IDs
|
|
5681
|
+
const idMapStateKey = React.useMemo(() => {
|
|
5682
|
+
// Create a key based on whether the required IDs are in idMap
|
|
5683
|
+
const hasRequiredIds = currentValue.every((id) => idMap[id]);
|
|
5684
|
+
return hasRequiredIds ? 'complete' : 'incomplete';
|
|
5685
|
+
}, [currentValue, idMap]);
|
|
5765
5686
|
// Query to fetch initial values that are missing from idMap
|
|
5766
5687
|
// This query runs automatically when missingIds.length > 0 and updates idMap
|
|
5767
5688
|
const initialValuesQuery = reactQuery.useQuery({
|
|
5768
|
-
queryKey: [`idpicker-initial`, column, missingIdsKey],
|
|
5689
|
+
queryKey: [`idpicker-initial`, column, missingIdsKey, idMapStateKey],
|
|
5769
5690
|
queryFn: async () => {
|
|
5770
5691
|
if (missingIds.length === 0) {
|
|
5771
5692
|
return { data: [], count: 0 };
|
|
5772
5693
|
}
|
|
5773
|
-
// Use
|
|
5694
|
+
// Use schema's loadInitialValues (required for id-picker)
|
|
5695
|
+
if (!loadInitialValues) {
|
|
5696
|
+
throw new Error(`loadInitialValues is required in schema for IdPicker field '${column}'.`);
|
|
5697
|
+
}
|
|
5774
5698
|
const result = await loadInitialValues({
|
|
5775
5699
|
ids: missingIds,
|
|
5776
5700
|
foreign_key: foreign_key,
|
|
5777
|
-
serverUrl,
|
|
5778
5701
|
setIdMap,
|
|
5779
5702
|
});
|
|
5780
5703
|
return result.data;
|
|
5781
5704
|
},
|
|
5782
5705
|
enabled: missingIds.length > 0, // Only fetch if there are missing IDs
|
|
5783
|
-
staleTime:
|
|
5706
|
+
staleTime: 0, // Always consider data stale to refetch on remount
|
|
5707
|
+
refetchOnMount: true, // Always refetch when component remounts (e.g., from another page)
|
|
5708
|
+
refetchOnWindowFocus: false, // Don't refetch on window focus
|
|
5784
5709
|
});
|
|
5785
5710
|
const { isLoading: isLoadingInitialValues, isFetching: isFetchingInitialValues, } = initialValuesQuery;
|
|
5786
5711
|
// Query for search results (async loading)
|
|
5787
5712
|
const query = reactQuery.useQuery({
|
|
5788
5713
|
queryKey: [`idpicker`, { column, searchText: debouncedSearchText, limit }],
|
|
5789
5714
|
queryFn: async () => {
|
|
5790
|
-
|
|
5791
|
-
|
|
5792
|
-
|
|
5793
|
-
limit: limit,
|
|
5794
|
-
offset: 0,
|
|
5795
|
-
});
|
|
5796
|
-
setIdMap((state) => {
|
|
5797
|
-
return { ...state, ...idMap };
|
|
5798
|
-
});
|
|
5799
|
-
return data;
|
|
5715
|
+
// customQueryFn is required when serverUrl is not available
|
|
5716
|
+
if (!customQueryFn) {
|
|
5717
|
+
throw new Error(`customQueryFn is required in foreign_key for table ${table}. serverUrl has been removed.`);
|
|
5800
5718
|
}
|
|
5801
|
-
const data = await
|
|
5802
|
-
serverUrl,
|
|
5719
|
+
const { data, idMap } = await customQueryFn({
|
|
5803
5720
|
searching: debouncedSearchText ?? '',
|
|
5804
|
-
in_table: table,
|
|
5805
5721
|
limit: limit,
|
|
5806
5722
|
offset: 0,
|
|
5807
5723
|
});
|
|
5808
|
-
|
|
5809
|
-
|
|
5810
|
-
|
|
5811
|
-
{
|
|
5812
|
-
|
|
5813
|
-
|
|
5814
|
-
];
|
|
5815
|
-
}));
|
|
5816
|
-
setIdMap((state) => {
|
|
5817
|
-
return { ...state, ...newMap };
|
|
5818
|
-
});
|
|
5724
|
+
// Update idMap with returned values
|
|
5725
|
+
if (idMap && Object.keys(idMap).length > 0) {
|
|
5726
|
+
setIdMap((state) => {
|
|
5727
|
+
return { ...state, ...idMap };
|
|
5728
|
+
});
|
|
5729
|
+
}
|
|
5819
5730
|
return data;
|
|
5820
5731
|
},
|
|
5821
5732
|
enabled: true, // Always enabled for combobox
|
|
@@ -5939,6 +5850,7 @@ const useIdPickerData = ({ column, schema, prefix, isMultiple, }) => {
|
|
|
5939
5850
|
idPickerLabels,
|
|
5940
5851
|
insideDialog: insideDialog ?? false,
|
|
5941
5852
|
renderDisplay,
|
|
5853
|
+
loadInitialValues: loadInitialValues, // Required for id-picker, checked above
|
|
5942
5854
|
column_ref,
|
|
5943
5855
|
errors,
|
|
5944
5856
|
setValue,
|
|
@@ -6232,31 +6144,35 @@ react.RadioCard.ItemIndicator;
|
|
|
6232
6144
|
|
|
6233
6145
|
const TagPicker = ({ column, schema, prefix }) => {
|
|
6234
6146
|
const { watch, formState: { errors }, setValue, } = reactHookForm.useFormContext();
|
|
6235
|
-
const { serverUrl } = useSchemaContext();
|
|
6236
6147
|
if (schema.properties == undefined) {
|
|
6237
|
-
throw new Error(
|
|
6148
|
+
throw new Error('schema properties undefined when using DatePicker');
|
|
6238
6149
|
}
|
|
6239
|
-
const { gridColumn, gridRow, in_table, object_id_column } = schema;
|
|
6150
|
+
const { gridColumn, gridRow, in_table, object_id_column, tagPicker } = schema;
|
|
6240
6151
|
if (in_table === undefined) {
|
|
6241
|
-
throw new Error(
|
|
6152
|
+
throw new Error('in_table is undefined when using TagPicker');
|
|
6242
6153
|
}
|
|
6243
6154
|
if (object_id_column === undefined) {
|
|
6244
|
-
throw new Error(
|
|
6155
|
+
throw new Error('object_id_column is undefined when using TagPicker');
|
|
6156
|
+
}
|
|
6157
|
+
if (!tagPicker?.queryFn) {
|
|
6158
|
+
throw new Error('tagPicker.queryFn is required in schema. serverUrl has been removed.');
|
|
6245
6159
|
}
|
|
6246
6160
|
const query = reactQuery.useQuery({
|
|
6247
6161
|
queryKey: [`tagpicker`, in_table],
|
|
6248
6162
|
queryFn: async () => {
|
|
6249
|
-
|
|
6250
|
-
|
|
6251
|
-
in_table: "tables_tags_view",
|
|
6163
|
+
const result = await tagPicker.queryFn({
|
|
6164
|
+
in_table: 'tables_tags_view',
|
|
6252
6165
|
where: [
|
|
6253
6166
|
{
|
|
6254
|
-
id:
|
|
6167
|
+
id: 'table_name',
|
|
6255
6168
|
value: [in_table],
|
|
6256
6169
|
},
|
|
6257
6170
|
],
|
|
6258
6171
|
limit: 100,
|
|
6172
|
+
offset: 0,
|
|
6173
|
+
searching: '',
|
|
6259
6174
|
});
|
|
6175
|
+
return result.data || { data: [] };
|
|
6260
6176
|
},
|
|
6261
6177
|
staleTime: 10000,
|
|
6262
6178
|
});
|
|
@@ -6264,17 +6180,19 @@ const TagPicker = ({ column, schema, prefix }) => {
|
|
|
6264
6180
|
const existingTagsQuery = reactQuery.useQuery({
|
|
6265
6181
|
queryKey: [`existing`, { in_table, object_id_column }, object_id],
|
|
6266
6182
|
queryFn: async () => {
|
|
6267
|
-
|
|
6268
|
-
serverUrl,
|
|
6183
|
+
const result = await tagPicker.queryFn({
|
|
6269
6184
|
in_table: in_table,
|
|
6270
6185
|
where: [
|
|
6271
6186
|
{
|
|
6272
6187
|
id: object_id_column,
|
|
6273
|
-
value: object_id[0],
|
|
6188
|
+
value: [object_id[0]],
|
|
6274
6189
|
},
|
|
6275
6190
|
],
|
|
6276
6191
|
limit: 100,
|
|
6192
|
+
offset: 0,
|
|
6193
|
+
searching: '',
|
|
6277
6194
|
});
|
|
6195
|
+
return result.data || { data: [] };
|
|
6278
6196
|
},
|
|
6279
6197
|
enabled: object_id != undefined,
|
|
6280
6198
|
staleTime: 10000,
|
|
@@ -6285,9 +6203,9 @@ const TagPicker = ({ column, schema, prefix }) => {
|
|
|
6285
6203
|
if (!!object_id === false) {
|
|
6286
6204
|
return jsxRuntime.jsx(jsxRuntime.Fragment, {});
|
|
6287
6205
|
}
|
|
6288
|
-
return (jsxRuntime.jsxs(react.Flex, { flexFlow:
|
|
6206
|
+
return (jsxRuntime.jsxs(react.Flex, { flexFlow: 'column', gap: 4, gridColumn,
|
|
6289
6207
|
gridRow, children: [isFetching && jsxRuntime.jsx(jsxRuntime.Fragment, { children: "isFetching" }), isLoading && jsxRuntime.jsx(jsxRuntime.Fragment, { children: "isLoading" }), isPending && jsxRuntime.jsx(jsxRuntime.Fragment, { children: "isPending" }), isError && jsxRuntime.jsx(jsxRuntime.Fragment, { children: "isError" }), dataList.map(({ parent_tag_name, all_tags, is_mutually_exclusive }) => {
|
|
6290
|
-
return (jsxRuntime.jsxs(react.Flex, { flexFlow:
|
|
6208
|
+
return (jsxRuntime.jsxs(react.Flex, { flexFlow: 'column', gap: 2, children: [jsxRuntime.jsx(react.Text, { children: parent_tag_name }), is_mutually_exclusive && (jsxRuntime.jsx(RadioCardRoot, { defaultValue: "next", variant: 'surface', onValueChange: (tagIds) => {
|
|
6291
6209
|
const existedTags = Object.values(all_tags)
|
|
6292
6210
|
.filter(({ id }) => {
|
|
6293
6211
|
return existingTagList.some(({ tag_id }) => tag_id === id);
|
|
@@ -6299,20 +6217,20 @@ const TagPicker = ({ column, schema, prefix }) => {
|
|
|
6299
6217
|
tagIds.value,
|
|
6300
6218
|
]);
|
|
6301
6219
|
setValue(`${column}.${parent_tag_name}.old`, existedTags);
|
|
6302
|
-
}, children: jsxRuntime.jsx(react.Flex, { flexFlow:
|
|
6220
|
+
}, children: jsxRuntime.jsx(react.Flex, { flexFlow: 'wrap', gap: 2, children: Object.entries(all_tags).map(([tagName, { id }]) => {
|
|
6303
6221
|
if (existingTagList.some(({ tag_id }) => tag_id === id)) {
|
|
6304
|
-
return (jsxRuntime.jsx(RadioCardItem, { label: tagName, value: id, flex:
|
|
6222
|
+
return (jsxRuntime.jsx(RadioCardItem, { label: tagName, value: id, flex: '0 0 0%', disabled: true }, `${tagName}-${id}`));
|
|
6305
6223
|
}
|
|
6306
|
-
return (jsxRuntime.jsx(RadioCardItem, { label: tagName, value: id, flex:
|
|
6224
|
+
return (jsxRuntime.jsx(RadioCardItem, { label: tagName, value: id, flex: '0 0 0%', colorPalette: 'blue' }, `${tagName}-${id}`));
|
|
6307
6225
|
}) }) })), !is_mutually_exclusive && (jsxRuntime.jsx(react.CheckboxGroup, { onValueChange: (tagIds) => {
|
|
6308
6226
|
setValue(`${column}.${parent_tag_name}.current`, tagIds);
|
|
6309
|
-
}, children: jsxRuntime.jsx(react.Flex, { flexFlow:
|
|
6227
|
+
}, children: jsxRuntime.jsx(react.Flex, { flexFlow: 'wrap', gap: 2, children: Object.entries(all_tags).map(([tagName, { id }]) => {
|
|
6310
6228
|
if (existingTagList.some(({ tag_id }) => tag_id === id)) {
|
|
6311
|
-
return (jsxRuntime.jsx(CheckboxCard, { label: tagName, value: id, flex:
|
|
6229
|
+
return (jsxRuntime.jsx(CheckboxCard, { label: tagName, value: id, flex: '0 0 0%', disabled: true, colorPalette: 'blue' }, `${tagName}-${id}`));
|
|
6312
6230
|
}
|
|
6313
|
-
return (jsxRuntime.jsx(CheckboxCard, { label: tagName, value: id, flex:
|
|
6231
|
+
return (jsxRuntime.jsx(CheckboxCard, { label: tagName, value: id, flex: '0 0 0%' }, `${tagName}-${id}`));
|
|
6314
6232
|
}) }) }))] }, `tag-${parent_tag_name}`));
|
|
6315
|
-
}), errors[`${column}`] && (jsxRuntime.jsx(react.Text, { color:
|
|
6233
|
+
}), errors[`${column}`] && (jsxRuntime.jsx(react.Text, { color: 'red.400', children: (errors[`${column}`]?.message ?? 'No error message') }))] }));
|
|
6316
6234
|
};
|
|
6317
6235
|
|
|
6318
6236
|
const Textarea = React.forwardRef(({ value, defaultValue, placeholder, onChange, onFocus, onBlur, disabled = false, readOnly = false, className, rows = 4, maxLength, autoFocus = false, invalid = false, required = false, label, helperText, errorText, ...props }, ref) => {
|
|
@@ -7994,31 +7912,35 @@ const StringViewer = ({ column, schema, prefix, }) => {
|
|
|
7994
7912
|
|
|
7995
7913
|
const TagViewer = ({ column, schema, prefix }) => {
|
|
7996
7914
|
const { watch, formState: { errors }, setValue, } = reactHookForm.useFormContext();
|
|
7997
|
-
const { serverUrl } = useSchemaContext();
|
|
7998
7915
|
if (schema.properties == undefined) {
|
|
7999
|
-
throw new Error(
|
|
7916
|
+
throw new Error('schema properties undefined when using DatePicker');
|
|
8000
7917
|
}
|
|
8001
|
-
const { gridColumn, gridRow, in_table, object_id_column } = schema;
|
|
7918
|
+
const { gridColumn, gridRow, in_table, object_id_column, tagPicker } = schema;
|
|
8002
7919
|
if (in_table === undefined) {
|
|
8003
|
-
throw new Error(
|
|
7920
|
+
throw new Error('in_table is undefined when using TagPicker');
|
|
8004
7921
|
}
|
|
8005
7922
|
if (object_id_column === undefined) {
|
|
8006
|
-
throw new Error(
|
|
7923
|
+
throw new Error('object_id_column is undefined when using TagPicker');
|
|
7924
|
+
}
|
|
7925
|
+
if (!tagPicker?.queryFn) {
|
|
7926
|
+
throw new Error('tagPicker.queryFn is required in schema. serverUrl has been removed.');
|
|
8007
7927
|
}
|
|
8008
7928
|
const query = reactQuery.useQuery({
|
|
8009
7929
|
queryKey: [`tagpicker`, in_table],
|
|
8010
7930
|
queryFn: async () => {
|
|
8011
|
-
|
|
8012
|
-
|
|
8013
|
-
in_table: "tables_tags_view",
|
|
7931
|
+
const result = await tagPicker.queryFn({
|
|
7932
|
+
in_table: 'tables_tags_view',
|
|
8014
7933
|
where: [
|
|
8015
7934
|
{
|
|
8016
|
-
id:
|
|
7935
|
+
id: 'table_name',
|
|
8017
7936
|
value: [in_table],
|
|
8018
7937
|
},
|
|
8019
7938
|
],
|
|
8020
7939
|
limit: 100,
|
|
7940
|
+
offset: 0,
|
|
7941
|
+
searching: '',
|
|
8021
7942
|
});
|
|
7943
|
+
return result.data || { data: [] };
|
|
8022
7944
|
},
|
|
8023
7945
|
staleTime: 10000,
|
|
8024
7946
|
});
|
|
@@ -8026,17 +7948,19 @@ const TagViewer = ({ column, schema, prefix }) => {
|
|
|
8026
7948
|
const existingTagsQuery = reactQuery.useQuery({
|
|
8027
7949
|
queryKey: [`existing`, { in_table, object_id_column }, object_id],
|
|
8028
7950
|
queryFn: async () => {
|
|
8029
|
-
|
|
8030
|
-
serverUrl,
|
|
7951
|
+
const result = await tagPicker.queryFn({
|
|
8031
7952
|
in_table: in_table,
|
|
8032
7953
|
where: [
|
|
8033
7954
|
{
|
|
8034
7955
|
id: object_id_column,
|
|
8035
|
-
value: object_id[0],
|
|
7956
|
+
value: [object_id[0]],
|
|
8036
7957
|
},
|
|
8037
7958
|
],
|
|
8038
7959
|
limit: 100,
|
|
7960
|
+
offset: 0,
|
|
7961
|
+
searching: '',
|
|
8039
7962
|
});
|
|
7963
|
+
return result.data || { data: [] };
|
|
8040
7964
|
},
|
|
8041
7965
|
enabled: object_id != undefined,
|
|
8042
7966
|
staleTime: 10000,
|
|
@@ -8047,9 +7971,9 @@ const TagViewer = ({ column, schema, prefix }) => {
|
|
|
8047
7971
|
if (!!object_id === false) {
|
|
8048
7972
|
return jsxRuntime.jsx(jsxRuntime.Fragment, {});
|
|
8049
7973
|
}
|
|
8050
|
-
return (jsxRuntime.jsxs(react.Flex, { flexFlow:
|
|
7974
|
+
return (jsxRuntime.jsxs(react.Flex, { flexFlow: 'column', gap: 4, gridColumn,
|
|
8051
7975
|
gridRow, children: [isFetching && jsxRuntime.jsx(jsxRuntime.Fragment, { children: "isFetching" }), isLoading && jsxRuntime.jsx(jsxRuntime.Fragment, { children: "isLoading" }), isPending && jsxRuntime.jsx(jsxRuntime.Fragment, { children: "isPending" }), isError && jsxRuntime.jsx(jsxRuntime.Fragment, { children: "isError" }), dataList.map(({ parent_tag_name, all_tags, is_mutually_exclusive }) => {
|
|
8052
|
-
return (jsxRuntime.jsxs(react.Flex, { flexFlow:
|
|
7976
|
+
return (jsxRuntime.jsxs(react.Flex, { flexFlow: 'column', gap: 2, children: [jsxRuntime.jsx(react.Text, { children: parent_tag_name }), is_mutually_exclusive && (jsxRuntime.jsx(RadioCardRoot, { defaultValue: "next", variant: 'surface', onValueChange: (tagIds) => {
|
|
8053
7977
|
const existedTags = Object.values(all_tags)
|
|
8054
7978
|
.filter(({ id }) => {
|
|
8055
7979
|
return existingTagList.some(({ tag_id }) => tag_id === id);
|
|
@@ -8061,20 +7985,20 @@ const TagViewer = ({ column, schema, prefix }) => {
|
|
|
8061
7985
|
tagIds.value,
|
|
8062
7986
|
]);
|
|
8063
7987
|
setValue(`${column}.${parent_tag_name}.old`, existedTags);
|
|
8064
|
-
}, children: jsxRuntime.jsx(react.Flex, { flexFlow:
|
|
7988
|
+
}, children: jsxRuntime.jsx(react.Flex, { flexFlow: 'wrap', gap: 2, children: Object.entries(all_tags).map(([tagName, { id }]) => {
|
|
8065
7989
|
if (existingTagList.some(({ tag_id }) => tag_id === id)) {
|
|
8066
|
-
return (jsxRuntime.jsx(RadioCardItem, { label: tagName, value: id, flex:
|
|
7990
|
+
return (jsxRuntime.jsx(RadioCardItem, { label: tagName, value: id, flex: '0 0 0%', disabled: true }, `${tagName}-${id}`));
|
|
8067
7991
|
}
|
|
8068
|
-
return (jsxRuntime.jsx(RadioCardItem, { label: tagName, value: id, flex:
|
|
7992
|
+
return (jsxRuntime.jsx(RadioCardItem, { label: tagName, value: id, flex: '0 0 0%', colorPalette: 'blue' }, `${tagName}-${id}`));
|
|
8069
7993
|
}) }) })), !is_mutually_exclusive && (jsxRuntime.jsx(react.CheckboxGroup, { onValueChange: (tagIds) => {
|
|
8070
7994
|
setValue(`${column}.${parent_tag_name}.current`, tagIds);
|
|
8071
|
-
}, children: jsxRuntime.jsx(react.Flex, { flexFlow:
|
|
7995
|
+
}, children: jsxRuntime.jsx(react.Flex, { flexFlow: 'wrap', gap: 2, children: Object.entries(all_tags).map(([tagName, { id }]) => {
|
|
8072
7996
|
if (existingTagList.some(({ tag_id }) => tag_id === id)) {
|
|
8073
|
-
return (jsxRuntime.jsx(CheckboxCard, { label: tagName, value: id, flex:
|
|
7997
|
+
return (jsxRuntime.jsx(CheckboxCard, { label: tagName, value: id, flex: '0 0 0%', disabled: true, colorPalette: 'blue' }, `${tagName}-${id}`));
|
|
8074
7998
|
}
|
|
8075
|
-
return (jsxRuntime.jsx(CheckboxCard, { label: tagName, value: id, flex:
|
|
7999
|
+
return (jsxRuntime.jsx(CheckboxCard, { label: tagName, value: id, flex: '0 0 0%' }, `${tagName}-${id}`));
|
|
8076
8000
|
}) }) }))] }, `tag-${parent_tag_name}`));
|
|
8077
|
-
}), errors[`${column}`] && (jsxRuntime.jsx(react.Text, { color:
|
|
8001
|
+
}), errors[`${column}`] && (jsxRuntime.jsx(react.Text, { color: 'red.400', children: (errors[`${column}`]?.message ?? 'No error message') }))] }));
|
|
8078
8002
|
};
|
|
8079
8003
|
|
|
8080
8004
|
const TextAreaViewer = ({ column, schema, prefix, }) => {
|
package/dist/index.mjs
CHANGED
|
@@ -3694,7 +3694,7 @@ const TextWithCopy = ({ text, globalFilter, highlightedText, }) => {
|
|
|
3694
3694
|
const displayText = highlightedText !== undefined
|
|
3695
3695
|
? highlightedText
|
|
3696
3696
|
: highlightText$1(textValue, globalFilter);
|
|
3697
|
-
return (jsxs(HStack, { gap: 2, alignItems: "center", children: [jsx(Text, { as: "span", children: displayText }), jsx(Clipboard.Root, { value: textValue, children: jsx(Clipboard.Trigger, { asChild: true, children: jsx(IconButton, { size: "
|
|
3697
|
+
return (jsxs(HStack, { gap: 2, alignItems: "center", children: [jsx(Text, { as: "span", children: displayText }), jsx(Clipboard.Root, { value: textValue, children: jsx(Clipboard.Trigger, { asChild: true, children: jsx(IconButton, { size: "2xs", variant: "ghost", "aria-label": "Copy", fontSize: "1em", children: jsx(Clipboard.Indicator, { copied: jsx(LuCheck, {}), children: jsx(LuCopy, {}) }) }) }) })] }));
|
|
3698
3698
|
};
|
|
3699
3699
|
|
|
3700
3700
|
// Helper function to highlight matching text
|
|
@@ -4016,7 +4016,6 @@ const getColumns = ({ schema, include = [], ignore = [], width = [], meta = {},
|
|
|
4016
4016
|
//@ts-expect-error TODO: find appropriate type
|
|
4017
4017
|
const SchemaFormContext = createContext({
|
|
4018
4018
|
schema: {},
|
|
4019
|
-
serverUrl: '',
|
|
4020
4019
|
requestUrl: '',
|
|
4021
4020
|
order: [],
|
|
4022
4021
|
ignore: [],
|
|
@@ -4256,7 +4255,7 @@ const idPickerSanityCheck = (column, foreign_key) => {
|
|
|
4256
4255
|
throw new Error(`The key column does not exist in properties of column ${column} when using id-picker.`);
|
|
4257
4256
|
}
|
|
4258
4257
|
};
|
|
4259
|
-
const FormRoot = ({ schema, idMap, setIdMap, form,
|
|
4258
|
+
const FormRoot = ({ schema, idMap, setIdMap, form, translate, children, order = [], ignore = [], include = [], onSubmit = undefined, rowNumber = undefined, requestOptions = {}, getUpdatedData = () => { }, customErrorRenderer, customSuccessRenderer, displayConfig = {
|
|
4260
4259
|
showSubmitButton: true,
|
|
4261
4260
|
showResetButton: true,
|
|
4262
4261
|
showTitle: true,
|
|
@@ -4297,9 +4296,11 @@ const FormRoot = ({ schema, idMap, setIdMap, form, serverUrl, translate, childre
|
|
|
4297
4296
|
}
|
|
4298
4297
|
};
|
|
4299
4298
|
const defaultSubmitPromise = (data) => {
|
|
4299
|
+
if (!requestOptions.url) {
|
|
4300
|
+
throw new Error('requestOptions.url is required when onSubmit is not provided');
|
|
4301
|
+
}
|
|
4300
4302
|
const options = {
|
|
4301
4303
|
method: 'POST',
|
|
4302
|
-
url: `${serverUrl}`,
|
|
4303
4304
|
data: clearEmptyString(data),
|
|
4304
4305
|
...requestOptions,
|
|
4305
4306
|
};
|
|
@@ -4317,7 +4318,6 @@ const FormRoot = ({ schema, idMap, setIdMap, form, serverUrl, translate, childre
|
|
|
4317
4318
|
};
|
|
4318
4319
|
return (jsx(SchemaFormContext.Provider, { value: {
|
|
4319
4320
|
schema,
|
|
4320
|
-
serverUrl,
|
|
4321
4321
|
order,
|
|
4322
4322
|
ignore,
|
|
4323
4323
|
include,
|
|
@@ -5598,106 +5598,20 @@ const FormMediaLibraryBrowser = ({ column, schema, prefix, }) => {
|
|
|
5598
5598
|
}) })] }));
|
|
5599
5599
|
};
|
|
5600
5600
|
|
|
5601
|
-
const getTableData = async ({ serverUrl, in_table, searching = "", where = [], limit = 10, offset = 0, }) => {
|
|
5602
|
-
if (serverUrl === undefined || serverUrl.length == 0) {
|
|
5603
|
-
throw new Error("The serverUrl is missing");
|
|
5604
|
-
}
|
|
5605
|
-
if (in_table === undefined || in_table.length == 0) {
|
|
5606
|
-
throw new Error("The in_table is missing");
|
|
5607
|
-
}
|
|
5608
|
-
const options = {
|
|
5609
|
-
method: "GET",
|
|
5610
|
-
url: `${serverUrl}/api/g/${in_table}`,
|
|
5611
|
-
params: {
|
|
5612
|
-
searching,
|
|
5613
|
-
where,
|
|
5614
|
-
limit,
|
|
5615
|
-
offset
|
|
5616
|
-
},
|
|
5617
|
-
};
|
|
5618
|
-
try {
|
|
5619
|
-
const { data } = await axios.request(options);
|
|
5620
|
-
console.log(data);
|
|
5621
|
-
return data;
|
|
5622
|
-
}
|
|
5623
|
-
catch (error) {
|
|
5624
|
-
console.error(error);
|
|
5625
|
-
throw error;
|
|
5626
|
-
}
|
|
5627
|
-
};
|
|
5628
|
-
|
|
5629
5601
|
// Default renderDisplay function that stringifies JSON
|
|
5630
5602
|
const defaultRenderDisplay = (item) => {
|
|
5631
5603
|
return JSON.stringify(item);
|
|
5632
5604
|
};
|
|
5633
5605
|
|
|
5634
|
-
/**
|
|
5635
|
-
* Load initial values for IdPicker fields into idMap
|
|
5636
|
-
* Uses customQueryFn if available, otherwise falls back to getTableData
|
|
5637
|
-
*
|
|
5638
|
-
* @param params - Configuration for loading initial values
|
|
5639
|
-
* @returns Promise with fetched data and idMap
|
|
5640
|
-
*/
|
|
5641
|
-
const loadInitialValues = async ({ ids, foreign_key, serverUrl, setIdMap, }) => {
|
|
5642
|
-
if (!ids || ids.length === 0) {
|
|
5643
|
-
return { data: { data: [], count: 0 }, idMap: {} };
|
|
5644
|
-
}
|
|
5645
|
-
const { table, column: column_ref, customQueryFn } = foreign_key;
|
|
5646
|
-
// Filter out IDs that are already in idMap (optional optimization)
|
|
5647
|
-
// For now, we'll fetch all requested IDs to ensure consistency
|
|
5648
|
-
if (customQueryFn) {
|
|
5649
|
-
const { data, idMap: returnedIdMap } = await customQueryFn({
|
|
5650
|
-
searching: '',
|
|
5651
|
-
limit: ids.length,
|
|
5652
|
-
offset: 0,
|
|
5653
|
-
where: [
|
|
5654
|
-
{
|
|
5655
|
-
id: column_ref,
|
|
5656
|
-
value: ids.length === 1 ? ids[0] : ids, // CustomQueryFn accepts string | string[]
|
|
5657
|
-
},
|
|
5658
|
-
],
|
|
5659
|
-
});
|
|
5660
|
-
// Update idMap with returned values
|
|
5661
|
-
if (returnedIdMap && Object.keys(returnedIdMap).length > 0) {
|
|
5662
|
-
setIdMap((state) => {
|
|
5663
|
-
return { ...state, ...returnedIdMap };
|
|
5664
|
-
});
|
|
5665
|
-
}
|
|
5666
|
-
return { data, idMap: returnedIdMap || {} };
|
|
5667
|
-
}
|
|
5668
|
-
// Fallback to default getTableData
|
|
5669
|
-
const data = await getTableData({
|
|
5670
|
-
serverUrl,
|
|
5671
|
-
searching: '',
|
|
5672
|
-
in_table: table,
|
|
5673
|
-
limit: ids.length,
|
|
5674
|
-
offset: 0,
|
|
5675
|
-
where: [
|
|
5676
|
-
{
|
|
5677
|
-
id: column_ref,
|
|
5678
|
-
value: ids, // Always pass as array
|
|
5679
|
-
},
|
|
5680
|
-
],
|
|
5681
|
-
});
|
|
5682
|
-
// Build idMap from fetched data
|
|
5683
|
-
const newMap = Object.fromEntries((data ?? { data: [] }).data.map((item) => {
|
|
5684
|
-
return [
|
|
5685
|
-
item[column_ref],
|
|
5686
|
-
{
|
|
5687
|
-
...item,
|
|
5688
|
-
},
|
|
5689
|
-
];
|
|
5690
|
-
}));
|
|
5691
|
-
// Update idMap state
|
|
5692
|
-
setIdMap((state) => {
|
|
5693
|
-
return { ...state, ...newMap };
|
|
5694
|
-
});
|
|
5695
|
-
return { data: data, idMap: newMap };
|
|
5696
|
-
};
|
|
5697
5606
|
const useIdPickerData = ({ column, schema, prefix, isMultiple, }) => {
|
|
5698
5607
|
const { watch, getValues, formState: { errors }, setValue, } = useFormContext();
|
|
5699
|
-
const {
|
|
5700
|
-
const { renderDisplay, foreign_key } = schema;
|
|
5608
|
+
const { idMap, setIdMap, idPickerLabels, insideDialog } = useSchemaContext();
|
|
5609
|
+
const { renderDisplay, loadInitialValues, foreign_key, variant } = schema;
|
|
5610
|
+
// loadInitialValues must be provided in schema for id-picker fields
|
|
5611
|
+
// It's used to load the record of the id so the display is human-readable
|
|
5612
|
+
if (variant === 'id-picker' && !loadInitialValues) {
|
|
5613
|
+
throw new Error(`loadInitialValues is required in schema for IdPicker field '${column}'. Please provide loadInitialValues function in the schema to load records for human-readable display.`);
|
|
5614
|
+
}
|
|
5701
5615
|
const { table, column: column_ref, customQueryFn, } = foreign_key;
|
|
5702
5616
|
const [searchText, setSearchText] = useState('');
|
|
5703
5617
|
const [debouncedSearchText, setDebouncedSearchText] = useState('');
|
|
@@ -5742,60 +5656,57 @@ const useIdPickerData = ({ column, schema, prefix, isMultiple, }) => {
|
|
|
5742
5656
|
const missingIdsKey = useMemo(() => {
|
|
5743
5657
|
return JSON.stringify([...missingIds].sort());
|
|
5744
5658
|
}, [missingIds]);
|
|
5659
|
+
// Include idMap state in query key to force refetch when idMap is reset (e.g., on remount from another page)
|
|
5660
|
+
// This ensures the query runs even if React Query has cached data for the same missing IDs
|
|
5661
|
+
const idMapStateKey = useMemo(() => {
|
|
5662
|
+
// Create a key based on whether the required IDs are in idMap
|
|
5663
|
+
const hasRequiredIds = currentValue.every((id) => idMap[id]);
|
|
5664
|
+
return hasRequiredIds ? 'complete' : 'incomplete';
|
|
5665
|
+
}, [currentValue, idMap]);
|
|
5745
5666
|
// Query to fetch initial values that are missing from idMap
|
|
5746
5667
|
// This query runs automatically when missingIds.length > 0 and updates idMap
|
|
5747
5668
|
const initialValuesQuery = useQuery({
|
|
5748
|
-
queryKey: [`idpicker-initial`, column, missingIdsKey],
|
|
5669
|
+
queryKey: [`idpicker-initial`, column, missingIdsKey, idMapStateKey],
|
|
5749
5670
|
queryFn: async () => {
|
|
5750
5671
|
if (missingIds.length === 0) {
|
|
5751
5672
|
return { data: [], count: 0 };
|
|
5752
5673
|
}
|
|
5753
|
-
// Use
|
|
5674
|
+
// Use schema's loadInitialValues (required for id-picker)
|
|
5675
|
+
if (!loadInitialValues) {
|
|
5676
|
+
throw new Error(`loadInitialValues is required in schema for IdPicker field '${column}'.`);
|
|
5677
|
+
}
|
|
5754
5678
|
const result = await loadInitialValues({
|
|
5755
5679
|
ids: missingIds,
|
|
5756
5680
|
foreign_key: foreign_key,
|
|
5757
|
-
serverUrl,
|
|
5758
5681
|
setIdMap,
|
|
5759
5682
|
});
|
|
5760
5683
|
return result.data;
|
|
5761
5684
|
},
|
|
5762
5685
|
enabled: missingIds.length > 0, // Only fetch if there are missing IDs
|
|
5763
|
-
staleTime:
|
|
5686
|
+
staleTime: 0, // Always consider data stale to refetch on remount
|
|
5687
|
+
refetchOnMount: true, // Always refetch when component remounts (e.g., from another page)
|
|
5688
|
+
refetchOnWindowFocus: false, // Don't refetch on window focus
|
|
5764
5689
|
});
|
|
5765
5690
|
const { isLoading: isLoadingInitialValues, isFetching: isFetchingInitialValues, } = initialValuesQuery;
|
|
5766
5691
|
// Query for search results (async loading)
|
|
5767
5692
|
const query = useQuery({
|
|
5768
5693
|
queryKey: [`idpicker`, { column, searchText: debouncedSearchText, limit }],
|
|
5769
5694
|
queryFn: async () => {
|
|
5770
|
-
|
|
5771
|
-
|
|
5772
|
-
|
|
5773
|
-
limit: limit,
|
|
5774
|
-
offset: 0,
|
|
5775
|
-
});
|
|
5776
|
-
setIdMap((state) => {
|
|
5777
|
-
return { ...state, ...idMap };
|
|
5778
|
-
});
|
|
5779
|
-
return data;
|
|
5695
|
+
// customQueryFn is required when serverUrl is not available
|
|
5696
|
+
if (!customQueryFn) {
|
|
5697
|
+
throw new Error(`customQueryFn is required in foreign_key for table ${table}. serverUrl has been removed.`);
|
|
5780
5698
|
}
|
|
5781
|
-
const data = await
|
|
5782
|
-
serverUrl,
|
|
5699
|
+
const { data, idMap } = await customQueryFn({
|
|
5783
5700
|
searching: debouncedSearchText ?? '',
|
|
5784
|
-
in_table: table,
|
|
5785
5701
|
limit: limit,
|
|
5786
5702
|
offset: 0,
|
|
5787
5703
|
});
|
|
5788
|
-
|
|
5789
|
-
|
|
5790
|
-
|
|
5791
|
-
{
|
|
5792
|
-
|
|
5793
|
-
|
|
5794
|
-
];
|
|
5795
|
-
}));
|
|
5796
|
-
setIdMap((state) => {
|
|
5797
|
-
return { ...state, ...newMap };
|
|
5798
|
-
});
|
|
5704
|
+
// Update idMap with returned values
|
|
5705
|
+
if (idMap && Object.keys(idMap).length > 0) {
|
|
5706
|
+
setIdMap((state) => {
|
|
5707
|
+
return { ...state, ...idMap };
|
|
5708
|
+
});
|
|
5709
|
+
}
|
|
5799
5710
|
return data;
|
|
5800
5711
|
},
|
|
5801
5712
|
enabled: true, // Always enabled for combobox
|
|
@@ -5919,6 +5830,7 @@ const useIdPickerData = ({ column, schema, prefix, isMultiple, }) => {
|
|
|
5919
5830
|
idPickerLabels,
|
|
5920
5831
|
insideDialog: insideDialog ?? false,
|
|
5921
5832
|
renderDisplay,
|
|
5833
|
+
loadInitialValues: loadInitialValues, // Required for id-picker, checked above
|
|
5922
5834
|
column_ref,
|
|
5923
5835
|
errors,
|
|
5924
5836
|
setValue,
|
|
@@ -6212,31 +6124,35 @@ RadioCard.ItemIndicator;
|
|
|
6212
6124
|
|
|
6213
6125
|
const TagPicker = ({ column, schema, prefix }) => {
|
|
6214
6126
|
const { watch, formState: { errors }, setValue, } = useFormContext();
|
|
6215
|
-
const { serverUrl } = useSchemaContext();
|
|
6216
6127
|
if (schema.properties == undefined) {
|
|
6217
|
-
throw new Error(
|
|
6128
|
+
throw new Error('schema properties undefined when using DatePicker');
|
|
6218
6129
|
}
|
|
6219
|
-
const { gridColumn, gridRow, in_table, object_id_column } = schema;
|
|
6130
|
+
const { gridColumn, gridRow, in_table, object_id_column, tagPicker } = schema;
|
|
6220
6131
|
if (in_table === undefined) {
|
|
6221
|
-
throw new Error(
|
|
6132
|
+
throw new Error('in_table is undefined when using TagPicker');
|
|
6222
6133
|
}
|
|
6223
6134
|
if (object_id_column === undefined) {
|
|
6224
|
-
throw new Error(
|
|
6135
|
+
throw new Error('object_id_column is undefined when using TagPicker');
|
|
6136
|
+
}
|
|
6137
|
+
if (!tagPicker?.queryFn) {
|
|
6138
|
+
throw new Error('tagPicker.queryFn is required in schema. serverUrl has been removed.');
|
|
6225
6139
|
}
|
|
6226
6140
|
const query = useQuery({
|
|
6227
6141
|
queryKey: [`tagpicker`, in_table],
|
|
6228
6142
|
queryFn: async () => {
|
|
6229
|
-
|
|
6230
|
-
|
|
6231
|
-
in_table: "tables_tags_view",
|
|
6143
|
+
const result = await tagPicker.queryFn({
|
|
6144
|
+
in_table: 'tables_tags_view',
|
|
6232
6145
|
where: [
|
|
6233
6146
|
{
|
|
6234
|
-
id:
|
|
6147
|
+
id: 'table_name',
|
|
6235
6148
|
value: [in_table],
|
|
6236
6149
|
},
|
|
6237
6150
|
],
|
|
6238
6151
|
limit: 100,
|
|
6152
|
+
offset: 0,
|
|
6153
|
+
searching: '',
|
|
6239
6154
|
});
|
|
6155
|
+
return result.data || { data: [] };
|
|
6240
6156
|
},
|
|
6241
6157
|
staleTime: 10000,
|
|
6242
6158
|
});
|
|
@@ -6244,17 +6160,19 @@ const TagPicker = ({ column, schema, prefix }) => {
|
|
|
6244
6160
|
const existingTagsQuery = useQuery({
|
|
6245
6161
|
queryKey: [`existing`, { in_table, object_id_column }, object_id],
|
|
6246
6162
|
queryFn: async () => {
|
|
6247
|
-
|
|
6248
|
-
serverUrl,
|
|
6163
|
+
const result = await tagPicker.queryFn({
|
|
6249
6164
|
in_table: in_table,
|
|
6250
6165
|
where: [
|
|
6251
6166
|
{
|
|
6252
6167
|
id: object_id_column,
|
|
6253
|
-
value: object_id[0],
|
|
6168
|
+
value: [object_id[0]],
|
|
6254
6169
|
},
|
|
6255
6170
|
],
|
|
6256
6171
|
limit: 100,
|
|
6172
|
+
offset: 0,
|
|
6173
|
+
searching: '',
|
|
6257
6174
|
});
|
|
6175
|
+
return result.data || { data: [] };
|
|
6258
6176
|
},
|
|
6259
6177
|
enabled: object_id != undefined,
|
|
6260
6178
|
staleTime: 10000,
|
|
@@ -6265,9 +6183,9 @@ const TagPicker = ({ column, schema, prefix }) => {
|
|
|
6265
6183
|
if (!!object_id === false) {
|
|
6266
6184
|
return jsx(Fragment, {});
|
|
6267
6185
|
}
|
|
6268
|
-
return (jsxs(Flex, { flexFlow:
|
|
6186
|
+
return (jsxs(Flex, { flexFlow: 'column', gap: 4, gridColumn,
|
|
6269
6187
|
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 }) => {
|
|
6270
|
-
return (jsxs(Flex, { flexFlow:
|
|
6188
|
+
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) => {
|
|
6271
6189
|
const existedTags = Object.values(all_tags)
|
|
6272
6190
|
.filter(({ id }) => {
|
|
6273
6191
|
return existingTagList.some(({ tag_id }) => tag_id === id);
|
|
@@ -6279,20 +6197,20 @@ const TagPicker = ({ column, schema, prefix }) => {
|
|
|
6279
6197
|
tagIds.value,
|
|
6280
6198
|
]);
|
|
6281
6199
|
setValue(`${column}.${parent_tag_name}.old`, existedTags);
|
|
6282
|
-
}, children: jsx(Flex, { flexFlow:
|
|
6200
|
+
}, children: jsx(Flex, { flexFlow: 'wrap', gap: 2, children: Object.entries(all_tags).map(([tagName, { id }]) => {
|
|
6283
6201
|
if (existingTagList.some(({ tag_id }) => tag_id === id)) {
|
|
6284
|
-
return (jsx(RadioCardItem, { label: tagName, value: id, flex:
|
|
6202
|
+
return (jsx(RadioCardItem, { label: tagName, value: id, flex: '0 0 0%', disabled: true }, `${tagName}-${id}`));
|
|
6285
6203
|
}
|
|
6286
|
-
return (jsx(RadioCardItem, { label: tagName, value: id, flex:
|
|
6204
|
+
return (jsx(RadioCardItem, { label: tagName, value: id, flex: '0 0 0%', colorPalette: 'blue' }, `${tagName}-${id}`));
|
|
6287
6205
|
}) }) })), !is_mutually_exclusive && (jsx(CheckboxGroup, { onValueChange: (tagIds) => {
|
|
6288
6206
|
setValue(`${column}.${parent_tag_name}.current`, tagIds);
|
|
6289
|
-
}, children: jsx(Flex, { flexFlow:
|
|
6207
|
+
}, children: jsx(Flex, { flexFlow: 'wrap', gap: 2, children: Object.entries(all_tags).map(([tagName, { id }]) => {
|
|
6290
6208
|
if (existingTagList.some(({ tag_id }) => tag_id === id)) {
|
|
6291
|
-
return (jsx(CheckboxCard, { label: tagName, value: id, flex:
|
|
6209
|
+
return (jsx(CheckboxCard, { label: tagName, value: id, flex: '0 0 0%', disabled: true, colorPalette: 'blue' }, `${tagName}-${id}`));
|
|
6292
6210
|
}
|
|
6293
|
-
return (jsx(CheckboxCard, { label: tagName, value: id, flex:
|
|
6211
|
+
return (jsx(CheckboxCard, { label: tagName, value: id, flex: '0 0 0%' }, `${tagName}-${id}`));
|
|
6294
6212
|
}) }) }))] }, `tag-${parent_tag_name}`));
|
|
6295
|
-
}), errors[`${column}`] && (jsx(Text, { color:
|
|
6213
|
+
}), errors[`${column}`] && (jsx(Text, { color: 'red.400', children: (errors[`${column}`]?.message ?? 'No error message') }))] }));
|
|
6296
6214
|
};
|
|
6297
6215
|
|
|
6298
6216
|
const Textarea = forwardRef(({ value, defaultValue, placeholder, onChange, onFocus, onBlur, disabled = false, readOnly = false, className, rows = 4, maxLength, autoFocus = false, invalid = false, required = false, label, helperText, errorText, ...props }, ref) => {
|
|
@@ -7974,31 +7892,35 @@ const StringViewer = ({ column, schema, prefix, }) => {
|
|
|
7974
7892
|
|
|
7975
7893
|
const TagViewer = ({ column, schema, prefix }) => {
|
|
7976
7894
|
const { watch, formState: { errors }, setValue, } = useFormContext();
|
|
7977
|
-
const { serverUrl } = useSchemaContext();
|
|
7978
7895
|
if (schema.properties == undefined) {
|
|
7979
|
-
throw new Error(
|
|
7896
|
+
throw new Error('schema properties undefined when using DatePicker');
|
|
7980
7897
|
}
|
|
7981
|
-
const { gridColumn, gridRow, in_table, object_id_column } = schema;
|
|
7898
|
+
const { gridColumn, gridRow, in_table, object_id_column, tagPicker } = schema;
|
|
7982
7899
|
if (in_table === undefined) {
|
|
7983
|
-
throw new Error(
|
|
7900
|
+
throw new Error('in_table is undefined when using TagPicker');
|
|
7984
7901
|
}
|
|
7985
7902
|
if (object_id_column === undefined) {
|
|
7986
|
-
throw new Error(
|
|
7903
|
+
throw new Error('object_id_column is undefined when using TagPicker');
|
|
7904
|
+
}
|
|
7905
|
+
if (!tagPicker?.queryFn) {
|
|
7906
|
+
throw new Error('tagPicker.queryFn is required in schema. serverUrl has been removed.');
|
|
7987
7907
|
}
|
|
7988
7908
|
const query = useQuery({
|
|
7989
7909
|
queryKey: [`tagpicker`, in_table],
|
|
7990
7910
|
queryFn: async () => {
|
|
7991
|
-
|
|
7992
|
-
|
|
7993
|
-
in_table: "tables_tags_view",
|
|
7911
|
+
const result = await tagPicker.queryFn({
|
|
7912
|
+
in_table: 'tables_tags_view',
|
|
7994
7913
|
where: [
|
|
7995
7914
|
{
|
|
7996
|
-
id:
|
|
7915
|
+
id: 'table_name',
|
|
7997
7916
|
value: [in_table],
|
|
7998
7917
|
},
|
|
7999
7918
|
],
|
|
8000
7919
|
limit: 100,
|
|
7920
|
+
offset: 0,
|
|
7921
|
+
searching: '',
|
|
8001
7922
|
});
|
|
7923
|
+
return result.data || { data: [] };
|
|
8002
7924
|
},
|
|
8003
7925
|
staleTime: 10000,
|
|
8004
7926
|
});
|
|
@@ -8006,17 +7928,19 @@ const TagViewer = ({ column, schema, prefix }) => {
|
|
|
8006
7928
|
const existingTagsQuery = useQuery({
|
|
8007
7929
|
queryKey: [`existing`, { in_table, object_id_column }, object_id],
|
|
8008
7930
|
queryFn: async () => {
|
|
8009
|
-
|
|
8010
|
-
serverUrl,
|
|
7931
|
+
const result = await tagPicker.queryFn({
|
|
8011
7932
|
in_table: in_table,
|
|
8012
7933
|
where: [
|
|
8013
7934
|
{
|
|
8014
7935
|
id: object_id_column,
|
|
8015
|
-
value: object_id[0],
|
|
7936
|
+
value: [object_id[0]],
|
|
8016
7937
|
},
|
|
8017
7938
|
],
|
|
8018
7939
|
limit: 100,
|
|
7940
|
+
offset: 0,
|
|
7941
|
+
searching: '',
|
|
8019
7942
|
});
|
|
7943
|
+
return result.data || { data: [] };
|
|
8020
7944
|
},
|
|
8021
7945
|
enabled: object_id != undefined,
|
|
8022
7946
|
staleTime: 10000,
|
|
@@ -8027,9 +7951,9 @@ const TagViewer = ({ column, schema, prefix }) => {
|
|
|
8027
7951
|
if (!!object_id === false) {
|
|
8028
7952
|
return jsx(Fragment, {});
|
|
8029
7953
|
}
|
|
8030
|
-
return (jsxs(Flex, { flexFlow:
|
|
7954
|
+
return (jsxs(Flex, { flexFlow: 'column', gap: 4, gridColumn,
|
|
8031
7955
|
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 }) => {
|
|
8032
|
-
return (jsxs(Flex, { flexFlow:
|
|
7956
|
+
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) => {
|
|
8033
7957
|
const existedTags = Object.values(all_tags)
|
|
8034
7958
|
.filter(({ id }) => {
|
|
8035
7959
|
return existingTagList.some(({ tag_id }) => tag_id === id);
|
|
@@ -8041,20 +7965,20 @@ const TagViewer = ({ column, schema, prefix }) => {
|
|
|
8041
7965
|
tagIds.value,
|
|
8042
7966
|
]);
|
|
8043
7967
|
setValue(`${column}.${parent_tag_name}.old`, existedTags);
|
|
8044
|
-
}, children: jsx(Flex, { flexFlow:
|
|
7968
|
+
}, children: jsx(Flex, { flexFlow: 'wrap', gap: 2, children: Object.entries(all_tags).map(([tagName, { id }]) => {
|
|
8045
7969
|
if (existingTagList.some(({ tag_id }) => tag_id === id)) {
|
|
8046
|
-
return (jsx(RadioCardItem, { label: tagName, value: id, flex:
|
|
7970
|
+
return (jsx(RadioCardItem, { label: tagName, value: id, flex: '0 0 0%', disabled: true }, `${tagName}-${id}`));
|
|
8047
7971
|
}
|
|
8048
|
-
return (jsx(RadioCardItem, { label: tagName, value: id, flex:
|
|
7972
|
+
return (jsx(RadioCardItem, { label: tagName, value: id, flex: '0 0 0%', colorPalette: 'blue' }, `${tagName}-${id}`));
|
|
8049
7973
|
}) }) })), !is_mutually_exclusive && (jsx(CheckboxGroup, { onValueChange: (tagIds) => {
|
|
8050
7974
|
setValue(`${column}.${parent_tag_name}.current`, tagIds);
|
|
8051
|
-
}, children: jsx(Flex, { flexFlow:
|
|
7975
|
+
}, children: jsx(Flex, { flexFlow: 'wrap', gap: 2, children: Object.entries(all_tags).map(([tagName, { id }]) => {
|
|
8052
7976
|
if (existingTagList.some(({ tag_id }) => tag_id === id)) {
|
|
8053
|
-
return (jsx(CheckboxCard, { label: tagName, value: id, flex:
|
|
7977
|
+
return (jsx(CheckboxCard, { label: tagName, value: id, flex: '0 0 0%', disabled: true, colorPalette: 'blue' }, `${tagName}-${id}`));
|
|
8054
7978
|
}
|
|
8055
|
-
return (jsx(CheckboxCard, { label: tagName, value: id, flex:
|
|
7979
|
+
return (jsx(CheckboxCard, { label: tagName, value: id, flex: '0 0 0%' }, `${tagName}-${id}`));
|
|
8056
7980
|
}) }) }))] }, `tag-${parent_tag_name}`));
|
|
8057
|
-
}), errors[`${column}`] && (jsx(Text, { color:
|
|
7981
|
+
}), errors[`${column}`] && (jsx(Text, { color: 'red.400', children: (errors[`${column}`]?.message ?? 'No error message') }))] }));
|
|
8058
7982
|
};
|
|
8059
7983
|
|
|
8060
7984
|
const TextAreaViewer = ({ column, schema, prefix, }) => {
|
|
@@ -6,7 +6,6 @@ import { Translate } from './useForm';
|
|
|
6
6
|
import { DateTimePickerLabels, IdPickerLabels, EnumPickerLabels, FilePickerLabels, FormButtonLabels, TimePickerLabels } from './components/types/CustomJSONSchema7';
|
|
7
7
|
export interface SchemaFormContext<TData extends FieldValues> {
|
|
8
8
|
schema: JSONSchema7;
|
|
9
|
-
serverUrl: string;
|
|
10
9
|
requestUrl: string;
|
|
11
10
|
order: string[];
|
|
12
11
|
ignore: string[];
|
|
@@ -7,7 +7,6 @@ import { Translate } from '../../useForm';
|
|
|
7
7
|
import { CustomJSONSchema7, DateTimePickerLabels, IdPickerLabels, EnumPickerLabels, FilePickerLabels, FormButtonLabels, TimePickerLabels } from '../types/CustomJSONSchema7';
|
|
8
8
|
export interface FormRootProps<TData extends FieldValues> {
|
|
9
9
|
schema: CustomJSONSchema7;
|
|
10
|
-
serverUrl: string;
|
|
11
10
|
requestUrl?: string;
|
|
12
11
|
idMap: Record<string, object>;
|
|
13
12
|
setIdMap: Dispatch<SetStateAction<Record<string, object>>>;
|
|
@@ -51,4 +50,4 @@ export declare const idPickerSanityCheck: (column: string, foreign_key?: {
|
|
|
51
50
|
table?: string | undefined;
|
|
52
51
|
column?: string | undefined;
|
|
53
52
|
} | undefined) => void;
|
|
54
|
-
export declare const FormRoot: <TData extends FieldValues>({ schema, idMap, setIdMap, form,
|
|
53
|
+
export declare const FormRoot: <TData extends FieldValues>({ schema, idMap, setIdMap, form, translate, children, order, ignore, include, onSubmit, rowNumber, requestOptions, getUpdatedData, customErrorRenderer, customSuccessRenderer, displayConfig, requireConfirmation, dateTimePickerLabels, idPickerLabels, enumPickerLabels, filePickerLabels, formButtonLabels, timePickerLabels, insideDialog, }: FormRootProps<TData>) => import("react/jsx-runtime").JSX.Element;
|
|
@@ -1,30 +1,9 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
|
-
import {
|
|
3
|
-
import { CustomJSONSchema7 } from '../types/CustomJSONSchema7';
|
|
2
|
+
import { CustomJSONSchema7, LoadInitialValuesParams, LoadInitialValuesResult } from '../types/CustomJSONSchema7';
|
|
4
3
|
export interface RecordType {
|
|
5
4
|
[key: string]: any;
|
|
6
5
|
}
|
|
7
|
-
export
|
|
8
|
-
ids: string[];
|
|
9
|
-
foreign_key: ForeignKeyProps;
|
|
10
|
-
serverUrl: string;
|
|
11
|
-
setIdMap: React.Dispatch<React.SetStateAction<Record<string, object>>>;
|
|
12
|
-
}
|
|
13
|
-
export interface LoadInitialValuesResult {
|
|
14
|
-
data: {
|
|
15
|
-
data: RecordType[];
|
|
16
|
-
count: number;
|
|
17
|
-
};
|
|
18
|
-
idMap: Record<string, object>;
|
|
19
|
-
}
|
|
20
|
-
/**
|
|
21
|
-
* Load initial values for IdPicker fields into idMap
|
|
22
|
-
* Uses customQueryFn if available, otherwise falls back to getTableData
|
|
23
|
-
*
|
|
24
|
-
* @param params - Configuration for loading initial values
|
|
25
|
-
* @returns Promise with fetched data and idMap
|
|
26
|
-
*/
|
|
27
|
-
export declare const loadInitialValues: ({ ids, foreign_key, serverUrl, setIdMap, }: LoadInitialValuesParams) => Promise<LoadInitialValuesResult>;
|
|
6
|
+
export type { LoadInitialValuesParams, LoadInitialValuesResult, } from '../types/CustomJSONSchema7';
|
|
28
7
|
export interface UseIdPickerDataProps {
|
|
29
8
|
column: string;
|
|
30
9
|
schema: CustomJSONSchema7;
|
|
@@ -61,6 +40,7 @@ export interface UseIdPickerDataReturn {
|
|
|
61
40
|
idPickerLabels: any;
|
|
62
41
|
insideDialog: boolean;
|
|
63
42
|
renderDisplay: ((item: RecordType) => React.ReactNode) | undefined;
|
|
43
|
+
loadInitialValues: (params: LoadInitialValuesParams) => Promise<LoadInitialValuesResult>;
|
|
64
44
|
column_ref: string;
|
|
65
45
|
errors: any;
|
|
66
46
|
setValue: (name: string, value: any) => void;
|
|
@@ -3,6 +3,7 @@ import { ReactNode } from 'react';
|
|
|
3
3
|
import { ForeignKeyProps } from '../fields/StringInputField';
|
|
4
4
|
import { UseFormReturn } from 'react-hook-form';
|
|
5
5
|
import { ValidationErrorType } from '../../utils/buildErrorMessages';
|
|
6
|
+
import React from 'react';
|
|
6
7
|
export interface DateTimePickerLabels {
|
|
7
8
|
monthNamesShort?: string[];
|
|
8
9
|
weekdayNamesShort?: string[];
|
|
@@ -60,12 +61,25 @@ export interface TimePickerLabels {
|
|
|
60
61
|
placeholder?: string;
|
|
61
62
|
emptyMessage?: string;
|
|
62
63
|
}
|
|
64
|
+
export interface LoadInitialValuesParams {
|
|
65
|
+
ids: string[];
|
|
66
|
+
foreign_key: ForeignKeyProps;
|
|
67
|
+
setIdMap: React.Dispatch<React.SetStateAction<Record<string, object>>>;
|
|
68
|
+
}
|
|
69
|
+
export interface LoadInitialValuesResult {
|
|
70
|
+
data: {
|
|
71
|
+
data: Record<string, any>[];
|
|
72
|
+
count: number;
|
|
73
|
+
};
|
|
74
|
+
idMap: Record<string, object>;
|
|
75
|
+
}
|
|
63
76
|
export interface CustomJSONSchema7 extends JSONSchema7 {
|
|
64
77
|
gridColumn?: string;
|
|
65
78
|
gridRow?: string;
|
|
66
79
|
foreign_key?: ForeignKeyProps;
|
|
67
80
|
variant?: string;
|
|
68
81
|
renderDisplay?: (item: unknown) => ReactNode;
|
|
82
|
+
loadInitialValues?: (params: LoadInitialValuesParams) => Promise<LoadInitialValuesResult>;
|
|
69
83
|
inputRender?: (props: {
|
|
70
84
|
column: string;
|
|
71
85
|
schema: CustomJSONSchema7;
|
|
@@ -87,6 +101,24 @@ export interface CustomJSONSchema7 extends JSONSchema7 {
|
|
|
87
101
|
numberStorageType?: 'string' | 'number';
|
|
88
102
|
errorMessages?: Partial<Record<ValidationErrorType | string, string>>;
|
|
89
103
|
filePicker?: FilePickerProps;
|
|
104
|
+
tagPicker?: {
|
|
105
|
+
queryFn?: (params: {
|
|
106
|
+
in_table: string;
|
|
107
|
+
where?: {
|
|
108
|
+
id: string;
|
|
109
|
+
value: string[];
|
|
110
|
+
}[];
|
|
111
|
+
limit?: number;
|
|
112
|
+
offset?: number;
|
|
113
|
+
searching?: string;
|
|
114
|
+
}) => Promise<{
|
|
115
|
+
data: {
|
|
116
|
+
data: any[];
|
|
117
|
+
count: number;
|
|
118
|
+
};
|
|
119
|
+
idMap?: Record<string, object>;
|
|
120
|
+
}>;
|
|
121
|
+
};
|
|
90
122
|
}
|
|
91
123
|
export declare const defaultRenderDisplay: (item: unknown) => ReactNode;
|
|
92
124
|
export interface TagPickerProps {
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
export interface GetTableDataConfig {
|
|
2
|
-
serverUrl: string;
|
|
3
2
|
in_table: string;
|
|
4
3
|
limit?: number;
|
|
5
4
|
offset?: number;
|
|
@@ -13,4 +12,4 @@ export interface GetTableResponse {
|
|
|
13
12
|
data?: object[];
|
|
14
13
|
count: number;
|
|
15
14
|
}
|
|
16
|
-
export declare const getTableData: ({
|
|
15
|
+
export declare const getTableData: ({ in_table, searching, where, limit, offset, }: GetTableDataConfig) => Promise<never>;
|