@visns-studio/visns-components 3.6.8 → 3.6.9
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/Form.jsx
CHANGED
|
@@ -709,7 +709,7 @@ const DataGrid = forwardRef(
|
|
|
709
709
|
{(form.create &&
|
|
710
710
|
form.create.title &&
|
|
711
711
|
form.create.title !== '') ||
|
|
712
|
-
(form.url && form.create?.title) ? (
|
|
712
|
+
(form.url && form.create?.title !== '') ? (
|
|
713
713
|
<button
|
|
714
714
|
className="btn"
|
|
715
715
|
onClick={(e) => {
|
|
@@ -734,7 +734,7 @@ const DataGrid = forwardRef(
|
|
|
734
734
|
>
|
|
735
735
|
<div className="icon-plus"></div> Create
|
|
736
736
|
</button>
|
|
737
|
-
) : form.url ? (
|
|
737
|
+
) : form.url && form.modal === false ? (
|
|
738
738
|
<button
|
|
739
739
|
className="btn"
|
|
740
740
|
onClick={(e) => {
|
|
@@ -75,12 +75,14 @@ function TableFilter({ filters, setFilters, setSettings, type }) {
|
|
|
75
75
|
},
|
|
76
76
|
};
|
|
77
77
|
} else {
|
|
78
|
-
let w = prevState.where
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
78
|
+
let w = prevState.where
|
|
79
|
+
? prevState.where.map((a) => {
|
|
80
|
+
if (id === a.id) {
|
|
81
|
+
return { ...a, value: value };
|
|
82
|
+
}
|
|
83
|
+
return a;
|
|
84
|
+
})
|
|
85
|
+
: [];
|
|
84
86
|
|
|
85
87
|
return { ...prevState, where: w };
|
|
86
88
|
}
|
|
@@ -1,212 +1,291 @@
|
|
|
1
|
-
import React, { useEffect, useRef, useState } from 'react';
|
|
1
|
+
import React, { useCallback, useEffect, useRef, useState } from 'react';
|
|
2
2
|
import { Outlet } from 'react-router-dom';
|
|
3
3
|
import { toast } from 'react-toastify';
|
|
4
|
+
import { saveAs } from 'file-saver';
|
|
4
5
|
import CustomFetch from '../Fetch';
|
|
6
|
+
import Download from '../Download';
|
|
7
|
+
import Field from '../Field';
|
|
5
8
|
import Table from '../DataGrid';
|
|
6
9
|
import TableFilter from '../TableFilter';
|
|
7
10
|
|
|
8
|
-
function
|
|
9
|
-
const
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
settings,
|
|
17
|
-
tableSetting,
|
|
18
|
-
tabs,
|
|
19
|
-
} = setting;
|
|
20
|
-
const gridRef = useRef(null);
|
|
11
|
+
function useWindowHeight() {
|
|
12
|
+
const [windowHeight, setWindowHeight] = useState(window.innerHeight);
|
|
13
|
+
|
|
14
|
+
useEffect(() => {
|
|
15
|
+
const handleResize = () => setWindowHeight(window.innerHeight);
|
|
16
|
+
window.addEventListener('resize', handleResize);
|
|
17
|
+
return () => window.removeEventListener('resize', handleResize);
|
|
18
|
+
}, []);
|
|
21
19
|
|
|
20
|
+
return windowHeight;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
function useConfig(setting, tabs, filters, setRowsSelected, tableSetting) {
|
|
22
24
|
const [config, setConfig] = useState({});
|
|
23
|
-
const [rowsSelected, setRowsSelected] = useState({});
|
|
24
25
|
const [subnav, setSubnav] = useState(filters || []);
|
|
25
|
-
const [total, setTotal] = useState(0);
|
|
26
|
-
const [windowHeight, setWindowHeight] = useState(window.innerHeight);
|
|
27
|
-
const pageTitle = page?.title;
|
|
28
26
|
|
|
29
|
-
|
|
30
|
-
|
|
27
|
+
useEffect(() => {
|
|
28
|
+
setConfig({
|
|
29
|
+
ajaxSetting: setting.ajaxSetting,
|
|
30
|
+
form: setting.form,
|
|
31
|
+
columns: setting.columns,
|
|
32
|
+
setRowsSelected,
|
|
33
|
+
settings: setting.settings,
|
|
34
|
+
tableSetting,
|
|
35
|
+
type: setting.type ? setting.type : 'table',
|
|
36
|
+
});
|
|
37
|
+
setSubnav(filters);
|
|
38
|
+
}, [setting, filters, setRowsSelected, tableSetting]);
|
|
39
|
+
|
|
40
|
+
useEffect(() => {
|
|
41
|
+
if (tabs?.length > 0 && subnav) {
|
|
42
|
+
const activeTab = subnav.find((s) => s.show);
|
|
43
|
+
const activeTabConfig = tabs.find((t) => t.id === activeTab?.id);
|
|
44
|
+
|
|
45
|
+
if (activeTabConfig) {
|
|
46
|
+
setConfig((currentConfig) => ({
|
|
47
|
+
...currentConfig,
|
|
48
|
+
ajaxSetting: activeTabConfig.ajaxSetting,
|
|
49
|
+
form: activeTabConfig.form,
|
|
50
|
+
columns: activeTabConfig.columns,
|
|
51
|
+
settings: activeTabConfig.settings,
|
|
52
|
+
type: activeTabConfig.type ? activeTabConfig.type : 'table',
|
|
53
|
+
}));
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
}, [subnav, tabs]);
|
|
57
|
+
|
|
58
|
+
return { config, setConfig, subnav, setSubnav };
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
const ReportForm = ({ config, userProfile }) => {
|
|
62
|
+
const [formData, setFormData] = useState({});
|
|
63
|
+
|
|
64
|
+
const handleChange = (e) => {
|
|
65
|
+
const {
|
|
66
|
+
value,
|
|
67
|
+
dataset: { name },
|
|
68
|
+
} = e.target;
|
|
69
|
+
|
|
70
|
+
setFormData((prevData) => ({ ...prevData, [name]: value }));
|
|
71
|
+
};
|
|
72
|
+
|
|
73
|
+
const handleChangeDate = (date, id) => {
|
|
74
|
+
setFormData((prevData) => ({ ...prevData, [id]: date }));
|
|
75
|
+
};
|
|
76
|
+
|
|
77
|
+
const handleChangeSelect = (inputValue, action, id) => {
|
|
78
|
+
setFormData((prevData) => ({ ...prevData, [id]: inputValue }));
|
|
31
79
|
};
|
|
32
80
|
|
|
33
|
-
const
|
|
81
|
+
const handleExport = async (e) => {
|
|
34
82
|
try {
|
|
35
|
-
e
|
|
36
|
-
|
|
83
|
+
if (e) {
|
|
84
|
+
e.preventDefault();
|
|
85
|
+
}
|
|
37
86
|
|
|
38
|
-
|
|
39
|
-
|
|
87
|
+
const missingFields = config.form.filters
|
|
88
|
+
.filter(
|
|
89
|
+
(item) => item.required === true && formData[item.id] === ''
|
|
90
|
+
)
|
|
91
|
+
.map((item) => item.label);
|
|
92
|
+
|
|
93
|
+
if (missingFields.length > 0) {
|
|
94
|
+
const fieldNames = missingFields.join(', ');
|
|
95
|
+
const errorMessage = `Please fill in a value for the following field(s): ${fieldNames}.`;
|
|
96
|
+
toast.error(errorMessage);
|
|
40
97
|
} else {
|
|
41
|
-
const res = await
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
98
|
+
const res = await Download(
|
|
99
|
+
config.form.url,
|
|
100
|
+
config.form.method,
|
|
101
|
+
formData
|
|
102
|
+
);
|
|
103
|
+
|
|
104
|
+
if (res.data.error) {
|
|
105
|
+
toast.error(res.data.error);
|
|
49
106
|
} else {
|
|
50
|
-
|
|
107
|
+
// Assuming the response contains a Blob or similar data
|
|
108
|
+
if (res.data && res.data instanceof Blob) {
|
|
109
|
+
const fileName = `${config.form.filename}`;
|
|
110
|
+
saveAs(res.data, fileName);
|
|
111
|
+
} else {
|
|
112
|
+
// Handle the case where the response is not a Blob
|
|
113
|
+
toast.error('Invalid file format received.');
|
|
114
|
+
}
|
|
51
115
|
}
|
|
116
|
+
|
|
117
|
+
// Proceed with the export functionality
|
|
118
|
+
console.info(formData, res);
|
|
52
119
|
}
|
|
53
|
-
} catch (
|
|
54
|
-
console.error(
|
|
120
|
+
} catch (err) {
|
|
121
|
+
console.error(err);
|
|
55
122
|
}
|
|
56
123
|
};
|
|
57
124
|
|
|
58
125
|
useEffect(() => {
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
settings,
|
|
66
|
-
tableSetting,
|
|
67
|
-
}));
|
|
68
|
-
}
|
|
126
|
+
const tmpForm = config.form?.filters.reduce((acc, item) => {
|
|
127
|
+
acc[item.id] = '';
|
|
128
|
+
return acc;
|
|
129
|
+
}, {});
|
|
130
|
+
setFormData(tmpForm);
|
|
131
|
+
}, [config.form?.filters]);
|
|
69
132
|
|
|
70
|
-
|
|
71
|
-
|
|
133
|
+
return (
|
|
134
|
+
<div className="formcontainer">
|
|
135
|
+
<form className="modalForm">
|
|
136
|
+
{config.form?.filters.map((item, key) => (
|
|
137
|
+
<Field
|
|
138
|
+
api={userProfile.settings.api}
|
|
139
|
+
autocompleteCallback={() => {}}
|
|
140
|
+
childDropdownCallback={() => {}}
|
|
141
|
+
fetchData={() => {}}
|
|
142
|
+
formData={formData}
|
|
143
|
+
inputClass={''}
|
|
144
|
+
inputValue={formData[item.id]}
|
|
145
|
+
key={`filter-fields-${key}`}
|
|
146
|
+
mapbox={{}}
|
|
147
|
+
onChange={handleChange}
|
|
148
|
+
onChangeCheckbox={() => {}}
|
|
149
|
+
onChangeDate={handleChangeDate}
|
|
150
|
+
onChangeNumberFormat={() => {}}
|
|
151
|
+
onChangeRicheditor={() => {}}
|
|
152
|
+
onChangeSelect={handleChangeSelect}
|
|
153
|
+
onChangeToggle={() => {}}
|
|
154
|
+
settings={item}
|
|
155
|
+
setFormData={setFormData}
|
|
156
|
+
style={userProfile.settings.style}
|
|
157
|
+
uploadProgress={0}
|
|
158
|
+
userProfile={userProfile}
|
|
159
|
+
/>
|
|
160
|
+
))}
|
|
161
|
+
<div className="formItem fwItem lastItem">
|
|
162
|
+
<button className="btn modalsave" onClick={handleExport}>
|
|
163
|
+
Export
|
|
164
|
+
</button>
|
|
165
|
+
</div>
|
|
166
|
+
</form>
|
|
167
|
+
</div>
|
|
168
|
+
);
|
|
169
|
+
};
|
|
72
170
|
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
171
|
+
function GenericIndex({ layout = 'full', setting, userProfile }) {
|
|
172
|
+
const gridRef = useRef(null);
|
|
173
|
+
const [rowsSelected, setRowsSelected] = useState({});
|
|
174
|
+
const [total, setTotal] = useState(0);
|
|
175
|
+
const windowHeight = useWindowHeight();
|
|
176
|
+
const { config, setConfig, subnav, setSubnav } = useConfig(
|
|
177
|
+
setting,
|
|
178
|
+
setting.tabs,
|
|
179
|
+
setting.filters,
|
|
180
|
+
setRowsSelected,
|
|
181
|
+
setting.tableSetting
|
|
182
|
+
);
|
|
183
|
+
|
|
184
|
+
const handleCheckboxUpdate = useCallback(async () => {
|
|
185
|
+
try {
|
|
186
|
+
const { data, method, message, url } =
|
|
187
|
+
setting.functions.checkboxUpdate;
|
|
188
|
+
if (!Object.keys(rowsSelected).length) {
|
|
189
|
+
toast.warning(message.warning);
|
|
190
|
+
return;
|
|
90
191
|
}
|
|
192
|
+
const res = await CustomFetch(url, method, {
|
|
193
|
+
...data,
|
|
194
|
+
rows: rowsSelected,
|
|
195
|
+
});
|
|
196
|
+
if (res.data.error === '') {
|
|
197
|
+
toast.success(message.success);
|
|
198
|
+
gridRef.current.reload();
|
|
199
|
+
} else {
|
|
200
|
+
toast.error(message.error);
|
|
201
|
+
}
|
|
202
|
+
} catch (error) {
|
|
203
|
+
console.error(error);
|
|
91
204
|
}
|
|
92
|
-
}, [
|
|
205
|
+
}, [rowsSelected, setting?.functions?.checkboxUpdate]);
|
|
93
206
|
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
207
|
+
const renderTable = useCallback(
|
|
208
|
+
() =>
|
|
209
|
+
config.ajaxSetting &&
|
|
210
|
+
config.form &&
|
|
211
|
+
config.columns &&
|
|
212
|
+
config.settings ? (
|
|
213
|
+
<Table
|
|
214
|
+
{...config}
|
|
215
|
+
ref={gridRef}
|
|
216
|
+
gridHeight={windowHeight * 0.65}
|
|
217
|
+
setConfig={setConfig}
|
|
218
|
+
setTotal={setTotal}
|
|
219
|
+
style={userProfile?.settings?.style || {}}
|
|
220
|
+
/>
|
|
221
|
+
) : null,
|
|
222
|
+
[config, windowHeight, userProfile, setConfig, setTotal]
|
|
223
|
+
);
|
|
98
224
|
|
|
99
|
-
|
|
225
|
+
const renderContentBasedOnType = useCallback(() => {
|
|
226
|
+
switch (config.type) {
|
|
227
|
+
case 'table':
|
|
228
|
+
return renderTable();
|
|
229
|
+
case 'report':
|
|
230
|
+
return <ReportForm config={config} userProfile={userProfile} />;
|
|
231
|
+
default:
|
|
232
|
+
return renderTable(); // Fallback to table if no type is specified or recognized
|
|
233
|
+
}
|
|
234
|
+
}, [config, renderTable]);
|
|
100
235
|
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
236
|
+
const renderContent = useCallback(
|
|
237
|
+
() => (
|
|
238
|
+
<div className={`grid__${subnav?.length > 0 ? 'subrow' : 'full'}`}>
|
|
239
|
+
{subnav?.length > 0 && (
|
|
240
|
+
<div
|
|
241
|
+
className={`grid__${
|
|
242
|
+
layout === 'full' ? 'subnav' : 'full'
|
|
243
|
+
}`}
|
|
244
|
+
>
|
|
245
|
+
<TableFilter
|
|
246
|
+
filters={subnav}
|
|
247
|
+
setFilters={setSubnav}
|
|
248
|
+
setSettings={setConfig}
|
|
249
|
+
type={layout}
|
|
250
|
+
/>
|
|
251
|
+
</div>
|
|
252
|
+
)}
|
|
253
|
+
<div
|
|
254
|
+
className={`grid__${
|
|
255
|
+
subnav?.length > 0 ? 'subcontent' : 'full'
|
|
256
|
+
}`}
|
|
257
|
+
>
|
|
258
|
+
{renderContentBasedOnType()}
|
|
259
|
+
</div>
|
|
260
|
+
</div>
|
|
261
|
+
),
|
|
262
|
+
[layout, subnav, setSubnav, setConfig, renderTable]
|
|
263
|
+
);
|
|
106
264
|
|
|
107
265
|
return (
|
|
108
266
|
<>
|
|
109
267
|
<div className="grid">
|
|
110
268
|
<div className="grid__row">
|
|
111
269
|
<div className="grid__full crmtitle">
|
|
112
|
-
<h1>{
|
|
270
|
+
<h1>{setting.page?.title}</h1>
|
|
113
271
|
<div className="titleInfo">
|
|
114
272
|
<span>
|
|
115
|
-
[<strong>{total}</strong> Total
|
|
273
|
+
[<strong>{total}</strong> Total{' '}
|
|
274
|
+
{setting.page?.title}]
|
|
116
275
|
</span>
|
|
117
276
|
</div>
|
|
118
277
|
</div>
|
|
119
278
|
</div>
|
|
279
|
+
{renderContent()}
|
|
120
280
|
</div>
|
|
121
|
-
|
|
122
|
-
{
|
|
123
|
-
config.form &&
|
|
124
|
-
config.columns &&
|
|
125
|
-
config.settings ? (
|
|
126
|
-
<>
|
|
127
|
-
<div className="grid">
|
|
128
|
-
{subnav && subnav.length > 0 ? (
|
|
129
|
-
<div className="grid__subrow">
|
|
130
|
-
{layout === 'full' ? (
|
|
131
|
-
<>
|
|
132
|
-
<div className={`grid__subnav`}>
|
|
133
|
-
<TableFilter
|
|
134
|
-
filters={subnav}
|
|
135
|
-
setFilters={setSubnav}
|
|
136
|
-
setSettings={setConfig}
|
|
137
|
-
type={layout}
|
|
138
|
-
/>
|
|
139
|
-
</div>
|
|
140
|
-
<div className={`grid__subcontent`}>
|
|
141
|
-
<Table
|
|
142
|
-
{...config}
|
|
143
|
-
ref={gridRef}
|
|
144
|
-
gridHeight={windowHeight * 0.65}
|
|
145
|
-
setConfig={setConfig}
|
|
146
|
-
setTotal={setTotal}
|
|
147
|
-
style={
|
|
148
|
-
userProfile?.settings
|
|
149
|
-
?.style || {}
|
|
150
|
-
}
|
|
151
|
-
/>
|
|
152
|
-
</div>
|
|
153
|
-
</>
|
|
154
|
-
) : (
|
|
155
|
-
<div className="grid__full">
|
|
156
|
-
<div className="tabcontent">
|
|
157
|
-
<div className={`tabcontent__menu`}>
|
|
158
|
-
<TableFilter
|
|
159
|
-
filters={subnav}
|
|
160
|
-
setFilters={setSubnav}
|
|
161
|
-
setSettings={setConfig}
|
|
162
|
-
type={layout}
|
|
163
|
-
/>
|
|
164
|
-
</div>
|
|
165
|
-
<div className={`tabcontent__main`}>
|
|
166
|
-
<Table
|
|
167
|
-
{...config}
|
|
168
|
-
ref={gridRef}
|
|
169
|
-
gridHeight={
|
|
170
|
-
windowHeight * 0.65
|
|
171
|
-
}
|
|
172
|
-
setConfig={setConfig}
|
|
173
|
-
setTotal={setTotal}
|
|
174
|
-
style={
|
|
175
|
-
userProfile?.settings
|
|
176
|
-
?.style || {}
|
|
177
|
-
}
|
|
178
|
-
/>
|
|
179
|
-
</div>
|
|
180
|
-
</div>
|
|
181
|
-
</div>
|
|
182
|
-
)}
|
|
183
|
-
</div>
|
|
184
|
-
) : (
|
|
185
|
-
<div className="grid__full">
|
|
186
|
-
<Table
|
|
187
|
-
{...config}
|
|
188
|
-
ref={gridRef}
|
|
189
|
-
gridHeight={windowHeight * 0.65}
|
|
190
|
-
setConfig={setConfig}
|
|
191
|
-
setTotal={setTotal}
|
|
192
|
-
style={userProfile?.settings?.style || {}}
|
|
193
|
-
/>
|
|
194
|
-
</div>
|
|
195
|
-
)}
|
|
196
|
-
</div>
|
|
197
|
-
<Outlet />
|
|
198
|
-
</>
|
|
199
|
-
) : null}
|
|
200
|
-
|
|
201
|
-
{functions && functions.checkboxUpdate ? (
|
|
281
|
+
<Outlet />
|
|
282
|
+
{setting.functions?.checkboxUpdate && (
|
|
202
283
|
<div className="polActions">
|
|
203
284
|
<button className="btn" onClick={handleCheckboxUpdate}>
|
|
204
|
-
{functions.checkboxUpdate.label
|
|
205
|
-
? functions.checkboxUpdate.label
|
|
206
|
-
: 'Update'}
|
|
285
|
+
{setting.functions.checkboxUpdate.label || 'Update'}
|
|
207
286
|
</button>
|
|
208
287
|
</div>
|
|
209
|
-
)
|
|
288
|
+
)}
|
|
210
289
|
</>
|
|
211
290
|
);
|
|
212
291
|
}
|
package/package.json
CHANGED