@backstage/plugin-home 0.9.9-next.1 → 0.9.9

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 (28) hide show
  1. package/CHANGELOG.md +25 -0
  2. package/README.md +3 -642
  3. package/dist/alpha/DefaultHomePageLayout.esm.js +16 -3
  4. package/dist/alpha/DefaultHomePageLayout.esm.js.map +1 -1
  5. package/dist/alpha.d.ts +79 -2
  6. package/dist/alpha.esm.js +112 -21
  7. package/dist/alpha.esm.js.map +1 -1
  8. package/dist/components/CustomHomepage/CustomHomepageGrid.esm.js +32 -11
  9. package/dist/components/CustomHomepage/CustomHomepageGrid.esm.js.map +1 -1
  10. package/dist/homePageComponents/HeaderWorldClock/HeaderWorldClock.esm.js +1 -37
  11. package/dist/homePageComponents/HeaderWorldClock/HeaderWorldClock.esm.js.map +1 -1
  12. package/dist/homePageComponents/Toolkit/Content.esm.js +4 -1
  13. package/dist/homePageComponents/Toolkit/Content.esm.js.map +1 -1
  14. package/dist/homePageComponents/VisitedByType/Content.esm.js +20 -6
  15. package/dist/homePageComponents/VisitedByType/Content.esm.js.map +1 -1
  16. package/dist/homePageComponents/VisitedByType/RecentlyVisited.esm.js +3 -3
  17. package/dist/homePageComponents/VisitedByType/TopVisited.esm.js +3 -3
  18. package/dist/homePageComponents/WorldClock/WorldClock.esm.js +55 -0
  19. package/dist/homePageComponents/WorldClock/WorldClock.esm.js.map +1 -0
  20. package/dist/homePageComponents/WorldClock/clocks.esm.js +40 -0
  21. package/dist/homePageComponents/WorldClock/clocks.esm.js.map +1 -0
  22. package/dist/homePageComponents/WorldClock/index.esm.js +6 -0
  23. package/dist/homePageComponents/WorldClock/index.esm.js.map +1 -0
  24. package/dist/index.d.ts +2 -0
  25. package/dist/package.json.esm.js +1 -1
  26. package/dist/translation.esm.js +4 -0
  27. package/dist/translation.esm.js.map +1 -1
  28. package/package.json +17 -17
@@ -1,5 +1,5 @@
1
1
  import { jsx } from 'react/jsx-runtime';
2
- import { Fragment } from 'react';
2
+ import { useMemo, Fragment } from 'react';
3
3
  import { Content } from '@backstage/core-components';
4
4
  import 'react-router-dom';
5
5
  import { CustomHomepageGrid } from '../components/CustomHomepage/CustomHomepageGrid.esm.js';
@@ -10,8 +10,21 @@ import '@backstage/catalog-model';
10
10
  import '../components/VisitList/Context.esm.js';
11
11
 
12
12
  function DefaultHomePageLayout(props) {
13
- const { widgets } = props;
14
- return /* @__PURE__ */ jsx(Content, { children: /* @__PURE__ */ jsx(CustomHomepageGrid, { children: widgets.map((widget, index) => /* @__PURE__ */ jsx(Fragment, { children: widget.component }, widget.name ?? index)) }) });
13
+ const { widgets, defaultConfig } = props;
14
+ const gridConfig = useMemo(
15
+ () => defaultConfig?.map((item) => ({
16
+ component: item.component,
17
+ x: item.column,
18
+ y: item.row,
19
+ width: item.width,
20
+ height: item.height,
21
+ movable: item.movable,
22
+ deletable: item.deletable,
23
+ resizable: item.resizable
24
+ })),
25
+ [defaultConfig]
26
+ );
27
+ return /* @__PURE__ */ jsx(Content, { children: /* @__PURE__ */ jsx(CustomHomepageGrid, { config: gridConfig, children: widgets.map((widget, index) => /* @__PURE__ */ jsx(Fragment, { children: widget.component }, widget.name ?? index)) }) });
15
28
  }
16
29
 
17
30
  export { DefaultHomePageLayout };
@@ -1 +1 @@
1
- {"version":3,"file":"DefaultHomePageLayout.esm.js","sources":["../../src/alpha/DefaultHomePageLayout.tsx"],"sourcesContent":["/*\n * Copyright 2025 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 { Fragment } from 'react';\nimport { Content } from '@backstage/core-components';\nimport type { HomePageLayoutProps } from '@backstage/plugin-home-react/alpha';\nimport { CustomHomepageGrid } from '../components';\n\n/**\n * The default home page layout component.\n *\n * Renders widgets inside a `<CustomHomepageGrid/>` wrapped in `<Content/>`.\n * This is used when no custom layout extension is installed.\n */\nexport function DefaultHomePageLayout(props: HomePageLayoutProps) {\n const { widgets } = props;\n return (\n <Content>\n <CustomHomepageGrid>\n {widgets.map((widget, index) => (\n <Fragment key={widget.name ?? index}>{widget.component}</Fragment>\n ))}\n </CustomHomepageGrid>\n </Content>\n );\n}\n"],"names":[],"mappings":";;;;;;;;;;;AA2BO,SAAS,sBAAsB,KAAA,EAA4B;AAChE,EAAA,MAAM,EAAE,SAAQ,GAAI,KAAA;AACpB,EAAA,2BACG,OAAA,EAAA,EACC,QAAA,kBAAA,GAAA,CAAC,sBACE,QAAA,EAAA,OAAA,CAAQ,GAAA,CAAI,CAAC,MAAA,EAAQ,KAAA,qBACpB,GAAA,CAAC,QAAA,EAAA,EAAqC,iBAAO,SAAA,EAAA,EAA9B,MAAA,CAAO,QAAQ,KAAyB,CACxD,GACH,CAAA,EACF,CAAA;AAEJ;;;;"}
1
+ {"version":3,"file":"DefaultHomePageLayout.esm.js","sources":["../../src/alpha/DefaultHomePageLayout.tsx"],"sourcesContent":["/*\n * Copyright 2025 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 { Fragment, useMemo } from 'react';\nimport { Content } from '@backstage/core-components';\nimport type { HomePageLayoutProps } from '@backstage/plugin-home-react/alpha';\nimport { CustomHomepageGrid } from '../components';\n\n/**\n * The default home page layout component.\n *\n * Renders widgets inside a `<CustomHomepageGrid/>` wrapped in `<Content/>`.\n * This is used when no custom layout extension is installed.\n */\nexport function DefaultHomePageLayout(props: HomePageLayoutProps) {\n const { widgets, defaultConfig } = props;\n const gridConfig = useMemo(\n () =>\n defaultConfig?.map(item => ({\n component: item.component,\n x: item.column,\n y: item.row,\n width: item.width,\n height: item.height,\n movable: item.movable,\n deletable: item.deletable,\n resizable: item.resizable,\n })),\n [defaultConfig],\n );\n return (\n <Content>\n <CustomHomepageGrid config={gridConfig}>\n {widgets.map((widget, index) => (\n <Fragment key={widget.name ?? index}>{widget.component}</Fragment>\n ))}\n </CustomHomepageGrid>\n </Content>\n );\n}\n"],"names":[],"mappings":";;;;;;;;;;;AA2BO,SAAS,sBAAsB,KAAA,EAA4B;AAChE,EAAA,MAAM,EAAE,OAAA,EAAS,aAAA,EAAc,GAAI,KAAA;AACnC,EAAA,MAAM,UAAA,GAAa,OAAA;AAAA,IACjB,MACE,aAAA,EAAe,GAAA,CAAI,CAAA,IAAA,MAAS;AAAA,MAC1B,WAAW,IAAA,CAAK,SAAA;AAAA,MAChB,GAAG,IAAA,CAAK,MAAA;AAAA,MACR,GAAG,IAAA,CAAK,GAAA;AAAA,MACR,OAAO,IAAA,CAAK,KAAA;AAAA,MACZ,QAAQ,IAAA,CAAK,MAAA;AAAA,MACb,SAAS,IAAA,CAAK,OAAA;AAAA,MACd,WAAW,IAAA,CAAK,SAAA;AAAA,MAChB,WAAW,IAAA,CAAK;AAAA,KAClB,CAAE,CAAA;AAAA,IACJ,CAAC,aAAa;AAAA,GAChB;AACA,EAAA,uBACE,GAAA,CAAC,WACC,QAAA,kBAAA,GAAA,CAAC,kBAAA,EAAA,EAAmB,QAAQ,UAAA,EACzB,QAAA,EAAA,OAAA,CAAQ,IAAI,CAAC,MAAA,EAAQ,0BACpB,GAAA,CAAC,QAAA,EAAA,EAAqC,iBAAO,SAAA,EAAA,EAA9B,MAAA,CAAO,QAAQ,KAAyB,CACxD,GACH,CAAA,EACF,CAAA;AAEJ;;;;"}
package/dist/alpha.d.ts CHANGED
@@ -34,6 +34,15 @@ declare const _default: _backstage_frontend_plugin_api.OverridableFrontendPlugin
34
34
  element: JSX.Element;
35
35
  };
36
36
  }>;
37
+ "home-page-widget:home/most-visited": _backstage_frontend_plugin_api.OverridableExtensionDefinition<{
38
+ kind: "home-page-widget";
39
+ name: "most-visited";
40
+ config: {};
41
+ configInput: {};
42
+ output: _backstage_frontend_plugin_api.ExtensionDataRef<_backstage_plugin_home_react_alpha.HomePageWidgetData, "home.widget.data", {}>;
43
+ inputs: {};
44
+ params: _backstage_plugin_home_react_alpha.HomePageWidgetBlueprintParams;
45
+ }>;
37
46
  "home-page-widget:home/random-joke": _backstage_frontend_plugin_api.OverridableExtensionDefinition<{
38
47
  kind: "home-page-widget";
39
48
  name: "random-joke";
@@ -43,6 +52,15 @@ declare const _default: _backstage_frontend_plugin_api.OverridableFrontendPlugin
43
52
  inputs: {};
44
53
  params: _backstage_plugin_home_react_alpha.HomePageWidgetBlueprintParams;
45
54
  }>;
55
+ "home-page-widget:home/recently-visited": _backstage_frontend_plugin_api.OverridableExtensionDefinition<{
56
+ kind: "home-page-widget";
57
+ name: "recently-visited";
58
+ config: {};
59
+ configInput: {};
60
+ output: _backstage_frontend_plugin_api.ExtensionDataRef<_backstage_plugin_home_react_alpha.HomePageWidgetData, "home.widget.data", {}>;
61
+ inputs: {};
62
+ params: _backstage_plugin_home_react_alpha.HomePageWidgetBlueprintParams;
63
+ }>;
46
64
  "home-page-widget:home/starred-entities": _backstage_frontend_plugin_api.OverridableExtensionDefinition<{
47
65
  kind: "home-page-widget";
48
66
  name: "starred-entities";
@@ -53,20 +71,77 @@ declare const _default: _backstage_frontend_plugin_api.OverridableFrontendPlugin
53
71
  params: _backstage_plugin_home_react_alpha.HomePageWidgetBlueprintParams;
54
72
  }>;
55
73
  "home-page-widget:home/toolkit": _backstage_frontend_plugin_api.OverridableExtensionDefinition<{
74
+ config: {
75
+ tools: {
76
+ url: string;
77
+ label: string;
78
+ icon?: string | undefined;
79
+ }[];
80
+ };
81
+ configInput: {
82
+ tools?: {
83
+ url: string;
84
+ label: string;
85
+ icon?: string | undefined;
86
+ }[] | undefined;
87
+ };
88
+ output: _backstage_frontend_plugin_api.ExtensionDataRef<_backstage_plugin_home_react_alpha.HomePageWidgetData, "home.widget.data", {}>;
89
+ inputs: {};
56
90
  kind: "home-page-widget";
57
91
  name: "toolkit";
58
- config: {};
59
- configInput: {};
92
+ params: _backstage_plugin_home_react_alpha.HomePageWidgetBlueprintParams;
93
+ }>;
94
+ "home-page-widget:home/world-clock": _backstage_frontend_plugin_api.OverridableExtensionDefinition<{
95
+ config: {
96
+ clockConfigs: {
97
+ label: string;
98
+ timeZone: string;
99
+ }[] | undefined;
100
+ customTimeFormat: {
101
+ hour12?: boolean | undefined;
102
+ } | undefined;
103
+ };
104
+ configInput: {
105
+ clockConfigs?: {
106
+ label: string;
107
+ timeZone: string;
108
+ }[] | undefined;
109
+ customTimeFormat?: {
110
+ hour12?: boolean | undefined;
111
+ } | undefined;
112
+ };
60
113
  output: _backstage_frontend_plugin_api.ExtensionDataRef<_backstage_plugin_home_react_alpha.HomePageWidgetData, "home.widget.data", {}>;
61
114
  inputs: {};
115
+ kind: "home-page-widget";
116
+ name: "world-clock";
62
117
  params: _backstage_plugin_home_react_alpha.HomePageWidgetBlueprintParams;
63
118
  }>;
64
119
  "page:home": _backstage_frontend_plugin_api.OverridableExtensionDefinition<{
65
120
  config: {
121
+ defaultConfig: {
122
+ component: string;
123
+ column: number;
124
+ row: number;
125
+ width: number;
126
+ height: number;
127
+ movable?: boolean | undefined;
128
+ deletable?: boolean | undefined;
129
+ resizable?: boolean | undefined;
130
+ }[] | undefined;
66
131
  path: string | undefined;
67
132
  title: string | undefined;
68
133
  };
69
134
  configInput: {
135
+ defaultConfig?: {
136
+ component: string;
137
+ column: number;
138
+ row: number;
139
+ width: number;
140
+ height: number;
141
+ movable?: boolean | undefined;
142
+ deletable?: boolean | undefined;
143
+ resizable?: boolean | undefined;
144
+ }[] | undefined;
70
145
  path?: string | undefined;
71
146
  title?: string | undefined;
72
147
  };
@@ -134,6 +209,8 @@ declare const homeTranslationRef: _backstage_frontend_plugin_api.TranslationRef<
134
209
  readonly "widgetSettingsOverlay.deleteWidgetTooltip": "Delete widget";
135
210
  readonly "widgetSettingsOverlay.submitButtonTitle": "Submit";
136
211
  readonly "starredEntityListItem.removeFavoriteEntityTitle": "Remove entity from favorites";
212
+ readonly "visitList.disabled.title": "Visit tracking is not enabled.";
213
+ readonly "visitList.disabled.description": "Enable visit tracking in your app-config.yaml to see your most visited and recently visited pages here.";
137
214
  readonly "visitList.empty.title": "There are no visits to show yet.";
138
215
  readonly "visitList.empty.description": "Once you start using Backstage, your visits will appear here as a quick link to carry on where you left off.";
139
216
  readonly "visitList.few.title": "The more pages you visit, the more pages will appear here.";
package/dist/alpha.esm.js CHANGED
@@ -1,6 +1,8 @@
1
1
  import { jsx } from 'react/jsx-runtime';
2
2
  import { lazy } from 'react';
3
- import { createRouteRef, PageBlueprint, createExtensionInput, AppRootElementBlueprint, ApiBlueprint, errorApiRef, identityApiRef, storageApiRef, createFrontendPlugin, ExtensionBoundary } from '@backstage/frontend-plugin-api';
3
+ import { z } from 'zod/v4';
4
+ import { createRouteRef, PageBlueprint, createExtensionInput, AppRootElementBlueprint, ApiBlueprint, errorApiRef, identityApiRef, storageApiRef, iconsApiRef, createFrontendPlugin, ExtensionBoundary } from '@backstage/frontend-plugin-api';
5
+ import { useApi } from '@backstage/core-plugin-api';
4
6
  import 'react-router-dom';
5
7
  import './components/CustomHomepage/CustomHomepageGrid.esm.js';
6
8
  import { VisitListener } from './components/VisitListener.esm.js';
@@ -9,10 +11,21 @@ import { VisitsStorageApi } from './api/VisitsStorageApi.esm.js';
9
11
  import { VisitsWebStorageApi } from './api/VisitsWebStorageApi.esm.js';
10
12
  import { visitsApiRef } from './api/VisitsApi.esm.js';
11
13
  import HomeIcon from '@material-ui/icons/Home';
14
+ import LinkIcon from '@material-ui/icons/Link';
12
15
  import { homePageLayoutComponentDataRef, homePageWidgetDataRef, HomePageLayoutBlueprint, HomePageWidgetBlueprint } from '@backstage/plugin-home-react/alpha';
13
16
  import { homeTranslationRef as homeTranslationRef$1 } from './translation.esm.js';
14
17
 
15
18
  const rootRouteRef = createRouteRef();
19
+ const defaultConfigItemSchema = z.object({
20
+ component: z.string(),
21
+ column: z.number(),
22
+ row: z.number(),
23
+ width: z.number(),
24
+ height: z.number(),
25
+ movable: z.boolean().optional(),
26
+ deletable: z.boolean().optional(),
27
+ resizable: z.boolean().optional()
28
+ });
16
29
  const homePage = PageBlueprint.makeWithOverrides({
17
30
  inputs: {
18
31
  widgets: createExtensionInput([homePageWidgetDataRef]),
@@ -22,7 +35,10 @@ const homePage = PageBlueprint.makeWithOverrides({
22
35
  internal: true
23
36
  })
24
37
  },
25
- factory(originalFactory, { node, inputs }) {
38
+ configSchema: {
39
+ defaultConfig: z.array(defaultConfigItemSchema).optional()
40
+ },
41
+ factory(originalFactory, { node, inputs, config }) {
26
42
  return originalFactory({
27
43
  path: "/home",
28
44
  noHeader: true,
@@ -41,7 +57,7 @@ const homePage = PageBlueprint.makeWithOverrides({
41
57
  ...widget.get(homePageWidgetDataRef),
42
58
  node: widget.node
43
59
  }));
44
- return /* @__PURE__ */ jsx(Layout, { widgets });
60
+ return /* @__PURE__ */ jsx(Layout, { widgets, defaultConfig: config.defaultConfig });
45
61
  }
46
62
  });
47
63
  }
@@ -71,24 +87,35 @@ const visitsApi = ApiBlueprint.make({
71
87
  }
72
88
  })
73
89
  });
74
- const homePageToolkitWidget = HomePageWidgetBlueprint.make({
90
+ const homePageToolkitWidget = HomePageWidgetBlueprint.makeWithOverrides({
75
91
  name: "toolkit",
76
- params: {
77
- name: "HomePageToolkit",
78
- title: "Toolkit",
79
- components: () => import('./homePageComponents/Toolkit/index.esm.js').then((m) => ({
80
- Content: m.Content,
81
- ContextProvider: m.ContextProvider
82
- })),
83
- componentProps: {
84
- tools: [
85
- {
86
- url: "https://backstage.io",
87
- label: "Backstage Docs",
88
- icon: /* @__PURE__ */ jsx(HomeIcon, {})
89
- }
90
- ]
91
- }
92
+ configSchema: {
93
+ tools: z.array(
94
+ z.object({
95
+ url: z.string(),
96
+ label: z.string(),
97
+ icon: z.string().optional()
98
+ })
99
+ ).default([{ url: "https://backstage.io", label: "Backstage Docs" }])
100
+ },
101
+ *factory(originalFactory, { config }) {
102
+ yield* originalFactory({
103
+ name: "HomePageToolkit",
104
+ title: "Toolkit",
105
+ description: "A collection of useful links and tools",
106
+ components: () => import('./homePageComponents/Toolkit/index.esm.js').then((m) => ({
107
+ Content: (props) => {
108
+ const iconsApi = useApi(iconsApiRef);
109
+ const tools = config.tools.map((tool) => ({
110
+ url: tool.url,
111
+ label: tool.label,
112
+ icon: (tool.icon && iconsApi.icon(tool.icon)) ?? /* @__PURE__ */ jsx(LinkIcon, {})
113
+ }));
114
+ return /* @__PURE__ */ jsx(m.Content, { ...props, tools });
115
+ },
116
+ ContextProvider: m.ContextProvider
117
+ }))
118
+ });
92
119
  }
93
120
  });
94
121
  const homePageStarredEntitiesWidget = HomePageWidgetBlueprint.make({
@@ -96,6 +123,7 @@ const homePageStarredEntitiesWidget = HomePageWidgetBlueprint.make({
96
123
  params: {
97
124
  name: "HomePageStarredEntities",
98
125
  title: "Your Starred Entities",
126
+ description: "Shows entities you have starred in the catalog",
99
127
  components: () => import('./homePageComponents/StarredEntities/index.esm.js').then((m) => ({
100
128
  Content: m.Content
101
129
  }))
@@ -133,6 +161,66 @@ const homePageRandomJokeWidget = HomePageWidgetBlueprint.make({
133
161
  }
134
162
  }
135
163
  });
164
+ const homePageMostVisitedWidget = HomePageWidgetBlueprint.make({
165
+ name: "most-visited",
166
+ params: {
167
+ name: "HomePageMostVisited",
168
+ title: "Most Visited",
169
+ description: "Shows your most frequently visited pages",
170
+ components: () => import('./homePageComponents/VisitedByType/TopVisited.esm.js').then((m) => ({
171
+ Content: m.Content,
172
+ Actions: m.Actions,
173
+ ContextProvider: m.ContextProvider
174
+ }))
175
+ }
176
+ });
177
+ const homePageRecentlyVisitedWidget = HomePageWidgetBlueprint.make({
178
+ name: "recently-visited",
179
+ params: {
180
+ name: "HomePageRecentlyVisited",
181
+ title: "Recently Visited",
182
+ description: "Shows pages you have recently visited",
183
+ components: () => import('./homePageComponents/VisitedByType/RecentlyVisited.esm.js').then((m) => ({
184
+ Content: m.Content,
185
+ Actions: m.Actions,
186
+ ContextProvider: m.ContextProvider
187
+ }))
188
+ }
189
+ });
190
+ const homePageWorldClockWidget = HomePageWidgetBlueprint.makeWithOverrides({
191
+ name: "world-clock",
192
+ configSchema: {
193
+ clockConfigs: z.array(
194
+ z.object({
195
+ label: z.string(),
196
+ timeZone: z.string()
197
+ })
198
+ ).optional(),
199
+ customTimeFormat: z.object({
200
+ hour12: z.boolean().optional()
201
+ }).optional()
202
+ },
203
+ *factory(originalFactory, { config }) {
204
+ yield* originalFactory({
205
+ name: "HomePageWorldClock",
206
+ title: "World Clocks",
207
+ description: "Displays clocks for configured time zones",
208
+ components: () => import('./homePageComponents/WorldClock/index.esm.js').then((m) => ({
209
+ Content: () => /* @__PURE__ */ jsx(
210
+ m.WorldClock,
211
+ {
212
+ clockConfigs: config.clockConfigs,
213
+ customTimeFormat: config.customTimeFormat ? {
214
+ hour: "2-digit",
215
+ minute: "2-digit",
216
+ ...config.customTimeFormat
217
+ } : void 0
218
+ }
219
+ )
220
+ }))
221
+ });
222
+ }
223
+ });
136
224
  var alpha = createFrontendPlugin({
137
225
  pluginId: "home",
138
226
  title: "Home",
@@ -144,7 +232,10 @@ var alpha = createFrontendPlugin({
144
232
  visitListenerAppRootElement,
145
233
  homePageToolkitWidget,
146
234
  homePageStarredEntitiesWidget,
147
- homePageRandomJokeWidget
235
+ homePageRandomJokeWidget,
236
+ homePageMostVisitedWidget,
237
+ homePageRecentlyVisitedWidget,
238
+ homePageWorldClockWidget
148
239
  ],
149
240
  routes: {
150
241
  root: rootRouteRef
@@ -1 +1 @@
1
- {"version":3,"file":"alpha.esm.js","sources":["../src/alpha.tsx"],"sourcesContent":["/*\n * Copyright 2023 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * The home plugin for Backstage's new frontend system.\n *\n * @remarks\n * This package provides the new frontend system implementation of the home plugin,\n * which offers customizable home pages with widget support and optional visit tracking.\n *\n * @packageDocumentation\n */\n\nimport { lazy as reactLazy } from 'react';\nimport {\n createExtensionInput,\n PageBlueprint,\n createFrontendPlugin,\n createRouteRef,\n AppRootElementBlueprint,\n identityApiRef,\n storageApiRef,\n errorApiRef,\n ApiBlueprint,\n ExtensionBoundary,\n} from '@backstage/frontend-plugin-api';\nimport { VisitListener } from './components/';\nimport { visitsApiRef, VisitsStorageApi, VisitsWebStorageApi } from './api';\nimport HomeIcon from '@material-ui/icons/Home';\nimport {\n homePageWidgetDataRef,\n homePageLayoutComponentDataRef,\n HomePageLayoutBlueprint,\n HomePageWidgetBlueprint,\n type HomePageLayoutProps,\n} from '@backstage/plugin-home-react/alpha';\n\nconst rootRouteRef = createRouteRef();\n\nconst homePage = PageBlueprint.makeWithOverrides({\n inputs: {\n widgets: createExtensionInput([homePageWidgetDataRef]),\n layout: createExtensionInput([HomePageLayoutBlueprint.dataRefs.component], {\n singleton: true,\n optional: true,\n internal: true,\n }),\n },\n factory(originalFactory, { node, inputs }) {\n return originalFactory({\n path: '/home',\n noHeader: true,\n routeRef: rootRouteRef,\n title: 'Home',\n icon: <HomeIcon fontSize=\"inherit\" />,\n loader: async () => {\n const LazyDefaultLayout = reactLazy(() =>\n import('./alpha/DefaultHomePageLayout').then(m => ({\n default: m.DefaultHomePageLayout,\n })),\n );\n\n const DefaultLayoutComponent = (props: HomePageLayoutProps) => (\n <ExtensionBoundary node={node}>\n <LazyDefaultLayout {...props} />\n </ExtensionBoundary>\n );\n\n const Layout =\n inputs.layout?.get(homePageLayoutComponentDataRef) ??\n DefaultLayoutComponent;\n\n const widgets = inputs.widgets.map(widget => ({\n ...widget.get(homePageWidgetDataRef),\n node: widget.node,\n }));\n\n return <Layout widgets={widgets} />;\n },\n });\n },\n});\n\nconst visitListenerAppRootElement = AppRootElementBlueprint.make({\n name: 'visit-listener',\n disabled: true,\n params: {\n element: <VisitListener />,\n },\n});\n\nconst visitsApi = ApiBlueprint.make({\n name: 'visits',\n disabled: true,\n params: defineParams =>\n defineParams({\n api: visitsApiRef,\n deps: {\n storageApi: storageApiRef,\n identityApi: identityApiRef,\n errorApi: errorApiRef,\n },\n factory: ({ storageApi, identityApi, errorApi }) => {\n // Smart fallback: use custom storage API if available, otherwise localStorage\n if (storageApi) {\n return VisitsStorageApi.create({ storageApi, identityApi });\n }\n return VisitsWebStorageApi.create({ identityApi, errorApi });\n },\n }),\n});\n\nconst homePageToolkitWidget = HomePageWidgetBlueprint.make({\n name: 'toolkit',\n params: {\n name: 'HomePageToolkit',\n title: 'Toolkit',\n components: () =>\n import('./homePageComponents/Toolkit').then(m => ({\n Content: m.Content,\n ContextProvider: m.ContextProvider,\n })),\n componentProps: {\n tools: [\n {\n url: 'https://backstage.io',\n label: 'Backstage Docs',\n icon: <HomeIcon />,\n },\n ],\n },\n },\n});\n\nconst homePageStarredEntitiesWidget = HomePageWidgetBlueprint.make({\n name: 'starred-entities',\n params: {\n name: 'HomePageStarredEntities',\n title: 'Your Starred Entities',\n components: () =>\n import('./homePageComponents/StarredEntities').then(m => ({\n Content: m.Content,\n })),\n },\n});\n\nconst homePageRandomJokeWidget = HomePageWidgetBlueprint.make({\n name: 'random-joke',\n params: {\n name: 'HomePageRandomJoke',\n title: 'Random Joke',\n description: 'Shows a random programming joke',\n components: () =>\n import('./homePageComponents/RandomJoke').then(m => ({\n Content: m.Content,\n Settings: m.Settings,\n Actions: m.Actions,\n ContextProvider: m.ContextProvider,\n })),\n layout: {\n height: { minRows: 4 },\n width: { minColumns: 3 },\n },\n settings: {\n schema: {\n title: 'Random Joke settings',\n type: 'object',\n properties: {\n defaultCategory: {\n title: 'Category',\n type: 'string',\n enum: ['any', 'programming', 'dad'],\n default: 'any',\n },\n },\n },\n },\n },\n});\n\n/**\n * Home plugin for the new frontend system.\n *\n * Provides core homepage functionality with optional visit tracking extensions.\n * Visit tracking extensions are disabled by default and can be enabled via app-config.yaml.\n *\n * @alpha\n */\nexport default createFrontendPlugin({\n pluginId: 'home',\n title: 'Home',\n icon: <HomeIcon />,\n info: { packageJson: () => import('../package.json') },\n extensions: [\n homePage,\n visitsApi,\n visitListenerAppRootElement,\n homePageToolkitWidget,\n homePageStarredEntitiesWidget,\n homePageRandomJokeWidget,\n ],\n routes: {\n root: rootRouteRef,\n },\n});\n\nimport { homeTranslationRef as _homeTranslationRef } from './translation';\n\n/**\n * @alpha\n * @deprecated Import from `@backstage/plugin-home` instead.\n */\nexport const homeTranslationRef = _homeTranslationRef;\n"],"names":["reactLazy","_homeTranslationRef"],"mappings":"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"}
1
+ {"version":3,"file":"alpha.esm.js","sources":["../src/alpha.tsx"],"sourcesContent":["/*\n * Copyright 2023 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * The home plugin for Backstage's new frontend system.\n *\n * @remarks\n * This package provides the new frontend system implementation of the home plugin,\n * which offers customizable home pages with widget support and optional visit tracking.\n *\n * @packageDocumentation\n */\n\nimport { lazy as reactLazy } from 'react';\nimport { z } from 'zod/v4';\nimport {\n createExtensionInput,\n PageBlueprint,\n createFrontendPlugin,\n createRouteRef,\n AppRootElementBlueprint,\n identityApiRef,\n storageApiRef,\n errorApiRef,\n ApiBlueprint,\n ExtensionBoundary,\n iconsApiRef,\n} from '@backstage/frontend-plugin-api';\nimport { useApi } from '@backstage/core-plugin-api';\nimport { VisitListener } from './components/';\nimport { visitsApiRef, VisitsStorageApi, VisitsWebStorageApi } from './api';\nimport HomeIcon from '@material-ui/icons/Home';\nimport LinkIcon from '@material-ui/icons/Link';\nimport {\n homePageWidgetDataRef,\n homePageLayoutComponentDataRef,\n HomePageLayoutBlueprint,\n HomePageWidgetBlueprint,\n type HomePageLayoutProps,\n} from '@backstage/plugin-home-react/alpha';\n\nconst rootRouteRef = createRouteRef();\n\nconst defaultConfigItemSchema = z.object({\n component: z.string(),\n column: z.number(),\n row: z.number(),\n width: z.number(),\n height: z.number(),\n movable: z.boolean().optional(),\n deletable: z.boolean().optional(),\n resizable: z.boolean().optional(),\n});\n\nconst homePage = PageBlueprint.makeWithOverrides({\n inputs: {\n widgets: createExtensionInput([homePageWidgetDataRef]),\n layout: createExtensionInput([HomePageLayoutBlueprint.dataRefs.component], {\n singleton: true,\n optional: true,\n internal: true,\n }),\n },\n configSchema: {\n defaultConfig: z.array(defaultConfigItemSchema).optional(),\n },\n factory(originalFactory, { node, inputs, config }) {\n return originalFactory({\n path: '/home',\n noHeader: true,\n routeRef: rootRouteRef,\n title: 'Home',\n icon: <HomeIcon fontSize=\"inherit\" />,\n loader: async () => {\n const LazyDefaultLayout = reactLazy(() =>\n import('./alpha/DefaultHomePageLayout').then(m => ({\n default: m.DefaultHomePageLayout,\n })),\n );\n\n const DefaultLayoutComponent = (props: HomePageLayoutProps) => (\n <ExtensionBoundary node={node}>\n <LazyDefaultLayout {...props} />\n </ExtensionBoundary>\n );\n\n const Layout =\n inputs.layout?.get(homePageLayoutComponentDataRef) ??\n DefaultLayoutComponent;\n\n const widgets = inputs.widgets.map(widget => ({\n ...widget.get(homePageWidgetDataRef),\n node: widget.node,\n }));\n\n return (\n <Layout widgets={widgets} defaultConfig={config.defaultConfig} />\n );\n },\n });\n },\n});\n\nconst visitListenerAppRootElement = AppRootElementBlueprint.make({\n name: 'visit-listener',\n disabled: true,\n params: {\n element: <VisitListener />,\n },\n});\n\nconst visitsApi = ApiBlueprint.make({\n name: 'visits',\n disabled: true,\n params: defineParams =>\n defineParams({\n api: visitsApiRef,\n deps: {\n storageApi: storageApiRef,\n identityApi: identityApiRef,\n errorApi: errorApiRef,\n },\n factory: ({ storageApi, identityApi, errorApi }) => {\n // Smart fallback: use custom storage API if available, otherwise localStorage\n if (storageApi) {\n return VisitsStorageApi.create({ storageApi, identityApi });\n }\n return VisitsWebStorageApi.create({ identityApi, errorApi });\n },\n }),\n});\n\nconst homePageToolkitWidget = HomePageWidgetBlueprint.makeWithOverrides({\n name: 'toolkit',\n configSchema: {\n tools: z\n .array(\n z.object({\n url: z.string(),\n label: z.string(),\n icon: z.string().optional(),\n }),\n )\n .default([{ url: 'https://backstage.io', label: 'Backstage Docs' }]),\n },\n *factory(originalFactory, { config }) {\n yield* originalFactory({\n name: 'HomePageToolkit',\n title: 'Toolkit',\n description: 'A collection of useful links and tools',\n components: () =>\n import('./homePageComponents/Toolkit').then(m => ({\n Content: (props: Record<string, unknown>) => {\n const iconsApi = useApi(iconsApiRef);\n const tools = config.tools.map(tool => ({\n url: tool.url,\n label: tool.label,\n icon: (tool.icon && iconsApi.icon(tool.icon)) ?? <LinkIcon />,\n }));\n return <m.Content {...props} tools={tools} />;\n },\n ContextProvider: m.ContextProvider,\n })),\n });\n },\n});\n\nconst homePageStarredEntitiesWidget = HomePageWidgetBlueprint.make({\n name: 'starred-entities',\n params: {\n name: 'HomePageStarredEntities',\n title: 'Your Starred Entities',\n description: 'Shows entities you have starred in the catalog',\n components: () =>\n import('./homePageComponents/StarredEntities').then(m => ({\n Content: m.Content,\n })),\n },\n});\n\nconst homePageRandomJokeWidget = HomePageWidgetBlueprint.make({\n name: 'random-joke',\n params: {\n name: 'HomePageRandomJoke',\n title: 'Random Joke',\n description: 'Shows a random programming joke',\n components: () =>\n import('./homePageComponents/RandomJoke').then(m => ({\n Content: m.Content,\n Settings: m.Settings,\n Actions: m.Actions,\n ContextProvider: m.ContextProvider,\n })),\n layout: {\n height: { minRows: 4 },\n width: { minColumns: 3 },\n },\n settings: {\n schema: {\n title: 'Random Joke settings',\n type: 'object',\n properties: {\n defaultCategory: {\n title: 'Category',\n type: 'string',\n enum: ['any', 'programming', 'dad'],\n default: 'any',\n },\n },\n },\n },\n },\n});\n\nconst homePageMostVisitedWidget = HomePageWidgetBlueprint.make({\n name: 'most-visited',\n params: {\n name: 'HomePageMostVisited',\n title: 'Most Visited',\n description: 'Shows your most frequently visited pages',\n components: () =>\n import('./homePageComponents/VisitedByType/TopVisited').then(m => ({\n Content: m.Content,\n Actions: m.Actions,\n ContextProvider: m.ContextProvider,\n })),\n },\n});\n\nconst homePageRecentlyVisitedWidget = HomePageWidgetBlueprint.make({\n name: 'recently-visited',\n params: {\n name: 'HomePageRecentlyVisited',\n title: 'Recently Visited',\n description: 'Shows pages you have recently visited',\n components: () =>\n import('./homePageComponents/VisitedByType/RecentlyVisited').then(m => ({\n Content: m.Content,\n Actions: m.Actions,\n ContextProvider: m.ContextProvider,\n })),\n },\n});\n\nconst homePageWorldClockWidget = HomePageWidgetBlueprint.makeWithOverrides({\n name: 'world-clock',\n configSchema: {\n clockConfigs: z\n .array(\n z.object({\n label: z.string(),\n timeZone: z.string(),\n }),\n )\n .optional(),\n customTimeFormat: z\n .object({\n hour12: z.boolean().optional(),\n })\n .optional(),\n },\n *factory(originalFactory, { config }) {\n yield* originalFactory({\n name: 'HomePageWorldClock',\n title: 'World Clocks',\n description: 'Displays clocks for configured time zones',\n components: () =>\n import('./homePageComponents/WorldClock').then(m => ({\n Content: () => (\n <m.WorldClock\n clockConfigs={config.clockConfigs}\n customTimeFormat={\n config.customTimeFormat\n ? {\n hour: '2-digit',\n minute: '2-digit',\n ...config.customTimeFormat,\n }\n : undefined\n }\n />\n ),\n })),\n });\n },\n});\n\n/**\n * Home plugin for the new frontend system.\n *\n * Provides core homepage functionality with optional visit tracking extensions.\n * Visit tracking extensions are disabled by default and can be enabled via app-config.yaml.\n *\n * @alpha\n */\nexport default createFrontendPlugin({\n pluginId: 'home',\n title: 'Home',\n icon: <HomeIcon />,\n info: { packageJson: () => import('../package.json') },\n extensions: [\n homePage,\n visitsApi,\n visitListenerAppRootElement,\n homePageToolkitWidget,\n homePageStarredEntitiesWidget,\n homePageRandomJokeWidget,\n homePageMostVisitedWidget,\n homePageRecentlyVisitedWidget,\n homePageWorldClockWidget,\n ],\n routes: {\n root: rootRouteRef,\n },\n});\n\nimport { homeTranslationRef as _homeTranslationRef } from './translation';\n\n/**\n * @alpha\n * @deprecated Import from `@backstage/plugin-home` instead.\n */\nexport const homeTranslationRef = _homeTranslationRef;\n"],"names":["reactLazy","_homeTranslationRef"],"mappings":"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"}
@@ -46,6 +46,15 @@ const useStyles = makeStyles(
46
46
  "&.edit > :active": {
47
47
  cursor: "move"
48
48
  }
49
+ },
50
+ layoutLabel: {
51
+ position: "absolute",
52
+ bottom: 4,
53
+ left: 8,
54
+ fontSize: "0.7rem",
55
+ color: theme.palette.text.disabled,
56
+ pointerEvents: "none",
57
+ zIndex: 1
49
58
  }
50
59
  })
51
60
  );
@@ -332,17 +341,29 @@ const CustomHomepageGrid = (props) => {
332
341
  className: `${styles.widgetWrapper} ${editMode && "edit"} ${w.movable === false && "disabled"}`,
333
342
  children: [
334
343
  /* @__PURE__ */ jsx(ErrorBoundary, { children: /* @__PURE__ */ jsx(widget.component.type, { ...widgetProps }) }),
335
- editMode && /* @__PURE__ */ jsx(
336
- WidgetSettingsOverlay,
337
- {
338
- id: l.i,
339
- widget,
340
- handleRemove,
341
- handleSettingsSave,
342
- settings: w.settings,
343
- deletable: w.deletable
344
- }
345
- )
344
+ editMode && /* @__PURE__ */ jsxs(Fragment, { children: [
345
+ /* @__PURE__ */ jsxs(Typography, { variant: "caption", className: styles.layoutLabel, children: [
346
+ "column: ",
347
+ l.x,
348
+ ", row: ",
349
+ l.y,
350
+ ", width: ",
351
+ l.w,
352
+ ", height: ",
353
+ l.h
354
+ ] }),
355
+ /* @__PURE__ */ jsx(
356
+ WidgetSettingsOverlay,
357
+ {
358
+ id: l.i,
359
+ widget,
360
+ handleRemove,
361
+ handleSettingsSave,
362
+ settings: w.settings,
363
+ deletable: w.deletable
364
+ }
365
+ )
366
+ ] })
346
367
  ]
347
368
  },
348
369
  l.i
@@ -1 +1 @@
1
- {"version":3,"file":"CustomHomepageGrid.esm.js","sources":["../../../src/components/CustomHomepage/CustomHomepageGrid.tsx"],"sourcesContent":["/*\n * Copyright 2023 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport {\n isValidElement,\n useState,\n useCallback,\n useMemo,\n useEffect,\n} from 'react';\nimport { Layout, Layouts, Responsive, WidthProvider } from 'react-grid-layout';\nimport {\n ElementCollection,\n getComponentData,\n storageApiRef,\n useApi,\n useElementFilter,\n} from '@backstage/core-plugin-api';\nimport 'react-grid-layout/css/styles.css';\nimport 'react-resizable/css/styles.css';\nimport Dialog from '@material-ui/core/Dialog';\nimport {\n createStyles,\n makeStyles,\n Theme,\n useTheme,\n} from '@material-ui/core/styles';\nimport { compact } from 'lodash';\nimport useObservable from 'react-use/esm/useObservable';\nimport {\n ContentHeader,\n ErrorBoundary,\n Progress,\n} from '@backstage/core-components';\nimport Typography from '@material-ui/core/Typography';\nimport { WidgetSettingsOverlay } from './WidgetSettingsOverlay';\nimport { AddWidgetDialog } from './AddWidgetDialog';\nimport { CustomHomepageButtons } from './CustomHomepageButtons';\nimport {\n CustomHomepageGridProps,\n CustomHomepageGridStateV1,\n CustomHomepageGridStateV1Schema,\n GridWidget,\n LayoutConfiguration,\n LayoutConfigurationSchema,\n Widget,\n WidgetSchema,\n} from './types';\nimport { CardConfig } from '@backstage/plugin-home-react';\nimport { useTranslationRef } from '@backstage/frontend-plugin-api';\nimport { homeTranslationRef } from '../../translation';\n\n// eslint-disable-next-line new-cap\nconst ResponsiveGrid = WidthProvider(Responsive);\n\nconst useStyles = makeStyles((theme: Theme) =>\n createStyles({\n responsiveGrid: {\n '& .react-grid-item > .react-resizable-handle:after': {\n position: 'absolute',\n content: '\"\"',\n borderStyle: 'solid',\n borderWidth: '0 0 20px 20px',\n borderColor: `transparent transparent ${theme.palette.primary.light} transparent`,\n },\n },\n contentHeaderBtn: {\n marginLeft: theme.spacing(2),\n },\n widgetWrapper: {\n '& > div[class*=\"MuiCard-root\"]': {\n width: '100%',\n height: '100%',\n },\n '& div[class*=\"MuiCardContent-root\"]': {\n overflow: 'auto',\n },\n '& + .react-grid-placeholder': {\n backgroundColor: theme.palette.primary.light,\n },\n '&.edit > :active': {\n cursor: 'move',\n },\n },\n }),\n);\n\nfunction useHomeStorage(\n defaultWidgets: GridWidget[],\n): [GridWidget[], (value: GridWidget[]) => void, boolean] {\n const key = 'home';\n const storageApi = useApi(storageApiRef).forBucket('home.customHomepage');\n // TODO: Support multiple home pages\n const setWidgets = useCallback(\n (value: GridWidget[]) => {\n const grid: CustomHomepageGridStateV1 = {\n version: 1,\n pages: {\n default: value,\n },\n };\n storageApi.set(key, JSON.stringify(grid));\n },\n [key, storageApi],\n );\n const homeSnapshot = useObservable(\n storageApi.observe$<string>(key),\n storageApi.snapshot(key),\n );\n\n const isStorageLoading = homeSnapshot.presence === 'unknown' || !homeSnapshot;\n\n const widgets: GridWidget[] = useMemo(() => {\n if (homeSnapshot.presence === 'absent') {\n return defaultWidgets;\n }\n try {\n const grid: CustomHomepageGridStateV1 = JSON.parse(homeSnapshot.value!);\n return CustomHomepageGridStateV1Schema.parse(grid).pages.default;\n } catch (e) {\n return defaultWidgets;\n }\n }, [homeSnapshot, defaultWidgets]);\n\n return [widgets, setWidgets, isStorageLoading];\n}\n\nconst convertConfigToDefaultWidgets = (\n config: LayoutConfiguration[],\n availableWidgets: Widget[],\n): GridWidget[] => {\n const ret = config.map((conf, i) => {\n const c = LayoutConfigurationSchema.parse(conf);\n const name = isValidElement(c.component)\n ? getComponentData(c.component, 'core.extensionName')\n : (c.component as unknown as string);\n if (!name) {\n return null;\n }\n const widget = availableWidgets.find(w => w.name === name);\n if (!widget) {\n return null;\n }\n const widgetId = `${widget.name}__${i}${Math.random()\n .toString(36)\n .slice(2)}`;\n return {\n id: widgetId,\n layout: {\n i: widgetId,\n x: c.x,\n y: c.y,\n w: Math.min(widget.maxWidth ?? Number.MAX_VALUE, c.width),\n h: Math.min(widget.maxHeight ?? Number.MAX_VALUE, c.height),\n minW: widget.minWidth,\n maxW: widget.maxWidth,\n minH: widget.minHeight,\n maxH: widget.maxHeight,\n isDraggable: false,\n isResizable: false,\n },\n settings: {},\n movable: conf.movable,\n deletable: conf.deletable,\n resizable: conf.resizable,\n };\n });\n return compact(ret);\n};\n\nconst availableWidgetsFilter = (elements: ElementCollection) => {\n return elements\n .selectByComponentData({\n key: 'core.extensionName',\n })\n .getElements<Widget>()\n .flatMap(elem => {\n const config = getComponentData<CardConfig>(elem, 'home.widget.config');\n return [\n WidgetSchema.parse({\n component: elem,\n name: getComponentData<string>(elem, 'core.extensionName'),\n title: getComponentData<string>(elem, 'title'),\n description: getComponentData<string>(elem, 'description'),\n settingsSchema: config?.settings?.schema,\n uiSchema: config?.settings?.uiSchema,\n width: config?.layout?.width?.defaultColumns,\n minWidth: config?.layout?.width?.minColumns,\n maxWidth: config?.layout?.width?.maxColumns,\n height: config?.layout?.height?.defaultRows,\n minHeight: config?.layout?.height?.minRows,\n maxHeight: config?.layout?.height?.maxRows,\n }),\n ];\n });\n};\n\n/**\n * A component that allows customizing components in home grid layout.\n *\n * @public\n */\nexport const CustomHomepageGrid = (props: CustomHomepageGridProps) => {\n const styles = useStyles();\n const theme = useTheme();\n const availableWidgets = useElementFilter(\n props.children,\n availableWidgetsFilter,\n [props],\n );\n const defaultLayout = useMemo(() => {\n return props.config\n ? convertConfigToDefaultWidgets(props.config, availableWidgets)\n : [];\n }, [props.config, availableWidgets]);\n const [storedWidgets, storeWidgets, isStorageLoading] =\n useHomeStorage(defaultLayout);\n const [widgets, setWidgets] = useState(storedWidgets);\n\n const preventDuplicateWidgets = props.preventDuplicateWidgets ?? false;\n\n const [addWidgetDialogOpen, setAddWidgetDialogOpen] = useState(false);\n const editModeOn = widgets.find(w => w.layout.isResizable) !== undefined;\n const [editMode, setEditMode] = useState(editModeOn);\n\n useEffect(() => {\n setWidgets(storedWidgets);\n }, [storedWidgets]);\n\n const getWidgetByName = (name: string) => {\n return availableWidgets.find(widget => widget.name === name);\n };\n\n const getWidgetNameFromKey = (key: string) => {\n return key.split('__')[0];\n };\n const { t } = useTranslationRef(homeTranslationRef);\n\n const getAvailableWidgets = () => {\n if (!preventDuplicateWidgets) {\n return availableWidgets;\n }\n const usedWidgetNames = new Set(\n widgets.map(w => getWidgetNameFromKey(w.id)),\n );\n return availableWidgets.filter(widget => !usedWidgetNames.has(widget.name));\n };\n\n const handleAdd = (widget: Widget) => {\n const widgetId = `${widget.name}__${widgets.length + 1}${Math.random()\n .toString(36)\n .slice(2)}`;\n\n setWidgets([\n ...widgets,\n {\n id: widgetId,\n layout: {\n i: widgetId,\n x: 0,\n y: Math.max(...widgets.map(w => w.layout.y + w.layout.h)) + 1,\n w: Math.min(widget.maxWidth ?? Number.MAX_VALUE, widget.width ?? 12),\n h: Math.min(widget.maxHeight ?? Number.MAX_VALUE, widget.height ?? 4),\n minW: widget.minWidth,\n maxW: widget.maxWidth,\n minH: widget.minHeight,\n maxH: widget.maxHeight,\n isResizable: editMode,\n isDraggable: editMode,\n },\n settings: {},\n movable: widget.movable,\n deletable: widget.deletable,\n resizable: widget.resizable,\n },\n ]);\n setAddWidgetDialogOpen(false);\n };\n\n const handleRemove = (widgetId: string) => {\n setWidgets(widgets.filter(w => w.id !== widgetId));\n };\n\n const handleSettingsSave = (\n widgetId: string,\n widgetSettings: Record<string, any>,\n ) => {\n const idx = widgets.findIndex(w => w.id === widgetId);\n if (idx >= 0) {\n const widget = widgets[idx];\n widget.settings = widgetSettings;\n widgets[idx] = widget;\n setWidgets(widgets);\n }\n };\n\n const clearLayout = () => {\n setWidgets(widgets.filter(w => w.deletable === false));\n };\n\n const changeEditMode = (mode: boolean) => {\n setEditMode(mode);\n\n const newWidgets = widgets.map(w => {\n const resizable = w.resizable === false ? false : mode;\n const movable = w.movable === false ? false : mode;\n return {\n ...w,\n layout: { ...w.layout, isDraggable: movable, isResizable: resizable },\n };\n });\n\n if (mode) {\n setWidgets(newWidgets);\n } else {\n storeWidgets(newWidgets);\n }\n };\n\n const handleLayoutChange = (newLayout: Layout[], _: Layouts) => {\n if (editMode) {\n const newWidgets = newLayout.map(l => {\n const widget = widgets.find(w => w.id === l.i);\n return {\n ...widget,\n layout: l,\n } as GridWidget;\n });\n setWidgets(newWidgets);\n }\n };\n\n const handleRestoreDefaultConfig = () => {\n setWidgets(\n defaultLayout.map(w => {\n const resizable = w.resizable === false ? false : editMode;\n const movable = w.movable === false ? false : editMode;\n return {\n ...w,\n layout: {\n ...w.layout,\n isDraggable: movable,\n isResizable: resizable,\n },\n };\n }),\n );\n };\n\n const handleCancel = () => {\n setWidgets(storedWidgets);\n setEditMode(false);\n };\n\n if (isStorageLoading) {\n return <Progress />;\n }\n\n return (\n <>\n <ContentHeader title={props.title}>\n <CustomHomepageButtons\n editMode={editMode}\n numWidgets={widgets.length}\n clearLayout={clearLayout}\n setAddWidgetDialogOpen={setAddWidgetDialogOpen}\n changeEditMode={changeEditMode}\n defaultConfigAvailable={props.config !== undefined}\n restoreDefault={handleRestoreDefaultConfig}\n cancel={handleCancel}\n />\n </ContentHeader>\n <Dialog\n open={addWidgetDialogOpen}\n onClose={() => setAddWidgetDialogOpen(false)}\n >\n {/* Only mount when open so the list does not update (e.g. remove the added widget) before the modal closes */}\n {addWidgetDialogOpen && (\n <AddWidgetDialog\n widgets={getAvailableWidgets()}\n handleAdd={handleAdd}\n />\n )}\n </Dialog>\n {!editMode && widgets.length === 0 && (\n <Typography variant=\"h5\" align=\"center\">\n {t('customHomepage.noWidgets')}\n </Typography>\n )}\n <ResponsiveGrid\n className={styles.responsiveGrid}\n measureBeforeMount\n compactType={props.compactType}\n style={props.style}\n allowOverlap={props.allowOverlap}\n preventCollision={props.preventCollision ?? true}\n draggableCancel=\".overlayGridItem,.widgetSettingsDialog,.disabled\"\n containerPadding={props.containerPadding}\n margin={props.containerMargin}\n breakpoints={\n props.breakpoints ? props.breakpoints : theme.breakpoints.values\n }\n cols={\n props.cols\n ? props.cols\n : { xl: 12, lg: 12, md: 10, sm: 6, xs: 4, xxs: 2 }\n }\n rowHeight={props.rowHeight ?? 60}\n onLayoutChange={handleLayoutChange}\n layouts={{ xl: widgets.map(w => w.layout) }}\n >\n {widgets.map((w: GridWidget) => {\n const l = w.layout;\n const widgetName = getWidgetNameFromKey(l.i);\n const widget = getWidgetByName(widgetName);\n if (!widget || !widget.component) {\n return null;\n }\n\n const widgetProps = {\n ...widget.component.props,\n ...(w.settings ?? {}),\n };\n\n return (\n <div\n key={l.i}\n className={`${styles.widgetWrapper} ${editMode && 'edit'} ${\n w.movable === false && 'disabled'\n }`}\n >\n <ErrorBoundary>\n <widget.component.type {...widgetProps} />\n </ErrorBoundary>\n {editMode && (\n <WidgetSettingsOverlay\n id={l.i}\n widget={widget}\n handleRemove={handleRemove}\n handleSettingsSave={handleSettingsSave}\n settings={w.settings}\n deletable={w.deletable}\n />\n )}\n </div>\n );\n })}\n </ResponsiveGrid>\n </>\n );\n};\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"CustomHomepageGrid.esm.js","sources":["../../../src/components/CustomHomepage/CustomHomepageGrid.tsx"],"sourcesContent":["/*\n * Copyright 2023 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport {\n isValidElement,\n useState,\n useCallback,\n useMemo,\n useEffect,\n} from 'react';\nimport { Layout, Layouts, Responsive, WidthProvider } from 'react-grid-layout';\nimport {\n ElementCollection,\n getComponentData,\n storageApiRef,\n useApi,\n useElementFilter,\n} from '@backstage/core-plugin-api';\nimport 'react-grid-layout/css/styles.css';\nimport 'react-resizable/css/styles.css';\nimport Dialog from '@material-ui/core/Dialog';\nimport {\n createStyles,\n makeStyles,\n Theme,\n useTheme,\n} from '@material-ui/core/styles';\nimport { compact } from 'lodash';\nimport useObservable from 'react-use/esm/useObservable';\nimport {\n ContentHeader,\n ErrorBoundary,\n Progress,\n} from '@backstage/core-components';\nimport Typography from '@material-ui/core/Typography';\nimport { WidgetSettingsOverlay } from './WidgetSettingsOverlay';\nimport { AddWidgetDialog } from './AddWidgetDialog';\nimport { CustomHomepageButtons } from './CustomHomepageButtons';\nimport {\n CustomHomepageGridProps,\n CustomHomepageGridStateV1,\n CustomHomepageGridStateV1Schema,\n GridWidget,\n LayoutConfiguration,\n LayoutConfigurationSchema,\n Widget,\n WidgetSchema,\n} from './types';\nimport { CardConfig } from '@backstage/plugin-home-react';\nimport { useTranslationRef } from '@backstage/frontend-plugin-api';\nimport { homeTranslationRef } from '../../translation';\n\n// eslint-disable-next-line new-cap\nconst ResponsiveGrid = WidthProvider(Responsive);\n\nconst useStyles = makeStyles((theme: Theme) =>\n createStyles({\n responsiveGrid: {\n '& .react-grid-item > .react-resizable-handle:after': {\n position: 'absolute',\n content: '\"\"',\n borderStyle: 'solid',\n borderWidth: '0 0 20px 20px',\n borderColor: `transparent transparent ${theme.palette.primary.light} transparent`,\n },\n },\n contentHeaderBtn: {\n marginLeft: theme.spacing(2),\n },\n widgetWrapper: {\n '& > div[class*=\"MuiCard-root\"]': {\n width: '100%',\n height: '100%',\n },\n '& div[class*=\"MuiCardContent-root\"]': {\n overflow: 'auto',\n },\n '& + .react-grid-placeholder': {\n backgroundColor: theme.palette.primary.light,\n },\n '&.edit > :active': {\n cursor: 'move',\n },\n },\n layoutLabel: {\n position: 'absolute',\n bottom: 4,\n left: 8,\n fontSize: '0.7rem',\n color: theme.palette.text.disabled,\n pointerEvents: 'none',\n zIndex: 1,\n },\n }),\n);\n\nfunction useHomeStorage(\n defaultWidgets: GridWidget[],\n): [GridWidget[], (value: GridWidget[]) => void, boolean] {\n const key = 'home';\n const storageApi = useApi(storageApiRef).forBucket('home.customHomepage');\n // TODO: Support multiple home pages\n const setWidgets = useCallback(\n (value: GridWidget[]) => {\n const grid: CustomHomepageGridStateV1 = {\n version: 1,\n pages: {\n default: value,\n },\n };\n storageApi.set(key, JSON.stringify(grid));\n },\n [key, storageApi],\n );\n const homeSnapshot = useObservable(\n storageApi.observe$<string>(key),\n storageApi.snapshot(key),\n );\n\n const isStorageLoading = homeSnapshot.presence === 'unknown' || !homeSnapshot;\n\n const widgets: GridWidget[] = useMemo(() => {\n if (homeSnapshot.presence === 'absent') {\n return defaultWidgets;\n }\n try {\n const grid: CustomHomepageGridStateV1 = JSON.parse(homeSnapshot.value!);\n return CustomHomepageGridStateV1Schema.parse(grid).pages.default;\n } catch (e) {\n return defaultWidgets;\n }\n }, [homeSnapshot, defaultWidgets]);\n\n return [widgets, setWidgets, isStorageLoading];\n}\n\nconst convertConfigToDefaultWidgets = (\n config: LayoutConfiguration[],\n availableWidgets: Widget[],\n): GridWidget[] => {\n const ret = config.map((conf, i) => {\n const c = LayoutConfigurationSchema.parse(conf);\n const name = isValidElement(c.component)\n ? getComponentData(c.component, 'core.extensionName')\n : (c.component as unknown as string);\n if (!name) {\n return null;\n }\n const widget = availableWidgets.find(w => w.name === name);\n if (!widget) {\n return null;\n }\n const widgetId = `${widget.name}__${i}${Math.random()\n .toString(36)\n .slice(2)}`;\n return {\n id: widgetId,\n layout: {\n i: widgetId,\n x: c.x,\n y: c.y,\n w: Math.min(widget.maxWidth ?? Number.MAX_VALUE, c.width),\n h: Math.min(widget.maxHeight ?? Number.MAX_VALUE, c.height),\n minW: widget.minWidth,\n maxW: widget.maxWidth,\n minH: widget.minHeight,\n maxH: widget.maxHeight,\n isDraggable: false,\n isResizable: false,\n },\n settings: {},\n movable: conf.movable,\n deletable: conf.deletable,\n resizable: conf.resizable,\n };\n });\n return compact(ret);\n};\n\nconst availableWidgetsFilter = (elements: ElementCollection) => {\n return elements\n .selectByComponentData({\n key: 'core.extensionName',\n })\n .getElements<Widget>()\n .flatMap(elem => {\n const config = getComponentData<CardConfig>(elem, 'home.widget.config');\n return [\n WidgetSchema.parse({\n component: elem,\n name: getComponentData<string>(elem, 'core.extensionName'),\n title: getComponentData<string>(elem, 'title'),\n description: getComponentData<string>(elem, 'description'),\n settingsSchema: config?.settings?.schema,\n uiSchema: config?.settings?.uiSchema,\n width: config?.layout?.width?.defaultColumns,\n minWidth: config?.layout?.width?.minColumns,\n maxWidth: config?.layout?.width?.maxColumns,\n height: config?.layout?.height?.defaultRows,\n minHeight: config?.layout?.height?.minRows,\n maxHeight: config?.layout?.height?.maxRows,\n }),\n ];\n });\n};\n\n/**\n * A component that allows customizing components in home grid layout.\n *\n * @public\n */\nexport const CustomHomepageGrid = (props: CustomHomepageGridProps) => {\n const styles = useStyles();\n const theme = useTheme();\n const availableWidgets = useElementFilter(\n props.children,\n availableWidgetsFilter,\n [props],\n );\n const defaultLayout = useMemo(() => {\n return props.config\n ? convertConfigToDefaultWidgets(props.config, availableWidgets)\n : [];\n }, [props.config, availableWidgets]);\n const [storedWidgets, storeWidgets, isStorageLoading] =\n useHomeStorage(defaultLayout);\n const [widgets, setWidgets] = useState(storedWidgets);\n\n const preventDuplicateWidgets = props.preventDuplicateWidgets ?? false;\n\n const [addWidgetDialogOpen, setAddWidgetDialogOpen] = useState(false);\n const editModeOn = widgets.find(w => w.layout.isResizable) !== undefined;\n const [editMode, setEditMode] = useState(editModeOn);\n\n useEffect(() => {\n setWidgets(storedWidgets);\n }, [storedWidgets]);\n\n const getWidgetByName = (name: string) => {\n return availableWidgets.find(widget => widget.name === name);\n };\n\n const getWidgetNameFromKey = (key: string) => {\n return key.split('__')[0];\n };\n const { t } = useTranslationRef(homeTranslationRef);\n\n const getAvailableWidgets = () => {\n if (!preventDuplicateWidgets) {\n return availableWidgets;\n }\n const usedWidgetNames = new Set(\n widgets.map(w => getWidgetNameFromKey(w.id)),\n );\n return availableWidgets.filter(widget => !usedWidgetNames.has(widget.name));\n };\n\n const handleAdd = (widget: Widget) => {\n const widgetId = `${widget.name}__${widgets.length + 1}${Math.random()\n .toString(36)\n .slice(2)}`;\n\n setWidgets([\n ...widgets,\n {\n id: widgetId,\n layout: {\n i: widgetId,\n x: 0,\n y: Math.max(...widgets.map(w => w.layout.y + w.layout.h)) + 1,\n w: Math.min(widget.maxWidth ?? Number.MAX_VALUE, widget.width ?? 12),\n h: Math.min(widget.maxHeight ?? Number.MAX_VALUE, widget.height ?? 4),\n minW: widget.minWidth,\n maxW: widget.maxWidth,\n minH: widget.minHeight,\n maxH: widget.maxHeight,\n isResizable: editMode,\n isDraggable: editMode,\n },\n settings: {},\n movable: widget.movable,\n deletable: widget.deletable,\n resizable: widget.resizable,\n },\n ]);\n setAddWidgetDialogOpen(false);\n };\n\n const handleRemove = (widgetId: string) => {\n setWidgets(widgets.filter(w => w.id !== widgetId));\n };\n\n const handleSettingsSave = (\n widgetId: string,\n widgetSettings: Record<string, any>,\n ) => {\n const idx = widgets.findIndex(w => w.id === widgetId);\n if (idx >= 0) {\n const widget = widgets[idx];\n widget.settings = widgetSettings;\n widgets[idx] = widget;\n setWidgets(widgets);\n }\n };\n\n const clearLayout = () => {\n setWidgets(widgets.filter(w => w.deletable === false));\n };\n\n const changeEditMode = (mode: boolean) => {\n setEditMode(mode);\n\n const newWidgets = widgets.map(w => {\n const resizable = w.resizable === false ? false : mode;\n const movable = w.movable === false ? false : mode;\n return {\n ...w,\n layout: { ...w.layout, isDraggable: movable, isResizable: resizable },\n };\n });\n\n if (mode) {\n setWidgets(newWidgets);\n } else {\n storeWidgets(newWidgets);\n }\n };\n\n const handleLayoutChange = (newLayout: Layout[], _: Layouts) => {\n if (editMode) {\n const newWidgets = newLayout.map(l => {\n const widget = widgets.find(w => w.id === l.i);\n return {\n ...widget,\n layout: l,\n } as GridWidget;\n });\n setWidgets(newWidgets);\n }\n };\n\n const handleRestoreDefaultConfig = () => {\n setWidgets(\n defaultLayout.map(w => {\n const resizable = w.resizable === false ? false : editMode;\n const movable = w.movable === false ? false : editMode;\n return {\n ...w,\n layout: {\n ...w.layout,\n isDraggable: movable,\n isResizable: resizable,\n },\n };\n }),\n );\n };\n\n const handleCancel = () => {\n setWidgets(storedWidgets);\n setEditMode(false);\n };\n\n if (isStorageLoading) {\n return <Progress />;\n }\n\n return (\n <>\n <ContentHeader title={props.title}>\n <CustomHomepageButtons\n editMode={editMode}\n numWidgets={widgets.length}\n clearLayout={clearLayout}\n setAddWidgetDialogOpen={setAddWidgetDialogOpen}\n changeEditMode={changeEditMode}\n defaultConfigAvailable={props.config !== undefined}\n restoreDefault={handleRestoreDefaultConfig}\n cancel={handleCancel}\n />\n </ContentHeader>\n <Dialog\n open={addWidgetDialogOpen}\n onClose={() => setAddWidgetDialogOpen(false)}\n >\n {/* Only mount when open so the list does not update (e.g. remove the added widget) before the modal closes */}\n {addWidgetDialogOpen && (\n <AddWidgetDialog\n widgets={getAvailableWidgets()}\n handleAdd={handleAdd}\n />\n )}\n </Dialog>\n {!editMode && widgets.length === 0 && (\n <Typography variant=\"h5\" align=\"center\">\n {t('customHomepage.noWidgets')}\n </Typography>\n )}\n <ResponsiveGrid\n className={styles.responsiveGrid}\n measureBeforeMount\n compactType={props.compactType}\n style={props.style}\n allowOverlap={props.allowOverlap}\n preventCollision={props.preventCollision ?? true}\n draggableCancel=\".overlayGridItem,.widgetSettingsDialog,.disabled\"\n containerPadding={props.containerPadding}\n margin={props.containerMargin}\n breakpoints={\n props.breakpoints ? props.breakpoints : theme.breakpoints.values\n }\n cols={\n props.cols\n ? props.cols\n : { xl: 12, lg: 12, md: 10, sm: 6, xs: 4, xxs: 2 }\n }\n rowHeight={props.rowHeight ?? 60}\n onLayoutChange={handleLayoutChange}\n layouts={{ xl: widgets.map(w => w.layout) }}\n >\n {widgets.map((w: GridWidget) => {\n const l = w.layout;\n const widgetName = getWidgetNameFromKey(l.i);\n const widget = getWidgetByName(widgetName);\n if (!widget || !widget.component) {\n return null;\n }\n\n const widgetProps = {\n ...widget.component.props,\n ...(w.settings ?? {}),\n };\n\n return (\n <div\n key={l.i}\n className={`${styles.widgetWrapper} ${editMode && 'edit'} ${\n w.movable === false && 'disabled'\n }`}\n >\n <ErrorBoundary>\n <widget.component.type {...widgetProps} />\n </ErrorBoundary>\n {editMode && (\n <>\n <Typography variant=\"caption\" className={styles.layoutLabel}>\n column: {l.x}, row: {l.y}, width: {l.w}, height: {l.h}\n </Typography>\n <WidgetSettingsOverlay\n id={l.i}\n widget={widget}\n handleRemove={handleRemove}\n handleSettingsSave={handleSettingsSave}\n settings={w.settings}\n deletable={w.deletable}\n />\n </>\n )}\n </div>\n );\n })}\n </ResponsiveGrid>\n </>\n );\n};\n"],"names":[],"mappings":"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"}