@sentry/junior-dashboard 0.266.0 → 0.268.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/app.js +85 -12
- package/dist/client.js +94 -64
- package/dist/index.js +85 -12
- package/dist/tailwind.css +1 -1
- package/package.json +11 -5
- package/src/app.ts +0 -2
- package/src/auth.ts +4 -7
- package/src/client/App.tsx +55 -53
- package/src/client/components/DetailsPanel.tsx +12 -13
- package/src/client/components/Drawer.tsx +46 -23
- package/src/client/components/ImageAttachment.tsx +1 -1
- package/src/client/components/ParticipantAvatarStack.tsx +6 -2
- package/src/client/components/README.md +15 -2
- package/src/client/components/UserInputForm.tsx +283 -0
- package/src/client/components/layout/DashboardHeader.tsx +13 -0
- package/src/client/components/ui/alert.tsx +1 -1
- package/src/client/components/ui/button-group.tsx +59 -0
- package/src/client/components/ui/button.tsx +11 -1
- package/src/client/components/ui/dialog.tsx +29 -35
- package/src/client/components/ui/drawer.tsx +140 -0
- package/src/client/components/ui/empty.tsx +30 -1
- package/src/client/components/ui/separator.tsx +22 -0
- package/src/client/components/ui/useSheet.ts +5 -1
- package/src/client/conversations/ComposerImages.tsx +66 -14
- package/src/client/conversations/ConversationComposer.tsx +84 -12
- package/src/client/conversations/ConversationDetails.tsx +3 -27
- package/src/client/conversations/ConversationEventDetails.tsx +26 -10
- package/src/client/conversations/ConversationHomeList.tsx +6 -0
- package/src/client/conversations/ConversationListStatusIcon.tsx +15 -1
- package/src/client/conversations/ConversationPage.tsx +160 -2
- package/src/client/conversations/ConversationSidebar.tsx +6 -0
- package/src/client/conversations/ConversationTranscript.tsx +48 -16
- package/src/client/conversations/ConversationWorkspace.tsx +4 -0
- package/src/client/conversations/DetailsList.tsx +33 -0
- package/src/client/conversations/EventDetails.tsx +46 -19
- package/src/client/conversations/ForkConversationButton.tsx +79 -73
- package/src/client/conversations/PendingMailboxStack.tsx +310 -112
- package/src/client/conversations/README.md +30 -13
- package/src/client/conversations/SubagentTranscriptDrawer.tsx +19 -22
- package/src/client/conversations/TranscriptActivityGroup.tsx +27 -19
- package/src/client/conversations/TranscriptAttachment.tsx +39 -4
- package/src/client/conversations/TranscriptAutomationTriggerView.tsx +14 -19
- package/src/client/conversations/TranscriptFailureView.tsx +10 -13
- package/src/client/conversations/TranscriptMarkdown.tsx +232 -436
- package/src/client/conversations/TranscriptMessageContextView.tsx +12 -1
- package/src/client/conversations/TranscriptMessageView.tsx +10 -1
- package/src/client/conversations/TranscriptSummary.tsx +5 -31
- package/src/client/conversations/TranscriptToolView.tsx +13 -1
- package/src/client/conversations/TranscriptTurnContextView.tsx +174 -161
- package/src/client/conversations/TranscriptView.tsx +7 -3
- package/src/client/conversations/UserInputRequestCard.tsx +39 -0
- package/src/client/conversations/conversationOutbox.ts +46 -0
- package/src/client/conversations/eventTime.ts +13 -1
- package/src/client/conversations/eventTranscript.ts +12 -5
- package/src/client/conversations/queries.ts +127 -26
- package/src/client/conversations/transcriptMarkdownLinks.ts +5 -367
- package/src/client/conversations/turnContext.ts +15 -0
- package/src/client/conversations/userInputRequest.ts +56 -0
- package/src/client/format.ts +31 -8
- package/src/client/pages/SettingsPage.tsx +103 -3
- package/src/client/pages/automations/{AutomationLifecycle.tsx → AutomationActions.tsx} +60 -69
- package/src/client/pages/automations/AutomationDraftChanges.tsx +171 -0
- package/src/client/pages/automations/AutomationEditor.tsx +182 -156
- package/src/client/pages/automations/AutomationEventFields.tsx +119 -45
- package/src/client/pages/automations/AutomationExecutionStatusChart.tsx +1 -1
- package/src/client/pages/automations/AutomationFormSection.tsx +20 -2
- package/src/client/pages/automations/AutomationOutcomeFields.tsx +1 -1
- package/src/client/pages/automations/AutomationOverview.tsx +238 -0
- package/src/client/pages/automations/AutomationPage.tsx +343 -0
- package/src/client/pages/automations/AutomationRecentRuns.tsx +3 -2
- package/src/client/pages/automations/AutomationRow.tsx +11 -13
- package/src/client/pages/automations/AutomationRunDetails.tsx +4 -2
- package/src/client/pages/automations/{AutomationExecutionsPage.tsx → AutomationRunsTab.tsx} +94 -103
- package/src/client/pages/automations/AutomationStatus.tsx +164 -108
- package/src/client/pages/automations/AutomationVersionsTab.tsx +518 -0
- package/src/client/pages/automations/AutomationsPage.tsx +10 -98
- package/src/client/pages/automations/AutomationsPageLayout.tsx +5 -23
- package/src/client/pages/automations/README.md +56 -46
- package/src/client/pages/code/RepositorySections.tsx +1 -0
- package/src/client/pages/code/RepositoryTabs.tsx +3 -0
- package/src/client/primaryNav.ts +15 -2
- package/src/client/review-desk/ConversationReviewBar.tsx +62 -0
- package/src/client/review-desk/ReviewDeskPage.tsx +277 -0
- package/src/client/review-desk/ReviewItemActions.tsx +165 -0
- package/src/client/review-desk/ReviewItemCard.tsx +47 -0
- package/src/client/review-desk/ReviewItemDetail.tsx +115 -0
- package/src/client/review-desk/queries.ts +164 -0
- package/src/client/review-desk/reviewItemFormat.ts +61 -0
- package/src/client/types.ts +3 -0
- package/src/mock-reporting/fixtures.ts +54 -2
- package/src/mock-reporting/routes.ts +20 -0
- package/src/shell.ts +3 -0
- package/src/client/conversations/transcriptStyles.ts +0 -10
- package/src/client/pages/automations/AutomationDetails.tsx +0 -193
- package/src/client/pages/automations/AutomationEditPage.tsx +0 -176
- package/src/client/pages/automations/AutomationVersionsPage.tsx +0 -390
|
@@ -28,6 +28,9 @@ import {
|
|
|
28
28
|
personalSpendReportSchema,
|
|
29
29
|
personParamsSchema,
|
|
30
30
|
pluginOperationalReportFeedSchema,
|
|
31
|
+
reviewItemCountSchema,
|
|
32
|
+
reviewItemListSchema,
|
|
33
|
+
reviewItemWaitingConversationsSchema,
|
|
31
34
|
automationExecutionListSchema,
|
|
32
35
|
automationListSchema,
|
|
33
36
|
automationParamsSchema,
|
|
@@ -294,6 +297,23 @@ export function createMockReportingApi(): Hono<{
|
|
|
294
297
|
}
|
|
295
298
|
return errorResponse("Attachment not found.", 404);
|
|
296
299
|
});
|
|
300
|
+
// Mock reporting has no Review items. Answer the reads here so the
|
|
301
|
+
// dashboard does not query a database that has no review item tables.
|
|
302
|
+
app.get("/review-items", () =>
|
|
303
|
+
jsonResponse(reviewItemListSchema, { items: [] }),
|
|
304
|
+
);
|
|
305
|
+
app.get("/review-items/count", () =>
|
|
306
|
+
jsonResponse(reviewItemCountSchema, { mine: 0 }),
|
|
307
|
+
);
|
|
308
|
+
app.get("/review-items/waiting-conversations", () =>
|
|
309
|
+
jsonResponse(reviewItemWaitingConversationsSchema, { conversationIds: [] }),
|
|
310
|
+
);
|
|
311
|
+
app.get("/review-items/:id", () =>
|
|
312
|
+
errorResponse("Review item not found.", 404),
|
|
313
|
+
);
|
|
314
|
+
app.post("/review-items/:id/actions", () =>
|
|
315
|
+
errorResponse("Review item not found.", 404),
|
|
316
|
+
);
|
|
297
317
|
app.get("/automations", (c) => {
|
|
298
318
|
const report = readMockAutomationList();
|
|
299
319
|
return jsonResponse(
|
package/src/shell.ts
CHANGED
|
@@ -131,6 +131,9 @@ export function dashboardPagePaths(
|
|
|
131
131
|
nested: true,
|
|
132
132
|
path: basePath === "/" ? "/conversations" : `${basePath}/conversations`,
|
|
133
133
|
},
|
|
134
|
+
{
|
|
135
|
+
path: basePath === "/" ? "/review" : `${basePath}/review`,
|
|
136
|
+
},
|
|
134
137
|
{
|
|
135
138
|
nested: true,
|
|
136
139
|
path: basePath === "/" ? "/people" : `${basePath}/people`,
|
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
/** Share the transcript empty/unavailable frame across top-level and segment views. */
|
|
2
|
-
export function transcriptEmptyClass(
|
|
3
|
-
tone: "default" | "error" = "default",
|
|
4
|
-
): string {
|
|
5
|
-
const colors =
|
|
6
|
-
tone === "error"
|
|
7
|
-
? "border-rose-300/25 bg-rose-300/[0.07] text-rose-100"
|
|
8
|
-
: "border-dashboard-border bg-dashboard-fill-soft text-dashboard-text-muted";
|
|
9
|
-
return `rounded-lg border p-5 text-sm leading-relaxed ${colors}`;
|
|
10
|
-
}
|
|
@@ -1,193 +0,0 @@
|
|
|
1
|
-
import type { AutomationSummary } from "@sentry/junior/api/schema";
|
|
2
|
-
import type { ReactNode } from "react";
|
|
3
|
-
import { Link, useLocation } from "react-router";
|
|
4
|
-
|
|
5
|
-
import {
|
|
6
|
-
Accordion,
|
|
7
|
-
AccordionContent,
|
|
8
|
-
AccordionItem,
|
|
9
|
-
AccordionTrigger,
|
|
10
|
-
} from "../../components/ui/accordion";
|
|
11
|
-
import { Button } from "../../components/ui/button";
|
|
12
|
-
import { DetailsPanel } from "../../components/DetailsPanel";
|
|
13
|
-
import { InlineError } from "../../components/InlineError";
|
|
14
|
-
import { PageContentSkeleton } from "../../components/PageContentSkeleton";
|
|
15
|
-
import {
|
|
16
|
-
timeRangeLabel,
|
|
17
|
-
type TimeRangeDays,
|
|
18
|
-
} from "../../components/controls/TimeRangeSelector";
|
|
19
|
-
import { TranscriptText } from "../../conversations/TranscriptText";
|
|
20
|
-
import { peoplePath } from "../../format";
|
|
21
|
-
import { dashboardInlineLinkClass } from "../../styles";
|
|
22
|
-
import { TriggerFilters } from "./TriggerFilters";
|
|
23
|
-
import { AutomationLifecycle } from "./AutomationLifecycle";
|
|
24
|
-
import { AutomationRecentRuns } from "./AutomationRecentRuns";
|
|
25
|
-
import { AutomationStatus } from "./AutomationStatus";
|
|
26
|
-
import {
|
|
27
|
-
automationScheduleLabel,
|
|
28
|
-
formatAutomationRunTime,
|
|
29
|
-
} from "./automationFormat";
|
|
30
|
-
import { automationOutcomeLabel } from "./automationOutcomes";
|
|
31
|
-
|
|
32
|
-
/** Keep Automation context scrollable above persistent, permission-aware actions. */
|
|
33
|
-
export function AutomationDetails(props: {
|
|
34
|
-
onClose(): void;
|
|
35
|
-
onDelete(source: HTMLButtonElement): void;
|
|
36
|
-
onRetry(): void;
|
|
37
|
-
error: boolean;
|
|
38
|
-
range: TimeRangeDays;
|
|
39
|
-
automation: AutomationSummary | undefined;
|
|
40
|
-
}) {
|
|
41
|
-
const location = useLocation();
|
|
42
|
-
const { automation } = props;
|
|
43
|
-
return (
|
|
44
|
-
<DetailsPanel
|
|
45
|
-
label="Automation details"
|
|
46
|
-
sheetTitle={automation?.title}
|
|
47
|
-
onClose={props.onClose}
|
|
48
|
-
title={
|
|
49
|
-
<h2 className="m-0 break-words font-display text-base font-medium text-dashboard-text">
|
|
50
|
-
{automation?.title ?? "Automation details"}
|
|
51
|
-
</h2>
|
|
52
|
-
}
|
|
53
|
-
>
|
|
54
|
-
<div className="grid h-full min-h-0 grid-rows-[minmax(0,1fr)_auto]">
|
|
55
|
-
<div
|
|
56
|
-
aria-label="Automation content"
|
|
57
|
-
role="region"
|
|
58
|
-
tabIndex={0}
|
|
59
|
-
className="min-h-0 overflow-y-auto overscroll-contain p-4 outline-none focus-visible:outline-2 focus-visible:-outline-offset-2 focus-visible:outline-dashboard-focus [overflow-wrap:anywhere]"
|
|
60
|
-
>
|
|
61
|
-
{automation ? (
|
|
62
|
-
<AutomationDetailsContent
|
|
63
|
-
automation={automation}
|
|
64
|
-
range={props.range}
|
|
65
|
-
/>
|
|
66
|
-
) : null}
|
|
67
|
-
{props.error ? (
|
|
68
|
-
<InlineError>
|
|
69
|
-
Automation details could not be loaded. It may be unavailable or
|
|
70
|
-
you may not have access.{" "}
|
|
71
|
-
<Button onClick={props.onRetry}>Try again</Button>
|
|
72
|
-
</InlineError>
|
|
73
|
-
) : !automation ? (
|
|
74
|
-
<PageContentSkeleton
|
|
75
|
-
label="Loading automation details"
|
|
76
|
-
variant="panel"
|
|
77
|
-
/>
|
|
78
|
-
) : null}
|
|
79
|
-
</div>
|
|
80
|
-
{automation ? (
|
|
81
|
-
<AutomationLifecycle
|
|
82
|
-
automation={automation}
|
|
83
|
-
onDelete={props.onDelete}
|
|
84
|
-
editPath={`/automations/${encodeURIComponent(automation.id)}/edit${location.search}`}
|
|
85
|
-
/>
|
|
86
|
-
) : null}
|
|
87
|
-
</div>
|
|
88
|
-
</DetailsPanel>
|
|
89
|
-
);
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
function AutomationDetailsContent({
|
|
93
|
-
automation,
|
|
94
|
-
range,
|
|
95
|
-
}: {
|
|
96
|
-
automation: AutomationSummary;
|
|
97
|
-
range: TimeRangeDays;
|
|
98
|
-
}) {
|
|
99
|
-
const location = useLocation();
|
|
100
|
-
return (
|
|
101
|
-
<div className="grid min-w-0 gap-5">
|
|
102
|
-
<AutomationStatus automation={automation} />
|
|
103
|
-
<section aria-label="Instructions" className="text-sm leading-relaxed">
|
|
104
|
-
<TranscriptText
|
|
105
|
-
mentions={automation.mentions ?? []}
|
|
106
|
-
text={automation.instruction}
|
|
107
|
-
/>
|
|
108
|
-
</section>
|
|
109
|
-
<dl className="m-0 grid gap-3 text-xs leading-relaxed">
|
|
110
|
-
<AutomationFact label="Trigger">
|
|
111
|
-
{automation.kind === "scheduled" ? (
|
|
112
|
-
<p className="m-0">{automationScheduleLabel(automation)}</p>
|
|
113
|
-
) : (
|
|
114
|
-
<>
|
|
115
|
-
<p className="m-0 break-words">{automation.resource}</p>
|
|
116
|
-
<p className="m-0 mt-1 text-dashboard-text-muted">
|
|
117
|
-
{automation.trigger.events.join(", ")}
|
|
118
|
-
</p>
|
|
119
|
-
<TriggerFilters filters={automation.trigger.filters} />
|
|
120
|
-
</>
|
|
121
|
-
)}
|
|
122
|
-
</AutomationFact>
|
|
123
|
-
<AutomationFact label="On success">
|
|
124
|
-
{automation.outcomes.length === 0 ? (
|
|
125
|
-
<span className="text-dashboard-text-muted">No message</span>
|
|
126
|
-
) : (
|
|
127
|
-
<ol className="m-0 grid list-none gap-2 p-0">
|
|
128
|
-
{automation.outcomes.map((outcome, index) => (
|
|
129
|
-
<li key={index}>
|
|
130
|
-
Message{" "}
|
|
131
|
-
{automationOutcomeLabel(outcome, automation.destination)}
|
|
132
|
-
</li>
|
|
133
|
-
))}
|
|
134
|
-
</ol>
|
|
135
|
-
)}
|
|
136
|
-
</AutomationFact>
|
|
137
|
-
</dl>
|
|
138
|
-
<AutomationRecentRuns automation={automation} />
|
|
139
|
-
<Accordion className="border-t border-dashboard-border pt-1">
|
|
140
|
-
<AccordionItem value="about">
|
|
141
|
-
<AccordionTrigger className="min-h-11 text-xs text-dashboard-text-muted">
|
|
142
|
-
About this Automation
|
|
143
|
-
</AccordionTrigger>
|
|
144
|
-
<AccordionContent>
|
|
145
|
-
<dl className="m-0 grid gap-3 text-xs leading-relaxed">
|
|
146
|
-
<AutomationFact label="Created by">
|
|
147
|
-
{automation.createdByEmail ? (
|
|
148
|
-
<Link
|
|
149
|
-
className={dashboardInlineLinkClass}
|
|
150
|
-
to={peoplePath(automation.createdByEmail)}
|
|
151
|
-
>
|
|
152
|
-
{automation.ownedByViewer ? "you" : automation.createdBy}
|
|
153
|
-
</Link>
|
|
154
|
-
) : automation.ownedByViewer ? (
|
|
155
|
-
"you"
|
|
156
|
-
) : (
|
|
157
|
-
automation.createdBy
|
|
158
|
-
)}
|
|
159
|
-
</AutomationFact>
|
|
160
|
-
<AutomationFact label="Created">
|
|
161
|
-
{formatAutomationRunTime(automation.createdAt)}
|
|
162
|
-
</AutomationFact>
|
|
163
|
-
<AutomationFact label="Accounts">
|
|
164
|
-
{automation.credentialMode === "creator"
|
|
165
|
-
? `Uses accounts connected by ${automation.ownedByViewer ? "you" : automation.createdBy}.`
|
|
166
|
-
: "Junior’s accounts only"}
|
|
167
|
-
</AutomationFact>
|
|
168
|
-
<AutomationFact label="Runs">
|
|
169
|
-
{automation.runs[range]} runs / {timeRangeLabel(range)} ·{" "}
|
|
170
|
-
{automation.totalRuns} total
|
|
171
|
-
</AutomationFact>
|
|
172
|
-
</dl>
|
|
173
|
-
<Link
|
|
174
|
-
className={`${dashboardInlineLinkClass} mt-3 inline-block py-2 text-xs`}
|
|
175
|
-
to={`/automations/${encodeURIComponent(automation.id)}/versions${location.search}`}
|
|
176
|
-
>
|
|
177
|
-
Version history
|
|
178
|
-
</Link>
|
|
179
|
-
</AccordionContent>
|
|
180
|
-
</AccordionItem>
|
|
181
|
-
</Accordion>
|
|
182
|
-
</div>
|
|
183
|
-
);
|
|
184
|
-
}
|
|
185
|
-
|
|
186
|
-
function AutomationFact(props: { label: string; children: ReactNode }) {
|
|
187
|
-
return (
|
|
188
|
-
<div className="grid min-w-0 grid-cols-[5.25rem_minmax(0,1fr)] gap-3">
|
|
189
|
-
<dt className="text-dashboard-text-muted">{props.label}</dt>
|
|
190
|
-
<dd className="m-0 min-w-0">{props.children}</dd>
|
|
191
|
-
</div>
|
|
192
|
-
);
|
|
193
|
-
}
|
|
@@ -1,176 +0,0 @@
|
|
|
1
|
-
import { Link, useLocation, useParams } from "react-router";
|
|
2
|
-
import { useQuery } from "@tanstack/react-query";
|
|
3
|
-
import { ArrowLeft } from "lucide-react";
|
|
4
|
-
import {
|
|
5
|
-
automationEditSchema,
|
|
6
|
-
type AutomationSummary,
|
|
7
|
-
} from "@sentry/junior/api/schema";
|
|
8
|
-
import { useAutomationData } from "../../api";
|
|
9
|
-
import { useDocumentTitle } from "../../documentTitle";
|
|
10
|
-
import { fetchDashboardJson } from "../../http";
|
|
11
|
-
import { Button } from "../../components/ui/button";
|
|
12
|
-
import { FormNotice } from "../../components/FormNotice";
|
|
13
|
-
import { StatusChip } from "../../components/StatusChip";
|
|
14
|
-
import { AutomationsNavigation } from "./AutomationsPageLayout";
|
|
15
|
-
import { TriggerFilters } from "./TriggerFilters";
|
|
16
|
-
import { AutomationEditor } from "./AutomationEditor";
|
|
17
|
-
import { AutomationEditorLoading } from "./AutomationEditorLoading";
|
|
18
|
-
import { AutomationFormSection } from "./AutomationFormSection";
|
|
19
|
-
import { AutomationOutcomeList } from "./AutomationOutcomeFields";
|
|
20
|
-
|
|
21
|
-
/** Load a linkable editor. Owners and public readers can edit until work completes. */
|
|
22
|
-
export function AutomationEditPage(props: { enabled: boolean }) {
|
|
23
|
-
const { automationId } = useParams();
|
|
24
|
-
const location = useLocation();
|
|
25
|
-
const summary = useAutomationData(props.enabled, automationId);
|
|
26
|
-
const canEdit =
|
|
27
|
-
summary.data &&
|
|
28
|
-
!(summary.data.kind === "scheduled" && summary.data.status === "completed");
|
|
29
|
-
const edit = useQuery({
|
|
30
|
-
queryKey: ["dashboard", "automations", "edit", automationId],
|
|
31
|
-
enabled: props.enabled && Boolean(canEdit),
|
|
32
|
-
retry: false,
|
|
33
|
-
queryFn: ({ signal }) =>
|
|
34
|
-
fetchDashboardJson(
|
|
35
|
-
automationEditSchema,
|
|
36
|
-
`/api/automations/${encodeURIComponent(automationId!)}/edit`,
|
|
37
|
-
signal,
|
|
38
|
-
),
|
|
39
|
-
});
|
|
40
|
-
const returnPath = `/automations/list${location.search}`;
|
|
41
|
-
const value = summary.data;
|
|
42
|
-
useDocumentTitle(
|
|
43
|
-
value
|
|
44
|
-
? canEdit
|
|
45
|
-
? `${value.title} · Edit`
|
|
46
|
-
: value.title
|
|
47
|
-
: "Edit automation",
|
|
48
|
-
);
|
|
49
|
-
const status =
|
|
50
|
-
value?.kind === "event"
|
|
51
|
-
? value.status !== "active"
|
|
52
|
-
? value.status
|
|
53
|
-
: value.trigger.problems.length === 0
|
|
54
|
-
? "active"
|
|
55
|
-
: "unavailable"
|
|
56
|
-
: value?.status;
|
|
57
|
-
const statusTone =
|
|
58
|
-
status === "active"
|
|
59
|
-
? "success"
|
|
60
|
-
: status === "blocked" || status === "unavailable"
|
|
61
|
-
? "warning"
|
|
62
|
-
: "neutral";
|
|
63
|
-
return (
|
|
64
|
-
<AutomationsNavigation>
|
|
65
|
-
<div className="mx-auto w-full min-w-0 max-w-5xl px-4 pt-7 sm:px-8 sm:pt-9">
|
|
66
|
-
<Link
|
|
67
|
-
to={returnPath}
|
|
68
|
-
className="inline-flex min-h-8 items-center gap-2 text-sm text-dashboard-text-muted no-underline hover:text-dashboard-text"
|
|
69
|
-
>
|
|
70
|
-
<ArrowLeft aria-hidden size={15} />
|
|
71
|
-
All automations
|
|
72
|
-
</Link>
|
|
73
|
-
<div className="mt-4 mb-8 flex flex-wrap items-start justify-between gap-4">
|
|
74
|
-
<div className="min-w-0">
|
|
75
|
-
<h1 className="m-0 break-words font-display text-3xl font-light tracking-tight">
|
|
76
|
-
{value && !canEdit ? value.title : "Edit automation"}
|
|
77
|
-
</h1>
|
|
78
|
-
{value ? (
|
|
79
|
-
<p className="mt-2 mb-0 text-sm text-dashboard-text-muted">
|
|
80
|
-
Created by {value.ownedByViewer ? "you" : value.createdBy} ·{" "}
|
|
81
|
-
{value.destination.label}
|
|
82
|
-
</p>
|
|
83
|
-
) : null}
|
|
84
|
-
</div>
|
|
85
|
-
{value ? (
|
|
86
|
-
<div className="flex items-center gap-4">
|
|
87
|
-
<Link
|
|
88
|
-
to={`/automations/${encodeURIComponent(value.id)}/versions${location.search}`}
|
|
89
|
-
className="text-sm text-dashboard-text-muted underline underline-offset-2 hover:text-dashboard-text"
|
|
90
|
-
>
|
|
91
|
-
Version history
|
|
92
|
-
</Link>
|
|
93
|
-
<StatusChip tone={statusTone}>
|
|
94
|
-
{status === "unavailable" ? "Trigger unavailable" : status}
|
|
95
|
-
</StatusChip>
|
|
96
|
-
</div>
|
|
97
|
-
) : null}
|
|
98
|
-
</div>
|
|
99
|
-
{(!value && summary.error) || (!edit.data && edit.error) ? (
|
|
100
|
-
<FormNotice tone="error" title="Automation could not be loaded.">
|
|
101
|
-
It may no longer be available, or you may not have access.{" "}
|
|
102
|
-
<Button
|
|
103
|
-
onClick={() => {
|
|
104
|
-
void summary.refetch();
|
|
105
|
-
if (canEdit) void edit.refetch();
|
|
106
|
-
}}
|
|
107
|
-
>
|
|
108
|
-
Try again
|
|
109
|
-
</Button>
|
|
110
|
-
</FormNotice>
|
|
111
|
-
) : !value || (canEdit && !edit.data) ? (
|
|
112
|
-
<AutomationEditorLoading />
|
|
113
|
-
) : canEdit && edit.data ? (
|
|
114
|
-
<AutomationEditor
|
|
115
|
-
key={automationId}
|
|
116
|
-
automation={edit.data}
|
|
117
|
-
summary={value}
|
|
118
|
-
returnPath={returnPath}
|
|
119
|
-
/>
|
|
120
|
-
) : (
|
|
121
|
-
<AutomationReadOnly automation={value} />
|
|
122
|
-
)}
|
|
123
|
-
</div>
|
|
124
|
-
</AutomationsNavigation>
|
|
125
|
-
);
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
function AutomationReadOnly({ automation }: { automation: AutomationSummary }) {
|
|
129
|
-
return (
|
|
130
|
-
<>
|
|
131
|
-
<p className="mb-6 text-sm text-dashboard-text-muted">
|
|
132
|
-
This automation has completed and cannot be edited. It will not run
|
|
133
|
-
again.
|
|
134
|
-
</p>
|
|
135
|
-
<AutomationFormSection title="What to do" detail="The saved instruction.">
|
|
136
|
-
<p className="m-0 whitespace-pre-wrap break-words text-sm leading-relaxed">
|
|
137
|
-
{automation.instruction}
|
|
138
|
-
</p>
|
|
139
|
-
</AutomationFormSection>
|
|
140
|
-
<AutomationFormSection title="When to run" detail="The saved trigger.">
|
|
141
|
-
{automation.kind === "scheduled" ? (
|
|
142
|
-
<p className="m-0 text-sm">
|
|
143
|
-
{automation.schedule} · {automation.timezone}
|
|
144
|
-
</p>
|
|
145
|
-
) : (
|
|
146
|
-
<div className="grid gap-3 text-sm">
|
|
147
|
-
<p className="m-0 break-words">{automation.resource}</p>
|
|
148
|
-
<p className="m-0 break-words">
|
|
149
|
-
{automation.trigger.events.join(", ")}
|
|
150
|
-
</p>
|
|
151
|
-
<TriggerFilters filters={automation.trigger.filters} />
|
|
152
|
-
</div>
|
|
153
|
-
)}
|
|
154
|
-
</AutomationFormSection>
|
|
155
|
-
<AutomationFormSection
|
|
156
|
-
title="Where results go"
|
|
157
|
-
detail="Messages after successful work."
|
|
158
|
-
>
|
|
159
|
-
<AutomationOutcomeList
|
|
160
|
-
outcomes={automation.outcomes}
|
|
161
|
-
destination={automation.destination}
|
|
162
|
-
/>
|
|
163
|
-
</AutomationFormSection>
|
|
164
|
-
<AutomationFormSection
|
|
165
|
-
title="Credentials"
|
|
166
|
-
detail="The accounts Junior can use."
|
|
167
|
-
>
|
|
168
|
-
<p className="m-0 text-sm">
|
|
169
|
-
{automation.credentialMode === "creator"
|
|
170
|
-
? `Uses ${automation.ownedByViewer ? "your" : `${automation.createdBy}’s`} connected accounts.`
|
|
171
|
-
: "System credentials only."}
|
|
172
|
-
</p>
|
|
173
|
-
</AutomationFormSection>
|
|
174
|
-
</>
|
|
175
|
-
);
|
|
176
|
-
}
|