@contractspec/example.saas-boilerplate 3.8.9 → 3.8.11
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/.turbo/turbo-build.log +155 -155
- package/CHANGELOG.md +34 -0
- package/dist/billing/billing.entity.js +1 -113
- package/dist/billing/billing.enum.js +1 -19
- package/dist/billing/billing.event.js +1 -90
- package/dist/billing/billing.handler.js +1 -148
- package/dist/billing/billing.operations.js +1 -278
- package/dist/billing/billing.presentation.js +1 -55
- package/dist/billing/billing.schema.js +1 -121
- package/dist/billing/index.js +1 -691
- package/dist/browser/billing/billing.entity.js +1 -113
- package/dist/browser/billing/billing.enum.js +1 -19
- package/dist/browser/billing/billing.event.js +1 -90
- package/dist/browser/billing/billing.handler.js +1 -148
- package/dist/browser/billing/billing.operations.js +1 -278
- package/dist/browser/billing/billing.presentation.js +1 -55
- package/dist/browser/billing/billing.schema.js +1 -121
- package/dist/browser/billing/index.js +1 -691
- package/dist/browser/dashboard/dashboard.presentation.js +1 -55
- package/dist/browser/dashboard/index.js +1 -55
- package/dist/browser/docs/index.js +5 -49
- package/dist/browser/docs/saas-boilerplate.docblock.js +5 -49
- package/dist/browser/example.js +1 -39
- package/dist/browser/handlers/index.js +2 -358
- package/dist/browser/handlers/saas.handlers.js +2 -134
- package/dist/browser/index.js +9 -3591
- package/dist/browser/presentations/index.js +1 -299
- package/dist/browser/project/index.js +1 -793
- package/dist/browser/project/project.entity.js +1 -77
- package/dist/browser/project/project.enum.js +1 -18
- package/dist/browser/project/project.event.js +1 -103
- package/dist/browser/project/project.handler.js +1 -178
- package/dist/browser/project/project.operations.js +1 -372
- package/dist/browser/project/project.presentation.js +1 -180
- package/dist/browser/project/project.schema.js +1 -134
- package/dist/browser/saas-boilerplate.feature.js +1 -304
- package/dist/browser/seeders/index.js +2 -20
- package/dist/browser/settings/index.js +1 -75
- package/dist/browser/settings/settings.entity.js +1 -74
- package/dist/browser/settings/settings.enum.js +1 -11
- package/dist/browser/shared/mock-data.js +1 -104
- package/dist/browser/tests/operations.test-spec.js +1 -112
- package/dist/browser/ui/SaasDashboard.js +1 -1239
- package/dist/browser/ui/SaasDashboard.visualizations.js +1 -249
- package/dist/browser/ui/SaasProjectList.js +1 -162
- package/dist/browser/ui/SaasSettingsPanel.js +1 -145
- package/dist/browser/ui/hooks/index.js +1 -159
- package/dist/browser/ui/hooks/useProjectList.js +1 -66
- package/dist/browser/ui/hooks/useProjectMutations.js +1 -91
- package/dist/browser/ui/index.js +5 -2077
- package/dist/browser/ui/modals/CreateProjectModal.js +1 -153
- package/dist/browser/ui/modals/ProjectActionsModal.js +1 -335
- package/dist/browser/ui/modals/index.js +1 -487
- package/dist/browser/ui/overlays/demo-overlays.js +1 -61
- package/dist/browser/ui/overlays/index.js +1 -61
- package/dist/browser/ui/renderers/index.js +5 -901
- package/dist/browser/ui/renderers/project-list.markdown.js +5 -725
- package/dist/browser/ui/renderers/project-list.renderer.js +1 -177
- package/dist/browser/visualizations/catalog.js +1 -155
- package/dist/browser/visualizations/index.js +1 -217
- package/dist/browser/visualizations/selectors.js +1 -210
- package/dist/dashboard/dashboard.presentation.js +1 -55
- package/dist/dashboard/index.js +1 -55
- package/dist/docs/index.js +5 -49
- package/dist/docs/saas-boilerplate.docblock.js +5 -49
- package/dist/example.js +1 -39
- package/dist/handlers/index.js +2 -358
- package/dist/handlers/saas.handlers.js +2 -134
- package/dist/index.js +9 -3591
- package/dist/node/billing/billing.entity.js +1 -113
- package/dist/node/billing/billing.enum.js +1 -19
- package/dist/node/billing/billing.event.js +1 -90
- package/dist/node/billing/billing.handler.js +1 -148
- package/dist/node/billing/billing.operations.js +1 -278
- package/dist/node/billing/billing.presentation.js +1 -55
- package/dist/node/billing/billing.schema.js +1 -121
- package/dist/node/billing/index.js +1 -691
- package/dist/node/dashboard/dashboard.presentation.js +1 -55
- package/dist/node/dashboard/index.js +1 -55
- package/dist/node/docs/index.js +5 -49
- package/dist/node/docs/saas-boilerplate.docblock.js +5 -49
- package/dist/node/example.js +1 -39
- package/dist/node/handlers/index.js +2 -358
- package/dist/node/handlers/saas.handlers.js +2 -134
- package/dist/node/index.js +9 -3591
- package/dist/node/presentations/index.js +1 -299
- package/dist/node/project/index.js +1 -793
- package/dist/node/project/project.entity.js +1 -77
- package/dist/node/project/project.enum.js +1 -18
- package/dist/node/project/project.event.js +1 -103
- package/dist/node/project/project.handler.js +1 -178
- package/dist/node/project/project.operations.js +1 -372
- package/dist/node/project/project.presentation.js +1 -180
- package/dist/node/project/project.schema.js +1 -134
- package/dist/node/saas-boilerplate.feature.js +1 -304
- package/dist/node/seeders/index.js +2 -20
- package/dist/node/settings/index.js +1 -75
- package/dist/node/settings/settings.entity.js +1 -74
- package/dist/node/settings/settings.enum.js +1 -11
- package/dist/node/shared/mock-data.js +1 -104
- package/dist/node/tests/operations.test-spec.js +1 -112
- package/dist/node/ui/SaasDashboard.js +1 -1239
- package/dist/node/ui/SaasDashboard.visualizations.js +1 -249
- package/dist/node/ui/SaasProjectList.js +1 -162
- package/dist/node/ui/SaasSettingsPanel.js +1 -145
- package/dist/node/ui/hooks/index.js +1 -159
- package/dist/node/ui/hooks/useProjectList.js +1 -66
- package/dist/node/ui/hooks/useProjectMutations.js +1 -91
- package/dist/node/ui/index.js +5 -2077
- package/dist/node/ui/modals/CreateProjectModal.js +1 -153
- package/dist/node/ui/modals/ProjectActionsModal.js +1 -335
- package/dist/node/ui/modals/index.js +1 -487
- package/dist/node/ui/overlays/demo-overlays.js +1 -61
- package/dist/node/ui/overlays/index.js +1 -61
- package/dist/node/ui/renderers/index.js +5 -901
- package/dist/node/ui/renderers/project-list.markdown.js +5 -725
- package/dist/node/ui/renderers/project-list.renderer.js +1 -177
- package/dist/node/visualizations/catalog.js +1 -155
- package/dist/node/visualizations/index.js +1 -217
- package/dist/node/visualizations/selectors.js +1 -210
- package/dist/presentations/index.js +1 -299
- package/dist/project/index.js +1 -793
- package/dist/project/project.entity.js +1 -77
- package/dist/project/project.enum.js +1 -18
- package/dist/project/project.event.js +1 -103
- package/dist/project/project.handler.js +1 -178
- package/dist/project/project.operations.js +1 -372
- package/dist/project/project.presentation.js +1 -180
- package/dist/project/project.schema.js +1 -134
- package/dist/saas-boilerplate.feature.js +1 -304
- package/dist/seeders/index.js +2 -20
- package/dist/settings/index.js +1 -75
- package/dist/settings/settings.entity.js +1 -74
- package/dist/settings/settings.enum.js +1 -11
- package/dist/shared/mock-data.js +1 -104
- package/dist/tests/operations.test-spec.js +1 -112
- package/dist/ui/SaasDashboard.js +1 -1239
- package/dist/ui/SaasDashboard.visualizations.js +1 -249
- package/dist/ui/SaasProjectList.js +1 -162
- package/dist/ui/SaasSettingsPanel.js +1 -145
- package/dist/ui/hooks/index.js +1 -159
- package/dist/ui/hooks/useProjectList.js +1 -66
- package/dist/ui/hooks/useProjectMutations.js +1 -91
- package/dist/ui/index.js +5 -2077
- package/dist/ui/modals/CreateProjectModal.js +1 -153
- package/dist/ui/modals/ProjectActionsModal.js +1 -335
- package/dist/ui/modals/index.js +1 -487
- package/dist/ui/overlays/demo-overlays.js +1 -61
- package/dist/ui/overlays/index.js +1 -61
- package/dist/ui/renderers/index.js +5 -901
- package/dist/ui/renderers/project-list.markdown.js +5 -725
- package/dist/ui/renderers/project-list.renderer.js +1 -177
- package/dist/visualizations/catalog.js +1 -155
- package/dist/visualizations/index.js +1 -217
- package/dist/visualizations/selectors.js +1 -210
- package/package.json +12 -12
|
@@ -1,249 +1 @@
|
|
|
1
|
-
|
|
2
|
-
import {
|
|
3
|
-
defineVisualization,
|
|
4
|
-
VisualizationRegistry
|
|
5
|
-
} from "@contractspec/lib.contracts-spec/visualizations";
|
|
6
|
-
var PROJECT_LIST_REF = {
|
|
7
|
-
key: "saas.project.list",
|
|
8
|
-
version: "1.0.0"
|
|
9
|
-
};
|
|
10
|
-
var META = {
|
|
11
|
-
version: "1.0.0",
|
|
12
|
-
domain: "saas",
|
|
13
|
-
stability: "experimental",
|
|
14
|
-
owners: ["@example.saas-boilerplate"],
|
|
15
|
-
tags: ["saas", "visualization", "projects"]
|
|
16
|
-
};
|
|
17
|
-
var SaasProjectUsageVisualization = defineVisualization({
|
|
18
|
-
meta: {
|
|
19
|
-
...META,
|
|
20
|
-
key: "saas-boilerplate.visualization.project-usage",
|
|
21
|
-
title: "Project Capacity",
|
|
22
|
-
description: "Current project count against the current plan limit.",
|
|
23
|
-
goal: "Show usage against the active plan allowance.",
|
|
24
|
-
context: "SaaS account overview."
|
|
25
|
-
},
|
|
26
|
-
source: { primary: PROJECT_LIST_REF, resultPath: "data" },
|
|
27
|
-
visualization: {
|
|
28
|
-
kind: "metric",
|
|
29
|
-
measure: "totalProjects",
|
|
30
|
-
comparisonMeasure: "projectLimit",
|
|
31
|
-
measures: [
|
|
32
|
-
{
|
|
33
|
-
key: "totalProjects",
|
|
34
|
-
label: "Projects",
|
|
35
|
-
dataPath: "totalProjects",
|
|
36
|
-
format: "number"
|
|
37
|
-
},
|
|
38
|
-
{
|
|
39
|
-
key: "projectLimit",
|
|
40
|
-
label: "Plan Limit",
|
|
41
|
-
dataPath: "projectLimit",
|
|
42
|
-
format: "number"
|
|
43
|
-
}
|
|
44
|
-
],
|
|
45
|
-
table: { caption: "Current project count and plan limit." }
|
|
46
|
-
}
|
|
47
|
-
});
|
|
48
|
-
var SaasProjectStatusVisualization = defineVisualization({
|
|
49
|
-
meta: {
|
|
50
|
-
...META,
|
|
51
|
-
key: "saas-boilerplate.visualization.project-status",
|
|
52
|
-
title: "Project Status",
|
|
53
|
-
description: "Distribution of project states.",
|
|
54
|
-
goal: "Show the mix of active, draft, and archived projects.",
|
|
55
|
-
context: "Project portfolio overview."
|
|
56
|
-
},
|
|
57
|
-
source: { primary: PROJECT_LIST_REF, resultPath: "data" },
|
|
58
|
-
visualization: {
|
|
59
|
-
kind: "pie",
|
|
60
|
-
nameDimension: "status",
|
|
61
|
-
valueMeasure: "projects",
|
|
62
|
-
dimensions: [
|
|
63
|
-
{ key: "status", label: "Status", dataPath: "status", type: "category" }
|
|
64
|
-
],
|
|
65
|
-
measures: [
|
|
66
|
-
{
|
|
67
|
-
key: "projects",
|
|
68
|
-
label: "Projects",
|
|
69
|
-
dataPath: "projects",
|
|
70
|
-
format: "number"
|
|
71
|
-
}
|
|
72
|
-
],
|
|
73
|
-
table: { caption: "Project counts by status." }
|
|
74
|
-
}
|
|
75
|
-
});
|
|
76
|
-
var SaasProjectTierVisualization = defineVisualization({
|
|
77
|
-
meta: {
|
|
78
|
-
...META,
|
|
79
|
-
key: "saas-boilerplate.visualization.project-tiers",
|
|
80
|
-
title: "Tier Comparison",
|
|
81
|
-
description: "Distribution of projects across tiers.",
|
|
82
|
-
goal: "Compare how the current portfolio is distributed by tier.",
|
|
83
|
-
context: "Plan and packaging overview."
|
|
84
|
-
},
|
|
85
|
-
source: { primary: PROJECT_LIST_REF, resultPath: "data" },
|
|
86
|
-
visualization: {
|
|
87
|
-
kind: "cartesian",
|
|
88
|
-
variant: "bar",
|
|
89
|
-
xDimension: "tier",
|
|
90
|
-
yMeasures: ["projects"],
|
|
91
|
-
dimensions: [
|
|
92
|
-
{ key: "tier", label: "Tier", dataPath: "tier", type: "category" }
|
|
93
|
-
],
|
|
94
|
-
measures: [
|
|
95
|
-
{
|
|
96
|
-
key: "projects",
|
|
97
|
-
label: "Projects",
|
|
98
|
-
dataPath: "projects",
|
|
99
|
-
format: "number",
|
|
100
|
-
color: "#1d4ed8"
|
|
101
|
-
}
|
|
102
|
-
],
|
|
103
|
-
table: { caption: "Project counts by tier." }
|
|
104
|
-
}
|
|
105
|
-
});
|
|
106
|
-
var SaasProjectActivityVisualization = defineVisualization({
|
|
107
|
-
meta: {
|
|
108
|
-
...META,
|
|
109
|
-
key: "saas-boilerplate.visualization.project-activity",
|
|
110
|
-
title: "Recent Project Activity",
|
|
111
|
-
description: "Daily project creation activity.",
|
|
112
|
-
goal: "Show recent project activity over time.",
|
|
113
|
-
context: "Project portfolio trend view."
|
|
114
|
-
},
|
|
115
|
-
source: { primary: PROJECT_LIST_REF, resultPath: "data" },
|
|
116
|
-
visualization: {
|
|
117
|
-
kind: "cartesian",
|
|
118
|
-
variant: "line",
|
|
119
|
-
xDimension: "day",
|
|
120
|
-
yMeasures: ["projects"],
|
|
121
|
-
dimensions: [{ key: "day", label: "Day", dataPath: "day", type: "time" }],
|
|
122
|
-
measures: [
|
|
123
|
-
{
|
|
124
|
-
key: "projects",
|
|
125
|
-
label: "Projects",
|
|
126
|
-
dataPath: "projects",
|
|
127
|
-
format: "number",
|
|
128
|
-
color: "#0f766e"
|
|
129
|
-
}
|
|
130
|
-
],
|
|
131
|
-
table: { caption: "Daily project creation counts." }
|
|
132
|
-
}
|
|
133
|
-
});
|
|
134
|
-
var SaasVisualizationSpecs = [
|
|
135
|
-
SaasProjectUsageVisualization,
|
|
136
|
-
SaasProjectStatusVisualization,
|
|
137
|
-
SaasProjectTierVisualization,
|
|
138
|
-
SaasProjectActivityVisualization
|
|
139
|
-
];
|
|
140
|
-
var SaasVisualizationRegistry = new VisualizationRegistry([
|
|
141
|
-
...SaasVisualizationSpecs
|
|
142
|
-
]);
|
|
143
|
-
var SaasVisualizationRefs = SaasVisualizationSpecs.map((spec) => ({
|
|
144
|
-
key: spec.meta.key,
|
|
145
|
-
version: spec.meta.version
|
|
146
|
-
}));
|
|
147
|
-
|
|
148
|
-
// src/visualizations/selectors.ts
|
|
149
|
-
function toDayKey(value) {
|
|
150
|
-
const date = value instanceof Date ? value : new Date(value);
|
|
151
|
-
return date.toISOString().slice(0, 10);
|
|
152
|
-
}
|
|
153
|
-
function createSaasVisualizationItems(projects, projectLimit = 10) {
|
|
154
|
-
const statusCounts = new Map;
|
|
155
|
-
const tierCounts = new Map;
|
|
156
|
-
const activityCounts = new Map;
|
|
157
|
-
for (const project of projects) {
|
|
158
|
-
statusCounts.set(project.status, (statusCounts.get(project.status) ?? 0) + 1);
|
|
159
|
-
tierCounts.set(project.tier, (tierCounts.get(project.tier) ?? 0) + 1);
|
|
160
|
-
const day = toDayKey(project.createdAt);
|
|
161
|
-
activityCounts.set(day, (activityCounts.get(day) ?? 0) + 1);
|
|
162
|
-
}
|
|
163
|
-
return [
|
|
164
|
-
{
|
|
165
|
-
key: "saas-capacity",
|
|
166
|
-
spec: SaasProjectUsageVisualization,
|
|
167
|
-
data: { data: [{ totalProjects: projects.length, projectLimit }] },
|
|
168
|
-
title: "Project Capacity",
|
|
169
|
-
description: "Current project count compared to the active limit.",
|
|
170
|
-
height: 220
|
|
171
|
-
},
|
|
172
|
-
{
|
|
173
|
-
key: "saas-status",
|
|
174
|
-
spec: SaasProjectStatusVisualization,
|
|
175
|
-
data: {
|
|
176
|
-
data: Array.from(statusCounts.entries()).map(([status, count]) => ({
|
|
177
|
-
status,
|
|
178
|
-
projects: count
|
|
179
|
-
}))
|
|
180
|
-
},
|
|
181
|
-
title: "Project Status",
|
|
182
|
-
description: "Status mix across the current project portfolio.",
|
|
183
|
-
height: 260
|
|
184
|
-
},
|
|
185
|
-
{
|
|
186
|
-
key: "saas-tier",
|
|
187
|
-
spec: SaasProjectTierVisualization,
|
|
188
|
-
data: {
|
|
189
|
-
data: Array.from(tierCounts.entries()).map(([tier, count]) => ({
|
|
190
|
-
tier,
|
|
191
|
-
projects: count
|
|
192
|
-
}))
|
|
193
|
-
},
|
|
194
|
-
title: "Tier Comparison",
|
|
195
|
-
description: "How projects are distributed across tiers."
|
|
196
|
-
},
|
|
197
|
-
{
|
|
198
|
-
key: "saas-activity",
|
|
199
|
-
spec: SaasProjectActivityVisualization,
|
|
200
|
-
data: {
|
|
201
|
-
data: Array.from(activityCounts.entries()).sort(([left], [right]) => left.localeCompare(right)).map(([day, count]) => ({ day, projects: count }))
|
|
202
|
-
},
|
|
203
|
-
title: "Recent Project Activity",
|
|
204
|
-
description: "Daily project creation activity."
|
|
205
|
-
}
|
|
206
|
-
];
|
|
207
|
-
}
|
|
208
|
-
// src/ui/SaasDashboard.visualizations.tsx
|
|
209
|
-
import {
|
|
210
|
-
VisualizationCard,
|
|
211
|
-
VisualizationGrid
|
|
212
|
-
} from "@contractspec/lib.design-system";
|
|
213
|
-
import { jsxDEV } from "react/jsx-dev-runtime";
|
|
214
|
-
"use client";
|
|
215
|
-
function SaasVisualizationOverview({
|
|
216
|
-
projects,
|
|
217
|
-
projectLimit
|
|
218
|
-
}) {
|
|
219
|
-
const items = createSaasVisualizationItems(projects, projectLimit);
|
|
220
|
-
return /* @__PURE__ */ jsxDEV("section", {
|
|
221
|
-
className: "space-y-3",
|
|
222
|
-
children: [
|
|
223
|
-
/* @__PURE__ */ jsxDEV("div", {
|
|
224
|
-
children: [
|
|
225
|
-
/* @__PURE__ */ jsxDEV("h3", {
|
|
226
|
-
className: "font-semibold text-lg",
|
|
227
|
-
children: "Portfolio Visualizations"
|
|
228
|
-
}, undefined, false, undefined, this),
|
|
229
|
-
/* @__PURE__ */ jsxDEV("p", {
|
|
230
|
-
className: "text-muted-foreground text-sm",
|
|
231
|
-
children: "Contract-backed charts for project mix, capacity, and activity."
|
|
232
|
-
}, undefined, false, undefined, this)
|
|
233
|
-
]
|
|
234
|
-
}, undefined, true, undefined, this),
|
|
235
|
-
/* @__PURE__ */ jsxDEV(VisualizationGrid, {
|
|
236
|
-
children: items.map((item) => /* @__PURE__ */ jsxDEV(VisualizationCard, {
|
|
237
|
-
data: item.data,
|
|
238
|
-
description: item.description,
|
|
239
|
-
height: item.height,
|
|
240
|
-
spec: item.spec,
|
|
241
|
-
title: item.title
|
|
242
|
-
}, item.key, false, undefined, this))
|
|
243
|
-
}, undefined, false, undefined, this)
|
|
244
|
-
]
|
|
245
|
-
}, undefined, true, undefined, this);
|
|
246
|
-
}
|
|
247
|
-
export {
|
|
248
|
-
SaasVisualizationOverview
|
|
249
|
-
};
|
|
1
|
+
import{defineVisualization as r,VisualizationRegistry as Y}from"@contractspec/lib.contracts-spec/visualizations";var N={key:"saas.project.list",version:"1.0.0"},p={version:"1.0.0",domain:"saas",stability:"experimental",owners:["@example.saas-boilerplate"],tags:["saas","visualization","projects"]},q=r({meta:{...p,key:"saas-boilerplate.visualization.project-usage",title:"Project Capacity",description:"Current project count against the current plan limit.",goal:"Show usage against the active plan allowance.",context:"SaaS account overview."},source:{primary:N,resultPath:"data"},visualization:{kind:"metric",measure:"totalProjects",comparisonMeasure:"projectLimit",measures:[{key:"totalProjects",label:"Projects",dataPath:"totalProjects",format:"number"},{key:"projectLimit",label:"Plan Limit",dataPath:"projectLimit",format:"number"}],table:{caption:"Current project count and plan limit."}}}),x=r({meta:{...p,key:"saas-boilerplate.visualization.project-status",title:"Project Status",description:"Distribution of project states.",goal:"Show the mix of active, draft, and archived projects.",context:"Project portfolio overview."},source:{primary:N,resultPath:"data"},visualization:{kind:"pie",nameDimension:"status",valueMeasure:"projects",dimensions:[{key:"status",label:"Status",dataPath:"status",type:"category"}],measures:[{key:"projects",label:"Projects",dataPath:"projects",format:"number"}],table:{caption:"Project counts by status."}}}),B=r({meta:{...p,key:"saas-boilerplate.visualization.project-tiers",title:"Tier Comparison",description:"Distribution of projects across tiers.",goal:"Compare how the current portfolio is distributed by tier.",context:"Plan and packaging overview."},source:{primary:N,resultPath:"data"},visualization:{kind:"cartesian",variant:"bar",xDimension:"tier",yMeasures:["projects"],dimensions:[{key:"tier",label:"Tier",dataPath:"tier",type:"category"}],measures:[{key:"projects",label:"Projects",dataPath:"projects",format:"number",color:"#1d4ed8"}],table:{caption:"Project counts by tier."}}}),H=r({meta:{...p,key:"saas-boilerplate.visualization.project-activity",title:"Recent Project Activity",description:"Daily project creation activity.",goal:"Show recent project activity over time.",context:"Project portfolio trend view."},source:{primary:N,resultPath:"data"},visualization:{kind:"cartesian",variant:"line",xDimension:"day",yMeasures:["projects"],dimensions:[{key:"day",label:"Day",dataPath:"day",type:"time"}],measures:[{key:"projects",label:"Projects",dataPath:"projects",format:"number",color:"#0f766e"}],table:{caption:"Daily project creation counts."}}}),Q=[q,x,B,H],K=new Y([...Q]),U=Q.map((d)=>({key:d.meta.key,version:d.meta.version}));function Z(d){return(d instanceof Date?d:new Date(d)).toISOString().slice(0,10)}function W(d,k=10){let b=new Map,h=new Map,w=new Map;for(let m of d){b.set(m.status,(b.get(m.status)??0)+1),h.set(m.tier,(h.get(m.tier)??0)+1);let f=Z(m.createdAt);w.set(f,(w.get(f)??0)+1)}return[{key:"saas-capacity",spec:q,data:{data:[{totalProjects:d.length,projectLimit:k}]},title:"Project Capacity",description:"Current project count compared to the active limit.",height:220},{key:"saas-status",spec:x,data:{data:Array.from(b.entries()).map(([m,f])=>({status:m,projects:f}))},title:"Project Status",description:"Status mix across the current project portfolio.",height:260},{key:"saas-tier",spec:B,data:{data:Array.from(h.entries()).map(([m,f])=>({tier:m,projects:f}))},title:"Tier Comparison",description:"How projects are distributed across tiers."},{key:"saas-activity",spec:H,data:{data:Array.from(w.entries()).sort(([m],[f])=>m.localeCompare(f)).map(([m,f])=>({day:m,projects:f}))},title:"Recent Project Activity",description:"Daily project creation activity."}]}import{VisualizationCard as $,VisualizationGrid as g}from"@contractspec/lib.design-system";import{jsx as G,jsxs as X}from"react/jsx-runtime";function y({projects:d,projectLimit:k}){let b=W(d,k);return X("section",{className:"space-y-3",children:[X("div",{children:[G("h3",{className:"font-semibold text-lg",children:"Portfolio Visualizations"}),G("p",{className:"text-muted-foreground text-sm",children:"Contract-backed charts for project mix, capacity, and activity."})]}),G(g,{children:b.map((h)=>G($,{data:h.data,description:h.description,height:h.height,spec:h.spec,title:h.title},h.key))})]})}export{y as SaasVisualizationOverview};
|
|
@@ -1,162 +1 @@
|
|
|
1
|
-
|
|
2
|
-
import { useTemplateRuntime } from "@contractspec/lib.example-shared-ui";
|
|
3
|
-
import { useCallback, useEffect, useMemo, useState } from "react";
|
|
4
|
-
function useProjectList(options = {}) {
|
|
5
|
-
const { handlers, projectId } = useTemplateRuntime();
|
|
6
|
-
const { saas } = handlers;
|
|
7
|
-
const [data, setData] = useState(null);
|
|
8
|
-
const [subscription, setSubscription] = useState(null);
|
|
9
|
-
const [loading, setLoading] = useState(true);
|
|
10
|
-
const [error, setError] = useState(null);
|
|
11
|
-
const [page, setPage] = useState(1);
|
|
12
|
-
const fetchData = useCallback(async () => {
|
|
13
|
-
setLoading(true);
|
|
14
|
-
setError(null);
|
|
15
|
-
try {
|
|
16
|
-
const [projectsResult, subscriptionResult] = await Promise.all([
|
|
17
|
-
saas.listProjects({
|
|
18
|
-
projectId,
|
|
19
|
-
status: options.status === "all" ? undefined : options.status,
|
|
20
|
-
search: options.search,
|
|
21
|
-
limit: options.limit ?? 20,
|
|
22
|
-
offset: (page - 1) * (options.limit ?? 20)
|
|
23
|
-
}),
|
|
24
|
-
saas.getSubscription({ projectId })
|
|
25
|
-
]);
|
|
26
|
-
setData({
|
|
27
|
-
items: projectsResult.items,
|
|
28
|
-
total: projectsResult.total
|
|
29
|
-
});
|
|
30
|
-
setSubscription(subscriptionResult);
|
|
31
|
-
} catch (err) {
|
|
32
|
-
setError(err instanceof Error ? err : new Error("Unknown error"));
|
|
33
|
-
} finally {
|
|
34
|
-
setLoading(false);
|
|
35
|
-
}
|
|
36
|
-
}, [saas, projectId, options.status, options.search, options.limit, page]);
|
|
37
|
-
useEffect(() => {
|
|
38
|
-
fetchData();
|
|
39
|
-
}, [fetchData]);
|
|
40
|
-
const stats = useMemo(() => {
|
|
41
|
-
if (!data)
|
|
42
|
-
return null;
|
|
43
|
-
const items = data.items;
|
|
44
|
-
return {
|
|
45
|
-
total: data.total,
|
|
46
|
-
activeCount: items.filter((p) => p.status === "ACTIVE").length,
|
|
47
|
-
draftCount: items.filter((p) => p.status === "DRAFT").length,
|
|
48
|
-
projectLimit: 10,
|
|
49
|
-
usagePercent: Math.min(data.total / 10 * 100, 100)
|
|
50
|
-
};
|
|
51
|
-
}, [data]);
|
|
52
|
-
return {
|
|
53
|
-
data,
|
|
54
|
-
subscription,
|
|
55
|
-
loading,
|
|
56
|
-
error,
|
|
57
|
-
stats,
|
|
58
|
-
page,
|
|
59
|
-
refetch: fetchData,
|
|
60
|
-
nextPage: () => setPage((p) => p + 1),
|
|
61
|
-
prevPage: () => page > 1 && setPage((p) => p - 1)
|
|
62
|
-
};
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
// src/ui/SaasProjectList.tsx
|
|
66
|
-
import {
|
|
67
|
-
Button,
|
|
68
|
-
EmptyState,
|
|
69
|
-
EntityCard,
|
|
70
|
-
ErrorState,
|
|
71
|
-
LoaderBlock,
|
|
72
|
-
StatCard,
|
|
73
|
-
StatCardGroup,
|
|
74
|
-
StatusChip
|
|
75
|
-
} from "@contractspec/lib.design-system";
|
|
76
|
-
import { jsxDEV } from "react/jsx-dev-runtime";
|
|
77
|
-
"use client";
|
|
78
|
-
function getStatusTone(status) {
|
|
79
|
-
switch (status) {
|
|
80
|
-
case "ACTIVE":
|
|
81
|
-
return "success";
|
|
82
|
-
case "DRAFT":
|
|
83
|
-
return "neutral";
|
|
84
|
-
case "ARCHIVED":
|
|
85
|
-
return "danger";
|
|
86
|
-
default:
|
|
87
|
-
return "neutral";
|
|
88
|
-
}
|
|
89
|
-
}
|
|
90
|
-
function SaasProjectList({
|
|
91
|
-
onProjectClick,
|
|
92
|
-
onCreateProject
|
|
93
|
-
}) {
|
|
94
|
-
const { data, loading, error, stats, refetch } = useProjectList();
|
|
95
|
-
if (loading && !data) {
|
|
96
|
-
return /* @__PURE__ */ jsxDEV(LoaderBlock, {
|
|
97
|
-
label: "Loading projects..."
|
|
98
|
-
}, undefined, false, undefined, this);
|
|
99
|
-
}
|
|
100
|
-
if (error) {
|
|
101
|
-
return /* @__PURE__ */ jsxDEV(ErrorState, {
|
|
102
|
-
title: "Failed to load projects",
|
|
103
|
-
description: error.message,
|
|
104
|
-
onRetry: refetch,
|
|
105
|
-
retryLabel: "Retry"
|
|
106
|
-
}, undefined, false, undefined, this);
|
|
107
|
-
}
|
|
108
|
-
if (!data?.items.length) {
|
|
109
|
-
return /* @__PURE__ */ jsxDEV(EmptyState, {
|
|
110
|
-
title: "No projects found",
|
|
111
|
-
description: "Create your first project to get started.",
|
|
112
|
-
primaryAction: onCreateProject ? /* @__PURE__ */ jsxDEV(Button, {
|
|
113
|
-
onPress: onCreateProject,
|
|
114
|
-
children: "Create Project"
|
|
115
|
-
}, undefined, false, undefined, this) : undefined
|
|
116
|
-
}, undefined, false, undefined, this);
|
|
117
|
-
}
|
|
118
|
-
return /* @__PURE__ */ jsxDEV("div", {
|
|
119
|
-
className: "space-y-6",
|
|
120
|
-
children: [
|
|
121
|
-
stats && /* @__PURE__ */ jsxDEV(StatCardGroup, {
|
|
122
|
-
children: [
|
|
123
|
-
/* @__PURE__ */ jsxDEV(StatCard, {
|
|
124
|
-
label: "Total Projects",
|
|
125
|
-
value: stats.total.toString()
|
|
126
|
-
}, undefined, false, undefined, this),
|
|
127
|
-
/* @__PURE__ */ jsxDEV(StatCard, {
|
|
128
|
-
label: "Active",
|
|
129
|
-
value: stats.activeCount.toString()
|
|
130
|
-
}, undefined, false, undefined, this),
|
|
131
|
-
/* @__PURE__ */ jsxDEV(StatCard, {
|
|
132
|
-
label: "Draft",
|
|
133
|
-
value: stats.draftCount.toString()
|
|
134
|
-
}, undefined, false, undefined, this)
|
|
135
|
-
]
|
|
136
|
-
}, undefined, true, undefined, this),
|
|
137
|
-
/* @__PURE__ */ jsxDEV("div", {
|
|
138
|
-
className: "grid gap-4 md:grid-cols-2 lg:grid-cols-3",
|
|
139
|
-
children: data.items.map((project) => /* @__PURE__ */ jsxDEV(EntityCard, {
|
|
140
|
-
cardTitle: project.name,
|
|
141
|
-
cardSubtitle: project.tier,
|
|
142
|
-
meta: /* @__PURE__ */ jsxDEV("p", {
|
|
143
|
-
className: "text-muted-foreground text-sm",
|
|
144
|
-
children: project.description
|
|
145
|
-
}, undefined, false, undefined, this),
|
|
146
|
-
chips: /* @__PURE__ */ jsxDEV(StatusChip, {
|
|
147
|
-
tone: getStatusTone(project.status),
|
|
148
|
-
label: project.status
|
|
149
|
-
}, undefined, false, undefined, this),
|
|
150
|
-
footer: /* @__PURE__ */ jsxDEV("span", {
|
|
151
|
-
className: "text-muted-foreground text-xs",
|
|
152
|
-
children: project.updatedAt.toLocaleDateString()
|
|
153
|
-
}, undefined, false, undefined, this),
|
|
154
|
-
onClick: onProjectClick ? () => onProjectClick(project.id) : undefined
|
|
155
|
-
}, project.id, false, undefined, this))
|
|
156
|
-
}, undefined, false, undefined, this)
|
|
157
|
-
]
|
|
158
|
-
}, undefined, true, undefined, this);
|
|
159
|
-
}
|
|
160
|
-
export {
|
|
161
|
-
SaasProjectList
|
|
162
|
-
};
|
|
1
|
+
import{useTemplateRuntime as T}from"@contractspec/lib.example-shared-ui";import{useCallback as y,useEffect as I,useMemo as D,useState as N}from"react";function _(q={}){let{handlers:O,projectId:F}=T(),{saas:J}=O,[A,H]=N(null),[U,z]=N(null),[G,X]=N(!0),[M,Y]=N(null),[Q,Z]=N(1),V=y(async()=>{X(!0),Y(null);try{let[v,K]=await Promise.all([J.listProjects({projectId:F,status:q.status==="all"?void 0:q.status,search:q.search,limit:q.limit??20,offset:(Q-1)*(q.limit??20)}),J.getSubscription({projectId:F})]);H({items:v.items,total:v.total}),z(K)}catch(v){Y(v instanceof Error?v:Error("Unknown error"))}finally{X(!1)}},[J,F,q.status,q.search,q.limit,Q]);I(()=>{V()},[V]);let B=D(()=>{if(!A)return null;let v=A.items;return{total:A.total,activeCount:v.filter((K)=>K.status==="ACTIVE").length,draftCount:v.filter((K)=>K.status==="DRAFT").length,projectLimit:10,usagePercent:Math.min(A.total/10*100,100)}},[A]);return{data:A,subscription:U,loading:G,error:M,stats:B,page:Q,refetch:V,nextPage:()=>Z((v)=>v+1),prevPage:()=>Q>1&&Z((v)=>v-1)}}import{Button as R,EmptyState as b,EntityCard as f,ErrorState as E,LoaderBlock as L,StatCard as W,StatCardGroup as k,StatusChip as h}from"@contractspec/lib.design-system";import{jsx as w,jsxs as $}from"react/jsx-runtime";function m(q){switch(q){case"ACTIVE":return"success";case"DRAFT":return"neutral";case"ARCHIVED":return"danger";default:return"neutral"}}function l({onProjectClick:q,onCreateProject:O}){let{data:F,loading:J,error:A,stats:H,refetch:U}=_();if(J&&!F)return w(L,{label:"Loading projects..."});if(A)return w(E,{title:"Failed to load projects",description:A.message,onRetry:U,retryLabel:"Retry"});if(!F?.items.length)return w(b,{title:"No projects found",description:"Create your first project to get started.",primaryAction:O?w(R,{onPress:O,children:"Create Project"}):void 0});return $("div",{className:"space-y-6",children:[H&&$(k,{children:[w(W,{label:"Total Projects",value:H.total.toString()}),w(W,{label:"Active",value:H.activeCount.toString()}),w(W,{label:"Draft",value:H.draftCount.toString()})]}),w("div",{className:"grid gap-4 md:grid-cols-2 lg:grid-cols-3",children:F.items.map((z)=>w(f,{cardTitle:z.name,cardSubtitle:z.tier,meta:w("p",{className:"text-muted-foreground text-sm",children:z.description}),chips:w(h,{tone:m(z.status),label:z.status}),footer:w("span",{className:"text-muted-foreground text-xs",children:z.updatedAt.toLocaleDateString()}),onClick:q?()=>q(z.id):void 0},z.id))})]})}export{l as SaasProjectList};
|
|
@@ -1,145 +1 @@
|
|
|
1
|
-
|
|
2
|
-
import { Button } from "@contractspec/lib.design-system";
|
|
3
|
-
import { useState } from "react";
|
|
4
|
-
import { jsxDEV } from "react/jsx-dev-runtime";
|
|
5
|
-
"use client";
|
|
6
|
-
function SaasSettingsPanel() {
|
|
7
|
-
const [orgName, setOrgName] = useState("Demo Organization");
|
|
8
|
-
const [timezone, setTimezone] = useState("UTC");
|
|
9
|
-
return /* @__PURE__ */ jsxDEV("div", {
|
|
10
|
-
className: "space-y-6",
|
|
11
|
-
children: [
|
|
12
|
-
/* @__PURE__ */ jsxDEV("div", {
|
|
13
|
-
className: "rounded-xl border border-border bg-card p-6",
|
|
14
|
-
children: [
|
|
15
|
-
/* @__PURE__ */ jsxDEV("h3", {
|
|
16
|
-
className: "mb-4 font-semibold text-lg",
|
|
17
|
-
children: "Organization Settings"
|
|
18
|
-
}, undefined, false, undefined, this),
|
|
19
|
-
/* @__PURE__ */ jsxDEV("div", {
|
|
20
|
-
className: "space-y-4",
|
|
21
|
-
children: [
|
|
22
|
-
/* @__PURE__ */ jsxDEV("div", {
|
|
23
|
-
children: [
|
|
24
|
-
/* @__PURE__ */ jsxDEV("label", {
|
|
25
|
-
htmlFor: "setting-org-name",
|
|
26
|
-
className: "block font-medium text-sm",
|
|
27
|
-
children: "Organization Name"
|
|
28
|
-
}, undefined, false, undefined, this),
|
|
29
|
-
/* @__PURE__ */ jsxDEV("input", {
|
|
30
|
-
id: "setting-org-name",
|
|
31
|
-
type: "text",
|
|
32
|
-
value: orgName,
|
|
33
|
-
onChange: (e) => setOrgName(e.target.value),
|
|
34
|
-
className: "mt-1 block w-full rounded-md border border-input bg-background px-3 py-2"
|
|
35
|
-
}, undefined, false, undefined, this)
|
|
36
|
-
]
|
|
37
|
-
}, undefined, true, undefined, this),
|
|
38
|
-
/* @__PURE__ */ jsxDEV("div", {
|
|
39
|
-
children: [
|
|
40
|
-
/* @__PURE__ */ jsxDEV("label", {
|
|
41
|
-
htmlFor: "setting-timezone",
|
|
42
|
-
className: "block font-medium text-sm",
|
|
43
|
-
children: "Default Timezone"
|
|
44
|
-
}, undefined, false, undefined, this),
|
|
45
|
-
/* @__PURE__ */ jsxDEV("select", {
|
|
46
|
-
id: "setting-timezone",
|
|
47
|
-
value: timezone,
|
|
48
|
-
onChange: (e) => setTimezone(e.target.value),
|
|
49
|
-
className: "mt-1 block w-full rounded-md border border-input bg-background px-3 py-2",
|
|
50
|
-
children: [
|
|
51
|
-
/* @__PURE__ */ jsxDEV("option", {
|
|
52
|
-
value: "UTC",
|
|
53
|
-
children: "UTC"
|
|
54
|
-
}, undefined, false, undefined, this),
|
|
55
|
-
/* @__PURE__ */ jsxDEV("option", {
|
|
56
|
-
value: "America/New_York",
|
|
57
|
-
children: "America/New_York"
|
|
58
|
-
}, undefined, false, undefined, this),
|
|
59
|
-
/* @__PURE__ */ jsxDEV("option", {
|
|
60
|
-
value: "Europe/London",
|
|
61
|
-
children: "Europe/London"
|
|
62
|
-
}, undefined, false, undefined, this),
|
|
63
|
-
/* @__PURE__ */ jsxDEV("option", {
|
|
64
|
-
value: "Asia/Tokyo",
|
|
65
|
-
children: "Asia/Tokyo"
|
|
66
|
-
}, undefined, false, undefined, this)
|
|
67
|
-
]
|
|
68
|
-
}, undefined, true, undefined, this)
|
|
69
|
-
]
|
|
70
|
-
}, undefined, true, undefined, this)
|
|
71
|
-
]
|
|
72
|
-
}, undefined, true, undefined, this),
|
|
73
|
-
/* @__PURE__ */ jsxDEV("div", {
|
|
74
|
-
className: "mt-6",
|
|
75
|
-
children: /* @__PURE__ */ jsxDEV(Button, {
|
|
76
|
-
variant: "default",
|
|
77
|
-
children: "Save Changes"
|
|
78
|
-
}, undefined, false, undefined, this)
|
|
79
|
-
}, undefined, false, undefined, this)
|
|
80
|
-
]
|
|
81
|
-
}, undefined, true, undefined, this),
|
|
82
|
-
/* @__PURE__ */ jsxDEV("div", {
|
|
83
|
-
className: "rounded-xl border border-border bg-card p-6",
|
|
84
|
-
children: [
|
|
85
|
-
/* @__PURE__ */ jsxDEV("h3", {
|
|
86
|
-
className: "mb-4 font-semibold text-lg",
|
|
87
|
-
children: "Notifications"
|
|
88
|
-
}, undefined, false, undefined, this),
|
|
89
|
-
/* @__PURE__ */ jsxDEV("div", {
|
|
90
|
-
className: "space-y-3",
|
|
91
|
-
children: [
|
|
92
|
-
{ label: "Email notifications", defaultChecked: true },
|
|
93
|
-
{ label: "Usage alerts", defaultChecked: true },
|
|
94
|
-
{ label: "Weekly digest", defaultChecked: false }
|
|
95
|
-
].map((item) => /* @__PURE__ */ jsxDEV("label", {
|
|
96
|
-
className: "flex items-center gap-3",
|
|
97
|
-
children: [
|
|
98
|
-
/* @__PURE__ */ jsxDEV("input", {
|
|
99
|
-
type: "checkbox",
|
|
100
|
-
defaultChecked: item.defaultChecked,
|
|
101
|
-
className: "h-4 w-4 rounded border-input"
|
|
102
|
-
}, undefined, false, undefined, this),
|
|
103
|
-
/* @__PURE__ */ jsxDEV("span", {
|
|
104
|
-
className: "text-sm",
|
|
105
|
-
children: item.label
|
|
106
|
-
}, undefined, false, undefined, this)
|
|
107
|
-
]
|
|
108
|
-
}, item.label, true, undefined, this))
|
|
109
|
-
}, undefined, false, undefined, this)
|
|
110
|
-
]
|
|
111
|
-
}, undefined, true, undefined, this),
|
|
112
|
-
/* @__PURE__ */ jsxDEV("div", {
|
|
113
|
-
className: "rounded-xl border border-red-200 bg-red-50 p-6 dark:border-red-900 dark:bg-red-950/20",
|
|
114
|
-
children: [
|
|
115
|
-
/* @__PURE__ */ jsxDEV("h3", {
|
|
116
|
-
className: "mb-2 font-semibold text-lg text-red-700 dark:text-red-400",
|
|
117
|
-
children: "Danger Zone"
|
|
118
|
-
}, undefined, false, undefined, this),
|
|
119
|
-
/* @__PURE__ */ jsxDEV("p", {
|
|
120
|
-
className: "mb-4 text-red-600 text-sm dark:text-red-300",
|
|
121
|
-
children: "These actions are irreversible. Please proceed with caution."
|
|
122
|
-
}, undefined, false, undefined, this),
|
|
123
|
-
/* @__PURE__ */ jsxDEV("div", {
|
|
124
|
-
className: "flex gap-3",
|
|
125
|
-
children: [
|
|
126
|
-
/* @__PURE__ */ jsxDEV(Button, {
|
|
127
|
-
variant: "secondary",
|
|
128
|
-
size: "sm",
|
|
129
|
-
children: "Export Data"
|
|
130
|
-
}, undefined, false, undefined, this),
|
|
131
|
-
/* @__PURE__ */ jsxDEV(Button, {
|
|
132
|
-
variant: "secondary",
|
|
133
|
-
size: "sm",
|
|
134
|
-
children: "Delete Organization"
|
|
135
|
-
}, undefined, false, undefined, this)
|
|
136
|
-
]
|
|
137
|
-
}, undefined, true, undefined, this)
|
|
138
|
-
]
|
|
139
|
-
}, undefined, true, undefined, this)
|
|
140
|
-
]
|
|
141
|
-
}, undefined, true, undefined, this);
|
|
142
|
-
}
|
|
143
|
-
export {
|
|
144
|
-
SaasSettingsPanel
|
|
145
|
-
};
|
|
1
|
+
import{Button as q}from"@contractspec/lib.design-system";import{useState as v}from"react";import{jsx as f,jsxs as h}from"react/jsx-runtime";function G(){let[w,A]=v("Demo Organization"),[C,D]=v("UTC");return h("div",{className:"space-y-6",children:[h("div",{className:"rounded-xl border border-border bg-card p-6",children:[f("h3",{className:"mb-4 font-semibold text-lg",children:"Organization Settings"}),h("div",{className:"space-y-4",children:[h("div",{children:[f("label",{htmlFor:"setting-org-name",className:"block font-medium text-sm",children:"Organization Name"}),f("input",{id:"setting-org-name",type:"text",value:w,onChange:(k)=>A(k.target.value),className:"mt-1 block w-full rounded-md border border-input bg-background px-3 py-2"})]}),h("div",{children:[f("label",{htmlFor:"setting-timezone",className:"block font-medium text-sm",children:"Default Timezone"}),h("select",{id:"setting-timezone",value:C,onChange:(k)=>D(k.target.value),className:"mt-1 block w-full rounded-md border border-input bg-background px-3 py-2",children:[f("option",{value:"UTC",children:"UTC"}),f("option",{value:"America/New_York",children:"America/New_York"}),f("option",{value:"Europe/London",children:"Europe/London"}),f("option",{value:"Asia/Tokyo",children:"Asia/Tokyo"})]})]})]}),f("div",{className:"mt-6",children:f(q,{variant:"default",children:"Save Changes"})})]}),h("div",{className:"rounded-xl border border-border bg-card p-6",children:[f("h3",{className:"mb-4 font-semibold text-lg",children:"Notifications"}),f("div",{className:"space-y-3",children:[{label:"Email notifications",defaultChecked:!0},{label:"Usage alerts",defaultChecked:!0},{label:"Weekly digest",defaultChecked:!1}].map((k)=>h("label",{className:"flex items-center gap-3",children:[f("input",{type:"checkbox",defaultChecked:k.defaultChecked,className:"h-4 w-4 rounded border-input"}),f("span",{className:"text-sm",children:k.label})]},k.label))})]}),h("div",{className:"rounded-xl border border-red-200 bg-red-50 p-6 dark:border-red-900 dark:bg-red-950/20",children:[f("h3",{className:"mb-2 font-semibold text-lg text-red-700 dark:text-red-400",children:"Danger Zone"}),f("p",{className:"mb-4 text-red-600 text-sm dark:text-red-300",children:"These actions are irreversible. Please proceed with caution."}),h("div",{className:"flex gap-3",children:[f(q,{variant:"secondary",size:"sm",children:"Export Data"}),f(q,{variant:"secondary",size:"sm",children:"Delete Organization"})]})]})]})}export{G as SaasSettingsPanel};
|