@solidstarters/solid-core-ui 1.1.54 → 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.
Files changed (77) hide show
  1. package/dist/components/common/SolidFormStepper.d.ts.map +1 -1
  2. package/dist/components/common/SolidFormStepper.js +0 -4
  3. package/dist/components/common/SolidFormStepper.js.map +1 -1
  4. package/dist/components/core/common/SolidGlobalSearchElement.d.ts.map +1 -1
  5. package/dist/components/core/common/SolidGlobalSearchElement.js +7 -2
  6. package/dist/components/core/common/SolidGlobalSearchElement.js.map +1 -1
  7. package/dist/components/core/form/SolidFormUserViewLayout.d.ts +2 -0
  8. package/dist/components/core/form/SolidFormUserViewLayout.d.ts.map +1 -0
  9. package/dist/components/core/form/SolidFormUserViewLayout.js +112 -0
  10. package/dist/components/core/form/SolidFormUserViewLayout.js.map +1 -0
  11. package/dist/components/core/form/SolidFormView.d.ts.map +1 -1
  12. package/dist/components/core/form/SolidFormView.js +29 -22
  13. package/dist/components/core/form/SolidFormView.js.map +1 -1
  14. package/dist/components/core/form/fields/SolidMediaMultipleField.d.ts.map +1 -1
  15. package/dist/components/core/form/fields/SolidMediaMultipleField.js +1 -1
  16. package/dist/components/core/form/fields/SolidMediaMultipleField.js.map +1 -1
  17. package/dist/components/core/form/fields/SolidMediaSingleField.d.ts.map +1 -1
  18. package/dist/components/core/form/fields/SolidMediaSingleField.js +1 -1
  19. package/dist/components/core/form/fields/SolidMediaSingleField.js.map +1 -1
  20. package/dist/components/core/form/fields/SolidSelectionDynamicField.d.ts.map +1 -1
  21. package/dist/components/core/form/fields/SolidSelectionDynamicField.js +12 -1
  22. package/dist/components/core/form/fields/SolidSelectionDynamicField.js.map +1 -1
  23. package/dist/components/core/form/fields/relations/SolidRelationManyToOneField.d.ts.map +1 -1
  24. package/dist/components/core/form/fields/relations/SolidRelationManyToOneField.js +4 -0
  25. package/dist/components/core/form/fields/relations/SolidRelationManyToOneField.js.map +1 -1
  26. package/dist/components/core/form/fields/relations/SolidRelationOneToManyField.d.ts.map +1 -1
  27. package/dist/components/core/form/fields/relations/SolidRelationOneToManyField.js +9 -7
  28. package/dist/components/core/form/fields/relations/SolidRelationOneToManyField.js.map +1 -1
  29. package/dist/components/core/kanban/KanbanBoard.d.ts.map +1 -1
  30. package/dist/components/core/kanban/KanbanBoard.js +1 -0
  31. package/dist/components/core/kanban/KanbanBoard.js.map +1 -1
  32. package/dist/components/core/kanban/KanbanUserViewLayout.d.ts +2 -0
  33. package/dist/components/core/kanban/KanbanUserViewLayout.d.ts.map +1 -0
  34. package/dist/components/core/kanban/KanbanUserViewLayout.js +112 -0
  35. package/dist/components/core/kanban/KanbanUserViewLayout.js.map +1 -0
  36. package/dist/components/core/kanban/SolidKanbanView.d.ts.map +1 -1
  37. package/dist/components/core/kanban/SolidKanbanView.js +41 -35
  38. package/dist/components/core/kanban/SolidKanbanView.js.map +1 -1
  39. package/dist/components/core/kanban/SolidKanbanViewConfigure.d.ts +1 -1
  40. package/dist/components/core/kanban/SolidKanbanViewConfigure.d.ts.map +1 -1
  41. package/dist/components/core/kanban/SolidKanbanViewConfigure.js +2 -2
  42. package/dist/components/core/kanban/SolidKanbanViewConfigure.js.map +1 -1
  43. package/dist/components/core/list/SolidListColumnSelector.d.ts +2 -0
  44. package/dist/components/core/list/SolidListColumnSelector.d.ts.map +1 -0
  45. package/dist/components/core/list/SolidListColumnSelector.js +182 -0
  46. package/dist/components/core/list/SolidListColumnSelector.js.map +1 -0
  47. package/dist/components/core/list/SolidListView.d.ts.map +1 -1
  48. package/dist/components/core/list/SolidListView.js +48 -45
  49. package/dist/components/core/list/SolidListView.js.map +1 -1
  50. package/dist/components/core/list/SolidListViewConfigure.d.ts +1 -1
  51. package/dist/components/core/list/SolidListViewConfigure.d.ts.map +1 -1
  52. package/dist/components/core/list/SolidListViewConfigure.js +7 -49
  53. package/dist/components/core/list/SolidListViewConfigure.js.map +1 -1
  54. package/dist/redux/api/solidEntityApi.d.ts +1 -0
  55. package/dist/redux/api/solidEntityApi.d.ts.map +1 -1
  56. package/dist/redux/api/solidEntityApi.js +7 -0
  57. package/dist/redux/api/solidEntityApi.js.map +1 -1
  58. package/dist/resources/globals.css +1 -0
  59. package/package.json +1 -1
  60. package/src/components/common/SolidFormStepper.tsx +0 -4
  61. package/src/components/core/common/SolidGlobalSearchElement.tsx +14 -3
  62. package/src/components/core/form/SolidFormUserViewLayout.tsx +87 -0
  63. package/src/components/core/form/SolidFormView.tsx +30 -5
  64. package/src/components/core/form/fields/SolidMediaMultipleField.tsx +16 -14
  65. package/src/components/core/form/fields/SolidMediaSingleField.tsx +16 -14
  66. package/src/components/core/form/fields/SolidSelectionDynamicField.tsx +12 -4
  67. package/src/components/core/form/fields/relations/SolidRelationManyToOneField.tsx +5 -2
  68. package/src/components/core/form/fields/relations/SolidRelationOneToManyField.tsx +4 -2
  69. package/src/components/core/kanban/KanbanBoard.tsx +1 -0
  70. package/src/components/core/kanban/KanbanUserViewLayout.tsx +87 -0
  71. package/src/components/core/kanban/SolidKanbanView.tsx +18 -3
  72. package/src/components/core/kanban/SolidKanbanViewConfigure.tsx +3 -3
  73. package/src/components/core/list/SolidListColumnSelector.tsx +170 -0
  74. package/src/components/core/list/SolidListView.tsx +16 -12
  75. package/src/components/core/list/SolidListViewConfigure.tsx +2 -77
  76. package/src/redux/api/solidEntityApi.tsx +7 -0
  77. package/src/resources/globals.css +1 -0
@@ -34,10 +34,8 @@ export const SolidFormStepper = (props: Props) => {
34
34
 
35
35
  setSolidWorkflowFieldValue(() => {
36
36
  if (initialEntityData?.[solidWorkflowField] !== undefined) {
37
- console.log("checkloginitial", initialEntityData[solidWorkflowField]);
38
37
  return initialEntityData[solidWorkflowField];
39
38
  } else if (defaultWorkflowFieldValue !== undefined) {
40
- console.log("checklogdefault", defaultWorkflowFieldValue);
41
39
  return defaultWorkflowFieldValue;
42
40
  } else {
43
41
  return activeStep;
@@ -98,7 +96,6 @@ export const SolidFormStepper = (props: Props) => {
98
96
 
99
97
  const activeIndex = solidFormViewWorkflowData.findIndex((step: any) => step.value === solidWorkflowFieldValue);
100
98
  const visibleSteps = solidFormViewWorkflowData.length > 5 ? solidFormViewWorkflowData.slice(0, 5) : solidFormViewWorkflowData;
101
- console.log("activeIndex:", activeIndex, "solidWorkflowFieldValue:", solidWorkflowFieldValue);
102
99
 
103
100
  return (
104
101
  <>
@@ -112,7 +109,6 @@ export const SolidFormStepper = (props: Props) => {
112
109
  const isLastVisible = index === visibleSteps.length - 1;
113
110
  const isNextAfterActive = index === activeIndex + 1;
114
111
  const isTwoStepsOnly = visibleSteps.length === 2;
115
- console.log("isActive", isActive);
116
112
 
117
113
  return (
118
114
  <Button
@@ -383,6 +383,13 @@ export const SolidGlobalSearchElement = forwardRef(({ viewData, handleApplyCusto
383
383
  return acc;
384
384
  }, {} as Record<string, string[]>);
385
385
 
386
+ const handleRemoveChipGroup = (columnName: string) => {
387
+ const updatedChips = searchChips.filter(chip => chip.columnName !== columnName);
388
+ setSearchChips(updatedChips);
389
+ setHasSearched(true);
390
+ };
391
+
392
+
386
393
  const CustomChip = () => (
387
394
  <li>
388
395
  <div className="custom-filter-chip-type">
@@ -397,7 +404,9 @@ export const SolidGlobalSearchElement = forwardRef(({ viewData, handleApplyCusto
397
404
  </div>
398
405
 
399
406
  {/* button to clear filter */}
400
- <a onClick={clearCustomFilter}>
407
+ <a onClick={clearCustomFilter}
408
+ style={{ cursor: "pointer" }}
409
+ >
401
410
  <i className="pi pi-times ml-1">
402
411
  </i></a>
403
412
  </div>
@@ -421,8 +430,10 @@ export const SolidGlobalSearchElement = forwardRef(({ viewData, handleApplyCusto
421
430
  </React.Fragment>
422
431
  ))}
423
432
  {/* button to clear filter */}
424
- <i className="pi pi-times ml-1">
425
- </i>
433
+ <i className="pi pi-times ml-1"
434
+ style={{ cursor: "pointer" }}
435
+ onClick={() => handleRemoveChipGroup(column)}
436
+ > </i>
426
437
  </div>
427
438
  </li>
428
439
  ))}
@@ -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 SolidFormUserViewLayout = ({ solidFormViewMetaData, 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 (!solidFormViewMetaData?.data?.solidView) return null;
20
+
21
+ const solidView = solidFormViewMetaData.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
+ };
@@ -43,6 +43,8 @@ import { SolidEmailField } from "./fields/SolidEmailField";
43
43
  import { Panel } from "primereact/panel";
44
44
  import { SolidFormStepper } from "@/components/common/SolidFormStepper";
45
45
  import { SolidFormHeader } from "@/components/common/SolidFormHeader";
46
+ import { SolidFormUserViewLayout } from "./SolidFormUserViewLayout";
47
+ import { useSelector } from "react-redux";
46
48
 
47
49
  export type SolidFormViewProps = {
48
50
  moduleName: string;
@@ -342,7 +344,7 @@ const SolidPage = ({ attrs, children, key }: any) => (
342
344
  // };
343
345
 
344
346
  const SolidFormView = (params: SolidFormViewProps) => {
345
-
347
+ const { user } = useSelector((state: any) => state.auth);
346
348
  const pathname = usePathname();
347
349
  const router = useRouter();
348
350
  const toast = useRef<Toast>(null);
@@ -352,6 +354,7 @@ const SolidFormView = (params: SolidFormViewProps) => {
352
354
  const [redirectToList, setRedirectToList] = useState(false);
353
355
 
354
356
  const [isDeleteDialogVisible, setDeleteDialogVisible] = useState(false);
357
+ const [isLayoutDialogVisible, setLayoutDialogVisible] = useState(false);
355
358
 
356
359
  const [actionsAllowed, setActionsAllowed] = useState<string[]>([]);
357
360
  const [viewMode, setViewMode] = useState<"view" | "edit">("view");
@@ -437,7 +440,7 @@ const SolidFormView = (params: SolidFormViewProps) => {
437
440
 
438
441
  // - - - - - - - - - - - -- - - - - - - - - - - - METADATA here
439
442
  // Get the form view layout & metadata first.
440
- const formViewMetaDataQs = qs.stringify({ ...params, viewType: 'form' }, {
443
+ const formViewMetaDataQs = qs.stringify({ ...params, viewType: 'form', userId: user?.user?.id }, {
441
444
  encodeValuesOnly: true,
442
445
  });
443
446
  const [formViewMetaData, setFormViewMetaData] = useState({});
@@ -919,7 +922,7 @@ const SolidFormView = (params: SolidFormViewProps) => {
919
922
  // const fieldMetadata = solidFieldsMetadata[attrs.name];
920
923
  const fieldMetadata = solidFormViewMetaData.data.solidFieldsMetadata[attrs.name];
921
924
  // Read only permission if there is no update permission on model and router doesnt contains new
922
- const readOnlyPermission = !actionsAllowed.includes(`${updatePermission(params.modelName)}`) && params.id !== "new"
925
+ const readOnlyPermission = !actionsAllowed.includes(`${updatePermission(params.modelName)}`) && params.id !== "new";
923
926
  return <SolidField
924
927
  key={key}
925
928
  field={element}
@@ -1042,6 +1045,7 @@ const SolidFormView = (params: SolidFormViewProps) => {
1042
1045
  </svg>}
1043
1046
  /> */}
1044
1047
  {params.embeded !== true &&
1048
+ params.id !== "new" &&
1045
1049
  actionsAllowed.includes(`${deletePermission(params.modelName)}`) &&
1046
1050
  !formViewLayout.attrs.readonly &&
1047
1051
  <Button
@@ -1056,6 +1060,17 @@ const SolidFormView = (params: SolidFormViewProps) => {
1056
1060
  onClick={() => setDeleteDialogVisible(true)}
1057
1061
  />
1058
1062
  }
1063
+ <Button
1064
+ text
1065
+ type="button"
1066
+ className="w-8rem text-left gap-2 purple-200"
1067
+ label="Layout"
1068
+ size="small"
1069
+ iconPos="left"
1070
+ severity="contrast"
1071
+ icon={'pi pi-objects-column'}
1072
+ onClick={() => setLayoutDialogVisible(true)}
1073
+ />
1059
1074
  </div>
1060
1075
  </OverlayPanel>
1061
1076
  </div>
@@ -1137,7 +1152,7 @@ const SolidFormView = (params: SolidFormViewProps) => {
1137
1152
  {params.embeded !== true &&
1138
1153
  <SolidCancelButton />
1139
1154
  }
1140
-
1155
+ {formActionDropdown()}
1141
1156
  </div>
1142
1157
  </>
1143
1158
  ) : (
@@ -1266,9 +1281,19 @@ const SolidFormView = (params: SolidFormViewProps) => {
1266
1281
  >
1267
1282
  <p>Are you sure you want to delete?</p>
1268
1283
  </Dialog>
1284
+ <Dialog
1285
+ visible={isLayoutDialogVisible}
1286
+ header="Change Form Layout"
1287
+ modal
1288
+ onHide={() => setLayoutDialogVisible(false)}
1289
+ contentStyle={{
1290
+ width: 800
1291
+ }}
1292
+ >
1293
+ <SolidFormUserViewLayout solidFormViewMetaData={solidFormViewMetaData} setLayoutDialogVisible={setLayoutDialogVisible} />
1294
+ </Dialog>
1269
1295
  </div>
1270
1296
  );
1271
-
1272
1297
  }
1273
1298
  };
1274
1299
 
@@ -240,21 +240,23 @@ export class SolidMediaMultipleField implements ISolidField {
240
240
  {/* &nbsp; {fieldDescription && <span className="form_field_help">({fieldDescription}) </span>} */}
241
241
  </label>
242
242
  }
243
- <div
244
- {...getRootProps()}
245
- className="solid-dropzone-wrapper"
246
- >
247
- <input {...getInputProps()} />
248
- <DropzonePlaceholder
249
- mediaTypes={fieldMetadata.mediaTypes}
250
- mediaMaxSizeKb={fieldMetadata.mediaMaxSizeKb}
251
- />
252
- </div>
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
  {/* &nbsp; {fieldDescription && <span className="form_field_help">({fieldDescription}) </span>} */}
236
236
  </label>
237
237
  }
238
- <div
239
- {...getRootProps()}
240
- className="solid-dropzone-wrapper"
241
- >
242
- <input {...getInputProps()} />
243
- <DropzonePlaceholder
244
- mediaTypes={fieldMetadata.mediaTypes}
245
- mediaMaxSizeKb={fieldMetadata.mediaMaxSizeKb}
246
- />
247
- </div>
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
- const sdQs = qs.stringify(queryData, {
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
- const autocompleteQs = qs.stringify(queryData, {
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;
@@ -5,6 +5,7 @@ import React, { useState, useEffect } from "react";
5
5
  import { DragDropContext, DropResult } from "@hello-pangea/dnd";
6
6
  import axios from "axios";
7
7
  import KanbanColumn from "./KanbanColumn";
8
+ import { Button } from "primereact/button";
8
9
 
9
10
  // Define types for groupData and Grouped Data
10
11
  interface Post {
@@ -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
- // setLayoutDialogVisible={setLayoutDialogVisible}
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} editButtonUrl={editButtonUrl}></KanbanBoard>
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
- {/* <Button
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" />