@stigmer/react 3.0.7 → 3.0.8-dev.20260612062921
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/access/ManageAccessButton.d.ts +47 -0
- package/access/ManageAccessButton.d.ts.map +1 -0
- package/access/ManageAccessButton.js +45 -0
- package/access/ManageAccessButton.js.map +1 -0
- package/access/ManageAccessDialog.d.ts +60 -0
- package/access/ManageAccessDialog.d.ts.map +1 -0
- package/access/ManageAccessDialog.js +83 -0
- package/access/ManageAccessDialog.js.map +1 -0
- package/access/index.d.ts +5 -0
- package/access/index.d.ts.map +1 -0
- package/access/index.js +7 -0
- package/access/index.js.map +1 -0
- package/access/types.d.ts +56 -0
- package/access/types.d.ts.map +1 -0
- package/access/types.js +2 -0
- package/access/types.js.map +1 -0
- package/access/useManageAccess.d.ts +60 -0
- package/access/useManageAccess.d.ts.map +1 -0
- package/access/useManageAccess.js +41 -0
- package/access/useManageAccess.js.map +1 -0
- package/agent/AgentDetailView.d.ts.map +1 -1
- package/agent/AgentDetailView.js +34 -4
- package/agent/AgentDetailView.js.map +1 -1
- package/agent-instance/AgentInstanceDetailPanel.d.ts.map +1 -1
- package/agent-instance/AgentInstanceDetailPanel.js +14 -4
- package/agent-instance/AgentInstanceDetailPanel.js.map +1 -1
- package/iam-policy/GrantAccessForm.d.ts +15 -5
- package/iam-policy/GrantAccessForm.d.ts.map +1 -1
- package/iam-policy/GrantAccessForm.js +15 -12
- package/iam-policy/GrantAccessForm.js.map +1 -1
- package/iam-policy/OrgMembersPanel.d.ts.map +1 -1
- package/iam-policy/OrgMembersPanel.js +2 -1
- package/iam-policy/OrgMembersPanel.js.map +1 -1
- package/iam-policy/PeopleWithAccess.d.ts +34 -0
- package/iam-policy/PeopleWithAccess.d.ts.map +1 -0
- package/iam-policy/PeopleWithAccess.js +55 -0
- package/iam-policy/PeopleWithAccess.js.map +1 -0
- package/iam-policy/PrincipalPicker.d.ts +48 -0
- package/iam-policy/PrincipalPicker.d.ts.map +1 -0
- package/iam-policy/PrincipalPicker.js +139 -0
- package/iam-policy/PrincipalPicker.js.map +1 -0
- package/iam-policy/ProviderBadge.d.ts +28 -0
- package/iam-policy/ProviderBadge.d.ts.map +1 -0
- package/iam-policy/ProviderBadge.js +31 -0
- package/iam-policy/ProviderBadge.js.map +1 -0
- package/iam-policy/SharePanel.d.ts +13 -5
- package/iam-policy/SharePanel.d.ts.map +1 -1
- package/iam-policy/SharePanel.js +9 -34
- package/iam-policy/SharePanel.js.map +1 -1
- package/iam-policy/index.d.ts +3 -0
- package/iam-policy/index.d.ts.map +1 -1
- package/iam-policy/index.js +3 -0
- package/iam-policy/index.js.map +1 -1
- package/index.d.ts +7 -5
- package/index.d.ts.map +1 -1
- package/index.js +6 -3
- package/index.js.map +1 -1
- package/mcp-server/McpServerDetailView.d.ts.map +1 -1
- package/mcp-server/McpServerDetailView.js +41 -12
- package/mcp-server/McpServerDetailView.js.map +1 -1
- package/organization/OrgProvider.d.ts +9 -0
- package/organization/OrgProvider.d.ts.map +1 -1
- package/organization/OrgProvider.js +12 -0
- package/organization/OrgProvider.js.map +1 -1
- package/organization/index.d.ts +1 -1
- package/organization/index.d.ts.map +1 -1
- package/organization/index.js +1 -1
- package/organization/index.js.map +1 -1
- package/package.json +12 -12
- package/skill/SkillDetailView.d.ts.map +1 -1
- package/skill/SkillDetailView.js +31 -3
- package/skill/SkillDetailView.js.map +1 -1
- package/src/access/ManageAccessButton.tsx +115 -0
- package/src/access/ManageAccessDialog.tsx +239 -0
- package/src/access/__tests__/ManageAccessButton.test.tsx +62 -0
- package/src/access/__tests__/ManageAccessDialog.test.tsx +146 -0
- package/src/access/index.ts +21 -0
- package/src/access/types.ts +58 -0
- package/src/access/useManageAccess.tsx +101 -0
- package/src/agent/AgentDetailView.tsx +50 -21
- package/src/agent-instance/AgentInstanceDetailPanel.tsx +24 -42
- package/src/iam-policy/GrantAccessForm.tsx +30 -35
- package/src/iam-policy/OrgMembersPanel.tsx +2 -0
- package/src/iam-policy/PeopleWithAccess.tsx +220 -0
- package/src/iam-policy/PrincipalPicker.tsx +347 -0
- package/src/iam-policy/ProviderBadge.tsx +53 -0
- package/src/iam-policy/SharePanel.tsx +20 -165
- package/src/iam-policy/index.ts +17 -0
- package/src/index.ts +30 -0
- package/src/mcp-server/McpServerDetailView.tsx +37 -9
- package/src/organization/OrgProvider.tsx +13 -0
- package/src/organization/index.ts +1 -1
- package/src/skill/SkillDetailView.tsx +34 -9
- package/src/workflow/WorkflowDetailView.tsx +49 -22
- package/src/workflow/WorkflowExecutionHeader.tsx +12 -1
- package/src/workflow/WorkflowExecutionViewer.tsx +8 -1
- package/src/workflow/index.ts +4 -0
- package/src/workflow/instance/RunVisibilityControl.tsx +116 -0
- package/src/workflow/instance/WorkflowInstanceDetailPanel.tsx +55 -42
- package/src/workflow/instance/index.ts +5 -0
- package/src/workflow/instance/useUpdateWorkflowInstanceExecutionVisibility.ts +74 -0
- package/styles.css +1 -1
- package/workflow/WorkflowDetailView.d.ts.map +1 -1
- package/workflow/WorkflowDetailView.js +31 -3
- package/workflow/WorkflowDetailView.js.map +1 -1
- package/workflow/WorkflowExecutionHeader.d.ts +7 -0
- package/workflow/WorkflowExecutionHeader.d.ts.map +1 -1
- package/workflow/WorkflowExecutionHeader.js +2 -2
- package/workflow/WorkflowExecutionHeader.js.map +1 -1
- package/workflow/WorkflowExecutionViewer.d.ts +6 -1
- package/workflow/WorkflowExecutionViewer.d.ts.map +1 -1
- package/workflow/WorkflowExecutionViewer.js +2 -2
- package/workflow/WorkflowExecutionViewer.js.map +1 -1
- package/workflow/index.d.ts +1 -1
- package/workflow/index.d.ts.map +1 -1
- package/workflow/index.js +1 -1
- package/workflow/index.js.map +1 -1
- package/workflow/instance/RunVisibilityControl.d.ts +25 -0
- package/workflow/instance/RunVisibilityControl.d.ts.map +1 -0
- package/workflow/instance/RunVisibilityControl.js +56 -0
- package/workflow/instance/RunVisibilityControl.js.map +1 -0
- package/workflow/instance/WorkflowInstanceDetailPanel.d.ts.map +1 -1
- package/workflow/instance/WorkflowInstanceDetailPanel.js +30 -4
- package/workflow/instance/WorkflowInstanceDetailPanel.js.map +1 -1
- package/workflow/instance/index.d.ts +2 -0
- package/workflow/instance/index.d.ts.map +1 -1
- package/workflow/instance/index.js +2 -0
- package/workflow/instance/index.js.map +1 -1
- package/workflow/instance/useUpdateWorkflowInstanceExecutionVisibility.d.ts +30 -0
- package/workflow/instance/useUpdateWorkflowInstanceExecutionVisibility.d.ts.map +1 -0
- package/workflow/instance/useUpdateWorkflowInstanceExecutionVisibility.js +39 -0
- package/workflow/instance/useUpdateWorkflowInstanceExecutionVisibility.js.map +1 -0
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import type { AccessResource, AccessVisibility, AccessExtraSection } from "./types";
|
|
2
|
+
/** Props for {@link ManageAccessButton}. */
|
|
3
|
+
export interface ManageAccessButtonProps {
|
|
4
|
+
/** The resource whose access is managed. */
|
|
5
|
+
readonly resource: AccessResource;
|
|
6
|
+
/** General access (visibility) axis; omit for resources without visibility. */
|
|
7
|
+
readonly visibility?: AccessVisibility;
|
|
8
|
+
/** Optional resource-specific section (e.g. run observability). */
|
|
9
|
+
readonly extraSection?: AccessExtraSection;
|
|
10
|
+
/** Button label. @default "Manage access" */
|
|
11
|
+
readonly label?: string;
|
|
12
|
+
/** Additional CSS classes for the trigger button. */
|
|
13
|
+
readonly className?: string;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* The single drop-in, visible trigger for the unified Manage access dialog —
|
|
17
|
+
* used by surfaces that render a button in a header or panel (session and
|
|
18
|
+
* workflow-execution viewers, instance panels) rather than a kebab menu (those
|
|
19
|
+
* use {@link useManageAccess}).
|
|
20
|
+
*
|
|
21
|
+
* Self-gates on `can_view_access`: the button renders only for users who may
|
|
22
|
+
* see the access list, and the dialog's sections gate editing further. Because
|
|
23
|
+
* it lives in the SDK, web and desktop hosts stop re-implementing their own
|
|
24
|
+
* share buttons — one component, every host.
|
|
25
|
+
*
|
|
26
|
+
* All visual properties flow through `--stgm-*` design tokens.
|
|
27
|
+
*
|
|
28
|
+
* @example
|
|
29
|
+
* ```tsx
|
|
30
|
+
* // A session has no visibility axis, so the dialog shows only People.
|
|
31
|
+
* <SessionViewer
|
|
32
|
+
* sessionId={id}
|
|
33
|
+
* headerActions={
|
|
34
|
+
* <ManageAccessButton
|
|
35
|
+
* resource={{
|
|
36
|
+
* kind: ApiResourceKind.session,
|
|
37
|
+
* kindString: "session",
|
|
38
|
+
* id,
|
|
39
|
+
* org: orgId,
|
|
40
|
+
* }}
|
|
41
|
+
* />
|
|
42
|
+
* }
|
|
43
|
+
* />
|
|
44
|
+
* ```
|
|
45
|
+
*/
|
|
46
|
+
export declare function ManageAccessButton({ resource, visibility, extraSection, label, className, }: ManageAccessButtonProps): import("react/jsx-runtime").JSX.Element;
|
|
47
|
+
//# sourceMappingURL=ManageAccessButton.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ManageAccessButton.d.ts","sourceRoot":"","sources":["../../src/access/ManageAccessButton.tsx"],"names":[],"mappings":"AAMA,OAAO,KAAK,EACV,cAAc,EACd,gBAAgB,EAChB,kBAAkB,EACnB,MAAM,SAAS,CAAC;AAEjB,4CAA4C;AAC5C,MAAM,WAAW,uBAAuB;IACtC,4CAA4C;IAC5C,QAAQ,CAAC,QAAQ,EAAE,cAAc,CAAC;IAClC,+EAA+E;IAC/E,QAAQ,CAAC,UAAU,CAAC,EAAE,gBAAgB,CAAC;IACvC,mEAAmE;IACnE,QAAQ,CAAC,YAAY,CAAC,EAAE,kBAAkB,CAAC;IAC3C,6CAA6C;IAC7C,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IACxB,qDAAqD;IACrD,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC;CAC7B;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AACH,wBAAgB,kBAAkB,CAAC,EACjC,QAAQ,EACR,UAAU,EACV,YAAY,EACZ,KAAuB,EACvB,SAAS,GACV,EAAE,uBAAuB,2CA8BzB"}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
+
import { useState } from "react";
|
|
4
|
+
import { cn } from "@stigmer/theme";
|
|
5
|
+
import { PermissionGate } from "../iam-policy/PermissionGate";
|
|
6
|
+
import { ManageAccessDialog } from "./ManageAccessDialog";
|
|
7
|
+
/**
|
|
8
|
+
* The single drop-in, visible trigger for the unified Manage access dialog —
|
|
9
|
+
* used by surfaces that render a button in a header or panel (session and
|
|
10
|
+
* workflow-execution viewers, instance panels) rather than a kebab menu (those
|
|
11
|
+
* use {@link useManageAccess}).
|
|
12
|
+
*
|
|
13
|
+
* Self-gates on `can_view_access`: the button renders only for users who may
|
|
14
|
+
* see the access list, and the dialog's sections gate editing further. Because
|
|
15
|
+
* it lives in the SDK, web and desktop hosts stop re-implementing their own
|
|
16
|
+
* share buttons — one component, every host.
|
|
17
|
+
*
|
|
18
|
+
* All visual properties flow through `--stgm-*` design tokens.
|
|
19
|
+
*
|
|
20
|
+
* @example
|
|
21
|
+
* ```tsx
|
|
22
|
+
* // A session has no visibility axis, so the dialog shows only People.
|
|
23
|
+
* <SessionViewer
|
|
24
|
+
* sessionId={id}
|
|
25
|
+
* headerActions={
|
|
26
|
+
* <ManageAccessButton
|
|
27
|
+
* resource={{
|
|
28
|
+
* kind: ApiResourceKind.session,
|
|
29
|
+
* kindString: "session",
|
|
30
|
+
* id,
|
|
31
|
+
* org: orgId,
|
|
32
|
+
* }}
|
|
33
|
+
* />
|
|
34
|
+
* }
|
|
35
|
+
* />
|
|
36
|
+
* ```
|
|
37
|
+
*/
|
|
38
|
+
export function ManageAccessButton({ resource, visibility, extraSection, label = "Manage access", className, }) {
|
|
39
|
+
const [open, setOpen] = useState(false);
|
|
40
|
+
return (_jsxs(PermissionGate, { resource: { kind: resource.kindString, id: resource.id }, relation: "can_view_access", children: [_jsxs("button", { type: "button", onClick: () => setOpen(true), className: cn("inline-flex items-center gap-1.5 rounded-md px-2.5 py-1 text-xs font-medium", "border border-border text-foreground hover:bg-accent-hover", "focus:outline-none focus:ring-2 focus:ring-ring", className), children: [_jsx(ShareIcon, {}), label] }), _jsx(ManageAccessDialog, { open: open, onOpenChange: setOpen, resource: resource, visibility: visibility, extraSection: extraSection })] }));
|
|
41
|
+
}
|
|
42
|
+
function ShareIcon() {
|
|
43
|
+
return (_jsxs("svg", { width: "13", height: "13", viewBox: "0 0 16 16", fill: "none", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round", strokeLinejoin: "round", "aria-hidden": "true", children: [_jsx("circle", { cx: "12", cy: "3.5", r: "1.75" }), _jsx("circle", { cx: "4", cy: "8", r: "1.75" }), _jsx("circle", { cx: "12", cy: "12.5", r: "1.75" }), _jsx("path", { d: "M5.5 7.1l5-2.7M5.5 8.9l5 2.7" })] }));
|
|
44
|
+
}
|
|
45
|
+
//# sourceMappingURL=ManageAccessButton.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ManageAccessButton.js","sourceRoot":"","sources":["../../src/access/ManageAccessButton.tsx"],"names":[],"mappings":"AAAA,YAAY,CAAC;;AAEb,OAAO,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AACjC,OAAO,EAAE,EAAE,EAAE,MAAM,gBAAgB,CAAC;AACpC,OAAO,EAAE,cAAc,EAAE,MAAM,8BAA8B,CAAC;AAC9D,OAAO,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;AAqB1D;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AACH,MAAM,UAAU,kBAAkB,CAAC,EACjC,QAAQ,EACR,UAAU,EACV,YAAY,EACZ,KAAK,GAAG,eAAe,EACvB,SAAS,GACe;IACxB,MAAM,CAAC,IAAI,EAAE,OAAO,CAAC,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC;IAExC,OAAO,CACL,MAAC,cAAc,IACb,QAAQ,EAAE,EAAE,IAAI,EAAE,QAAQ,CAAC,UAAU,EAAE,EAAE,EAAE,QAAQ,CAAC,EAAE,EAAE,EACxD,QAAQ,EAAC,iBAAiB,aAE1B,kBACE,IAAI,EAAC,QAAQ,EACb,OAAO,EAAE,GAAG,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,EAC5B,SAAS,EAAE,EAAE,CACX,6EAA6E,EAC7E,4DAA4D,EAC5D,iDAAiD,EACjD,SAAS,CACV,aAED,KAAC,SAAS,KAAG,EACZ,KAAK,IACC,EACT,KAAC,kBAAkB,IACjB,IAAI,EAAE,IAAI,EACV,YAAY,EAAE,OAAO,EACrB,QAAQ,EAAE,QAAQ,EAClB,UAAU,EAAE,UAAU,EACtB,YAAY,EAAE,YAAY,GAC1B,IACa,CAClB,CAAC;AACJ,CAAC;AAED,SAAS,SAAS;IAChB,OAAO,CACL,eACE,KAAK,EAAC,IAAI,EACV,MAAM,EAAC,IAAI,EACX,OAAO,EAAC,WAAW,EACnB,IAAI,EAAC,MAAM,EACX,MAAM,EAAC,cAAc,EACrB,WAAW,EAAC,KAAK,EACjB,aAAa,EAAC,OAAO,EACrB,cAAc,EAAC,OAAO,iBACV,MAAM,aAElB,iBAAQ,EAAE,EAAC,IAAI,EAAC,EAAE,EAAC,KAAK,EAAC,CAAC,EAAC,MAAM,GAAG,EACpC,iBAAQ,EAAE,EAAC,GAAG,EAAC,EAAE,EAAC,GAAG,EAAC,CAAC,EAAC,MAAM,GAAG,EACjC,iBAAQ,EAAE,EAAC,IAAI,EAAC,EAAE,EAAC,MAAM,EAAC,CAAC,EAAC,MAAM,GAAG,EACrC,eAAM,CAAC,EAAC,8BAA8B,GAAG,IACrC,CACP,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import type { AccessResource, AccessVisibility, AccessExtraSection } from "./types";
|
|
2
|
+
/** Props for {@link ManageAccessDialog}. */
|
|
3
|
+
export interface ManageAccessDialogProps {
|
|
4
|
+
/** Whether the dialog is open. */
|
|
5
|
+
readonly open: boolean;
|
|
6
|
+
/** Called when the dialog should open or close. */
|
|
7
|
+
readonly onOpenChange: (open: boolean) => void;
|
|
8
|
+
/** The resource whose access is managed. */
|
|
9
|
+
readonly resource: AccessResource;
|
|
10
|
+
/**
|
|
11
|
+
* General access (visibility) axis. Omit for resources without visibility
|
|
12
|
+
* (e.g. sessions, workflow executions).
|
|
13
|
+
*/
|
|
14
|
+
readonly visibility?: AccessVisibility;
|
|
15
|
+
/**
|
|
16
|
+
* An optional resource-specific section appended below People (e.g.
|
|
17
|
+
* workflow-instance run observability).
|
|
18
|
+
*/
|
|
19
|
+
readonly extraSection?: AccessExtraSection;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* The one canonical "Manage access" dialog, mounted identically across every
|
|
23
|
+
* resource with a detail surface. Composes the platform's two access axes into
|
|
24
|
+
* a single Drive/GitHub-style modal: *General access* (visibility) over
|
|
25
|
+
* *People with access* (explicit grants), plus an optional resource-specific
|
|
26
|
+
* section.
|
|
27
|
+
*
|
|
28
|
+
* Each section renders only when it applies:
|
|
29
|
+
* - **General access** — only when {@link ManageAccessDialogProps.visibility}
|
|
30
|
+
* is provided. Delegates to {@link ResourceVisibilityControl}, which owns
|
|
31
|
+
* level selection and the `can_edit` gate.
|
|
32
|
+
* - **People with access** — only when the resource kind has grantable roles
|
|
33
|
+
* (`hasGrantableRoles`, proto-generated single source of truth). Delegates
|
|
34
|
+
* to {@link PeopleWithAccess}, which gates grant/revoke on `can_grant_access`.
|
|
35
|
+
* - **Extra section** — only when provided.
|
|
36
|
+
*
|
|
37
|
+
* The body mounts lazily (only while `open`) so its access-list fetch never
|
|
38
|
+
* fires on a closed dialog. Built on the native `<dialog>` element for focus
|
|
39
|
+
* trapping and escape handling, matching the SDK's modal convention. All
|
|
40
|
+
* visual properties flow through `--stgm-*` design tokens.
|
|
41
|
+
*
|
|
42
|
+
* Most hosts mount it indirectly via {@link ManageAccessButton} (a visible
|
|
43
|
+
* trigger) or {@link useManageAccess} (a kebab-menu action). Render it directly
|
|
44
|
+
* only when you own the open-state.
|
|
45
|
+
*
|
|
46
|
+
* @example
|
|
47
|
+
* ```tsx
|
|
48
|
+
* const [open, setOpen] = useState(false);
|
|
49
|
+
*
|
|
50
|
+
* // A blueprint has both axes: General access (visibility) over People.
|
|
51
|
+
* <ManageAccessDialog
|
|
52
|
+
* open={open}
|
|
53
|
+
* onOpenChange={setOpen}
|
|
54
|
+
* resource={{ kind: ApiResourceKind.agent, kindString: "agent", id, org, name }}
|
|
55
|
+
* visibility={{ kind: "agent", current: visibility, org, onChanged: refetch }}
|
|
56
|
+
* />
|
|
57
|
+
* ```
|
|
58
|
+
*/
|
|
59
|
+
export declare function ManageAccessDialog({ open, onOpenChange, resource, visibility, extraSection, }: ManageAccessDialogProps): import("react/jsx-runtime").JSX.Element;
|
|
60
|
+
//# sourceMappingURL=ManageAccessDialog.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ManageAccessDialog.d.ts","sourceRoot":"","sources":["../../src/access/ManageAccessDialog.tsx"],"names":[],"mappings":"AAOA,OAAO,KAAK,EACV,cAAc,EACd,gBAAgB,EAChB,kBAAkB,EACnB,MAAM,SAAS,CAAC;AAEjB,4CAA4C;AAC5C,MAAM,WAAW,uBAAuB;IACtC,kCAAkC;IAClC,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC;IACvB,mDAAmD;IACnD,QAAQ,CAAC,YAAY,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,IAAI,CAAC;IAC/C,4CAA4C;IAC5C,QAAQ,CAAC,QAAQ,EAAE,cAAc,CAAC;IAClC;;;OAGG;IACH,QAAQ,CAAC,UAAU,CAAC,EAAE,gBAAgB,CAAC;IACvC;;;OAGG;IACH,QAAQ,CAAC,YAAY,CAAC,EAAE,kBAAkB,CAAC;CAC5C;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAqCG;AACH,wBAAgB,kBAAkB,CAAC,EACjC,IAAI,EACJ,YAAY,EACZ,QAAQ,EACR,UAAU,EACV,YAAY,GACb,EAAE,uBAAuB,2CA+HzB"}
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
+
import { useCallback, useRef } from "react";
|
|
4
|
+
import { cn } from "@stigmer/theme";
|
|
5
|
+
import { hasGrantableRoles } from "@stigmer/sdk";
|
|
6
|
+
import { PeopleWithAccess } from "../iam-policy/PeopleWithAccess";
|
|
7
|
+
import { ResourceVisibilityControl } from "../library/ResourceVisibilityControl";
|
|
8
|
+
/**
|
|
9
|
+
* The one canonical "Manage access" dialog, mounted identically across every
|
|
10
|
+
* resource with a detail surface. Composes the platform's two access axes into
|
|
11
|
+
* a single Drive/GitHub-style modal: *General access* (visibility) over
|
|
12
|
+
* *People with access* (explicit grants), plus an optional resource-specific
|
|
13
|
+
* section.
|
|
14
|
+
*
|
|
15
|
+
* Each section renders only when it applies:
|
|
16
|
+
* - **General access** — only when {@link ManageAccessDialogProps.visibility}
|
|
17
|
+
* is provided. Delegates to {@link ResourceVisibilityControl}, which owns
|
|
18
|
+
* level selection and the `can_edit` gate.
|
|
19
|
+
* - **People with access** — only when the resource kind has grantable roles
|
|
20
|
+
* (`hasGrantableRoles`, proto-generated single source of truth). Delegates
|
|
21
|
+
* to {@link PeopleWithAccess}, which gates grant/revoke on `can_grant_access`.
|
|
22
|
+
* - **Extra section** — only when provided.
|
|
23
|
+
*
|
|
24
|
+
* The body mounts lazily (only while `open`) so its access-list fetch never
|
|
25
|
+
* fires on a closed dialog. Built on the native `<dialog>` element for focus
|
|
26
|
+
* trapping and escape handling, matching the SDK's modal convention. All
|
|
27
|
+
* visual properties flow through `--stgm-*` design tokens.
|
|
28
|
+
*
|
|
29
|
+
* Most hosts mount it indirectly via {@link ManageAccessButton} (a visible
|
|
30
|
+
* trigger) or {@link useManageAccess} (a kebab-menu action). Render it directly
|
|
31
|
+
* only when you own the open-state.
|
|
32
|
+
*
|
|
33
|
+
* @example
|
|
34
|
+
* ```tsx
|
|
35
|
+
* const [open, setOpen] = useState(false);
|
|
36
|
+
*
|
|
37
|
+
* // A blueprint has both axes: General access (visibility) over People.
|
|
38
|
+
* <ManageAccessDialog
|
|
39
|
+
* open={open}
|
|
40
|
+
* onOpenChange={setOpen}
|
|
41
|
+
* resource={{ kind: ApiResourceKind.agent, kindString: "agent", id, org, name }}
|
|
42
|
+
* visibility={{ kind: "agent", current: visibility, org, onChanged: refetch }}
|
|
43
|
+
* />
|
|
44
|
+
* ```
|
|
45
|
+
*/
|
|
46
|
+
export function ManageAccessDialog({ open, onOpenChange, resource, visibility, extraSection, }) {
|
|
47
|
+
const dialogRef = useRef(null);
|
|
48
|
+
const handleClose = useCallback(() => {
|
|
49
|
+
dialogRef.current?.close();
|
|
50
|
+
onOpenChange(false);
|
|
51
|
+
}, [onOpenChange]);
|
|
52
|
+
// Sync native dialog open state (matches the SDK dialog convention).
|
|
53
|
+
const prevOpenRef = useRef(false);
|
|
54
|
+
if (open !== prevOpenRef.current) {
|
|
55
|
+
prevOpenRef.current = open;
|
|
56
|
+
if (open) {
|
|
57
|
+
requestAnimationFrame(() => {
|
|
58
|
+
if (dialogRef.current && !dialogRef.current.open) {
|
|
59
|
+
dialogRef.current.showModal();
|
|
60
|
+
}
|
|
61
|
+
});
|
|
62
|
+
}
|
|
63
|
+
else if (dialogRef.current?.open) {
|
|
64
|
+
dialogRef.current.close();
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
const showPeople = hasGrantableRoles(resource.kind);
|
|
68
|
+
return (_jsx("dialog", { ref: dialogRef, onClose: handleClose, className: cn("fixed inset-0 m-auto w-full max-w-md rounded-xl border border-border bg-popover p-0 shadow-xl", "backdrop:bg-black/50"), "aria-labelledby": "manage-access-title", children: open && (_jsxs("div", { className: "flex flex-col", children: [_jsxs("div", { className: "flex items-start justify-between border-b border-border px-6 py-4", children: [_jsxs("div", { className: "min-w-0", children: [_jsx("h2", { id: "manage-access-title", className: "text-base font-semibold text-foreground", children: "Manage access" }), resource.name && (_jsx("p", { className: "mt-0.5 truncate text-xs text-muted-foreground", children: resource.name }))] }), _jsx("button", { type: "button", onClick: handleClose, "aria-label": "Close", className: cn("rounded-md p-1 text-muted-foreground", "hover:text-foreground hover:bg-accent-hover", "focus:outline-none focus:ring-2 focus:ring-ring"), children: _jsx(CloseIcon, {}) })] }), _jsxs("div", { className: "flex flex-col divide-y divide-border", children: [visibility && (_jsx(AccessSection, { title: "General access", description: "Who can find and open this resource.", children: _jsx(ResourceVisibilityControl, { kind: visibility.kind, resourceId: resource.id, visibility: visibility.current, org: visibility.org, onChanged: visibility.onChanged }) })), showPeople && (_jsx(AccessSection, { title: "People with access", children: _jsx(PeopleWithAccess, { resource: {
|
|
69
|
+
kind: resource.kindString,
|
|
70
|
+
id: resource.id,
|
|
71
|
+
resourceKind: resource.kind,
|
|
72
|
+
}, resourceKindString: resource.kindString, resourceKind: resource.kind, orgId: resource.org }) })), extraSection && (_jsx(AccessSection, { title: extraSection.title, description: extraSection.description, children: extraSection.content }))] }), _jsx("div", { className: "flex items-center justify-end border-t border-border px-6 py-3", children: _jsx("button", { type: "button", onClick: handleClose, className: cn("rounded-md px-3 py-1.5 text-sm font-medium", "bg-primary text-primary-foreground hover:bg-primary-hover", "focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2"), children: "Done" }) })] })) }));
|
|
73
|
+
}
|
|
74
|
+
// ---------------------------------------------------------------------------
|
|
75
|
+
// Internal section chrome
|
|
76
|
+
// ---------------------------------------------------------------------------
|
|
77
|
+
function AccessSection({ title, description, children, }) {
|
|
78
|
+
return (_jsxs("section", { className: "px-6 py-4", children: [_jsx("h3", { className: "text-xs font-medium text-muted-foreground", children: title }), description && (_jsx("p", { className: "mt-0.5 text-[0.65rem] text-muted-foreground", children: description })), _jsx("div", { className: "mt-2.5", children: children })] }));
|
|
79
|
+
}
|
|
80
|
+
function CloseIcon() {
|
|
81
|
+
return (_jsx("svg", { width: "16", height: "16", viewBox: "0 0 16 16", fill: "none", "aria-hidden": "true", children: _jsx("path", { d: "M4 4l8 8M12 4l-8 8", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round" }) }));
|
|
82
|
+
}
|
|
83
|
+
//# sourceMappingURL=ManageAccessDialog.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ManageAccessDialog.js","sourceRoot":"","sources":["../../src/access/ManageAccessDialog.tsx"],"names":[],"mappings":"AAAA,YAAY,CAAC;;AAEb,OAAO,EAAE,WAAW,EAAE,MAAM,EAAkB,MAAM,OAAO,CAAC;AAC5D,OAAO,EAAE,EAAE,EAAE,MAAM,gBAAgB,CAAC;AACpC,OAAO,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAC;AACjD,OAAO,EAAE,gBAAgB,EAAE,MAAM,gCAAgC,CAAC;AAClE,OAAO,EAAE,yBAAyB,EAAE,MAAM,sCAAsC,CAAC;AA2BjF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAqCG;AACH,MAAM,UAAU,kBAAkB,CAAC,EACjC,IAAI,EACJ,YAAY,EACZ,QAAQ,EACR,UAAU,EACV,YAAY,GACY;IACxB,MAAM,SAAS,GAAG,MAAM,CAAoB,IAAI,CAAC,CAAC;IAElD,MAAM,WAAW,GAAG,WAAW,CAAC,GAAG,EAAE;QACnC,SAAS,CAAC,OAAO,EAAE,KAAK,EAAE,CAAC;QAC3B,YAAY,CAAC,KAAK,CAAC,CAAC;IACtB,CAAC,EAAE,CAAC,YAAY,CAAC,CAAC,CAAC;IAEnB,qEAAqE;IACrE,MAAM,WAAW,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC;IAClC,IAAI,IAAI,KAAK,WAAW,CAAC,OAAO,EAAE,CAAC;QACjC,WAAW,CAAC,OAAO,GAAG,IAAI,CAAC;QAC3B,IAAI,IAAI,EAAE,CAAC;YACT,qBAAqB,CAAC,GAAG,EAAE;gBACzB,IAAI,SAAS,CAAC,OAAO,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC;oBACjD,SAAS,CAAC,OAAO,CAAC,SAAS,EAAE,CAAC;gBAChC,CAAC;YACH,CAAC,CAAC,CAAC;QACL,CAAC;aAAM,IAAI,SAAS,CAAC,OAAO,EAAE,IAAI,EAAE,CAAC;YACnC,SAAS,CAAC,OAAO,CAAC,KAAK,EAAE,CAAC;QAC5B,CAAC;IACH,CAAC;IAED,MAAM,UAAU,GAAG,iBAAiB,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;IAEpD,OAAO,CACL,iBACE,GAAG,EAAE,SAAS,EACd,OAAO,EAAE,WAAW,EACpB,SAAS,EAAE,EAAE,CACX,+FAA+F,EAC/F,sBAAsB,CACvB,qBACe,qBAAqB,YAGpC,IAAI,IAAI,CACP,eAAK,SAAS,EAAC,eAAe,aAE5B,eAAK,SAAS,EAAC,mEAAmE,aAChF,eAAK,SAAS,EAAC,SAAS,aACtB,aACE,EAAE,EAAC,qBAAqB,EACxB,SAAS,EAAC,yCAAyC,8BAGhD,EACJ,QAAQ,CAAC,IAAI,IAAI,CAChB,YAAG,SAAS,EAAC,+CAA+C,YACzD,QAAQ,CAAC,IAAI,GACZ,CACL,IACG,EACN,iBACE,IAAI,EAAC,QAAQ,EACb,OAAO,EAAE,WAAW,gBACT,OAAO,EAClB,SAAS,EAAE,EAAE,CACX,sCAAsC,EACtC,6CAA6C,EAC7C,iDAAiD,CAClD,YAED,KAAC,SAAS,KAAG,GACN,IACL,EAGN,eAAK,SAAS,EAAC,sCAAsC,aAClD,UAAU,IAAI,CACb,KAAC,aAAa,IACZ,KAAK,EAAC,gBAAgB,EACtB,WAAW,EAAC,sCAAsC,YAElD,KAAC,yBAAyB,IACxB,IAAI,EAAE,UAAU,CAAC,IAAI,EACrB,UAAU,EAAE,QAAQ,CAAC,EAAE,EACvB,UAAU,EAAE,UAAU,CAAC,OAAO,EAC9B,GAAG,EAAE,UAAU,CAAC,GAAG,EACnB,SAAS,EAAE,UAAU,CAAC,SAAS,GAC/B,GACY,CACjB,EAEA,UAAU,IAAI,CACb,KAAC,aAAa,IAAC,KAAK,EAAC,oBAAoB,YACvC,KAAC,gBAAgB,IACf,QAAQ,EAAE;oCACR,IAAI,EAAE,QAAQ,CAAC,UAAU;oCACzB,EAAE,EAAE,QAAQ,CAAC,EAAE;oCACf,YAAY,EAAE,QAAQ,CAAC,IAAI;iCAC5B,EACD,kBAAkB,EAAE,QAAQ,CAAC,UAAU,EACvC,YAAY,EAAE,QAAQ,CAAC,IAAI,EAC3B,KAAK,EAAE,QAAQ,CAAC,GAAG,GACnB,GACY,CACjB,EAEA,YAAY,IAAI,CACf,KAAC,aAAa,IACZ,KAAK,EAAE,YAAY,CAAC,KAAK,EACzB,WAAW,EAAE,YAAY,CAAC,WAAW,YAEpC,YAAY,CAAC,OAAO,GACP,CACjB,IACG,EAGN,cAAK,SAAS,EAAC,gEAAgE,YAC7E,iBACE,IAAI,EAAC,QAAQ,EACb,OAAO,EAAE,WAAW,EACpB,SAAS,EAAE,EAAE,CACX,4CAA4C,EAC5C,2DAA2D,EAC3D,qEAAqE,CACtE,qBAGM,GACL,IACF,CACP,GACM,CACV,CAAC;AACJ,CAAC;AAED,8EAA8E;AAC9E,0BAA0B;AAC1B,8EAA8E;AAE9E,SAAS,aAAa,CAAC,EACrB,KAAK,EACL,WAAW,EACX,QAAQ,GAKT;IACC,OAAO,CACL,mBAAS,SAAS,EAAC,WAAW,aAC5B,aAAI,SAAS,EAAC,2CAA2C,YAAE,KAAK,GAAM,EACrE,WAAW,IAAI,CACd,YAAG,SAAS,EAAC,6CAA6C,YACvD,WAAW,GACV,CACL,EACD,cAAK,SAAS,EAAC,QAAQ,YAAE,QAAQ,GAAO,IAChC,CACX,CAAC;AACJ,CAAC;AAED,SAAS,SAAS;IAChB,OAAO,CACL,cAAK,KAAK,EAAC,IAAI,EAAC,MAAM,EAAC,IAAI,EAAC,OAAO,EAAC,WAAW,EAAC,IAAI,EAAC,MAAM,iBAAa,MAAM,YAC5E,eAAM,CAAC,EAAC,oBAAoB,EAAC,MAAM,EAAC,cAAc,EAAC,WAAW,EAAC,KAAK,EAAC,aAAa,EAAC,OAAO,GAAG,GACzF,CACP,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export { ManageAccessDialog, type ManageAccessDialogProps, } from "./ManageAccessDialog";
|
|
2
|
+
export { ManageAccessButton, type ManageAccessButtonProps, } from "./ManageAccessButton";
|
|
3
|
+
export { useManageAccess, type UseManageAccessArgs, type UseManageAccessReturn, } from "./useManageAccess";
|
|
4
|
+
export type { AccessResource, AccessVisibility, AccessExtraSection, } from "./types";
|
|
5
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/access/index.ts"],"names":[],"mappings":"AAGA,OAAO,EACL,kBAAkB,EAClB,KAAK,uBAAuB,GAC7B,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EACL,kBAAkB,EAClB,KAAK,uBAAuB,GAC7B,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EACL,eAAe,EACf,KAAK,mBAAmB,EACxB,KAAK,qBAAqB,GAC3B,MAAM,mBAAmB,CAAC;AAC3B,YAAY,EACV,cAAc,EACd,gBAAgB,EAChB,kBAAkB,GACnB,MAAM,SAAS,CAAC"}
|
package/access/index.js
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
// Access — the unified "Manage access" experience composing visibility
|
|
2
|
+
// (library) and explicit grants (iam-policy) into one dialog, with a kebab
|
|
3
|
+
// hook and a visible-button trigger for the surfaces that mount it.
|
|
4
|
+
export { ManageAccessDialog, } from "./ManageAccessDialog";
|
|
5
|
+
export { ManageAccessButton, } from "./ManageAccessButton";
|
|
6
|
+
export { useManageAccess, } from "./useManageAccess";
|
|
7
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/access/index.ts"],"names":[],"mappings":"AAAA,uEAAuE;AACvE,2EAA2E;AAC3E,oEAAoE;AACpE,OAAO,EACL,kBAAkB,GAEnB,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EACL,kBAAkB,GAEnB,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EACL,eAAe,GAGhB,MAAM,mBAAmB,CAAC"}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import type { ReactNode } from "react";
|
|
2
|
+
import type { ApiResourceKind } from "@stigmer/protos/ai/stigmer/commons/apiresource/apiresourcekind/api_resource_kind_pb";
|
|
3
|
+
import type { ApiResourceVisibility } from "@stigmer/protos/ai/stigmer/commons/apiresource/enum_pb";
|
|
4
|
+
import type { VisibilityResourceKind } from "../library/useUpdateVisibility";
|
|
5
|
+
/**
|
|
6
|
+
* The resource whose access is being managed. Carries everything the People
|
|
7
|
+
* section needs: the enum {@link ApiResourceKind} (for grantable-role lookup),
|
|
8
|
+
* the FGA/API kind string (for IAM refs and permission checks), the id, and
|
|
9
|
+
* the owning org (drives the org-member typeahead).
|
|
10
|
+
*/
|
|
11
|
+
export interface AccessResource {
|
|
12
|
+
/** ApiResourceKind enum — drives grantable-role lookup and capability. */
|
|
13
|
+
readonly kind: ApiResourceKind;
|
|
14
|
+
/** FGA/API kind string (e.g. "mcp_server", "session", "workflow_execution"). */
|
|
15
|
+
readonly kindString: string;
|
|
16
|
+
/** Resource id. */
|
|
17
|
+
readonly id: string;
|
|
18
|
+
/** Slug of the owning organization (`metadata.org`). */
|
|
19
|
+
readonly org: string;
|
|
20
|
+
/** Optional display name, shown as the dialog subtitle for context. */
|
|
21
|
+
readonly name?: string;
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Describes the "General access" (visibility) axis for the Manage access
|
|
25
|
+
* dialog. Optional because not every resource has visibility (e.g. sessions
|
|
26
|
+
* and workflow executions do not). When present, the dialog renders the
|
|
27
|
+
* shared `ResourceVisibilityControl`, which owns level selection and
|
|
28
|
+
* the `can_edit` gate.
|
|
29
|
+
*/
|
|
30
|
+
export interface AccessVisibility {
|
|
31
|
+
/** Resource kind, selecting both the updateVisibility RPC and FGA type. */
|
|
32
|
+
readonly kind: VisibilityResourceKind;
|
|
33
|
+
/** Current visibility of the resource. */
|
|
34
|
+
readonly current: ApiResourceVisibility;
|
|
35
|
+
/**
|
|
36
|
+
* Slug of the owning org (`metadata.org`); gates the Platform option for
|
|
37
|
+
* blueprints. Omit for instances and where Platform should not be offered.
|
|
38
|
+
*/
|
|
39
|
+
readonly org?: string;
|
|
40
|
+
/** Called after a successful visibility change so the host can refetch. */
|
|
41
|
+
readonly onChanged?: () => void;
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* A generic, resource-specific access section appended below People — the
|
|
45
|
+
* escape hatch for the rare per-kind axis (today: workflow-instance run
|
|
46
|
+
* observability) without baking that knowledge into a generic dialog.
|
|
47
|
+
*/
|
|
48
|
+
export interface AccessExtraSection {
|
|
49
|
+
/** Section heading. */
|
|
50
|
+
readonly title: string;
|
|
51
|
+
/** Optional one-line explanation under the heading. */
|
|
52
|
+
readonly description?: string;
|
|
53
|
+
/** The section body (e.g. a `<RunVisibilityControl />`). */
|
|
54
|
+
readonly content: ReactNode;
|
|
55
|
+
}
|
|
56
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/access/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AACvC,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,qFAAqF,CAAC;AAC3H,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,wDAAwD,CAAC;AACpG,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,gCAAgC,CAAC;AAE7E;;;;;GAKG;AACH,MAAM,WAAW,cAAc;IAC7B,0EAA0E;IAC1E,QAAQ,CAAC,IAAI,EAAE,eAAe,CAAC;IAC/B,gFAAgF;IAChF,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,mBAAmB;IACnB,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,wDAAwD;IACxD,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,uEAAuE;IACvE,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;CACxB;AAED;;;;;;GAMG;AACH,MAAM,WAAW,gBAAgB;IAC/B,2EAA2E;IAC3E,QAAQ,CAAC,IAAI,EAAE,sBAAsB,CAAC;IACtC,0CAA0C;IAC1C,QAAQ,CAAC,OAAO,EAAE,qBAAqB,CAAC;IACxC;;;OAGG;IACH,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,CAAC;IACtB,2EAA2E;IAC3E,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,IAAI,CAAC;CACjC;AAED;;;;GAIG;AACH,MAAM,WAAW,kBAAkB;IACjC,uBAAuB;IACvB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,uDAAuD;IACvD,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAC;IAC9B,4DAA4D;IAC5D,QAAQ,CAAC,OAAO,EAAE,SAAS,CAAC;CAC7B"}
|
package/access/types.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/access/types.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import { type ReactNode } from "react";
|
|
2
|
+
import type { DetailAction } from "../resource-detail/types";
|
|
3
|
+
import type { AccessResource, AccessVisibility, AccessExtraSection } from "./types";
|
|
4
|
+
/** Arguments for {@link useManageAccess}. */
|
|
5
|
+
export interface UseManageAccessArgs {
|
|
6
|
+
/**
|
|
7
|
+
* The resource whose access is managed, or `null` while it is still
|
|
8
|
+
* loading. When `null`, {@link UseManageAccessReturn.action} is `null` and
|
|
9
|
+
* the dialog renders nothing — safe to call before the resource is ready.
|
|
10
|
+
*/
|
|
11
|
+
readonly resource: AccessResource | null;
|
|
12
|
+
/** General access (visibility) axis; omit for resources without visibility. */
|
|
13
|
+
readonly visibility?: AccessVisibility;
|
|
14
|
+
/** Optional resource-specific section (e.g. run observability). */
|
|
15
|
+
readonly extraSection?: AccessExtraSection;
|
|
16
|
+
/** Menu-item label. @default "Manage access" */
|
|
17
|
+
readonly label?: string;
|
|
18
|
+
}
|
|
19
|
+
/** Return value of {@link useManageAccess}. */
|
|
20
|
+
export interface UseManageAccessReturn {
|
|
21
|
+
/**
|
|
22
|
+
* A ready-to-spread {@link DetailAction} for a kebab/overflow menu, or
|
|
23
|
+
* `null` when the resource is unavailable or the user lacks
|
|
24
|
+
* `can_view_access`. Lives in the `"sharing"` group.
|
|
25
|
+
*/
|
|
26
|
+
readonly action: DetailAction | null;
|
|
27
|
+
/** The {@link ManageAccessDialog} node — render it once in the host tree. */
|
|
28
|
+
readonly dialog: ReactNode;
|
|
29
|
+
/** Imperatively open the dialog. */
|
|
30
|
+
readonly open: () => void;
|
|
31
|
+
/** Whether the dialog is currently open. */
|
|
32
|
+
readonly isOpen: boolean;
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Wires the unified Manage access dialog to a kebab/overflow menu — the
|
|
36
|
+
* trigger shape used by static resource detail views (agent, skill,
|
|
37
|
+
* mcp_server, workflow), whose actions live in {@link ResourceActionBar}'s
|
|
38
|
+
* menu rather than as a standalone button.
|
|
39
|
+
*
|
|
40
|
+
* Owns the open-state and the `can_view_access` gate (a viewer may open the
|
|
41
|
+
* dialog to read general access and the people list; the dialog's own sections
|
|
42
|
+
* gate editing). Returns a `null` action when the resource is still loading or
|
|
43
|
+
* the user cannot view access — so the host can unconditionally fold
|
|
44
|
+
* `action` into its actions array.
|
|
45
|
+
*
|
|
46
|
+
* Surfaces that want a *visible* trigger instead use {@link ManageAccessButton}.
|
|
47
|
+
*
|
|
48
|
+
* @example
|
|
49
|
+
* ```tsx
|
|
50
|
+
* const access = useManageAccess({
|
|
51
|
+
* resource: meta ? { kind: ApiResourceKind.agent, kindString: "agent", id: meta.id, org: meta.org } : null,
|
|
52
|
+
* visibility: meta ? { kind: "agent", current: meta.visibility, org: meta.org, onChanged: refetch } : undefined,
|
|
53
|
+
* });
|
|
54
|
+
* // ...
|
|
55
|
+
* <ResourceDetailShell actions={access.action ? [...actions, access.action] : actions} ... />
|
|
56
|
+
* {access.dialog}
|
|
57
|
+
* ```
|
|
58
|
+
*/
|
|
59
|
+
export declare function useManageAccess({ resource, visibility, extraSection, label, }: UseManageAccessArgs): UseManageAccessReturn;
|
|
60
|
+
//# sourceMappingURL=useManageAccess.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useManageAccess.d.ts","sourceRoot":"","sources":["../../src/access/useManageAccess.tsx"],"names":[],"mappings":"AAEA,OAAO,EAAyB,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AAE9D,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAC;AAE7D,OAAO,KAAK,EACV,cAAc,EACd,gBAAgB,EAChB,kBAAkB,EACnB,MAAM,SAAS,CAAC;AAEjB,6CAA6C;AAC7C,MAAM,WAAW,mBAAmB;IAClC;;;;OAIG;IACH,QAAQ,CAAC,QAAQ,EAAE,cAAc,GAAG,IAAI,CAAC;IACzC,+EAA+E;IAC/E,QAAQ,CAAC,UAAU,CAAC,EAAE,gBAAgB,CAAC;IACvC,mEAAmE;IACnE,QAAQ,CAAC,YAAY,CAAC,EAAE,kBAAkB,CAAC;IAC3C,gDAAgD;IAChD,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;CACzB;AAED,+CAA+C;AAC/C,MAAM,WAAW,qBAAqB;IACpC;;;;OAIG;IACH,QAAQ,CAAC,MAAM,EAAE,YAAY,GAAG,IAAI,CAAC;IACrC,6EAA6E;IAC7E,QAAQ,CAAC,MAAM,EAAE,SAAS,CAAC;IAC3B,oCAAoC;IACpC,QAAQ,CAAC,IAAI,EAAE,MAAM,IAAI,CAAC;IAC1B,4CAA4C;IAC5C,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC;CAC1B;AAED;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,wBAAgB,eAAe,CAAC,EAC9B,QAAQ,EACR,UAAU,EACV,YAAY,EACZ,KAAuB,GACxB,EAAE,mBAAmB,GAAG,qBAAqB,CA0B7C"}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
3
|
+
import { useCallback, useState } from "react";
|
|
4
|
+
import { useCheckPermission } from "../iam-policy/useCheckPermission";
|
|
5
|
+
import { ManageAccessDialog } from "./ManageAccessDialog";
|
|
6
|
+
/**
|
|
7
|
+
* Wires the unified Manage access dialog to a kebab/overflow menu — the
|
|
8
|
+
* trigger shape used by static resource detail views (agent, skill,
|
|
9
|
+
* mcp_server, workflow), whose actions live in {@link ResourceActionBar}'s
|
|
10
|
+
* menu rather than as a standalone button.
|
|
11
|
+
*
|
|
12
|
+
* Owns the open-state and the `can_view_access` gate (a viewer may open the
|
|
13
|
+
* dialog to read general access and the people list; the dialog's own sections
|
|
14
|
+
* gate editing). Returns a `null` action when the resource is still loading or
|
|
15
|
+
* the user cannot view access — so the host can unconditionally fold
|
|
16
|
+
* `action` into its actions array.
|
|
17
|
+
*
|
|
18
|
+
* Surfaces that want a *visible* trigger instead use {@link ManageAccessButton}.
|
|
19
|
+
*
|
|
20
|
+
* @example
|
|
21
|
+
* ```tsx
|
|
22
|
+
* const access = useManageAccess({
|
|
23
|
+
* resource: meta ? { kind: ApiResourceKind.agent, kindString: "agent", id: meta.id, org: meta.org } : null,
|
|
24
|
+
* visibility: meta ? { kind: "agent", current: meta.visibility, org: meta.org, onChanged: refetch } : undefined,
|
|
25
|
+
* });
|
|
26
|
+
* // ...
|
|
27
|
+
* <ResourceDetailShell actions={access.action ? [...actions, access.action] : actions} ... />
|
|
28
|
+
* {access.dialog}
|
|
29
|
+
* ```
|
|
30
|
+
*/
|
|
31
|
+
export function useManageAccess({ resource, visibility, extraSection, label = "Manage access", }) {
|
|
32
|
+
const [isOpen, setIsOpen] = useState(false);
|
|
33
|
+
const { allowed: canView } = useCheckPermission(resource ? { kind: resource.kindString, id: resource.id } : null, "can_view_access");
|
|
34
|
+
const open = useCallback(() => setIsOpen(true), []);
|
|
35
|
+
const action = resource && canView
|
|
36
|
+
? { id: "manage-access", label, group: "sharing", onAction: open }
|
|
37
|
+
: null;
|
|
38
|
+
const dialog = resource ? (_jsx(ManageAccessDialog, { open: isOpen, onOpenChange: setIsOpen, resource: resource, visibility: visibility, extraSection: extraSection })) : null;
|
|
39
|
+
return { action, dialog, open, isOpen };
|
|
40
|
+
}
|
|
41
|
+
//# sourceMappingURL=useManageAccess.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useManageAccess.js","sourceRoot":"","sources":["../../src/access/useManageAccess.tsx"],"names":[],"mappings":"AAAA,YAAY,CAAC;;AAEb,OAAO,EAAE,WAAW,EAAE,QAAQ,EAAkB,MAAM,OAAO,CAAC;AAC9D,OAAO,EAAE,kBAAkB,EAAE,MAAM,kCAAkC,CAAC;AAEtE,OAAO,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;AAuC1D;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,MAAM,UAAU,eAAe,CAAC,EAC9B,QAAQ,EACR,UAAU,EACV,YAAY,EACZ,KAAK,GAAG,eAAe,GACH;IACpB,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC;IAE5C,MAAM,EAAE,OAAO,EAAE,OAAO,EAAE,GAAG,kBAAkB,CAC7C,QAAQ,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,QAAQ,CAAC,UAAU,EAAE,EAAE,EAAE,QAAQ,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,EAChE,iBAAiB,CAClB,CAAC;IAEF,MAAM,IAAI,GAAG,WAAW,CAAC,GAAG,EAAE,CAAC,SAAS,CAAC,IAAI,CAAC,EAAE,EAAE,CAAC,CAAC;IAEpD,MAAM,MAAM,GACV,QAAQ,IAAI,OAAO;QACjB,CAAC,CAAC,EAAE,EAAE,EAAE,eAAe,EAAE,KAAK,EAAE,KAAK,EAAE,SAAS,EAAE,QAAQ,EAAE,IAAI,EAAE;QAClE,CAAC,CAAC,IAAI,CAAC;IAEX,MAAM,MAAM,GAAG,QAAQ,CAAC,CAAC,CAAC,CACxB,KAAC,kBAAkB,IACjB,IAAI,EAAE,MAAM,EACZ,YAAY,EAAE,SAAS,EACvB,QAAQ,EAAE,QAAQ,EAClB,UAAU,EAAE,UAAU,EACtB,YAAY,EAAE,YAAY,GAC1B,CACH,CAAC,CAAC,CAAC,IAAI,CAAC;IAET,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;AAC1C,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AgentDetailView.d.ts","sourceRoot":"","sources":["../../src/agent/AgentDetailView.tsx"],"names":[],"mappings":"AAWA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,4DAA4D,CAAC;
|
|
1
|
+
{"version":3,"file":"AgentDetailView.d.ts","sourceRoot":"","sources":["../../src/agent/AgentDetailView.tsx"],"names":[],"mappings":"AAWA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,4DAA4D,CAAC;AAWhG,OAAO,KAAK,EAAE,aAAa,EAAE,YAAY,EAAsB,MAAM,0BAA0B,CAAC;AAkBhG,yCAAyC;AACzC,MAAM,WAAW,oBAAoB;IACnC,6CAA6C;IAC7C,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,kEAAkE;IAClE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB;;;;;OAKG;IACH,QAAQ,CAAC,gBAAgB,CAAC,EAAE,CAAC,GAAG,EAAE;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,KAAK,IAAI,CAAC;IACzE;;;OAGG;IACH,QAAQ,CAAC,YAAY,CAAC,EAAE,CAAC,GAAG,EAAE;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,KAAK,IAAI,CAAC;IACrE;;;;;;;OAOG;IACH,QAAQ,CAAC,cAAc,CAAC,EAAE,CAAC,IAAI,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,EAAE,EAAE,MAAM,CAAA;KAAE,KAAK,IAAI,CAAC;IACvE;;;OAGG;IACH,QAAQ,CAAC,aAAa,CAAC,EAAE,YAAY,CAAC;IACtC;;;OAGG;IACH,QAAQ,CAAC,OAAO,CAAC,EAAE,SAAS,YAAY,EAAE,CAAC;IAC3C;;;;;;;;;;;;;;;;;;OAkBG;IACH,QAAQ,CAAC,cAAc,CAAC,EAAE,SAAS,aAAa,EAAE,CAAC;IACnD;;;;OAIG;IACH,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC;IAC5B;;;OAGG;IACH,QAAQ,CAAC,WAAW,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IAC/C;;;OAGG;IACH,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAC;IAC7B;;;;OAIG;IACH,QAAQ,CAAC,QAAQ,CAAC,EAAE,OAAO,CAAC;IAC5B;;;OAGG;IACH,QAAQ,CAAC,iBAAiB,CAAC,EAAE,CAAC,KAAK,EAAE,OAAO,oDAAoD,EAAE,KAAK,KAAK,IAAI,CAAC;IACjH;;;OAGG;IACH,QAAQ,CAAC,qBAAqB,CAAC,EAAE,MAAM,IAAI,CAAC;IAC5C;;;OAGG;IACH,QAAQ,CAAC,eAAe,CAAC,EAAE,CAAC,QAAQ,EAAE,aAAa,KAAK,IAAI,CAAC;IAC7D;;;OAGG;IACH,QAAQ,CAAC,2BAA2B,CAAC,EAAE,CAAC,QAAQ,EAAE,aAAa,KAAK,IAAI,CAAC;IACzE;;OAEG;IACH,QAAQ,CAAC,qBAAqB,CAAC,EAAE,CAAC,QAAQ,EAAE,aAAa,KAAK,IAAI,CAAC;IACnE;;;OAGG;IACH,QAAQ,CAAC,mBAAmB,CAAC,EAAE,MAAM,CAAC;IACtC,qDAAqD;IACrD,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC;CAC7B;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAuCG;AACH,wBAAgB,eAAe,CAAC,EAC9B,GAAG,EACH,IAAI,EACJ,gBAAgB,EAChB,YAAY,EACZ,cAAc,EACd,aAAa,EACb,OAAO,EACP,cAAc,EACd,SAAS,EACT,WAAW,EACX,UAAU,EACV,QAAgB,EAChB,iBAAiB,EACjB,qBAAqB,EACrB,eAAe,EACf,2BAA2B,EAC3B,qBAAqB,EACrB,mBAAmB,EACnB,SAAS,GACV,EAAE,oBAAoB,2CAkMtB"}
|
package/agent/AgentDetailView.js
CHANGED
|
@@ -1,13 +1,15 @@
|
|
|
1
1
|
"use client";
|
|
2
|
-
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
3
|
import { useCallback, useEffect, useMemo, useRef, useState } from "react";
|
|
4
4
|
import { cn } from "@stigmer/theme";
|
|
5
5
|
import { timestampDate } from "@bufbuild/protobuf/wkt";
|
|
6
|
+
import { ApiResourceKind } from "@stigmer/protos/ai/stigmer/commons/apiresource/apiresourcekind/api_resource_kind_pb";
|
|
6
7
|
import { useAgent } from "./useAgent";
|
|
7
8
|
import { useUpdateAgent } from "./useUpdateAgent";
|
|
8
9
|
import { agentToInput } from "./internal/agentToInput";
|
|
9
10
|
import { ErrorMessage } from "../error/ErrorMessage";
|
|
10
|
-
import {
|
|
11
|
+
import { VisibilityBadge } from "../library/VisibilitySelector";
|
|
12
|
+
import { useManageAccess } from "../access/useManageAccess";
|
|
11
13
|
import { ResourceDetailShell } from "../resource-detail/ResourceDetailShell";
|
|
12
14
|
import { Section } from "../resource-detail/Section";
|
|
13
15
|
import { useDetailTabs } from "../resource-detail/useDetailTabs";
|
|
@@ -112,6 +114,29 @@ export function AgentDetailView({ org, slug, onMcpServerClick, onSkillClick, onR
|
|
|
112
114
|
onResourceLoadRef.current?.({ name: agent.metadata.name, id: agent.metadata.id });
|
|
113
115
|
}
|
|
114
116
|
}, [agent]);
|
|
117
|
+
// Unified Manage access — visibility (General access) over explicit grants
|
|
118
|
+
// (People), opened from the kebab. Derived from the loaded metadata, so the
|
|
119
|
+
// action stays null until the resource is ready (and folds harmlessly into
|
|
120
|
+
// the actions array meanwhile).
|
|
121
|
+
const access = useManageAccess({
|
|
122
|
+
resource: agent?.metadata
|
|
123
|
+
? {
|
|
124
|
+
kind: ApiResourceKind.agent,
|
|
125
|
+
kindString: "agent",
|
|
126
|
+
id: agent.metadata.id,
|
|
127
|
+
org: agent.metadata.org,
|
|
128
|
+
name: agent.metadata.name,
|
|
129
|
+
}
|
|
130
|
+
: null,
|
|
131
|
+
visibility: agent?.metadata
|
|
132
|
+
? {
|
|
133
|
+
kind: "agent",
|
|
134
|
+
current: agent.metadata.visibility,
|
|
135
|
+
org: agent.metadata.org,
|
|
136
|
+
onChanged: refetch,
|
|
137
|
+
}
|
|
138
|
+
: undefined,
|
|
139
|
+
});
|
|
115
140
|
if (isLoading)
|
|
116
141
|
return _jsx(LoadingSkeleton, { className: className });
|
|
117
142
|
if (error)
|
|
@@ -135,7 +160,12 @@ export function AgentDetailView({ org, slug, onMcpServerClick, onSkillClick, onR
|
|
|
135
160
|
createdAt: specAudit?.createdAt ? timestampDate(specAudit.createdAt) : null,
|
|
136
161
|
updatedAt: specAudit?.updatedAt ? timestampDate(specAudit.updatedAt) : null,
|
|
137
162
|
};
|
|
138
|
-
|
|
163
|
+
// Inline visibility is read-only (at-a-glance); editing lives in the
|
|
164
|
+
// Manage access dialog, the single writer for both access axes.
|
|
165
|
+
const visibilityControl = meta ? (_jsx(VisibilityBadge, { visibility: meta.visibility })) : undefined;
|
|
166
|
+
const mergedActions = access.action
|
|
167
|
+
? [...(actions ?? []), access.action]
|
|
168
|
+
: actions;
|
|
139
169
|
let tabContent;
|
|
140
170
|
if (activeAdditionalTab) {
|
|
141
171
|
tabContent = activeAdditionalTab.content;
|
|
@@ -149,7 +179,7 @@ export function AgentDetailView({ org, slug, onMcpServerClick, onSkillClick, onR
|
|
|
149
179
|
else {
|
|
150
180
|
tabContent = (_jsx(AgentOverview, { spec: spec, agentOrg: agentOrg, description: spec?.description, onMcpServerClick: onMcpServerClick, onSkillClick: onSkillClick, editable: editable, isSaving: isUpdating, saveField: saveField }));
|
|
151
181
|
}
|
|
152
|
-
return (_jsx(ResourceDetailShell, { header: headerMeta, visibilityControl: visibilityControl, primaryAction: primaryAction, actions:
|
|
182
|
+
return (_jsxs(_Fragment, { children: [_jsx(ResourceDetailShell, { header: headerMeta, visibilityControl: visibilityControl, primaryAction: primaryAction, actions: mergedActions, tabs: effectiveTabs, activeTab: effectiveTabs ? effectiveActiveTab : undefined, onTabChange: effectiveTabs ? effectiveOnTabChange : undefined, tabsAriaLabel: "Agent detail sections", className: className, children: tabContent }), access.dialog] }));
|
|
153
183
|
}
|
|
154
184
|
// ---------------------------------------------------------------------------
|
|
155
185
|
// Overview content — the agent's configuration sections
|