@contractspec/example.integration-hub 1.46.0 → 1.47.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/connection/connection.enum.d.ts +2 -2
- package/dist/connection/connection.enum.d.ts.map +1 -1
- package/dist/connection/connection.operation.d.ts +27 -27
- package/dist/connection/connection.operation.d.ts.map +1 -1
- package/dist/connection/connection.presentation.d.ts +3 -3
- package/dist/connection/connection.presentation.d.ts.map +1 -1
- package/dist/connection/connection.presentation.js +5 -5
- package/dist/connection/connection.presentation.js.map +1 -1
- package/dist/connection/connection.schema.d.ts +16 -16
- package/dist/connection/connection.schema.d.ts.map +1 -1
- package/dist/events.d.ts +10 -10
- package/dist/example.d.ts +2 -2
- package/dist/example.d.ts.map +1 -1
- package/dist/example.js +4 -2
- package/dist/example.js.map +1 -1
- package/dist/handlers/index.d.ts +2 -0
- package/dist/handlers/index.js +3 -0
- package/dist/handlers/integration.handlers.d.ts +130 -0
- package/dist/handlers/integration.handlers.d.ts.map +1 -0
- package/dist/handlers/integration.handlers.js +282 -0
- package/dist/handlers/integration.handlers.js.map +1 -0
- package/dist/index.d.ts +6 -1
- package/dist/index.js +6 -1
- package/dist/integration/integration.enum.d.ts +2 -2
- package/dist/integration/integration.enum.d.ts.map +1 -1
- package/dist/integration/integration.operations.d.ts +25 -25
- package/dist/integration/integration.operations.d.ts.map +1 -1
- package/dist/integration/integration.presentation.d.ts +4 -4
- package/dist/integration/integration.presentation.d.ts.map +1 -1
- package/dist/integration/integration.presentation.js +7 -7
- package/dist/integration/integration.presentation.js.map +1 -1
- package/dist/integration/integration.schema.d.ts +16 -16
- package/dist/integration/integration.schema.d.ts.map +1 -1
- package/dist/integration-hub.capability.d.ts +9 -0
- package/dist/integration-hub.capability.d.ts.map +1 -0
- package/dist/integration-hub.capability.js +38 -0
- package/dist/integration-hub.capability.js.map +1 -0
- package/dist/integration-hub.feature.d.ts +2 -3
- package/dist/integration-hub.feature.d.ts.map +1 -1
- package/dist/integration-hub.feature.js +7 -2
- package/dist/integration-hub.feature.js.map +1 -1
- package/dist/seeders/index.d.ts +10 -0
- package/dist/seeders/index.d.ts.map +1 -0
- package/dist/seeders/index.js +19 -0
- package/dist/seeders/index.js.map +1 -0
- package/dist/sync/sync.enum.d.ts +4 -4
- package/dist/sync/sync.enum.d.ts.map +1 -1
- package/dist/sync/sync.operations.d.ts +126 -126
- package/dist/sync/sync.operations.d.ts.map +1 -1
- package/dist/sync/sync.presentation.d.ts +7 -7
- package/dist/sync/sync.presentation.d.ts.map +1 -1
- package/dist/sync/sync.presentation.js +13 -13
- package/dist/sync/sync.presentation.js.map +1 -1
- package/dist/sync/sync.schema.d.ts +85 -85
- package/dist/sync-engine/index.js.map +1 -1
- package/dist/tests/operations.test-spec.d.ts +9 -0
- package/dist/tests/operations.test-spec.d.ts.map +1 -0
- package/dist/tests/operations.test-spec.js +94 -0
- package/dist/tests/operations.test-spec.js.map +1 -0
- package/dist/ui/IntegrationDashboard.d.ts +7 -0
- package/dist/ui/IntegrationDashboard.d.ts.map +1 -0
- package/dist/ui/IntegrationDashboard.js +266 -0
- package/dist/ui/IntegrationDashboard.js.map +1 -0
- package/dist/ui/hooks/index.d.ts +2 -0
- package/dist/ui/hooks/index.js +5 -0
- package/dist/ui/hooks/useIntegrationData.d.ts +23 -0
- package/dist/ui/hooks/useIntegrationData.d.ts.map +1 -0
- package/dist/ui/hooks/useIntegrationData.js +59 -0
- package/dist/ui/hooks/useIntegrationData.js.map +1 -0
- package/dist/ui/index.d.ts +6 -0
- package/dist/ui/index.js +6 -0
- package/dist/ui/renderers/index.d.ts +2 -0
- package/dist/ui/renderers/index.js +3 -0
- package/dist/ui/renderers/integration.markdown.d.ts +28 -0
- package/dist/ui/renderers/integration.markdown.d.ts.map +1 -0
- package/dist/ui/renderers/integration.markdown.js +256 -0
- package/dist/ui/renderers/integration.markdown.js.map +1 -0
- package/package.json +24 -8
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
import { defineTestSpec } from "@contractspec/lib.contracts";
|
|
2
|
+
|
|
3
|
+
//#region src/tests/operations.test-spec.ts
|
|
4
|
+
const SyncConfigCreateTest = defineTestSpec({
|
|
5
|
+
meta: {
|
|
6
|
+
key: "integration.syncConfig.create.test",
|
|
7
|
+
version: "1.0.0",
|
|
8
|
+
stability: "experimental",
|
|
9
|
+
owners: ["@example.integration-hub"],
|
|
10
|
+
description: "Test for creating sync config",
|
|
11
|
+
tags: ["test"]
|
|
12
|
+
},
|
|
13
|
+
target: {
|
|
14
|
+
type: "operation",
|
|
15
|
+
operation: {
|
|
16
|
+
key: "integration.syncConfig.create",
|
|
17
|
+
version: "1.0.0"
|
|
18
|
+
}
|
|
19
|
+
},
|
|
20
|
+
scenarios: [{
|
|
21
|
+
key: "success",
|
|
22
|
+
when: { operation: { key: "integration.syncConfig.create" } },
|
|
23
|
+
then: [{
|
|
24
|
+
type: "expectOutput",
|
|
25
|
+
match: {}
|
|
26
|
+
}]
|
|
27
|
+
}, {
|
|
28
|
+
key: "error",
|
|
29
|
+
when: { operation: { key: "integration.syncConfig.create" } },
|
|
30
|
+
then: [{ type: "expectError" }]
|
|
31
|
+
}]
|
|
32
|
+
});
|
|
33
|
+
const FieldMappingAddTest = defineTestSpec({
|
|
34
|
+
meta: {
|
|
35
|
+
key: "integration.fieldMapping.add.test",
|
|
36
|
+
version: "1.0.0",
|
|
37
|
+
stability: "experimental",
|
|
38
|
+
owners: ["@example.integration-hub"],
|
|
39
|
+
description: "Test for adding field mapping",
|
|
40
|
+
tags: ["test"]
|
|
41
|
+
},
|
|
42
|
+
target: {
|
|
43
|
+
type: "operation",
|
|
44
|
+
operation: {
|
|
45
|
+
key: "integration.fieldMapping.add",
|
|
46
|
+
version: "1.0.0"
|
|
47
|
+
}
|
|
48
|
+
},
|
|
49
|
+
scenarios: [{
|
|
50
|
+
key: "success",
|
|
51
|
+
when: { operation: { key: "integration.fieldMapping.add" } },
|
|
52
|
+
then: [{
|
|
53
|
+
type: "expectOutput",
|
|
54
|
+
match: {}
|
|
55
|
+
}]
|
|
56
|
+
}, {
|
|
57
|
+
key: "error",
|
|
58
|
+
when: { operation: { key: "integration.fieldMapping.add" } },
|
|
59
|
+
then: [{ type: "expectError" }]
|
|
60
|
+
}]
|
|
61
|
+
});
|
|
62
|
+
const SyncRunListTest = defineTestSpec({
|
|
63
|
+
meta: {
|
|
64
|
+
key: "integration.syncRun.list.test",
|
|
65
|
+
version: "1.0.0",
|
|
66
|
+
stability: "experimental",
|
|
67
|
+
owners: ["@example.integration-hub"],
|
|
68
|
+
description: "Test for listing sync runs",
|
|
69
|
+
tags: ["test"]
|
|
70
|
+
},
|
|
71
|
+
target: {
|
|
72
|
+
type: "operation",
|
|
73
|
+
operation: {
|
|
74
|
+
key: "integration.syncRun.list",
|
|
75
|
+
version: "1.0.0"
|
|
76
|
+
}
|
|
77
|
+
},
|
|
78
|
+
scenarios: [{
|
|
79
|
+
key: "success",
|
|
80
|
+
when: { operation: { key: "integration.syncRun.list" } },
|
|
81
|
+
then: [{
|
|
82
|
+
type: "expectOutput",
|
|
83
|
+
match: {}
|
|
84
|
+
}]
|
|
85
|
+
}, {
|
|
86
|
+
key: "error",
|
|
87
|
+
when: { operation: { key: "integration.syncRun.list" } },
|
|
88
|
+
then: [{ type: "expectError" }]
|
|
89
|
+
}]
|
|
90
|
+
});
|
|
91
|
+
|
|
92
|
+
//#endregion
|
|
93
|
+
export { FieldMappingAddTest, SyncConfigCreateTest, SyncRunListTest };
|
|
94
|
+
//# sourceMappingURL=operations.test-spec.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"operations.test-spec.js","names":[],"sources":["../../src/tests/operations.test-spec.ts"],"sourcesContent":["import { defineTestSpec } from '@contractspec/lib.contracts';\n\nexport const SyncConfigCreateTest = defineTestSpec({\n meta: {\n key: 'integration.syncConfig.create.test',\n version: '1.0.0',\n stability: 'experimental',\n owners: ['@example.integration-hub'],\n description: 'Test for creating sync config',\n tags: ['test'],\n },\n target: {\n type: 'operation',\n operation: { key: 'integration.syncConfig.create', version: '1.0.0' },\n },\n scenarios: [\n {\n key: 'success',\n when: { operation: { key: 'integration.syncConfig.create' } },\n then: [{ type: 'expectOutput', match: {} }],\n },\n {\n key: 'error',\n when: { operation: { key: 'integration.syncConfig.create' } },\n then: [{ type: 'expectError' }],\n },\n ],\n});\n\nexport const FieldMappingAddTest = defineTestSpec({\n meta: {\n key: 'integration.fieldMapping.add.test',\n version: '1.0.0',\n stability: 'experimental',\n owners: ['@example.integration-hub'],\n description: 'Test for adding field mapping',\n tags: ['test'],\n },\n target: {\n type: 'operation',\n operation: { key: 'integration.fieldMapping.add', version: '1.0.0' },\n },\n scenarios: [\n {\n key: 'success',\n when: { operation: { key: 'integration.fieldMapping.add' } },\n then: [{ type: 'expectOutput', match: {} }],\n },\n {\n key: 'error',\n when: { operation: { key: 'integration.fieldMapping.add' } },\n then: [{ type: 'expectError' }],\n },\n ],\n});\n\nexport const SyncRunListTest = defineTestSpec({\n meta: {\n key: 'integration.syncRun.list.test',\n version: '1.0.0',\n stability: 'experimental',\n owners: ['@example.integration-hub'],\n description: 'Test for listing sync runs',\n tags: ['test'],\n },\n target: {\n type: 'operation',\n operation: { key: 'integration.syncRun.list', version: '1.0.0' },\n },\n scenarios: [\n {\n key: 'success',\n when: { operation: { key: 'integration.syncRun.list' } },\n then: [{ type: 'expectOutput', match: {} }],\n },\n {\n key: 'error',\n when: { operation: { key: 'integration.syncRun.list' } },\n then: [{ type: 'expectError' }],\n },\n ],\n});\n"],"mappings":";;;AAEA,MAAa,uBAAuB,eAAe;CACjD,MAAM;EACJ,KAAK;EACL,SAAS;EACT,WAAW;EACX,QAAQ,CAAC,2BAA2B;EACpC,aAAa;EACb,MAAM,CAAC,OAAO;EACf;CACD,QAAQ;EACN,MAAM;EACN,WAAW;GAAE,KAAK;GAAiC,SAAS;GAAS;EACtE;CACD,WAAW,CACT;EACE,KAAK;EACL,MAAM,EAAE,WAAW,EAAE,KAAK,iCAAiC,EAAE;EAC7D,MAAM,CAAC;GAAE,MAAM;GAAgB,OAAO,EAAE;GAAE,CAAC;EAC5C,EACD;EACE,KAAK;EACL,MAAM,EAAE,WAAW,EAAE,KAAK,iCAAiC,EAAE;EAC7D,MAAM,CAAC,EAAE,MAAM,eAAe,CAAC;EAChC,CACF;CACF,CAAC;AAEF,MAAa,sBAAsB,eAAe;CAChD,MAAM;EACJ,KAAK;EACL,SAAS;EACT,WAAW;EACX,QAAQ,CAAC,2BAA2B;EACpC,aAAa;EACb,MAAM,CAAC,OAAO;EACf;CACD,QAAQ;EACN,MAAM;EACN,WAAW;GAAE,KAAK;GAAgC,SAAS;GAAS;EACrE;CACD,WAAW,CACT;EACE,KAAK;EACL,MAAM,EAAE,WAAW,EAAE,KAAK,gCAAgC,EAAE;EAC5D,MAAM,CAAC;GAAE,MAAM;GAAgB,OAAO,EAAE;GAAE,CAAC;EAC5C,EACD;EACE,KAAK;EACL,MAAM,EAAE,WAAW,EAAE,KAAK,gCAAgC,EAAE;EAC5D,MAAM,CAAC,EAAE,MAAM,eAAe,CAAC;EAChC,CACF;CACF,CAAC;AAEF,MAAa,kBAAkB,eAAe;CAC5C,MAAM;EACJ,KAAK;EACL,SAAS;EACT,WAAW;EACX,QAAQ,CAAC,2BAA2B;EACpC,aAAa;EACb,MAAM,CAAC,OAAO;EACf;CACD,QAAQ;EACN,MAAM;EACN,WAAW;GAAE,KAAK;GAA4B,SAAS;GAAS;EACjE;CACD,WAAW,CACT;EACE,KAAK;EACL,MAAM,EAAE,WAAW,EAAE,KAAK,4BAA4B,EAAE;EACxD,MAAM,CAAC;GAAE,MAAM;GAAgB,OAAO,EAAE;GAAE,CAAC;EAC5C,EACD;EACE,KAAK;EACL,MAAM,EAAE,WAAW,EAAE,KAAK,4BAA4B,EAAE;EACxD,MAAM,CAAC,EAAE,MAAM,eAAe,CAAC;EAChC,CACF;CACF,CAAC"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import * as react_jsx_runtime0 from "react/jsx-runtime";
|
|
2
|
+
|
|
3
|
+
//#region src/ui/IntegrationDashboard.d.ts
|
|
4
|
+
declare function IntegrationDashboard(): react_jsx_runtime0.JSX.Element;
|
|
5
|
+
//#endregion
|
|
6
|
+
export { IntegrationDashboard };
|
|
7
|
+
//# sourceMappingURL=IntegrationDashboard.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"IntegrationDashboard.d.ts","names":[],"sources":["../../src/ui/IntegrationDashboard.tsx"],"sourcesContent":[],"mappings":";;;iBA4CgB,oBAAA,CAAA,GAAoB,kBAAA,CAAA,GAAA,CAAA"}
|
|
@@ -0,0 +1,266 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
|
|
3
|
+
import { useIntegrationData } from "./hooks/useIntegrationData.js";
|
|
4
|
+
import { useState } from "react";
|
|
5
|
+
import { Button, ErrorState, LoaderBlock, StatCard, StatCardGroup } from "@contractspec/lib.design-system";
|
|
6
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
7
|
+
|
|
8
|
+
//#region src/ui/IntegrationDashboard.tsx
|
|
9
|
+
/**
|
|
10
|
+
* Integration Hub Dashboard
|
|
11
|
+
*
|
|
12
|
+
* Interactive dashboard for the integration-hub template.
|
|
13
|
+
* Displays integrations, connections, and sync configurations.
|
|
14
|
+
*/
|
|
15
|
+
const STATUS_COLORS = {
|
|
16
|
+
ACTIVE: "bg-green-100 text-green-700 dark:bg-green-900/30 dark:text-green-400",
|
|
17
|
+
INACTIVE: "bg-gray-100 text-gray-700 dark:bg-gray-900/30 dark:text-gray-400",
|
|
18
|
+
CONNECTED: "bg-green-100 text-green-700 dark:bg-green-900/30 dark:text-green-400",
|
|
19
|
+
DISCONNECTED: "bg-gray-100 text-gray-700 dark:bg-gray-900/30 dark:text-gray-400",
|
|
20
|
+
PENDING: "bg-yellow-100 text-yellow-700 dark:bg-yellow-900/30 dark:text-yellow-400",
|
|
21
|
+
ERROR: "bg-red-100 text-red-700 dark:bg-red-900/30 dark:text-red-400",
|
|
22
|
+
PAUSED: "bg-yellow-100 text-yellow-700 dark:bg-yellow-900/30 dark:text-yellow-400"
|
|
23
|
+
};
|
|
24
|
+
const TYPE_ICONS = {
|
|
25
|
+
CRM: "📊",
|
|
26
|
+
MARKETING: "📣",
|
|
27
|
+
PAYMENT: "💳",
|
|
28
|
+
COMMUNICATION: "💬",
|
|
29
|
+
DATA: "🗄️",
|
|
30
|
+
CUSTOM: "⚙️"
|
|
31
|
+
};
|
|
32
|
+
function IntegrationDashboard() {
|
|
33
|
+
const [activeTab, setActiveTab] = useState("integrations");
|
|
34
|
+
const { integrations, connections, syncConfigs, loading, error, stats, refetch } = useIntegrationData();
|
|
35
|
+
const tabs = [
|
|
36
|
+
{
|
|
37
|
+
id: "integrations",
|
|
38
|
+
label: "Integrations",
|
|
39
|
+
icon: "🔌"
|
|
40
|
+
},
|
|
41
|
+
{
|
|
42
|
+
id: "connections",
|
|
43
|
+
label: "Connections",
|
|
44
|
+
icon: "🔗"
|
|
45
|
+
},
|
|
46
|
+
{
|
|
47
|
+
id: "syncs",
|
|
48
|
+
label: "Sync Configs",
|
|
49
|
+
icon: "🔄"
|
|
50
|
+
}
|
|
51
|
+
];
|
|
52
|
+
if (loading) return /* @__PURE__ */ jsx(LoaderBlock, { label: "Loading Integrations..." });
|
|
53
|
+
if (error) return /* @__PURE__ */ jsx(ErrorState, {
|
|
54
|
+
title: "Failed to load Integrations",
|
|
55
|
+
description: error.message,
|
|
56
|
+
onRetry: refetch,
|
|
57
|
+
retryLabel: "Retry"
|
|
58
|
+
});
|
|
59
|
+
return /* @__PURE__ */ jsxs("div", {
|
|
60
|
+
className: "space-y-6",
|
|
61
|
+
children: [
|
|
62
|
+
/* @__PURE__ */ jsxs("div", {
|
|
63
|
+
className: "flex items-center justify-between",
|
|
64
|
+
children: [/* @__PURE__ */ jsx("h2", {
|
|
65
|
+
className: "text-2xl font-bold",
|
|
66
|
+
children: "Integration Hub"
|
|
67
|
+
}), /* @__PURE__ */ jsxs(Button, {
|
|
68
|
+
onClick: () => alert("Add integration modal"),
|
|
69
|
+
children: [/* @__PURE__ */ jsx("span", {
|
|
70
|
+
className: "mr-2",
|
|
71
|
+
children: "+"
|
|
72
|
+
}), " Add Integration"]
|
|
73
|
+
})]
|
|
74
|
+
}),
|
|
75
|
+
/* @__PURE__ */ jsxs(StatCardGroup, { children: [
|
|
76
|
+
/* @__PURE__ */ jsx(StatCard, {
|
|
77
|
+
label: "Integrations",
|
|
78
|
+
value: stats.totalIntegrations,
|
|
79
|
+
hint: `${stats.activeIntegrations} active`
|
|
80
|
+
}),
|
|
81
|
+
/* @__PURE__ */ jsx(StatCard, {
|
|
82
|
+
label: "Connections",
|
|
83
|
+
value: stats.totalConnections,
|
|
84
|
+
hint: `${stats.connectedCount} connected`
|
|
85
|
+
}),
|
|
86
|
+
/* @__PURE__ */ jsx(StatCard, {
|
|
87
|
+
label: "Syncs",
|
|
88
|
+
value: stats.totalSyncs,
|
|
89
|
+
hint: `${stats.activeSyncs} active`
|
|
90
|
+
})
|
|
91
|
+
] }),
|
|
92
|
+
/* @__PURE__ */ jsx("nav", {
|
|
93
|
+
className: "bg-muted flex gap-1 rounded-lg p-1",
|
|
94
|
+
role: "tablist",
|
|
95
|
+
children: tabs.map((tab) => /* @__PURE__ */ jsxs(Button, {
|
|
96
|
+
type: "button",
|
|
97
|
+
role: "tab",
|
|
98
|
+
"aria-selected": activeTab === tab.id,
|
|
99
|
+
onClick: () => setActiveTab(tab.id),
|
|
100
|
+
className: `flex flex-1 items-center justify-center gap-2 rounded-md px-4 py-2 text-sm font-medium transition-colors ${activeTab === tab.id ? "bg-background text-foreground shadow-sm" : "text-muted-foreground hover:text-foreground"}`,
|
|
101
|
+
children: [/* @__PURE__ */ jsx("span", { children: tab.icon }), tab.label]
|
|
102
|
+
}, tab.id))
|
|
103
|
+
}),
|
|
104
|
+
/* @__PURE__ */ jsxs("div", {
|
|
105
|
+
className: "min-h-[400px]",
|
|
106
|
+
role: "tabpanel",
|
|
107
|
+
children: [
|
|
108
|
+
activeTab === "integrations" && /* @__PURE__ */ jsxs("div", {
|
|
109
|
+
className: "grid gap-4 sm:grid-cols-2 lg:grid-cols-3",
|
|
110
|
+
children: [integrations.map((integration) => /* @__PURE__ */ jsxs("div", {
|
|
111
|
+
className: "border-border bg-card hover:bg-muted/50 cursor-pointer rounded-lg border p-4 transition-colors",
|
|
112
|
+
children: [/* @__PURE__ */ jsxs("div", {
|
|
113
|
+
className: "mb-3 flex items-center gap-3",
|
|
114
|
+
children: [/* @__PURE__ */ jsx("span", {
|
|
115
|
+
className: "text-2xl",
|
|
116
|
+
children: TYPE_ICONS[integration.type] ?? "⚙️"
|
|
117
|
+
}), /* @__PURE__ */ jsxs("div", { children: [/* @__PURE__ */ jsx("h3", {
|
|
118
|
+
className: "font-medium",
|
|
119
|
+
children: integration.name
|
|
120
|
+
}), /* @__PURE__ */ jsx("p", {
|
|
121
|
+
className: "text-muted-foreground text-sm",
|
|
122
|
+
children: integration.type
|
|
123
|
+
})] })]
|
|
124
|
+
}), /* @__PURE__ */ jsxs("div", {
|
|
125
|
+
className: "flex items-center justify-between",
|
|
126
|
+
children: [/* @__PURE__ */ jsx("span", {
|
|
127
|
+
className: `inline-flex rounded-full px-2 py-0.5 text-xs font-medium ${STATUS_COLORS[integration.status] ?? ""}`,
|
|
128
|
+
children: integration.status
|
|
129
|
+
}), /* @__PURE__ */ jsx("span", {
|
|
130
|
+
className: "text-muted-foreground text-xs",
|
|
131
|
+
children: integration.createdAt.toLocaleDateString()
|
|
132
|
+
})]
|
|
133
|
+
})]
|
|
134
|
+
}, integration.id)), integrations.length === 0 && /* @__PURE__ */ jsx("div", {
|
|
135
|
+
className: "text-muted-foreground col-span-full flex h-64 items-center justify-center",
|
|
136
|
+
children: "No integrations configured"
|
|
137
|
+
})]
|
|
138
|
+
}),
|
|
139
|
+
activeTab === "connections" && /* @__PURE__ */ jsx("div", {
|
|
140
|
+
className: "border-border rounded-lg border",
|
|
141
|
+
children: /* @__PURE__ */ jsxs("table", {
|
|
142
|
+
className: "w-full",
|
|
143
|
+
children: [/* @__PURE__ */ jsx("thead", {
|
|
144
|
+
className: "border-border bg-muted/30 border-b",
|
|
145
|
+
children: /* @__PURE__ */ jsxs("tr", { children: [
|
|
146
|
+
/* @__PURE__ */ jsx("th", {
|
|
147
|
+
className: "px-4 py-3 text-left text-sm font-medium",
|
|
148
|
+
children: "Connection"
|
|
149
|
+
}),
|
|
150
|
+
/* @__PURE__ */ jsx("th", {
|
|
151
|
+
className: "px-4 py-3 text-left text-sm font-medium",
|
|
152
|
+
children: "Status"
|
|
153
|
+
}),
|
|
154
|
+
/* @__PURE__ */ jsx("th", {
|
|
155
|
+
className: "px-4 py-3 text-left text-sm font-medium",
|
|
156
|
+
children: "Last Sync"
|
|
157
|
+
})
|
|
158
|
+
] })
|
|
159
|
+
}), /* @__PURE__ */ jsxs("tbody", {
|
|
160
|
+
className: "divide-border divide-y",
|
|
161
|
+
children: [connections.map((conn) => /* @__PURE__ */ jsxs("tr", {
|
|
162
|
+
className: "hover:bg-muted/50",
|
|
163
|
+
children: [
|
|
164
|
+
/* @__PURE__ */ jsx("td", {
|
|
165
|
+
className: "px-4 py-3",
|
|
166
|
+
children: /* @__PURE__ */ jsx("div", {
|
|
167
|
+
className: "font-medium",
|
|
168
|
+
children: conn.name
|
|
169
|
+
})
|
|
170
|
+
}),
|
|
171
|
+
/* @__PURE__ */ jsx("td", {
|
|
172
|
+
className: "px-4 py-3",
|
|
173
|
+
children: /* @__PURE__ */ jsx("span", {
|
|
174
|
+
className: `inline-flex rounded-full px-2 py-0.5 text-xs font-medium ${STATUS_COLORS[conn.status] ?? ""}`,
|
|
175
|
+
children: conn.status
|
|
176
|
+
})
|
|
177
|
+
}),
|
|
178
|
+
/* @__PURE__ */ jsx("td", {
|
|
179
|
+
className: "text-muted-foreground px-4 py-3 text-sm",
|
|
180
|
+
children: conn.lastSyncAt?.toLocaleString() ?? "Never"
|
|
181
|
+
})
|
|
182
|
+
]
|
|
183
|
+
}, conn.id)), connections.length === 0 && /* @__PURE__ */ jsx("tr", { children: /* @__PURE__ */ jsx("td", {
|
|
184
|
+
colSpan: 3,
|
|
185
|
+
className: "text-muted-foreground px-4 py-8 text-center",
|
|
186
|
+
children: "No connections found"
|
|
187
|
+
}) })]
|
|
188
|
+
})]
|
|
189
|
+
})
|
|
190
|
+
}),
|
|
191
|
+
activeTab === "syncs" && /* @__PURE__ */ jsx("div", {
|
|
192
|
+
className: "border-border rounded-lg border",
|
|
193
|
+
children: /* @__PURE__ */ jsxs("table", {
|
|
194
|
+
className: "w-full",
|
|
195
|
+
children: [/* @__PURE__ */ jsx("thead", {
|
|
196
|
+
className: "border-border bg-muted/30 border-b",
|
|
197
|
+
children: /* @__PURE__ */ jsxs("tr", { children: [
|
|
198
|
+
/* @__PURE__ */ jsx("th", {
|
|
199
|
+
className: "px-4 py-3 text-left text-sm font-medium",
|
|
200
|
+
children: "Sync Config"
|
|
201
|
+
}),
|
|
202
|
+
/* @__PURE__ */ jsx("th", {
|
|
203
|
+
className: "px-4 py-3 text-left text-sm font-medium",
|
|
204
|
+
children: "Frequency"
|
|
205
|
+
}),
|
|
206
|
+
/* @__PURE__ */ jsx("th", {
|
|
207
|
+
className: "px-4 py-3 text-left text-sm font-medium",
|
|
208
|
+
children: "Status"
|
|
209
|
+
}),
|
|
210
|
+
/* @__PURE__ */ jsx("th", {
|
|
211
|
+
className: "px-4 py-3 text-left text-sm font-medium",
|
|
212
|
+
children: "Records"
|
|
213
|
+
})
|
|
214
|
+
] })
|
|
215
|
+
}), /* @__PURE__ */ jsxs("tbody", {
|
|
216
|
+
className: "divide-border divide-y",
|
|
217
|
+
children: [syncConfigs.map((sync) => /* @__PURE__ */ jsxs("tr", {
|
|
218
|
+
className: "hover:bg-muted/50",
|
|
219
|
+
children: [
|
|
220
|
+
/* @__PURE__ */ jsxs("td", {
|
|
221
|
+
className: "px-4 py-3",
|
|
222
|
+
children: [/* @__PURE__ */ jsx("div", {
|
|
223
|
+
className: "font-medium",
|
|
224
|
+
children: sync.name
|
|
225
|
+
}), /* @__PURE__ */ jsxs("div", {
|
|
226
|
+
className: "text-muted-foreground text-sm",
|
|
227
|
+
children: [
|
|
228
|
+
sync.sourceEntity,
|
|
229
|
+
" → ",
|
|
230
|
+
sync.targetEntity
|
|
231
|
+
]
|
|
232
|
+
})]
|
|
233
|
+
}),
|
|
234
|
+
/* @__PURE__ */ jsx("td", {
|
|
235
|
+
className: "px-4 py-3 text-sm",
|
|
236
|
+
children: sync.frequency
|
|
237
|
+
}),
|
|
238
|
+
/* @__PURE__ */ jsx("td", {
|
|
239
|
+
className: "px-4 py-3",
|
|
240
|
+
children: /* @__PURE__ */ jsx("span", {
|
|
241
|
+
className: `inline-flex rounded-full px-2 py-0.5 text-xs font-medium ${STATUS_COLORS[sync.status] ?? ""}`,
|
|
242
|
+
children: sync.status
|
|
243
|
+
})
|
|
244
|
+
}),
|
|
245
|
+
/* @__PURE__ */ jsx("td", {
|
|
246
|
+
className: "text-muted-foreground px-4 py-3 text-sm",
|
|
247
|
+
children: sync.recordsSynced.toLocaleString()
|
|
248
|
+
})
|
|
249
|
+
]
|
|
250
|
+
}, sync.id)), syncConfigs.length === 0 && /* @__PURE__ */ jsx("tr", { children: /* @__PURE__ */ jsx("td", {
|
|
251
|
+
colSpan: 4,
|
|
252
|
+
className: "text-muted-foreground px-4 py-8 text-center",
|
|
253
|
+
children: "No sync configurations found"
|
|
254
|
+
}) })]
|
|
255
|
+
})]
|
|
256
|
+
})
|
|
257
|
+
})
|
|
258
|
+
]
|
|
259
|
+
})
|
|
260
|
+
]
|
|
261
|
+
});
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
//#endregion
|
|
265
|
+
export { IntegrationDashboard };
|
|
266
|
+
//# sourceMappingURL=IntegrationDashboard.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"IntegrationDashboard.js","names":[],"sources":["../../src/ui/IntegrationDashboard.tsx"],"sourcesContent":["'use client';\n\n/**\n * Integration Hub Dashboard\n *\n * Interactive dashboard for the integration-hub template.\n * Displays integrations, connections, and sync configurations.\n */\nimport { useState } from 'react';\nimport {\n Button,\n ErrorState,\n LoaderBlock,\n StatCard,\n StatCardGroup,\n} from '@contractspec/lib.design-system';\nimport { useIntegrationData } from './hooks/useIntegrationData';\n\ntype Tab = 'integrations' | 'connections' | 'syncs';\n\nconst STATUS_COLORS: Record<string, string> = {\n ACTIVE:\n 'bg-green-100 text-green-700 dark:bg-green-900/30 dark:text-green-400',\n INACTIVE: 'bg-gray-100 text-gray-700 dark:bg-gray-900/30 dark:text-gray-400',\n CONNECTED:\n 'bg-green-100 text-green-700 dark:bg-green-900/30 dark:text-green-400',\n DISCONNECTED:\n 'bg-gray-100 text-gray-700 dark:bg-gray-900/30 dark:text-gray-400',\n PENDING:\n 'bg-yellow-100 text-yellow-700 dark:bg-yellow-900/30 dark:text-yellow-400',\n ERROR: 'bg-red-100 text-red-700 dark:bg-red-900/30 dark:text-red-400',\n PAUSED:\n 'bg-yellow-100 text-yellow-700 dark:bg-yellow-900/30 dark:text-yellow-400',\n};\n\nconst TYPE_ICONS: Record<string, string> = {\n CRM: '📊',\n MARKETING: '📣',\n PAYMENT: '💳',\n COMMUNICATION: '💬',\n DATA: '🗄️',\n CUSTOM: '⚙️',\n};\n\nexport function IntegrationDashboard() {\n const [activeTab, setActiveTab] = useState<Tab>('integrations');\n const {\n integrations,\n connections,\n syncConfigs,\n loading,\n error,\n stats,\n refetch,\n } = useIntegrationData();\n\n const tabs: { id: Tab; label: string; icon: string }[] = [\n { id: 'integrations', label: 'Integrations', icon: '🔌' },\n { id: 'connections', label: 'Connections', icon: '🔗' },\n { id: 'syncs', label: 'Sync Configs', icon: '🔄' },\n ];\n\n if (loading) {\n return <LoaderBlock label=\"Loading Integrations...\" />;\n }\n\n if (error) {\n return (\n <ErrorState\n title=\"Failed to load Integrations\"\n description={error.message}\n onRetry={refetch}\n retryLabel=\"Retry\"\n />\n );\n }\n\n return (\n <div className=\"space-y-6\">\n {/* Header */}\n <div className=\"flex items-center justify-between\">\n <h2 className=\"text-2xl font-bold\">Integration Hub</h2>\n <Button onClick={() => alert('Add integration modal')}>\n <span className=\"mr-2\">+</span> Add Integration\n </Button>\n </div>\n\n {/* Stats Row */}\n <StatCardGroup>\n <StatCard\n label=\"Integrations\"\n value={stats.totalIntegrations}\n hint={`${stats.activeIntegrations} active`}\n />\n <StatCard\n label=\"Connections\"\n value={stats.totalConnections}\n hint={`${stats.connectedCount} connected`}\n />\n <StatCard\n label=\"Syncs\"\n value={stats.totalSyncs}\n hint={`${stats.activeSyncs} active`}\n />\n </StatCardGroup>\n\n {/* Navigation Tabs */}\n <nav className=\"bg-muted flex gap-1 rounded-lg p-1\" role=\"tablist\">\n {tabs.map((tab) => (\n <Button\n key={tab.id}\n type=\"button\"\n role=\"tab\"\n aria-selected={activeTab === tab.id}\n onClick={() => setActiveTab(tab.id)}\n className={`flex flex-1 items-center justify-center gap-2 rounded-md px-4 py-2 text-sm font-medium transition-colors ${\n activeTab === tab.id\n ? 'bg-background text-foreground shadow-sm'\n : 'text-muted-foreground hover:text-foreground'\n }`}\n >\n <span>{tab.icon}</span>\n {tab.label}\n </Button>\n ))}\n </nav>\n\n {/* Tab Content */}\n <div className=\"min-h-[400px]\" role=\"tabpanel\">\n {activeTab === 'integrations' && (\n <div className=\"grid gap-4 sm:grid-cols-2 lg:grid-cols-3\">\n {integrations.map((integration) => (\n <div\n key={integration.id}\n className=\"border-border bg-card hover:bg-muted/50 cursor-pointer rounded-lg border p-4 transition-colors\"\n >\n <div className=\"mb-3 flex items-center gap-3\">\n <span className=\"text-2xl\">\n {TYPE_ICONS[integration.type] ?? '⚙️'}\n </span>\n <div>\n <h3 className=\"font-medium\">{integration.name}</h3>\n <p className=\"text-muted-foreground text-sm\">\n {integration.type}\n </p>\n </div>\n </div>\n <div className=\"flex items-center justify-between\">\n <span\n className={`inline-flex rounded-full px-2 py-0.5 text-xs font-medium ${STATUS_COLORS[integration.status] ?? ''}`}\n >\n {integration.status}\n </span>\n <span className=\"text-muted-foreground text-xs\">\n {integration.createdAt.toLocaleDateString()}\n </span>\n </div>\n </div>\n ))}\n {integrations.length === 0 && (\n <div className=\"text-muted-foreground col-span-full flex h-64 items-center justify-center\">\n No integrations configured\n </div>\n )}\n </div>\n )}\n\n {activeTab === 'connections' && (\n <div className=\"border-border rounded-lg border\">\n <table className=\"w-full\">\n <thead className=\"border-border bg-muted/30 border-b\">\n <tr>\n <th className=\"px-4 py-3 text-left text-sm font-medium\">\n Connection\n </th>\n <th className=\"px-4 py-3 text-left text-sm font-medium\">\n Status\n </th>\n <th className=\"px-4 py-3 text-left text-sm font-medium\">\n Last Sync\n </th>\n </tr>\n </thead>\n <tbody className=\"divide-border divide-y\">\n {connections.map((conn) => (\n <tr key={conn.id} className=\"hover:bg-muted/50\">\n <td className=\"px-4 py-3\">\n <div className=\"font-medium\">{conn.name}</div>\n </td>\n <td className=\"px-4 py-3\">\n <span\n className={`inline-flex rounded-full px-2 py-0.5 text-xs font-medium ${STATUS_COLORS[conn.status] ?? ''}`}\n >\n {conn.status}\n </span>\n </td>\n <td className=\"text-muted-foreground px-4 py-3 text-sm\">\n {conn.lastSyncAt?.toLocaleString() ?? 'Never'}\n </td>\n </tr>\n ))}\n {connections.length === 0 && (\n <tr>\n <td\n colSpan={3}\n className=\"text-muted-foreground px-4 py-8 text-center\"\n >\n No connections found\n </td>\n </tr>\n )}\n </tbody>\n </table>\n </div>\n )}\n\n {activeTab === 'syncs' && (\n <div className=\"border-border rounded-lg border\">\n <table className=\"w-full\">\n <thead className=\"border-border bg-muted/30 border-b\">\n <tr>\n <th className=\"px-4 py-3 text-left text-sm font-medium\">\n Sync Config\n </th>\n <th className=\"px-4 py-3 text-left text-sm font-medium\">\n Frequency\n </th>\n <th className=\"px-4 py-3 text-left text-sm font-medium\">\n Status\n </th>\n <th className=\"px-4 py-3 text-left text-sm font-medium\">\n Records\n </th>\n </tr>\n </thead>\n <tbody className=\"divide-border divide-y\">\n {syncConfigs.map((sync) => (\n <tr key={sync.id} className=\"hover:bg-muted/50\">\n <td className=\"px-4 py-3\">\n <div className=\"font-medium\">{sync.name}</div>\n <div className=\"text-muted-foreground text-sm\">\n {sync.sourceEntity} → {sync.targetEntity}\n </div>\n </td>\n <td className=\"px-4 py-3 text-sm\">{sync.frequency}</td>\n <td className=\"px-4 py-3\">\n <span\n className={`inline-flex rounded-full px-2 py-0.5 text-xs font-medium ${STATUS_COLORS[sync.status] ?? ''}`}\n >\n {sync.status}\n </span>\n </td>\n <td className=\"text-muted-foreground px-4 py-3 text-sm\">\n {sync.recordsSynced.toLocaleString()}\n </td>\n </tr>\n ))}\n {syncConfigs.length === 0 && (\n <tr>\n <td\n colSpan={4}\n className=\"text-muted-foreground px-4 py-8 text-center\"\n >\n No sync configurations found\n </td>\n </tr>\n )}\n </tbody>\n </table>\n </div>\n )}\n </div>\n </div>\n );\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { Connection, Integration, SyncConfig } from "../../handlers/integration.handlers.js";
|
|
2
|
+
|
|
3
|
+
//#region src/ui/hooks/useIntegrationData.d.ts
|
|
4
|
+
interface IntegrationStats {
|
|
5
|
+
totalIntegrations: number;
|
|
6
|
+
activeIntegrations: number;
|
|
7
|
+
totalConnections: number;
|
|
8
|
+
connectedCount: number;
|
|
9
|
+
totalSyncs: number;
|
|
10
|
+
activeSyncs: number;
|
|
11
|
+
}
|
|
12
|
+
declare function useIntegrationData(projectId?: string): {
|
|
13
|
+
integrations: Integration[];
|
|
14
|
+
connections: Connection[];
|
|
15
|
+
syncConfigs: SyncConfig[];
|
|
16
|
+
loading: boolean;
|
|
17
|
+
error: Error | null;
|
|
18
|
+
stats: IntegrationStats;
|
|
19
|
+
refetch: () => Promise<void>;
|
|
20
|
+
};
|
|
21
|
+
//#endregion
|
|
22
|
+
export { IntegrationStats, useIntegrationData };
|
|
23
|
+
//# sourceMappingURL=useIntegrationData.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useIntegrationData.d.ts","names":[],"sources":["../../../src/ui/hooks/useIntegrationData.ts"],"sourcesContent":[],"mappings":";;;UAWiB,gBAAA;;EAAA,kBAAA,EAAgB,MAAA;EASjB,gBAAA,EAAA,MAAkB;;;;;iBAAlB,kBAAA"}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
|
|
3
|
+
import { useCallback, useEffect, useState } from "react";
|
|
4
|
+
import { useTemplateRuntime } from "@contractspec/lib.example-shared-ui";
|
|
5
|
+
|
|
6
|
+
//#region src/ui/hooks/useIntegrationData.ts
|
|
7
|
+
function useIntegrationData(projectId = "local-project") {
|
|
8
|
+
const { handlers } = useTemplateRuntime();
|
|
9
|
+
const integration = handlers.integration;
|
|
10
|
+
const [integrations, setIntegrations] = useState([]);
|
|
11
|
+
const [connections, setConnections] = useState([]);
|
|
12
|
+
const [syncConfigs, setSyncConfigs] = useState([]);
|
|
13
|
+
const [loading, setLoading] = useState(true);
|
|
14
|
+
const [error, setError] = useState(null);
|
|
15
|
+
const fetchData = useCallback(async () => {
|
|
16
|
+
try {
|
|
17
|
+
setLoading(true);
|
|
18
|
+
setError(null);
|
|
19
|
+
const [integResult, connResult, syncResult] = await Promise.all([
|
|
20
|
+
integration.listIntegrations({
|
|
21
|
+
projectId,
|
|
22
|
+
limit: 100
|
|
23
|
+
}),
|
|
24
|
+
integration.listConnections({ limit: 100 }),
|
|
25
|
+
integration.listSyncConfigs({ limit: 100 })
|
|
26
|
+
]);
|
|
27
|
+
setIntegrations(integResult.integrations);
|
|
28
|
+
setConnections(connResult.connections);
|
|
29
|
+
setSyncConfigs(syncResult.configs);
|
|
30
|
+
} catch (err) {
|
|
31
|
+
setError(err instanceof Error ? err : /* @__PURE__ */ new Error("Failed to load integrations"));
|
|
32
|
+
} finally {
|
|
33
|
+
setLoading(false);
|
|
34
|
+
}
|
|
35
|
+
}, [integration, projectId]);
|
|
36
|
+
useEffect(() => {
|
|
37
|
+
fetchData();
|
|
38
|
+
}, [fetchData]);
|
|
39
|
+
return {
|
|
40
|
+
integrations,
|
|
41
|
+
connections,
|
|
42
|
+
syncConfigs,
|
|
43
|
+
loading,
|
|
44
|
+
error,
|
|
45
|
+
stats: {
|
|
46
|
+
totalIntegrations: integrations.length,
|
|
47
|
+
activeIntegrations: integrations.filter((i) => i.status === "ACTIVE").length,
|
|
48
|
+
totalConnections: connections.length,
|
|
49
|
+
connectedCount: connections.filter((c) => c.status === "CONNECTED").length,
|
|
50
|
+
totalSyncs: syncConfigs.length,
|
|
51
|
+
activeSyncs: syncConfigs.filter((s) => s.status === "ACTIVE").length
|
|
52
|
+
},
|
|
53
|
+
refetch: fetchData
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
//#endregion
|
|
58
|
+
export { useIntegrationData };
|
|
59
|
+
//# sourceMappingURL=useIntegrationData.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useIntegrationData.js","names":[],"sources":["../../../src/ui/hooks/useIntegrationData.ts"],"sourcesContent":["'use client';\n\nimport { useCallback, useEffect, useState } from 'react';\nimport type {\n Connection,\n Integration,\n IntegrationHandlers,\n SyncConfig,\n} from '../../handlers/integration.handlers';\nimport { useTemplateRuntime } from '@contractspec/lib.example-shared-ui';\n\nexport interface IntegrationStats {\n totalIntegrations: number;\n activeIntegrations: number;\n totalConnections: number;\n connectedCount: number;\n totalSyncs: number;\n activeSyncs: number;\n}\n\nexport function useIntegrationData(projectId = 'local-project') {\n const { handlers } = useTemplateRuntime<{\n integration: IntegrationHandlers;\n }>();\n const integration = handlers.integration;\n const [integrations, setIntegrations] = useState<Integration[]>([]);\n const [connections, setConnections] = useState<Connection[]>([]);\n const [syncConfigs, setSyncConfigs] = useState<SyncConfig[]>([]);\n const [loading, setLoading] = useState(true);\n const [error, setError] = useState<Error | null>(null);\n\n const fetchData = useCallback(async () => {\n try {\n setLoading(true);\n setError(null);\n\n const [integResult, connResult, syncResult] = await Promise.all([\n integration.listIntegrations({ projectId, limit: 100 }),\n integration.listConnections({ limit: 100 }),\n integration.listSyncConfigs({ limit: 100 }),\n ]);\n\n setIntegrations(integResult.integrations);\n setConnections(connResult.connections);\n setSyncConfigs(syncResult.configs);\n } catch (err) {\n setError(\n err instanceof Error ? err : new Error('Failed to load integrations')\n );\n } finally {\n setLoading(false);\n }\n }, [integration, projectId]);\n\n useEffect(() => {\n fetchData();\n }, [fetchData]);\n\n const stats: IntegrationStats = {\n totalIntegrations: integrations.length,\n activeIntegrations: integrations.filter((i) => i.status === 'ACTIVE')\n .length,\n totalConnections: connections.length,\n connectedCount: connections.filter((c) => c.status === 'CONNECTED').length,\n totalSyncs: syncConfigs.length,\n activeSyncs: syncConfigs.filter((s) => s.status === 'ACTIVE').length,\n };\n\n return {\n integrations,\n connections,\n syncConfigs,\n loading,\n error,\n stats,\n refetch: fetchData,\n };\n}\n"],"mappings":";;;;;;AAoBA,SAAgB,mBAAmB,YAAY,iBAAiB;CAC9D,MAAM,EAAE,aAAa,oBAEjB;CACJ,MAAM,cAAc,SAAS;CAC7B,MAAM,CAAC,cAAc,mBAAmB,SAAwB,EAAE,CAAC;CACnE,MAAM,CAAC,aAAa,kBAAkB,SAAuB,EAAE,CAAC;CAChE,MAAM,CAAC,aAAa,kBAAkB,SAAuB,EAAE,CAAC;CAChE,MAAM,CAAC,SAAS,cAAc,SAAS,KAAK;CAC5C,MAAM,CAAC,OAAO,YAAY,SAAuB,KAAK;CAEtD,MAAM,YAAY,YAAY,YAAY;AACxC,MAAI;AACF,cAAW,KAAK;AAChB,YAAS,KAAK;GAEd,MAAM,CAAC,aAAa,YAAY,cAAc,MAAM,QAAQ,IAAI;IAC9D,YAAY,iBAAiB;KAAE;KAAW,OAAO;KAAK,CAAC;IACvD,YAAY,gBAAgB,EAAE,OAAO,KAAK,CAAC;IAC3C,YAAY,gBAAgB,EAAE,OAAO,KAAK,CAAC;IAC5C,CAAC;AAEF,mBAAgB,YAAY,aAAa;AACzC,kBAAe,WAAW,YAAY;AACtC,kBAAe,WAAW,QAAQ;WAC3B,KAAK;AACZ,YACE,eAAe,QAAQ,sBAAM,IAAI,MAAM,8BAA8B,CACtE;YACO;AACR,cAAW,MAAM;;IAElB,CAAC,aAAa,UAAU,CAAC;AAE5B,iBAAgB;AACd,aAAW;IACV,CAAC,UAAU,CAAC;AAYf,QAAO;EACL;EACA;EACA;EACA;EACA;EACA,OAhB8B;GAC9B,mBAAmB,aAAa;GAChC,oBAAoB,aAAa,QAAQ,MAAM,EAAE,WAAW,SAAS,CAClE;GACH,kBAAkB,YAAY;GAC9B,gBAAgB,YAAY,QAAQ,MAAM,EAAE,WAAW,YAAY,CAAC;GACpE,YAAY,YAAY;GACxB,aAAa,YAAY,QAAQ,MAAM,EAAE,WAAW,SAAS,CAAC;GAC/D;EASC,SAAS;EACV"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { connectionListMarkdownRenderer, integrationDashboardMarkdownRenderer, syncConfigMarkdownRenderer } from "./renderers/integration.markdown.js";
|
|
2
|
+
import "./renderers/index.js";
|
|
3
|
+
import { IntegrationDashboard } from "./IntegrationDashboard.js";
|
|
4
|
+
import { IntegrationStats, useIntegrationData } from "./hooks/useIntegrationData.js";
|
|
5
|
+
import "./hooks/index.js";
|
|
6
|
+
export { IntegrationDashboard, IntegrationStats, connectionListMarkdownRenderer, integrationDashboardMarkdownRenderer, syncConfigMarkdownRenderer, useIntegrationData };
|
package/dist/ui/index.js
ADDED
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { connectionListMarkdownRenderer, integrationDashboardMarkdownRenderer, syncConfigMarkdownRenderer } from "./renderers/integration.markdown.js";
|
|
2
|
+
import { useIntegrationData } from "./hooks/useIntegrationData.js";
|
|
3
|
+
import { IntegrationDashboard } from "./IntegrationDashboard.js";
|
|
4
|
+
import "./hooks/index.js";
|
|
5
|
+
|
|
6
|
+
export { IntegrationDashboard, connectionListMarkdownRenderer, integrationDashboardMarkdownRenderer, syncConfigMarkdownRenderer, useIntegrationData };
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { PresentationRenderer } from "@contractspec/lib.contracts";
|
|
2
|
+
|
|
3
|
+
//#region src/ui/renderers/integration.markdown.d.ts
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Markdown renderer for Integration Dashboard
|
|
7
|
+
*/
|
|
8
|
+
declare const integrationDashboardMarkdownRenderer: PresentationRenderer<{
|
|
9
|
+
mimeType: string;
|
|
10
|
+
body: string;
|
|
11
|
+
}>;
|
|
12
|
+
/**
|
|
13
|
+
* Markdown renderer for Connection List
|
|
14
|
+
*/
|
|
15
|
+
declare const connectionListMarkdownRenderer: PresentationRenderer<{
|
|
16
|
+
mimeType: string;
|
|
17
|
+
body: string;
|
|
18
|
+
}>;
|
|
19
|
+
/**
|
|
20
|
+
* Markdown renderer for Sync Config
|
|
21
|
+
*/
|
|
22
|
+
declare const syncConfigMarkdownRenderer: PresentationRenderer<{
|
|
23
|
+
mimeType: string;
|
|
24
|
+
body: string;
|
|
25
|
+
}>;
|
|
26
|
+
//#endregion
|
|
27
|
+
export { connectionListMarkdownRenderer, integrationDashboardMarkdownRenderer, syncConfigMarkdownRenderer };
|
|
28
|
+
//# sourceMappingURL=integration.markdown.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"integration.markdown.d.ts","names":[],"sources":["../../../src/ui/renderers/integration.markdown.ts"],"sourcesContent":[],"mappings":";;;;AAgOA;AA8DA;;cAjKa,sCAAsC;;;;;;;cAmGtC,gCAAgC;;;;;;;cA8DhC,4BAA4B"}
|