@activecollab/components 2.0.345 → 2.0.347

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.
Files changed (47) hide show
  1. package/dist/cjs/components/Icons/collection/Git.js +47 -0
  2. package/dist/cjs/components/Icons/collection/Git.js.map +1 -0
  3. package/dist/cjs/components/Icons/collection/GitHub.js +47 -0
  4. package/dist/cjs/components/Icons/collection/GitHub.js.map +1 -0
  5. package/dist/cjs/components/Icons/collection/GitLab.js +47 -0
  6. package/dist/cjs/components/Icons/collection/GitLab.js.map +1 -0
  7. package/dist/cjs/components/Icons/collection/index.js +21 -0
  8. package/dist/cjs/components/Icons/collection/index.js.map +1 -1
  9. package/dist/cjs/presentation/shared/WebhookLogsDialog.js +585 -0
  10. package/dist/cjs/presentation/shared/WebhookLogsDialog.js.map +1 -0
  11. package/dist/cjs/presentation/shared/headers.js +93 -24
  12. package/dist/cjs/presentation/shared/headers.js.map +1 -1
  13. package/dist/cjs/presentation/shared/index.js +15 -0
  14. package/dist/cjs/presentation/shared/index.js.map +1 -1
  15. package/dist/esm/components/Icons/collection/Git.d.ts +17 -0
  16. package/dist/esm/components/Icons/collection/Git.d.ts.map +1 -0
  17. package/dist/esm/components/Icons/collection/Git.js +40 -0
  18. package/dist/esm/components/Icons/collection/Git.js.map +1 -0
  19. package/dist/esm/components/Icons/collection/GitHub.d.ts +17 -0
  20. package/dist/esm/components/Icons/collection/GitHub.d.ts.map +1 -0
  21. package/dist/esm/components/Icons/collection/GitHub.js +40 -0
  22. package/dist/esm/components/Icons/collection/GitHub.js.map +1 -0
  23. package/dist/esm/components/Icons/collection/GitLab.d.ts +17 -0
  24. package/dist/esm/components/Icons/collection/GitLab.d.ts.map +1 -0
  25. package/dist/esm/components/Icons/collection/GitLab.js +40 -0
  26. package/dist/esm/components/Icons/collection/GitLab.js.map +1 -0
  27. package/dist/esm/components/Icons/collection/index.d.ts +3 -0
  28. package/dist/esm/components/Icons/collection/index.d.ts.map +1 -1
  29. package/dist/esm/components/Icons/collection/index.js +3 -0
  30. package/dist/esm/components/Icons/collection/index.js.map +1 -1
  31. package/dist/esm/presentation/shared/WebhookLogsDialog.d.ts +62 -0
  32. package/dist/esm/presentation/shared/WebhookLogsDialog.d.ts.map +1 -0
  33. package/dist/esm/presentation/shared/WebhookLogsDialog.js +537 -0
  34. package/dist/esm/presentation/shared/WebhookLogsDialog.js.map +1 -0
  35. package/dist/esm/presentation/shared/headers.d.ts +6 -1
  36. package/dist/esm/presentation/shared/headers.d.ts.map +1 -1
  37. package/dist/esm/presentation/shared/headers.js +94 -31
  38. package/dist/esm/presentation/shared/headers.js.map +1 -1
  39. package/dist/esm/presentation/shared/index.d.ts +2 -0
  40. package/dist/esm/presentation/shared/index.d.ts.map +1 -1
  41. package/dist/esm/presentation/shared/index.js +1 -0
  42. package/dist/esm/presentation/shared/index.js.map +1 -1
  43. package/dist/index.js +331 -220
  44. package/dist/index.js.map +1 -1
  45. package/dist/index.min.js +1 -1
  46. package/dist/index.min.js.map +1 -1
  47. package/package.json +1 -1
@@ -0,0 +1,537 @@
1
+ import React, { useMemo, useState } from "react";
2
+ import styled from "styled-components";
3
+ import { Button } from "../../components/Button";
4
+ import { Chip } from "../../components/Chip";
5
+ import { Dialog } from "../../components/Dialog";
6
+ import { Filter } from "../../components/Filter";
7
+ import { IconButton } from "../../components/IconButton";
8
+ import { CancelCrossIcon, CollapseExpandSingleIcon, GitHubIcon, GitIcon, GitLabIcon } from "../../components/Icons";
9
+ import { Body2, Caption1, Caption2, Header3 } from "../../components/Typography";
10
+
11
+ /**
12
+ * "Webhook Logs" — the VCS webhook delivery log, shown as a wide dialog with a
13
+ * filterable, expandable list. Extracted into `shared/` so it can be opened
14
+ * from more than one surface (the Apps & Integrations Repositories page and the
15
+ * project "..." menu on the Project Repos story).
16
+ *
17
+ * Mirrors the app's webhook log model:
18
+ * `vcs_webhook_logs` → connection_id, event_type, processing_status
19
+ * (received / unhandled / skipped / processed /
20
+ * failed / duplicate), delivery_identifier, payload,
21
+ * created_on
22
+ * `vcs_webhook_outcomes` → one row per outcome, each with a localized summary
23
+ *
24
+ * The status is derived from the outcomes server-side; here we render the
25
+ * stored value and map it to a palette colour. The connection glyph is the
26
+ * provider icon (GitHub / GitLab, Git for anything else).
27
+ */
28
+
29
+ /**
30
+ * Normalized event kind. The processor layer maps each provider's raw event
31
+ * header (GitHub `issues`, GitLab `Issue Hook`, …) onto one provider-agnostic
32
+ * kind, so the same logical event reads — and filters — identically across
33
+ * connections instead of appearing once per provider.
34
+ */
35
+
36
+ export const WEBHOOK_CONNECTIONS = [{
37
+ id: "gh-activecollab",
38
+ name: "ActiveCollab",
39
+ service: "github"
40
+ }, {
41
+ id: "gh-abstergo",
42
+ name: "Abstergo Ltd.",
43
+ service: "github"
44
+ }, {
45
+ id: "gh-binford",
46
+ name: "Binford & Co.",
47
+ service: "github"
48
+ }, {
49
+ id: "gl-platform",
50
+ name: "Platform",
51
+ service: "gitlab"
52
+ }, {
53
+ id: "gl-content",
54
+ name: "Content",
55
+ service: "gitlab"
56
+ }, {
57
+ id: "gl-acme-ce",
58
+ name: "Acme Community",
59
+ service: "gitlab"
60
+ }];
61
+ const EVENT_KIND_LABELS = {
62
+ issue: "Issue",
63
+ push: "Push",
64
+ merge_request: "Merge request",
65
+ repository: "Repository",
66
+ ping: "Ping"
67
+ };
68
+ const STATUS_LABELS = {
69
+ received: "Received",
70
+ unhandled: "Unhandled",
71
+ skipped: "Skipped",
72
+ processed: "Processed",
73
+ failed: "Failed",
74
+ duplicate: "Duplicate"
75
+ };
76
+
77
+ /**
78
+ * Status → palette colour, chosen so the colour matches the meaning:
79
+ * processed → green (success), failed → coral (error),
80
+ * skipped → orange (warning), received → sky-blue (in progress),
81
+ * unhandled → silver (neutral / no handler matched),
82
+ * duplicate → purple (replayed delivery, dropped before processing).
83
+ */
84
+ const STATUS_COLORS = {
85
+ processed: {
86
+ bg: "var(--color-green-pale)",
87
+ fg: "var(--color-green-pale-darker)"
88
+ },
89
+ failed: {
90
+ bg: "var(--color-coral)",
91
+ fg: "var(--color-coral-darker)"
92
+ },
93
+ skipped: {
94
+ bg: "var(--color-orange)",
95
+ fg: "var(--color-orange-darker)"
96
+ },
97
+ received: {
98
+ bg: "var(--color-blue-sky)",
99
+ fg: "var(--color-blue-sky-darker)"
100
+ },
101
+ unhandled: {
102
+ bg: "var(--color-gray-silver)",
103
+ fg: "var(--color-gray-silver-darker)"
104
+ },
105
+ duplicate: {
106
+ bg: "var(--color-purple)",
107
+ fg: "var(--color-purple-darker)"
108
+ }
109
+ };
110
+
111
+ /** Provider glyph for a connection: GitHub / GitLab, Git for anything else. */
112
+ const connectionIcon = service => {
113
+ if (service === "github") {
114
+ return GitHubIcon;
115
+ }
116
+ if (service === "gitlab") {
117
+ return GitLabIcon;
118
+ }
119
+ return GitIcon;
120
+ };
121
+ const StatusChip = _ref => {
122
+ let status = _ref.status;
123
+ const _STATUS_COLORS$status = STATUS_COLORS[status],
124
+ bg = _STATUS_COLORS$status.bg,
125
+ fg = _STATUS_COLORS$status.fg;
126
+ return /*#__PURE__*/React.createElement(Chip, {
127
+ label: STATUS_LABELS[status],
128
+ backgroundColor: bg,
129
+ color: fg,
130
+ typographyProps: {
131
+ variant: "Caption 1",
132
+ weight: "medium"
133
+ },
134
+ style: {
135
+ borderRadius: 6
136
+ }
137
+ });
138
+ };
139
+
140
+ /* --- Mock log data (newest first is enforced by sorting on receivedAt) --- */
141
+
142
+ const PAYLOAD_ISSUE_OPENED = JSON.stringify({
143
+ action: "opened",
144
+ issue: {
145
+ id: 2002934201,
146
+ number: 42,
147
+ title: "Webhook delivery retries are not logged",
148
+ state: "open",
149
+ html_url: "https://github.com/activecollab/feather/issues/42",
150
+ labels: [{
151
+ name: "bug"
152
+ }, {
153
+ name: "vcs"
154
+ }],
155
+ user: {
156
+ login: "octocat",
157
+ id: 583231
158
+ }
159
+ },
160
+ repository: {
161
+ id: 776611234,
162
+ full_name: "activecollab/feather",
163
+ private: true
164
+ },
165
+ sender: {
166
+ login: "octocat",
167
+ id: 583231
168
+ }
169
+ }, null, 2);
170
+ const PAYLOAD_MERGE_REQUEST = JSON.stringify({
171
+ object_kind: "merge_request",
172
+ event_type: "merge_request",
173
+ user: {
174
+ id: 41,
175
+ name: "Jane Doe",
176
+ username: "jdoe"
177
+ },
178
+ project: {
179
+ id: 1801,
180
+ path_with_namespace: "content/handbook"
181
+ },
182
+ object_attributes: {
183
+ iid: 318,
184
+ title: "Add changelog for 8.2",
185
+ state: "merged",
186
+ action: "merge",
187
+ source_branch: "changelog-8-2",
188
+ target_branch: "main"
189
+ }
190
+ }, null, 2);
191
+ const PAYLOAD_PUSH = JSON.stringify({
192
+ ref: "refs/heads/main",
193
+ before: "9b2c1f0e",
194
+ after: "f4a7d3c1",
195
+ commits: [{
196
+ id: "f4a7d3c1",
197
+ message: "Fix typo in webhook log repository",
198
+ author: {
199
+ name: "Marko",
200
+ email: "marko@example.com"
201
+ }
202
+ }],
203
+ repository: {
204
+ full_name: "activecollab/feather"
205
+ }
206
+ }, null, 2);
207
+ const WEBHOOK_LOGS = [{
208
+ id: "log-7",
209
+ connectionId: "gh-activecollab",
210
+ eventKind: "issue",
211
+ status: "processed",
212
+ deliveryIdentifier: "d3b07384-d9a0-4c9b-8f1e-2a6f1b9c4e21",
213
+ outcomes: ["Created task #1842 from issue #42"],
214
+ payload: PAYLOAD_ISSUE_OPENED,
215
+ receivedOn: "Jun 29, 2026 · 14:32",
216
+ receivedAt: 1751207520
217
+ }, {
218
+ id: "log-6",
219
+ connectionId: "gl-content",
220
+ eventKind: "merge_request",
221
+ status: "skipped",
222
+ deliveryIdentifier: "b1946ac9-2f3a-4c0d-9b7e-1d2c3e4f5a6b",
223
+ outcomes: ["Skipped: merge request has no linked issue"],
224
+ payload: PAYLOAD_MERGE_REQUEST,
225
+ receivedOn: "Jun 29, 2026 · 11:08",
226
+ receivedAt: 1751195280
227
+ }, {
228
+ id: "log-5",
229
+ connectionId: "gh-activecollab",
230
+ eventKind: "issue",
231
+ status: "failed",
232
+ deliveryIdentifier: "9c1185a5-c5e9-4e3f-8a1b-7d6e5f4c3b2a",
233
+ outcomes: ["Failed at task creation: project not found"],
234
+ payload: PAYLOAD_ISSUE_OPENED,
235
+ receivedOn: "Jun 28, 2026 · 18:54",
236
+ receivedAt: 1751136840
237
+ }, {
238
+ id: "log-4",
239
+ connectionId: "gl-content",
240
+ eventKind: "push",
241
+ status: "processed",
242
+ deliveryIdentifier: "f7c3bc1d-8c5a-4b2e-9f0a-1b2c3d4e5f60",
243
+ outcomes: ["Created task #1839 from issue #311", "Created task #1840 from issue #312"],
244
+ payload: PAYLOAD_PUSH,
245
+ receivedOn: "Jun 28, 2026 · 09:21",
246
+ receivedAt: 1751102460
247
+ }, {
248
+ id: "log-3",
249
+ connectionId: "gh-activecollab",
250
+ eventKind: "ping",
251
+ status: "unhandled",
252
+ deliveryIdentifier: "1574bddb-75c3-4b1e-8a9c-0d1e2f3a4b5c",
253
+ outcomes: [],
254
+ payload: JSON.stringify({
255
+ zen: "Keep it logically awesome.",
256
+ hook_id: 552012
257
+ }, null, 2),
258
+ receivedOn: "Jun 27, 2026 · 16:05",
259
+ receivedAt: 1751040300
260
+ }, {
261
+ id: "log-2",
262
+ connectionId: "gl-content",
263
+ eventKind: "issue",
264
+ status: "received",
265
+ deliveryIdentifier: "0716d970-2b9e-4a1d-9c3f-5e6a7b8c9d01",
266
+ outcomes: [],
267
+ receivedOn: "Jun 27, 2026 · 08:47",
268
+ receivedAt: 1751013420
269
+ }, {
270
+ id: "log-1",
271
+ connectionId: "gh-activecollab",
272
+ eventKind: "issue",
273
+ status: "processed",
274
+ deliveryIdentifier: "fa3ebd6742c360b2d9652b7f78d9bd7d",
275
+ outcomes: ["Created task #1804 from issue #29"],
276
+ payload: PAYLOAD_ISSUE_OPENED,
277
+ receivedOn: "Jun 26, 2026 · 13:12",
278
+ receivedAt: 1750943520
279
+ }, {
280
+ id: "log-1-replay",
281
+ connectionId: "gh-activecollab",
282
+ eventKind: "issue",
283
+ status: "duplicate",
284
+ deliveryIdentifier: "fa3ebd6742c360b2d9652b7f78d9bd7d",
285
+ outcomes: [],
286
+ payload: PAYLOAD_ISSUE_OPENED,
287
+ receivedOn: "Jun 26, 2026 · 13:18",
288
+ receivedAt: 1750943880
289
+ }];
290
+
291
+ /* --- Lightweight, Prism-style JSON syntax highlighter -------------------- */
292
+ /* design-system has no `prismjs` dependency (it's an app dependency), so for */
293
+ /* this throwaway mock we tokenize JSON ourselves and colour the tokens with */
294
+ /* the same token classes Prism uses, styled via PayloadPre below. */
295
+
296
+ const escapeHtml = value => value.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
297
+ const highlightJson = json => escapeHtml(json).replace(/("(?:\\u[a-zA-Z0-9]{4}|\\[^u]|[^\\"])*"(\s*:)?|\b(?:true|false)\b|\bnull\b|-?\d+(?:\.\d*)?(?:[eE][+-]?\d+)?)/g, match => {
298
+ let cls = "tok-number";
299
+ if (/^"/.test(match)) {
300
+ cls = /:$/.test(match) ? "tok-key" : "tok-string";
301
+ } else if (/true|false/.test(match)) {
302
+ cls = "tok-boolean";
303
+ } else if (/null/.test(match)) {
304
+ cls = "tok-null";
305
+ }
306
+ return "<span class=\"" + cls + "\">" + match + "</span>";
307
+ });
308
+ const PAYLOAD_COLLAPSED_LINES = 6;
309
+ const PayloadPre = styled.pre.withConfig({
310
+ displayName: "WebhookLogsDialog__PayloadPre",
311
+ componentId: "sc-6ol7f6-0"
312
+ })(["margin:0;padding:12px 14px;border:1px solid var(--color-theme-400);border-radius:6px;background-color:var(--color-theme-200);color:var(--color-theme-800);font-family:\"SFMono-Regular\",Consolas,\"Liberation Mono\",Menlo,monospace;font-size:12px;line-height:18px;overflow-x:auto;white-space:pre;position:relative;", " .tok-key{color:var(--color-coral-lighter);}.tok-string{color:var(--color-green-pale-lighter);}.tok-number{color:var(--color-orange-lighter);}.tok-boolean{color:var(--color-blue-sky-lighter);}.tok-null{color:var(--color-purple-lighter);}"], _ref2 => {
313
+ let $collapsed = _ref2.$collapsed;
314
+ return $collapsed ? "max-height: " + (PAYLOAD_COLLAPSED_LINES * 18 + 24) + "px;\n overflow-y: hidden;" : "";
315
+ });
316
+ const PayloadWrap = styled.div.withConfig({
317
+ displayName: "WebhookLogsDialog__PayloadWrap",
318
+ componentId: "sc-6ol7f6-1"
319
+ })([".payload-toggle{display:flex;justify-content:flex-end;min-height:24px;margin-bottom:4px;}"]);
320
+ const PayloadBlock = _ref3 => {
321
+ let payload = _ref3.payload;
322
+ const _useState = useState(true),
323
+ collapsed = _useState[0],
324
+ setCollapsed = _useState[1];
325
+ const lineCount = useMemo(() => payload.split("\n").length, [payload]);
326
+ const html = useMemo(() => highlightJson(payload), [payload]);
327
+ const canToggle = lineCount > PAYLOAD_COLLAPSED_LINES;
328
+ return /*#__PURE__*/React.createElement(PayloadWrap, null, canToggle ? /*#__PURE__*/React.createElement("div", {
329
+ className: "payload-toggle"
330
+ }, /*#__PURE__*/React.createElement(Button, {
331
+ variant: "text colored",
332
+ size: "small",
333
+ onClick: () => setCollapsed(value => !value)
334
+ }, collapsed ? "Show More" : "Show Less")) : null, /*#__PURE__*/React.createElement(PayloadPre, {
335
+ $collapsed: collapsed && canToggle,
336
+ dangerouslySetInnerHTML: {
337
+ __html: html
338
+ }
339
+ }));
340
+ };
341
+
342
+ /* --- A single, expandable log row ---------------------------------------- */
343
+
344
+ const LogRowWrap = styled.div.withConfig({
345
+ displayName: "WebhookLogsDialog__LogRowWrap",
346
+ componentId: "sc-6ol7f6-2"
347
+ })(["border-top:1px solid var(--color-theme-300);.lr-summary{box-sizing:border-box;display:flex;align-items:center;gap:12px;width:100%;min-height:56px;padding:8px 8px 8px 12px;background:none;border:0;text-align:left;cursor:pointer;font-family:inherit;&:hover{background-color:var(--color-theme-200);}}.lr-expand{flex-shrink:0;color:var(--color-theme-600);transform:rotate(90deg);transition:transform 150ms ease;}.lr-expand.open{transform:rotate(180deg);}.lr-conn{display:flex;align-items:center;gap:8px;width:180px;min-width:0;flex-shrink:0;}.lr-conn svg{width:20px;height:20px;flex-shrink:0;}.lr-conn .lr-conn-name{overflow:hidden;white-space:nowrap;text-overflow:ellipsis;}.lr-event{flex:1 1 0%;min-width:0;}.lr-status{flex-shrink:0;}.lr-outcomes{width:96px;flex-shrink:0;text-align:right;}.lr-detail{padding:4px 16px 20px 44px;display:flex;flex-direction:column;gap:16px;}.lr-field-label{display:block;margin-bottom:4px;}.lr-id{font-family:\"SFMono-Regular\",Consolas,\"Liberation Mono\",Menlo,monospace;word-break:break-all;}.lr-outcome-list{margin:0;padding-left:18px;display:flex;flex-direction:column;gap:4px;}"]);
348
+ const LogRow = _ref4 => {
349
+ var _connection$name;
350
+ let log = _ref4.log,
351
+ connection = _ref4.connection;
352
+ const _useState2 = useState(false),
353
+ open = _useState2[0],
354
+ setOpen = _useState2[1];
355
+ const ConnIcon = connectionIcon(connection == null ? void 0 : connection.service);
356
+ return /*#__PURE__*/React.createElement(LogRowWrap, null, /*#__PURE__*/React.createElement("button", {
357
+ type: "button",
358
+ className: "lr-summary",
359
+ "aria-expanded": open,
360
+ onClick: () => setOpen(value => !value)
361
+ }, /*#__PURE__*/React.createElement(CollapseExpandSingleIcon, {
362
+ className: open ? "lr-expand open" : "lr-expand"
363
+ }), /*#__PURE__*/React.createElement("span", {
364
+ className: "lr-conn"
365
+ }, /*#__PURE__*/React.createElement(ConnIcon, null), /*#__PURE__*/React.createElement(Body2, {
366
+ className: "lr-conn-name",
367
+ weight: "bold"
368
+ }, (_connection$name = connection == null ? void 0 : connection.name) != null ? _connection$name : "Unknown")), /*#__PURE__*/React.createElement(Body2, {
369
+ className: "lr-event",
370
+ color: "tertiary"
371
+ }, EVENT_KIND_LABELS[log.eventKind]), /*#__PURE__*/React.createElement("span", {
372
+ className: "lr-status"
373
+ }, /*#__PURE__*/React.createElement(StatusChip, {
374
+ status: log.status
375
+ })), /*#__PURE__*/React.createElement(Caption1, {
376
+ className: "lr-outcomes",
377
+ color: "tertiary"
378
+ }, log.outcomes.length > 0 ? log.outcomes.length + " " + (log.outcomes.length === 1 ? "outcome" : "outcomes") : "")), open ? /*#__PURE__*/React.createElement("div", {
379
+ className: "lr-detail"
380
+ }, /*#__PURE__*/React.createElement("div", null, /*#__PURE__*/React.createElement(Caption1, {
381
+ className: "lr-field-label",
382
+ color: "secondary",
383
+ weight: "bold"
384
+ }, "Webhook identifier"), /*#__PURE__*/React.createElement(Body2, {
385
+ className: "lr-id",
386
+ color: "tertiary"
387
+ }, log.deliveryIdentifier)), /*#__PURE__*/React.createElement("div", null, /*#__PURE__*/React.createElement(Caption1, {
388
+ className: "lr-field-label",
389
+ color: "secondary",
390
+ weight: "bold"
391
+ }, "Outcomes"), log.outcomes.length > 0 ? /*#__PURE__*/React.createElement("ul", {
392
+ className: "lr-outcome-list"
393
+ }, log.outcomes.map((outcome, index) => /*#__PURE__*/React.createElement("li", {
394
+ key: index
395
+ }, /*#__PURE__*/React.createElement(Body2, {
396
+ color: "tertiary"
397
+ }, outcome)))) : /*#__PURE__*/React.createElement(Body2, {
398
+ color: "tertiary"
399
+ }, "No outcomes were recorded for this webhook.")), log.payload ? /*#__PURE__*/React.createElement("div", null, /*#__PURE__*/React.createElement(Caption1, {
400
+ className: "lr-field-label",
401
+ color: "secondary",
402
+ weight: "bold"
403
+ }, "Payload"), /*#__PURE__*/React.createElement(PayloadBlock, {
404
+ payload: log.payload
405
+ })) : null) : null);
406
+ };
407
+
408
+ /* --- The dialog ---------------------------------------------------------- */
409
+
410
+ /** Wider than the default 540px dialog so the log columns have room. */
411
+ const WebhookLogsDialogStyled = styled(Dialog).withConfig({
412
+ displayName: "WebhookLogsDialog__WebhookLogsDialogStyled",
413
+ componentId: "sc-6ol7f6-3"
414
+ })(["&&{width:calc(100vw - 64px);max-width:760px;}"]);
415
+ const DialogTitleBar = styled.div.withConfig({
416
+ displayName: "WebhookLogsDialog__DialogTitleBar",
417
+ componentId: "sc-6ol7f6-4"
418
+ })(["display:flex;align-items:center;justify-content:space-between;gap:16px;.title-actions{display:flex;align-items:center;gap:8px;flex-shrink:0;}"]);
419
+ const LogListHeader = styled.div.withConfig({
420
+ displayName: "WebhookLogsDialog__LogListHeader",
421
+ componentId: "sc-6ol7f6-5"
422
+ })(["box-sizing:border-box;display:flex;align-items:center;gap:12px;padding:0 8px 8px 44px;.lh-conn{width:180px;flex-shrink:0;}.lh-event{flex:1 1 0%;min-width:0;}.lh-status{width:96px;flex-shrink:0;}.lh-outcomes{width:96px;flex-shrink:0;text-align:right;}"]);
423
+ const EmptyLogs = styled.div.withConfig({
424
+ displayName: "WebhookLogsDialog__EmptyLogs",
425
+ componentId: "sc-6ol7f6-6"
426
+ })(["padding:40px 0;text-align:center;"]);
427
+ export const WebhookLogsDialog = _ref5 => {
428
+ let open = _ref5.open,
429
+ onClose = _ref5.onClose,
430
+ initialConnectionId = _ref5.initialConnectionId,
431
+ connectionIds = _ref5.connectionIds;
432
+ const _useState3 = useState(() => {
433
+ if (connectionIds && connectionIds.length > 0) {
434
+ return {
435
+ connection: connectionIds
436
+ };
437
+ }
438
+ if (initialConnectionId) {
439
+ return {
440
+ connection: [initialConnectionId]
441
+ };
442
+ }
443
+ return {};
444
+ }),
445
+ filters = _useState3[0],
446
+ setFilters = _useState3[1];
447
+ const connectionsById = useMemo(() => {
448
+ const map = {};
449
+ WEBHOOK_CONNECTIONS.forEach(connection => {
450
+ map[connection.id] = connection;
451
+ });
452
+ return map;
453
+ }, []);
454
+ const filterData = useMemo(() => [{
455
+ id: "connection",
456
+ title: "Connection",
457
+ submenu: WEBHOOK_CONNECTIONS.map(connection => ({
458
+ id: connection.id,
459
+ name: connection.name
460
+ }))
461
+ }, {
462
+ id: "event_type",
463
+ title: "Event Type",
464
+ submenu: Array.from(new Set(WEBHOOK_LOGS.map(log => log.eventKind))).map(eventKind => ({
465
+ id: eventKind,
466
+ name: EVENT_KIND_LABELS[eventKind]
467
+ }))
468
+ }, {
469
+ id: "status",
470
+ title: "Processing Status",
471
+ submenu: Object.keys(STATUS_LABELS).map(status => ({
472
+ id: status,
473
+ name: STATUS_LABELS[status]
474
+ }))
475
+ }], []);
476
+ const visibleLogs = useMemo(() => {
477
+ var _filters$connection, _filters$event_type, _filters$status;
478
+ const byConnection = (_filters$connection = filters.connection) != null ? _filters$connection : [];
479
+ const byEvent = (_filters$event_type = filters.event_type) != null ? _filters$event_type : [];
480
+ const byStatus = (_filters$status = filters.status) != null ? _filters$status : [];
481
+ return WEBHOOK_LOGS.filter(log => {
482
+ if (byConnection.length && !byConnection.includes(log.connectionId)) {
483
+ return false;
484
+ }
485
+ if (byEvent.length && !byEvent.includes(log.eventKind)) {
486
+ return false;
487
+ }
488
+ if (byStatus.length && !byStatus.includes(log.status)) {
489
+ return false;
490
+ }
491
+ return true;
492
+ }).sort((a, b) => b.receivedAt - a.receivedAt);
493
+ }, [filters]);
494
+ return /*#__PURE__*/React.createElement(WebhookLogsDialogStyled, {
495
+ open: open,
496
+ onClose: onClose,
497
+ enableBackgroundClick: true
498
+ }, /*#__PURE__*/React.createElement(Dialog.Title, {
499
+ disableDefaultHeading: true
500
+ }, /*#__PURE__*/React.createElement(DialogTitleBar, null, /*#__PURE__*/React.createElement(Header3, null, "Webhook Logs"), /*#__PURE__*/React.createElement("div", {
501
+ className: "title-actions"
502
+ }, /*#__PURE__*/React.createElement(Filter, {
503
+ data: filterData,
504
+ selected: filters,
505
+ label: "Filter",
506
+ clearAllText: "Clear All",
507
+ noResultText: "No results",
508
+ emptyFilterText: "No filters to show",
509
+ onChange: setFilters
510
+ }), /*#__PURE__*/React.createElement(IconButton, {
511
+ variant: "text gray",
512
+ onClick: onClose
513
+ }, /*#__PURE__*/React.createElement(CancelCrossIcon, null))))), /*#__PURE__*/React.createElement(Dialog.ContentDivider, null), /*#__PURE__*/React.createElement(Dialog.Content, null, visibleLogs.length > 0 ? /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement(LogListHeader, null, /*#__PURE__*/React.createElement(Caption2, {
514
+ className: "lh-conn",
515
+ color: "secondary",
516
+ weight: "bold"
517
+ }, "CONNECTION"), /*#__PURE__*/React.createElement(Caption2, {
518
+ className: "lh-event",
519
+ color: "secondary",
520
+ weight: "bold"
521
+ }, "EVENT TYPE"), /*#__PURE__*/React.createElement(Caption2, {
522
+ className: "lh-status",
523
+ color: "secondary",
524
+ weight: "bold"
525
+ }, "STATUS"), /*#__PURE__*/React.createElement(Caption2, {
526
+ className: "lh-outcomes",
527
+ color: "secondary",
528
+ weight: "bold"
529
+ }, "OUTCOMES")), visibleLogs.map(log => /*#__PURE__*/React.createElement(LogRow, {
530
+ key: log.id,
531
+ log: log,
532
+ connection: connectionsById[log.connectionId]
533
+ }))) : /*#__PURE__*/React.createElement(EmptyLogs, null, /*#__PURE__*/React.createElement(Body2, {
534
+ color: "tertiary"
535
+ }, "No webhook logs match the selected filters."))));
536
+ };
537
+ //# sourceMappingURL=WebhookLogsDialog.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"WebhookLogsDialog.js","names":["React","useMemo","useState","styled","Button","Chip","Dialog","Filter","IconButton","CancelCrossIcon","CollapseExpandSingleIcon","GitHubIcon","GitIcon","GitLabIcon","Body2","Caption1","Caption2","Header3","WEBHOOK_CONNECTIONS","id","name","service","EVENT_KIND_LABELS","issue","push","merge_request","repository","ping","STATUS_LABELS","received","unhandled","skipped","processed","failed","duplicate","STATUS_COLORS","bg","fg","connectionIcon","StatusChip","_ref","status","_STATUS_COLORS$status","createElement","label","backgroundColor","color","typographyProps","variant","weight","style","borderRadius","PAYLOAD_ISSUE_OPENED","JSON","stringify","action","number","title","state","html_url","labels","user","login","full_name","private","sender","PAYLOAD_MERGE_REQUEST","object_kind","event_type","username","project","path_with_namespace","object_attributes","iid","source_branch","target_branch","PAYLOAD_PUSH","ref","before","after","commits","message","author","email","WEBHOOK_LOGS","connectionId","eventKind","deliveryIdentifier","outcomes","payload","receivedOn","receivedAt","zen","hook_id","escapeHtml","value","replace","highlightJson","json","match","cls","test","PAYLOAD_COLLAPSED_LINES","PayloadPre","pre","withConfig","displayName","componentId","_ref2","$collapsed","PayloadWrap","div","PayloadBlock","_ref3","_useState","collapsed","setCollapsed","lineCount","split","length","html","canToggle","className","size","onClick","dangerouslySetInnerHTML","__html","LogRowWrap","LogRow","_ref4","_connection$name","log","connection","_useState2","open","setOpen","ConnIcon","type","map","outcome","index","key","WebhookLogsDialogStyled","DialogTitleBar","LogListHeader","EmptyLogs","WebhookLogsDialog","_ref5","onClose","initialConnectionId","connectionIds","_useState3","filters","setFilters","connectionsById","forEach","filterData","submenu","Array","from","Set","Object","keys","visibleLogs","_filters$connection","_filters$event_type","_filters$status","byConnection","byEvent","byStatus","filter","includes","sort","a","b","enableBackgroundClick","Title","disableDefaultHeading","data","selected","clearAllText","noResultText","emptyFilterText","onChange","ContentDivider","Content","Fragment"],"sources":["../../../../src/presentation/shared/WebhookLogsDialog.tsx"],"sourcesContent":["import React, { ElementType, ReactElement, useMemo, useState } from \"react\";\n\nimport styled from \"styled-components\";\n\nimport { Button } from \"../../components/Button\";\nimport { Chip } from \"../../components/Chip\";\nimport { Dialog } from \"../../components/Dialog\";\nimport { Filter, SelectedType } from \"../../components/Filter\";\nimport { IconButton } from \"../../components/IconButton\";\nimport {\n CancelCrossIcon,\n CollapseExpandSingleIcon,\n GitHubIcon,\n GitIcon,\n GitLabIcon,\n} from \"../../components/Icons\";\nimport {\n Body2,\n Caption1,\n Caption2,\n Header3,\n} from \"../../components/Typography\";\n\n/**\n * \"Webhook Logs\" — the VCS webhook delivery log, shown as a wide dialog with a\n * filterable, expandable list. Extracted into `shared/` so it can be opened\n * from more than one surface (the Apps & Integrations Repositories page and the\n * project \"...\" menu on the Project Repos story).\n *\n * Mirrors the app's webhook log model:\n * `vcs_webhook_logs` → connection_id, event_type, processing_status\n * (received / unhandled / skipped / processed /\n * failed / duplicate), delivery_identifier, payload,\n * created_on\n * `vcs_webhook_outcomes` → one row per outcome, each with a localized summary\n *\n * The status is derived from the outcomes server-side; here we render the\n * stored value and map it to a palette colour. The connection glyph is the\n * provider icon (GitHub / GitLab, Git for anything else).\n */\n\ntype WebhookStatus =\n | \"received\"\n | \"unhandled\"\n | \"skipped\"\n | \"processed\"\n | \"failed\"\n | \"duplicate\";\n\nexport interface WebhookConnection {\n id: string;\n name: string;\n service: \"github\" | \"gitlab\";\n}\n\n/**\n * Normalized event kind. The processor layer maps each provider's raw event\n * header (GitHub `issues`, GitLab `Issue Hook`, …) onto one provider-agnostic\n * kind, so the same logical event reads — and filters — identically across\n * connections instead of appearing once per provider.\n */\ntype WebhookEventKind =\n | \"issue\"\n | \"push\"\n | \"merge_request\"\n | \"repository\"\n | \"ping\";\n\nexport interface WebhookLog {\n id: string;\n connectionId: string;\n eventKind: WebhookEventKind;\n status: WebhookStatus;\n /** X-GitHub-Delivery GUID / X-Gitlab-Event-UUID. */\n deliveryIdentifier: string;\n /** Localized outcome summaries; empty when we never reached that stage. */\n outcomes: string[];\n /** Pretty-printed JSON payload; absent when no JSON body was logged. */\n payload?: string;\n /** Display timestamp. */\n receivedOn: string;\n /** Sort key — newest logs render at the top. */\n receivedAt: number;\n}\n\nexport const WEBHOOK_CONNECTIONS: WebhookConnection[] = [\n { id: \"gh-activecollab\", name: \"ActiveCollab\", service: \"github\" },\n { id: \"gh-abstergo\", name: \"Abstergo Ltd.\", service: \"github\" },\n { id: \"gh-binford\", name: \"Binford & Co.\", service: \"github\" },\n { id: \"gl-platform\", name: \"Platform\", service: \"gitlab\" },\n { id: \"gl-content\", name: \"Content\", service: \"gitlab\" },\n { id: \"gl-acme-ce\", name: \"Acme Community\", service: \"gitlab\" },\n];\n\nconst EVENT_KIND_LABELS: Record<WebhookEventKind, string> = {\n issue: \"Issue\",\n push: \"Push\",\n merge_request: \"Merge request\",\n repository: \"Repository\",\n ping: \"Ping\",\n};\n\nconst STATUS_LABELS: Record<WebhookStatus, string> = {\n received: \"Received\",\n unhandled: \"Unhandled\",\n skipped: \"Skipped\",\n processed: \"Processed\",\n failed: \"Failed\",\n duplicate: \"Duplicate\",\n};\n\n/**\n * Status → palette colour, chosen so the colour matches the meaning:\n * processed → green (success), failed → coral (error),\n * skipped → orange (warning), received → sky-blue (in progress),\n * unhandled → silver (neutral / no handler matched),\n * duplicate → purple (replayed delivery, dropped before processing).\n */\nconst STATUS_COLORS: Record<WebhookStatus, { bg: string; fg: string }> = {\n processed: {\n bg: \"var(--color-green-pale)\",\n fg: \"var(--color-green-pale-darker)\",\n },\n failed: { bg: \"var(--color-coral)\", fg: \"var(--color-coral-darker)\" },\n skipped: { bg: \"var(--color-orange)\", fg: \"var(--color-orange-darker)\" },\n received: {\n bg: \"var(--color-blue-sky)\",\n fg: \"var(--color-blue-sky-darker)\",\n },\n unhandled: {\n bg: \"var(--color-gray-silver)\",\n fg: \"var(--color-gray-silver-darker)\",\n },\n duplicate: {\n bg: \"var(--color-purple)\",\n fg: \"var(--color-purple-darker)\",\n },\n};\n\n/** Provider glyph for a connection: GitHub / GitLab, Git for anything else. */\nconst connectionIcon = (\n service?: WebhookConnection[\"service\"]\n): ElementType => {\n if (service === \"github\") {\n return GitHubIcon;\n }\n if (service === \"gitlab\") {\n return GitLabIcon;\n }\n return GitIcon;\n};\n\nconst StatusChip = ({ status }: { status: WebhookStatus }): ReactElement => {\n const { bg, fg } = STATUS_COLORS[status];\n\n return (\n <Chip\n label={STATUS_LABELS[status]}\n backgroundColor={bg}\n color={fg}\n typographyProps={{ variant: \"Caption 1\", weight: \"medium\" }}\n style={{ borderRadius: 6 }}\n />\n );\n};\n\n/* --- Mock log data (newest first is enforced by sorting on receivedAt) --- */\n\nconst PAYLOAD_ISSUE_OPENED = JSON.stringify(\n {\n action: \"opened\",\n issue: {\n id: 2002934201,\n number: 42,\n title: \"Webhook delivery retries are not logged\",\n state: \"open\",\n html_url: \"https://github.com/activecollab/feather/issues/42\",\n labels: [{ name: \"bug\" }, { name: \"vcs\" }],\n user: { login: \"octocat\", id: 583231 },\n },\n repository: {\n id: 776611234,\n full_name: \"activecollab/feather\",\n private: true,\n },\n sender: { login: \"octocat\", id: 583231 },\n },\n null,\n 2\n);\n\nconst PAYLOAD_MERGE_REQUEST = JSON.stringify(\n {\n object_kind: \"merge_request\",\n event_type: \"merge_request\",\n user: { id: 41, name: \"Jane Doe\", username: \"jdoe\" },\n project: { id: 1801, path_with_namespace: \"content/handbook\" },\n object_attributes: {\n iid: 318,\n title: \"Add changelog for 8.2\",\n state: \"merged\",\n action: \"merge\",\n source_branch: \"changelog-8-2\",\n target_branch: \"main\",\n },\n },\n null,\n 2\n);\n\nconst PAYLOAD_PUSH = JSON.stringify(\n {\n ref: \"refs/heads/main\",\n before: \"9b2c1f0e\",\n after: \"f4a7d3c1\",\n commits: [\n {\n id: \"f4a7d3c1\",\n message: \"Fix typo in webhook log repository\",\n author: { name: \"Marko\", email: \"marko@example.com\" },\n },\n ],\n repository: { full_name: \"activecollab/feather\" },\n },\n null,\n 2\n);\n\nconst WEBHOOK_LOGS: WebhookLog[] = [\n {\n id: \"log-7\",\n connectionId: \"gh-activecollab\",\n eventKind: \"issue\",\n status: \"processed\",\n deliveryIdentifier: \"d3b07384-d9a0-4c9b-8f1e-2a6f1b9c4e21\",\n outcomes: [\"Created task #1842 from issue #42\"],\n payload: PAYLOAD_ISSUE_OPENED,\n receivedOn: \"Jun 29, 2026 · 14:32\",\n receivedAt: 1751207520,\n },\n {\n id: \"log-6\",\n connectionId: \"gl-content\",\n eventKind: \"merge_request\",\n status: \"skipped\",\n deliveryIdentifier: \"b1946ac9-2f3a-4c0d-9b7e-1d2c3e4f5a6b\",\n outcomes: [\"Skipped: merge request has no linked issue\"],\n payload: PAYLOAD_MERGE_REQUEST,\n receivedOn: \"Jun 29, 2026 · 11:08\",\n receivedAt: 1751195280,\n },\n {\n id: \"log-5\",\n connectionId: \"gh-activecollab\",\n eventKind: \"issue\",\n status: \"failed\",\n deliveryIdentifier: \"9c1185a5-c5e9-4e3f-8a1b-7d6e5f4c3b2a\",\n outcomes: [\"Failed at task creation: project not found\"],\n payload: PAYLOAD_ISSUE_OPENED,\n receivedOn: \"Jun 28, 2026 · 18:54\",\n receivedAt: 1751136840,\n },\n {\n id: \"log-4\",\n connectionId: \"gl-content\",\n eventKind: \"push\",\n status: \"processed\",\n deliveryIdentifier: \"f7c3bc1d-8c5a-4b2e-9f0a-1b2c3d4e5f60\",\n outcomes: [\n \"Created task #1839 from issue #311\",\n \"Created task #1840 from issue #312\",\n ],\n payload: PAYLOAD_PUSH,\n receivedOn: \"Jun 28, 2026 · 09:21\",\n receivedAt: 1751102460,\n },\n {\n id: \"log-3\",\n connectionId: \"gh-activecollab\",\n eventKind: \"ping\",\n status: \"unhandled\",\n deliveryIdentifier: \"1574bddb-75c3-4b1e-8a9c-0d1e2f3a4b5c\",\n outcomes: [],\n payload: JSON.stringify(\n { zen: \"Keep it logically awesome.\", hook_id: 552012 },\n null,\n 2\n ),\n receivedOn: \"Jun 27, 2026 · 16:05\",\n receivedAt: 1751040300,\n },\n {\n id: \"log-2\",\n connectionId: \"gl-content\",\n eventKind: \"issue\",\n status: \"received\",\n deliveryIdentifier: \"0716d970-2b9e-4a1d-9c3f-5e6a7b8c9d01\",\n outcomes: [],\n receivedOn: \"Jun 27, 2026 · 08:47\",\n receivedAt: 1751013420,\n },\n {\n id: \"log-1\",\n connectionId: \"gh-activecollab\",\n eventKind: \"issue\",\n status: \"processed\",\n deliveryIdentifier: \"fa3ebd6742c360b2d9652b7f78d9bd7d\",\n outcomes: [\"Created task #1804 from issue #29\"],\n payload: PAYLOAD_ISSUE_OPENED,\n receivedOn: \"Jun 26, 2026 · 13:12\",\n receivedAt: 1750943520,\n },\n {\n id: \"log-1-replay\",\n connectionId: \"gh-activecollab\",\n eventKind: \"issue\",\n status: \"duplicate\",\n deliveryIdentifier: \"fa3ebd6742c360b2d9652b7f78d9bd7d\",\n outcomes: [],\n payload: PAYLOAD_ISSUE_OPENED,\n receivedOn: \"Jun 26, 2026 · 13:18\",\n receivedAt: 1750943880,\n },\n];\n\n/* --- Lightweight, Prism-style JSON syntax highlighter -------------------- */\n/* design-system has no `prismjs` dependency (it's an app dependency), so for */\n/* this throwaway mock we tokenize JSON ourselves and colour the tokens with */\n/* the same token classes Prism uses, styled via PayloadPre below. */\n\nconst escapeHtml = (value: string): string =>\n value.replace(/&/g, \"&amp;\").replace(/</g, \"&lt;\").replace(/>/g, \"&gt;\");\n\nconst highlightJson = (json: string): string =>\n escapeHtml(json).replace(\n /(\"(?:\\\\u[a-zA-Z0-9]{4}|\\\\[^u]|[^\\\\\"])*\"(\\s*:)?|\\b(?:true|false)\\b|\\bnull\\b|-?\\d+(?:\\.\\d*)?(?:[eE][+-]?\\d+)?)/g,\n (match) => {\n let cls = \"tok-number\";\n\n if (/^\"/.test(match)) {\n cls = /:$/.test(match) ? \"tok-key\" : \"tok-string\";\n } else if (/true|false/.test(match)) {\n cls = \"tok-boolean\";\n } else if (/null/.test(match)) {\n cls = \"tok-null\";\n }\n\n return `<span class=\"${cls}\">${match}</span>`;\n }\n );\n\nconst PAYLOAD_COLLAPSED_LINES = 6;\n\nconst PayloadPre = styled.pre<{ $collapsed: boolean }>`\n margin: 0;\n padding: 12px 14px;\n border: 1px solid var(--color-theme-400);\n border-radius: 6px;\n background-color: var(--color-theme-200);\n color: var(--color-theme-800);\n font-family: \"SFMono-Regular\", Consolas, \"Liberation Mono\", Menlo, monospace;\n font-size: 12px;\n line-height: 18px;\n overflow-x: auto;\n white-space: pre;\n position: relative;\n\n ${({ $collapsed }) =>\n $collapsed\n ? `max-height: ${PAYLOAD_COLLAPSED_LINES * 18 + 24}px;\n overflow-y: hidden;`\n : \"\"}\n\n .tok-key {\n color: var(--color-coral-lighter);\n }\n .tok-string {\n color: var(--color-green-pale-lighter);\n }\n .tok-number {\n color: var(--color-orange-lighter);\n }\n .tok-boolean {\n color: var(--color-blue-sky-lighter);\n }\n .tok-null {\n color: var(--color-purple-lighter);\n }\n`;\n\nconst PayloadWrap = styled.div`\n .payload-toggle {\n display: flex;\n justify-content: flex-end;\n min-height: 24px;\n margin-bottom: 4px;\n }\n`;\n\nconst PayloadBlock = ({ payload }: { payload: string }): ReactElement => {\n const [collapsed, setCollapsed] = useState(true);\n\n const lineCount = useMemo(() => payload.split(\"\\n\").length, [payload]);\n const html = useMemo(() => highlightJson(payload), [payload]);\n const canToggle = lineCount > PAYLOAD_COLLAPSED_LINES;\n\n return (\n <PayloadWrap>\n {canToggle ? (\n <div className=\"payload-toggle\">\n <Button\n variant=\"text colored\"\n size=\"small\"\n onClick={() => setCollapsed((value) => !value)}\n >\n {collapsed ? \"Show More\" : \"Show Less\"}\n </Button>\n </div>\n ) : null}\n <PayloadPre\n $collapsed={collapsed && canToggle}\n dangerouslySetInnerHTML={{ __html: html }}\n />\n </PayloadWrap>\n );\n};\n\n/* --- A single, expandable log row ---------------------------------------- */\n\nconst LogRowWrap = styled.div`\n border-top: 1px solid var(--color-theme-300);\n\n .lr-summary {\n box-sizing: border-box;\n display: flex;\n align-items: center;\n gap: 12px;\n width: 100%;\n min-height: 56px;\n padding: 8px 8px 8px 12px;\n background: none;\n border: 0;\n text-align: left;\n cursor: pointer;\n font-family: inherit;\n\n &:hover {\n background-color: var(--color-theme-200);\n }\n }\n\n /* Default icon points up; collapsed → point right, expanded → point down. */\n .lr-expand {\n flex-shrink: 0;\n color: var(--color-theme-600);\n transform: rotate(90deg);\n transition: transform 150ms ease;\n }\n\n .lr-expand.open {\n transform: rotate(180deg);\n }\n\n .lr-conn {\n display: flex;\n align-items: center;\n gap: 8px;\n width: 180px;\n min-width: 0;\n flex-shrink: 0;\n }\n\n .lr-conn svg {\n width: 20px;\n height: 20px;\n flex-shrink: 0;\n }\n\n .lr-conn .lr-conn-name {\n overflow: hidden;\n white-space: nowrap;\n text-overflow: ellipsis;\n }\n\n .lr-event {\n flex: 1 1 0%;\n min-width: 0;\n }\n\n .lr-status {\n flex-shrink: 0;\n }\n\n .lr-outcomes {\n width: 96px;\n flex-shrink: 0;\n text-align: right;\n }\n\n .lr-detail {\n padding: 4px 16px 20px 44px;\n display: flex;\n flex-direction: column;\n gap: 16px;\n }\n\n .lr-field-label {\n display: block;\n margin-bottom: 4px;\n }\n\n .lr-id {\n font-family: \"SFMono-Regular\", Consolas, \"Liberation Mono\", Menlo, monospace;\n word-break: break-all;\n }\n\n .lr-outcome-list {\n margin: 0;\n padding-left: 18px;\n display: flex;\n flex-direction: column;\n gap: 4px;\n }\n`;\n\ninterface LogRowProps {\n log: WebhookLog;\n connection?: WebhookConnection;\n}\n\nconst LogRow = ({ log, connection }: LogRowProps): ReactElement => {\n const [open, setOpen] = useState(false);\n const ConnIcon = connectionIcon(connection?.service);\n\n return (\n <LogRowWrap>\n <button\n type=\"button\"\n className=\"lr-summary\"\n aria-expanded={open}\n onClick={() => setOpen((value) => !value)}\n >\n <CollapseExpandSingleIcon\n className={open ? \"lr-expand open\" : \"lr-expand\"}\n />\n <span className=\"lr-conn\">\n <ConnIcon />\n <Body2 className=\"lr-conn-name\" weight=\"bold\">\n {connection?.name ?? \"Unknown\"}\n </Body2>\n </span>\n <Body2 className=\"lr-event\" color=\"tertiary\">\n {EVENT_KIND_LABELS[log.eventKind]}\n </Body2>\n <span className=\"lr-status\">\n <StatusChip status={log.status} />\n </span>\n <Caption1 className=\"lr-outcomes\" color=\"tertiary\">\n {log.outcomes.length > 0\n ? `${log.outcomes.length} ${\n log.outcomes.length === 1 ? \"outcome\" : \"outcomes\"\n }`\n : \"\"}\n </Caption1>\n </button>\n\n {open ? (\n <div className=\"lr-detail\">\n <div>\n <Caption1\n className=\"lr-field-label\"\n color=\"secondary\"\n weight=\"bold\"\n >\n Webhook identifier\n </Caption1>\n <Body2 className=\"lr-id\" color=\"tertiary\">\n {log.deliveryIdentifier}\n </Body2>\n </div>\n\n <div>\n <Caption1\n className=\"lr-field-label\"\n color=\"secondary\"\n weight=\"bold\"\n >\n Outcomes\n </Caption1>\n {log.outcomes.length > 0 ? (\n <ul className=\"lr-outcome-list\">\n {log.outcomes.map((outcome, index) => (\n <li key={index}>\n <Body2 color=\"tertiary\">{outcome}</Body2>\n </li>\n ))}\n </ul>\n ) : (\n <Body2 color=\"tertiary\">\n No outcomes were recorded for this webhook.\n </Body2>\n )}\n </div>\n\n {log.payload ? (\n <div>\n <Caption1\n className=\"lr-field-label\"\n color=\"secondary\"\n weight=\"bold\"\n >\n Payload\n </Caption1>\n <PayloadBlock payload={log.payload} />\n </div>\n ) : null}\n </div>\n ) : null}\n </LogRowWrap>\n );\n};\n\n/* --- The dialog ---------------------------------------------------------- */\n\n/** Wider than the default 540px dialog so the log columns have room. */\nconst WebhookLogsDialogStyled = styled(Dialog)`\n && {\n width: calc(100vw - 64px);\n max-width: 760px;\n }\n`;\n\nconst DialogTitleBar = styled.div`\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: 16px;\n\n .title-actions {\n display: flex;\n align-items: center;\n gap: 8px;\n flex-shrink: 0;\n }\n`;\n\nconst LogListHeader = styled.div`\n box-sizing: border-box;\n display: flex;\n align-items: center;\n gap: 12px;\n padding: 0 8px 8px 44px;\n\n .lh-conn {\n width: 180px;\n flex-shrink: 0;\n }\n .lh-event {\n flex: 1 1 0%;\n min-width: 0;\n }\n .lh-status {\n width: 96px;\n flex-shrink: 0;\n }\n .lh-outcomes {\n width: 96px;\n flex-shrink: 0;\n text-align: right;\n }\n`;\n\nconst EmptyLogs = styled.div`\n padding: 40px 0;\n text-align: center;\n`;\n\nexport interface WebhookLogsDialogProps {\n open: boolean;\n onClose: () => void;\n /** Pre-filter to a single connection (used when opened from its row menu). */\n initialConnectionId?: string;\n /**\n * Pre-filter to a set of connections (e.g. the connections a project's\n * repositories belong to). Takes precedence over `initialConnectionId`.\n */\n connectionIds?: string[];\n}\n\nexport const WebhookLogsDialog = ({\n open,\n onClose,\n initialConnectionId,\n connectionIds,\n}: WebhookLogsDialogProps): ReactElement => {\n const [filters, setFilters] = useState<SelectedType>((): SelectedType => {\n if (connectionIds && connectionIds.length > 0) {\n return { connection: connectionIds };\n }\n if (initialConnectionId) {\n return { connection: [initialConnectionId] };\n }\n return {};\n });\n\n const connectionsById = useMemo(() => {\n const map: Record<string, WebhookConnection> = {};\n WEBHOOK_CONNECTIONS.forEach((connection) => {\n map[connection.id] = connection;\n });\n return map;\n }, []);\n\n const filterData = useMemo(\n () => [\n {\n id: \"connection\",\n title: \"Connection\",\n submenu: WEBHOOK_CONNECTIONS.map((connection) => ({\n id: connection.id,\n name: connection.name,\n })),\n },\n {\n id: \"event_type\",\n title: \"Event Type\",\n submenu: Array.from(\n new Set(WEBHOOK_LOGS.map((log) => log.eventKind))\n ).map((eventKind) => ({\n id: eventKind,\n name: EVENT_KIND_LABELS[eventKind],\n })),\n },\n {\n id: \"status\",\n title: \"Processing Status\",\n submenu: (Object.keys(STATUS_LABELS) as WebhookStatus[]).map(\n (status) => ({ id: status, name: STATUS_LABELS[status] })\n ),\n },\n ],\n []\n );\n\n const visibleLogs = useMemo(() => {\n const byConnection = filters.connection ?? [];\n const byEvent = filters.event_type ?? [];\n const byStatus = filters.status ?? [];\n\n return WEBHOOK_LOGS.filter((log) => {\n if (byConnection.length && !byConnection.includes(log.connectionId)) {\n return false;\n }\n if (byEvent.length && !byEvent.includes(log.eventKind)) {\n return false;\n }\n if (byStatus.length && !byStatus.includes(log.status)) {\n return false;\n }\n return true;\n }).sort((a, b) => b.receivedAt - a.receivedAt);\n }, [filters]);\n\n return (\n <WebhookLogsDialogStyled\n open={open}\n onClose={onClose}\n enableBackgroundClick\n >\n <Dialog.Title disableDefaultHeading>\n <DialogTitleBar>\n <Header3>Webhook Logs</Header3>\n <div className=\"title-actions\">\n <Filter\n data={filterData}\n selected={filters}\n label=\"Filter\"\n clearAllText=\"Clear All\"\n noResultText=\"No results\"\n emptyFilterText=\"No filters to show\"\n onChange={setFilters}\n />\n <IconButton variant=\"text gray\" onClick={onClose}>\n <CancelCrossIcon />\n </IconButton>\n </div>\n </DialogTitleBar>\n </Dialog.Title>\n <Dialog.ContentDivider />\n <Dialog.Content>\n {visibleLogs.length > 0 ? (\n <>\n <LogListHeader>\n <Caption2 className=\"lh-conn\" color=\"secondary\" weight=\"bold\">\n CONNECTION\n </Caption2>\n <Caption2 className=\"lh-event\" color=\"secondary\" weight=\"bold\">\n EVENT TYPE\n </Caption2>\n <Caption2 className=\"lh-status\" color=\"secondary\" weight=\"bold\">\n STATUS\n </Caption2>\n <Caption2 className=\"lh-outcomes\" color=\"secondary\" weight=\"bold\">\n OUTCOMES\n </Caption2>\n </LogListHeader>\n {visibleLogs.map((log) => (\n <LogRow\n key={log.id}\n log={log}\n connection={connectionsById[log.connectionId]}\n />\n ))}\n </>\n ) : (\n <EmptyLogs>\n <Body2 color=\"tertiary\">\n No webhook logs match the selected filters.\n </Body2>\n </EmptyLogs>\n )}\n </Dialog.Content>\n </WebhookLogsDialogStyled>\n );\n};\n"],"mappings":"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","ignoreList":[]}
@@ -1,4 +1,5 @@
1
1
  import { ReactElement, ReactNode } from "react";
2
+ import { Repository } from "./ConnectRepositoryDialog";
2
3
  export interface PageHeaderProps {
3
4
  title: string;
4
5
  children?: ReactNode;
@@ -11,16 +12,20 @@ export declare const PageHeader: {
11
12
  export interface ProjectOptionsMenuProps {
12
13
  /** When the `source` module is loaded, show the Repositories section. */
13
14
  sourceModuleLoaded?: boolean;
15
+ /** Repositories already connected to the project when the menu first mounts. */
16
+ initialConnectedRepositories?: Repository[];
14
17
  }
15
18
  export interface ProjectPageHeaderProps {
16
19
  title?: string;
17
20
  /** When the `source` module is loaded, the "..." menu shows a Repositories
18
21
  * section (connected repositories + Connect Repository). */
19
22
  sourceModuleLoaded?: boolean;
23
+ /** Repositories already connected to the project (seeds the count + submenu). */
24
+ initialConnectedRepositories?: Repository[];
20
25
  }
21
26
  /** The project page header: back arrow, title, progress, info, people, options. */
22
27
  export declare const ProjectPageHeader: {
23
- ({ title, sourceModuleLoaded, }: ProjectPageHeaderProps): ReactElement;
28
+ ({ title, sourceModuleLoaded, initialConnectedRepositories, }: ProjectPageHeaderProps): ReactElement;
24
29
  displayName: string;
25
30
  };
26
31
  export interface TabHeaderProps {