@solidxai/core-ui 0.1.4-beta.0 → 0.1.4-beta.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/components/core/common/SolidAccountSettings/SolidAccountSettings.d.ts.map +1 -1
- package/dist/components/core/common/SolidAccountSettings/SolidAccountSettings.js +8 -0
- package/dist/components/core/common/SolidAccountSettings/SolidAccountSettings.js.map +1 -1
- package/dist/components/core/common/SolidAccountSettings/SolidAccountSettings.tsx +8 -0
- package/dist/components/core/common/SolidAccountSettings/SolidVersionInfo.d.ts +2 -0
- package/dist/components/core/common/SolidAccountSettings/SolidVersionInfo.d.ts.map +1 -0
- package/dist/components/core/common/SolidAccountSettings/SolidVersionInfo.js +34 -0
- package/dist/components/core/common/SolidAccountSettings/SolidVersionInfo.js.map +1 -0
- package/dist/components/core/common/SolidAccountSettings/SolidVersionInfo.tsx +83 -0
- package/dist/components/core/common/SolidGlobalSearchElement.d.ts.map +1 -1
- package/dist/components/core/common/SolidGlobalSearchElement.js +6 -8
- package/dist/components/core/common/SolidGlobalSearchElement.js.map +1 -1
- package/dist/components/core/common/SolidGlobalSearchElement.tsx +21 -21
- package/dist/components/core/dashboard/SolidDashboard.d.ts +1 -1
- package/dist/components/core/dashboard/SolidDashboard.d.ts.map +1 -1
- package/dist/components/core/dashboard/SolidDashboard.js.map +1 -1
- package/dist/components/core/dashboard/SolidDashboard.tsx +1 -1
- package/dist/components/core/dashboard/SolidDashboardVariable.js +1 -1
- package/dist/components/core/dashboard/SolidDashboardVariable.js.map +1 -1
- package/dist/components/core/dashboard/SolidDashboardVariable.tsx +1 -1
- package/dist/components/core/extension/solid-core/roleMetadata/RolePermissionsManyToManyFieldWidget.d.ts.map +1 -1
- package/dist/components/core/extension/solid-core/roleMetadata/RolePermissionsManyToManyFieldWidget.js +15 -30
- package/dist/components/core/extension/solid-core/roleMetadata/RolePermissionsManyToManyFieldWidget.js.map +1 -1
- package/dist/components/core/extension/solid-core/roleMetadata/RolePermissionsManyToManyFieldWidget.tsx +46 -36
- 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 +315 -160
- package/dist/components/core/form/fields/relations/SolidRelationManyToManyField.js.map +1 -1
- package/dist/components/core/form/fields/relations/SolidRelationManyToManyField.tsx +459 -249
- 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 -5
- 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 +203 -67
- 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 +147 -67
- package/dist/components/core/kanban/SolidKanbanView.d.ts.map +1 -1
- package/dist/components/core/kanban/SolidKanbanView.js +8 -7
- package/dist/components/core/kanban/SolidKanbanView.js.map +1 -1
- package/dist/components/core/kanban/SolidKanbanView.tsx +3 -2
- package/dist/components/core/list/SolidListView.d.ts +8 -5
- package/dist/components/core/list/SolidListView.d.ts.map +1 -1
- package/dist/components/core/list/SolidListView.js +95 -84
- package/dist/components/core/list/SolidListView.js.map +1 -1
- package/dist/components/core/list/SolidListView.tsx +55 -62
- 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/SolidBooleanColumn.d.ts.map +1 -1
- package/dist/components/core/list/columns/SolidBooleanColumn.js +1 -24
- package/dist/components/core/list/columns/SolidBooleanColumn.js.map +1 -1
- package/dist/components/core/list/columns/SolidBooleanColumn.tsx +1 -35
- package/dist/components/core/list/columns/SolidDateColumn.d.ts +0 -5
- package/dist/components/core/list/columns/SolidDateColumn.d.ts.map +1 -1
- package/dist/components/core/list/columns/SolidDateColumn.js +1 -31
- package/dist/components/core/list/columns/SolidDateColumn.js.map +1 -1
- package/dist/components/core/list/columns/SolidDateColumn.tsx +2 -49
- package/dist/components/core/list/columns/SolidDatetimeColumn.d.ts.map +1 -1
- package/dist/components/core/list/columns/SolidDatetimeColumn.js +1 -20
- package/dist/components/core/list/columns/SolidDatetimeColumn.js.map +1 -1
- package/dist/components/core/list/columns/SolidDatetimeColumn.tsx +2 -37
- package/dist/components/core/list/columns/SolidExternalIdColumn.d.ts.map +1 -1
- package/dist/components/core/list/columns/SolidExternalIdColumn.js +1 -21
- package/dist/components/core/list/columns/SolidExternalIdColumn.js.map +1 -1
- package/dist/components/core/list/columns/SolidExternalIdColumn.tsx +1 -38
- package/dist/components/core/list/columns/SolidIdColumn.d.ts.map +1 -1
- package/dist/components/core/list/columns/SolidIdColumn.js +1 -21
- package/dist/components/core/list/columns/SolidIdColumn.js.map +1 -1
- package/dist/components/core/list/columns/SolidIdColumn.tsx +1 -36
- package/dist/components/core/list/columns/SolidIntColumn.d.ts.map +1 -1
- package/dist/components/core/list/columns/SolidIntColumn.js +1 -30
- package/dist/components/core/list/columns/SolidIntColumn.js.map +1 -1
- package/dist/components/core/list/columns/SolidIntColumn.tsx +2 -46
- package/dist/components/core/list/columns/SolidMediaMultipleColumn.d.ts.map +1 -1
- package/dist/components/core/list/columns/SolidMediaMultipleColumn.js +1 -5
- package/dist/components/core/list/columns/SolidMediaMultipleColumn.js.map +1 -1
- package/dist/components/core/list/columns/SolidMediaMultipleColumn.tsx +0 -7
- package/dist/components/core/list/columns/SolidMediaSingleColumn.d.ts.map +1 -1
- package/dist/components/core/list/columns/SolidMediaSingleColumn.js +1 -1
- package/dist/components/core/list/columns/SolidMediaSingleColumn.js.map +1 -1
- package/dist/components/core/list/columns/SolidMediaSingleColumn.tsx +0 -1
- package/dist/components/core/list/columns/SolidSelectionDynamicColumn.d.ts.map +1 -1
- package/dist/components/core/list/columns/SolidSelectionDynamicColumn.js +1 -21
- package/dist/components/core/list/columns/SolidSelectionDynamicColumn.js.map +1 -1
- package/dist/components/core/list/columns/SolidSelectionDynamicColumn.tsx +1 -37
- package/dist/components/core/list/columns/SolidSelectionStaticColumn.d.ts.map +1 -1
- package/dist/components/core/list/columns/SolidSelectionStaticColumn.js +1 -21
- package/dist/components/core/list/columns/SolidSelectionStaticColumn.js.map +1 -1
- package/dist/components/core/list/columns/SolidSelectionStaticColumn.tsx +1 -38
- package/dist/components/core/list/columns/SolidShortTextColumn.d.ts.map +1 -1
- package/dist/components/core/list/columns/SolidShortTextColumn.js +2 -66
- package/dist/components/core/list/columns/SolidShortTextColumn.js.map +1 -1
- package/dist/components/core/list/columns/SolidShortTextColumn.tsx +3 -86
- package/dist/components/core/list/columns/SolidTimeColumn.d.ts.map +1 -1
- package/dist/components/core/list/columns/SolidTimeColumn.js +1 -20
- package/dist/components/core/list/columns/SolidTimeColumn.js.map +1 -1
- package/dist/components/core/list/columns/SolidTimeColumn.tsx +2 -37
- package/dist/components/core/list/columns/SolidUuidColumn.d.ts.map +1 -1
- package/dist/components/core/list/columns/SolidUuidColumn.js +1 -21
- package/dist/components/core/list/columns/SolidUuidColumn.js.map +1 -1
- package/dist/components/core/list/columns/SolidUuidColumn.tsx +1 -37
- package/dist/components/core/list/columns/relations/SolidRelationManyToManyColumn.d.ts.map +1 -1
- package/dist/components/core/list/columns/relations/SolidRelationManyToManyColumn.js +1 -17
- package/dist/components/core/list/columns/relations/SolidRelationManyToManyColumn.js.map +1 -1
- package/dist/components/core/list/columns/relations/SolidRelationManyToManyColumn.tsx +2 -35
- package/dist/components/core/list/columns/relations/SolidRelationManyToOneColumn.d.ts.map +1 -1
- package/dist/components/core/list/columns/relations/SolidRelationManyToOneColumn.js +10 -20
- package/dist/components/core/list/columns/relations/SolidRelationManyToOneColumn.js.map +1 -1
- package/dist/components/core/list/columns/relations/SolidRelationManyToOneColumn.tsx +15 -36
- package/dist/components/core/list/columns/relations/SolidRelationOneToManyColumn.d.ts.map +1 -1
- package/dist/components/core/list/columns/relations/SolidRelationOneToManyColumn.js +1 -15
- package/dist/components/core/list/columns/relations/SolidRelationOneToManyColumn.js.map +1 -1
- package/dist/components/core/list/columns/relations/SolidRelationOneToManyColumn.tsx +1 -31
- package/dist/components/core/tree/SolidTreeView.d.ts.map +1 -1
- package/dist/components/core/tree/SolidTreeView.js +23 -14
- package/dist/components/core/tree/SolidTreeView.js.map +1 -1
- package/dist/components/core/tree/SolidTreeView.tsx +50 -16
- package/dist/helpers/registry.js +3 -1
- package/dist/helpers/registry.js.map +1 -1
- package/dist/helpers/registry.ts +4 -1
- package/dist/index.d.ts +3 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -2
- package/dist/index.js.map +1 -1
- package/dist/index.ts +5 -2
- package/dist/redux/api/fetchBaseQuery.js +4 -5
- package/dist/redux/api/fetchBaseQuery.js.map +1 -1
- package/dist/redux/api/fetchBaseQuery.tsx +4 -4
- package/dist/redux/api/solidSettingsApi.d.ts +2 -1
- package/dist/redux/api/solidSettingsApi.d.ts.map +1 -1
- package/dist/redux/api/solidSettingsApi.js +4 -1
- package/dist/redux/api/solidSettingsApi.js.map +1 -1
- package/dist/redux/api/solidSettingsApi.tsx +6 -1
- package/dist/redux/store/defaultStoreConfig.d.ts +1 -0
- package/dist/redux/store/defaultStoreConfig.d.ts.map +1 -1
- package/dist/resources/globals.css +14 -0
- package/dist/routes/pages/admin/core/DashboardPage.d.ts +2 -0
- package/dist/routes/pages/admin/core/DashboardPage.d.ts.map +1 -0
- package/dist/routes/pages/admin/core/DashboardPage.js +14 -0
- package/dist/routes/pages/admin/core/DashboardPage.js.map +1 -0
- package/dist/routes/pages/admin/core/DashboardPage.tsx +17 -0
- package/dist/routes/pages/admin/core/ListPage.js +1 -1
- package/dist/routes/pages/admin/core/ListPage.js.map +1 -1
- package/dist/routes/pages/admin/core/ListPage.tsx +1 -1
- 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/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 +2 -0
- 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/solid-core.d.ts +1 -1
- 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,80 +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, populateFormikWithRelatedEntities, 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 });
|
|
170
133
|
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
}, [formik.values?.id]);
|
|
134
|
+
const isFormFieldValid = (formik: any, fieldName: string) =>
|
|
135
|
+
formik.touched[fieldName] && formik.errors[fieldName];
|
|
174
136
|
|
|
137
|
+
// On mount: load already-linked items into currentValues
|
|
138
|
+
useEffect(() => {
|
|
139
|
+
fetchCurrentValues();
|
|
140
|
+
}, [fieldContext.data?.id]);
|
|
175
141
|
|
|
176
142
|
const autoCompleteSearch = async (event: AutoCompleteCompleteEvent) => {
|
|
177
143
|
const queryData: any = {
|
|
@@ -181,93 +147,72 @@ export const DefaultRelationManyToManyAutoCompleteFormEditWidget = ({ formik, fi
|
|
|
181
147
|
$and: [
|
|
182
148
|
{
|
|
183
149
|
[fieldMetadata?.relationModel?.userKeyField?.name]: {
|
|
184
|
-
[fieldLayoutInfo?.attrs?.autocompleteMatchMode || '$containsi']: event.query
|
|
185
|
-
}
|
|
186
|
-
}
|
|
187
|
-
]
|
|
188
|
-
}
|
|
150
|
+
[fieldLayoutInfo?.attrs?.autocompleteMatchMode || '$containsi']: event.query,
|
|
151
|
+
},
|
|
152
|
+
},
|
|
153
|
+
],
|
|
154
|
+
},
|
|
189
155
|
};
|
|
156
|
+
|
|
190
157
|
let fixedFilterToBeApplied = false;
|
|
191
158
|
let fixedFilterParsed = false;
|
|
192
159
|
|
|
193
160
|
if (fieldMetadata?.relationFieldFixedFilter || fieldLayoutInfo?.attrs?.whereClause) {
|
|
194
|
-
const
|
|
161
|
+
const rawFilter = fieldLayoutInfo?.attrs?.whereClause ?? fieldMetadata?.relationFieldFixedFilter;
|
|
195
162
|
fixedFilterToBeApplied = true;
|
|
196
|
-
const
|
|
197
|
-
const renderedFilter = fixedFilterTemplate(formik.values);
|
|
163
|
+
const rendered = Handlebars.compile(rawFilter)(formik.values);
|
|
198
164
|
|
|
199
|
-
let parsedFilter: any;
|
|
200
165
|
try {
|
|
201
|
-
|
|
202
|
-
const
|
|
203
|
-
if (
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
if (val === null || val === undefined || val === '') return false;
|
|
207
|
-
if (typeof val === 'object') {
|
|
208
|
-
return Object.values(val).some(hasValidValue);
|
|
209
|
-
}
|
|
210
|
-
return true;
|
|
211
|
-
};
|
|
212
|
-
|
|
213
|
-
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;
|
|
214
171
|
};
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
queryData.filters.$and.push(parsedFilter);
|
|
172
|
+
if (hasValue(parsed)) {
|
|
173
|
+
queryData.filters.$and.push(parsed);
|
|
218
174
|
fixedFilterParsed = true;
|
|
219
175
|
} else {
|
|
220
|
-
console.warn(ERROR_MESSAGES.SKIPPING_EMPTY_FIXED_FILTER,
|
|
176
|
+
console.warn(ERROR_MESSAGES.SKIPPING_EMPTY_FIXED_FILTER, parsed);
|
|
221
177
|
}
|
|
222
178
|
} catch (e) {
|
|
223
|
-
console.error(ERROR_MESSAGES.INVALID_JSON_WHERECLAUSE,
|
|
224
|
-
parsedFilter = {};
|
|
179
|
+
console.error(ERROR_MESSAGES.INVALID_JSON_WHERECLAUSE, rendered);
|
|
225
180
|
}
|
|
226
|
-
|
|
227
181
|
}
|
|
228
182
|
|
|
229
|
-
let autocompleteQs = qs.stringify(queryData, {
|
|
230
|
-
encodeValuesOnly: true,
|
|
231
|
-
});
|
|
232
|
-
// if (whereClause) {
|
|
233
|
-
// autocompleteQs = `${autocompleteQs}&${whereClause}`;
|
|
234
|
-
// }
|
|
235
|
-
|
|
236
183
|
if (fixedFilterToBeApplied && !fixedFilterParsed) {
|
|
237
184
|
console.error(ERROR_MESSAGES.FIXED_FILTER_NOT_APPLIED);
|
|
238
|
-
|
|
239
185
|
} else {
|
|
240
|
-
|
|
241
|
-
// encodeValuesOnly: true,
|
|
242
|
-
// });
|
|
243
|
-
fetchRelationEntities(autocompleteQs);
|
|
186
|
+
fetchSuggestions(qs.stringify(queryData, { encodeValuesOnly: true }));
|
|
244
187
|
}
|
|
245
188
|
};
|
|
246
189
|
|
|
247
190
|
return (
|
|
248
|
-
|
|
249
191
|
<div className="relative">
|
|
250
192
|
<div className="flex flex-column gap-2 mt-1 sm:mt-2 md:mt-3 lg:mt-4">
|
|
251
|
-
{showFieldLabel
|
|
193
|
+
{showFieldLabel !== false && (
|
|
252
194
|
<label htmlFor={fieldLayoutInfo.attrs.name} className="form-field-label">
|
|
253
195
|
{fieldLabel}
|
|
254
196
|
{fieldMetadata.required && <span className="text-red-500"> *</span>}
|
|
255
197
|
<SolidFieldTooltip fieldContext={fieldContext} />
|
|
256
198
|
</label>
|
|
257
|
-
}
|
|
199
|
+
)}
|
|
258
200
|
<div className="flex align-items-center gap-3">
|
|
259
201
|
<AutoComplete
|
|
260
202
|
readOnly={readOnly || readOnlyPermission}
|
|
261
203
|
disabled={disabled || readOnlyPermission}
|
|
262
204
|
multiple
|
|
263
|
-
{...formik.getFieldProps(fieldLayoutInfo.attrs.name)}
|
|
264
205
|
id={fieldLayoutInfo.attrs.name}
|
|
265
206
|
field="label"
|
|
266
|
-
value={
|
|
207
|
+
value={currentValues}
|
|
267
208
|
dropdown={!readOnlyPermission}
|
|
268
|
-
suggestions={
|
|
209
|
+
suggestions={suggestions}
|
|
269
210
|
completeMethod={autoCompleteSearch}
|
|
270
|
-
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)}
|
|
271
216
|
className="solid-standard-autocomplete w-full"
|
|
272
217
|
/>
|
|
273
218
|
{fieldContext.field.attrs.inlineCreate && (
|
|
@@ -301,163 +246,428 @@ export const DefaultRelationManyToManyAutoCompleteFormEditWidget = ({ formik, fi
|
|
|
301
246
|
)}
|
|
302
247
|
</div>
|
|
303
248
|
);
|
|
304
|
-
}
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
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
|
+
*/
|
|
308
265
|
export const DefaultRelationManyToManyCheckBoxFormEditWidget = ({ formik, fieldContext }: SolidFormFieldWidgetProps) => {
|
|
309
266
|
const fieldMetadata = fieldContext.fieldMetadata;
|
|
310
267
|
const fieldLayoutInfo = fieldContext.field;
|
|
311
268
|
const showFieldLabel = fieldLayoutInfo?.attrs?.showLabel;
|
|
312
|
-
|
|
313
269
|
const readOnlyPermission = fieldContext.readOnly;
|
|
270
|
+
|
|
314
271
|
const [visibleCreateDialog, setVisibleCreateDialog] = useState(false);
|
|
315
|
-
const { autoCompleteItems, fetchRelationEntities, populateFormikWithRelatedEntities, addNewRelation } = useRelationEntityHandler({ fieldContext, formik });
|
|
316
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
|
|
317
284
|
useEffect(() => {
|
|
318
|
-
|
|
319
|
-
}, [
|
|
320
|
-
|
|
285
|
+
fetchCurrentValues();
|
|
286
|
+
}, [fieldContext.data?.id]);
|
|
321
287
|
|
|
322
288
|
useEffect(() => {
|
|
323
|
-
const fieldMetadata = fieldContext.fieldMetadata;
|
|
324
|
-
const fieldLayoutInfo = fieldContext.field;
|
|
325
289
|
const queryData: any = {
|
|
326
290
|
offset: 0,
|
|
327
291
|
limit: 1000,
|
|
328
|
-
filters: {
|
|
329
|
-
$and: []
|
|
330
|
-
}
|
|
292
|
+
filters: { $and: [] },
|
|
331
293
|
};
|
|
332
294
|
|
|
333
295
|
let fixedFilterToBeApplied = false;
|
|
334
296
|
let fixedFilterParsed = false;
|
|
335
297
|
|
|
336
298
|
if (fieldMetadata?.relationFieldFixedFilter || fieldLayoutInfo?.attrs?.whereClause) {
|
|
337
|
-
const
|
|
299
|
+
const rawFilter = fieldLayoutInfo?.attrs?.whereClause ?? fieldMetadata?.relationFieldFixedFilter;
|
|
338
300
|
fixedFilterToBeApplied = true;
|
|
339
|
-
const
|
|
340
|
-
const renderedFilter = fixedFilterTemplate(formik.values);
|
|
301
|
+
const rendered = Handlebars.compile(rawFilter)(formik.values);
|
|
341
302
|
|
|
342
|
-
let parsedFilter: any;
|
|
343
303
|
try {
|
|
344
|
-
|
|
345
|
-
const
|
|
346
|
-
if (
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
if (val === null || val === undefined || val === '') return false;
|
|
350
|
-
if (typeof val === 'object') {
|
|
351
|
-
return Object.values(val).some(hasValidValue);
|
|
352
|
-
}
|
|
353
|
-
return true;
|
|
354
|
-
};
|
|
355
|
-
|
|
356
|
-
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;
|
|
357
309
|
};
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
queryData.filters.$and.push(parsedFilter);
|
|
310
|
+
if (hasValue(parsed)) {
|
|
311
|
+
queryData.filters.$and.push(parsed);
|
|
361
312
|
fixedFilterParsed = true;
|
|
362
313
|
} else {
|
|
363
|
-
console.warn(ERROR_MESSAGES.SKIPPING_EMPTY_FIXED_FILTER,
|
|
314
|
+
console.warn(ERROR_MESSAGES.SKIPPING_EMPTY_FIXED_FILTER, parsed);
|
|
364
315
|
}
|
|
365
316
|
} catch (e) {
|
|
366
|
-
console.error(ERROR_MESSAGES.INVALID_JSON_WHERECLAUSE,
|
|
367
|
-
parsedFilter = {};
|
|
317
|
+
console.error(ERROR_MESSAGES.INVALID_JSON_WHERECLAUSE, rendered);
|
|
368
318
|
}
|
|
369
|
-
|
|
370
319
|
}
|
|
371
320
|
|
|
372
321
|
if (fixedFilterToBeApplied && !fixedFilterParsed) {
|
|
373
322
|
console.error(ERROR_MESSAGES.FIXED_FILTER_NOT_APPLIED);
|
|
374
|
-
|
|
375
323
|
} else {
|
|
376
|
-
|
|
377
|
-
encodeValuesOnly: true,
|
|
378
|
-
});
|
|
379
|
-
fetchRelationEntities(autocompleteQs);
|
|
324
|
+
fetchAllOptions(qs.stringify(queryData, { encodeValuesOnly: true }));
|
|
380
325
|
}
|
|
381
|
-
|
|
382
326
|
}, [fieldContext, formik.values]);
|
|
383
327
|
|
|
384
|
-
const handleCheckboxChange = (
|
|
385
|
-
|
|
386
|
-
|
|
328
|
+
const handleCheckboxChange = (item: any) => {
|
|
329
|
+
const isCurrentlyLinked = currentValues.some((s) => s.value === item.value);
|
|
330
|
+
if (isCurrentlyLinked) {
|
|
331
|
+
unlinkItem(item);
|
|
387
332
|
} else {
|
|
388
|
-
|
|
333
|
+
linkItem(item);
|
|
389
334
|
}
|
|
390
335
|
};
|
|
391
336
|
|
|
392
|
-
const headerTemplate = (options: any) =>
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
<
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
<>
|
|
407
|
-
<Button
|
|
408
|
-
icon="pi pi-plus"
|
|
409
|
-
rounded
|
|
410
|
-
outlined
|
|
411
|
-
aria-label="Filter"
|
|
412
|
-
type="button"
|
|
413
|
-
size="small"
|
|
414
|
-
onClick={() => setVisibleCreateDialog(true)}
|
|
415
|
-
className="custom-add-button"
|
|
416
|
-
/>
|
|
417
|
-
<InlineRelationEntityDialog
|
|
418
|
-
visible={visibleCreateDialog}
|
|
419
|
-
setVisible={setVisibleCreateDialog}
|
|
420
|
-
fieldContext={fieldContext}
|
|
421
|
-
onCreate={addNewRelation}
|
|
422
|
-
/>
|
|
423
|
-
</>
|
|
424
|
-
)}
|
|
425
|
-
{/* <div className="many-to-many-add" >
|
|
426
|
-
<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"
|
|
427
351
|
rounded
|
|
428
352
|
outlined
|
|
429
353
|
aria-label="Filter"
|
|
430
354
|
type="button"
|
|
431
|
-
|
|
355
|
+
size="small"
|
|
356
|
+
onClick={() => setVisibleCreateDialog(true)}
|
|
357
|
+
className="custom-add-button"
|
|
432
358
|
/>
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
359
|
+
<InlineRelationEntityDialog
|
|
360
|
+
visible={visibleCreateDialog}
|
|
361
|
+
setVisible={setVisibleCreateDialog}
|
|
362
|
+
fieldContext={fieldContext}
|
|
363
|
+
onCreate={addNewRelation}
|
|
364
|
+
/>
|
|
365
|
+
</>
|
|
366
|
+
)}
|
|
438
367
|
</div>
|
|
439
|
-
|
|
440
|
-
|
|
368
|
+
<div>{options.togglerElement}</div>
|
|
369
|
+
</div>
|
|
370
|
+
);
|
|
371
|
+
|
|
441
372
|
return (
|
|
442
373
|
<div>
|
|
443
374
|
<Panel toggleable headerTemplate={headerTemplate}>
|
|
444
375
|
<div className="formgrid grid">
|
|
445
|
-
{
|
|
446
|
-
|
|
447
|
-
<
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
</
|
|
456
|
-
|
|
457
|
-
|
|
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
|
+
))}
|
|
458
389
|
</div>
|
|
459
390
|
</Panel>
|
|
460
391
|
</div>
|
|
461
|
-
)
|
|
392
|
+
);
|
|
393
|
+
};
|
|
462
394
|
|
|
463
|
-
|
|
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
|
+
};
|