@pagerduty/backstage-plugin 0.19.0 → 0.21.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.
Files changed (49) hide show
  1. package/CHANGELOG.md +24 -0
  2. package/dist/alpha/pages.esm.js +41 -4
  3. package/dist/alpha/pages.esm.js.map +1 -1
  4. package/dist/alpha/plugin.esm.js +4 -3
  5. package/dist/alpha/plugin.esm.js.map +1 -1
  6. package/dist/alpha.d.ts +105 -26
  7. package/dist/api/client.esm.js +145 -3
  8. package/dist/api/client.esm.js.map +1 -1
  9. package/dist/components/PagerDutyPage/AutomaticMappingsDialog.esm.js +86 -40
  10. package/dist/components/PagerDutyPage/AutomaticMappingsDialog.esm.js.map +1 -1
  11. package/dist/components/PagerDutyPage/ConfigurationPage.esm.js +119 -0
  12. package/dist/components/PagerDutyPage/ConfigurationPage.esm.js.map +1 -0
  13. package/dist/components/PagerDutyPage/CustomFieldModal.esm.js +152 -0
  14. package/dist/components/PagerDutyPage/CustomFieldModal.esm.js.map +1 -0
  15. package/dist/components/PagerDutyPage/CustomFields/ButtonTabs.esm.js +51 -0
  16. package/dist/components/PagerDutyPage/CustomFields/ButtonTabs.esm.js.map +1 -0
  17. package/dist/components/PagerDutyPage/CustomFields/CustomFieldsEmptyState.esm.js +46 -0
  18. package/dist/components/PagerDutyPage/CustomFields/CustomFieldsEmptyState.esm.js.map +1 -0
  19. package/dist/components/PagerDutyPage/CustomFields/CustomFieldsTabPanel.esm.js +154 -0
  20. package/dist/components/PagerDutyPage/CustomFields/CustomFieldsTabPanel.esm.js.map +1 -0
  21. package/dist/components/PagerDutyPage/CustomFields/DeleteCustomFieldDialog.esm.js +63 -0
  22. package/dist/components/PagerDutyPage/CustomFields/DeleteCustomFieldDialog.esm.js.map +1 -0
  23. package/dist/components/PagerDutyPage/CustomFields/SyncLogsFilters.esm.js +126 -0
  24. package/dist/components/PagerDutyPage/CustomFields/SyncLogsFilters.esm.js.map +1 -0
  25. package/dist/components/PagerDutyPage/CustomFields/SyncLogsTab.esm.js +285 -0
  26. package/dist/components/PagerDutyPage/CustomFields/SyncLogsTab.esm.js.map +1 -0
  27. package/dist/components/PagerDutyPage/CustomFields/customFieldErrors.esm.js +13 -0
  28. package/dist/components/PagerDutyPage/CustomFields/customFieldErrors.esm.js.map +1 -0
  29. package/dist/components/PagerDutyPage/CustomFields.esm.js +192 -0
  30. package/dist/components/PagerDutyPage/CustomFields.esm.js.map +1 -0
  31. package/dist/components/PagerDutyPage/MappingsDialog.esm.js +2 -0
  32. package/dist/components/PagerDutyPage/MappingsDialog.esm.js.map +1 -1
  33. package/dist/components/PagerDutyPage/MappingsTable/MappingsTable.esm.js +1 -1
  34. package/dist/components/PagerDutyPage/MappingsTable/MappingsTable.esm.js.map +1 -1
  35. package/dist/components/PagerDutyPage/MappingsTable/MappingsTableContent.esm.js +15 -3
  36. package/dist/components/PagerDutyPage/MappingsTable/MappingsTableContent.esm.js.map +1 -1
  37. package/dist/components/PagerDutyPage/MappingsTable/NameCell.esm.js +35 -0
  38. package/dist/components/PagerDutyPage/MappingsTable/NameCell.esm.js.map +1 -0
  39. package/dist/components/PagerDutyPage/MappingsTable/TableSkeleton.esm.js +26 -29
  40. package/dist/components/PagerDutyPage/MappingsTable/TableSkeleton.esm.js.map +1 -1
  41. package/dist/components/PagerDutyPage/ServiceMappingPage.esm.js +22 -0
  42. package/dist/components/PagerDutyPage/ServiceMappingPage.esm.js.map +1 -0
  43. package/dist/components/PagerDutyPage/index.esm.js +12 -127
  44. package/dist/components/PagerDutyPage/index.esm.js.map +1 -1
  45. package/dist/index.d.ts +60 -8
  46. package/dist/package.json.esm.js +1 -1
  47. package/package.json +17 -17
  48. package/dist/alpha/nav-items.esm.js +0 -21
  49. package/dist/alpha/nav-items.esm.js.map +0 -1
@@ -0,0 +1,126 @@
1
+ import { jsxs, jsx } from 'react/jsx-runtime';
2
+ import { Flex, Box, SearchField, Select, Button } from '@backstage/ui';
3
+ import { makeStyles } from '@material-ui/core';
4
+ import { Refresh, FileDownload } from '@mui/icons-material';
5
+
6
+ const useStyles = makeStyles(() => ({
7
+ wrap: {
8
+ flexWrap: "wrap"
9
+ }
10
+ }));
11
+ const EMPTY_SYNC_LOG_FILTERS = {
12
+ search: "",
13
+ severity: "",
14
+ customField: "",
15
+ entityPath: "",
16
+ service: ""
17
+ };
18
+ const SEVERITY_OPTIONS = [
19
+ { value: "", label: "All" },
20
+ { value: "info", label: "Info" },
21
+ { value: "warning", label: "Warning" },
22
+ { value: "error", label: "Error" }
23
+ ];
24
+ const SyncLogsFilters = ({
25
+ values,
26
+ onChange,
27
+ customFieldOptions,
28
+ entityPathOptions,
29
+ serviceOptions,
30
+ onExport,
31
+ exportDisabled,
32
+ onRefresh
33
+ }) => {
34
+ const classes = useStyles();
35
+ const update = (key, value) => {
36
+ onChange({ ...values, [key]: value });
37
+ };
38
+ return /* @__PURE__ */ jsxs(Flex, { align: "end", justify: "between", gap: "3", className: classes.wrap, children: [
39
+ /* @__PURE__ */ jsxs(Flex, { align: "end", gap: "3", className: classes.wrap, children: [
40
+ /* @__PURE__ */ jsx(Box, { width: "200px", children: /* @__PURE__ */ jsx(
41
+ SearchField,
42
+ {
43
+ label: "Search",
44
+ size: "small",
45
+ placeholder: "Search...",
46
+ value: values.search,
47
+ onChange: (value) => update("search", value)
48
+ }
49
+ ) }),
50
+ /* @__PURE__ */ jsx(Box, { width: "150px", children: /* @__PURE__ */ jsx(
51
+ Select,
52
+ {
53
+ label: "Severity",
54
+ selectionMode: "single",
55
+ size: "small",
56
+ value: values.severity,
57
+ onChange: (value) => update("severity", value?.toString() ?? ""),
58
+ placeholder: "All",
59
+ options: SEVERITY_OPTIONS
60
+ }
61
+ ) }),
62
+ /* @__PURE__ */ jsx(Box, { width: "160px", children: /* @__PURE__ */ jsx(
63
+ Select,
64
+ {
65
+ label: "Custom Field",
66
+ selectionMode: "single",
67
+ size: "small",
68
+ value: values.customField,
69
+ onChange: (value) => update("customField", value?.toString() ?? ""),
70
+ placeholder: "All",
71
+ options: customFieldOptions
72
+ }
73
+ ) }),
74
+ /* @__PURE__ */ jsx(Box, { width: "160px", children: /* @__PURE__ */ jsx(
75
+ Select,
76
+ {
77
+ label: "Entity Path",
78
+ selectionMode: "single",
79
+ size: "small",
80
+ value: values.entityPath,
81
+ onChange: (value) => update("entityPath", value?.toString() ?? ""),
82
+ placeholder: "All",
83
+ options: entityPathOptions
84
+ }
85
+ ) }),
86
+ /* @__PURE__ */ jsx(Box, { width: "160px", children: /* @__PURE__ */ jsx(
87
+ Select,
88
+ {
89
+ label: "Service",
90
+ selectionMode: "single",
91
+ size: "small",
92
+ value: values.service,
93
+ onChange: (value) => update("service", value?.toString() ?? ""),
94
+ placeholder: "All",
95
+ options: serviceOptions
96
+ }
97
+ ) })
98
+ ] }),
99
+ /* @__PURE__ */ jsxs(Flex, { align: "end", gap: "3", children: [
100
+ /* @__PURE__ */ jsx(
101
+ Button,
102
+ {
103
+ variant: "secondary",
104
+ size: "small",
105
+ iconStart: /* @__PURE__ */ jsx(Refresh, { fontSize: "small" }),
106
+ onClick: onRefresh,
107
+ children: "Refresh"
108
+ }
109
+ ),
110
+ /* @__PURE__ */ jsx(
111
+ Button,
112
+ {
113
+ variant: "secondary",
114
+ size: "small",
115
+ iconStart: /* @__PURE__ */ jsx(FileDownload, { fontSize: "small" }),
116
+ onClick: onExport,
117
+ isDisabled: exportDisabled,
118
+ children: "Export CSV"
119
+ }
120
+ )
121
+ ] })
122
+ ] });
123
+ };
124
+
125
+ export { EMPTY_SYNC_LOG_FILTERS, SyncLogsFilters };
126
+ //# sourceMappingURL=SyncLogsFilters.esm.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SyncLogsFilters.esm.js","sources":["../../../../src/components/PagerDutyPage/CustomFields/SyncLogsFilters.tsx"],"sourcesContent":["import { Box, Button, Flex, SearchField, Select, type Option } from '@backstage/ui';\nimport { makeStyles } from '@material-ui/core';\nimport { FileDownload, Refresh } from '@mui/icons-material';\n\nconst useStyles = makeStyles(() => ({\n wrap: {\n flexWrap: 'wrap',\n },\n}));\n\n/** @public */\nexport type SyncLogsFilterValues = {\n search: string;\n severity: string;\n customField: string;\n entityPath: string;\n service: string;\n};\n\n/** @public */\nexport const EMPTY_SYNC_LOG_FILTERS: SyncLogsFilterValues = {\n search: '',\n severity: '',\n customField: '',\n entityPath: '',\n service: '',\n};\n\ninterface SyncLogsFiltersProps {\n values: SyncLogsFilterValues;\n onChange: (next: SyncLogsFilterValues) => void;\n customFieldOptions: Option[];\n entityPathOptions: Option[];\n serviceOptions: Option[];\n onExport: () => void;\n exportDisabled?: boolean;\n onRefresh: () => void;\n}\n\nconst SEVERITY_OPTIONS: Option[] = [\n { value: '', label: 'All' },\n { value: 'info', label: 'Info' },\n { value: 'warning', label: 'Warning' },\n { value: 'error', label: 'Error' },\n];\n\n/** @public */\nexport const SyncLogsFilters = ({\n values,\n onChange,\n customFieldOptions,\n entityPathOptions,\n serviceOptions,\n onExport,\n exportDisabled,\n onRefresh,\n}: SyncLogsFiltersProps) => {\n const classes = useStyles();\n const update = <K extends keyof SyncLogsFilterValues>(\n key: K,\n value: SyncLogsFilterValues[K],\n ) => {\n onChange({ ...values, [key]: value });\n };\n\n return (\n <Flex align=\"end\" justify=\"between\" gap=\"3\" className={classes.wrap}>\n <Flex align=\"end\" gap=\"3\" className={classes.wrap}>\n <Box width=\"200px\">\n <SearchField\n label=\"Search\"\n size=\"small\"\n placeholder=\"Search...\"\n value={values.search}\n onChange={value => update('search', value)}\n />\n </Box>\n <Box width=\"150px\">\n <Select\n label=\"Severity\"\n selectionMode=\"single\"\n size=\"small\"\n value={values.severity}\n onChange={value => update('severity', value?.toString() ?? '')}\n placeholder=\"All\"\n options={SEVERITY_OPTIONS}\n />\n </Box>\n <Box width=\"160px\">\n <Select\n label=\"Custom Field\"\n selectionMode=\"single\"\n size=\"small\"\n value={values.customField}\n onChange={value => update('customField', value?.toString() ?? '')}\n placeholder=\"All\"\n options={customFieldOptions}\n />\n </Box>\n <Box width=\"160px\">\n <Select\n label=\"Entity Path\"\n selectionMode=\"single\"\n size=\"small\"\n value={values.entityPath}\n onChange={value => update('entityPath', value?.toString() ?? '')}\n placeholder=\"All\"\n options={entityPathOptions}\n />\n </Box>\n <Box width=\"160px\">\n <Select\n label=\"Service\"\n selectionMode=\"single\"\n size=\"small\"\n value={values.service}\n onChange={value => update('service', value?.toString() ?? '')}\n placeholder=\"All\"\n options={serviceOptions}\n />\n </Box>\n </Flex>\n <Flex align=\"end\" gap=\"3\">\n <Button\n variant=\"secondary\"\n size=\"small\"\n iconStart={<Refresh fontSize=\"small\" />}\n onClick={onRefresh}\n >\n Refresh\n </Button>\n <Button\n variant=\"secondary\"\n size=\"small\"\n iconStart={<FileDownload fontSize=\"small\" />}\n onClick={onExport}\n isDisabled={exportDisabled}\n >\n Export CSV\n </Button>\n </Flex>\n </Flex>\n );\n};\n"],"names":[],"mappings":"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"}
@@ -0,0 +1,285 @@
1
+ import { jsx, jsxs } from 'react/jsx-runtime';
2
+ import { useState, useMemo } from 'react';
3
+ import { useQuery } from '@tanstack/react-query';
4
+ import { useTable, CellText, Flex, Table, Text } from '@backstage/ui';
5
+ import { makeStyles, Typography } from '@material-ui/core';
6
+ import { useApi } from '@backstage/core-plugin-api';
7
+ import { pagerDutyApiRef } from '../../../api/client.esm.js';
8
+ import { TableSkeleton } from '../MappingsTable/TableSkeleton.esm.js';
9
+ import { useAccountContext } from '../AccountContext.esm.js';
10
+ import { EMPTY_SYNC_LOG_FILTERS, SyncLogsFilters } from './SyncLogsFilters.esm.js';
11
+
12
+ const useStyles = makeStyles((theme) => ({
13
+ emptyState: {
14
+ padding: theme.spacing(6),
15
+ width: "100%",
16
+ textAlign: "center"
17
+ },
18
+ severityBadge: {
19
+ display: "inline-block",
20
+ padding: "2px 8px",
21
+ borderRadius: "4px",
22
+ fontSize: "12px",
23
+ fontWeight: 400,
24
+ border: "1px solid"
25
+ },
26
+ severityWarning: {
27
+ backgroundColor: "#fff1e1",
28
+ borderColor: "#e08824",
29
+ color: "#bb6b10"
30
+ },
31
+ severityError: {
32
+ backgroundColor: "#fde8e8",
33
+ borderColor: "#d92626",
34
+ color: "#a01b1b"
35
+ },
36
+ severityInfo: {
37
+ backgroundColor: "#e8f0fe",
38
+ borderColor: "#3b82f6",
39
+ color: "#1e63c7"
40
+ },
41
+ tableWidth: {
42
+ width: "100%"
43
+ }
44
+ }));
45
+ const ERROR_CODES_ERROR = /* @__PURE__ */ new Set([
46
+ "PD_API_ERROR"
47
+ ]);
48
+ const INFO_CODES = /* @__PURE__ */ new Set([
49
+ "SYNC_SUCCESS"
50
+ ]);
51
+ const getSeverity = (errorCode) => {
52
+ if (INFO_CODES.has(errorCode)) {
53
+ return "info";
54
+ }
55
+ if (ERROR_CODES_ERROR.has(errorCode) || errorCode.toLowerCase().includes("error")) {
56
+ return "error";
57
+ }
58
+ return "warning";
59
+ };
60
+ const formatTimestamp = (timestamp) => {
61
+ const d = new Date(timestamp);
62
+ return d.toLocaleString([], {
63
+ year: "numeric",
64
+ month: "2-digit",
65
+ day: "2-digit",
66
+ hour: "2-digit",
67
+ minute: "2-digit",
68
+ second: "2-digit"
69
+ });
70
+ };
71
+ const escapeCsv = (value) => {
72
+ if (/[",\n]/.test(value)) {
73
+ return `"${value.replace(/"/g, '""')}"`;
74
+ }
75
+ return value;
76
+ };
77
+ const downloadCsv = (logs) => {
78
+ const header = ["Timestamp", "Severity", "Custom Field", "Entity Path", "Service", "Message"];
79
+ const rows = logs.map((l) => [
80
+ new Date(l.timestamp).toISOString(),
81
+ getSeverity(l.errorCode),
82
+ l.customFieldName,
83
+ l.entityPath,
84
+ l.serviceName,
85
+ l.errorMessage
86
+ ]);
87
+ const csv = [header, ...rows].map((row) => row.map((cell) => escapeCsv(String(cell))).join(",")).join("\n");
88
+ const blob = new Blob([csv], { type: "text/csv;charset=utf-8;" });
89
+ const url = URL.createObjectURL(blob);
90
+ const link = document.createElement("a");
91
+ link.href = url;
92
+ link.download = `sync-logs-${(/* @__PURE__ */ new Date()).toISOString().slice(0, 10)}.csv`;
93
+ document.body.appendChild(link);
94
+ link.click();
95
+ document.body.removeChild(link);
96
+ URL.revokeObjectURL(url);
97
+ };
98
+ const SeverityBadge = ({ severity }) => {
99
+ const classes = useStyles();
100
+ const config = {
101
+ info: { label: "Info", className: classes.severityInfo },
102
+ warning: { label: "Warning", className: classes.severityWarning },
103
+ error: { label: "Error", className: classes.severityError }
104
+ };
105
+ const { label, className } = config[severity];
106
+ return /* @__PURE__ */ jsx(
107
+ Typography,
108
+ {
109
+ component: "span",
110
+ className: `${classes.severityBadge} ${className}`,
111
+ children: label
112
+ }
113
+ );
114
+ };
115
+ const PAGE_SIZE = 20;
116
+ const EXPORT_LIMIT = 1e4;
117
+ const filtersToApi = (values) => {
118
+ const result = {};
119
+ if (values.search.trim()) result.search = values.search.trim();
120
+ if (values.severity === "error" || values.severity === "warning" || values.severity === "info") {
121
+ result.severity = values.severity;
122
+ }
123
+ if (values.customField) result.customFieldName = values.customField;
124
+ if (values.entityPath) result.entityPath = values.entityPath;
125
+ if (values.service) result.serviceName = values.service;
126
+ return result;
127
+ };
128
+ const toOption = (v) => ({ value: v, label: v });
129
+ const SyncLogsTab = () => {
130
+ const classes = useStyles();
131
+ const pagerDutyApi = useApi(pagerDutyApiRef);
132
+ const { selectedAccount } = useAccountContext();
133
+ const account = selectedAccount || void 0;
134
+ const [filters, setFilters] = useState(EMPTY_SYNC_LOG_FILTERS);
135
+ const apiFilters = useMemo(() => filtersToApi(filters), [filters]);
136
+ const { data: optionsData } = useQuery({
137
+ queryKey: ["pagerduty", "syncLogs", "filterOptions", account ?? ""],
138
+ queryFn: () => pagerDutyApi.getSyncLogs(account)
139
+ });
140
+ const customFieldOptions = useMemo(
141
+ () => [
142
+ { value: "", label: "All" },
143
+ ...(optionsData?.customFieldNames ?? []).map(toOption)
144
+ ],
145
+ [optionsData]
146
+ );
147
+ const entityPathOptions = useMemo(
148
+ () => [
149
+ { value: "", label: "All" },
150
+ ...(optionsData?.entityPaths ?? []).map(toOption)
151
+ ],
152
+ [optionsData]
153
+ );
154
+ const serviceOptions = useMemo(
155
+ () => [
156
+ { value: "", label: "All" },
157
+ ...(optionsData?.serviceNames ?? []).map(toOption)
158
+ ],
159
+ [optionsData]
160
+ );
161
+ const { tableProps, reload } = useTable({
162
+ mode: "offset",
163
+ filter: apiFilters,
164
+ getData: async ({ offset, pageSize, filter }) => {
165
+ const result = await pagerDutyApi.getSyncLogs(account, {
166
+ limit: pageSize,
167
+ offset,
168
+ ...filter
169
+ });
170
+ return {
171
+ data: result.logs,
172
+ totalCount: result.total
173
+ };
174
+ },
175
+ paginationOptions: { pageSize: PAGE_SIZE, pageSizeOptions: [20, 50, 100] }
176
+ });
177
+ const columnConfig = useMemo(
178
+ () => [
179
+ {
180
+ id: "timestamp",
181
+ label: "Timestamp",
182
+ isRowHeader: true,
183
+ isSortable: false,
184
+ cell: (item) => /* @__PURE__ */ jsx(CellText, { title: formatTimestamp(item.timestamp) })
185
+ },
186
+ {
187
+ id: "severity",
188
+ label: "Severity",
189
+ isRowHeader: false,
190
+ isSortable: false,
191
+ cell: (item) => /* @__PURE__ */ jsx(
192
+ CellText,
193
+ {
194
+ title: "",
195
+ leadingIcon: /* @__PURE__ */ jsx(SeverityBadge, { severity: getSeverity(item.errorCode) })
196
+ }
197
+ )
198
+ },
199
+ {
200
+ id: "customField",
201
+ label: "Custom Field",
202
+ isRowHeader: false,
203
+ isSortable: false,
204
+ cell: (item) => /* @__PURE__ */ jsx(CellText, { title: item.customFieldName })
205
+ },
206
+ {
207
+ id: "entityPath",
208
+ label: "Entity Path",
209
+ isRowHeader: false,
210
+ isSortable: false,
211
+ cell: (item) => /* @__PURE__ */ jsx(CellText, { title: item.entityPath })
212
+ },
213
+ {
214
+ id: "service",
215
+ label: "Service",
216
+ isRowHeader: false,
217
+ isSortable: false,
218
+ cell: (item) => /* @__PURE__ */ jsx(CellText, { title: item.serviceName })
219
+ },
220
+ {
221
+ id: "message",
222
+ label: "Message",
223
+ isRowHeader: false,
224
+ isSortable: false,
225
+ cell: (item) => /* @__PURE__ */ jsx(CellText, { title: item.errorMessage })
226
+ }
227
+ ],
228
+ []
229
+ );
230
+ const [exporting, setExporting] = useState(false);
231
+ const handleExport = async () => {
232
+ setExporting(true);
233
+ try {
234
+ const result = await pagerDutyApi.getSyncLogs(account, {
235
+ limit: EXPORT_LIMIT,
236
+ offset: 0,
237
+ ...apiFilters
238
+ });
239
+ if (result.logs.length > 0) {
240
+ downloadCsv(result.logs);
241
+ }
242
+ } finally {
243
+ setExporting(false);
244
+ }
245
+ };
246
+ if (tableProps.isPending && !tableProps.data) {
247
+ return /* @__PURE__ */ jsx(TableSkeleton, {});
248
+ }
249
+ return /* @__PURE__ */ jsxs(Flex, { direction: "column", gap: "3", children: [
250
+ /* @__PURE__ */ jsx(
251
+ SyncLogsFilters,
252
+ {
253
+ values: filters,
254
+ onChange: setFilters,
255
+ customFieldOptions,
256
+ entityPathOptions,
257
+ serviceOptions,
258
+ onExport: handleExport,
259
+ exportDisabled: exporting || tableProps.data?.length === 0,
260
+ onRefresh: reload
261
+ }
262
+ ),
263
+ /* @__PURE__ */ jsx(
264
+ Table,
265
+ {
266
+ columnConfig,
267
+ ...tableProps,
268
+ emptyState: /* @__PURE__ */ jsx(
269
+ Flex,
270
+ {
271
+ direction: "column",
272
+ align: "center",
273
+ justify: "center",
274
+ className: classes.emptyState,
275
+ children: /* @__PURE__ */ jsx(Text, { color: "secondary", children: "No sync log entries found" })
276
+ }
277
+ ),
278
+ className: classes.tableWidth
279
+ }
280
+ )
281
+ ] });
282
+ };
283
+
284
+ export { SyncLogsTab };
285
+ //# sourceMappingURL=SyncLogsTab.esm.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SyncLogsTab.esm.js","sources":["../../../../src/components/PagerDutyPage/CustomFields/SyncLogsTab.tsx"],"sourcesContent":["import { useMemo, useState } from 'react';\nimport { useQuery } from '@tanstack/react-query';\nimport {\n CellText,\n Flex,\n Table,\n Text,\n useTable,\n type ColumnConfig,\n} from '@backstage/ui';\nimport { Typography, makeStyles } from '@material-ui/core';\nimport { useApi } from '@backstage/core-plugin-api';\nimport { pagerDutyApiRef } from '../../../api';\nimport {\n CustomFieldSyncLog,\n CustomFieldSyncLogFilters,\n} from '@pagerduty/backstage-plugin-common';\nimport { TableSkeleton } from '../MappingsTable/TableSkeleton';\nimport { useAccountContext } from '../AccountContext';\nimport {\n SyncLogsFilters,\n SyncLogsFilterValues,\n EMPTY_SYNC_LOG_FILTERS,\n} from './SyncLogsFilters';\n\nconst useStyles = makeStyles(theme => ({\n emptyState: {\n padding: theme.spacing(6),\n width: '100%',\n textAlign: 'center' as const,\n },\n severityBadge: {\n display: 'inline-block',\n padding: '2px 8px',\n borderRadius: '4px',\n fontSize: '12px',\n fontWeight: 400,\n border: '1px solid',\n },\n severityWarning: {\n backgroundColor: '#fff1e1',\n borderColor: '#e08824',\n color: '#bb6b10',\n },\n severityError: {\n backgroundColor: '#fde8e8',\n borderColor: '#d92626',\n color: '#a01b1b',\n },\n severityInfo: {\n backgroundColor: '#e8f0fe',\n borderColor: '#3b82f6',\n color: '#1e63c7',\n },\n tableWidth: {\n width: '100%'\n }\n}));\n\ntype Severity = 'info' | 'warning' | 'error';\n\nconst ERROR_CODES_ERROR: ReadonlySet<string> = new Set([\n 'PD_API_ERROR',\n]);\n\nconst INFO_CODES: ReadonlySet<string> = new Set([\n 'SYNC_SUCCESS',\n]);\n\nconst getSeverity = (errorCode: string): Severity => {\n // Info is checked first so a success code can never be mistaken for an\n // error/warning, mirroring the backend's three-way derivation.\n if (INFO_CODES.has(errorCode)) {\n return 'info';\n }\n if (ERROR_CODES_ERROR.has(errorCode) || errorCode.toLowerCase().includes('error')) {\n return 'error';\n }\n return 'warning';\n};\n\nconst formatTimestamp = (timestamp: Date) => {\n const d = new Date(timestamp);\n return d.toLocaleString([], {\n year: 'numeric',\n month: '2-digit',\n day: '2-digit',\n hour: '2-digit',\n minute: '2-digit',\n second: '2-digit',\n });\n};\n\nconst escapeCsv = (value: string) => {\n if (/[\",\\n]/.test(value)) {\n return `\"${value.replace(/\"/g, '\"\"')}\"`;\n }\n return value;\n};\n\nconst downloadCsv = (logs: CustomFieldSyncLog[]) => {\n const header = ['Timestamp', 'Severity', 'Custom Field', 'Entity Path', 'Service', 'Message'];\n const rows = logs.map(l => [\n new Date(l.timestamp).toISOString(),\n getSeverity(l.errorCode),\n l.customFieldName,\n l.entityPath,\n l.serviceName,\n l.errorMessage,\n ]);\n const csv = [header, ...rows]\n .map(row => row.map(cell => escapeCsv(String(cell))).join(','))\n .join('\\n');\n\n const blob = new Blob([csv], { type: 'text/csv;charset=utf-8;' });\n const url = URL.createObjectURL(blob);\n const link = document.createElement('a');\n link.href = url;\n link.download = `sync-logs-${new Date().toISOString().slice(0, 10)}.csv`;\n document.body.appendChild(link);\n link.click();\n document.body.removeChild(link);\n URL.revokeObjectURL(url);\n};\n\nconst SeverityBadge = ({ severity }: { severity: Severity }) => {\n const classes = useStyles();\n const config: Record<Severity, { label: string; className: string }> = {\n info: { label: 'Info', className: classes.severityInfo },\n warning: { label: 'Warning', className: classes.severityWarning },\n error: { label: 'Error', className: classes.severityError },\n };\n const { label, className } = config[severity];\n return (\n <Typography\n component=\"span\"\n className={`${classes.severityBadge} ${className}`}\n >\n {label}\n </Typography>\n );\n};\n\nconst PAGE_SIZE = 20;\nconst EXPORT_LIMIT = 10000;\n\nconst filtersToApi = (values: SyncLogsFilterValues): CustomFieldSyncLogFilters => {\n const result: CustomFieldSyncLogFilters = {};\n if (values.search.trim()) result.search = values.search.trim();\n if (\n values.severity === 'error' ||\n values.severity === 'warning' ||\n values.severity === 'info'\n ) {\n result.severity = values.severity;\n }\n if (values.customField) result.customFieldName = values.customField;\n if (values.entityPath) result.entityPath = values.entityPath;\n if (values.service) result.serviceName = values.service;\n return result;\n};\n\nconst toOption = (v: string) => ({ value: v, label: v });\n\n/** @public */\nexport const SyncLogsTab = () => {\n const classes = useStyles();\n const pagerDutyApi = useApi(pagerDutyApiRef);\n const { selectedAccount } = useAccountContext();\n const account = selectedAccount || undefined;\n\n const [filters, setFilters] = useState<SyncLogsFilterValues>(EMPTY_SYNC_LOG_FILTERS);\n\n const apiFilters = useMemo(() => filtersToApi(filters), [filters]);\n\n const { data: optionsData } = useQuery({\n queryKey: ['pagerduty', 'syncLogs', 'filterOptions', account ?? ''],\n queryFn: () => pagerDutyApi.getSyncLogs(account),\n });\n\n const customFieldOptions = useMemo(\n () => [\n { value: '', label: 'All' },\n ...(optionsData?.customFieldNames ?? []).map(toOption),\n ],\n [optionsData],\n );\n const entityPathOptions = useMemo(\n () => [\n { value: '', label: 'All' },\n ...(optionsData?.entityPaths ?? []).map(toOption),\n ],\n [optionsData],\n );\n const serviceOptions = useMemo(\n () => [\n { value: '', label: 'All' },\n ...(optionsData?.serviceNames ?? []).map(toOption),\n ],\n [optionsData],\n );\n\n const { tableProps, reload } = useTable<CustomFieldSyncLog, CustomFieldSyncLogFilters>({\n mode: 'offset',\n filter: apiFilters,\n getData: async ({ offset, pageSize, filter }) => {\n const result = await pagerDutyApi.getSyncLogs(account, {\n limit: pageSize,\n offset,\n ...filter,\n });\n return {\n data: result.logs,\n totalCount: result.total,\n };\n },\n paginationOptions: { pageSize: PAGE_SIZE, pageSizeOptions: [20, 50, 100] },\n });\n\n const columnConfig: ColumnConfig<CustomFieldSyncLog>[] = useMemo(\n () => [\n {\n id: 'timestamp',\n label: 'Timestamp',\n isRowHeader: true,\n isSortable: false,\n cell: item => <CellText title={formatTimestamp(item.timestamp)} />,\n },\n {\n id: 'severity',\n label: 'Severity',\n isRowHeader: false,\n isSortable: false,\n cell: item => (\n <CellText\n title=\"\"\n leadingIcon={<SeverityBadge severity={getSeverity(item.errorCode)} />}\n />\n ),\n },\n {\n id: 'customField',\n label: 'Custom Field',\n isRowHeader: false,\n isSortable: false,\n cell: item => <CellText title={item.customFieldName} />,\n },\n {\n id: 'entityPath',\n label: 'Entity Path',\n isRowHeader: false,\n isSortable: false,\n cell: item => <CellText title={item.entityPath} />,\n },\n {\n id: 'service',\n label: 'Service',\n isRowHeader: false,\n isSortable: false,\n cell: item => <CellText title={item.serviceName} />,\n },\n {\n id: 'message',\n label: 'Message',\n isRowHeader: false,\n isSortable: false,\n cell: item => <CellText title={item.errorMessage} />,\n },\n ],\n [],\n );\n\n const [exporting, setExporting] = useState(false);\n\n const handleExport = async () => {\n setExporting(true);\n try {\n const result = await pagerDutyApi.getSyncLogs(account, {\n limit: EXPORT_LIMIT,\n offset: 0,\n ...apiFilters,\n });\n if (result.logs.length > 0) {\n downloadCsv(result.logs);\n }\n } finally {\n setExporting(false);\n }\n };\n\n if (tableProps.isPending && !tableProps.data) {\n return <TableSkeleton />;\n }\n\n return (\n <Flex direction=\"column\" gap=\"3\">\n <SyncLogsFilters\n values={filters}\n onChange={setFilters}\n customFieldOptions={customFieldOptions}\n entityPathOptions={entityPathOptions}\n serviceOptions={serviceOptions}\n onExport={handleExport}\n exportDisabled={exporting || tableProps.data?.length === 0}\n onRefresh={reload}\n />\n\n <Table\n columnConfig={columnConfig}\n {...tableProps}\n emptyState={\n <Flex\n direction=\"column\"\n align=\"center\"\n justify=\"center\"\n className={classes.emptyState}\n >\n <Text color=\"secondary\">No sync log entries found</Text>\n </Flex>\n }\n className={classes.tableWidth}\n />\n </Flex>\n );\n};\n"],"names":[],"mappings":"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"}
@@ -0,0 +1,13 @@
1
+ const toFieldErrors = (message) => {
2
+ const lower = message.toLowerCase();
3
+ if (lower.includes("name") && lower.includes("already exists")) {
4
+ return { name: "Entered Name matches one already in use. Please make changes to continue." };
5
+ }
6
+ if (lower.includes("entity path") && lower.includes("already")) {
7
+ return { entityPath: "Entered Entity Path matches one already in use. Please make changes to continue." };
8
+ }
9
+ return { general: message };
10
+ };
11
+
12
+ export { toFieldErrors };
13
+ //# sourceMappingURL=customFieldErrors.esm.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"customFieldErrors.esm.js","sources":["../../../../src/components/PagerDutyPage/CustomFields/customFieldErrors.ts"],"sourcesContent":["import { FieldErrors } from '../CustomFieldModal';\n\nexport const toFieldErrors = (message: string): FieldErrors => {\n const lower = message.toLowerCase();\n if (lower.includes('name') && lower.includes('already exists')) {\n return { name: 'Entered Name matches one already in use. Please make changes to continue.' };\n }\n if (lower.includes('entity path') && lower.includes('already')) {\n return { entityPath: 'Entered Entity Path matches one already in use. Please make changes to continue.' };\n }\n return { general: message };\n};\n"],"names":[],"mappings":"AAEO,MAAM,aAAA,GAAgB,CAAC,OAAA,KAAiC;AAC7D,EAAA,MAAM,KAAA,GAAQ,QAAQ,WAAA,EAAY;AAClC,EAAA,IAAI,MAAM,QAAA,CAAS,MAAM,KAAK,KAAA,CAAM,QAAA,CAAS,gBAAgB,CAAA,EAAG;AAC9D,IAAA,OAAO,EAAE,MAAM,2EAAA,EAA4E;AAAA,EAC7F;AACA,EAAA,IAAI,MAAM,QAAA,CAAS,aAAa,KAAK,KAAA,CAAM,QAAA,CAAS,SAAS,CAAA,EAAG;AAC9D,IAAA,OAAO,EAAE,YAAY,kFAAA,EAAmF;AAAA,EAC1G;AACA,EAAA,OAAO,EAAE,SAAS,OAAA,EAAQ;AAC5B;;;;"}