@stigmer/react 0.0.98 → 0.0.100
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/index.d.ts +17 -3
- package/index.d.ts.map +1 -1
- package/index.js +16 -3
- package/index.js.map +1 -1
- package/internal/menu.d.ts +17 -0
- package/internal/menu.d.ts.map +1 -0
- package/internal/menu.js +43 -0
- package/internal/menu.js.map +1 -0
- package/library/LibraryBreadcrumbContext.d.ts +30 -0
- package/library/LibraryBreadcrumbContext.d.ts.map +1 -0
- package/library/LibraryBreadcrumbContext.js +39 -0
- package/library/LibraryBreadcrumbContext.js.map +1 -0
- package/library/index.d.ts +1 -0
- package/library/index.d.ts.map +1 -1
- package/library/index.js +1 -0
- package/library/index.js.map +1 -1
- package/organization/OrgProvider.d.ts +59 -0
- package/organization/OrgProvider.d.ts.map +1 -0
- package/organization/OrgProvider.js +130 -0
- package/organization/OrgProvider.js.map +1 -0
- package/organization/OrgSwitcher.d.ts +36 -0
- package/organization/OrgSwitcher.d.ts.map +1 -0
- package/organization/OrgSwitcher.js +73 -0
- package/organization/OrgSwitcher.js.map +1 -0
- package/organization/index.d.ts +6 -0
- package/organization/index.d.ts.map +1 -1
- package/organization/index.js +3 -0
- package/organization/index.js.map +1 -1
- package/organization/useOrgGate.d.ts +101 -0
- package/organization/useOrgGate.d.ts.map +1 -0
- package/organization/useOrgGate.js +99 -0
- package/organization/useOrgGate.js.map +1 -0
- package/package.json +5 -4
- package/runner/RunnerListPanel.d.ts +13 -8
- package/runner/RunnerListPanel.d.ts.map +1 -1
- package/runner/RunnerListPanel.js +10 -6
- package/runner/RunnerListPanel.js.map +1 -1
- package/settings/ApiKeysSection.d.ts +3 -0
- package/settings/ApiKeysSection.d.ts.map +1 -0
- package/settings/ApiKeysSection.js +30 -0
- package/settings/ApiKeysSection.js.map +1 -0
- package/settings/EnvironmentsSection.d.ts +3 -0
- package/settings/EnvironmentsSection.d.ts.map +1 -0
- package/settings/EnvironmentsSection.js +49 -0
- package/settings/EnvironmentsSection.js.map +1 -0
- package/settings/IdentityProvidersSection.d.ts +12 -0
- package/settings/IdentityProvidersSection.d.ts.map +1 -0
- package/settings/IdentityProvidersSection.js +34 -0
- package/settings/IdentityProvidersSection.js.map +1 -0
- package/settings/InvitationsSection.d.ts +3 -0
- package/settings/InvitationsSection.d.ts.map +1 -0
- package/settings/InvitationsSection.js +13 -0
- package/settings/InvitationsSection.js.map +1 -0
- package/settings/MembersSection.d.ts +3 -0
- package/settings/MembersSection.d.ts.map +1 -0
- package/settings/MembersSection.js +14 -0
- package/settings/MembersSection.js.map +1 -0
- package/settings/OAuthAppsSection.d.ts +3 -0
- package/settings/OAuthAppsSection.d.ts.map +1 -0
- package/settings/OAuthAppsSection.js +33 -0
- package/settings/OAuthAppsSection.js.map +1 -0
- package/settings/OrgProfileSection.d.ts +3 -0
- package/settings/OrgProfileSection.d.ts.map +1 -0
- package/settings/OrgProfileSection.js +15 -0
- package/settings/OrgProfileSection.js.map +1 -0
- package/settings/PlatformClientsSection.d.ts +3 -0
- package/settings/PlatformClientsSection.d.ts.map +1 -0
- package/settings/PlatformClientsSection.js +48 -0
- package/settings/PlatformClientsSection.js.map +1 -0
- package/settings/UsageSection.d.ts +3 -0
- package/settings/UsageSection.d.ts.map +1 -0
- package/settings/UsageSection.js +14 -0
- package/settings/UsageSection.js.map +1 -0
- package/settings/index.d.ts +13 -0
- package/settings/index.d.ts.map +1 -0
- package/settings/index.js +11 -0
- package/settings/index.js.map +1 -0
- package/settings/settings-nav.d.ts +25 -0
- package/settings/settings-nav.d.ts.map +1 -0
- package/settings/settings-nav.js +41 -0
- package/settings/settings-nav.js.map +1 -0
- package/src/index.ts +32 -1
- package/src/internal/menu.tsx +160 -0
- package/src/library/LibraryBreadcrumbContext.tsx +70 -0
- package/src/library/index.ts +6 -0
- package/src/organization/OrgProvider.tsx +184 -0
- package/src/organization/OrgSwitcher.tsx +275 -0
- package/src/organization/index.ts +10 -0
- package/src/organization/useOrgGate.ts +183 -0
- package/src/runner/RunnerListPanel.tsx +14 -9
- package/src/settings/ApiKeysSection.tsx +96 -0
- package/src/settings/EnvironmentsSection.tsx +162 -0
- package/src/settings/IdentityProvidersSection.tsx +123 -0
- package/src/settings/InvitationsSection.tsx +42 -0
- package/src/settings/MembersSection.tsx +41 -0
- package/src/settings/OAuthAppsSection.tsx +100 -0
- package/src/settings/OrgProfileSection.tsx +41 -0
- package/src/settings/PlatformClientsSection.tsx +149 -0
- package/src/settings/UsageSection.tsx +41 -0
- package/src/settings/index.ts +13 -0
- package/src/settings/settings-nav.ts +78 -0
- package/src/user/UserMenu.tsx +241 -0
- package/src/user/index.ts +2 -0
- package/styles.css +1 -1
- package/user/UserMenu.d.ts +82 -0
- package/user/UserMenu.d.ts.map +1 -0
- package/user/UserMenu.js +51 -0
- package/user/UserMenu.js.map +1 -0
- package/user/index.d.ts +3 -0
- package/user/index.d.ts.map +1 -0
- package/user/index.js +2 -0
- package/user/index.js.map +1 -0
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import { OrgMembersPanel } from "../iam-policy/OrgMembersPanel";
|
|
4
|
+
import { useResourceAvailable, ApiResourceKind } from "../deployment-mode";
|
|
5
|
+
import { CloudFeatureNotice } from "../internal/CloudFeatureNotice";
|
|
6
|
+
import { useOrg } from "../organization/OrgProvider";
|
|
7
|
+
|
|
8
|
+
/** Settings section for organization membership and role management. */
|
|
9
|
+
export function MembersSection() {
|
|
10
|
+
const { activeOrg } = useOrg();
|
|
11
|
+
const membersAvailable = useResourceAvailable(ApiResourceKind.iam_policy);
|
|
12
|
+
const orgId = activeOrg?.metadata?.id ?? "";
|
|
13
|
+
|
|
14
|
+
return (
|
|
15
|
+
<section aria-labelledby="members-heading">
|
|
16
|
+
<h2
|
|
17
|
+
id="members-heading"
|
|
18
|
+
className="text-foreground mb-1 text-sm font-semibold"
|
|
19
|
+
>
|
|
20
|
+
Members
|
|
21
|
+
</h2>
|
|
22
|
+
<p className="text-muted-foreground mb-4 text-xs">
|
|
23
|
+
Manage who has access to this organization and what they can do.
|
|
24
|
+
Members can be granted owner, admin, member, or viewer roles.
|
|
25
|
+
</p>
|
|
26
|
+
|
|
27
|
+
{!membersAvailable ? (
|
|
28
|
+
<CloudFeatureNotice>
|
|
29
|
+
Members management is not available in local mode. IAM policies
|
|
30
|
+
require Stigmer Cloud.
|
|
31
|
+
</CloudFeatureNotice>
|
|
32
|
+
) : !orgId ? (
|
|
33
|
+
<p className="text-muted-foreground py-4 text-center text-xs">
|
|
34
|
+
Select an organization to manage members.
|
|
35
|
+
</p>
|
|
36
|
+
) : (
|
|
37
|
+
<OrgMembersPanel orgId={orgId} />
|
|
38
|
+
)}
|
|
39
|
+
</section>
|
|
40
|
+
);
|
|
41
|
+
}
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import { useCallback, useRef, useState } from "react";
|
|
4
|
+
import type { OAuthApp } from "@stigmer/protos/ai/stigmer/iam/oauthapp/v1/api_pb";
|
|
5
|
+
import { OAuthAppListPanel } from "../oauth-app/OAuthAppListPanel";
|
|
6
|
+
import { CreateOAuthAppForm } from "../oauth-app/CreateOAuthAppForm";
|
|
7
|
+
import { OAuthAppDetailPanel } from "../oauth-app/OAuthAppDetailPanel";
|
|
8
|
+
import { useResourceAvailable, ApiResourceKind } from "../deployment-mode";
|
|
9
|
+
import { CloudFeatureNotice } from "../internal/CloudFeatureNotice";
|
|
10
|
+
import { useActiveOrgSlug } from "../organization/OrgProvider";
|
|
11
|
+
|
|
12
|
+
type FlowState =
|
|
13
|
+
| { phase: "idle" }
|
|
14
|
+
| { phase: "creating" }
|
|
15
|
+
| { phase: "editing"; oauthApp: OAuthApp };
|
|
16
|
+
|
|
17
|
+
/** Settings section for organization OAuth app credentials. */
|
|
18
|
+
export function OAuthAppsSection() {
|
|
19
|
+
const org = useActiveOrgSlug();
|
|
20
|
+
const oauthAppsAvailable = useResourceAvailable(ApiResourceKind.oauth_app);
|
|
21
|
+
|
|
22
|
+
const [flow, setFlow] = useState<FlowState>({ phase: "idle" });
|
|
23
|
+
const listRefetchRef = useRef<(() => void) | null>(null);
|
|
24
|
+
|
|
25
|
+
const handleRefetchRef = useCallback((refetch: () => void) => {
|
|
26
|
+
listRefetchRef.current = refetch;
|
|
27
|
+
}, []);
|
|
28
|
+
|
|
29
|
+
const handleCreated = useCallback(() => {
|
|
30
|
+
listRefetchRef.current?.();
|
|
31
|
+
setFlow({ phase: "idle" });
|
|
32
|
+
}, []);
|
|
33
|
+
|
|
34
|
+
const handleUpdated = useCallback(() => {
|
|
35
|
+
listRefetchRef.current?.();
|
|
36
|
+
setFlow({ phase: "idle" });
|
|
37
|
+
}, []);
|
|
38
|
+
|
|
39
|
+
const handleDeleted = useCallback(() => {
|
|
40
|
+
listRefetchRef.current?.();
|
|
41
|
+
setFlow({ phase: "idle" });
|
|
42
|
+
}, []);
|
|
43
|
+
|
|
44
|
+
return (
|
|
45
|
+
<section aria-labelledby="oauth-apps-heading">
|
|
46
|
+
<div className="mb-3 flex items-center justify-between">
|
|
47
|
+
<h2
|
|
48
|
+
id="oauth-apps-heading"
|
|
49
|
+
className="text-foreground text-sm font-semibold"
|
|
50
|
+
>
|
|
51
|
+
OAuth Apps
|
|
52
|
+
</h2>
|
|
53
|
+
|
|
54
|
+
{oauthAppsAvailable && org && flow.phase === "idle" && (
|
|
55
|
+
<button
|
|
56
|
+
type="button"
|
|
57
|
+
onClick={() => setFlow({ phase: "creating" })}
|
|
58
|
+
className="text-primary hover:text-foreground text-xs font-medium transition-colors"
|
|
59
|
+
>
|
|
60
|
+
+ New OAuth app
|
|
61
|
+
</button>
|
|
62
|
+
)}
|
|
63
|
+
</div>
|
|
64
|
+
<p className="text-muted-foreground mb-4 text-xs">
|
|
65
|
+
OAuth app credentials configured for your organization. Create new
|
|
66
|
+
apps here or bring your own from an MCP server's detail page.
|
|
67
|
+
</p>
|
|
68
|
+
|
|
69
|
+
{!oauthAppsAvailable ? (
|
|
70
|
+
<CloudFeatureNotice>
|
|
71
|
+
OAuth apps are not available in local mode. Bring-your-own-app
|
|
72
|
+
OAuth requires the cloud platform.
|
|
73
|
+
</CloudFeatureNotice>
|
|
74
|
+
) : flow.phase === "creating" ? (
|
|
75
|
+
<div className="border-border bg-card rounded-lg border p-4">
|
|
76
|
+
<CreateOAuthAppForm
|
|
77
|
+
org={org}
|
|
78
|
+
onCreated={handleCreated}
|
|
79
|
+
onCancel={() => setFlow({ phase: "idle" })}
|
|
80
|
+
/>
|
|
81
|
+
</div>
|
|
82
|
+
) : flow.phase === "editing" ? (
|
|
83
|
+
<div className="border-border bg-card rounded-lg border p-4">
|
|
84
|
+
<OAuthAppDetailPanel
|
|
85
|
+
oauthApp={flow.oauthApp}
|
|
86
|
+
onUpdated={handleUpdated}
|
|
87
|
+
onDeleted={handleDeleted}
|
|
88
|
+
onBack={() => setFlow({ phase: "idle" })}
|
|
89
|
+
/>
|
|
90
|
+
</div>
|
|
91
|
+
) : (
|
|
92
|
+
<OAuthAppListPanel
|
|
93
|
+
org={org}
|
|
94
|
+
onEdit={(app) => setFlow({ phase: "editing", oauthApp: app })}
|
|
95
|
+
onRefetchRef={handleRefetchRef}
|
|
96
|
+
/>
|
|
97
|
+
)}
|
|
98
|
+
</section>
|
|
99
|
+
);
|
|
100
|
+
}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import { useCallback } from "react";
|
|
4
|
+
import type { Organization } from "@stigmer/protos/ai/stigmer/tenancy/organization/v1/api_pb";
|
|
5
|
+
import { OrgProfilePanel } from "../organization/OrgProfilePanel";
|
|
6
|
+
import { useOrg } from "../organization/OrgProvider";
|
|
7
|
+
|
|
8
|
+
/** Settings section for editing the active organization profile. */
|
|
9
|
+
export function OrgProfileSection() {
|
|
10
|
+
const { activeOrg, refresh } = useOrg();
|
|
11
|
+
const orgId = activeOrg?.metadata?.id ?? "";
|
|
12
|
+
|
|
13
|
+
const handleUpdated = useCallback(
|
|
14
|
+
(org: Organization) => {
|
|
15
|
+
refresh(org.metadata?.slug);
|
|
16
|
+
},
|
|
17
|
+
[refresh],
|
|
18
|
+
);
|
|
19
|
+
|
|
20
|
+
return (
|
|
21
|
+
<section aria-labelledby="org-profile-heading">
|
|
22
|
+
<h2
|
|
23
|
+
id="org-profile-heading"
|
|
24
|
+
className="text-foreground mb-1 text-sm font-semibold"
|
|
25
|
+
>
|
|
26
|
+
Organization Profile
|
|
27
|
+
</h2>
|
|
28
|
+
<p className="text-muted-foreground mb-6 text-xs">
|
|
29
|
+
Manage your organization's display name, description, and logo.
|
|
30
|
+
</p>
|
|
31
|
+
|
|
32
|
+
{!orgId ? (
|
|
33
|
+
<p className="text-muted-foreground py-4 text-center text-xs">
|
|
34
|
+
Select an organization to view its profile.
|
|
35
|
+
</p>
|
|
36
|
+
) : (
|
|
37
|
+
<OrgProfilePanel orgId={orgId} onUpdated={handleUpdated} />
|
|
38
|
+
)}
|
|
39
|
+
</section>
|
|
40
|
+
);
|
|
41
|
+
}
|
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import { useCallback, useRef, useState } from "react";
|
|
4
|
+
import type { PlatformClient } from "@stigmer/protos/ai/stigmer/iam/platformclient/v1/api_pb";
|
|
5
|
+
import type { PlatformClientCreateResponse } from "@stigmer/protos/ai/stigmer/iam/platformclient/v1/io_pb";
|
|
6
|
+
import { PlatformClientListPanel } from "../platform-client/PlatformClientListPanel";
|
|
7
|
+
import { CreatePlatformClientForm } from "../platform-client/CreatePlatformClientForm";
|
|
8
|
+
import { PlatformClientDetailPanel } from "../platform-client/PlatformClientDetailPanel";
|
|
9
|
+
import { PlatformClientSecretAlert } from "../platform-client/PlatformClientSecretAlert";
|
|
10
|
+
import { useResourceAvailable, ApiResourceKind } from "../deployment-mode";
|
|
11
|
+
import { CloudFeatureNotice } from "../internal/CloudFeatureNotice";
|
|
12
|
+
import { useActiveOrgSlug } from "../organization/OrgProvider";
|
|
13
|
+
|
|
14
|
+
type FlowState =
|
|
15
|
+
| { phase: "idle" }
|
|
16
|
+
| { phase: "creating" }
|
|
17
|
+
| {
|
|
18
|
+
phase: "revealing";
|
|
19
|
+
clientId: string;
|
|
20
|
+
clientSecret: string;
|
|
21
|
+
context: "created" | "rotated";
|
|
22
|
+
}
|
|
23
|
+
| { phase: "editing"; platformClient: PlatformClient };
|
|
24
|
+
|
|
25
|
+
/** Settings section for creating and maintaining platform clients. */
|
|
26
|
+
export function PlatformClientsSection() {
|
|
27
|
+
const org = useActiveOrgSlug();
|
|
28
|
+
const pcAvailable = useResourceAvailable(ApiResourceKind.platform_client);
|
|
29
|
+
|
|
30
|
+
const [flow, setFlow] = useState<FlowState>({ phase: "idle" });
|
|
31
|
+
const listRefetchRef = useRef<(() => void) | null>(null);
|
|
32
|
+
|
|
33
|
+
const handleRefetchRef = useCallback((refetch: () => void) => {
|
|
34
|
+
listRefetchRef.current = refetch;
|
|
35
|
+
}, []);
|
|
36
|
+
|
|
37
|
+
const handleCreated = useCallback(
|
|
38
|
+
(response: PlatformClientCreateResponse) => {
|
|
39
|
+
listRefetchRef.current?.();
|
|
40
|
+
setFlow({
|
|
41
|
+
phase: "revealing",
|
|
42
|
+
clientId: response.platformClient?.spec?.clientId ?? "",
|
|
43
|
+
clientSecret: response.clientSecret,
|
|
44
|
+
context: "created",
|
|
45
|
+
});
|
|
46
|
+
},
|
|
47
|
+
[],
|
|
48
|
+
);
|
|
49
|
+
|
|
50
|
+
const handleSecretRotated = useCallback(
|
|
51
|
+
(response: PlatformClientCreateResponse) => {
|
|
52
|
+
listRefetchRef.current?.();
|
|
53
|
+
setFlow({
|
|
54
|
+
phase: "revealing",
|
|
55
|
+
clientId: response.platformClient?.spec?.clientId ?? "",
|
|
56
|
+
clientSecret: response.clientSecret,
|
|
57
|
+
context: "rotated",
|
|
58
|
+
});
|
|
59
|
+
},
|
|
60
|
+
[],
|
|
61
|
+
);
|
|
62
|
+
|
|
63
|
+
const handleUpdated = useCallback(() => {
|
|
64
|
+
listRefetchRef.current?.();
|
|
65
|
+
setFlow({ phase: "idle" });
|
|
66
|
+
}, []);
|
|
67
|
+
|
|
68
|
+
const handleDeleted = useCallback(() => {
|
|
69
|
+
listRefetchRef.current?.();
|
|
70
|
+
setFlow({ phase: "idle" });
|
|
71
|
+
}, []);
|
|
72
|
+
|
|
73
|
+
return (
|
|
74
|
+
<section aria-labelledby="platform-clients-heading">
|
|
75
|
+
<div className="mb-3 flex items-center justify-between">
|
|
76
|
+
<h2
|
|
77
|
+
id="platform-clients-heading"
|
|
78
|
+
className="text-foreground text-sm font-semibold"
|
|
79
|
+
>
|
|
80
|
+
Platform Clients
|
|
81
|
+
</h2>
|
|
82
|
+
|
|
83
|
+
{pcAvailable && org && flow.phase === "idle" && (
|
|
84
|
+
<button
|
|
85
|
+
type="button"
|
|
86
|
+
onClick={() => setFlow({ phase: "creating" })}
|
|
87
|
+
className="text-primary hover:text-foreground text-xs font-medium transition-colors"
|
|
88
|
+
>
|
|
89
|
+
+ New platform client
|
|
90
|
+
</button>
|
|
91
|
+
)}
|
|
92
|
+
</div>
|
|
93
|
+
<p className="text-muted-foreground mb-4 text-xs">
|
|
94
|
+
Platform clients let your backend mint Stigmer user tokens so you
|
|
95
|
+
can embed Stigmer components in your application without requiring
|
|
96
|
+
OIDC federation.
|
|
97
|
+
</p>
|
|
98
|
+
|
|
99
|
+
{!pcAvailable ? (
|
|
100
|
+
<CloudFeatureNotice>
|
|
101
|
+
Platform clients are not available in local mode. Token minting
|
|
102
|
+
requires Stigmer Cloud.
|
|
103
|
+
</CloudFeatureNotice>
|
|
104
|
+
) : flow.phase === "creating" ? (
|
|
105
|
+
<div className="border-border bg-card rounded-lg border p-4">
|
|
106
|
+
<CreatePlatformClientForm
|
|
107
|
+
org={org}
|
|
108
|
+
onCreated={handleCreated}
|
|
109
|
+
onCancel={() => setFlow({ phase: "idle" })}
|
|
110
|
+
/>
|
|
111
|
+
</div>
|
|
112
|
+
) : flow.phase === "revealing" ? (
|
|
113
|
+
<div className="space-y-4">
|
|
114
|
+
<PlatformClientSecretAlert
|
|
115
|
+
clientId={flow.clientId}
|
|
116
|
+
clientSecret={flow.clientSecret}
|
|
117
|
+
context={flow.context}
|
|
118
|
+
onDismiss={() => setFlow({ phase: "idle" })}
|
|
119
|
+
/>
|
|
120
|
+
<PlatformClientListPanel
|
|
121
|
+
org={org}
|
|
122
|
+
onEdit={(pc) =>
|
|
123
|
+
setFlow({ phase: "editing", platformClient: pc })
|
|
124
|
+
}
|
|
125
|
+
onRefetchRef={handleRefetchRef}
|
|
126
|
+
/>
|
|
127
|
+
</div>
|
|
128
|
+
) : flow.phase === "editing" ? (
|
|
129
|
+
<div className="border-border bg-card rounded-lg border p-4">
|
|
130
|
+
<PlatformClientDetailPanel
|
|
131
|
+
platformClient={flow.platformClient}
|
|
132
|
+
onUpdated={handleUpdated}
|
|
133
|
+
onSecretRotated={handleSecretRotated}
|
|
134
|
+
onDeleted={handleDeleted}
|
|
135
|
+
onBack={() => setFlow({ phase: "idle" })}
|
|
136
|
+
/>
|
|
137
|
+
</div>
|
|
138
|
+
) : (
|
|
139
|
+
<PlatformClientListPanel
|
|
140
|
+
org={org}
|
|
141
|
+
onEdit={(pc) =>
|
|
142
|
+
setFlow({ phase: "editing", platformClient: pc })
|
|
143
|
+
}
|
|
144
|
+
onRefetchRef={handleRefetchRef}
|
|
145
|
+
/>
|
|
146
|
+
)}
|
|
147
|
+
</section>
|
|
148
|
+
);
|
|
149
|
+
}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import { OrgUsagePanel } from "../usage/OrgUsagePanel";
|
|
4
|
+
import { useDeploymentMode } from "../deployment-mode";
|
|
5
|
+
import { CloudFeatureNotice } from "../internal/CloudFeatureNotice";
|
|
6
|
+
import { useOrg } from "../organization/OrgProvider";
|
|
7
|
+
|
|
8
|
+
/** Settings section for organization usage and cost reporting. */
|
|
9
|
+
export function UsageSection() {
|
|
10
|
+
const { activeOrg } = useOrg();
|
|
11
|
+
const mode = useDeploymentMode();
|
|
12
|
+
const orgId = activeOrg?.metadata?.id ?? "";
|
|
13
|
+
|
|
14
|
+
return (
|
|
15
|
+
<section aria-labelledby="usage-heading">
|
|
16
|
+
<h2
|
|
17
|
+
id="usage-heading"
|
|
18
|
+
className="text-foreground mb-1 text-sm font-semibold"
|
|
19
|
+
>
|
|
20
|
+
Usage
|
|
21
|
+
</h2>
|
|
22
|
+
<p className="text-muted-foreground mb-4 text-xs">
|
|
23
|
+
Monitor token consumption, cost, and execution activity across
|
|
24
|
+
your organization.
|
|
25
|
+
</p>
|
|
26
|
+
|
|
27
|
+
{mode === "local" ? (
|
|
28
|
+
<CloudFeatureNotice>
|
|
29
|
+
Usage reports are not available in local mode. Connect to Stigmer
|
|
30
|
+
Cloud to view organization-level cost and token analytics.
|
|
31
|
+
</CloudFeatureNotice>
|
|
32
|
+
) : !orgId ? (
|
|
33
|
+
<p className="text-muted-foreground py-4 text-center text-xs">
|
|
34
|
+
Select an organization to view usage.
|
|
35
|
+
</p>
|
|
36
|
+
) : (
|
|
37
|
+
<OrgUsagePanel orgId={orgId} />
|
|
38
|
+
)}
|
|
39
|
+
</section>
|
|
40
|
+
);
|
|
41
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export { SETTINGS_NAV_GROUPS } from "./settings-nav";
|
|
2
|
+
export type { SettingsNavItem, SettingsNavGroup } from "./settings-nav";
|
|
3
|
+
|
|
4
|
+
export { ApiKeysSection } from "./ApiKeysSection";
|
|
5
|
+
export { MembersSection } from "./MembersSection";
|
|
6
|
+
export { OrgProfileSection } from "./OrgProfileSection";
|
|
7
|
+
export { EnvironmentsSection } from "./EnvironmentsSection";
|
|
8
|
+
export { InvitationsSection } from "./InvitationsSection";
|
|
9
|
+
export { IdentityProvidersSection } from "./IdentityProvidersSection";
|
|
10
|
+
export type { IdentityProvidersSectionProps } from "./IdentityProvidersSection";
|
|
11
|
+
export { PlatformClientsSection } from "./PlatformClientsSection";
|
|
12
|
+
export { OAuthAppsSection } from "./OAuthAppsSection";
|
|
13
|
+
export { UsageSection } from "./UsageSection";
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import type { ComponentType } from "react";
|
|
2
|
+
import {
|
|
3
|
+
AppWindow,
|
|
4
|
+
BarChart3,
|
|
5
|
+
Box,
|
|
6
|
+
Building2,
|
|
7
|
+
CreditCard,
|
|
8
|
+
KeyRound,
|
|
9
|
+
Link,
|
|
10
|
+
Plug,
|
|
11
|
+
ShieldCheck,
|
|
12
|
+
Users,
|
|
13
|
+
} from "lucide-react";
|
|
14
|
+
|
|
15
|
+
/** Single navigable entry in the settings sidebar. */
|
|
16
|
+
export interface SettingsNavItem {
|
|
17
|
+
/** Route for the settings page entry. */
|
|
18
|
+
readonly href: string;
|
|
19
|
+
/** Short, user-facing label shown in navigation. */
|
|
20
|
+
readonly label: string;
|
|
21
|
+
/** Lucide icon component rendered next to the label. */
|
|
22
|
+
readonly icon: ComponentType<{
|
|
23
|
+
/** Optional CSS class name applied to the icon. */
|
|
24
|
+
className?: string;
|
|
25
|
+
}>;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/** Grouping model used to render settings navigation sections. */
|
|
29
|
+
export interface SettingsNavGroup {
|
|
30
|
+
/** Group heading shown in the settings navigation. */
|
|
31
|
+
readonly label: string;
|
|
32
|
+
/** Helper text describing the group purpose. */
|
|
33
|
+
readonly description: string;
|
|
34
|
+
/** Entries that belong to this group. */
|
|
35
|
+
readonly items: readonly SettingsNavItem[];
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/** Canonical settings sidebar/grouped navigation model. */
|
|
39
|
+
export const SETTINGS_NAV_GROUPS: readonly SettingsNavGroup[] = [
|
|
40
|
+
{
|
|
41
|
+
label: "Organization",
|
|
42
|
+
description:
|
|
43
|
+
"Manage your team, organization identity, and identity providers.",
|
|
44
|
+
items: [
|
|
45
|
+
{ href: "/settings/org-profile", label: "Org Profile", icon: Building2 },
|
|
46
|
+
{ href: "/settings/members", label: "Members", icon: Users },
|
|
47
|
+
{ href: "/settings/invitations", label: "Invitations", icon: Link },
|
|
48
|
+
{
|
|
49
|
+
href: "/settings/identity-providers",
|
|
50
|
+
label: "Identity Providers",
|
|
51
|
+
icon: ShieldCheck,
|
|
52
|
+
},
|
|
53
|
+
],
|
|
54
|
+
},
|
|
55
|
+
{
|
|
56
|
+
label: "Configuration",
|
|
57
|
+
description:
|
|
58
|
+
"API keys, environment variables, and OAuth app credentials for your integrations.",
|
|
59
|
+
items: [
|
|
60
|
+
{ href: "/settings/api-keys", label: "API Keys", icon: KeyRound },
|
|
61
|
+
{
|
|
62
|
+
href: "/settings/platform-clients",
|
|
63
|
+
label: "Platform Clients",
|
|
64
|
+
icon: Plug,
|
|
65
|
+
},
|
|
66
|
+
{ href: "/settings/environments", label: "Environments", icon: Box },
|
|
67
|
+
{ href: "/settings/oauth-apps", label: "OAuth Apps", icon: AppWindow },
|
|
68
|
+
],
|
|
69
|
+
},
|
|
70
|
+
{
|
|
71
|
+
label: "Billing & Usage",
|
|
72
|
+
description: "Subscription management and usage metrics.",
|
|
73
|
+
items: [
|
|
74
|
+
{ href: "/settings/billing", label: "Billing", icon: CreditCard },
|
|
75
|
+
{ href: "/settings/usage", label: "Usage", icon: BarChart3 },
|
|
76
|
+
],
|
|
77
|
+
},
|
|
78
|
+
];
|