@zealamic/payload-auth-rbac-plugin 1.0.0-beta.9 → 1.0.1
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 +27 -31
- package/assets/cover-photo.jpg +0 -0
- package/dist/components/role-permission-matrix-client/default-data.js +3 -2
- package/dist/components/role-permission-matrix-client/default-data.js.map +1 -1
- package/dist/components/role-permission-matrix-client/index.js +20 -70
- package/dist/components/role-permission-matrix-client/index.js.map +1 -1
- package/dist/components/role-permission-matrix-client/matrix.module.scss +66 -0
- package/dist/components/role-permission-matrix-client/types.d.ts +4 -6
- package/dist/components/role-permission-matrix-client/types.js.map +1 -1
- package/dist/styles/variables.scss +1 -0
- package/docs/COLLECTIONS.md +440 -0
- package/docs/TRANSLATIONS.md +469 -0
- package/docs/UTILS.md +226 -0
- package/package.json +7 -28
- package/src/collections/permission-actions/default-data.ts +36 -0
- package/src/collections/permission-actions/index.ts +144 -0
- package/src/collections/permission-actions/types.ts +56 -0
- package/src/collections/permission-features/default-data.ts +30 -0
- package/src/collections/permission-features/index.ts +122 -0
- package/src/collections/permission-features/types.ts +47 -0
- package/src/collections/permissions/default-data.ts +38 -0
- package/src/collections/permissions/index.ts +160 -0
- package/src/collections/permissions/types.ts +57 -0
- package/src/collections/roles/default-data.ts +44 -0
- package/src/collections/roles/hooks/sync-permission-matrix-draft.ts +73 -0
- package/src/collections/roles/index.ts +178 -0
- package/src/collections/roles/types.ts +56 -0
- package/src/collections/roles-permissions/default-data.ts +28 -0
- package/src/collections/roles-permissions/index.ts +107 -0
- package/src/collections/roles-permissions/types.ts +42 -0
- package/src/collections/users/default-data.ts +19 -0
- package/src/collections/users/index.ts +148 -0
- package/src/collections/users/parent-path.ts +310 -0
- package/src/collections/users/types.ts +25 -0
- package/src/components/role-permission-matrix-client/default-data.ts +25 -0
- package/src/components/role-permission-matrix-client/index.tsx +369 -0
- package/src/components/role-permission-matrix-client/matrix.module.scss +66 -0
- package/src/components/role-permission-matrix-client/types.ts +16 -0
- package/src/endpoints/customEndpointHandler.ts +5 -0
- package/src/exports/client.ts +1 -0
- package/src/exports/rsc.ts +0 -0
- package/src/general-types.d.ts +5 -0
- package/src/index.ts +249 -0
- package/src/lib/constants/general.ts +1 -0
- package/src/lib/constants/index.ts +15 -0
- package/src/lib/constants/permission-action.ts +9 -0
- package/src/lib/constants/permission-feature.ts +4 -0
- package/src/lib/constants/permission.ts +4 -0
- package/src/lib/constants/role.ts +10 -0
- package/src/lib/constants/user.ts +1 -0
- package/src/lib/utils/access.ts +611 -0
- package/src/lib/utils/data.ts +7 -0
- package/src/lib/utils/fields.ts +62 -0
- package/src/lib/utils/index.ts +4 -0
- package/src/lib/utils/localization.ts +106 -0
- package/src/styles/variables.scss +1 -0
- package/src/types.ts +64 -0
package/README.md
CHANGED
|
@@ -10,13 +10,13 @@ Permissions live in the database (feature + action), are assigned to roles, and
|
|
|
10
10
|
|
|
11
11
|
## Documentation
|
|
12
12
|
|
|
13
|
-
| Guide
|
|
14
|
-
|
|
|
15
|
-
| **[COLLECTIONS](
|
|
16
|
-
| **[UTILS](
|
|
17
|
-
| **[TRANSLATIONS](
|
|
13
|
+
| Guide | Read when you need to… |
|
|
14
|
+
| ------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------ |
|
|
15
|
+
| **[COLLECTIONS](https://github.com/zealamic/payload-auth-rbac-plugin/blob/main/docs/COLLECTIONS.md)** | Understand plugin collections, users augmentation, `dataScope`, permission matrix, and **customize** fields/access/admin |
|
|
16
|
+
| **[UTILS](https://github.com/zealamic/payload-auth-rbac-plugin/blob/main/docs/UTILS.md)** | Wire **access helpers** on your app collections (`getPermissionAccess`, data-scope filters, examples) |
|
|
17
|
+
| **[TRANSLATIONS](https://github.com/zealamic/payload-auth-rbac-plugin/blob/main/docs/TRANSLATIONS.md)** | Localize Admin labels, select options, and permission-matrix UI (`en`, `vi`, …) |
|
|
18
18
|
|
|
19
|
-
**Typical flow:** install → register plugin → seed RBAC data ([COLLECTIONS](
|
|
19
|
+
**Typical flow:** install → register plugin → seed RBAC data ([COLLECTIONS](https://github.com/zealamic/payload-auth-rbac-plugin/blob/main/docs/COLLECTIONS.md)) → protect app collections ([UTILS](https://github.com/zealamic/payload-auth-rbac-plugin/blob/main/docs/UTILS.md)) → translate Admin UI ([TRANSLATIONS](https://github.com/zealamic/payload-auth-rbac-plugin/blob/main/docs/TRANSLATIONS.md)).
|
|
20
20
|
|
|
21
21
|
Demo: `dev/rbac.ts`, `dev/collections/posts.ts`.
|
|
22
22
|
|
|
@@ -24,13 +24,13 @@ Demo: `dev/rbac.ts`, `dev/collections/posts.ts`.
|
|
|
24
24
|
|
|
25
25
|
## Key features
|
|
26
26
|
|
|
27
|
-
- **Five RBAC collections** — features, actions, permissions, roles, join table ([details](
|
|
27
|
+
- **Five RBAC collections** — features, actions, permissions, roles, join table ([details](https://github.com/zealamic/payload-auth-rbac-plugin/blob/main/docs/COLLECTIONS.md))
|
|
28
28
|
- **Multi-role users** — union of enabled grants across assigned roles
|
|
29
|
-
- **Granular permissions** — any `featureCode` + `actionCode` pair ([helpers](
|
|
30
|
-
- **Data scope** — per-role `own` / `hierarchy` / `all` for row-level filtering (`
|
|
29
|
+
- **Granular permissions** — any `featureCode` + `actionCode` pair ([helpers](https://github.com/zealamic/payload-auth-rbac-plugin/blob/main/docs/UTILS.md))
|
|
30
|
+
- **Data scope** — per-role `own` / `hierarchy` / `all` for row-level filtering ([`dataScope` vs `isSuperAdmin`](https://github.com/zealamic/payload-auth-rbac-plugin/blob/main/docs/COLLECTIONS.md#what-is-datascope)`)
|
|
31
31
|
- **Permission matrix** — role edit UI; syncs to `roles-permissions` on save
|
|
32
32
|
- **TypeScript** — typed plugin options and exports (`/types`)
|
|
33
|
-
- **i18n** — plugin-owned translations merged into Payload i18n ([guide](
|
|
33
|
+
- **i18n** — plugin-owned translations merged into Payload i18n ([guide](https://github.com/zealamic/payload-auth-rbac-plugin/blob/main/docs/TRANSLATIONS.md))
|
|
34
34
|
|
|
35
35
|
---
|
|
36
36
|
|
|
@@ -66,17 +66,15 @@ export default buildConfig({
|
|
|
66
66
|
1. **permission-features** — e.g. `posts`, `users` (`code` = `featureCode` in access helpers)
|
|
67
67
|
2. **permission-actions** — e.g. `create`, `read`, `update`, `delete`
|
|
68
68
|
3. **permissions** — one row per feature + action pair
|
|
69
|
-
4. **roles** — set
|
|
70
|
-
5. **users** — assign roles; bootstrap
|
|
69
|
+
4. **roles** — set [dataScope](https://github.com/zealamic/payload-auth-rbac-plugin/blob/main/docs/COLLECTIONS.md#what-is-datascope); configure matrix on update screen → Save
|
|
70
|
+
5. **users** — assign roles; bootstrap [isSuperAdmin](https://github.com/zealamic/payload-auth-rbac-plugin/blob/main/docs/COLLECTIONS.md#bootstrap-super-admin) via seed/API
|
|
71
71
|
|
|
72
|
-
→ Full collection reference: **[COLLECTIONS](
|
|
72
|
+
→ Full collection reference: **[COLLECTIONS](https://github.com/zealamic/payload-auth-rbac-plugin/blob/main/docs/COLLECTIONS.md)**
|
|
73
73
|
|
|
74
74
|
### 3. Protect app collections
|
|
75
75
|
|
|
76
76
|
```ts
|
|
77
|
-
import {
|
|
78
|
-
getPermissionAccess,
|
|
79
|
-
} from "@zealamic/payload-auth-rbac-plugin";
|
|
77
|
+
import { getPermissionAccess } from "@zealamic/payload-auth-rbac-plugin";
|
|
80
78
|
|
|
81
79
|
export const Posts: CollectionConfig = {
|
|
82
80
|
slug: "posts",
|
|
@@ -121,18 +119,18 @@ export const Posts: CollectionConfig = {
|
|
|
121
119
|
|
|
122
120
|
**Access order:** anonymous → deny · super admin → allow · else → matrix permission (+ data scope when using scope helpers).
|
|
123
121
|
|
|
124
|
-
→ All helpers with examples: **[UTILS](
|
|
122
|
+
→ All helpers with examples: **[UTILS](https://github.com/zealamic/payload-auth-rbac-plugin/blob/main/docs/UTILS.md)**
|
|
125
123
|
|
|
126
124
|
---
|
|
127
125
|
|
|
128
126
|
## Plugin options
|
|
129
127
|
|
|
130
|
-
| Option | Default | Description
|
|
131
|
-
| --------------------------- | ------- |
|
|
132
|
-
| `disabled` | `false` | Skip runtime wiring; schema still registers
|
|
133
|
-
| `autoModifyUsersCollection` | `true` | Add RBAC fields + access on users collection
|
|
134
|
-
| `translations` | — | Admin / matrix i18n → **[TRANSLATIONS](
|
|
135
|
-
| `collections` | — | Per-collection overrides → **[COLLECTIONS](
|
|
128
|
+
| Option | Default | Description |
|
|
129
|
+
| --------------------------- | ------- | -------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
130
|
+
| `disabled` | `false` | Skip runtime wiring; schema still registers |
|
|
131
|
+
| `autoModifyUsersCollection` | `true` | Add RBAC fields + access on users collection |
|
|
132
|
+
| `translations` | — | Admin / matrix i18n → **[TRANSLATIONS](https://github.com/zealamic/payload-auth-rbac-plugin/blob/main/docs/TRANSLATIONS.md)** |
|
|
133
|
+
| `collections` | — | Per-collection overrides → **[COLLECTIONS](https://github.com/zealamic/payload-auth-rbac-plugin/blob/main/docs/COLLECTIONS.md#customizing-collections)** |
|
|
136
134
|
|
|
137
135
|
Types: `@zealamic/payload-auth-rbac-plugin/types`
|
|
138
136
|
|
|
@@ -140,14 +138,14 @@ Types: `@zealamic/payload-auth-rbac-plugin/types`
|
|
|
140
138
|
|
|
141
139
|
## Exported helpers (summary)
|
|
142
140
|
|
|
143
|
-
Full reference: **[UTILS](
|
|
141
|
+
Full reference: **[UTILS](https://github.com/zealamic/payload-auth-rbac-plugin/blob/main/docs/UTILS.md)**
|
|
144
142
|
|
|
145
|
-
| Function | Purpose
|
|
146
|
-
| ----------------------------------------------------- |
|
|
143
|
+
| Function | Purpose |
|
|
144
|
+
| ----------------------------------------------------- | ------------------------------------------------------ |
|
|
147
145
|
| `getPermissionAccess` | Unified helper: permission / read scope / modify scope |
|
|
148
|
-
| `getSuperAdminAccess` | Super admin only (RBAC collections default)
|
|
149
|
-
| `canAccessDocumentByDataScope` | Single-document scope check
|
|
150
|
-
| `resolveEffectiveDataScope` / `getDataScopeReadWhere` | Scope resolution & query filters
|
|
146
|
+
| `getSuperAdminAccess` | Super admin only (RBAC collections default) |
|
|
147
|
+
| `canAccessDocumentByDataScope` | Single-document scope check |
|
|
148
|
+
| `resolveEffectiveDataScope` / `getDataScopeReadWhere` | Scope resolution & query filters |
|
|
151
149
|
|
|
152
150
|
Constants: `CONSTANTS.ROLE.DATA_SCOPE`, etc.
|
|
153
151
|
|
|
@@ -171,5 +169,3 @@ MIT
|
|
|
171
169
|
---
|
|
172
170
|
|
|
173
171
|
> _If this plugin helps your team ship safer access control with less friction, thank you for giving it a place in your stack._
|
|
174
|
-
|
|
175
|
-
|
|
Binary file
|
|
@@ -7,11 +7,12 @@ export const rolePermissionMatrixClientDefaultTranslations = {
|
|
|
7
7
|
placeholder: "Loading permission matrix..."
|
|
8
8
|
},
|
|
9
9
|
title: "Permission Matrix",
|
|
10
|
+
featuresLabel: "Features",
|
|
10
11
|
features: {
|
|
11
|
-
|
|
12
|
+
users: "Users"
|
|
12
13
|
},
|
|
14
|
+
actionsLabel: "Actions",
|
|
13
15
|
actions: {
|
|
14
|
-
label: "Actions",
|
|
15
16
|
create: "Create",
|
|
16
17
|
read: "Read",
|
|
17
18
|
update: "Update",
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/components/role-permission-matrix-client/default-data.ts"],"sourcesContent":["import type { RolePermissionMatrixClientTranslations } from \"./types.js\"
|
|
1
|
+
{"version":3,"sources":["../../../src/components/role-permission-matrix-client/default-data.ts"],"sourcesContent":["import type { RolePermissionMatrixClientTranslations } from \"./types.js\";\n\nexport const rolePermissionMatrixClientDefaultTranslations: RolePermissionMatrixClientTranslations =\n {\n en: {\n viewInUpdateScreenOnly: {\n label: \"View permission matrix in update screen only\",\n },\n loading: {\n placeholder: \"Loading permission matrix...\",\n },\n title: \"Permission Matrix\",\n featuresLabel: \"Features\",\n features: {\n users: \"Users\",\n },\n actionsLabel: \"Actions\",\n actions: {\n create: \"Create\",\n read: \"Read\",\n update: \"Update\",\n delete: \"Delete\",\n },\n },\n };\n"],"names":["rolePermissionMatrixClientDefaultTranslations","en","viewInUpdateScreenOnly","label","loading","placeholder","title","featuresLabel","features","users","actionsLabel","actions","create","read","update","delete"],"mappings":"AAEA,OAAO,MAAMA,gDACX;IACEC,IAAI;QACFC,wBAAwB;YACtBC,OAAO;QACT;QACAC,SAAS;YACPC,aAAa;QACf;QACAC,OAAO;QACPC,eAAe;QACfC,UAAU;YACRC,OAAO;QACT;QACAC,cAAc;QACdC,SAAS;YACPC,QAAQ;YACRC,MAAM;YACNC,QAAQ;YACRC,QAAQ;QACV;IACF;AACF,EAAE"}
|
|
@@ -6,6 +6,8 @@ import { STATUS as PERMISSION_STATUS } from "../../lib/constants/permission.js";
|
|
|
6
6
|
import { STATUS as PERMISSION_ACTION_STATUS, TYPE } from "../../lib/constants/permission-action.js";
|
|
7
7
|
import { STATUS as PERMISSION_FEATURE_STATUS } from "../../lib/constants/permission-feature.js";
|
|
8
8
|
import { toID } from "../../lib/utils/data.js";
|
|
9
|
+
import styles from "./matrix.module.scss";
|
|
10
|
+
const RBAC_PREFIX = "rbac";
|
|
9
11
|
export const RolePermissionMatrixClient = ()=>{
|
|
10
12
|
const checkboxId = useId();
|
|
11
13
|
const { config } = useConfig();
|
|
@@ -103,61 +105,38 @@ export const RolePermissionMatrixClient = ()=>{
|
|
|
103
105
|
]);
|
|
104
106
|
if (!id) {
|
|
105
107
|
return /*#__PURE__*/ _jsx("div", {
|
|
106
|
-
|
|
107
|
-
opacity: 0.8,
|
|
108
|
-
padding: "8px 0"
|
|
109
|
-
},
|
|
108
|
+
className: styles[`${RBAC_PREFIX}-component-placeholder`],
|
|
110
109
|
children: t(`components:rolePermissionMatrix:viewInUpdateScreenOnly:label`)
|
|
111
110
|
});
|
|
112
111
|
}
|
|
113
112
|
if (loading) {
|
|
114
113
|
return /*#__PURE__*/ _jsx("div", {
|
|
115
|
-
|
|
116
|
-
opacity: 0.8,
|
|
117
|
-
padding: "8px 0"
|
|
118
|
-
},
|
|
114
|
+
className: styles[`${RBAC_PREFIX}-component-placeholder`],
|
|
119
115
|
children: t(`components:rolePermissionMatrix:loading:placeholder`)
|
|
120
116
|
});
|
|
121
117
|
}
|
|
122
118
|
return /*#__PURE__*/ _jsxs("div", {
|
|
123
119
|
children: [
|
|
124
120
|
/*#__PURE__*/ _jsx("div", {
|
|
125
|
-
|
|
126
|
-
fontWeight: 600,
|
|
127
|
-
marginBottom: 8
|
|
128
|
-
},
|
|
121
|
+
className: styles[`${RBAC_PREFIX}-component-title`],
|
|
129
122
|
children: t(`components:rolePermissionMatrix:title`)
|
|
130
123
|
}),
|
|
131
124
|
/*#__PURE__*/ _jsx("div", {
|
|
132
|
-
|
|
133
|
-
border: "1px solid #333",
|
|
134
|
-
borderRadius: 8
|
|
135
|
-
},
|
|
125
|
+
className: styles[`${RBAC_PREFIX}-table-container`],
|
|
136
126
|
children: /*#__PURE__*/ _jsxs("table", {
|
|
137
|
-
|
|
138
|
-
borderCollapse: "collapse",
|
|
139
|
-
width: "100%"
|
|
140
|
-
},
|
|
127
|
+
className: styles[`${RBAC_PREFIX}-table`],
|
|
141
128
|
children: [
|
|
142
129
|
/*#__PURE__*/ _jsx("thead", {
|
|
143
130
|
children: /*#__PURE__*/ _jsxs("tr", {
|
|
144
131
|
children: [
|
|
145
132
|
/*#__PURE__*/ _jsx("th", {
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
textAlign: "left",
|
|
149
|
-
borderRight: "1px solid #333",
|
|
150
|
-
width: "25%"
|
|
151
|
-
},
|
|
152
|
-
children: t(`components:rolePermissionMatrix:features:label`)
|
|
133
|
+
className: styles[`${RBAC_PREFIX}-table-th-feature`],
|
|
134
|
+
children: t(`components:rolePermissionMatrix:featuresLabel`)
|
|
153
135
|
}),
|
|
154
136
|
/*#__PURE__*/ _jsx("th", {
|
|
155
|
-
|
|
156
|
-
padding: "8px",
|
|
157
|
-
textAlign: "left"
|
|
158
|
-
},
|
|
137
|
+
className: styles[`${RBAC_PREFIX}-table-th-action`],
|
|
159
138
|
colSpan: actions.filter((action)=>action.type === TYPE.MAIN).length,
|
|
160
|
-
children: t(`components:rolePermissionMatrix:
|
|
139
|
+
children: t(`components:rolePermissionMatrix:actionsLabel`)
|
|
161
140
|
})
|
|
162
141
|
]
|
|
163
142
|
})
|
|
@@ -172,36 +151,23 @@ export const RolePermissionMatrixClient = ()=>{
|
|
|
172
151
|
/*#__PURE__*/ _jsxs("tr", {
|
|
173
152
|
children: [
|
|
174
153
|
/*#__PURE__*/ _jsx("td", {
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
padding: "0.5rem",
|
|
178
|
-
borderRight: "1px solid #333"
|
|
179
|
-
},
|
|
180
|
-
children: feature.code || feature.id
|
|
154
|
+
className: styles[`${RBAC_PREFIX}-table-td-feature`],
|
|
155
|
+
children: t(`components:rolePermissionMatrix:features:${feature.code}`) || feature.id
|
|
181
156
|
}),
|
|
182
157
|
mainActions.map((action)=>{
|
|
183
158
|
const matchedPermission = permissions.find((permission)=>toID(permission.permissionFeature) === String(feature.id) && toID(permission.permissionAction) === String(action.id));
|
|
184
159
|
if (!matchedPermission) {
|
|
185
160
|
return /*#__PURE__*/ _jsx("td", {
|
|
186
|
-
|
|
187
|
-
borderTop: "1px solid #333",
|
|
188
|
-
padding: "0.5rem"
|
|
189
|
-
},
|
|
161
|
+
className: styles[`${RBAC_PREFIX}-table-td-action`],
|
|
190
162
|
children: "-"
|
|
191
163
|
}, `${feature.id}-${action.id}`);
|
|
192
164
|
}
|
|
193
165
|
const permissionID = String(matchedPermission.id);
|
|
194
166
|
const checked = typeof draftValue[permissionID] === "boolean" ? draftValue[permissionID] : enabledByPermissionID.get(permissionID) ?? false;
|
|
195
167
|
return /*#__PURE__*/ _jsx("td", {
|
|
196
|
-
|
|
197
|
-
borderTop: "1px solid #333",
|
|
198
|
-
padding: "0.5rem"
|
|
199
|
-
},
|
|
168
|
+
className: styles[`${RBAC_PREFIX}-table-td-action`],
|
|
200
169
|
children: /*#__PURE__*/ _jsxs("div", {
|
|
201
|
-
|
|
202
|
-
display: "flex",
|
|
203
|
-
alignItems: "center"
|
|
204
|
-
},
|
|
170
|
+
className: styles[`${RBAC_PREFIX}-table-td-action-container`],
|
|
205
171
|
children: [
|
|
206
172
|
/*#__PURE__*/ _jsx("input", {
|
|
207
173
|
type: "checkbox",
|
|
@@ -215,19 +181,11 @@ export const RolePermissionMatrixClient = ()=>{
|
|
|
215
181
|
[permissionID]: event.target.checked
|
|
216
182
|
});
|
|
217
183
|
},
|
|
218
|
-
|
|
219
|
-
userSelect: "none",
|
|
220
|
-
cursor: "pointer"
|
|
221
|
-
}
|
|
184
|
+
className: styles[`${RBAC_PREFIX}-table-td-action-input`]
|
|
222
185
|
}),
|
|
223
186
|
/*#__PURE__*/ _jsx("label", {
|
|
224
187
|
htmlFor: `permission-matrix-checkbox-${checkboxId}-${feature.id}-${action.id}`,
|
|
225
|
-
|
|
226
|
-
display: "inline-block",
|
|
227
|
-
paddingLeft: "0.25rem",
|
|
228
|
-
userSelect: "none",
|
|
229
|
-
cursor: "pointer"
|
|
230
|
-
},
|
|
188
|
+
className: styles[`${RBAC_PREFIX}-table-td-action-label`],
|
|
231
189
|
children: t(`components:rolePermissionMatrix:actions:${action.code}`) || action.id
|
|
232
190
|
})
|
|
233
191
|
]
|
|
@@ -239,18 +197,10 @@ export const RolePermissionMatrixClient = ()=>{
|
|
|
239
197
|
isSubActionInPermission && /*#__PURE__*/ _jsxs("tr", {
|
|
240
198
|
children: [
|
|
241
199
|
/*#__PURE__*/ _jsx("td", {
|
|
242
|
-
|
|
243
|
-
borderRight: "1px solid #333",
|
|
244
|
-
padding: "8px",
|
|
245
|
-
textAlign: "right"
|
|
246
|
-
}
|
|
200
|
+
className: styles[`${RBAC_PREFIX}-table-td-feature`]
|
|
247
201
|
}),
|
|
248
202
|
/*#__PURE__*/ _jsx("td", {
|
|
249
|
-
|
|
250
|
-
borderTop: "1px solid #333",
|
|
251
|
-
padding: "8px",
|
|
252
|
-
textAlign: "left"
|
|
253
|
-
},
|
|
203
|
+
className: styles[`${RBAC_PREFIX}-table-td-action`],
|
|
254
204
|
colSpan: mainActions.length,
|
|
255
205
|
children: subActions.map((action)=>{
|
|
256
206
|
const matchedPermission = permissions.find((permission)=>toID(permission.permissionFeature) === String(feature.id) && toID(permission.permissionAction) === String(action.id));
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/components/role-permission-matrix-client/index.tsx"],"sourcesContent":["\"use client\";\n\nimport {\n useConfig,\n useDocumentInfo,\n useField,\n useTranslation,\n} from \"@payloadcms/ui\";\nimport { Fragment, useEffect, useId, useMemo, useRef, useState } from \"react\";\nimport type { PermissionAction } from \"../../collections/permission-actions/types.js\";\nimport type { PermissionFeature } from \"../../collections/permission-features/types.js\";\nimport type { Permission } from \"../../collections/permissions/types.js\";\nimport type { RolePermission } from \"../../collections/roles-permissions/types.js\";\nimport { STATUS as PERMISSION_STATUS } from \"../../lib/constants/permission.js\";\nimport {\n STATUS as PERMISSION_ACTION_STATUS,\n TYPE,\n} from \"../../lib/constants/permission-action.js\";\nimport { STATUS as PERMISSION_FEATURE_STATUS } from \"../../lib/constants/permission-feature.js\";\nimport { toID } from \"../../lib/utils/data.js\";\n\ntype ApiListResponse<T> = {\n docs?: T[];\n};\n\nexport const RolePermissionMatrixClient = () => {\n const checkboxId = useId();\n const { config } = useConfig();\n const { hasSavePermission, id } = useDocumentInfo();\n const { setValue, value } = useField<Record<string, boolean> | null>({\n path: \"permissionMatrixDraft\",\n });\n const isReadOnly = !hasSavePermission;\n\n const [features, setFeatures] = useState<PermissionFeature[]>([]);\n const [actions, setActions] = useState<PermissionAction[]>([]);\n const [permissions, setPermissions] = useState<Permission[]>([]);\n const [rolePermissions, setRolePermissions] = useState<RolePermission[]>([]);\n const [loading, setLoading] = useState(true);\n const { t } = useTranslation();\n const seededForRoleIdRef = useRef<string | null>(null);\n\n useEffect(() => {\n const run = async () => {\n setLoading(true);\n try {\n const base = config?.routes?.api || \"/api\";\n\n const [featuresRes, actionsRes, permissionsRes, rolePermissionsRes] =\n await Promise.all([\n fetch(\n `${base}/permission-features?limit=0&depth=0&where[status][equals]=${PERMISSION_FEATURE_STATUS.ACTIVE}`,\n { credentials: \"include\" },\n ),\n fetch(\n `${base}/permission-actions?limit=0&depth=0&where[status][equals]=${PERMISSION_ACTION_STATUS.ACTIVE}`,\n { credentials: \"include\" },\n ),\n fetch(\n `${base}/permissions?limit=0&depth=1&where[status][equals]=${PERMISSION_STATUS.ACTIVE}`,\n { credentials: \"include\" },\n ),\n id\n ? fetch(\n `${base}/roles-permissions?limit=0&depth=0&where[role][equals]=${id}`,\n {\n credentials: \"include\",\n },\n )\n : Promise.resolve(new Response(JSON.stringify({ docs: [] }))),\n ]);\n\n const featuresJson =\n (await featuresRes.json()) as ApiListResponse<PermissionFeature>;\n const actionsJson =\n (await actionsRes.json()) as ApiListResponse<PermissionAction>;\n const permissionsJson =\n (await permissionsRes.json()) as ApiListResponse<Permission>;\n const rolePermissionsJson =\n (await rolePermissionsRes.json()) as ApiListResponse<RolePermission>;\n\n setFeatures(\n featuresJson.docs?.sort(\n (a, b) => (a?.sortOrder ?? 0) - (b?.sortOrder ?? 0),\n ) || [],\n );\n setActions(\n actionsJson.docs?.sort(\n (a, b) => (a?.sortOrder ?? 0) - (b?.sortOrder ?? 0),\n ) || [],\n );\n setPermissions(permissionsJson.docs || []);\n setRolePermissions(rolePermissionsJson.docs || []);\n } finally {\n setLoading(false);\n }\n };\n\n void run();\n }, [config?.routes?.api, id]);\n\n const enabledByPermissionID = useMemo(() => {\n const map = new Map<string, boolean>();\n for (const row of rolePermissions) {\n map.set(toID(row.permission), Boolean(row.enabled));\n }\n return map;\n }, [rolePermissions]);\n\n const draftValue = (\n value && typeof value === \"object\" && !Array.isArray(value) ? value : {}\n ) as Record<string, boolean>;\n\n useEffect(() => {\n if (!id || loading) {\n return;\n }\n\n const roleId = String(id);\n if (seededForRoleIdRef.current === roleId) {\n return;\n }\n\n const fromRolesPermissions: Record<string, boolean> = {};\n for (const [permissionID, enabled] of enabledByPermissionID.entries()) {\n if (permissionID) {\n fromRolesPermissions[permissionID] = enabled;\n }\n }\n\n const fromDocument =\n value && typeof value === \"object\" && !Array.isArray(value)\n ? (value as Record<string, boolean>)\n : {};\n\n const hasRolesPermissions = Object.keys(fromRolesPermissions).length > 0;\n const hasDocumentDraft = Object.keys(fromDocument).length > 0;\n\n if (!hasRolesPermissions && !hasDocumentDraft) {\n return;\n }\n\n seededForRoleIdRef.current = roleId;\n setValue({\n ...fromRolesPermissions,\n ...fromDocument,\n });\n }, [enabledByPermissionID, id, loading, setValue, value]);\n\n if (!id) {\n return (\n <div style={{ opacity: 0.8, padding: \"8px 0\" }}>\n {t(\n `components:rolePermissionMatrix:viewInUpdateScreenOnly:label` as Parameters<\n typeof t\n >[0],\n )}\n </div>\n );\n }\n\n if (loading) {\n return (\n <div style={{ opacity: 0.8, padding: \"8px 0\" }}>\n {t(\n `components:rolePermissionMatrix:loading:placeholder` as Parameters<\n typeof t\n >[0],\n )}\n </div>\n );\n }\n\n return (\n <div>\n <div style={{ fontWeight: 600, marginBottom: 8 }}>\n {t(`components:rolePermissionMatrix:title` as Parameters<typeof t>[0])}\n </div>\n\n <div style={{ border: \"1px solid #333\", borderRadius: 8 }}>\n <table\n style={{\n borderCollapse: \"collapse\",\n width: \"100%\",\n }}\n >\n <thead>\n <tr>\n <th\n style={{\n padding: \"8px\",\n textAlign: \"left\",\n borderRight: \"1px solid #333\",\n width: \"25%\",\n }}\n >\n {t(\n `components:rolePermissionMatrix:features:label` as Parameters<\n typeof t\n >[0],\n )}\n </th>\n <th\n style={{ padding: \"8px\", textAlign: \"left\" }}\n colSpan={\n actions.filter((action) => action.type === TYPE.MAIN).length\n }\n >\n {t(\n `components:rolePermissionMatrix:actions:label` as Parameters<\n typeof t\n >[0],\n )}\n </th>\n </tr>\n </thead>\n <tbody>\n {features.map((feature) => {\n const mainActions = actions.filter(\n (action) => action.type === TYPE.MAIN,\n );\n const subActions = actions.filter(\n (action) =>\n action.type === TYPE.SUB &&\n permissions.some(\n (permission) =>\n toID(permission.permissionAction) === String(action.id) &&\n toID(permission.permissionFeature) === String(feature.id),\n ),\n );\n const isSubActionInPermission = subActions.length > 0;\n\n return (\n <Fragment key={String(feature.id)}>\n <tr>\n <td\n style={{\n borderTop: \"1px solid #333\",\n padding: \"0.5rem\",\n borderRight: \"1px solid #333\",\n }}\n >\n {feature.code || feature.id}\n </td>\n\n {mainActions.map((action) => {\n const matchedPermission = permissions.find(\n (permission) =>\n toID(permission.permissionFeature) ===\n String(feature.id) &&\n toID(permission.permissionAction) ===\n String(action.id),\n );\n\n if (!matchedPermission) {\n return (\n <td\n key={`${feature.id}-${action.id}`}\n style={{\n borderTop: \"1px solid #333\",\n padding: \"0.5rem\",\n }}\n >\n -\n </td>\n );\n }\n\n const permissionID = String(matchedPermission.id);\n const checked =\n typeof draftValue[permissionID] === \"boolean\"\n ? draftValue[permissionID]\n : (enabledByPermissionID.get(permissionID) ?? false);\n\n return (\n <td\n key={`${feature.id}-${action.id}`}\n style={{\n borderTop: \"1px solid #333\",\n padding: \"0.5rem\",\n }}\n >\n <div\n style={{\n display: \"flex\",\n alignItems: \"center\",\n }}\n >\n <input\n type=\"checkbox\"\n id={`permission-matrix-checkbox-${checkboxId}-${feature.id}-${action.id}`}\n name={`permission-matrix-checkbox-${checkboxId}-${feature.id}-${action.id}`}\n checked={checked}\n disabled={isReadOnly}\n onChange={(event) => {\n setValue({\n ...draftValue,\n [permissionID]: event.target.checked,\n });\n }}\n style={{\n userSelect: \"none\",\n cursor: \"pointer\",\n }}\n />\n <label\n htmlFor={`permission-matrix-checkbox-${checkboxId}-${feature.id}-${action.id}`}\n style={{\n display: \"inline-block\",\n paddingLeft: \"0.25rem\",\n userSelect: \"none\",\n cursor: \"pointer\",\n }}\n >\n {t(\n `components:rolePermissionMatrix:actions:${action.code}` as Parameters<\n typeof t\n >[0],\n ) || action.id}\n </label>\n </div>\n </td>\n );\n })}\n </tr>\n\n {isSubActionInPermission && (\n <tr>\n <td\n style={{\n borderRight: \"1px solid #333\",\n padding: \"8px\",\n textAlign: \"right\",\n }}\n ></td>\n <td\n style={{\n borderTop: \"1px solid #333\",\n padding: \"8px\",\n textAlign: \"left\",\n }}\n colSpan={mainActions.length}\n >\n {subActions.map((action) => {\n const matchedPermission = permissions.find(\n (permission) =>\n toID(permission.permissionFeature) ===\n String(feature.id) &&\n toID(permission.permissionAction) ===\n String(action.id),\n );\n\n if (!matchedPermission) {\n return null;\n }\n\n const permissionID = String(matchedPermission.id);\n const checked =\n typeof draftValue[permissionID] === \"boolean\"\n ? draftValue[permissionID]\n : (enabledByPermissionID.get(permissionID) ??\n false);\n\n return (\n <div key={`${feature.id}-${action.id}-sub`}>\n <input\n type=\"checkbox\"\n checked={checked}\n disabled={isReadOnly}\n onChange={(event) => {\n setValue({\n ...draftValue,\n [permissionID]: event.target.checked,\n });\n }}\n />{\" \"}\n <span\n style={{\n display: \"inline-block\",\n }}\n >\n {action.code || action.id}\n </span>\n </div>\n );\n })}\n </td>\n </tr>\n )}\n </Fragment>\n );\n })}\n </tbody>\n </table>\n </div>\n </div>\n );\n};\n"],"names":["useConfig","useDocumentInfo","useField","useTranslation","Fragment","useEffect","useId","useMemo","useRef","useState","STATUS","PERMISSION_STATUS","PERMISSION_ACTION_STATUS","TYPE","PERMISSION_FEATURE_STATUS","toID","RolePermissionMatrixClient","checkboxId","config","hasSavePermission","id","setValue","value","path","isReadOnly","features","setFeatures","actions","setActions","permissions","setPermissions","rolePermissions","setRolePermissions","loading","setLoading","t","seededForRoleIdRef","run","base","routes","api","featuresRes","actionsRes","permissionsRes","rolePermissionsRes","Promise","all","fetch","ACTIVE","credentials","resolve","Response","JSON","stringify","docs","featuresJson","json","actionsJson","permissionsJson","rolePermissionsJson","sort","a","b","sortOrder","enabledByPermissionID","map","Map","row","set","permission","Boolean","enabled","draftValue","Array","isArray","roleId","String","current","fromRolesPermissions","permissionID","entries","fromDocument","hasRolesPermissions","Object","keys","length","hasDocumentDraft","div","style","opacity","padding","fontWeight","marginBottom","border","borderRadius","table","borderCollapse","width","thead","tr","th","textAlign","borderRight","colSpan","filter","action","type","MAIN","tbody","feature","mainActions","subActions","SUB","some","permissionAction","permissionFeature","isSubActionInPermission","td","borderTop","code","matchedPermission","find","checked","get","display","alignItems","input","name","disabled","onChange","event","target","userSelect","cursor","label","htmlFor","paddingLeft","span"],"mappings":"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"}
|
|
1
|
+
{"version":3,"sources":["../../../src/components/role-permission-matrix-client/index.tsx"],"sourcesContent":["\"use client\";\n\nimport {\n useConfig,\n useDocumentInfo,\n useField,\n useTranslation,\n} from \"@payloadcms/ui\";\nimport { Fragment, useEffect, useId, useMemo, useRef, useState } from \"react\";\nimport type { PermissionAction } from \"../../collections/permission-actions/types.js\";\nimport type { PermissionFeature } from \"../../collections/permission-features/types.js\";\nimport type { Permission } from \"../../collections/permissions/types.js\";\nimport type { RolePermission } from \"../../collections/roles-permissions/types.js\";\nimport { STATUS as PERMISSION_STATUS } from \"../../lib/constants/permission.js\";\nimport {\n STATUS as PERMISSION_ACTION_STATUS,\n TYPE,\n} from \"../../lib/constants/permission-action.js\";\nimport { STATUS as PERMISSION_FEATURE_STATUS } from \"../../lib/constants/permission-feature.js\";\nimport { toID } from \"../../lib/utils/data.js\";\n\nimport styles from \"./matrix.module.scss\";\n\nconst RBAC_PREFIX = \"rbac\";\n\ntype ApiListResponse<T> = {\n docs?: T[];\n};\n\nexport const RolePermissionMatrixClient = () => {\n const checkboxId = useId();\n const { config } = useConfig();\n const { hasSavePermission, id } = useDocumentInfo();\n const { setValue, value } = useField<Record<string, boolean> | null>({\n path: \"permissionMatrixDraft\",\n });\n const isReadOnly = !hasSavePermission;\n\n const [features, setFeatures] = useState<PermissionFeature[]>([]);\n const [actions, setActions] = useState<PermissionAction[]>([]);\n const [permissions, setPermissions] = useState<Permission[]>([]);\n const [rolePermissions, setRolePermissions] = useState<RolePermission[]>([]);\n const [loading, setLoading] = useState(true);\n const { t } = useTranslation();\n const seededForRoleIdRef = useRef<string | null>(null);\n\n useEffect(() => {\n const run = async () => {\n setLoading(true);\n try {\n const base = config?.routes?.api || \"/api\";\n\n const [featuresRes, actionsRes, permissionsRes, rolePermissionsRes] =\n await Promise.all([\n fetch(\n `${base}/permission-features?limit=0&depth=0&where[status][equals]=${PERMISSION_FEATURE_STATUS.ACTIVE}`,\n { credentials: \"include\" },\n ),\n fetch(\n `${base}/permission-actions?limit=0&depth=0&where[status][equals]=${PERMISSION_ACTION_STATUS.ACTIVE}`,\n { credentials: \"include\" },\n ),\n fetch(\n `${base}/permissions?limit=0&depth=1&where[status][equals]=${PERMISSION_STATUS.ACTIVE}`,\n { credentials: \"include\" },\n ),\n id\n ? fetch(\n `${base}/roles-permissions?limit=0&depth=0&where[role][equals]=${id}`,\n {\n credentials: \"include\",\n },\n )\n : Promise.resolve(new Response(JSON.stringify({ docs: [] }))),\n ]);\n\n const featuresJson =\n (await featuresRes.json()) as ApiListResponse<PermissionFeature>;\n const actionsJson =\n (await actionsRes.json()) as ApiListResponse<PermissionAction>;\n const permissionsJson =\n (await permissionsRes.json()) as ApiListResponse<Permission>;\n const rolePermissionsJson =\n (await rolePermissionsRes.json()) as ApiListResponse<RolePermission>;\n\n setFeatures(\n featuresJson.docs?.sort(\n (a, b) => (a?.sortOrder ?? 0) - (b?.sortOrder ?? 0),\n ) || [],\n );\n setActions(\n actionsJson.docs?.sort(\n (a, b) => (a?.sortOrder ?? 0) - (b?.sortOrder ?? 0),\n ) || [],\n );\n setPermissions(permissionsJson.docs || []);\n setRolePermissions(rolePermissionsJson.docs || []);\n } finally {\n setLoading(false);\n }\n };\n\n void run();\n }, [config?.routes?.api, id]);\n\n const enabledByPermissionID = useMemo(() => {\n const map = new Map<string, boolean>();\n for (const row of rolePermissions) {\n map.set(toID(row.permission), Boolean(row.enabled));\n }\n return map;\n }, [rolePermissions]);\n\n const draftValue = (\n value && typeof value === \"object\" && !Array.isArray(value) ? value : {}\n ) as Record<string, boolean>;\n\n useEffect(() => {\n if (!id || loading) {\n return;\n }\n\n const roleId = String(id);\n if (seededForRoleIdRef.current === roleId) {\n return;\n }\n\n const fromRolesPermissions: Record<string, boolean> = {};\n for (const [permissionID, enabled] of enabledByPermissionID.entries()) {\n if (permissionID) {\n fromRolesPermissions[permissionID] = enabled;\n }\n }\n\n const fromDocument =\n value && typeof value === \"object\" && !Array.isArray(value)\n ? (value as Record<string, boolean>)\n : {};\n\n const hasRolesPermissions = Object.keys(fromRolesPermissions).length > 0;\n const hasDocumentDraft = Object.keys(fromDocument).length > 0;\n\n if (!hasRolesPermissions && !hasDocumentDraft) {\n return;\n }\n\n seededForRoleIdRef.current = roleId;\n setValue({\n ...fromRolesPermissions,\n ...fromDocument,\n });\n }, [enabledByPermissionID, id, loading, setValue, value]);\n\n if (!id) {\n return (\n <div className={styles[`${RBAC_PREFIX}-component-placeholder`]}>\n {t(\n `components:rolePermissionMatrix:viewInUpdateScreenOnly:label` as Parameters<\n typeof t\n >[0],\n )}\n </div>\n );\n }\n\n if (loading) {\n return (\n <div className={styles[`${RBAC_PREFIX}-component-placeholder`]}>\n {t(\n `components:rolePermissionMatrix:loading:placeholder` as Parameters<\n typeof t\n >[0],\n )}\n </div>\n );\n }\n\n return (\n <div>\n <div className={styles[`${RBAC_PREFIX}-component-title`]}>\n {t(`components:rolePermissionMatrix:title` as Parameters<typeof t>[0])}\n </div>\n\n <div className={styles[`${RBAC_PREFIX}-table-container`]}>\n <table className={styles[`${RBAC_PREFIX}-table`]}>\n <thead>\n <tr>\n <th className={styles[`${RBAC_PREFIX}-table-th-feature`]}>\n {t(\n `components:rolePermissionMatrix:featuresLabel` as Parameters<\n typeof t\n >[0],\n )}\n </th>\n <th\n className={styles[`${RBAC_PREFIX}-table-th-action`]}\n colSpan={\n actions.filter((action) => action.type === TYPE.MAIN).length\n }\n >\n {t(\n `components:rolePermissionMatrix:actionsLabel` as Parameters<\n typeof t\n >[0],\n )}\n </th>\n </tr>\n </thead>\n <tbody>\n {features.map((feature) => {\n const mainActions = actions.filter(\n (action) => action.type === TYPE.MAIN,\n );\n const subActions = actions.filter(\n (action) =>\n action.type === TYPE.SUB &&\n permissions.some(\n (permission) =>\n toID(permission.permissionAction) === String(action.id) &&\n toID(permission.permissionFeature) === String(feature.id),\n ),\n );\n const isSubActionInPermission = subActions.length > 0;\n\n return (\n <Fragment key={String(feature.id)}>\n <tr>\n <td className={styles[`${RBAC_PREFIX}-table-td-feature`]}>\n {t(\n `components:rolePermissionMatrix:features:${feature.code}` as Parameters<\n typeof t\n >[0],\n ) || feature.id}\n </td>\n\n {mainActions.map((action) => {\n const matchedPermission = permissions.find(\n (permission) =>\n toID(permission.permissionFeature) ===\n String(feature.id) &&\n toID(permission.permissionAction) ===\n String(action.id),\n );\n\n if (!matchedPermission) {\n return (\n <td\n key={`${feature.id}-${action.id}`}\n className={styles[`${RBAC_PREFIX}-table-td-action`]}\n >\n -\n </td>\n );\n }\n\n const permissionID = String(matchedPermission.id);\n const checked =\n typeof draftValue[permissionID] === \"boolean\"\n ? draftValue[permissionID]\n : (enabledByPermissionID.get(permissionID) ?? false);\n\n return (\n <td\n key={`${feature.id}-${action.id}`}\n className={styles[`${RBAC_PREFIX}-table-td-action`]}\n >\n <div\n className={\n styles[`${RBAC_PREFIX}-table-td-action-container`]\n }\n >\n <input\n type=\"checkbox\"\n id={`permission-matrix-checkbox-${checkboxId}-${feature.id}-${action.id}`}\n name={`permission-matrix-checkbox-${checkboxId}-${feature.id}-${action.id}`}\n checked={checked}\n disabled={isReadOnly}\n onChange={(event) => {\n setValue({\n ...draftValue,\n [permissionID]: event.target.checked,\n });\n }}\n className={\n styles[`${RBAC_PREFIX}-table-td-action-input`]\n }\n />\n <label\n htmlFor={`permission-matrix-checkbox-${checkboxId}-${feature.id}-${action.id}`}\n className={\n styles[`${RBAC_PREFIX}-table-td-action-label`]\n }\n >\n {t(\n `components:rolePermissionMatrix:actions:${action.code}` as Parameters<\n typeof t\n >[0],\n ) || action.id}\n </label>\n </div>\n </td>\n );\n })}\n </tr>\n\n {isSubActionInPermission && (\n <tr>\n <td\n className={styles[`${RBAC_PREFIX}-table-td-feature`]}\n ></td>\n <td\n className={styles[`${RBAC_PREFIX}-table-td-action`]}\n colSpan={mainActions.length}\n >\n {subActions.map((action) => {\n const matchedPermission = permissions.find(\n (permission) =>\n toID(permission.permissionFeature) ===\n String(feature.id) &&\n toID(permission.permissionAction) ===\n String(action.id),\n );\n\n if (!matchedPermission) {\n return null;\n }\n\n const permissionID = String(matchedPermission.id);\n const checked =\n typeof draftValue[permissionID] === \"boolean\"\n ? draftValue[permissionID]\n : (enabledByPermissionID.get(permissionID) ??\n false);\n\n return (\n <div key={`${feature.id}-${action.id}-sub`}>\n <input\n type=\"checkbox\"\n checked={checked}\n disabled={isReadOnly}\n onChange={(event) => {\n setValue({\n ...draftValue,\n [permissionID]: event.target.checked,\n });\n }}\n />{\" \"}\n <span\n style={{\n display: \"inline-block\",\n }}\n >\n {action.code || action.id}\n </span>\n </div>\n );\n })}\n </td>\n </tr>\n )}\n </Fragment>\n );\n })}\n </tbody>\n </table>\n </div>\n </div>\n );\n};\n"],"names":["useConfig","useDocumentInfo","useField","useTranslation","Fragment","useEffect","useId","useMemo","useRef","useState","STATUS","PERMISSION_STATUS","PERMISSION_ACTION_STATUS","TYPE","PERMISSION_FEATURE_STATUS","toID","styles","RBAC_PREFIX","RolePermissionMatrixClient","checkboxId","config","hasSavePermission","id","setValue","value","path","isReadOnly","features","setFeatures","actions","setActions","permissions","setPermissions","rolePermissions","setRolePermissions","loading","setLoading","t","seededForRoleIdRef","run","base","routes","api","featuresRes","actionsRes","permissionsRes","rolePermissionsRes","Promise","all","fetch","ACTIVE","credentials","resolve","Response","JSON","stringify","docs","featuresJson","json","actionsJson","permissionsJson","rolePermissionsJson","sort","a","b","sortOrder","enabledByPermissionID","map","Map","row","set","permission","Boolean","enabled","draftValue","Array","isArray","roleId","String","current","fromRolesPermissions","permissionID","entries","fromDocument","hasRolesPermissions","Object","keys","length","hasDocumentDraft","div","className","table","thead","tr","th","colSpan","filter","action","type","MAIN","tbody","feature","mainActions","subActions","SUB","some","permissionAction","permissionFeature","isSubActionInPermission","td","code","matchedPermission","find","checked","get","input","name","disabled","onChange","event","target","label","htmlFor","span","style","display"],"mappings":"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"}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
// Import Payload compile-time SCSS vars ($breakpoint-s-width, etc.).
|
|
2
|
+
// Note: @payloadcms/ui/scss/vars is not a published export — use dist/scss/vars.
|
|
3
|
+
// @use "../../../node_modules/@payloadcms/ui/dist/scss/vars" as payload-vars;
|
|
4
|
+
@use "../../styles/variables" as rbac-vars;
|
|
5
|
+
|
|
6
|
+
$local-prefix: rbac-vars.$rbac-prefix;
|
|
7
|
+
|
|
8
|
+
.#{$local-prefix}-component {
|
|
9
|
+
&-label {
|
|
10
|
+
opacity: 0.8;
|
|
11
|
+
padding: 0.5rem 0;
|
|
12
|
+
}
|
|
13
|
+
&-placeholder {
|
|
14
|
+
opacity: 0.8;
|
|
15
|
+
padding: 0.5rem 0;
|
|
16
|
+
}
|
|
17
|
+
&-title {
|
|
18
|
+
font-weight: 600;
|
|
19
|
+
margin-bottom: 0.5rem;
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
.#{$local-prefix}-table {
|
|
24
|
+
border-collapse: collapse;
|
|
25
|
+
width: 100%;
|
|
26
|
+
&-container {
|
|
27
|
+
border-radius: var(--style-radius-m);
|
|
28
|
+
border: 1px solid var(--theme-border-color);
|
|
29
|
+
}
|
|
30
|
+
&-th {
|
|
31
|
+
&-feature {
|
|
32
|
+
padding: 0.5rem;
|
|
33
|
+
text-align: left;
|
|
34
|
+
border-right: 1px solid var(--theme-border-color);
|
|
35
|
+
width: 25%;
|
|
36
|
+
}
|
|
37
|
+
&-action {
|
|
38
|
+
padding: 0.5rem;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
&-td {
|
|
42
|
+
&-feature {
|
|
43
|
+
border-right: 1px solid var(--theme-border-color);
|
|
44
|
+
border-top: 1px solid var(--theme-border-color);
|
|
45
|
+
padding: 0.5rem;
|
|
46
|
+
}
|
|
47
|
+
&-action {
|
|
48
|
+
border-top: 1px solid var(--theme-border-color);
|
|
49
|
+
padding: 0.5rem;
|
|
50
|
+
&-container {
|
|
51
|
+
display: flex;
|
|
52
|
+
align-items: center;
|
|
53
|
+
}
|
|
54
|
+
&-input {
|
|
55
|
+
user-select: none;
|
|
56
|
+
cursor: pointer;
|
|
57
|
+
}
|
|
58
|
+
&-label {
|
|
59
|
+
display: inline-block;
|
|
60
|
+
padding-left: 0.25rem;
|
|
61
|
+
user-select: none;
|
|
62
|
+
cursor: pointer;
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
}
|
|
@@ -8,11 +8,9 @@ export type RolePermissionMatrixClientTranslations = {
|
|
|
8
8
|
placeholder?: string;
|
|
9
9
|
};
|
|
10
10
|
title?: string;
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
actions?:
|
|
15
|
-
label?: string;
|
|
16
|
-
} | Record<string, string>;
|
|
11
|
+
featuresLabel?: string;
|
|
12
|
+
features?: Record<string, string>;
|
|
13
|
+
actionsLabel?: string;
|
|
14
|
+
actions?: Record<string, string>;
|
|
17
15
|
};
|
|
18
16
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/components/role-permission-matrix-client/types.ts"],"sourcesContent":["export type RolePermissionMatrixClientTranslations = {\n [locale: string]: {\n viewInUpdateScreenOnly?: {\n label?: string
|
|
1
|
+
{"version":3,"sources":["../../../src/components/role-permission-matrix-client/types.ts"],"sourcesContent":["export type RolePermissionMatrixClientTranslations = {\n [locale: string]: {\n viewInUpdateScreenOnly?: {\n label?: string;\n placeholder?: string;\n };\n loading?: {\n placeholder?: string;\n };\n title?: string;\n featuresLabel?: string;\n features?: Record<string, string>;\n actionsLabel?: string;\n actions?: Record<string, string>;\n };\n};\n"],"names":[],"mappings":"AAAA,WAeE"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
$rbac-prefix: "rbac";
|