@visns-studio/visns-components 6.34.0 → 6.35.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/README.md +37 -1
- package/package.json +1 -1
- package/src/components/DataGrid.jsx +44 -7
- package/src/components/auth/Login.jsx +2 -2
- package/src/components/auth/Reset.jsx +1 -1
- package/src/components/auth/TwoFactorAuth.jsx +1 -1
- package/src/components/auth/Verify.jsx +2 -2
- package/src/components/emailCampaigns/BlockEditor.jsx +486 -0
- package/src/components/emailCampaigns/CampaignEditor.jsx +614 -0
- package/src/components/emailCampaigns/CampaignReport.jsx +98 -0
- package/src/components/emailCampaigns/EmailCampaigns.jsx +422 -0
- package/src/components/emailCampaigns/EmailLists.jsx +505 -0
- package/src/components/emailCampaigns/emailCampaignApi.js +135 -0
- package/src/components/sms/SmsCampaigns.jsx +34 -4
- package/src/components/sms/SmsInbox.jsx +2 -5
- package/src/components/sms/SmsLineSettings.jsx +2 -5
- package/src/components/styles/EmailCampaigns.module.scss +922 -0
- package/src/components/styles/Sms.module.scss +33 -4
- package/src/components/styles/Vault.module.scss +5 -3
- package/src/components/styles/global.css +14 -2
- package/src/index.js +4 -0
package/README.md
CHANGED
|
@@ -9,7 +9,42 @@ A comprehensive React component library used by the VISNS Studio team for CRM an
|
|
|
9
9
|
|
|
10
10
|
VISNS Components is a React-based UI component library that provides a set of reusable, consistent, and customizable components for building web applications. It includes components for authentication, data grids, forms, navigation, and more, designed to work seamlessly together.
|
|
11
11
|
|
|
12
|
-
## Recent Updates (v6.
|
|
12
|
+
## Recent Updates (v6.35.0)
|
|
13
|
+
|
|
14
|
+
### `fixedLimit` pins a grid's page size
|
|
15
|
+
|
|
16
|
+
`Table` (the `DataGrid`) has always worked out its rows per page for itself.
|
|
17
|
+
The profile's `rows_per_page` seeds it, a fixed-height grid falls back to
|
|
18
|
+
`tableSetting.pageSize` or `ajaxSetting.take`, and a grid sized to the window
|
|
19
|
+
replaces all of that with however many rows fit the screen — and re-works it on
|
|
20
|
+
every resize. That is right for an index page and wrong for a page whose page
|
|
21
|
+
size is part of what it means: the same page shows a different number of rows
|
|
22
|
+
on every monitor, and a staff member's stored preference quietly changes it
|
|
23
|
+
again.
|
|
24
|
+
|
|
25
|
+
Pass `fixedLimit={100}` and the grid always requests and shows 100 rows. The
|
|
26
|
+
pin is checked first everywhere the limit is decided, so it beats the profile
|
|
27
|
+
preference, `pageSize`, `take` and the window-fit arithmetic, and a resize no
|
|
28
|
+
longer moves it. The pager's "Results per page" control is pinned too: it is
|
|
29
|
+
given `pageSizes={[fixedLimit]}`, so it still shows the value but has nothing
|
|
30
|
+
else to offer, and any change that reaches the grid anyway is ignored. The
|
|
31
|
+
grid's drawn height is still fitted to the window as before — only the request
|
|
32
|
+
is pinned. Without the prop (or with `0`) nothing changes.
|
|
33
|
+
|
|
34
|
+
## Recent Updates (v6.34.3)
|
|
35
|
+
|
|
36
|
+
### The auth fields' values no longer sit on top of their labels
|
|
37
|
+
|
|
38
|
+
The sign-in, reset, verify and 2FA screens draw a floating label inside the
|
|
39
|
+
input, and `_authShell.scss` sizes those inputs for it — a 3.35rem box with a
|
|
40
|
+
top-heavy padding so the value clears the label. That rule is `.field input`,
|
|
41
|
+
(0,1,1), and `global.css` sizes every text input through a twenty-clause
|
|
42
|
+
`input[type]:not(...)` chain that outranks it. So the chain won: the box shrank
|
|
43
|
+
to `--field-height`, the padding went horizontal-only, and the value was drawn
|
|
44
|
+
straight through the label. The six auth inputs now carry `visns-auth-input`,
|
|
45
|
+
and both global chains (sizing and focus) exclude it, the same opt-out
|
|
46
|
+
`searchInput` and `filterInput` already have. Apps that keep a global input
|
|
47
|
+
rule of their own can exclude the same class.
|
|
13
48
|
|
|
14
49
|
### The shell layout is on `<html>`, where anything can read it
|
|
15
50
|
|
|
@@ -3360,6 +3395,7 @@ The frontend intelligent sorting works seamlessly with the backend `HasRelations
|
|
|
3360
3395
|
| defaultExpandedNodes | Initial expanded nodes for TreeGrid | Object | - |
|
|
3361
3396
|
| defaultGroupBy | Initial grouping configuration | Array | - |
|
|
3362
3397
|
| expandedNodes | Current expanded nodes for TreeGrid | Object | - |
|
|
3398
|
+
| fixedLimit | Pins rows per page; beats profile preference, take and window-fit | Number | - |
|
|
3363
3399
|
| form | Form configuration for editing | Object | - |
|
|
3364
3400
|
| gridHeight | Height of the grid | Number | 500 |
|
|
3365
3401
|
| groupBy | Current grouping configuration | Array | - |
|
package/package.json
CHANGED
|
@@ -93,7 +93,7 @@
|
|
|
93
93
|
"react-dom": "^17.0.0 || ^18.0.0 || ^19.0.0"
|
|
94
94
|
},
|
|
95
95
|
"name": "@visns-studio/visns-components",
|
|
96
|
-
"version": "6.
|
|
96
|
+
"version": "6.35.0",
|
|
97
97
|
"description": "Various packages to assist in the development of our Custom Applications.",
|
|
98
98
|
"main": "src/index.js",
|
|
99
99
|
"files": [
|
|
@@ -379,6 +379,14 @@ const DataGrid = forwardRef(
|
|
|
379
379
|
// grid. An empty object gives every one of those reads undefined,
|
|
380
380
|
// which is what they already treat as "not set".
|
|
381
381
|
form = {},
|
|
382
|
+
// A page-level pin on rows per page. When it is a positive number
|
|
383
|
+
// the grid always asks for and shows exactly that many rows: it
|
|
384
|
+
// wins over the profile's rows_per_page, `tableSetting.pageSize`,
|
|
385
|
+
// `ajaxSetting.take` and the window-fit arithmetic, and the pager's
|
|
386
|
+
// "Results per page" control is pinned to it. It exists for pages
|
|
387
|
+
// whose page size must not drift with the screen height or with a
|
|
388
|
+
// stored preference. Unset (or 0) changes nothing.
|
|
389
|
+
fixedLimit,
|
|
382
390
|
gridHeight,
|
|
383
391
|
hoverColor,
|
|
384
392
|
legend,
|
|
@@ -993,6 +1001,7 @@ const DataGrid = forwardRef(
|
|
|
993
1001
|
tableSetting_pageSize: tableSetting?.pageSize,
|
|
994
1002
|
userProfile: userProfile,
|
|
995
1003
|
});
|
|
1004
|
+
if (fixedLimit > 0) return fixedLimit;
|
|
996
1005
|
if (userProfile?.rows_per_page) return userProfile.rows_per_page;
|
|
997
1006
|
if (userProfile?.settings?.rows_per_page) return userProfile.settings.rows_per_page;
|
|
998
1007
|
if (tableSetting?.pageSize) return tableSetting.pageSize;
|
|
@@ -1016,10 +1025,17 @@ const DataGrid = forwardRef(
|
|
|
1016
1025
|
const limitRef = useRef(limit);
|
|
1017
1026
|
limitRef.current = limit;
|
|
1018
1027
|
|
|
1019
|
-
const handleLimitChange = useCallback(
|
|
1020
|
-
|
|
1021
|
-
|
|
1022
|
-
|
|
1028
|
+
const handleLimitChange = useCallback(
|
|
1029
|
+
(next) => {
|
|
1030
|
+
// A pinned page size is not the user's to change. The pager
|
|
1031
|
+
// only offers the pinned value, but ignore anything else that
|
|
1032
|
+
// arrives here too — and don't mark it as a user choice.
|
|
1033
|
+
if (fixedLimit > 0) return;
|
|
1034
|
+
userChoseLimitRef.current = true;
|
|
1035
|
+
setLimit(next);
|
|
1036
|
+
},
|
|
1037
|
+
[fixedLimit]
|
|
1038
|
+
);
|
|
1023
1039
|
const [search, setSearch] = useState('');
|
|
1024
1040
|
|
|
1025
1041
|
// This component instance survives client-side route changes — React Router
|
|
@@ -1058,7 +1074,9 @@ const DataGrid = forwardRef(
|
|
|
1058
1074
|
// becomes available — and never over a size the user has picked
|
|
1059
1075
|
// from the pager since. This seeds the limit for the first fetch;
|
|
1060
1076
|
// the sizing effect below replaces it as soon as the grid has
|
|
1061
|
-
// measured itself against the window.
|
|
1077
|
+
// measured itself against the window. A `fixedLimit` page never
|
|
1078
|
+
// takes the profile value at all.
|
|
1079
|
+
if (fixedLimit > 0) return;
|
|
1062
1080
|
if (!initialLimitApplied.current && !userChoseLimitRef.current) {
|
|
1063
1081
|
const userLimit = userProfile?.rows_per_page || userProfile?.settings?.rows_per_page;
|
|
1064
1082
|
debugLog('[DataGrid] Checking userLimit:', userLimit);
|
|
@@ -1068,7 +1086,11 @@ const DataGrid = forwardRef(
|
|
|
1068
1086
|
initialLimitApplied.current = true;
|
|
1069
1087
|
}
|
|
1070
1088
|
}
|
|
1071
|
-
}, [
|
|
1089
|
+
}, [
|
|
1090
|
+
fixedLimit,
|
|
1091
|
+
userProfile?.rows_per_page,
|
|
1092
|
+
userProfile?.settings?.rows_per_page,
|
|
1093
|
+
]);
|
|
1072
1094
|
|
|
1073
1095
|
/** Auto Refresh States */
|
|
1074
1096
|
const [autoRefreshEnabled, setAutoRefreshEnabled] = useState(false);
|
|
@@ -6367,7 +6389,15 @@ const DataGrid = forwardRef(
|
|
|
6367
6389
|
userProfile?.rows_per_page ||
|
|
6368
6390
|
userProfile?.settings?.rows_per_page;
|
|
6369
6391
|
|
|
6370
|
-
|
|
6392
|
+
// A page that passes `fixedLimit` has pinned its page size, and
|
|
6393
|
+
// the pin wins over everything below — the profile preference, a
|
|
6394
|
+
// configured `take` and the window-fit arithmetic — so the number
|
|
6395
|
+
// of rows never drifts with screen height or a resize. The grid's
|
|
6396
|
+
// drawn height above is still fitted to the window as usual; only
|
|
6397
|
+
// the request is pinned.
|
|
6398
|
+
if (fixedLimit > 0) {
|
|
6399
|
+
if (limitRef.current !== fixedLimit) setLimit(fixedLimit);
|
|
6400
|
+
} else if (userChoseLimitRef.current) {
|
|
6371
6401
|
debugLog(
|
|
6372
6402
|
'[DataGrid] Honouring the size the user picked this session:',
|
|
6373
6403
|
limitRef.current
|
|
@@ -6411,6 +6441,7 @@ const DataGrid = forwardRef(
|
|
|
6411
6441
|
ajaxSetting?.take,
|
|
6412
6442
|
userProfile?.rows_per_page,
|
|
6413
6443
|
userProfile?.settings?.rows_per_page,
|
|
6444
|
+
fixedLimit,
|
|
6414
6445
|
]);
|
|
6415
6446
|
|
|
6416
6447
|
useEffect(() => {
|
|
@@ -7120,6 +7151,12 @@ const DataGrid = forwardRef(
|
|
|
7120
7151
|
handleFilterChange(fv, filterValue);
|
|
7121
7152
|
}}
|
|
7122
7153
|
onLimitChange={handleLimitChange}
|
|
7154
|
+
// Offer only the pinned size in "Results per
|
|
7155
|
+
// page", so the selector shows the value but has
|
|
7156
|
+
// nothing else to pick.
|
|
7157
|
+
{...(fixedLimit > 0
|
|
7158
|
+
? { pageSizes: [fixedLimit] }
|
|
7159
|
+
: {})}
|
|
7123
7160
|
onSelectionChange={handleSelectionChange}
|
|
7124
7161
|
onSortInfoChange={handleSort}
|
|
7125
7162
|
onRenderRow={onRenderRow}
|
|
@@ -524,7 +524,7 @@ const Login = ({
|
|
|
524
524
|
value={auth.email}
|
|
525
525
|
onChange={handleChange}
|
|
526
526
|
tabIndex="1"
|
|
527
|
-
className={authClass.username}
|
|
527
|
+
className={`visns-auth-input ${authClass.username}`.trim()}
|
|
528
528
|
autoComplete="username"
|
|
529
529
|
placeholder=" "
|
|
530
530
|
disabled={isBusy}
|
|
@@ -540,7 +540,7 @@ const Login = ({
|
|
|
540
540
|
value={auth.password}
|
|
541
541
|
onChange={handleChange}
|
|
542
542
|
tabIndex="2"
|
|
543
|
-
className={authClass.password}
|
|
543
|
+
className={`visns-auth-input ${authClass.password}`.trim()}
|
|
544
544
|
autoComplete="current-password"
|
|
545
545
|
placeholder=" "
|
|
546
546
|
disabled={isBusy}
|
|
@@ -455,7 +455,7 @@ const TwoFactorAuth = ({
|
|
|
455
455
|
value={verificationCode}
|
|
456
456
|
onChange={handleChange}
|
|
457
457
|
tabIndex="1"
|
|
458
|
-
className={codeClass}
|
|
458
|
+
className={`visns-auth-input ${codeClass}`.trim()}
|
|
459
459
|
placeholder=" "
|
|
460
460
|
autoComplete="one-time-code"
|
|
461
461
|
inputMode="numeric"
|
|
@@ -201,7 +201,7 @@ const Verify = ({
|
|
|
201
201
|
value={password}
|
|
202
202
|
onChange={handleInputChange}
|
|
203
203
|
tabIndex="1"
|
|
204
|
-
className={passwordClass}
|
|
204
|
+
className={`visns-auth-input ${passwordClass}`.trim()}
|
|
205
205
|
autoComplete="new-password"
|
|
206
206
|
placeholder=" "
|
|
207
207
|
autoFocus
|
|
@@ -237,7 +237,7 @@ const Verify = ({
|
|
|
237
237
|
value={passwordRepeat}
|
|
238
238
|
onChange={handleInputChange}
|
|
239
239
|
tabIndex="2"
|
|
240
|
-
className={passwordRepeatClass}
|
|
240
|
+
className={`visns-auth-input ${passwordRepeatClass}`.trim()}
|
|
241
241
|
autoComplete="new-password"
|
|
242
242
|
placeholder=" "
|
|
243
243
|
disabled={isLoading}
|