@abinnovision/payloadcms-mcpx 2.0.0-beta.18 → 2.0.0-beta.20

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.
Files changed (65) hide show
  1. package/README.md +2 -2
  2. package/dist/admin/capability-matrix.d.mts +2 -1
  3. package/dist/admin/capability-matrix.mjs +291 -340
  4. package/dist/admin/capability-toggles.mjs +24 -31
  5. package/dist/admin/confirmations-panel.mjs +61 -71
  6. package/dist/admin/confirmations.mjs +2 -1
  7. package/dist/admin/endpoint-url.mjs +7 -0
  8. package/dist/admin/setup-guide.mjs +2 -1
  9. package/dist/api-keys/capability-matrix.d.mts +4 -7
  10. package/dist/api-keys/capability-matrix.mjs +12 -51
  11. package/dist/api-keys/collection.mjs +10 -17
  12. package/dist/api-keys/confirmation-view.mjs +2 -1
  13. package/dist/api-keys/fields.mjs +53 -69
  14. package/dist/auth/resolve.mjs +29 -10
  15. package/dist/capabilities.d.mts +2 -0
  16. package/dist/capabilities.mjs +62 -19
  17. package/dist/endpoint/confirmations.mjs +14 -14
  18. package/dist/endpoint/handler.mjs +6 -22
  19. package/dist/endpoint/http.mjs +27 -0
  20. package/dist/endpoint/upload.mjs +11 -43
  21. package/dist/grants/confirmation.mjs +11 -42
  22. package/dist/grants/grant.mjs +58 -40
  23. package/dist/guards.mjs +8 -1
  24. package/dist/index.d.mts +2 -2
  25. package/dist/index.mjs +1 -1
  26. package/dist/options.mjs +34 -54
  27. package/dist/plugin.mjs +2 -1
  28. package/dist/request.mjs +5 -1
  29. package/dist/result.mjs +11 -1
  30. package/dist/schema/admin-hidden.mjs +4 -4
  31. package/dist/schema/describe.mjs +12 -18
  32. package/dist/schema/index.mjs +5 -6
  33. package/dist/schema/lexical-pointer.mjs +8 -8
  34. package/dist/schema/lexical.mjs +15 -13
  35. package/dist/schema/outline.mjs +4 -5
  36. package/dist/schema/path.mjs +4 -1
  37. package/dist/schema/pointer.mjs +11 -17
  38. package/dist/schema/shape.mjs +38 -50
  39. package/dist/schema/walk.mjs +57 -18
  40. package/dist/tools/create-document.mjs +16 -44
  41. package/dist/tools/delete-document.mjs +14 -17
  42. package/dist/tools/describe-schema.mjs +7 -5
  43. package/dist/tools/document.mjs +130 -44
  44. package/dist/tools/duplicate-document.mjs +11 -10
  45. package/dist/tools/find-documents.mjs +15 -20
  46. package/dist/tools/find-versions.mjs +10 -14
  47. package/dist/tools/get-document.mjs +8 -12
  48. package/dist/tools/links.mjs +2 -1
  49. package/dist/tools/list-capabilities.mjs +2 -1
  50. package/dist/tools/patch-document.mjs +12 -44
  51. package/dist/tools/publish-document.mjs +9 -27
  52. package/dist/tools/query-paths.mjs +1 -1
  53. package/dist/tools/run-confirmed.mjs +38 -50
  54. package/dist/tools/shared.mjs +43 -41
  55. package/dist/tools/validate-document.mjs +4 -6
  56. package/dist/tools/versions.mjs +11 -6
  57. package/dist/types.d.mts +12 -26
  58. package/dist/upload/file.mjs +10 -18
  59. package/dist/write/draft-guard.mjs +20 -20
  60. package/dist/write/patch.mjs +4 -4
  61. package/dist/write/publish-intent.mjs +22 -28
  62. package/dist/write/row-ids.mjs +3 -1
  63. package/dist/write/write-data.mjs +18 -31
  64. package/package.json +5 -5
  65. package/dist/builtin-tool-names.mjs +0 -19
@@ -1,16 +1,69 @@
1
1
  "use client";
2
- import { CAPABILITIES_FIELD } from "../capabilities.mjs";
3
- import { CAPABILITY_OPERATIONS, STORED_OPERATIONS, capabilityPaths, toolPath } from "../api-keys/capability-matrix.mjs";
2
+ import { ACCESS_CHAIN, CAPABILITIES_FIELD } from "../capabilities.mjs";
3
+ import { capabilityPaths, toolPath } from "../api-keys/capability-matrix.mjs";
4
+ import { translateStatic } from "../i18n.mjs";
4
5
  import { accessLevelOf, accessLevelsOf, allAccessLevel, allDeleteMode, buildToggleActions, deleteModeOf, toolsState } from "./capability-toggles.mjs";
5
- import { jsx, jsxs } from "react/jsx-runtime";
6
- import { Button, CheckboxInput, FieldDescription, FieldLabel, Pill, useForm, useFormFields } from "@payloadcms/ui";
6
+ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
7
+ import { Button, CheckboxInput, FieldDescription, FieldLabel, Pill, useConfig, useForm, useFormFields, useTranslation } from "@payloadcms/ui";
7
8
  import { useCallback, useMemo } from "react";
8
9
  //#region src/admin/capability-matrix.tsx
9
10
  const BASE_CLASS = "mcpx-capabilities";
10
11
  const LIVE_WRITE = "Writes go live immediately.";
12
+ const cx = (...names) => names.filter(Boolean).join(" ");
11
13
  const SHEET = `
12
14
  .${BASE_CLASS} tbody tr:hover { background: var(--theme-elevation-50); }
13
- .${BASE_CLASS} section:last-of-type { margin-bottom: 0; }
15
+ .${BASE_CLASS}__sections {
16
+ display: flex;
17
+ flex-wrap: wrap;
18
+ gap: var(--base) calc(var(--base) * 2);
19
+ align-items: flex-start;
20
+ }
21
+ .${BASE_CLASS}__table {
22
+ table-layout: fixed;
23
+ width: auto;
24
+ border-collapse: separate;
25
+ border-spacing: 0;
26
+ text-align: left;
27
+ }
28
+ .${BASE_CLASS}__table thead { background: var(--theme-elevation-50); }
29
+ .${BASE_CLASS}__table th,
30
+ .${BASE_CLASS}__table td {
31
+ padding: calc(var(--base) * 0.6);
32
+ vertical-align: middle;
33
+ font-weight: normal;
34
+ text-align: center;
35
+ }
36
+ .${BASE_CLASS}__table thead th { color: var(--theme-elevation-400); }
37
+ .${BASE_CLASS}__table .${BASE_CLASS}__head { white-space: nowrap; }
38
+ .${BASE_CLASS}__table .${BASE_CLASS}__start { text-align: start; }
39
+ .${BASE_CLASS}__table .${BASE_CLASS}__row,
40
+ .${BASE_CLASS}__table .${BASE_CLASS}__title {
41
+ padding-inline-start: calc(var(--base) * 0.8);
42
+ text-align: inherit;
43
+ }
44
+ .${BASE_CLASS}__table .${BASE_CLASS}__row { word-break: break-word; }
45
+ .${BASE_CLASS}__table thead .${BASE_CLASS}__row { color: var(--theme-elevation-500); }
46
+ .${BASE_CLASS}__table .${BASE_CLASS}__title {
47
+ font-size: 0.8em;
48
+ letter-spacing: 0.08em;
49
+ text-transform: uppercase;
50
+ }
51
+ .${BASE_CLASS}__table td:last-child { padding-inline-end: calc(var(--base) * 0.8); }
52
+ .${BASE_CLASS}__table thead tr:first-child th:first-child { border-start-start-radius: var(--style-radius-s); }
53
+ .${BASE_CLASS}__table thead tr:first-child th:last-child { border-start-end-radius: var(--style-radius-s); }
54
+ .${BASE_CLASS}__table thead tr:last-child > * { border-bottom: 1px solid var(--theme-border-color); }
55
+ .${BASE_CLASS}__hint { display: block; color: var(--theme-elevation-400); }
56
+ .${BASE_CLASS}__badge {
57
+ display: inline-flex;
58
+ margin-inline-start: calc(var(--base) * 0.4);
59
+ vertical-align: middle;
60
+ cursor: help;
61
+ }
62
+ .${BASE_CLASS}__delete {
63
+ display: inline-flex;
64
+ align-items: center;
65
+ gap: calc(var(--base) * 0.4);
66
+ }
14
67
  .${BASE_CLASS}__segments {
15
68
  display: inline-flex;
16
69
  border: 1px solid var(--theme-elevation-150);
@@ -22,82 +75,22 @@ const SHEET = `
22
75
  .${BASE_CLASS}__segments .btn:first-child { border-start-start-radius: inherit; border-end-start-radius: inherit; }
23
76
  .${BASE_CLASS}__segments .btn:last-child { border-start-end-radius: inherit; border-end-end-radius: inherit; }
24
77
  .${BASE_CLASS}__segments .btn--style-transparent { --hover-bg: var(--theme-elevation-100); }
25
- .${BASE_CLASS}__segments .${BASE_CLASS}__danger { --bg-color: var(--theme-error-500); --hover-bg: var(--theme-error-600); }
78
+ .${BASE_CLASS}__shield {
79
+ display: inline-flex;
80
+ align-items: center;
81
+ justify-content: center;
82
+ padding: calc(var(--base) * 0.2);
83
+ border: 0;
84
+ border-radius: var(--style-radius-s);
85
+ background: transparent;
86
+ color: var(--theme-elevation-800);
87
+ line-height: 0;
88
+ cursor: pointer;
89
+ }
90
+ .${BASE_CLASS}__shield:hover:not(:disabled) { background: var(--theme-elevation-100); }
91
+ .${BASE_CLASS}__shield:disabled { cursor: not-allowed; opacity: 0.6; }
92
+ .${BASE_CLASS}__shield.${BASE_CLASS}__danger { color: var(--theme-error-500); }
26
93
  `;
27
- const CELL_PADDING = "calc(var(--base) * 0.6)";
28
- const EDGE_PADDING = "calc(var(--base) * 0.8)";
29
- const styles = {
30
- section: { marginBottom: "var(--base)" },
31
- table: {
32
- tableLayout: "fixed",
33
- width: "auto",
34
- borderCollapse: "separate",
35
- borderSpacing: 0,
36
- textAlign: "left"
37
- },
38
- head: { background: "var(--theme-elevation-50)" },
39
- headTitle: {
40
- padding: `${CELL_PADDING} ${CELL_PADDING} ${CELL_PADDING} ${EDGE_PADDING}`,
41
- verticalAlign: "middle",
42
- fontSize: "0.8em",
43
- letterSpacing: "0.08em",
44
- textTransform: "uppercase",
45
- color: "var(--theme-elevation-400)",
46
- fontWeight: "normal"
47
- },
48
- headOperation: {
49
- padding: CELL_PADDING,
50
- verticalAlign: "middle",
51
- color: "var(--theme-elevation-400)",
52
- fontWeight: "normal",
53
- textAlign: "center",
54
- whiteSpace: "nowrap"
55
- },
56
- headLabel: {
57
- padding: `${CELL_PADDING} ${CELL_PADDING} ${CELL_PADDING} ${EDGE_PADDING}`,
58
- verticalAlign: "middle",
59
- color: "var(--theme-elevation-500)",
60
- fontWeight: "normal"
61
- },
62
- rule: { borderBottom: "1px solid var(--theme-border-color)" },
63
- topStart: { borderStartStartRadius: "var(--style-radius-s)" },
64
- topEnd: { borderStartEndRadius: "var(--style-radius-s)" },
65
- rowHeader: {
66
- padding: `${CELL_PADDING} ${CELL_PADDING} ${CELL_PADDING} ${EDGE_PADDING}`,
67
- verticalAlign: "middle",
68
- fontWeight: "normal",
69
- wordBreak: "break-word"
70
- },
71
- hint: {
72
- display: "block",
73
- color: "var(--theme-elevation-400)"
74
- },
75
- badge: {
76
- display: "inline-flex",
77
- marginInlineStart: "calc(var(--base) * 0.4)",
78
- verticalAlign: "middle",
79
- cursor: "help"
80
- },
81
- visuallyHidden: {
82
- position: "absolute",
83
- width: "1px",
84
- height: "1px",
85
- overflow: "hidden",
86
- clip: "rect(0 0 0 0)",
87
- whiteSpace: "nowrap"
88
- },
89
- cell: {
90
- padding: CELL_PADDING,
91
- verticalAlign: "middle",
92
- textAlign: "center"
93
- },
94
- controlCell: {
95
- padding: CELL_PADDING,
96
- verticalAlign: "middle",
97
- textAlign: "start"
98
- },
99
- lastCell: { paddingInlineEnd: EDGE_PADDING }
100
- };
101
94
  const Box = ({ label, onChange, readOnly, state }) => /*#__PURE__*/ jsx(CheckboxInput, {
102
95
  checked: state === "on",
103
96
  name: label,
@@ -105,33 +98,17 @@ const Box = ({ label, onChange, readOnly, state }) => /*#__PURE__*/ jsx(Checkbox
105
98
  partialChecked: state === "mixed",
106
99
  readOnly
107
100
  });
108
- const descriptionOf = (operation) => STORED_OPERATIONS.find((candidate) => candidate.id === operation)?.description;
101
+ const deleteBoxState = (mode) => mode === void 0 ? "mixed" : mode === "off" ? "off" : "on";
102
+ const nextDeleteMode = (mode) => mode === "off" || mode === void 0 ? "approve" : "off";
109
103
  const ACCESS_OPTIONS = [{
110
104
  id: "none",
111
105
  label: "None",
112
106
  title: "No access"
113
- }, ...CAPABILITY_OPERATIONS.filter((operation) => operation.id !== "delete").map((operation) => ({
107
+ }, ...ACCESS_CHAIN.map((operation) => ({
114
108
  id: operation.id,
115
109
  label: operation.label,
116
110
  title: operation.description
117
111
  }))];
118
- const DELETE_OPTIONS = [
119
- {
120
- id: "off",
121
- label: "Off",
122
- title: "No delete"
123
- },
124
- {
125
- id: "approve",
126
- label: "Approval",
127
- title: descriptionOf("delete")
128
- },
129
- {
130
- id: "trash",
131
- label: "Trash",
132
- title: descriptionOf("deleteUnattended")
133
- }
134
- ];
135
112
  const ARROW_STEPS = {
136
113
  ArrowDown: 1,
137
114
  ArrowLeft: -1,
@@ -162,7 +139,6 @@ const Segments = ({ included = [], label, onSelect, options, readOnly, selected
162
139
  const checked = option.id === selected;
163
140
  return /*#__PURE__*/ jsx(Button, {
164
141
  buttonStyle: checked ? "primary" : included.includes(option.id) ? "pill" : "transparent",
165
- className: checked && option.id === "trash" ? `${BASE_CLASS}__danger` : "",
166
142
  disabled: readOnly,
167
143
  extraButtonProps: {
168
144
  "aria-checked": checked,
@@ -185,21 +161,12 @@ const includedBelow = (options, level) => {
185
161
  return selected < 1 ? [] : options.slice(1, selected).map((option) => option.id);
186
162
  };
187
163
  const accessOptions = (rows) => ACCESS_OPTIONS.filter((option) => rows.some((row) => accessLevelsOf(row).includes(option.id)));
188
- const LABEL_WIDTH = "calc(var(--base) * 9)";
164
+ const LABEL_WIDTH = "calc(var(--base) * 11)";
189
165
  const OPERATION_WIDTH = "calc(var(--base) * 3.5)";
190
166
  const ACCESS_WIDTH = "calc(var(--base) * 13)";
191
- const DELETE_WIDTH = "calc(var(--base) * 10)";
192
- const Columns = ({ widths }) => /*#__PURE__*/ jsxs("colgroup", { children: [/*#__PURE__*/ jsx("col", { style: { width: LABEL_WIDTH } }), widths.map((width, index) => /*#__PURE__*/ jsx("col", { style: { width } }, index))] });
193
- const lastCellStyle = {
194
- ...styles.cell,
195
- ...styles.lastCell
196
- };
197
- const controlStyle = (isLast) => isLast ? {
198
- ...styles.controlCell,
199
- ...styles.lastCell
200
- } : styles.controlCell;
167
+ const DELETE_WIDTH = "calc(var(--base) * 4)";
201
168
  const LiveBadge = () => /*#__PURE__*/ jsx("span", {
202
- style: styles.badge,
169
+ className: `${BASE_CLASS}__badge`,
203
170
  title: LIVE_WRITE,
204
171
  children: /*#__PURE__*/ jsxs(Pill, {
205
172
  pillStyle: "warning",
@@ -208,230 +175,221 @@ const LiveBadge = () => /*#__PURE__*/ jsx("span", {
208
175
  "aria-hidden": "true",
209
176
  children: "Live"
210
177
  }), /*#__PURE__*/ jsx("span", {
211
- style: styles.visuallyHidden,
178
+ className: "sr-only",
212
179
  children: LIVE_WRITE
213
180
  })]
214
181
  })
215
182
  });
183
+ const APPROVED_ALWAYS = "Always approved: the plugin config does not allow unattended deletes";
184
+ const ApprovalToggle = ({ label, locked = false, onToggle, pressed, readOnly }) => {
185
+ const title = locked ? APPROVED_ALWAYS : pressed ? "A person approves each delete" : "Each delete runs without approval";
186
+ return /*#__PURE__*/ jsxs("button", {
187
+ "aria-pressed": pressed,
188
+ className: cx(`${BASE_CLASS}__shield`, !pressed && `${BASE_CLASS}__danger`),
189
+ disabled: readOnly || locked,
190
+ onClick: onToggle,
191
+ title,
192
+ type: "button",
193
+ children: [/*#__PURE__*/ jsxs("svg", {
194
+ "aria-hidden": "true",
195
+ fill: "none",
196
+ height: "16",
197
+ stroke: "currentColor",
198
+ strokeLinecap: "round",
199
+ strokeLinejoin: "round",
200
+ strokeWidth: "2",
201
+ viewBox: "0 0 24 24",
202
+ width: "16",
203
+ children: [/*#__PURE__*/ jsx("path", { d: "M12 3l8 3v6c0 4.5-3.2 8-8 9-4.8-1-8-4.5-8-9V6z" }), pressed ? /*#__PURE__*/ jsx("path", { d: "M9 12l2 2 4-4" }) : null]
204
+ }), /*#__PURE__*/ jsx("span", {
205
+ className: "sr-only",
206
+ children: `${label}: ${title}`
207
+ })]
208
+ });
209
+ };
210
+ const MatrixTable = ({ all, children, heads, start = false, title, widths }) => /*#__PURE__*/ jsx("section", { children: /*#__PURE__*/ jsxs("table", {
211
+ className: `${BASE_CLASS}__table`,
212
+ children: [
213
+ /*#__PURE__*/ jsxs("colgroup", { children: [/*#__PURE__*/ jsx("col", { style: { width: LABEL_WIDTH } }), widths.map((width, index) => /*#__PURE__*/ jsx("col", { style: { width } }, index))] }),
214
+ /*#__PURE__*/ jsxs("thead", { children: [/*#__PURE__*/ jsxs("tr", { children: [/*#__PURE__*/ jsx("th", {
215
+ className: `${BASE_CLASS}__title`,
216
+ scope: "col",
217
+ children: title
218
+ }), heads.map((head) => /*#__PURE__*/ jsx("th", {
219
+ className: `${BASE_CLASS}__head${start ? ` ${BASE_CLASS}__start` : ""}`,
220
+ scope: "col",
221
+ children: head
222
+ }, head))] }), /*#__PURE__*/ jsxs("tr", { children: [/*#__PURE__*/ jsx("th", {
223
+ className: `${BASE_CLASS}__row`,
224
+ scope: "row",
225
+ children: "All"
226
+ }), all] })] }),
227
+ /*#__PURE__*/ jsx("tbody", { children })
228
+ ]
229
+ }) });
216
230
  const NamespaceTable = ({ matrix, namespace, path, readOnly, toggle, values }) => {
217
231
  const rows = matrix[namespace.id];
218
232
  const withDelete = rows.some((row) => row.delete);
219
233
  const allOptions = accessOptions(rows);
220
234
  const allLevel = allAccessLevel(matrix, path, namespace.id, values);
221
235
  const entries = namespace.title.toLowerCase();
222
- return /*#__PURE__*/ jsx("section", {
223
- style: styles.section,
224
- children: /*#__PURE__*/ jsxs("table", {
225
- style: styles.table,
226
- children: [
227
- /*#__PURE__*/ jsx(Columns, { widths: withDelete ? [ACCESS_WIDTH, DELETE_WIDTH] : [ACCESS_WIDTH] }),
228
- /*#__PURE__*/ jsxs("thead", {
229
- style: styles.head,
230
- children: [/*#__PURE__*/ jsxs("tr", { children: [
231
- /*#__PURE__*/ jsx("th", {
232
- scope: "col",
233
- style: {
234
- ...styles.headTitle,
235
- ...styles.topStart
236
- },
237
- children: namespace.title
238
- }),
239
- /*#__PURE__*/ jsx("th", {
240
- scope: "col",
241
- style: {
242
- ...styles.headOperation,
243
- textAlign: "start",
244
- ...withDelete ? {} : styles.topEnd
245
- },
246
- children: "Access"
247
- }),
248
- withDelete ? /*#__PURE__*/ jsx("th", {
249
- scope: "col",
250
- style: {
251
- ...styles.headOperation,
252
- textAlign: "start",
253
- ...styles.topEnd
254
- },
255
- children: "Delete"
256
- }) : null
257
- ] }), /*#__PURE__*/ jsxs("tr", { children: [
258
- /*#__PURE__*/ jsx("th", {
259
- scope: "row",
260
- style: {
261
- ...styles.headLabel,
262
- ...styles.rule
263
- },
264
- children: "All"
265
- }),
266
- /*#__PURE__*/ jsx("td", {
267
- style: {
268
- ...controlStyle(!withDelete),
269
- ...styles.rule
270
- },
271
- children: /*#__PURE__*/ jsx(Segments, {
272
- included: includedBelow(allOptions, allLevel),
273
- label: `Access for every ${entries} entry`,
274
- onSelect: (level) => {
275
- toggle({
276
- kind: "access",
277
- namespace: namespace.id,
278
- level
279
- });
280
- },
281
- options: allOptions,
282
- readOnly,
283
- selected: allLevel
284
- })
285
- }),
286
- withDelete ? /*#__PURE__*/ jsx("td", {
287
- style: {
288
- ...controlStyle(true),
289
- ...styles.rule
290
- },
291
- children: /*#__PURE__*/ jsx(Segments, {
292
- label: `Delete for every ${entries} entry`,
293
- onSelect: (mode) => {
294
- toggle({
295
- kind: "deleteMode",
296
- namespace: namespace.id,
297
- mode
298
- });
299
- },
300
- options: DELETE_OPTIONS.filter((option) => option.id !== "trash"),
301
- readOnly,
302
- selected: allDeleteMode(matrix, path, namespace.id, values)
303
- })
304
- }) : null
305
- ] })]
306
- }),
307
- /*#__PURE__*/ jsx("tbody", { children: rows.map((row) => {
308
- const options = accessOptions([row]);
309
- const level = accessLevelOf(path, namespace.id, row, values);
310
- return /*#__PURE__*/ jsxs("tr", { children: [
311
- /*#__PURE__*/ jsxs("th", {
312
- scope: "row",
313
- style: styles.rowHeader,
314
- children: [row.label, row.live ? /*#__PURE__*/ jsx(LiveBadge, {}) : null]
315
- }),
316
- /*#__PURE__*/ jsx("td", {
317
- style: controlStyle(!withDelete),
318
- children: /*#__PURE__*/ jsx(Segments, {
319
- included: includedBelow(options, level),
320
- label: `Access for ${row.label}`,
321
- onSelect: (next) => {
322
- toggle({
323
- kind: "access",
324
- namespace: namespace.id,
325
- fieldName: row.fieldName,
326
- level: next
327
- });
328
- },
329
- options,
330
- readOnly,
331
- selected: level
332
- })
333
- }),
334
- withDelete ? /*#__PURE__*/ jsx("td", {
335
- style: controlStyle(true),
336
- children: row.delete ? /*#__PURE__*/ jsx(Segments, {
337
- label: `Delete for ${row.label}`,
338
- onSelect: (mode) => {
339
- toggle({
340
- kind: "deleteMode",
341
- namespace: namespace.id,
342
- fieldName: row.fieldName,
343
- mode
344
- });
345
- },
346
- options: DELETE_OPTIONS.filter((option) => option.id !== "trash" || row.deleteUnattended),
347
- readOnly,
348
- selected: deleteModeOf(path, namespace.id, row, values)
349
- }) : null
350
- }) : null
351
- ] }, row.fieldName);
352
- }) })
353
- ]
354
- })
355
- });
356
- };
357
- const ToolsTable = ({ matrix, path, readOnly, toggle, values }) => {
358
- const toolState = toolsState(matrix, path, values);
359
- return /*#__PURE__*/ jsx("section", {
360
- style: styles.section,
361
- children: /*#__PURE__*/ jsxs("table", {
362
- style: styles.table,
363
- children: [
364
- /*#__PURE__*/ jsx(Columns, { widths: [OPERATION_WIDTH] }),
365
- /*#__PURE__*/ jsxs("thead", {
366
- style: styles.head,
367
- children: [/*#__PURE__*/ jsxs("tr", { children: [/*#__PURE__*/ jsx("th", {
368
- scope: "col",
369
- style: {
370
- ...styles.headTitle,
371
- ...styles.topStart
372
- },
373
- children: "Tools"
374
- }), /*#__PURE__*/ jsx("th", {
375
- scope: "col",
376
- style: {
377
- ...styles.headOperation,
378
- ...styles.topEnd
379
- },
380
- children: "Enabled"
381
- })] }), /*#__PURE__*/ jsxs("tr", { children: [/*#__PURE__*/ jsx("th", {
382
- scope: "row",
383
- style: {
384
- ...styles.headLabel,
385
- ...styles.rule
386
- },
387
- children: "All"
388
- }), /*#__PURE__*/ jsx("td", {
389
- style: {
390
- ...lastCellStyle,
391
- ...styles.rule
392
- },
393
- children: /*#__PURE__*/ jsx(Box, {
394
- label: "Enable every tool",
395
- onChange: () => {
396
- toggle({
397
- kind: "tools",
398
- value: toolState !== "on"
399
- });
400
- },
401
- readOnly,
402
- state: toolState
236
+ const { i18n } = useTranslation();
237
+ const { getEntityConfig } = useConfig();
238
+ const nameOf = (row) => translateStatic(namespace.id === "collections" ? getEntityConfig({ collectionSlug: row.slug }).labels.plural : getEntityConfig({ globalSlug: row.slug }).label, i18n) ?? row.slug;
239
+ const allDelete = allDeleteMode(matrix, path, namespace.id, values);
240
+ return /*#__PURE__*/ jsx(MatrixTable, {
241
+ all: /*#__PURE__*/ jsxs(Fragment, { children: [/*#__PURE__*/ jsx("td", {
242
+ className: `${BASE_CLASS}__start`,
243
+ children: /*#__PURE__*/ jsx(Segments, {
244
+ included: includedBelow(allOptions, allLevel),
245
+ label: `Access for every ${entries} entry`,
246
+ onSelect: (level) => {
247
+ toggle({
248
+ kind: "access",
249
+ namespace: namespace.id,
250
+ level
251
+ });
252
+ },
253
+ options: allOptions,
254
+ readOnly,
255
+ selected: allLevel
256
+ })
257
+ }), withDelete ? /*#__PURE__*/ jsx("td", {
258
+ className: `${BASE_CLASS}__start`,
259
+ children: /*#__PURE__*/ jsx(Box, {
260
+ label: `Delete for every ${entries} entry`,
261
+ onChange: () => {
262
+ toggle({
263
+ kind: "deleteMode",
264
+ namespace: namespace.id,
265
+ mode: nextDeleteMode(allDelete)
266
+ });
267
+ },
268
+ readOnly,
269
+ state: deleteBoxState(allDelete)
270
+ })
271
+ }) : null] }),
272
+ heads: withDelete ? ["Access", "Delete"] : ["Access"],
273
+ start: true,
274
+ title: namespace.title,
275
+ widths: withDelete ? [ACCESS_WIDTH, DELETE_WIDTH] : [ACCESS_WIDTH],
276
+ children: rows.map((row) => {
277
+ const options = accessOptions([row]);
278
+ const level = accessLevelOf(path, namespace.id, row, values);
279
+ const mode = deleteModeOf(path, namespace.id, row, values);
280
+ const name = nameOf(row);
281
+ return /*#__PURE__*/ jsxs("tr", { children: [
282
+ /*#__PURE__*/ jsxs("th", {
283
+ className: `${BASE_CLASS}__row`,
284
+ scope: "row",
285
+ children: [
286
+ name,
287
+ row.live ? /*#__PURE__*/ jsx(LiveBadge, {}) : null,
288
+ name === row.slug ? null : /*#__PURE__*/ jsx("span", {
289
+ className: `${BASE_CLASS}__hint`,
290
+ children: row.slug
403
291
  })
404
- })] })]
292
+ ]
405
293
  }),
406
- /*#__PURE__*/ jsx("tbody", { children: matrix.tools.map((tool) => /*#__PURE__*/ jsxs("tr", { children: [/*#__PURE__*/ jsxs("th", {
407
- scope: "row",
408
- style: styles.rowHeader,
409
- children: [tool.name, /*#__PURE__*/ jsx("span", {
410
- style: styles.hint,
411
- children: tool.description
412
- })]
413
- }), /*#__PURE__*/ jsx("td", {
414
- style: lastCellStyle,
415
- children: /*#__PURE__*/ jsx(Box, {
416
- label: `Enable ${tool.name}`,
417
- onChange: () => {
294
+ /*#__PURE__*/ jsx("td", {
295
+ className: `${BASE_CLASS}__start`,
296
+ children: /*#__PURE__*/ jsx(Segments, {
297
+ included: includedBelow(options, level),
298
+ label: `Access for ${name}`,
299
+ onSelect: (next) => {
418
300
  toggle({
419
- kind: "tool",
420
- name: tool.name,
421
- value: values[toolPath(path, tool.name)] !== true
301
+ kind: "access",
302
+ namespace: namespace.id,
303
+ fieldName: row.fieldName,
304
+ level: next
422
305
  });
423
306
  },
307
+ options,
424
308
  readOnly,
425
- state: values[toolPath(path, tool.name)] === true ? "on" : "off"
309
+ selected: level
426
310
  })
427
- })] }, tool.name)) })
428
- ]
311
+ }),
312
+ withDelete ? /*#__PURE__*/ jsx("td", {
313
+ className: `${BASE_CLASS}__start`,
314
+ children: row.delete ? /*#__PURE__*/ jsxs("span", {
315
+ className: `${BASE_CLASS}__delete`,
316
+ children: [/*#__PURE__*/ jsx(Box, {
317
+ label: `Delete ${name}`,
318
+ onChange: () => {
319
+ toggle({
320
+ kind: "deleteMode",
321
+ namespace: namespace.id,
322
+ fieldName: row.fieldName,
323
+ mode: nextDeleteMode(mode)
324
+ });
325
+ },
326
+ readOnly,
327
+ state: deleteBoxState(mode)
328
+ }), mode === "off" ? null : /*#__PURE__*/ jsx(ApprovalToggle, {
329
+ label: `Approval for deleting ${name}`,
330
+ locked: !row.deleteUnattended,
331
+ onToggle: () => {
332
+ toggle({
333
+ kind: "deleteMode",
334
+ namespace: namespace.id,
335
+ fieldName: row.fieldName,
336
+ mode: mode === "trash" ? "approve" : "trash"
337
+ });
338
+ },
339
+ pressed: mode !== "trash",
340
+ readOnly
341
+ })]
342
+ }) : null
343
+ }) : null
344
+ ] }, row.fieldName);
345
+ })
346
+ });
347
+ };
348
+ const ToolsTable = ({ matrix, path, readOnly, toggle, values }) => {
349
+ const toolState = toolsState(matrix, path, values);
350
+ return /*#__PURE__*/ jsx(MatrixTable, {
351
+ all: /*#__PURE__*/ jsx("td", { children: /*#__PURE__*/ jsx(Box, {
352
+ label: "Enable every tool",
353
+ onChange: () => {
354
+ toggle({
355
+ kind: "tools",
356
+ value: toolState !== "on"
357
+ });
358
+ },
359
+ readOnly,
360
+ state: toolState
361
+ }) }),
362
+ heads: ["Enabled"],
363
+ title: "Tools",
364
+ widths: [OPERATION_WIDTH],
365
+ children: matrix.tools.map((tool) => {
366
+ const granted = values[toolPath(path, tool.name)] === true;
367
+ return /*#__PURE__*/ jsxs("tr", { children: [/*#__PURE__*/ jsxs("th", {
368
+ className: `${BASE_CLASS}__row`,
369
+ scope: "row",
370
+ children: [tool.name, /*#__PURE__*/ jsx("span", {
371
+ className: `${BASE_CLASS}__hint`,
372
+ children: tool.description
373
+ })]
374
+ }), /*#__PURE__*/ jsx("td", { children: /*#__PURE__*/ jsx(Box, {
375
+ label: `Enable ${tool.name}`,
376
+ onChange: () => {
377
+ toggle({
378
+ kind: "tool",
379
+ name: tool.name,
380
+ value: !granted
381
+ });
382
+ },
383
+ readOnly,
384
+ state: granted ? "on" : "off"
385
+ }) })] }, tool.name);
429
386
  })
430
387
  });
431
388
  };
432
389
  /**
433
390
  * What an API key may do, as one table per namespace: a row per entity with
434
- * segmented Access and Delete controls, and an "All" row that sets every row.
391
+ * an Access control and a Delete checkbox with an approval shield, and an
392
+ * "All" row that sets every row.
435
393
  * The nested checkbox fields back every control, so the stored document is
436
394
  * unaffected.
437
395
  */ const McpxCapabilityMatrix = ({ field, matrix, path = CAPABILITIES_FIELD, readOnly = false, withinTab = false }) => {
@@ -459,45 +417,38 @@ const ToolsTable = ({ matrix, path, readOnly, toggle, values }) => {
459
417
  title: "Globals"
460
418
  }].filter((namespace) => matrix[namespace.id].length > 0);
461
419
  return /*#__PURE__*/ jsxs("div", {
462
- className: [
463
- "field-type",
464
- "group-field",
465
- "group-field--top-level",
466
- withinTab && "group-field--within-tab",
467
- BASE_CLASS
468
- ].filter(Boolean).join(" "),
420
+ className: cx("field-type", "group-field", "group-field--top-level", withinTab && "group-field--within-tab", BASE_CLASS),
469
421
  children: [/*#__PURE__*/ jsx("style", { children: SHEET }), /*#__PURE__*/ jsxs("div", {
470
422
  className: "group-field__wrap",
471
- children: [
472
- /*#__PURE__*/ jsx("div", {
473
- className: "group-field__header",
474
- children: /*#__PURE__*/ jsxs("header", { children: [/*#__PURE__*/ jsx("h3", {
475
- className: "group-field__title",
476
- children: /*#__PURE__*/ jsx(FieldLabel, {
477
- as: "span",
478
- label: "Capabilities"
479
- })
480
- }), typeof field?.admin?.description === "string" ? /*#__PURE__*/ jsx(FieldDescription, {
481
- description: field.admin.description,
482
- path
483
- }) : null] })
484
- }),
485
- namespaces.map((namespace) => /*#__PURE__*/ jsx(NamespaceTable, {
423
+ children: [/*#__PURE__*/ jsx("div", {
424
+ className: "group-field__header",
425
+ children: /*#__PURE__*/ jsxs("header", { children: [withinTab ? null : /*#__PURE__*/ jsx("h3", {
426
+ className: "group-field__title",
427
+ children: /*#__PURE__*/ jsx(FieldLabel, {
428
+ as: "span",
429
+ label: "Capabilities"
430
+ })
431
+ }), typeof field?.admin?.description === "string" ? /*#__PURE__*/ jsx(FieldDescription, {
432
+ description: field.admin.description,
433
+ path
434
+ }) : null] })
435
+ }), /*#__PURE__*/ jsxs("div", {
436
+ className: `${BASE_CLASS}__sections`,
437
+ children: [namespaces.map((namespace) => /*#__PURE__*/ jsx(NamespaceTable, {
486
438
  matrix,
487
439
  namespace,
488
440
  path,
489
441
  readOnly,
490
442
  toggle,
491
443
  values
492
- }, namespace.id)),
493
- matrix.tools.length > 0 ? /*#__PURE__*/ jsx(ToolsTable, {
444
+ }, namespace.id)), matrix.tools.length > 0 ? /*#__PURE__*/ jsx(ToolsTable, {
494
445
  matrix,
495
446
  path,
496
447
  readOnly,
497
448
  toggle,
498
449
  values
499
- }) : null
500
- ]
450
+ }) : null]
451
+ })]
501
452
  })]
502
453
  });
503
454
  };