@stapel/workspaces-react 0.16.0 → 0.19.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.
Files changed (128) hide show
  1. package/CHANGELOG.md +194 -0
  2. package/README.md +39 -8
  3. package/dist/api/generated/schema.d.ts +187 -60
  4. package/dist/api/generated/schema.d.ts.map +1 -1
  5. package/dist/default/ActiveWorkspace.d.ts +43 -0
  6. package/dist/default/ActiveWorkspace.d.ts.map +1 -0
  7. package/dist/default/ActiveWorkspace.js +33 -0
  8. package/dist/default/ActiveWorkspace.js.map +1 -0
  9. package/dist/default/AuditTrailPane.d.ts +12 -0
  10. package/dist/default/AuditTrailPane.d.ts.map +1 -0
  11. package/dist/default/AuditTrailPane.js +154 -0
  12. package/dist/default/AuditTrailPane.js.map +1 -0
  13. package/dist/default/InvitationsPane.d.ts +19 -0
  14. package/dist/default/InvitationsPane.d.ts.map +1 -0
  15. package/dist/default/InvitationsPane.js +217 -0
  16. package/dist/default/InvitationsPane.js.map +1 -0
  17. package/dist/default/InviteAcceptPage.d.ts +7 -0
  18. package/dist/default/InviteAcceptPage.d.ts.map +1 -1
  19. package/dist/default/InviteAcceptPage.js +74 -38
  20. package/dist/default/InviteAcceptPage.js.map +1 -1
  21. package/dist/default/MembersManager.d.ts +12 -4
  22. package/dist/default/MembersManager.d.ts.map +1 -1
  23. package/dist/default/MembersManager.js +320 -84
  24. package/dist/default/MembersManager.js.map +1 -1
  25. package/dist/default/RoleSelectField.d.ts +64 -0
  26. package/dist/default/RoleSelectField.d.ts.map +1 -0
  27. package/dist/default/RoleSelectField.js +78 -0
  28. package/dist/default/RoleSelectField.js.map +1 -0
  29. package/dist/default/WorkspaceSettings.d.ts +7 -1
  30. package/dist/default/WorkspaceSettings.d.ts.map +1 -1
  31. package/dist/default/WorkspaceSettings.js +203 -45
  32. package/dist/default/WorkspaceSettings.js.map +1 -1
  33. package/dist/default/WorkspacesPage.d.ts +13 -0
  34. package/dist/default/WorkspacesPage.d.ts.map +1 -0
  35. package/dist/default/WorkspacesPage.js +108 -0
  36. package/dist/default/WorkspacesPage.js.map +1 -0
  37. package/dist/default/index.d.ts +28 -7
  38. package/dist/default/index.d.ts.map +1 -1
  39. package/dist/default/index.js +24 -7
  40. package/dist/default/index.js.map +1 -1
  41. package/dist/default/parts.d.ts +104 -0
  42. package/dist/default/parts.d.ts.map +1 -0
  43. package/dist/default/parts.js +140 -0
  44. package/dist/default/parts.js.map +1 -0
  45. package/dist/headless/Members.d.ts +59 -14
  46. package/dist/headless/Members.d.ts.map +1 -1
  47. package/dist/headless/Members.js +35 -10
  48. package/dist/headless/Members.js.map +1 -1
  49. package/dist/headless/RoleSelect.d.ts +9 -3
  50. package/dist/headless/RoleSelect.d.ts.map +1 -1
  51. package/dist/headless/RoleSelect.js +3 -2
  52. package/dist/headless/RoleSelect.js.map +1 -1
  53. package/dist/i18n/es.d.ts +11 -12
  54. package/dist/i18n/es.d.ts.map +1 -1
  55. package/dist/i18n/es.js +267 -14
  56. package/dist/i18n/es.js.map +1 -1
  57. package/dist/i18n/generated/errors.es.gen.d.ts.map +1 -1
  58. package/dist/i18n/generated/errors.es.gen.js +5 -0
  59. package/dist/i18n/generated/errors.es.gen.js.map +1 -1
  60. package/dist/i18n/generated/errors.gen.d.ts +30 -0
  61. package/dist/i18n/generated/errors.gen.d.ts.map +1 -1
  62. package/dist/i18n/generated/errors.gen.js +15 -0
  63. package/dist/i18n/generated/errors.gen.js.map +1 -1
  64. package/dist/i18n/generated/errors.ru.gen.d.ts.map +1 -1
  65. package/dist/i18n/generated/errors.ru.gen.js +5 -0
  66. package/dist/i18n/generated/errors.ru.gen.js.map +1 -1
  67. package/dist/i18n/keys.d.ts +209 -1
  68. package/dist/i18n/keys.d.ts.map +1 -1
  69. package/dist/i18n/keys.js +410 -4
  70. package/dist/i18n/keys.js.map +1 -1
  71. package/dist/i18n/ru.d.ts +7 -2
  72. package/dist/i18n/ru.d.ts.map +1 -1
  73. package/dist/i18n/ru.js +209 -4
  74. package/dist/i18n/ru.js.map +1 -1
  75. package/dist/index.d.ts +2 -2
  76. package/dist/index.d.ts.map +1 -1
  77. package/dist/index.js +6 -2
  78. package/dist/index.js.map +1 -1
  79. package/dist/model/format.d.ts +56 -0
  80. package/dist/model/format.d.ts.map +1 -0
  81. package/dist/model/format.js +125 -0
  82. package/dist/model/format.js.map +1 -0
  83. package/dist/model/mandate.d.ts +23 -1
  84. package/dist/model/mandate.d.ts.map +1 -1
  85. package/dist/model/mandate.js +24 -0
  86. package/dist/model/mandate.js.map +1 -1
  87. package/dist/model/selection.d.ts +15 -0
  88. package/dist/model/selection.d.ts.map +1 -1
  89. package/dist/model/selection.js +18 -1
  90. package/dist/model/selection.js.map +1 -1
  91. package/dist/nav/manifest.d.ts +45 -0
  92. package/dist/nav/manifest.d.ts.map +1 -0
  93. package/dist/nav/manifest.js +77 -0
  94. package/dist/nav/manifest.js.map +1 -0
  95. package/llms.txt +11 -10
  96. package/manifest.json +282 -69
  97. package/package.json +18 -12
  98. package/src/analytics/generated/events.json +1 -1
  99. package/src/api/generated/schema.ts +187 -60
  100. package/src/default/ActiveWorkspace.tsx +97 -0
  101. package/src/default/AuditTrailPane.tsx +309 -0
  102. package/src/default/InvitationsPane.tsx +501 -0
  103. package/src/default/InviteAcceptPage.tsx +187 -90
  104. package/src/default/MembersManager.tsx +832 -222
  105. package/src/default/RoleSelectField.tsx +187 -0
  106. package/src/default/WorkspaceSettings.tsx +540 -125
  107. package/src/default/WorkspacesPage.tsx +387 -0
  108. package/src/default/index.ts +28 -7
  109. package/src/default/parts.tsx +308 -0
  110. package/src/headless/Members.tsx +84 -16
  111. package/src/headless/RoleSelect.tsx +12 -5
  112. package/src/i18n/es.ts +326 -14
  113. package/src/i18n/generated/errors.es.gen.ts +5 -0
  114. package/src/i18n/generated/errors.gen.ts +15 -0
  115. package/src/i18n/generated/errors.json +37 -0
  116. package/src/i18n/generated/errors.ru.gen.ts +5 -0
  117. package/src/i18n/keys.ts +462 -5
  118. package/src/i18n/ru.ts +259 -5
  119. package/src/index.ts +6 -1
  120. package/src/model/format.ts +158 -0
  121. package/src/model/mandate.ts +26 -1
  122. package/src/model/selection.tsx +19 -1
  123. package/src/nav/manifest.ts +120 -0
  124. package/dist/default/ErrorAlert.d.ts +0 -8
  125. package/dist/default/ErrorAlert.d.ts.map +0 -1
  126. package/dist/default/ErrorAlert.js +0 -30
  127. package/dist/default/ErrorAlert.js.map +0 -1
  128. package/src/default/ErrorAlert.tsx +0 -47
@@ -0,0 +1,78 @@
1
+ import { Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { Flex, Select, Typography } from "antd";
3
+ import { matchList, useI18n, useT } from "@stapel/core";
4
+ import { spacing, fontSize } from "@stapel/tokens";
5
+ import { RoleSelect } from "../headless/RoleSelect.js";
6
+ import { titleCaseKey } from "../model/format.js";
7
+ import { WORKSPACES_I18N_KEYS } from "../i18n/keys.js";
8
+ import { Muted } from "./parts.js";
9
+ /** The system-protected role only an owner may grant. */
10
+ const OWNER_ROLE = "owner";
11
+ /**
12
+ * Role key → the word for it, with no registry read behind it.
13
+ *
14
+ * `RoleSelect`'s own `labelFor` is a bundle lookup that never touches the
15
+ * query, but mounting `<RoleSelect>` to reach it also fires GET /roles — which
16
+ * on the PUBLIC invitation page is a call an anonymous reader cannot make.
17
+ * A caption that only needs a word asks for a word.
18
+ */
19
+ export function useRoleLabel() {
20
+ const i18n = useI18n();
21
+ // Raw bundle lookup, NOT `t()`: `t` falls back to the key itself, and
22
+ // `workspaces.role.secretary` is the one thing this must never print.
23
+ const bundle = i18n.getBundle();
24
+ return (role) => bundle[`workspaces.role.${role}`] ?? titleCaseKey(role);
25
+ }
26
+ /**
27
+ * A role as a WORD, where there is nothing to pick — an invitation's granted
28
+ * role, a read-only roster. The same label resolution as the field, so one
29
+ * screen never calls `admin` "Admin" while its neighbour prints `admin`.
30
+ */
31
+ export function RoleLabel(props) {
32
+ const labelFor = useRoleLabel();
33
+ return _jsx(_Fragment, { children: labelFor(props.role) });
34
+ }
35
+ export function RoleSelectField(props) {
36
+ const t = useT();
37
+ return (_jsx(RoleSelect, { children: ({ state, labelFor }) => {
38
+ const control = matchList(state, {
39
+ loading: () => (_jsx(Select, { value: props.value, loading: true, open: false, size: props.size ?? "middle", style: { width: "100%" }, "aria-label": props.label, options: [{ value: props.value, label: labelFor(props.value) }], onChange: props.onChange, disabled: true, "data-disabled-reason": "the role registry is still loading; the current role is shown meanwhile", ...(props.testId !== undefined ? { "data-testid": props.testId } : {}) })),
40
+ // A failed registry read is not an empty registry, and neither is a
41
+ // picker. The role still READS; only the choice is withdrawn.
42
+ failed: () => (_jsxs(Flex, { vertical: true, gap: spacing["1"], align: "flex-start", children: [_jsx(Typography.Text, { children: labelFor(props.value) }), _jsx(Muted, { testId: props.testId !== undefined ? `${props.testId}-blocked` : undefined, children: t(WORKSPACES_I18N_KEYS.rolesLoadFailed) })] })),
43
+ // A registry that came back EMPTY is not a registry that failed —
44
+ // saying "we could not load the role list" about a successful read
45
+ // is the same class of lie as an empty state over a failed one.
46
+ empty: () => (_jsxs(Flex, { vertical: true, gap: spacing["1"], align: "flex-start", children: [_jsx(Typography.Text, { children: labelFor(props.value) }), _jsx(Muted, { children: t(WORKSPACES_I18N_KEYS.rolesEmpty) })] })),
47
+ ready: (roles) => {
48
+ const offered = props.excludeOwner === true
49
+ ? roles.filter((role) => role.role !== OWNER_ROLE)
50
+ : roles;
51
+ const rankOf = new Map(offered.map((role) => [role.role, role.rank]));
52
+ const options = offered.map((role) => ({
53
+ value: role.role,
54
+ label: labelFor(role.role),
55
+ }));
56
+ // The member's CURRENT role may be missing from the offered set
57
+ // (an overlay role a deployment removed, or `owner` on the invite
58
+ // path). Antd would render the bare key for it; the registry's
59
+ // own label is better, and the row must keep showing what the
60
+ // person actually holds.
61
+ const hasCurrent = options.some((option) => option.value === props.value);
62
+ const allOptions = hasCurrent
63
+ ? options
64
+ : [{ value: props.value, label: labelFor(props.value) }, ...options];
65
+ return (_jsx(Select, { value: props.value, onChange: props.onChange, size: props.size ?? "middle", style: { width: "100%" }, "aria-label": props.label, ...(props["aria-describedby"] !== undefined
66
+ ? { "aria-describedby": props["aria-describedby"] }
67
+ : {}), ...(props.disabled !== undefined ? { disabled: props.disabled } : {}), options: allOptions, optionRender: (option) => {
68
+ const rank = rankOf.get(String(option.value));
69
+ return (_jsxs(Flex, { vertical: true, gap: spacing["0"], children: [_jsx("span", { children: option.label }), rank !== undefined && (_jsx(Typography.Text, { type: "secondary", style: { fontSize: fontSize.xs.fontSize }, children: t(WORKSPACES_I18N_KEYS.roleRankCaption, { rank }) }))] }));
70
+ }, ...(props.testId !== undefined ? { "data-testid": props.testId } : {}) }));
71
+ },
72
+ });
73
+ if (props.showLabel !== true)
74
+ return control;
75
+ return (_jsxs(Flex, { vertical: true, gap: spacing["1"], style: { width: "100%" }, children: [_jsx(Typography.Text, { children: props.label }), control] }));
76
+ } }));
77
+ }
78
+ //# sourceMappingURL=RoleSelectField.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"RoleSelectField.js","sourceRoot":"","sources":["../../src/default/RoleSelectField.tsx"],"names":[],"mappings":"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"}
@@ -1,6 +1,12 @@
1
1
  import type { ReactElement } from "react";
2
2
  export interface WorkspaceSettingsProps {
3
- workspaceId: string;
3
+ /**
4
+ * The workspace being configured. OPTIONAL: omitted (the way the nav
5
+ * contract mounts this screen — a route, never an ambient scope), the
6
+ * active workspace comes from the runtime selection, and a screen with none
7
+ * renders the designed "choose a workspace" state rather than a blank.
8
+ */
9
+ workspaceId?: string;
4
10
  /** Called after a successful delete — the host navigates away / switches
5
11
  * to another workspace. Not called on cancel or failure. */
6
12
  onDeleted?(): void;
@@ -1 +1 @@
1
- {"version":3,"file":"WorkspaceSettings.d.ts","sourceRoot":"","sources":["../../src/default/WorkspaceSettings.tsx"],"names":[],"mappings":"AASA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,OAAO,CAAC;AAe1C,MAAM,WAAW,sBAAsB;IACrC,WAAW,EAAE,MAAM,CAAC;IACpB;gEAC4D;IAC5D,SAAS,CAAC,IAAI,IAAI,CAAC;CACpB;AAED,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,sBAAsB,GAAG,YAAY,CAqI7E"}
1
+ {"version":3,"file":"WorkspaceSettings.d.ts","sourceRoot":"","sources":["../../src/default/WorkspaceSettings.tsx"],"names":[],"mappings":"AA8BA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,OAAO,CAAC;AAqC1C,MAAM,WAAW,sBAAsB;IACrC;;;;;OAKG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB;gEAC4D;IAC5D,SAAS,CAAC,IAAI,IAAI,CAAC;CACpB;AA8CD,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,sBAAsB,GAAG,YAAY,CAgB7E"}
@@ -1,56 +1,214 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  /**
3
- * `<WorkspaceSettings/>` — default skin for the "workspace" settings screen
4
- * (owner directive: workspace name/general settings, one of the settings
5
- * surfaces this liberary pair owns). Built entirely on this pair's EXISTING
6
- * hooks (`useWorkspace`, `useUpdateWorkspace`, `useDeleteWorkspace`) — no new
7
- * backend surface. Participants/roles live in the sibling
8
- * `<MembersManager/>` (a workspace's settings page composes both).
3
+ * `<WorkspaceSettings/>` — the default skin for a workspace's own settings:
4
+ * its name, the security policy everyone in it has to meet, and the one
5
+ * irreversible act (deletion). Participants and roles live in the sibling
6
+ * `<MembersManager/>`; invitations in `<InvitationsPane/>`.
7
+ *
8
+ * ## Two rules this screen exists to state
9
+ *
10
+ * **A control never claims what the endpoint would refuse.** The delete
11
+ * button used to be drawn from `my_role === "owner"`. That derivation is
12
+ * wrong on exactly two workspaces — the instance's default one, and a
13
+ * personal one the next sign-in re-mints — and the backend added
14
+ * `WorkspaceResponse.can_delete` + `delete_blocked_reason` (0.26.0) because
15
+ * of it: the verdict comes from the SAME `deletion_block_reason()` the DELETE
16
+ * raises from, so a screen built on it cannot promise what the endpoint
17
+ * denies. `delete_blocked_reason` is an error CODE (`error.409.workspace_is_
18
+ * personal`), which is already a key in this pair's generated bundle, so the
19
+ * refusal renders in the reader's language beside the switched-off control.
20
+ * The same rule applies to the name field, which is gated on the capability
21
+ * `workspace.update` rather than on a role name — a deployment role can hold
22
+ * the capability without being called owner.
23
+ *
24
+ * **A policy says what HOLDS, not what was asked for.** `settings.security.
25
+ * require_mfa` is a flag somebody set; `mfa_enforcement` is how far the
26
+ * sweep actually got (WORK-01, 0.25.0). An administrator who switched MFA on
27
+ * and was told "saved" while half the organization was never checked is the
28
+ * defect the status block answers, and `unverified_members` is the number
29
+ * they have to get to zero.
9
30
  */
10
- import { useEffect, useState } from "react";
11
- import { Badge, Button, Card, Input, Popconfirm, Spin, Typography } from "antd";
12
- import { actionAvailable, actionBlocked, firstBlock, useActionGate, useErrorDisplay, useT, } from "@stapel/core";
13
- import { useWorkspace } from "../model/queries.js";
14
- import { useUpdateWorkspace, useDeleteWorkspace } from "../model/mutations.js";
31
+ import { useEffect, useMemo, useState } from "react";
32
+ import { Card, Checkbox, Flex, Input, Switch, Typography } from "antd";
33
+ import { actionAvailable, actionBlocked, firstBlock, loadStateFromQuery, useT, useTPlural, } from "@stapel/core";
34
+ import { ErrorAlert, GatedButton, GatedControl, LoadBoundary, SkinConfirm, SkinTheme, } from "@stapel/tokens-antd/skin";
35
+ import { spacing } from "@stapel/tokens";
36
+ import { hasCapability } from "../model/capabilities.js";
37
+ import { useCapabilityGate, useWorkspace } from "../model/queries.js";
38
+ import { useDeleteWorkspace, useUpdateSecuritySettings, useUpdateWorkspace, } from "../model/mutations.js";
39
+ import { useWorkspaceFormat } from "../model/format.js";
15
40
  import { WORKSPACES_I18N_KEYS } from "../i18n/keys.js";
16
- import { ErrorAlert } from "./ErrorAlert.js";
41
+ import { ActiveWorkspaceBoundary } from "./ActiveWorkspace.js";
42
+ import { Muted, StatusTag, SCREEN_STACK, FIELD_STACK } from "./parts.js";
43
+ /** The two first-login demands an organization may raise, in the order the
44
+ * backend documents them. Independent checkboxes, never alternatives. */
45
+ const POLICIES = [
46
+ {
47
+ value: "password_change",
48
+ labelKey: WORKSPACES_I18N_KEYS.securityPolicyPasswordChange,
49
+ },
50
+ { value: "mfa_enroll", labelKey: WORKSPACES_I18N_KEYS.securityPolicyMfaEnroll },
51
+ ];
52
+ /** `settings.security`, typed. The block lives inside the free-form settings
53
+ * JSON, so the generated types say `object` and this is the read side of the
54
+ * documented correction in `api/types.ts`. */
55
+ function securityOf(workspace) {
56
+ const settings = (workspace.settings ?? {});
57
+ return (settings["security"] ?? {});
58
+ }
59
+ function sameStringSet(a, b) {
60
+ return a.length === b.length && a.every((value) => b.includes(value));
61
+ }
62
+ /**
63
+ * May this caller exercise `capability` in this workspace?
64
+ *
65
+ * `my_capabilities` is the mandate the server granted, and it is what the
66
+ * server re-checks — so it is what the screen reads. It is also ADDITIVE
67
+ * (stapel-workspaces ≥0.6.0): a deployment on an older backend sends the
68
+ * field not at all, and treating that silence as "no" would switch the whole
69
+ * settings screen off for its owner. So the absence — and only the absence —
70
+ * falls back to the pre-0.6 rule this pair used to apply everywhere. Where
71
+ * the field IS present, `my_role` is never consulted: a deployment role can
72
+ * hold `workspace.update` without being called owner, and the endpoint would
73
+ * accept it.
74
+ */
75
+ function mayUse(workspace, capability) {
76
+ const granted = workspace.my_capabilities;
77
+ if (granted === undefined)
78
+ return workspace.my_role === "owner";
79
+ return hasCapability(granted, capability);
80
+ }
17
81
  export function WorkspaceSettings(props) {
18
- const t = useT();
19
- // Never the raw `.message` — for a response with no error envelope that
20
- // is the transport's own "Request failed with status 500" (owner report
21
- // 2026-08-09). `useErrorText` folds any thrown value into the one dialect.
22
- const errorDisplay = useErrorDisplay(WORKSPACES_I18N_KEYS.unknownError);
82
+ return (_jsx(SkinTheme, { surface: "base", "data-testid": "workspace-settings", children: _jsx(ActiveWorkspaceBoundary, { workspaceId: props.workspaceId, testId: "workspace-settings-workspace", children: (workspaceId) => (_jsx(SettingsBody, { workspaceId: workspaceId, ...(props.onDeleted !== undefined ? { onDeleted: props.onDeleted } : {}) })) }) }));
83
+ }
84
+ function SettingsBody(props) {
23
85
  const query = useWorkspace(props.workspaceId);
86
+ return (_jsx(LoadBoundary, { state: loadStateFromQuery(query), testId: "workspace-settings-load", onRetry: () => {
87
+ void query.refetch();
88
+ }, children: (workspace) => (_jsxs("div", { style: SCREEN_STACK, children: [_jsx(GeneralCard, { workspace: workspace, workspaceId: props.workspaceId }), _jsx(SecurityCard, { workspace: workspace, workspaceId: props.workspaceId }), _jsx(DangerZone, { workspace: workspace, workspaceId: props.workspaceId, ...(props.onDeleted !== undefined ? { onDeleted: props.onDeleted } : {}) })] })) }));
89
+ }
90
+ /** Name, slug, type — the parts of a workspace a person renames. */
91
+ function GeneralCard(props) {
92
+ const t = useT();
24
93
  const updateMutation = useUpdateWorkspace(props.workspaceId);
25
- const deleteMutation = useDeleteWorkspace();
26
- const workspace = query.data;
27
- const [name, setName] = useState("");
28
- // Two unrelated situations used to share one `disabled={!isOwner ||
29
- // !name.trim()}` bit, and a person facing either of them saw the same dead
30
- // button. `firstBlock` keeps them two, in the order you would explain them.
31
- const isOwner = workspace?.my_role === "owner";
32
- const saveGate = useActionGate(firstBlock(isOwner ? actionAvailable() : actionBlocked(WORKSPACES_I18N_KEYS.blockedNotOwner), name.trim() ? actionAvailable() : actionBlocked(WORKSPACES_I18N_KEYS.blockedNameRequired)));
94
+ const [name, setName] = useState(props.workspace.name);
33
95
  useEffect(() => {
34
- if (workspace)
35
- setName(workspace.name);
36
- }, [workspace]);
37
- function handleSave() {
38
- updateMutation.mutate({ name: name.trim() });
39
- }
40
- function handleDelete() {
41
- deleteMutation.mutate(props.workspaceId, {
42
- onSuccess: () => props.onDeleted?.(),
43
- });
44
- }
45
- if (query.isLoading && !workspace) {
46
- return _jsx(Spin, { "data-testid": "workspace-settings-loading" });
47
- }
48
- if (!workspace) {
49
- return (_jsx(ErrorAlert, { testId: "workspace-settings-error", error: errorDisplay(query.error) ?? {
50
- message: t(WORKSPACES_I18N_KEYS.unknownError),
51
- detail: undefined,
52
- } }));
96
+ setName(props.workspace.name);
97
+ }, [props.workspace.name]);
98
+ // Ordered the way it would be explained out loud: what you may do first,
99
+ // then what you have not done yet.
100
+ const canManage = mayUse(props.workspace, "workspace.update")
101
+ ? actionAvailable()
102
+ : actionBlocked(WORKSPACES_I18N_KEYS.blockedCannotManage);
103
+ const saveGate = firstBlock(canManage, name.trim() === ""
104
+ ? actionBlocked(WORKSPACES_I18N_KEYS.blockedNameRequired)
105
+ : actionAvailable(), name.trim() === props.workspace.name
106
+ ? actionBlocked(WORKSPACES_I18N_KEYS.blockedUnchanged)
107
+ : actionAvailable());
108
+ const typeKey = props.workspace.type === "personal"
109
+ ? WORKSPACES_I18N_KEYS.typePersonal
110
+ : WORKSPACES_I18N_KEYS.typeWork;
111
+ return (_jsxs(Card, { children: [_jsx(Typography.Title, { level: 4, style: { marginTop: 0 }, children: t(WORKSPACES_I18N_KEYS.settingsTitle) }), _jsx(Typography.Text, { type: "secondary", children: t(WORKSPACES_I18N_KEYS.settingsSubtitle) }), _jsxs("div", { style: { ...FIELD_STACK, marginTop: spacing["4"] }, children: [_jsx(GatedControl, { gate: canManage, testId: "workspace-name-field", children: (bind) => (_jsxs(Flex, { vertical: true, gap: spacing["1"], style: { width: "100%" }, children: [_jsx(Typography.Text, { children: t(WORKSPACES_I18N_KEYS.fieldName) }), _jsx(Input, { value: name, onChange: (event) => setName(event.target.value), "aria-label": t(WORKSPACES_I18N_KEYS.fieldName), ...bind })] })) }), _jsxs(Flex, { vertical: true, gap: spacing["1"], children: [_jsx(Typography.Text, { children: t(WORKSPACES_I18N_KEYS.fieldSlug) }), _jsx(Typography.Text, { code: true, children: props.workspace.slug })] }), _jsxs(Flex, { vertical: true, gap: spacing["1"], align: "flex-start", children: [_jsx(Typography.Text, { children: t(WORKSPACES_I18N_KEYS.fieldType) }), _jsx(StatusTag, { tone: "neutral", testId: "workspace-type", children: t(typeKey) })] })] }), _jsx(ErrorAlert, { thrown: updateMutation.error, style: { marginTop: spacing["3"] }, testId: "workspace-settings-write-error" }), _jsx("div", { style: { marginTop: spacing["4"] }, children: _jsx(GatedButton, { gate: saveGate, type: "primary", loading: updateMutation.isPending, onClick: () => {
112
+ updateMutation.mutate({ name: name.trim() });
113
+ }, testId: "workspace-save", "data-analytics": "none", "data-analytics-reason": "business action \u2014 host app wraps with its own tracked(); pairs carry no @stapel/analytics runtime dependency by architecture", children: updateMutation.isPending
114
+ ? t(WORKSPACES_I18N_KEYS.saving)
115
+ : t(WORKSPACES_I18N_KEYS.save) }) })] }));
116
+ }
117
+ /** The `require_mfa` policy: what was asked for, and what actually holds. */
118
+ function SecurityCard(props) {
119
+ const t = useT();
120
+ const tPlural = useTPlural();
121
+ const format = useWorkspaceFormat();
122
+ const mutation = useUpdateSecuritySettings(props.workspaceId);
123
+ const gate = useCapabilityGate(props.workspaceId, "workspace.security.manage");
124
+ const stored = useMemo(() => securityOf(props.workspace), [props.workspace]);
125
+ const storedPolicies = useMemo(() => stored.provisioned_user_policies ?? [], [stored]);
126
+ /** What is SAVED, not what the person has just toggled: the enforcement
127
+ * block describes the policy the server is acting on. */
128
+ const storedRequireMfa = stored.require_mfa === true;
129
+ const [requireMfa, setRequireMfa] = useState(stored.require_mfa === true);
130
+ const [policies, setPolicies] = useState(storedPolicies);
131
+ useEffect(() => {
132
+ setRequireMfa(stored.require_mfa === true);
133
+ setPolicies(storedPolicies);
134
+ }, [stored, storedPolicies]);
135
+ const allowed = mayUse(props.workspace, "workspace.security.manage");
136
+ const canManage = allowed
137
+ ? actionAvailable()
138
+ : actionBlocked(WORKSPACES_I18N_KEYS.securityBlockedCapability);
139
+ const unchanged = requireMfa === (stored.require_mfa === true) &&
140
+ sameStringSet(policies, storedPolicies);
141
+ const saveGate = firstBlock(canManage, unchanged ? actionBlocked(WORKSPACES_I18N_KEYS.blockedUnchanged) : actionAvailable());
142
+ const enforcement = props.workspace.mfa_enforcement ?? null;
143
+ return (_jsxs(Card, { "data-testid": "workspace-security", children: [_jsx(Typography.Title, { level: 5, style: { marginTop: 0 }, children: t(WORKSPACES_I18N_KEYS.securityTitle) }), _jsx(Typography.Text, { type: "secondary", children: t(WORKSPACES_I18N_KEYS.securitySubtitle) }), _jsxs("div", { style: { ...FIELD_STACK, marginTop: spacing["4"] }, children: [_jsx(GatedControl, { gate: canManage, testId: "workspace-require-mfa-field", children: (bind) => (_jsxs(Flex, { gap: spacing["3"], align: "flex-start", children: [_jsx(Switch, { checked: requireMfa, onChange: setRequireMfa, "aria-label": t(WORKSPACES_I18N_KEYS.securityRequireMfa), "data-testid": "workspace-require-mfa", ...bind }), _jsxs(Flex, { vertical: true, gap: spacing["0"], children: [_jsx(Typography.Text, { children: t(WORKSPACES_I18N_KEYS.securityRequireMfa) }), _jsx(Muted, { children: t(WORKSPACES_I18N_KEYS.securityRequireMfaHint) })] })] })) }), _jsx(GatedControl, { gate: canManage, testId: "workspace-policies-field", children: (bind) => (_jsxs(Flex, { vertical: true, gap: spacing["2"], align: "flex-start", children: [_jsx(Typography.Text, { children: t(WORKSPACES_I18N_KEYS.securityPoliciesLabel) }), _jsx(Muted, { children: t(WORKSPACES_I18N_KEYS.securityPoliciesHint) }), POLICIES.map((policy) => (_jsx(Checkbox, { checked: policies.includes(policy.value), onChange: (event) => {
144
+ setPolicies((current) => event.target.checked
145
+ ? [...current, policy.value]
146
+ : current.filter((value) => value !== policy.value));
147
+ }, "data-testid": `workspace-policy-${policy.value}`, ...bind, children: t(policy.labelKey) }, policy.value)))] })) })] }), allowed && gate.requiresStepUp && (_jsx("div", { style: { marginTop: spacing["3"] }, children: _jsx(Muted, { testId: "workspace-security-stepup", children: t(WORKSPACES_I18N_KEYS.securityStepUpNotice) }) })), _jsx(ErrorAlert, { thrown: mutation.error, style: { marginTop: spacing["3"] }, testId: "workspace-security-error" }), _jsx("div", { style: { marginTop: spacing["4"] }, children: _jsx(GatedButton, { gate: saveGate, type: "primary", loading: mutation.isPending, onClick: () => {
148
+ mutation.mutate({
149
+ require_mfa: requireMfa,
150
+ provisioned_user_policies: policies,
151
+ });
152
+ }, testId: "workspace-security-save", "data-analytics": "none", "data-analytics-reason": "business action \u2014 host app wraps with its own tracked()", children: mutation.isPending
153
+ ? t(WORKSPACES_I18N_KEYS.securitySaving)
154
+ : t(WORKSPACES_I18N_KEYS.securitySave) }) }), _jsxs("div", { style: { marginTop: spacing["5"] }, children: [_jsx(Typography.Text, { strong: true, children: t(WORKSPACES_I18N_KEYS.mfaStatusTitle) }), enforcement === null ? (_jsx("div", { style: { marginTop: spacing["2"] }, children: _jsx(Muted, { testId: "workspace-mfa-off", children: t(storedRequireMfa
155
+ ? WORKSPACES_I18N_KEYS.mfaNoStatusYet
156
+ : WORKSPACES_I18N_KEYS.mfaOffNotice) }) })) : (_jsxs(Flex, { vertical: true, gap: spacing["2"], align: "flex-start", style: { marginTop: spacing["2"] }, "data-testid": "workspace-mfa-status", children: [_jsxs(Flex, { gap: spacing["2"], align: "center", wrap: true, children: [_jsx(Muted, { children: t(WORKSPACES_I18N_KEYS.mfaStateLabel) }), _jsx(StatusTag, { tone: enforcement.state === "enforced"
157
+ ? "success"
158
+ : enforcement.state === "failed"
159
+ ? "danger"
160
+ : "warning", testId: "workspace-mfa-state", children: mfaStateLabel(t, enforcement.state) })] }), _jsx(Muted, { children: tPlural(WORKSPACES_I18N_KEYS.mfaCheckedCount, {
161
+ count: enforcement.checked_members ?? 0,
162
+ }) }), _jsx(Muted, { children: tPlural(WORKSPACES_I18N_KEYS.mfaNoncompliantCount, {
163
+ count: enforcement.noncompliant_members ?? 0,
164
+ }) }), _jsx(Typography.Text, { type: (enforcement.unverified_members ?? 0) > 0 ? "warning" : "secondary", "data-testid": "workspace-mfa-unverified", children: tPlural(WORKSPACES_I18N_KEYS.mfaUnverifiedCount, {
165
+ count: enforcement.unverified_members ?? 0,
166
+ }) }), (enforcement.unverified_members ?? 0) > 0 && (_jsx(Muted, { children: t(WORKSPACES_I18N_KEYS.mfaUnverifiedHint) })), _jsx(Muted, { children: tPlural(WORKSPACES_I18N_KEYS.mfaAttemptsCount, {
167
+ count: enforcement.attempts ?? 0,
168
+ }) }), format.timestamp(enforcement.last_attempt_at) !== null && (_jsx(Muted, { children: t(WORKSPACES_I18N_KEYS.mfaLastAttempt, {
169
+ date: format.timestamp(enforcement.last_attempt_at),
170
+ }) })), format.timestamp(enforcement.completed_at) !== null && (_jsx(Muted, { children: t(WORKSPACES_I18N_KEYS.mfaCompletedAt, {
171
+ date: format.timestamp(enforcement.completed_at),
172
+ }) })), enforcement.last_error !== undefined && enforcement.last_error !== "" && (_jsx(Muted, { testId: "workspace-mfa-error", children: t(WORKSPACES_I18N_KEYS.mfaLastError, { error: enforcement.last_error }) }))] }))] })] }));
173
+ }
174
+ /** The four states the backend names, plus an honest line for a fifth this
175
+ * build has never heard of. */
176
+ function mfaStateLabel(t, state) {
177
+ switch (state) {
178
+ case "pending":
179
+ return t(WORKSPACES_I18N_KEYS.mfaStatePending);
180
+ case "enforcing":
181
+ return t(WORKSPACES_I18N_KEYS.mfaStateEnforcing);
182
+ case "enforced":
183
+ return t(WORKSPACES_I18N_KEYS.mfaStateEnforced);
184
+ case "failed":
185
+ return t(WORKSPACES_I18N_KEYS.mfaStateFailed);
186
+ default:
187
+ return t(WORKSPACES_I18N_KEYS.mfaStateOther, { state });
53
188
  }
54
- return (_jsxs("div", { "data-testid": "workspace-settings", style: { display: "grid", gap: 16 }, children: [_jsxs(Card, { children: [_jsx(Typography.Title, { level: 4, style: { marginTop: 0 }, children: t(WORKSPACES_I18N_KEYS.settingsTitle) }), _jsx(Typography.Text, { type: "secondary", children: t(WORKSPACES_I18N_KEYS.settingsSubtitle) }), _jsxs("div", { style: { display: "grid", gap: 12, maxWidth: 480, marginTop: 16 }, children: [_jsxs("div", { children: [_jsx(Typography.Text, { children: t(WORKSPACES_I18N_KEYS.fieldName) }), _jsx(Input, { value: name, onChange: (e) => setName(e.target.value), disabled: !isOwner }), !isOwner && (_jsx("div", { children: _jsx(Typography.Text, { type: "secondary", "data-testid": "workspace-name-blocked", children: t(WORKSPACES_I18N_KEYS.blockedNotOwner) }) }))] }), _jsxs("div", { children: [_jsx(Typography.Text, { children: t(WORKSPACES_I18N_KEYS.fieldSlug) }), _jsx("div", { children: _jsx(Typography.Text, { code: true, children: workspace.slug }) })] }), _jsxs("div", { children: [_jsx(Typography.Text, { children: t(WORKSPACES_I18N_KEYS.fieldType) }), _jsx("div", { children: _jsx(Badge, { status: "default", text: workspace.type }) })] })] }), _jsx(ErrorAlert, { error: errorDisplay(updateMutation.error), style: { marginTop: 12 } }), _jsx(Button, { type: "primary", style: { marginTop: 16 }, loading: updateMutation.isPending, disabled: saveGate.disabled, onClick: handleSave, "data-analytics": "none", "data-analytics-reason": "business action \u2014 host app wraps with its own tracked(); pairs carry no @stapel/analytics runtime dependency by architecture", children: updateMutation.isPending ? t(WORKSPACES_I18N_KEYS.saving) : t(WORKSPACES_I18N_KEYS.save) }), saveGate.reason !== undefined && (_jsx("div", { style: { marginTop: 8 }, children: _jsx(Typography.Text, { type: "secondary", "data-testid": "workspace-save-blocked", children: saveGate.reason }) }))] }), isOwner && (_jsxs(Card, { children: [_jsx(Typography.Title, { level: 5, type: "danger", style: { marginTop: 0 }, children: t(WORKSPACES_I18N_KEYS.dangerZoneTitle) }), _jsx(Popconfirm, { title: t(WORKSPACES_I18N_KEYS.deleteWorkspaceConfirm), onConfirm: handleDelete, okButtonProps: { loading: deleteMutation.isPending, danger: true }, children: _jsx(Button, { danger: true, children: t(WORKSPACES_I18N_KEYS.deleteWorkspace) }) })] }))] }));
189
+ }
190
+ /** Deletion — the one act on this screen nobody can take back. */
191
+ function DangerZone(props) {
192
+ const t = useT();
193
+ const mutation = useDeleteWorkspace();
194
+ const [confirming, setConfirming] = useState(false);
195
+ // THE SERVER'S ANSWER, not a rule re-derived from `my_role`. `can_delete`
196
+ // is additive on the wire, so a backend that predates it sends neither
197
+ // field; treating "absent" as "allowed" keeps such a deployment working
198
+ // exactly as it did, and the refusal it might answer is a translated 409
199
+ // rather than a promise this screen made.
200
+ const canDelete = props.workspace.can_delete ?? true;
201
+ const blockedReason = props.workspace.delete_blocked_reason;
202
+ const deleteGate = canDelete
203
+ ? actionAvailable()
204
+ : actionBlocked(blockedReason !== undefined && blockedReason !== ""
205
+ ? blockedReason
206
+ : WORKSPACES_I18N_KEYS.deleteBlockedFallback);
207
+ return (_jsxs(Card, { "data-testid": "workspace-danger-zone", children: [_jsx(Typography.Title, { level: 5, type: "danger", style: { marginTop: 0 }, children: t(WORKSPACES_I18N_KEYS.dangerZoneTitle) }), _jsx(ErrorAlert, { thrown: mutation.error, style: { marginBottom: spacing["3"] }, testId: "workspace-delete-error" }), _jsx(GatedButton, { gate: deleteGate, danger: true, onClick: () => setConfirming(true), testId: "workspace-delete", "data-analytics": "none", "data-analytics-reason": "opens the confirm; the delete itself is the tracked point", children: t(WORKSPACES_I18N_KEYS.deleteWorkspace) }), _jsx(SkinConfirm, { open: confirming, danger: true, title: t(WORKSPACES_I18N_KEYS.deleteWorkspaceConfirm), body: t(WORKSPACES_I18N_KEYS.deleteWorkspaceConfirmBody), confirmLabel: t(WORKSPACES_I18N_KEYS.deleteWorkspace), cancelLabel: t(WORKSPACES_I18N_KEYS.cancel), confirming: mutation.isPending, onConfirm: () => {
208
+ mutation.mutate(props.workspaceId, {
209
+ onSuccess: () => props.onDeleted?.(),
210
+ onSettled: () => setConfirming(false),
211
+ });
212
+ }, onCancel: () => setConfirming(false), "data-testid": "workspace-delete-confirm" })] }));
55
213
  }
56
214
  //# sourceMappingURL=WorkspaceSettings.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"WorkspaceSettings.js","sourceRoot":"","sources":["../../src/default/WorkspaceSettings.tsx"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"WorkspaceSettings.js","sourceRoot":"","sources":["../../src/default/WorkspaceSettings.tsx"],"names":[],"mappings":"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"}
@@ -0,0 +1,13 @@
1
+ import type { ReactElement } from "react";
2
+ import type { Workspace } from "../api/types.js";
3
+ export interface WorkspacesPageProps {
4
+ /**
5
+ * Open a workspace. The pair owns no router (there are several, and a
6
+ * library that picks one picks it for every host), so the door is the
7
+ * host's: omit it and no "Open" control is drawn, because a button that
8
+ * goes nowhere is worse than no button.
9
+ */
10
+ onOpen?(workspace: Workspace): void;
11
+ }
12
+ export declare function WorkspacesPage(props: WorkspacesPageProps): ReactElement;
13
+ //# sourceMappingURL=WorkspacesPage.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"WorkspacesPage.d.ts","sourceRoot":"","sources":["../../src/default/WorkspacesPage.tsx"],"names":[],"mappings":"AAsBA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,OAAO,CAAC;AA0B1C,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAKjD,MAAM,WAAW,mBAAmB;IAClC;;;;;OAKG;IACH,MAAM,CAAC,CAAC,SAAS,EAAE,SAAS,GAAG,IAAI,CAAC;CACrC;AAED,wBAAgB,cAAc,CAAC,KAAK,EAAE,mBAAmB,GAAG,YAAY,CAavE"}
@@ -0,0 +1,108 @@
1
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
+ /**
3
+ * `<WorkspacesPage/>` — the default skin for {@link WorkspaceList}: the
4
+ * roster of workspaces a person belongs to, the door into each one, the
5
+ * "open this one by default" choice, and the create control.
6
+ *
7
+ * §54 said every headless primitive gets an AntD default; this was the one
8
+ * missing, and it is the one every app needs on day one — the audit found
9
+ * `useCanCreateWorkspace` existing only to feed a create button nobody had
10
+ * drawn.
11
+ *
12
+ * Three answers come from the SERVER and are never re-derived here:
13
+ *
14
+ * - `can_create_workspace` — the instance's `WORKSPACE_CREATE_POLICY`, over
15
+ * the same helper the POST gate uses, so a drawn button always opens.
16
+ * - `preferred_workspace_id` — the person's explicit home, which the
17
+ * instance default documents itself as yielding to. Never `workspaces[0]`
18
+ * (that guess was tracker #239) and never `last_accessed_at`, which is
19
+ * telemetry.
20
+ * - `is_guest` — someone here on a link rather than a membership. An empty
21
+ * list means something different to them, and the screen says which.
22
+ */
23
+ import { useId, useState } from "react";
24
+ import { Button, Card, Flex, Input, Typography, theme as antdTheme } from "antd";
25
+ import { actionAvailable, actionBlocked, loadStateFromQuery, requireLoaded, useT, useTPlural, } from "@stapel/core";
26
+ import { EmptyState, ErrorAlert, GatedButton, LoadList, SkinDialog, SkinTheme, } from "@stapel/tokens-antd/skin";
27
+ import { spacing } from "@stapel/tokens";
28
+ import { WorkspaceList } from "../headless/WorkspaceList.js";
29
+ import { useWorkspaces } from "../model/queries.js";
30
+ import { useClearPreferredWorkspace, useSetPreferredWorkspace, } from "../model/mutations.js";
31
+ import { WORKSPACES_I18N_KEYS } from "../i18n/keys.js";
32
+ import { LoadFailure, Muted, StatusTag, SCREEN_STACK } from "./parts.js";
33
+ import { RoleLabel } from "./RoleSelectField.js";
34
+ export function WorkspacesPage(props) {
35
+ return (_jsx(SkinTheme, { surface: "base", "data-testid": "workspaces-page", children: _jsx(WorkspaceList, { children: (bag) => (_jsx(PageBody, { bag: bag, ...(props.onOpen !== undefined ? { onOpen: props.onOpen } : {}) })) }) }));
36
+ }
37
+ function PageBody(props) {
38
+ const t = useT();
39
+ const tPlural = useTPlural();
40
+ const { bag } = props;
41
+ const listQuery = useWorkspaces();
42
+ const [creating, setCreating] = useState(false);
43
+ const list = listQuery.data ?? null;
44
+ const failureId = useId();
45
+ // The create verdict is a property of the LIST response, so it is blocked
46
+ // while the list is loading — with core's own sentence — and by the policy
47
+ // when the list arrived and says no.
48
+ //
49
+ // A FAILED read is deliberately not routed through the gate. `requireLoaded`
50
+ // would hand the button its own copy of the outage ("We could not load what
51
+ // this needs…" plus `HTTP 503`) directly above the alert that states the
52
+ // same outage with the retry — the same bad news twice, in two wordings,
53
+ // with two different recoveries. The read has exactly one failure surface on
54
+ // this screen, and the button points at it.
55
+ const listState = loadStateFromQuery(listQuery);
56
+ const listFailed = listState.status === "failed";
57
+ const createGate = requireLoaded(listState, (loaded) => loaded.can_create_workspace === true
58
+ ? actionAvailable()
59
+ : actionBlocked(WORKSPACES_I18N_KEYS.listCreateBlockedPolicy));
60
+ const rows = bag.state.status === "ready" ? bag.state.data : [];
61
+ return (_jsxs("div", { style: SCREEN_STACK, children: [_jsxs(Card, { children: [_jsxs(Flex, { justify: "space-between", align: "flex-start", gap: spacing["4"], wrap: true, children: [_jsxs(Flex, { vertical: true, gap: spacing["1"], children: [_jsx(Typography.Title, { level: 4, style: { marginTop: 0, marginBottom: 0 }, children: t(WORKSPACES_I18N_KEYS.pageTitle) }), _jsx(Typography.Text, { type: "secondary", children: t(WORKSPACES_I18N_KEYS.pageSubtitle) }), bag.state.status === "ready" && (_jsx(Muted, { testId: "workspaces-count", children: tPlural(WORKSPACES_I18N_KEYS.listCount, { count: rows.length }) }))] }), listFailed ? (_jsx(Button, { type: "primary", disabled: true, "aria-describedby": failureId, "data-disabled-reason": "the roster read failed; the alert below says so once and carries the retry", "data-analytics": "none", "data-analytics-reason": "local-ui-open-create-dialog", "data-testid": "workspaces-create-open", children: t(WORKSPACES_I18N_KEYS.listCreate) })) : (_jsx(GatedButton, { gate: createGate, type: "primary", onClick: () => setCreating(true), testId: "workspaces-create-open", "data-analytics": "none", "data-analytics-reason": "local-ui-open-create-dialog", children: t(WORKSPACES_I18N_KEYS.listCreate) }))] }), list?.is_guest === true && (_jsx("div", { style: { marginTop: spacing["3"] }, children: _jsx(Muted, { testId: "workspaces-guest", children: t(WORKSPACES_I18N_KEYS.listGuestNotice) }) })), _jsx(ErrorAlert, { thrown: bag.createError, style: { marginTop: spacing["3"] }, testId: "workspaces-create-error" }), _jsx("div", { style: { marginTop: spacing["4"] }, children: _jsx(LoadList, { state: bag.state, testId: "workspaces-list", onRetry: bag.refetch, failed: (error) => (_jsx("div", { id: failureId, children: _jsx(LoadFailure, { error: error, onRetry: bag.refetch, testId: "workspaces-list-failed" }) })), empty: _jsx(EmptyState, { title: t(WORKSPACES_I18N_KEYS.listEmpty), testId: "workspaces-list-empty",
62
+ // The RESTRICTION is stated once, beside the switched-off
63
+ // control above; this line is the other half — what the person
64
+ // can actually do about it. Saying "this installation does not
65
+ // hand out workspaces" here as well was the same fact twice in
66
+ // two wordings on one 390px screen.
67
+ hint: createGate.available === true
68
+ ? t(WORKSPACES_I18N_KEYS.listEmptyHint)
69
+ : t(WORKSPACES_I18N_KEYS.listInstanceClosed), ...(createGate.available === true
70
+ ? {
71
+ action: (_jsx(Button, { type: "primary", onClick: () => setCreating(true), "data-analytics": "none", "data-analytics-reason": "local-ui-open-create-dialog", children: t(WORKSPACES_I18N_KEYS.listCreate) })),
72
+ }
73
+ : {}) }), children: (workspaces) => (_jsx("div", { role: "list", "data-testid": "workspaces-rows", children: workspaces.map((workspace) => (_jsx(WorkspaceRow, { workspace: workspace, isPreferred: list?.preferred_workspace_id === workspace.id, ...(props.onOpen !== undefined ? { onOpen: props.onOpen } : {}) }, workspace.id))) })) }) })] }), _jsx(CreateDialog, { open: creating, onClose: () => setCreating(false), isCreating: bag.isCreating, onCreate: (name) => {
74
+ bag.create({ name });
75
+ setCreating(false);
76
+ } })] }));
77
+ }
78
+ function WorkspaceRow(props) {
79
+ const t = useT();
80
+ const tPlural = useTPlural();
81
+ const { token } = antdTheme.useToken();
82
+ const setPreferred = useSetPreferredWorkspace();
83
+ const clearPreferred = useClearPreferredWorkspace();
84
+ const { workspace } = props;
85
+ const owner = workspace.owner_display_name?.trim();
86
+ return (_jsxs("div", { role: "listitem", "data-testid": `workspace-row-${workspace.id}`, style: {
87
+ display: "flex",
88
+ flexWrap: "wrap",
89
+ alignItems: "center",
90
+ justifyContent: "space-between",
91
+ gap: spacing["3"],
92
+ paddingTop: spacing["3"],
93
+ paddingBottom: spacing["3"],
94
+ borderBottom: `1px solid ${token.colorSplit}`,
95
+ }, children: [_jsxs(Flex, { vertical: true, gap: spacing["1"], style: { minWidth: 0 }, children: [_jsxs(Flex, { gap: spacing["2"], align: "center", wrap: true, children: [_jsx(Typography.Text, { strong: true, children: workspace.name }), props.isPreferred && (_jsx(StatusTag, { tone: "info", testId: `workspace-preferred-${workspace.id}`, children: t(WORKSPACES_I18N_KEYS.listPreferredTag) }))] }), owner !== undefined && owner !== "" && (_jsx(Muted, { children: t(WORKSPACES_I18N_KEYS.listOwnerLine, { owner }) })), _jsxs(Muted, { children: [tPlural(WORKSPACES_I18N_KEYS.listMemberCount, { count: workspace.member_count }), workspace.my_role !== null && (_jsxs(_Fragment, { children: [" · ", t(WORKSPACES_I18N_KEYS.listYourRole), ":", " ", _jsx(RoleLabel, { role: workspace.my_role })] }))] })] }), _jsxs(Flex, { gap: spacing["2"], align: "center", wrap: true, children: [props.isPreferred ? (_jsx(Button, { type: "link", size: "small", loading: clearPreferred.isPending, onClick: () => clearPreferred.mutate(), "data-analytics": "none", "data-analytics-reason": "business action \u2014 host app wraps with its own tracked()", "data-testid": `workspace-clear-home-${workspace.id}`, children: t(WORKSPACES_I18N_KEYS.listClearPreferred) })) : (_jsx(Button, { type: "link", size: "small", loading: setPreferred.isPending, onClick: () => setPreferred.mutate({ workspace_id: workspace.id }), "data-analytics": "none", "data-analytics-reason": "business action \u2014 host app wraps with its own tracked()", "data-testid": `workspace-set-home-${workspace.id}`, children: t(WORKSPACES_I18N_KEYS.listSetPreferred) })), props.onOpen !== undefined && (_jsx(Button, { onClick: () => props.onOpen?.(workspace), "data-analytics": "none", "data-analytics-reason": "navigation \u2014 the host owns the router", "data-testid": `workspace-open-${workspace.id}`, children: t(WORKSPACES_I18N_KEYS.listOpen) }))] })] }));
96
+ }
97
+ function CreateDialog(props) {
98
+ const t = useT();
99
+ const [name, setName] = useState("");
100
+ const gate = name.trim() === ""
101
+ ? actionBlocked(WORKSPACES_I18N_KEYS.listCreateBlockedNoName)
102
+ : actionAvailable();
103
+ return (_jsx(SkinDialog, { open: props.open, onClose: props.onClose, title: t(WORKSPACES_I18N_KEYS.listCreateDialogTitle), dismissLabel: t(WORKSPACES_I18N_KEYS.dialogClose), "data-testid": "workspaces-create-dialog", footer: _jsx(GatedButton, { gate: gate, type: "primary", loading: props.isCreating, onClick: () => {
104
+ props.onCreate(name.trim());
105
+ setName("");
106
+ }, testId: "workspaces-create-submit", "data-analytics": "none", "data-analytics-reason": "business action \u2014 host app wraps with its own tracked()", children: t(WORKSPACES_I18N_KEYS.listCreateSubmit) }), children: _jsxs(Flex, { vertical: true, gap: spacing["2"], children: [_jsx(Typography.Text, { children: t(WORKSPACES_I18N_KEYS.listCreateNameLabel) }), _jsx(Input, { value: name, onChange: (event) => setName(event.target.value), placeholder: t(WORKSPACES_I18N_KEYS.listCreateNamePlaceholder), "aria-label": t(WORKSPACES_I18N_KEYS.listCreateNameLabel), "data-testid": "workspaces-create-name" })] }) }));
107
+ }
108
+ //# sourceMappingURL=WorkspacesPage.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"WorkspacesPage.js","sourceRoot":"","sources":["../../src/default/WorkspacesPage.tsx"],"names":[],"mappings":"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"}