@axis-backstage/plugin-statuspage 0.10.2 → 0.11.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,31 @@
1
1
  # @axis-backstage/plugin-statuspage
2
2
 
3
+ ## 0.11.0
4
+
5
+ ### Minor Changes
6
+
7
+ - d29962b: Add support for the new frontend system (NFS). The plugin can now be imported from the `./alpha` entry point and registered as a feature in a new-system app.
8
+
9
+ The plugin provides three extensions out of the box:
10
+
11
+ - `api:statuspage` — registers the `StatuspageClient`
12
+ - `page:statuspage` — mounts the full statuspage at `/statuspage`
13
+ - `entity-card:statuspage` — renders the `StatuspageEntityCard` on entity pages
14
+
15
+ Configure the instance name for the page extension in `app-config.yaml`:
16
+
17
+ ```yaml
18
+ app:
19
+ extensions:
20
+ - page:statuspage:
21
+ config:
22
+ name: mystatuspageinstance
23
+ ```
24
+
25
+ ### Patch Changes
26
+
27
+ - d29962b: Use EntityInfoCard as the entity card wrapper
28
+
3
29
  ## 0.10.2
4
30
 
5
31
  ### Patch Changes
package/README.md CHANGED
@@ -101,3 +101,39 @@ The `component_id` could be the id of either a component or a component group. T
101
101
 
102
102
  <Route path="/statuspage" element={<StatuspagePage name="myid" />} />
103
103
  ```
104
+
105
+ ## New Frontend System
106
+
107
+ 1. First, install the plugin into your app:
108
+
109
+ ```bash
110
+ # From your Backstage root directory
111
+ yarn --cwd packages/app add @axis-backstage/plugin-statuspage
112
+ ```
113
+
114
+ 2. If [feature discovery](https://backstage.io/docs/frontend-system/architecture/app/#feature-discovery) is enabled in your app, the plugin will be automatically discovered. If not, add it manually:
115
+
116
+ ```ts
117
+ // packages/app/src/App.tsx
118
+ import statuspagePlugin from '@axis-backstage/plugin-statuspage/alpha';
119
+
120
+ const app = createApp({
121
+ features: [
122
+ // ...
123
+ statuspagePlugin,
124
+ ],
125
+ });
126
+ ```
127
+
128
+ 3. Configure the statuspage instance name for the page extension in `app-config.yaml`:
129
+
130
+ ```yaml
131
+ # app-config.yaml
132
+ app:
133
+ extensions:
134
+ - page:statuspage:
135
+ config:
136
+ name: mystatuspageinstance
137
+ ```
138
+
139
+ The `StatuspageEntityCard` is automatically added to entity pages via the `entity-card:statuspage` extension. No additional wiring in `EntityPage.tsx` is needed. The entity annotation setup remains the same — see [Integration with the Catalog](#integration-with-the-catalog) above.
@@ -0,0 +1,94 @@
1
+ import * as _backstage_plugin_catalog_react_alpha from '@backstage/plugin-catalog-react/alpha';
2
+ import * as _backstage_catalog_model from '@backstage/catalog-model';
3
+ import * as react from 'react';
4
+ import * as _backstage_filter_predicates from '@backstage/filter-predicates';
5
+ import * as _backstage_frontend_plugin_api from '@backstage/frontend-plugin-api';
6
+ import * as _backstage_core_plugin_api from '@backstage/core-plugin-api';
7
+
8
+ /**
9
+ * Frontend plugin that allows visualization of component statuses from statuspage.io.
10
+ *
11
+ * @packageDocumentation
12
+ */
13
+ declare const _default: _backstage_frontend_plugin_api.OverridableFrontendPlugin<{
14
+ root: _backstage_core_plugin_api.RouteRef<undefined>;
15
+ }, {}, {
16
+ "api:statuspage": _backstage_frontend_plugin_api.OverridableExtensionDefinition<{
17
+ kind: "api";
18
+ name: undefined;
19
+ config: {};
20
+ configInput: {};
21
+ output: _backstage_frontend_plugin_api.ExtensionDataRef<_backstage_frontend_plugin_api.AnyApiFactory, "core.api.factory", {}>;
22
+ inputs: {};
23
+ params: <TApi, TImpl extends TApi, TDeps extends { [name in string]: unknown; }>(params: _backstage_frontend_plugin_api.ApiFactory<TApi, TImpl, TDeps>) => _backstage_frontend_plugin_api.ExtensionBlueprintParams<_backstage_frontend_plugin_api.AnyApiFactory>;
24
+ }>;
25
+ "entity-card:statuspage": _backstage_frontend_plugin_api.OverridableExtensionDefinition<{
26
+ kind: "entity-card";
27
+ name: undefined;
28
+ config: {
29
+ filter: _backstage_filter_predicates.FilterPredicate | undefined;
30
+ type: "content" | "info" | undefined;
31
+ };
32
+ configInput: {
33
+ filter?: _backstage_filter_predicates.FilterPredicate | undefined;
34
+ type?: "content" | "info" | undefined;
35
+ };
36
+ output: _backstage_frontend_plugin_api.ExtensionDataRef<react.JSX.Element, "core.reactElement", {}> | _backstage_frontend_plugin_api.ExtensionDataRef<(entity: _backstage_catalog_model.Entity) => boolean, "catalog.entity-filter-function", {
37
+ optional: true;
38
+ }> | _backstage_frontend_plugin_api.ExtensionDataRef<string, "catalog.entity-filter-expression", {
39
+ optional: true;
40
+ }> | _backstage_frontend_plugin_api.ExtensionDataRef<_backstage_plugin_catalog_react_alpha.EntityCardType, "catalog.entity-card-type", {
41
+ optional: true;
42
+ }>;
43
+ inputs: {};
44
+ params: {
45
+ loader: () => Promise<JSX.Element>;
46
+ filter?: string | _backstage_filter_predicates.FilterPredicate | ((entity: _backstage_catalog_model.Entity) => boolean);
47
+ type?: _backstage_plugin_catalog_react_alpha.EntityCardType;
48
+ };
49
+ }>;
50
+ "page:statuspage": _backstage_frontend_plugin_api.OverridableExtensionDefinition<{
51
+ config: {
52
+ name: string;
53
+ path: string | undefined;
54
+ title: string | undefined;
55
+ };
56
+ configInput: {
57
+ name?: string | undefined;
58
+ path?: string | undefined | undefined;
59
+ title?: string | undefined | undefined;
60
+ };
61
+ output: _backstage_frontend_plugin_api.ExtensionDataRef<react.JSX.Element, "core.reactElement", {}> | _backstage_frontend_plugin_api.ExtensionDataRef<string, "core.routing.path", {}> | _backstage_frontend_plugin_api.ExtensionDataRef<_backstage_frontend_plugin_api.RouteRef<_backstage_frontend_plugin_api.AnyRouteRefParams>, "core.routing.ref", {
62
+ optional: true;
63
+ }> | _backstage_frontend_plugin_api.ExtensionDataRef<string, "core.title", {
64
+ optional: true;
65
+ }> | _backstage_frontend_plugin_api.ExtensionDataRef<_backstage_frontend_plugin_api.IconElement, "core.icon", {
66
+ optional: true;
67
+ }>;
68
+ inputs: {
69
+ pages: _backstage_frontend_plugin_api.ExtensionInput<_backstage_frontend_plugin_api.ConfigurableExtensionDataRef<react.JSX.Element, "core.reactElement", {}> | _backstage_frontend_plugin_api.ConfigurableExtensionDataRef<string, "core.routing.path", {}> | _backstage_frontend_plugin_api.ConfigurableExtensionDataRef<_backstage_frontend_plugin_api.RouteRef<_backstage_frontend_plugin_api.AnyRouteRefParams>, "core.routing.ref", {
70
+ optional: true;
71
+ }> | _backstage_frontend_plugin_api.ConfigurableExtensionDataRef<string, "core.title", {
72
+ optional: true;
73
+ }> | _backstage_frontend_plugin_api.ConfigurableExtensionDataRef<_backstage_frontend_plugin_api.IconElement, "core.icon", {
74
+ optional: true;
75
+ }>, {
76
+ singleton: false;
77
+ optional: false;
78
+ internal: false;
79
+ }>;
80
+ };
81
+ kind: "page";
82
+ name: undefined;
83
+ params: {
84
+ path: string;
85
+ title?: string;
86
+ icon?: _backstage_frontend_plugin_api.IconElement;
87
+ loader?: () => Promise<react.JSX.Element>;
88
+ routeRef?: _backstage_frontend_plugin_api.RouteRef;
89
+ noHeader?: boolean;
90
+ };
91
+ }>;
92
+ }>;
93
+
94
+ export { _default as default };
@@ -0,0 +1,58 @@
1
+ import { jsx } from 'react/jsx-runtime';
2
+ import { ApiBlueprint, fetchApiRef, discoveryApiRef, PageBlueprint, createFrontendPlugin } from '@backstage/frontend-plugin-api';
3
+ import { statuspageApiRef } from './api/StatuspageApi.esm.js';
4
+ import { StatuspageClient } from './api/StatuspageClient.esm.js';
5
+ import { EntityCardBlueprint } from '@backstage/plugin-catalog-react/alpha';
6
+ import { rootRouteRef } from './routes.esm.js';
7
+ import { z } from 'zod';
8
+
9
+ const statuspageApi = ApiBlueprint.make({
10
+ params: (defineParams) => defineParams({
11
+ api: statuspageApiRef,
12
+ deps: {
13
+ discoveryApi: discoveryApiRef,
14
+ fetchApi: fetchApiRef
15
+ },
16
+ factory: ({ discoveryApi, fetchApi }) => new StatuspageClient({ discoveryApi, fetchApi })
17
+ })
18
+ });
19
+ const statuspagePage = PageBlueprint.makeWithOverrides({
20
+ configSchema: {
21
+ /**
22
+ * The name of the statuspage instance as configured in `app-config.yaml`.
23
+ *
24
+ * @example
25
+ * ```yaml
26
+ * # app-config.yaml
27
+ * app:
28
+ * extensions:
29
+ * - page:statuspage:
30
+ * config:
31
+ * name: mystatuspageinstance
32
+ * ```
33
+ */
34
+ name: z.string().default("")
35
+ },
36
+ factory(originalFactory, { config }) {
37
+ return originalFactory({
38
+ path: "/statuspage",
39
+ routeRef: rootRouteRef,
40
+ loader: async () => import('./components/StatuspageComponent.esm.js').then((m) => /* @__PURE__ */ jsx(m.StatuspageComponent, { name: config.name }))
41
+ });
42
+ }
43
+ });
44
+ const statuspageEntityCard = EntityCardBlueprint.make({
45
+ params: {
46
+ loader: async () => import('./components/StatuspageEntityCard.esm.js').then((m) => /* @__PURE__ */ jsx(m.StatuspageEntityCard, {}))
47
+ }
48
+ });
49
+ var alpha = createFrontendPlugin({
50
+ pluginId: "statuspage",
51
+ extensions: [statuspageApi, statuspagePage, statuspageEntityCard],
52
+ routes: {
53
+ root: rootRouteRef
54
+ }
55
+ });
56
+
57
+ export { alpha as default };
58
+ //# sourceMappingURL=alpha.esm.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"alpha.esm.js","sources":["../src/alpha.tsx"],"sourcesContent":["/**\n * Frontend plugin that allows visualization of component statuses from statuspage.io.\n *\n * @packageDocumentation\n */\n\nimport {\n ApiBlueprint,\n createFrontendPlugin,\n discoveryApiRef,\n fetchApiRef,\n PageBlueprint,\n} from '@backstage/frontend-plugin-api';\nimport { statuspageApiRef } from './api/StatuspageApi';\nimport { StatuspageClient } from './api/StatuspageClient';\nimport { EntityCardBlueprint } from '@backstage/plugin-catalog-react/alpha';\nimport { rootRouteRef } from './routes';\nimport { z } from 'zod';\n\nconst statuspageApi = ApiBlueprint.make({\n params: defineParams =>\n defineParams({\n api: statuspageApiRef,\n deps: {\n discoveryApi: discoveryApiRef,\n fetchApi: fetchApiRef,\n },\n factory: ({ discoveryApi, fetchApi }) =>\n new StatuspageClient({ discoveryApi, fetchApi }),\n }),\n});\n\nconst statuspagePage = PageBlueprint.makeWithOverrides({\n configSchema: {\n /**\n * The name of the statuspage instance as configured in `app-config.yaml`.\n *\n * @example\n * ```yaml\n * # app-config.yaml\n * app:\n * extensions:\n * - page:statuspage:\n * config:\n * name: mystatuspageinstance\n * ```\n */\n name: z.string().default(''),\n },\n factory(originalFactory, { config }) {\n return originalFactory({\n path: '/statuspage',\n routeRef: rootRouteRef,\n loader: async () =>\n import('./components/StatuspageComponent').then(m => (\n <m.StatuspageComponent name={config.name} />\n )),\n });\n },\n});\n\nconst statuspageEntityCard = EntityCardBlueprint.make({\n params: {\n loader: async () =>\n import('./components/StatuspageEntityCard').then(m => (\n <m.StatuspageEntityCard />\n )),\n },\n});\n\nexport default createFrontendPlugin({\n pluginId: 'statuspage',\n extensions: [statuspageApi, statuspagePage, statuspageEntityCard],\n routes: {\n root: rootRouteRef,\n },\n});\n"],"names":[],"mappings":";;;;;;;;AAmBA,MAAM,aAAA,GAAgB,aAAa,IAAA,CAAK;AAAA,EACtC,MAAA,EAAQ,kBACN,YAAA,CAAa;AAAA,IACX,GAAA,EAAK,gBAAA;AAAA,IACL,IAAA,EAAM;AAAA,MACJ,YAAA,EAAc,eAAA;AAAA,MACd,QAAA,EAAU;AAAA,KACZ;AAAA,IACA,OAAA,EAAS,CAAC,EAAE,YAAA,EAAc,QAAA,EAAS,KACjC,IAAI,gBAAA,CAAiB,EAAE,YAAA,EAAc,QAAA,EAAU;AAAA,GAClD;AACL,CAAC,CAAA;AAED,MAAM,cAAA,GAAiB,cAAc,iBAAA,CAAkB;AAAA,EACrD,YAAA,EAAc;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAcZ,IAAA,EAAM,CAAA,CAAE,MAAA,EAAO,CAAE,QAAQ,EAAE;AAAA,GAC7B;AAAA,EACA,OAAA,CAAQ,eAAA,EAAiB,EAAE,MAAA,EAAO,EAAG;AACnC,IAAA,OAAO,eAAA,CAAgB;AAAA,MACrB,IAAA,EAAM,aAAA;AAAA,MACN,QAAA,EAAU,YAAA;AAAA,MACV,MAAA,EAAQ,YACN,OAAO,yCAAkC,EAAE,IAAA,CAAK,CAAA,CAAA,qBAC9C,GAAA,CAAC,CAAA,CAAE,mBAAA,EAAF,EAAsB,IAAA,EAAM,MAAA,CAAO,MAAM,CAC3C;AAAA,KACJ,CAAA;AAAA,EACH;AACF,CAAC,CAAA;AAED,MAAM,oBAAA,GAAuB,oBAAoB,IAAA,CAAK;AAAA,EACpD,MAAA,EAAQ;AAAA,IACN,MAAA,EAAQ,YACN,OAAO,0CAAmC,CAAA,CAAE,IAAA,CAAK,CAAA,CAAA,qBAC/C,GAAA,CAAC,CAAA,CAAE,oBAAA,EAAF,EAAuB,CACzB;AAAA;AAEP,CAAC,CAAA;AAED,YAAe,oBAAA,CAAqB;AAAA,EAClC,QAAA,EAAU,YAAA;AAAA,EACV,UAAA,EAAY,CAAC,aAAA,EAAe,cAAA,EAAgB,oBAAoB,CAAA;AAAA,EAChE,MAAA,EAAQ;AAAA,IACN,IAAA,EAAM;AAAA;AAEV,CAAC,CAAA;;;;"}
@@ -1,7 +1,7 @@
1
1
  import { jsx, jsxs } from 'react/jsx-runtime';
2
- import { Progress, ResponseErrorPanel, InfoCard } from '@backstage/core-components';
2
+ import { Progress, ResponseErrorPanel } from '@backstage/core-components';
3
3
  import OpenInNewIcon from '@mui/icons-material/OpenInNew';
4
- import { useEntity } from '@backstage/plugin-catalog-react';
4
+ import { useEntity, EntityInfoCard } from '@backstage/plugin-catalog-react';
5
5
  import { ComponentsTable } from './ComponentsTable.esm.js';
6
6
  import { ComponentGroupsList } from './ComponentGroupsList.esm.js';
7
7
  import IconButton from '@mui/material/IconButton';
@@ -46,9 +46,9 @@ const StatuspageEntityCard = () => {
46
46
  ) || [];
47
47
  const noComponents = (!filteredComponents || filteredComponentGroups.length === 0) && filteredComponents && filteredComponents.length === 0;
48
48
  if (noComponents) {
49
- return /* @__PURE__ */ jsx(InfoCard, { title: "Service Status", action: linkAction, children: /* @__PURE__ */ jsx(Typography, { variant: "body2", color: "#FF5555", children: "The specified statuspage.io components could not be found. Check your annotation." }) });
49
+ return /* @__PURE__ */ jsx(EntityInfoCard, { title: "Service Status", headerActions: linkAction, children: /* @__PURE__ */ jsx(Typography, { variant: "body2", color: "#FF5555", children: "The specified statuspage.io components could not be found. Check your annotation." }) });
50
50
  }
51
- return /* @__PURE__ */ jsxs(InfoCard, { title: "Service Status", action: linkAction, children: [
51
+ return /* @__PURE__ */ jsxs(EntityInfoCard, { title: "Service Status", headerActions: linkAction, children: [
52
52
  filteredComponents && filteredComponents.length > 0 && /* @__PURE__ */ jsx(ComponentsTable, { components: filteredComponents }),
53
53
  filteredComponentGroups && filteredComponentGroups.length > 0 && /* @__PURE__ */ jsx(
54
54
  ComponentGroupsList,
@@ -1 +1 @@
1
- {"version":3,"file":"StatuspageEntityCard.esm.js","sources":["../../src/components/StatuspageEntityCard.tsx"],"sourcesContent":["import {\n InfoCard,\n Progress,\n ResponseErrorPanel,\n} from '@backstage/core-components';\nimport OpenInNewIcon from '@mui/icons-material/OpenInNew';\nimport { useEntity } from '@backstage/plugin-catalog-react';\nimport { ComponentsTable } from './ComponentsTable';\nimport { ComponentGroupsList } from './ComponentGroupsList';\nimport IconButton from '@mui/material/IconButton';\nimport Typography from '@mui/material/Typography';\nimport { STATUSPAGE_ANNOTATION } from '@axis-backstage/plugin-statuspage-common';\nimport { useComponents } from '../hooks/useComponents';\n\n/**\n * Statuspage card intended for the EntityPage. Allows embedding of specific\n * statuspage components and component groups.\n *\n * @public\n */\nexport const StatuspageEntityCard = () => {\n const { entity } = useEntity();\n const [name, wantedComponentsStr] =\n entity.metadata.annotations?.[STATUSPAGE_ANNOTATION]?.split(':')!;\n const wantedComponents = wantedComponentsStr?.split(',').map(it => it.trim());\n\n const { loading, error, value } = useComponents(name);\n\n if (loading) {\n return <Progress />;\n }\n if (error) {\n return <ResponseErrorPanel error={error} />;\n }\n\n if (loading) {\n return <Progress />;\n }\n if (error) {\n return <ResponseErrorPanel error={error} />;\n }\n\n const linkAction = value?.url && (\n <IconButton\n aria-label=\"Go to our statuspage\"\n role=\"button\"\n title=\"Go to statuspage(.io)\"\n href={value?.url}\n target=\"_blank\"\n >\n <OpenInNewIcon />\n </IconButton>\n );\n\n const fullStatuspage = !wantedComponents;\n const filteredComponents =\n value?.components.filter(\n c => !fullStatuspage && !c.group && wantedComponents.includes(c.id),\n ) || [];\n const filteredComponentGroups =\n value?.componentGroups.filter(\n c => fullStatuspage || wantedComponents.includes(c.id),\n ) || [];\n const noComponents =\n (!filteredComponents || filteredComponentGroups.length === 0) &&\n filteredComponents &&\n filteredComponents.length === 0;\n\n if (noComponents) {\n return (\n <InfoCard title=\"Service Status\" action={linkAction}>\n <Typography variant=\"body2\" color=\"#FF5555\">\n The specified statuspage.io components could not be found. Check your\n annotation.\n </Typography>\n </InfoCard>\n );\n }\n return (\n <InfoCard title=\"Service Status\" action={linkAction}>\n {filteredComponents && filteredComponents.length > 0 && (\n <ComponentsTable components={filteredComponents} />\n )}\n {filteredComponentGroups && filteredComponentGroups.length > 0 && (\n <ComponentGroupsList\n components={value?.components || []}\n componentGroups={filteredComponentGroups}\n expanded={!fullStatuspage}\n />\n )}\n </InfoCard>\n );\n};\n"],"names":[],"mappings":";;;;;;;;;;;AAoBO,MAAM,uBAAuB,MAAM;AACxC,EAAA,MAAM,EAAE,MAAA,EAAO,GAAI,SAAA,EAAU;AAC7B,EAAA,MAAM,CAAC,IAAA,EAAM,mBAAmB,CAAA,GAC9B,MAAA,CAAO,SAAS,WAAA,GAAc,qBAAqB,CAAA,EAAG,KAAA,CAAM,GAAG,CAAA;AACjE,EAAA,MAAM,gBAAA,GAAmB,qBAAqB,KAAA,CAAM,GAAG,EAAE,GAAA,CAAI,CAAA,EAAA,KAAM,EAAA,CAAG,IAAA,EAAM,CAAA;AAE5E,EAAA,MAAM,EAAE,OAAA,EAAS,KAAA,EAAO,KAAA,EAAM,GAAI,cAAc,IAAI,CAAA;AAEpD,EAAA,IAAI,OAAA,EAAS;AACX,IAAA,2BAAQ,QAAA,EAAA,EAAS,CAAA;AAAA,EACnB;AACA,EAAA,IAAI,KAAA,EAAO;AACT,IAAA,uBAAO,GAAA,CAAC,sBAAmB,KAAA,EAAc,CAAA;AAAA,EAC3C;AAEA,EAAA,IAAI,OAAA,EAAS;AACX,IAAA,2BAAQ,QAAA,EAAA,EAAS,CAAA;AAAA,EACnB;AACA,EAAA,IAAI,KAAA,EAAO;AACT,IAAA,uBAAO,GAAA,CAAC,sBAAmB,KAAA,EAAc,CAAA;AAAA,EAC3C;AAEA,EAAA,MAAM,UAAA,GAAa,OAAO,GAAA,oBACxB,GAAA;AAAA,IAAC,UAAA;AAAA,IAAA;AAAA,MACC,YAAA,EAAW,sBAAA;AAAA,MACX,IAAA,EAAK,QAAA;AAAA,MACL,KAAA,EAAM,uBAAA;AAAA,MACN,MAAM,KAAA,EAAO,GAAA;AAAA,MACb,MAAA,EAAO,QAAA;AAAA,MAEP,8BAAC,aAAA,EAAA,EAAc;AAAA;AAAA,GACjB;AAGF,EAAA,MAAM,iBAAiB,CAAC,gBAAA;AACxB,EAAA,MAAM,kBAAA,GACJ,OAAO,UAAA,CAAW,MAAA;AAAA,IAChB,CAAA,CAAA,KAAK,CAAC,cAAA,IAAkB,CAAC,EAAE,KAAA,IAAS,gBAAA,CAAiB,QAAA,CAAS,CAAA,CAAE,EAAE;AAAA,OAC/D,EAAC;AACR,EAAA,MAAM,uBAAA,GACJ,OAAO,eAAA,CAAgB,MAAA;AAAA,IACrB,CAAA,CAAA,KAAK,cAAA,IAAkB,gBAAA,CAAiB,QAAA,CAAS,EAAE,EAAE;AAAA,OAClD,EAAC;AACR,EAAA,MAAM,YAAA,GAAA,CACH,CAAC,kBAAA,IAAsB,uBAAA,CAAwB,WAAW,CAAA,KAC3D,kBAAA,IACA,mBAAmB,MAAA,KAAW,CAAA;AAEhC,EAAA,IAAI,YAAA,EAAc;AAChB,IAAA,uBACE,GAAA,CAAC,QAAA,EAAA,EAAS,KAAA,EAAM,gBAAA,EAAiB,MAAA,EAAQ,UAAA,EACvC,QAAA,kBAAA,GAAA,CAAC,UAAA,EAAA,EAAW,OAAA,EAAQ,OAAA,EAAQ,KAAA,EAAM,SAAA,EAAU,+FAG5C,CAAA,EACF,CAAA;AAAA,EAEJ;AACA,EAAA,uBACE,IAAA,CAAC,QAAA,EAAA,EAAS,KAAA,EAAM,gBAAA,EAAiB,QAAQ,UAAA,EACtC,QAAA,EAAA;AAAA,IAAA,kBAAA,IAAsB,mBAAmB,MAAA,GAAS,CAAA,oBACjD,GAAA,CAAC,eAAA,EAAA,EAAgB,YAAY,kBAAA,EAAoB,CAAA;AAAA,IAElD,uBAAA,IAA2B,uBAAA,CAAwB,MAAA,GAAS,CAAA,oBAC3D,GAAA;AAAA,MAAC,mBAAA;AAAA,MAAA;AAAA,QACC,UAAA,EAAY,KAAA,EAAO,UAAA,IAAc,EAAC;AAAA,QAClC,eAAA,EAAiB,uBAAA;AAAA,QACjB,UAAU,CAAC;AAAA;AAAA;AACb,GAAA,EAEJ,CAAA;AAEJ;;;;"}
1
+ {"version":3,"file":"StatuspageEntityCard.esm.js","sources":["../../src/components/StatuspageEntityCard.tsx"],"sourcesContent":["import { Progress, ResponseErrorPanel } from '@backstage/core-components';\nimport OpenInNewIcon from '@mui/icons-material/OpenInNew';\nimport { EntityInfoCard } from '@backstage/plugin-catalog-react';\nimport { useEntity } from '@backstage/plugin-catalog-react';\nimport { ComponentsTable } from './ComponentsTable';\nimport { ComponentGroupsList } from './ComponentGroupsList';\nimport IconButton from '@mui/material/IconButton';\nimport Typography from '@mui/material/Typography';\nimport { STATUSPAGE_ANNOTATION } from '@axis-backstage/plugin-statuspage-common';\nimport { useComponents } from '../hooks/useComponents';\n\n/**\n * Statuspage card intended for the EntityPage. Allows embedding of specific\n * statuspage components and component groups.\n *\n * @public\n */\nexport const StatuspageEntityCard = () => {\n const { entity } = useEntity();\n const [name, wantedComponentsStr] =\n entity.metadata.annotations?.[STATUSPAGE_ANNOTATION]?.split(':')!;\n const wantedComponents = wantedComponentsStr?.split(',').map(it => it.trim());\n\n const { loading, error, value } = useComponents(name);\n\n if (loading) {\n return <Progress />;\n }\n if (error) {\n return <ResponseErrorPanel error={error} />;\n }\n\n if (loading) {\n return <Progress />;\n }\n if (error) {\n return <ResponseErrorPanel error={error} />;\n }\n\n const linkAction = value?.url && (\n <IconButton\n aria-label=\"Go to our statuspage\"\n role=\"button\"\n title=\"Go to statuspage(.io)\"\n href={value?.url}\n target=\"_blank\"\n >\n <OpenInNewIcon />\n </IconButton>\n );\n\n const fullStatuspage = !wantedComponents;\n const filteredComponents =\n value?.components.filter(\n c => !fullStatuspage && !c.group && wantedComponents.includes(c.id),\n ) || [];\n const filteredComponentGroups =\n value?.componentGroups.filter(\n c => fullStatuspage || wantedComponents.includes(c.id),\n ) || [];\n const noComponents =\n (!filteredComponents || filteredComponentGroups.length === 0) &&\n filteredComponents &&\n filteredComponents.length === 0;\n\n if (noComponents) {\n return (\n <EntityInfoCard title=\"Service Status\" headerActions={linkAction}>\n <Typography variant=\"body2\" color=\"#FF5555\">\n The specified statuspage.io components could not be found. Check your\n annotation.\n </Typography>\n </EntityInfoCard>\n );\n }\n return (\n <EntityInfoCard title=\"Service Status\" headerActions={linkAction}>\n {filteredComponents && filteredComponents.length > 0 && (\n <ComponentsTable components={filteredComponents} />\n )}\n {filteredComponentGroups && filteredComponentGroups.length > 0 && (\n <ComponentGroupsList\n components={value?.components || []}\n componentGroups={filteredComponentGroups}\n expanded={!fullStatuspage}\n />\n )}\n </EntityInfoCard>\n );\n};\n"],"names":[],"mappings":";;;;;;;;;;;AAiBO,MAAM,uBAAuB,MAAM;AACxC,EAAA,MAAM,EAAE,MAAA,EAAO,GAAI,SAAA,EAAU;AAC7B,EAAA,MAAM,CAAC,IAAA,EAAM,mBAAmB,CAAA,GAC9B,MAAA,CAAO,SAAS,WAAA,GAAc,qBAAqB,CAAA,EAAG,KAAA,CAAM,GAAG,CAAA;AACjE,EAAA,MAAM,gBAAA,GAAmB,qBAAqB,KAAA,CAAM,GAAG,EAAE,GAAA,CAAI,CAAA,EAAA,KAAM,EAAA,CAAG,IAAA,EAAM,CAAA;AAE5E,EAAA,MAAM,EAAE,OAAA,EAAS,KAAA,EAAO,KAAA,EAAM,GAAI,cAAc,IAAI,CAAA;AAEpD,EAAA,IAAI,OAAA,EAAS;AACX,IAAA,2BAAQ,QAAA,EAAA,EAAS,CAAA;AAAA,EACnB;AACA,EAAA,IAAI,KAAA,EAAO;AACT,IAAA,uBAAO,GAAA,CAAC,sBAAmB,KAAA,EAAc,CAAA;AAAA,EAC3C;AAEA,EAAA,IAAI,OAAA,EAAS;AACX,IAAA,2BAAQ,QAAA,EAAA,EAAS,CAAA;AAAA,EACnB;AACA,EAAA,IAAI,KAAA,EAAO;AACT,IAAA,uBAAO,GAAA,CAAC,sBAAmB,KAAA,EAAc,CAAA;AAAA,EAC3C;AAEA,EAAA,MAAM,UAAA,GAAa,OAAO,GAAA,oBACxB,GAAA;AAAA,IAAC,UAAA;AAAA,IAAA;AAAA,MACC,YAAA,EAAW,sBAAA;AAAA,MACX,IAAA,EAAK,QAAA;AAAA,MACL,KAAA,EAAM,uBAAA;AAAA,MACN,MAAM,KAAA,EAAO,GAAA;AAAA,MACb,MAAA,EAAO,QAAA;AAAA,MAEP,8BAAC,aAAA,EAAA,EAAc;AAAA;AAAA,GACjB;AAGF,EAAA,MAAM,iBAAiB,CAAC,gBAAA;AACxB,EAAA,MAAM,kBAAA,GACJ,OAAO,UAAA,CAAW,MAAA;AAAA,IAChB,CAAA,CAAA,KAAK,CAAC,cAAA,IAAkB,CAAC,EAAE,KAAA,IAAS,gBAAA,CAAiB,QAAA,CAAS,CAAA,CAAE,EAAE;AAAA,OAC/D,EAAC;AACR,EAAA,MAAM,uBAAA,GACJ,OAAO,eAAA,CAAgB,MAAA;AAAA,IACrB,CAAA,CAAA,KAAK,cAAA,IAAkB,gBAAA,CAAiB,QAAA,CAAS,EAAE,EAAE;AAAA,OAClD,EAAC;AACR,EAAA,MAAM,YAAA,GAAA,CACH,CAAC,kBAAA,IAAsB,uBAAA,CAAwB,WAAW,CAAA,KAC3D,kBAAA,IACA,mBAAmB,MAAA,KAAW,CAAA;AAEhC,EAAA,IAAI,YAAA,EAAc;AAChB,IAAA,uBACE,GAAA,CAAC,cAAA,EAAA,EAAe,KAAA,EAAM,gBAAA,EAAiB,aAAA,EAAe,UAAA,EACpD,QAAA,kBAAA,GAAA,CAAC,UAAA,EAAA,EAAW,OAAA,EAAQ,OAAA,EAAQ,KAAA,EAAM,SAAA,EAAU,+FAG5C,CAAA,EACF,CAAA;AAAA,EAEJ;AACA,EAAA,uBACE,IAAA,CAAC,cAAA,EAAA,EAAe,KAAA,EAAM,gBAAA,EAAiB,eAAe,UAAA,EACnD,QAAA,EAAA;AAAA,IAAA,kBAAA,IAAsB,mBAAmB,MAAA,GAAS,CAAA,oBACjD,GAAA,CAAC,eAAA,EAAA,EAAgB,YAAY,kBAAA,EAAoB,CAAA;AAAA,IAElD,uBAAA,IAA2B,uBAAA,CAAwB,MAAA,GAAS,CAAA,oBAC3D,GAAA;AAAA,MAAC,mBAAA;AAAA,MAAA;AAAA,QACC,UAAA,EAAY,KAAA,EAAO,UAAA,IAAc,EAAC;AAAA,QAClC,eAAA,EAAiB,uBAAA;AAAA,QACjB,UAAU,CAAC;AAAA;AAAA;AACb,GAAA,EAEJ,CAAA;AAEJ;;;;"}
package/package.json CHANGED
@@ -1,8 +1,32 @@
1
1
  {
2
2
  "name": "@axis-backstage/plugin-statuspage",
3
- "version": "0.10.2",
3
+ "version": "0.11.0",
4
+ "exports": {
5
+ ".": {
6
+ "import": "./dist/index.esm.js",
7
+ "types": "./dist/index.d.ts",
8
+ "default": "./dist/index.esm.js"
9
+ },
10
+ "./alpha": {
11
+ "backstage": "@backstage/FrontendPlugin",
12
+ "import": "./dist/alpha.esm.js",
13
+ "types": "./dist/alpha.d.ts",
14
+ "default": "./dist/alpha.esm.js"
15
+ },
16
+ "./package.json": "./package.json"
17
+ },
4
18
  "main": "dist/index.esm.js",
5
19
  "types": "dist/index.d.ts",
20
+ "typesVersions": {
21
+ "*": {
22
+ "alpha": [
23
+ "dist/alpha.d.ts"
24
+ ],
25
+ "package.json": [
26
+ "package.json"
27
+ ]
28
+ }
29
+ },
6
30
  "license": "Apache-2.0",
7
31
  "publishConfig": {
8
32
  "access": "public",
@@ -17,7 +41,10 @@
17
41
  "@axis-backstage/plugin-statuspage",
18
42
  "@axis-backstage/plugin-statuspage-backend",
19
43
  "@axis-backstage/plugin-statuspage-common"
20
- ]
44
+ ],
45
+ "features": {
46
+ "./alpha": "@backstage/FrontendPlugin"
47
+ }
21
48
  },
22
49
  "sideEffects": false,
23
50
  "scripts": {
@@ -34,10 +61,12 @@
34
61
  "@backstage/catalog-model": "^1.8.0",
35
62
  "@backstage/core-components": "^0.18.9",
36
63
  "@backstage/core-plugin-api": "^1.12.5",
64
+ "@backstage/frontend-plugin-api": "^0.16.2",
37
65
  "@backstage/plugin-catalog-react": "^2.1.4",
38
66
  "@mui/icons-material": "^5.15.7",
39
67
  "@mui/material": "^5.15.7",
40
- "react-use": "^17.2.4"
68
+ "react-use": "^17.2.4",
69
+ "zod": "^4.3.6"
41
70
  },
42
71
  "peerDependencies": {
43
72
  "@types/react": "^17.0.0 || ^18.0.0",
@@ -53,13 +82,6 @@
53
82
  "files": [
54
83
  "dist"
55
84
  ],
56
- "typesVersions": {
57
- "*": {
58
- "package.json": [
59
- "package.json"
60
- ]
61
- }
62
- },
63
85
  "module": "./dist/index.esm.js",
64
86
  "directory": "_release/package"
65
87
  }