@visns-studio/visns-components 4.7.0 → 4.7.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/104e5636d8ddb791614c.woff2 +0 -0
- package/dist/11fe6a83d647de5daf95.woff +0 -0
- package/dist/141e2a8c7836495afe2a.woff +0 -0
- package/dist/2ba5877f7079830b5383.woff +0 -0
- package/dist/2d6836f45b2037be41f3.woff +0 -0
- package/dist/399.0a0f3e0d21be1057d599.css +8 -0
- package/dist/399.b8f57fa3f8c0c10119e4.js +1 -0
- package/dist/47d566c3b1293dfd9d77.woff +0 -0
- package/dist/6282a13cbba671a71913.woff2 +0 -0
- package/dist/78266f551031aa9db127.woff +0 -0
- package/dist/7b7da89f1e3fdcbfe36c.woff2 +0 -0
- package/dist/7e78e8338af7efeda712.woff2 +0 -0
- package/dist/7fa387951673abf164b1.woff2 +0 -0
- package/dist/819d59862c2d0640aad8.woff +0 -0
- package/dist/b615e1a6c838ea059a56.woff +0 -0
- package/dist/b9b1aa739c660c4ce67c.woff2 +0 -0
- package/dist/c5f3640b11df9414facb.woff +0 -0
- package/dist/da26d162ff5af71d6590.woff2 +0 -0
- package/dist/dd5b2912dbf896310865.woff2 +0 -0
- package/dist/f282b331272463c1aa6c.woff2 +0 -0
- package/dist/index.css +2902 -0
- package/dist/index.js +2 -0
- package/dist/index.js.LICENSE.txt +150 -0
- package/dist/main.83b033670d64419bb497.css +1 -0
- package/dist/main.b1723d17cd2d3513ab62.js +1 -0
- package/dist/report.html +39 -0
- package/dist/runtime.33c276593b23f8035b8d.js +1 -0
- package/package.json +26 -6
- package/.idea/codeStyles/Project.xml +0 -50
- package/.idea/codeStyles/codeStyleConfig.xml +0 -5
- package/.idea/deployment.xml +0 -4
- package/.idea/modules.xml +0 -8
- package/.idea/php.xml +0 -19
- package/.idea/vcs.xml +0 -6
- package/.idea/visns-components.iml +0 -8
- package/.prettierrc.json +0 -7
- package/.yarn/plugins/@yarnpkg/plugin-interactive-tools.cjs +0 -541
- package/.yarn/releases/yarn-3.6.1.cjs +0 -874
- package/.yarnrc.yml +0 -7
- package/components/cms/DataGrid.jsx +0 -1461
- package/components/cms/DropZone.jsx +0 -349
- package/components/cms/Field.jsx +0 -802
- package/components/cms/Form.jsx +0 -476
- package/components/cms/generic/CmsDetail.jsx +0 -36
- package/components/cms/generic/CmsIndex.jsx +0 -73
- package/components/cms/generic/CmsSort.jsx +0 -125
- package/components/cms/sorting/Item.jsx +0 -115
- package/components/cms/sorting/List.jsx +0 -30
- package/components/crm/AsyncSelect.jsx +0 -125
- package/components/crm/Autocomplete.jsx +0 -174
- package/components/crm/Breadcrumb.jsx +0 -52
- package/components/crm/Call.jsx +0 -220
- package/components/crm/DataGrid.jsx +0 -2701
- package/components/crm/Download.jsx +0 -101
- package/components/crm/Fetch.jsx +0 -119
- package/components/crm/Field.jsx +0 -1557
- package/components/crm/Form.jsx +0 -1409
- package/components/crm/Loader.jsx +0 -29
- package/components/crm/MultiSelect.jsx +0 -78
- package/components/crm/Navigation.jsx +0 -619
- package/components/crm/Notification.jsx +0 -197
- package/components/crm/QrCode.jsx +0 -83
- package/components/crm/Select.jsx +0 -58
- package/components/crm/SelectList.jsx +0 -21
- package/components/crm/TableFilter.jsx +0 -198
- package/components/crm/auth/Login.jsx +0 -223
- package/components/crm/auth/Profile.jsx +0 -280
- package/components/crm/auth/Reset.jsx +0 -111
- package/components/crm/auth/Verify.jsx +0 -174
- package/components/crm/auth/styles/Login.module.css +0 -243
- package/components/crm/auth/styles/Profile.module.css +0 -222
- package/components/crm/auth/styles/Reset.module.css +0 -216
- package/components/crm/auth/styles/Verify.module.css +0 -216
- package/components/crm/generic/AuditLog.jsx +0 -108
- package/components/crm/generic/AuditLogs.jsx +0 -115
- package/components/crm/generic/GenericAuth.jsx +0 -166
- package/components/crm/generic/GenericDashboard.jsx +0 -42
- package/components/crm/generic/GenericDetail.jsx +0 -1499
- package/components/crm/generic/GenericDynamic.jsx +0 -915
- package/components/crm/generic/GenericFormBuilder.jsx +0 -1765
- package/components/crm/generic/GenericIndex.jsx +0 -376
- package/components/crm/generic/GenericMain.jsx +0 -129
- package/components/crm/generic/GenericSort.jsx +0 -188
- package/components/crm/generic/NotificationList.jsx +0 -64
- package/components/crm/generic/styles/AuditLog.module.css +0 -147
- package/components/crm/generic/styles/AuditLogs.module.css +0 -92
- package/components/crm/generic/styles/GenericDetail.module.css +0 -634
- package/components/crm/generic/styles/GenericDynamic.module.css +0 -932
- package/components/crm/generic/styles/GenericFormBuilder.module.css +0 -944
- package/components/crm/generic/styles/GenericIndex.module.css +0 -247
- package/components/crm/generic/styles/GenericMain.module.css +0 -91
- package/components/crm/generic/styles/GenericSort.module.css +0 -123
- package/components/crm/generic/styles/NotificationList.module.css +0 -67
- package/components/crm/sorting/Item.jsx +0 -117
- package/components/crm/sorting/List.jsx +0 -32
- package/components/crm/sorting/styles/Item.module.css +0 -68
- package/components/crm/sorting/styles/List.module.css +0 -68
- package/components/crm/styles/AsyncSelect.module.css +0 -8
- package/components/crm/styles/Autocomplete.module.css +0 -44
- package/components/crm/styles/DataGrid.module.css +0 -210
- package/components/crm/styles/Field.module.css +0 -311
- package/components/crm/styles/Form.module.css +0 -499
- package/components/crm/styles/Loader.module.css +0 -94
- package/components/crm/styles/MultiSelect.module.css +0 -8
- package/components/crm/styles/Navigation.module.css +0 -978
- package/components/crm/styles/Notification.module.css +0 -147
- package/components/crm/styles/QrCode.module.css +0 -87
- package/components/crm/styles/TableFilter.module.css +0 -52
- package/components/styles/global.css +0 -73
- package/index.js +0 -86
|
@@ -1,376 +0,0 @@
|
|
|
1
|
-
import '../../styles/global.css';
|
|
2
|
-
|
|
3
|
-
import React, { useCallback, useEffect, useRef, useState } from 'react';
|
|
4
|
-
import { Outlet } from 'react-router-dom';
|
|
5
|
-
import { toast } from 'react-toastify';
|
|
6
|
-
import { saveAs } from 'file-saver';
|
|
7
|
-
import _ from 'lodash';
|
|
8
|
-
|
|
9
|
-
import CustomFetch from '../Fetch';
|
|
10
|
-
import Download from '../Download';
|
|
11
|
-
import Field from '../Field';
|
|
12
|
-
import Table from '../DataGrid';
|
|
13
|
-
import TableFilter from '../TableFilter';
|
|
14
|
-
|
|
15
|
-
import styles from './styles/GenericIndex.module.css';
|
|
16
|
-
|
|
17
|
-
function useWindowHeight() {
|
|
18
|
-
const [windowHeight, setWindowHeight] = useState(window.innerHeight);
|
|
19
|
-
|
|
20
|
-
useEffect(() => {
|
|
21
|
-
const handleResize = () => setWindowHeight(window.innerHeight);
|
|
22
|
-
window.addEventListener('resize', handleResize);
|
|
23
|
-
return () => window.removeEventListener('resize', handleResize);
|
|
24
|
-
}, []);
|
|
25
|
-
|
|
26
|
-
return windowHeight;
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
function useConfig(setting, tabs, filters, setRowsSelected, tableSetting) {
|
|
30
|
-
const [config, setConfig] = useState({});
|
|
31
|
-
const [subnav, setSubnav] = useState(filters || []);
|
|
32
|
-
|
|
33
|
-
useEffect(() => {
|
|
34
|
-
setConfig({
|
|
35
|
-
ajaxSetting: setting.ajaxSetting,
|
|
36
|
-
form: setting.form,
|
|
37
|
-
columns: setting.columns,
|
|
38
|
-
setRowsSelected,
|
|
39
|
-
settings: setting.settings,
|
|
40
|
-
tableSetting,
|
|
41
|
-
type: setting.type ? setting.type : 'table',
|
|
42
|
-
});
|
|
43
|
-
setSubnav(filters);
|
|
44
|
-
}, [setting, filters, setRowsSelected, tableSetting]);
|
|
45
|
-
|
|
46
|
-
useEffect(() => {
|
|
47
|
-
if (tabs?.length > 0 && subnav) {
|
|
48
|
-
const activeTab = subnav.find((s) => s.show);
|
|
49
|
-
const activeTabConfig = tabs.find((t) => t.id === activeTab?.id);
|
|
50
|
-
|
|
51
|
-
if (activeTabConfig) {
|
|
52
|
-
setConfig((currentConfig) => ({
|
|
53
|
-
...currentConfig,
|
|
54
|
-
id: activeTabConfig.id,
|
|
55
|
-
ajaxSetting: activeTabConfig.ajaxSetting,
|
|
56
|
-
form: activeTabConfig.form,
|
|
57
|
-
columns: activeTabConfig.columns,
|
|
58
|
-
settings: activeTabConfig.settings,
|
|
59
|
-
type: activeTabConfig.type ? activeTabConfig.type : 'table',
|
|
60
|
-
}));
|
|
61
|
-
}
|
|
62
|
-
}
|
|
63
|
-
}, [subnav, tabs]);
|
|
64
|
-
|
|
65
|
-
return { config, setConfig, subnav, setSubnav };
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
const ReportForm = ({ config, userProfile }) => {
|
|
69
|
-
const [formData, setFormData] = useState({});
|
|
70
|
-
|
|
71
|
-
const handleChange = (e) => {
|
|
72
|
-
const {
|
|
73
|
-
value,
|
|
74
|
-
dataset: { name },
|
|
75
|
-
} = e.target;
|
|
76
|
-
|
|
77
|
-
setFormData((prevData) => ({ ...prevData, [name]: value }));
|
|
78
|
-
};
|
|
79
|
-
|
|
80
|
-
const handleChangeDate = (date, id) => {
|
|
81
|
-
setFormData((prevData) => ({ ...prevData, [id]: date }));
|
|
82
|
-
};
|
|
83
|
-
|
|
84
|
-
const handleChangeSelect = (inputValue, action, id) => {
|
|
85
|
-
setFormData((prevData) => ({ ...prevData, [id]: inputValue }));
|
|
86
|
-
};
|
|
87
|
-
|
|
88
|
-
const handleExport = async (e) => {
|
|
89
|
-
try {
|
|
90
|
-
if (e) {
|
|
91
|
-
e.preventDefault();
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
const missingFields = config.form.filters
|
|
95
|
-
.filter(
|
|
96
|
-
(item) => item.required === true && formData[item.id] === ''
|
|
97
|
-
)
|
|
98
|
-
.map((item) => item.label);
|
|
99
|
-
|
|
100
|
-
if (missingFields.length > 0) {
|
|
101
|
-
const fieldNames = missingFields.join(', ');
|
|
102
|
-
const errorMessage = `Please fill in a value for the following field(s): ${fieldNames}.`;
|
|
103
|
-
toast.error(errorMessage);
|
|
104
|
-
} else {
|
|
105
|
-
const res = await Download(
|
|
106
|
-
config.form.url,
|
|
107
|
-
config.form.method,
|
|
108
|
-
formData
|
|
109
|
-
);
|
|
110
|
-
|
|
111
|
-
if (res.data.error) {
|
|
112
|
-
toast.error(res.data.error);
|
|
113
|
-
} else {
|
|
114
|
-
// Assuming the response contains a Blob or similar data
|
|
115
|
-
if (res.data && res.data instanceof Blob) {
|
|
116
|
-
const fileName = `${config.form.filename}`;
|
|
117
|
-
saveAs(res.data, fileName);
|
|
118
|
-
} else {
|
|
119
|
-
// Handle the case where the response is not a Blob
|
|
120
|
-
toast.error('Invalid file format received.');
|
|
121
|
-
}
|
|
122
|
-
}
|
|
123
|
-
}
|
|
124
|
-
} catch (err) {
|
|
125
|
-
console.error(err);
|
|
126
|
-
}
|
|
127
|
-
};
|
|
128
|
-
|
|
129
|
-
useEffect(() => {
|
|
130
|
-
const tmpForm = config.form?.filters.reduce((acc, item) => {
|
|
131
|
-
acc[item.id] = '';
|
|
132
|
-
return acc;
|
|
133
|
-
}, {});
|
|
134
|
-
setFormData(tmpForm);
|
|
135
|
-
}, [config.form?.filters]);
|
|
136
|
-
|
|
137
|
-
return (
|
|
138
|
-
<div className="formcontainer">
|
|
139
|
-
<form className="modalForm">
|
|
140
|
-
{config.form?.filters.map((item, key) => (
|
|
141
|
-
<Field
|
|
142
|
-
api={userProfile.settings.api}
|
|
143
|
-
autocompleteCallback={() => {}}
|
|
144
|
-
childDropdownCallback={() => {}}
|
|
145
|
-
fetchData={() => {}}
|
|
146
|
-
formData={formData}
|
|
147
|
-
inputClass={''}
|
|
148
|
-
inputValue={formData[item.id]}
|
|
149
|
-
key={`filter-fields-${key}`}
|
|
150
|
-
mapbox={{}}
|
|
151
|
-
onChange={handleChange}
|
|
152
|
-
onChangeCheckbox={() => {}}
|
|
153
|
-
onChangeDate={handleChangeDate}
|
|
154
|
-
onChangeNumberFormat={() => {}}
|
|
155
|
-
onChangeRicheditor={() => {}}
|
|
156
|
-
onChangeSelect={handleChangeSelect}
|
|
157
|
-
onChangeToggle={() => {}}
|
|
158
|
-
settings={item}
|
|
159
|
-
setFormData={setFormData}
|
|
160
|
-
style={userProfile.settings.style}
|
|
161
|
-
uploadProgress={0}
|
|
162
|
-
userProfile={userProfile}
|
|
163
|
-
/>
|
|
164
|
-
))}
|
|
165
|
-
<div className="formItem fwItem lastItem">
|
|
166
|
-
<button className="btn modalsave" onClick={handleExport}>
|
|
167
|
-
Export
|
|
168
|
-
</button>
|
|
169
|
-
</div>
|
|
170
|
-
</form>
|
|
171
|
-
</div>
|
|
172
|
-
);
|
|
173
|
-
};
|
|
174
|
-
|
|
175
|
-
function GenericIndex({ layout = 'full', setting, userProfile }) {
|
|
176
|
-
const gridRef = useRef(null);
|
|
177
|
-
const [rowsSelected, setRowsSelected] = useState({});
|
|
178
|
-
const [total, setTotal] = useState(0);
|
|
179
|
-
const windowHeight = useWindowHeight();
|
|
180
|
-
const { config, setConfig, subnav, setSubnav } = useConfig(
|
|
181
|
-
setting,
|
|
182
|
-
setting.tabs,
|
|
183
|
-
setting.filters,
|
|
184
|
-
setRowsSelected,
|
|
185
|
-
setting.tableSetting
|
|
186
|
-
);
|
|
187
|
-
|
|
188
|
-
const handleCheckboxUpdate = useCallback(async () => {
|
|
189
|
-
try {
|
|
190
|
-
const { data, method, message, url } = setting?.functions
|
|
191
|
-
?.checkboxUpdate
|
|
192
|
-
? setting.functions.checkboxUpdate
|
|
193
|
-
: config.form.functions.checkboxUpdate;
|
|
194
|
-
if (!Object.keys(rowsSelected).length) {
|
|
195
|
-
toast.warning(message.warning);
|
|
196
|
-
return;
|
|
197
|
-
}
|
|
198
|
-
const res = await CustomFetch(url, method, {
|
|
199
|
-
...data,
|
|
200
|
-
rows: rowsSelected,
|
|
201
|
-
});
|
|
202
|
-
if (res.data.error === '') {
|
|
203
|
-
toast.success(message.success);
|
|
204
|
-
gridRef.current.reload();
|
|
205
|
-
} else {
|
|
206
|
-
toast.error(message.error);
|
|
207
|
-
}
|
|
208
|
-
} catch (error) {
|
|
209
|
-
console.error(error);
|
|
210
|
-
}
|
|
211
|
-
}, [rowsSelected, setting?.functions?.checkboxUpdate]);
|
|
212
|
-
|
|
213
|
-
const renderTable = useCallback(() => {
|
|
214
|
-
const isConfigValid = (config) => {
|
|
215
|
-
return (
|
|
216
|
-
config.ajaxSetting &&
|
|
217
|
-
config.form &&
|
|
218
|
-
config.columns &&
|
|
219
|
-
config.settings
|
|
220
|
-
);
|
|
221
|
-
};
|
|
222
|
-
|
|
223
|
-
const renderTableComponent = () => (
|
|
224
|
-
<Table
|
|
225
|
-
{...config}
|
|
226
|
-
ref={gridRef}
|
|
227
|
-
gridHeight={windowHeight * 0.65}
|
|
228
|
-
setConfig={setConfig}
|
|
229
|
-
setTotal={setTotal}
|
|
230
|
-
style={userProfile?.settings?.style || {}}
|
|
231
|
-
userProfile={userProfile}
|
|
232
|
-
/>
|
|
233
|
-
);
|
|
234
|
-
|
|
235
|
-
if (subnav) {
|
|
236
|
-
// Find the active subnav item with show: true
|
|
237
|
-
const activeSubnav = subnav.find((item) => item.show === true);
|
|
238
|
-
|
|
239
|
-
// Check if the config.id matches the active subnav id
|
|
240
|
-
if (
|
|
241
|
-
activeSubnav &&
|
|
242
|
-
activeSubnav.id === config.id &&
|
|
243
|
-
isConfigValid(config)
|
|
244
|
-
) {
|
|
245
|
-
return renderTableComponent();
|
|
246
|
-
}
|
|
247
|
-
|
|
248
|
-
// Check for active alternative subnav
|
|
249
|
-
const activeAltSubNav = subnav.find(
|
|
250
|
-
(item) =>
|
|
251
|
-
item.class === 'subactive' || item.class === 'activetab'
|
|
252
|
-
);
|
|
253
|
-
|
|
254
|
-
const activeTabExist =
|
|
255
|
-
config.ajaxSetting?.where?.some(
|
|
256
|
-
(w) =>
|
|
257
|
-
w.id === activeAltSubNav?.id &&
|
|
258
|
-
parseInt(w.value) === parseInt(activeAltSubNav?.value)
|
|
259
|
-
) || false;
|
|
260
|
-
|
|
261
|
-
if (isConfigValid(config) && activeTabExist) {
|
|
262
|
-
return renderTableComponent();
|
|
263
|
-
}
|
|
264
|
-
} else if (isConfigValid(config)) {
|
|
265
|
-
return renderTableComponent();
|
|
266
|
-
}
|
|
267
|
-
|
|
268
|
-
return null;
|
|
269
|
-
}, [config, subnav, windowHeight, userProfile, setConfig, setTotal]);
|
|
270
|
-
|
|
271
|
-
const renderContentBasedOnType = useCallback(() => {
|
|
272
|
-
switch (config.type) {
|
|
273
|
-
case 'table':
|
|
274
|
-
return renderTable();
|
|
275
|
-
case 'report':
|
|
276
|
-
return <ReportForm config={config} userProfile={userProfile} />;
|
|
277
|
-
default:
|
|
278
|
-
return renderTable(); // Fallback to table if no type is specified or recognized
|
|
279
|
-
}
|
|
280
|
-
}, [config, renderTable]);
|
|
281
|
-
|
|
282
|
-
const renderContent = useCallback(() => {
|
|
283
|
-
if (subnav?.length > 0) {
|
|
284
|
-
return (
|
|
285
|
-
<div className={styles.grid__subrow}>
|
|
286
|
-
{layout === 'simple' ? (
|
|
287
|
-
<div className={styles.grid__full}>
|
|
288
|
-
<div className={styles.tabcontent}>
|
|
289
|
-
<div className={styles.tabcontent__menu}>
|
|
290
|
-
<TableFilter
|
|
291
|
-
filters={subnav}
|
|
292
|
-
setFilters={setSubnav}
|
|
293
|
-
setSettings={setConfig}
|
|
294
|
-
type={layout}
|
|
295
|
-
/>
|
|
296
|
-
</div>
|
|
297
|
-
<div className={styles.tabcontent__main}>
|
|
298
|
-
{renderContentBasedOnType()}
|
|
299
|
-
</div>
|
|
300
|
-
</div>
|
|
301
|
-
</div>
|
|
302
|
-
) : (
|
|
303
|
-
<>
|
|
304
|
-
<div className={styles.grid__subnav}>
|
|
305
|
-
<TableFilter
|
|
306
|
-
filters={subnav}
|
|
307
|
-
setFilters={setSubnav}
|
|
308
|
-
setSettings={setConfig}
|
|
309
|
-
type={layout}
|
|
310
|
-
/>
|
|
311
|
-
</div>
|
|
312
|
-
<div className={styles.grid__subcontent}>
|
|
313
|
-
{renderContentBasedOnType()}
|
|
314
|
-
</div>
|
|
315
|
-
</>
|
|
316
|
-
)}
|
|
317
|
-
</div>
|
|
318
|
-
);
|
|
319
|
-
} else {
|
|
320
|
-
return (
|
|
321
|
-
<div className={styles.grid__full}>
|
|
322
|
-
{renderContentBasedOnType()}
|
|
323
|
-
</div>
|
|
324
|
-
);
|
|
325
|
-
}
|
|
326
|
-
}, [layout, subnav, setSubnav, setConfig, renderTable]);
|
|
327
|
-
|
|
328
|
-
return (
|
|
329
|
-
<>
|
|
330
|
-
<div className={styles.grid}>
|
|
331
|
-
<div className={styles.grid__row}>
|
|
332
|
-
<div
|
|
333
|
-
className={`${styles.grid__full} ${
|
|
334
|
-
layout === 'full'
|
|
335
|
-
? styles.crmtitle
|
|
336
|
-
: styles.crmtitleSimple
|
|
337
|
-
}`}
|
|
338
|
-
>
|
|
339
|
-
<h1>{setting.page?.title}</h1>
|
|
340
|
-
<div className={styles.titleInfo}>
|
|
341
|
-
<span>
|
|
342
|
-
[<strong>{total}</strong> Total{' '}
|
|
343
|
-
{setting.page?.title}]
|
|
344
|
-
</span>
|
|
345
|
-
</div>
|
|
346
|
-
</div>
|
|
347
|
-
</div>
|
|
348
|
-
</div>
|
|
349
|
-
|
|
350
|
-
<div className={styles.grid}>{renderContent()}</div>
|
|
351
|
-
<Outlet />
|
|
352
|
-
{setting.functions?.checkboxUpdate && (
|
|
353
|
-
<div className={styles.polActions}>
|
|
354
|
-
<button
|
|
355
|
-
className={styles.btn}
|
|
356
|
-
onClick={handleCheckboxUpdate}
|
|
357
|
-
>
|
|
358
|
-
{setting.functions.checkboxUpdate.label || 'Update'}
|
|
359
|
-
</button>
|
|
360
|
-
</div>
|
|
361
|
-
)}
|
|
362
|
-
{config?.form?.functions?.checkboxUpdate && (
|
|
363
|
-
<div className={styles.polActions}>
|
|
364
|
-
<button
|
|
365
|
-
className={styles.btn}
|
|
366
|
-
onClick={handleCheckboxUpdate}
|
|
367
|
-
>
|
|
368
|
-
{config.form.functions.checkboxUpdate.label || 'Update'}
|
|
369
|
-
</button>
|
|
370
|
-
</div>
|
|
371
|
-
)}
|
|
372
|
-
</>
|
|
373
|
-
);
|
|
374
|
-
}
|
|
375
|
-
|
|
376
|
-
export default GenericIndex;
|
|
@@ -1,129 +0,0 @@
|
|
|
1
|
-
import '../../styles/global.css';
|
|
2
|
-
|
|
3
|
-
import React, { useState } from 'react';
|
|
4
|
-
import { Routes, Route, Navigate } from 'react-router-dom';
|
|
5
|
-
|
|
6
|
-
import Call from '../Call';
|
|
7
|
-
import Loader from '../Loader';
|
|
8
|
-
import Navigation from '../Navigation';
|
|
9
|
-
|
|
10
|
-
import styles from './styles/GenericMain.module.css';
|
|
11
|
-
|
|
12
|
-
const GenericMain = ({
|
|
13
|
-
layout = 'full',
|
|
14
|
-
logo,
|
|
15
|
-
navigation,
|
|
16
|
-
routeConfig,
|
|
17
|
-
setSystemAuth,
|
|
18
|
-
setUserProfile,
|
|
19
|
-
themeType,
|
|
20
|
-
userProfile,
|
|
21
|
-
}) => {
|
|
22
|
-
const [incomingCallData, setIncomingCallData] = useState({});
|
|
23
|
-
|
|
24
|
-
// Function to extract route parameters
|
|
25
|
-
const extractRouteParams = (path) => {
|
|
26
|
-
const params = path.match(/:\w+/g) || [];
|
|
27
|
-
return params.map((param) => param.substring(1));
|
|
28
|
-
};
|
|
29
|
-
|
|
30
|
-
// Recursive function to render routes
|
|
31
|
-
const renderRoutes = (routes) => {
|
|
32
|
-
return routes.map((route, index) => {
|
|
33
|
-
let elementProps = {
|
|
34
|
-
userProfile: userProfile,
|
|
35
|
-
setUserProfile: setUserProfile,
|
|
36
|
-
};
|
|
37
|
-
|
|
38
|
-
const routeParams = extractRouteParams(route.path);
|
|
39
|
-
const extraParams = routeParams.filter(
|
|
40
|
-
(param) => param !== 'dataId'
|
|
41
|
-
);
|
|
42
|
-
|
|
43
|
-
if (routeParams.includes('dataId')) {
|
|
44
|
-
elementProps.urlParam = 'dataId';
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
if (extraParams.length > 0) {
|
|
48
|
-
elementProps.extraUrlParam = extraParams;
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
let element = route.element
|
|
52
|
-
? React.cloneElement(route.element, elementProps)
|
|
53
|
-
: null;
|
|
54
|
-
|
|
55
|
-
if (route.children && route.children.length > 0) {
|
|
56
|
-
// If the route has children, render them recursively
|
|
57
|
-
return (
|
|
58
|
-
<Route key={index} path={route.path}>
|
|
59
|
-
{renderRoutes(route.children)}
|
|
60
|
-
</Route>
|
|
61
|
-
);
|
|
62
|
-
} else {
|
|
63
|
-
return (
|
|
64
|
-
<Route key={index} path={route.path} element={element} />
|
|
65
|
-
);
|
|
66
|
-
}
|
|
67
|
-
});
|
|
68
|
-
};
|
|
69
|
-
|
|
70
|
-
return layout === 'full' ? (
|
|
71
|
-
<div>
|
|
72
|
-
<header
|
|
73
|
-
className={
|
|
74
|
-
themeType === 'alternate'
|
|
75
|
-
? styles.headerAlternate
|
|
76
|
-
: styles.header
|
|
77
|
-
}
|
|
78
|
-
>
|
|
79
|
-
<Navigation
|
|
80
|
-
layout={layout}
|
|
81
|
-
logo={logo}
|
|
82
|
-
navConfig={navigation}
|
|
83
|
-
setSystemAuth={setSystemAuth}
|
|
84
|
-
themeType={themeType}
|
|
85
|
-
userProfile={userProfile}
|
|
86
|
-
/>
|
|
87
|
-
</header>
|
|
88
|
-
<main className={styles.content}>
|
|
89
|
-
<div className={styles['content-main']} id="app">
|
|
90
|
-
<div className={styles.padding}>
|
|
91
|
-
<Routes>
|
|
92
|
-
{renderRoutes(routeConfig)}
|
|
93
|
-
{/* Add a wildcard route for handling unknown paths */}
|
|
94
|
-
<Route
|
|
95
|
-
path="*"
|
|
96
|
-
element={<Navigate to="/" replace />}
|
|
97
|
-
/>
|
|
98
|
-
</Routes>
|
|
99
|
-
</div>
|
|
100
|
-
<Call incomingCallData={incomingCallData} />
|
|
101
|
-
<Loader />
|
|
102
|
-
</div>
|
|
103
|
-
</main>
|
|
104
|
-
</div>
|
|
105
|
-
) : (
|
|
106
|
-
<Navigation
|
|
107
|
-
layout={layout}
|
|
108
|
-
logo={logo}
|
|
109
|
-
navConfig={navigation}
|
|
110
|
-
setSystemAuth={setSystemAuth}
|
|
111
|
-
themeType={themeType}
|
|
112
|
-
userProfile={userProfile}
|
|
113
|
-
>
|
|
114
|
-
<div className={styles['content-main']} id="app">
|
|
115
|
-
<div className={styles.paddingSimple}>
|
|
116
|
-
<Routes>
|
|
117
|
-
{renderRoutes(routeConfig)}
|
|
118
|
-
{/* Add a wildcard route for handling unknown paths */}
|
|
119
|
-
<Route path="*" element={<Navigate to="/" replace />} />
|
|
120
|
-
</Routes>
|
|
121
|
-
</div>
|
|
122
|
-
<Call incomingCallData={incomingCallData} />
|
|
123
|
-
<Loader />
|
|
124
|
-
</div>
|
|
125
|
-
</Navigation>
|
|
126
|
-
);
|
|
127
|
-
};
|
|
128
|
-
|
|
129
|
-
export default GenericMain;
|
|
@@ -1,188 +0,0 @@
|
|
|
1
|
-
import React, { useState, useEffect } from 'react';
|
|
2
|
-
import { useLocation, useParams } from 'react-router-dom';
|
|
3
|
-
import { arrayMoveImmutable } from 'array-move';
|
|
4
|
-
import { toast } from 'react-toastify';
|
|
5
|
-
import CustomFetch from '../../crm/Fetch';
|
|
6
|
-
import SortableList from '../sorting/List';
|
|
7
|
-
import Breadcrumb from '../Breadcrumb';
|
|
8
|
-
import styles from './styles/GenericSort.module.css';
|
|
9
|
-
|
|
10
|
-
// Utility function to convert camelCase to space-separated words with uppercase first letters
|
|
11
|
-
function camelCaseToUcFirst(str) {
|
|
12
|
-
return str
|
|
13
|
-
.replace(/([A-Z])/g, ' $1') // Add a space before each uppercase letter
|
|
14
|
-
.replace(/^./, function (str) {
|
|
15
|
-
return str.toUpperCase();
|
|
16
|
-
}) // Capitalize the first letter
|
|
17
|
-
.trim(); // Remove leading and trailing whitespace
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
const ChildSort = ({ item, url }) => {
|
|
21
|
-
const [data, setData] = useState(item.child);
|
|
22
|
-
|
|
23
|
-
const onSortEnd = ({ oldIndex, newIndex }) => {
|
|
24
|
-
setData((prevItem) => arrayMoveImmutable(prevItem, oldIndex, newIndex));
|
|
25
|
-
};
|
|
26
|
-
|
|
27
|
-
useEffect(() => {
|
|
28
|
-
if (data.length > 0) {
|
|
29
|
-
CustomFetch(
|
|
30
|
-
`${url}/sort_update`,
|
|
31
|
-
'POST',
|
|
32
|
-
{
|
|
33
|
-
list: data,
|
|
34
|
-
},
|
|
35
|
-
function (result) {
|
|
36
|
-
if (result.error === '') {
|
|
37
|
-
toast.success('Sort updated successfully');
|
|
38
|
-
} else {
|
|
39
|
-
toast.error(String(result.error));
|
|
40
|
-
}
|
|
41
|
-
}
|
|
42
|
-
);
|
|
43
|
-
}
|
|
44
|
-
}, [data]);
|
|
45
|
-
|
|
46
|
-
return (
|
|
47
|
-
<>
|
|
48
|
-
<h1>{item.label}</h1>
|
|
49
|
-
<SortableList
|
|
50
|
-
items={data}
|
|
51
|
-
onSortEnd={onSortEnd}
|
|
52
|
-
axis="xy"
|
|
53
|
-
helperClass="dragitem"
|
|
54
|
-
transitionDuration={250}
|
|
55
|
-
useDragHandle
|
|
56
|
-
/>
|
|
57
|
-
</>
|
|
58
|
-
);
|
|
59
|
-
};
|
|
60
|
-
|
|
61
|
-
const GenericSort = ({ category = false, layout = 'full' }) => {
|
|
62
|
-
const location = useLocation();
|
|
63
|
-
const routeParams = useParams();
|
|
64
|
-
const {
|
|
65
|
-
form,
|
|
66
|
-
page = {}, // Provide a default empty object for page
|
|
67
|
-
paramValue,
|
|
68
|
-
} = location.state || {}; // Safely access location.state
|
|
69
|
-
|
|
70
|
-
const [sortData, setSortData] = useState([]);
|
|
71
|
-
const url = form?.url;
|
|
72
|
-
const data = page?.data || {}; // Safely access data from page, default to an empty object
|
|
73
|
-
|
|
74
|
-
const onSortEnd = ({ oldIndex, newIndex }) => {
|
|
75
|
-
setSortData((prevItem) =>
|
|
76
|
-
arrayMoveImmutable(prevItem, oldIndex, newIndex)
|
|
77
|
-
);
|
|
78
|
-
};
|
|
79
|
-
|
|
80
|
-
const sortList = async () => {
|
|
81
|
-
try {
|
|
82
|
-
let fetchUrl = url;
|
|
83
|
-
let payload = {};
|
|
84
|
-
|
|
85
|
-
if (form?.json) {
|
|
86
|
-
fetchUrl = fetchUrl + '/jsonSortList';
|
|
87
|
-
payload.id = paramValue;
|
|
88
|
-
} else {
|
|
89
|
-
fetchUrl = fetchUrl + '/sort_list';
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
const res = await CustomFetch(fetchUrl, 'POST', payload);
|
|
93
|
-
setSortData(res.data);
|
|
94
|
-
} catch (err) {
|
|
95
|
-
console.log(err);
|
|
96
|
-
}
|
|
97
|
-
};
|
|
98
|
-
|
|
99
|
-
const sortUpdate = async () => {
|
|
100
|
-
try {
|
|
101
|
-
let fetchUrl = url;
|
|
102
|
-
let payload = {
|
|
103
|
-
list: sortData,
|
|
104
|
-
};
|
|
105
|
-
|
|
106
|
-
if (form?.json) {
|
|
107
|
-
fetchUrl = fetchUrl + '/jsonSortUpdate';
|
|
108
|
-
payload.id = paramValue;
|
|
109
|
-
} else {
|
|
110
|
-
fetchUrl = fetchUrl + '/sort_update';
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
if (category === false) {
|
|
114
|
-
if (sortData.length > 0) {
|
|
115
|
-
const res = await CustomFetch(fetchUrl, 'POST', payload);
|
|
116
|
-
|
|
117
|
-
if (res.data.error !== '') {
|
|
118
|
-
toast.error(String(res.data.error));
|
|
119
|
-
}
|
|
120
|
-
}
|
|
121
|
-
}
|
|
122
|
-
} catch (err) {
|
|
123
|
-
console.log(err);
|
|
124
|
-
}
|
|
125
|
-
};
|
|
126
|
-
|
|
127
|
-
useEffect(() => {
|
|
128
|
-
sortUpdate();
|
|
129
|
-
}, [sortData]);
|
|
130
|
-
|
|
131
|
-
useEffect(() => {
|
|
132
|
-
sortList();
|
|
133
|
-
}, []);
|
|
134
|
-
|
|
135
|
-
return (
|
|
136
|
-
<>
|
|
137
|
-
<div className={styles.grid}>
|
|
138
|
-
<div className={styles.grid__row}>
|
|
139
|
-
<div
|
|
140
|
-
className={`${styles.grid__full} ${
|
|
141
|
-
layout === 'full'
|
|
142
|
-
? styles.crmtitle
|
|
143
|
-
: styles.crmtitleSimple
|
|
144
|
-
}`}
|
|
145
|
-
>
|
|
146
|
-
<Breadcrumb
|
|
147
|
-
data={{
|
|
148
|
-
label: camelCaseToUcFirst(routeParams.dataId),
|
|
149
|
-
}} // Use utility function here
|
|
150
|
-
page={{
|
|
151
|
-
parentTitle: 'Settings',
|
|
152
|
-
parentUrl: '/settings',
|
|
153
|
-
titleKey: 'label',
|
|
154
|
-
}}
|
|
155
|
-
/>
|
|
156
|
-
</div>
|
|
157
|
-
</div>
|
|
158
|
-
</div>
|
|
159
|
-
<div className={styles.grid}>
|
|
160
|
-
<div className={styles.grid__row}>
|
|
161
|
-
<div className={styles.grid__full}>
|
|
162
|
-
{category === false ? (
|
|
163
|
-
<SortableList
|
|
164
|
-
items={sortData}
|
|
165
|
-
onSortEnd={onSortEnd}
|
|
166
|
-
axis="xy"
|
|
167
|
-
helperClass={styles.dragitem}
|
|
168
|
-
transitionDuration={250}
|
|
169
|
-
useDragHandle
|
|
170
|
-
/>
|
|
171
|
-
) : (
|
|
172
|
-
sortData.length > 0 &&
|
|
173
|
-
sortData.map((item) => (
|
|
174
|
-
<ChildSort
|
|
175
|
-
key={`category-${item.id}`}
|
|
176
|
-
item={item}
|
|
177
|
-
url={url}
|
|
178
|
-
/>
|
|
179
|
-
))
|
|
180
|
-
)}
|
|
181
|
-
</div>
|
|
182
|
-
</div>
|
|
183
|
-
</div>
|
|
184
|
-
</>
|
|
185
|
-
);
|
|
186
|
-
};
|
|
187
|
-
|
|
188
|
-
export default GenericSort;
|