@growthub/cli 0.13.4 → 0.13.6
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/assets/worker-kits/growthub-custom-workspace-starter-v1/QUICKSTART.md +19 -0
- package/assets/worker-kits/growthub-custom-workspace-starter-v1/apps/workspace/.env.example +8 -0
- package/assets/worker-kits/growthub-custom-workspace-starter-v1/apps/workspace/README.md +4 -0
- package/assets/worker-kits/growthub-custom-workspace-starter-v1/apps/workspace/app/api/workspace/integrations/nango/action/execute/route.js +60 -0
- package/assets/worker-kits/growthub-custom-workspace-starter-v1/apps/workspace/app/api/workspace/integrations/nango/actions/route.js +50 -0
- package/assets/worker-kits/growthub-custom-workspace-starter-v1/apps/workspace/app/api/workspace/integrations/nango/connect-session/route.js +68 -0
- package/assets/worker-kits/growthub-custom-workspace-starter-v1/apps/workspace/app/api/workspace/integrations/nango/connection-status/route.js +56 -0
- package/assets/worker-kits/growthub-custom-workspace-starter-v1/apps/workspace/app/api/workspace/integrations/nango/proxy/route.js +67 -0
- package/assets/worker-kits/growthub-custom-workspace-starter-v1/apps/workspace/app/api/workspace/integrations/nango/status/route.js +50 -0
- package/assets/worker-kits/growthub-custom-workspace-starter-v1/apps/workspace/app/api/workspace/metadata-graph/route.js +184 -0
- package/assets/worker-kits/growthub-custom-workspace-starter-v1/apps/workspace/app/api/workspace/sandbox-run/route.js +25 -2
- package/assets/worker-kits/growthub-custom-workspace-starter-v1/apps/workspace/app/data-model/components/AgentSwarmPanel.jsx +326 -0
- package/assets/worker-kits/growthub-custom-workspace-starter-v1/apps/workspace/app/data-model/components/DataModelShell.jsx +161 -50
- package/assets/worker-kits/growthub-custom-workspace-starter-v1/apps/workspace/app/data-model/components/NangoConnectionPanel.jsx +496 -0
- package/assets/worker-kits/growthub-custom-workspace-starter-v1/apps/workspace/app/data-model/components/OrchestrationGraphEmptyCanvas.jsx +6 -0
- package/assets/worker-kits/growthub-custom-workspace-starter-v1/apps/workspace/app/data-model/components/OrchestrationNodeConfigPanel.jsx +88 -1
- package/assets/worker-kits/growthub-custom-workspace-starter-v1/apps/workspace/app/data-model/components/OrchestrationRunTracePanel.jsx +41 -0
- package/assets/worker-kits/growthub-custom-workspace-starter-v1/apps/workspace/app/data-model/components/WorkspaceGraphInspectorPanel.jsx +226 -0
- package/assets/worker-kits/growthub-custom-workspace-starter-v1/apps/workspace/app/globals.css +120 -17
- package/assets/worker-kits/growthub-custom-workspace-starter-v1/apps/workspace/app/settings/integrations/nango/page.jsx +167 -0
- package/assets/worker-kits/growthub-custom-workspace-starter-v1/apps/workspace/app/settings/integrations/page.jsx +1 -0
- package/assets/worker-kits/growthub-custom-workspace-starter-v1/apps/workspace/app/workflows/WorkflowSurface.jsx +67 -11
- package/assets/worker-kits/growthub-custom-workspace-starter-v1/apps/workspace/app/workspace-builder.jsx +31 -10
- package/assets/worker-kits/growthub-custom-workspace-starter-v1/apps/workspace/app/workspace-rail.jsx +16 -14
- package/assets/worker-kits/growthub-custom-workspace-starter-v1/apps/workspace/lib/adapters/env.js +7 -0
- package/assets/worker-kits/growthub-custom-workspace-starter-v1/apps/workspace/lib/adapters/integrations/nango/index.js +38 -0
- package/assets/worker-kits/growthub-custom-workspace-starter-v1/apps/workspace/lib/adapters/integrations/nango/nango-adapter.js +552 -0
- package/assets/worker-kits/growthub-custom-workspace-starter-v1/apps/workspace/lib/adapters/integrations/nango/nango-config-loader.js +202 -0
- package/assets/worker-kits/growthub-custom-workspace-starter-v1/apps/workspace/lib/adapters/integrations/nango/nango-schema.js +303 -0
- package/assets/worker-kits/growthub-custom-workspace-starter-v1/apps/workspace/lib/adapters/integrations/resolver-loader.js +49 -10
- package/assets/worker-kits/growthub-custom-workspace-starter-v1/apps/workspace/lib/adapters/integrations/source-resolver-registry.js +1 -1
- package/assets/worker-kits/growthub-custom-workspace-starter-v1/apps/workspace/lib/adapters/integrations/templates/nango.js +49 -0
- package/assets/worker-kits/growthub-custom-workspace-starter-v1/apps/workspace/lib/adapters/integrations/templates/template-registry.js +4 -2
- package/assets/worker-kits/growthub-custom-workspace-starter-v1/apps/workspace/lib/orchestration-agent-swarm.js +923 -0
- package/assets/worker-kits/growthub-custom-workspace-starter-v1/apps/workspace/lib/orchestration-graph-runner.js +14 -1
- package/assets/worker-kits/growthub-custom-workspace-starter-v1/apps/workspace/lib/orchestration-graph.js +218 -7
- package/assets/worker-kits/growthub-custom-workspace-starter-v1/apps/workspace/lib/orchestration-run-console.js +28 -0
- package/assets/worker-kits/growthub-custom-workspace-starter-v1/apps/workspace/lib/orchestration-run-inputs.js +43 -0
- package/assets/worker-kits/growthub-custom-workspace-starter-v1/apps/workspace/lib/orchestration-run-trace.js +3 -1
- package/assets/worker-kits/growthub-custom-workspace-starter-v1/apps/workspace/lib/sandbox-agent-auth.js +36 -0
- package/assets/worker-kits/growthub-custom-workspace-starter-v1/apps/workspace/lib/workspace-chart-values.js +53 -0
- package/assets/worker-kits/growthub-custom-workspace-starter-v1/apps/workspace/lib/workspace-data-model.js +2 -1
- package/assets/worker-kits/growthub-custom-workspace-starter-v1/apps/workspace/lib/workspace-metadata-graph.js +646 -0
- package/assets/worker-kits/growthub-custom-workspace-starter-v1/apps/workspace/lib/workspace-metadata-selectors.js +249 -0
- package/assets/worker-kits/growthub-custom-workspace-starter-v1/apps/workspace/lib/workspace-metadata-store.js +1186 -0
- package/assets/worker-kits/growthub-custom-workspace-starter-v1/apps/workspace/lib/workspace-schema.js +102 -3
- package/assets/worker-kits/growthub-custom-workspace-starter-v1/apps/workspace/package.json +1 -0
- package/assets/worker-kits/growthub-custom-workspace-starter-v1/bundles/growthub-custom-workspace-starter-v1.json +1 -0
- package/assets/worker-kits/growthub-custom-workspace-starter-v1/kit.json +7 -0
- package/assets/worker-kits/growthub-custom-workspace-starter-v1/templates/seeded-configs/project-management.config.json +276 -0
- package/dist/index.js +127 -44
- package/package.json +1 -1
|
@@ -31,9 +31,11 @@ import { findSandboxRowByWorkflowRef } from "@/lib/nav-workflows";
|
|
|
31
31
|
import {
|
|
32
32
|
addCanonicalNodeToGraph,
|
|
33
33
|
buildBlankOrchestrationGraphShell,
|
|
34
|
+
buildDefaultAgentSwarmGraph,
|
|
34
35
|
buildDefaultOrchestrationGraphFromRegistry,
|
|
35
36
|
getNextCanonicalNodeId,
|
|
36
37
|
getOrchestrationGraphUiState,
|
|
38
|
+
isAgentSwarmGraph,
|
|
37
39
|
parseOrchestrationGraph,
|
|
38
40
|
redactSecretsFromText,
|
|
39
41
|
serializeOrchestrationGraph,
|
|
@@ -45,11 +47,22 @@ import { OrchestrationGraphCanvas } from "../data-model/components/Orchestration
|
|
|
45
47
|
import { OrchestrationGraphEmptyCanvas } from "../data-model/components/OrchestrationGraphEmptyCanvas.jsx";
|
|
46
48
|
import { OrchestrationNodeConfigPanel } from "../data-model/components/OrchestrationNodeConfigPanel.jsx";
|
|
47
49
|
import { OrchestrationRunTracePanel } from "../data-model/components/OrchestrationRunTracePanel.jsx";
|
|
50
|
+
import { AgentSwarmPanel } from "../data-model/components/AgentSwarmPanel.jsx";
|
|
48
51
|
import { RunSetupPanel } from "./RunSetupPanel.jsx";
|
|
49
|
-
import { discoverRunInputSchema } from "@/lib/orchestration-run-inputs";
|
|
52
|
+
import { describeRunInputMetadataItems, discoverRunInputSchema } from "@/lib/orchestration-run-inputs";
|
|
53
|
+
import { selectWorkflowNodeInputSchema } from "@/lib/workspace-metadata-selectors";
|
|
54
|
+
|
|
55
|
+
// Workspace Metadata Graph V1 — read-only dependency metadata for workflow
|
|
56
|
+
// sidecars. The runtime path (sandbox-run, publish, draft/live) is
|
|
57
|
+
// unchanged; this only exposes typed dependency descriptors so the sidecar
|
|
58
|
+
// can render "this node requires N inputs from M source nodes".
|
|
59
|
+
const WORKFLOW_METADATA_SELECTORS = Object.freeze({
|
|
60
|
+
describeRunInputMetadataItems,
|
|
61
|
+
selectWorkflowNodeInputSchema
|
|
62
|
+
});
|
|
50
63
|
|
|
51
64
|
function resolveRegistryRowForSandbox(workspaceConfig, sandboxRow) {
|
|
52
|
-
const graph = parseOrchestrationGraph(sandboxRow?.orchestrationGraph);
|
|
65
|
+
const graph = parseOrchestrationGraph(sandboxRow?.orchestrationConfig || sandboxRow?.orchestrationGraph);
|
|
53
66
|
const apiNode = graph?.nodes?.find((n) => n?.type === "api-registry-call");
|
|
54
67
|
const registryId = String(
|
|
55
68
|
apiNode?.config?.registryId || apiNode?.config?.integrationId || sandboxRow?.schedulerRegistryId || ""
|
|
@@ -278,6 +291,10 @@ function isPassingRun(payload) {
|
|
|
278
291
|
return payload?.ok === true && Number(payload?.exitCode ?? payload?.response?.exitCode) === 0;
|
|
279
292
|
}
|
|
280
293
|
|
|
294
|
+
function graphHasNodes(graph) {
|
|
295
|
+
return Array.isArray(graph?.nodes) && graph.nodes.length > 0;
|
|
296
|
+
}
|
|
297
|
+
|
|
281
298
|
function WorkflowAddStepPanel({ target, onSelect }) {
|
|
282
299
|
return (
|
|
283
300
|
<div className="dm-workflow-add-panel">
|
|
@@ -310,7 +327,7 @@ export default function WorkflowSurface() {
|
|
|
310
327
|
const searchParams = useSearchParams();
|
|
311
328
|
const objectId = String(searchParams.get("object") || "").trim();
|
|
312
329
|
const rowId = String(searchParams.get("row") || "").trim();
|
|
313
|
-
const fieldName = String(searchParams.get("field") || "
|
|
330
|
+
const fieldName = String(searchParams.get("field") || "orchestrationConfig").trim();
|
|
314
331
|
const runId = String(searchParams.get("run") || "").trim();
|
|
315
332
|
|
|
316
333
|
const [workspaceConfig, setWorkspaceConfig] = useState(null);
|
|
@@ -356,11 +373,14 @@ export default function WorkflowSurface() {
|
|
|
356
373
|
);
|
|
357
374
|
|
|
358
375
|
const sandboxRow = resolved.row;
|
|
359
|
-
const
|
|
376
|
+
const hasGraphValue = (value) => Boolean(parseOrchestrationGraph(value));
|
|
377
|
+
const effectiveFieldName = hasGraphValue(sandboxRow?.[fieldName])
|
|
360
378
|
? fieldName
|
|
361
|
-
: sandboxRow?.orchestrationConfig
|
|
379
|
+
: hasGraphValue(sandboxRow?.orchestrationConfig)
|
|
362
380
|
? "orchestrationConfig"
|
|
363
|
-
:
|
|
381
|
+
: hasGraphValue(sandboxRow?.orchestrationGraph)
|
|
382
|
+
? "orchestrationGraph"
|
|
383
|
+
: (fieldName || "orchestrationConfig");
|
|
364
384
|
const draftFieldName = effectiveFieldName === "orchestrationConfig" ? "orchestrationDraftConfig" : "orchestrationDraftGraph";
|
|
365
385
|
const registryRow = useMemo(
|
|
366
386
|
() => (sandboxRow && workspaceConfig ? resolveRegistryRowForSandbox(workspaceConfig, sandboxRow) : null),
|
|
@@ -373,7 +393,11 @@ export default function WorkflowSurface() {
|
|
|
373
393
|
|
|
374
394
|
useEffect(() => {
|
|
375
395
|
if (!sandboxRow) return;
|
|
376
|
-
const
|
|
396
|
+
const draftParsed = parseOrchestrationGraph(sandboxRow[draftFieldName]);
|
|
397
|
+
const publishedParsed = parseOrchestrationGraph(sandboxRow[effectiveFieldName])
|
|
398
|
+
|| parseOrchestrationGraph(sandboxRow.orchestrationConfig)
|
|
399
|
+
|| parseOrchestrationGraph(sandboxRow.orchestrationGraph);
|
|
400
|
+
const parsed = graphHasNodes(draftParsed) || !graphHasNodes(publishedParsed) ? draftParsed : publishedParsed;
|
|
377
401
|
setOrchestrationGraph(parsed);
|
|
378
402
|
setDirty(false);
|
|
379
403
|
setGraphError("");
|
|
@@ -382,9 +406,10 @@ export default function WorkflowSurface() {
|
|
|
382
406
|
const graphUiState = getOrchestrationGraphUiState(orchestrationGraph);
|
|
383
407
|
const graphUnset = graphUiState === "unset";
|
|
384
408
|
const graphBlankShell = graphUiState === "blank-shell";
|
|
409
|
+
const swarmMode = useMemo(() => isAgentSwarmGraph(orchestrationGraph), [orchestrationGraph]);
|
|
385
410
|
const nextNodeId = useMemo(
|
|
386
|
-
() => (orchestrationGraph ? getNextCanonicalNodeId(orchestrationGraph) :
|
|
387
|
-
[orchestrationGraph]
|
|
411
|
+
() => (orchestrationGraph && !swarmMode ? getNextCanonicalNodeId(orchestrationGraph) : null),
|
|
412
|
+
[orchestrationGraph, swarmMode]
|
|
388
413
|
);
|
|
389
414
|
|
|
390
415
|
const selectedNode = useMemo(() => {
|
|
@@ -649,6 +674,16 @@ export default function WorkflowSurface() {
|
|
|
649
674
|
setDirty(true);
|
|
650
675
|
}
|
|
651
676
|
|
|
677
|
+
function startAgentSwarm() {
|
|
678
|
+
const graph = buildDefaultAgentSwarmGraph({
|
|
679
|
+
agentHost: String(sandboxRow?.agentHost || "").trim()
|
|
680
|
+
});
|
|
681
|
+
setOrchestrationGraph(graph);
|
|
682
|
+
setSelectedNodeId("orchestrator");
|
|
683
|
+
setConfigTab("swarm");
|
|
684
|
+
setDirty(true);
|
|
685
|
+
}
|
|
686
|
+
|
|
652
687
|
function applyPastedGraph(text) {
|
|
653
688
|
const parsed = parseOrchestrationGraph(text);
|
|
654
689
|
if (parsed) {
|
|
@@ -736,7 +771,7 @@ export default function WorkflowSurface() {
|
|
|
736
771
|
const publishReady = draftPassed && String(sandboxRow?.orchestrationDraftTestedConfig || "") === currentGraphSerialized && !dirty;
|
|
737
772
|
const savedDraftValue = String(sandboxRow?.[draftFieldName] || "").trim();
|
|
738
773
|
const draftStatus = String(sandboxRow?.orchestrationDraftStatus || "").trim();
|
|
739
|
-
const hasSavedDraft = Boolean(savedDraftValue) && draftStatus !== "published";
|
|
774
|
+
const hasSavedDraft = Boolean(savedDraftValue) && draftStatus !== "published" && graphHasNodes(parseOrchestrationGraph(savedDraftValue));
|
|
740
775
|
const isDraftMode = dirty || hasSavedDraft;
|
|
741
776
|
const canTest = !graphUnset && !graphBlankShell && Boolean(sandboxRow) && !Boolean(graphError);
|
|
742
777
|
const showDiscardDraft = isDraftMode;
|
|
@@ -871,6 +906,7 @@ export default function WorkflowSurface() {
|
|
|
871
906
|
disabled={false}
|
|
872
907
|
onStartFromRegistry={registryRow ? startFromRegistry : undefined}
|
|
873
908
|
onStartBlank={startBlank}
|
|
909
|
+
onStartAgentSwarm={startAgentSwarm}
|
|
874
910
|
onPasteGraph={applyPastedGraph}
|
|
875
911
|
/>
|
|
876
912
|
) : graphBlankShell ? (
|
|
@@ -932,7 +968,27 @@ export default function WorkflowSurface() {
|
|
|
932
968
|
/>
|
|
933
969
|
</div>
|
|
934
970
|
)}
|
|
935
|
-
{graphUiState === "populated" && !runSetupOpen && !addTarget && selectedNode && (
|
|
971
|
+
{graphUiState === "populated" && !runSetupOpen && !addTarget && selectedNode && swarmMode && selectedNode?.type === "thinAdapter" && (
|
|
972
|
+
<div className="dm-orchestration-sidecar__config-col">
|
|
973
|
+
<div className="dm-workflow-panel-head">
|
|
974
|
+
<button type="button" className="dm-workflow-icon-btn" onClick={() => setSelectedNodeId("")} aria-label="Close side panel">
|
|
975
|
+
<X size={14} />
|
|
976
|
+
</button>
|
|
977
|
+
<span>Agent swarm</span>
|
|
978
|
+
<em>agent-swarm-v1</em>
|
|
979
|
+
</div>
|
|
980
|
+
<AgentSwarmPanel
|
|
981
|
+
graph={orchestrationGraph}
|
|
982
|
+
disabled={false}
|
|
983
|
+
onGraphChange={(updater) => {
|
|
984
|
+
setOrchestrationGraph((g) => (typeof updater === "function" ? updater(g) : updater));
|
|
985
|
+
setDirty(true);
|
|
986
|
+
}}
|
|
987
|
+
/>
|
|
988
|
+
{graphError && <p className="dm-orchestration-config__error">{graphError}</p>}
|
|
989
|
+
</div>
|
|
990
|
+
)}
|
|
991
|
+
{graphUiState === "populated" && !runSetupOpen && !addTarget && selectedNode && !(swarmMode && selectedNode?.type === "thinAdapter") && (
|
|
936
992
|
<div className="dm-orchestration-sidecar__config-col">
|
|
937
993
|
<div className="dm-workflow-panel-head">
|
|
938
994
|
<button type="button" className="dm-workflow-icon-btn" onClick={() => setSelectedNodeId("")} aria-label="Close side panel">
|
|
@@ -81,11 +81,24 @@ import { governedWorkspaceIntegrationCatalog } from "@/lib/domain/integrations";
|
|
|
81
81
|
import { OBJECT_TYPE_PRESETS, listWorkspaceDataModelTables } from "@/lib/workspace-data-model";
|
|
82
82
|
import {
|
|
83
83
|
computeChartProjectionDebug,
|
|
84
|
-
computeChartValuesFromRows
|
|
84
|
+
computeChartValuesFromRows,
|
|
85
|
+
deriveWidgetDependencyContract
|
|
85
86
|
} from "@/lib/workspace-chart-values";
|
|
87
|
+
import { selectObjectFilterableFields, selectObjectSortableFields } from "@/lib/workspace-metadata-selectors";
|
|
86
88
|
import { HelperSidecar } from "./data-model/components/HelperSidecar.jsx";
|
|
87
89
|
import { WorkspaceRail } from "./workspace-rail.jsx";
|
|
88
90
|
|
|
91
|
+
// Workspace Metadata Graph V1 — typed dependency contracts.
|
|
92
|
+
// Used by sidecar dependency summaries; the existing chart hydration path
|
|
93
|
+
// continues to compute values via `computeChartValuesFromRows`. These
|
|
94
|
+
// selectors only describe the widget's typed contract — they never mutate
|
|
95
|
+
// config or trigger network calls.
|
|
96
|
+
const WORKSPACE_METADATA_SELECTORS = Object.freeze({
|
|
97
|
+
deriveWidgetDependencyContract,
|
|
98
|
+
selectObjectFilterableFields,
|
|
99
|
+
selectObjectSortableFields
|
|
100
|
+
});
|
|
101
|
+
|
|
89
102
|
const DEFAULT_CHART_TYPE = "bar-vertical";
|
|
90
103
|
const DEFAULT_FILTER_OP = "and";
|
|
91
104
|
const DEFAULT_FILTER_OPERATOR = "contains";
|
|
@@ -293,7 +306,7 @@ const GRID_COLUMNS = 12;
|
|
|
293
306
|
const GRID_ROWS = 16;
|
|
294
307
|
const GRID_CELL_COUNT = GRID_COLUMNS * GRID_ROWS;
|
|
295
308
|
const DEFAULT_TAB_ID = "tab-default";
|
|
296
|
-
const COLLAPSED_GRID_COLUMNS = "264px minmax(0, 1fr)";
|
|
309
|
+
const COLLAPSED_GRID_COLUMNS = "var(--workspace-rail-width, 264px) minmax(0, 1fr)";
|
|
297
310
|
|
|
298
311
|
function generateId(prefix) {
|
|
299
312
|
if (typeof globalThis !== "undefined" && globalThis.crypto?.randomUUID) {
|
|
@@ -3915,8 +3928,9 @@ function WorkspaceBuilder({ initialConfig, initialSourceRecords, adapterConfig,
|
|
|
3915
3928
|
const resizeDragRef = useRef(null);
|
|
3916
3929
|
const moveDragRef = useRef(null);
|
|
3917
3930
|
const importInputRef = useRef(null);
|
|
3918
|
-
const addSlot = dragPreview || selectedPosition;
|
|
3919
3931
|
const selectedWidgetLookupId = selectedWidgetId || pendingSelectedWidgetId;
|
|
3932
|
+
const addSlot = dragPreview || selectedPosition;
|
|
3933
|
+
const showAddWidgetSlot = dashboardDraftMode && !selectedWidgetLookupId && panelOpen && addSlot;
|
|
3920
3934
|
const selectedWidget = activeWidgets.find((widget) => widget.id === selectedWidgetLookupId) || null;
|
|
3921
3935
|
const availableIntegrations = useMemo(() => flattenIntegrationSettings(integrationSettings), [integrationSettings]);
|
|
3922
3936
|
const dataModelTables = useMemo(
|
|
@@ -5136,6 +5150,12 @@ function WorkspaceBuilder({ initialConfig, initialSourceRecords, adapterConfig,
|
|
|
5136
5150
|
return () => window.removeEventListener("keydown", handler);
|
|
5137
5151
|
}, [addWidget, commandPaletteOpen, managementOpen, panelOpen, settingsOpen, templateGalleryOpen, workspaceView]);
|
|
5138
5152
|
|
|
5153
|
+
useEffect(() => {
|
|
5154
|
+
const openFromRail = () => setCommandPaletteOpen(true);
|
|
5155
|
+
window.addEventListener("growthub:open-command-palette", openFromRail);
|
|
5156
|
+
return () => window.removeEventListener("growthub:open-command-palette", openFromRail);
|
|
5157
|
+
}, []);
|
|
5158
|
+
|
|
5139
5159
|
const builderStyle = workspaceView === "dashboards" || !panelOpen
|
|
5140
5160
|
? { gridTemplateColumns: COLLAPSED_GRID_COLUMNS }
|
|
5141
5161
|
: undefined;
|
|
@@ -5304,6 +5324,7 @@ function WorkspaceBuilder({ initialConfig, initialSourceRecords, adapterConfig,
|
|
|
5304
5324
|
<WorkspaceRail
|
|
5305
5325
|
workspaceConfig={config}
|
|
5306
5326
|
authority={integrationAdapter.authority}
|
|
5327
|
+
defaultCollapsed={workspaceView === "builder"}
|
|
5307
5328
|
helperOpen={helperOpen}
|
|
5308
5329
|
onOpenHelper={() => {
|
|
5309
5330
|
if (helperOpen) { setHelperOpen(false); return; }
|
|
@@ -5341,11 +5362,11 @@ function WorkspaceBuilder({ initialConfig, initialSourceRecords, adapterConfig,
|
|
|
5341
5362
|
)}
|
|
5342
5363
|
/>
|
|
5343
5364
|
|
|
5344
|
-
<section className={`workspace-surface${workspaceView === "builder" ?
|
|
5365
|
+
<section className={`workspace-surface${workspaceView === "builder" ? ` dm-workflow-surface workspace-dashboard-surface${dashboardDraftMode ? " is-dashboard-editing" : ""}` : ""}`}>
|
|
5345
5366
|
<header className={`workspace-toolbar${workspaceView === "builder" ? " dm-workflow-toolbar" : ""}`}>
|
|
5346
5367
|
<div className={workspaceView === "builder" ? "dm-workflow-titlebar" : undefined}>
|
|
5347
5368
|
{workspaceView === "builder" ? <>
|
|
5348
|
-
<
|
|
5369
|
+
<button type="button" className="dm-workflow-breadcrumb-link" onClick={showDashboardHome}>Dashboards</button>
|
|
5349
5370
|
<span className="dm-workflow-title-separator">/</span>
|
|
5350
5371
|
<h1>{activeDashboard?.name || "Untitled"}</h1>
|
|
5351
5372
|
<span className="dm-workflow-count">({activeWidgets.length}) · v{activeDashboard?.version || "1"} · {dashboardModeLabel}</span>
|
|
@@ -5596,7 +5617,7 @@ function WorkspaceBuilder({ initialConfig, initialSourceRecords, adapterConfig,
|
|
|
5596
5617
|
<button type="button" onClick={duplicateTab} disabled={!dashboardDraftMode}><Copy size={15} />Duplicate Tab</button>
|
|
5597
5618
|
</div>
|
|
5598
5619
|
<div
|
|
5599
|
-
className={`workspace-grid${moveDrag ? " moving-widget" : ""}`}
|
|
5620
|
+
className={`workspace-grid${moveDrag ? " moving-widget" : ""}${dashboardDraftMode ? " is-edit-mode" : " is-view-mode"}`}
|
|
5600
5621
|
ref={gridRef}
|
|
5601
5622
|
onPointerMove={updatePointerDrag}
|
|
5602
5623
|
onPointerUp={(event) => {
|
|
@@ -5614,7 +5635,7 @@ function WorkspaceBuilder({ initialConfig, initialSourceRecords, adapterConfig,
|
|
|
5614
5635
|
}}
|
|
5615
5636
|
style={{ "--workspace-columns": canvas.layout.columns, "--workspace-rows": GRID_ROWS }}
|
|
5616
5637
|
>
|
|
5617
|
-
{Array.from({ length: GRID_CELL_COUNT }).map((_, index) => {
|
|
5638
|
+
{dashboardDraftMode ? Array.from({ length: GRID_CELL_COUNT }).map((_, index) => {
|
|
5618
5639
|
const x = index % GRID_COLUMNS;
|
|
5619
5640
|
const y = Math.floor(index / GRID_COLUMNS);
|
|
5620
5641
|
const isOccupied = occupiedCells.has(`${x}:${y}`);
|
|
@@ -5632,15 +5653,15 @@ function WorkspaceBuilder({ initialConfig, initialSourceRecords, adapterConfig,
|
|
|
5632
5653
|
}}
|
|
5633
5654
|
type="button"
|
|
5634
5655
|
/>;
|
|
5635
|
-
})}
|
|
5636
|
-
<button className={`workspace-add-widget${dragPreview ? " selecting" : ""}`} type="button"
|
|
5656
|
+
}) : null}
|
|
5657
|
+
{showAddWidgetSlot ? <button className={`workspace-add-widget${dragPreview ? " selecting" : ""}`} type="button" onClick={() => setPanelOpen(true)} style={{
|
|
5637
5658
|
gridColumn: `${addSlot.x + 1} / span ${addSlot.w}`,
|
|
5638
5659
|
gridRow: `${addSlot.y + 1} / span ${addSlot.h}`
|
|
5639
5660
|
}}>
|
|
5640
5661
|
<span className="workspace-widget-icon" aria-hidden="true"><span /></span>
|
|
5641
5662
|
<strong>Add widget</strong>
|
|
5642
5663
|
<small>Click to add your first widget</small>
|
|
5643
|
-
</button>
|
|
5664
|
+
</button> : null}
|
|
5644
5665
|
{activeWidgets.map((widget) => <WidgetPreview
|
|
5645
5666
|
key={widget.id}
|
|
5646
5667
|
branding={branding}
|
|
@@ -1488,6 +1488,7 @@ export function WorkspaceRail({
|
|
|
1488
1488
|
onConfigChange,
|
|
1489
1489
|
dashboardsSlot,
|
|
1490
1490
|
dataModelSlot,
|
|
1491
|
+
defaultCollapsed = false,
|
|
1491
1492
|
// `managementSlot` retained as accepted-but-ignored prop for backward
|
|
1492
1493
|
// compatibility with callers that still pass it. The Management item
|
|
1493
1494
|
// moved to the Workspace Settings → Ownership tab.
|
|
@@ -1500,7 +1501,7 @@ export function WorkspaceRail({
|
|
|
1500
1501
|
const router = useRouter();
|
|
1501
1502
|
|
|
1502
1503
|
const [activeTab, setActiveTab] = useState("home");
|
|
1503
|
-
const [railCollapsed, setRailCollapsed] = useState(
|
|
1504
|
+
const [railCollapsed, setRailCollapsed] = useState(Boolean(defaultCollapsed));
|
|
1504
1505
|
const [openMenuId, setOpenMenuId] = useState(null);
|
|
1505
1506
|
const [renamingId, setRenamingId] = useState(null);
|
|
1506
1507
|
const [renameDraft, setRenameDraft] = useState("");
|
|
@@ -1521,6 +1522,10 @@ export function WorkspaceRail({
|
|
|
1521
1522
|
|
|
1522
1523
|
const threads = useMemo(() => getHelperThreadRows(workspaceConfig), [workspaceConfig]);
|
|
1523
1524
|
|
|
1525
|
+
useEffect(() => {
|
|
1526
|
+
setRailCollapsed(Boolean(defaultCollapsed));
|
|
1527
|
+
}, [defaultCollapsed]);
|
|
1528
|
+
|
|
1524
1529
|
useEffect(() => {
|
|
1525
1530
|
if (typeof document === "undefined") return undefined;
|
|
1526
1531
|
document.body.classList.toggle("workspace-rail-collapsed", railCollapsed);
|
|
@@ -1640,6 +1645,16 @@ export function WorkspaceRail({
|
|
|
1640
1645
|
<ChevronDown size={13} className="workspace-brand-caret" aria-hidden="true" />
|
|
1641
1646
|
</button>
|
|
1642
1647
|
<div className="workspace-rail-topbar-actions">
|
|
1648
|
+
<button
|
|
1649
|
+
type="button"
|
|
1650
|
+
className="workspace-rail-icon-btn"
|
|
1651
|
+
aria-label={railCollapsed ? "Expand sidebar" : "Collapse sidebar"}
|
|
1652
|
+
title={railCollapsed ? "Expand sidebar" : "Collapse sidebar"}
|
|
1653
|
+
aria-pressed={railCollapsed}
|
|
1654
|
+
onClick={() => setRailCollapsed((v) => !v)}
|
|
1655
|
+
>
|
|
1656
|
+
<PanelLeftClose size={13} />
|
|
1657
|
+
</button>
|
|
1643
1658
|
<button
|
|
1644
1659
|
type="button"
|
|
1645
1660
|
className="workspace-rail-icon-btn"
|
|
@@ -1647,9 +1662,6 @@ export function WorkspaceRail({
|
|
|
1647
1662
|
title="Search (⌘K)"
|
|
1648
1663
|
data-rail-search=""
|
|
1649
1664
|
onClick={() => {
|
|
1650
|
-
// Surfaces with a command palette (DataModelShell) listen
|
|
1651
|
-
// for this event and open the palette in place. Other
|
|
1652
|
-
// surfaces are free to ignore it.
|
|
1653
1665
|
if (typeof window !== "undefined") {
|
|
1654
1666
|
window.dispatchEvent(new CustomEvent("growthub:open-command-palette"));
|
|
1655
1667
|
}
|
|
@@ -1657,16 +1669,6 @@ export function WorkspaceRail({
|
|
|
1657
1669
|
>
|
|
1658
1670
|
<Search size={13} />
|
|
1659
1671
|
</button>
|
|
1660
|
-
<button
|
|
1661
|
-
type="button"
|
|
1662
|
-
className="workspace-rail-icon-btn"
|
|
1663
|
-
aria-label={railCollapsed ? "Expand sidebar" : "Collapse sidebar"}
|
|
1664
|
-
title={railCollapsed ? "Expand sidebar" : "Collapse sidebar"}
|
|
1665
|
-
aria-pressed={railCollapsed}
|
|
1666
|
-
onClick={() => setRailCollapsed((v) => !v)}
|
|
1667
|
-
>
|
|
1668
|
-
<PanelLeftClose size={13} />
|
|
1669
|
-
</button>
|
|
1670
1672
|
<button
|
|
1671
1673
|
type="button"
|
|
1672
1674
|
className="workspace-rail-icon-btn"
|
package/assets/worker-kits/growthub-custom-workspace-starter-v1/apps/workspace/lib/adapters/env.js
CHANGED
|
@@ -12,6 +12,13 @@ function readAdapterConfig() {
|
|
|
12
12
|
userId: process.env.GROWTHUB_BRIDGE_USER_ID || void 0,
|
|
13
13
|
hasAccessToken: Boolean(process.env.GROWTHUB_BRIDGE_ACCESS_TOKEN)
|
|
14
14
|
},
|
|
15
|
+
nango: {
|
|
16
|
+
mode: readEnum(["NANGO_MODE"], ["cloud", "self-hosted"], "cloud"),
|
|
17
|
+
hostUrl: process.env.NANGO_HOST_URL || void 0,
|
|
18
|
+
environment: process.env.NANGO_ENVIRONMENT || "dev",
|
|
19
|
+
secretEnvName: "NANGO_SECRET_KEY",
|
|
20
|
+
hasSecretKey: Boolean(process.env.NANGO_SECRET_KEY)
|
|
21
|
+
},
|
|
15
22
|
dataSources: {
|
|
16
23
|
hasWindsorApiKey: Boolean(process.env.WINDSOR_API_KEY)
|
|
17
24
|
}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Nango adapter barrel — server-side imports only.
|
|
3
|
+
*
|
|
4
|
+
* The browser must never import any module under this path. Routes consume
|
|
5
|
+
* this barrel; UI components hit the routes.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
export {
|
|
9
|
+
DEFAULT_NANGO_SECRET_ENV,
|
|
10
|
+
createConnectSession,
|
|
11
|
+
describeNangoAdapter,
|
|
12
|
+
executeAction,
|
|
13
|
+
getConnectionSummary,
|
|
14
|
+
getStatus,
|
|
15
|
+
listActions,
|
|
16
|
+
pickSafeConnectionFields,
|
|
17
|
+
projectNangoBinding,
|
|
18
|
+
proxyRequest,
|
|
19
|
+
resolveNangoEnv
|
|
20
|
+
} from "./nango-adapter.js";
|
|
21
|
+
|
|
22
|
+
export {
|
|
23
|
+
buildNangoResolver,
|
|
24
|
+
registerNangoResolversFromConfig
|
|
25
|
+
} from "./nango-config-loader.js";
|
|
26
|
+
|
|
27
|
+
export {
|
|
28
|
+
validateActionExecuteRequest,
|
|
29
|
+
validateActionsListInput,
|
|
30
|
+
validateConnectSessionRequest,
|
|
31
|
+
validateConnectionId,
|
|
32
|
+
validateConnectionStatusRequest,
|
|
33
|
+
validateConnectionSummaryRequest,
|
|
34
|
+
validateHostUrl,
|
|
35
|
+
validateNangoMode,
|
|
36
|
+
validateProviderConfigKey,
|
|
37
|
+
validateProxyRequest
|
|
38
|
+
} from "./nango-schema.js";
|