@solidstarters/solid-core-ui 1.1.7 → 1.1.8

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 (49) hide show
  1. package/dist/components/auth/SolidForgotPassword.js +2 -2
  2. package/dist/components/auth/SolidForgotPassword.js.map +1 -1
  3. package/dist/components/auth/SolidLogin.js +4 -4
  4. package/dist/components/auth/SolidLogin.js.map +1 -1
  5. package/dist/components/core/common/LoadDynamicJsxComponent.d.ts.map +1 -1
  6. package/dist/components/core/common/LoadDynamicJsxComponent.js +2 -1
  7. package/dist/components/core/common/LoadDynamicJsxComponent.js.map +1 -1
  8. package/dist/components/core/common/SolidGlobalSearchElement.d.ts.map +1 -1
  9. package/dist/components/core/common/SolidGlobalSearchElement.js +6 -5
  10. package/dist/components/core/common/SolidGlobalSearchElement.js.map +1 -1
  11. package/dist/components/core/extension/solid-core/modelMetadata/list/GenerateModelCodeRowAction.d.ts +2 -1
  12. package/dist/components/core/extension/solid-core/modelMetadata/list/GenerateModelCodeRowAction.d.ts.map +1 -1
  13. package/dist/components/core/extension/solid-core/modelMetadata/list/GenerateModelCodeRowAction.js +4 -3
  14. package/dist/components/core/extension/solid-core/modelMetadata/list/GenerateModelCodeRowAction.js.map +1 -1
  15. package/dist/components/core/list/SolidListView.d.ts.map +1 -1
  16. package/dist/components/core/list/SolidListView.js +99 -21
  17. package/dist/components/core/list/SolidListView.js.map +1 -1
  18. package/dist/components/core/model/FieldMetaDataForm.d.ts.map +1 -1
  19. package/dist/components/core/model/FieldMetaDataForm.js +26 -28
  20. package/dist/components/core/model/FieldMetaDataForm.js.map +1 -1
  21. package/dist/components/core/model/ModelMetaData.d.ts.map +1 -1
  22. package/dist/components/core/model/ModelMetaData.js +10 -3
  23. package/dist/components/core/model/ModelMetaData.js.map +1 -1
  24. package/dist/components/layout/user-profile-menu.d.ts.map +1 -1
  25. package/dist/components/layout/user-profile-menu.js +3 -1
  26. package/dist/components/layout/user-profile-menu.js.map +1 -1
  27. package/dist/index.d.ts +1 -0
  28. package/dist/index.d.ts.map +1 -1
  29. package/dist/index.js +1 -0
  30. package/dist/index.js.map +1 -1
  31. package/dist/redux/api/solidEntityApi.d.ts +2 -0
  32. package/dist/redux/api/solidEntityApi.d.ts.map +1 -1
  33. package/dist/redux/api/solidEntityApi.js +10 -0
  34. package/dist/redux/api/solidEntityApi.js.map +1 -1
  35. package/dist/redux/api/solidSettingsApi.js +1 -1
  36. package/dist/redux/api/solidSettingsApi.js.map +1 -1
  37. package/package.json +1 -1
  38. package/src/components/auth/SolidForgotPassword.tsx +2 -2
  39. package/src/components/auth/SolidLogin.tsx +5 -5
  40. package/src/components/core/common/LoadDynamicJsxComponent.tsx +2 -1
  41. package/src/components/core/common/SolidGlobalSearchElement.tsx +6 -2
  42. package/src/components/core/extension/solid-core/modelMetadata/list/GenerateModelCodeRowAction.tsx +4 -4
  43. package/src/components/core/list/SolidListView.tsx +118 -8
  44. package/src/components/core/model/FieldMetaDataForm.tsx +6 -4
  45. package/src/components/core/model/ModelMetaData.tsx +10 -3
  46. package/src/components/layout/user-profile-menu.tsx +6 -1
  47. package/src/index.ts +1 -0
  48. package/src/redux/api/solidEntityApi.tsx +11 -0
  49. package/src/redux/api/solidSettingsApi.tsx +1 -1
@@ -30,6 +30,7 @@ import { SolidLayoutViews } from '../common/SolidLayoutViews'
30
30
  import { SolidConfigureLayoutElement } from '../common/SolidConfigureLayoutElement'
31
31
  import { FilterIcon } from '../../modelsComponents/filterIcon';
32
32
  import { OverlayPanel } from "primereact/overlaypanel";
33
+ import { Toast } from "primereact/toast";
33
34
  const getRandomInt = (min: number, max: number) => {
34
35
  return Math.floor(Math.random() * (max - min + 1)) + min;
35
36
  }
@@ -94,7 +95,10 @@ export const SolidListView = (params: SolidListViewParams) => {
94
95
  useLazyGetSolidEntitiesQuery,
95
96
  useLazyGetSolidEntityByIdQuery,
96
97
  usePrefetch,
97
- useUpdateSolidEntityMutation
98
+ useUpdateSolidEntityMutation,
99
+ useRecoverSolidEntityByIdQuery,
100
+ useLazyRecoverSolidEntityByIdQuery,
101
+ useRecoverSolidEntityMutation
98
102
  } = entityApi;
99
103
 
100
104
  // Get the list view layout & metadata first.
@@ -110,7 +114,6 @@ export const SolidListView = (params: SolidListViewParams) => {
110
114
  refetch
111
115
  } = useGetSolidViewLayoutQuery(listViewMetaDataQs);
112
116
 
113
-
114
117
  const initialFilterMethod = () => {
115
118
 
116
119
  const solidView = solidListViewMetaData.data.solidView;
@@ -179,24 +182,30 @@ export const SolidListView = (params: SolidListViewParams) => {
179
182
  const [sortField, setSortField] = useState("");
180
183
  const [sortOrder, setSortOrder] = useState(0);
181
184
  const [selectedRecords, setSelectedRecords] = useState<any[]>([]);
185
+ const [selectedRecoverRecords, setSelectedRecoverRecords] = useState<any[]>([]);
182
186
  const [loading, setLoading] = useState<boolean>(true);
183
187
  const [isDialogVisible, setDialogVisible] = useState(false);
188
+ const [isRecoverDialogVisible, setRecoverDialogVisible] = useState(false);
184
189
  const [createButtonUrl, setCreateButtonUrl] = useState<string>();
185
190
  const [editButtonUrl, setEditButtonUrl] = useState<string>();
191
+ const [showArchived, setShowArchived] = useState(false);
186
192
 
187
193
  // Custom Row Action
188
194
  const [listViewRowActionPopupState, setListViewRowActionPopupState] = useState(false);
189
195
  const [listViewRowActionData, setListRowActionData] = useState<any>();
190
196
 
197
+ const toast = useRef<Toast>(null);
198
+
191
199
  // Get the list view data.
192
200
  const [triggerGetSolidEntities, { data: solidEntityListViewData, isLoading, error }] = useLazyGetSolidEntitiesQuery();
193
201
 
202
+ const [triggerRecoverSolidEntitiesById, { data: recoverByIdData, isLoading: recoverByIdIsLoading, error: recoverByIdError, isError: recoverByIdIsError, isSuccess: recoverByIdIsSuccess }] = useLazyRecoverSolidEntityByIdQuery();
194
203
 
204
+ const [triggerRecoverSolidEntities, { data: recoverByData, isLoading: recoverByIsLoading, error: recoverError, isError: recoverIsError, isSuccess: recoverByIsSuccess }] = useRecoverSolidEntityMutation();
195
205
 
196
206
  // After data is fetched populate the list view state so as to be able to render the data.
197
207
  useEffect(() => {
198
208
  if (solidEntityListViewData) {
199
-
200
209
  setListViewData(solidEntityListViewData?.records);
201
210
  setTotalRecords(solidEntityListViewData?.meta.totalRecords);
202
211
  setLoading(false);
@@ -231,6 +240,27 @@ export const SolidListView = (params: SolidListViewParams) => {
231
240
  },
232
241
  ] = useDeleteMultipleSolidEntitiesMutation();
233
242
 
243
+ // Fetch Soft Deleted data
244
+ useEffect(() => {
245
+ const queryData = {
246
+ offset: 0,
247
+ limit: 25,
248
+ populate: toPopulate,
249
+ sort: [`id:desc`],
250
+ };
251
+ if (showArchived) {
252
+ queryData.showSoftDeleted = 'true';
253
+ }
254
+ const queryString = qs.stringify(queryData, {
255
+ encodeValuesOnly: true
256
+ });
257
+
258
+ triggerGetSolidEntities(queryString);
259
+ setSelectedRecords([]);
260
+ setSelectedRecoverRecords([]);
261
+ }, [showArchived, recoverByIdIsSuccess, recoverByIsSuccess]);
262
+
263
+
234
264
  // Fetch data after toPopulate has been populated...
235
265
  useEffect(() => {
236
266
  if (toPopulate) {
@@ -250,6 +280,8 @@ export const SolidListView = (params: SolidListViewParams) => {
250
280
 
251
281
  triggerGetSolidEntities(queryString);
252
282
  setSelectedRecords([]);
283
+ setSelectedRecoverRecords([]);
284
+ setShowArchived(false);
253
285
  }
254
286
  }, [isDeleteSolidEntitiesSucess, isDeleteSolidSingleEntitySuccess, toPopulate]);
255
287
 
@@ -279,7 +311,11 @@ export const SolidListView = (params: SolidListViewParams) => {
279
311
  // handle change in the records which are currently selected...
280
312
  const onSelectionChange = (event: any) => {
281
313
  const value = event.value;
282
- setSelectedRecords(value);
314
+ const activeRecords = value.filter((record: any) => record.deletedAt === null);
315
+ const deletedRecords = value.filter((record: any) => record.deletedAt !== null);
316
+
317
+ setSelectedRecords(activeRecords);
318
+ setSelectedRecoverRecords(deletedRecords);
283
319
  };
284
320
 
285
321
  const identifySolidOperatorAndValue = (primeReactMatchMode: FilterMatchMode, value: any): { operator: string, value: string | string[] | any[] } => {
@@ -475,6 +511,51 @@ export const SolidListView = (params: SolidListViewParams) => {
475
511
  );
476
512
  };
477
513
 
514
+ // Recover functions
515
+ const recoverById = (id) => {
516
+ triggerRecoverSolidEntitiesById(id);
517
+ }
518
+
519
+ const recoverAll = () => {
520
+ let recoverList: any = [];
521
+ selectedRecoverRecords.forEach((element: any) => {
522
+ recoverList.push(element.id);
523
+ });
524
+ triggerRecoverSolidEntities(recoverList);
525
+ setRecoverDialogVisible(false);
526
+ }
527
+
528
+ useEffect(() => {
529
+ if (recoverIsError || recoverByIdIsError) {
530
+ showError(recoverByIdIsError ? recoverByIdError : recoverError);
531
+ }
532
+ }, [recoverIsError, recoverByIdIsError])
533
+
534
+ const showError = async (error) => {
535
+ const errorMessages = error?.data?.message;
536
+ if (errorMessages.length > 0) {
537
+ toast?.current?.show({
538
+ severity: "error",
539
+ summary: "Can you send me the report?",
540
+ // sticky: true,
541
+ life: 3000,
542
+ //@ts-ignore
543
+ content: (props) => (
544
+ <div
545
+ className="flex flex-column align-items-left"
546
+ style={{ flex: "1" }}
547
+ >
548
+ {errorMessages.map((m, index) => (
549
+ <div className="flex align-items-center gap-2" key={index}>
550
+ <span className="font-bold text-900">{String(m)}</span>
551
+ </div>
552
+ ))}
553
+ </div>
554
+ ),
555
+ });
556
+ }
557
+ };
558
+
478
559
  // handle bulk deletion
479
560
  const deleteBulk = () => {
480
561
  let deleteList: any = [];
@@ -490,6 +571,7 @@ export const SolidListView = (params: SolidListViewParams) => {
490
571
  const onDeleteClose = () => {
491
572
  setDialogVisible(false);
492
573
  setSelectedRecords([]);
574
+ setSelectedRecoverRecords([]);
493
575
  }
494
576
 
495
577
  // Render columns dynamically based on metadata
@@ -542,6 +624,7 @@ export const SolidListView = (params: SolidListViewParams) => {
542
624
  return (
543
625
  <>
544
626
  <div className="page-header">
627
+ <Toast ref={toast} />
545
628
  <div className="flex gap-3 align-items-center">
546
629
 
547
630
 
@@ -566,7 +649,7 @@ export const SolidListView = (params: SolidListViewParams) => {
566
649
  }
567
650
 
568
651
  {solidListViewMetaData?.data?.solidView?.layout?.attrs?.enableGlobalSearch === true && params.embeded === false &&
569
- <SolidGlobalSearchElement ref={solidGlobalSearchElementRef} viewData={solidListViewMetaData} handleApplyCustomFilter={handleApplyCustomFilter} ></SolidGlobalSearchElement>
652
+ <SolidGlobalSearchElement ref={solidGlobalSearchElementRef} viewData={solidListViewMetaData} handleApplyCustomFilter={handleApplyCustomFilter} setShowArchived={setShowArchived} showArchived={showArchived}></SolidGlobalSearchElement>
570
653
  }
571
654
  </div>
572
655
  <div className="flex align-items-center gap-3">
@@ -580,6 +663,9 @@ export const SolidListView = (params: SolidListViewParams) => {
580
663
  onClick={() => params.handlePopUpOpen(true)}
581
664
  ></Button>
582
665
  }
666
+ {showArchived && <Button type="button" icon="pi pi-refresh" label="Recover" size='small' severity="warning"
667
+ onClick={() => setRecoverDialogVisible(true)}
668
+ ></Button>}
583
669
  <SolidLayoutViews
584
670
  sizeOptions={sizeOptions}
585
671
  setSize={setSize}
@@ -596,10 +682,13 @@ export const SolidListView = (params: SolidListViewParams) => {
596
682
  } */}
597
683
  </div>
598
684
  </div>
599
- <style>{`.p-datatable .p-datatable-loading-overlay {background-color: rgba(0, 0, 0, 0.0);}`}</style>
685
+ <style>{`.p-datatable .p-datatable-loading-overlay {background-color: rgba(0, 0, 0, 0.0);} .greyed-out-row { background-color: #f5f5f5 !important; color: #a0a0a0 !important; opacity: 0.6;}`}</style>
600
686
  <div className="solid-datatable-wrapper">
601
687
  <DataTable
602
688
  value={listViewData}
689
+ rowClassName={(rowData) => {
690
+ return rowData.deletedAt ? "greyed-out-row" : "";
691
+ }}
603
692
  showGridlines={false}
604
693
  lazy
605
694
  scrollable
@@ -620,7 +709,7 @@ export const SolidListView = (params: SolidListViewParams) => {
620
709
  sortOrder={sortOrder === 1 || sortOrder === -1 ? sortOrder : 0}
621
710
  loading={loading || isLoading}
622
711
  loadingIcon="pi pi-spinner"
623
- selection={selectedRecords}
712
+ selection={[...selectedRecords, ...selectedRecoverRecords]}
624
713
  onSelectionChange={onSelectionChange}
625
714
  selectionMode="multiple"
626
715
  removableSort
@@ -635,7 +724,14 @@ export const SolidListView = (params: SolidListViewParams) => {
635
724
 
636
725
  {renderColumnsDynamically(listViewMetaData)}
637
726
  {actionsAllowed.includes(`${updatePermission(params.modelName)}`) && solidListViewMetaData?.data?.solidView?.layout?.attrs?.edit !== false &&
638
- <Column body={detailsBodyTemplate} ></Column>
727
+ <Column body={(rowData) => (
728
+ rowData.deletedAt ? (
729
+ <a onClick={() => recoverById(rowData.id)} className="retrieve-button">
730
+ <i className="pi pi-refresh" style={{ fontSize: "1rem" }}/>
731
+ </a>
732
+ ) :
733
+ detailsBodyTemplate(rowData)
734
+ )}></Column>
639
735
  }
640
736
  {solidListViewMetaData?.data?.solidView?.layout?.attrs?.rowButtons &&
641
737
  solidListViewMetaData?.data?.solidView?.layout?.attrs?.rowButtons.map((rowAction: any) => {
@@ -678,6 +774,20 @@ export const SolidListView = (params: SolidListViewParams) => {
678
774
  <p>Are you sure you want to delete the selected records?</p>
679
775
  </Dialog>
680
776
 
777
+ <Dialog
778
+ visible={isRecoverDialogVisible}
779
+ header="Confirm Recover"
780
+ modal
781
+ footer={() => (
782
+ <div className="flex justify-content-center">
783
+ <Button label="Yes" icon="pi pi-check" className='small-button' severity="danger" autoFocus onClick={recoverAll} />
784
+ <Button label="No" icon="pi pi-times" className='small-button' onClick={() => setRecoverDialogVisible(false)} />
785
+ </div>
786
+ )}
787
+ onHide={() => setRecoverDialogVisible(false)}
788
+ >
789
+ <p>Are you sure you want to recover all records?</p>
790
+ </Dialog>
681
791
 
682
792
  {listViewRowActionData &&
683
793
  <Dialog
@@ -2622,9 +2622,10 @@ const FieldMetaDataForm = ({ modelMetaData, fieldMetaData, setFieldMetaData, all
2622
2622
  )}
2623
2623
  </div>
2624
2624
  )}
2625
- {currentFields.includes("isSystem") && (
2626
- <div className="field col-6 flex-flex-column gap-2 mt-3">
2627
- <div className="flex align-items-center gap-2">
2625
+ {/* {currentFields.includes("isSystem") && (
2626
+ <div className="md:col-6 sm:col-12">
2627
+ <div className="field">
2628
+ <div className="flex align-items-center">
2628
2629
  <Checkbox
2629
2630
  name="isSystem"
2630
2631
  onChange={(e) => {
@@ -2643,7 +2644,8 @@ const FieldMetaDataForm = ({ modelMetaData, fieldMetaData, setFieldMetaData, all
2643
2644
  />
2644
2645
  )}
2645
2646
  </div>
2646
- )}
2647
+ </div>
2648
+ )} */}
2647
2649
  {currentFields.includes("isUserKey") && (
2648
2650
  <div className="field col-6 flex-flex-column gap-2 mt-3">
2649
2651
  <div className="flex align-items-center gap-2">
@@ -4,6 +4,7 @@ import { getSingularAndPlural } from "@/helpers/helpers";
4
4
  import { useGetFieldDefaultMetaDataQuery } from "@/redux/api/fieldApi";
5
5
  import { useLazyGetmodulesQuery } from "@/redux/api/moduleApi";
6
6
  import { useFormik } from "formik";
7
+ import { snakeCase } from "lodash";
7
8
  import { usePathname, useRouter } from "next/navigation";
8
9
  import { Checkbox } from "primereact/checkbox";
9
10
  import { Divider } from "primereact/divider";
@@ -107,6 +108,7 @@ const ModelMetaData = React.forwardRef(({ modelMetaData, setModelMetaData, allMo
107
108
  enableReinitialize: true,
108
109
  innerRef: formikModelMetadataRef,
109
110
  onSubmit: async (values) => {
111
+ const tableName = generateTableName(values.module.displayName, values.singularName);
110
112
  try {
111
113
  const modelData = {
112
114
  ...modelMetaData,
@@ -116,7 +118,7 @@ const ModelMetaData = React.forwardRef(({ modelMetaData, setModelMetaData, allMo
116
118
  description: values.description,
117
119
  dataSource: values.dataSource,
118
120
  dataSourceType: values.dataSourceType,
119
- tableName: showTableName === true ? values?.tableName : null,
121
+ tableName: showTableName === true ? values?.tableName : tableName,
120
122
  moduleId: values.moduleId,
121
123
  module: values.module,
122
124
  isSystem: values.isSystem ? values.isSystem === true : '',
@@ -124,7 +126,6 @@ const ModelMetaData = React.forwardRef(({ modelMetaData, setModelMetaData, allMo
124
126
  enableAuditTracking: values.enableAuditTracking === true ? true : '',
125
127
  internationalisation: values.internationalisation === true ? true : '',
126
128
  };
127
-
128
129
  setModelMetaData(modelData);
129
130
  nextTab()
130
131
 
@@ -134,6 +135,12 @@ const ModelMetaData = React.forwardRef(({ modelMetaData, setModelMetaData, allMo
134
135
  },
135
136
  });
136
137
 
138
+ function generateTableName(moduleSlug: string, modelName: string): string {
139
+ const snakeCaseModelName = snakeCase(modelName);
140
+ const sankeCaseModuleName = snakeCase(moduleSlug);
141
+ return `${sankeCaseModuleName}_${snakeCaseModelName}`;
142
+ }
143
+
137
144
  const showError = async () => {
138
145
  const errors = await formik.validateForm(); // Trigger validation and get the updated errors
139
146
  const errorMessages = Object.values(errors);
@@ -588,7 +595,7 @@ const ModelMetaData = React.forwardRef(({ modelMetaData, setModelMetaData, allMo
588
595
  }
589
596
  }
590
597
 
591
- }} checked={showTableName}></Checkbox>
598
+ }} checked={showTableName} disabled={params.id !== 'new'}></Checkbox>
592
599
  <label htmlFor="ingredient1" className="form-field-label">
593
600
  Set table name
594
601
  </label>
@@ -10,8 +10,11 @@ import { LayoutConfig } from "@/types";
10
10
  import { toggleTheme } from "@/redux/features/themeSlice";
11
11
  import { InputSwitch } from "primereact/inputswitch";
12
12
  import { Button } from "primereact/button";
13
+ import { useRouter } from "next/navigation";
13
14
 
14
15
  const UserProfileMenu = () => {
16
+ const router = useRouter();
17
+
15
18
  // const { user } = useAppSelector((state) => state.auth);
16
19
  const { changeTheme } = useContext(PrimeReactContext);
17
20
  const { layoutConfig, setLayoutConfig } = useContext(LayoutContext);
@@ -76,7 +79,9 @@ const UserProfileMenu = () => {
76
79
  </div>
77
80
  <InputSwitch checked={checked} onChange={handleThemeToggle} />
78
81
  </div>
79
-
82
+ <div className="p-2">
83
+ <Button icon="pi pi-cog" label="General Settings" size="small" text severity="secondary" className="w-full text-left gap-2" onClick={()=>router.push("/admin/settings") }/>
84
+ </div>
80
85
  <div className="user-profile-body p-3">
81
86
  <Button
82
87
  text
package/src/index.ts CHANGED
@@ -592,6 +592,7 @@ export { default as popupReducer } from '@/redux/features/popupSlice';
592
592
  export { default as themeReducer } from '@/redux/features/themeSlice';
593
593
  export { default as userReducer } from '@/redux/features/userSlice';
594
594
 
595
+ export {default as GenerateModelCodeRowAction } from '@/components/core/extension/solid-core/modelMetadata/list/GenerateModelCodeRowAction'
595
596
 
596
597
  // types
597
598
  export type { LayoutConfig } from '@/types';
@@ -69,6 +69,17 @@ export const createSolidEntityApi = (entityName: string) => {
69
69
  method: 'DELETE',
70
70
  }),
71
71
  }),
72
+ recoverSolidEntityById: builder.query({
73
+ query: (id) => `/${kebabEntityName}/recover/${id}`,
74
+ }),
75
+ recoverSolidEntity: builder.mutation({
76
+ query: (data) => ({
77
+ url: `/${kebabEntityName}/bulk-recover/`,
78
+ method: 'POST',
79
+ body: data
80
+ })
81
+
82
+ }),
72
83
  }),
73
84
  });
74
85
  };
@@ -19,7 +19,7 @@ export const solidSettingsApi = createApi({
19
19
  }),
20
20
  getAuthSettings: builder.query({
21
21
  query: () => {
22
- return `/setting/getSettings`
22
+ return `/setting/wrapped`
23
23
  },
24
24
  }),
25
25
  getSolidSettingsById: builder.query({