@red-hat-developer-hub/backstage-plugin-dynamic-home-page 1.11.0 → 1.13.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 +30 -0
- package/dist/alpha/components/CustomizableGridLayout.esm.js +17 -7
- package/dist/alpha/components/CustomizableGridLayout.esm.js.map +1 -1
- package/dist/alpha/extensions/apis.esm.js +15 -2
- package/dist/alpha/extensions/apis.esm.js.map +1 -1
- package/dist/alpha/extensions/homePageCards.esm.js +6 -6
- package/dist/alpha/extensions/homePageCards.esm.js.map +1 -1
- package/dist/alpha.d.ts +1 -1
- package/dist/alpha.esm.js +2 -1
- package/dist/alpha.esm.js.map +1 -1
- package/dist/api/DefaultWidgetsApiClient.esm.js +26 -0
- package/dist/api/DefaultWidgetsApiClient.esm.js.map +1 -0
- package/dist/components/CustomizableGrid.esm.js +17 -7
- package/dist/components/CustomizableGrid.esm.js.map +1 -1
- package/dist/components/DefaultWidgetsCustomizableGrid.esm.js +138 -0
- package/dist/components/DefaultWidgetsCustomizableGrid.esm.js.map +1 -0
- package/dist/components/DefaultWidgetsReadOnlyGrid.esm.js +146 -0
- package/dist/components/DefaultWidgetsReadOnlyGrid.esm.js.map +1 -0
- package/dist/components/EntitySection/EntitySection.esm.js +1 -8
- package/dist/components/EntitySection/EntitySection.esm.js.map +1 -1
- package/dist/components/HomePage.esm.js +27 -3
- package/dist/components/HomePage.esm.js.map +1 -1
- package/dist/hooks/useContainerQuery.esm.js +40 -5
- package/dist/hooks/useContainerQuery.esm.js.map +1 -1
- package/dist/hooks/useDefaultWidgets.esm.js +19 -0
- package/dist/hooks/useDefaultWidgets.esm.js.map +1 -0
- package/dist/index.d.ts +24 -11
- package/dist/index.esm.js +1 -0
- package/dist/index.esm.js.map +1 -1
- package/dist/plugin.esm.js +11 -2
- package/dist/plugin.esm.js.map +1 -1
- package/dist/translations/de.esm.js +1 -1
- package/dist/translations/de.esm.js.map +1 -1
- package/dist/translations/es.esm.js +1 -1
- package/dist/translations/es.esm.js.map +1 -1
- package/dist/translations/fr.esm.js +1 -1
- package/dist/translations/fr.esm.js.map +1 -1
- package/dist/translations/it.esm.js +1 -1
- package/dist/translations/it.esm.js.map +1 -1
- package/dist/translations/ja.esm.js +1 -1
- package/dist/translations/ja.esm.js.map +1 -1
- package/dist/translations/ref.esm.js +1 -1
- package/dist/translations/ref.esm.js.map +1 -1
- package/dist/utils/customizable-cards.esm.js.map +1 -1
- package/package.json +27 -23
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,35 @@
|
|
|
1
1
|
# @red-hat-developer-hub/backstage-plugin-dynamic-home-page
|
|
2
2
|
|
|
3
|
+
## 1.13.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- a5a1846: Homepage default content is now resolved through a new backend with RBAC, widget-oriented configuration, and translated titles. Bumps `@red-hat-developer-hub/backstage-plugin-theme` to `^0.14.1`.
|
|
8
|
+
|
|
9
|
+
**`@red-hat-developer-hub/backstage-plugin-dynamic-home-page`**
|
|
10
|
+
|
|
11
|
+
- Load default widgets from the homepage backend API (permission-aware), with a frontend API client and hooks.
|
|
12
|
+
|
|
13
|
+
**`@red-hat-developer-hub/backstage-plugin-homepage-backend` and `@red-hat-developer-hub/backstage-plugin-homepage-common`**
|
|
14
|
+
|
|
15
|
+
- Initial release: backend resolves default widgets using user context, `if` conditions; shared types and permission definitions live in homepage-common.
|
|
16
|
+
|
|
17
|
+
### Patch Changes
|
|
18
|
+
|
|
19
|
+
- Updated dependencies [a5a1846]
|
|
20
|
+
- @red-hat-developer-hub/backstage-plugin-homepage-common@0.1.0
|
|
21
|
+
|
|
22
|
+
## 1.12.0
|
|
23
|
+
|
|
24
|
+
### Minor Changes
|
|
25
|
+
|
|
26
|
+
- e8780ce: Backstage version bump to v1.49.3
|
|
27
|
+
|
|
28
|
+
### Patch Changes
|
|
29
|
+
|
|
30
|
+
- 7ea283a: fixes the responsiveness issue of the customizable home-page
|
|
31
|
+
- 4e40bf1: Fix misleading entity count in EntitySection card link
|
|
32
|
+
|
|
3
33
|
## 1.11.0
|
|
4
34
|
|
|
5
35
|
### Minor Changes
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import { jsxs, Fragment, jsx } from 'react/jsx-runtime';
|
|
2
|
-
import { useMemo, Fragment as Fragment$1 } from 'react';
|
|
2
|
+
import { useRef, useMemo, Fragment as Fragment$1 } from 'react';
|
|
3
3
|
import { CustomHomepageGrid } from '@backstage/plugin-home';
|
|
4
4
|
import { useTheme } from '@mui/material/styles';
|
|
5
5
|
import GlobalStyles from '@mui/material/GlobalStyles';
|
|
6
|
+
import { useContainerQuery } from '../../hooks/useContainerQuery.esm.js';
|
|
6
7
|
import 'react-grid-layout/css/styles.css';
|
|
7
8
|
import { isCardADefaultConfiguration } from '../utils.esm.js';
|
|
8
9
|
|
|
@@ -10,6 +11,8 @@ const CustomizableGridLayout = ({
|
|
|
10
11
|
homepageCards
|
|
11
12
|
}) => {
|
|
12
13
|
const theme = useTheme();
|
|
14
|
+
const gridContainerRef = useRef(null);
|
|
15
|
+
useContainerQuery(gridContainerRef, { notifyWindowResize: true });
|
|
13
16
|
const config = useMemo(() => {
|
|
14
17
|
const defaultConfig = [];
|
|
15
18
|
homepageCards.forEach((homepageCard) => {
|
|
@@ -44,13 +47,20 @@ const CustomizableGridLayout = ({
|
|
|
44
47
|
}
|
|
45
48
|
),
|
|
46
49
|
/* @__PURE__ */ jsx(
|
|
47
|
-
|
|
50
|
+
"div",
|
|
48
51
|
{
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
52
|
+
ref: gridContainerRef,
|
|
53
|
+
style: { width: "100%", minWidth: 0, boxSizing: "border-box" },
|
|
54
|
+
children: /* @__PURE__ */ jsx(
|
|
55
|
+
CustomHomepageGrid,
|
|
56
|
+
{
|
|
57
|
+
config,
|
|
58
|
+
preventCollision: false,
|
|
59
|
+
compactType: "vertical",
|
|
60
|
+
style: { margin: "-10px" },
|
|
61
|
+
children: homepageCards.map((card, index) => /* @__PURE__ */ jsx(Fragment$1, { children: card.component }, card.name ?? index))
|
|
62
|
+
}
|
|
63
|
+
)
|
|
54
64
|
}
|
|
55
65
|
)
|
|
56
66
|
] });
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"CustomizableGridLayout.esm.js","sources":["../../../src/alpha/components/CustomizableGridLayout.tsx"],"sourcesContent":["/*\n * Copyright Red Hat, Inc.\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// This complete read-only home page grid picks up the idea and styles from\n// https://github.com/backstage/backstage/blob/master/plugins/home\n// Esp. from the CustomHomepageGrid component:\n// https://github.com/backstage/backstage/blob/master/plugins/home/src/components/CustomHomepage/CustomHomepageGrid.tsx\n// but without the drag and drop functionality.\n\nimport { Fragment, useMemo } from 'react';\n\nimport {\n CustomHomepageGrid,\n LayoutConfiguration,\n} from '@backstage/plugin-home';\nimport { useTheme } from '@mui/material/styles';\nimport GlobalStyles from '@mui/material/GlobalStyles';\nimport { HomePageCardConfig } from '../../types';\n\nimport 'react-grid-layout/css/styles.css';\nimport { isCardADefaultConfiguration } from '../utils';\n\n/**\n * Props for the customizable grid layout.\n * @alpha\n */\nexport interface CustomizableGridLayoutProps {\n homepageCards: HomePageCardConfig[];\n}\n\n/**\n * Customizable grid layout for the NFS home page (drag, drop, resize).\n *\n * @alpha\n */\nexport const CustomizableGridLayout = ({\n homepageCards,\n}: CustomizableGridLayoutProps) => {\n const theme = useTheme();\n\n const config = useMemo(() => {\n const defaultConfig: LayoutConfiguration[] = [];\n\n homepageCards.forEach(homepageCard => {\n if (!homepageCard.node) {\n return;\n }\n\n if (isCardADefaultConfiguration(homepageCard)) {\n const layout = homepageCard.breakpointLayouts?.xl || {};\n\n defaultConfig.push({\n component: homepageCard.component,\n x: layout.x ?? 0,\n y: layout.y ?? 0,\n width: layout.w ?? 12,\n height: layout.h ?? 4,\n movable: true,\n deletable: true,\n resizable: true,\n });\n }\n });\n\n return defaultConfig;\n }, [homepageCards]);\n\n return (\n <>\n <GlobalStyles\n styles={{\n '[class*=\"makeStyles-settingsOverlay\"]': {\n backgroundColor:\n theme.palette.mode === 'dark'\n ? 'rgba(20, 20, 20, 0.95) !important'\n : 'rgba(40, 40, 40, 0.93) !important',\n },\n }}\n />\n <CustomHomepageGrid\n
|
|
1
|
+
{"version":3,"file":"CustomizableGridLayout.esm.js","sources":["../../../src/alpha/components/CustomizableGridLayout.tsx"],"sourcesContent":["/*\n * Copyright Red Hat, Inc.\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// This complete read-only home page grid picks up the idea and styles from\n// https://github.com/backstage/backstage/blob/master/plugins/home\n// Esp. from the CustomHomepageGrid component:\n// https://github.com/backstage/backstage/blob/master/plugins/home/src/components/CustomHomepage/CustomHomepageGrid.tsx\n// but without the drag and drop functionality.\n\nimport { Fragment, useMemo, useRef } from 'react';\n\nimport {\n CustomHomepageGrid,\n LayoutConfiguration,\n} from '@backstage/plugin-home';\nimport { useTheme } from '@mui/material/styles';\nimport GlobalStyles from '@mui/material/GlobalStyles';\nimport { HomePageCardConfig } from '../../types';\nimport { useContainerQuery } from '../../hooks/useContainerQuery';\n\nimport 'react-grid-layout/css/styles.css';\nimport { isCardADefaultConfiguration } from '../utils';\n\n/**\n * Props for the customizable grid layout.\n * @alpha\n */\nexport interface CustomizableGridLayoutProps {\n homepageCards: HomePageCardConfig[];\n}\n\n/**\n * Customizable grid layout for the NFS home page (drag, drop, resize).\n *\n * @alpha\n */\nexport const CustomizableGridLayout = ({\n homepageCards,\n}: CustomizableGridLayoutProps) => {\n const theme = useTheme();\n const gridContainerRef = useRef<HTMLDivElement>(null);\n useContainerQuery(gridContainerRef, { notifyWindowResize: true });\n\n const config = useMemo(() => {\n const defaultConfig: LayoutConfiguration[] = [];\n\n homepageCards.forEach(homepageCard => {\n if (!homepageCard.node) {\n return;\n }\n\n if (isCardADefaultConfiguration(homepageCard)) {\n const layout = homepageCard.breakpointLayouts?.xl || {};\n\n defaultConfig.push({\n component: homepageCard.component,\n x: layout.x ?? 0,\n y: layout.y ?? 0,\n width: layout.w ?? 12,\n height: layout.h ?? 4,\n movable: true,\n deletable: true,\n resizable: true,\n });\n }\n });\n\n return defaultConfig;\n }, [homepageCards]);\n\n return (\n <>\n <GlobalStyles\n styles={{\n '[class*=\"makeStyles-settingsOverlay\"]': {\n backgroundColor:\n theme.palette.mode === 'dark'\n ? 'rgba(20, 20, 20, 0.95) !important'\n : 'rgba(40, 40, 40, 0.93) !important',\n },\n }}\n />\n <div\n ref={gridContainerRef}\n style={{ width: '100%', minWidth: 0, boxSizing: 'border-box' }}\n >\n <CustomHomepageGrid\n config={config}\n preventCollision={false}\n compactType=\"vertical\"\n style={{ margin: '-10px' }}\n >\n {homepageCards.map((card, index) => (\n <Fragment key={card.name ?? index}>{card.component}</Fragment>\n ))}\n </CustomHomepageGrid>\n </div>\n </>\n );\n};\n"],"names":["Fragment"],"mappings":";;;;;;;;;AAiDO,MAAM,yBAAyB,CAAC;AAAA,EACrC;AACF,CAAmC,KAAA;AACjC,EAAA,MAAM,QAAQ,QAAS,EAAA;AACvB,EAAM,MAAA,gBAAA,GAAmB,OAAuB,IAAI,CAAA;AACpD,EAAA,iBAAA,CAAkB,gBAAkB,EAAA,EAAE,kBAAoB,EAAA,IAAA,EAAM,CAAA;AAEhE,EAAM,MAAA,MAAA,GAAS,QAAQ,MAAM;AAC3B,IAAA,MAAM,gBAAuC,EAAC;AAE9C,IAAA,aAAA,CAAc,QAAQ,CAAgB,YAAA,KAAA;AACpC,MAAI,IAAA,CAAC,aAAa,IAAM,EAAA;AACtB,QAAA;AAAA;AAGF,MAAI,IAAA,2BAAA,CAA4B,YAAY,CAAG,EAAA;AAC7C,QAAA,MAAM,MAAS,GAAA,YAAA,CAAa,iBAAmB,EAAA,EAAA,IAAM,EAAC;AAEtD,QAAA,aAAA,CAAc,IAAK,CAAA;AAAA,UACjB,WAAW,YAAa,CAAA,SAAA;AAAA,UACxB,CAAA,EAAG,OAAO,CAAK,IAAA,CAAA;AAAA,UACf,CAAA,EAAG,OAAO,CAAK,IAAA,CAAA;AAAA,UACf,KAAA,EAAO,OAAO,CAAK,IAAA,EAAA;AAAA,UACnB,MAAA,EAAQ,OAAO,CAAK,IAAA,CAAA;AAAA,UACpB,OAAS,EAAA,IAAA;AAAA,UACT,SAAW,EAAA,IAAA;AAAA,UACX,SAAW,EAAA;AAAA,SACZ,CAAA;AAAA;AACH,KACD,CAAA;AAED,IAAO,OAAA,aAAA;AAAA,GACT,EAAG,CAAC,aAAa,CAAC,CAAA;AAElB,EAAA,uBAEI,IAAA,CAAA,QAAA,EAAA,EAAA,QAAA,EAAA;AAAA,oBAAA,GAAA;AAAA,MAAC,YAAA;AAAA,MAAA;AAAA,QACC,MAAQ,EAAA;AAAA,UACN,uCAAyC,EAAA;AAAA,YACvC,eACE,EAAA,KAAA,CAAM,OAAQ,CAAA,IAAA,KAAS,SACnB,mCACA,GAAA;AAAA;AACR;AACF;AAAA,KACF;AAAA,oBACA,GAAA;AAAA,MAAC,KAAA;AAAA,MAAA;AAAA,QACC,GAAK,EAAA,gBAAA;AAAA,QACL,OAAO,EAAE,KAAA,EAAO,QAAQ,QAAU,EAAA,CAAA,EAAG,WAAW,YAAa,EAAA;AAAA,QAE7D,QAAA,kBAAA,GAAA;AAAA,UAAC,kBAAA;AAAA,UAAA;AAAA,YACC,MAAA;AAAA,YACA,gBAAkB,EAAA,KAAA;AAAA,YAClB,WAAY,EAAA,UAAA;AAAA,YACZ,KAAA,EAAO,EAAE,MAAA,EAAQ,OAAQ,EAAA;AAAA,YAExB,QAAc,EAAA,aAAA,CAAA,GAAA,CAAI,CAAC,IAAA,EAAM,KACxB,qBAAA,GAAA,CAACA,UAAA,EAAA,EAAmC,QAAK,EAAA,IAAA,CAAA,SAAA,EAAA,EAA1B,IAAK,CAAA,IAAA,IAAQ,KAAuB,CACpD;AAAA;AAAA;AACH;AAAA;AACF,GACF,EAAA,CAAA;AAEJ;;;;"}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import { ApiBlueprint, discoveryApiRef, configApiRef, identityApiRef } from '@backstage/frontend-plugin-api';
|
|
1
|
+
import { ApiBlueprint, discoveryApiRef, configApiRef, identityApiRef, fetchApiRef } from '@backstage/frontend-plugin-api';
|
|
2
|
+
import { defaultWidgetsApiRef, DefaultWidgetsApiClient } from '../../api/DefaultWidgetsApiClient.esm.js';
|
|
2
3
|
import { quickAccessApiRef, QuickAccessApiClient } from '../../api/QuickAccessApiClient.esm.js';
|
|
3
4
|
|
|
4
5
|
const quickAccessApi = ApiBlueprint.make({
|
|
@@ -14,6 +15,18 @@ const quickAccessApi = ApiBlueprint.make({
|
|
|
14
15
|
factory: ({ discoveryApi, configApi, identityApi }) => new QuickAccessApiClient({ discoveryApi, configApi, identityApi })
|
|
15
16
|
})
|
|
16
17
|
});
|
|
18
|
+
const defaultWidgetsApi = ApiBlueprint.make({
|
|
19
|
+
name: "default-widgets",
|
|
20
|
+
disabled: false,
|
|
21
|
+
params: (defineParams) => defineParams({
|
|
22
|
+
api: defaultWidgetsApiRef,
|
|
23
|
+
deps: {
|
|
24
|
+
discoveryApi: discoveryApiRef,
|
|
25
|
+
fetchApi: fetchApiRef
|
|
26
|
+
},
|
|
27
|
+
factory: ({ discoveryApi, fetchApi }) => new DefaultWidgetsApiClient({ discoveryApi, fetchApi })
|
|
28
|
+
})
|
|
29
|
+
});
|
|
17
30
|
|
|
18
|
-
export { quickAccessApi };
|
|
31
|
+
export { defaultWidgetsApi, quickAccessApi };
|
|
19
32
|
//# sourceMappingURL=apis.esm.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"apis.esm.js","sources":["../../../src/alpha/extensions/apis.ts"],"sourcesContent":["/*\n * Copyright Red Hat, Inc.\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 ApiBlueprint,\n configApiRef,\n discoveryApiRef,\n identityApiRef,\n} from '@backstage/frontend-plugin-api';\nimport {
|
|
1
|
+
{"version":3,"file":"apis.esm.js","sources":["../../../src/alpha/extensions/apis.ts"],"sourcesContent":["/*\n * Copyright Red Hat, Inc.\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 ApiBlueprint,\n configApiRef,\n discoveryApiRef,\n fetchApiRef,\n identityApiRef,\n} from '@backstage/frontend-plugin-api';\nimport {\n DefaultWidgetsApiClient,\n defaultWidgetsApiRef,\n QuickAccessApiClient,\n quickAccessApiRef,\n} from '../../api';\n\n/**\n * Quick access API for the New Frontend System.\n * Provides access to quick access links from app config.\n *\n * @alpha\n */\nconst quickAccessApi = ApiBlueprint.make({\n name: 'quickaccess',\n disabled: false,\n params: defineParams =>\n defineParams({\n api: quickAccessApiRef,\n deps: {\n discoveryApi: discoveryApiRef,\n configApi: configApiRef,\n identityApi: identityApiRef,\n },\n factory: ({ discoveryApi, configApi, identityApi }) =>\n new QuickAccessApiClient({ discoveryApi, configApi, identityApi }),\n }),\n});\n\n/**\n * Default cards API for the New Frontend System.\n * Provides access to permission-filtered homepage cards from the backend.\n *\n * @alpha\n */\nconst defaultWidgetsApi = ApiBlueprint.make({\n name: 'default-widgets',\n disabled: false,\n params: defineParams =>\n defineParams({\n api: defaultWidgetsApiRef,\n deps: {\n discoveryApi: discoveryApiRef,\n fetchApi: fetchApiRef,\n },\n factory: ({ discoveryApi, fetchApi }) =>\n new DefaultWidgetsApiClient({ discoveryApi, fetchApi }),\n }),\n});\n\nexport { defaultWidgetsApi, quickAccessApi };\n"],"names":[],"mappings":";;;;AAoCM,MAAA,cAAA,GAAiB,aAAa,IAAK,CAAA;AAAA,EACvC,IAAM,EAAA,aAAA;AAAA,EACN,QAAU,EAAA,KAAA;AAAA,EACV,MAAA,EAAQ,kBACN,YAAa,CAAA;AAAA,IACX,GAAK,EAAA,iBAAA;AAAA,IACL,IAAM,EAAA;AAAA,MACJ,YAAc,EAAA,eAAA;AAAA,MACd,SAAW,EAAA,YAAA;AAAA,MACX,WAAa,EAAA;AAAA,KACf;AAAA,IACA,OAAS,EAAA,CAAC,EAAE,YAAA,EAAc,SAAW,EAAA,WAAA,EACnC,KAAA,IAAI,oBAAqB,CAAA,EAAE,YAAc,EAAA,SAAA,EAAW,aAAa;AAAA,GACpE;AACL,CAAC;AAQK,MAAA,iBAAA,GAAoB,aAAa,IAAK,CAAA;AAAA,EAC1C,IAAM,EAAA,iBAAA;AAAA,EACN,QAAU,EAAA,KAAA;AAAA,EACV,MAAA,EAAQ,kBACN,YAAa,CAAA;AAAA,IACX,GAAK,EAAA,oBAAA;AAAA,IACL,IAAM,EAAA;AAAA,MACJ,YAAc,EAAA,eAAA;AAAA,MACd,QAAU,EAAA;AAAA,KACZ;AAAA,IACA,OAAA,EAAS,CAAC,EAAE,YAAc,EAAA,QAAA,EACxB,KAAA,IAAI,uBAAwB,CAAA,EAAE,YAAc,EAAA,QAAA,EAAU;AAAA,GACzD;AACL,CAAC;;;;"}
|
|
@@ -18,7 +18,7 @@ const defaultCardLayout = {
|
|
|
18
18
|
const onboardingSectionWidget = HomePageWidgetBlueprint.make({
|
|
19
19
|
name: "rhdh-onboarding-section",
|
|
20
20
|
params: {
|
|
21
|
-
name: "
|
|
21
|
+
name: "Red Hat Developer Hub - Onboarding",
|
|
22
22
|
layout: defaultCardLayout,
|
|
23
23
|
components: () => import('../../components/OnboardingSection/index.esm.js').then((m) => ({
|
|
24
24
|
Content: m.OnboardingSection
|
|
@@ -28,7 +28,7 @@ const onboardingSectionWidget = HomePageWidgetBlueprint.make({
|
|
|
28
28
|
const entitySectionWidget = HomePageWidgetBlueprint.make({
|
|
29
29
|
name: "rhdh-entity-section",
|
|
30
30
|
params: {
|
|
31
|
-
name: "
|
|
31
|
+
name: "Red Hat Developer Hub - Software Catalog",
|
|
32
32
|
layout: defaultCardLayout,
|
|
33
33
|
components: () => import('../../components/EntitySection/index.esm.js').then((m) => ({
|
|
34
34
|
Content: () => compatWrapper(/* @__PURE__ */ jsx(m.EntitySection, {}))
|
|
@@ -38,7 +38,7 @@ const entitySectionWidget = HomePageWidgetBlueprint.make({
|
|
|
38
38
|
const templateSectionWidget = HomePageWidgetBlueprint.make({
|
|
39
39
|
name: "rhdh-template-section",
|
|
40
40
|
params: {
|
|
41
|
-
name: "
|
|
41
|
+
name: "Red Hat Developer Hub - Explore templates",
|
|
42
42
|
layout: defaultCardLayout,
|
|
43
43
|
components: () => import('../../components/TemplateSection/index.esm.js').then((m) => ({
|
|
44
44
|
Content: m.TemplateSection
|
|
@@ -48,7 +48,7 @@ const templateSectionWidget = HomePageWidgetBlueprint.make({
|
|
|
48
48
|
const quickAccessCardWidget = HomePageWidgetBlueprint.make({
|
|
49
49
|
name: "quick-access-card",
|
|
50
50
|
params: {
|
|
51
|
-
name: "
|
|
51
|
+
name: "Quick Access Card",
|
|
52
52
|
layout: defaultCardLayout,
|
|
53
53
|
components: () => import('../../components/QuickAccessCard.esm.js').then((m) => ({
|
|
54
54
|
Content: () => compatWrapper(/* @__PURE__ */ jsx(m.QuickAccessCard, {}))
|
|
@@ -58,7 +58,7 @@ const quickAccessCardWidget = HomePageWidgetBlueprint.make({
|
|
|
58
58
|
const searchBarWidget = HomePageWidgetBlueprint.make({
|
|
59
59
|
name: "search-bar",
|
|
60
60
|
params: {
|
|
61
|
-
name: "
|
|
61
|
+
name: "Search",
|
|
62
62
|
layout: {
|
|
63
63
|
...defaultCardLayout,
|
|
64
64
|
height: {
|
|
@@ -76,7 +76,7 @@ const searchBarWidget = HomePageWidgetBlueprint.make({
|
|
|
76
76
|
const featuredDocsCardWidget = HomePageWidgetBlueprint.make({
|
|
77
77
|
name: "featured-docs-card",
|
|
78
78
|
params: {
|
|
79
|
-
name: "
|
|
79
|
+
name: "Featured docs",
|
|
80
80
|
layout: defaultCardLayout,
|
|
81
81
|
components: () => import('../../components/FeaturedDocsCard.esm.js').then((m) => ({
|
|
82
82
|
Content: m.FeaturedDocsCard
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"homePageCards.esm.js","sources":["../../../src/alpha/extensions/homePageCards.tsx"],"sourcesContent":["/*\n * Copyright Red Hat, Inc.\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 { HomePageWidgetBlueprint } from '@backstage/plugin-home-react/alpha';\nimport homePlugin from '@backstage/plugin-home/alpha';\nimport { compatWrapper } from '@backstage/core-compat-api';\n\nconst defaultCardLayout = {\n width: {\n minColumns: 4,\n maxColumns: 12,\n defaultColumns: 12,\n },\n height: {\n minRows: 2,\n maxRows: 12,\n defaultRows: 4,\n },\n} as const;\n\n/**\n * NFS widget: OnboardingSection (migrated from mountPoint home.page/cards).\n * @alpha\n */\nexport const onboardingSectionWidget = HomePageWidgetBlueprint.make({\n name: 'rhdh-onboarding-section',\n params: {\n name: '
|
|
1
|
+
{"version":3,"file":"homePageCards.esm.js","sources":["../../../src/alpha/extensions/homePageCards.tsx"],"sourcesContent":["/*\n * Copyright Red Hat, Inc.\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 { HomePageWidgetBlueprint } from '@backstage/plugin-home-react/alpha';\nimport homePlugin from '@backstage/plugin-home/alpha';\nimport { compatWrapper } from '@backstage/core-compat-api';\n\nconst defaultCardLayout = {\n width: {\n minColumns: 4,\n maxColumns: 12,\n defaultColumns: 12,\n },\n height: {\n minRows: 2,\n maxRows: 12,\n defaultRows: 4,\n },\n} as const;\n\n/**\n * NFS widget: OnboardingSection (migrated from mountPoint home.page/cards).\n * @alpha\n */\nexport const onboardingSectionWidget = HomePageWidgetBlueprint.make({\n name: 'rhdh-onboarding-section',\n params: {\n name: 'Red Hat Developer Hub - Onboarding',\n layout: defaultCardLayout,\n components: () =>\n import('../../components/OnboardingSection').then(m => ({\n Content: m.OnboardingSection,\n })),\n },\n});\n\n/**\n * NFS widget: EntitySection (migrated from mountPoint home.page/cards).\n * @alpha\n */\nexport const entitySectionWidget = HomePageWidgetBlueprint.make({\n name: 'rhdh-entity-section',\n params: {\n name: 'Red Hat Developer Hub - Software Catalog',\n layout: defaultCardLayout,\n components: () =>\n import('../../components/EntitySection').then(m => ({\n Content: () => compatWrapper(<m.EntitySection />),\n })),\n },\n});\n\n/**\n * NFS widget: TemplateSection (migrated from mountPoint home.page/cards).\n * @alpha\n */\nexport const templateSectionWidget = HomePageWidgetBlueprint.make({\n name: 'rhdh-template-section',\n params: {\n name: 'Red Hat Developer Hub - Explore templates',\n layout: defaultCardLayout,\n components: () =>\n import('../../components/TemplateSection').then(m => ({\n Content: m.TemplateSection,\n })),\n },\n});\n\n/**\n * NFS widget: QuickAccessCard (migrated from mountPoint home.page/cards).\n * @alpha\n */\nexport const quickAccessCardWidget = HomePageWidgetBlueprint.make({\n name: 'quick-access-card',\n params: {\n name: 'Quick Access Card',\n layout: defaultCardLayout,\n components: () =>\n import('../../components/QuickAccessCard').then(m => ({\n Content: () => compatWrapper(<m.QuickAccessCard />),\n })),\n },\n});\n\n/**\n * NFS widget: SearchBar (migrated from mountPoint home.page/cards).\n * @alpha\n */\nexport const searchBarWidget = HomePageWidgetBlueprint.make({\n name: 'search-bar',\n params: {\n name: 'Search',\n layout: {\n ...defaultCardLayout,\n height: {\n ...defaultCardLayout.height,\n defaultRows: 2,\n minRows: 1,\n maxRows: 1,\n },\n },\n components: () =>\n import('../../components/SearchBar').then(m => ({\n Content: () => compatWrapper(<m.SearchBar />),\n })),\n },\n});\n\n/**\n * NFS widget: FeaturedDocsCard (migrated from mountPoint home.page/cards).\n * @alpha\n */\nexport const featuredDocsCardWidget = HomePageWidgetBlueprint.make({\n name: 'featured-docs-card',\n params: {\n name: 'Featured docs',\n layout: defaultCardLayout,\n components: () =>\n import('../../components/FeaturedDocsCard').then(m => ({\n Content: m.FeaturedDocsCard,\n })),\n },\n});\n\n/**\n * NFS widget: CatalogStarred (migrated from mountPoint home.page/cards).\n * @alpha\n */\nexport const catalogStarredWidget = homePlugin\n .getExtension('home-page-widget:home/starred-entities')\n .override({\n params: {\n name: 'CatalogStarred',\n title: 'Starred catalog entities',\n },\n });\n\n/**\n * Disables the default home plugin toolkit widget.\n * @alpha\n */\nexport const disableToolkit = homePlugin\n .getExtension('home-page-widget:home/toolkit')\n .override({\n disabled: true,\n });\n\n/**\n * NFS widget: RecentlyVisited (migrated from mountPoint home.page/cards).\n * @alpha\n */\nexport const RecentlyVisitedWidget = HomePageWidgetBlueprint.make({\n name: 'recently-visited',\n params: {\n layout: defaultCardLayout,\n name: 'Recently visited',\n components: () =>\n import('@backstage/plugin-home').then(m => ({\n Content: m.HomePageRecentlyVisited,\n })),\n },\n});\n\n/**\n * NFS widget: TopVisited (migrated from mountPoint home.page/cards).\n * @alpha\n */\nexport const TopVisitedWidget = HomePageWidgetBlueprint.make({\n name: 'top-visited',\n params: {\n layout: defaultCardLayout,\n name: 'Top visited',\n components: () =>\n import('@backstage/plugin-home').then(m => ({\n Content: () => <m.HomePageTopVisited />,\n })),\n },\n});\n"],"names":[],"mappings":"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"}
|
package/dist/alpha.d.ts
CHANGED
|
@@ -47,7 +47,7 @@ declare const homepageTranslationRef: _backstage_frontend_plugin_api.Translation
|
|
|
47
47
|
readonly "entities.fetchError": string;
|
|
48
48
|
readonly "entities.emptyDescription": string;
|
|
49
49
|
readonly "entities.register": string;
|
|
50
|
-
readonly "entities.
|
|
50
|
+
readonly "entities.browseTheCatalog": string;
|
|
51
51
|
}>;
|
|
52
52
|
|
|
53
53
|
/**
|
package/dist/alpha.esm.js
CHANGED
|
@@ -3,7 +3,7 @@ import { createFrontendModule } from '@backstage/frontend-plugin-api';
|
|
|
3
3
|
import { onboardingSectionWidget, entitySectionWidget, templateSectionWidget, quickAccessCardWidget, featuredDocsCardWidget, searchBarWidget, TopVisitedWidget, RecentlyVisitedWidget, catalogStarredWidget, disableToolkit } from './alpha/extensions/homePageCards.esm.js';
|
|
4
4
|
import { homepageTranslations } from './translations/index.esm.js';
|
|
5
5
|
import { homePageLayoutExtension } from './alpha/extensions/homePageLayoutExtension.esm.js';
|
|
6
|
-
import { quickAccessApi } from './alpha/extensions/apis.esm.js';
|
|
6
|
+
import { defaultWidgetsApi, quickAccessApi } from './alpha/extensions/apis.esm.js';
|
|
7
7
|
export { homepageTranslationRef } from './translations/ref.esm.js';
|
|
8
8
|
|
|
9
9
|
const homePageModule = createFrontendModule({
|
|
@@ -13,6 +13,7 @@ const homePageModule = createFrontendModule({
|
|
|
13
13
|
onboardingSectionWidget,
|
|
14
14
|
entitySectionWidget,
|
|
15
15
|
templateSectionWidget,
|
|
16
|
+
defaultWidgetsApi,
|
|
16
17
|
quickAccessApi,
|
|
17
18
|
quickAccessCardWidget,
|
|
18
19
|
featuredDocsCardWidget,
|
package/dist/alpha.esm.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"alpha.esm.js","sources":["../src/alpha/index.ts"],"sourcesContent":["/*\n * Copyright Red Hat, Inc.\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 { TranslationBlueprint } from '@backstage/plugin-app-react';\nimport { createFrontendModule } from '@backstage/frontend-plugin-api';\nimport {\n catalogStarredWidget,\n disableToolkit,\n entitySectionWidget,\n featuredDocsCardWidget,\n onboardingSectionWidget,\n quickAccessCardWidget,\n RecentlyVisitedWidget,\n searchBarWidget,\n templateSectionWidget,\n TopVisitedWidget,\n} from './extensions/homePageCards';\nimport { homepageTranslations } from '../translations';\n\nimport { homePageLayoutExtension } from './extensions/homePageLayoutExtension';\nimport { quickAccessApi } from './extensions/apis';\n\n/**\n * Frontend module for the Dynamic Home Page plugin (New Frontend System).\n *\n * Extends the `home` plugin with a custom layout and RHDH widgets: Onboarding,\n * Entity Catalog, Templates, Quick Access, Search, Recently Visited, Top Visited, etc.\n * Add to your app's `createApp({ features: [..., homePageDevModule] })`.\n *\n * @alpha\n */\nexport const homePageModule = createFrontendModule({\n pluginId: 'home',\n extensions: [\n homePageLayoutExtension,\n onboardingSectionWidget,\n entitySectionWidget,\n templateSectionWidget,\n quickAccessApi,\n quickAccessCardWidget,\n featuredDocsCardWidget,\n searchBarWidget,\n TopVisitedWidget,\n RecentlyVisitedWidget,\n catalogStarredWidget,\n disableToolkit,\n ],\n});\n\n/**\n * Translation module for the Dynamic Home Page plugin.\n *\n * @alpha\n */\nexport const homepageTranslationsModule = createFrontendModule({\n pluginId: 'app',\n extensions: [\n TranslationBlueprint.make({\n name: 'homepage-translations',\n params: {\n resource: homepageTranslations,\n },\n }),\n ],\n});\n\n/**\n *\n * @alpha\n */\nexport { homepageTranslationRef, homepageTranslations } from '../translations';\n"],"names":[],"mappings":";;;;;;;;AA4CO,MAAM,iBAAiB,oBAAqB,CAAA;AAAA,EACjD,QAAU,EAAA,MAAA;AAAA,EACV,UAAY,EAAA;AAAA,IACV,uBAAA;AAAA,IACA,uBAAA;AAAA,IACA,mBAAA;AAAA,IACA,qBAAA;AAAA,IACA,cAAA;AAAA,IACA,qBAAA;AAAA,IACA,sBAAA;AAAA,IACA,eAAA;AAAA,IACA,gBAAA;AAAA,IACA,qBAAA;AAAA,IACA,oBAAA;AAAA,IACA;AAAA;AAEJ,CAAC;AAOM,MAAM,6BAA6B,oBAAqB,CAAA;AAAA,EAC7D,QAAU,EAAA,KAAA;AAAA,EACV,UAAY,EAAA;AAAA,IACV,qBAAqB,IAAK,CAAA;AAAA,MACxB,IAAM,EAAA,uBAAA;AAAA,MACN,MAAQ,EAAA;AAAA,QACN,QAAU,EAAA;AAAA;AACZ,KACD;AAAA;AAEL,CAAC;;;;"}
|
|
1
|
+
{"version":3,"file":"alpha.esm.js","sources":["../src/alpha/index.ts"],"sourcesContent":["/*\n * Copyright Red Hat, Inc.\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 { TranslationBlueprint } from '@backstage/plugin-app-react';\nimport { createFrontendModule } from '@backstage/frontend-plugin-api';\nimport {\n catalogStarredWidget,\n disableToolkit,\n entitySectionWidget,\n featuredDocsCardWidget,\n onboardingSectionWidget,\n quickAccessCardWidget,\n RecentlyVisitedWidget,\n searchBarWidget,\n templateSectionWidget,\n TopVisitedWidget,\n} from './extensions/homePageCards';\nimport { homepageTranslations } from '../translations';\n\nimport { homePageLayoutExtension } from './extensions/homePageLayoutExtension';\nimport { defaultWidgetsApi, quickAccessApi } from './extensions/apis';\n\n/**\n * Frontend module for the Dynamic Home Page plugin (New Frontend System).\n *\n * Extends the `home` plugin with a custom layout and RHDH widgets: Onboarding,\n * Entity Catalog, Templates, Quick Access, Search, Recently Visited, Top Visited, etc.\n * Add to your app's `createApp({ features: [..., homePageDevModule] })`.\n *\n * @alpha\n */\nexport const homePageModule = createFrontendModule({\n pluginId: 'home',\n extensions: [\n homePageLayoutExtension,\n onboardingSectionWidget,\n entitySectionWidget,\n templateSectionWidget,\n defaultWidgetsApi,\n quickAccessApi,\n quickAccessCardWidget,\n featuredDocsCardWidget,\n searchBarWidget,\n TopVisitedWidget,\n RecentlyVisitedWidget,\n catalogStarredWidget,\n disableToolkit,\n ],\n});\n\n/**\n * Translation module for the Dynamic Home Page plugin.\n *\n * @alpha\n */\nexport const homepageTranslationsModule = createFrontendModule({\n pluginId: 'app',\n extensions: [\n TranslationBlueprint.make({\n name: 'homepage-translations',\n params: {\n resource: homepageTranslations,\n },\n }),\n ],\n});\n\n/**\n *\n * @alpha\n */\nexport { homepageTranslationRef, homepageTranslations } from '../translations';\n"],"names":[],"mappings":";;;;;;;;AA4CO,MAAM,iBAAiB,oBAAqB,CAAA;AAAA,EACjD,QAAU,EAAA,MAAA;AAAA,EACV,UAAY,EAAA;AAAA,IACV,uBAAA;AAAA,IACA,uBAAA;AAAA,IACA,mBAAA;AAAA,IACA,qBAAA;AAAA,IACA,iBAAA;AAAA,IACA,cAAA;AAAA,IACA,qBAAA;AAAA,IACA,sBAAA;AAAA,IACA,eAAA;AAAA,IACA,gBAAA;AAAA,IACA,qBAAA;AAAA,IACA,oBAAA;AAAA,IACA;AAAA;AAEJ,CAAC;AAOM,MAAM,6BAA6B,oBAAqB,CAAA;AAAA,EAC7D,QAAU,EAAA,KAAA;AAAA,EACV,UAAY,EAAA;AAAA,IACV,qBAAqB,IAAK,CAAA;AAAA,MACxB,IAAM,EAAA,uBAAA;AAAA,MACN,MAAQ,EAAA;AAAA,QACN,QAAU,EAAA;AAAA;AACZ,KACD;AAAA;AAEL,CAAC;;;;"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { createApiRef } from '@backstage/core-plugin-api';
|
|
2
|
+
|
|
3
|
+
const defaultWidgetsApiRef = createApiRef({
|
|
4
|
+
id: "plugin.homepage.default-widgets"
|
|
5
|
+
});
|
|
6
|
+
class DefaultWidgetsApiClient {
|
|
7
|
+
discoveryApi;
|
|
8
|
+
fetchApi;
|
|
9
|
+
constructor(options) {
|
|
10
|
+
this.discoveryApi = options.discoveryApi;
|
|
11
|
+
this.fetchApi = options.fetchApi;
|
|
12
|
+
}
|
|
13
|
+
async getDefaultWidgets() {
|
|
14
|
+
const baseUrl = await this.discoveryApi.getBaseUrl("homepage");
|
|
15
|
+
const response = await this.fetchApi.fetch(`${baseUrl}/default-widgets`);
|
|
16
|
+
if (!response.ok) {
|
|
17
|
+
throw new Error(
|
|
18
|
+
`Failed to fetch default cards, status ${response.status}: ${response.statusText}`
|
|
19
|
+
);
|
|
20
|
+
}
|
|
21
|
+
return await response.json();
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export { DefaultWidgetsApiClient, defaultWidgetsApiRef };
|
|
26
|
+
//# sourceMappingURL=DefaultWidgetsApiClient.esm.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"DefaultWidgetsApiClient.esm.js","sources":["../../src/api/DefaultWidgetsApiClient.ts"],"sourcesContent":["/*\n * Copyright Red Hat, Inc.\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 createApiRef,\n DiscoveryApi,\n FetchApi,\n} from '@backstage/core-plugin-api';\nimport type { DefaultWidgetsResponse } from '@red-hat-developer-hub/backstage-plugin-homepage-common';\n\nexport type {\n DefaultWidgetsResponse,\n VisibleDefaultWidget,\n} from '@red-hat-developer-hub/backstage-plugin-homepage-common';\n\n/**\n * @public\n */\nexport interface DefaultWidgetsApi {\n getDefaultWidgets(): Promise<DefaultWidgetsResponse>;\n}\n\n/**\n * @public\n */\nexport const defaultWidgetsApiRef = createApiRef<DefaultWidgetsApi>({\n id: 'plugin.homepage.default-widgets',\n});\n\n/**\n * @public\n */\nexport class DefaultWidgetsApiClient implements DefaultWidgetsApi {\n private readonly discoveryApi: DiscoveryApi;\n private readonly fetchApi: FetchApi;\n\n constructor(options: { discoveryApi: DiscoveryApi; fetchApi: FetchApi }) {\n this.discoveryApi = options.discoveryApi;\n this.fetchApi = options.fetchApi;\n }\n\n async getDefaultWidgets(): Promise<DefaultWidgetsResponse> {\n const baseUrl = await this.discoveryApi.getBaseUrl('homepage');\n const response = await this.fetchApi.fetch(`${baseUrl}/default-widgets`);\n if (!response.ok) {\n throw new Error(\n `Failed to fetch default cards, status ${response.status}: ${response.statusText}`,\n );\n }\n return await response.json();\n }\n}\n"],"names":[],"mappings":";;AAsCO,MAAM,uBAAuB,YAAgC,CAAA;AAAA,EAClE,EAAI,EAAA;AACN,CAAC;AAKM,MAAM,uBAAqD,CAAA;AAAA,EAC/C,YAAA;AAAA,EACA,QAAA;AAAA,EAEjB,YAAY,OAA6D,EAAA;AACvE,IAAA,IAAA,CAAK,eAAe,OAAQ,CAAA,YAAA;AAC5B,IAAA,IAAA,CAAK,WAAW,OAAQ,CAAA,QAAA;AAAA;AAC1B,EAEA,MAAM,iBAAqD,GAAA;AACzD,IAAA,MAAM,OAAU,GAAA,MAAM,IAAK,CAAA,YAAA,CAAa,WAAW,UAAU,CAAA;AAC7D,IAAA,MAAM,WAAW,MAAM,IAAA,CAAK,SAAS,KAAM,CAAA,CAAA,EAAG,OAAO,CAAkB,gBAAA,CAAA,CAAA;AACvE,IAAI,IAAA,CAAC,SAAS,EAAI,EAAA;AAChB,MAAA,MAAM,IAAI,KAAA;AAAA,QACR,CAAyC,sCAAA,EAAA,QAAA,CAAS,MAAM,CAAA,EAAA,EAAK,SAAS,UAAU,CAAA;AAAA,OAClF;AAAA;AAEF,IAAO,OAAA,MAAM,SAAS,IAAK,EAAA;AAAA;AAE/B;;;;"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
|
|
2
|
-
import { useMemo } from 'react';
|
|
2
|
+
import { useRef, useMemo } from 'react';
|
|
3
3
|
import { CustomHomepageGrid } from '@backstage/plugin-home';
|
|
4
4
|
import { createCardExtension } from '@backstage/plugin-home-react';
|
|
5
5
|
import GlobalStyles from '@mui/material/GlobalStyles';
|
|
@@ -7,11 +7,14 @@ import { useTheme } from '@mui/material/styles';
|
|
|
7
7
|
import 'react-grid-layout/css/styles.css';
|
|
8
8
|
import { dynamicHomePagePlugin } from '../plugin.esm.js';
|
|
9
9
|
import { useTranslation } from '../hooks/useTranslation.esm.js';
|
|
10
|
+
import { useContainerQuery } from '../hooks/useContainerQuery.esm.js';
|
|
10
11
|
import { getCardTitle, getCardDescription, isCardADefaultConfiguration } from '../utils/customizable-cards.esm.js';
|
|
11
12
|
|
|
12
13
|
const CustomizableGrid = ({ mountPoints }) => {
|
|
13
14
|
const theme = useTheme();
|
|
14
15
|
const { t } = useTranslation();
|
|
16
|
+
const gridContainerRef = useRef(null);
|
|
17
|
+
useContainerQuery(gridContainerRef, { notifyWindowResize: true });
|
|
15
18
|
const { children, config } = useMemo(() => {
|
|
16
19
|
const childDictionary = {};
|
|
17
20
|
const defaultConfig = [];
|
|
@@ -77,13 +80,20 @@ const CustomizableGrid = ({ mountPoints }) => {
|
|
|
77
80
|
}
|
|
78
81
|
),
|
|
79
82
|
/* @__PURE__ */ jsx(
|
|
80
|
-
|
|
83
|
+
"div",
|
|
81
84
|
{
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
85
|
+
ref: gridContainerRef,
|
|
86
|
+
style: { width: "100%", minWidth: 0, boxSizing: "border-box" },
|
|
87
|
+
children: /* @__PURE__ */ jsx(
|
|
88
|
+
CustomHomepageGrid,
|
|
89
|
+
{
|
|
90
|
+
config,
|
|
91
|
+
preventCollision: false,
|
|
92
|
+
compactType: "vertical",
|
|
93
|
+
style: { margin: "-10px" },
|
|
94
|
+
children
|
|
95
|
+
}
|
|
96
|
+
)
|
|
87
97
|
}
|
|
88
98
|
)
|
|
89
99
|
] });
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"CustomizableGrid.esm.js","sources":["../../src/components/CustomizableGrid.tsx"],"sourcesContent":["/*\n * Copyright Red Hat, Inc.\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// This complete read-only home page grid picks up the idea and styles from\n// https://github.com/backstage/backstage/blob/master/plugins/home\n// Esp. from the CustomHomepageGrid component:\n// https://github.com/backstage/backstage/blob/master/plugins/home/src/components/CustomHomepage/CustomHomepageGrid.tsx\n// but without the drag and drop functionality.\n\nimport type { ReactElement } from 'react';\nimport { useMemo } from 'react';\n\nimport {\n CustomHomepageGrid,\n LayoutConfiguration,\n} from '@backstage/plugin-home';\nimport {\n ComponentParts,\n createCardExtension,\n} from '@backstage/plugin-home-react';\n\nimport GlobalStyles from '@mui/material/GlobalStyles';\nimport { useTheme } from '@mui/material/styles';\n\n// Removes the doubled scrollbar\nimport 'react-grid-layout/css/styles.css';\n\nimport { HomePageCardMountPoint } from '../types';\nimport { dynamicHomePagePlugin } from '../plugin';\nimport { useTranslation } from '../hooks/useTranslation';\nimport {\n isCardADefaultConfiguration,\n getCardTitle,\n getCardDescription,\n} from '../utils/customizable-cards';\n\n/**\n * @public\n */\nexport interface CustomizableGridProps {\n mountPoints: HomePageCardMountPoint[];\n}\n\n/**\n * @public\n */\nexport const CustomizableGrid = ({ mountPoints }: CustomizableGridProps) => {\n const theme = useTheme();\n const { t } = useTranslation();\n\n const { children, config } = useMemo(() => {\n // Children contains the additional / available cards a user can add.\n // Maps the card name to the actual card component.\n // Contains also the title to allow sorting before rendering.\n const childDictionary: Record<\n string,\n { child: ReactElement; title: string | undefined }\n > = {};\n\n // Config contains the default layout of the homepage\n const defaultConfig: LayoutConfiguration[] = [];\n\n mountPoints.forEach(mountPoint => {\n if (!mountPoint.config?.id) {\n return;\n }\n const id = mountPoint.config.id;\n const title = getCardTitle(t, mountPoint);\n const description = getCardDescription(t, mountPoint);\n\n const automaticallyWrapInInfoCard = false;\n\n const componentParts: ComponentParts = {\n Content: props => (\n <mountPoint.Component {...mountPoint.config!.props} {...props} />\n ),\n // Untested and unsupported for now!\n Actions: mountPoint.Actions as () => JSX.Element,\n // Untested and unsupported for now!\n Settings: mountPoint.Settings as () => JSX.Element,\n // This is a workaround to NOT automatically wrap in an InfoCard\n ContextProvider: automaticallyWrapInInfoCard\n ? undefined\n : props => (\n <mountPoint.Component {...mountPoint.config!.props} {...props} />\n ),\n };\n\n const cardExtension = createCardExtension({\n name: id,\n title,\n description,\n layout: mountPoint.config.cardLayout,\n settings: mountPoint.config.settings,\n components: () => Promise.resolve(componentParts),\n });\n\n const Card = dynamicHomePagePlugin.provide(cardExtension);\n\n childDictionary[id] = {\n child: <Card />,\n title,\n };\n\n if (isCardADefaultConfiguration(mountPoint)) {\n const layout = mountPoint.config?.layouts?.xl || {};\n\n defaultConfig.push({\n component: id,\n x: layout.x ?? 0,\n y: layout.y ?? 0,\n width: layout.w ?? 12,\n height: layout.h ?? 4,\n movable: true,\n deletable: true,\n resizable: true,\n });\n }\n });\n\n return {\n children: Object.values(childDictionary)\n .sort((a, b) =>\n a.title && b.title ? a.title.localeCompare(b.title) : 0,\n )\n .map(e => e.child),\n config: defaultConfig,\n };\n }, [mountPoints, t]);\n\n return (\n <>\n <GlobalStyles\n styles={{\n '[class*=\"makeStyles-settingsOverlay\"]': {\n backgroundColor:\n theme.palette.mode === 'dark'\n ? 'rgba(20, 20, 20, 0.95) !important'\n : 'rgba(40, 40, 40, 0.93) !important',\n },\n }}\n />\n <CustomHomepageGrid\n
|
|
1
|
+
{"version":3,"file":"CustomizableGrid.esm.js","sources":["../../src/components/CustomizableGrid.tsx"],"sourcesContent":["/*\n * Copyright Red Hat, Inc.\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// This complete read-only home page grid picks up the idea and styles from\n// https://github.com/backstage/backstage/blob/master/plugins/home\n// Esp. from the CustomHomepageGrid component:\n// https://github.com/backstage/backstage/blob/master/plugins/home/src/components/CustomHomepage/CustomHomepageGrid.tsx\n// but without the drag and drop functionality.\n\nimport type { ReactElement } from 'react';\nimport { useMemo, useRef } from 'react';\n\nimport {\n CustomHomepageGrid,\n LayoutConfiguration,\n} from '@backstage/plugin-home';\nimport {\n ComponentParts,\n createCardExtension,\n} from '@backstage/plugin-home-react';\n\nimport GlobalStyles from '@mui/material/GlobalStyles';\nimport { useTheme } from '@mui/material/styles';\n\n// Removes the doubled scrollbar\nimport 'react-grid-layout/css/styles.css';\n\nimport { HomePageCardMountPoint } from '../types';\nimport { dynamicHomePagePlugin } from '../plugin';\nimport { useTranslation } from '../hooks/useTranslation';\nimport { useContainerQuery } from '../hooks/useContainerQuery';\nimport {\n isCardADefaultConfiguration,\n getCardTitle,\n getCardDescription,\n} from '../utils/customizable-cards';\n\n/**\n * @public\n */\nexport interface CustomizableGridProps {\n mountPoints: HomePageCardMountPoint[];\n}\n\n/**\n * @public\n */\nexport const CustomizableGrid = ({ mountPoints }: CustomizableGridProps) => {\n const theme = useTheme();\n const { t } = useTranslation();\n const gridContainerRef = useRef<HTMLDivElement>(null);\n useContainerQuery(gridContainerRef, { notifyWindowResize: true });\n\n const { children, config } = useMemo(() => {\n // Children contains the additional / available cards a user can add.\n // Maps the card name to the actual card component.\n // Contains also the title to allow sorting before rendering.\n const childDictionary: Record<\n string,\n { child: ReactElement; title: string | undefined }\n > = {};\n\n // Config contains the default layout of the homepage\n const defaultConfig: LayoutConfiguration[] = [];\n\n mountPoints.forEach(mountPoint => {\n if (!mountPoint.config?.id) {\n return;\n }\n const id = mountPoint.config.id;\n const title = getCardTitle(t, mountPoint);\n const description = getCardDescription(t, mountPoint);\n\n const automaticallyWrapInInfoCard = false;\n\n const componentParts: ComponentParts = {\n Content: props => (\n <mountPoint.Component {...mountPoint.config!.props} {...props} />\n ),\n // Untested and unsupported for now!\n Actions: mountPoint.Actions as () => JSX.Element,\n // Untested and unsupported for now!\n Settings: mountPoint.Settings as () => JSX.Element,\n // This is a workaround to NOT automatically wrap in an InfoCard\n ContextProvider: automaticallyWrapInInfoCard\n ? undefined\n : props => (\n <mountPoint.Component {...mountPoint.config!.props} {...props} />\n ),\n };\n\n const cardExtension = createCardExtension({\n name: id,\n title,\n description,\n layout: mountPoint.config.cardLayout,\n settings: mountPoint.config.settings,\n components: () => Promise.resolve(componentParts),\n });\n\n const Card = dynamicHomePagePlugin.provide(cardExtension);\n\n childDictionary[id] = {\n child: <Card />,\n title,\n };\n\n if (isCardADefaultConfiguration(mountPoint)) {\n const layout = mountPoint.config?.layouts?.xl || {};\n\n defaultConfig.push({\n component: id,\n x: layout.x ?? 0,\n y: layout.y ?? 0,\n width: layout.w ?? 12,\n height: layout.h ?? 4,\n movable: true,\n deletable: true,\n resizable: true,\n });\n }\n });\n\n return {\n children: Object.values(childDictionary)\n .sort((a, b) =>\n a.title && b.title ? a.title.localeCompare(b.title) : 0,\n )\n .map(e => e.child),\n config: defaultConfig,\n };\n }, [mountPoints, t]);\n\n return (\n <>\n <GlobalStyles\n styles={{\n '[class*=\"makeStyles-settingsOverlay\"]': {\n backgroundColor:\n theme.palette.mode === 'dark'\n ? 'rgba(20, 20, 20, 0.95) !important'\n : 'rgba(40, 40, 40, 0.93) !important',\n },\n }}\n />\n <div\n ref={gridContainerRef}\n style={{ width: '100%', minWidth: 0, boxSizing: 'border-box' }}\n >\n <CustomHomepageGrid\n config={config}\n preventCollision={false}\n compactType=\"vertical\"\n style={{ margin: '-10px' }}\n >\n {children}\n </CustomHomepageGrid>\n </div>\n </>\n );\n};\n"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
|
|
2
|
+
import { useRef, useMemo } from 'react';
|
|
3
|
+
import { CustomHomepageGrid } from '@backstage/plugin-home';
|
|
4
|
+
import { createCardExtension } from '@backstage/plugin-home-react';
|
|
5
|
+
import GlobalStyles from '@mui/material/GlobalStyles';
|
|
6
|
+
import { useTheme } from '@mui/material/styles';
|
|
7
|
+
import 'react-grid-layout/css/styles.css';
|
|
8
|
+
import { dynamicHomePagePlugin } from '../plugin.esm.js';
|
|
9
|
+
import { useTranslation } from '../hooks/useTranslation.esm.js';
|
|
10
|
+
import { useContainerQuery } from '../hooks/useContainerQuery.esm.js';
|
|
11
|
+
import { getCardTitle, getCardDescription } from '../utils/customizable-cards.esm.js';
|
|
12
|
+
|
|
13
|
+
const DefaultWidgetsCustomizableGrid = ({
|
|
14
|
+
defaultWidgets,
|
|
15
|
+
mountPoints
|
|
16
|
+
}) => {
|
|
17
|
+
const theme = useTheme();
|
|
18
|
+
const { t } = useTranslation();
|
|
19
|
+
const gridContainerRef = useRef(null);
|
|
20
|
+
useContainerQuery(gridContainerRef, { notifyWindowResize: true });
|
|
21
|
+
const mountPointsById = useMemo(() => {
|
|
22
|
+
const map = /* @__PURE__ */ new Map();
|
|
23
|
+
for (const mp of mountPoints) {
|
|
24
|
+
if (mp.config?.id) {
|
|
25
|
+
map.set(mp.config.id, mp);
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
return map;
|
|
29
|
+
}, [mountPoints]);
|
|
30
|
+
const widgetsToRender = useMemo(() => {
|
|
31
|
+
if (defaultWidgets.length > 0) {
|
|
32
|
+
return defaultWidgets.map((widget, index) => ({
|
|
33
|
+
id: widget.id || `config-widget-${index}`,
|
|
34
|
+
ref: widget.ref,
|
|
35
|
+
layout: widget.layout,
|
|
36
|
+
source: "config"
|
|
37
|
+
}));
|
|
38
|
+
}
|
|
39
|
+
return mountPoints.filter((mp) => mp.config?.id).map((mp) => ({
|
|
40
|
+
id: mp.config.id,
|
|
41
|
+
ref: mp.config.id,
|
|
42
|
+
layout: undefined,
|
|
43
|
+
source: "mountpoint"
|
|
44
|
+
}));
|
|
45
|
+
}, [defaultWidgets, mountPoints]);
|
|
46
|
+
const { children, config } = useMemo(() => {
|
|
47
|
+
const childDictionary = {};
|
|
48
|
+
const defaultConfig = [];
|
|
49
|
+
widgetsToRender.forEach((widget) => {
|
|
50
|
+
const widgetId = widget.id;
|
|
51
|
+
const widgetRef = widget.ref ?? widgetId;
|
|
52
|
+
if (!widgetId || !widgetRef) {
|
|
53
|
+
console.warn(
|
|
54
|
+
`Widget missing id or ref (id: ${String(widget.id)}, ref: ${String(widget.ref)}).`
|
|
55
|
+
);
|
|
56
|
+
return;
|
|
57
|
+
}
|
|
58
|
+
const mountPoint = mountPointsById.get(widgetRef);
|
|
59
|
+
if (!mountPoint || !mountPoint.config?.id) {
|
|
60
|
+
console.warn(
|
|
61
|
+
`No mount point found for widget ref ${widgetRef}. Available mount points: ${[...mountPointsById.keys()].join(", ")}`
|
|
62
|
+
);
|
|
63
|
+
return;
|
|
64
|
+
}
|
|
65
|
+
const title = getCardTitle(t, mountPoint);
|
|
66
|
+
const description = getCardDescription(t, mountPoint);
|
|
67
|
+
const componentParts = {
|
|
68
|
+
Content: (props) => /* @__PURE__ */ jsx(mountPoint.Component, { ...mountPoint.config.props, ...props }),
|
|
69
|
+
Actions: mountPoint.Actions,
|
|
70
|
+
Settings: mountPoint.Settings,
|
|
71
|
+
ContextProvider: (props) => /* @__PURE__ */ jsx(mountPoint.Component, { ...mountPoint.config.props, ...props })
|
|
72
|
+
};
|
|
73
|
+
const cardExtension = createCardExtension({
|
|
74
|
+
name: widgetId,
|
|
75
|
+
title,
|
|
76
|
+
description,
|
|
77
|
+
layout: mountPoint.config.cardLayout,
|
|
78
|
+
settings: mountPoint.config.settings,
|
|
79
|
+
components: () => Promise.resolve(componentParts)
|
|
80
|
+
});
|
|
81
|
+
const Card = dynamicHomePagePlugin.provide(cardExtension);
|
|
82
|
+
childDictionary[widgetId] = {
|
|
83
|
+
child: /* @__PURE__ */ jsx(Card, {}),
|
|
84
|
+
title
|
|
85
|
+
};
|
|
86
|
+
const widgetLayout = widget.layout;
|
|
87
|
+
const layout = widgetLayout?.xl ?? {};
|
|
88
|
+
defaultConfig.push({
|
|
89
|
+
component: widgetId,
|
|
90
|
+
x: layout.x ?? 0,
|
|
91
|
+
y: layout.y ?? 0,
|
|
92
|
+
width: layout.w ?? 12,
|
|
93
|
+
height: layout.h ?? 4,
|
|
94
|
+
movable: true,
|
|
95
|
+
deletable: true,
|
|
96
|
+
resizable: true
|
|
97
|
+
});
|
|
98
|
+
});
|
|
99
|
+
return {
|
|
100
|
+
children: Object.values(childDictionary).sort(
|
|
101
|
+
(a, b) => a.title && b.title ? a.title.localeCompare(b.title) : 0
|
|
102
|
+
).map((e) => e.child),
|
|
103
|
+
config: defaultConfig
|
|
104
|
+
};
|
|
105
|
+
}, [widgetsToRender, mountPointsById, t]);
|
|
106
|
+
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
107
|
+
/* @__PURE__ */ jsx(
|
|
108
|
+
GlobalStyles,
|
|
109
|
+
{
|
|
110
|
+
styles: {
|
|
111
|
+
'[class*="makeStyles-settingsOverlay"]': {
|
|
112
|
+
backgroundColor: theme.palette.mode === "dark" ? "rgba(20, 20, 20, 0.95) !important" : "rgba(40, 40, 40, 0.93) !important"
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
),
|
|
117
|
+
/* @__PURE__ */ jsx(
|
|
118
|
+
"div",
|
|
119
|
+
{
|
|
120
|
+
ref: gridContainerRef,
|
|
121
|
+
style: { width: "100%", minWidth: 0, boxSizing: "border-box" },
|
|
122
|
+
children: /* @__PURE__ */ jsx(
|
|
123
|
+
CustomHomepageGrid,
|
|
124
|
+
{
|
|
125
|
+
config,
|
|
126
|
+
preventCollision: false,
|
|
127
|
+
compactType: "vertical",
|
|
128
|
+
style: { margin: "-10px" },
|
|
129
|
+
children
|
|
130
|
+
}
|
|
131
|
+
)
|
|
132
|
+
}
|
|
133
|
+
)
|
|
134
|
+
] });
|
|
135
|
+
};
|
|
136
|
+
|
|
137
|
+
export { DefaultWidgetsCustomizableGrid };
|
|
138
|
+
//# sourceMappingURL=DefaultWidgetsCustomizableGrid.esm.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"DefaultWidgetsCustomizableGrid.esm.js","sources":["../../src/components/DefaultWidgetsCustomizableGrid.tsx"],"sourcesContent":["/*\n * Copyright Red Hat, Inc.\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 type { ReactElement } from 'react';\nimport { useMemo, useRef } from 'react';\n\nimport {\n CustomHomepageGrid,\n LayoutConfiguration,\n} from '@backstage/plugin-home';\nimport {\n ComponentParts,\n createCardExtension,\n} from '@backstage/plugin-home-react';\n\nimport GlobalStyles from '@mui/material/GlobalStyles';\nimport { useTheme } from '@mui/material/styles';\n\nimport 'react-grid-layout/css/styles.css';\n\nimport type { VisibleDefaultWidget } from '../api/DefaultWidgetsApiClient';\nimport { HomePageCardMountPoint } from '../types';\nimport { dynamicHomePagePlugin } from '../plugin';\nimport { useTranslation } from '../hooks/useTranslation';\nimport { useContainerQuery } from '../hooks/useContainerQuery';\nimport { getCardTitle, getCardDescription } from '../utils/customizable-cards';\n\nexport interface DefaultWidgetsCustomizableGridProps {\n defaultWidgets: VisibleDefaultWidget[];\n mountPoints: HomePageCardMountPoint[];\n}\n\nexport const DefaultWidgetsCustomizableGrid = ({\n defaultWidgets,\n mountPoints,\n}: DefaultWidgetsCustomizableGridProps) => {\n const theme = useTheme();\n const { t } = useTranslation();\n const gridContainerRef = useRef<HTMLDivElement>(null);\n useContainerQuery(gridContainerRef, { notifyWindowResize: true });\n\n const mountPointsById = useMemo(() => {\n const map = new Map<string, HomePageCardMountPoint>();\n for (const mp of mountPoints) {\n if (mp.config?.id) {\n map.set(mp.config.id, mp);\n }\n }\n return map;\n }, [mountPoints]);\n\n const widgetsToRender = useMemo(() => {\n // If config exists, use it exclusively; otherwise fall back to mount points\n if (defaultWidgets.length > 0) {\n return defaultWidgets.map((widget, index) => ({\n id: widget.id || `config-widget-${index}`,\n ref: widget.ref,\n layout: widget.layout,\n source: 'config' as const,\n }));\n }\n\n // Fallback: render all mount points\n return mountPoints\n .filter(mp => mp.config?.id)\n .map(mp => ({\n id: mp.config!.id,\n ref: mp.config!.id,\n layout: undefined,\n source: 'mountpoint' as const,\n }));\n }, [defaultWidgets, mountPoints]);\n\n const { children, config } = useMemo(() => {\n const childDictionary: Record<\n string,\n { child: ReactElement; title: string | undefined }\n > = {};\n const defaultConfig: LayoutConfiguration[] = [];\n\n widgetsToRender.forEach(widget => {\n const widgetId = widget.id;\n const widgetRef = widget.ref ?? widgetId;\n if (!widgetId || !widgetRef) {\n // eslint-disable-next-line no-console\n console.warn(\n `Widget missing id or ref (id: ${String(widget.id)}, ref: ${String(widget.ref)}).`,\n );\n return;\n }\n\n const mountPoint = mountPointsById.get(widgetRef);\n\n if (!mountPoint || !mountPoint.config?.id) {\n // eslint-disable-next-line no-console\n console.warn(\n `No mount point found for widget ref ${widgetRef}. Available mount points: ${[...mountPointsById.keys()].join(', ')}`,\n );\n return;\n }\n\n const title = getCardTitle(t, mountPoint);\n const description = getCardDescription(t, mountPoint);\n\n const automaticallyWrapInInfoCard = false;\n\n const componentParts: ComponentParts = {\n Content: props => (\n <mountPoint.Component {...mountPoint.config!.props} {...props} />\n ),\n Actions: mountPoint.Actions as () => JSX.Element,\n Settings: mountPoint.Settings as () => JSX.Element,\n ContextProvider: automaticallyWrapInInfoCard\n ? undefined\n : props => (\n <mountPoint.Component {...mountPoint.config!.props} {...props} />\n ),\n };\n\n const cardExtension = createCardExtension({\n name: widgetId,\n title,\n description,\n layout: mountPoint.config.cardLayout,\n settings: mountPoint.config.settings,\n components: () => Promise.resolve(componentParts),\n });\n\n const Card = dynamicHomePagePlugin.provide(cardExtension);\n\n childDictionary[widgetId] = {\n child: <Card />,\n title,\n };\n\n const widgetLayout = widget.layout as\n | Record<string, { x?: number; y?: number; w?: number; h?: number }>\n | undefined;\n const layout = widgetLayout?.xl ?? {};\n\n defaultConfig.push({\n component: widgetId,\n x: layout.x ?? 0,\n y: layout.y ?? 0,\n width: layout.w ?? 12,\n height: layout.h ?? 4,\n movable: true,\n deletable: true,\n resizable: true,\n });\n });\n\n return {\n children: Object.values(childDictionary)\n .sort((a, b) =>\n a.title && b.title ? a.title.localeCompare(b.title) : 0,\n )\n .map(e => e.child),\n config: defaultConfig,\n };\n }, [widgetsToRender, mountPointsById, t]);\n\n return (\n <>\n <GlobalStyles\n styles={{\n '[class*=\"makeStyles-settingsOverlay\"]': {\n backgroundColor:\n theme.palette.mode === 'dark'\n ? 'rgba(20, 20, 20, 0.95) !important'\n : 'rgba(40, 40, 40, 0.93) !important',\n },\n }}\n />\n <div\n ref={gridContainerRef}\n style={{ width: '100%', minWidth: 0, boxSizing: 'border-box' }}\n >\n <CustomHomepageGrid\n config={config}\n preventCollision={false}\n compactType=\"vertical\"\n style={{ margin: '-10px' }}\n >\n {children}\n </CustomHomepageGrid>\n </div>\n </>\n );\n};\n"],"names":[],"mappings":"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"}
|