@solidstarters/solid-core-ui 1.1.55 → 1.1.56
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/common/SolidFormStepper.d.ts.map +1 -1
- package/dist/components/common/SolidFormStepper.js +0 -4
- package/dist/components/common/SolidFormStepper.js.map +1 -1
- package/dist/components/core/form/SolidFormUserViewLayout.d.ts +2 -0
- package/dist/components/core/form/SolidFormUserViewLayout.d.ts.map +1 -0
- package/dist/components/core/form/SolidFormUserViewLayout.js +112 -0
- package/dist/components/core/form/SolidFormUserViewLayout.js.map +1 -0
- package/dist/components/core/form/SolidFormView.d.ts.map +1 -1
- package/dist/components/core/form/SolidFormView.js +29 -22
- package/dist/components/core/form/SolidFormView.js.map +1 -1
- package/dist/components/core/form/fields/SolidMediaMultipleField.d.ts.map +1 -1
- package/dist/components/core/form/fields/SolidMediaMultipleField.js +1 -1
- package/dist/components/core/form/fields/SolidMediaMultipleField.js.map +1 -1
- package/dist/components/core/form/fields/SolidMediaSingleField.d.ts.map +1 -1
- package/dist/components/core/form/fields/SolidMediaSingleField.js +1 -1
- package/dist/components/core/form/fields/SolidMediaSingleField.js.map +1 -1
- package/dist/components/core/form/fields/SolidSelectionDynamicField.d.ts.map +1 -1
- package/dist/components/core/form/fields/SolidSelectionDynamicField.js +12 -1
- package/dist/components/core/form/fields/SolidSelectionDynamicField.js.map +1 -1
- package/dist/components/core/form/fields/relations/SolidRelationManyToOneField.d.ts.map +1 -1
- package/dist/components/core/form/fields/relations/SolidRelationManyToOneField.js +4 -0
- package/dist/components/core/form/fields/relations/SolidRelationManyToOneField.js.map +1 -1
- package/dist/components/core/form/fields/relations/SolidRelationOneToManyField.d.ts.map +1 -1
- package/dist/components/core/form/fields/relations/SolidRelationOneToManyField.js +9 -7
- package/dist/components/core/form/fields/relations/SolidRelationOneToManyField.js.map +1 -1
- package/dist/components/core/kanban/KanbanUserViewLayout.d.ts +2 -0
- package/dist/components/core/kanban/KanbanUserViewLayout.d.ts.map +1 -0
- package/dist/components/core/kanban/KanbanUserViewLayout.js +112 -0
- package/dist/components/core/kanban/KanbanUserViewLayout.js.map +1 -0
- package/dist/components/core/kanban/SolidKanbanView.d.ts.map +1 -1
- package/dist/components/core/kanban/SolidKanbanView.js +41 -35
- package/dist/components/core/kanban/SolidKanbanView.js.map +1 -1
- package/dist/components/core/kanban/SolidKanbanViewConfigure.d.ts +1 -1
- package/dist/components/core/kanban/SolidKanbanViewConfigure.d.ts.map +1 -1
- package/dist/components/core/kanban/SolidKanbanViewConfigure.js +2 -2
- package/dist/components/core/kanban/SolidKanbanViewConfigure.js.map +1 -1
- package/dist/components/core/list/SolidListColumnSelector.d.ts +2 -0
- package/dist/components/core/list/SolidListColumnSelector.d.ts.map +1 -0
- package/dist/components/core/list/SolidListColumnSelector.js +182 -0
- package/dist/components/core/list/SolidListColumnSelector.js.map +1 -0
- package/dist/components/core/list/SolidListView.d.ts.map +1 -1
- package/dist/components/core/list/SolidListView.js +48 -45
- package/dist/components/core/list/SolidListView.js.map +1 -1
- package/dist/components/core/list/SolidListViewConfigure.d.ts +1 -1
- package/dist/components/core/list/SolidListViewConfigure.d.ts.map +1 -1
- package/dist/components/core/list/SolidListViewConfigure.js +7 -49
- package/dist/components/core/list/SolidListViewConfigure.js.map +1 -1
- package/dist/redux/api/solidEntityApi.d.ts +1 -0
- package/dist/redux/api/solidEntityApi.d.ts.map +1 -1
- package/dist/redux/api/solidEntityApi.js +7 -0
- package/dist/redux/api/solidEntityApi.js.map +1 -1
- package/dist/resources/globals.css +1 -0
- package/package.json +1 -1
- package/src/components/common/SolidFormStepper.tsx +0 -4
- package/src/components/core/form/SolidFormUserViewLayout.tsx +87 -0
- package/src/components/core/form/SolidFormView.tsx +30 -5
- package/src/components/core/form/fields/SolidMediaMultipleField.tsx +16 -14
- package/src/components/core/form/fields/SolidMediaSingleField.tsx +16 -14
- package/src/components/core/form/fields/SolidSelectionDynamicField.tsx +12 -4
- package/src/components/core/form/fields/relations/SolidRelationManyToOneField.tsx +5 -2
- package/src/components/core/form/fields/relations/SolidRelationOneToManyField.tsx +4 -2
- package/src/components/core/kanban/KanbanUserViewLayout.tsx +87 -0
- package/src/components/core/kanban/SolidKanbanView.tsx +18 -3
- package/src/components/core/kanban/SolidKanbanViewConfigure.tsx +3 -3
- package/src/components/core/list/SolidListColumnSelector.tsx +170 -0
- package/src/components/core/list/SolidListView.tsx +16 -12
- package/src/components/core/list/SolidListViewConfigure.tsx +2 -77
- package/src/redux/api/solidEntityApi.tsx +7 -0
- package/src/resources/globals.css +1 -0
|
@@ -240,21 +240,23 @@ export class SolidMediaMultipleField implements ISolidField {
|
|
|
240
240
|
{/* {fieldDescription && <span className="form_field_help">({fieldDescription}) </span>} */}
|
|
241
241
|
</label>
|
|
242
242
|
}
|
|
243
|
-
<div
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
{isFormFieldValid(formik, fieldLayoutInfo.attrs.name) && (
|
|
254
|
-
<div className="absolute mt-1">
|
|
255
|
-
<Message severity="error" text={formik?.errors[fieldLayoutInfo.attrs.name]?.toString()} />
|
|
243
|
+
<div className="relative">
|
|
244
|
+
<div
|
|
245
|
+
{...getRootProps()}
|
|
246
|
+
className="solid-dropzone-wrapper"
|
|
247
|
+
>
|
|
248
|
+
<input {...getInputProps()} />
|
|
249
|
+
<DropzonePlaceholder
|
|
250
|
+
mediaTypes={fieldMetadata.mediaTypes}
|
|
251
|
+
mediaMaxSizeKb={fieldMetadata.mediaMaxSizeKb}
|
|
252
|
+
/>
|
|
256
253
|
</div>
|
|
257
|
-
|
|
254
|
+
{isFormFieldValid(formik, fieldLayoutInfo.attrs.name) && (
|
|
255
|
+
<div className="absolute mt-1">
|
|
256
|
+
<Message severity="error" text={formik?.errors[fieldLayoutInfo.attrs.name]?.toString()} />
|
|
257
|
+
</div>
|
|
258
|
+
)}
|
|
259
|
+
</div>
|
|
258
260
|
{
|
|
259
261
|
fileSizeError &&
|
|
260
262
|
<Message severity="error" text={fileSizeError?.toString()} />
|
|
@@ -235,21 +235,23 @@ export class SolidMediaSingleField implements ISolidField {
|
|
|
235
235
|
{/* {fieldDescription && <span className="form_field_help">({fieldDescription}) </span>} */}
|
|
236
236
|
</label>
|
|
237
237
|
}
|
|
238
|
-
<div
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
{isFormFieldValid(formik, fieldLayoutInfo.attrs.name) && (
|
|
249
|
-
<div className="absolute mt-1">
|
|
250
|
-
<Message severity="error" text={formik?.errors[fieldLayoutInfo.attrs.name]?.toString()} />
|
|
238
|
+
<div className="relative">
|
|
239
|
+
<div
|
|
240
|
+
{...getRootProps()}
|
|
241
|
+
className="solid-dropzone-wrapper"
|
|
242
|
+
>
|
|
243
|
+
<input {...getInputProps()} />
|
|
244
|
+
<DropzonePlaceholder
|
|
245
|
+
mediaTypes={fieldMetadata.mediaTypes}
|
|
246
|
+
mediaMaxSizeKb={fieldMetadata.mediaMaxSizeKb}
|
|
247
|
+
/>
|
|
251
248
|
</div>
|
|
252
|
-
|
|
249
|
+
{isFormFieldValid(formik, fieldLayoutInfo.attrs.name) && (
|
|
250
|
+
<div className="absolute mt-1">
|
|
251
|
+
<Message severity="error" text={formik?.errors[fieldLayoutInfo.attrs.name]?.toString()} />
|
|
252
|
+
</div>
|
|
253
|
+
)}
|
|
254
|
+
</div>
|
|
253
255
|
{
|
|
254
256
|
fileSizeError &&
|
|
255
257
|
<Message severity="error" text={fileSizeError?.toString()} />
|
|
@@ -64,6 +64,7 @@ export class SolidSelectionDynamicField implements ISolidField {
|
|
|
64
64
|
|
|
65
65
|
const formDisabled = solidFormViewMetaData.data.solidView?.layout?.attrs?.disabled;
|
|
66
66
|
const formReadonly = solidFormViewMetaData.data.solidView?.layout?.attrs?.readonly;
|
|
67
|
+
const whereClause = fieldLayoutInfo.attrs.whereClause;
|
|
67
68
|
|
|
68
69
|
// selection dynamic specific code.
|
|
69
70
|
const [triggerGetSelectionDynamicValues] = useLazyGetSelectionDynamicValuesQuery();
|
|
@@ -77,11 +78,18 @@ export class SolidSelectionDynamicField implements ISolidField {
|
|
|
77
78
|
query: event.query,
|
|
78
79
|
fieldId: fieldMetadata.id
|
|
79
80
|
};
|
|
80
|
-
|
|
81
|
-
|
|
81
|
+
if (whereClause) {
|
|
82
|
+
queryData.query = whereClause;
|
|
83
|
+
}
|
|
84
|
+
let sdQs = qs.stringify(queryData, {
|
|
82
85
|
encodeValuesOnly: true,
|
|
86
|
+
encoder: (str, defaultEncoder, charset, type) => {
|
|
87
|
+
if (type === 'key' || type === 'value') {
|
|
88
|
+
if (str === queryData.query) return str;
|
|
89
|
+
}
|
|
90
|
+
return defaultEncoder(str);
|
|
91
|
+
}
|
|
83
92
|
});
|
|
84
|
-
|
|
85
93
|
// TODO: do error handling here, possible errors like modelname is incorrect etc...
|
|
86
94
|
const sdResponse = await triggerGetSelectionDynamicValues(sdQs);
|
|
87
95
|
|
|
@@ -98,7 +106,7 @@ export class SolidSelectionDynamicField implements ISolidField {
|
|
|
98
106
|
let DynamicWidget = getExtensionComponent("SolidFormFieldViewModeWidget");
|
|
99
107
|
const widgetProps = {
|
|
100
108
|
label: fieldLabel,
|
|
101
|
-
value: formik.values[fieldLayoutInfo.attrs.name],
|
|
109
|
+
value: formik.values[fieldLayoutInfo.attrs.name] && formik.values[fieldLayoutInfo.attrs.name].value,
|
|
102
110
|
}
|
|
103
111
|
return (
|
|
104
112
|
<>
|
|
@@ -78,6 +78,7 @@ export class SolidRelationManyToOneField implements ISolidField {
|
|
|
78
78
|
|
|
79
79
|
const formDisabled = solidFormViewMetaData.data.solidView?.layout?.attrs?.disabled;
|
|
80
80
|
const formReadonly = solidFormViewMetaData.data.solidView?.layout?.attrs?.readonly;
|
|
81
|
+
const whereClause = fieldLayoutInfo.attrs.whereClause;
|
|
81
82
|
|
|
82
83
|
const [autoCompleteItems, setAutoCompleteItems] = useState([]);
|
|
83
84
|
const autoCompleteSearch = async (event: AutoCompleteCompleteEvent) => {
|
|
@@ -93,10 +94,12 @@ export class SolidRelationManyToOneField implements ISolidField {
|
|
|
93
94
|
}
|
|
94
95
|
};
|
|
95
96
|
|
|
96
|
-
|
|
97
|
+
let autocompleteQs = qs.stringify(queryData, {
|
|
97
98
|
encodeValuesOnly: true,
|
|
98
99
|
});
|
|
99
|
-
|
|
100
|
+
if (whereClause) {
|
|
101
|
+
autocompleteQs = `${autocompleteQs}&${whereClause}`;
|
|
102
|
+
}
|
|
100
103
|
// TODO: do error handling here, possible errors like modelname is incorrect etc...
|
|
101
104
|
const autocompleteResponse = await triggerGetSolidEntities(autocompleteQs);
|
|
102
105
|
|
|
@@ -93,6 +93,7 @@ export class SolidRelationOneToManyField implements ISolidField {
|
|
|
93
93
|
inlineCreate: readOnlyPermission === false ? true : false,
|
|
94
94
|
customLayout: fieldLayoutInfo?.attrs?.inlineListLayout,
|
|
95
95
|
embeded: true,
|
|
96
|
+
id: this.fieldContext.data ? this?.fieldContext?.data?.id : 'new',
|
|
96
97
|
customFilter: {
|
|
97
98
|
[customFilter]: {
|
|
98
99
|
id: {
|
|
@@ -113,6 +114,7 @@ export class SolidRelationOneToManyField implements ISolidField {
|
|
|
113
114
|
inlineCreate: readOnlyPermission === false ? true : false,
|
|
114
115
|
customLayout: fieldLayoutInfo?.attrs?.inlineListLayout,
|
|
115
116
|
embeded: true,
|
|
117
|
+
id: this.fieldContext.data ? this?.fieldContext?.data?.id : 'new',
|
|
116
118
|
customFilter: {
|
|
117
119
|
[customFilter]: {
|
|
118
120
|
id: {
|
|
@@ -128,11 +130,11 @@ export class SolidRelationOneToManyField implements ISolidField {
|
|
|
128
130
|
embeded: true,
|
|
129
131
|
isCustomCreate: false,
|
|
130
132
|
customLayout: fieldLayoutInfo?.attrs?.inlineCreateLayout,
|
|
131
|
-
modelName: camelCase(this.fieldContext.fieldMetadata.relationCoModelSingularName)
|
|
133
|
+
modelName: camelCase(this.fieldContext.fieldMetadata.relationCoModelSingularName),
|
|
132
134
|
}
|
|
133
135
|
setformViewParams(formviewparams)
|
|
134
136
|
|
|
135
|
-
}, [])
|
|
137
|
+
}, [readOnlyPermission])
|
|
136
138
|
|
|
137
139
|
const fieldDisabled = fieldLayoutInfo.attrs?.disabled;
|
|
138
140
|
const fieldReadonly = fieldLayoutInfo.attrs?.readonly;
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { useFormik } from "formik";
|
|
3
|
+
import { Button } from "primereact/button";
|
|
4
|
+
import { useSelector } from "react-redux";
|
|
5
|
+
import React, { useRef } from "react";
|
|
6
|
+
import { createSolidEntityApi } from "@/redux/api/solidEntityApi";
|
|
7
|
+
import { javascript } from "@codemirror/lang-javascript";
|
|
8
|
+
import { oneDark } from "@codemirror/theme-one-dark";
|
|
9
|
+
import CodeMirror, { EditorView } from "@uiw/react-codemirror";
|
|
10
|
+
import { Toast } from "primereact/toast";
|
|
11
|
+
|
|
12
|
+
export const KanbanUserViewLayout = ({ solidKanbanViewMetaData, setLayoutDialogVisible }: any) => {
|
|
13
|
+
const toast = useRef<Toast>(null);
|
|
14
|
+
const { user } = useSelector((state: any) => state.auth);
|
|
15
|
+
const entityApi = createSolidEntityApi("userViewMetadata");
|
|
16
|
+
const { useUpsertSolidEntityMutation } = entityApi;
|
|
17
|
+
const [upsertUserView] = useUpsertSolidEntityMutation();
|
|
18
|
+
|
|
19
|
+
if (!solidKanbanViewMetaData?.data?.solidView) return null;
|
|
20
|
+
|
|
21
|
+
const solidView = solidKanbanViewMetaData.data.solidView;
|
|
22
|
+
|
|
23
|
+
const showToast = (severity: "success" | "error", summary: string, detail: string) => {
|
|
24
|
+
toast.current?.show({
|
|
25
|
+
severity,
|
|
26
|
+
summary,
|
|
27
|
+
detail,
|
|
28
|
+
life: 3000,
|
|
29
|
+
});
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
const formik = useFormik({
|
|
33
|
+
initialValues: {
|
|
34
|
+
layoutString: JSON.stringify(solidView.layout, null, 2),
|
|
35
|
+
},
|
|
36
|
+
onSubmit: async (values) => {
|
|
37
|
+
const parsedLayout = JSON.parse(values.layoutString);
|
|
38
|
+
console.log("updatedLayout", parsedLayout);
|
|
39
|
+
|
|
40
|
+
try {
|
|
41
|
+
if (solidView.id) {
|
|
42
|
+
const response = await upsertUserView({
|
|
43
|
+
userId: user?.user?.id,
|
|
44
|
+
viewMetadataId: solidView.id,
|
|
45
|
+
layout: JSON.stringify(parsedLayout),
|
|
46
|
+
}).unwrap();
|
|
47
|
+
console.log("Response", response);
|
|
48
|
+
if (response.statusCode === 200) {
|
|
49
|
+
showToast("success", "Layout", "Form Layout Updated successfully!");
|
|
50
|
+
setLayoutDialogVisible(false);
|
|
51
|
+
window.location.reload();
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
} catch (error) {
|
|
55
|
+
console.error("Update failed:", error);
|
|
56
|
+
}
|
|
57
|
+
},
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
return (
|
|
61
|
+
<>
|
|
62
|
+
<Toast ref={toast} />
|
|
63
|
+
<form onSubmit={formik.handleSubmit}>
|
|
64
|
+
<CodeMirror
|
|
65
|
+
value={formik.values.layoutString}
|
|
66
|
+
height="500px"
|
|
67
|
+
theme={oneDark}
|
|
68
|
+
style={{ fontSize: '10px' }}
|
|
69
|
+
extensions={[javascript(), EditorView.lineWrapping]}
|
|
70
|
+
onChange={(value) => {
|
|
71
|
+
formik.setFieldValue("layoutString", value);
|
|
72
|
+
}}
|
|
73
|
+
/>
|
|
74
|
+
<div className="pt-3 flex gap-2">
|
|
75
|
+
<Button type="submit" label="Apply" size="small" />
|
|
76
|
+
<Button
|
|
77
|
+
type="button"
|
|
78
|
+
outlined
|
|
79
|
+
label="Cancel"
|
|
80
|
+
size="small"
|
|
81
|
+
onClick={() => setLayoutDialogVisible(false)}
|
|
82
|
+
/>
|
|
83
|
+
</div>
|
|
84
|
+
</form>
|
|
85
|
+
</>
|
|
86
|
+
);
|
|
87
|
+
};
|
|
@@ -28,6 +28,8 @@ import "yet-another-react-lightbox/styles.css";
|
|
|
28
28
|
import "yet-another-react-lightbox/plugins/counter.css";
|
|
29
29
|
import { useRouter, useSearchParams } from "next/navigation";
|
|
30
30
|
import { SolidKanbanViewConfigure } from "./SolidKanbanViewConfigure";
|
|
31
|
+
import { KanbanUserViewLayout } from "./KanbanUserViewLayout";
|
|
32
|
+
import { useSelector } from "react-redux";
|
|
31
33
|
|
|
32
34
|
|
|
33
35
|
|
|
@@ -39,6 +41,7 @@ type SolidKanbanViewParams = {
|
|
|
39
41
|
|
|
40
42
|
|
|
41
43
|
export const SolidKanbanView = (params: SolidKanbanViewParams) => {
|
|
44
|
+
const { user } = useSelector((state: any) => state.auth);
|
|
42
45
|
const solidGlobalSearchElementRef = useRef();
|
|
43
46
|
const searchParams = useSearchParams().toString(); // Converts the query params to a string
|
|
44
47
|
const router = useRouter();
|
|
@@ -62,6 +65,7 @@ export const SolidKanbanView = (params: SolidKanbanViewParams) => {
|
|
|
62
65
|
const [openLightbox, setOpenLightbox] = useState(false);
|
|
63
66
|
const [lightboxUrls, setLightboxUrls] = useState({});
|
|
64
67
|
const [filterQueryString, setFilterQueryString] = useState<any>();
|
|
68
|
+
const [isLayoutDialogVisible, setLayoutDialogVisible] = useState(false);
|
|
65
69
|
|
|
66
70
|
|
|
67
71
|
|
|
@@ -117,7 +121,7 @@ export const SolidKanbanView = (params: SolidKanbanViewParams) => {
|
|
|
117
121
|
} = entityApi;
|
|
118
122
|
|
|
119
123
|
// Get the kanban view layout & metadata first.
|
|
120
|
-
const kanbanViewMetaDataQs = qs.stringify({ ...params, viewType: 'kanban' }, {
|
|
124
|
+
const kanbanViewMetaDataQs = qs.stringify({ ...params, viewType: 'kanban', userId: user?.user?.id }, {
|
|
121
125
|
encodeValuesOnly: true,
|
|
122
126
|
});
|
|
123
127
|
const [kanbanViewMetaData, setKanbanViewMetaData] = useState<any>({});
|
|
@@ -706,14 +710,14 @@ export const SolidKanbanView = (params: SolidKanbanViewParams) => {
|
|
|
706
710
|
solidKanbanViewMetaData={solidKanbanViewMetaData}
|
|
707
711
|
actionsAllowed={actionsAllowed}
|
|
708
712
|
viewModes={viewModes}
|
|
709
|
-
|
|
713
|
+
setLayoutDialogVisible={setLayoutDialogVisible}
|
|
710
714
|
/>
|
|
711
715
|
{/* <SolidConfigureLayoutElement></SolidConfigureLayoutElement> */}
|
|
712
716
|
</div>
|
|
713
717
|
</div>
|
|
714
718
|
<style>{`.p-datatable .p-datatable-loading-overlay {background-color: rgba(0, 0, 0, 0.0);}`}</style>
|
|
715
719
|
{solidKanbanViewMetaData && kanbanViewData &&
|
|
716
|
-
<KanbanBoard groupedView={groupedView} kanbanViewData={kanbanViewData} solidKanbanViewMetaData={solidKanbanViewMetaData?.data} setKanbanViewData={setKanbanViewData} handleLoadMore={handleLoadMore} onDragEnd={onDragEnd} handleSwimLinPagination={handleSwimLinPagination} setLightboxUrls={setLightboxUrls} setOpenLightbox={setOpenLightbox}
|
|
720
|
+
<KanbanBoard groupedView={groupedView} kanbanViewData={kanbanViewData} solidKanbanViewMetaData={solidKanbanViewMetaData?.data} setKanbanViewData={setKanbanViewData} handleLoadMore={handleLoadMore} onDragEnd={onDragEnd} handleSwimLinPagination={handleSwimLinPagination} setLightboxUrls={setLightboxUrls} setOpenLightbox={setOpenLightbox} editButtonUrl={editButtonUrl}></KanbanBoard>
|
|
717
721
|
}
|
|
718
722
|
|
|
719
723
|
<Dialog
|
|
@@ -738,6 +742,17 @@ export const SolidKanbanView = (params: SolidKanbanViewParams) => {
|
|
|
738
742
|
slides={lightboxUrls}
|
|
739
743
|
/>
|
|
740
744
|
}
|
|
745
|
+
<Dialog
|
|
746
|
+
visible={isLayoutDialogVisible}
|
|
747
|
+
header="Change Kanban Layout"
|
|
748
|
+
modal
|
|
749
|
+
onHide={() => setLayoutDialogVisible(false)}
|
|
750
|
+
contentStyle={{
|
|
751
|
+
width: 800
|
|
752
|
+
}}
|
|
753
|
+
>
|
|
754
|
+
<KanbanUserViewLayout solidKanbanViewMetaData={solidKanbanViewMetaData} setLayoutDialogVisible={setLayoutDialogVisible} />
|
|
755
|
+
</Dialog>
|
|
741
756
|
</div>
|
|
742
757
|
);
|
|
743
758
|
};
|
|
@@ -7,7 +7,7 @@ import { OverlayPanel } from 'primereact/overlaypanel';
|
|
|
7
7
|
import { RadioButton } from 'primereact/radiobutton';
|
|
8
8
|
import React, { useEffect, useRef, useState } from 'react'
|
|
9
9
|
|
|
10
|
-
export const SolidKanbanViewConfigure = ({ solidKanbanViewMetaData, actionsAllowed, viewModes }: any) => {
|
|
10
|
+
export const SolidKanbanViewConfigure = ({ solidKanbanViewMetaData, actionsAllowed, setLayoutDialogVisible, viewModes }: any) => {
|
|
11
11
|
const op = useRef(null);
|
|
12
12
|
const customizeLayout = useRef<OverlayPanel | null>(null);
|
|
13
13
|
const pathname = usePathname();
|
|
@@ -68,7 +68,7 @@ export const SolidKanbanViewConfigure = ({ solidKanbanViewMetaData, actionsAllow
|
|
|
68
68
|
<div className="flex flex-column">
|
|
69
69
|
<Button text icon='pi pi-download' label="Import" size="small" severity="secondary" className="text-left gap-2 text-base" />
|
|
70
70
|
<Button text icon='pi pi-upload' label="Export" size="small" severity="secondary" className="text-left gap-2 text-base" />
|
|
71
|
-
|
|
71
|
+
<Button
|
|
72
72
|
text
|
|
73
73
|
type="button"
|
|
74
74
|
className="w-8rem text-left gap-2 purple-200"
|
|
@@ -78,7 +78,7 @@ export const SolidKanbanViewConfigure = ({ solidKanbanViewMetaData, actionsAllow
|
|
|
78
78
|
severity="contrast"
|
|
79
79
|
icon={'pi pi-objects-column'}
|
|
80
80
|
onClick={() => setLayoutDialogVisible(true)}
|
|
81
|
-
/>
|
|
81
|
+
/>
|
|
82
82
|
</div>
|
|
83
83
|
</div>
|
|
84
84
|
<Divider className="m-0" />
|
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
"use client"
|
|
2
|
+
import { useFormik } from 'formik';
|
|
3
|
+
import { Button } from 'primereact/button';
|
|
4
|
+
import { Checkbox, CheckboxChangeEvent } from 'primereact/checkbox';
|
|
5
|
+
import React, { useEffect, useRef, useState } from 'react'
|
|
6
|
+
import qs from "qs";
|
|
7
|
+
import { useSelector } from 'react-redux';
|
|
8
|
+
import { createSolidEntityApi } from '@/redux/api/solidEntityApi';
|
|
9
|
+
import { Toast } from "primereact/toast";
|
|
10
|
+
|
|
11
|
+
interface FieldMetadata {
|
|
12
|
+
displayName: string;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
interface FilterColumns {
|
|
16
|
+
name: string;
|
|
17
|
+
key: string;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export const SolidListColumnSelector = ({ listViewMetaData }: any) => {
|
|
21
|
+
const toast = useRef<Toast>(null);
|
|
22
|
+
|
|
23
|
+
const { user } = useSelector((state: any) => state.auth);
|
|
24
|
+
const entityApi = createSolidEntityApi('userViewMetadata');
|
|
25
|
+
const {
|
|
26
|
+
useUpsertSolidEntityMutation
|
|
27
|
+
} = entityApi;
|
|
28
|
+
|
|
29
|
+
const [upsertUserView, { isLoading, error: viewCreateError, isSuccess, data: data }] = useUpsertSolidEntityMutation();
|
|
30
|
+
const showToast = (severity: "success" | "error", summary: string, detail: string) => {
|
|
31
|
+
toast.current?.show({
|
|
32
|
+
severity,
|
|
33
|
+
summary,
|
|
34
|
+
detail,
|
|
35
|
+
life: 3000,
|
|
36
|
+
});
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
if (!listViewMetaData) {
|
|
40
|
+
return;
|
|
41
|
+
}
|
|
42
|
+
if (!listViewMetaData.data) {
|
|
43
|
+
return;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
const solidView = listViewMetaData?.data?.solidView;
|
|
47
|
+
|
|
48
|
+
// This is a key value map of field name vs field metadata.
|
|
49
|
+
const solidFieldsMetadata = listViewMetaData?.data?.solidFieldsMetadata as Record<string, FieldMetadata>;
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
if (!solidView || !solidFieldsMetadata) {
|
|
53
|
+
return;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
const checkedFieldNames = new Set(solidView.layout.children.map((col: { attrs: { name: string } }) => col.attrs.name));
|
|
57
|
+
|
|
58
|
+
const solidListColumns: FilterColumns[] = Object.entries(solidFieldsMetadata).map(([key, field]) => ({
|
|
59
|
+
name: field.displayName,
|
|
60
|
+
key,
|
|
61
|
+
}));
|
|
62
|
+
|
|
63
|
+
const formik = useFormik({
|
|
64
|
+
initialValues: {
|
|
65
|
+
selectedColumns: solidListColumns.filter(col => checkedFieldNames.has(col.key)),
|
|
66
|
+
},
|
|
67
|
+
onSubmit: async (values) => {
|
|
68
|
+
const selectedKeys = values.selectedColumns.map(col => col.key);
|
|
69
|
+
|
|
70
|
+
// Step 1: Extract current children
|
|
71
|
+
const currentChildren = solidView.layout.children;
|
|
72
|
+
|
|
73
|
+
// Step 2: Create a map of all available metadata
|
|
74
|
+
const allFieldMeta = solidFieldsMetadata;
|
|
75
|
+
|
|
76
|
+
// Step 3: Filter children to include only selected keys
|
|
77
|
+
const newChildren = selectedKeys.map((key) => {
|
|
78
|
+
const existingChild = currentChildren.find((child: any) => child.attrs.name === key);
|
|
79
|
+
if (existingChild) {
|
|
80
|
+
return existingChild; // keep original config
|
|
81
|
+
} else {
|
|
82
|
+
// construct a new one if it wasn't in the original
|
|
83
|
+
return {
|
|
84
|
+
type: 'field',
|
|
85
|
+
attrs: {
|
|
86
|
+
name: key,
|
|
87
|
+
label: allFieldMeta[key]?.displayName || key,
|
|
88
|
+
sortable: true,
|
|
89
|
+
filterable: true,
|
|
90
|
+
}
|
|
91
|
+
};
|
|
92
|
+
}
|
|
93
|
+
});
|
|
94
|
+
|
|
95
|
+
// Now build updated solidView
|
|
96
|
+
const updatedView = {
|
|
97
|
+
layout: {
|
|
98
|
+
...solidView.layout,
|
|
99
|
+
children: newChildren
|
|
100
|
+
}
|
|
101
|
+
};
|
|
102
|
+
|
|
103
|
+
try {
|
|
104
|
+
if (listViewMetaData?.data?.solidView?.id) {
|
|
105
|
+
// Update existing user view
|
|
106
|
+
const response = await upsertUserView({
|
|
107
|
+
userId: user?.user?.id,
|
|
108
|
+
viewMetadataId: listViewMetaData?.data?.solidView?.id,
|
|
109
|
+
layout: JSON.stringify(updatedView.layout),
|
|
110
|
+
}).unwrap();
|
|
111
|
+
if (response.statusCode === 200) {
|
|
112
|
+
showToast("success", "Layout", "Form Layout Updated successfully!");
|
|
113
|
+
window.location.reload();
|
|
114
|
+
}
|
|
115
|
+
console.log("Successfully updated:", response);
|
|
116
|
+
} else {
|
|
117
|
+
// Create new user view
|
|
118
|
+
console.log("Error:");
|
|
119
|
+
}
|
|
120
|
+
} catch (error) {
|
|
121
|
+
console.error("Error updating user view:", error);
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
console.log("Updated solidView", updatedView);
|
|
125
|
+
|
|
126
|
+
},
|
|
127
|
+
});
|
|
128
|
+
|
|
129
|
+
return (
|
|
130
|
+
<>
|
|
131
|
+
<Toast ref={toast} />
|
|
132
|
+
<form onSubmit={formik.handleSubmit} className="flex flex-column gap-1 p-1">
|
|
133
|
+
<div className="flex flex-column gap-3 px-3 cogwheel-column-filter" style={{ maxHeight: 400, overflowY: 'auto' }}>
|
|
134
|
+
{solidListColumns.map((column) => {
|
|
135
|
+
return (
|
|
136
|
+
<div key={column.key} className="flex align-items-center gap-1">
|
|
137
|
+
<Checkbox
|
|
138
|
+
inputId={column.key}
|
|
139
|
+
name="selectedColumns"
|
|
140
|
+
value={column}
|
|
141
|
+
onChange={(e) => {
|
|
142
|
+
const isChecked = formik.values.selectedColumns.some(item => item.key === column.key);
|
|
143
|
+
formik.setFieldValue(
|
|
144
|
+
"selectedColumns",
|
|
145
|
+
isChecked
|
|
146
|
+
? formik.values.selectedColumns.filter(item => item.key !== column.key)
|
|
147
|
+
: [...formik.values.selectedColumns, column]
|
|
148
|
+
);
|
|
149
|
+
}}
|
|
150
|
+
checked={formik.values.selectedColumns.some(item => item.key === column.key)}
|
|
151
|
+
className="text-base"
|
|
152
|
+
/>
|
|
153
|
+
<label htmlFor={column.key} className="ml-2 text-base">
|
|
154
|
+
{column.name}
|
|
155
|
+
</label>
|
|
156
|
+
</div>
|
|
157
|
+
);
|
|
158
|
+
})}
|
|
159
|
+
</div>
|
|
160
|
+
<div className="p-3 flex gap-2">
|
|
161
|
+
<Button type='submit' label="Apply" size="small" />
|
|
162
|
+
<Button type='button' outlined label="Cancel" size="small"
|
|
163
|
+
// @ts-ignore
|
|
164
|
+
onClick={(e) => op.current.hide(e)}
|
|
165
|
+
/>
|
|
166
|
+
</div>
|
|
167
|
+
</form>
|
|
168
|
+
</>
|
|
169
|
+
)
|
|
170
|
+
}
|
|
@@ -43,6 +43,7 @@ import Download from "yet-another-react-lightbox/plugins/download";
|
|
|
43
43
|
import "yet-another-react-lightbox/styles.css";
|
|
44
44
|
import "yet-another-react-lightbox/plugins/counter.css";
|
|
45
45
|
import { SolidListViewConfigure } from "./SolidListViewConfigure";
|
|
46
|
+
import { useSelector } from "react-redux";
|
|
46
47
|
|
|
47
48
|
|
|
48
49
|
const getRandomInt = (min: number, max: number) => {
|
|
@@ -91,6 +92,7 @@ type SolidListViewParams = {
|
|
|
91
92
|
export const SolidListView = (params: SolidListViewParams) => {
|
|
92
93
|
|
|
93
94
|
const solidGlobalSearchElementRef = useRef();
|
|
95
|
+
const { user } = useSelector((state: any) => state.auth);
|
|
94
96
|
|
|
95
97
|
|
|
96
98
|
const router = useRouter()
|
|
@@ -148,7 +150,7 @@ export const SolidListView = (params: SolidListViewParams) => {
|
|
|
148
150
|
} = entityApi;
|
|
149
151
|
|
|
150
152
|
// Get the list view layout & metadata first.
|
|
151
|
-
const listViewMetaDataQs = qs.stringify({ modelName: params.modelName, moduleName: params.moduleName, viewType: 'list' }, {
|
|
153
|
+
const listViewMetaDataQs = qs.stringify({ modelName: params.modelName, moduleName: params.moduleName, viewType: 'list', userId: user?.user?.id }, {
|
|
152
154
|
encodeValuesOnly: true,
|
|
153
155
|
});
|
|
154
156
|
const [listViewMetaData, setListViewMetaData] = useState({});
|
|
@@ -722,23 +724,25 @@ export const SolidListView = (params: SolidListViewParams) => {
|
|
|
722
724
|
{actionsAllowed.includes(`${createPermission(params.modelName)}`) && solidListViewMetaData?.data?.solidView?.layout?.attrs?.create !== false && params.embeded !== true &&
|
|
723
725
|
<SolidCreateButton url={createButtonUrl} />
|
|
724
726
|
}
|
|
725
|
-
{actionsAllowed.includes(`${createPermission(params.modelName)}`) && solidListViewMetaData?.data?.solidView?.layout?.attrs?.create !== false && params.embeded == true && params.inlineCreate == true &&
|
|
727
|
+
{actionsAllowed.includes(`${createPermission(params.modelName)}`) && solidListViewMetaData?.data?.solidView?.layout?.attrs?.create !== false && params.embeded == true && params.inlineCreate == true && params.id !== 'new' &&
|
|
726
728
|
// < SolidCreateButton url={createButtonUrl} />
|
|
727
729
|
<Button type="button" icon="pi pi-plus" label="Add" size='small'
|
|
728
730
|
onClick={() => params.handlePopUpOpen("new")}
|
|
729
731
|
></Button>
|
|
730
732
|
}
|
|
731
733
|
{/* Button For Manual Refresh */}
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
734
|
+
{params.embeded !== true &&
|
|
735
|
+
<Button
|
|
736
|
+
type="button"
|
|
737
|
+
size="small"
|
|
738
|
+
icon="pi pi-refresh"
|
|
739
|
+
severity="secondary"
|
|
740
|
+
outlined
|
|
741
|
+
onClick={() => {
|
|
742
|
+
setQueryString(first, rows, sortField, sortOrder, filters, showArchived);
|
|
743
|
+
}}
|
|
744
|
+
/>
|
|
745
|
+
}
|
|
742
746
|
{showArchived && <Button type="button" icon="pi pi-refresh" label="Recover" size='small' severity="secondary"
|
|
743
747
|
onClick={() => setRecoverDialogVisible(true)}
|
|
744
748
|
></Button>}
|