@visns-studio/visns-components 5.5.6 → 5.5.8
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/package.json +11 -11
- package/src/components/crm/AsyncSelect.jsx +41 -1
- package/src/components/crm/DataGrid.jsx +107 -33
- package/src/components/crm/MultiSelect.jsx +50 -2
- package/src/components/crm/Navigation.jsx +12 -2
- package/src/components/crm/generic/GenericReport.jsx +787 -275
- package/src/components/crm/generic/styles/GenericReport.module.scss +200 -0
- package/src/components/crm/styles/DataGrid.module.scss +226 -44
- package/src/components/crm/styles/MultiSelect.module.scss +105 -1
- package/src/components/crm/styles/global-datagrid.css +34 -0
package/package.json
CHANGED
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
"@nivo/line": "^0.88.0",
|
|
10
10
|
"@nivo/pie": "^0.88.0",
|
|
11
11
|
"@tinymce/tinymce-react": "^6.1.0",
|
|
12
|
-
"@vitejs/plugin-react": "^4.4.
|
|
12
|
+
"@vitejs/plugin-react": "^4.4.1",
|
|
13
13
|
"add": "^2.0.6",
|
|
14
14
|
"akar-icons": "^1.9.31",
|
|
15
15
|
"array-move": "^4.0.0",
|
|
@@ -19,12 +19,12 @@
|
|
|
19
19
|
"dayjs": "^1.11.13",
|
|
20
20
|
"fabric": "^6.6.4",
|
|
21
21
|
"file-saver": "^2.0.5",
|
|
22
|
-
"framer-motion": "^
|
|
22
|
+
"framer-motion": "^12.7.4",
|
|
23
23
|
"html-react-parser": "^5.2.3",
|
|
24
24
|
"lodash": "^4.17.21",
|
|
25
25
|
"lodash.debounce": "^4.0.8",
|
|
26
26
|
"moment": "^2.30.1",
|
|
27
|
-
"motion": "^
|
|
27
|
+
"motion": "^12.7.4",
|
|
28
28
|
"numeral": "^2.0.6",
|
|
29
29
|
"pluralize": "^8.0.0",
|
|
30
30
|
"qrcode.react": "^4.2.0",
|
|
@@ -33,7 +33,7 @@
|
|
|
33
33
|
"react-color": "^2.19.3",
|
|
34
34
|
"react-confirm-alert": "^3.0.6",
|
|
35
35
|
"react-copy-to-clipboard": "^5.1.0",
|
|
36
|
-
"react-datepicker": "^
|
|
36
|
+
"react-datepicker": "^8.3.0",
|
|
37
37
|
"react-dropzone": "^14.3.8",
|
|
38
38
|
"react-grid-gallery": "^1.0.1",
|
|
39
39
|
"react-number-format": "^5.4.4",
|
|
@@ -46,8 +46,8 @@
|
|
|
46
46
|
"react-signature-pad-wrapper": "^4.1.0",
|
|
47
47
|
"react-slugify": "^4.0.1",
|
|
48
48
|
"react-sortable-hoc": "^2.0.0",
|
|
49
|
-
"react-to-print": "^
|
|
50
|
-
"react-toastify": "^
|
|
49
|
+
"react-to-print": "^3.0.6",
|
|
50
|
+
"react-toastify": "^11.0.5",
|
|
51
51
|
"react-toggle": "^4.1.3",
|
|
52
52
|
"react-tooltip": "^5.28.1",
|
|
53
53
|
"react-window": "^1.8.11",
|
|
@@ -56,7 +56,7 @@
|
|
|
56
56
|
"swapy": "^1.0.5",
|
|
57
57
|
"sweetalert2": "^11.19.1",
|
|
58
58
|
"truncate": "^3.0.0",
|
|
59
|
-
"uuid": "^
|
|
59
|
+
"uuid": "^11.1.0",
|
|
60
60
|
"validator": "^13.15.0",
|
|
61
61
|
"vite": "^5.4.18",
|
|
62
62
|
"yarn": "^1.22.22",
|
|
@@ -67,8 +67,8 @@
|
|
|
67
67
|
"@babel/plugin-transform-runtime": "^7.26.10",
|
|
68
68
|
"@babel/preset-env": "^7.26.9",
|
|
69
69
|
"@babel/preset-react": "^7.26.3",
|
|
70
|
-
"babel-loader": "^
|
|
71
|
-
"copy-webpack-plugin": "^
|
|
70
|
+
"babel-loader": "^10.0.0",
|
|
71
|
+
"copy-webpack-plugin": "^13.0.0",
|
|
72
72
|
"css-loader": "^7.1.2",
|
|
73
73
|
"css-minimizer-webpack-plugin": "^7.0.2",
|
|
74
74
|
"mini-css-extract-plugin": "^2.9.2",
|
|
@@ -82,7 +82,7 @@
|
|
|
82
82
|
"react-dom": "^17.0.0 || ^18.0.0"
|
|
83
83
|
},
|
|
84
84
|
"name": "@visns-studio/visns-components",
|
|
85
|
-
"version": "5.5.
|
|
85
|
+
"version": "5.5.8",
|
|
86
86
|
"description": "Various packages to assist in the development of our Custom Applications.",
|
|
87
87
|
"main": "src/index.js",
|
|
88
88
|
"files": [
|
|
@@ -103,5 +103,5 @@
|
|
|
103
103
|
"url": "https://github.com/visnsstudio/visns-components/issues"
|
|
104
104
|
},
|
|
105
105
|
"homepage": "https://github.com/visnsstudio/visns-components#readme",
|
|
106
|
-
"packageManager": "yarn@4.
|
|
106
|
+
"packageManager": "yarn@4.8.1"
|
|
107
107
|
}
|
|
@@ -223,7 +223,47 @@ function VisnsAsyncSelect({
|
|
|
223
223
|
minHeight:
|
|
224
224
|
style && style.multi_select_height
|
|
225
225
|
? style.multi_select_height
|
|
226
|
-
: '
|
|
226
|
+
: '50px',
|
|
227
|
+
height: 'auto', // Allow height to grow with content
|
|
228
|
+
}),
|
|
229
|
+
valueContainer: (base) => ({
|
|
230
|
+
...base,
|
|
231
|
+
padding: '2px 8px',
|
|
232
|
+
display: 'flex',
|
|
233
|
+
alignItems: 'flex-start',
|
|
234
|
+
flexWrap: 'wrap',
|
|
235
|
+
maxHeight: '100px', // Set a max height
|
|
236
|
+
overflowY: 'auto', // Add scrolling when needed
|
|
237
|
+
}),
|
|
238
|
+
indicatorsContainer: (base) => ({
|
|
239
|
+
...base,
|
|
240
|
+
height: 'auto',
|
|
241
|
+
display: 'flex',
|
|
242
|
+
alignItems: 'center',
|
|
243
|
+
alignSelf: 'stretch', // Stretch to full height of container
|
|
244
|
+
}),
|
|
245
|
+
dropdownIndicator: (base) => ({
|
|
246
|
+
...base,
|
|
247
|
+
padding: '8px',
|
|
248
|
+
display: 'flex',
|
|
249
|
+
alignItems: 'center',
|
|
250
|
+
alignSelf: 'stretch', // Stretch to full height
|
|
251
|
+
}),
|
|
252
|
+
clearIndicator: (base) => ({
|
|
253
|
+
...base,
|
|
254
|
+
padding: '8px',
|
|
255
|
+
display: 'flex',
|
|
256
|
+
alignItems: 'center',
|
|
257
|
+
alignSelf: 'stretch', // Stretch to full height
|
|
258
|
+
}),
|
|
259
|
+
indicatorSeparator: (base) => ({
|
|
260
|
+
...base,
|
|
261
|
+
alignSelf: 'stretch', // Stretch to full height
|
|
262
|
+
margin: '4px 0',
|
|
263
|
+
}),
|
|
264
|
+
multiValue: (base) => ({
|
|
265
|
+
...base,
|
|
266
|
+
margin: '2px',
|
|
227
267
|
}),
|
|
228
268
|
input: (styles) => ({
|
|
229
269
|
...styles,
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import '../styles/global.css';
|
|
2
|
+
import './styles/global-datagrid.css';
|
|
2
3
|
|
|
3
4
|
import React, {
|
|
4
5
|
forwardRef,
|
|
@@ -53,6 +54,7 @@ import {
|
|
|
53
54
|
LinkOut,
|
|
54
55
|
LockOn,
|
|
55
56
|
Network,
|
|
57
|
+
Plus,
|
|
56
58
|
Ribbon,
|
|
57
59
|
Search,
|
|
58
60
|
ShippingBoxV1,
|
|
@@ -1081,15 +1083,36 @@ const DataGrid = forwardRef(
|
|
|
1081
1083
|
return null;
|
|
1082
1084
|
}
|
|
1083
1085
|
|
|
1086
|
+
const isSearchEnabled = !(form.searchDisable === true);
|
|
1087
|
+
const buttonClassName = isSearchEnabled
|
|
1088
|
+
? styles.actionButtons
|
|
1089
|
+
: styles.actionButtonsStandalone;
|
|
1090
|
+
|
|
1084
1091
|
return (
|
|
1085
|
-
<div className={
|
|
1092
|
+
<div className={buttonClassName}>
|
|
1086
1093
|
{form.export && form.export.url && (
|
|
1087
|
-
<button
|
|
1094
|
+
<button
|
|
1095
|
+
className={styles.btn}
|
|
1096
|
+
style={{
|
|
1097
|
+
borderRadius: isSearchEnabled
|
|
1098
|
+
? 0
|
|
1099
|
+
: 'var(--br, 4px)',
|
|
1100
|
+
}}
|
|
1101
|
+
onClick={exportTrigger}
|
|
1102
|
+
>
|
|
1088
1103
|
Export
|
|
1089
1104
|
</button>
|
|
1090
1105
|
)}
|
|
1091
1106
|
{form.sort && form.sort.title && (
|
|
1092
|
-
<button
|
|
1107
|
+
<button
|
|
1108
|
+
className={styles.btn}
|
|
1109
|
+
style={{
|
|
1110
|
+
borderRadius: isSearchEnabled
|
|
1111
|
+
? 0
|
|
1112
|
+
: 'var(--br, 4px)',
|
|
1113
|
+
}}
|
|
1114
|
+
onClick={sortTrigger}
|
|
1115
|
+
>
|
|
1093
1116
|
<div className="icon-plus"></div> Sort Order
|
|
1094
1117
|
</button>
|
|
1095
1118
|
)}
|
|
@@ -1100,6 +1123,11 @@ const DataGrid = forwardRef(
|
|
|
1100
1123
|
(form.url && form.create?.title !== '') ? (
|
|
1101
1124
|
<button
|
|
1102
1125
|
className={styles.btn}
|
|
1126
|
+
style={{
|
|
1127
|
+
borderRadius: isSearchEnabled
|
|
1128
|
+
? 0
|
|
1129
|
+
: 'var(--br, 4px)',
|
|
1130
|
+
}}
|
|
1103
1131
|
onClick={(e) => {
|
|
1104
1132
|
e.preventDefault();
|
|
1105
1133
|
|
|
@@ -1135,11 +1163,21 @@ const DataGrid = forwardRef(
|
|
|
1135
1163
|
}
|
|
1136
1164
|
}}
|
|
1137
1165
|
>
|
|
1138
|
-
<
|
|
1166
|
+
<Plus
|
|
1167
|
+
strokeWidth={2}
|
|
1168
|
+
size={16}
|
|
1169
|
+
style={{ marginRight: '10px' }}
|
|
1170
|
+
/>
|
|
1171
|
+
Add New
|
|
1139
1172
|
</button>
|
|
1140
1173
|
) : form.url && form.modal === false ? (
|
|
1141
1174
|
<button
|
|
1142
1175
|
className={styles.btn}
|
|
1176
|
+
style={{
|
|
1177
|
+
borderRadius: isSearchEnabled
|
|
1178
|
+
? 0
|
|
1179
|
+
: 'var(--br, 4px)',
|
|
1180
|
+
}}
|
|
1143
1181
|
onClick={(e) => {
|
|
1144
1182
|
e.preventDefault();
|
|
1145
1183
|
|
|
@@ -1150,7 +1188,12 @@ const DataGrid = forwardRef(
|
|
|
1150
1188
|
);
|
|
1151
1189
|
}}
|
|
1152
1190
|
>
|
|
1153
|
-
<
|
|
1191
|
+
<Plus
|
|
1192
|
+
strokeWidth={2}
|
|
1193
|
+
size={16}
|
|
1194
|
+
style={{ marginRight: '10px' }}
|
|
1195
|
+
/>
|
|
1196
|
+
Add New
|
|
1154
1197
|
</button>
|
|
1155
1198
|
) : null}
|
|
1156
1199
|
</div>
|
|
@@ -1161,34 +1204,46 @@ const DataGrid = forwardRef(
|
|
|
1161
1204
|
const isSearchEnabled = !(form.searchDisable === true);
|
|
1162
1205
|
const isCreateDisabled = form.createDisable === true;
|
|
1163
1206
|
|
|
1164
|
-
if
|
|
1207
|
+
// Don't render anything if both search and create are disabled
|
|
1208
|
+
if (!isSearchEnabled && isCreateDisabled) {
|
|
1209
|
+
return null;
|
|
1210
|
+
}
|
|
1211
|
+
|
|
1212
|
+
// If search is disabled but create button is enabled, render only the button with its own container
|
|
1213
|
+
if (!isSearchEnabled && !isCreateDisabled) {
|
|
1165
1214
|
return (
|
|
1166
|
-
<div className={styles
|
|
1167
|
-
|
|
1168
|
-
|
|
1215
|
+
<div className={styles.actionButtonsContainer}>
|
|
1216
|
+
{renderCreateButton()}
|
|
1217
|
+
</div>
|
|
1218
|
+
);
|
|
1219
|
+
}
|
|
1220
|
+
|
|
1221
|
+
// If search is enabled, render the full search container with both search and buttons
|
|
1222
|
+
return (
|
|
1223
|
+
<div className={styles.searchContainer}>
|
|
1224
|
+
<div className={styles.searchInputWrapper}>
|
|
1225
|
+
<div
|
|
1226
|
+
className={styles['icon-search']}
|
|
1227
|
+
style={{ left: 25, opacity: 0.5 }}
|
|
1228
|
+
>
|
|
1229
|
+
<Search strokeWidth={1} size={14} />
|
|
1169
1230
|
</div>
|
|
1170
1231
|
<input
|
|
1171
1232
|
type="text"
|
|
1172
1233
|
placeholder="Search"
|
|
1173
1234
|
value={search}
|
|
1174
1235
|
onChange={handleChangeSearch}
|
|
1236
|
+
style={{ borderRadius: 0, paddingLeft: 55 }}
|
|
1237
|
+
className={styles.searchInput}
|
|
1175
1238
|
/>
|
|
1176
1239
|
</div>
|
|
1177
|
-
|
|
1178
|
-
|
|
1179
|
-
|
|
1180
|
-
|
|
1181
|
-
|
|
1182
|
-
|
|
1183
|
-
|
|
1184
|
-
? style.data_grid_search_height
|
|
1185
|
-
: '58px',
|
|
1186
|
-
}}
|
|
1187
|
-
></div>
|
|
1188
|
-
);
|
|
1189
|
-
}
|
|
1190
|
-
|
|
1191
|
-
return null; // Return null if neither search is enabled nor create is disabled
|
|
1240
|
+
{!isCreateDisabled && (
|
|
1241
|
+
<div className={styles.actionButtonsWrapper}>
|
|
1242
|
+
{renderCreateButton()}
|
|
1243
|
+
</div>
|
|
1244
|
+
)}
|
|
1245
|
+
</div>
|
|
1246
|
+
);
|
|
1192
1247
|
};
|
|
1193
1248
|
|
|
1194
1249
|
const renderRowContextMenu = useCallback(
|
|
@@ -3078,11 +3133,25 @@ const DataGrid = forwardRef(
|
|
|
3078
3133
|
}, []);
|
|
3079
3134
|
|
|
3080
3135
|
return (
|
|
3081
|
-
|
|
3082
|
-
{
|
|
3083
|
-
|
|
3084
|
-
|
|
3085
|
-
|
|
3136
|
+
<div
|
|
3137
|
+
style={{
|
|
3138
|
+
display: 'flex',
|
|
3139
|
+
flexDirection: 'column',
|
|
3140
|
+
border: 'none',
|
|
3141
|
+
borderRadius: '0',
|
|
3142
|
+
overflow: 'hidden',
|
|
3143
|
+
}}
|
|
3144
|
+
>
|
|
3145
|
+
{/* Search and action buttons container - separated from the DataGrid */}
|
|
3146
|
+
{renderSearch() && (
|
|
3147
|
+
<div className={styles.dataGridTopContainer}>
|
|
3148
|
+
{renderSearch()}
|
|
3149
|
+
</div>
|
|
3150
|
+
)}
|
|
3151
|
+
|
|
3152
|
+
{/* DataGrid container with its own border */}
|
|
3153
|
+
<div className={styles.dataGridContainer}>
|
|
3154
|
+
{limit && limit > 0 ? (
|
|
3086
3155
|
<ReactDataGrid
|
|
3087
3156
|
{...tableSetting}
|
|
3088
3157
|
columns={gridColumns}
|
|
@@ -3124,10 +3193,15 @@ const DataGrid = forwardRef(
|
|
|
3124
3193
|
}
|
|
3125
3194
|
: null
|
|
3126
3195
|
}
|
|
3127
|
-
style={
|
|
3196
|
+
style={{
|
|
3197
|
+
...gridStyle,
|
|
3198
|
+
border: '1px solid #d1d5db',
|
|
3199
|
+
borderRadius: 'var(--br, 4px)',
|
|
3200
|
+
overflow: 'hidden',
|
|
3201
|
+
}}
|
|
3128
3202
|
/>
|
|
3129
|
-
|
|
3130
|
-
|
|
3203
|
+
) : null}
|
|
3204
|
+
</div>
|
|
3131
3205
|
{audioSource && <audio src={audioSource} ref={audioRef} />}
|
|
3132
3206
|
<Popup
|
|
3133
3207
|
open={modalShow}
|
|
@@ -3373,7 +3447,7 @@ const DataGrid = forwardRef(
|
|
|
3373
3447
|
index={lightboxIndex}
|
|
3374
3448
|
slides={galleryData.map((img) => ({ src: img.src }))}
|
|
3375
3449
|
/>
|
|
3376
|
-
|
|
3450
|
+
</div>
|
|
3377
3451
|
);
|
|
3378
3452
|
}
|
|
3379
3453
|
);
|
|
@@ -108,6 +108,7 @@ function MultiSelect({
|
|
|
108
108
|
filterOption={createFilter({ ignoreAccents: false })}
|
|
109
109
|
components={{ SelectList }}
|
|
110
110
|
options={selectOptions}
|
|
111
|
+
menuPortalTarget={document.body}
|
|
111
112
|
onChange={(inputValue, action) => {
|
|
112
113
|
// Special handling for limit=1: keep only the most recent selection
|
|
113
114
|
if (
|
|
@@ -130,13 +131,60 @@ function MultiSelect({
|
|
|
130
131
|
}
|
|
131
132
|
classNamePrefix="visns-select"
|
|
132
133
|
styles={{
|
|
133
|
-
menu: (provided) => ({
|
|
134
|
+
menu: (provided) => ({
|
|
135
|
+
...provided,
|
|
136
|
+
zIndex: 99999,
|
|
137
|
+
}),
|
|
138
|
+
menuPortal: (base) => ({
|
|
139
|
+
...base,
|
|
140
|
+
zIndex: 99999,
|
|
141
|
+
}),
|
|
134
142
|
control: (base) => ({
|
|
135
143
|
...base,
|
|
136
144
|
minHeight:
|
|
137
145
|
style && style.multi_select_height
|
|
138
146
|
? style.multi_select_height
|
|
139
|
-
: '
|
|
147
|
+
: '50px',
|
|
148
|
+
height: 'auto', // Allow height to grow with content
|
|
149
|
+
}),
|
|
150
|
+
valueContainer: (base) => ({
|
|
151
|
+
...base,
|
|
152
|
+
padding: '2px 8px',
|
|
153
|
+
display: 'flex',
|
|
154
|
+
alignItems: 'flex-start',
|
|
155
|
+
flexWrap: 'wrap',
|
|
156
|
+
maxHeight: '100px', // Set a max height
|
|
157
|
+
overflowY: 'auto', // Add scrolling when needed
|
|
158
|
+
}),
|
|
159
|
+
indicatorsContainer: (base) => ({
|
|
160
|
+
...base,
|
|
161
|
+
height: 'auto',
|
|
162
|
+
display: 'flex',
|
|
163
|
+
alignItems: 'center',
|
|
164
|
+
alignSelf: 'stretch', // Stretch to full height of container
|
|
165
|
+
}),
|
|
166
|
+
dropdownIndicator: (base) => ({
|
|
167
|
+
...base,
|
|
168
|
+
padding: '8px',
|
|
169
|
+
display: 'flex',
|
|
170
|
+
alignItems: 'center',
|
|
171
|
+
alignSelf: 'stretch', // Stretch to full height
|
|
172
|
+
}),
|
|
173
|
+
clearIndicator: (base) => ({
|
|
174
|
+
...base,
|
|
175
|
+
padding: '8px',
|
|
176
|
+
display: 'flex',
|
|
177
|
+
alignItems: 'center',
|
|
178
|
+
alignSelf: 'stretch', // Stretch to full height
|
|
179
|
+
}),
|
|
180
|
+
indicatorSeparator: (base) => ({
|
|
181
|
+
...base,
|
|
182
|
+
alignSelf: 'stretch', // Stretch to full height
|
|
183
|
+
margin: '4px 0',
|
|
184
|
+
}),
|
|
185
|
+
multiValue: (base) => ({
|
|
186
|
+
...base,
|
|
187
|
+
margin: '2px',
|
|
140
188
|
}),
|
|
141
189
|
}}
|
|
142
190
|
value={selectValue}
|
|
@@ -337,7 +337,17 @@ function Navigation({
|
|
|
337
337
|
);
|
|
338
338
|
};
|
|
339
339
|
|
|
340
|
-
const
|
|
340
|
+
const getUserPermissions = () => {
|
|
341
|
+
// First check if userProfile has direct permissions
|
|
342
|
+
if (
|
|
343
|
+
userProfile.permissions &&
|
|
344
|
+
Array.isArray(userProfile.permissions) &&
|
|
345
|
+
userProfile.permissions.length > 0
|
|
346
|
+
) {
|
|
347
|
+
return userProfile.permissions.map((permission) => permission.name);
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
// Fall back to role-based permissions if direct permissions don't exist
|
|
341
351
|
if (
|
|
342
352
|
userProfile.roles &&
|
|
343
353
|
userProfile.roles.length > 0 &&
|
|
@@ -351,7 +361,7 @@ function Navigation({
|
|
|
351
361
|
};
|
|
352
362
|
|
|
353
363
|
useEffect(() => {
|
|
354
|
-
const permissions =
|
|
364
|
+
const permissions = getUserPermissions();
|
|
355
365
|
|
|
356
366
|
setNavData((prevNavData) => {
|
|
357
367
|
const updatePermissions = (nav) => {
|