@visns-studio/visns-components 2.3.2 → 2.3.4
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/components/cms/DataGrid.jsx +12 -9
- package/components/cms/Form.jsx +75 -76
- package/components/cms/generic/CmsDetail.jsx +31 -0
- package/components/cms/generic/CmsIndex.jsx +72 -0
- package/components/cms/generic/CmsSort.jsx +69 -0
- package/components/crm/Form.jsx +59 -72
- package/components/crm/Navigation.jsx +91 -4
- package/components/crm/generic/GenericIndex.jsx +61 -22
- package/index.js +9 -1
- package/package.json +2 -1
|
@@ -93,14 +93,12 @@ const loadData = async (
|
|
|
93
93
|
|
|
94
94
|
const DataGrid = ({
|
|
95
95
|
ajaxSetting,
|
|
96
|
-
form,
|
|
97
96
|
columns,
|
|
97
|
+
form,
|
|
98
|
+
gridHeight,
|
|
98
99
|
settings,
|
|
99
100
|
setFilterData,
|
|
100
101
|
style,
|
|
101
|
-
tableFilters,
|
|
102
|
-
historySearch,
|
|
103
|
-
historyUrl,
|
|
104
102
|
}) => {
|
|
105
103
|
const navigate = useNavigate();
|
|
106
104
|
|
|
@@ -325,7 +323,6 @@ const DataGrid = ({
|
|
|
325
323
|
|
|
326
324
|
const sortTrigger = () => {
|
|
327
325
|
const url = form.url.replace('/ajax', '');
|
|
328
|
-
console.info(url);
|
|
329
326
|
const newState = {
|
|
330
327
|
form: form,
|
|
331
328
|
};
|
|
@@ -1294,7 +1291,9 @@ const DataGrid = ({
|
|
|
1294
1291
|
const [dataCount, setDataCount] = useState(0);
|
|
1295
1292
|
const [gridStyle, setGridStyle] = useState({
|
|
1296
1293
|
minHeight:
|
|
1297
|
-
|
|
1294
|
+
gridHeight && gridHeight > 0
|
|
1295
|
+
? gridHeight
|
|
1296
|
+
: dataCount > 5
|
|
1298
1297
|
? dataCount > 8
|
|
1299
1298
|
? windowHeight * 0.7 > 550
|
|
1300
1299
|
? windowHeight * 0.7
|
|
@@ -1311,7 +1310,9 @@ const DataGrid = ({
|
|
|
1311
1310
|
setGridStyle((prevState) => ({
|
|
1312
1311
|
...prevState,
|
|
1313
1312
|
minHeight:
|
|
1314
|
-
|
|
1313
|
+
gridHeight && gridHeight > 0
|
|
1314
|
+
? gridHeight
|
|
1315
|
+
: dataCount > 5
|
|
1315
1316
|
? dataCount > 8
|
|
1316
1317
|
? windowHeight * 0.7 > 550
|
|
1317
1318
|
? windowHeight * 0.7
|
|
@@ -1321,7 +1322,9 @@ const DataGrid = ({
|
|
|
1321
1322
|
}));
|
|
1322
1323
|
|
|
1323
1324
|
let dgHeight =
|
|
1324
|
-
|
|
1325
|
+
gridHeight && gridHeight > 0
|
|
1326
|
+
? gridHeight
|
|
1327
|
+
: dataCount > 5
|
|
1325
1328
|
? dataCount > 8
|
|
1326
1329
|
? windowHeight * 0.7 > 550
|
|
1327
1330
|
? windowHeight * 0.7
|
|
@@ -1329,7 +1332,7 @@ const DataGrid = ({
|
|
|
1329
1332
|
: 450
|
|
1330
1333
|
: 400;
|
|
1331
1334
|
|
|
1332
|
-
let rowCount = Math.floor((dgHeight -
|
|
1335
|
+
let rowCount = Math.floor((dgHeight - 100) / 40);
|
|
1333
1336
|
setLimit(rowCount);
|
|
1334
1337
|
}, [dataCount]);
|
|
1335
1338
|
|
package/components/cms/Form.jsx
CHANGED
|
@@ -1,25 +1,25 @@
|
|
|
1
|
-
import React, { useState, useEffect } from
|
|
2
|
-
import CustomFetch from
|
|
3
|
-
import Field from
|
|
4
|
-
import slugify from
|
|
5
|
-
import moment from
|
|
6
|
-
import Reveal from
|
|
7
|
-
import parse from
|
|
8
|
-
import { confirmAlert } from
|
|
9
|
-
import { toast } from
|
|
10
|
-
import { Copy, TrashBin } from
|
|
11
|
-
|
|
12
|
-
import
|
|
1
|
+
import React, { useState, useEffect } from 'react';
|
|
2
|
+
import CustomFetch from '../crm/Fetch';
|
|
3
|
+
import Field from './Field';
|
|
4
|
+
import slugify from 'react-slugify';
|
|
5
|
+
import moment from 'moment';
|
|
6
|
+
import Reveal from 'react-reveal/Reveal';
|
|
7
|
+
import parse from 'html-react-parser';
|
|
8
|
+
import { confirmAlert } from 'react-confirm-alert';
|
|
9
|
+
import { toast } from 'react-toastify';
|
|
10
|
+
import { Copy, TrashBin } from 'akar-icons';
|
|
11
|
+
|
|
12
|
+
import 'react-confirm-alert/src/react-confirm-alert.css';
|
|
13
13
|
|
|
14
14
|
function Form(props) {
|
|
15
|
-
const { dataId, navigate, form
|
|
15
|
+
const { dataId, navigate, form } = props;
|
|
16
16
|
const [data, setData] = useState({});
|
|
17
17
|
const [dataClass, setDataClass] = useState({});
|
|
18
18
|
const [audit, setAudit] = useState({
|
|
19
19
|
createdBy: {},
|
|
20
|
-
created:
|
|
20
|
+
created: '',
|
|
21
21
|
updatedBy: {},
|
|
22
|
-
updated:
|
|
22
|
+
updated: '',
|
|
23
23
|
});
|
|
24
24
|
const [uploadProgress, setUploadProgress] = useState({});
|
|
25
25
|
|
|
@@ -28,7 +28,7 @@ function Form(props) {
|
|
|
28
28
|
const { name, value } = e.target;
|
|
29
29
|
|
|
30
30
|
switch (e.target.name) {
|
|
31
|
-
case
|
|
31
|
+
case 'title':
|
|
32
32
|
setData((prevState) => ({
|
|
33
33
|
...prevState,
|
|
34
34
|
[name]: value,
|
|
@@ -39,7 +39,7 @@ function Form(props) {
|
|
|
39
39
|
slug: slugify(value),
|
|
40
40
|
}));
|
|
41
41
|
break;
|
|
42
|
-
case
|
|
42
|
+
case 'name':
|
|
43
43
|
setData((prevState) => ({
|
|
44
44
|
...prevState,
|
|
45
45
|
[name]: value,
|
|
@@ -118,7 +118,7 @@ function Form(props) {
|
|
|
118
118
|
}));
|
|
119
119
|
},
|
|
120
120
|
}).then((response) => {
|
|
121
|
-
if (data.hasOwnProperty(
|
|
121
|
+
if (data.hasOwnProperty('files')) {
|
|
122
122
|
let _files = data.files;
|
|
123
123
|
let _new = true;
|
|
124
124
|
|
|
@@ -184,32 +184,32 @@ function Form(props) {
|
|
|
184
184
|
if (e) {
|
|
185
185
|
e.preventDefault();
|
|
186
186
|
|
|
187
|
-
let error =
|
|
188
|
-
let url =
|
|
189
|
-
let method =
|
|
190
|
-
let message =
|
|
187
|
+
let error = '';
|
|
188
|
+
let url = '';
|
|
189
|
+
let method = '';
|
|
190
|
+
let message = '';
|
|
191
191
|
|
|
192
|
-
if (data.title ===
|
|
193
|
-
error +=
|
|
192
|
+
if (data.title === '') {
|
|
193
|
+
error += 'Please enter a title.<br />';
|
|
194
194
|
}
|
|
195
195
|
|
|
196
|
-
if (data.summary ===
|
|
197
|
-
error +=
|
|
196
|
+
if (data.summary === '') {
|
|
197
|
+
error += 'Please enter a summary.<br />';
|
|
198
198
|
}
|
|
199
199
|
|
|
200
|
-
if (error ===
|
|
201
|
-
if (dataId ===
|
|
200
|
+
if (error === '') {
|
|
201
|
+
if (dataId === 'create') {
|
|
202
202
|
url = form.url;
|
|
203
|
-
method =
|
|
204
|
-
message =
|
|
203
|
+
method = 'POST';
|
|
204
|
+
message = 'You have successfully created a new entry.';
|
|
205
205
|
} else {
|
|
206
|
-
url = form.url +
|
|
207
|
-
method =
|
|
208
|
-
message =
|
|
206
|
+
url = form.url + '/' + dataId;
|
|
207
|
+
method = 'PUT';
|
|
208
|
+
message = 'You have successfully updated this entry.';
|
|
209
209
|
}
|
|
210
210
|
|
|
211
211
|
CustomFetch(url, method, data, function (result) {
|
|
212
|
-
if (result.error ===
|
|
212
|
+
if (result.error === '') {
|
|
213
213
|
let _uploadProgress = uploadProgress;
|
|
214
214
|
|
|
215
215
|
Object.keys(_uploadProgress).forEach((a, b) => {
|
|
@@ -221,10 +221,10 @@ function Form(props) {
|
|
|
221
221
|
|
|
222
222
|
toast.success(message);
|
|
223
223
|
|
|
224
|
-
if (dataId ===
|
|
224
|
+
if (dataId === 'create') {
|
|
225
225
|
navigate(
|
|
226
|
-
form.url.replace(
|
|
227
|
-
|
|
226
|
+
form.url.replace('/ajax', '') +
|
|
227
|
+
'/' +
|
|
228
228
|
result.data.id,
|
|
229
229
|
{
|
|
230
230
|
state: {
|
|
@@ -246,21 +246,21 @@ function Form(props) {
|
|
|
246
246
|
const handleDelete = (e) => {
|
|
247
247
|
if (e) {
|
|
248
248
|
confirmAlert({
|
|
249
|
-
title:
|
|
250
|
-
message:
|
|
249
|
+
title: 'Delete this entry',
|
|
250
|
+
message: 'Are you sure you want to delete it?',
|
|
251
251
|
buttons: [
|
|
252
252
|
{
|
|
253
|
-
label:
|
|
253
|
+
label: 'Yes',
|
|
254
254
|
onClick: () =>
|
|
255
255
|
CustomFetch(
|
|
256
256
|
`${form.url}/${dataId}`,
|
|
257
|
-
|
|
257
|
+
'DELETE',
|
|
258
258
|
{},
|
|
259
259
|
function (result) {
|
|
260
|
-
if (result.error ===
|
|
261
|
-
navigate(form.url.replace(
|
|
260
|
+
if (result.error === '') {
|
|
261
|
+
navigate(form.url.replace('/ajax', ''));
|
|
262
262
|
toast.success(
|
|
263
|
-
|
|
263
|
+
'You have successfully deleted this entry.'
|
|
264
264
|
);
|
|
265
265
|
} else {
|
|
266
266
|
toast.error(result.error);
|
|
@@ -269,7 +269,7 @@ function Form(props) {
|
|
|
269
269
|
),
|
|
270
270
|
},
|
|
271
271
|
{
|
|
272
|
-
label:
|
|
272
|
+
label: 'No',
|
|
273
273
|
onClick: () => close(),
|
|
274
274
|
},
|
|
275
275
|
],
|
|
@@ -281,14 +281,14 @@ function Form(props) {
|
|
|
281
281
|
form.fields.forEach((a) => {
|
|
282
282
|
setData((prevState) => ({
|
|
283
283
|
...prevState,
|
|
284
|
-
[a.id]:
|
|
284
|
+
[a.id]: '',
|
|
285
285
|
}));
|
|
286
286
|
});
|
|
287
287
|
|
|
288
|
-
if (dataId !==
|
|
288
|
+
if (dataId !== 'create') {
|
|
289
289
|
CustomFetch(
|
|
290
290
|
`${form.url}/${dataId}`,
|
|
291
|
-
|
|
291
|
+
'GET',
|
|
292
292
|
{},
|
|
293
293
|
function (result) {
|
|
294
294
|
let now = moment();
|
|
@@ -306,32 +306,32 @@ function Form(props) {
|
|
|
306
306
|
created:
|
|
307
307
|
created.hours() > 24
|
|
308
308
|
? created.days() +
|
|
309
|
-
|
|
309
|
+
' Days ' +
|
|
310
310
|
created.hours() +
|
|
311
|
-
|
|
311
|
+
' Hour(s) ' +
|
|
312
312
|
created.minutes() +
|
|
313
|
-
|
|
313
|
+
' Minutes'
|
|
314
314
|
: created.hours() +
|
|
315
|
-
|
|
315
|
+
' Hour(s) ' +
|
|
316
316
|
created.minutes() +
|
|
317
|
-
|
|
317
|
+
' Minutes',
|
|
318
318
|
updatedBy: result.audit_latest,
|
|
319
319
|
updated:
|
|
320
320
|
updated.hours() > 24
|
|
321
321
|
? updated.days() +
|
|
322
|
-
|
|
322
|
+
' Days ' +
|
|
323
323
|
updated.hours() +
|
|
324
|
-
|
|
324
|
+
' Hour(s) ' +
|
|
325
325
|
updated.minutes() +
|
|
326
|
-
|
|
326
|
+
' Minutes'
|
|
327
327
|
: updated.hours() +
|
|
328
|
-
|
|
328
|
+
' Hour(s) ' +
|
|
329
329
|
updated.minutes() +
|
|
330
|
-
|
|
330
|
+
' Minutes',
|
|
331
331
|
}));
|
|
332
332
|
},
|
|
333
333
|
function (error) {
|
|
334
|
-
navigate(
|
|
334
|
+
navigate('/');
|
|
335
335
|
|
|
336
336
|
toast.error(String(error));
|
|
337
337
|
}
|
|
@@ -341,7 +341,7 @@ function Form(props) {
|
|
|
341
341
|
|
|
342
342
|
useEffect(() => {
|
|
343
343
|
form.fields.forEach((a) => {
|
|
344
|
-
if (a.type ===
|
|
344
|
+
if (a.type === 'image') {
|
|
345
345
|
setUploadProgress((prevState) => ({
|
|
346
346
|
...prevState,
|
|
347
347
|
[a.id]: 0,
|
|
@@ -350,17 +350,16 @@ function Form(props) {
|
|
|
350
350
|
|
|
351
351
|
setData((prevState) => ({
|
|
352
352
|
...prevState,
|
|
353
|
-
[a.id]:
|
|
353
|
+
[a.id]: '',
|
|
354
354
|
}));
|
|
355
355
|
|
|
356
356
|
setDataClass((prevState) => ({
|
|
357
357
|
...prevState,
|
|
358
|
-
[a.id]:
|
|
358
|
+
[a.id]: '',
|
|
359
359
|
}));
|
|
360
360
|
});
|
|
361
361
|
|
|
362
362
|
fetchData();
|
|
363
|
-
setActiveNav();
|
|
364
363
|
}, [dataId]);
|
|
365
364
|
|
|
366
365
|
return (
|
|
@@ -371,7 +370,7 @@ function Form(props) {
|
|
|
371
370
|
<h1>
|
|
372
371
|
{data.title
|
|
373
372
|
? data.title
|
|
374
|
-
: dataId !==
|
|
373
|
+
: dataId !== 'create'
|
|
375
374
|
? form.update.title
|
|
376
375
|
: form.create.title}
|
|
377
376
|
</h1>
|
|
@@ -380,8 +379,8 @@ function Form(props) {
|
|
|
380
379
|
className="btn actionbtn"
|
|
381
380
|
onClick={handleSubmit}
|
|
382
381
|
>
|
|
383
|
-
<Copy size={18} strokeWidth={2} />{
|
|
384
|
-
{dataId !==
|
|
382
|
+
<Copy size={18} strokeWidth={2} />{' '}
|
|
383
|
+
{dataId !== 'create' ? 'Save' : 'Create'}
|
|
385
384
|
</button>
|
|
386
385
|
</div>
|
|
387
386
|
</div>
|
|
@@ -396,19 +395,19 @@ function Form(props) {
|
|
|
396
395
|
settings={a}
|
|
397
396
|
key={
|
|
398
397
|
b +
|
|
399
|
-
|
|
400
|
-
(a.hasOwnProperty(
|
|
401
|
-
? a.id +
|
|
398
|
+
'-fields-' +
|
|
399
|
+
(a.hasOwnProperty('key')
|
|
400
|
+
? a.id + '-' + a.key
|
|
402
401
|
: a.id)
|
|
403
402
|
}
|
|
404
403
|
inputValue={
|
|
405
|
-
a.hasOwnProperty(
|
|
404
|
+
a.hasOwnProperty('key')
|
|
406
405
|
? data[a.key]
|
|
407
406
|
: Array.isArray(data[a.id]) &&
|
|
408
|
-
a.type ===
|
|
407
|
+
a.type === 'image'
|
|
409
408
|
? data[a.id].length > 0
|
|
410
409
|
? data[a.id][0]
|
|
411
|
-
:
|
|
410
|
+
: ''
|
|
412
411
|
: data[a.id]
|
|
413
412
|
}
|
|
414
413
|
inputClass={dataClass}
|
|
@@ -432,7 +431,7 @@ function Form(props) {
|
|
|
432
431
|
Created: <span>{audit.created} Ago</span>
|
|
433
432
|
</li>
|
|
434
433
|
<li>
|
|
435
|
-
By:{
|
|
434
|
+
By:{' '}
|
|
436
435
|
<span>
|
|
437
436
|
{audit &&
|
|
438
437
|
audit.createdBy &&
|
|
@@ -445,7 +444,7 @@ function Form(props) {
|
|
|
445
444
|
Last Update: <span>{audit.updated} Ago</span>
|
|
446
445
|
</li>
|
|
447
446
|
<li>
|
|
448
|
-
by:{
|
|
447
|
+
by:{' '}
|
|
449
448
|
<span>
|
|
450
449
|
{audit &&
|
|
451
450
|
audit.updatedBy &&
|
|
@@ -454,13 +453,13 @@ function Form(props) {
|
|
|
454
453
|
: null}
|
|
455
454
|
</span>
|
|
456
455
|
</li>
|
|
457
|
-
{dataId !==
|
|
456
|
+
{dataId !== 'create' ? (
|
|
458
457
|
<li>
|
|
459
458
|
<button
|
|
460
459
|
className="btn actionbtn deletebtn"
|
|
461
460
|
onClick={handleDelete}
|
|
462
461
|
>
|
|
463
|
-
<TrashBin size={14} strokeWidth={2} />{
|
|
462
|
+
<TrashBin size={14} strokeWidth={2} />{' '}
|
|
464
463
|
Delete Entry
|
|
465
464
|
</button>
|
|
466
465
|
</li>
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { useParams, useNavigate, useLocation } from 'react-router-dom';
|
|
3
|
+
import Reveal from 'react-reveal/Reveal';
|
|
4
|
+
import CmsForm from '../Form';
|
|
5
|
+
|
|
6
|
+
import 'react-confirm-alert/src/react-confirm-alert.css';
|
|
7
|
+
|
|
8
|
+
function CmsDetail({}) {
|
|
9
|
+
const { dataId } = useParams();
|
|
10
|
+
const navigate = useNavigate();
|
|
11
|
+
const location = useLocation();
|
|
12
|
+
const { form } = location.state;
|
|
13
|
+
|
|
14
|
+
return (
|
|
15
|
+
<Reveal effect="fadeInUp">
|
|
16
|
+
<div className="grid">
|
|
17
|
+
<div className="grid__row">
|
|
18
|
+
<div className="grid__full">
|
|
19
|
+
<CmsForm
|
|
20
|
+
dataId={dataId}
|
|
21
|
+
navigate={navigate}
|
|
22
|
+
form={form}
|
|
23
|
+
/>
|
|
24
|
+
</div>
|
|
25
|
+
</div>
|
|
26
|
+
</div>
|
|
27
|
+
</Reveal>
|
|
28
|
+
);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
export default CmsDetail;
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import React, { useEffect, useState } from 'react';
|
|
2
|
+
import { Outlet } from 'react-router-dom';
|
|
3
|
+
import Reveal from 'react-reveal/Reveal';
|
|
4
|
+
import DataGrid from '../DataGrid';
|
|
5
|
+
|
|
6
|
+
function CmsIndex({ setting, userProfile }) {
|
|
7
|
+
const { ajaxSetting, columns, form, filters, page, settings } = setting;
|
|
8
|
+
|
|
9
|
+
const [config, setConfig] = useState({});
|
|
10
|
+
const [windowHeight, setWindowHeight] = useState(window.innerHeight);
|
|
11
|
+
const pageTitle = page?.title;
|
|
12
|
+
|
|
13
|
+
useEffect(() => {
|
|
14
|
+
setConfig(() => ({
|
|
15
|
+
ajaxSetting,
|
|
16
|
+
form,
|
|
17
|
+
columns,
|
|
18
|
+
settings,
|
|
19
|
+
}));
|
|
20
|
+
}, [setting]);
|
|
21
|
+
|
|
22
|
+
useEffect(() => {
|
|
23
|
+
const handleResize = () => {
|
|
24
|
+
setWindowHeight(window.innerHeight);
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
window.addEventListener('resize', handleResize);
|
|
28
|
+
|
|
29
|
+
// Clean up the event listener
|
|
30
|
+
return () => {
|
|
31
|
+
window.removeEventListener('resize', handleResize);
|
|
32
|
+
};
|
|
33
|
+
}, []);
|
|
34
|
+
|
|
35
|
+
return (
|
|
36
|
+
<>
|
|
37
|
+
<Reveal effect="fadeInUp">
|
|
38
|
+
<>
|
|
39
|
+
<div className="grid">
|
|
40
|
+
<div className="grid__row">
|
|
41
|
+
<div className="grid__full cmstitle">
|
|
42
|
+
<h1>{pageTitle}</h1>
|
|
43
|
+
</div>
|
|
44
|
+
</div>
|
|
45
|
+
</div>
|
|
46
|
+
{config.ajaxSetting &&
|
|
47
|
+
config.form &&
|
|
48
|
+
config.columns &&
|
|
49
|
+
config.settings && (
|
|
50
|
+
<div className="grid">
|
|
51
|
+
<div className="grid__row">
|
|
52
|
+
<div className="grid__full">
|
|
53
|
+
<DataGrid
|
|
54
|
+
{...config}
|
|
55
|
+
gridHeight={windowHeight * 0.65}
|
|
56
|
+
style={
|
|
57
|
+
userProfile?.settings?.style ||
|
|
58
|
+
{}
|
|
59
|
+
}
|
|
60
|
+
/>
|
|
61
|
+
</div>
|
|
62
|
+
</div>
|
|
63
|
+
</div>
|
|
64
|
+
)}
|
|
65
|
+
<Outlet />
|
|
66
|
+
</>
|
|
67
|
+
</Reveal>
|
|
68
|
+
</>
|
|
69
|
+
);
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
export default CmsIndex;
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import React, { useState, useEffect } from 'react';
|
|
2
|
+
import { useLocation } from 'react-router-dom';
|
|
3
|
+
import Reveal from 'react-reveal/Reveal';
|
|
4
|
+
import { arrayMoveImmutable } from 'array-move';
|
|
5
|
+
import { toast } from 'react-toastify';
|
|
6
|
+
import CustomFetch from '../../crm/Fetch';
|
|
7
|
+
import SortableList from '../sorting/List';
|
|
8
|
+
|
|
9
|
+
function CmsSort({}) {
|
|
10
|
+
const location = useLocation();
|
|
11
|
+
const { form } = location.state;
|
|
12
|
+
const [data, setData] = useState([]);
|
|
13
|
+
const url = form.url;
|
|
14
|
+
|
|
15
|
+
const onSortEnd = ({ oldIndex, newIndex }) => {
|
|
16
|
+
setData((prevItem) => arrayMoveImmutable(prevItem, oldIndex, newIndex));
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
useEffect(() => {
|
|
20
|
+
if (data.length > 0) {
|
|
21
|
+
CustomFetch(
|
|
22
|
+
url + '/sort_update',
|
|
23
|
+
'POST',
|
|
24
|
+
{
|
|
25
|
+
list: data,
|
|
26
|
+
},
|
|
27
|
+
function (result) {
|
|
28
|
+
if (result.error === '') {
|
|
29
|
+
} else {
|
|
30
|
+
toast.error(String(result.error));
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
);
|
|
34
|
+
}
|
|
35
|
+
}, [data]);
|
|
36
|
+
|
|
37
|
+
useEffect(() => {
|
|
38
|
+
CustomFetch(url + '/sort_list', 'POST', {}, function (result) {
|
|
39
|
+
setData(result);
|
|
40
|
+
});
|
|
41
|
+
}, []);
|
|
42
|
+
|
|
43
|
+
return (
|
|
44
|
+
<Reveal effect="fadeInUp">
|
|
45
|
+
<div className="grid">
|
|
46
|
+
<div className="grid__row">
|
|
47
|
+
<div className="grid__full cmstitle">
|
|
48
|
+
<h1>{form.sort.title}</h1>
|
|
49
|
+
</div>
|
|
50
|
+
</div>
|
|
51
|
+
</div>
|
|
52
|
+
<div className="grid">
|
|
53
|
+
<div className="grid__row">
|
|
54
|
+
<div className="grid__full">
|
|
55
|
+
<SortableList
|
|
56
|
+
items={data}
|
|
57
|
+
onSortEnd={onSortEnd}
|
|
58
|
+
axis="xy"
|
|
59
|
+
helperClass="dragitem"
|
|
60
|
+
transitionDuration={250}
|
|
61
|
+
/>
|
|
62
|
+
</div>
|
|
63
|
+
</div>
|
|
64
|
+
</div>
|
|
65
|
+
</Reveal>
|
|
66
|
+
);
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
export default CmsSort;
|
package/components/crm/Form.jsx
CHANGED
|
@@ -163,12 +163,12 @@ function Form(props) {
|
|
|
163
163
|
|
|
164
164
|
Object.keys(inputValue).forEach((a) => {
|
|
165
165
|
if (formData.hasOwnProperty(a)) {
|
|
166
|
-
updateFormData({
|
|
166
|
+
updateFormData((prevState) => ({
|
|
167
167
|
[a]:
|
|
168
|
-
prevState[a] !== ''
|
|
168
|
+
prevState && prevState[a] !== ''
|
|
169
169
|
? prevState[a]
|
|
170
170
|
: inputValue[a],
|
|
171
|
-
});
|
|
171
|
+
}));
|
|
172
172
|
}
|
|
173
173
|
});
|
|
174
174
|
|
|
@@ -224,20 +224,22 @@ function Form(props) {
|
|
|
224
224
|
|
|
225
225
|
const id = e.target.dataset.jsonkey || e.target.dataset.name;
|
|
226
226
|
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
227
|
+
const updateFormData = (dataToUpdate) => {
|
|
228
|
+
setFormData((prevState) => ({
|
|
229
|
+
...prevState,
|
|
230
|
+
...dataToUpdate,
|
|
231
|
+
}));
|
|
232
|
+
};
|
|
231
233
|
|
|
232
|
-
|
|
233
|
-
const postalData =
|
|
234
|
+
const updatePostalData = (checked) => {
|
|
235
|
+
const postalData = checked
|
|
234
236
|
? {
|
|
235
|
-
postal_address1:
|
|
236
|
-
postal_address2:
|
|
237
|
-
postal_suburb:
|
|
238
|
-
postal_postcode:
|
|
239
|
-
postal_state:
|
|
240
|
-
postal_country:
|
|
237
|
+
postal_address1: formData.address1,
|
|
238
|
+
postal_address2: formData.address2,
|
|
239
|
+
postal_suburb: formData.suburb,
|
|
240
|
+
postal_postcode: formData.postcode,
|
|
241
|
+
postal_state: formData.state,
|
|
242
|
+
postal_country: formData.country,
|
|
241
243
|
}
|
|
242
244
|
: {
|
|
243
245
|
postal_address1: '',
|
|
@@ -248,10 +250,11 @@ function Form(props) {
|
|
|
248
250
|
postal_country: '',
|
|
249
251
|
};
|
|
250
252
|
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
253
|
+
updateFormData(postalData);
|
|
254
|
+
};
|
|
255
|
+
|
|
256
|
+
if (id === 'same_address') {
|
|
257
|
+
updatePostalData(e.target.checked);
|
|
255
258
|
}
|
|
256
259
|
|
|
257
260
|
if (e.target.dataset.show) {
|
|
@@ -260,28 +263,26 @@ function Form(props) {
|
|
|
260
263
|
: [];
|
|
261
264
|
|
|
262
265
|
if (_show.length > 0) {
|
|
263
|
-
const
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
266
|
+
const updatedFields = formSettings.fields.map((field) => {
|
|
267
|
+
const showObject = _show.find(
|
|
268
|
+
(showItem) => showItem.id === field.id
|
|
269
|
+
);
|
|
270
|
+
if (
|
|
271
|
+
showObject &&
|
|
272
|
+
showObject.value &&
|
|
273
|
+
showObject.value.length > 0
|
|
274
|
+
) {
|
|
275
|
+
field.hide = !showObject.value.includes(
|
|
276
|
+
e.target.checked
|
|
271
277
|
);
|
|
272
|
-
|
|
273
|
-
if (index !== -1) {
|
|
274
|
-
_fields[index].hide = !value.includes(
|
|
275
|
-
e.target.checked
|
|
276
|
-
);
|
|
277
|
-
}
|
|
278
278
|
}
|
|
279
|
+
return field;
|
|
279
280
|
});
|
|
280
281
|
|
|
281
282
|
if (updateForm) {
|
|
282
283
|
updateForm((prevState) => ({
|
|
283
284
|
...prevState,
|
|
284
|
-
fields:
|
|
285
|
+
fields: updatedFields,
|
|
285
286
|
}));
|
|
286
287
|
}
|
|
287
288
|
}
|
|
@@ -776,50 +777,36 @@ function Form(props) {
|
|
|
776
777
|
}, []);
|
|
777
778
|
|
|
778
779
|
useEffect(() => {
|
|
779
|
-
formSettings.fields.forEach((
|
|
780
|
-
|
|
781
|
-
let _show = a.show;
|
|
782
|
-
if (_show.length > 0) {
|
|
783
|
-
_show.forEach((showObject) => {
|
|
784
|
-
if (
|
|
785
|
-
showObject.hasOwnProperty('id') &&
|
|
786
|
-
showObject.hasOwnProperty('value')
|
|
787
|
-
) {
|
|
788
|
-
if (
|
|
789
|
-
showObject.id !== '' &&
|
|
790
|
-
showObject.value.length > 0
|
|
791
|
-
) {
|
|
792
|
-
let _fields = formSettings.fields;
|
|
793
|
-
let _counter;
|
|
794
|
-
_fields.forEach((a, b) => {
|
|
795
|
-
if (a.id === showObject.id) {
|
|
796
|
-
_counter = b;
|
|
797
|
-
}
|
|
798
|
-
});
|
|
780
|
+
formSettings.fields.forEach((field) => {
|
|
781
|
+
const showConditions = field.show || [];
|
|
799
782
|
|
|
800
|
-
|
|
783
|
+
showConditions.forEach((showObject) => {
|
|
784
|
+
const { id, value } = showObject;
|
|
801
785
|
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
) {
|
|
807
|
-
_fields[_counter].hide = false;
|
|
808
|
-
} else {
|
|
809
|
-
_fields[_counter].hide = true;
|
|
810
|
-
}
|
|
786
|
+
if (id !== '' && value.length > 0) {
|
|
787
|
+
const targetField = formSettings.fields.find(
|
|
788
|
+
(f) => f.id === id
|
|
789
|
+
);
|
|
811
790
|
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
|
|
791
|
+
if (targetField) {
|
|
792
|
+
const valueChecker = formData[field.id];
|
|
793
|
+
|
|
794
|
+
if (valueChecker) {
|
|
795
|
+
const shouldShow =
|
|
796
|
+
valueChecker && value.includes(valueChecker);
|
|
797
|
+
|
|
798
|
+
targetField.hide = !shouldShow;
|
|
799
|
+
|
|
800
|
+
if (updateForm) {
|
|
801
|
+
updateForm((prevState) => ({
|
|
802
|
+
...prevState,
|
|
803
|
+
fields: [...formSettings.fields],
|
|
804
|
+
}));
|
|
818
805
|
}
|
|
819
806
|
}
|
|
820
|
-
}
|
|
807
|
+
}
|
|
821
808
|
}
|
|
822
|
-
}
|
|
809
|
+
});
|
|
823
810
|
});
|
|
824
811
|
}, [fetchTrigger]);
|
|
825
812
|
|
|
@@ -9,18 +9,22 @@ import {
|
|
|
9
9
|
Clipboard,
|
|
10
10
|
DoubleSword,
|
|
11
11
|
Draft,
|
|
12
|
+
Gear,
|
|
12
13
|
Grid,
|
|
13
14
|
Home,
|
|
14
15
|
LightBulb,
|
|
15
16
|
Microphone,
|
|
16
17
|
Newspaper,
|
|
18
|
+
Paper,
|
|
17
19
|
PeopleGroup,
|
|
18
20
|
PeopleMultiple,
|
|
19
21
|
Person,
|
|
20
22
|
SettingsVertical,
|
|
23
|
+
ShippingBoxV1,
|
|
21
24
|
SignOut,
|
|
22
25
|
Shield,
|
|
23
26
|
StatisticUp,
|
|
27
|
+
TextAlignLeft,
|
|
24
28
|
Ticket,
|
|
25
29
|
Utensils,
|
|
26
30
|
} from 'akar-icons';
|
|
@@ -28,12 +32,21 @@ import {
|
|
|
28
32
|
import CustomFetch from './Fetch';
|
|
29
33
|
import Notification from './Notification';
|
|
30
34
|
|
|
31
|
-
function Navigation({
|
|
35
|
+
function Navigation({
|
|
36
|
+
children,
|
|
37
|
+
layout = 'full',
|
|
38
|
+
logo,
|
|
39
|
+
navConfig,
|
|
40
|
+
searchComponent,
|
|
41
|
+
setSystemAuth,
|
|
42
|
+
userProfile,
|
|
43
|
+
}) {
|
|
32
44
|
const location = useLocation();
|
|
33
45
|
const navigate = useNavigate();
|
|
34
46
|
const currentPage = location.pathname.substr(1) || 'dashboard';
|
|
35
|
-
const [
|
|
47
|
+
const [isOpen, setOpen] = useState('false');
|
|
36
48
|
const [isScrolled, setIsScrolled] = useState(false);
|
|
49
|
+
const [navData, setNavData] = useState(navConfig);
|
|
37
50
|
const appNavClasses = `app-nav ${isScrolled ? 'navscrolled' : ''}`;
|
|
38
51
|
|
|
39
52
|
const handleLogout = () => {
|
|
@@ -100,15 +113,20 @@ function Navigation({ logo, logout, navConfig, setSystemAuth, userProfile }) {
|
|
|
100
113
|
clipboard: Clipboard,
|
|
101
114
|
doubleSword: DoubleSword,
|
|
102
115
|
draft: Draft,
|
|
116
|
+
gear: Gear,
|
|
103
117
|
grid: Grid,
|
|
104
118
|
home: Home,
|
|
105
119
|
lightBulb: LightBulb,
|
|
106
120
|
microphone: Microphone,
|
|
107
121
|
newspaper: Newspaper,
|
|
122
|
+
paper: Paper,
|
|
108
123
|
peopleGroup: PeopleGroup,
|
|
109
124
|
peopleMultiple: PeopleMultiple,
|
|
110
125
|
settingsVertical: SettingsVertical,
|
|
126
|
+
signOut: SignOut,
|
|
127
|
+
shippingboxv1: ShippingBoxV1,
|
|
111
128
|
statisticUp: StatisticUp,
|
|
129
|
+
textAlignLeft: TextAlignLeft,
|
|
112
130
|
ticket: Ticket,
|
|
113
131
|
utensils: Utensils,
|
|
114
132
|
};
|
|
@@ -235,9 +253,12 @@ function Navigation({ logo, logout, navConfig, setSystemAuth, userProfile }) {
|
|
|
235
253
|
};
|
|
236
254
|
|
|
237
255
|
const currentUrl = cleanUrl(currentPage);
|
|
256
|
+
const navUrl = cleanUrl(nav.url)
|
|
257
|
+
? cleanUrl(nav.url)
|
|
258
|
+
: 'dashboard';
|
|
238
259
|
|
|
239
260
|
if (
|
|
240
|
-
|
|
261
|
+
navUrl === currentUrl ||
|
|
241
262
|
(nav.children &&
|
|
242
263
|
nav.children.some(
|
|
243
264
|
(child) => cleanUrl(child.url) === currentUrl
|
|
@@ -267,7 +288,73 @@ function Navigation({ logo, logout, navConfig, setSystemAuth, userProfile }) {
|
|
|
267
288
|
};
|
|
268
289
|
}, []);
|
|
269
290
|
|
|
270
|
-
return (
|
|
291
|
+
return layout === 'simple' || layout === 'cms' ? (
|
|
292
|
+
<div className="cwrap">
|
|
293
|
+
<aside
|
|
294
|
+
className={
|
|
295
|
+
layout === 'cms'
|
|
296
|
+
? 'aside--cms aside--cms--open'
|
|
297
|
+
: 'aside aside--open'
|
|
298
|
+
}
|
|
299
|
+
>
|
|
300
|
+
<div className="logo">
|
|
301
|
+
<Link to="/">
|
|
302
|
+
<img src={logo} alt="Visns Studio CRM" />
|
|
303
|
+
</Link>
|
|
304
|
+
</div>
|
|
305
|
+
<div className="awrap">
|
|
306
|
+
<nav className="navwrap">
|
|
307
|
+
<ul className={appNavClasses}>
|
|
308
|
+
{navData.navigations.map((nav, navKey) =>
|
|
309
|
+
nav.permission === true ||
|
|
310
|
+
nav.permissionKey === '' ? (
|
|
311
|
+
<React.Fragment key={`nav-item-${navKey}`}>
|
|
312
|
+
{renderNav(nav)}
|
|
313
|
+
</React.Fragment>
|
|
314
|
+
) : null
|
|
315
|
+
)}
|
|
316
|
+
</ul>
|
|
317
|
+
</nav>
|
|
318
|
+
</div>
|
|
319
|
+
</aside>
|
|
320
|
+
<main className="content">
|
|
321
|
+
<div className="content-header">
|
|
322
|
+
{searchComponent}
|
|
323
|
+
<div className="content-title">
|
|
324
|
+
<button
|
|
325
|
+
className={
|
|
326
|
+
isOpen ? 'mobmenu' : 'mobmenu mobmenu--open'
|
|
327
|
+
}
|
|
328
|
+
onClick={() => {
|
|
329
|
+
setOpen(!isOpen);
|
|
330
|
+
}}
|
|
331
|
+
>
|
|
332
|
+
<span></span>
|
|
333
|
+
<span></span>
|
|
334
|
+
<span></span>
|
|
335
|
+
<span></span>
|
|
336
|
+
<span></span>
|
|
337
|
+
<span></span>
|
|
338
|
+
</button>
|
|
339
|
+
</div>
|
|
340
|
+
<div className="hactions">
|
|
341
|
+
<ul>
|
|
342
|
+
{navData.settings.map((setting, settingKey) =>
|
|
343
|
+
setting.permission === true ? (
|
|
344
|
+
<React.Fragment
|
|
345
|
+
key={`setting-${settingKey}`}
|
|
346
|
+
>
|
|
347
|
+
{renderSetting(setting)}
|
|
348
|
+
</React.Fragment>
|
|
349
|
+
) : null
|
|
350
|
+
)}
|
|
351
|
+
</ul>
|
|
352
|
+
</div>
|
|
353
|
+
</div>
|
|
354
|
+
{children}
|
|
355
|
+
</main>
|
|
356
|
+
</div>
|
|
357
|
+
) : (
|
|
271
358
|
<header className="header">
|
|
272
359
|
<div className="hwrap">
|
|
273
360
|
<div className="logo">
|
|
@@ -3,8 +3,8 @@ import { Outlet } from 'react-router-dom';
|
|
|
3
3
|
import Table from '../DataGrid';
|
|
4
4
|
import TableFilter from '../TableFilter';
|
|
5
5
|
|
|
6
|
-
function GenericIndex({ setting, userProfile }) {
|
|
7
|
-
const {
|
|
6
|
+
function GenericIndex({ layout = 'full', setting, userProfile }) {
|
|
7
|
+
const { ajaxSetting, columns, form, filters, page, settings, tabs } =
|
|
8
8
|
setting;
|
|
9
9
|
|
|
10
10
|
const [config, setConfig] = useState({});
|
|
@@ -27,7 +27,7 @@ function GenericIndex({ setting, userProfile }) {
|
|
|
27
27
|
}, [setting]);
|
|
28
28
|
|
|
29
29
|
useEffect(() => {
|
|
30
|
-
if (tabs && tabs.length > 0) {
|
|
30
|
+
if (tabs && tabs.length > 0 && subnav) {
|
|
31
31
|
const activeTab = subnav.find((s) => s.show === true);
|
|
32
32
|
|
|
33
33
|
if (activeTab) {
|
|
@@ -81,25 +81,64 @@ function GenericIndex({ setting, userProfile }) {
|
|
|
81
81
|
<div className="grid">
|
|
82
82
|
{subnav && subnav.length > 0 ? (
|
|
83
83
|
<div className="grid__subrow">
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
84
|
+
{layout === 'full' ? (
|
|
85
|
+
<>
|
|
86
|
+
<div className={`grid__subnav`}>
|
|
87
|
+
<TableFilter
|
|
88
|
+
filters={subnav}
|
|
89
|
+
setFilters={setSubnav}
|
|
90
|
+
setSettings={setConfig}
|
|
91
|
+
type={layout}
|
|
92
|
+
/>
|
|
93
|
+
</div>
|
|
94
|
+
<div className={`grid__subcontent`}>
|
|
95
|
+
<Table
|
|
96
|
+
{...config}
|
|
97
|
+
gridHeight={
|
|
98
|
+
windowHeight * 0.65
|
|
99
|
+
}
|
|
100
|
+
setConfig={setConfig}
|
|
101
|
+
setTotal={setTotal}
|
|
102
|
+
style={
|
|
103
|
+
userProfile?.settings
|
|
104
|
+
?.style || {}
|
|
105
|
+
}
|
|
106
|
+
/>
|
|
107
|
+
</div>
|
|
108
|
+
</>
|
|
109
|
+
) : (
|
|
110
|
+
<div className="grid__full">
|
|
111
|
+
<div className="tabcontent">
|
|
112
|
+
<div
|
|
113
|
+
className={`tabcontent__menu`}
|
|
114
|
+
>
|
|
115
|
+
<TableFilter
|
|
116
|
+
filters={subnav}
|
|
117
|
+
setFilters={setSubnav}
|
|
118
|
+
setSettings={setConfig}
|
|
119
|
+
type={layout}
|
|
120
|
+
/>
|
|
121
|
+
</div>
|
|
122
|
+
<div
|
|
123
|
+
className={`tabcontent__main`}
|
|
124
|
+
>
|
|
125
|
+
<Table
|
|
126
|
+
{...config}
|
|
127
|
+
gridHeight={
|
|
128
|
+
windowHeight * 0.65
|
|
129
|
+
}
|
|
130
|
+
setConfig={setConfig}
|
|
131
|
+
setTotal={setTotal}
|
|
132
|
+
style={
|
|
133
|
+
userProfile
|
|
134
|
+
?.settings
|
|
135
|
+
?.style || {}
|
|
136
|
+
}
|
|
137
|
+
/>
|
|
138
|
+
</div>
|
|
139
|
+
</div>
|
|
140
|
+
</div>
|
|
141
|
+
)}
|
|
103
142
|
</div>
|
|
104
143
|
) : (
|
|
105
144
|
<div className="grid__full">
|
package/index.js
CHANGED
|
@@ -27,7 +27,12 @@ import Profile from './components/crm/auth/Profile';
|
|
|
27
27
|
import Reset from './components/crm/auth/Reset';
|
|
28
28
|
import Verify from './components/crm/auth/Verify';
|
|
29
29
|
|
|
30
|
-
/** Generic Components */
|
|
30
|
+
/** CMS Generic Components */
|
|
31
|
+
import CmsDetail from './components/cms/generic/CmsDetail';
|
|
32
|
+
import CmsIndex from './components/cms/generic/CmsIndex';
|
|
33
|
+
import CmsSort from './components/cms/generic/CmsSort';
|
|
34
|
+
|
|
35
|
+
/** CRM Generic Components */
|
|
31
36
|
import GenericDetail from './components/crm/generic/GenericDetail';
|
|
32
37
|
import GenericIndex from './components/crm/generic/GenericIndex';
|
|
33
38
|
import NotificationList from './components/crm/generic/NotificationList';
|
|
@@ -36,7 +41,10 @@ export {
|
|
|
36
41
|
AsyncSelect,
|
|
37
42
|
Autocomplete,
|
|
38
43
|
Call,
|
|
44
|
+
CmsDetail,
|
|
39
45
|
CmsForm,
|
|
46
|
+
CmsIndex,
|
|
47
|
+
CmsSort,
|
|
40
48
|
CustomFetch,
|
|
41
49
|
DataGrid,
|
|
42
50
|
Download,
|
package/package.json
CHANGED
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
"@inovua/reactdatagrid-community": "^5.10.2",
|
|
4
4
|
"add": "^2.0.6",
|
|
5
5
|
"akar-icons": "^1.9.28",
|
|
6
|
+
"array-move": "^4.0.0",
|
|
6
7
|
"awesome-debounce-promise": "^2.1.0",
|
|
7
8
|
"axios": "^1.4.0",
|
|
8
9
|
"framer-motion": "^10.15.1",
|
|
@@ -41,7 +42,7 @@
|
|
|
41
42
|
"react-dom": "^17.0.1"
|
|
42
43
|
},
|
|
43
44
|
"name": "@visns-studio/visns-components",
|
|
44
|
-
"version": "2.3.
|
|
45
|
+
"version": "2.3.4",
|
|
45
46
|
"description": "Various packages to assist in the development of our Custom Applications.",
|
|
46
47
|
"main": "index.js",
|
|
47
48
|
"scripts": {
|