@red-hat-developer-hub/backstage-plugin-openshift-image-registry 1.9.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (32) hide show
  1. package/CHANGELOG.md +521 -0
  2. package/README.md +99 -0
  3. package/app-config.yaml +20 -0
  4. package/config.d.ts +26 -0
  5. package/dist/api/index.esm.js +77 -0
  6. package/dist/api/index.esm.js.map +1 -0
  7. package/dist/components/OcirImages/OcirImageSearchBar.esm.js +62 -0
  8. package/dist/components/OcirImages/OcirImageSearchBar.esm.js.map +1 -0
  9. package/dist/components/OcirImages/OcirImageSidebar.esm.js +107 -0
  10. package/dist/components/OcirImages/OcirImageSidebar.esm.js.map +1 -0
  11. package/dist/components/OcirImages/OcirImagesCard.esm.js +64 -0
  12. package/dist/components/OcirImages/OcirImagesCard.esm.js.map +1 -0
  13. package/dist/components/OcirImages/OcirImagesCards.esm.js +44 -0
  14. package/dist/components/OcirImages/OcirImagesCards.esm.js.map +1 -0
  15. package/dist/components/OcirImages/OcirImagesView.esm.js +17 -0
  16. package/dist/components/OcirImages/OcirImagesView.esm.js.map +1 -0
  17. package/dist/components/OcirPage/OcirPage.esm.js +8 -0
  18. package/dist/components/OcirPage/OcirPage.esm.js.map +1 -0
  19. package/dist/components/OcirPage/index.esm.js +2 -0
  20. package/dist/components/OcirPage/index.esm.js.map +1 -0
  21. package/dist/hooks/useAllNsImageStreams.esm.js +31 -0
  22. package/dist/hooks/useAllNsImageStreams.esm.js.map +1 -0
  23. package/dist/hooks/useImageStreamsMetadataFromTag.esm.js +36 -0
  24. package/dist/hooks/useImageStreamsMetadataFromTag.esm.js.map +1 -0
  25. package/dist/index.d.ts +10 -0
  26. package/dist/index.esm.js +2 -0
  27. package/dist/index.esm.js.map +1 -0
  28. package/dist/plugin.esm.js +35 -0
  29. package/dist/plugin.esm.js.map +1 -0
  30. package/dist/routes.esm.js +8 -0
  31. package/dist/routes.esm.js.map +1 -0
  32. package/package.json +94 -0
package/config.d.ts ADDED
@@ -0,0 +1,26 @@
1
+ /*
2
+ * Copyright 2024 The Backstage Authors
3
+ *
4
+ * Licensed under the Apache License, Version 2.0 (the "License");
5
+ * you may not use this file except in compliance with the License.
6
+ * You may obtain a copy of the License at
7
+ *
8
+ * http://www.apache.org/licenses/LICENSE-2.0
9
+ *
10
+ * Unless required by applicable law or agreed to in writing, software
11
+ * distributed under the License is distributed on an "AS IS" BASIS,
12
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ * See the License for the specific language governing permissions and
14
+ * limitations under the License.
15
+ */
16
+
17
+ export interface Config {
18
+ /** Configurations for the Openshift Image Registry plugin */
19
+ openshiftImageRegistry?: {
20
+ /**
21
+ * The base url of the Openshift instance.
22
+ * @visibility frontend
23
+ */
24
+ proxyPath?: string;
25
+ };
26
+ }
@@ -0,0 +1,77 @@
1
+ import { createApiRef } from '@backstage/core-plugin-api';
2
+
3
+ const DEFAULT_PROXY_PATH = "/openshift-image-registry/api";
4
+ const openshiftImageRegistryApiRef = createApiRef({
5
+ id: "plugin.openshift-image-registry.service"
6
+ });
7
+ class OpenshiftImageRegistryApiClient {
8
+ // @ts-ignore
9
+ discoveryApi;
10
+ configApi;
11
+ identityApi;
12
+ constructor(options) {
13
+ this.discoveryApi = options.discoveryApi;
14
+ this.configApi = options.configApi;
15
+ this.identityApi = options.identityApi;
16
+ }
17
+ async getBaseUrl() {
18
+ const proxyPath = this.configApi.getOptionalString("openshiftImageRegistry.proxyPath") ?? DEFAULT_PROXY_PATH;
19
+ return `${await this.discoveryApi.getBaseUrl("proxy")}${proxyPath}`;
20
+ }
21
+ async fetcher(url) {
22
+ const { token: idToken } = await this.identityApi.getCredentials();
23
+ const response = await fetch(url, {
24
+ headers: {
25
+ "Content-Type": "application/json",
26
+ ...idToken && { Authorization: `Bearer ${idToken}` }
27
+ }
28
+ });
29
+ if (!response.ok) {
30
+ throw new Error(
31
+ `failed to fetch data, status ${response.status}: ${response.statusText}`
32
+ );
33
+ }
34
+ return await response.json();
35
+ }
36
+ async getNamespaces() {
37
+ const proxyUrl = await this.getBaseUrl();
38
+ return (await this.fetcher(`${proxyUrl}/api/v1/namespaces`)).items;
39
+ }
40
+ async getImageStreams(ns) {
41
+ const proxyUrl = await this.getBaseUrl();
42
+ return (await this.fetcher(
43
+ `${proxyUrl}/apis/image.openshift.io/v1/namespaces/${ns}/imagestreams`
44
+ )).items;
45
+ }
46
+ async getAllImageStreams() {
47
+ const proxyUrl = await this.getBaseUrl();
48
+ return (await this.fetcher(`${proxyUrl}/apis/image.openshift.io/v1/imagestreams`)).items;
49
+ }
50
+ async getImageStream(ns, imageName) {
51
+ const proxyUrl = await this.getBaseUrl();
52
+ return await this.fetcher(
53
+ `${proxyUrl}/apis/image.openshift.io/v1/namespaces/${ns}/imagestreams/${imageName}`
54
+ );
55
+ }
56
+ async getImageStreamTags(ns, imageName) {
57
+ const imageStream = await this.getImageStream(ns, imageName);
58
+ const allTags = imageStream.status.tags.map((tag) => tag.tag);
59
+ const proxyUrl = await this.getBaseUrl();
60
+ return Promise.all(
61
+ allTags.map(
62
+ async (tag) => await this.fetcher(
63
+ `${proxyUrl}/apis/image.openshift.io/v1/namespaces/${ns}/imagestreamtags/${imageName}:${tag}`
64
+ )
65
+ )
66
+ );
67
+ }
68
+ async getImageStreamTag(ns, imageName, tag) {
69
+ const proxyUrl = await this.getBaseUrl();
70
+ return await this.fetcher(
71
+ `${proxyUrl}/apis/image.openshift.io/v1/namespaces/${ns}/imagestreamtags/${imageName}:${tag}`
72
+ );
73
+ }
74
+ }
75
+
76
+ export { OpenshiftImageRegistryApiClient, openshiftImageRegistryApiRef };
77
+ //# sourceMappingURL=index.esm.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.esm.js","sources":["../../src/api/index.ts"],"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 */\n\nimport {\n ConfigApi,\n createApiRef,\n DiscoveryApi,\n IdentityApi,\n} from '@backstage/core-plugin-api';\n\nconst DEFAULT_PROXY_PATH = '/openshift-image-registry/api';\n\nexport interface OpenshiftImageRegistryApiV1 {\n getImageStreams(ns: string): Promise<any>;\n getAllImageStreams(): Promise<any>;\n getImageStream(ns: string, imageName: string): Promise<any>;\n getImageStreamTags(ns: string, imageName: string): Promise<any>;\n getImageStreamTag(ns: string, imageName: string, tag: string): Promise<any>;\n getNamespaces(): Promise<any>;\n}\n\nexport const openshiftImageRegistryApiRef =\n createApiRef<OpenshiftImageRegistryApiV1>({\n id: 'plugin.openshift-image-registry.service',\n });\n\nexport type Options = {\n discoveryApi: DiscoveryApi;\n configApi: ConfigApi;\n identityApi: IdentityApi;\n};\n\nexport class OpenshiftImageRegistryApiClient\n implements OpenshiftImageRegistryApiV1\n{\n // @ts-ignore\n private readonly discoveryApi: DiscoveryApi;\n\n private readonly configApi: ConfigApi;\n\n private readonly identityApi: IdentityApi;\n\n constructor(options: Options) {\n this.discoveryApi = options.discoveryApi;\n this.configApi = options.configApi;\n this.identityApi = options.identityApi;\n }\n\n private async getBaseUrl() {\n const proxyPath =\n this.configApi.getOptionalString('openshiftImageRegistry.proxyPath') ??\n DEFAULT_PROXY_PATH;\n return `${await this.discoveryApi.getBaseUrl('proxy')}${proxyPath}`;\n }\n\n private async fetcher(url: string) {\n const { token: idToken } = await this.identityApi.getCredentials();\n const response = await fetch(url, {\n headers: {\n 'Content-Type': 'application/json',\n ...(idToken && { Authorization: `Bearer ${idToken}` }),\n },\n });\n if (!response.ok) {\n throw new Error(\n `failed to fetch data, status ${response.status}: ${response.statusText}`,\n );\n }\n return await response.json();\n }\n\n async getNamespaces() {\n const proxyUrl = await this.getBaseUrl();\n return (await this.fetcher(`${proxyUrl}/api/v1/namespaces`)).items as any[];\n }\n\n async getImageStreams(ns: string) {\n const proxyUrl = await this.getBaseUrl();\n return (\n await this.fetcher(\n `${proxyUrl}/apis/image.openshift.io/v1/namespaces/${ns}/imagestreams`,\n )\n ).items as any[];\n }\n\n async getAllImageStreams() {\n const proxyUrl = await this.getBaseUrl();\n return (\n await this.fetcher(`${proxyUrl}/apis/image.openshift.io/v1/imagestreams`)\n ).items as any[];\n }\n\n async getImageStream(ns: string, imageName: string) {\n const proxyUrl = await this.getBaseUrl();\n return await this.fetcher(\n `${proxyUrl}/apis/image.openshift.io/v1/namespaces/${ns}/imagestreams/${imageName}`,\n );\n }\n\n async getImageStreamTags(ns: string, imageName: string) {\n const imageStream = await this.getImageStream(ns, imageName);\n const allTags = imageStream.status.tags.map((tag: any) => tag.tag);\n\n const proxyUrl = await this.getBaseUrl();\n\n return Promise.all(\n allTags.map(\n async (tag: any) =>\n await this.fetcher(\n `${proxyUrl}/apis/image.openshift.io/v1/namespaces/${ns}/imagestreamtags/${imageName}:${tag}`,\n ),\n ),\n );\n }\n\n async getImageStreamTag(ns: string, imageName: string, tag: string) {\n const proxyUrl = await this.getBaseUrl();\n return await this.fetcher(\n `${proxyUrl}/apis/image.openshift.io/v1/namespaces/${ns}/imagestreamtags/${imageName}:${tag}`,\n );\n }\n}\n"],"names":[],"mappings":"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"}
@@ -0,0 +1,62 @@
1
+ import React from 'react';
2
+ import useDebounce from 'react-use/lib/useDebounce';
3
+ import { makeStyles, Toolbar, FormControl, Input, InputAdornment, IconButton } from '@material-ui/core';
4
+ import Clear from '@material-ui/icons/Clear';
5
+ import Search from '@material-ui/icons/Search';
6
+
7
+ const useStyles = makeStyles((_theme) => ({
8
+ searchToolbar: {
9
+ paddingLeft: 0,
10
+ paddingRight: 0
11
+ },
12
+ input: {}
13
+ }));
14
+ const OcirImageSearchBar = ({
15
+ imageStreams,
16
+ setImageStreams
17
+ }) => {
18
+ const classes = useStyles();
19
+ const [search, setSearch] = React.useState("");
20
+ const searchByName = () => {
21
+ const filteredImageStreams = imageStreams ? imageStreams.filter((imgSt) => {
22
+ const s = search.toLocaleUpperCase("en-US");
23
+ const { name, description = "", tags } = imgSt;
24
+ const n = name.toLocaleUpperCase("en-US");
25
+ const d = description.toLocaleUpperCase("en-US");
26
+ return n.includes(s) || d.includes(s) || !!tags.find((t) => t.toLocaleUpperCase("en-US").includes(s));
27
+ }) : void 0;
28
+ setImageStreams(filteredImageStreams);
29
+ };
30
+ useDebounce(
31
+ () => {
32
+ searchByName();
33
+ },
34
+ 100,
35
+ [search]
36
+ );
37
+ return /* @__PURE__ */ React.createElement(Toolbar, { className: classes.searchToolbar }, /* @__PURE__ */ React.createElement(FormControl, null, /* @__PURE__ */ React.createElement(
38
+ Input,
39
+ {
40
+ "aria-label": "search",
41
+ className: classes.input,
42
+ placeholder: "Search",
43
+ autoComplete: "off",
44
+ onChange: (event) => setSearch(event.target.value),
45
+ value: search,
46
+ startAdornment: /* @__PURE__ */ React.createElement(InputAdornment, { position: "start" }, /* @__PURE__ */ React.createElement(Search, null)),
47
+ endAdornment: /* @__PURE__ */ React.createElement(InputAdornment, { position: "end" }, /* @__PURE__ */ React.createElement(
48
+ IconButton,
49
+ {
50
+ "aria-label": "clear search",
51
+ onClick: () => setSearch(""),
52
+ edge: "end",
53
+ disabled: search.length === 0
54
+ },
55
+ /* @__PURE__ */ React.createElement(Clear, null)
56
+ ))
57
+ }
58
+ )));
59
+ };
60
+
61
+ export { OcirImageSearchBar };
62
+ //# sourceMappingURL=OcirImageSearchBar.esm.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"OcirImageSearchBar.esm.js","sources":["../../../src/components/OcirImages/OcirImageSearchBar.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 */\n\nimport React from 'react';\nimport useDebounce from 'react-use/lib/useDebounce';\n\nimport {\n FormControl,\n IconButton,\n Input,\n InputAdornment,\n makeStyles,\n Toolbar,\n} from '@material-ui/core';\nimport Clear from '@material-ui/icons/Clear';\nimport Search from '@material-ui/icons/Search';\n\nimport { ImageStreamMetadata } from '../../types';\n\nconst useStyles = makeStyles(_theme => ({\n searchToolbar: {\n paddingLeft: 0,\n paddingRight: 0,\n },\n input: {},\n}));\n\ntype OcirImageSearchBarProps = {\n imageStreams: ImageStreamMetadata[];\n setImageStreams: React.Dispatch<\n React.SetStateAction<ImageStreamMetadata[] | undefined>\n >;\n};\n\nexport const OcirImageSearchBar = ({\n imageStreams,\n setImageStreams,\n}: OcirImageSearchBarProps) => {\n const classes = useStyles();\n\n const [search, setSearch] = React.useState<string>('');\n\n const searchByName = () => {\n const filteredImageStreams = imageStreams\n ? imageStreams.filter((imgSt: ImageStreamMetadata) => {\n const s = search.toLocaleUpperCase('en-US');\n const { name, description = '', tags } = imgSt;\n const n = name.toLocaleUpperCase('en-US');\n const d = description.toLocaleUpperCase('en-US');\n return (\n n.includes(s) ||\n d.includes(s) ||\n !!tags.find(t => t.toLocaleUpperCase('en-US').includes(s))\n );\n })\n : undefined;\n setImageStreams(filteredImageStreams);\n };\n\n useDebounce(\n () => {\n searchByName();\n },\n 100,\n [search],\n );\n\n return (\n <Toolbar className={classes.searchToolbar}>\n <FormControl>\n <Input\n aria-label=\"search\"\n className={classes.input}\n placeholder=\"Search\"\n autoComplete=\"off\"\n onChange={event => setSearch(event.target.value)}\n value={search}\n startAdornment={\n <InputAdornment position=\"start\">\n <Search />\n </InputAdornment>\n }\n endAdornment={\n <InputAdornment position=\"end\">\n <IconButton\n aria-label=\"clear search\"\n onClick={() => setSearch('')}\n edge=\"end\"\n disabled={search.length === 0}\n >\n <Clear />\n </IconButton>\n </InputAdornment>\n }\n />\n </FormControl>\n </Toolbar>\n );\n};\n"],"names":[],"mappings":";;;;;;AAgCA,MAAM,SAAA,GAAY,WAAW,CAAW,MAAA,MAAA;AAAA,EACtC,aAAe,EAAA;AAAA,IACb,WAAa,EAAA,CAAA;AAAA,IACb,YAAc,EAAA,CAAA;AAAA,GAChB;AAAA,EACA,OAAO,EAAC;AACV,CAAE,CAAA,CAAA,CAAA;AASK,MAAM,qBAAqB,CAAC;AAAA,EACjC,YAAA;AAAA,EACA,eAAA;AACF,CAA+B,KAAA;AAC7B,EAAA,MAAM,UAAU,SAAU,EAAA,CAAA;AAE1B,EAAA,MAAM,CAAC,MAAQ,EAAA,SAAS,CAAI,GAAA,KAAA,CAAM,SAAiB,EAAE,CAAA,CAAA;AAErD,EAAA,MAAM,eAAe,MAAM;AACzB,IAAA,MAAM,oBAAuB,GAAA,YAAA,GACzB,YAAa,CAAA,MAAA,CAAO,CAAC,KAA+B,KAAA;AAClD,MAAM,MAAA,CAAA,GAAI,MAAO,CAAA,iBAAA,CAAkB,OAAO,CAAA,CAAA;AAC1C,MAAA,MAAM,EAAE,IAAA,EAAM,WAAc,GAAA,EAAA,EAAI,MAAS,GAAA,KAAA,CAAA;AACzC,MAAM,MAAA,CAAA,GAAI,IAAK,CAAA,iBAAA,CAAkB,OAAO,CAAA,CAAA;AACxC,MAAM,MAAA,CAAA,GAAI,WAAY,CAAA,iBAAA,CAAkB,OAAO,CAAA,CAAA;AAC/C,MAAA,OACE,EAAE,QAAS,CAAA,CAAC,KACZ,CAAE,CAAA,QAAA,CAAS,CAAC,CACZ,IAAA,CAAC,CAAC,IAAK,CAAA,IAAA,CAAK,OAAK,CAAE,CAAA,iBAAA,CAAkB,OAAO,CAAE,CAAA,QAAA,CAAS,CAAC,CAAC,CAAA,CAAA;AAAA,KAE5D,CACD,GAAA,KAAA,CAAA,CAAA;AACJ,IAAA,eAAA,CAAgB,oBAAoB,CAAA,CAAA;AAAA,GACtC,CAAA;AAEA,EAAA,WAAA;AAAA,IACE,MAAM;AACJ,MAAa,YAAA,EAAA,CAAA;AAAA,KACf;AAAA,IACA,GAAA;AAAA,IACA,CAAC,MAAM,CAAA;AAAA,GACT,CAAA;AAEA,EAAA,2CACG,OAAQ,EAAA,EAAA,SAAA,EAAW,OAAQ,CAAA,aAAA,EAAA,sCACzB,WACC,EAAA,IAAA,kBAAA,KAAA,CAAA,aAAA;AAAA,IAAC,KAAA;AAAA,IAAA;AAAA,MACC,YAAW,EAAA,QAAA;AAAA,MACX,WAAW,OAAQ,CAAA,KAAA;AAAA,MACnB,WAAY,EAAA,QAAA;AAAA,MACZ,YAAa,EAAA,KAAA;AAAA,MACb,QAAU,EAAA,CAAA,KAAA,KAAS,SAAU,CAAA,KAAA,CAAM,OAAO,KAAK,CAAA;AAAA,MAC/C,KAAO,EAAA,MAAA;AAAA,MACP,gCACG,KAAA,CAAA,aAAA,CAAA,cAAA,EAAA,EAAe,UAAS,OACvB,EAAA,kBAAA,KAAA,CAAA,aAAA,CAAC,YAAO,CACV,CAAA;AAAA,MAEF,YACE,kBAAA,KAAA,CAAA,aAAA,CAAC,cAAe,EAAA,EAAA,QAAA,EAAS,KACvB,EAAA,kBAAA,KAAA,CAAA,aAAA;AAAA,QAAC,UAAA;AAAA,QAAA;AAAA,UACC,YAAW,EAAA,cAAA;AAAA,UACX,OAAA,EAAS,MAAM,SAAA,CAAU,EAAE,CAAA;AAAA,UAC3B,IAAK,EAAA,KAAA;AAAA,UACL,QAAA,EAAU,OAAO,MAAW,KAAA,CAAA;AAAA,SAAA;AAAA,4CAE3B,KAAM,EAAA,IAAA,CAAA;AAAA,OAEX,CAAA;AAAA,KAAA;AAAA,GAGN,CACF,CAAA,CAAA;AAEJ;;;;"}
@@ -0,0 +1,107 @@
1
+ import React from 'react';
2
+ import { MarkdownContent, CopyTextButton } from '@backstage/core-components';
3
+ import { makeStyles, createStyles, Drawer, Typography, IconButton, Box, Chip, Input } from '@material-ui/core';
4
+ import Close from '@material-ui/icons/Close';
5
+
6
+ const useDrawerStyles = makeStyles(
7
+ (theme) => createStyles({
8
+ paper: {
9
+ width: "40%",
10
+ padding: theme.spacing(2.5),
11
+ gap: "3%"
12
+ }
13
+ })
14
+ );
15
+ const useDrawerContentStyles = makeStyles(
16
+ (theme) => createStyles({
17
+ header: {
18
+ display: "flex",
19
+ flexDirection: "row",
20
+ justifyContent: "space-between",
21
+ alignItems: "baseline"
22
+ },
23
+ icon: {
24
+ fontSize: 20
25
+ },
26
+ label: {
27
+ color: theme.palette.text.secondary,
28
+ textTransform: "uppercase",
29
+ fontSize: "0.65rem",
30
+ fontWeight: "bold",
31
+ letterSpacing: 0.5,
32
+ lineHeight: 1,
33
+ paddingBottom: "0.2rem"
34
+ },
35
+ description: {
36
+ "& p": {
37
+ margin: "0px"
38
+ }
39
+ }
40
+ })
41
+ );
42
+ const OcirImageSidebar = ({
43
+ open,
44
+ onClose,
45
+ imageStream
46
+ }) => {
47
+ const classes = useDrawerStyles();
48
+ const contentClasses = useDrawerContentStyles();
49
+ return /* @__PURE__ */ React.createElement(
50
+ Drawer,
51
+ {
52
+ anchor: "right",
53
+ open,
54
+ onClose,
55
+ classes: {
56
+ paper: classes.paper
57
+ }
58
+ },
59
+ /* @__PURE__ */ React.createElement(React.Fragment, null, /* @__PURE__ */ React.createElement("div", { className: contentClasses.header }, /* @__PURE__ */ React.createElement(Typography, { variant: "h5" }, imageStream.name), /* @__PURE__ */ React.createElement(
60
+ IconButton,
61
+ {
62
+ key: "dismiss",
63
+ title: "Close the drawer",
64
+ onClick: onClose,
65
+ color: "inherit"
66
+ },
67
+ /* @__PURE__ */ React.createElement(Close, { className: contentClasses.icon })
68
+ )), /* @__PURE__ */ React.createElement(React.Fragment, null, /* @__PURE__ */ React.createElement(Box, null, /* @__PURE__ */ React.createElement(Typography, { variant: "body2", className: contentClasses.label }, "Description"), /* @__PURE__ */ React.createElement(
69
+ MarkdownContent,
70
+ {
71
+ content: imageStream.description ?? "N/A",
72
+ className: contentClasses.description
73
+ }
74
+ )), /* @__PURE__ */ React.createElement(Box, null, /* @__PURE__ */ React.createElement(Typography, { variant: "body2", className: contentClasses.label }, "Last Modified"), /* @__PURE__ */ React.createElement(Typography, { className: contentClasses.description }, imageStream.last_modified || "N/A")), /* @__PURE__ */ React.createElement(Box, null, /* @__PURE__ */ React.createElement(Typography, { variant: "body2", className: contentClasses.label }, "Version"), /* @__PURE__ */ React.createElement(Typography, { className: contentClasses.description }, imageStream.version ?? "N/A")), /* @__PURE__ */ React.createElement(Box, null, /* @__PURE__ */ React.createElement(Typography, { variant: "body2", className: contentClasses.label }, "Size"), /* @__PURE__ */ React.createElement(Typography, { className: contentClasses.description }, imageStream.size ?? "N/A")), /* @__PURE__ */ React.createElement(Box, null, /* @__PURE__ */ React.createElement(
75
+ Typography,
76
+ {
77
+ variant: "body2",
78
+ className: contentClasses.label,
79
+ style: { marginBottom: "4px" }
80
+ },
81
+ "Tags"
82
+ ), imageStream.tags?.length ? imageStream.tags.map((tag) => /* @__PURE__ */ React.createElement(Chip, { key: tag, size: "small", label: tag })) : "N/A"), /* @__PURE__ */ React.createElement(Box, null, /* @__PURE__ */ React.createElement(Typography, { variant: "body2", className: contentClasses.label }, "Docker Pull Command"), imageStream.dockerImageRepo ? /* @__PURE__ */ React.createElement(
83
+ Input,
84
+ {
85
+ defaultValue: `docker pull ${imageStream.dockerImageRepo}`,
86
+ readOnly: true,
87
+ fullWidth: true,
88
+ style: {
89
+ fontSize: "14px",
90
+ paddingLeft: "12px"
91
+ },
92
+ margin: "dense",
93
+ endAdornment: /* @__PURE__ */ React.createElement(
94
+ CopyTextButton,
95
+ {
96
+ text: `docker pull ${imageStream.dockerImageRepo}`,
97
+ tooltipText: "Command copied to clipboard",
98
+ tooltipDelay: 2e3
99
+ }
100
+ )
101
+ }
102
+ ) : "N/A")))
103
+ );
104
+ };
105
+
106
+ export { OcirImageSidebar };
107
+ //# sourceMappingURL=OcirImageSidebar.esm.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"OcirImageSidebar.esm.js","sources":["../../../src/components/OcirImages/OcirImageSidebar.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 */\n\nimport React from 'react';\n\nimport { CopyTextButton, MarkdownContent } from '@backstage/core-components';\n\nimport {\n Box,\n Chip,\n createStyles,\n Drawer,\n IconButton,\n Input,\n makeStyles,\n Theme,\n Typography,\n} from '@material-ui/core';\nimport Close from '@material-ui/icons/Close';\n\nimport { ImageStreamMetadata } from '../../types';\n\nconst useDrawerStyles = makeStyles<Theme>(theme =>\n createStyles({\n paper: {\n width: '40%',\n padding: theme.spacing(2.5),\n gap: '3%',\n },\n }),\n);\n\nconst useDrawerContentStyles = makeStyles<Theme>(theme =>\n createStyles({\n header: {\n display: 'flex',\n flexDirection: 'row',\n justifyContent: 'space-between',\n alignItems: 'baseline',\n },\n icon: {\n fontSize: 20,\n },\n label: {\n color: theme.palette.text.secondary,\n textTransform: 'uppercase',\n fontSize: '0.65rem',\n fontWeight: 'bold',\n letterSpacing: 0.5,\n lineHeight: 1,\n paddingBottom: '0.2rem',\n },\n description: {\n '& p': {\n margin: '0px',\n },\n },\n }),\n);\n\ntype OcirImageSidebarProps = {\n open: boolean;\n onClose: () => void;\n imageStream: ImageStreamMetadata;\n};\n\nexport const OcirImageSidebar = ({\n open,\n onClose,\n imageStream,\n}: OcirImageSidebarProps) => {\n const classes = useDrawerStyles();\n const contentClasses = useDrawerContentStyles();\n return (\n <Drawer\n anchor=\"right\"\n open={open}\n onClose={onClose}\n classes={{\n paper: classes.paper,\n }}\n >\n <>\n <div className={contentClasses.header}>\n <Typography variant=\"h5\">{imageStream.name}</Typography>\n <IconButton\n key=\"dismiss\"\n title=\"Close the drawer\"\n onClick={onClose}\n color=\"inherit\"\n >\n <Close className={contentClasses.icon} />\n </IconButton>\n </div>\n <>\n <Box>\n <Typography variant=\"body2\" className={contentClasses.label}>\n Description\n </Typography>\n <MarkdownContent\n content={imageStream.description ?? 'N/A'}\n className={contentClasses.description}\n />\n </Box>\n <Box>\n <Typography variant=\"body2\" className={contentClasses.label}>\n Last Modified\n </Typography>\n <Typography className={contentClasses.description}>\n {imageStream.last_modified || 'N/A'}\n </Typography>\n </Box>\n <Box>\n <Typography variant=\"body2\" className={contentClasses.label}>\n Version\n </Typography>\n <Typography className={contentClasses.description}>\n {imageStream.version ?? 'N/A'}\n </Typography>\n </Box>\n <Box>\n <Typography variant=\"body2\" className={contentClasses.label}>\n Size\n </Typography>\n <Typography className={contentClasses.description}>\n {imageStream.size ?? 'N/A'}\n </Typography>\n </Box>\n <Box>\n <Typography\n variant=\"body2\"\n className={contentClasses.label}\n style={{ marginBottom: '4px' }}\n >\n Tags\n </Typography>\n {imageStream.tags?.length\n ? imageStream.tags.map((tag: string) => (\n <Chip key={tag} size=\"small\" label={tag} />\n ))\n : 'N/A'}\n </Box>\n <Box>\n <Typography variant=\"body2\" className={contentClasses.label}>\n Docker Pull Command\n </Typography>\n {imageStream.dockerImageRepo ? (\n <Input\n defaultValue={`docker pull ${imageStream.dockerImageRepo}`}\n readOnly\n fullWidth\n style={{\n fontSize: '14px',\n paddingLeft: '12px',\n }}\n margin=\"dense\"\n endAdornment={\n <CopyTextButton\n text={`docker pull ${imageStream.dockerImageRepo}`}\n tooltipText=\"Command copied to clipboard\"\n tooltipDelay={2000}\n />\n }\n />\n ) : (\n 'N/A'\n )}\n </Box>\n </>\n </>\n </Drawer>\n );\n};\n"],"names":[],"mappings":"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"}
@@ -0,0 +1,64 @@
1
+ import React from 'react';
2
+ import { ItemCardHeader, MarkdownContent, LinkButton } from '@backstage/core-components';
3
+ import { makeStyles, Card, CardMedia, CardContent, Box, Typography, Chip, CardActions } from '@material-ui/core';
4
+
5
+ const useStyles = makeStyles((theme) => ({
6
+ label: {
7
+ color: theme.palette.text.secondary,
8
+ textTransform: "uppercase",
9
+ fontSize: "0.65rem",
10
+ fontWeight: "bold",
11
+ letterSpacing: 0.5,
12
+ lineHeight: 1,
13
+ paddingBottom: "0.2rem"
14
+ },
15
+ description: {
16
+ "& p": {
17
+ margin: "0px"
18
+ }
19
+ }
20
+ }));
21
+ const OcirImagesCard = ({
22
+ imageStream,
23
+ onImageStreamSelected
24
+ }) => {
25
+ const classes = useStyles();
26
+ return /* @__PURE__ */ React.createElement(Card, null, /* @__PURE__ */ React.createElement(CardMedia, null, /* @__PURE__ */ React.createElement(ItemCardHeader, { title: imageStream.name })), /* @__PURE__ */ React.createElement(
27
+ CardContent,
28
+ {
29
+ style: {
30
+ display: "flex",
31
+ flexDirection: "column",
32
+ gap: "16px"
33
+ }
34
+ },
35
+ /* @__PURE__ */ React.createElement(Box, null, /* @__PURE__ */ React.createElement(Typography, { variant: "body2", className: classes.label }, "Description"), /* @__PURE__ */ React.createElement(
36
+ MarkdownContent,
37
+ {
38
+ content: imageStream.description ?? "N/A",
39
+ className: classes.description
40
+ }
41
+ )),
42
+ /* @__PURE__ */ React.createElement(Box, null, /* @__PURE__ */ React.createElement(Typography, { variant: "body2", className: classes.label }, "Last Modified"), /* @__PURE__ */ React.createElement(Typography, { className: classes.description }, imageStream.last_modified || "N/A")),
43
+ /* @__PURE__ */ React.createElement(Box, null, /* @__PURE__ */ React.createElement(
44
+ Typography,
45
+ {
46
+ variant: "body2",
47
+ className: classes.label,
48
+ style: { marginBottom: "4px" }
49
+ },
50
+ "Tags"
51
+ ), imageStream.tags?.length ? imageStream.tags.map((tag) => /* @__PURE__ */ React.createElement(Chip, { key: tag, size: "small", label: tag })) : "N/A")
52
+ ), /* @__PURE__ */ React.createElement(CardActions, null, /* @__PURE__ */ React.createElement(
53
+ LinkButton,
54
+ {
55
+ color: "primary",
56
+ to: "",
57
+ onClick: () => onImageStreamSelected(imageStream)
58
+ },
59
+ "Open"
60
+ )));
61
+ };
62
+
63
+ export { OcirImagesCard };
64
+ //# sourceMappingURL=OcirImagesCard.esm.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"OcirImagesCard.esm.js","sources":["../../../src/components/OcirImages/OcirImagesCard.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 */\n\nimport React from 'react';\n\nimport {\n ItemCardHeader,\n LinkButton,\n MarkdownContent,\n} from '@backstage/core-components';\n\nimport {\n Box,\n Card,\n CardActions,\n CardContent,\n CardMedia,\n Chip,\n makeStyles,\n Theme,\n Typography,\n} from '@material-ui/core';\n\nimport { ImageStreamMetadata } from '../../types';\n\nconst useStyles = makeStyles<Theme>(theme => ({\n label: {\n color: theme.palette.text.secondary,\n textTransform: 'uppercase',\n fontSize: '0.65rem',\n fontWeight: 'bold',\n letterSpacing: 0.5,\n lineHeight: 1,\n paddingBottom: '0.2rem',\n },\n description: {\n '& p': {\n margin: '0px',\n },\n },\n}));\n\ntype OcirImagesCardProps = {\n imageStream: ImageStreamMetadata;\n onImageStreamSelected: (imageStream: ImageStreamMetadata) => void;\n};\n\nexport const OcirImagesCard = ({\n imageStream,\n onImageStreamSelected,\n}: OcirImagesCardProps) => {\n const classes = useStyles();\n\n return (\n <Card>\n <CardMedia>\n <ItemCardHeader title={imageStream.name} />\n </CardMedia>\n <CardContent\n style={{\n display: 'flex',\n flexDirection: 'column',\n gap: '16px',\n }}\n >\n <Box>\n <Typography variant=\"body2\" className={classes.label}>\n Description\n </Typography>\n <MarkdownContent\n content={imageStream.description ?? 'N/A'}\n className={classes.description}\n />\n </Box>\n <Box>\n <Typography variant=\"body2\" className={classes.label}>\n Last Modified\n </Typography>\n <Typography className={classes.description}>\n {imageStream.last_modified || 'N/A'}\n </Typography>\n </Box>\n <Box>\n <Typography\n variant=\"body2\"\n className={classes.label}\n style={{ marginBottom: '4px' }}\n >\n Tags\n </Typography>\n {imageStream.tags?.length\n ? imageStream.tags.map((tag: string) => (\n <Chip key={tag} size=\"small\" label={tag} />\n ))\n : 'N/A'}\n </Box>\n </CardContent>\n <CardActions>\n <LinkButton\n color=\"primary\"\n to=\"\"\n onClick={() => onImageStreamSelected(imageStream)}\n >\n Open\n </LinkButton>\n </CardActions>\n </Card>\n );\n};\n"],"names":[],"mappings":";;;;AAsCA,MAAM,SAAA,GAAY,WAAkB,CAAU,KAAA,MAAA;AAAA,EAC5C,KAAO,EAAA;AAAA,IACL,KAAA,EAAO,KAAM,CAAA,OAAA,CAAQ,IAAK,CAAA,SAAA;AAAA,IAC1B,aAAe,EAAA,WAAA;AAAA,IACf,QAAU,EAAA,SAAA;AAAA,IACV,UAAY,EAAA,MAAA;AAAA,IACZ,aAAe,EAAA,GAAA;AAAA,IACf,UAAY,EAAA,CAAA;AAAA,IACZ,aAAe,EAAA,QAAA;AAAA,GACjB;AAAA,EACA,WAAa,EAAA;AAAA,IACX,KAAO,EAAA;AAAA,MACL,MAAQ,EAAA,KAAA;AAAA,KACV;AAAA,GACF;AACF,CAAE,CAAA,CAAA,CAAA;AAOK,MAAM,iBAAiB,CAAC;AAAA,EAC7B,WAAA;AAAA,EACA,qBAAA;AACF,CAA2B,KAAA;AACzB,EAAA,MAAM,UAAU,SAAU,EAAA,CAAA;AAE1B,EACE,uBAAA,KAAA,CAAA,aAAA,CAAC,IACC,EAAA,IAAA,kBAAA,KAAA,CAAA,aAAA,CAAC,SACC,EAAA,IAAA,kBAAA,KAAA,CAAA,aAAA,CAAC,kBAAe,KAAO,EAAA,WAAA,CAAY,IAAM,EAAA,CAC3C,CACA,kBAAA,KAAA,CAAA,aAAA;AAAA,IAAC,WAAA;AAAA,IAAA;AAAA,MACC,KAAO,EAAA;AAAA,QACL,OAAS,EAAA,MAAA;AAAA,QACT,aAAe,EAAA,QAAA;AAAA,QACf,GAAK,EAAA,MAAA;AAAA,OACP;AAAA,KAAA;AAAA,oBAEA,KAAA,CAAA,aAAA,CAAC,GACC,EAAA,IAAA,kBAAA,KAAA,CAAA,aAAA,CAAC,UAAW,EAAA,EAAA,OAAA,EAAQ,SAAQ,SAAW,EAAA,OAAA,CAAQ,KAAO,EAAA,EAAA,aAEtD,CACA,kBAAA,KAAA,CAAA,aAAA;AAAA,MAAC,eAAA;AAAA,MAAA;AAAA,QACC,OAAA,EAAS,YAAY,WAAe,IAAA,KAAA;AAAA,QACpC,WAAW,OAAQ,CAAA,WAAA;AAAA,OAAA;AAAA,KAEvB,CAAA;AAAA,wCACC,GACC,EAAA,IAAA,kBAAA,KAAA,CAAA,aAAA,CAAC,cAAW,OAAQ,EAAA,OAAA,EAAQ,WAAW,OAAQ,CAAA,KAAA,EAAA,EAAO,eAEtD,CACA,kBAAA,KAAA,CAAA,aAAA,CAAC,cAAW,SAAW,EAAA,OAAA,CAAQ,eAC5B,WAAY,CAAA,aAAA,IAAiB,KAChC,CACF,CAAA;AAAA,wCACC,GACC,EAAA,IAAA,kBAAA,KAAA,CAAA,aAAA;AAAA,MAAC,UAAA;AAAA,MAAA;AAAA,QACC,OAAQ,EAAA,OAAA;AAAA,QACR,WAAW,OAAQ,CAAA,KAAA;AAAA,QACnB,KAAA,EAAO,EAAE,YAAA,EAAc,KAAM,EAAA;AAAA,OAAA;AAAA,MAC9B,MAAA;AAAA,OAGA,WAAY,CAAA,IAAA,EAAM,SACf,WAAY,CAAA,IAAA,CAAK,IAAI,CAAC,GAAA,yCACnB,IAAK,EAAA,EAAA,GAAA,EAAK,KAAK,IAAK,EAAA,OAAA,EAAQ,OAAO,GAAK,EAAA,CAC1C,IACD,KACN,CAAA;AAAA,GACF,sCACC,WACC,EAAA,IAAA,kBAAA,KAAA,CAAA,aAAA;AAAA,IAAC,UAAA;AAAA,IAAA;AAAA,MACC,KAAM,EAAA,SAAA;AAAA,MACN,EAAG,EAAA,EAAA;AAAA,MACH,OAAA,EAAS,MAAM,qBAAA,CAAsB,WAAW,CAAA;AAAA,KAAA;AAAA,IACjD,MAAA;AAAA,GAGH,CACF,CAAA,CAAA;AAEJ;;;;"}
@@ -0,0 +1,44 @@
1
+ import React from 'react';
2
+ import { ItemCardGrid, EmptyState } from '@backstage/core-components';
3
+ import { OcirImagesCard } from './OcirImagesCard.esm.js';
4
+ import { OcirImageSearchBar } from './OcirImageSearchBar.esm.js';
5
+ import { OcirImageSidebar } from './OcirImageSidebar.esm.js';
6
+
7
+ const OcirImagesCards = ({ imageStreams }) => {
8
+ const [isOpen, setIsOpen] = React.useState(false);
9
+ const [activeImageStream, setActiveImageStream] = React.useState();
10
+ const [filteredImageStreams, setFilteredImageStreams] = React.useState();
11
+ const imageStreamsList = filteredImageStreams ?? imageStreams;
12
+ const handleImageStreamSelected = React.useCallback(
13
+ (imageStream) => {
14
+ setActiveImageStream(imageStream);
15
+ setIsOpen(true);
16
+ },
17
+ []
18
+ );
19
+ const handleClose = React.useCallback(() => setIsOpen(false), [setIsOpen]);
20
+ return /* @__PURE__ */ React.createElement(React.Fragment, null, /* @__PURE__ */ React.createElement(
21
+ OcirImageSearchBar,
22
+ {
23
+ imageStreams,
24
+ setImageStreams: setFilteredImageStreams
25
+ }
26
+ ), imageStreamsList?.length ? /* @__PURE__ */ React.createElement(React.Fragment, null, /* @__PURE__ */ React.createElement(ItemCardGrid, null, imageStreamsList.map((imageStream) => /* @__PURE__ */ React.createElement(
27
+ OcirImagesCard,
28
+ {
29
+ key: imageStream.uid,
30
+ imageStream,
31
+ onImageStreamSelected: handleImageStreamSelected
32
+ }
33
+ ))), activeImageStream && /* @__PURE__ */ React.createElement(
34
+ OcirImageSidebar,
35
+ {
36
+ open: isOpen,
37
+ onClose: handleClose,
38
+ imageStream: activeImageStream
39
+ }
40
+ )) : /* @__PURE__ */ React.createElement("div", { style: { width: "100%", height: "100vh" } }, /* @__PURE__ */ React.createElement(EmptyState, { missing: "content", title: "No ImageStreams found" })));
41
+ };
42
+
43
+ export { OcirImagesCards };
44
+ //# sourceMappingURL=OcirImagesCards.esm.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"OcirImagesCards.esm.js","sources":["../../../src/components/OcirImages/OcirImagesCards.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 */\n\nimport React from 'react';\n\nimport { EmptyState, ItemCardGrid } from '@backstage/core-components';\n\nimport { ImageStreamMetadata } from '../../types';\nimport { OcirImagesCard } from './OcirImagesCard';\nimport { OcirImageSearchBar } from './OcirImageSearchBar';\nimport { OcirImageSidebar } from './OcirImageSidebar';\n\ntype OcirImagesCardsProps = {\n imageStreams: ImageStreamMetadata[];\n};\n\nexport const OcirImagesCards = ({ imageStreams }: OcirImagesCardsProps) => {\n const [isOpen, setIsOpen] = React.useState<boolean>(false);\n const [activeImageStream, setActiveImageStream] =\n React.useState<ImageStreamMetadata>();\n const [filteredImageStreams, setFilteredImageStreams] = React.useState<\n ImageStreamMetadata[] | undefined\n >();\n\n const imageStreamsList = filteredImageStreams ?? imageStreams;\n\n const handleImageStreamSelected = React.useCallback(\n (imageStream: ImageStreamMetadata) => {\n setActiveImageStream(imageStream);\n setIsOpen(true);\n },\n [],\n );\n const handleClose = React.useCallback(() => setIsOpen(false), [setIsOpen]);\n\n return (\n <>\n <OcirImageSearchBar\n imageStreams={imageStreams}\n setImageStreams={setFilteredImageStreams}\n />\n {imageStreamsList?.length ? (\n <>\n <ItemCardGrid>\n {imageStreamsList.map((imageStream: ImageStreamMetadata) => (\n <OcirImagesCard\n key={imageStream.uid}\n imageStream={imageStream}\n onImageStreamSelected={handleImageStreamSelected}\n />\n ))}\n </ItemCardGrid>\n {activeImageStream && (\n <OcirImageSidebar\n open={isOpen}\n onClose={handleClose}\n imageStream={activeImageStream}\n />\n )}\n </>\n ) : (\n <div style={{ width: '100%', height: '100vh' }}>\n <EmptyState missing=\"content\" title=\"No ImageStreams found\" />\n </div>\n )}\n </>\n );\n};\n"],"names":[],"mappings":";;;;;;AA6BO,MAAM,eAAkB,GAAA,CAAC,EAAE,YAAA,EAAyC,KAAA;AACzE,EAAA,MAAM,CAAC,MAAQ,EAAA,SAAS,CAAI,GAAA,KAAA,CAAM,SAAkB,KAAK,CAAA,CAAA;AACzD,EAAA,MAAM,CAAC,iBAAA,EAAmB,oBAAoB,CAAA,GAC5C,MAAM,QAA8B,EAAA,CAAA;AACtC,EAAA,MAAM,CAAC,oBAAA,EAAsB,uBAAuB,CAAA,GAAI,MAAM,QAE5D,EAAA,CAAA;AAEF,EAAA,MAAM,mBAAmB,oBAAwB,IAAA,YAAA,CAAA;AAEjD,EAAA,MAAM,4BAA4B,KAAM,CAAA,WAAA;AAAA,IACtC,CAAC,WAAqC,KAAA;AACpC,MAAA,oBAAA,CAAqB,WAAW,CAAA,CAAA;AAChC,MAAA,SAAA,CAAU,IAAI,CAAA,CAAA;AAAA,KAChB;AAAA,IACA,EAAC;AAAA,GACH,CAAA;AACA,EAAM,MAAA,WAAA,GAAc,MAAM,WAAY,CAAA,MAAM,UAAU,KAAK,CAAA,EAAG,CAAC,SAAS,CAAC,CAAA,CAAA;AAEzE,EAAA,uBAEI,KAAA,CAAA,aAAA,CAAA,KAAA,CAAA,QAAA,EAAA,IAAA,kBAAA,KAAA,CAAA,aAAA;AAAA,IAAC,kBAAA;AAAA,IAAA;AAAA,MACC,YAAA;AAAA,MACA,eAAiB,EAAA,uBAAA;AAAA,KAAA;AAAA,GACnB,EACC,kBAAkB,MACjB,mBAAA,KAAA,CAAA,aAAA,CAAA,KAAA,CAAA,QAAA,EAAA,IAAA,sCACG,YACE,EAAA,IAAA,EAAA,gBAAA,CAAiB,GAAI,CAAA,CAAC,WACrB,qBAAA,KAAA,CAAA,aAAA;AAAA,IAAC,cAAA;AAAA,IAAA;AAAA,MACC,KAAK,WAAY,CAAA,GAAA;AAAA,MACjB,WAAA;AAAA,MACA,qBAAuB,EAAA,yBAAA;AAAA,KAAA;AAAA,GAE1B,CACH,CAAA,EACC,iBACC,oBAAA,KAAA,CAAA,aAAA;AAAA,IAAC,gBAAA;AAAA,IAAA;AAAA,MACC,IAAM,EAAA,MAAA;AAAA,MACN,OAAS,EAAA,WAAA;AAAA,MACT,WAAa,EAAA,iBAAA;AAAA,KAAA;AAAA,GAGnB,CAEA,mBAAA,KAAA,CAAA,aAAA,CAAC,SAAI,KAAO,EAAA,EAAE,OAAO,MAAQ,EAAA,MAAA,EAAQ,OAAQ,EAAA,EAAA,sCAC1C,UAAW,EAAA,EAAA,OAAA,EAAQ,WAAU,KAAM,EAAA,uBAAA,EAAwB,CAC9D,CAEJ,CAAA,CAAA;AAEJ;;;;"}
@@ -0,0 +1,17 @@
1
+ import React from 'react';
2
+ import { Progress, EmptyState } from '@backstage/core-components';
3
+ import { useAllNsImageStreams } from '../../hooks/useAllNsImageStreams.esm.js';
4
+ import { useImageStreamsMetadataFromTag } from '../../hooks/useImageStreamsMetadataFromTag.esm.js';
5
+ import { OcirImagesCards } from './OcirImagesCards.esm.js';
6
+
7
+ const OcirImagesView = () => {
8
+ const { loading: imageStreamsLoading, imageStreams } = useAllNsImageStreams();
9
+ const { loading: metadataLoading, imageStreamsMetadata } = useImageStreamsMetadataFromTag(imageStreams);
10
+ if (imageStreamsLoading || metadataLoading) {
11
+ return /* @__PURE__ */ React.createElement(Progress, null);
12
+ }
13
+ return imageStreamsMetadata?.length ? /* @__PURE__ */ React.createElement(OcirImagesCards, { imageStreams: imageStreamsMetadata }) : /* @__PURE__ */ React.createElement("div", { style: { width: "100%", height: "100vh" } }, /* @__PURE__ */ React.createElement(EmptyState, { missing: "content", title: "No ImageStreams found" }));
14
+ };
15
+
16
+ export { OcirImagesView };
17
+ //# sourceMappingURL=OcirImagesView.esm.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"OcirImagesView.esm.js","sources":["../../../src/components/OcirImages/OcirImagesView.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 */\n\nimport React from 'react';\n\nimport { EmptyState, Progress } from '@backstage/core-components';\n\nimport { useAllNsImageStreams } from '../../hooks/useAllNsImageStreams';\nimport { useImageStreamsMetadataFromTag } from '../../hooks/useImageStreamsMetadataFromTag';\nimport { OcirImagesCards } from './OcirImagesCards';\n\nexport const OcirImagesView = () => {\n const { loading: imageStreamsLoading, imageStreams } = useAllNsImageStreams();\n\n const { loading: metadataLoading, imageStreamsMetadata } =\n useImageStreamsMetadataFromTag(imageStreams);\n\n if (imageStreamsLoading || metadataLoading) {\n return <Progress />;\n }\n\n return imageStreamsMetadata?.length ? (\n <OcirImagesCards imageStreams={imageStreamsMetadata} />\n ) : (\n <div style={{ width: '100%', height: '100vh' }}>\n <EmptyState missing=\"content\" title=\"No ImageStreams found\" />\n </div>\n );\n};\n"],"names":[],"mappings":";;;;;;AAwBO,MAAM,iBAAiB,MAAM;AAClC,EAAA,MAAM,EAAE,OAAA,EAAS,mBAAqB,EAAA,YAAA,KAAiB,oBAAqB,EAAA,CAAA;AAE5E,EAAA,MAAM,EAAE,OAAS,EAAA,eAAA,EAAiB,oBAAqB,EAAA,GACrD,+BAA+B,YAAY,CAAA,CAAA;AAE7C,EAAA,IAAI,uBAAuB,eAAiB,EAAA;AAC1C,IAAA,2CAAQ,QAAS,EAAA,IAAA,CAAA,CAAA;AAAA,GACnB;AAEA,EAAO,OAAA,oBAAA,EAAsB,yBAC1B,KAAA,CAAA,aAAA,CAAA,eAAA,EAAA,EAAgB,cAAc,oBAAsB,EAAA,CAAA,mBAEpD,KAAA,CAAA,aAAA,CAAA,KAAA,EAAA,EAAI,KAAO,EAAA,EAAE,OAAO,MAAQ,EAAA,MAAA,EAAQ,SACnC,EAAA,kBAAA,KAAA,CAAA,aAAA,CAAC,cAAW,OAAQ,EAAA,SAAA,EAAU,KAAM,EAAA,uBAAA,EAAwB,CAC9D,CAAA,CAAA;AAEJ;;;;"}
@@ -0,0 +1,8 @@
1
+ import React from 'react';
2
+ import { Page, Header, Content } from '@backstage/core-components';
3
+ import { OcirImagesView } from '../OcirImages/OcirImagesView.esm.js';
4
+
5
+ const OcirPage = () => /* @__PURE__ */ React.createElement(Page, { themeId: "home" }, /* @__PURE__ */ React.createElement(Header, { title: "Image Registry" }), /* @__PURE__ */ React.createElement(Content, null, /* @__PURE__ */ React.createElement(OcirImagesView, null)));
6
+
7
+ export { OcirPage };
8
+ //# sourceMappingURL=OcirPage.esm.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"OcirPage.esm.js","sources":["../../../src/components/OcirPage/OcirPage.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 */\n\nimport React from 'react';\n\nimport { Content, Header, Page } from '@backstage/core-components';\n\nimport { OcirImagesView } from '../OcirImages/OcirImagesView';\n\nexport const OcirPage = () => (\n <Page themeId=\"home\">\n <Header title=\"Image Registry\" />\n <Content>\n <OcirImagesView />\n </Content>\n </Page>\n);\n"],"names":[],"mappings":";;;;AAsBO,MAAM,WAAW,sBACtB,KAAA,CAAA,aAAA,CAAC,IAAK,EAAA,EAAA,OAAA,EAAQ,0BACX,KAAA,CAAA,aAAA,CAAA,MAAA,EAAA,EAAO,KAAM,EAAA,gBAAA,EAAiB,mBAC9B,KAAA,CAAA,aAAA,CAAA,OAAA,EAAA,IAAA,kBACE,KAAA,CAAA,aAAA,CAAA,cAAA,EAAA,IAAe,CAClB,CACF;;;;"}
@@ -0,0 +1,2 @@
1
+ export { OcirPage } from './OcirPage.esm.js';
2
+ //# sourceMappingURL=index.esm.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.esm.js","sources":[],"sourcesContent":[],"names":[],"mappings":""}
@@ -0,0 +1,31 @@
1
+ import { useState, useMemo } from 'react';
2
+ import { useAsync } from 'react-use';
3
+ import { useApi } from '@backstage/core-plugin-api';
4
+ import { formatDate } from '@janus-idp/shared-react';
5
+ import { openshiftImageRegistryApiRef } from '../api/index.esm.js';
6
+
7
+ const useAllNsImageStreams = () => {
8
+ const client = useApi(openshiftImageRegistryApiRef);
9
+ const [imageStreams, setImageStreams] = useState([]);
10
+ const { loading } = useAsync(async () => {
11
+ const imgSts = await client.getAllImageStreams() ?? [];
12
+ setImageStreams(imgSts);
13
+ });
14
+ const imageStreamsData = useMemo(() => {
15
+ if (imageStreams?.length) {
16
+ return imageStreams.map((imgSt) => ({
17
+ uid: imgSt.metadata.uid,
18
+ name: imgSt.metadata.name,
19
+ namespace: imgSt.metadata.namespace,
20
+ last_modified: imgSt.status?.tags?.[0]?.items?.[0]?.created ? formatDate(imgSt.status.tags[0].items[0].created) : "",
21
+ tags: imgSt.status?.tags?.map((t) => t.tag) ?? [],
22
+ dockerImageRepo: imgSt.status?.dockerImageRepository ?? ""
23
+ }));
24
+ }
25
+ return [];
26
+ }, [imageStreams]);
27
+ return { loading, imageStreams: imageStreamsData };
28
+ };
29
+
30
+ export { useAllNsImageStreams };
31
+ //# sourceMappingURL=useAllNsImageStreams.esm.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useAllNsImageStreams.esm.js","sources":["../../src/hooks/useAllNsImageStreams.ts"],"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 */\n\nimport { useMemo, useState } from 'react';\nimport { useAsync } from 'react-use';\n\nimport { useApi } from '@backstage/core-plugin-api';\n\nimport { formatDate } from '@janus-idp/shared-react';\n\nimport { openshiftImageRegistryApiRef } from '../api';\nimport { ImageStream } from '../types';\n\nexport const useAllNsImageStreams = () => {\n const client = useApi(openshiftImageRegistryApiRef);\n const [imageStreams, setImageStreams] = useState<any[]>([]);\n\n const { loading } = useAsync(async () => {\n const imgSts = (await client.getAllImageStreams()) ?? [];\n setImageStreams(imgSts);\n });\n\n const imageStreamsData: ImageStream[] = useMemo(() => {\n if (imageStreams?.length) {\n return imageStreams.map((imgSt: any) => ({\n uid: imgSt.metadata.uid,\n name: imgSt.metadata.name,\n namespace: imgSt.metadata.namespace,\n last_modified: imgSt.status?.tags?.[0]?.items?.[0]?.created\n ? formatDate(imgSt.status.tags[0].items[0].created)\n : '',\n tags: imgSt.status?.tags?.map((t: any) => t.tag) ?? [],\n dockerImageRepo: imgSt.status?.dockerImageRepository ?? '',\n }));\n }\n return [];\n }, [imageStreams]);\n\n return { loading, imageStreams: imageStreamsData };\n};\n"],"names":[],"mappings":";;;;;;AA0BO,MAAM,uBAAuB,MAAM;AACxC,EAAM,MAAA,MAAA,GAAS,OAAO,4BAA4B,CAAA,CAAA;AAClD,EAAA,MAAM,CAAC,YAAc,EAAA,eAAe,CAAI,GAAA,QAAA,CAAgB,EAAE,CAAA,CAAA;AAE1D,EAAA,MAAM,EAAE,OAAA,EAAY,GAAA,QAAA,CAAS,YAAY;AACvC,IAAA,MAAM,MAAU,GAAA,MAAM,MAAO,CAAA,kBAAA,MAAyB,EAAC,CAAA;AACvD,IAAA,eAAA,CAAgB,MAAM,CAAA,CAAA;AAAA,GACvB,CAAA,CAAA;AAED,EAAM,MAAA,gBAAA,GAAkC,QAAQ,MAAM;AACpD,IAAA,IAAI,cAAc,MAAQ,EAAA;AACxB,MAAO,OAAA,YAAA,CAAa,GAAI,CAAA,CAAC,KAAgB,MAAA;AAAA,QACvC,GAAA,EAAK,MAAM,QAAS,CAAA,GAAA;AAAA,QACpB,IAAA,EAAM,MAAM,QAAS,CAAA,IAAA;AAAA,QACrB,SAAA,EAAW,MAAM,QAAS,CAAA,SAAA;AAAA,QAC1B,aAAA,EAAe,MAAM,MAAQ,EAAA,IAAA,GAAO,CAAC,CAAG,EAAA,KAAA,GAAQ,CAAC,CAAG,EAAA,OAAA,GAChD,WAAW,KAAM,CAAA,MAAA,CAAO,KAAK,CAAC,CAAA,CAAE,MAAM,CAAC,CAAA,CAAE,OAAO,CAChD,GAAA,EAAA;AAAA,QACJ,IAAA,EAAM,KAAM,CAAA,MAAA,EAAQ,IAAM,EAAA,GAAA,CAAI,CAAC,CAAW,KAAA,CAAA,CAAE,GAAG,CAAA,IAAK,EAAC;AAAA,QACrD,eAAA,EAAiB,KAAM,CAAA,MAAA,EAAQ,qBAAyB,IAAA,EAAA;AAAA,OACxD,CAAA,CAAA,CAAA;AAAA,KACJ;AACA,IAAA,OAAO,EAAC,CAAA;AAAA,GACV,EAAG,CAAC,YAAY,CAAC,CAAA,CAAA;AAEjB,EAAO,OAAA,EAAE,OAAS,EAAA,YAAA,EAAc,gBAAiB,EAAA,CAAA;AACnD;;;;"}
@@ -0,0 +1,36 @@
1
+ import { useState } from 'react';
2
+ import { useAsync } from 'react-use';
3
+ import { useApi } from '@backstage/core-plugin-api';
4
+ import { formatByteSize } from '@janus-idp/shared-react';
5
+ import { openshiftImageRegistryApiRef } from '../api/index.esm.js';
6
+
7
+ const useImageStreamsMetadataFromTag = (imageStreams) => {
8
+ const client = useApi(openshiftImageRegistryApiRef);
9
+ const [imageStreamsData, setImageStreamsData] = useState([]);
10
+ const { loading } = useAsync(async () => {
11
+ const imgStsData = imageStreams?.length ? await Promise.all(
12
+ imageStreams.map(async (imst) => {
13
+ try {
14
+ const tag = await client.getImageStreamTag(
15
+ imst.namespace,
16
+ imst.name,
17
+ imst.tags[0] || ""
18
+ );
19
+ return {
20
+ ...imst,
21
+ description: tag.image.dockerImageMetadata?.Config?.Labels?.["io.k8s.description"] || tag.image.dockerImageMetadata?.Config?.description || "",
22
+ version: tag.image.dockerImageMetadata?.Config?.Labels?.version || "",
23
+ size: formatByteSize(tag.image.dockerImageMetadata?.Size) || ""
24
+ };
25
+ } catch {
26
+ return imst;
27
+ }
28
+ })
29
+ ) : [];
30
+ setImageStreamsData(imgStsData);
31
+ }, [imageStreams]);
32
+ return { loading, imageStreamsMetadata: imageStreamsData };
33
+ };
34
+
35
+ export { useImageStreamsMetadataFromTag };
36
+ //# sourceMappingURL=useImageStreamsMetadataFromTag.esm.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useImageStreamsMetadataFromTag.esm.js","sources":["../../src/hooks/useImageStreamsMetadataFromTag.ts"],"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 */\n\nimport { useState } from 'react';\nimport { useAsync } from 'react-use';\n\nimport { useApi } from '@backstage/core-plugin-api';\n\nimport { formatByteSize } from '@janus-idp/shared-react';\n\nimport { openshiftImageRegistryApiRef } from '../api';\nimport { ImageStream, ImageStreamMetadata } from '../types';\n\nexport const useImageStreamsMetadataFromTag = (imageStreams: ImageStream[]) => {\n const client = useApi(openshiftImageRegistryApiRef);\n const [imageStreamsData, setImageStreamsData] = useState<\n ImageStreamMetadata[]\n >([]);\n\n const { loading } = useAsync(async () => {\n const imgStsData = imageStreams?.length\n ? await Promise.all(\n imageStreams.map(async (imst: ImageStream) => {\n try {\n const tag = await client.getImageStreamTag(\n imst.namespace,\n imst.name,\n imst.tags[0] || '',\n );\n return {\n ...imst,\n description:\n tag.image.dockerImageMetadata?.Config?.Labels?.[\n 'io.k8s.description'\n ] ||\n tag.image.dockerImageMetadata?.Config?.description ||\n '',\n version:\n tag.image.dockerImageMetadata?.Config?.Labels?.version || '',\n size: formatByteSize(tag.image.dockerImageMetadata?.Size) || '',\n };\n } catch {\n return imst;\n }\n }),\n )\n : [];\n setImageStreamsData(imgStsData);\n }, [imageStreams]);\n\n return { loading, imageStreamsMetadata: imageStreamsData };\n};\n"],"names":[],"mappings":";;;;;;AA0Ba,MAAA,8BAAA,GAAiC,CAAC,YAAgC,KAAA;AAC7E,EAAM,MAAA,MAAA,GAAS,OAAO,4BAA4B,CAAA,CAAA;AAClD,EAAA,MAAM,CAAC,gBAAkB,EAAA,mBAAmB,CAAI,GAAA,QAAA,CAE9C,EAAE,CAAA,CAAA;AAEJ,EAAA,MAAM,EAAE,OAAA,EAAY,GAAA,QAAA,CAAS,YAAY;AACvC,IAAA,MAAM,UAAa,GAAA,YAAA,EAAc,MAC7B,GAAA,MAAM,OAAQ,CAAA,GAAA;AAAA,MACZ,YAAA,CAAa,GAAI,CAAA,OAAO,IAAsB,KAAA;AAC5C,QAAI,IAAA;AACF,UAAM,MAAA,GAAA,GAAM,MAAM,MAAO,CAAA,iBAAA;AAAA,YACvB,IAAK,CAAA,SAAA;AAAA,YACL,IAAK,CAAA,IAAA;AAAA,YACL,IAAA,CAAK,IAAK,CAAA,CAAC,CAAK,IAAA,EAAA;AAAA,WAClB,CAAA;AACA,UAAO,OAAA;AAAA,YACL,GAAG,IAAA;AAAA,YACH,WACE,EAAA,GAAA,CAAI,KAAM,CAAA,mBAAA,EAAqB,MAAQ,EAAA,MAAA,GACrC,oBACF,CAAA,IACA,GAAI,CAAA,KAAA,CAAM,mBAAqB,EAAA,MAAA,EAAQ,WACvC,IAAA,EAAA;AAAA,YACF,SACE,GAAI,CAAA,KAAA,CAAM,mBAAqB,EAAA,MAAA,EAAQ,QAAQ,OAAW,IAAA,EAAA;AAAA,YAC5D,MAAM,cAAe,CAAA,GAAA,CAAI,KAAM,CAAA,mBAAA,EAAqB,IAAI,CAAK,IAAA,EAAA;AAAA,WAC/D,CAAA;AAAA,SACM,CAAA,MAAA;AACN,UAAO,OAAA,IAAA,CAAA;AAAA,SACT;AAAA,OACD,CAAA;AAAA,QAEH,EAAC,CAAA;AACL,IAAA,mBAAA,CAAoB,UAAU,CAAA,CAAA;AAAA,GAChC,EAAG,CAAC,YAAY,CAAC,CAAA,CAAA;AAEjB,EAAO,OAAA,EAAE,OAAS,EAAA,oBAAA,EAAsB,gBAAiB,EAAA,CAAA;AAC3D;;;;"}
@@ -0,0 +1,10 @@
1
+ /// <reference types="react" />
2
+ import * as react from 'react';
3
+ import * as _backstage_core_plugin_api from '@backstage/core-plugin-api';
4
+
5
+ declare const openshiftImageRegistryPlugin: _backstage_core_plugin_api.BackstagePlugin<{
6
+ root: _backstage_core_plugin_api.RouteRef<undefined>;
7
+ }, {}, {}>;
8
+ declare const OpenshiftImageRegistryPage: () => react.JSX.Element;
9
+
10
+ export { OpenshiftImageRegistryPage, openshiftImageRegistryPlugin };
@@ -0,0 +1,2 @@
1
+ export { OpenshiftImageRegistryPage, openshiftImageRegistryPlugin } from './plugin.esm.js';
2
+ //# sourceMappingURL=index.esm.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.esm.js","sources":[],"sourcesContent":[],"names":[],"mappings":""}