@visns-studio/visns-components 5.11.21 → 5.12.0

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 (159) hide show
  1. package/package.json +5 -5
  2. package/src/components/{crm/Autocomplete.jsx → Autocomplete.jsx} +1 -1
  3. package/src/components/{crm/BusinessCardOcr.jsx → BusinessCardOcr.jsx} +1 -1
  4. package/src/components/{crm/DataGrid.jsx → DataGrid.jsx} +57 -9
  5. package/src/components/{crm/Download.jsx → Download.jsx} +1 -1
  6. package/src/components/{cms/DropZone.jsx → DropZone.jsx} +1 -1
  7. package/src/components/{crm/Field.jsx → Field.jsx} +2 -2
  8. package/src/components/{crm/Form.jsx → Form.jsx} +65 -30
  9. package/src/components/{crm/auth → auth}/ClientLogin.jsx +2 -2
  10. package/src/components/{crm/auth → auth}/ClientOTPVerify.jsx +2 -2
  11. package/src/components/{crm/auth → auth}/Login.jsx +2 -2
  12. package/src/components/{crm/auth → auth}/Profile.jsx +3 -3
  13. package/src/components/{crm/auth → auth}/Reset.jsx +2 -2
  14. package/src/components/{crm/auth → auth}/TwoFactorAuth.jsx +2 -2
  15. package/src/components/{crm/auth → auth}/Verify.jsx +2 -2
  16. package/src/components/{crm/client → client}/ClientDashboard.jsx +1 -1
  17. package/src/components/{crm/client → client}/ClientPortal.jsx +1 -1
  18. package/src/components/{crm/columns → columns}/ColumnRenderers.jsx +31 -20
  19. package/src/components/{crm/generic → generic}/ActionButtons.jsx +1 -1
  20. package/src/components/{crm/generic → generic}/AlternativeActionModal.jsx +2 -2
  21. package/src/components/{crm/generic → generic}/AuditLog.jsx +1 -1
  22. package/src/components/{crm/generic → generic}/AuditLogs.jsx +1 -1
  23. package/src/components/{cms/generic → generic}/CmsDetail.jsx +2 -2
  24. package/src/components/{cms/generic → generic}/CmsSort.jsx +1 -1
  25. package/src/components/{crm/generic → generic}/ConfirmationDialog.jsx +1 -1
  26. package/src/components/{crm/generic → generic}/ContactSelectorModal.jsx +2 -2
  27. package/src/components/{crm/generic → generic}/DatePickerDialog.jsx +2 -2
  28. package/src/components/{crm/generic → generic}/DateRangeSelectorModal.jsx +2 -2
  29. package/src/components/{crm/generic → generic}/GenericClientPortal.jsx +1 -1
  30. package/src/components/{crm/generic → generic}/GenericDashboard.jsx +4 -4
  31. package/src/components/{crm/generic → generic}/GenericDetail.jsx +5 -5
  32. package/src/components/{crm/generic → generic}/GenericDynamic.jsx +1 -1
  33. package/src/components/{crm/generic → generic}/GenericEditableTable.jsx +1 -1
  34. package/src/components/{crm/generic → generic}/GenericFormBuilder.jsx +2 -2
  35. package/src/components/{crm/generic → generic}/GenericGrid.jsx +2 -2
  36. package/src/components/{crm/generic → generic}/GenericIndex.jsx +2 -2
  37. package/src/components/{crm/generic → generic}/GenericMain.jsx +2 -2
  38. package/src/components/{crm/generic → generic}/GenericQuote.jsx +4 -4
  39. package/src/components/{crm/generic → generic}/GenericReport.jsx +2 -2
  40. package/src/components/{crm/generic → generic}/GenericReportForm.jsx +1 -1
  41. package/src/components/{crm/generic → generic}/GenericSort.jsx +2 -2
  42. package/src/components/{crm/generic → generic}/NotificationList.jsx +1 -1
  43. package/src/components/{crm/generic → generic}/ReasonCollectorModal.jsx +2 -2
  44. package/src/components/{crm/generic → generic}/SortableQuoteItems.jsx +1 -1
  45. package/src/components/proposal/SectionEditor.jsx +1 -1
  46. package/src/components/{crm/sorting → sorting}/Item.jsx +1 -1
  47. package/src/components/{crm/sorting → sorting}/List.jsx +1 -1
  48. package/src/index.js +57 -59
  49. package/src/utils/{ConfirmDialog.js → ConfirmDialog.jsx} +1 -1
  50. package/src/components/cms/DataGrid.jsx +0 -1652
  51. package/src/components/cms/Field.jsx +0 -802
  52. package/src/components/cms/Form.jsx +0 -475
  53. package/src/components/cms/sorting/Item.jsx +0 -121
  54. package/src/components/cms/sorting/List.jsx +0 -32
  55. package/src/components/cms/sorting/styles/Item.module.scss +0 -38
  56. package/src/components/crm/sorting/styles/List.module.scss +0 -74
  57. /package/src/components/{crm/AssociationManager.jsx → AssociationManager.jsx} +0 -0
  58. /package/src/components/{crm/AsyncSelect.jsx → AsyncSelect.jsx} +0 -0
  59. /package/src/components/{crm/Breadcrumb.jsx → Breadcrumb.jsx} +0 -0
  60. /package/src/components/{crm/Call.jsx → Call.jsx} +0 -0
  61. /package/src/components/{crm/ClientAssociationManager.jsx → ClientAssociationManager.jsx} +0 -0
  62. /package/src/components/{crm/Fetch.jsx → Fetch.jsx} +0 -0
  63. /package/src/components/{cms/Gallery.jsx → Gallery.jsx} +0 -0
  64. /package/src/components/{crm/Loader.jsx → Loader.jsx} +0 -0
  65. /package/src/components/{crm/MergeEntity.jsx → MergeEntity.jsx} +0 -0
  66. /package/src/components/{crm/MultiSelect.jsx → MultiSelect.jsx} +0 -0
  67. /package/src/components/{crm/Navigation.jsx → Navigation.jsx} +0 -0
  68. /package/src/components/{crm/Notification.jsx → Notification.jsx} +0 -0
  69. /package/src/components/{crm/QrCode.jsx → QrCode.jsx} +0 -0
  70. /package/src/components/{crm/QuickAction.jsx → QuickAction.jsx} +0 -0
  71. /package/src/components/{crm/SectionHeader.jsx → SectionHeader.jsx} +0 -0
  72. /package/src/components/{crm/Select.jsx → Select.jsx} +0 -0
  73. /package/src/components/{crm/SelectList.jsx → SelectList.jsx} +0 -0
  74. /package/src/components/{crm/SwitchAccount.jsx → SwitchAccount.jsx} +0 -0
  75. /package/src/components/{crm/TableFilter.jsx → TableFilter.jsx} +0 -0
  76. /package/src/components/{crm/cells → cells}/CellWithTooltip.jsx +0 -0
  77. /package/src/components/{crm/controls → controls}/AudioPlayer.jsx +0 -0
  78. /package/src/components/{crm/controls → controls}/AutoRefreshControls.jsx +0 -0
  79. /package/src/components/{crm/controls → controls}/DataGridSearch.jsx +0 -0
  80. /package/src/components/{crm/examples → examples}/FilterExample.jsx +0 -0
  81. /package/src/components/{crm/examples → examples}/FormStylingGuide.md +0 -0
  82. /package/src/components/{crm/examples → examples}/FormWithSectionHeaders.jsx +0 -0
  83. /package/src/components/{crm/examples → examples}/README.md +0 -0
  84. /package/src/components/{cms/generic → generic}/CmsIndex.jsx +0 -0
  85. /package/src/components/{crm/generic → generic}/GenericAuth.jsx +0 -0
  86. /package/src/components/{crm/generic → generic}/shared/formatters.js +0 -0
  87. /package/src/components/{crm/generic → generic}/shared/gridUtils.js +0 -0
  88. /package/src/components/{crm/generic → generic}/utils/formatters.js +0 -0
  89. /package/src/components/{crm/modals → modals}/GalleryModal.jsx +0 -0
  90. /package/src/components/{crm/sketch → sketch}/SketchField.jsx +0 -0
  91. /package/src/components/{crm/sketch → sketch}/arrow.jsx +0 -0
  92. /package/src/components/{crm/sketch → sketch}/circle.jsx +0 -0
  93. /package/src/components/{crm/sketch → sketch}/default-tool.jsx +0 -0
  94. /package/src/components/{crm/sketch → sketch}/fabrictool.jsx +0 -0
  95. /package/src/components/{crm/sketch → sketch}/history.jsx +0 -0
  96. /package/src/components/{crm/sketch → sketch}/json/config.json +0 -0
  97. /package/src/components/{crm/sketch → sketch}/line.jsx +0 -0
  98. /package/src/components/{crm/sketch → sketch}/pan.jsx +0 -0
  99. /package/src/components/{crm/sketch → sketch}/pencil.jsx +0 -0
  100. /package/src/components/{crm/sketch → sketch}/rectangle-label-object.jsx +0 -0
  101. /package/src/components/{crm/sketch → sketch}/rectangle-label.jsx +0 -0
  102. /package/src/components/{crm/sketch → sketch}/rectangle.jsx +0 -0
  103. /package/src/components/{crm/sketch → sketch}/select.jsx +0 -0
  104. /package/src/components/{crm/sketch → sketch}/tools.jsx +0 -0
  105. /package/src/components/{crm/sketch → sketch}/utils.jsx +0 -0
  106. /package/src/components/{crm/generic/styles → styles}/ActionButtons.module.scss +0 -0
  107. /package/src/components/{crm/generic/styles → styles}/AlternativeActionModal.css +0 -0
  108. /package/src/components/{crm/styles → styles}/AssociationManager.module.scss +0 -0
  109. /package/src/components/{crm/styles → styles}/AsyncSelect.module.scss +0 -0
  110. /package/src/components/{crm/generic/styles → styles}/AuditLog.module.scss +0 -0
  111. /package/src/components/{crm/generic/styles → styles}/AuditLogs.module.scss +0 -0
  112. /package/src/components/{crm/auth/styles → styles}/AuthForm.module.scss +0 -0
  113. /package/src/components/{crm/styles → styles}/Autocomplete.module.scss +0 -0
  114. /package/src/components/{crm/styles → styles}/BusinessCardOcr.module.scss +0 -0
  115. /package/src/components/{crm/styles → styles}/ClientAssociationManager.module.scss +0 -0
  116. /package/src/components/{crm/auth/styles → styles}/ClientAuth.module.scss +0 -0
  117. /package/src/components/{crm/client/styles → styles}/ClientDashboard.module.scss +0 -0
  118. /package/src/components/{crm/client/styles → styles}/ClientPortal.module.scss +0 -0
  119. /package/src/components/{crm/generic/styles → styles}/ContactSelectorModal.css +0 -0
  120. /package/src/components/{crm/styles → styles}/DataGrid.module.scss +0 -0
  121. /package/src/components/{crm/generic/styles → styles}/DatePickerDialog.css +0 -0
  122. /package/src/components/{crm/generic/styles → styles}/DateRangeSelectorModal.css +0 -0
  123. /package/src/components/{cms/styles → styles}/DropZone.module.css +0 -0
  124. /package/src/components/{crm/styles → styles}/Field.module.scss +0 -0
  125. /package/src/components/{crm/styles → styles}/Form.module.scss +0 -0
  126. /package/src/components/{cms/styles → styles}/Gallery.module.css +0 -0
  127. /package/src/components/{crm/generic/styles → styles}/GenericClientPortal.module.scss +0 -0
  128. /package/src/components/{crm/generic/styles → styles}/GenericDashboard.module.scss +0 -0
  129. /package/src/components/{crm/generic/styles → styles}/GenericDetail.module.scss +0 -0
  130. /package/src/components/{crm/generic/styles → styles}/GenericDynamic.module.scss +0 -0
  131. /package/src/components/{crm/generic/styles → styles}/GenericEditableTable.module.scss +0 -0
  132. /package/src/components/{crm/generic/styles → styles}/GenericFormBuilder.module.scss +0 -0
  133. /package/src/components/{crm/generic/styles → styles}/GenericIndex.module.scss +0 -0
  134. /package/src/components/{crm/generic/styles → styles}/GenericMain.module.scss +0 -0
  135. /package/src/components/{crm/generic/styles → styles}/GenericQuote.module.scss +0 -0
  136. /package/src/components/{crm/generic/styles → styles}/GenericReport.module.scss +0 -0
  137. /package/src/components/{crm/generic/styles → styles}/GenericSort.module.scss +0 -0
  138. /package/src/components/{crm/sorting/styles → styles}/Item.module.scss +0 -0
  139. /package/src/components/{cms/sorting/styles → styles}/List.module.scss +0 -0
  140. /package/src/components/{crm/styles → styles}/Loader.module.scss +0 -0
  141. /package/src/components/{crm/auth/styles → styles}/Login.module.scss +0 -0
  142. /package/src/components/{crm/styles → styles}/MergeEntity.module.scss +0 -0
  143. /package/src/components/{crm/styles → styles}/MultiSelect.module.scss +0 -0
  144. /package/src/components/{crm/styles → styles}/Navigation.module.scss +0 -0
  145. /package/src/components/{crm/styles → styles}/Notification.module.scss +0 -0
  146. /package/src/components/{crm/generic/styles → styles}/NotificationList.module.scss +0 -0
  147. /package/src/components/{crm/auth/styles → styles}/Profile.module.scss +0 -0
  148. /package/src/components/{crm/styles → styles}/QrCode.module.scss +0 -0
  149. /package/src/components/{crm/styles → styles}/QuickAction.module.scss +0 -0
  150. /package/src/components/{crm/generic/styles → styles}/ReasonCollectorModal.css +0 -0
  151. /package/src/components/{crm/generic/styles → styles}/ReportForm.module.scss +0 -0
  152. /package/src/components/{crm/auth/styles → styles}/Reset.module.scss +0 -0
  153. /package/src/components/{crm/generic/styles → styles}/SortableQuoteItems.module.scss +0 -0
  154. /package/src/components/{crm/generic/styles → styles}/SweetAlert.module.css +0 -0
  155. /package/src/components/{crm/styles → styles}/SwitchAccount.module.scss +0 -0
  156. /package/src/components/{crm/styles → styles}/TableFilter.module.scss +0 -0
  157. /package/src/components/{crm/auth/styles → styles}/TwoFactorAuth.module.scss +0 -0
  158. /package/src/components/{crm/auth/styles → styles}/Verify.module.scss +0 -0
  159. /package/src/components/{crm/styles → styles}/global-datagrid.css +0 -0
package/package.json CHANGED
@@ -14,8 +14,8 @@
14
14
  "@tinymce/miniature": "^6.0.0",
15
15
  "@tinymce/tinymce-react": "^6.2.1",
16
16
  "@uiw/react-color": "^2.6.0",
17
- "@visns-studio/visns-datagrid-community": "^1.0.14",
18
- "@visns-studio/visns-datagrid-enterprise": "^1.0.14",
17
+ "@visns-studio/visns-datagrid-community": "^1.0.23",
18
+ "@visns-studio/visns-datagrid-enterprise": "^1.0.23",
19
19
  "@vitejs/plugin-react": "^4.6.0",
20
20
  "add": "^2.0.6",
21
21
  "array-move": "^4.0.0",
@@ -24,13 +24,13 @@
24
24
  "dayjs": "^1.11.13",
25
25
  "fabric": "^6.7.0",
26
26
  "file-saver": "^2.0.5",
27
- "framer-motion": "^12.19.1",
27
+ "framer-motion": "^12.19.2",
28
28
  "html-react-parser": "^5.2.5",
29
29
  "lodash": "^4.17.21",
30
30
  "lodash.debounce": "^4.0.8",
31
31
  "lucide-react": "^0.518.0",
32
32
  "moment": "^2.30.1",
33
- "motion": "^12.19.1",
33
+ "motion": "^12.19.2",
34
34
  "numeral": "^2.0.6",
35
35
  "pluralize": "^8.0.0",
36
36
  "qrcode.react": "^4.2.0",
@@ -87,7 +87,7 @@
87
87
  "react-dom": "^17.0.0 || ^18.0.0"
88
88
  },
89
89
  "name": "@visns-studio/visns-components",
90
- "version": "5.11.21",
90
+ "version": "5.12.0",
91
91
  "description": "Various packages to assist in the development of our Custom Applications.",
92
92
  "main": "src/index.js",
93
93
  "files": [
@@ -2,7 +2,7 @@ import { useState, useEffect, useCallback, useMemo, memo, useRef } from 'react';
2
2
  import AwesomeDebouncePromise from 'awesome-debounce-promise';
3
3
  import { ToggleLeft, ToggleRight, Search } from 'lucide-react';
4
4
  import styles from './styles/Autocomplete.module.scss';
5
- import fetchUtil from '../../utils/fetchUtil';
5
+ import fetchUtil from '../utils/fetchUtil';
6
6
 
7
7
  // Create the debounced function outside the component to prevent recreation
8
8
  const createDebouncedSearch = (fn) =>
@@ -1,4 +1,4 @@
1
- import '../styles/global.css';
1
+ import './styles/global.css';
2
2
 
3
3
  import { useState, useRef, useCallback, useEffect } from 'react';
4
4
  import { motion } from 'framer-motion';
@@ -1,4 +1,4 @@
1
- import '../styles/global.css';
1
+ import './styles/global.css';
2
2
  import './styles/global-datagrid.css';
3
3
 
4
4
  /**
@@ -39,10 +39,10 @@ import SelectFilter from '@visns-studio/visns-datagrid-enterprise/SelectFilter';
39
39
  import DateFilter from '@visns-studio/visns-datagrid-enterprise/DateFilter';
40
40
  import ReactDataGrid from '@visns-studio/visns-datagrid-enterprise';
41
41
  import { toast } from 'react-toastify';
42
- import fetchUtil from '../../utils/fetchUtil';
42
+ import fetchUtil from '../utils/fetchUtil';
43
43
  import { confirmDialog } from '../utils/ConfirmDialog';
44
- import { DEFAULT_INTELLIGENT_SORTING_CONFIG } from '../../utils/relationshipSortingUtils';
45
- import { extractColumnsMetadata, isColumnSortable } from '../../utils/columnsMetadataUtils';
44
+ import { DEFAULT_INTELLIGENT_SORTING_CONFIG } from '../utils/relationshipSortingUtils';
45
+ import { extractColumnsMetadata, isColumnSortable } from '../utils/columnsMetadataUtils';
46
46
  import {
47
47
  AlarmClock,
48
48
  RotateCcw,
@@ -275,6 +275,8 @@ const DataGrid = forwardRef(
275
275
  const [formType, setFormType] = useState('');
276
276
  const [formId, setFormId] = useState(0);
277
277
  const [modalShow, setModalShow] = useState(false);
278
+ const [bulkEditMode, setBulkEditMode] = useState(false);
279
+ const [bulkEditGroupData, setBulkEditGroupData] = useState(null);
278
280
 
279
281
  /** Modal Functions */
280
282
  const modalOpen = (formType, formId) => {
@@ -285,6 +287,8 @@ const DataGrid = forwardRef(
285
287
 
286
288
  const modalClose = () => {
287
289
  setModalShow(false);
290
+ setBulkEditMode(false);
291
+ setBulkEditGroupData(null);
288
292
  };
289
293
 
290
294
  useEffect(() => {
@@ -1209,7 +1213,13 @@ const DataGrid = forwardRef(
1209
1213
  // Get all rows for this group
1210
1214
  const groupRows = getGroupRows(groupValue);
1211
1215
 
1212
- // Show confirmation dialog to prevent accidental clicks
1216
+ // Skip confirmation dialog for edit actions - open modal directly
1217
+ if (iconConfig.id === 'edit' && iconConfig.formModal) {
1218
+ executeGroupAction(groupValue, iconConfig);
1219
+ return;
1220
+ }
1221
+
1222
+ // Show confirmation dialog for other actions to prevent accidental clicks
1213
1223
  const confirmMessage = `Are you sure you want to perform "${iconConfig.label}" action on group "${groupValue}" (${groupRows.length} rows)?`;
1214
1224
 
1215
1225
  confirmDialog({
@@ -1310,7 +1320,10 @@ const DataGrid = forwardRef(
1310
1320
  }
1311
1321
  } else {
1312
1322
  // Fallback to existing switch logic if no fetch config
1313
- toast.info(`${iconConfig.label} - Group: ${groupValue}`);
1323
+ // Skip toast notification for edit actions
1324
+ if (iconConfig.id !== 'edit') {
1325
+ toast.info(`${iconConfig.label} - Group: ${groupValue}`);
1326
+ }
1314
1327
 
1315
1328
  switch (iconConfig.id) {
1316
1329
  case 'clock':
@@ -1329,9 +1342,28 @@ const DataGrid = forwardRef(
1329
1342
  );
1330
1343
  break;
1331
1344
  case 'edit':
1332
- console.log(
1333
- `Bulk edit action for group: ${groupValue}`
1334
- );
1345
+ // Handle bulk edit action
1346
+ if (iconConfig.formModal) {
1347
+ // Get all rows in the group for bulk editing
1348
+ const groupRows = getGroupRows(groupValue);
1349
+ const groupRowIds = groupRows.map(row => row[form?.primaryKey || 'id']);
1350
+
1351
+ // Set bulk edit data
1352
+ setBulkEditMode(true);
1353
+ setBulkEditGroupData({
1354
+ groupValue: groupValue,
1355
+ groupRows: groupRows,
1356
+ groupRowIds: groupRowIds,
1357
+ iconConfig: iconConfig
1358
+ });
1359
+
1360
+ // Open modal for bulk editing
1361
+ modalOpen('update', null);
1362
+ } else {
1363
+ console.log(
1364
+ `Bulk edit action for group: ${groupValue}`
1365
+ );
1366
+ }
1335
1367
  break;
1336
1368
  case 'envelope':
1337
1369
  console.log(
@@ -2449,7 +2481,21 @@ const DataGrid = forwardRef(
2449
2481
  ? column.filter.placeholder
2450
2482
  : 'All Options',
2451
2483
  dataSource: selectedDataSource,
2484
+ searchable: column.filter.searchable !== false,
2485
+ // Enable clear functionality even when searchable is false
2486
+ allowClearWhenNotSearchable: column.filter.searchable === false,
2487
+ // Explicitly enable clear icon
2488
+ clearIcon: true,
2452
2489
  };
2490
+
2491
+ // Debug: Check if fix is applied
2492
+ if (column.filter.searchable === false) {
2493
+ console.log('Filter Debug - searchable=false:', {
2494
+ columnName: column.name || 'unknown',
2495
+ props: filterEditorProps,
2496
+ visnsDataGridVersion: 'v1.0.18'
2497
+ });
2498
+ }
2453
2499
  break;
2454
2500
  default:
2455
2501
  filterEditor = null;
@@ -3607,6 +3653,8 @@ const DataGrid = forwardRef(
3607
3653
  style={style}
3608
3654
  updateForm={setFormData}
3609
3655
  userProfile={userProfile}
3656
+ bulkEditMode={bulkEditMode}
3657
+ bulkEditGroupData={bulkEditGroupData}
3610
3658
  />
3611
3659
  </div>
3612
3660
  </div>
@@ -2,7 +2,7 @@ import React from 'react';
2
2
  import { trackPromise } from 'react-promise-tracker';
3
3
  import { toast } from 'react-toastify';
4
4
  import parse from 'html-react-parser';
5
- import fetchUtil from '../../utils/fetchUtil';
5
+ import fetchUtil from '../utils/fetchUtil';
6
6
 
7
7
  const CustomDownload = (
8
8
  url,
@@ -8,7 +8,7 @@ import Popup from 'reactjs-popup';
8
8
  import imageCompression from 'browser-image-compression';
9
9
 
10
10
  import { confirmDialog } from '../utils/ConfirmDialog';
11
- import CustomFetch from '../crm/Fetch';
11
+ import CustomFetch from './Fetch';
12
12
  import Gallery from './Gallery';
13
13
  import styles from './styles/DropZone.module.css';
14
14
 
@@ -1,4 +1,4 @@
1
- import '../styles/global.css';
1
+ import './styles/global.css';
2
2
 
3
3
  import React, { useEffect, useRef, useState, useMemo } from 'react';
4
4
  import DatePicker from 'react-datepicker';
@@ -36,7 +36,7 @@ import SketchField from './sketch/SketchField';
36
36
  import Tools from './sketch/tools';
37
37
  import VisnsAsyncSelect from './AsyncSelect';
38
38
  import VisnsAutocomplete from './Autocomplete';
39
- import VisnsDropZone from '../cms/DropZone';
39
+ import VisnsDropZone from './DropZone';
40
40
 
41
41
  import 'react-toggle/style.css';
42
42
  import 'react-datepicker/dist/react-datepicker.css';
@@ -1,4 +1,4 @@
1
- import '../styles/global.css';
1
+ import './styles/global.css';
2
2
 
3
3
  import React, { useState, useEffect, useRef, useCallback } from 'react';
4
4
  import { useNavigate } from 'react-router-dom';
@@ -80,6 +80,8 @@ function Form({
80
80
  type,
81
81
  updateForm,
82
82
  userProfile,
83
+ bulkEditMode = false,
84
+ bulkEditGroupData = null,
83
85
  }) {
84
86
  const navigate = useNavigate();
85
87
  const [fetchTrigger, setFetchTrigger] = useState(false);
@@ -888,34 +890,42 @@ function Form({
888
890
  }
889
891
  method = formSettings.customMethod;
890
892
  } else {
891
- switch (formType) {
892
- case 'create':
893
- if (formSettings.json) {
894
- url += '/json/store';
895
- }
896
- break;
897
- case 'update':
898
- case 'delete':
899
- if (formSettings.json) {
900
- url +=
893
+ // Check if this is bulk edit mode
894
+ if (bulkEditMode && bulkEditGroupData?.iconConfig?.formModal) {
895
+ // Use bulk edit endpoint configuration
896
+ const formModalConfig = bulkEditGroupData.iconConfig.formModal;
897
+ url = formModalConfig.url || url;
898
+ method = formModalConfig.method || 'POST';
899
+ } else {
900
+ switch (formType) {
901
+ case 'create':
902
+ if (formSettings.json) {
903
+ url += '/json/store';
904
+ }
905
+ break;
906
+ case 'update':
907
+ case 'delete':
908
+ if (formSettings.json) {
909
+ url +=
910
+ formType === 'update'
911
+ ? '/json/update'
912
+ : `/json/delete/${
913
+ formData[
914
+ formSettings
915
+ .primaryKey
916
+ ]
917
+ }`;
918
+ } else {
919
+ url += `/${
920
+ formData[formSettings.primaryKey]
921
+ }`;
922
+ }
923
+ method =
901
924
  formType === 'update'
902
- ? '/json/update'
903
- : `/json/delete/${
904
- formData[
905
- formSettings
906
- .primaryKey
907
- ]
908
- }`;
909
- } else {
910
- url += `/${
911
- formData[formSettings.primaryKey]
912
- }`;
913
- }
914
- method =
915
- formType === 'update'
916
- ? 'PUT'
917
- : 'DELETE';
918
- break;
925
+ ? 'PUT'
926
+ : 'DELETE';
927
+ break;
928
+ }
919
929
  }
920
930
  }
921
931
 
@@ -1046,7 +1056,7 @@ function Form({
1046
1056
  }
1047
1057
 
1048
1058
  // Transform keys with dots into nested objects
1049
- const payload = Object.keys(updatedFormData).reduce(
1059
+ let payload = Object.keys(updatedFormData).reduce(
1050
1060
  (acc, key) => {
1051
1061
  if (key.includes('.')) {
1052
1062
  const [root, sub] = key.split('.');
@@ -1060,6 +1070,18 @@ function Form({
1060
1070
  {}
1061
1071
  );
1062
1072
 
1073
+ // Add bulk edit data to payload if in bulk edit mode
1074
+ if (bulkEditMode && bulkEditGroupData) {
1075
+ payload = {
1076
+ ...payload,
1077
+ bulkEdit: true,
1078
+ groupValue: bulkEditGroupData.groupValue,
1079
+ groupKey: bulkEditGroupData.iconConfig.formModal?.groupKey || ajaxSetting?.groupBy?.[0],
1080
+ rowIds: bulkEditGroupData.groupRowIds,
1081
+ ...bulkEditGroupData.iconConfig.formModal?.data
1082
+ };
1083
+ }
1084
+
1063
1085
  const res = await CustomFetch(url, method, payload);
1064
1086
 
1065
1087
  if (res.data.error === '') {
@@ -2233,7 +2255,12 @@ function Form({
2233
2255
  <div className={styles.modalwrap}>
2234
2256
  <div className={styles.modal}>
2235
2257
  <div className={styles.modal__header}>
2236
- <h1>{formSettings[formType]?.title}</h1>
2258
+ <h1>
2259
+ {bulkEditMode && bulkEditGroupData
2260
+ ? `${bulkEditGroupData.iconConfig.formModal?.title || 'Bulk Edit'} - ${bulkEditGroupData.groupValue} (${bulkEditGroupData.groupRows.length} items)`
2261
+ : formSettings[formType]?.title
2262
+ }
2263
+ </h1>
2237
2264
  <button
2238
2265
  className={styles.modal__close}
2239
2266
  onClick={closeModal}
@@ -2265,6 +2292,14 @@ function Form({
2265
2292
  ) {
2266
2293
  return null;
2267
2294
  }
2295
+ // In bulk edit mode, only show fields specified in the formModal configuration
2296
+ if (
2297
+ bulkEditMode &&
2298
+ bulkEditGroupData?.iconConfig?.formModal?.fields &&
2299
+ !bulkEditGroupData.iconConfig.formModal.fields.includes(item.id)
2300
+ ) {
2301
+ return null;
2302
+ }
2268
2303
 
2269
2304
  return (
2270
2305
  <Field
@@ -1,4 +1,4 @@
1
- import '../../styles/global.css';
1
+ import '../styles/global.css';
2
2
 
3
3
  import React, { useState } from 'react';
4
4
  import { useLocation, useNavigate } from 'react-router-dom';
@@ -7,7 +7,7 @@ import { User } from 'lucide-react';
7
7
 
8
8
  import CustomFetch from '../Fetch';
9
9
 
10
- import styles from './styles/ClientAuth.module.scss';
10
+ import styles from '../styles/ClientAuth.module.scss';
11
11
 
12
12
  const ClientLogin = ({ logo, setSystemAuth, urls = {} }) => {
13
13
  const location = useLocation();
@@ -1,4 +1,4 @@
1
- import '../../styles/global.css';
1
+ import '../styles/global.css';
2
2
 
3
3
  import React, { useState, useEffect } from 'react';
4
4
  import { useNavigate, useLocation } from 'react-router-dom';
@@ -7,7 +7,7 @@ import { Lock, ArrowLeft } from 'lucide-react';
7
7
 
8
8
  import CustomFetch from '../Fetch';
9
9
 
10
- import styles from './styles/ClientAuth.module.scss';
10
+ import styles from '../styles/ClientAuth.module.scss';
11
11
 
12
12
  const ClientOTPVerify = ({
13
13
  logo,
@@ -1,4 +1,4 @@
1
- import '../../styles/global.css';
1
+ import '../styles/global.css';
2
2
 
3
3
  import React, { useState } from 'react';
4
4
  import { Link, useLocation, useNavigate } from 'react-router-dom';
@@ -8,7 +8,7 @@ import { User, Lock } from 'lucide-react';
8
8
 
9
9
  import CustomFetch from '../Fetch';
10
10
 
11
- import styles from './styles/Login.module.scss';
11
+ import styles from '../styles/Login.module.scss';
12
12
 
13
13
  const Login = ({ logo, providers, setSystemAuth, setUserProfile }) => {
14
14
  const location = useLocation();
@@ -1,5 +1,5 @@
1
- // src/components/crm/auth/Profile.jsx
2
- import '../../styles/global.css';
1
+ // src/components/auth/Profile.jsx
2
+ import '../styles/global.css';
3
3
 
4
4
  import React, { useState, useEffect, useRef, useCallback, memo } from 'react';
5
5
  import { useLocation } from 'react-router-dom';
@@ -9,7 +9,7 @@ import SignaturePad from 'react-signature-pad-wrapper';
9
9
  import Swal from 'sweetalert2';
10
10
  import CustomFetch from '../Fetch';
11
11
  import TableFilter from '../TableFilter';
12
- import styles from './styles/Profile.module.scss';
12
+ import styles from '../styles/Profile.module.scss';
13
13
 
14
14
  // Form field component to reduce repetition
15
15
  const FormField = memo(
@@ -1,4 +1,4 @@
1
- import '../../styles/global.css';
1
+ import '../styles/global.css';
2
2
 
3
3
  import React, { useState } from 'react';
4
4
  import Reveal from 'react-reveal/Reveal';
@@ -8,7 +8,7 @@ import { User } from 'lucide-react';
8
8
 
9
9
  import CustomFetch from '../Fetch';
10
10
 
11
- import styles from './styles/Reset.module.scss';
11
+ import styles from '../styles/Reset.module.scss';
12
12
 
13
13
  const Reset = ({ logo }) => {
14
14
  const [email, setEmail] = useState('');
@@ -1,4 +1,4 @@
1
- import '../../styles/global.css';
1
+ import '../styles/global.css';
2
2
 
3
3
  import React, { useState, useEffect } from 'react';
4
4
  import { useNavigate, useLocation } from 'react-router-dom';
@@ -8,7 +8,7 @@ import { Lock } from 'lucide-react';
8
8
 
9
9
  import CustomFetch from '../Fetch';
10
10
 
11
- import styles from './styles/TwoFactorAuth.module.scss';
11
+ import styles from '../styles/TwoFactorAuth.module.scss';
12
12
 
13
13
  const TwoFactorAuth = ({ logo, setSystemAuth, setUserProfile }) => {
14
14
  const navigate = useNavigate();
@@ -1,4 +1,4 @@
1
- import '../../styles/global.css';
1
+ import '../styles/global.css';
2
2
 
3
3
  import React, { useState } from 'react';
4
4
  import { useNavigate, useParams } from 'react-router-dom';
@@ -9,7 +9,7 @@ import Reveal from 'react-reveal/Reveal';
9
9
 
10
10
  import CustomFetch from '../Fetch';
11
11
 
12
- import styles from './styles/Verify.module.scss';
12
+ import styles from '../styles/Verify.module.scss';
13
13
 
14
14
  const Verify = ({ logo }) => {
15
15
  const navigate = useNavigate();
@@ -1,6 +1,6 @@
1
1
  import React from 'react';
2
2
 
3
- import styles from './styles/ClientDashboard.module.scss';
3
+ import styles from '../styles/ClientDashboard.module.scss';
4
4
 
5
5
  /**
6
6
  * ClientDashboard - Example dashboard component for client portal
@@ -4,7 +4,7 @@ import { toast } from 'react-toastify';
4
4
 
5
5
  import CustomFetch from '../Fetch';
6
6
 
7
- import styles from './styles/ClientPortal.module.scss';
7
+ import styles from '../styles/ClientPortal.module.scss';
8
8
 
9
9
  const ClientPortal = ({
10
10
  clientProfile,
@@ -8,7 +8,7 @@ import {
8
8
  isRelationshipColumnSortable,
9
9
  getRelationshipPath,
10
10
  DEFAULT_INTELLIGENT_SORTING_CONFIG,
11
- } from '../../../utils/relationshipSortingUtils';
11
+ } from '../../utils/relationshipSortingUtils';
12
12
 
13
13
  // Boolean Column Renderer
14
14
  export const renderBooleanColumn = ({
@@ -135,11 +135,11 @@ export const renderDateTimeColumn = ({
135
135
  moment(data[column.id]).format('YYYY-MM-DD') !== '1970-01-01'
136
136
  ) {
137
137
  let dateValue = moment(data[column.id]);
138
-
138
+
139
139
  // Apply modifier if present
140
140
  if (column.modifier) {
141
141
  const { operator, value, unit } = column.modifier;
142
-
142
+
143
143
  if (operator === '+') {
144
144
  dateValue = dateValue.add(value, unit);
145
145
  } else if (operator === '-') {
@@ -1453,16 +1453,22 @@ export const renderGalleryColumn = ({
1453
1453
  : data[column.id];
1454
1454
 
1455
1455
  // Check if we have valid image data
1456
- if (!imagesArray || !Array.isArray(imagesArray) || imagesArray.length === 0) {
1456
+ if (
1457
+ !imagesArray ||
1458
+ !Array.isArray(imagesArray) ||
1459
+ imagesArray.length === 0
1460
+ ) {
1457
1461
  return (
1458
- <div style={{
1459
- display: 'flex',
1460
- alignItems: 'center',
1461
- justifyContent: 'center',
1462
- height: '40px',
1463
- color: '#999',
1464
- fontSize: '12px'
1465
- }}>
1462
+ <div
1463
+ style={{
1464
+ display: 'flex',
1465
+ alignItems: 'center',
1466
+ justifyContent: 'center',
1467
+ height: '40px',
1468
+ color: '#999',
1469
+ fontSize: '12px',
1470
+ }}
1471
+ >
1466
1472
  No images
1467
1473
  </div>
1468
1474
  );
@@ -1486,13 +1492,13 @@ export const renderGalleryColumn = ({
1486
1492
 
1487
1493
  // Set gallery data and current item
1488
1494
  setGalleryData(galleryData);
1489
- setCurrentItem({
1490
- data: data,
1495
+ setCurrentItem({
1496
+ data: data,
1491
1497
  settings: {
1492
1498
  relation: column.relation,
1493
1499
  key: column.key,
1494
- captionKey: column.captionKey || 'file_name'
1495
- }
1500
+ captionKey: column.captionKey || 'file_name',
1501
+ },
1496
1502
  });
1497
1503
 
1498
1504
  // Open the gallery modal
@@ -1533,7 +1539,7 @@ export const renderGalleryColumn = ({
1533
1539
  {displayImages.map((image, index) => {
1534
1540
  const imageUrl = image[column.key];
1535
1541
  if (!imageUrl) return null;
1536
-
1542
+
1537
1543
  return (
1538
1544
  <div
1539
1545
  key={index}
@@ -1548,7 +1554,11 @@ export const renderGalleryColumn = ({
1548
1554
  >
1549
1555
  <img
1550
1556
  src={imageUrl}
1551
- alt={image[column.captionKey || 'file_name'] || `Image ${index + 1}`}
1557
+ alt={
1558
+ image[
1559
+ column.captionKey || 'file_name'
1560
+ ] || `Image ${index + 1}`
1561
+ }
1552
1562
  style={{
1553
1563
  width: '100%',
1554
1564
  height: '100%',
@@ -1562,7 +1572,7 @@ export const renderGalleryColumn = ({
1562
1572
  );
1563
1573
  })}
1564
1574
  </div>
1565
-
1575
+
1566
1576
  {/* Count badge */}
1567
1577
  <div
1568
1578
  style={{
@@ -1572,7 +1582,8 @@ export const renderGalleryColumn = ({
1572
1582
  lineHeight: '1.2',
1573
1583
  }}
1574
1584
  >
1575
- {imagesArray.length} {imagesArray.length === 1 ? 'image' : 'images'}
1585
+ {imagesArray.length}{' '}
1586
+ {imagesArray.length === 1 ? 'image' : 'images'}
1576
1587
  {remainingCount > 0 && ` (+${remainingCount})`}
1577
1588
  </div>
1578
1589
  </div>
@@ -1,5 +1,5 @@
1
1
  import React from 'react';
2
- import styles from './styles/ActionButtons.module.scss';
2
+ import styles from '../styles/ActionButtons.module.scss';
3
3
 
4
4
  function ActionButtons({ actions, onActionClick }) {
5
5
  return (
@@ -1,6 +1,6 @@
1
1
  import Swal from 'sweetalert2';
2
- import './styles/SweetAlert.module.css';
3
- import './styles/AlternativeActionModal.css';
2
+ import '../styles/SweetAlert.module.css';
3
+ import '../styles/AlternativeActionModal.css';
4
4
 
5
5
  /**
6
6
  * Show an alternative action modal for choosing between different workflows
@@ -3,7 +3,7 @@ import { useParams } from 'react-router-dom';
3
3
  import dayjs from 'dayjs';
4
4
  import Breadcrumb from '../Breadcrumb';
5
5
  import CustomFetch from '../Fetch';
6
- import styles from './styles/AuditLog.module.scss';
6
+ import styles from '../styles/AuditLog.module.scss';
7
7
 
8
8
  const AuditLog = ({ userProfile }) => {
9
9
  const routeParams = useParams();
@@ -1,6 +1,6 @@
1
1
  import React from 'react';
2
2
  import Table from '../DataGrid';
3
- import styles from './styles/AuditLogs.module.scss';
3
+ import styles from '../styles/AuditLogs.module.scss';
4
4
 
5
5
  const AuditLogs = ({ layout }) => {
6
6
  const setting = {