@checkstack/integration-frontend 0.4.5 → 0.5.1
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/CHANGELOG.md +154 -0
- package/package.json +8 -8
- package/src/components/IntegrationMenuItem.tsx +14 -9
- package/src/index.tsx +9 -14
- package/src/pages/IntegrationsLandingPage.tsx +116 -0
- package/src/components/CreateSubscriptionDialog.tsx +0 -652
- package/src/pages/DeliveryLogsPage.tsx +0 -300
- package/src/pages/IntegrationsPage.tsx +0 -378
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,159 @@
|
|
|
1
1
|
# @checkstack/integration-frontend
|
|
2
2
|
|
|
3
|
+
## 0.5.1
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- Updated dependencies [b995afb]
|
|
8
|
+
- Updated dependencies [270ef29]
|
|
9
|
+
- Updated dependencies [b995afb]
|
|
10
|
+
- Updated dependencies [b995afb]
|
|
11
|
+
- Updated dependencies [b995afb]
|
|
12
|
+
- Updated dependencies [b995afb]
|
|
13
|
+
- Updated dependencies [270ef29]
|
|
14
|
+
- Updated dependencies [b995afb]
|
|
15
|
+
- Updated dependencies [b995afb]
|
|
16
|
+
- Updated dependencies [b995afb]
|
|
17
|
+
- Updated dependencies [270ef29]
|
|
18
|
+
- Updated dependencies [b995afb]
|
|
19
|
+
- Updated dependencies [270ef29]
|
|
20
|
+
- @checkstack/ui@1.12.0
|
|
21
|
+
- @checkstack/tips-frontend@0.2.7
|
|
22
|
+
|
|
23
|
+
## 0.5.0
|
|
24
|
+
|
|
25
|
+
### Minor Changes
|
|
26
|
+
|
|
27
|
+
- e2d6f25: feat(automation): connection picker for integration actions + restore Integrations menu
|
|
28
|
+
|
|
29
|
+
Connection-backed automation actions (Jira, Teams, Webex) now render a
|
|
30
|
+
working connection picker plus cascading provider dropdowns in the
|
|
31
|
+
visual editor, and the Integrations entry is back in the user menu.
|
|
32
|
+
|
|
33
|
+
**Contract.** `ActionDefinition` gained an optional
|
|
34
|
+
`connectionProviderId` (and it is surfaced on `ActionInfoSchema` and
|
|
35
|
+
mapped in the `listActions` router). It carries the integration
|
|
36
|
+
provider's fully-qualified id, derived from the provider plugin's own
|
|
37
|
+
`pluginMetadata.pluginId` (never a hardcoded string), so the editor
|
|
38
|
+
knows which provider backs an action's dropdowns and it matches the
|
|
39
|
+
`qualifiedId` the integration provider registry assigns.
|
|
40
|
+
|
|
41
|
+
**Providers.** Jira, Teams and Webex each export
|
|
42
|
+
`*_PROVIDER_LOCAL_ID` / `*_PROVIDER_QUALIFIED_ID`, register their
|
|
43
|
+
provider with the local id, and add a `CONNECTION_OPTIONS`
|
|
44
|
+
(`"connectionOptions"`) resolver name. Their `post_message` /
|
|
45
|
+
issue actions set `connectionProviderId` and expose `connectionId`
|
|
46
|
+
as an `x-options-resolver` dropdown instead of a hidden field.
|
|
47
|
+
|
|
48
|
+
**Frontend bridge.** A new `useConnectionOptionResolvers` hook
|
|
49
|
+
(`@checkstack/automation-frontend`, which now depends on
|
|
50
|
+
`@checkstack/integration-common`) turns an action's
|
|
51
|
+
`x-options-resolver` schema fields into live data: the
|
|
52
|
+
`connectionOptions` resolver lists the provider's connections via
|
|
53
|
+
`listConnections`, and every other resolver name is forwarded to
|
|
54
|
+
`getConnectionOptions` for the selected `connectionId`, passing the
|
|
55
|
+
live form values as `context` for dependent fields. `ProviderActionBody`
|
|
56
|
+
now passes this map to `DynamicForm` (it was previously missing
|
|
57
|
+
entirely, so connection-backed actions had no working dropdowns).
|
|
58
|
+
|
|
59
|
+
**frontend-api.** `usePluginClient` procedures now also expose a typed
|
|
60
|
+
imperative `.call(input)` alongside `.useQuery` / `.useMutation`, for
|
|
61
|
+
async callbacks that cannot host a hook (such as a `DynamicForm`
|
|
62
|
+
options resolver). Additive, non-breaking.
|
|
63
|
+
|
|
64
|
+
**Integrations menu.** Re-added `IntegrationMenuItem` and a new
|
|
65
|
+
`IntegrationsLandingPage`, wired into `integration-frontend` as a list
|
|
66
|
+
route and a `UserMenuItemsSlot` entry under the "Configuration" group.
|
|
67
|
+
|
|
68
|
+
**Action card polish.** The action editor's secondary metadata (id,
|
|
69
|
+
description, failure behaviour) is now grouped into one quiet settings
|
|
70
|
+
panel with consistent small uppercase "eyebrow" labels, so the action's
|
|
71
|
+
own configuration stays the focal point. The raw failure checkbox was
|
|
72
|
+
replaced with the standard `Checkbox` control, and the provider action
|
|
73
|
+
picker / configuration sections gained consistent section headers and a
|
|
74
|
+
divider. The per-step "type" dropdown was removed: an action's kind is
|
|
75
|
+
fixed at creation, so changing it now means adding a new step and
|
|
76
|
+
deleting the old one (avoids the surprising full-config reset that
|
|
77
|
+
switching kinds used to trigger).
|
|
78
|
+
|
|
79
|
+
**Add-step picker.** Adding a step now opens a Home-Assistant-style
|
|
80
|
+
dialog where the operator decides the step type up front: an "Actions"
|
|
81
|
+
tab lists the registered provider actions grouped by category
|
|
82
|
+
(searchable; picking one presets the step's `action`), and a "Blocks"
|
|
83
|
+
tab lists the structural building blocks (choose / parallel / repeat /
|
|
84
|
+
etc.). Because the concrete action is chosen here, the in-card action
|
|
85
|
+
switcher was removed - a step's action is fixed once created. Composite
|
|
86
|
+
blocks now start with an empty child list (filled via the nested
|
|
87
|
+
add-step picker) instead of seeding an unconfigurable empty action.
|
|
88
|
+
|
|
89
|
+
- 41c77f4: feat(automation): one-time migration of webhook subscriptions + remove legacy integration backend
|
|
90
|
+
|
|
91
|
+
**BREAKING CHANGES** (platform is in BETA — no major bump):
|
|
92
|
+
|
|
93
|
+
- `IntegrationProvider` no longer carries `config` (subscription
|
|
94
|
+
config) or `deliver`. The interface now models a connection provider
|
|
95
|
+
only: connection schema + `getConnectionOptions` + `testConnection`.
|
|
96
|
+
- The legacy subscription / delivery-log / event endpoints
|
|
97
|
+
(`listSubscriptions`, `createSubscription`, `getDeliveryLogs`,
|
|
98
|
+
`listEventTypes`, …) are removed from `integrationContract`.
|
|
99
|
+
- `delivery-coordinator`, `hook-subscriber`, `event-registry`, and the
|
|
100
|
+
`integrationEventExtensionPoint` are deleted. Plugins that
|
|
101
|
+
previously called `integrationEvents.registerEvent(...)` now
|
|
102
|
+
register their hooks as automation triggers via
|
|
103
|
+
`automationTriggerExtensionPoint.registerTrigger(...)`.
|
|
104
|
+
- Frontend pages `IntegrationsPage` and `DeliveryLogsPage` are gone;
|
|
105
|
+
the integration plugin's only remaining UI is connection
|
|
106
|
+
management. Subscription management lives under `/automation/...`.
|
|
107
|
+
- `webhook_subscriptions` and `delivery_logs` tables stay in the
|
|
108
|
+
database for one release as a safety net (no code reads or writes
|
|
109
|
+
them), and will be dropped in a follow-up migration.
|
|
110
|
+
|
|
111
|
+
**New**:
|
|
112
|
+
|
|
113
|
+
- `jira.create_issue`, `teams.post_message`, `webex.post_message`,
|
|
114
|
+
`webhook.send`, `integration-script.run_shell`, and
|
|
115
|
+
`integration-script.run_script` actions registered against the
|
|
116
|
+
Automation Platform with matching `*.message`, `*.delivery`,
|
|
117
|
+
`shell.result`, and `script.result` artifact types. The script
|
|
118
|
+
plugin exposes **two** actions — `run_shell` runs bash via the
|
|
119
|
+
shared `ShellScriptRunner` (Monaco `shell` editor), `run_script`
|
|
120
|
+
runs an ESM module in a Bun subprocess via `EsmScriptRunner`
|
|
121
|
+
(Monaco `typescript` editor + `defineIntegration` helper) — to
|
|
122
|
+
preserve the legacy provider split. `jira.create_issue` keeps the
|
|
123
|
+
dynamic field-mapping dropdown (driven by
|
|
124
|
+
`JIRA_RESOLVERS.FIELD_OPTIONS`).
|
|
125
|
+
- One-time data migration runs on boot in
|
|
126
|
+
`automation-backend.afterPluginsReady`. It reads
|
|
127
|
+
`webhook_subscriptions` via a new service RPC
|
|
128
|
+
`IntegrationApi.listLegacySubscriptions`, translates each row into
|
|
129
|
+
a single-trigger / single-action automation (marked with
|
|
130
|
+
`managed_by = "migrated-subscription:<id>"`), and is idempotent
|
|
131
|
+
across restarts.
|
|
132
|
+
- Failed translations are recorded in a new
|
|
133
|
+
`automation_migration_failures` table and surfaced via
|
|
134
|
+
`AutomationApi.listMigrationFailures` /
|
|
135
|
+
`acknowledgeMigrationFailure` so admins can review and re-create
|
|
136
|
+
failed entries by hand.
|
|
137
|
+
|
|
138
|
+
### Patch Changes
|
|
139
|
+
|
|
140
|
+
- Updated dependencies [e2d6f25]
|
|
141
|
+
- Updated dependencies [41c77f4]
|
|
142
|
+
- Updated dependencies [41c77f4]
|
|
143
|
+
- Updated dependencies [41c77f4]
|
|
144
|
+
- Updated dependencies [41c77f4]
|
|
145
|
+
- Updated dependencies [41c77f4]
|
|
146
|
+
- Updated dependencies [4832e33]
|
|
147
|
+
- Updated dependencies [6d52276]
|
|
148
|
+
- Updated dependencies [35bc682]
|
|
149
|
+
- Updated dependencies [c39ee69]
|
|
150
|
+
- @checkstack/frontend-api@0.6.0
|
|
151
|
+
- @checkstack/ui@1.11.0
|
|
152
|
+
- @checkstack/integration-common@0.6.0
|
|
153
|
+
- @checkstack/common@0.12.0
|
|
154
|
+
- @checkstack/tips-frontend@0.2.6
|
|
155
|
+
- @checkstack/signal-frontend@0.1.5
|
|
156
|
+
|
|
3
157
|
## 0.4.5
|
|
4
158
|
|
|
5
159
|
### Patch Changes
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@checkstack/integration-frontend",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.5.1",
|
|
4
4
|
"license": "Elastic-2.0",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "src/index.tsx",
|
|
@@ -13,12 +13,12 @@
|
|
|
13
13
|
"lint:code": "eslint . --max-warnings 0"
|
|
14
14
|
},
|
|
15
15
|
"dependencies": {
|
|
16
|
-
"@checkstack/common": "0.
|
|
17
|
-
"@checkstack/frontend-api": "0.
|
|
18
|
-
"@checkstack/integration-common": "0.
|
|
19
|
-
"@checkstack/signal-frontend": "0.1.
|
|
20
|
-
"@checkstack/tips-frontend": "0.2.
|
|
21
|
-
"@checkstack/ui": "1.
|
|
16
|
+
"@checkstack/common": "0.12.0",
|
|
17
|
+
"@checkstack/frontend-api": "0.6.0",
|
|
18
|
+
"@checkstack/integration-common": "0.6.0",
|
|
19
|
+
"@checkstack/signal-frontend": "0.1.5",
|
|
20
|
+
"@checkstack/tips-frontend": "0.2.6",
|
|
21
|
+
"@checkstack/ui": "1.11.0",
|
|
22
22
|
"lucide-react": "^0.344.0",
|
|
23
23
|
"react": "^18.2.0",
|
|
24
24
|
"react-router-dom": "^6.22.0"
|
|
@@ -27,6 +27,6 @@
|
|
|
27
27
|
"typescript": "^5.0.0",
|
|
28
28
|
"@types/react": "^18.2.0",
|
|
29
29
|
"@checkstack/tsconfig": "0.0.7",
|
|
30
|
-
"@checkstack/scripts": "0.3.
|
|
30
|
+
"@checkstack/scripts": "0.3.4"
|
|
31
31
|
}
|
|
32
32
|
}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import
|
|
1
|
+
import React from "react";
|
|
2
|
+
import { Link } from "react-router-dom";
|
|
2
3
|
import { Webhook } from "lucide-react";
|
|
3
4
|
import { DropdownMenuItem } from "@checkstack/ui";
|
|
4
5
|
import type { UserMenuItemsContext } from "@checkstack/frontend-api";
|
|
@@ -8,12 +9,17 @@ import {
|
|
|
8
9
|
integrationAccess,
|
|
9
10
|
pluginMetadata,
|
|
10
11
|
} from "@checkstack/integration-common";
|
|
11
|
-
import React from "react";
|
|
12
12
|
|
|
13
|
+
/**
|
|
14
|
+
* "Integrations" entry in the user menu. Links to the integrations landing
|
|
15
|
+
* page (provider list); each provider links on to its connection-management
|
|
16
|
+
* page. Gated on `integration.manage` — mirrors the access check the routes
|
|
17
|
+
* themselves enforce, but hiding the link is the cleaner UX for users who
|
|
18
|
+
* can't manage connections.
|
|
19
|
+
*/
|
|
13
20
|
export const IntegrationMenuItem = ({
|
|
14
21
|
accessRules: userPerms,
|
|
15
22
|
}: UserMenuItemsContext) => {
|
|
16
|
-
const navigate = useNavigate();
|
|
17
23
|
const qualifiedId = `${pluginMetadata.pluginId}.${integrationAccess.manage.id}`;
|
|
18
24
|
const allowed = userPerms.includes("*") || userPerms.includes(qualifiedId);
|
|
19
25
|
|
|
@@ -22,11 +28,10 @@ export const IntegrationMenuItem = ({
|
|
|
22
28
|
}
|
|
23
29
|
|
|
24
30
|
return (
|
|
25
|
-
<
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
</DropdownMenuItem>
|
|
31
|
+
<Link to={resolveRoute(integrationRoutes.routes.list)}>
|
|
32
|
+
<DropdownMenuItem icon={<Webhook className="h-4 w-4" />}>
|
|
33
|
+
Integrations
|
|
34
|
+
</DropdownMenuItem>
|
|
35
|
+
</Link>
|
|
31
36
|
);
|
|
32
37
|
};
|
package/src/index.tsx
CHANGED
|
@@ -8,27 +8,23 @@ import {
|
|
|
8
8
|
pluginMetadata,
|
|
9
9
|
integrationAccess,
|
|
10
10
|
} from "@checkstack/integration-common";
|
|
11
|
-
import {
|
|
12
|
-
import { DeliveryLogsPage } from "./pages/DeliveryLogsPage";
|
|
11
|
+
import { IntegrationsLandingPage } from "./pages/IntegrationsLandingPage";
|
|
13
12
|
import { ProviderConnectionsPage } from "./pages/ProviderConnectionsPage";
|
|
14
13
|
import { IntegrationMenuItem } from "./components/IntegrationMenuItem";
|
|
15
14
|
|
|
15
|
+
/**
|
|
16
|
+
* Integration frontend — now scoped to connection management. The
|
|
17
|
+
* legacy subscription / delivery-log pages were removed when the
|
|
18
|
+
* platform moved to the Automation Platform model; operators manage
|
|
19
|
+
* automations in `/automation/...` instead. The landing page lists
|
|
20
|
+
* providers and links each to its connection-management page.
|
|
21
|
+
*/
|
|
16
22
|
export const integrationPlugin = createFrontendPlugin({
|
|
17
23
|
metadata: pluginMetadata,
|
|
18
24
|
routes: [
|
|
19
25
|
{
|
|
20
26
|
route: integrationRoutes.routes.list,
|
|
21
|
-
element: <
|
|
22
|
-
accessRule: integrationAccess.manage,
|
|
23
|
-
},
|
|
24
|
-
{
|
|
25
|
-
route: integrationRoutes.routes.logs,
|
|
26
|
-
element: <DeliveryLogsPage />,
|
|
27
|
-
accessRule: integrationAccess.manage,
|
|
28
|
-
},
|
|
29
|
-
{
|
|
30
|
-
route: integrationRoutes.routes.deliveryLogs,
|
|
31
|
-
element: <DeliveryLogsPage />,
|
|
27
|
+
element: <IntegrationsLandingPage />,
|
|
32
28
|
accessRule: integrationAccess.manage,
|
|
33
29
|
},
|
|
34
30
|
{
|
|
@@ -48,7 +44,6 @@ export const integrationPlugin = createFrontendPlugin({
|
|
|
48
44
|
|
|
49
45
|
export default integrationPlugin;
|
|
50
46
|
|
|
51
|
-
// Re-export registry and types for providers to register custom config components
|
|
52
47
|
export {
|
|
53
48
|
registerProviderConfigExtension,
|
|
54
49
|
getProviderConfigExtension,
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
import { Link } from "react-router-dom";
|
|
2
|
+
import {
|
|
3
|
+
PageLayout,
|
|
4
|
+
Card,
|
|
5
|
+
CardContent,
|
|
6
|
+
EmptyState,
|
|
7
|
+
LoadingSpinner,
|
|
8
|
+
DynamicIcon,
|
|
9
|
+
Badge,
|
|
10
|
+
type LucideIconName,
|
|
11
|
+
} from "@checkstack/ui";
|
|
12
|
+
import { Webhook, ArrowRight } from "lucide-react";
|
|
13
|
+
import { usePluginClient } from "@checkstack/frontend-api";
|
|
14
|
+
import { resolveRoute } from "@checkstack/common";
|
|
15
|
+
import { IntegrationApi, integrationRoutes } from "@checkstack/integration-common";
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Integrations landing page — lists every registered integration provider
|
|
19
|
+
* and links each to its connection-management page. This is the entry
|
|
20
|
+
* point reached from the "Integrations" user-menu item; the per-provider
|
|
21
|
+
* `ProviderConnectionsPage` lives at `/connections/:providerId`.
|
|
22
|
+
*
|
|
23
|
+
* Only providers that declare a `connectionSchema` (i.e. need site-wide
|
|
24
|
+
* credentials) are actionable here; others are shown disabled so operators
|
|
25
|
+
* understand why there's nothing to configure.
|
|
26
|
+
*/
|
|
27
|
+
export const IntegrationsLandingPage = () => {
|
|
28
|
+
const client = usePluginClient(IntegrationApi);
|
|
29
|
+
const { data: providers = [], isLoading } = client.listProviders.useQuery({});
|
|
30
|
+
|
|
31
|
+
if (isLoading) {
|
|
32
|
+
return (
|
|
33
|
+
<PageLayout title="Integrations" icon={Webhook}>
|
|
34
|
+
<div className="flex items-center justify-center py-12">
|
|
35
|
+
<LoadingSpinner />
|
|
36
|
+
</div>
|
|
37
|
+
</PageLayout>
|
|
38
|
+
);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
if (providers.length === 0) {
|
|
42
|
+
return (
|
|
43
|
+
<PageLayout title="Integrations" icon={Webhook}>
|
|
44
|
+
<EmptyState
|
|
45
|
+
icon={<Webhook className="h-12 w-12" />}
|
|
46
|
+
title="No integration providers"
|
|
47
|
+
description="Install an integration plugin (e.g. Jira, Teams, Webex) to manage its connections here."
|
|
48
|
+
/>
|
|
49
|
+
</PageLayout>
|
|
50
|
+
);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
return (
|
|
54
|
+
<PageLayout
|
|
55
|
+
title="Integrations"
|
|
56
|
+
subtitle="Manage site-wide connections for your integration providers"
|
|
57
|
+
icon={Webhook}
|
|
58
|
+
>
|
|
59
|
+
<div className="grid gap-3 sm:grid-cols-2 lg:grid-cols-3">
|
|
60
|
+
{providers.map((provider) => {
|
|
61
|
+
const card = (
|
|
62
|
+
<Card
|
|
63
|
+
className={
|
|
64
|
+
provider.hasConnectionSchema
|
|
65
|
+
? "transition-colors hover:border-primary/50"
|
|
66
|
+
: "opacity-60"
|
|
67
|
+
}
|
|
68
|
+
>
|
|
69
|
+
<CardContent className="flex items-start gap-3 p-4">
|
|
70
|
+
<DynamicIcon
|
|
71
|
+
name={(provider.icon as LucideIconName) ?? "Webhook"}
|
|
72
|
+
className="mt-0.5 h-5 w-5 shrink-0 text-muted-foreground"
|
|
73
|
+
/>
|
|
74
|
+
<div className="min-w-0 flex-1">
|
|
75
|
+
<div className="flex items-center gap-2">
|
|
76
|
+
<span className="truncate text-sm font-semibold">
|
|
77
|
+
{provider.displayName}
|
|
78
|
+
</span>
|
|
79
|
+
{!provider.hasConnectionSchema && (
|
|
80
|
+
<Badge variant="outline" className="shrink-0 text-[10px]">
|
|
81
|
+
No connections
|
|
82
|
+
</Badge>
|
|
83
|
+
)}
|
|
84
|
+
</div>
|
|
85
|
+
{provider.description && (
|
|
86
|
+
<p className="mt-0.5 truncate text-xs text-muted-foreground">
|
|
87
|
+
{provider.description}
|
|
88
|
+
</p>
|
|
89
|
+
)}
|
|
90
|
+
</div>
|
|
91
|
+
{provider.hasConnectionSchema && (
|
|
92
|
+
<ArrowRight className="mt-0.5 h-4 w-4 shrink-0 text-muted-foreground" />
|
|
93
|
+
)}
|
|
94
|
+
</CardContent>
|
|
95
|
+
</Card>
|
|
96
|
+
);
|
|
97
|
+
|
|
98
|
+
if (!provider.hasConnectionSchema) {
|
|
99
|
+
return <div key={provider.qualifiedId}>{card}</div>;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
return (
|
|
103
|
+
<Link
|
|
104
|
+
key={provider.qualifiedId}
|
|
105
|
+
to={resolveRoute(integrationRoutes.routes.connections, {
|
|
106
|
+
providerId: provider.qualifiedId,
|
|
107
|
+
})}
|
|
108
|
+
>
|
|
109
|
+
{card}
|
|
110
|
+
</Link>
|
|
111
|
+
);
|
|
112
|
+
})}
|
|
113
|
+
</div>
|
|
114
|
+
</PageLayout>
|
|
115
|
+
);
|
|
116
|
+
};
|