@backstage/plugin-catalog-unprocessed-entities 0.2.3 → 0.2.4-next.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/CHANGELOG.md CHANGED
@@ -1,5 +1,15 @@
1
1
  # @backstage/plugin-catalog-unprocessed-entities
2
2
 
3
+ ## 0.2.4-next.0
4
+
5
+ ### Patch Changes
6
+
7
+ - Updated dependencies
8
+ - @backstage/catalog-model@1.5.0-next.0
9
+ - @backstage/core-components@0.14.5-next.0
10
+ - @backstage/core-plugin-api@1.9.2
11
+ - @backstage/errors@1.2.4
12
+
3
13
  ## 0.2.3
4
14
 
5
15
  ### Patch Changes
@@ -0,0 +1,34 @@
1
+ import { createApiRef } from '@backstage/core-plugin-api';
2
+ import { ResponseError } from '@backstage/errors';
3
+
4
+ const catalogUnprocessedEntitiesApiRef = createApiRef({
5
+ id: "plugin.catalog-unprocessed-entities.service"
6
+ });
7
+ class CatalogUnprocessedEntitiesClient {
8
+ constructor(discovery, fetchApi) {
9
+ this.discovery = discovery;
10
+ this.fetchApi = fetchApi;
11
+ }
12
+ async fetch(path, init) {
13
+ const url = await this.discovery.getBaseUrl("catalog");
14
+ const resp = await this.fetchApi.fetch(`${url}/${path}`, init);
15
+ if (!resp.ok) {
16
+ throw await ResponseError.fromResponse(resp);
17
+ }
18
+ return resp.status === 204 ? resp : await resp.json();
19
+ }
20
+ async pending() {
21
+ return await this.fetch("entities/unprocessed/pending");
22
+ }
23
+ async failed() {
24
+ return await this.fetch("entities/unprocessed/failed");
25
+ }
26
+ async delete(entityId) {
27
+ await this.fetch(`entities/unprocessed/delete/${entityId}`, {
28
+ method: "DELETE"
29
+ });
30
+ }
31
+ }
32
+
33
+ export { CatalogUnprocessedEntitiesClient, catalogUnprocessedEntitiesApiRef };
34
+ //# sourceMappingURL=index.esm.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.esm.js","sources":["../../src/api/index.ts"],"sourcesContent":["/*\n * Copyright 2023 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nimport {\n DiscoveryApi,\n createApiRef,\n FetchApi,\n} from '@backstage/core-plugin-api';\nimport { ResponseError } from '@backstage/errors';\nimport { UnprocessedEntity } from '../types';\n\n/**\n * {@link @backstage/core-plugin-api#ApiRef} for the {@link CatalogUnprocessedEntitiesApi}\n *\n * @public\n */\nexport const catalogUnprocessedEntitiesApiRef =\n createApiRef<CatalogUnprocessedEntitiesApi>({\n id: 'plugin.catalog-unprocessed-entities.service',\n });\n\n/**\n * Response expected by the {@link CatalogUnprocessedEntitiesApi}\n *\n * @public\n */\nexport type CatalogUnprocessedEntitiesApiResponse = {\n entities: UnprocessedEntity[];\n};\n\n/**\n * Interface for the CatalogUnprocessedEntitiesApi.\n *\n * @public\n */\nexport interface CatalogUnprocessedEntitiesApi {\n /**\n * Returns a list of entities with state 'pending'\n */\n pending(): Promise<CatalogUnprocessedEntitiesApiResponse>;\n /**\n * Returns a list of entities with state 'failed'\n */\n failed(): Promise<CatalogUnprocessedEntitiesApiResponse>;\n /**\n * Deletes an entity from the refresh_state table\n */\n delete(entityId: string): Promise<void>;\n}\n\n/**\n * Default API implementation for the Catalog Unprocessed Entities plugin\n *\n * @public\n */\nexport class CatalogUnprocessedEntitiesClient\n implements CatalogUnprocessedEntitiesApi\n{\n constructor(public discovery: DiscoveryApi, public fetchApi: FetchApi) {}\n\n private async fetch<T>(path: string, init?: RequestInit): Promise<T> {\n const url = await this.discovery.getBaseUrl('catalog');\n const resp = await this.fetchApi.fetch(`${url}/${path}`, init);\n\n if (!resp.ok) {\n throw await ResponseError.fromResponse(resp);\n }\n\n return resp.status === 204 ? (resp as T) : await resp.json();\n }\n\n async pending(): Promise<CatalogUnprocessedEntitiesApiResponse> {\n return await this.fetch('entities/unprocessed/pending');\n }\n\n async failed(): Promise<CatalogUnprocessedEntitiesApiResponse> {\n return await this.fetch('entities/unprocessed/failed');\n }\n\n async delete(entityId: string): Promise<void> {\n await this.fetch(`entities/unprocessed/delete/${entityId}`, {\n method: 'DELETE',\n });\n }\n}\n"],"names":[],"mappings":";;;AA4BO,MAAM,mCACX,YAA4C,CAAA;AAAA,EAC1C,EAAI,EAAA,6CAAA;AACN,CAAC,EAAA;AAoCI,MAAM,gCAEb,CAAA;AAAA,EACE,WAAA,CAAmB,WAAgC,QAAoB,EAAA;AAApD,IAAA,IAAA,CAAA,SAAA,GAAA,SAAA,CAAA;AAAgC,IAAA,IAAA,CAAA,QAAA,GAAA,QAAA,CAAA;AAAA,GAAqB;AAAA,EAExE,MAAc,KAAS,CAAA,IAAA,EAAc,IAAgC,EAAA;AACnE,IAAA,MAAM,GAAM,GAAA,MAAM,IAAK,CAAA,SAAA,CAAU,WAAW,SAAS,CAAA,CAAA;AACrD,IAAM,MAAA,IAAA,GAAO,MAAM,IAAA,CAAK,QAAS,CAAA,KAAA,CAAM,GAAG,GAAG,CAAA,CAAA,EAAI,IAAI,CAAA,CAAA,EAAI,IAAI,CAAA,CAAA;AAE7D,IAAI,IAAA,CAAC,KAAK,EAAI,EAAA;AACZ,MAAM,MAAA,MAAM,aAAc,CAAA,YAAA,CAAa,IAAI,CAAA,CAAA;AAAA,KAC7C;AAEA,IAAA,OAAO,KAAK,MAAW,KAAA,GAAA,GAAO,IAAa,GAAA,MAAM,KAAK,IAAK,EAAA,CAAA;AAAA,GAC7D;AAAA,EAEA,MAAM,OAA0D,GAAA;AAC9D,IAAO,OAAA,MAAM,IAAK,CAAA,KAAA,CAAM,8BAA8B,CAAA,CAAA;AAAA,GACxD;AAAA,EAEA,MAAM,MAAyD,GAAA;AAC7D,IAAO,OAAA,MAAM,IAAK,CAAA,KAAA,CAAM,6BAA6B,CAAA,CAAA;AAAA,GACvD;AAAA,EAEA,MAAM,OAAO,QAAiC,EAAA;AAC5C,IAAA,MAAM,IAAK,CAAA,KAAA,CAAM,CAA+B,4BAAA,EAAA,QAAQ,CAAI,CAAA,EAAA;AAAA,MAC1D,MAAQ,EAAA,QAAA;AAAA,KACT,CAAA,CAAA;AAAA,GACH;AACF;;;;"}
@@ -0,0 +1,60 @@
1
+ import React, { useState } from 'react';
2
+ import Dialog from '@material-ui/core/Dialog';
3
+ import DialogContent from '@material-ui/core/DialogContent';
4
+ import DialogTitle from '@material-ui/core/DialogTitle';
5
+ import IconButton from '@material-ui/core/IconButton';
6
+ import { makeStyles, createStyles } from '@material-ui/core/styles';
7
+ import CloseIcon from '@material-ui/icons/Close';
8
+ import DescriptionIcon from '@material-ui/icons/Description';
9
+ import { CodeSnippet } from '@backstage/core-components';
10
+
11
+ const useStyles = makeStyles(
12
+ (theme) => createStyles({
13
+ closeButton: {
14
+ position: "absolute",
15
+ right: theme.spacing(1),
16
+ top: theme.spacing(1),
17
+ color: theme.palette.grey[500]
18
+ },
19
+ entity: {
20
+ overflow: "scroll",
21
+ width: "100%"
22
+ },
23
+ codeBox: {
24
+ border: "1px solid black",
25
+ padding: "1em"
26
+ }
27
+ })
28
+ );
29
+ const EntityDialog = ({ entity }) => {
30
+ const [open, setOpen] = useState(false);
31
+ const classes = useStyles();
32
+ const openDialog = () => {
33
+ setOpen(true);
34
+ };
35
+ const closeDialog = () => {
36
+ setOpen(false);
37
+ };
38
+ const dialogContent = () => {
39
+ return /* @__PURE__ */ React.createElement(
40
+ CodeSnippet,
41
+ {
42
+ language: "json",
43
+ showLineNumbers: true,
44
+ text: JSON.stringify(entity, null, 4)
45
+ }
46
+ );
47
+ };
48
+ return /* @__PURE__ */ React.createElement(React.Fragment, null, /* @__PURE__ */ React.createElement(IconButton, { color: "primary", onClick: openDialog }, /* @__PURE__ */ React.createElement(DescriptionIcon, null)), /* @__PURE__ */ React.createElement(Dialog, { fullWidth: true, open, onClose: closeDialog }, /* @__PURE__ */ React.createElement(DialogTitle, { id: "dialog-title" }, /* @__PURE__ */ React.createElement(
49
+ IconButton,
50
+ {
51
+ "aria-label": "close",
52
+ className: classes.closeButton,
53
+ onClick: closeDialog
54
+ },
55
+ /* @__PURE__ */ React.createElement(CloseIcon, null)
56
+ )), /* @__PURE__ */ React.createElement(DialogContent, null, dialogContent())));
57
+ };
58
+
59
+ export { EntityDialog };
60
+ //# sourceMappingURL=EntityDialog.esm.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"EntityDialog.esm.js","sources":["../../src/components/EntityDialog.tsx"],"sourcesContent":["/*\n * Copyright 2023 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nimport React, { useState } from 'react';\n\nimport Dialog from '@material-ui/core/Dialog';\nimport DialogContent from '@material-ui/core/DialogContent';\nimport DialogTitle from '@material-ui/core/DialogTitle';\nimport IconButton from '@material-ui/core/IconButton';\nimport { makeStyles, createStyles, Theme } from '@material-ui/core/styles';\nimport CloseIcon from '@material-ui/icons/Close';\nimport DescriptionIcon from '@material-ui/icons/Description';\n\nimport { UnprocessedEntity } from './../types';\nimport { CodeSnippet } from '@backstage/core-components';\n\nconst useStyles = makeStyles((theme: Theme) =>\n createStyles({\n closeButton: {\n position: 'absolute',\n right: theme.spacing(1),\n top: theme.spacing(1),\n color: theme.palette.grey[500],\n },\n entity: {\n overflow: 'scroll',\n width: '100%',\n },\n codeBox: {\n border: '1px solid black',\n padding: '1em',\n },\n }),\n);\n\nexport const EntityDialog = ({ entity }: { entity: UnprocessedEntity }) => {\n const [open, setOpen] = useState(false);\n const classes = useStyles();\n\n const openDialog = () => {\n setOpen(true);\n };\n\n const closeDialog = () => {\n setOpen(false);\n };\n\n const dialogContent = () => {\n return (\n <CodeSnippet\n language=\"json\"\n showLineNumbers\n text={JSON.stringify(entity, null, 4)}\n />\n );\n };\n\n return (\n <>\n <IconButton color=\"primary\" onClick={openDialog}>\n <DescriptionIcon />\n </IconButton>\n <Dialog fullWidth open={open} onClose={closeDialog}>\n <DialogTitle id=\"dialog-title\">\n <IconButton\n aria-label=\"close\"\n className={classes.closeButton}\n onClick={closeDialog}\n >\n <CloseIcon />\n </IconButton>\n </DialogTitle>\n <DialogContent>{dialogContent()}</DialogContent>\n </Dialog>\n </>\n );\n};\n"],"names":[],"mappings":";;;;;;;;;;AA4BA,MAAM,SAAY,GAAA,UAAA;AAAA,EAAW,CAAC,UAC5B,YAAa,CAAA;AAAA,IACX,WAAa,EAAA;AAAA,MACX,QAAU,EAAA,UAAA;AAAA,MACV,KAAA,EAAO,KAAM,CAAA,OAAA,CAAQ,CAAC,CAAA;AAAA,MACtB,GAAA,EAAK,KAAM,CAAA,OAAA,CAAQ,CAAC,CAAA;AAAA,MACpB,KAAO,EAAA,KAAA,CAAM,OAAQ,CAAA,IAAA,CAAK,GAAG,CAAA;AAAA,KAC/B;AAAA,IACA,MAAQ,EAAA;AAAA,MACN,QAAU,EAAA,QAAA;AAAA,MACV,KAAO,EAAA,MAAA;AAAA,KACT;AAAA,IACA,OAAS,EAAA;AAAA,MACP,MAAQ,EAAA,iBAAA;AAAA,MACR,OAAS,EAAA,KAAA;AAAA,KACX;AAAA,GACD,CAAA;AACH,CAAA,CAAA;AAEO,MAAM,YAAe,GAAA,CAAC,EAAE,MAAA,EAA4C,KAAA;AACzE,EAAA,MAAM,CAAC,IAAA,EAAM,OAAO,CAAA,GAAI,SAAS,KAAK,CAAA,CAAA;AACtC,EAAA,MAAM,UAAU,SAAU,EAAA,CAAA;AAE1B,EAAA,MAAM,aAAa,MAAM;AACvB,IAAA,OAAA,CAAQ,IAAI,CAAA,CAAA;AAAA,GACd,CAAA;AAEA,EAAA,MAAM,cAAc,MAAM;AACxB,IAAA,OAAA,CAAQ,KAAK,CAAA,CAAA;AAAA,GACf,CAAA;AAEA,EAAA,MAAM,gBAAgB,MAAM;AAC1B,IACE,uBAAA,KAAA,CAAA,aAAA;AAAA,MAAC,WAAA;AAAA,MAAA;AAAA,QACC,QAAS,EAAA,MAAA;AAAA,QACT,eAAe,EAAA,IAAA;AAAA,QACf,IAAM,EAAA,IAAA,CAAK,SAAU,CAAA,MAAA,EAAQ,MAAM,CAAC,CAAA;AAAA,OAAA;AAAA,KACtC,CAAA;AAAA,GAEJ,CAAA;AAEA,EACE,uBAAA,KAAA,CAAA,aAAA,CAAA,KAAA,CAAA,QAAA,EAAA,IAAA,sCACG,UAAW,EAAA,EAAA,KAAA,EAAM,WAAU,OAAS,EAAA,UAAA,EAAA,sCAClC,eAAgB,EAAA,IAAA,CACnB,mBACC,KAAA,CAAA,aAAA,CAAA,MAAA,EAAA,EAAO,WAAS,IAAC,EAAA,IAAA,EAAY,SAAS,WACrC,EAAA,kBAAA,KAAA,CAAA,aAAA,CAAC,WAAY,EAAA,EAAA,EAAA,EAAG,cACd,EAAA,kBAAA,KAAA,CAAA,aAAA;AAAA,IAAC,UAAA;AAAA,IAAA;AAAA,MACC,YAAW,EAAA,OAAA;AAAA,MACX,WAAW,OAAQ,CAAA,WAAA;AAAA,MACnB,OAAS,EAAA,WAAA;AAAA,KAAA;AAAA,wCAER,SAAU,EAAA,IAAA,CAAA;AAAA,GAEf,CACA,kBAAA,KAAA,CAAA,aAAA,CAAC,qBAAe,aAAc,EAAE,CAClC,CACF,CAAA,CAAA;AAEJ;;;;"}
@@ -0,0 +1,150 @@
1
+ import React, { useState } from 'react';
2
+ import { Progress, ErrorPanel, Table, MarkdownContent } from '@backstage/core-components';
3
+ import Box from '@material-ui/core/Box';
4
+ import Typography from '@material-ui/core/Typography';
5
+ import IconButton from '@material-ui/core/IconButton';
6
+ import { makeStyles } from '@material-ui/core/styles';
7
+ import { useApi, alertApiRef } from '@backstage/core-plugin-api';
8
+ import { EntityDialog } from './EntityDialog.esm.js';
9
+ import { catalogUnprocessedEntitiesApiRef } from '../api/index.esm.js';
10
+ import useAsync from 'react-use/esm/useAsync';
11
+ import DeleteIcon from '@material-ui/icons/Delete';
12
+
13
+ const useStyles = makeStyles((theme) => ({
14
+ errorBox: {
15
+ color: theme.palette.status.error,
16
+ backgroundColor: theme.palette.errorBackground,
17
+ padding: "1em",
18
+ margin: "1em",
19
+ border: `1px solid ${theme.palette.status.error}`
20
+ },
21
+ errorTitle: {
22
+ width: "100%",
23
+ fontWeight: "bold"
24
+ },
25
+ successMessage: {
26
+ background: theme.palette.infoBackground,
27
+ color: theme.palette.infoText,
28
+ padding: theme.spacing(2)
29
+ }
30
+ }));
31
+ const RenderErrorContext = ({
32
+ error,
33
+ rowData
34
+ }) => {
35
+ var _a;
36
+ if (error.message.includes("tags.")) {
37
+ return /* @__PURE__ */ React.createElement(React.Fragment, null, /* @__PURE__ */ React.createElement(Typography, null, "Tags"), /* @__PURE__ */ React.createElement("ul", null, (_a = rowData.unprocessed_entity.metadata.tags) == null ? void 0 : _a.map((t) => /* @__PURE__ */ React.createElement("li", null, t))));
38
+ }
39
+ if (error.message.includes("metadata.name")) {
40
+ return /* @__PURE__ */ React.createElement(React.Fragment, null, /* @__PURE__ */ React.createElement(Typography, null, "Name"), /* @__PURE__ */ React.createElement(Typography, { variant: "caption" }, rowData.unprocessed_entity.metadata.name));
41
+ }
42
+ return null;
43
+ };
44
+ const FailedEntities = () => {
45
+ var _a;
46
+ const classes = useStyles();
47
+ const unprocessedApi = useApi(catalogUnprocessedEntitiesApiRef);
48
+ const {
49
+ loading,
50
+ error,
51
+ value: data
52
+ } = useAsync(async () => await unprocessedApi.failed());
53
+ const [, setSelectedSearchTerm] = useState("");
54
+ const unprocessedEntityApi = useApi(catalogUnprocessedEntitiesApiRef);
55
+ const alertApi = useApi(alertApiRef);
56
+ if (loading) {
57
+ return /* @__PURE__ */ React.createElement(Progress, null);
58
+ }
59
+ if (error) {
60
+ return /* @__PURE__ */ React.createElement(ErrorPanel, { error });
61
+ }
62
+ const handleDelete = async ({
63
+ entityId,
64
+ entityRef
65
+ }) => {
66
+ try {
67
+ await unprocessedEntityApi.delete(entityId);
68
+ alertApi.post({
69
+ message: `Entity ${entityRef} has been deleted`,
70
+ severity: "success"
71
+ });
72
+ } catch (e) {
73
+ alertApi.post({
74
+ message: `Ran into an issue when deleting ${entityRef}. Please try again later.`,
75
+ severity: "error"
76
+ });
77
+ }
78
+ };
79
+ const columns = [
80
+ {
81
+ title: /* @__PURE__ */ React.createElement(Typography, null, "entityRef"),
82
+ sorting: true,
83
+ field: "entity_ref",
84
+ customFilterAndSearch: (query, row) => row.entity_ref.toLocaleUpperCase("en-US").includes(query.toLocaleUpperCase("en-US")),
85
+ render: (rowData) => rowData.entity_ref
86
+ },
87
+ {
88
+ title: /* @__PURE__ */ React.createElement(Typography, null, "Kind"),
89
+ sorting: true,
90
+ field: "kind",
91
+ render: (rowData) => rowData.unprocessed_entity.kind
92
+ },
93
+ {
94
+ title: /* @__PURE__ */ React.createElement(Typography, null, "Owner"),
95
+ sorting: true,
96
+ field: "unprocessed_entity.spec.owner",
97
+ render: (rowData) => {
98
+ var _a2;
99
+ return ((_a2 = rowData.unprocessed_entity.spec) == null ? void 0 : _a2.owner) || "unknown";
100
+ }
101
+ },
102
+ {
103
+ title: /* @__PURE__ */ React.createElement(Typography, null, "Raw"),
104
+ sorting: false,
105
+ render: (rowData) => /* @__PURE__ */ React.createElement(EntityDialog, { entity: rowData })
106
+ },
107
+ {
108
+ title: /* @__PURE__ */ React.createElement(Typography, null, "Actions"),
109
+ render: (rowData) => {
110
+ const { entity_id, entity_ref } = rowData;
111
+ return /* @__PURE__ */ React.createElement(
112
+ IconButton,
113
+ {
114
+ "aria-label": "delete",
115
+ onClick: async () => await handleDelete({
116
+ entityId: entity_id,
117
+ entityRef: entity_ref
118
+ })
119
+ },
120
+ /* @__PURE__ */ React.createElement(DeleteIcon, { fontSize: "small", "data-testid": "delete-icon" })
121
+ );
122
+ }
123
+ }
124
+ ];
125
+ return /* @__PURE__ */ React.createElement(
126
+ Table,
127
+ {
128
+ options: { pageSize: 20, search: true },
129
+ columns,
130
+ data: (_a = data == null ? void 0 : data.entities) != null ? _a : [],
131
+ emptyContent: /* @__PURE__ */ React.createElement(Typography, { className: classes.successMessage }, "No failed entities found"),
132
+ onSearchChange: (searchTerm) => setSelectedSearchTerm(searchTerm),
133
+ detailPanel: ({ rowData }) => {
134
+ const errors = rowData.errors;
135
+ return /* @__PURE__ */ React.createElement(React.Fragment, null, errors == null ? void 0 : errors.map((e, idx) => {
136
+ return /* @__PURE__ */ React.createElement(Box, { key: idx, className: classes.errorBox }, /* @__PURE__ */ React.createElement(Typography, { className: classes.errorTitle }, e.name), /* @__PURE__ */ React.createElement(MarkdownContent, { content: e.message }), /* @__PURE__ */ React.createElement(
137
+ RenderErrorContext,
138
+ {
139
+ error: e,
140
+ rowData
141
+ }
142
+ ));
143
+ }));
144
+ }
145
+ }
146
+ );
147
+ };
148
+
149
+ export { FailedEntities };
150
+ //# sourceMappingURL=FailedEntities.esm.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"FailedEntities.esm.js","sources":["../../src/components/FailedEntities.tsx"],"sourcesContent":["/*\n * Copyright 2023 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nimport React, { useState } from 'react';\n\nimport {\n ErrorPanel,\n MarkdownContent,\n Progress,\n Table,\n TableColumn,\n} from '@backstage/core-components';\n\nimport Box from '@material-ui/core/Box';\nimport Typography from '@material-ui/core/Typography';\nimport IconButton from '@material-ui/core/IconButton';\nimport { Theme, makeStyles } from '@material-ui/core/styles';\nimport { alertApiRef, useApi } from '@backstage/core-plugin-api';\n\nimport { UnprocessedEntity } from '../types';\nimport { EntityDialog } from './EntityDialog';\nimport { catalogUnprocessedEntitiesApiRef } from '../api';\nimport useAsync from 'react-use/esm/useAsync';\nimport DeleteIcon from '@material-ui/icons/Delete';\n\nconst useStyles = makeStyles((theme: Theme) => ({\n errorBox: {\n color: theme.palette.status.error,\n backgroundColor: theme.palette.errorBackground,\n padding: '1em',\n margin: '1em',\n border: `1px solid ${theme.palette.status.error}`,\n },\n errorTitle: {\n width: '100%',\n fontWeight: 'bold',\n },\n successMessage: {\n background: theme.palette.infoBackground,\n color: theme.palette.infoText,\n padding: theme.spacing(2),\n },\n}));\n\nconst RenderErrorContext = ({\n error,\n rowData,\n}: {\n error: { message: string };\n rowData: UnprocessedEntity;\n}) => {\n if (error.message.includes('tags.')) {\n return (\n <>\n <Typography>Tags</Typography>\n <ul>\n {rowData.unprocessed_entity.metadata.tags?.map(t => (\n <li>{t}</li>\n ))}\n </ul>\n </>\n );\n }\n\n if (error.message.includes('metadata.name')) {\n return (\n <>\n <Typography>Name</Typography>\n <Typography variant=\"caption\">\n {rowData.unprocessed_entity.metadata.name}\n </Typography>\n </>\n );\n }\n\n return null;\n};\n\nexport const FailedEntities = () => {\n const classes = useStyles();\n const unprocessedApi = useApi(catalogUnprocessedEntitiesApiRef);\n const {\n loading,\n error,\n value: data,\n } = useAsync(async () => await unprocessedApi.failed());\n const [, setSelectedSearchTerm] = useState<string>('');\n const unprocessedEntityApi = useApi(catalogUnprocessedEntitiesApiRef);\n const alertApi = useApi(alertApiRef);\n\n if (loading) {\n return <Progress />;\n }\n if (error) {\n return <ErrorPanel error={error} />;\n }\n\n const handleDelete = async ({\n entityId,\n entityRef,\n }: {\n entityId: string;\n entityRef: string;\n }) => {\n try {\n await unprocessedEntityApi.delete(entityId);\n alertApi.post({\n message: `Entity ${entityRef} has been deleted`,\n severity: 'success',\n });\n } catch (e) {\n alertApi.post({\n message: `Ran into an issue when deleting ${entityRef}. Please try again later.`,\n severity: 'error',\n });\n }\n };\n\n const columns: TableColumn[] = [\n {\n title: <Typography>entityRef</Typography>,\n sorting: true,\n field: 'entity_ref',\n customFilterAndSearch: (query, row: any) =>\n row.entity_ref\n .toLocaleUpperCase('en-US')\n .includes(query.toLocaleUpperCase('en-US')),\n render: (rowData: UnprocessedEntity | {}) =>\n (rowData as UnprocessedEntity).entity_ref,\n },\n {\n title: <Typography>Kind</Typography>,\n sorting: true,\n field: 'kind',\n render: (rowData: UnprocessedEntity | {}) =>\n (rowData as UnprocessedEntity).unprocessed_entity.kind,\n },\n {\n title: <Typography>Owner</Typography>,\n sorting: true,\n field: 'unprocessed_entity.spec.owner',\n render: (rowData: UnprocessedEntity | {}) =>\n (rowData as UnprocessedEntity).unprocessed_entity.spec?.owner ||\n 'unknown',\n },\n {\n title: <Typography>Raw</Typography>,\n sorting: false,\n render: (rowData: UnprocessedEntity | {}) => (\n <EntityDialog entity={rowData as UnprocessedEntity} />\n ),\n },\n {\n title: <Typography>Actions</Typography>,\n render: (rowData: UnprocessedEntity | {}) => {\n const { entity_id, entity_ref } = rowData as UnprocessedEntity;\n\n return (\n <IconButton\n aria-label=\"delete\"\n onClick={async () =>\n await handleDelete({\n entityId: entity_id,\n entityRef: entity_ref,\n })\n }\n >\n <DeleteIcon fontSize=\"small\" data-testid=\"delete-icon\" />\n </IconButton>\n );\n },\n },\n ];\n\n return (\n <Table\n options={{ pageSize: 20, search: true }}\n columns={columns}\n data={data?.entities ?? []}\n emptyContent={\n <Typography className={classes.successMessage}>\n No failed entities found\n </Typography>\n }\n onSearchChange={(searchTerm: string) => setSelectedSearchTerm(searchTerm)}\n detailPanel={({ rowData }) => {\n const errors = (rowData as UnprocessedEntity).errors;\n return (\n <>\n {errors?.map((e, idx) => {\n return (\n <Box key={idx} className={classes.errorBox}>\n <Typography className={classes.errorTitle}>\n {e.name}\n </Typography>\n <MarkdownContent content={e.message} />\n <RenderErrorContext\n error={e}\n rowData={rowData as UnprocessedEntity}\n />\n </Box>\n );\n })}\n </>\n );\n }}\n />\n );\n};\n"],"names":["_a"],"mappings":"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"}
@@ -0,0 +1,74 @@
1
+ import React, { useState } from 'react';
2
+ import { Progress, ErrorPanel, Table } from '@backstage/core-components';
3
+ import Typography from '@material-ui/core/Typography';
4
+ import { makeStyles } from '@material-ui/core/styles';
5
+ import { EntityDialog } from './EntityDialog.esm.js';
6
+ import { useApi } from '@backstage/core-plugin-api';
7
+ import useAsync from 'react-use/esm/useAsync';
8
+ import { catalogUnprocessedEntitiesApiRef } from '../api/index.esm.js';
9
+
10
+ const useStyles = makeStyles((theme) => ({
11
+ successMessage: {
12
+ background: theme.palette.infoBackground,
13
+ color: theme.palette.infoText,
14
+ padding: theme.spacing(2)
15
+ }
16
+ }));
17
+ const PendingEntities = () => {
18
+ const classes = useStyles();
19
+ const unprocessedApi = useApi(catalogUnprocessedEntitiesApiRef);
20
+ const {
21
+ loading,
22
+ error,
23
+ value: data
24
+ } = useAsync(async () => await unprocessedApi.pending());
25
+ const [, setSelectedSearchTerm] = useState("");
26
+ if (loading) {
27
+ return /* @__PURE__ */ React.createElement(Progress, null);
28
+ }
29
+ if (error) {
30
+ return /* @__PURE__ */ React.createElement(ErrorPanel, { error });
31
+ }
32
+ const columns = [
33
+ {
34
+ title: /* @__PURE__ */ React.createElement(Typography, null, "entityRef"),
35
+ sorting: true,
36
+ field: "entity_ref",
37
+ customFilterAndSearch: (query, row) => row.entity_ref.toLocaleUpperCase("en-US").includes(query.toLocaleUpperCase("en-US")),
38
+ render: (rowData) => rowData.entity_ref
39
+ },
40
+ {
41
+ title: /* @__PURE__ */ React.createElement(Typography, null, "Kind"),
42
+ sorting: true,
43
+ field: "kind",
44
+ render: (rowData) => rowData.unprocessed_entity.kind
45
+ },
46
+ {
47
+ title: /* @__PURE__ */ React.createElement(Typography, null, "Owner"),
48
+ sorting: true,
49
+ field: "unprocessed_entity.spec.owner",
50
+ render: (rowData) => {
51
+ var _a;
52
+ return ((_a = rowData.unprocessed_entity.spec) == null ? void 0 : _a.owner) || "unknown";
53
+ }
54
+ },
55
+ {
56
+ title: /* @__PURE__ */ React.createElement(Typography, null, "Raw"),
57
+ sorting: false,
58
+ render: (rowData) => /* @__PURE__ */ React.createElement(EntityDialog, { entity: rowData })
59
+ }
60
+ ];
61
+ return /* @__PURE__ */ React.createElement(React.Fragment, null, /* @__PURE__ */ React.createElement(
62
+ Table,
63
+ {
64
+ options: { pageSize: 20 },
65
+ columns,
66
+ data: (data == null ? void 0 : data.entities) || [],
67
+ onSearchChange: (searchTerm) => setSelectedSearchTerm(searchTerm),
68
+ emptyContent: /* @__PURE__ */ React.createElement(Typography, { className: classes.successMessage }, "No pending entities found")
69
+ }
70
+ ));
71
+ };
72
+
73
+ export { PendingEntities };
74
+ //# sourceMappingURL=PendingEntities.esm.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"PendingEntities.esm.js","sources":["../../src/components/PendingEntities.tsx"],"sourcesContent":["/*\n * Copyright 2023 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nimport React, { useState } from 'react';\n\nimport {\n ErrorPanel,\n Progress,\n TableColumn,\n Table,\n} from '@backstage/core-components';\nimport Typography from '@material-ui/core/Typography';\nimport { Theme, makeStyles } from '@material-ui/core/styles';\n\nimport { UnprocessedEntity } from '../types';\n\nimport { EntityDialog } from './EntityDialog';\nimport { useApi } from '@backstage/core-plugin-api';\nimport useAsync from 'react-use/esm/useAsync';\nimport { catalogUnprocessedEntitiesApiRef } from '../api';\n\nconst useStyles = makeStyles((theme: Theme) => ({\n successMessage: {\n background: theme.palette.infoBackground,\n color: theme.palette.infoText,\n padding: theme.spacing(2),\n },\n}));\n\nexport const PendingEntities = () => {\n const classes = useStyles();\n const unprocessedApi = useApi(catalogUnprocessedEntitiesApiRef);\n const {\n loading,\n error,\n value: data,\n } = useAsync(async () => await unprocessedApi.pending());\n const [, setSelectedSearchTerm] = useState<string>('');\n\n if (loading) {\n return <Progress />;\n }\n if (error) {\n return <ErrorPanel error={error} />;\n }\n\n const columns: TableColumn[] = [\n {\n title: <Typography>entityRef</Typography>,\n sorting: true,\n field: 'entity_ref',\n customFilterAndSearch: (query, row: any) =>\n row.entity_ref\n .toLocaleUpperCase('en-US')\n .includes(query.toLocaleUpperCase('en-US')),\n render: (rowData: UnprocessedEntity | {}) =>\n (rowData as UnprocessedEntity).entity_ref,\n },\n {\n title: <Typography>Kind</Typography>,\n sorting: true,\n field: 'kind',\n render: (rowData: UnprocessedEntity | {}) =>\n (rowData as UnprocessedEntity).unprocessed_entity.kind,\n },\n {\n title: <Typography>Owner</Typography>,\n sorting: true,\n field: 'unprocessed_entity.spec.owner',\n render: (rowData: UnprocessedEntity | {}) =>\n (rowData as UnprocessedEntity).unprocessed_entity.spec?.owner ||\n 'unknown',\n },\n {\n title: <Typography>Raw</Typography>,\n sorting: false,\n render: (rowData: UnprocessedEntity | {}) => (\n <EntityDialog entity={rowData as UnprocessedEntity} />\n ),\n },\n ];\n return (\n <>\n <Table\n options={{ pageSize: 20 }}\n columns={columns}\n data={data?.entities || []}\n onSearchChange={(searchTerm: string) =>\n setSelectedSearchTerm(searchTerm)\n }\n emptyContent={\n <Typography className={classes.successMessage}>\n No pending entities found\n </Typography>\n }\n />\n </>\n );\n};\n"],"names":[],"mappings":"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"}
@@ -0,0 +1,30 @@
1
+ import React, { useState } from 'react';
2
+ import { Page, Header, Content } from '@backstage/core-components';
3
+ import Tab from '@material-ui/core/Tab';
4
+ import { makeStyles } from '@material-ui/core/styles';
5
+ import TabContext from '@material-ui/lab/TabContext';
6
+ import TabList from '@material-ui/lab/TabList';
7
+ import TabPanel from '@material-ui/lab/TabPanel';
8
+ import { FailedEntities } from './FailedEntities.esm.js';
9
+ import { PendingEntities } from './PendingEntities.esm.js';
10
+
11
+ const useStyles = makeStyles(() => ({
12
+ tabPanel: {
13
+ paddingLeft: "0px",
14
+ paddingRight: "0px"
15
+ }
16
+ }));
17
+ const UnprocessedEntitiesContent = () => {
18
+ const classes = useStyles();
19
+ const [tab, setTab] = useState("failed");
20
+ const handleChange = (_event, tabValue) => {
21
+ setTab(tabValue);
22
+ };
23
+ return /* @__PURE__ */ React.createElement(TabContext, { value: tab }, /* @__PURE__ */ React.createElement(TabList, { onChange: handleChange }, /* @__PURE__ */ React.createElement(Tab, { label: "Failed", value: "failed" }), /* @__PURE__ */ React.createElement(Tab, { label: "Pending", value: "pending" })), /* @__PURE__ */ React.createElement(TabPanel, { value: "failed", className: classes.tabPanel }, /* @__PURE__ */ React.createElement(FailedEntities, null)), /* @__PURE__ */ React.createElement(TabPanel, { value: "pending", className: classes.tabPanel }, /* @__PURE__ */ React.createElement(PendingEntities, null)));
24
+ };
25
+ const UnprocessedEntities = () => {
26
+ return /* @__PURE__ */ React.createElement(Page, { themeId: "tool" }, /* @__PURE__ */ React.createElement(Header, { title: "Unprocessed Entities" }), /* @__PURE__ */ React.createElement(Content, null, /* @__PURE__ */ React.createElement(UnprocessedEntitiesContent, null)));
27
+ };
28
+
29
+ export { UnprocessedEntities, UnprocessedEntitiesContent };
30
+ //# sourceMappingURL=UnprocessedEntities.esm.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"UnprocessedEntities.esm.js","sources":["../../src/components/UnprocessedEntities.tsx"],"sourcesContent":["/*\n * Copyright 2023 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nimport React, { useState } from 'react';\n\nimport { Page, Header, Content } from '@backstage/core-components';\nimport Tab from '@material-ui/core/Tab';\nimport { makeStyles } from '@material-ui/core/styles';\nimport TabContext from '@material-ui/lab/TabContext';\nimport TabList from '@material-ui/lab/TabList';\nimport TabPanel from '@material-ui/lab/TabPanel';\n\nimport { FailedEntities } from './FailedEntities';\nimport { PendingEntities } from './PendingEntities';\n\nconst useStyles = makeStyles(() => ({\n tabPanel: {\n paddingLeft: '0px',\n paddingRight: '0px',\n },\n}));\n\n/** @public */\nexport const UnprocessedEntitiesContent = () => {\n const classes = useStyles();\n const [tab, setTab] = useState('failed');\n const handleChange = (_event: React.ChangeEvent<{}>, tabValue: string) => {\n setTab(tabValue);\n };\n\n return (\n <TabContext value={tab}>\n <TabList onChange={handleChange}>\n <Tab label=\"Failed\" value=\"failed\" />\n <Tab label=\"Pending\" value=\"pending\" />\n </TabList>\n <TabPanel value=\"failed\" className={classes.tabPanel}>\n <FailedEntities />\n </TabPanel>\n <TabPanel value=\"pending\" className={classes.tabPanel}>\n <PendingEntities />\n </TabPanel>\n </TabContext>\n );\n};\n\nexport const UnprocessedEntities = () => {\n return (\n <Page themeId=\"tool\">\n <Header title=\"Unprocessed Entities\" />\n <Content>\n <UnprocessedEntitiesContent />\n </Content>\n </Page>\n );\n};\n"],"names":[],"mappings":";;;;;;;;;;AA2BA,MAAM,SAAA,GAAY,WAAW,OAAO;AAAA,EAClC,QAAU,EAAA;AAAA,IACR,WAAa,EAAA,KAAA;AAAA,IACb,YAAc,EAAA,KAAA;AAAA,GAChB;AACF,CAAE,CAAA,CAAA,CAAA;AAGK,MAAM,6BAA6B,MAAM;AAC9C,EAAA,MAAM,UAAU,SAAU,EAAA,CAAA;AAC1B,EAAA,MAAM,CAAC,GAAA,EAAK,MAAM,CAAA,GAAI,SAAS,QAAQ,CAAA,CAAA;AACvC,EAAM,MAAA,YAAA,GAAe,CAAC,MAAA,EAA+B,QAAqB,KAAA;AACxE,IAAA,MAAA,CAAO,QAAQ,CAAA,CAAA;AAAA,GACjB,CAAA;AAEA,EACE,uBAAA,KAAA,CAAA,aAAA,CAAC,cAAW,KAAO,EAAA,GAAA,EAAA,sCAChB,OAAQ,EAAA,EAAA,QAAA,EAAU,gCAChB,KAAA,CAAA,aAAA,CAAA,GAAA,EAAA,EAAI,OAAM,QAAS,EAAA,KAAA,EAAM,UAAS,CACnC,kBAAA,KAAA,CAAA,aAAA,CAAC,OAAI,KAAM,EAAA,SAAA,EAAU,OAAM,SAAU,EAAA,CACvC,mBACC,KAAA,CAAA,aAAA,CAAA,QAAA,EAAA,EAAS,OAAM,QAAS,EAAA,SAAA,EAAW,QAAQ,QAC1C,EAAA,kBAAA,KAAA,CAAA,aAAA,CAAC,oBAAe,CAClB,CAAA,sCACC,QAAS,EAAA,EAAA,KAAA,EAAM,WAAU,SAAW,EAAA,OAAA,CAAQ,4BAC1C,KAAA,CAAA,aAAA,CAAA,eAAA,EAAA,IAAgB,CACnB,CACF,CAAA,CAAA;AAEJ,EAAA;AAEO,MAAM,sBAAsB,MAAM;AACvC,EAAA,uBACG,KAAA,CAAA,aAAA,CAAA,IAAA,EAAA,EAAK,OAAQ,EAAA,MAAA,EAAA,sCACX,MAAO,EAAA,EAAA,KAAA,EAAM,sBAAuB,EAAA,CAAA,kBACpC,KAAA,CAAA,aAAA,CAAA,OAAA,EAAA,IAAA,kBACE,KAAA,CAAA,aAAA,CAAA,0BAAA,EAAA,IAA2B,CAC9B,CACF,CAAA,CAAA;AAEJ;;;;"}
package/dist/index.esm.js CHANGED
@@ -1,349 +1,4 @@
1
- import { createRouteRef, createApiRef, createPlugin, createApiFactory, discoveryApiRef, fetchApiRef, createRoutableExtension, useApi, alertApiRef } from '@backstage/core-plugin-api';
2
- import { ResponseError } from '@backstage/errors';
3
- import React, { useState } from 'react';
4
- import { CodeSnippet, Progress, ErrorPanel, Table, MarkdownContent, Page, Header, Content } from '@backstage/core-components';
5
- import Tab from '@material-ui/core/Tab';
6
- import { makeStyles, createStyles } from '@material-ui/core/styles';
7
- import TabContext from '@material-ui/lab/TabContext';
8
- import TabList from '@material-ui/lab/TabList';
9
- import TabPanel from '@material-ui/lab/TabPanel';
10
- import Box from '@material-ui/core/Box';
11
- import Typography from '@material-ui/core/Typography';
12
- import IconButton from '@material-ui/core/IconButton';
13
- import Dialog from '@material-ui/core/Dialog';
14
- import DialogContent from '@material-ui/core/DialogContent';
15
- import DialogTitle from '@material-ui/core/DialogTitle';
16
- import CloseIcon from '@material-ui/icons/Close';
17
- import DescriptionIcon from '@material-ui/icons/Description';
18
- import useAsync from 'react-use/esm/useAsync';
19
- import DeleteIcon from '@material-ui/icons/Delete';
20
-
21
- const rootRouteRef = createRouteRef({
22
- id: "catalog-unprocessed-entities"
23
- });
24
-
25
- const catalogUnprocessedEntitiesApiRef = createApiRef({
26
- id: "plugin.catalog-unprocessed-entities.service"
27
- });
28
- class CatalogUnprocessedEntitiesClient {
29
- constructor(discovery, fetchApi) {
30
- this.discovery = discovery;
31
- this.fetchApi = fetchApi;
32
- }
33
- async fetch(path, init) {
34
- const url = await this.discovery.getBaseUrl("catalog");
35
- const resp = await this.fetchApi.fetch(`${url}/${path}`, init);
36
- if (!resp.ok) {
37
- throw await ResponseError.fromResponse(resp);
38
- }
39
- return resp.status === 204 ? resp : await resp.json();
40
- }
41
- async pending() {
42
- return await this.fetch("entities/unprocessed/pending");
43
- }
44
- async failed() {
45
- return await this.fetch("entities/unprocessed/failed");
46
- }
47
- async delete(entityId) {
48
- await this.fetch(`entities/unprocessed/delete/${entityId}`, {
49
- method: "DELETE"
50
- });
51
- }
52
- }
53
-
54
- const catalogUnprocessedEntitiesPlugin = createPlugin({
55
- id: "catalog-unprocessed-entities",
56
- routes: {
57
- root: rootRouteRef
58
- },
59
- apis: [
60
- createApiFactory({
61
- api: catalogUnprocessedEntitiesApiRef,
62
- deps: { discoveryApi: discoveryApiRef, fetchApi: fetchApiRef },
63
- factory: ({ discoveryApi, fetchApi }) => new CatalogUnprocessedEntitiesClient(discoveryApi, fetchApi)
64
- })
65
- ]
66
- });
67
- const CatalogUnprocessedEntitiesPage = catalogUnprocessedEntitiesPlugin.provide(
68
- createRoutableExtension({
69
- name: "CatalogUnprocessedEntitiesPage",
70
- component: () => Promise.resolve().then(function () { return UnprocessedEntities$1; }).then(
71
- (m) => m.UnprocessedEntities
72
- ),
73
- mountPoint: rootRouteRef
74
- })
75
- );
76
-
77
- const useStyles$3 = makeStyles(
78
- (theme) => createStyles({
79
- closeButton: {
80
- position: "absolute",
81
- right: theme.spacing(1),
82
- top: theme.spacing(1),
83
- color: theme.palette.grey[500]
84
- },
85
- entity: {
86
- overflow: "scroll",
87
- width: "100%"
88
- },
89
- codeBox: {
90
- border: "1px solid black",
91
- padding: "1em"
92
- }
93
- })
94
- );
95
- const EntityDialog = ({ entity }) => {
96
- const [open, setOpen] = useState(false);
97
- const classes = useStyles$3();
98
- const openDialog = () => {
99
- setOpen(true);
100
- };
101
- const closeDialog = () => {
102
- setOpen(false);
103
- };
104
- const dialogContent = () => {
105
- return /* @__PURE__ */ React.createElement(
106
- CodeSnippet,
107
- {
108
- language: "json",
109
- showLineNumbers: true,
110
- text: JSON.stringify(entity, null, 4)
111
- }
112
- );
113
- };
114
- return /* @__PURE__ */ React.createElement(React.Fragment, null, /* @__PURE__ */ React.createElement(IconButton, { color: "primary", onClick: openDialog }, /* @__PURE__ */ React.createElement(DescriptionIcon, null)), /* @__PURE__ */ React.createElement(Dialog, { fullWidth: true, open, onClose: closeDialog }, /* @__PURE__ */ React.createElement(DialogTitle, { id: "dialog-title" }, /* @__PURE__ */ React.createElement(
115
- IconButton,
116
- {
117
- "aria-label": "close",
118
- className: classes.closeButton,
119
- onClick: closeDialog
120
- },
121
- /* @__PURE__ */ React.createElement(CloseIcon, null)
122
- )), /* @__PURE__ */ React.createElement(DialogContent, null, dialogContent())));
123
- };
124
-
125
- const useStyles$2 = makeStyles((theme) => ({
126
- errorBox: {
127
- color: theme.palette.status.error,
128
- backgroundColor: theme.palette.errorBackground,
129
- padding: "1em",
130
- margin: "1em",
131
- border: `1px solid ${theme.palette.status.error}`
132
- },
133
- errorTitle: {
134
- width: "100%",
135
- fontWeight: "bold"
136
- },
137
- successMessage: {
138
- background: theme.palette.infoBackground,
139
- color: theme.palette.infoText,
140
- padding: theme.spacing(2)
141
- }
142
- }));
143
- const RenderErrorContext = ({
144
- error,
145
- rowData
146
- }) => {
147
- var _a;
148
- if (error.message.includes("tags.")) {
149
- return /* @__PURE__ */ React.createElement(React.Fragment, null, /* @__PURE__ */ React.createElement(Typography, null, "Tags"), /* @__PURE__ */ React.createElement("ul", null, (_a = rowData.unprocessed_entity.metadata.tags) == null ? void 0 : _a.map((t) => /* @__PURE__ */ React.createElement("li", null, t))));
150
- }
151
- if (error.message.includes("metadata.name")) {
152
- return /* @__PURE__ */ React.createElement(React.Fragment, null, /* @__PURE__ */ React.createElement(Typography, null, "Name"), /* @__PURE__ */ React.createElement(Typography, { variant: "caption" }, rowData.unprocessed_entity.metadata.name));
153
- }
154
- return null;
155
- };
156
- const FailedEntities = () => {
157
- var _a;
158
- const classes = useStyles$2();
159
- const unprocessedApi = useApi(catalogUnprocessedEntitiesApiRef);
160
- const {
161
- loading,
162
- error,
163
- value: data
164
- } = useAsync(async () => await unprocessedApi.failed());
165
- const [, setSelectedSearchTerm] = useState("");
166
- const unprocessedEntityApi = useApi(catalogUnprocessedEntitiesApiRef);
167
- const alertApi = useApi(alertApiRef);
168
- if (loading) {
169
- return /* @__PURE__ */ React.createElement(Progress, null);
170
- }
171
- if (error) {
172
- return /* @__PURE__ */ React.createElement(ErrorPanel, { error });
173
- }
174
- const handleDelete = async ({
175
- entityId,
176
- entityRef
177
- }) => {
178
- try {
179
- await unprocessedEntityApi.delete(entityId);
180
- alertApi.post({
181
- message: `Entity ${entityRef} has been deleted`,
182
- severity: "success"
183
- });
184
- } catch (e) {
185
- alertApi.post({
186
- message: `Ran into an issue when deleting ${entityRef}. Please try again later.`,
187
- severity: "error"
188
- });
189
- }
190
- };
191
- const columns = [
192
- {
193
- title: /* @__PURE__ */ React.createElement(Typography, null, "entityRef"),
194
- sorting: true,
195
- field: "entity_ref",
196
- customFilterAndSearch: (query, row) => row.entity_ref.toLocaleUpperCase("en-US").includes(query.toLocaleUpperCase("en-US")),
197
- render: (rowData) => rowData.entity_ref
198
- },
199
- {
200
- title: /* @__PURE__ */ React.createElement(Typography, null, "Kind"),
201
- sorting: true,
202
- field: "kind",
203
- render: (rowData) => rowData.unprocessed_entity.kind
204
- },
205
- {
206
- title: /* @__PURE__ */ React.createElement(Typography, null, "Owner"),
207
- sorting: true,
208
- field: "unprocessed_entity.spec.owner",
209
- render: (rowData) => {
210
- var _a2;
211
- return ((_a2 = rowData.unprocessed_entity.spec) == null ? void 0 : _a2.owner) || "unknown";
212
- }
213
- },
214
- {
215
- title: /* @__PURE__ */ React.createElement(Typography, null, "Raw"),
216
- sorting: false,
217
- render: (rowData) => /* @__PURE__ */ React.createElement(EntityDialog, { entity: rowData })
218
- },
219
- {
220
- title: /* @__PURE__ */ React.createElement(Typography, null, "Actions"),
221
- render: (rowData) => {
222
- const { entity_id, entity_ref } = rowData;
223
- return /* @__PURE__ */ React.createElement(
224
- IconButton,
225
- {
226
- "aria-label": "delete",
227
- onClick: async () => await handleDelete({
228
- entityId: entity_id,
229
- entityRef: entity_ref
230
- })
231
- },
232
- /* @__PURE__ */ React.createElement(DeleteIcon, { fontSize: "small", "data-testid": "delete-icon" })
233
- );
234
- }
235
- }
236
- ];
237
- return /* @__PURE__ */ React.createElement(
238
- Table,
239
- {
240
- options: { pageSize: 20, search: true },
241
- columns,
242
- data: (_a = data == null ? void 0 : data.entities) != null ? _a : [],
243
- emptyContent: /* @__PURE__ */ React.createElement(Typography, { className: classes.successMessage }, "No failed entities found"),
244
- onSearchChange: (searchTerm) => setSelectedSearchTerm(searchTerm),
245
- detailPanel: ({ rowData }) => {
246
- const errors = rowData.errors;
247
- return /* @__PURE__ */ React.createElement(React.Fragment, null, errors == null ? void 0 : errors.map((e, idx) => {
248
- return /* @__PURE__ */ React.createElement(Box, { key: idx, className: classes.errorBox }, /* @__PURE__ */ React.createElement(Typography, { className: classes.errorTitle }, e.name), /* @__PURE__ */ React.createElement(MarkdownContent, { content: e.message }), /* @__PURE__ */ React.createElement(
249
- RenderErrorContext,
250
- {
251
- error: e,
252
- rowData
253
- }
254
- ));
255
- }));
256
- }
257
- }
258
- );
259
- };
260
-
261
- const useStyles$1 = makeStyles((theme) => ({
262
- successMessage: {
263
- background: theme.palette.infoBackground,
264
- color: theme.palette.infoText,
265
- padding: theme.spacing(2)
266
- }
267
- }));
268
- const PendingEntities = () => {
269
- const classes = useStyles$1();
270
- const unprocessedApi = useApi(catalogUnprocessedEntitiesApiRef);
271
- const {
272
- loading,
273
- error,
274
- value: data
275
- } = useAsync(async () => await unprocessedApi.pending());
276
- const [, setSelectedSearchTerm] = useState("");
277
- if (loading) {
278
- return /* @__PURE__ */ React.createElement(Progress, null);
279
- }
280
- if (error) {
281
- return /* @__PURE__ */ React.createElement(ErrorPanel, { error });
282
- }
283
- const columns = [
284
- {
285
- title: /* @__PURE__ */ React.createElement(Typography, null, "entityRef"),
286
- sorting: true,
287
- field: "entity_ref",
288
- customFilterAndSearch: (query, row) => row.entity_ref.toLocaleUpperCase("en-US").includes(query.toLocaleUpperCase("en-US")),
289
- render: (rowData) => rowData.entity_ref
290
- },
291
- {
292
- title: /* @__PURE__ */ React.createElement(Typography, null, "Kind"),
293
- sorting: true,
294
- field: "kind",
295
- render: (rowData) => rowData.unprocessed_entity.kind
296
- },
297
- {
298
- title: /* @__PURE__ */ React.createElement(Typography, null, "Owner"),
299
- sorting: true,
300
- field: "unprocessed_entity.spec.owner",
301
- render: (rowData) => {
302
- var _a;
303
- return ((_a = rowData.unprocessed_entity.spec) == null ? void 0 : _a.owner) || "unknown";
304
- }
305
- },
306
- {
307
- title: /* @__PURE__ */ React.createElement(Typography, null, "Raw"),
308
- sorting: false,
309
- render: (rowData) => /* @__PURE__ */ React.createElement(EntityDialog, { entity: rowData })
310
- }
311
- ];
312
- return /* @__PURE__ */ React.createElement(React.Fragment, null, /* @__PURE__ */ React.createElement(
313
- Table,
314
- {
315
- options: { pageSize: 20 },
316
- columns,
317
- data: (data == null ? void 0 : data.entities) || [],
318
- onSearchChange: (searchTerm) => setSelectedSearchTerm(searchTerm),
319
- emptyContent: /* @__PURE__ */ React.createElement(Typography, { className: classes.successMessage }, "No pending entities found")
320
- }
321
- ));
322
- };
323
-
324
- const useStyles = makeStyles(() => ({
325
- tabPanel: {
326
- paddingLeft: "0px",
327
- paddingRight: "0px"
328
- }
329
- }));
330
- const UnprocessedEntitiesContent = () => {
331
- const classes = useStyles();
332
- const [tab, setTab] = useState("failed");
333
- const handleChange = (_event, tabValue) => {
334
- setTab(tabValue);
335
- };
336
- return /* @__PURE__ */ React.createElement(TabContext, { value: tab }, /* @__PURE__ */ React.createElement(TabList, { onChange: handleChange }, /* @__PURE__ */ React.createElement(Tab, { label: "Failed", value: "failed" }), /* @__PURE__ */ React.createElement(Tab, { label: "Pending", value: "pending" })), /* @__PURE__ */ React.createElement(TabPanel, { value: "failed", className: classes.tabPanel }, /* @__PURE__ */ React.createElement(FailedEntities, null)), /* @__PURE__ */ React.createElement(TabPanel, { value: "pending", className: classes.tabPanel }, /* @__PURE__ */ React.createElement(PendingEntities, null)));
337
- };
338
- const UnprocessedEntities = () => {
339
- return /* @__PURE__ */ React.createElement(Page, { themeId: "tool" }, /* @__PURE__ */ React.createElement(Header, { title: "Unprocessed Entities" }), /* @__PURE__ */ React.createElement(Content, null, /* @__PURE__ */ React.createElement(UnprocessedEntitiesContent, null)));
340
- };
341
-
342
- var UnprocessedEntities$1 = /*#__PURE__*/Object.freeze({
343
- __proto__: null,
344
- UnprocessedEntities: UnprocessedEntities,
345
- UnprocessedEntitiesContent: UnprocessedEntitiesContent
346
- });
347
-
348
- export { CatalogUnprocessedEntitiesPage, UnprocessedEntitiesContent, catalogUnprocessedEntitiesApiRef, catalogUnprocessedEntitiesPlugin };
1
+ export { CatalogUnprocessedEntitiesPage, catalogUnprocessedEntitiesPlugin } from './plugin.esm.js';
2
+ export { UnprocessedEntitiesContent } from './components/UnprocessedEntities.esm.js';
3
+ export { catalogUnprocessedEntitiesApiRef } from './api/index.esm.js';
349
4
  //# sourceMappingURL=index.esm.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.esm.js","sources":["../src/routes.ts","../src/api/index.ts","../src/plugin.ts","../src/components/EntityDialog.tsx","../src/components/FailedEntities.tsx","../src/components/PendingEntities.tsx","../src/components/UnprocessedEntities.tsx"],"sourcesContent":["/*\n * Copyright 2023 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nimport { createRouteRef } from '@backstage/core-plugin-api';\n\nexport const rootRouteRef = createRouteRef({\n id: 'catalog-unprocessed-entities',\n});\n","/*\n * Copyright 2023 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nimport {\n DiscoveryApi,\n createApiRef,\n FetchApi,\n} from '@backstage/core-plugin-api';\nimport { ResponseError } from '@backstage/errors';\nimport { UnprocessedEntity } from '../types';\n\n/**\n * {@link @backstage/core-plugin-api#ApiRef} for the {@link CatalogUnprocessedEntitiesApi}\n *\n * @public\n */\nexport const catalogUnprocessedEntitiesApiRef =\n createApiRef<CatalogUnprocessedEntitiesApi>({\n id: 'plugin.catalog-unprocessed-entities.service',\n });\n\n/**\n * Response expected by the {@link CatalogUnprocessedEntitiesApi}\n *\n * @public\n */\nexport type CatalogUnprocessedEntitiesApiResponse = {\n entities: UnprocessedEntity[];\n};\n\n/**\n * Interface for the CatalogUnprocessedEntitiesApi.\n *\n * @public\n */\nexport interface CatalogUnprocessedEntitiesApi {\n /**\n * Returns a list of entities with state 'pending'\n */\n pending(): Promise<CatalogUnprocessedEntitiesApiResponse>;\n /**\n * Returns a list of entities with state 'failed'\n */\n failed(): Promise<CatalogUnprocessedEntitiesApiResponse>;\n /**\n * Deletes an entity from the refresh_state table\n */\n delete(entityId: string): Promise<void>;\n}\n\n/**\n * Default API implementation for the Catalog Unprocessed Entities plugin\n *\n * @public\n */\nexport class CatalogUnprocessedEntitiesClient\n implements CatalogUnprocessedEntitiesApi\n{\n constructor(public discovery: DiscoveryApi, public fetchApi: FetchApi) {}\n\n private async fetch<T>(path: string, init?: RequestInit): Promise<T> {\n const url = await this.discovery.getBaseUrl('catalog');\n const resp = await this.fetchApi.fetch(`${url}/${path}`, init);\n\n if (!resp.ok) {\n throw await ResponseError.fromResponse(resp);\n }\n\n return resp.status === 204 ? (resp as T) : await resp.json();\n }\n\n async pending(): Promise<CatalogUnprocessedEntitiesApiResponse> {\n return await this.fetch('entities/unprocessed/pending');\n }\n\n async failed(): Promise<CatalogUnprocessedEntitiesApiResponse> {\n return await this.fetch('entities/unprocessed/failed');\n }\n\n async delete(entityId: string): Promise<void> {\n await this.fetch(`entities/unprocessed/delete/${entityId}`, {\n method: 'DELETE',\n });\n }\n}\n","/*\n * Copyright 2023 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nimport {\n createApiFactory,\n createPlugin,\n createRoutableExtension,\n discoveryApiRef,\n fetchApiRef,\n} from '@backstage/core-plugin-api';\n\nimport { rootRouteRef } from './routes';\nimport {\n CatalogUnprocessedEntitiesClient,\n catalogUnprocessedEntitiesApiRef,\n} from './api';\n\n/**\n * Plugin entry point\n *\n * @public\n */\nexport const catalogUnprocessedEntitiesPlugin = createPlugin({\n id: 'catalog-unprocessed-entities',\n routes: {\n root: rootRouteRef,\n },\n apis: [\n createApiFactory({\n api: catalogUnprocessedEntitiesApiRef,\n deps: { discoveryApi: discoveryApiRef, fetchApi: fetchApiRef },\n factory: ({ discoveryApi, fetchApi }) =>\n new CatalogUnprocessedEntitiesClient(discoveryApi, fetchApi),\n }),\n ],\n});\n\n/**\n * Tool page for the Catalog Unprocessed Entities Plugin\n *\n * @public\n */\nexport const CatalogUnprocessedEntitiesPage =\n catalogUnprocessedEntitiesPlugin.provide(\n createRoutableExtension({\n name: 'CatalogUnprocessedEntitiesPage',\n component: () =>\n import('./components/UnprocessedEntities').then(\n m => m.UnprocessedEntities,\n ),\n mountPoint: rootRouteRef,\n }),\n );\n","/*\n * Copyright 2023 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nimport React, { useState } from 'react';\n\nimport Dialog from '@material-ui/core/Dialog';\nimport DialogContent from '@material-ui/core/DialogContent';\nimport DialogTitle from '@material-ui/core/DialogTitle';\nimport IconButton from '@material-ui/core/IconButton';\nimport { makeStyles, createStyles, Theme } from '@material-ui/core/styles';\nimport CloseIcon from '@material-ui/icons/Close';\nimport DescriptionIcon from '@material-ui/icons/Description';\n\nimport { UnprocessedEntity } from './../types';\nimport { CodeSnippet } from '@backstage/core-components';\n\nconst useStyles = makeStyles((theme: Theme) =>\n createStyles({\n closeButton: {\n position: 'absolute',\n right: theme.spacing(1),\n top: theme.spacing(1),\n color: theme.palette.grey[500],\n },\n entity: {\n overflow: 'scroll',\n width: '100%',\n },\n codeBox: {\n border: '1px solid black',\n padding: '1em',\n },\n }),\n);\n\nexport const EntityDialog = ({ entity }: { entity: UnprocessedEntity }) => {\n const [open, setOpen] = useState(false);\n const classes = useStyles();\n\n const openDialog = () => {\n setOpen(true);\n };\n\n const closeDialog = () => {\n setOpen(false);\n };\n\n const dialogContent = () => {\n return (\n <CodeSnippet\n language=\"json\"\n showLineNumbers\n text={JSON.stringify(entity, null, 4)}\n />\n );\n };\n\n return (\n <>\n <IconButton color=\"primary\" onClick={openDialog}>\n <DescriptionIcon />\n </IconButton>\n <Dialog fullWidth open={open} onClose={closeDialog}>\n <DialogTitle id=\"dialog-title\">\n <IconButton\n aria-label=\"close\"\n className={classes.closeButton}\n onClick={closeDialog}\n >\n <CloseIcon />\n </IconButton>\n </DialogTitle>\n <DialogContent>{dialogContent()}</DialogContent>\n </Dialog>\n </>\n );\n};\n","/*\n * Copyright 2023 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nimport React, { useState } from 'react';\n\nimport {\n ErrorPanel,\n MarkdownContent,\n Progress,\n Table,\n TableColumn,\n} from '@backstage/core-components';\n\nimport Box from '@material-ui/core/Box';\nimport Typography from '@material-ui/core/Typography';\nimport IconButton from '@material-ui/core/IconButton';\nimport { Theme, makeStyles } from '@material-ui/core/styles';\nimport { alertApiRef, useApi } from '@backstage/core-plugin-api';\n\nimport { UnprocessedEntity } from '../types';\nimport { EntityDialog } from './EntityDialog';\nimport { catalogUnprocessedEntitiesApiRef } from '../api';\nimport useAsync from 'react-use/esm/useAsync';\nimport DeleteIcon from '@material-ui/icons/Delete';\n\nconst useStyles = makeStyles((theme: Theme) => ({\n errorBox: {\n color: theme.palette.status.error,\n backgroundColor: theme.palette.errorBackground,\n padding: '1em',\n margin: '1em',\n border: `1px solid ${theme.palette.status.error}`,\n },\n errorTitle: {\n width: '100%',\n fontWeight: 'bold',\n },\n successMessage: {\n background: theme.palette.infoBackground,\n color: theme.palette.infoText,\n padding: theme.spacing(2),\n },\n}));\n\nconst RenderErrorContext = ({\n error,\n rowData,\n}: {\n error: { message: string };\n rowData: UnprocessedEntity;\n}) => {\n if (error.message.includes('tags.')) {\n return (\n <>\n <Typography>Tags</Typography>\n <ul>\n {rowData.unprocessed_entity.metadata.tags?.map(t => (\n <li>{t}</li>\n ))}\n </ul>\n </>\n );\n }\n\n if (error.message.includes('metadata.name')) {\n return (\n <>\n <Typography>Name</Typography>\n <Typography variant=\"caption\">\n {rowData.unprocessed_entity.metadata.name}\n </Typography>\n </>\n );\n }\n\n return null;\n};\n\nexport const FailedEntities = () => {\n const classes = useStyles();\n const unprocessedApi = useApi(catalogUnprocessedEntitiesApiRef);\n const {\n loading,\n error,\n value: data,\n } = useAsync(async () => await unprocessedApi.failed());\n const [, setSelectedSearchTerm] = useState<string>('');\n const unprocessedEntityApi = useApi(catalogUnprocessedEntitiesApiRef);\n const alertApi = useApi(alertApiRef);\n\n if (loading) {\n return <Progress />;\n }\n if (error) {\n return <ErrorPanel error={error} />;\n }\n\n const handleDelete = async ({\n entityId,\n entityRef,\n }: {\n entityId: string;\n entityRef: string;\n }) => {\n try {\n await unprocessedEntityApi.delete(entityId);\n alertApi.post({\n message: `Entity ${entityRef} has been deleted`,\n severity: 'success',\n });\n } catch (e) {\n alertApi.post({\n message: `Ran into an issue when deleting ${entityRef}. Please try again later.`,\n severity: 'error',\n });\n }\n };\n\n const columns: TableColumn[] = [\n {\n title: <Typography>entityRef</Typography>,\n sorting: true,\n field: 'entity_ref',\n customFilterAndSearch: (query, row: any) =>\n row.entity_ref\n .toLocaleUpperCase('en-US')\n .includes(query.toLocaleUpperCase('en-US')),\n render: (rowData: UnprocessedEntity | {}) =>\n (rowData as UnprocessedEntity).entity_ref,\n },\n {\n title: <Typography>Kind</Typography>,\n sorting: true,\n field: 'kind',\n render: (rowData: UnprocessedEntity | {}) =>\n (rowData as UnprocessedEntity).unprocessed_entity.kind,\n },\n {\n title: <Typography>Owner</Typography>,\n sorting: true,\n field: 'unprocessed_entity.spec.owner',\n render: (rowData: UnprocessedEntity | {}) =>\n (rowData as UnprocessedEntity).unprocessed_entity.spec?.owner ||\n 'unknown',\n },\n {\n title: <Typography>Raw</Typography>,\n sorting: false,\n render: (rowData: UnprocessedEntity | {}) => (\n <EntityDialog entity={rowData as UnprocessedEntity} />\n ),\n },\n {\n title: <Typography>Actions</Typography>,\n render: (rowData: UnprocessedEntity | {}) => {\n const { entity_id, entity_ref } = rowData as UnprocessedEntity;\n\n return (\n <IconButton\n aria-label=\"delete\"\n onClick={async () =>\n await handleDelete({\n entityId: entity_id,\n entityRef: entity_ref,\n })\n }\n >\n <DeleteIcon fontSize=\"small\" data-testid=\"delete-icon\" />\n </IconButton>\n );\n },\n },\n ];\n\n return (\n <Table\n options={{ pageSize: 20, search: true }}\n columns={columns}\n data={data?.entities ?? []}\n emptyContent={\n <Typography className={classes.successMessage}>\n No failed entities found\n </Typography>\n }\n onSearchChange={(searchTerm: string) => setSelectedSearchTerm(searchTerm)}\n detailPanel={({ rowData }) => {\n const errors = (rowData as UnprocessedEntity).errors;\n return (\n <>\n {errors?.map((e, idx) => {\n return (\n <Box key={idx} className={classes.errorBox}>\n <Typography className={classes.errorTitle}>\n {e.name}\n </Typography>\n <MarkdownContent content={e.message} />\n <RenderErrorContext\n error={e}\n rowData={rowData as UnprocessedEntity}\n />\n </Box>\n );\n })}\n </>\n );\n }}\n />\n );\n};\n","/*\n * Copyright 2023 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nimport React, { useState } from 'react';\n\nimport {\n ErrorPanel,\n Progress,\n TableColumn,\n Table,\n} from '@backstage/core-components';\nimport Typography from '@material-ui/core/Typography';\nimport { Theme, makeStyles } from '@material-ui/core/styles';\n\nimport { UnprocessedEntity } from '../types';\n\nimport { EntityDialog } from './EntityDialog';\nimport { useApi } from '@backstage/core-plugin-api';\nimport useAsync from 'react-use/esm/useAsync';\nimport { catalogUnprocessedEntitiesApiRef } from '../api';\n\nconst useStyles = makeStyles((theme: Theme) => ({\n successMessage: {\n background: theme.palette.infoBackground,\n color: theme.palette.infoText,\n padding: theme.spacing(2),\n },\n}));\n\nexport const PendingEntities = () => {\n const classes = useStyles();\n const unprocessedApi = useApi(catalogUnprocessedEntitiesApiRef);\n const {\n loading,\n error,\n value: data,\n } = useAsync(async () => await unprocessedApi.pending());\n const [, setSelectedSearchTerm] = useState<string>('');\n\n if (loading) {\n return <Progress />;\n }\n if (error) {\n return <ErrorPanel error={error} />;\n }\n\n const columns: TableColumn[] = [\n {\n title: <Typography>entityRef</Typography>,\n sorting: true,\n field: 'entity_ref',\n customFilterAndSearch: (query, row: any) =>\n row.entity_ref\n .toLocaleUpperCase('en-US')\n .includes(query.toLocaleUpperCase('en-US')),\n render: (rowData: UnprocessedEntity | {}) =>\n (rowData as UnprocessedEntity).entity_ref,\n },\n {\n title: <Typography>Kind</Typography>,\n sorting: true,\n field: 'kind',\n render: (rowData: UnprocessedEntity | {}) =>\n (rowData as UnprocessedEntity).unprocessed_entity.kind,\n },\n {\n title: <Typography>Owner</Typography>,\n sorting: true,\n field: 'unprocessed_entity.spec.owner',\n render: (rowData: UnprocessedEntity | {}) =>\n (rowData as UnprocessedEntity).unprocessed_entity.spec?.owner ||\n 'unknown',\n },\n {\n title: <Typography>Raw</Typography>,\n sorting: false,\n render: (rowData: UnprocessedEntity | {}) => (\n <EntityDialog entity={rowData as UnprocessedEntity} />\n ),\n },\n ];\n return (\n <>\n <Table\n options={{ pageSize: 20 }}\n columns={columns}\n data={data?.entities || []}\n onSearchChange={(searchTerm: string) =>\n setSelectedSearchTerm(searchTerm)\n }\n emptyContent={\n <Typography className={classes.successMessage}>\n No pending entities found\n </Typography>\n }\n />\n </>\n );\n};\n","/*\n * Copyright 2023 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nimport React, { useState } from 'react';\n\nimport { Page, Header, Content } from '@backstage/core-components';\nimport Tab from '@material-ui/core/Tab';\nimport { makeStyles } from '@material-ui/core/styles';\nimport TabContext from '@material-ui/lab/TabContext';\nimport TabList from '@material-ui/lab/TabList';\nimport TabPanel from '@material-ui/lab/TabPanel';\n\nimport { FailedEntities } from './FailedEntities';\nimport { PendingEntities } from './PendingEntities';\n\nconst useStyles = makeStyles(() => ({\n tabPanel: {\n paddingLeft: '0px',\n paddingRight: '0px',\n },\n}));\n\n/** @public */\nexport const UnprocessedEntitiesContent = () => {\n const classes = useStyles();\n const [tab, setTab] = useState('failed');\n const handleChange = (_event: React.ChangeEvent<{}>, tabValue: string) => {\n setTab(tabValue);\n };\n\n return (\n <TabContext value={tab}>\n <TabList onChange={handleChange}>\n <Tab label=\"Failed\" value=\"failed\" />\n <Tab label=\"Pending\" value=\"pending\" />\n </TabList>\n <TabPanel value=\"failed\" className={classes.tabPanel}>\n <FailedEntities />\n </TabPanel>\n <TabPanel value=\"pending\" className={classes.tabPanel}>\n <PendingEntities />\n </TabPanel>\n </TabContext>\n );\n};\n\nexport const UnprocessedEntities = () => {\n return (\n <Page themeId=\"tool\">\n <Header title=\"Unprocessed Entities\" />\n <Content>\n <UnprocessedEntitiesContent />\n </Content>\n </Page>\n );\n};\n"],"names":["useStyles","_a"],"mappings":"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"}
1
+ {"version":3,"file":"index.esm.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;"}
@@ -0,0 +1,29 @@
1
+ import { createPlugin, createApiFactory, discoveryApiRef, fetchApiRef, createRoutableExtension } from '@backstage/core-plugin-api';
2
+ import { rootRouteRef } from './routes.esm.js';
3
+ import { catalogUnprocessedEntitiesApiRef, CatalogUnprocessedEntitiesClient } from './api/index.esm.js';
4
+
5
+ const catalogUnprocessedEntitiesPlugin = createPlugin({
6
+ id: "catalog-unprocessed-entities",
7
+ routes: {
8
+ root: rootRouteRef
9
+ },
10
+ apis: [
11
+ createApiFactory({
12
+ api: catalogUnprocessedEntitiesApiRef,
13
+ deps: { discoveryApi: discoveryApiRef, fetchApi: fetchApiRef },
14
+ factory: ({ discoveryApi, fetchApi }) => new CatalogUnprocessedEntitiesClient(discoveryApi, fetchApi)
15
+ })
16
+ ]
17
+ });
18
+ const CatalogUnprocessedEntitiesPage = catalogUnprocessedEntitiesPlugin.provide(
19
+ createRoutableExtension({
20
+ name: "CatalogUnprocessedEntitiesPage",
21
+ component: () => import('./components/UnprocessedEntities.esm.js').then(
22
+ (m) => m.UnprocessedEntities
23
+ ),
24
+ mountPoint: rootRouteRef
25
+ })
26
+ );
27
+
28
+ export { CatalogUnprocessedEntitiesPage, catalogUnprocessedEntitiesPlugin };
29
+ //# sourceMappingURL=plugin.esm.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"plugin.esm.js","sources":["../src/plugin.ts"],"sourcesContent":["/*\n * Copyright 2023 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nimport {\n createApiFactory,\n createPlugin,\n createRoutableExtension,\n discoveryApiRef,\n fetchApiRef,\n} from '@backstage/core-plugin-api';\n\nimport { rootRouteRef } from './routes';\nimport {\n CatalogUnprocessedEntitiesClient,\n catalogUnprocessedEntitiesApiRef,\n} from './api';\n\n/**\n * Plugin entry point\n *\n * @public\n */\nexport const catalogUnprocessedEntitiesPlugin = createPlugin({\n id: 'catalog-unprocessed-entities',\n routes: {\n root: rootRouteRef,\n },\n apis: [\n createApiFactory({\n api: catalogUnprocessedEntitiesApiRef,\n deps: { discoveryApi: discoveryApiRef, fetchApi: fetchApiRef },\n factory: ({ discoveryApi, fetchApi }) =>\n new CatalogUnprocessedEntitiesClient(discoveryApi, fetchApi),\n }),\n ],\n});\n\n/**\n * Tool page for the Catalog Unprocessed Entities Plugin\n *\n * @public\n */\nexport const CatalogUnprocessedEntitiesPage =\n catalogUnprocessedEntitiesPlugin.provide(\n createRoutableExtension({\n name: 'CatalogUnprocessedEntitiesPage',\n component: () =>\n import('./components/UnprocessedEntities').then(\n m => m.UnprocessedEntities,\n ),\n mountPoint: rootRouteRef,\n }),\n );\n"],"names":[],"mappings":";;;;AAkCO,MAAM,mCAAmC,YAAa,CAAA;AAAA,EAC3D,EAAI,EAAA,8BAAA;AAAA,EACJ,MAAQ,EAAA;AAAA,IACN,IAAM,EAAA,YAAA;AAAA,GACR;AAAA,EACA,IAAM,EAAA;AAAA,IACJ,gBAAiB,CAAA;AAAA,MACf,GAAK,EAAA,gCAAA;AAAA,MACL,IAAM,EAAA,EAAE,YAAc,EAAA,eAAA,EAAiB,UAAU,WAAY,EAAA;AAAA,MAC7D,OAAA,EAAS,CAAC,EAAE,YAAA,EAAc,UACxB,KAAA,IAAI,gCAAiC,CAAA,YAAA,EAAc,QAAQ,CAAA;AAAA,KAC9D,CAAA;AAAA,GACH;AACF,CAAC,EAAA;AAOM,MAAM,iCACX,gCAAiC,CAAA,OAAA;AAAA,EAC/B,uBAAwB,CAAA;AAAA,IACtB,IAAM,EAAA,gCAAA;AAAA,IACN,SAAW,EAAA,MACT,OAAO,yCAAkC,CAAE,CAAA,IAAA;AAAA,MACzC,OAAK,CAAE,CAAA,mBAAA;AAAA,KACT;AAAA,IACF,UAAY,EAAA,YAAA;AAAA,GACb,CAAA;AACH;;;;"}
@@ -0,0 +1,8 @@
1
+ import { createRouteRef } from '@backstage/core-plugin-api';
2
+
3
+ const rootRouteRef = createRouteRef({
4
+ id: "catalog-unprocessed-entities"
5
+ });
6
+
7
+ export { rootRouteRef };
8
+ //# sourceMappingURL=routes.esm.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"routes.esm.js","sources":["../src/routes.ts"],"sourcesContent":["/*\n * Copyright 2023 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nimport { createRouteRef } from '@backstage/core-plugin-api';\n\nexport const rootRouteRef = createRouteRef({\n id: 'catalog-unprocessed-entities',\n});\n"],"names":[],"mappings":";;AAiBO,MAAM,eAAe,cAAe,CAAA;AAAA,EACzC,EAAI,EAAA,8BAAA;AACN,CAAC;;;;"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@backstage/plugin-catalog-unprocessed-entities",
3
- "version": "0.2.3",
3
+ "version": "0.2.4-next.0",
4
4
  "backstage": {
5
5
  "role": "frontend-plugin"
6
6
  },
@@ -32,8 +32,8 @@
32
32
  "test": "backstage-cli package test"
33
33
  },
34
34
  "dependencies": {
35
- "@backstage/catalog-model": "^1.4.5",
36
- "@backstage/core-components": "^0.14.4",
35
+ "@backstage/catalog-model": "^1.5.0-next.0",
36
+ "@backstage/core-components": "^0.14.5-next.0",
37
37
  "@backstage/core-plugin-api": "^1.9.2",
38
38
  "@backstage/errors": "^1.2.4",
39
39
  "@material-ui/core": "^4.9.13",
@@ -43,8 +43,8 @@
43
43
  "react-use": "^17.2.4"
44
44
  },
45
45
  "devDependencies": {
46
- "@backstage/cli": "^0.26.3",
47
- "@backstage/dev-utils": "^1.0.31",
46
+ "@backstage/cli": "^0.26.5-next.0",
47
+ "@backstage/dev-utils": "^1.0.32-next.0",
48
48
  "@testing-library/jest-dom": "^6.0.0",
49
49
  "@testing-library/react": "^15.0.0"
50
50
  },