@visns-studio/visns-components 4.0.9 → 4.1.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.
- package/components/cms/sorting/Item.jsx +1 -1
- package/components/crm/Field.jsx +100 -0
- package/components/crm/auth/Profile.jsx +2 -2
- package/components/crm/generic/GenericFormBuilder.jsx +231 -2
- package/components/crm/generic/GenericIndex.jsx +1 -1
- package/components/crm/generic/styles/GenericFormBuilder.module.css +13 -10
- package/components/crm/styles/Field.module.css +76 -0
- package/package.json +1 -1
package/components/crm/Field.jsx
CHANGED
|
@@ -254,6 +254,8 @@ function Field({
|
|
|
254
254
|
'radio-ajax',
|
|
255
255
|
'richeditor',
|
|
256
256
|
'signature',
|
|
257
|
+
'table_radio',
|
|
258
|
+
'table_text',
|
|
257
259
|
'time',
|
|
258
260
|
].includes(settings.type)
|
|
259
261
|
) {
|
|
@@ -1096,6 +1098,102 @@ function Field({
|
|
|
1096
1098
|
)}
|
|
1097
1099
|
</>
|
|
1098
1100
|
);
|
|
1101
|
+
case 'table_radio':
|
|
1102
|
+
let tableRadioColumns = [];
|
|
1103
|
+
let tableRadioRows = [];
|
|
1104
|
+
|
|
1105
|
+
for (const key in formData) {
|
|
1106
|
+
if (formData[key].id === settings.id) {
|
|
1107
|
+
if (formData[key].hasOwnProperty('options')) {
|
|
1108
|
+
tableRadioColumns = formData[key].options;
|
|
1109
|
+
tableRadioRows = formData[key].rows;
|
|
1110
|
+
break; // Assuming there's only one match needed, break out of the loop
|
|
1111
|
+
}
|
|
1112
|
+
}
|
|
1113
|
+
}
|
|
1114
|
+
|
|
1115
|
+
return (
|
|
1116
|
+
<table className={styles.contentTable}>
|
|
1117
|
+
<thead>
|
|
1118
|
+
<tr>
|
|
1119
|
+
<th></th>
|
|
1120
|
+
{tableRadioColumns.map((column, columnKey) => (
|
|
1121
|
+
<th
|
|
1122
|
+
key={`${settings.id}-${columnKey.id}`}
|
|
1123
|
+
style={{
|
|
1124
|
+
width: '250px',
|
|
1125
|
+
whiteSpace: 'nowrap',
|
|
1126
|
+
}}
|
|
1127
|
+
>
|
|
1128
|
+
{column.label}
|
|
1129
|
+
</th>
|
|
1130
|
+
))}
|
|
1131
|
+
</tr>
|
|
1132
|
+
</thead>
|
|
1133
|
+
<tbody>
|
|
1134
|
+
{tableRadioRows.map((row, rowKey) => (
|
|
1135
|
+
<tr
|
|
1136
|
+
key={`table-radio-row-${settings.id}-${rowKey}`}
|
|
1137
|
+
>
|
|
1138
|
+
<td
|
|
1139
|
+
style={{
|
|
1140
|
+
whiteSpace: 'nowrap',
|
|
1141
|
+
}}
|
|
1142
|
+
>
|
|
1143
|
+
{row.label}
|
|
1144
|
+
</td>
|
|
1145
|
+
{tableRadioColumns.map(
|
|
1146
|
+
(column, columnKey) => (
|
|
1147
|
+
<td
|
|
1148
|
+
key={`table-radio-cell-${settings.id}-${rowKey}-${columnKey}`}
|
|
1149
|
+
>
|
|
1150
|
+
<input
|
|
1151
|
+
type="radio"
|
|
1152
|
+
name={`radio-${settings.id}-${rowKey}`}
|
|
1153
|
+
/>
|
|
1154
|
+
</td>
|
|
1155
|
+
)
|
|
1156
|
+
)}
|
|
1157
|
+
</tr>
|
|
1158
|
+
))}
|
|
1159
|
+
</tbody>
|
|
1160
|
+
</table>
|
|
1161
|
+
);
|
|
1162
|
+
case 'table_text':
|
|
1163
|
+
let tableTextColumns = [];
|
|
1164
|
+
|
|
1165
|
+
for (const key in formData) {
|
|
1166
|
+
if (formData[key].id === settings.id) {
|
|
1167
|
+
if (formData[key].hasOwnProperty('options')) {
|
|
1168
|
+
tableTextColumns = formData[key].options;
|
|
1169
|
+
break; // Assuming there's only one match needed, break out of the loop
|
|
1170
|
+
}
|
|
1171
|
+
}
|
|
1172
|
+
}
|
|
1173
|
+
return (
|
|
1174
|
+
<table className={styles.contentTable}>
|
|
1175
|
+
<thead>
|
|
1176
|
+
<tr>
|
|
1177
|
+
{tableTextColumns.map((column, columnKey) => (
|
|
1178
|
+
<th key={`${settings.id}-${columnKey.id}`}>
|
|
1179
|
+
{column.label}
|
|
1180
|
+
</th>
|
|
1181
|
+
))}
|
|
1182
|
+
</tr>
|
|
1183
|
+
</thead>
|
|
1184
|
+
<tbody>
|
|
1185
|
+
<tr>
|
|
1186
|
+
{tableTextColumns.map((column, columnKey) => (
|
|
1187
|
+
<td
|
|
1188
|
+
key={`${settings.id}-${columnKey.id}-input`}
|
|
1189
|
+
>
|
|
1190
|
+
<input type="text" />
|
|
1191
|
+
</td>
|
|
1192
|
+
))}
|
|
1193
|
+
</tr>
|
|
1194
|
+
</tbody>
|
|
1195
|
+
</table>
|
|
1196
|
+
);
|
|
1099
1197
|
case 'textarea':
|
|
1100
1198
|
return (
|
|
1101
1199
|
<textarea
|
|
@@ -1160,6 +1258,8 @@ function Field({
|
|
|
1160
1258
|
'radio-ajax',
|
|
1161
1259
|
'richeditor',
|
|
1162
1260
|
'signature',
|
|
1261
|
+
'table_radio',
|
|
1262
|
+
'table_text',
|
|
1163
1263
|
'time',
|
|
1164
1264
|
'toggle',
|
|
1165
1265
|
].includes(settings.type)
|
|
@@ -101,8 +101,8 @@ const Profile = ({ userProfile, setUserProfile }) => {
|
|
|
101
101
|
|
|
102
102
|
setUserProfile((prevState) => ({
|
|
103
103
|
...prevState,
|
|
104
|
-
name: res.data.name,
|
|
105
|
-
signature: res.data.signature,
|
|
104
|
+
name: res.data.user.name,
|
|
105
|
+
signature: res.data.user.signature,
|
|
106
106
|
}));
|
|
107
107
|
toast.success('Your profile has been successfully updated.');
|
|
108
108
|
} catch (err) {
|
|
@@ -34,6 +34,7 @@ function GenericFormBuilder({ setting, urlParam, userProfile }) {
|
|
|
34
34
|
description: '',
|
|
35
35
|
type: '',
|
|
36
36
|
options: [],
|
|
37
|
+
rows: [],
|
|
37
38
|
size: 'quarter',
|
|
38
39
|
required: 'no',
|
|
39
40
|
});
|
|
@@ -41,6 +42,10 @@ function GenericFormBuilder({ setting, urlParam, userProfile }) {
|
|
|
41
42
|
id: '',
|
|
42
43
|
label: '',
|
|
43
44
|
});
|
|
45
|
+
const [rowOption, setRowOption] = useState({
|
|
46
|
+
id: '',
|
|
47
|
+
label: '',
|
|
48
|
+
});
|
|
44
49
|
const [modalShow, setModalShow] = useState(false);
|
|
45
50
|
const [modalType, setModalType] = useState({
|
|
46
51
|
type: 'create',
|
|
@@ -101,6 +106,59 @@ function GenericFormBuilder({ setting, urlParam, userProfile }) {
|
|
|
101
106
|
});
|
|
102
107
|
};
|
|
103
108
|
|
|
109
|
+
/** Row Option Functionalities */
|
|
110
|
+
const handleRowOption = (e) => {
|
|
111
|
+
const { name, value } = e.target;
|
|
112
|
+
|
|
113
|
+
setRowOption((items) => ({
|
|
114
|
+
...items,
|
|
115
|
+
[name]: value,
|
|
116
|
+
id: `${slugify(value)}-`,
|
|
117
|
+
}));
|
|
118
|
+
};
|
|
119
|
+
|
|
120
|
+
const handleAddRowOption = (e) => {
|
|
121
|
+
e.preventDefault();
|
|
122
|
+
|
|
123
|
+
if (rowOption.label !== '') {
|
|
124
|
+
const isLabelUnique = !dataField.rows.some(
|
|
125
|
+
(option) => option.label === rowOption.label
|
|
126
|
+
);
|
|
127
|
+
|
|
128
|
+
if (isLabelUnique) {
|
|
129
|
+
setDataField((items) => ({
|
|
130
|
+
...items,
|
|
131
|
+
rows: [...items.rows, rowOption],
|
|
132
|
+
}));
|
|
133
|
+
|
|
134
|
+
setRowOption(() => ({
|
|
135
|
+
id: '',
|
|
136
|
+
label: '',
|
|
137
|
+
}));
|
|
138
|
+
} else {
|
|
139
|
+
toast.warn('Option label must be unique.');
|
|
140
|
+
}
|
|
141
|
+
} else {
|
|
142
|
+
toast.warn('Please enter a label for the option.');
|
|
143
|
+
}
|
|
144
|
+
};
|
|
145
|
+
|
|
146
|
+
const handleDeleteRowOption = (e) => {
|
|
147
|
+
e.preventDefault();
|
|
148
|
+
|
|
149
|
+
const { counter } = e.target.dataset;
|
|
150
|
+
|
|
151
|
+
setDataField((prevState) => {
|
|
152
|
+
const rows = prevState.rows.slice();
|
|
153
|
+
rows.splice(counter, 1);
|
|
154
|
+
|
|
155
|
+
return {
|
|
156
|
+
...prevState,
|
|
157
|
+
rows: rows,
|
|
158
|
+
};
|
|
159
|
+
});
|
|
160
|
+
};
|
|
161
|
+
|
|
104
162
|
/** Field Functionalities */
|
|
105
163
|
const onSortEnd = ({ oldIndex, newIndex }) => {
|
|
106
164
|
const newData = arrayMoveImmutable(data.detail, oldIndex, newIndex);
|
|
@@ -462,7 +520,36 @@ function GenericFormBuilder({ setting, urlParam, userProfile }) {
|
|
|
462
520
|
case 'table_radio':
|
|
463
521
|
return (
|
|
464
522
|
<label className={styles.fi__label}>
|
|
465
|
-
<table className={styles.contentTable}
|
|
523
|
+
<table className={styles.contentTable}>
|
|
524
|
+
<thead>
|
|
525
|
+
<tr>
|
|
526
|
+
<th></th>
|
|
527
|
+
{field.options.map((option, index) => (
|
|
528
|
+
<th
|
|
529
|
+
key={`${field.id}-table-text-option-${index}`}
|
|
530
|
+
>
|
|
531
|
+
{option.label}
|
|
532
|
+
</th>
|
|
533
|
+
))}
|
|
534
|
+
</tr>
|
|
535
|
+
</thead>
|
|
536
|
+
<tbody>
|
|
537
|
+
{field.rows.map((row, rowKey) => (
|
|
538
|
+
<tr
|
|
539
|
+
key={`${field.id}-table-text-row-data-${rowKey}`}
|
|
540
|
+
>
|
|
541
|
+
<td>{row.label}</td>
|
|
542
|
+
{field.options.map(
|
|
543
|
+
(option, optionKey) => (
|
|
544
|
+
<td
|
|
545
|
+
key={`${field.id}-table-text-data-${optionKey}-${rowKey}`}
|
|
546
|
+
></td>
|
|
547
|
+
)
|
|
548
|
+
)}
|
|
549
|
+
</tr>
|
|
550
|
+
))}
|
|
551
|
+
</tbody>
|
|
552
|
+
</table>
|
|
466
553
|
<span
|
|
467
554
|
className={`${styles.fi__span} ${styles.prefocus}`}
|
|
468
555
|
>
|
|
@@ -1008,7 +1095,9 @@ function GenericFormBuilder({ setting, urlParam, userProfile }) {
|
|
|
1008
1095
|
}}
|
|
1009
1096
|
>
|
|
1010
1097
|
{dataField.type ===
|
|
1011
|
-
|
|
1098
|
+
'table_text' ||
|
|
1099
|
+
dataField.type ===
|
|
1100
|
+
'table_radio'
|
|
1012
1101
|
? 'Column Header'
|
|
1013
1102
|
: 'Label'}
|
|
1014
1103
|
</th>
|
|
@@ -1131,6 +1220,146 @@ function GenericFormBuilder({ setting, urlParam, userProfile }) {
|
|
|
1131
1220
|
</table>
|
|
1132
1221
|
</div>
|
|
1133
1222
|
) : null}
|
|
1223
|
+
|
|
1224
|
+
{['table_radio'].includes(
|
|
1225
|
+
dataField.type
|
|
1226
|
+
) ? (
|
|
1227
|
+
<div
|
|
1228
|
+
className={`${styles.formItem} ${styles.fwItem}`}
|
|
1229
|
+
>
|
|
1230
|
+
<table
|
|
1231
|
+
className={styles.contentTable}
|
|
1232
|
+
>
|
|
1233
|
+
<thead
|
|
1234
|
+
className={
|
|
1235
|
+
styles.gridHeaders
|
|
1236
|
+
}
|
|
1237
|
+
>
|
|
1238
|
+
<tr>
|
|
1239
|
+
<th
|
|
1240
|
+
style={{
|
|
1241
|
+
width: '450px',
|
|
1242
|
+
}}
|
|
1243
|
+
>
|
|
1244
|
+
Row Label
|
|
1245
|
+
</th>
|
|
1246
|
+
<th></th>
|
|
1247
|
+
</tr>
|
|
1248
|
+
</thead>
|
|
1249
|
+
<tbody>
|
|
1250
|
+
{dataField.rows.length >
|
|
1251
|
+
0 ? (
|
|
1252
|
+
dataField.rows.map(
|
|
1253
|
+
(row, rowKey) => (
|
|
1254
|
+
<tr
|
|
1255
|
+
key={`row-${rowKey}`}
|
|
1256
|
+
>
|
|
1257
|
+
<td>
|
|
1258
|
+
{
|
|
1259
|
+
row.label
|
|
1260
|
+
}
|
|
1261
|
+
</td>
|
|
1262
|
+
<td
|
|
1263
|
+
style={{
|
|
1264
|
+
textAlign:
|
|
1265
|
+
'center',
|
|
1266
|
+
}}
|
|
1267
|
+
>
|
|
1268
|
+
<button
|
|
1269
|
+
className={
|
|
1270
|
+
styles.btn
|
|
1271
|
+
}
|
|
1272
|
+
style={{
|
|
1273
|
+
padding:
|
|
1274
|
+
'5px 20px',
|
|
1275
|
+
}}
|
|
1276
|
+
onClick={
|
|
1277
|
+
handleDeleteRowOption
|
|
1278
|
+
}
|
|
1279
|
+
data-counter={
|
|
1280
|
+
rowKey
|
|
1281
|
+
}
|
|
1282
|
+
data-tooltip-id="system-tooltip"
|
|
1283
|
+
data-tooltip-content={
|
|
1284
|
+
'Delete Option'
|
|
1285
|
+
}
|
|
1286
|
+
>
|
|
1287
|
+
<TrashCan
|
|
1288
|
+
strokeWidth={
|
|
1289
|
+
2
|
|
1290
|
+
}
|
|
1291
|
+
size={
|
|
1292
|
+
12
|
|
1293
|
+
}
|
|
1294
|
+
/>
|
|
1295
|
+
</button>
|
|
1296
|
+
</td>
|
|
1297
|
+
</tr>
|
|
1298
|
+
)
|
|
1299
|
+
)
|
|
1300
|
+
) : (
|
|
1301
|
+
<tr>
|
|
1302
|
+
<td colSpan="2">
|
|
1303
|
+
No entry have
|
|
1304
|
+
been added.
|
|
1305
|
+
</td>
|
|
1306
|
+
</tr>
|
|
1307
|
+
)}
|
|
1308
|
+
</tbody>
|
|
1309
|
+
<tfoot>
|
|
1310
|
+
<tr>
|
|
1311
|
+
<td>
|
|
1312
|
+
<input
|
|
1313
|
+
type="text"
|
|
1314
|
+
style={{
|
|
1315
|
+
padding:
|
|
1316
|
+
'5px',
|
|
1317
|
+
}}
|
|
1318
|
+
name="label"
|
|
1319
|
+
onChange={
|
|
1320
|
+
handleRowOption
|
|
1321
|
+
}
|
|
1322
|
+
value={
|
|
1323
|
+
rowOption.label
|
|
1324
|
+
}
|
|
1325
|
+
/>
|
|
1326
|
+
</td>
|
|
1327
|
+
<td
|
|
1328
|
+
style={{
|
|
1329
|
+
textAlign:
|
|
1330
|
+
'center',
|
|
1331
|
+
}}
|
|
1332
|
+
>
|
|
1333
|
+
<button
|
|
1334
|
+
className={
|
|
1335
|
+
styles.btn
|
|
1336
|
+
}
|
|
1337
|
+
style={{
|
|
1338
|
+
padding:
|
|
1339
|
+
'5px 20px',
|
|
1340
|
+
}}
|
|
1341
|
+
onClick={
|
|
1342
|
+
handleAddRowOption
|
|
1343
|
+
}
|
|
1344
|
+
data-tooltip-id="system-tooltip"
|
|
1345
|
+
data-tooltip-content={
|
|
1346
|
+
'Add Option'
|
|
1347
|
+
}
|
|
1348
|
+
>
|
|
1349
|
+
<CirclePlus
|
|
1350
|
+
strokeWidth={
|
|
1351
|
+
2
|
|
1352
|
+
}
|
|
1353
|
+
size={12}
|
|
1354
|
+
/>
|
|
1355
|
+
</button>
|
|
1356
|
+
</td>
|
|
1357
|
+
</tr>
|
|
1358
|
+
</tfoot>
|
|
1359
|
+
</table>
|
|
1360
|
+
</div>
|
|
1361
|
+
) : null}
|
|
1362
|
+
|
|
1134
1363
|
<div
|
|
1135
1364
|
className={`${styles.formItem} ${styles.fwItem} ${styles.lastItem}`}
|
|
1136
1365
|
>
|
|
@@ -863,15 +863,14 @@ select:not(:placeholder-shown) + .fi__span {
|
|
|
863
863
|
}
|
|
864
864
|
|
|
865
865
|
.sortlist li .delete {
|
|
866
|
-
width:
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
overflow: hidden;
|
|
866
|
+
width: 100%;
|
|
867
|
+
max-width: 18px;
|
|
868
|
+
position: absolute;
|
|
869
|
+
left: 5px;
|
|
870
|
+
top: 30px;
|
|
872
871
|
}
|
|
873
872
|
|
|
874
|
-
.sortlist li .
|
|
873
|
+
.sortlist li .sortimg img {
|
|
875
874
|
display: block;
|
|
876
875
|
object-fit: cover;
|
|
877
876
|
height: 100%;
|
|
@@ -906,7 +905,7 @@ select:not(:placeholder-shown) + .fi__span {
|
|
|
906
905
|
color: var(--paragraph-color);
|
|
907
906
|
}
|
|
908
907
|
|
|
909
|
-
.dragitem svg {
|
|
908
|
+
.dragitem svg:first-of-type {
|
|
910
909
|
width: 100%;
|
|
911
910
|
max-width: 18px;
|
|
912
911
|
position: absolute;
|
|
@@ -914,8 +913,12 @@ select:not(:placeholder-shown) + .fi__span {
|
|
|
914
913
|
top: 5px;
|
|
915
914
|
}
|
|
916
915
|
|
|
917
|
-
.dragitem
|
|
918
|
-
|
|
916
|
+
.dragitem svg:nth-of-type(2) {
|
|
917
|
+
width: 100%;
|
|
918
|
+
max-width: 18px;
|
|
919
|
+
position: absolute;
|
|
920
|
+
left: 5px;
|
|
921
|
+
top: 30px;
|
|
919
922
|
}
|
|
920
923
|
|
|
921
924
|
.dragitem .sortimg {
|
|
@@ -144,3 +144,79 @@ input[type='file']:hover {
|
|
|
144
144
|
background: var(--secondary-color);
|
|
145
145
|
color: var(--primary-color);
|
|
146
146
|
}
|
|
147
|
+
|
|
148
|
+
/* Table Styles */
|
|
149
|
+
|
|
150
|
+
.contentTable {
|
|
151
|
+
width: 100%;
|
|
152
|
+
border-collapse: collapse;
|
|
153
|
+
margin: 0 auto;
|
|
154
|
+
font-size: 1em;
|
|
155
|
+
border-radius: var(--br) var(--br) 0 0;
|
|
156
|
+
overflow: hidden;
|
|
157
|
+
border: none;
|
|
158
|
+
border-spacing: 0;
|
|
159
|
+
box-sizing: border-box;
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
.contentTable thead {
|
|
163
|
+
display: table-row-group;
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
.contentTable thead tr {
|
|
167
|
+
background: var(--table-color);
|
|
168
|
+
color: var(--primary-color);
|
|
169
|
+
text-align: left;
|
|
170
|
+
font-weight: 700;
|
|
171
|
+
text-transform: capitalize;
|
|
172
|
+
font-size: 1em;
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
.contentTable .filterRow th {
|
|
176
|
+
padding: 0;
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
.contentTable th,
|
|
180
|
+
.contentTable td {
|
|
181
|
+
font-size: 0.95em;
|
|
182
|
+
padding: 8px 15px;
|
|
183
|
+
color: var(--paragraph-color);
|
|
184
|
+
border-right: 1px solid var(--table-border);
|
|
185
|
+
line-height: 1;
|
|
186
|
+
border-spacing: 0;
|
|
187
|
+
border-collapse: collapse;
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
.contentTable th:last-of-type,
|
|
191
|
+
.contentTable td:last-of-type,
|
|
192
|
+
.contentTable th:last-child,
|
|
193
|
+
.contentTable td:last-child {
|
|
194
|
+
border-right: none;
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
.contentTable td .tdActions {
|
|
198
|
+
width: 100%;
|
|
199
|
+
display: flex;
|
|
200
|
+
flex-wrap: nowrap;
|
|
201
|
+
justify-content: flex-start;
|
|
202
|
+
align-items: center;
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
.contentTable td .tdAction {
|
|
206
|
+
background: #f0f0f0;
|
|
207
|
+
display: block;
|
|
208
|
+
line-height: 1;
|
|
209
|
+
padding: 0.05rem;
|
|
210
|
+
border-radius: var(--br);
|
|
211
|
+
margin: 0 0.25rem;
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
.contentTable tbody tr {
|
|
215
|
+
border-bottom: 1px solid var(--table-border);
|
|
216
|
+
cursor: pointer;
|
|
217
|
+
background: var(--tertiary-color);
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
.contentTable tbody tr:nth-of-type(even) {
|
|
221
|
+
background: darken(var(--secondary-color), 2%);
|
|
222
|
+
}
|
package/package.json
CHANGED