@backstage-community/plugin-quay 1.19.2 → 1.20.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,22 @@
1
1
  ### Dependencies
2
2
 
3
+ ## 1.20.1
4
+
5
+ ### Patch Changes
6
+
7
+ - fa53ba5: Updated dependency `@playwright/test` to `1.52.0`.
8
+
9
+ ## 1.20.0
10
+
11
+ ### Minor Changes
12
+
13
+ - e172aba: Bump backstage version to v1.38.1
14
+
15
+ ### Patch Changes
16
+
17
+ - Updated dependencies [e172aba]
18
+ - @backstage-community/plugin-quay-common@1.8.0
19
+
3
20
  ## 1.19.2
4
21
 
5
22
  ### Patch Changes
@@ -1,8 +1,11 @@
1
- import React from 'react';
1
+ import { jsxs, jsx } from 'react/jsx-runtime';
2
2
  import { Alert, AlertTitle } from '@material-ui/lab';
3
3
 
4
4
  const PermissionAlert = () => {
5
- return /* @__PURE__ */ React.createElement(Alert, { severity: "warning", "data-testid": "no-permission-alert" }, /* @__PURE__ */ React.createElement(AlertTitle, null, "Permission required"), "To view quay image registry, contact your administrator to give you the quay.view.read permission.");
5
+ return /* @__PURE__ */ jsxs(Alert, { severity: "warning", "data-testid": "no-permission-alert", children: [
6
+ /* @__PURE__ */ jsx(AlertTitle, { children: "Permission required" }),
7
+ "To view quay image registry, contact your administrator to give you the quay.view.read permission."
8
+ ] });
6
9
  };
7
10
 
8
11
  export { PermissionAlert as default };
@@ -1 +1 @@
1
- {"version":3,"file":"PermissionAlert.esm.js","sources":["../../../src/components/PermissionAlert/PermissionAlert.tsx"],"sourcesContent":["/*\n * Copyright 2024 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 from 'react';\n\nimport { Alert, AlertTitle } from '@material-ui/lab';\n\nconst PermissionAlert = () => {\n return (\n <Alert severity=\"warning\" data-testid=\"no-permission-alert\">\n <AlertTitle>Permission required</AlertTitle>\n To view quay image registry, contact your administrator to give you the\n quay.view.read permission.\n </Alert>\n );\n};\nexport default PermissionAlert;\n"],"names":[],"mappings":";;;AAmBA,MAAM,kBAAkB,MAAM;AAC5B,EACE,uBAAA,KAAA,CAAA,aAAA,CAAC,KAAM,EAAA,EAAA,QAAA,EAAS,SAAU,EAAA,aAAA,EAAY,yCACnC,KAAA,CAAA,aAAA,CAAA,UAAA,EAAA,IAAA,EAAW,qBAAmB,CAAA,EAAa,oGAG9C,CAAA;AAEJ;;;;"}
1
+ {"version":3,"file":"PermissionAlert.esm.js","sources":["../../../src/components/PermissionAlert/PermissionAlert.tsx"],"sourcesContent":["/*\n * Copyright 2024 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 { Alert, AlertTitle } from '@material-ui/lab';\n\nconst PermissionAlert = () => {\n return (\n <Alert severity=\"warning\" data-testid=\"no-permission-alert\">\n <AlertTitle>Permission required</AlertTitle>\n To view quay image registry, contact your administrator to give you the\n quay.view.read permission.\n </Alert>\n );\n};\nexport default PermissionAlert;\n"],"names":[],"mappings":";;;AAiBA,MAAM,kBAAkB,MAAM;AAC5B,EAAA,uBACG,IAAA,CAAA,KAAA,EAAA,EAAM,QAAS,EAAA,SAAA,EAAU,eAAY,qBACpC,EAAA,QAAA,EAAA;AAAA,oBAAA,GAAA,CAAC,cAAW,QAAmB,EAAA,qBAAA,EAAA,CAAA;AAAA,IAAa;AAAA,GAG9C,EAAA,CAAA;AAEJ;;;;"}
@@ -1,5 +1,5 @@
1
- import React from 'react';
2
- import { Link, Progress, Table } from '@backstage/core-components';
1
+ import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
2
+ import { Progress, Table, Link } from '@backstage/core-components';
3
3
  import { useApi, configApiRef } from '@backstage/core-plugin-api';
4
4
  import { useRepository, useTags } from '../../hooks/quay.esm.js';
5
5
  import { useQuayViewPermission } from '../../hooks/useQuayViewPermission.esm.js';
@@ -12,30 +12,33 @@ function QuayRepository(_props) {
12
12
  const configApi = useApi(configApiRef);
13
13
  const quayUiUrl = configApi.getOptionalString("quay.apiUrl") ?? configApi.getOptionalString("quay.uiUrl");
14
14
  const hasViewPermission = useQuayViewPermission();
15
- const title = quayUiUrl ? /* @__PURE__ */ React.createElement(React.Fragment, null, `Quay repository: `, /* @__PURE__ */ React.createElement(
16
- Link,
17
- {
18
- to: `${quayUiUrl}/repository/${organization}/${repository}`
19
- },
20
- `${organization}/${repository}`
21
- )) : `Quay repository: ${organization}/${repository}`;
15
+ const title = quayUiUrl ? /* @__PURE__ */ jsxs(Fragment, { children: [
16
+ `Quay repository: `,
17
+ /* @__PURE__ */ jsx(
18
+ Link,
19
+ {
20
+ to: `${quayUiUrl}/repository/${organization}/${repository}`,
21
+ children: `${organization}/${repository}`
22
+ }
23
+ )
24
+ ] }) : `Quay repository: ${organization}/${repository}`;
22
25
  const { loading, data } = useTags(organization, repository);
23
26
  if (!hasViewPermission) {
24
- return /* @__PURE__ */ React.createElement(PermissionAlert, null);
27
+ return /* @__PURE__ */ jsx(PermissionAlert, {});
25
28
  }
26
29
  if (loading) {
27
- return /* @__PURE__ */ React.createElement("div", { "data-testid": "quay-repo-progress" }, /* @__PURE__ */ React.createElement(Progress, null));
30
+ return /* @__PURE__ */ jsx("div", { "data-testid": "quay-repo-progress", children: /* @__PURE__ */ jsx(Progress, {}) });
28
31
  }
29
- return /* @__PURE__ */ React.createElement("div", { "data-testid": "quay-repo-table" }, /* @__PURE__ */ React.createElement(
32
+ return /* @__PURE__ */ jsx("div", { "data-testid": "quay-repo-table", children: /* @__PURE__ */ jsx(
30
33
  Table,
31
34
  {
32
35
  title,
33
36
  options: { sorting: true, paging: true, padding: "dense" },
34
37
  data,
35
38
  columns,
36
- emptyContent: /* @__PURE__ */ React.createElement("div", { "data-testid": "quay-repo-table-empty", className: classes.empty }, "There are no images available.")
39
+ emptyContent: /* @__PURE__ */ jsx("div", { "data-testid": "quay-repo-table-empty", className: classes.empty, children: "There are no images available." })
37
40
  }
38
- ));
41
+ ) });
39
42
  }
40
43
 
41
44
  export { QuayRepository };
@@ -1 +1 @@
1
- {"version":3,"file":"QuayRepository.esm.js","sources":["../../../src/components/QuayRepository/QuayRepository.tsx"],"sourcesContent":["/*\n * Copyright 2024 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 from 'react';\n\nimport { Link, Progress, Table } from '@backstage/core-components';\nimport { configApiRef, useApi } from '@backstage/core-plugin-api';\n\nimport { useRepository, useTags } from '../../hooks';\nimport { useQuayViewPermission } from '../../hooks/useQuayViewPermission';\nimport PermissionAlert from '../PermissionAlert/PermissionAlert';\nimport { columns, useStyles } from './tableHeading';\n\ntype QuayRepositoryProps = Record<never, any>;\n\nexport function QuayRepository(_props: QuayRepositoryProps) {\n const { repository, organization } = useRepository();\n const classes = useStyles();\n const configApi = useApi(configApiRef);\n const quayUiUrl =\n configApi.getOptionalString('quay.apiUrl') ??\n configApi.getOptionalString('quay.uiUrl');\n\n const hasViewPermission = useQuayViewPermission();\n\n const title = quayUiUrl ? (\n <>\n {`Quay repository: `}\n <Link\n to={`${quayUiUrl}/repository/${organization}/${repository}`}\n >{`${organization}/${repository}`}</Link>\n </>\n ) : (\n `Quay repository: ${organization}/${repository}`\n );\n const { loading, data } = useTags(organization, repository);\n\n if (!hasViewPermission) {\n return <PermissionAlert />;\n }\n\n if (loading) {\n return (\n <div data-testid=\"quay-repo-progress\">\n <Progress />\n </div>\n );\n }\n\n return (\n <div data-testid=\"quay-repo-table\">\n <Table\n title={title}\n options={{ sorting: true, paging: true, padding: 'dense' }}\n data={data}\n columns={columns}\n emptyContent={\n <div data-testid=\"quay-repo-table-empty\" className={classes.empty}>\n There are no images available.\n </div>\n }\n />\n </div>\n );\n}\n"],"names":[],"mappings":";;;;;;;;AA2BO,SAAS,eAAe,MAA6B,EAAA;AAC1D,EAAA,MAAM,EAAE,UAAA,EAAY,YAAa,EAAA,GAAI,aAAc,EAAA;AACnD,EAAA,MAAM,UAAU,SAAU,EAAA;AAC1B,EAAM,MAAA,SAAA,GAAY,OAAO,YAAY,CAAA;AACrC,EAAA,MAAM,YACJ,SAAU,CAAA,iBAAA,CAAkB,aAAa,CACzC,IAAA,SAAA,CAAU,kBAAkB,YAAY,CAAA;AAE1C,EAAA,MAAM,oBAAoB,qBAAsB,EAAA;AAEhD,EAAM,MAAA,KAAA,GAAQ,SACZ,mBAAA,KAAA,CAAA,aAAA,CAAA,KAAA,CAAA,QAAA,EAAA,IAAA,EACG,CACD,iBAAA,CAAA,kBAAA,KAAA,CAAA,aAAA;AAAA,IAAC,IAAA;AAAA,IAAA;AAAA,MACC,IAAI,CAAG,EAAA,SAAS,CAAe,YAAA,EAAA,YAAY,IAAI,UAAU,CAAA;AAAA,KAAA;AAAA,IACzD,CAAA,EAAG,YAAY,CAAA,CAAA,EAAI,UAAU,CAAA;AAAA,GACjC,CAAA,GAEA,CAAoB,iBAAA,EAAA,YAAY,IAAI,UAAU,CAAA,CAAA;AAEhD,EAAA,MAAM,EAAE,OAAS,EAAA,IAAA,EAAS,GAAA,OAAA,CAAQ,cAAc,UAAU,CAAA;AAE1D,EAAA,IAAI,CAAC,iBAAmB,EAAA;AACtB,IAAA,2CAAQ,eAAgB,EAAA,IAAA,CAAA;AAAA;AAG1B,EAAA,IAAI,OAAS,EAAA;AACX,IAAA,2CACG,KAAI,EAAA,EAAA,aAAA,EAAY,oBACf,EAAA,kBAAA,KAAA,CAAA,aAAA,CAAC,cAAS,CACZ,CAAA;AAAA;AAIJ,EACE,uBAAA,KAAA,CAAA,aAAA,CAAC,KAAI,EAAA,EAAA,aAAA,EAAY,iBACf,EAAA,kBAAA,KAAA,CAAA,aAAA;AAAA,IAAC,KAAA;AAAA,IAAA;AAAA,MACC,KAAA;AAAA,MACA,SAAS,EAAE,OAAA,EAAS,MAAM,MAAQ,EAAA,IAAA,EAAM,SAAS,OAAQ,EAAA;AAAA,MACzD,IAAA;AAAA,MACA,OAAA;AAAA,MACA,YAAA,sCACG,KAAI,EAAA,EAAA,aAAA,EAAY,yBAAwB,SAAW,EAAA,OAAA,CAAQ,SAAO,gCAEnE;AAAA;AAAA,GAGN,CAAA;AAEJ;;;;"}
1
+ {"version":3,"file":"QuayRepository.esm.js","sources":["../../../src/components/QuayRepository/QuayRepository.tsx"],"sourcesContent":["/*\n * Copyright 2024 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 { Link, Progress, Table } from '@backstage/core-components';\nimport { configApiRef, useApi } from '@backstage/core-plugin-api';\n\nimport { useRepository, useTags } from '../../hooks';\nimport { useQuayViewPermission } from '../../hooks/useQuayViewPermission';\nimport PermissionAlert from '../PermissionAlert/PermissionAlert';\nimport { columns, useStyles } from './tableHeading';\n\ntype QuayRepositoryProps = Record<never, any>;\n\nexport function QuayRepository(_props: QuayRepositoryProps) {\n const { repository, organization } = useRepository();\n const classes = useStyles();\n const configApi = useApi(configApiRef);\n const quayUiUrl =\n configApi.getOptionalString('quay.apiUrl') ??\n configApi.getOptionalString('quay.uiUrl');\n\n const hasViewPermission = useQuayViewPermission();\n\n const title = quayUiUrl ? (\n <>\n {`Quay repository: `}\n <Link\n to={`${quayUiUrl}/repository/${organization}/${repository}`}\n >{`${organization}/${repository}`}</Link>\n </>\n ) : (\n `Quay repository: ${organization}/${repository}`\n );\n const { loading, data } = useTags(organization, repository);\n\n if (!hasViewPermission) {\n return <PermissionAlert />;\n }\n\n if (loading) {\n return (\n <div data-testid=\"quay-repo-progress\">\n <Progress />\n </div>\n );\n }\n\n return (\n <div data-testid=\"quay-repo-table\">\n <Table\n title={title}\n options={{ sorting: true, paging: true, padding: 'dense' }}\n data={data}\n columns={columns}\n emptyContent={\n <div data-testid=\"quay-repo-table-empty\" className={classes.empty}>\n There are no images available.\n </div>\n }\n />\n </div>\n );\n}\n"],"names":[],"mappings":";;;;;;;;AAyBO,SAAS,eAAe,MAA6B,EAAA;AAC1D,EAAA,MAAM,EAAE,UAAA,EAAY,YAAa,EAAA,GAAI,aAAc,EAAA;AACnD,EAAA,MAAM,UAAU,SAAU,EAAA;AAC1B,EAAM,MAAA,SAAA,GAAY,OAAO,YAAY,CAAA;AACrC,EAAA,MAAM,YACJ,SAAU,CAAA,iBAAA,CAAkB,aAAa,CACzC,IAAA,SAAA,CAAU,kBAAkB,YAAY,CAAA;AAE1C,EAAA,MAAM,oBAAoB,qBAAsB,EAAA;AAEhD,EAAM,MAAA,KAAA,GAAQ,4BAET,IAAA,CAAA,QAAA,EAAA,EAAA,QAAA,EAAA;AAAA,IAAA,CAAA,iBAAA,CAAA;AAAA,oBACD,GAAA;AAAA,MAAC,IAAA;AAAA,MAAA;AAAA,QACC,IAAI,CAAG,EAAA,SAAS,CAAe,YAAA,EAAA,YAAY,IAAI,UAAU,CAAA,CAAA;AAAA,QACzD,QAAA,EAAA,CAAA,EAAG,YAAY,CAAA,CAAA,EAAI,UAAU,CAAA;AAAA;AAAA;AAAG,GAAA,EACpC,CAEA,GAAA,CAAA,iBAAA,EAAoB,YAAY,CAAA,CAAA,EAAI,UAAU,CAAA,CAAA;AAEhD,EAAA,MAAM,EAAE,OAAS,EAAA,IAAA,EAAS,GAAA,OAAA,CAAQ,cAAc,UAAU,CAAA;AAE1D,EAAA,IAAI,CAAC,iBAAmB,EAAA;AACtB,IAAA,2BAAQ,eAAgB,EAAA,EAAA,CAAA;AAAA;AAG1B,EAAA,IAAI,OAAS,EAAA;AACX,IAAA,2BACG,KAAI,EAAA,EAAA,aAAA,EAAY,oBACf,EAAA,QAAA,kBAAA,GAAA,CAAC,YAAS,CACZ,EAAA,CAAA;AAAA;AAIJ,EACE,uBAAA,GAAA,CAAC,KAAI,EAAA,EAAA,aAAA,EAAY,iBACf,EAAA,QAAA,kBAAA,GAAA;AAAA,IAAC,KAAA;AAAA,IAAA;AAAA,MACC,KAAA;AAAA,MACA,SAAS,EAAE,OAAA,EAAS,MAAM,MAAQ,EAAA,IAAA,EAAM,SAAS,OAAQ,EAAA;AAAA,MACzD,IAAA;AAAA,MACA,OAAA;AAAA,MACA,YAAA,sBACG,KAAI,EAAA,EAAA,aAAA,EAAY,yBAAwB,SAAW,EAAA,OAAA,CAAQ,OAAO,QAEnE,EAAA,gCAAA,EAAA;AAAA;AAAA,GAGN,EAAA,CAAA;AAEJ;;;;"}
@@ -1,4 +1,4 @@
1
- import React from 'react';
1
+ import { jsx } from 'react/jsx-runtime';
2
2
  import { Progress, Link } from '@backstage/core-components';
3
3
  import { Tooltip } from '@material-ui/core';
4
4
  import makeStyles from '@material-ui/core/styles/makeStyles';
@@ -21,23 +21,23 @@ const columns = [
21
21
  field: "securityScan",
22
22
  render: (rowData) => {
23
23
  if (!rowData.securityStatus && !rowData.securityDetails) {
24
- return /* @__PURE__ */ React.createElement("span", { "data-testid": "quay-repo-security-scan-progress" }, /* @__PURE__ */ React.createElement(Progress, null));
24
+ return /* @__PURE__ */ jsx("span", { "data-testid": "quay-repo-security-scan-progress", children: /* @__PURE__ */ jsx(Progress, {}) });
25
25
  }
26
26
  if (rowData.securityStatus === "queued") {
27
- return /* @__PURE__ */ React.createElement(Tooltip, { title: "The manifest for this tag is queued to be scanned for vulnerabilities" }, /* @__PURE__ */ React.createElement("span", { "data-testid": "quay-repo-queued-for-scan" }, "Queued"));
27
+ return /* @__PURE__ */ jsx(Tooltip, { title: "The manifest for this tag is queued to be scanned for vulnerabilities", children: /* @__PURE__ */ jsx("span", { "data-testid": "quay-repo-queued-for-scan", children: "Queued" }) });
28
28
  }
29
29
  if (rowData.securityStatus === "unsupported") {
30
- return /* @__PURE__ */ React.createElement(Tooltip, { title: "The manifest for this tag has an operating system or package manager unsupported by Quay Security Scanner" }, /* @__PURE__ */ React.createElement("span", { "data-testid": "quay-repo-security-scan-unsupported" }, "Unsupported"));
30
+ return /* @__PURE__ */ jsx(Tooltip, { title: "The manifest for this tag has an operating system or package manager unsupported by Quay Security Scanner", children: /* @__PURE__ */ jsx("span", { "data-testid": "quay-repo-security-scan-unsupported", children: "Unsupported" }) });
31
31
  }
32
32
  const tagManifest = rowData.manifest_digest_raw;
33
33
  const retStr = vulnerabilitySummary(rowData.securityDetails);
34
- return /* @__PURE__ */ React.createElement(
34
+ return /* @__PURE__ */ jsx(
35
35
  Link,
36
36
  {
37
37
  "data-testid": `${rowData.name}-security-scan`,
38
- to: `tag/${tagManifest}`
39
- },
40
- retStr
38
+ to: `tag/${tagManifest}`,
39
+ children: retStr
40
+ }
41
41
  );
42
42
  },
43
43
  id: "securityScan",
@@ -53,7 +53,7 @@ const columns = [
53
53
  title: "Expires",
54
54
  field: "expiration",
55
55
  type: "date",
56
- emptyValue: /* @__PURE__ */ React.createElement("i", null, "Never")
56
+ emptyValue: /* @__PURE__ */ jsx("i", { children: "Never" })
57
57
  },
58
58
  {
59
59
  title: "Manifest",
@@ -1 +1 @@
1
- {"version":3,"file":"tableHeading.esm.js","sources":["../../../src/components/QuayRepository/tableHeading.tsx"],"sourcesContent":["/*\n * Copyright 2024 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 from 'react';\n\nimport { Link, Progress, TableColumn } from '@backstage/core-components';\n\nimport { Tooltip } from '@material-ui/core';\nimport makeStyles from '@material-ui/core/styles/makeStyles';\n\nimport { securityScanComparator, vulnerabilitySummary } from '../../lib/utils';\nimport type { QuayTagData } from '../../types';\n\nexport const columns: TableColumn<QuayTagData>[] = [\n {\n title: 'Tag',\n field: 'name',\n type: 'string',\n highlight: true,\n },\n {\n title: 'Last Modified',\n field: 'last_modified',\n type: 'date',\n },\n {\n title: 'Security Scan',\n field: 'securityScan',\n render: (rowData: QuayTagData): React.ReactNode => {\n if (!rowData.securityStatus && !rowData.securityDetails) {\n return (\n <span data-testid=\"quay-repo-security-scan-progress\">\n <Progress />\n </span>\n );\n }\n\n if (rowData.securityStatus === 'queued') {\n return (\n <Tooltip title=\"The manifest for this tag is queued to be scanned for vulnerabilities\">\n <span data-testid=\"quay-repo-queued-for-scan\">Queued</span>\n </Tooltip>\n );\n }\n\n if (rowData.securityStatus === 'unsupported') {\n return (\n <Tooltip title=\"The manifest for this tag has an operating system or package manager unsupported by Quay Security Scanner\">\n <span data-testid=\"quay-repo-security-scan-unsupported\">\n Unsupported\n </span>\n </Tooltip>\n );\n }\n\n const tagManifest = rowData.manifest_digest_raw;\n const retStr = vulnerabilitySummary(rowData.securityDetails);\n return (\n <Link\n data-testid={`${rowData.name}-security-scan`}\n to={`tag/${tagManifest}`}\n >\n {retStr}\n </Link>\n );\n },\n id: 'securityScan',\n customSort: (a: QuayTagData, b: QuayTagData) =>\n securityScanComparator(a, b),\n },\n {\n title: 'Size',\n field: 'size',\n type: 'numeric',\n customSort: (a: QuayTagData, b: QuayTagData) => a.rawSize - b.rawSize,\n },\n {\n title: 'Expires',\n field: 'expiration',\n type: 'date',\n emptyValue: <i>Never</i>,\n },\n {\n title: 'Manifest',\n field: 'manifest_digest',\n type: 'string',\n customSort: (a: QuayTagData, b: QuayTagData) =>\n a.manifest_digest_raw.localeCompare(b.manifest_digest_raw),\n },\n];\n\nexport const useStyles = makeStyles(theme => ({\n empty: {\n padding: theme.spacing(2),\n display: 'flex',\n justifyContent: 'center',\n },\n}));\n"],"names":[],"mappings":";;;;;;AAyBO,MAAM,OAAsC,GAAA;AAAA,EACjD;AAAA,IACE,KAAO,EAAA,KAAA;AAAA,IACP,KAAO,EAAA,MAAA;AAAA,IACP,IAAM,EAAA,QAAA;AAAA,IACN,SAAW,EAAA;AAAA,GACb;AAAA,EACA;AAAA,IACE,KAAO,EAAA,eAAA;AAAA,IACP,KAAO,EAAA,eAAA;AAAA,IACP,IAAM,EAAA;AAAA,GACR;AAAA,EACA;AAAA,IACE,KAAO,EAAA,eAAA;AAAA,IACP,KAAO,EAAA,cAAA;AAAA,IACP,MAAA,EAAQ,CAAC,OAA0C,KAAA;AACjD,MAAA,IAAI,CAAC,OAAA,CAAQ,cAAkB,IAAA,CAAC,QAAQ,eAAiB,EAAA;AACvD,QAAA,2CACG,MAAK,EAAA,EAAA,aAAA,EAAY,kCAChB,EAAA,kBAAA,KAAA,CAAA,aAAA,CAAC,cAAS,CACZ,CAAA;AAAA;AAIJ,MAAI,IAAA,OAAA,CAAQ,mBAAmB,QAAU,EAAA;AACvC,QACE,uBAAA,KAAA,CAAA,aAAA,CAAC,WAAQ,KAAM,EAAA,uEAAA,EAAA,sCACZ,MAAK,EAAA,EAAA,aAAA,EAAY,2BAA4B,EAAA,EAAA,QAAM,CACtD,CAAA;AAAA;AAIJ,MAAI,IAAA,OAAA,CAAQ,mBAAmB,aAAe,EAAA;AAC5C,QACE,uBAAA,KAAA,CAAA,aAAA,CAAC,WAAQ,KAAM,EAAA,2GAAA,EAAA,sCACZ,MAAK,EAAA,EAAA,aAAA,EAAY,qCAAsC,EAAA,EAAA,aAExD,CACF,CAAA;AAAA;AAIJ,MAAA,MAAM,cAAc,OAAQ,CAAA,mBAAA;AAC5B,MAAM,MAAA,MAAA,GAAS,oBAAqB,CAAA,OAAA,CAAQ,eAAe,CAAA;AAC3D,MACE,uBAAA,KAAA,CAAA,aAAA;AAAA,QAAC,IAAA;AAAA,QAAA;AAAA,UACC,aAAA,EAAa,CAAG,EAAA,OAAA,CAAQ,IAAI,CAAA,cAAA,CAAA;AAAA,UAC5B,EAAA,EAAI,OAAO,WAAW,CAAA;AAAA,SAAA;AAAA,QAErB;AAAA,OACH;AAAA,KAEJ;AAAA,IACA,EAAI,EAAA,cAAA;AAAA,IACJ,YAAY,CAAC,CAAA,EAAgB,CAC3B,KAAA,sBAAA,CAAuB,GAAG,CAAC;AAAA,GAC/B;AAAA,EACA;AAAA,IACE,KAAO,EAAA,MAAA;AAAA,IACP,KAAO,EAAA,MAAA;AAAA,IACP,IAAM,EAAA,SAAA;AAAA,IACN,YAAY,CAAC,CAAA,EAAgB,CAAmB,KAAA,CAAA,CAAE,UAAU,CAAE,CAAA;AAAA,GAChE;AAAA,EACA;AAAA,IACE,KAAO,EAAA,SAAA;AAAA,IACP,KAAO,EAAA,YAAA;AAAA,IACP,IAAM,EAAA,MAAA;AAAA,IACN,UAAA,kBAAa,KAAA,CAAA,aAAA,CAAA,GAAA,EAAA,IAAA,EAAE,OAAK;AAAA,GACtB;AAAA,EACA;AAAA,IACE,KAAO,EAAA,UAAA;AAAA,IACP,KAAO,EAAA,iBAAA;AAAA,IACP,IAAM,EAAA,QAAA;AAAA,IACN,UAAA,EAAY,CAAC,CAAgB,EAAA,CAAA,KAC3B,EAAE,mBAAoB,CAAA,aAAA,CAAc,EAAE,mBAAmB;AAAA;AAE/D;AAEa,MAAA,SAAA,GAAY,WAAW,CAAU,KAAA,MAAA;AAAA,EAC5C,KAAO,EAAA;AAAA,IACL,OAAA,EAAS,KAAM,CAAA,OAAA,CAAQ,CAAC,CAAA;AAAA,IACxB,OAAS,EAAA,MAAA;AAAA,IACT,cAAgB,EAAA;AAAA;AAEpB,CAAE,CAAA;;;;"}
1
+ {"version":3,"file":"tableHeading.esm.js","sources":["../../../src/components/QuayRepository/tableHeading.tsx"],"sourcesContent":["/*\n * Copyright 2024 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 type { ReactNode } from 'react';\n\nimport { Link, Progress, TableColumn } from '@backstage/core-components';\n\nimport { Tooltip } from '@material-ui/core';\nimport makeStyles from '@material-ui/core/styles/makeStyles';\n\nimport { securityScanComparator, vulnerabilitySummary } from '../../lib/utils';\nimport type { QuayTagData } from '../../types';\n\nexport const columns: TableColumn<QuayTagData>[] = [\n {\n title: 'Tag',\n field: 'name',\n type: 'string',\n highlight: true,\n },\n {\n title: 'Last Modified',\n field: 'last_modified',\n type: 'date',\n },\n {\n title: 'Security Scan',\n field: 'securityScan',\n render: (rowData: QuayTagData): ReactNode => {\n if (!rowData.securityStatus && !rowData.securityDetails) {\n return (\n <span data-testid=\"quay-repo-security-scan-progress\">\n <Progress />\n </span>\n );\n }\n\n if (rowData.securityStatus === 'queued') {\n return (\n <Tooltip title=\"The manifest for this tag is queued to be scanned for vulnerabilities\">\n <span data-testid=\"quay-repo-queued-for-scan\">Queued</span>\n </Tooltip>\n );\n }\n\n if (rowData.securityStatus === 'unsupported') {\n return (\n <Tooltip title=\"The manifest for this tag has an operating system or package manager unsupported by Quay Security Scanner\">\n <span data-testid=\"quay-repo-security-scan-unsupported\">\n Unsupported\n </span>\n </Tooltip>\n );\n }\n\n const tagManifest = rowData.manifest_digest_raw;\n const retStr = vulnerabilitySummary(rowData.securityDetails);\n return (\n <Link\n data-testid={`${rowData.name}-security-scan`}\n to={`tag/${tagManifest}`}\n >\n {retStr}\n </Link>\n );\n },\n id: 'securityScan',\n customSort: (a: QuayTagData, b: QuayTagData) =>\n securityScanComparator(a, b),\n },\n {\n title: 'Size',\n field: 'size',\n type: 'numeric',\n customSort: (a: QuayTagData, b: QuayTagData) => a.rawSize - b.rawSize,\n },\n {\n title: 'Expires',\n field: 'expiration',\n type: 'date',\n emptyValue: <i>Never</i>,\n },\n {\n title: 'Manifest',\n field: 'manifest_digest',\n type: 'string',\n customSort: (a: QuayTagData, b: QuayTagData) =>\n a.manifest_digest_raw.localeCompare(b.manifest_digest_raw),\n },\n];\n\nexport const useStyles = makeStyles(theme => ({\n empty: {\n padding: theme.spacing(2),\n display: 'flex',\n justifyContent: 'center',\n },\n}));\n"],"names":[],"mappings":";;;;;;AAyBO,MAAM,OAAsC,GAAA;AAAA,EACjD;AAAA,IACE,KAAO,EAAA,KAAA;AAAA,IACP,KAAO,EAAA,MAAA;AAAA,IACP,IAAM,EAAA,QAAA;AAAA,IACN,SAAW,EAAA;AAAA,GACb;AAAA,EACA;AAAA,IACE,KAAO,EAAA,eAAA;AAAA,IACP,KAAO,EAAA,eAAA;AAAA,IACP,IAAM,EAAA;AAAA,GACR;AAAA,EACA;AAAA,IACE,KAAO,EAAA,eAAA;AAAA,IACP,KAAO,EAAA,cAAA;AAAA,IACP,MAAA,EAAQ,CAAC,OAAoC,KAAA;AAC3C,MAAA,IAAI,CAAC,OAAA,CAAQ,cAAkB,IAAA,CAAC,QAAQ,eAAiB,EAAA;AACvD,QAAA,2BACG,MAAK,EAAA,EAAA,aAAA,EAAY,kCAChB,EAAA,QAAA,kBAAA,GAAA,CAAC,YAAS,CACZ,EAAA,CAAA;AAAA;AAIJ,MAAI,IAAA,OAAA,CAAQ,mBAAmB,QAAU,EAAA;AACvC,QACE,uBAAA,GAAA,CAAC,WAAQ,KAAM,EAAA,uEAAA,EACb,8BAAC,MAAK,EAAA,EAAA,aAAA,EAAY,2BAA4B,EAAA,QAAA,EAAA,QAAA,EAAM,CACtD,EAAA,CAAA;AAAA;AAIJ,MAAI,IAAA,OAAA,CAAQ,mBAAmB,aAAe,EAAA;AAC5C,QACE,uBAAA,GAAA,CAAC,WAAQ,KAAM,EAAA,2GAAA,EACb,8BAAC,MAAK,EAAA,EAAA,aAAA,EAAY,qCAAsC,EAAA,QAAA,EAAA,aAAA,EAExD,CACF,EAAA,CAAA;AAAA;AAIJ,MAAA,MAAM,cAAc,OAAQ,CAAA,mBAAA;AAC5B,MAAM,MAAA,MAAA,GAAS,oBAAqB,CAAA,OAAA,CAAQ,eAAe,CAAA;AAC3D,MACE,uBAAA,GAAA;AAAA,QAAC,IAAA;AAAA,QAAA;AAAA,UACC,aAAA,EAAa,CAAG,EAAA,OAAA,CAAQ,IAAI,CAAA,cAAA,CAAA;AAAA,UAC5B,EAAA,EAAI,OAAO,WAAW,CAAA,CAAA;AAAA,UAErB,QAAA,EAAA;AAAA;AAAA,OACH;AAAA,KAEJ;AAAA,IACA,EAAI,EAAA,cAAA;AAAA,IACJ,YAAY,CAAC,CAAA,EAAgB,CAC3B,KAAA,sBAAA,CAAuB,GAAG,CAAC;AAAA,GAC/B;AAAA,EACA;AAAA,IACE,KAAO,EAAA,MAAA;AAAA,IACP,KAAO,EAAA,MAAA;AAAA,IACP,IAAM,EAAA,SAAA;AAAA,IACN,YAAY,CAAC,CAAA,EAAgB,CAAmB,KAAA,CAAA,CAAE,UAAU,CAAE,CAAA;AAAA,GAChE;AAAA,EACA;AAAA,IACE,KAAO,EAAA,SAAA;AAAA,IACP,KAAO,EAAA,YAAA;AAAA,IACP,IAAM,EAAA,MAAA;AAAA,IACN,UAAA,kBAAa,GAAA,CAAA,GAAA,EAAA,EAAE,QAAK,EAAA,OAAA,EAAA;AAAA,GACtB;AAAA,EACA;AAAA,IACE,KAAO,EAAA,UAAA;AAAA,IACP,KAAO,EAAA,iBAAA;AAAA,IACP,IAAM,EAAA,QAAA;AAAA,IACN,UAAA,EAAY,CAAC,CAAgB,EAAA,CAAA,KAC3B,EAAE,mBAAoB,CAAA,aAAA,CAAc,EAAE,mBAAmB;AAAA;AAE/D;AAEa,MAAA,SAAA,GAAY,WAAW,CAAU,KAAA,MAAA;AAAA,EAC5C,KAAO,EAAA;AAAA,IACL,OAAA,EAAS,KAAM,CAAA,OAAA,CAAQ,CAAC,CAAA;AAAA,IACxB,OAAS,EAAA,MAAA;AAAA,IACT,cAAgB,EAAA;AAAA;AAEpB,CAAE,CAAA;;;;"}
@@ -1,4 +1,4 @@
1
- import React from 'react';
1
+ import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
2
2
  import { Link, Table } from '@backstage/core-components';
3
3
  import { makeStyles, TableContainer, TableHead } from '@material-ui/core';
4
4
  import KeyboardBackspaceIcon from '@material-ui/icons/KeyboardBackspace';
@@ -13,7 +13,10 @@ const columns = [
13
13
  title: "Advisory",
14
14
  field: "name",
15
15
  render: (rowData) => {
16
- return /* @__PURE__ */ React.createElement("div", { style: { display: "flex", alignItems: "center" } }, rowData.Name, rowData.Link.trim().length > 0 ? /* @__PURE__ */ React.createElement(Link, { to: getVulnerabilityLink(rowData.Link) }, /* @__PURE__ */ React.createElement(LinkIcon, { style: { marginLeft: "0.5rem" } })) : null);
16
+ return /* @__PURE__ */ jsxs("div", { style: { display: "flex", alignItems: "center" }, children: [
17
+ rowData.Name,
18
+ rowData.Link.trim().length > 0 ? /* @__PURE__ */ jsx(Link, { to: getVulnerabilityLink(rowData.Link), children: /* @__PURE__ */ jsx(LinkIcon, { style: { marginLeft: "0.5rem" } }) }) : null
19
+ ] });
17
20
  },
18
21
  customSort: (a, b) => a.Name.localeCompare(b.Name, "en")
19
22
  },
@@ -26,15 +29,18 @@ const columns = [
26
29
  return severityA - severityB;
27
30
  },
28
31
  render: (rowData) => {
29
- return /* @__PURE__ */ React.createElement("div", { style: { display: "flex", alignItems: "center" } }, /* @__PURE__ */ React.createElement(
30
- WarningIcon,
31
- {
32
- htmlColor: SEVERITY_COLORS[rowData.Severity],
33
- style: {
34
- marginRight: "0.5rem"
32
+ return /* @__PURE__ */ jsxs("div", { style: { display: "flex", alignItems: "center" }, children: [
33
+ /* @__PURE__ */ jsx(
34
+ WarningIcon,
35
+ {
36
+ htmlColor: SEVERITY_COLORS[rowData.Severity],
37
+ style: {
38
+ marginRight: "0.5rem"
39
+ }
35
40
  }
36
- }
37
- ), /* @__PURE__ */ React.createElement("span", null, rowData.Severity));
41
+ ),
42
+ /* @__PURE__ */ jsx("span", { children: rowData.Severity })
43
+ ] });
38
44
  }
39
45
  },
40
46
  {
@@ -51,7 +57,7 @@ const columns = [
51
57
  title: "Fixed By",
52
58
  field: "FixedBy",
53
59
  render: (rowData) => {
54
- return /* @__PURE__ */ React.createElement(React.Fragment, null, rowData.FixedBy.length > 0 ? /* @__PURE__ */ React.createElement("span", null, rowData.FixedBy) : "(None)");
60
+ return /* @__PURE__ */ jsx(Fragment, { children: rowData.FixedBy.length > 0 ? /* @__PURE__ */ jsx("span", { children: rowData.FixedBy }) : "(None)" });
55
61
  }
56
62
  }
57
63
  ];
@@ -93,14 +99,20 @@ const QuayTagDetails = ({
93
99
  const severityB = VulnerabilityOrder[b.Severity];
94
100
  return severityA - severityB;
95
101
  });
96
- return /* @__PURE__ */ React.createElement(TableContainer, null, /* @__PURE__ */ React.createElement(TableHead, { className: classes.tableHead }, /* @__PURE__ */ React.createElement(Link, { to: rootLink(), className: classes.link }, /* @__PURE__ */ React.createElement(KeyboardBackspaceIcon, null), /* @__PURE__ */ React.createElement("span", { className: classes.linkText }, "Back to repository"))), /* @__PURE__ */ React.createElement(
97
- Table,
98
- {
99
- title: `Vulnerabilities for ${digest.substring(0, 17)}`,
100
- data: vulnerabilities,
101
- columns
102
- }
103
- ));
102
+ return /* @__PURE__ */ jsxs(TableContainer, { children: [
103
+ /* @__PURE__ */ jsx(TableHead, { className: classes.tableHead, children: /* @__PURE__ */ jsxs(Link, { to: rootLink(), className: classes.link, children: [
104
+ /* @__PURE__ */ jsx(KeyboardBackspaceIcon, {}),
105
+ /* @__PURE__ */ jsx("span", { className: classes.linkText, children: "Back to repository" })
106
+ ] }) }),
107
+ /* @__PURE__ */ jsx(
108
+ Table,
109
+ {
110
+ title: `Vulnerabilities for ${digest.substring(0, 17)}`,
111
+ data: vulnerabilities,
112
+ columns
113
+ }
114
+ )
115
+ ] });
104
116
  };
105
117
 
106
118
  export { QuayTagDetails, QuayTagDetails as default };
@@ -1 +1 @@
1
- {"version":3,"file":"component.esm.js","sources":["../../../src/components/QuayTagDetails/component.tsx"],"sourcesContent":["/*\n * Copyright 2024 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 from 'react';\n\nimport { Link, Table, TableColumn } from '@backstage/core-components';\nimport type { RouteFunc } from '@backstage/core-plugin-api';\n\nimport { makeStyles, TableContainer, TableHead } from '@material-ui/core';\nimport KeyboardBackspaceIcon from '@material-ui/icons/KeyboardBackspace';\nimport LinkIcon from '@material-ui/icons/Link';\nimport WarningIcon from '@material-ui/icons/Warning';\n\nimport { SEVERITY_COLORS } from '../../lib/utils';\nimport {\n Layer,\n Vulnerability,\n VulnerabilityListItem,\n VulnerabilityOrder,\n} from '../../types';\n\ntype QuayTagDetailsProps = {\n layer: Layer;\n digest: string;\n rootLink: RouteFunc<undefined>;\n};\n\n// from: https://github.com/quay/quay/blob/f1d85588157eababc3cbf789002c5db521dbd616/web/src/routes/TagDetails/SecurityReport/SecurityReportTable.tsx#L43\nconst getVulnerabilityLink = (link: string) => link.split(' ')[0];\n\nconst columns: TableColumn<VulnerabilityListItem>[] = [\n {\n title: 'Advisory',\n field: 'name',\n render: (rowData: VulnerabilityListItem): React.ReactNode => {\n return (\n <div style={{ display: 'flex', alignItems: 'center' }}>\n {rowData.Name}\n {rowData.Link.trim().length > 0 ? (\n <Link to={getVulnerabilityLink(rowData.Link)}>\n <LinkIcon style={{ marginLeft: '0.5rem' }} />\n </Link>\n ) : null}\n </div>\n );\n },\n customSort: (a: VulnerabilityListItem, b: VulnerabilityListItem) =>\n a.Name.localeCompare(b.Name, 'en'),\n },\n {\n title: 'Severity',\n field: 'Severity',\n customSort: (a: VulnerabilityListItem, b: VulnerabilityListItem) => {\n const severityA = VulnerabilityOrder[a.Severity];\n const severityB = VulnerabilityOrder[b.Severity];\n\n return severityA - severityB;\n },\n render: (rowData: VulnerabilityListItem): React.ReactNode => {\n return (\n <div style={{ display: 'flex', alignItems: 'center' }}>\n <WarningIcon\n htmlColor={SEVERITY_COLORS[rowData.Severity]}\n style={{\n marginRight: '0.5rem',\n }}\n />\n <span>{rowData.Severity}</span>\n </div>\n );\n },\n },\n {\n title: 'Package Name',\n field: 'PackageName',\n type: 'string',\n },\n {\n title: 'Current Version',\n field: 'CurrentVersion',\n type: 'string',\n },\n {\n title: 'Fixed By',\n field: 'FixedBy',\n render: (rowData: VulnerabilityListItem): React.ReactNode => {\n return (\n <>\n {rowData.FixedBy.length > 0 ? (\n <span>{rowData.FixedBy}</span>\n ) : (\n '(None)'\n )}\n </>\n );\n },\n },\n];\n\nconst useStyles = makeStyles({\n link: {\n display: 'flex',\n alignItems: 'center',\n },\n linkText: {\n marginLeft: '0.5rem',\n fontSize: '1.1rem',\n },\n tableHead: {\n display: 'flex',\n alignItems: 'center',\n marginBottom: '1rem',\n },\n});\n\nexport const QuayTagDetails = ({\n layer,\n rootLink,\n digest,\n}: QuayTagDetailsProps) => {\n const classes = useStyles();\n const vulnerabilities = layer.Features.filter(\n feat => typeof feat.Vulnerabilities !== 'undefined',\n )\n .map(feature => {\n // TS doesn't seem to register this list as never being undefined from the above filter\n // so we cast it into the list\n // NOSONAR - irrelevant as per above comment\n return (feature.Vulnerabilities as Vulnerability[]).map(\n (v: Vulnerability): VulnerabilityListItem => {\n return {\n ...v,\n PackageName: feature.Name,\n CurrentVersion: feature.Version,\n };\n },\n );\n })\n .flat()\n .sort((a, b) => {\n const severityA = VulnerabilityOrder[a.Severity];\n const severityB = VulnerabilityOrder[b.Severity];\n\n return severityA - severityB;\n });\n\n return (\n <TableContainer>\n <TableHead className={classes.tableHead}>\n <Link to={rootLink()} className={classes.link}>\n <KeyboardBackspaceIcon />\n <span className={classes.linkText}>Back to repository</span>\n </Link>\n </TableHead>\n <Table\n title={`Vulnerabilities for ${digest.substring(0, 17)}`}\n data={vulnerabilities}\n columns={columns}\n />\n </TableContainer>\n );\n};\n\nexport default QuayTagDetails;\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"component.esm.js","sources":["../../../src/components/QuayTagDetails/component.tsx"],"sourcesContent":["/*\n * Copyright 2024 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 type { ReactNode } from 'react';\n\nimport { Link, Table, TableColumn } from '@backstage/core-components';\nimport type { RouteFunc } from '@backstage/core-plugin-api';\n\nimport { makeStyles, TableContainer, TableHead } from '@material-ui/core';\nimport KeyboardBackspaceIcon from '@material-ui/icons/KeyboardBackspace';\nimport LinkIcon from '@material-ui/icons/Link';\nimport WarningIcon from '@material-ui/icons/Warning';\n\nimport { SEVERITY_COLORS } from '../../lib/utils';\nimport {\n Layer,\n Vulnerability,\n VulnerabilityListItem,\n VulnerabilityOrder,\n} from '../../types';\n\ntype QuayTagDetailsProps = {\n layer: Layer;\n digest: string;\n rootLink: RouteFunc<undefined>;\n};\n\n// from: https://github.com/quay/quay/blob/f1d85588157eababc3cbf789002c5db521dbd616/web/src/routes/TagDetails/SecurityReport/SecurityReportTable.tsx#L43\nconst getVulnerabilityLink = (link: string) => link.split(' ')[0];\n\nconst columns: TableColumn<VulnerabilityListItem>[] = [\n {\n title: 'Advisory',\n field: 'name',\n render: (rowData: VulnerabilityListItem): ReactNode => {\n return (\n <div style={{ display: 'flex', alignItems: 'center' }}>\n {rowData.Name}\n {rowData.Link.trim().length > 0 ? (\n <Link to={getVulnerabilityLink(rowData.Link)}>\n <LinkIcon style={{ marginLeft: '0.5rem' }} />\n </Link>\n ) : null}\n </div>\n );\n },\n customSort: (a: VulnerabilityListItem, b: VulnerabilityListItem) =>\n a.Name.localeCompare(b.Name, 'en'),\n },\n {\n title: 'Severity',\n field: 'Severity',\n customSort: (a: VulnerabilityListItem, b: VulnerabilityListItem) => {\n const severityA = VulnerabilityOrder[a.Severity];\n const severityB = VulnerabilityOrder[b.Severity];\n\n return severityA - severityB;\n },\n render: (rowData: VulnerabilityListItem): ReactNode => {\n return (\n <div style={{ display: 'flex', alignItems: 'center' }}>\n <WarningIcon\n htmlColor={SEVERITY_COLORS[rowData.Severity]}\n style={{\n marginRight: '0.5rem',\n }}\n />\n <span>{rowData.Severity}</span>\n </div>\n );\n },\n },\n {\n title: 'Package Name',\n field: 'PackageName',\n type: 'string',\n },\n {\n title: 'Current Version',\n field: 'CurrentVersion',\n type: 'string',\n },\n {\n title: 'Fixed By',\n field: 'FixedBy',\n render: (rowData: VulnerabilityListItem): ReactNode => {\n return (\n <>\n {rowData.FixedBy.length > 0 ? (\n <span>{rowData.FixedBy}</span>\n ) : (\n '(None)'\n )}\n </>\n );\n },\n },\n];\n\nconst useStyles = makeStyles({\n link: {\n display: 'flex',\n alignItems: 'center',\n },\n linkText: {\n marginLeft: '0.5rem',\n fontSize: '1.1rem',\n },\n tableHead: {\n display: 'flex',\n alignItems: 'center',\n marginBottom: '1rem',\n },\n});\n\nexport const QuayTagDetails = ({\n layer,\n rootLink,\n digest,\n}: QuayTagDetailsProps) => {\n const classes = useStyles();\n const vulnerabilities = layer.Features.filter(\n feat => typeof feat.Vulnerabilities !== 'undefined',\n )\n .map(feature => {\n // TS doesn't seem to register this list as never being undefined from the above filter\n // so we cast it into the list\n // NOSONAR - irrelevant as per above comment\n return (feature.Vulnerabilities as Vulnerability[]).map(\n (v: Vulnerability): VulnerabilityListItem => {\n return {\n ...v,\n PackageName: feature.Name,\n CurrentVersion: feature.Version,\n };\n },\n );\n })\n .flat()\n .sort((a, b) => {\n const severityA = VulnerabilityOrder[a.Severity];\n const severityB = VulnerabilityOrder[b.Severity];\n\n return severityA - severityB;\n });\n\n return (\n <TableContainer>\n <TableHead className={classes.tableHead}>\n <Link to={rootLink()} className={classes.link}>\n <KeyboardBackspaceIcon />\n <span className={classes.linkText}>Back to repository</span>\n </Link>\n </TableHead>\n <Table\n title={`Vulnerabilities for ${digest.substring(0, 17)}`}\n data={vulnerabilities}\n columns={columns}\n />\n </TableContainer>\n );\n};\n\nexport default QuayTagDetails;\n"],"names":[],"mappings":"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"}
@@ -1,4 +1,4 @@
1
- import React from 'react';
1
+ import { jsx } from 'react/jsx-runtime';
2
2
  import { useParams } from 'react-router-dom';
3
3
  import { Progress, ErrorPanel } from '@backstage/core-components';
4
4
  import { useRouteRef } from '@backstage/core-plugin-api';
@@ -18,15 +18,15 @@ const QuayTagPage = () => {
18
18
  }
19
19
  const { loading, value } = useTagDetails(organization, repository, digest);
20
20
  if (!hasViewPermission) {
21
- return /* @__PURE__ */ React.createElement(PermissionAlert, null);
21
+ return /* @__PURE__ */ jsx(PermissionAlert, {});
22
22
  }
23
23
  if (loading) {
24
- return /* @__PURE__ */ React.createElement("div", { "data-testid": "quay-tag-page-progress" }, /* @__PURE__ */ React.createElement(Progress, { variant: "query" }));
24
+ return /* @__PURE__ */ jsx("div", { "data-testid": "quay-tag-page-progress", children: /* @__PURE__ */ jsx(Progress, { variant: "query" }) });
25
25
  }
26
26
  if (!value?.data) {
27
- return /* @__PURE__ */ React.createElement(ErrorPanel, { error: new Error("no digest") });
27
+ return /* @__PURE__ */ jsx(ErrorPanel, { error: new Error("no digest") });
28
28
  }
29
- return /* @__PURE__ */ React.createElement(
29
+ return /* @__PURE__ */ jsx(
30
30
  QuayTagDetails,
31
31
  {
32
32
  rootLink,
@@ -1 +1 @@
1
- {"version":3,"file":"component.esm.js","sources":["../../../src/components/QuayTagPage/component.tsx"],"sourcesContent":["/*\n * Copyright 2024 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 from 'react';\nimport { useParams } from 'react-router-dom';\n\nimport { ErrorPanel, Progress } from '@backstage/core-components';\nimport { useRouteRef } from '@backstage/core-plugin-api';\n\nimport { useRepository, useTagDetails } from '../../hooks';\nimport { useQuayViewPermission } from '../../hooks/useQuayViewPermission';\nimport { rootRouteRef } from '../../routes';\nimport PermissionAlert from '../PermissionAlert/PermissionAlert';\nimport { QuayTagDetails } from '../QuayTagDetails';\n\nexport const QuayTagPage = () => {\n const rootLink = useRouteRef(rootRouteRef);\n const { repository, organization } = useRepository();\n const { digest } = useParams();\n const hasViewPermission = useQuayViewPermission();\n if (!digest) {\n throw new Error('digest is not defined');\n }\n const { loading, value } = useTagDetails(organization, repository, digest);\n\n if (!hasViewPermission) {\n return <PermissionAlert />;\n }\n\n if (loading) {\n return (\n <div data-testid=\"quay-tag-page-progress\">\n <Progress variant=\"query\" />\n </div>\n );\n }\n if (!value?.data) {\n return <ErrorPanel error={new Error('no digest')} />;\n }\n\n return (\n <QuayTagDetails\n rootLink={rootLink}\n layer={value.data.Layer}\n digest={digest}\n />\n );\n};\n\nexport default QuayTagPage;\n"],"names":[],"mappings":";;;;;;;;;;AA2BO,MAAM,cAAc,MAAM;AAC/B,EAAM,MAAA,QAAA,GAAW,YAAY,YAAY,CAAA;AACzC,EAAA,MAAM,EAAE,UAAA,EAAY,YAAa,EAAA,GAAI,aAAc,EAAA;AACnD,EAAM,MAAA,EAAE,MAAO,EAAA,GAAI,SAAU,EAAA;AAC7B,EAAA,MAAM,oBAAoB,qBAAsB,EAAA;AAChD,EAAA,IAAI,CAAC,MAAQ,EAAA;AACX,IAAM,MAAA,IAAI,MAAM,uBAAuB,CAAA;AAAA;AAEzC,EAAA,MAAM,EAAE,OAAS,EAAA,KAAA,KAAU,aAAc,CAAA,YAAA,EAAc,YAAY,MAAM,CAAA;AAEzE,EAAA,IAAI,CAAC,iBAAmB,EAAA;AACtB,IAAA,2CAAQ,eAAgB,EAAA,IAAA,CAAA;AAAA;AAG1B,EAAA,IAAI,OAAS,EAAA;AACX,IACE,uBAAA,KAAA,CAAA,aAAA,CAAC,SAAI,aAAY,EAAA,wBAAA,EAAA,sCACd,QAAS,EAAA,EAAA,OAAA,EAAQ,SAAQ,CAC5B,CAAA;AAAA;AAGJ,EAAI,IAAA,CAAC,OAAO,IAAM,EAAA;AAChB,IAAA,2CAAQ,UAAW,EAAA,EAAA,KAAA,EAAO,IAAI,KAAA,CAAM,WAAW,CAAG,EAAA,CAAA;AAAA;AAGpD,EACE,uBAAA,KAAA,CAAA,aAAA;AAAA,IAAC,cAAA;AAAA,IAAA;AAAA,MACC,QAAA;AAAA,MACA,KAAA,EAAO,MAAM,IAAK,CAAA,KAAA;AAAA,MAClB;AAAA;AAAA,GACF;AAEJ;;;;"}
1
+ {"version":3,"file":"component.esm.js","sources":["../../../src/components/QuayTagPage/component.tsx"],"sourcesContent":["/*\n * Copyright 2024 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 { useParams } from 'react-router-dom';\n\nimport { ErrorPanel, Progress } from '@backstage/core-components';\nimport { useRouteRef } from '@backstage/core-plugin-api';\n\nimport { useRepository, useTagDetails } from '../../hooks';\nimport { useQuayViewPermission } from '../../hooks/useQuayViewPermission';\nimport { rootRouteRef } from '../../routes';\nimport PermissionAlert from '../PermissionAlert/PermissionAlert';\nimport { QuayTagDetails } from '../QuayTagDetails';\n\nexport const QuayTagPage = () => {\n const rootLink = useRouteRef(rootRouteRef);\n const { repository, organization } = useRepository();\n const { digest } = useParams();\n const hasViewPermission = useQuayViewPermission();\n if (!digest) {\n throw new Error('digest is not defined');\n }\n const { loading, value } = useTagDetails(organization, repository, digest);\n\n if (!hasViewPermission) {\n return <PermissionAlert />;\n }\n\n if (loading) {\n return (\n <div data-testid=\"quay-tag-page-progress\">\n <Progress variant=\"query\" />\n </div>\n );\n }\n if (!value?.data) {\n return <ErrorPanel error={new Error('no digest')} />;\n }\n\n return (\n <QuayTagDetails\n rootLink={rootLink}\n layer={value.data.Layer}\n digest={digest}\n />\n );\n};\n\nexport default QuayTagPage;\n"],"names":[],"mappings":";;;;;;;;;;AA0BO,MAAM,cAAc,MAAM;AAC/B,EAAM,MAAA,QAAA,GAAW,YAAY,YAAY,CAAA;AACzC,EAAA,MAAM,EAAE,UAAA,EAAY,YAAa,EAAA,GAAI,aAAc,EAAA;AACnD,EAAM,MAAA,EAAE,MAAO,EAAA,GAAI,SAAU,EAAA;AAC7B,EAAA,MAAM,oBAAoB,qBAAsB,EAAA;AAChD,EAAA,IAAI,CAAC,MAAQ,EAAA;AACX,IAAM,MAAA,IAAI,MAAM,uBAAuB,CAAA;AAAA;AAEzC,EAAA,MAAM,EAAE,OAAS,EAAA,KAAA,KAAU,aAAc,CAAA,YAAA,EAAc,YAAY,MAAM,CAAA;AAEzE,EAAA,IAAI,CAAC,iBAAmB,EAAA;AACtB,IAAA,2BAAQ,eAAgB,EAAA,EAAA,CAAA;AAAA;AAG1B,EAAA,IAAI,OAAS,EAAA;AACX,IACE,uBAAA,GAAA,CAAC,SAAI,aAAY,EAAA,wBAAA,EACf,8BAAC,QAAS,EAAA,EAAA,OAAA,EAAQ,SAAQ,CAC5B,EAAA,CAAA;AAAA;AAGJ,EAAI,IAAA,CAAC,OAAO,IAAM,EAAA;AAChB,IAAA,2BAAQ,UAAW,EAAA,EAAA,KAAA,EAAO,IAAI,KAAA,CAAM,WAAW,CAAG,EAAA,CAAA;AAAA;AAGpD,EACE,uBAAA,GAAA;AAAA,IAAC,cAAA;AAAA,IAAA;AAAA,MACC,QAAA;AAAA,MACA,KAAA,EAAO,MAAM,IAAK,CAAA,KAAA;AAAA,MAClB;AAAA;AAAA,GACF;AAEJ;;;;"}
@@ -1,4 +1,4 @@
1
- import React from 'react';
1
+ import { jsxs, jsx } from 'react/jsx-runtime';
2
2
  import { Routes, Route } from 'react-router-dom';
3
3
  import { QUAY_ANNOTATION_REPOSITORY } from '../hooks/quay.esm.js';
4
4
  import { tagRouteRef } from '../routes.esm.js';
@@ -6,7 +6,10 @@ import { QuayRepository } from './QuayRepository/QuayRepository.esm.js';
6
6
  import { QuayTagPage } from './QuayTagPage/component.esm.js';
7
7
 
8
8
  const isQuayAvailable = (entity) => Boolean(entity?.metadata.annotations?.[QUAY_ANNOTATION_REPOSITORY]);
9
- const Router = () => /* @__PURE__ */ React.createElement(Routes, null, /* @__PURE__ */ React.createElement(Route, { path: "/", element: /* @__PURE__ */ React.createElement(QuayRepository, null) }), /* @__PURE__ */ React.createElement(Route, { path: tagRouteRef.path, element: /* @__PURE__ */ React.createElement(QuayTagPage, null) }));
9
+ const Router = () => /* @__PURE__ */ jsxs(Routes, { children: [
10
+ /* @__PURE__ */ jsx(Route, { path: "/", element: /* @__PURE__ */ jsx(QuayRepository, {}) }),
11
+ /* @__PURE__ */ jsx(Route, { path: tagRouteRef.path, element: /* @__PURE__ */ jsx(QuayTagPage, {}) })
12
+ ] });
10
13
 
11
14
  export { Router, isQuayAvailable };
12
15
  //# sourceMappingURL=Router.esm.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"Router.esm.js","sources":["../../src/components/Router.tsx"],"sourcesContent":["/*\n * Copyright 2024 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 from 'react';\nimport { Route, Routes } from 'react-router-dom';\n\nimport { Entity } from '@backstage/catalog-model';\n\nimport { QUAY_ANNOTATION_REPOSITORY } from '../hooks';\nimport { tagRouteRef } from '../routes';\nimport { QuayRepository } from './QuayRepository';\nimport { QuayTagPage } from './QuayTagPage';\n\n/** *\n * @public\n */\nexport const isQuayAvailable = (entity: Entity) =>\n Boolean(entity?.metadata.annotations?.[QUAY_ANNOTATION_REPOSITORY]);\n/**\n *\n * @public\n */\nexport const Router = () => (\n <Routes>\n <Route path=\"/\" element={<QuayRepository />} />\n <Route path={tagRouteRef.path} element={<QuayTagPage />} />\n </Routes>\n);\n"],"names":[],"mappings":";;;;;;;AA4Ba,MAAA,eAAA,GAAkB,CAAC,MAC9B,KAAA,OAAA,CAAQ,QAAQ,QAAS,CAAA,WAAA,GAAc,0BAA0B,CAAC;AAKvD,MAAA,MAAA,GAAS,sBACnB,KAAA,CAAA,aAAA,CAAA,MAAA,EAAA,IAAA,sCACE,KAAM,EAAA,EAAA,IAAA,EAAK,GAAI,EAAA,OAAA,kBAAU,KAAA,CAAA,aAAA,CAAA,cAAA,EAAA,IAAe,GAAI,CAC7C,kBAAA,KAAA,CAAA,aAAA,CAAC,SAAM,IAAM,EAAA,WAAA,CAAY,MAAM,OAAS,kBAAA,KAAA,CAAA,aAAA,CAAC,WAAY,EAAA,IAAA,CAAA,EAAI,CAC3D;;;;"}
1
+ {"version":3,"file":"Router.esm.js","sources":["../../src/components/Router.tsx"],"sourcesContent":["/*\n * Copyright 2024 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 { Route, Routes } from 'react-router-dom';\n\nimport { Entity } from '@backstage/catalog-model';\n\nimport { QUAY_ANNOTATION_REPOSITORY } from '../hooks';\nimport { tagRouteRef } from '../routes';\nimport { QuayRepository } from './QuayRepository';\nimport { QuayTagPage } from './QuayTagPage';\n\n/** *\n * @public\n */\nexport const isQuayAvailable = (entity: Entity) =>\n Boolean(entity?.metadata.annotations?.[QUAY_ANNOTATION_REPOSITORY]);\n/**\n *\n * @public\n */\nexport const Router = () => (\n <Routes>\n <Route path=\"/\" element={<QuayRepository />} />\n <Route path={tagRouteRef.path} element={<QuayTagPage />} />\n </Routes>\n);\n"],"names":[],"mappings":";;;;;;;AA2Ba,MAAA,eAAA,GAAkB,CAAC,MAC9B,KAAA,OAAA,CAAQ,QAAQ,QAAS,CAAA,WAAA,GAAc,0BAA0B,CAAC;AAKvD,MAAA,MAAA,GAAS,sBACpB,IAAA,CAAC,MACC,EAAA,EAAA,QAAA,EAAA;AAAA,kBAAA,GAAA,CAAC,SAAM,IAAK,EAAA,GAAA,EAAI,OAAS,kBAAA,GAAA,CAAC,kBAAe,CAAI,EAAA,CAAA;AAAA,kBAC7C,GAAA,CAAC,SAAM,IAAM,EAAA,WAAA,CAAY,MAAM,OAAS,kBAAA,GAAA,CAAC,eAAY,CAAI,EAAA;AAAA,CAC3D,EAAA;;;;"}
@@ -1,4 +1,5 @@
1
- import React, { useMemo } from 'react';
1
+ import { jsxs, jsx } from 'react/jsx-runtime';
2
+ import { useState, useMemo } from 'react';
2
3
  import { useAsync } from 'react-use';
3
4
  import { useApi } from '@backstage/core-plugin-api';
4
5
  import { useEntity } from '@backstage/plugin-catalog-react';
@@ -18,9 +19,9 @@ const useLocalStyles = makeStyles({
18
19
  });
19
20
  const useTags = (organization, repository) => {
20
21
  const quayClient = useApi(quayApiRef);
21
- const [tags, setTags] = React.useState([]);
22
- const [tagManifestLayers, setTagManifestLayers] = React.useState({});
23
- const [tagManifestStatuses, setTagManifestStatuses] = React.useState({});
22
+ const [tags, setTags] = useState([]);
23
+ const [tagManifestLayers, setTagManifestLayers] = useState({});
24
+ const [tagManifestStatuses, setTagManifestStatuses] = useState({});
24
25
  const localClasses = useLocalStyles();
25
26
  const fetchSecurityDetails = async (tag) => {
26
27
  const securityDetails = await quayClient.getSecurityDetails(
@@ -62,7 +63,10 @@ const useTags = (organization, repository) => {
62
63
  last_modified: formatDate(tag.last_modified),
63
64
  size: formatByteSize(tag.size),
64
65
  rawSize: tag.size,
65
- manifest_digest: /* @__PURE__ */ React.createElement(Box, { sx: { display: "flex", alignItems: "center" } }, /* @__PURE__ */ React.createElement(Chip, { label: hashFunc, className: localClasses.chip }), shortHash),
66
+ manifest_digest: /* @__PURE__ */ jsxs(Box, { sx: { display: "flex", alignItems: "center" }, children: [
67
+ /* @__PURE__ */ jsx(Chip, { label: hashFunc, className: localClasses.chip }),
68
+ shortHash
69
+ ] }),
66
70
  expiration: tag.expiration,
67
71
  securityDetails: tagManifestLayers[tag.manifest_digest],
68
72
  securityStatus: tagManifestStatuses[tag.manifest_digest],
@@ -1 +1 @@
1
- {"version":3,"file":"quay.esm.js","sources":["../../src/hooks/quay.tsx"],"sourcesContent":["/*\n * Copyright 2024 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, { useMemo } from 'react';\nimport { useAsync } from 'react-use';\n\nimport { Entity } from '@backstage/catalog-model';\nimport { useApi } from '@backstage/core-plugin-api';\nimport { useEntity } from '@backstage/plugin-catalog-react';\n\nimport { formatByteSize, formatDate } from '@janus-idp/shared-react';\nimport { Box, Chip, makeStyles } from '@material-ui/core';\n\nimport { quayApiRef } from '../api';\nimport { Layer, QuayTagData, Tag } from '../types';\n\nconst useLocalStyles = makeStyles({\n chip: {\n margin: 0,\n marginRight: '.2em',\n height: '1.5em',\n '& > span': {\n padding: '.3em',\n },\n },\n});\n\nexport const useTags = (organization: string, repository: string) => {\n const quayClient = useApi(quayApiRef);\n const [tags, setTags] = React.useState<Tag[]>([]);\n const [tagManifestLayers, setTagManifestLayers] = React.useState<\n Record<string, Layer>\n >({});\n const [tagManifestStatuses, setTagManifestStatuses] = React.useState<\n Record<string, string>\n >({});\n const localClasses = useLocalStyles();\n\n const fetchSecurityDetails = async (tag: Tag) => {\n const securityDetails = await quayClient.getSecurityDetails(\n organization,\n repository,\n tag.manifest_digest,\n );\n return securityDetails;\n };\n\n const { loading } = useAsync(async () => {\n const tagsResponse = await quayClient.getTags(organization, repository);\n Promise.all(\n tagsResponse.tags.map(async tag => {\n const securityDetails = await fetchSecurityDetails(tag);\n const securityData = securityDetails.data;\n const securityStatus = securityDetails.status;\n\n setTagManifestStatuses(prevState => ({\n ...prevState,\n [tag.manifest_digest]: securityStatus,\n }));\n\n if (securityData) {\n setTagManifestLayers(prevState => ({\n ...prevState,\n [tag.manifest_digest]: securityData.Layer,\n }));\n }\n }),\n );\n setTags(prevTags => [...prevTags, ...tagsResponse.tags]);\n return tagsResponse;\n });\n\n const data: QuayTagData[] = useMemo(() => {\n return Object.values(tags)?.map(tag => {\n const hashFunc = tag.manifest_digest.substring(0, 6);\n const shortHash = tag.manifest_digest.substring(7, 19);\n return {\n id: `${tag.manifest_digest}-${tag.name}`,\n name: tag.name,\n last_modified: formatDate(tag.last_modified),\n size: formatByteSize(tag.size),\n rawSize: tag.size,\n manifest_digest: (\n <Box sx={{ display: 'flex', alignItems: 'center' }}>\n <Chip label={hashFunc} className={localClasses.chip} />\n {shortHash}\n </Box>\n ),\n expiration: tag.expiration,\n securityDetails: tagManifestLayers[tag.manifest_digest],\n securityStatus: tagManifestStatuses[tag.manifest_digest],\n manifest_digest_raw: tag.manifest_digest,\n // is_manifest_list: tag.is_manifest_list,\n // reversion: tag.reversion,\n // start_ts: tag.start_ts,\n // end_ts: tag.end_ts,\n // manifest_list: tag.manifest_list,\n };\n });\n }, [tags, localClasses.chip, tagManifestLayers, tagManifestStatuses]);\n\n return { loading, data };\n};\n\nexport const QUAY_ANNOTATION_REPOSITORY = 'quay.io/repository-slug';\n\nexport const useQuayAppData = ({ entity }: { entity: Entity }) => {\n const repositorySlug =\n entity?.metadata.annotations?.[QUAY_ANNOTATION_REPOSITORY] ?? '';\n\n if (!repositorySlug) {\n throw new Error(\"'Quay' annotations are missing\");\n }\n return { repositorySlug };\n};\n\nexport const useRepository = () => {\n const { entity } = useEntity();\n const { repositorySlug } = useQuayAppData({ entity });\n const info = repositorySlug.split('/');\n\n const organization = info.shift() as 'string';\n const repository = info.join('/');\n return {\n organization,\n repository,\n };\n};\n\nexport const useTagDetails = (org: string, repo: string, digest: string) => {\n const quayClient = useApi(quayApiRef);\n const result = useAsync(async () => {\n const manifestLayer = await quayClient.getSecurityDetails(\n org,\n repo,\n digest,\n );\n return manifestLayer;\n });\n return result;\n};\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"quay.esm.js","sources":["../../src/hooks/quay.tsx"],"sourcesContent":["/*\n * Copyright 2024 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 { useMemo, useState } from 'react';\nimport { useAsync } from 'react-use';\n\nimport { Entity } from '@backstage/catalog-model';\nimport { useApi } from '@backstage/core-plugin-api';\nimport { useEntity } from '@backstage/plugin-catalog-react';\n\nimport { formatByteSize, formatDate } from '@janus-idp/shared-react';\nimport { Box, Chip, makeStyles } from '@material-ui/core';\n\nimport { quayApiRef } from '../api';\nimport { Layer, QuayTagData, Tag } from '../types';\n\nconst useLocalStyles = makeStyles({\n chip: {\n margin: 0,\n marginRight: '.2em',\n height: '1.5em',\n '& > span': {\n padding: '.3em',\n },\n },\n});\n\nexport const useTags = (organization: string, repository: string) => {\n const quayClient = useApi(quayApiRef);\n const [tags, setTags] = useState<Tag[]>([]);\n const [tagManifestLayers, setTagManifestLayers] = useState<\n Record<string, Layer>\n >({});\n const [tagManifestStatuses, setTagManifestStatuses] = useState<\n Record<string, string>\n >({});\n const localClasses = useLocalStyles();\n\n const fetchSecurityDetails = async (tag: Tag) => {\n const securityDetails = await quayClient.getSecurityDetails(\n organization,\n repository,\n tag.manifest_digest,\n );\n return securityDetails;\n };\n\n const { loading } = useAsync(async () => {\n const tagsResponse = await quayClient.getTags(organization, repository);\n Promise.all(\n tagsResponse.tags.map(async tag => {\n const securityDetails = await fetchSecurityDetails(tag);\n const securityData = securityDetails.data;\n const securityStatus = securityDetails.status;\n\n setTagManifestStatuses(prevState => ({\n ...prevState,\n [tag.manifest_digest]: securityStatus,\n }));\n\n if (securityData) {\n setTagManifestLayers(prevState => ({\n ...prevState,\n [tag.manifest_digest]: securityData.Layer,\n }));\n }\n }),\n );\n setTags(prevTags => [...prevTags, ...tagsResponse.tags]);\n return tagsResponse;\n });\n\n const data: QuayTagData[] = useMemo(() => {\n return Object.values(tags)?.map(tag => {\n const hashFunc = tag.manifest_digest.substring(0, 6);\n const shortHash = tag.manifest_digest.substring(7, 19);\n return {\n id: `${tag.manifest_digest}-${tag.name}`,\n name: tag.name,\n last_modified: formatDate(tag.last_modified),\n size: formatByteSize(tag.size),\n rawSize: tag.size,\n manifest_digest: (\n <Box sx={{ display: 'flex', alignItems: 'center' }}>\n <Chip label={hashFunc} className={localClasses.chip} />\n {shortHash}\n </Box>\n ),\n expiration: tag.expiration,\n securityDetails: tagManifestLayers[tag.manifest_digest],\n securityStatus: tagManifestStatuses[tag.manifest_digest],\n manifest_digest_raw: tag.manifest_digest,\n // is_manifest_list: tag.is_manifest_list,\n // reversion: tag.reversion,\n // start_ts: tag.start_ts,\n // end_ts: tag.end_ts,\n // manifest_list: tag.manifest_list,\n };\n });\n }, [tags, localClasses.chip, tagManifestLayers, tagManifestStatuses]);\n\n return { loading, data };\n};\n\nexport const QUAY_ANNOTATION_REPOSITORY = 'quay.io/repository-slug';\n\nexport const useQuayAppData = ({ entity }: { entity: Entity }) => {\n const repositorySlug =\n entity?.metadata.annotations?.[QUAY_ANNOTATION_REPOSITORY] ?? '';\n\n if (!repositorySlug) {\n throw new Error(\"'Quay' annotations are missing\");\n }\n return { repositorySlug };\n};\n\nexport const useRepository = () => {\n const { entity } = useEntity();\n const { repositorySlug } = useQuayAppData({ entity });\n const info = repositorySlug.split('/');\n\n const organization = info.shift() as 'string';\n const repository = info.join('/');\n return {\n organization,\n repository,\n };\n};\n\nexport const useTagDetails = (org: string, repo: string, digest: string) => {\n const quayClient = useApi(quayApiRef);\n const result = useAsync(async () => {\n const manifestLayer = await quayClient.getSecurityDetails(\n org,\n repo,\n digest,\n );\n return manifestLayer;\n });\n return result;\n};\n"],"names":[],"mappings":"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"}
package/dist/index.d.ts CHANGED
@@ -1,5 +1,4 @@
1
- /// <reference types="react" />
2
- import * as react from 'react';
1
+ import * as react_jsx_runtime from 'react/jsx-runtime';
3
2
  import * as _backstage_core_plugin_api from '@backstage/core-plugin-api';
4
3
  import { Entity } from '@backstage/catalog-model';
5
4
 
@@ -17,7 +16,7 @@ declare const quayPlugin: _backstage_core_plugin_api.BackstagePlugin<{
17
16
  *
18
17
  * @public
19
18
  */
20
- declare const QuayPage: () => react.JSX.Element;
19
+ declare const QuayPage: () => react_jsx_runtime.JSX.Element;
21
20
 
22
21
  /** *
23
22
  * @public
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@backstage-community/plugin-quay",
3
- "version": "1.19.2",
3
+ "version": "1.20.1",
4
4
  "main": "dist/index.esm.js",
5
5
  "types": "dist/index.d.ts",
6
6
  "license": "Apache-2.0",
@@ -37,14 +37,14 @@
37
37
  "ui-test": "start-server-and-test start localhost:3000 'playwright test'"
38
38
  },
39
39
  "dependencies": {
40
- "@backstage-community/plugin-quay-common": "^1.7.2",
40
+ "@backstage-community/plugin-quay-common": "^1.8.0",
41
41
  "@backstage/catalog-model": "^1.7.3",
42
- "@backstage/core-components": "^0.16.4",
43
- "@backstage/core-plugin-api": "^1.10.4",
42
+ "@backstage/core-components": "^0.17.1",
43
+ "@backstage/core-plugin-api": "^1.10.6",
44
44
  "@backstage/plugin-catalog-common": "^1.1.3",
45
- "@backstage/plugin-catalog-react": "^1.15.2",
46
- "@backstage/plugin-permission-react": "^0.4.31",
47
- "@backstage/theme": "^0.6.4",
45
+ "@backstage/plugin-catalog-react": "^1.17.0",
46
+ "@backstage/plugin-permission-react": "^0.4.33",
47
+ "@backstage/theme": "^0.6.5",
48
48
  "@janus-idp/shared-react": "^2.16.0",
49
49
  "@material-ui/core": "^4.12.2",
50
50
  "@material-ui/icons": "^4.11.3",
@@ -52,16 +52,16 @@
52
52
  "react-use": "^17.4.0"
53
53
  },
54
54
  "peerDependencies": {
55
- "react": "^16.13.1 || ^17.0.0 || ^18.0.0",
56
- "react-dom": "^16.13.1 || ^17.0.0 || ^18.0.0",
55
+ "react": "^17.0.0 || ^18.0.0",
56
+ "react-dom": "^17.0.0 || ^18.0.0",
57
57
  "react-router-dom": "^6.0.0"
58
58
  },
59
59
  "devDependencies": {
60
- "@backstage/cli": "^0.30.0",
61
- "@backstage/core-app-api": "^1.15.5",
62
- "@backstage/dev-utils": "^1.1.7",
63
- "@backstage/test-utils": "^1.7.5",
64
- "@playwright/test": "1.51.1",
60
+ "@backstage/cli": "^0.32.0",
61
+ "@backstage/core-app-api": "^1.16.1",
62
+ "@backstage/dev-utils": "^1.1.9",
63
+ "@backstage/test-utils": "^1.7.7",
64
+ "@playwright/test": "^1.52.0",
65
65
  "@redhat-developer/red-hat-developer-hub-theme": "0.4.0",
66
66
  "@testing-library/jest-dom": "^6.0.0",
67
67
  "@testing-library/react": "^15.0.0",
@@ -69,8 +69,8 @@
69
69
  "@types/react-dom": "^18.2.19",
70
70
  "cross-fetch": "4.0.0",
71
71
  "msw": "1.3.5",
72
- "react": "^16.13.1 || ^17.0.0 || ^18.0.0",
73
- "react-dom": "^16.13.1 || ^17.0.0 || ^18.0.0",
72
+ "react": "^17.0.0 || ^18.0.0",
73
+ "react-dom": "^17.0.0 || ^18.0.0",
74
74
  "react-router-dom": "^6.0.0",
75
75
  "start-server-and-test": "2.0.11"
76
76
  },
@@ -104,8 +104,8 @@
104
104
  "author": "Red Hat",
105
105
  "typesVersions": {
106
106
  "*": {
107
- "index": [
108
- "dist/index.d.ts"
107
+ "package.json": [
108
+ "package.json"
109
109
  ]
110
110
  }
111
111
  },