@solidxai/core-ui 0.1.3 → 0.1.4-beta.1
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/components/auth/SolidInitialLoginOtp.d.ts.map +1 -1
- package/dist/components/auth/SolidInitialLoginOtp.js +0 -5
- package/dist/components/auth/SolidInitialLoginOtp.js.map +1 -1
- package/dist/components/auth/SolidInitialLoginOtp.tsx +0 -5
- package/dist/components/auth/SolidLogin.d.ts.map +1 -1
- package/dist/components/auth/SolidLogin.js +7 -5
- package/dist/components/auth/SolidLogin.js.map +1 -1
- package/dist/components/auth/SolidLogin.tsx +10 -8
- package/dist/components/common/GeneralSettings.d.ts.map +1 -1
- package/dist/components/common/GeneralSettings.js +48 -47
- package/dist/components/common/GeneralSettings.js.map +1 -1
- package/dist/components/common/GeneralSettings.tsx +41 -10
- package/dist/components/core/common/FilterComponent.js.map +1 -1
- package/dist/components/core/common/FilterComponent.tsx +1 -1
- package/dist/components/core/common/GroupingComponent.d.ts +54 -0
- package/dist/components/core/common/GroupingComponent.d.ts.map +1 -0
- package/dist/components/core/common/GroupingComponent.js +196 -0
- package/dist/components/core/common/GroupingComponent.js.map +1 -0
- package/dist/components/core/common/GroupingComponent.tsx +452 -0
- package/dist/components/core/common/SolidGlobalSearchElement.d.ts +18 -1
- package/dist/components/core/common/SolidGlobalSearchElement.d.ts.map +1 -1
- package/dist/components/core/common/SolidGlobalSearchElement.js +152 -52
- package/dist/components/core/common/SolidGlobalSearchElement.js.map +1 -1
- package/dist/components/core/common/SolidGlobalSearchElement.tsx +212 -35
- package/dist/components/core/extension/solid-core/modelSequence/modelSequenceFormViewChangeHandler.d.ts +19 -0
- package/dist/components/core/extension/solid-core/modelSequence/modelSequenceFormViewChangeHandler.d.ts.map +1 -0
- package/dist/components/core/extension/solid-core/modelSequence/modelSequenceFormViewChangeHandler.js +90 -0
- package/dist/components/core/extension/solid-core/modelSequence/modelSequenceFormViewChangeHandler.js.map +1 -0
- package/dist/components/core/extension/solid-core/modelSequence/modelSequenceFormViewChangeHandler.tsx +59 -0
- package/dist/components/core/extension/solid-core/roleMetadata/RolePermissionsManyToManyFieldWidget.d.ts.map +1 -1
- package/dist/components/core/extension/solid-core/roleMetadata/RolePermissionsManyToManyFieldWidget.js +17 -28
- package/dist/components/core/extension/solid-core/roleMetadata/RolePermissionsManyToManyFieldWidget.js.map +1 -1
- package/dist/components/core/extension/solid-core/roleMetadata/RolePermissionsManyToManyFieldWidget.tsx +71 -56
- package/dist/components/core/filter/SolidOneToManyFilterElement.d.ts +2 -0
- package/dist/components/core/filter/SolidOneToManyFilterElement.d.ts.map +1 -0
- package/dist/components/core/filter/SolidOneToManyFilterElement.js +86 -0
- package/dist/components/core/filter/SolidOneToManyFilterElement.js.map +1 -0
- package/dist/components/core/filter/SolidOneToManyFilterElement.tsx +62 -0
- package/dist/components/core/filter/SolidVarInputsFilterElement.d.ts +1 -0
- package/dist/components/core/filter/SolidVarInputsFilterElement.d.ts.map +1 -1
- package/dist/components/core/filter/SolidVarInputsFilterElement.js +4 -1
- package/dist/components/core/filter/SolidVarInputsFilterElement.js.map +1 -1
- package/dist/components/core/filter/SolidVarInputsFilterElement.tsx +10 -0
- package/dist/components/core/filter/fields/SolidRelationField.d.ts.map +1 -1
- package/dist/components/core/filter/fields/SolidRelationField.js +4 -2
- package/dist/components/core/filter/fields/SolidRelationField.js.map +1 -1
- package/dist/components/core/filter/fields/SolidRelationField.tsx +4 -2
- package/dist/components/core/filter/fields/relations/SolidRelationOneToManyField.d.ts +4 -0
- package/dist/components/core/filter/fields/relations/SolidRelationOneToManyField.d.ts.map +1 -0
- package/dist/components/core/filter/fields/relations/SolidRelationOneToManyField.js +25 -0
- package/dist/components/core/filter/fields/relations/SolidRelationOneToManyField.js.map +1 -0
- package/dist/components/core/filter/fields/relations/SolidRelationOneToManyField.tsx +60 -0
- package/dist/components/core/form/SolidFormFooter.js +4 -4
- package/dist/components/core/form/SolidFormFooter.js.map +1 -1
- package/dist/components/core/form/SolidFormFooter.tsx +4 -4
- package/dist/components/core/form/fields/SolidBooleanField.d.ts.map +1 -1
- package/dist/components/core/form/fields/SolidBooleanField.js +11 -8
- package/dist/components/core/form/fields/SolidBooleanField.js.map +1 -1
- package/dist/components/core/form/fields/SolidBooleanField.tsx +20 -8
- package/dist/components/core/form/fields/relations/SolidRelationManyToManyField.d.ts +40 -0
- package/dist/components/core/form/fields/relations/SolidRelationManyToManyField.d.ts.map +1 -1
- package/dist/components/core/form/fields/relations/SolidRelationManyToManyField.js +317 -157
- package/dist/components/core/form/fields/relations/SolidRelationManyToManyField.js.map +1 -1
- package/dist/components/core/form/fields/relations/SolidRelationManyToManyField.tsx +463 -243
- package/dist/components/core/form/fields/relations/SolidRelationOneToManyField.d.ts.map +1 -1
- package/dist/components/core/form/fields/relations/SolidRelationOneToManyField.js +46 -95
- package/dist/components/core/form/fields/relations/SolidRelationOneToManyField.js.map +1 -1
- package/dist/components/core/form/fields/relations/SolidRelationOneToManyField.tsx +57 -113
- package/dist/components/core/form/fields/relations/widgets/helpers/useRelationEntityHandler.d.ts +15 -4
- package/dist/components/core/form/fields/relations/widgets/helpers/useRelationEntityHandler.d.ts.map +1 -1
- package/dist/components/core/form/fields/relations/widgets/helpers/useRelationEntityHandler.js +220 -33
- package/dist/components/core/form/fields/relations/widgets/helpers/useRelationEntityHandler.js.map +1 -1
- package/dist/components/core/form/fields/relations/widgets/helpers/useRelationEntityHandler.ts +167 -36
- package/dist/components/core/kanban/SolidKanbanView.d.ts.map +1 -1
- package/dist/components/core/kanban/SolidKanbanView.js +13 -12
- package/dist/components/core/kanban/SolidKanbanView.js.map +1 -1
- package/dist/components/core/kanban/SolidKanbanView.tsx +8 -7
- package/dist/components/core/list/SolidListView.d.ts +18 -10
- package/dist/components/core/list/SolidListView.d.ts.map +1 -1
- package/dist/components/core/list/SolidListView.js +176 -177
- package/dist/components/core/list/SolidListView.js.map +1 -1
- package/dist/components/core/list/SolidListView.tsx +130 -143
- package/dist/components/core/list/SolidListViewConfigure.d.ts +7 -0
- package/dist/components/core/list/SolidListViewConfigure.d.ts.map +1 -1
- package/dist/components/core/list/SolidListViewConfigure.js +6 -5
- package/dist/components/core/list/SolidListViewConfigure.js.map +1 -1
- package/dist/components/core/list/SolidListViewConfigure.tsx +21 -12
- package/dist/components/core/list/columns/SolidShortTextColumn.d.ts.map +1 -1
- package/dist/components/core/list/columns/SolidShortTextColumn.js +1 -37
- package/dist/components/core/list/columns/SolidShortTextColumn.js.map +1 -1
- package/dist/components/core/list/columns/SolidShortTextColumn.tsx +0 -41
- package/dist/components/core/list/columns/relations/SolidRelationManyToOneColumn.d.ts.map +1 -1
- package/dist/components/core/list/columns/relations/SolidRelationManyToOneColumn.js +9 -5
- package/dist/components/core/list/columns/relations/SolidRelationManyToOneColumn.js.map +1 -1
- package/dist/components/core/list/columns/relations/SolidRelationManyToOneColumn.tsx +14 -3
- package/dist/components/core/list/listViewRegistry.js.map +1 -1
- package/dist/components/core/list/listViewRegistry.ts +1 -2
- package/dist/components/core/tree/SolidTreeView.d.ts +38 -0
- package/dist/components/core/tree/SolidTreeView.d.ts.map +1 -0
- package/dist/components/core/tree/SolidTreeView.js +1179 -0
- package/dist/components/core/tree/SolidTreeView.js.map +1 -0
- package/dist/components/core/tree/SolidTreeView.tsx +1637 -0
- package/dist/components/core/tree/treeViewRegistry.d.ts +7 -0
- package/dist/components/core/tree/treeViewRegistry.d.ts.map +1 -0
- package/dist/components/core/tree/treeViewRegistry.js +17 -0
- package/dist/components/core/tree/treeViewRegistry.js.map +1 -0
- package/dist/components/core/tree/treeViewRegistry.ts +23 -0
- package/dist/components/core/users/CreateUser.d.ts.map +1 -1
- package/dist/components/core/users/CreateUser.js +19 -6
- package/dist/components/core/users/CreateUser.js.map +1 -1
- package/dist/components/core/users/CreateUser.tsx +39 -0
- package/dist/helpers/helpers.d.ts +2 -0
- package/dist/helpers/helpers.d.ts.map +1 -1
- package/dist/helpers/helpers.js +3 -1
- package/dist/helpers/helpers.js.map +1 -1
- package/dist/helpers/helpers.ts +4 -1
- package/dist/helpers/registry.d.ts.map +1 -1
- package/dist/helpers/registry.js +5 -1
- package/dist/helpers/registry.js.map +1 -1
- package/dist/helpers/registry.ts +7 -2
- package/dist/index.d.ts +3 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -1
- package/dist/index.ts +6 -1
- package/dist/resources/globals.css +32 -4
- package/dist/routes/pages/admin/core/ListPage.d.ts.map +1 -1
- package/dist/routes/pages/admin/core/ListPage.js +2 -2
- package/dist/routes/pages/admin/core/ListPage.js.map +1 -1
- package/dist/routes/pages/admin/core/ListPage.tsx +3 -2
- package/dist/routes/pages/admin/core/ModuleHomePage.d.ts.map +1 -1
- package/dist/routes/pages/admin/core/ModuleHomePage.js +4 -15
- package/dist/routes/pages/admin/core/ModuleHomePage.js.map +1 -1
- package/dist/routes/pages/admin/core/ModuleHomePage.tsx +4 -3
- package/dist/routes/pages/admin/core/TreePage.d.ts +2 -0
- package/dist/routes/pages/admin/core/TreePage.d.ts.map +1 -0
- package/dist/routes/pages/admin/core/TreePage.js +37 -0
- package/dist/routes/pages/admin/core/TreePage.js.map +1 -0
- package/dist/routes/pages/admin/core/TreePage.tsx +30 -0
- package/dist/routes/solidRoutes.d.ts.map +1 -1
- package/dist/routes/solidRoutes.js +2 -0
- package/dist/routes/solidRoutes.js.map +1 -1
- package/dist/routes/solidRoutes.tsx +3 -1
- package/dist/routes/types.d.ts +1 -1
- package/dist/routes/types.d.ts.map +1 -1
- package/dist/routes/types.js.map +1 -1
- package/dist/routes/types.ts +1 -0
- package/dist/types/index.d.ts +8 -2
- package/dist/types/solid-core.d.ts +40 -0
- package/package.json +1 -1
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
|
|
2
1
|
import { Message } from "primereact/message";
|
|
3
2
|
import { useEffect, useState } from "react";
|
|
4
3
|
import * as Yup from 'yup';
|
|
@@ -9,16 +8,33 @@ import { Button } from "primereact/button";
|
|
|
9
8
|
import { SolidFormFieldWidgetProps } from "../../../../../types/solid-core";
|
|
10
9
|
import { useRelationEntityHandler } from "./widgets/helpers/useRelationEntityHandler";
|
|
11
10
|
import { InlineRelationEntityDialog } from "./widgets/helpers/InlineRelationEntityDialog";
|
|
12
|
-
import { capitalize } from "lodash";
|
|
13
11
|
import { Checkbox } from "primereact/checkbox";
|
|
14
12
|
import { Panel } from "primereact/panel";
|
|
15
13
|
import { SolidFieldTooltip } from "../../../../../components/common/SolidFieldTooltip";
|
|
16
14
|
import qs from 'qs';
|
|
17
|
-
// import Handlebars from "handlebars/dist/handlebars";
|
|
18
15
|
import * as Handlebars from "handlebars";
|
|
19
16
|
import { ERROR_MESSAGES } from "../../../../../constants/error-messages";
|
|
20
|
-
|
|
21
|
-
|
|
17
|
+
import { useRouter } from "../../../../../hooks/useRouter";
|
|
18
|
+
import { usePathname } from "../../../../../hooks/usePathname";
|
|
19
|
+
import { camelCase, capitalize } from "lodash";
|
|
20
|
+
import { SolidListView } from "../../../../core/list/SolidListView";
|
|
21
|
+
import { RenderSolidFormEmbededView } from "./SolidRelationManyToOneField";
|
|
22
|
+
import { Dialog } from "primereact/dialog";
|
|
23
|
+
|
|
24
|
+
export type FormViewParams = {
|
|
25
|
+
moduleName: any;
|
|
26
|
+
id: any;
|
|
27
|
+
embeded: any;
|
|
28
|
+
isCustomCreate: any;
|
|
29
|
+
customLayout: any;
|
|
30
|
+
modelName: any;
|
|
31
|
+
parentFieldName?: any;
|
|
32
|
+
parentData: any;
|
|
33
|
+
onEmbeddedFormSave: any;
|
|
34
|
+
inlineCreateAutoSave: any;
|
|
35
|
+
customCreateHandler?: any;
|
|
36
|
+
handlePopupClose?: any;
|
|
37
|
+
};
|
|
22
38
|
|
|
23
39
|
|
|
24
40
|
|
|
@@ -31,63 +47,20 @@ export class SolidRelationManyToManyField implements ISolidField {
|
|
|
31
47
|
}
|
|
32
48
|
|
|
33
49
|
initialValue(): any {
|
|
34
|
-
|
|
35
|
-
const manyToManyFieldData = this.fieldContext.data[this.fieldContext.field.attrs.name];
|
|
36
|
-
const fieldMetadata = this.fieldContext.fieldMetadata;
|
|
37
|
-
const userKeyField = fieldMetadata?.relationModel?.userKeyField?.name;
|
|
38
|
-
if (manyToManyFieldData) {
|
|
39
|
-
return manyToManyFieldData.map((e: any) => {
|
|
40
|
-
const manyToManyColVal = e[userKeyField] || '';
|
|
41
|
-
return {
|
|
42
|
-
label: manyToManyColVal,
|
|
43
|
-
value: e?.id || '',
|
|
44
|
-
original: e
|
|
45
|
-
};
|
|
46
|
-
});
|
|
47
|
-
}
|
|
48
50
|
return [];
|
|
49
51
|
}
|
|
50
52
|
|
|
51
53
|
updateFormData(value: any, formData: FormData): any {
|
|
52
|
-
|
|
53
|
-
//
|
|
54
|
-
if(value && value.length === 0) {
|
|
55
|
-
formData.append(`${fieldLayoutInfo.attrs.name}Command`, "clear");
|
|
56
|
-
}
|
|
57
|
-
if (value && value.length > 0) {
|
|
58
|
-
const shouldUseOriginal = value.every((item: any) => item.original && item.original.id);
|
|
59
|
-
|
|
60
|
-
value.forEach((item: any, index: number) => {
|
|
61
|
-
if (shouldUseOriginal) {
|
|
62
|
-
formData.append(
|
|
63
|
-
`${fieldLayoutInfo.attrs.name}Ids[${index}]`,
|
|
64
|
-
item.value
|
|
65
|
-
);
|
|
66
|
-
} else {
|
|
67
|
-
formData.append(
|
|
68
|
-
`${fieldLayoutInfo.attrs.name}[${index}]`,
|
|
69
|
-
JSON.stringify(item.original)
|
|
70
|
-
);
|
|
71
|
-
}
|
|
72
|
-
});
|
|
73
|
-
if (shouldUseOriginal) {
|
|
74
|
-
formData.append(`${fieldLayoutInfo.attrs.name}Command`, "set")
|
|
75
|
-
} else {
|
|
76
|
-
formData.append(`${fieldLayoutInfo.attrs.name}Command`, "update")
|
|
77
|
-
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
}
|
|
54
|
+
// Link/unlink is handled per-interaction in each widget.
|
|
55
|
+
// No bulk update needed on form submit for many-to-many.
|
|
81
56
|
}
|
|
82
57
|
|
|
83
58
|
validationSchema(): Yup.Schema {
|
|
84
59
|
let schema = Yup.array();
|
|
85
|
-
|
|
86
60
|
const fieldMetadata = this.fieldContext.fieldMetadata;
|
|
87
61
|
const fieldLayoutInfo = this.fieldContext.field;
|
|
88
62
|
const fieldLabel = fieldLayoutInfo.attrs.label ?? fieldMetadata.displayName;
|
|
89
63
|
|
|
90
|
-
// 1. required
|
|
91
64
|
if (fieldMetadata.required) {
|
|
92
65
|
schema = schema
|
|
93
66
|
.min(1, ERROR_MESSAGES.SELECT_ATLEAST_ONE(fieldLabel))
|
|
@@ -98,75 +71,73 @@ export class SolidRelationManyToManyField implements ISolidField {
|
|
|
98
71
|
}
|
|
99
72
|
|
|
100
73
|
render(formik: FormikObject) {
|
|
101
|
-
const fieldMetadata = this.fieldContext.fieldMetadata;
|
|
102
74
|
const fieldLayoutInfo = this.fieldContext.field;
|
|
103
75
|
const className = fieldLayoutInfo.attrs?.className || 'field col-12';
|
|
104
76
|
|
|
105
|
-
const isFormFieldValid = (formik: any, fieldName: string) => formik.touched[fieldName] && formik.errors[fieldName];
|
|
106
|
-
const fieldLabel = fieldLayoutInfo.attrs.label ?? fieldMetadata.displayName;
|
|
107
|
-
|
|
108
77
|
let viewWidget = fieldLayoutInfo.attrs.viewWidget;
|
|
109
78
|
let editWidget = fieldLayoutInfo.attrs.editWidget;
|
|
110
|
-
if (!editWidget)
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
if (!viewWidget) {
|
|
114
|
-
viewWidget = 'DefaultRelationOneToManyFormViewWidget';
|
|
115
|
-
}
|
|
79
|
+
if (!editWidget) editWidget = 'DefaultRelationManyToManyAutoCompleteFormEditWidget';
|
|
80
|
+
if (!viewWidget) viewWidget = 'DefaultRelationManyToManyListFormEditWidget';
|
|
81
|
+
|
|
116
82
|
const viewMode: string = this.fieldContext.viewMode;
|
|
117
83
|
return (
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
}
|
|
123
|
-
{viewMode === "edit" && (
|
|
124
|
-
<>
|
|
125
|
-
{editWidget &&
|
|
126
|
-
this.renderExtensionRenderMode(editWidget, formik)
|
|
127
|
-
}
|
|
128
|
-
</>
|
|
129
|
-
)
|
|
130
|
-
}
|
|
131
|
-
</div>
|
|
132
|
-
</>
|
|
84
|
+
<div className={className}>
|
|
85
|
+
{viewMode === "view" && this.renderExtensionRenderMode(viewWidget, formik)}
|
|
86
|
+
{viewMode === "edit" && editWidget && this.renderExtensionRenderMode(editWidget, formik)}
|
|
87
|
+
</div>
|
|
133
88
|
);
|
|
134
89
|
}
|
|
135
90
|
|
|
136
91
|
renderExtensionRenderMode(widget: string, formik: FormikObject) {
|
|
137
|
-
|
|
138
|
-
const widgetProps: SolidFormFieldWidgetProps = {
|
|
139
|
-
|
|
140
|
-
fieldContext: this.fieldContext,
|
|
141
|
-
}
|
|
142
|
-
return (
|
|
143
|
-
<>
|
|
144
|
-
{DynamicWidget && <DynamicWidget {...widgetProps} />}
|
|
145
|
-
</>
|
|
146
|
-
)
|
|
92
|
+
const DynamicWidget = getExtensionComponent(widget);
|
|
93
|
+
const widgetProps: SolidFormFieldWidgetProps = { formik, fieldContext: this.fieldContext };
|
|
94
|
+
return <>{DynamicWidget && <DynamicWidget {...widgetProps} />}</>;
|
|
147
95
|
}
|
|
148
96
|
}
|
|
149
97
|
|
|
150
98
|
|
|
151
99
|
|
|
100
|
+
/**
|
|
101
|
+
* AUTOCOMPLETE WIDGET
|
|
102
|
+
*
|
|
103
|
+
* State:
|
|
104
|
+
* currentValues — chips shown in the input (currently linked items)
|
|
105
|
+
* suggestions — dropdown options populated on each keystroke
|
|
106
|
+
*
|
|
107
|
+
* Flow:
|
|
108
|
+
* mount → fetchCurrentValues()
|
|
109
|
+
* user types → fetchSuggestions() via completeMethod
|
|
110
|
+
* user selects → linkItem() → on success, adds to currentValues
|
|
111
|
+
* user removes chip→ unlinkItem() → on success, removes from currentValues
|
|
112
|
+
*/
|
|
152
113
|
export const DefaultRelationManyToManyAutoCompleteFormEditWidget = ({ formik, fieldContext }: SolidFormFieldWidgetProps) => {
|
|
153
114
|
const fieldMetadata = fieldContext.fieldMetadata;
|
|
154
115
|
const fieldLayoutInfo = fieldContext.field;
|
|
155
|
-
const className = fieldLayoutInfo.attrs?.className || 'field col-12';
|
|
156
116
|
const fieldLabel = fieldLayoutInfo.attrs.label ?? fieldMetadata.displayName;
|
|
157
117
|
const showFieldLabel = fieldLayoutInfo?.attrs?.showLabel;
|
|
158
118
|
const readOnlyPermission = fieldContext.readOnly;
|
|
159
119
|
const disabled = fieldLayoutInfo.attrs?.disabled;
|
|
160
120
|
const readOnly = fieldLayoutInfo.attrs?.readOnly;
|
|
161
|
-
const whereClause = fieldLayoutInfo.attrs.whereClause;
|
|
162
121
|
|
|
163
122
|
const [visibleCreateDialog, setVisibleCreateDialog] = useState(false);
|
|
164
|
-
const { autoCompleteItems, fetchRelationEntities, addNewRelation } = useRelationEntityHandler({ fieldContext, formik });
|
|
165
|
-
const isFormFieldValid = (formik: any, fieldName: string) => formik.touched[fieldName] && formik.errors[fieldName];
|
|
166
123
|
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
124
|
+
const {
|
|
125
|
+
currentValues,
|
|
126
|
+
suggestions,
|
|
127
|
+
fetchCurrentValues,
|
|
128
|
+
fetchSuggestions,
|
|
129
|
+
linkItem,
|
|
130
|
+
unlinkItem,
|
|
131
|
+
addNewRelation,
|
|
132
|
+
} = useRelationEntityHandler({ fieldContext });
|
|
133
|
+
|
|
134
|
+
const isFormFieldValid = (formik: any, fieldName: string) =>
|
|
135
|
+
formik.touched[fieldName] && formik.errors[fieldName];
|
|
136
|
+
|
|
137
|
+
// On mount: load already-linked items into currentValues
|
|
138
|
+
useEffect(() => {
|
|
139
|
+
fetchCurrentValues();
|
|
140
|
+
}, [fieldContext.data?.id]);
|
|
170
141
|
|
|
171
142
|
const autoCompleteSearch = async (event: AutoCompleteCompleteEvent) => {
|
|
172
143
|
const queryData: any = {
|
|
@@ -176,93 +147,72 @@ export const DefaultRelationManyToManyAutoCompleteFormEditWidget = ({ formik, fi
|
|
|
176
147
|
$and: [
|
|
177
148
|
{
|
|
178
149
|
[fieldMetadata?.relationModel?.userKeyField?.name]: {
|
|
179
|
-
[fieldLayoutInfo?.attrs?.autocompleteMatchMode || '$containsi']: event.query
|
|
180
|
-
}
|
|
181
|
-
}
|
|
182
|
-
]
|
|
183
|
-
}
|
|
150
|
+
[fieldLayoutInfo?.attrs?.autocompleteMatchMode || '$containsi']: event.query,
|
|
151
|
+
},
|
|
152
|
+
},
|
|
153
|
+
],
|
|
154
|
+
},
|
|
184
155
|
};
|
|
156
|
+
|
|
185
157
|
let fixedFilterToBeApplied = false;
|
|
186
158
|
let fixedFilterParsed = false;
|
|
187
159
|
|
|
188
160
|
if (fieldMetadata?.relationFieldFixedFilter || fieldLayoutInfo?.attrs?.whereClause) {
|
|
189
|
-
const
|
|
161
|
+
const rawFilter = fieldLayoutInfo?.attrs?.whereClause ?? fieldMetadata?.relationFieldFixedFilter;
|
|
190
162
|
fixedFilterToBeApplied = true;
|
|
191
|
-
const
|
|
192
|
-
const renderedFilter = fixedFilterTemplate(formik.values);
|
|
163
|
+
const rendered = Handlebars.compile(rawFilter)(formik.values);
|
|
193
164
|
|
|
194
|
-
let parsedFilter: any;
|
|
195
165
|
try {
|
|
196
|
-
|
|
197
|
-
const
|
|
198
|
-
if (
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
if (val === null || val === undefined || val === '') return false;
|
|
202
|
-
if (typeof val === 'object') {
|
|
203
|
-
return Object.values(val).some(hasValidValue);
|
|
204
|
-
}
|
|
205
|
-
return true;
|
|
206
|
-
};
|
|
207
|
-
|
|
208
|
-
return hasValidValue(parsedFilter);
|
|
166
|
+
const parsed = JSON.parse(rendered);
|
|
167
|
+
const hasValue = (val: any): boolean => {
|
|
168
|
+
if (val === null || val === undefined || val === '') return false;
|
|
169
|
+
if (typeof val === 'object') return Object.values(val).some(hasValue);
|
|
170
|
+
return true;
|
|
209
171
|
};
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
queryData.filters.$and.push(parsedFilter);
|
|
172
|
+
if (hasValue(parsed)) {
|
|
173
|
+
queryData.filters.$and.push(parsed);
|
|
213
174
|
fixedFilterParsed = true;
|
|
214
175
|
} else {
|
|
215
|
-
console.warn(ERROR_MESSAGES.SKIPPING_EMPTY_FIXED_FILTER,
|
|
176
|
+
console.warn(ERROR_MESSAGES.SKIPPING_EMPTY_FIXED_FILTER, parsed);
|
|
216
177
|
}
|
|
217
178
|
} catch (e) {
|
|
218
|
-
console.error(ERROR_MESSAGES.INVALID_JSON_WHERECLAUSE,
|
|
219
|
-
parsedFilter = {};
|
|
179
|
+
console.error(ERROR_MESSAGES.INVALID_JSON_WHERECLAUSE, rendered);
|
|
220
180
|
}
|
|
221
|
-
|
|
222
181
|
}
|
|
223
182
|
|
|
224
|
-
let autocompleteQs = qs.stringify(queryData, {
|
|
225
|
-
encodeValuesOnly: true,
|
|
226
|
-
});
|
|
227
|
-
// if (whereClause) {
|
|
228
|
-
// autocompleteQs = `${autocompleteQs}&${whereClause}`;
|
|
229
|
-
// }
|
|
230
|
-
|
|
231
183
|
if (fixedFilterToBeApplied && !fixedFilterParsed) {
|
|
232
184
|
console.error(ERROR_MESSAGES.FIXED_FILTER_NOT_APPLIED);
|
|
233
|
-
|
|
234
185
|
} else {
|
|
235
|
-
|
|
236
|
-
// encodeValuesOnly: true,
|
|
237
|
-
// });
|
|
238
|
-
fetchRelationEntities(autocompleteQs);
|
|
186
|
+
fetchSuggestions(qs.stringify(queryData, { encodeValuesOnly: true }));
|
|
239
187
|
}
|
|
240
188
|
};
|
|
241
189
|
|
|
242
190
|
return (
|
|
243
|
-
|
|
244
191
|
<div className="relative">
|
|
245
192
|
<div className="flex flex-column gap-2 mt-1 sm:mt-2 md:mt-3 lg:mt-4">
|
|
246
|
-
{showFieldLabel
|
|
193
|
+
{showFieldLabel !== false && (
|
|
247
194
|
<label htmlFor={fieldLayoutInfo.attrs.name} className="form-field-label">
|
|
248
195
|
{fieldLabel}
|
|
249
196
|
{fieldMetadata.required && <span className="text-red-500"> *</span>}
|
|
250
197
|
<SolidFieldTooltip fieldContext={fieldContext} />
|
|
251
198
|
</label>
|
|
252
|
-
}
|
|
199
|
+
)}
|
|
253
200
|
<div className="flex align-items-center gap-3">
|
|
254
201
|
<AutoComplete
|
|
255
202
|
readOnly={readOnly || readOnlyPermission}
|
|
256
203
|
disabled={disabled || readOnlyPermission}
|
|
257
204
|
multiple
|
|
258
|
-
{...formik.getFieldProps(fieldLayoutInfo.attrs.name)}
|
|
259
205
|
id={fieldLayoutInfo.attrs.name}
|
|
260
206
|
field="label"
|
|
261
|
-
value={
|
|
207
|
+
value={currentValues}
|
|
262
208
|
dropdown={!readOnlyPermission}
|
|
263
|
-
suggestions={
|
|
209
|
+
suggestions={suggestions}
|
|
264
210
|
completeMethod={autoCompleteSearch}
|
|
265
|
-
onChange={(
|
|
211
|
+
onChange={() => {
|
|
212
|
+
// Intentionally empty — currentValues is managed via onSelect/onUnselect
|
|
213
|
+
}}
|
|
214
|
+
onSelect={(e) => linkItem(e.value)}
|
|
215
|
+
onUnselect={(e) => unlinkItem(e.value)}
|
|
266
216
|
className="solid-standard-autocomplete w-full"
|
|
267
217
|
/>
|
|
268
218
|
{fieldContext.field.attrs.inlineCreate && (
|
|
@@ -296,158 +246,428 @@ export const DefaultRelationManyToManyAutoCompleteFormEditWidget = ({ formik, fi
|
|
|
296
246
|
)}
|
|
297
247
|
</div>
|
|
298
248
|
);
|
|
299
|
-
}
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
249
|
+
};
|
|
250
|
+
|
|
251
|
+
|
|
252
|
+
|
|
253
|
+
/**
|
|
254
|
+
* CHECKBOX WIDGET
|
|
255
|
+
*
|
|
256
|
+
* State:
|
|
257
|
+
* allOptions — every possible item to render as a checkbox row
|
|
258
|
+
* currentValues — the subset that is currently linked (drives checked state)
|
|
259
|
+
*
|
|
260
|
+
* Flow:
|
|
261
|
+
* mount → fetchCurrentValues() + fetchAllOptions()
|
|
262
|
+
* user checks → linkItem() → on success, adds to currentValues
|
|
263
|
+
* user unchecks → unlinkItem() → on success, removes from currentValues
|
|
264
|
+
*/
|
|
303
265
|
export const DefaultRelationManyToManyCheckBoxFormEditWidget = ({ formik, fieldContext }: SolidFormFieldWidgetProps) => {
|
|
304
266
|
const fieldMetadata = fieldContext.fieldMetadata;
|
|
305
267
|
const fieldLayoutInfo = fieldContext.field;
|
|
306
268
|
const showFieldLabel = fieldLayoutInfo?.attrs?.showLabel;
|
|
307
|
-
|
|
308
269
|
const readOnlyPermission = fieldContext.readOnly;
|
|
270
|
+
|
|
309
271
|
const [visibleCreateDialog, setVisibleCreateDialog] = useState(false);
|
|
310
|
-
|
|
272
|
+
|
|
273
|
+
const {
|
|
274
|
+
currentValues,
|
|
275
|
+
allOptions,
|
|
276
|
+
fetchCurrentValues,
|
|
277
|
+
fetchAllOptions,
|
|
278
|
+
linkItem,
|
|
279
|
+
unlinkItem,
|
|
280
|
+
addNewRelation,
|
|
281
|
+
} = useRelationEntityHandler({ fieldContext });
|
|
282
|
+
|
|
283
|
+
// On mount: load already-linked items + all possible options
|
|
284
|
+
useEffect(() => {
|
|
285
|
+
fetchCurrentValues();
|
|
286
|
+
}, [fieldContext.data?.id]);
|
|
311
287
|
|
|
312
288
|
useEffect(() => {
|
|
313
|
-
const fieldMetadata = fieldContext.fieldMetadata;
|
|
314
|
-
const fieldLayoutInfo = fieldContext.field;
|
|
315
289
|
const queryData: any = {
|
|
316
290
|
offset: 0,
|
|
317
291
|
limit: 1000,
|
|
318
|
-
filters: {
|
|
319
|
-
$and: []
|
|
320
|
-
}
|
|
292
|
+
filters: { $and: [] },
|
|
321
293
|
};
|
|
322
294
|
|
|
323
295
|
let fixedFilterToBeApplied = false;
|
|
324
296
|
let fixedFilterParsed = false;
|
|
325
297
|
|
|
326
298
|
if (fieldMetadata?.relationFieldFixedFilter || fieldLayoutInfo?.attrs?.whereClause) {
|
|
327
|
-
const
|
|
299
|
+
const rawFilter = fieldLayoutInfo?.attrs?.whereClause ?? fieldMetadata?.relationFieldFixedFilter;
|
|
328
300
|
fixedFilterToBeApplied = true;
|
|
329
|
-
const
|
|
330
|
-
const renderedFilter = fixedFilterTemplate(formik.values);
|
|
301
|
+
const rendered = Handlebars.compile(rawFilter)(formik.values);
|
|
331
302
|
|
|
332
|
-
let parsedFilter: any;
|
|
333
303
|
try {
|
|
334
|
-
|
|
335
|
-
const
|
|
336
|
-
if (
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
if (val === null || val === undefined || val === '') return false;
|
|
340
|
-
if (typeof val === 'object') {
|
|
341
|
-
return Object.values(val).some(hasValidValue);
|
|
342
|
-
}
|
|
343
|
-
return true;
|
|
344
|
-
};
|
|
345
|
-
|
|
346
|
-
return hasValidValue(parsedFilter);
|
|
304
|
+
const parsed = JSON.parse(rendered);
|
|
305
|
+
const hasValue = (val: any): boolean => {
|
|
306
|
+
if (val === null || val === undefined || val === '') return false;
|
|
307
|
+
if (typeof val === 'object') return Object.values(val).some(hasValue);
|
|
308
|
+
return true;
|
|
347
309
|
};
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
queryData.filters.$and.push(parsedFilter);
|
|
310
|
+
if (hasValue(parsed)) {
|
|
311
|
+
queryData.filters.$and.push(parsed);
|
|
351
312
|
fixedFilterParsed = true;
|
|
352
313
|
} else {
|
|
353
|
-
console.warn(ERROR_MESSAGES.SKIPPING_EMPTY_FIXED_FILTER,
|
|
314
|
+
console.warn(ERROR_MESSAGES.SKIPPING_EMPTY_FIXED_FILTER, parsed);
|
|
354
315
|
}
|
|
355
316
|
} catch (e) {
|
|
356
|
-
console.error(ERROR_MESSAGES.INVALID_JSON_WHERECLAUSE,
|
|
357
|
-
parsedFilter = {};
|
|
317
|
+
console.error(ERROR_MESSAGES.INVALID_JSON_WHERECLAUSE, rendered);
|
|
358
318
|
}
|
|
359
|
-
|
|
360
319
|
}
|
|
361
320
|
|
|
362
321
|
if (fixedFilterToBeApplied && !fixedFilterParsed) {
|
|
363
322
|
console.error(ERROR_MESSAGES.FIXED_FILTER_NOT_APPLIED);
|
|
364
|
-
|
|
365
323
|
} else {
|
|
366
|
-
|
|
367
|
-
encodeValuesOnly: true,
|
|
368
|
-
});
|
|
369
|
-
fetchRelationEntities(autocompleteQs);
|
|
324
|
+
fetchAllOptions(qs.stringify(queryData, { encodeValuesOnly: true }));
|
|
370
325
|
}
|
|
371
|
-
|
|
372
326
|
}, [fieldContext, formik.values]);
|
|
373
327
|
|
|
374
|
-
const handleCheckboxChange = (
|
|
375
|
-
|
|
376
|
-
|
|
328
|
+
const handleCheckboxChange = (item: any) => {
|
|
329
|
+
const isCurrentlyLinked = currentValues.some((s) => s.value === item.value);
|
|
330
|
+
if (isCurrentlyLinked) {
|
|
331
|
+
unlinkItem(item);
|
|
377
332
|
} else {
|
|
378
|
-
|
|
333
|
+
linkItem(item);
|
|
379
334
|
}
|
|
380
335
|
};
|
|
381
336
|
|
|
382
|
-
const headerTemplate = (options: any) =>
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
<
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
<>
|
|
397
|
-
<Button
|
|
398
|
-
icon="pi pi-plus"
|
|
399
|
-
rounded
|
|
400
|
-
outlined
|
|
401
|
-
aria-label="Filter"
|
|
402
|
-
type="button"
|
|
403
|
-
size="small"
|
|
404
|
-
onClick={() => setVisibleCreateDialog(true)}
|
|
405
|
-
className="custom-add-button"
|
|
406
|
-
/>
|
|
407
|
-
<InlineRelationEntityDialog
|
|
408
|
-
visible={visibleCreateDialog}
|
|
409
|
-
setVisible={setVisibleCreateDialog}
|
|
410
|
-
fieldContext={fieldContext}
|
|
411
|
-
onCreate={addNewRelation}
|
|
412
|
-
/>
|
|
413
|
-
</>
|
|
414
|
-
)}
|
|
415
|
-
{/* <div className="many-to-many-add" >
|
|
416
|
-
<Button icon="pi pi-plus"
|
|
337
|
+
const headerTemplate = (options: any) => (
|
|
338
|
+
<div className={`${options.className} justify-content-space-between`}>
|
|
339
|
+
<div className="flex align-items-center gap-3">
|
|
340
|
+
{showFieldLabel !== false && (
|
|
341
|
+
<label className="form-field-label">
|
|
342
|
+
{capitalize(fieldLayoutInfo.attrs.name)}
|
|
343
|
+
{fieldMetadata.required && <span className="text-red-500"> *</span>}
|
|
344
|
+
<SolidFieldTooltip fieldContext={fieldContext} />
|
|
345
|
+
</label>
|
|
346
|
+
)}
|
|
347
|
+
{fieldContext.field.attrs.inlineCreate && (
|
|
348
|
+
<>
|
|
349
|
+
<Button
|
|
350
|
+
icon="pi pi-plus"
|
|
417
351
|
rounded
|
|
418
352
|
outlined
|
|
419
353
|
aria-label="Filter"
|
|
420
354
|
type="button"
|
|
421
|
-
|
|
355
|
+
size="small"
|
|
356
|
+
onClick={() => setVisibleCreateDialog(true)}
|
|
357
|
+
className="custom-add-button"
|
|
422
358
|
/>
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
359
|
+
<InlineRelationEntityDialog
|
|
360
|
+
visible={visibleCreateDialog}
|
|
361
|
+
setVisible={setVisibleCreateDialog}
|
|
362
|
+
fieldContext={fieldContext}
|
|
363
|
+
onCreate={addNewRelation}
|
|
364
|
+
/>
|
|
365
|
+
</>
|
|
366
|
+
)}
|
|
428
367
|
</div>
|
|
429
|
-
|
|
430
|
-
|
|
368
|
+
<div>{options.togglerElement}</div>
|
|
369
|
+
</div>
|
|
370
|
+
);
|
|
371
|
+
|
|
431
372
|
return (
|
|
432
373
|
<div>
|
|
433
374
|
<Panel toggleable headerTemplate={headerTemplate}>
|
|
434
375
|
<div className="formgrid grid">
|
|
435
|
-
{
|
|
436
|
-
|
|
437
|
-
<
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
</
|
|
446
|
-
|
|
447
|
-
|
|
376
|
+
{allOptions.map((item: any, i: number) => (
|
|
377
|
+
<div key={item.value} className={`field col-6 flex gap-2 ${i >= 2 ? 'mt-3' : ''}`}>
|
|
378
|
+
<Checkbox
|
|
379
|
+
readOnly={readOnlyPermission}
|
|
380
|
+
inputId={item.label}
|
|
381
|
+
checked={currentValues.some((s) => s.value === item.value)}
|
|
382
|
+
onChange={() => handleCheckboxChange(item)}
|
|
383
|
+
/>
|
|
384
|
+
<label htmlFor={item.label} className="form-field-label m-0">
|
|
385
|
+
{item.label}
|
|
386
|
+
</label>
|
|
387
|
+
</div>
|
|
388
|
+
))}
|
|
448
389
|
</div>
|
|
449
390
|
</Panel>
|
|
450
391
|
</div>
|
|
451
|
-
)
|
|
392
|
+
);
|
|
393
|
+
};
|
|
452
394
|
|
|
453
|
-
|
|
395
|
+
|
|
396
|
+
|
|
397
|
+
const buildRelationCustomFilter = ({
|
|
398
|
+
fieldContext,
|
|
399
|
+
fieldLayoutInfo,
|
|
400
|
+
}: {
|
|
401
|
+
fieldContext: any;
|
|
402
|
+
fieldLayoutInfo?: any;
|
|
403
|
+
}) => {
|
|
404
|
+
if (!fieldContext) return { id: { $eq: -1 } };
|
|
405
|
+
|
|
406
|
+
const relationFieldName =
|
|
407
|
+
fieldContext.fieldMetadata?.relationCoModelFieldName ?? fieldContext.modelName;
|
|
408
|
+
const parentId = fieldContext.data?.id ?? -1;
|
|
409
|
+
const baseFilter = { [relationFieldName]: { id: { $eq: parentId } } };
|
|
410
|
+
const whereClause = fieldLayoutInfo?.attrs?.whereClause;
|
|
411
|
+
|
|
412
|
+
if (!whereClause) return { $and: [baseFilter] };
|
|
413
|
+
|
|
414
|
+
try {
|
|
415
|
+
return { $and: [baseFilter, JSON.parse(whereClause)] };
|
|
416
|
+
} catch (error) {
|
|
417
|
+
console.error("Failed to parse whereClause:", error);
|
|
418
|
+
return { $and: [baseFilter] };
|
|
419
|
+
}
|
|
420
|
+
};
|
|
421
|
+
|
|
422
|
+
export const DefaultRelationManyToManyListFormEditWidget = ({ formik, fieldContext }: SolidFormFieldWidgetProps) => {
|
|
423
|
+
const fieldMetadata = fieldContext.fieldMetadata;
|
|
424
|
+
const router = useRouter();
|
|
425
|
+
const fieldLayoutInfo = fieldContext.field;
|
|
426
|
+
const fieldLabel = fieldLayoutInfo.attrs.label ?? fieldMetadata.displayName;
|
|
427
|
+
const solidFormViewMetaData = fieldContext.solidFormViewMetaData;
|
|
428
|
+
const [visibleCreateRelationEntity, setvisibleCreateRelationEntity] = useState(false);
|
|
429
|
+
const [listViewParams, setListViewParams] = useState<any>();
|
|
430
|
+
const [formViewParams, setformViewParams] = useState<FormViewParams>();
|
|
431
|
+
const [refreshList, setRefreshList] = useState(false);
|
|
432
|
+
const showFieldLabel = fieldLayoutInfo?.attrs?.showLabel;
|
|
433
|
+
const readOnlyPermission = fieldContext.readOnly;
|
|
434
|
+
const pathname = usePathname();
|
|
435
|
+
const lastPathSegment = pathname.split('/').pop();
|
|
436
|
+
const userKeyField: any = Object.entries(
|
|
437
|
+
fieldContext.solidFormViewMetaData.data.solidFieldsMetadata
|
|
438
|
+
).find(([_, value]: any) => value.isUserKey)?.[0];
|
|
439
|
+
const [showSaveParentEntityConfirmationPopup, setShowSaveParentEntityConfirmationPopup] = useState(false);
|
|
440
|
+
|
|
441
|
+
|
|
442
|
+
|
|
443
|
+
const [visibleLinkDialog, setVisibleLinkDialog] = useState(false);
|
|
444
|
+
const [linkSearchResults, setLinkSearchResults] = useState<any[]>([]);
|
|
445
|
+
const [selectedLinkItem, setSelectedLinkItem] = useState<any>(null);
|
|
446
|
+
const [isLinking, setIsLinking] = useState(false);
|
|
447
|
+
|
|
448
|
+
const { fetchSuggestions, linkItem, unlinkItem, suggestions } = useRelationEntityHandler({ fieldContext });
|
|
449
|
+
|
|
450
|
+
const handleAddClickForEmbeddedView = () => {
|
|
451
|
+
if (lastPathSegment === "new") {
|
|
452
|
+
setShowSaveParentEntityConfirmationPopup(true);
|
|
453
|
+
} else {
|
|
454
|
+
setSelectedLinkItem(null);
|
|
455
|
+
setLinkSearchResults([]);
|
|
456
|
+
setVisibleLinkDialog(true);
|
|
457
|
+
}
|
|
458
|
+
};
|
|
459
|
+
|
|
460
|
+
const handleLinkSearch = async (event: AutoCompleteCompleteEvent) => {
|
|
461
|
+
const queryData: any = {
|
|
462
|
+
offset: 0,
|
|
463
|
+
limit: 1000,
|
|
464
|
+
filters: {
|
|
465
|
+
$and: [
|
|
466
|
+
{
|
|
467
|
+
[fieldMetadata?.relationModel?.userKeyField?.name]: {
|
|
468
|
+
[fieldLayoutInfo?.attrs?.autocompleteMatchMode || '$containsi']: event.query,
|
|
469
|
+
},
|
|
470
|
+
},
|
|
471
|
+
],
|
|
472
|
+
},
|
|
473
|
+
};
|
|
474
|
+
await fetchSuggestions(qs.stringify(queryData, { encodeValuesOnly: true }));
|
|
475
|
+
};
|
|
476
|
+
|
|
477
|
+
const handleLinkConfirm = async () => {
|
|
478
|
+
if (!selectedLinkItem) return;
|
|
479
|
+
setIsLinking(true);
|
|
480
|
+
try {
|
|
481
|
+
await linkItem(selectedLinkItem);
|
|
482
|
+
setVisibleLinkDialog(false);
|
|
483
|
+
setSelectedLinkItem(null);
|
|
484
|
+
setRefreshList((prev) => !prev);
|
|
485
|
+
} finally {
|
|
486
|
+
setIsLinking(false);
|
|
487
|
+
}
|
|
488
|
+
};
|
|
489
|
+
|
|
490
|
+
const handleDeleteClick = async (id: any) => {
|
|
491
|
+
await unlinkItem({ value: id, label: '' });
|
|
492
|
+
setRefreshList((prev) => !prev);
|
|
493
|
+
};
|
|
494
|
+
|
|
495
|
+
const handleEditClickForEmbeddedView = (id: any) => {
|
|
496
|
+
if (id === "new") {
|
|
497
|
+
setShowSaveParentEntityConfirmationPopup(true);
|
|
498
|
+
} else {
|
|
499
|
+
setformViewParams({
|
|
500
|
+
moduleName: fieldContext.fieldMetadata.relationModelModuleName,
|
|
501
|
+
id,
|
|
502
|
+
embeded: true,
|
|
503
|
+
isCustomCreate: false,
|
|
504
|
+
customLayout: fieldLayoutInfo?.attrs?.inlineCreateLayout,
|
|
505
|
+
modelName: camelCase(fieldContext.fieldMetadata.relationCoModelSingularName),
|
|
506
|
+
parentFieldName: fieldContext.fieldMetadata.relationCoModelFieldName,
|
|
507
|
+
parentData: userKeyField
|
|
508
|
+
? { [userKeyField]: { solidManyToOneLabel: fieldContext.data[userKeyField], solidManyToOneValue: fieldContext.data['id'] } }
|
|
509
|
+
: {},
|
|
510
|
+
onEmbeddedFormSave: fieldContext.onEmbeddedFormSave,
|
|
511
|
+
inlineCreateAutoSave: fieldLayoutInfo?.attrs?.inlineCreateAutoSave,
|
|
512
|
+
});
|
|
513
|
+
setvisibleCreateRelationEntity(true);
|
|
514
|
+
}
|
|
515
|
+
};
|
|
516
|
+
|
|
517
|
+
const handlePopupClose = () => {
|
|
518
|
+
setvisibleCreateRelationEntity(false);
|
|
519
|
+
const currentUrl = new URL(window.location.href);
|
|
520
|
+
currentUrl.searchParams.delete('childEntity');
|
|
521
|
+
router.push(currentUrl.toString());
|
|
522
|
+
setRefreshList((prev) => !prev);
|
|
523
|
+
setListViewParams({
|
|
524
|
+
moduleName: fieldContext.fieldMetadata.relationModelModuleName,
|
|
525
|
+
modelName: camelCase(fieldContext.fieldMetadata.relationCoModelSingularName),
|
|
526
|
+
inlineCreate: readOnlyPermission === false,
|
|
527
|
+
customLayout: fieldLayoutInfo?.attrs?.inlineListLayout,
|
|
528
|
+
embeded: true,
|
|
529
|
+
id: fieldContext.data?.id ?? 'new',
|
|
530
|
+
customFilter: buildRelationCustomFilter({ fieldContext, fieldLayoutInfo }),
|
|
531
|
+
});
|
|
532
|
+
};
|
|
533
|
+
|
|
534
|
+
useEffect(() => {
|
|
535
|
+
setListViewParams({
|
|
536
|
+
moduleName: fieldContext.fieldMetadata.relationModelModuleName,
|
|
537
|
+
modelName: camelCase(fieldContext.fieldMetadata.relationCoModelSingularName),
|
|
538
|
+
inlineCreate: readOnlyPermission === false,
|
|
539
|
+
customLayout: fieldLayoutInfo?.attrs?.inlineListLayout,
|
|
540
|
+
embeded: true,
|
|
541
|
+
id: fieldContext.data?.id ?? 'new',
|
|
542
|
+
customFilter: buildRelationCustomFilter({ fieldContext, fieldLayoutInfo }),
|
|
543
|
+
});
|
|
544
|
+
|
|
545
|
+
setformViewParams({
|
|
546
|
+
moduleName: fieldContext.fieldMetadata.relationModelModuleName,
|
|
547
|
+
modelName: camelCase(fieldContext.fieldMetadata.relationCoModelSingularName),
|
|
548
|
+
parentFieldName: fieldContext.fieldMetadata.relationCoModelFieldName,
|
|
549
|
+
id: "new",
|
|
550
|
+
embeded: true,
|
|
551
|
+
isCustomCreate: false,
|
|
552
|
+
customLayout: fieldLayoutInfo?.attrs?.inlineCreateLayout,
|
|
553
|
+
parentData: userKeyField
|
|
554
|
+
? { [userKeyField]: { solidManyToOneLabel: fieldContext.data[userKeyField], solidManyToOneValue: fieldContext.data['id'] } }
|
|
555
|
+
: {},
|
|
556
|
+
onEmbeddedFormSave: fieldContext.onEmbeddedFormSave,
|
|
557
|
+
inlineCreateAutoSave: fieldLayoutInfo?.attrs?.inlineCreateAutoSave,
|
|
558
|
+
});
|
|
559
|
+
}, [readOnlyPermission]);
|
|
560
|
+
|
|
561
|
+
const saveParentEntity = async () => {
|
|
562
|
+
const currentUrl = new URL(window.location.href);
|
|
563
|
+
currentUrl.searchParams.set('childEntity', fieldLayoutInfo.attrs.name);
|
|
564
|
+
currentUrl.searchParams.set('viewMode', 'edit');
|
|
565
|
+
try {
|
|
566
|
+
router.push(currentUrl.toString());
|
|
567
|
+
await formik.handleSubmit();
|
|
568
|
+
} catch { }
|
|
569
|
+
setShowSaveParentEntityConfirmationPopup(false);
|
|
570
|
+
};
|
|
571
|
+
|
|
572
|
+
return (
|
|
573
|
+
<div>
|
|
574
|
+
{showFieldLabel !== false && (
|
|
575
|
+
<label htmlFor={fieldLayoutInfo.attrs.name} className="form-field-label">
|
|
576
|
+
{fieldLabel}
|
|
577
|
+
{fieldMetadata.required && <span className="text-red-500"> *</span>}
|
|
578
|
+
<SolidFieldTooltip fieldContext={fieldContext} />
|
|
579
|
+
</label>
|
|
580
|
+
)}
|
|
581
|
+
{listViewParams && (
|
|
582
|
+
<SolidListView key={refreshList.toString()} {...listViewParams} embededFieldRelationType="many-to-many" handleAddClickForEmbeddedView={handleAddClickForEmbeddedView} handleEditClickForEmbeddedView={handleEditClickForEmbeddedView} handleDeleteClick={handleDeleteClick} />
|
|
583
|
+
)}
|
|
584
|
+
{readOnlyPermission !== true && formViewParams && (
|
|
585
|
+
<RenderSolidFormEmbededView
|
|
586
|
+
formik={formik}
|
|
587
|
+
fieldContext={fieldContext}
|
|
588
|
+
visibleCreateRelationEntity={visibleCreateRelationEntity}
|
|
589
|
+
setvisibleCreateRelationEntity={setvisibleCreateRelationEntity}
|
|
590
|
+
formViewParams={formViewParams}
|
|
591
|
+
handlePopupClose={handlePopupClose}
|
|
592
|
+
/>
|
|
593
|
+
)}
|
|
594
|
+
|
|
595
|
+
<Dialog
|
|
596
|
+
header={`Link existing ${fieldLabel}`}
|
|
597
|
+
visible={visibleLinkDialog}
|
|
598
|
+
style={{ width: '30vw', minWidth: 320 }}
|
|
599
|
+
onHide={() => setVisibleLinkDialog(false)}
|
|
600
|
+
footer={
|
|
601
|
+
<div className="flex gap-2 justify-content-end">
|
|
602
|
+
<Button
|
|
603
|
+
label="Link"
|
|
604
|
+
size="small"
|
|
605
|
+
disabled={!selectedLinkItem || isLinking}
|
|
606
|
+
loading={isLinking}
|
|
607
|
+
onClick={handleLinkConfirm}
|
|
608
|
+
/>
|
|
609
|
+
<Button
|
|
610
|
+
label="Cancel"
|
|
611
|
+
size="small"
|
|
612
|
+
outlined
|
|
613
|
+
className="bg-primary-reverse"
|
|
614
|
+
onClick={() => setVisibleLinkDialog(false)}
|
|
615
|
+
/>
|
|
616
|
+
</div>
|
|
617
|
+
}
|
|
618
|
+
>
|
|
619
|
+
<div className="flex flex-column gap-2 pt-2">
|
|
620
|
+
<label className="form-field-label">
|
|
621
|
+
Search {fieldLabel}
|
|
622
|
+
</label>
|
|
623
|
+
<AutoComplete
|
|
624
|
+
field="label"
|
|
625
|
+
value={selectedLinkItem}
|
|
626
|
+
suggestions={suggestions}
|
|
627
|
+
completeMethod={handleLinkSearch}
|
|
628
|
+
onChange={(e) => setSelectedLinkItem(e.value)}
|
|
629
|
+
onSelect={(e) => setSelectedLinkItem(e.value)}
|
|
630
|
+
placeholder={`Type to search...`}
|
|
631
|
+
className="w-full"
|
|
632
|
+
dropdown
|
|
633
|
+
/>
|
|
634
|
+
</div>
|
|
635
|
+
</Dialog>
|
|
636
|
+
|
|
637
|
+
|
|
638
|
+
<Dialog
|
|
639
|
+
showHeader={false}
|
|
640
|
+
headerClassName="py-2"
|
|
641
|
+
contentClassName="px-0 pb-0"
|
|
642
|
+
className="solid-confirm-dialog"
|
|
643
|
+
contentStyle={{ borderRadius: 6 }}
|
|
644
|
+
visible={showSaveParentEntityConfirmationPopup}
|
|
645
|
+
style={{ width: '20vw' }}
|
|
646
|
+
onHide={() => {
|
|
647
|
+
if (!showSaveParentEntityConfirmationPopup) return;
|
|
648
|
+
setShowSaveParentEntityConfirmationPopup(false);
|
|
649
|
+
}}
|
|
650
|
+
>
|
|
651
|
+
<div className="p-4">
|
|
652
|
+
<p className="m-0 solid-primary-title" style={{ fontSize: 16 }}>
|
|
653
|
+
Before Creating {fieldLabel} you need to save{' '}
|
|
654
|
+
{solidFormViewMetaData?.data?.solidView?.model?.displayName
|
|
655
|
+
? solidFormViewMetaData?.data?.solidView?.model?.displayName
|
|
656
|
+
: capitalize(fieldContext.modelName)}
|
|
657
|
+
. Please click save if you wish to proceed?
|
|
658
|
+
</p>
|
|
659
|
+
<div className="flex align-items-center justify-content-start gap-2 mt-3">
|
|
660
|
+
<Button label="Save" size="small" onClick={saveParentEntity} />
|
|
661
|
+
<Button
|
|
662
|
+
label="Cancel"
|
|
663
|
+
size="small"
|
|
664
|
+
onClick={() => setShowSaveParentEntityConfirmationPopup(false)}
|
|
665
|
+
outlined
|
|
666
|
+
className="bg-primary-reverse"
|
|
667
|
+
/>
|
|
668
|
+
</div>
|
|
669
|
+
</div>
|
|
670
|
+
</Dialog>
|
|
671
|
+
</div>
|
|
672
|
+
);
|
|
673
|
+
};
|