@dloizides/ui-access-admin 1.2.0 → 1.3.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/CHANGELOG.md +23 -0
- package/dist/index.d.mts +54 -7
- package/dist/index.d.ts +54 -7
- package/dist/index.js +201 -41
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +202 -44
- package/dist/index.mjs.map +1 -1
- package/package.json +4 -4
package/dist/index.mjs
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { useState, useRef, useEffect, useCallback, useMemo } from 'react';
|
|
2
|
-
import { StyleSheet, View, Text, Linking } from 'react-native';
|
|
2
|
+
import { StyleSheet, View, Text, useWindowDimensions, Linking, ScrollView } from 'react-native';
|
|
3
3
|
import { Button } from '@dloizides/ui-buttons';
|
|
4
4
|
import { useUi, ToastHost, createToastBus } from '@dloizides/ui-feedback';
|
|
5
|
-
import { copyText, ModalShell, ModalDropdown } from '@dloizides/ui-layout';
|
|
5
|
+
import { copyText, LAYOUT_COLLAPSE_BREAKPOINT, ModalShell, ModalDropdown, DropdownVariant } from '@dloizides/ui-layout';
|
|
6
6
|
import { jsxs, jsx } from 'react/jsx-runtime';
|
|
7
7
|
import { SelectControl, FormField, FormSwitch, Field } from '@dloizides/ui-forms';
|
|
8
8
|
import { FilterBar, DataTable } from '@dloizides/ui-tables';
|
|
@@ -167,12 +167,25 @@ var ACCESS_ADMIN_I18N = {
|
|
|
167
167
|
usersUpdateSuccess: "accessAdmin.users.updateSuccess",
|
|
168
168
|
usersUpdateFailed: "accessAdmin.users.updateFailed",
|
|
169
169
|
usersResetSuccess: "accessAdmin.users.resetSuccess",
|
|
170
|
-
usersResetFailed: "accessAdmin.users.resetFailed"
|
|
170
|
+
usersResetFailed: "accessAdmin.users.resetFailed",
|
|
171
|
+
usersFieldBlockedReason: "accessAdmin.users.fieldBlockedReason",
|
|
172
|
+
usersBlockedReasonPlaceholder: "accessAdmin.users.blockedReasonPlaceholder",
|
|
173
|
+
usersBlockedReasonHint: "accessAdmin.users.blockedReasonHint",
|
|
174
|
+
permissionsHeading: "accessAdmin.permissions.heading",
|
|
175
|
+
permissionsNote: "accessAdmin.permissions.note",
|
|
176
|
+
permissionsColPermission: "accessAdmin.permissions.colPermission",
|
|
177
|
+
permissionsGranted: "accessAdmin.permissions.granted",
|
|
178
|
+
permissionsNotGranted: "accessAdmin.permissions.notGranted",
|
|
179
|
+
permissionsCellLabel: "accessAdmin.permissions.cellLabel",
|
|
180
|
+
permissionsReadOnlyHint: "accessAdmin.permissions.readOnlyHint",
|
|
181
|
+
permissionsRoleCount: "accessAdmin.permissions.roleCount",
|
|
182
|
+
permissionsEmpty: "accessAdmin.permissions.empty"
|
|
171
183
|
};
|
|
172
184
|
var ACCESS_ADMIN_TEST_IDS = {
|
|
173
185
|
linkPanel: "access-link-panel",
|
|
174
186
|
accountPanel: "account-link-panel",
|
|
175
|
-
usersPanel: "user-management-panel"
|
|
187
|
+
usersPanel: "user-management-panel",
|
|
188
|
+
permissionMatrix: "permission-matrix"
|
|
176
189
|
};
|
|
177
190
|
|
|
178
191
|
// src/expiry/expiryPolicy.ts
|
|
@@ -317,7 +330,7 @@ var AccessLinkPanel = ({
|
|
|
317
330
|
}) => {
|
|
318
331
|
const { t } = useUi();
|
|
319
332
|
const palette = useAccessAdminPalette();
|
|
320
|
-
const
|
|
333
|
+
const styles2 = useMemo(() => buildStyles(palette), [palette]);
|
|
321
334
|
const state = useCapabilityLinkMint({
|
|
322
335
|
subject,
|
|
323
336
|
policy,
|
|
@@ -345,16 +358,16 @@ var AccessLinkPanel = ({
|
|
|
345
358
|
onResult(t(ACCESS_ADMIN_I18N.copyFailed, subject.displayName), "error" /* Error */);
|
|
346
359
|
});
|
|
347
360
|
};
|
|
348
|
-
return /* @__PURE__ */ jsxs(View, { style:
|
|
349
|
-
/* @__PURE__ */ jsx(Text, { style:
|
|
350
|
-
/* @__PURE__ */ jsx(Text, { style:
|
|
351
|
-
/* @__PURE__ */ jsx(Text, { style:
|
|
352
|
-
/* @__PURE__ */ jsx(Text, { style:
|
|
353
|
-
state.minted !== null ? /* @__PURE__ */ jsxs(View, { style:
|
|
354
|
-
/* @__PURE__ */ jsx(Text, { style:
|
|
355
|
-
/* @__PURE__ */ jsx(Text, { style:
|
|
356
|
-
/* @__PURE__ */ jsx(Text, { selectable: true, style:
|
|
357
|
-
/* @__PURE__ */ jsxs(View, { style:
|
|
361
|
+
return /* @__PURE__ */ jsxs(View, { style: styles2.panel, testID: testIDPrefix, children: [
|
|
362
|
+
/* @__PURE__ */ jsx(Text, { style: styles2.heading, children: t(ACCESS_ADMIN_I18N.panelHeading, subject.displayName) }),
|
|
363
|
+
/* @__PURE__ */ jsx(Text, { style: styles2.note, children: t(ACCESS_ADMIN_I18N.panelNote) }),
|
|
364
|
+
/* @__PURE__ */ jsx(Text, { style: styles2.warning, testID: `${testIDPrefix}-capability-warning`, children: t(ACCESS_ADMIN_I18N.capabilityWarning) }),
|
|
365
|
+
/* @__PURE__ */ jsx(Text, { style: styles2.note, testID: `${testIDPrefix}-expiry-preview`, children: t(ACCESS_ADMIN_I18N.expiryPreview, expiryDate) }),
|
|
366
|
+
state.minted !== null ? /* @__PURE__ */ jsxs(View, { style: styles2.revealBox, testID: `${testIDPrefix}-minted`, children: [
|
|
367
|
+
/* @__PURE__ */ jsx(Text, { style: styles2.revealTitle, children: t(ACCESS_ADMIN_I18N.mintedTitle, subject.displayName) }),
|
|
368
|
+
/* @__PURE__ */ jsx(Text, { style: styles2.note, children: t(ACCESS_ADMIN_I18N.mintedHint) }),
|
|
369
|
+
/* @__PURE__ */ jsx(Text, { selectable: true, style: styles2.url, testID: `${testIDPrefix}-minted-url`, children: mintedUrl }),
|
|
370
|
+
/* @__PURE__ */ jsxs(View, { style: styles2.actions, children: [
|
|
358
371
|
/* @__PURE__ */ jsx(
|
|
359
372
|
Button,
|
|
360
373
|
{
|
|
@@ -388,13 +401,13 @@ var AccessLinkPanel = ({
|
|
|
388
401
|
}
|
|
389
402
|
)
|
|
390
403
|
] }),
|
|
391
|
-
/* @__PURE__ */ jsx(Text, { style:
|
|
404
|
+
/* @__PURE__ */ jsx(Text, { style: styles2.note, children: t(ACCESS_ADMIN_I18N.emailNote) })
|
|
392
405
|
] }) : null,
|
|
393
|
-
linksFailed ? /* @__PURE__ */ jsx(Text, { style:
|
|
394
|
-
!linksFailed && liveLinks.length > 0 ? /* @__PURE__ */ jsxs(View, { style:
|
|
395
|
-
/* @__PURE__ */ jsx(Text, { style:
|
|
396
|
-
liveLinks.map((link) => /* @__PURE__ */ jsxs(View, { style:
|
|
397
|
-
/* @__PURE__ */ jsx(Text, { style:
|
|
406
|
+
linksFailed ? /* @__PURE__ */ jsx(Text, { style: styles2.warning, testID: `${testIDPrefix}-load-error`, children: t(ACCESS_ADMIN_I18N.liveLoadError) }) : null,
|
|
407
|
+
!linksFailed && liveLinks.length > 0 ? /* @__PURE__ */ jsxs(View, { style: styles2.liveBox, children: [
|
|
408
|
+
/* @__PURE__ */ jsx(Text, { style: styles2.subheading, children: t(ACCESS_ADMIN_I18N.liveHeading, String(liveLinks.length)) }),
|
|
409
|
+
liveLinks.map((link) => /* @__PURE__ */ jsxs(View, { style: styles2.liveRow, children: [
|
|
410
|
+
/* @__PURE__ */ jsx(Text, { style: styles2.liveMeta, children: t(
|
|
398
411
|
ACCESS_ADMIN_I18N.liveMeta,
|
|
399
412
|
formatLinkDate(link.createdAt, ""),
|
|
400
413
|
formatLinkDate(link.expiresAt, t(ACCESS_ADMIN_I18N.expiresNever))
|
|
@@ -402,8 +415,8 @@ var AccessLinkPanel = ({
|
|
|
402
415
|
renderLinkActions === void 0 ? null : renderLinkActions(link)
|
|
403
416
|
] }, link.id))
|
|
404
417
|
] }) : null,
|
|
405
|
-
!linksFailed && liveLinks.length === 0 ? /* @__PURE__ */ jsx(Text, { style:
|
|
406
|
-
/* @__PURE__ */ jsxs(View, { style:
|
|
418
|
+
!linksFailed && liveLinks.length === 0 ? /* @__PURE__ */ jsx(Text, { style: styles2.note, testID: `${testIDPrefix}-no-live`, children: t(ACCESS_ADMIN_I18N.noLive) }) : null,
|
|
419
|
+
/* @__PURE__ */ jsxs(View, { style: styles2.actions, children: [
|
|
407
420
|
/* @__PURE__ */ jsx(
|
|
408
421
|
Button,
|
|
409
422
|
{
|
|
@@ -549,7 +562,7 @@ var AccountLinkPanel = ({
|
|
|
549
562
|
}) => {
|
|
550
563
|
const { t } = useUi();
|
|
551
564
|
const palette = useAccessAdminPalette();
|
|
552
|
-
const
|
|
565
|
+
const styles2 = useMemo(() => buildStyles2(palette), [palette]);
|
|
553
566
|
const state = useSubjectAccountLink({
|
|
554
567
|
subject,
|
|
555
568
|
boundAccountId,
|
|
@@ -564,9 +577,9 @@ var AccountLinkPanel = ({
|
|
|
564
577
|
[accounts, bindings, subject, unnamedLabel]
|
|
565
578
|
);
|
|
566
579
|
const selectedLabel = options.find((option) => option.value === state.selectedAccountId)?.label ?? "";
|
|
567
|
-
return /* @__PURE__ */ jsxs(View, { style:
|
|
568
|
-
/* @__PURE__ */ jsx(Text, { style:
|
|
569
|
-
/* @__PURE__ */ jsx(Text, { style:
|
|
580
|
+
return /* @__PURE__ */ jsxs(View, { style: styles2.panel, testID: testIDPrefix, children: [
|
|
581
|
+
/* @__PURE__ */ jsx(Text, { style: styles2.heading, children: t(ACCESS_ADMIN_I18N.accountPanelHeading, subject.displayName) }),
|
|
582
|
+
/* @__PURE__ */ jsx(Text, { style: styles2.note, children: t(ACCESS_ADMIN_I18N.accountPanelNote) }),
|
|
570
583
|
options.length > 0 ? /* @__PURE__ */ jsx(
|
|
571
584
|
SelectControl,
|
|
572
585
|
{
|
|
@@ -579,8 +592,8 @@ var AccountLinkPanel = ({
|
|
|
579
592
|
testID: `${testIDPrefix}-picker`,
|
|
580
593
|
value: state.selectedAccountId ?? ""
|
|
581
594
|
}
|
|
582
|
-
) : /* @__PURE__ */ jsx(Text, { style:
|
|
583
|
-
/* @__PURE__ */ jsxs(View, { style:
|
|
595
|
+
) : /* @__PURE__ */ jsx(Text, { style: styles2.note, testID: `${testIDPrefix}-no-accounts`, children: t(ACCESS_ADMIN_I18N.accountNone) }),
|
|
596
|
+
/* @__PURE__ */ jsxs(View, { style: styles2.actions, children: [
|
|
584
597
|
/* @__PURE__ */ jsx(
|
|
585
598
|
Button,
|
|
586
599
|
{
|
|
@@ -673,6 +686,18 @@ function roleOptions(assignableRoles) {
|
|
|
673
686
|
function tenantValueToId(value) {
|
|
674
687
|
return value === NO_TENANT_VALUE ? null : value;
|
|
675
688
|
}
|
|
689
|
+
function isBlocking(wasActive, active) {
|
|
690
|
+
return wasActive && !active;
|
|
691
|
+
}
|
|
692
|
+
function isBlockReasonMissing(wasActive, active, blockedReason) {
|
|
693
|
+
return isBlocking(wasActive, active) && blockedReason.trim() === "";
|
|
694
|
+
}
|
|
695
|
+
function buildEditPatch(input) {
|
|
696
|
+
const patch = { displayName: input.displayName.trim(), role: input.role, active: input.active };
|
|
697
|
+
if (isBlocking(input.wasActive, input.active)) patch.blockedReason = input.blockedReason.trim();
|
|
698
|
+
if (input.tenantId !== void 0) patch.tenantId = input.tenantId;
|
|
699
|
+
return patch;
|
|
700
|
+
}
|
|
676
701
|
var ACTIONS_GAP = 8;
|
|
677
702
|
function buildUserColumns({
|
|
678
703
|
t,
|
|
@@ -763,7 +788,8 @@ var PickerField = ({
|
|
|
763
788
|
onChange,
|
|
764
789
|
options,
|
|
765
790
|
testID,
|
|
766
|
-
value
|
|
791
|
+
value,
|
|
792
|
+
variant: DropdownVariant.Modal
|
|
767
793
|
}
|
|
768
794
|
) });
|
|
769
795
|
};
|
|
@@ -910,6 +936,7 @@ var EditUserModal = ({
|
|
|
910
936
|
const [role, setRole] = useState("");
|
|
911
937
|
const [tenantValue, setTenantValue] = useState(NO_TENANT_VALUE);
|
|
912
938
|
const [active, setActive] = useState(true);
|
|
939
|
+
const [blockedReason, setBlockedReason] = useState("");
|
|
913
940
|
const [submitting, setSubmitting] = useState(false);
|
|
914
941
|
const userId = user?.id;
|
|
915
942
|
useEffect(() => {
|
|
@@ -918,28 +945,36 @@ var EditUserModal = ({
|
|
|
918
945
|
setRole(user.roles[0] ?? "");
|
|
919
946
|
setTenantValue(user.tenantId ?? NO_TENANT_VALUE);
|
|
920
947
|
setActive(user.active);
|
|
948
|
+
setBlockedReason(user.blockedReason ?? "");
|
|
921
949
|
setSubmitting(false);
|
|
922
950
|
}, [visible, userId, user]);
|
|
923
|
-
const
|
|
951
|
+
const wasActive = user?.active ?? true;
|
|
952
|
+
const canSubmit = !submitting && displayName.trim() !== "" && role !== "" && !isBlockReasonMissing(wasActive, active, blockedReason);
|
|
924
953
|
const handleSubmit = async () => {
|
|
925
954
|
if (user === null) return;
|
|
926
955
|
setSubmitting(true);
|
|
927
|
-
const patch = {
|
|
928
|
-
displayName
|
|
956
|
+
const patch = buildEditPatch({
|
|
957
|
+
displayName,
|
|
929
958
|
role,
|
|
930
|
-
|
|
931
|
-
|
|
932
|
-
|
|
959
|
+
wasActive,
|
|
960
|
+
active,
|
|
961
|
+
blockedReason,
|
|
962
|
+
tenantId: isPlatformAdmin ? tenantValueToId(tenantValue) : void 0
|
|
963
|
+
});
|
|
933
964
|
const ok = await onSubmit(user.id, patch);
|
|
934
965
|
setSubmitting(false);
|
|
935
966
|
if (ok) onCancel();
|
|
936
967
|
};
|
|
968
|
+
const submitIfReady = () => {
|
|
969
|
+
if (canSubmit) void handleSubmit();
|
|
970
|
+
};
|
|
937
971
|
return /* @__PURE__ */ jsx(ModalShell, { onCancel, title: t(ACCESS_ADMIN_I18N.usersEditTitle), visible, children: /* @__PURE__ */ jsxs(View, { style: modalFormStyles.body, testID: testIDPrefix, children: [
|
|
938
972
|
/* @__PURE__ */ jsx(
|
|
939
973
|
FormField,
|
|
940
974
|
{
|
|
941
975
|
label: t(ACCESS_ADMIN_I18N.usersFieldDisplayName),
|
|
942
976
|
onChangeText: setDisplayName,
|
|
977
|
+
onSubmitEditing: submitIfReady,
|
|
943
978
|
placeholder: t(ACCESS_ADMIN_I18N.usersDisplayNamePlaceholder),
|
|
944
979
|
required: true,
|
|
945
980
|
testID: `${testIDPrefix}-display-name`,
|
|
@@ -980,6 +1015,19 @@ var EditUserModal = ({
|
|
|
980
1015
|
value: active
|
|
981
1016
|
}
|
|
982
1017
|
),
|
|
1018
|
+
active ? null : /* @__PURE__ */ jsx(
|
|
1019
|
+
FormField,
|
|
1020
|
+
{
|
|
1021
|
+
accessibilityHint: t(ACCESS_ADMIN_I18N.usersBlockedReasonHint),
|
|
1022
|
+
label: t(ACCESS_ADMIN_I18N.usersFieldBlockedReason),
|
|
1023
|
+
onChangeText: setBlockedReason,
|
|
1024
|
+
onSubmitEditing: submitIfReady,
|
|
1025
|
+
placeholder: t(ACCESS_ADMIN_I18N.usersBlockedReasonPlaceholder),
|
|
1026
|
+
required: wasActive,
|
|
1027
|
+
testID: `${testIDPrefix}-blocked-reason`,
|
|
1028
|
+
value: blockedReason
|
|
1029
|
+
}
|
|
1030
|
+
),
|
|
983
1031
|
/* @__PURE__ */ jsxs(View, { style: modalFormStyles.actions, children: [
|
|
984
1032
|
/* @__PURE__ */ jsx(
|
|
985
1033
|
Button,
|
|
@@ -1161,7 +1209,7 @@ var UserManagementPanel = ({
|
|
|
1161
1209
|
testID = ACCESS_ADMIN_TEST_IDS.usersPanel
|
|
1162
1210
|
}) => {
|
|
1163
1211
|
const palette = useAccessAdminPalette();
|
|
1164
|
-
const
|
|
1212
|
+
const styles2 = useMemo(() => buildStyles3(palette), [palette]);
|
|
1165
1213
|
const controller = useUserManagement(api, t);
|
|
1166
1214
|
const [query, setQuery] = useState("");
|
|
1167
1215
|
const [openModal, setOpenModal] = useState("none" /* None */);
|
|
@@ -1183,10 +1231,10 @@ var UserManagementPanel = ({
|
|
|
1183
1231
|
() => buildUserColumns({ t, tenants, testIDPrefix: testID, onEdit: openEdit, onReset: openReset }),
|
|
1184
1232
|
[t, tenants, testID]
|
|
1185
1233
|
);
|
|
1186
|
-
return /* @__PURE__ */ jsxs(View, { style:
|
|
1234
|
+
return /* @__PURE__ */ jsxs(View, { style: styles2.panel, testID, children: [
|
|
1187
1235
|
/* @__PURE__ */ jsx(ToastHost, { subscribe: controller.toastSubscribe, toastTestID: `${testID}-toast` }),
|
|
1188
|
-
/* @__PURE__ */ jsx(Text, { style:
|
|
1189
|
-
/* @__PURE__ */ jsx(Text, { style:
|
|
1236
|
+
/* @__PURE__ */ jsx(Text, { style: styles2.heading, children: t(ACCESS_ADMIN_I18N.usersHeading) }),
|
|
1237
|
+
/* @__PURE__ */ jsx(Text, { style: styles2.note, children: t(ACCESS_ADMIN_I18N.usersNote) }),
|
|
1190
1238
|
/* @__PURE__ */ jsx(
|
|
1191
1239
|
FilterBar,
|
|
1192
1240
|
{
|
|
@@ -1203,7 +1251,7 @@ var UserManagementPanel = ({
|
|
|
1203
1251
|
resultsCount: visibleUsers.length,
|
|
1204
1252
|
resultsLabel: t(ACCESS_ADMIN_I18N.usersResultsLabel),
|
|
1205
1253
|
testID: `${testID}-filter-bar`,
|
|
1206
|
-
children: /* @__PURE__ */ jsx(View, { style:
|
|
1254
|
+
children: /* @__PURE__ */ jsx(View, { style: styles2.search, children: /* @__PURE__ */ jsx(
|
|
1207
1255
|
FormField,
|
|
1208
1256
|
{
|
|
1209
1257
|
accessibilityLabel: t(ACCESS_ADMIN_I18N.usersSearchLabel),
|
|
@@ -1218,8 +1266,8 @@ var UserManagementPanel = ({
|
|
|
1218
1266
|
) })
|
|
1219
1267
|
}
|
|
1220
1268
|
),
|
|
1221
|
-
controller.loadFailed ? /* @__PURE__ */ jsxs(View, { style:
|
|
1222
|
-
/* @__PURE__ */ jsx(Text, { style:
|
|
1269
|
+
controller.loadFailed ? /* @__PURE__ */ jsxs(View, { style: styles2.errorBox, testID: `${testID}-load-error`, children: [
|
|
1270
|
+
/* @__PURE__ */ jsx(Text, { style: styles2.warning, children: t(ACCESS_ADMIN_I18N.usersLoadError) }),
|
|
1223
1271
|
/* @__PURE__ */ jsx(
|
|
1224
1272
|
Button,
|
|
1225
1273
|
{
|
|
@@ -1301,6 +1349,116 @@ var buildStyles3 = (c) => StyleSheet.create({
|
|
|
1301
1349
|
warning: { color: c.danger, fontSize: FONT_SM3, fontWeight: "600" }
|
|
1302
1350
|
});
|
|
1303
1351
|
|
|
1304
|
-
|
|
1352
|
+
// src/PermissionMatrix/permissionMatrixModel.ts
|
|
1353
|
+
function buildPermissionMatrix(roles, permissions, grants) {
|
|
1354
|
+
return roles.map((role) => {
|
|
1355
|
+
const held = new Set(grants[role.id] ?? []);
|
|
1356
|
+
const cells = permissions.map((permission) => ({ permission, granted: held.has(permission.id) }));
|
|
1357
|
+
return { role, cells, grantedCount: cells.filter((cell) => cell.granted).length };
|
|
1358
|
+
});
|
|
1359
|
+
}
|
|
1360
|
+
function grantStatusLabel(granted, t) {
|
|
1361
|
+
return granted ? t(ACCESS_ADMIN_I18N.permissionsGranted) : t(ACCESS_ADMIN_I18N.permissionsNotGranted);
|
|
1362
|
+
}
|
|
1363
|
+
function cellAccessibilityLabel(role, permission, granted, t) {
|
|
1364
|
+
return t(ACCESS_ADMIN_I18N.permissionsCellLabel, role.label, permission.label, grantStatusLabel(granted, t));
|
|
1365
|
+
}
|
|
1366
|
+
var SPACE_XS4 = 4;
|
|
1367
|
+
var SPACE_SM5 = 8;
|
|
1368
|
+
var SPACE_MD5 = 12;
|
|
1369
|
+
var RADIUS = 8;
|
|
1370
|
+
var MAX_WIDTH = 1200;
|
|
1371
|
+
var LABEL_COLUMN_WIDTH = 280;
|
|
1372
|
+
var ROLE_COLUMN_WIDTH = 140;
|
|
1373
|
+
var HEADING_SIZE = 18;
|
|
1374
|
+
var BODY_SIZE = 14;
|
|
1375
|
+
var LINE_HEIGHT = 20;
|
|
1376
|
+
var styles = StyleSheet.create({
|
|
1377
|
+
root: { alignSelf: "center", gap: SPACE_MD5, maxWidth: MAX_WIDTH, width: "100%" },
|
|
1378
|
+
heading: { fontSize: HEADING_SIZE, fontWeight: "600", lineHeight: LINE_HEIGHT + SPACE_XS4 },
|
|
1379
|
+
body: { fontSize: BODY_SIZE, lineHeight: LINE_HEIGHT },
|
|
1380
|
+
strong: { fontSize: BODY_SIZE, fontWeight: "600", lineHeight: LINE_HEIGHT },
|
|
1381
|
+
list: { gap: SPACE_MD5 },
|
|
1382
|
+
card: { borderRadius: RADIUS, borderWidth: StyleSheet.hairlineWidth, gap: SPACE_SM5, padding: SPACE_MD5 },
|
|
1383
|
+
stackRow: { flexDirection: "row", flexWrap: "wrap", gap: SPACE_SM5, justifyContent: "space-between" },
|
|
1384
|
+
stackLabel: { flexBasis: 0, flexGrow: 1, minWidth: 0 },
|
|
1385
|
+
tableRow: { borderBottomWidth: StyleSheet.hairlineWidth, flexDirection: "row" },
|
|
1386
|
+
labelCell: { padding: SPACE_SM5, width: LABEL_COLUMN_WIDTH },
|
|
1387
|
+
roleCell: { padding: SPACE_SM5, width: ROLE_COLUMN_WIDTH }
|
|
1388
|
+
});
|
|
1389
|
+
var statusColor = (granted, palette) => granted ? palette.textPrimary : palette.textSecondary;
|
|
1390
|
+
var StackedMatrix = ({ columns, palette, t, testID }) => /* @__PURE__ */ jsx(View, { style: styles.list, children: columns.map(({ role, cells, grantedCount }) => /* @__PURE__ */ jsxs(
|
|
1391
|
+
View,
|
|
1392
|
+
{
|
|
1393
|
+
style: [styles.card, { backgroundColor: palette.panelSurface, borderColor: palette.border }],
|
|
1394
|
+
testID: `${testID}-role-${role.id}`,
|
|
1395
|
+
children: [
|
|
1396
|
+
/* @__PURE__ */ jsx(Text, { style: [styles.strong, { color: palette.textPrimary }], children: role.label }),
|
|
1397
|
+
/* @__PURE__ */ jsx(Text, { style: [styles.body, { color: palette.textSecondary }], children: t(ACCESS_ADMIN_I18N.permissionsRoleCount, String(grantedCount), String(cells.length)) }),
|
|
1398
|
+
cells.map(({ permission, granted }) => /* @__PURE__ */ jsxs(
|
|
1399
|
+
View,
|
|
1400
|
+
{
|
|
1401
|
+
accessibilityHint: t(ACCESS_ADMIN_I18N.permissionsReadOnlyHint),
|
|
1402
|
+
accessibilityLabel: cellAccessibilityLabel(role, permission, granted, t),
|
|
1403
|
+
accessible: true,
|
|
1404
|
+
style: styles.stackRow,
|
|
1405
|
+
testID: `${testID}-cell-${role.id}-${permission.id}`,
|
|
1406
|
+
children: [
|
|
1407
|
+
/* @__PURE__ */ jsx(Text, { style: [styles.body, styles.stackLabel, { color: palette.textPrimary }], children: permission.label }),
|
|
1408
|
+
/* @__PURE__ */ jsx(Text, { style: [granted ? styles.strong : styles.body, { color: statusColor(granted, palette) }], children: grantStatusLabel(granted, t) })
|
|
1409
|
+
]
|
|
1410
|
+
},
|
|
1411
|
+
permission.id
|
|
1412
|
+
))
|
|
1413
|
+
]
|
|
1414
|
+
},
|
|
1415
|
+
role.id
|
|
1416
|
+
)) });
|
|
1417
|
+
var TableMatrix = ({ columns, permissions, palette, t, testID }) => /* @__PURE__ */ jsx(ScrollView, { horizontal: true, testID: `${testID}-table`, children: /* @__PURE__ */ jsxs(View, { style: [styles.card, { backgroundColor: palette.panelSurface, borderColor: palette.border }], children: [
|
|
1418
|
+
/* @__PURE__ */ jsxs(View, { style: [styles.tableRow, { borderColor: palette.border }], children: [
|
|
1419
|
+
/* @__PURE__ */ jsx(Text, { style: [styles.strong, styles.labelCell, { color: palette.textPrimary }], children: t(ACCESS_ADMIN_I18N.permissionsColPermission) }),
|
|
1420
|
+
columns.map(({ role }) => /* @__PURE__ */ jsx(Text, { style: [styles.strong, styles.roleCell, { color: palette.textPrimary }], children: role.label }, role.id))
|
|
1421
|
+
] }),
|
|
1422
|
+
permissions.map((permission, index) => /* @__PURE__ */ jsxs(View, { style: [styles.tableRow, { borderColor: palette.border }], children: [
|
|
1423
|
+
/* @__PURE__ */ jsx(Text, { style: [styles.body, styles.labelCell, { color: palette.textPrimary }], children: permission.label }),
|
|
1424
|
+
columns.map(({ role, cells }) => {
|
|
1425
|
+
const granted = cells[index]?.granted === true;
|
|
1426
|
+
return /* @__PURE__ */ jsx(
|
|
1427
|
+
Text,
|
|
1428
|
+
{
|
|
1429
|
+
accessibilityHint: t(ACCESS_ADMIN_I18N.permissionsReadOnlyHint),
|
|
1430
|
+
accessibilityLabel: cellAccessibilityLabel(role, permission, granted, t),
|
|
1431
|
+
style: [granted ? styles.strong : styles.body, styles.roleCell, { color: statusColor(granted, palette) }],
|
|
1432
|
+
testID: `${testID}-cell-${role.id}-${permission.id}`,
|
|
1433
|
+
children: grantStatusLabel(granted, t)
|
|
1434
|
+
},
|
|
1435
|
+
role.id
|
|
1436
|
+
);
|
|
1437
|
+
})
|
|
1438
|
+
] }, permission.id))
|
|
1439
|
+
] }) });
|
|
1440
|
+
var PermissionMatrix = ({
|
|
1441
|
+
roles,
|
|
1442
|
+
permissions,
|
|
1443
|
+
grants,
|
|
1444
|
+
t,
|
|
1445
|
+
testID = ACCESS_ADMIN_TEST_IDS.permissionMatrix
|
|
1446
|
+
}) => {
|
|
1447
|
+
const palette = useAccessAdminPalette();
|
|
1448
|
+
const { width } = useWindowDimensions();
|
|
1449
|
+
const columns = useMemo(() => buildPermissionMatrix(roles, permissions, grants), [roles, permissions, grants]);
|
|
1450
|
+
const isWide = width >= LAYOUT_COLLAPSE_BREAKPOINT;
|
|
1451
|
+
const isEmpty = roles.length === 0 || permissions.length === 0;
|
|
1452
|
+
const partProps = { columns, permissions, palette, t, testID };
|
|
1453
|
+
return /* @__PURE__ */ jsxs(View, { style: styles.root, testID, children: [
|
|
1454
|
+
/* @__PURE__ */ jsx(Text, { accessibilityRole: "header", style: [styles.heading, { color: palette.textPrimary }], children: t(ACCESS_ADMIN_I18N.permissionsHeading) }),
|
|
1455
|
+
/* @__PURE__ */ jsx(Text, { style: [styles.body, { color: palette.textSecondary }], children: t(ACCESS_ADMIN_I18N.permissionsNote) }),
|
|
1456
|
+
isEmpty ? /* @__PURE__ */ jsx(Text, { style: [styles.body, { color: palette.textSecondary }], testID: `${testID}-empty`, children: t(ACCESS_ADMIN_I18N.permissionsEmpty) }) : null,
|
|
1457
|
+
!isEmpty && isWide ? /* @__PURE__ */ jsx(TableMatrix, { ...partProps }) : null,
|
|
1458
|
+
!isEmpty && !isWide ? /* @__PURE__ */ jsx(StackedMatrix, { ...partProps }) : null
|
|
1459
|
+
] });
|
|
1460
|
+
};
|
|
1461
|
+
|
|
1462
|
+
export { ACCESS_ADMIN_I18N, ACCESS_ADMIN_TEST_IDS, AccessLinkPanel, AccessResultTone, AccountLinkPanel, PermissionMatrix, UserManagementPanel, accountDisplayLabel, activeLinksForSubject, buildAccountOptions, buildCapabilityLinkMailto, buildPermissionMatrix, capabilityExpiryDate, capabilityExpiryDays, daysUntilAnchor, formatLinkDate, linksForSubject, useAccessAdminPalette, useCapabilityLinkMint, useSubjectAccountLink };
|
|
1305
1463
|
//# sourceMappingURL=index.mjs.map
|
|
1306
1464
|
//# sourceMappingURL=index.mjs.map
|