@red-hat-developer-hub/backstage-plugin-dynamic-home-page 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +7 -0
- package/README.md +5 -0
- package/app-config.dynamic.yaml +38 -0
- package/dist/api/QuickAccessApiClient.esm.js +43 -0
- package/dist/api/QuickAccessApiClient.esm.js.map +1 -0
- package/dist/components/DynamicHomePage.esm.js +30 -0
- package/dist/components/DynamicHomePage.esm.js.map +1 -0
- package/dist/components/Headline.esm.js +8 -0
- package/dist/components/Headline.esm.js.map +1 -0
- package/dist/components/Markdown.esm.js +30 -0
- package/dist/components/Markdown.esm.js.map +1 -0
- package/dist/components/MarkdownCard.esm.js +9 -0
- package/dist/components/MarkdownCard.esm.js.map +1 -0
- package/dist/components/Placeholder.esm.js +28 -0
- package/dist/components/Placeholder.esm.js.map +1 -0
- package/dist/components/QuickAccessCard.esm.js +72 -0
- package/dist/components/QuickAccessCard.esm.js.map +1 -0
- package/dist/components/ReadOnlyGrid.esm.js +129 -0
- package/dist/components/ReadOnlyGrid.esm.js.map +1 -0
- package/dist/components/SearchBar.esm.js +56 -0
- package/dist/components/SearchBar.esm.js.map +1 -0
- package/dist/hooks/useHomePageMountPoints.esm.js +10 -0
- package/dist/hooks/useHomePageMountPoints.esm.js.map +1 -0
- package/dist/hooks/useQuickAccessLinks.esm.js +40 -0
- package/dist/hooks/useQuickAccessLinks.esm.js.map +1 -0
- package/dist/index.d.ts +119 -0
- package/dist/index.esm.js +2 -0
- package/dist/index.esm.js.map +1 -0
- package/dist/plugin.esm.js +119 -0
- package/dist/plugin.esm.js.map +1 -0
- package/dist/routes.esm.js +8 -0
- package/dist/routes.esm.js.map +1 -0
- package/package.json +73 -0
package/CHANGELOG.md
ADDED
package/README.md
ADDED
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
# Dynamic Home Page plugin
|
|
2
|
+
|
|
3
|
+
This is a dynamic version of the upstream [home page plugin](https://github.com/backstage/backstage/tree/master/plugins/home).
|
|
4
|
+
|
|
5
|
+
Instead of manually adding supported "home page cards" to a custom route, it allows dynamic plugins to expose such cards.
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
# please keep this in sync with packages/app/src/App.tsx
|
|
2
|
+
dynamicPlugins:
|
|
3
|
+
frontend:
|
|
4
|
+
janus-idp.backstage-plugin-dynamic-home-page:
|
|
5
|
+
dynamicRoutes:
|
|
6
|
+
- path: /
|
|
7
|
+
importName: DynamicHomePage
|
|
8
|
+
mountPoints:
|
|
9
|
+
- mountPoint: home.page/cards
|
|
10
|
+
importName: SearchBar
|
|
11
|
+
config:
|
|
12
|
+
layouts:
|
|
13
|
+
xl: { w: 10, h: 1, x: 1 }
|
|
14
|
+
lg: { w: 10, h: 1, x: 1 }
|
|
15
|
+
md: { w: 10, h: 1, x: 1 }
|
|
16
|
+
sm: { w: 10, h: 1, x: 1 }
|
|
17
|
+
xs: { w: 12, h: 1 }
|
|
18
|
+
xxs: { w: 12, h: 1 }
|
|
19
|
+
- mountPoint: home.page/cards
|
|
20
|
+
importName: QuickAccessCard
|
|
21
|
+
config:
|
|
22
|
+
layouts:
|
|
23
|
+
xl: { w: 7, h: 8 }
|
|
24
|
+
lg: { w: 7, h: 8 }
|
|
25
|
+
md: { w: 7, h: 8 }
|
|
26
|
+
sm: { w: 12, h: 8 }
|
|
27
|
+
xs: { w: 12, h: 8 }
|
|
28
|
+
xxs: { w: 12, h: 8 }
|
|
29
|
+
- mountPoint: home.page/cards
|
|
30
|
+
importName: CatalogStarredEntitiesCard
|
|
31
|
+
config:
|
|
32
|
+
layouts:
|
|
33
|
+
xl: { w: 5, h: 4, x: 7 }
|
|
34
|
+
lg: { w: 5, h: 4, x: 7 }
|
|
35
|
+
md: { w: 5, h: 4, x: 7 }
|
|
36
|
+
sm: { w: 12, h: 4 }
|
|
37
|
+
xs: { w: 12, h: 4 }
|
|
38
|
+
xxs: { w: 12, h: 4 }
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { createApiRef } from '@backstage/core-plugin-api';
|
|
2
|
+
|
|
3
|
+
const DEFAULT_PROXY_PATH = "/developer-hub";
|
|
4
|
+
const quickAccessApiRef = createApiRef({
|
|
5
|
+
id: "app.developer-hub.quick-access.service"
|
|
6
|
+
});
|
|
7
|
+
class QuickAccessApiClient {
|
|
8
|
+
discoveryApi;
|
|
9
|
+
configApi;
|
|
10
|
+
identityApi;
|
|
11
|
+
constructor(options) {
|
|
12
|
+
this.discoveryApi = options.discoveryApi;
|
|
13
|
+
this.configApi = options.configApi;
|
|
14
|
+
this.identityApi = options.identityApi;
|
|
15
|
+
}
|
|
16
|
+
async getBaseUrl() {
|
|
17
|
+
const proxyPath = this.configApi.getOptionalString("developerHub.proxyPath") ?? DEFAULT_PROXY_PATH;
|
|
18
|
+
return `${await this.discoveryApi.getBaseUrl("proxy")}${proxyPath}`;
|
|
19
|
+
}
|
|
20
|
+
async fetcher(url) {
|
|
21
|
+
const { token: idToken } = await this.identityApi.getCredentials();
|
|
22
|
+
const response = await fetch(url, {
|
|
23
|
+
headers: {
|
|
24
|
+
"Content-Type": "application/json",
|
|
25
|
+
...idToken && { Authorization: `Bearer ${idToken}` }
|
|
26
|
+
}
|
|
27
|
+
});
|
|
28
|
+
if (!response.ok) {
|
|
29
|
+
throw new Error(
|
|
30
|
+
`failed to fetch data, status ${response.status}: ${response.statusText}`
|
|
31
|
+
);
|
|
32
|
+
}
|
|
33
|
+
return await response.json();
|
|
34
|
+
}
|
|
35
|
+
async getQuickAccessLinks(path) {
|
|
36
|
+
const proxyUrl = await this.getBaseUrl();
|
|
37
|
+
const data = await this.fetcher(path ? `${proxyUrl}${path}` : proxyUrl);
|
|
38
|
+
return data;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
export { QuickAccessApiClient, quickAccessApiRef };
|
|
43
|
+
//# sourceMappingURL=QuickAccessApiClient.esm.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"QuickAccessApiClient.esm.js","sources":["../../src/api/QuickAccessApiClient.ts"],"sourcesContent":["/*\n * Copyright 2024 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nimport {\n ConfigApi,\n createApiRef,\n DiscoveryApi,\n IdentityApi,\n} from '@backstage/core-plugin-api';\n\nimport { QuickAccessLink } from '../types';\n\nconst DEFAULT_PROXY_PATH = '/developer-hub';\n\nexport interface QuickAccessApi {\n getQuickAccessLinks(path?: string): Promise<QuickAccessLink[]>;\n}\n\nexport const quickAccessApiRef = createApiRef<QuickAccessApi>({\n id: 'app.developer-hub.quick-access.service',\n});\n\nexport type Options = {\n discoveryApi: DiscoveryApi;\n configApi: ConfigApi;\n identityApi: IdentityApi;\n};\n\nexport class QuickAccessApiClient implements QuickAccessApi {\n private readonly discoveryApi: DiscoveryApi;\n private readonly configApi: ConfigApi;\n private readonly identityApi: IdentityApi;\n\n constructor(options: Options) {\n this.discoveryApi = options.discoveryApi;\n this.configApi = options.configApi;\n this.identityApi = options.identityApi;\n }\n\n private async getBaseUrl() {\n const proxyPath =\n this.configApi.getOptionalString('developerHub.proxyPath') ??\n DEFAULT_PROXY_PATH;\n return `${await this.discoveryApi.getBaseUrl('proxy')}${proxyPath}`;\n }\n\n private async fetcher(url: string) {\n const { token: idToken } = await this.identityApi.getCredentials();\n const response = await fetch(url, {\n headers: {\n 'Content-Type': 'application/json',\n ...(idToken && { Authorization: `Bearer ${idToken}` }),\n },\n });\n if (!response.ok) {\n throw new Error(\n `failed to fetch data, status ${response.status}: ${response.statusText}`,\n );\n }\n return await response.json();\n }\n\n async getQuickAccessLinks(path?: string) {\n const proxyUrl = await this.getBaseUrl();\n const data = await this.fetcher(path ? `${proxyUrl}${path}` : proxyUrl);\n return data;\n }\n}\n"],"names":[],"mappings":";;AAwBA,MAAM,kBAAqB,GAAA,gBAAA;AAMpB,MAAM,oBAAoB,YAA6B,CAAA;AAAA,EAC5D,EAAI,EAAA;AACN,CAAC;AAQM,MAAM,oBAA+C,CAAA;AAAA,EACzC,YAAA;AAAA,EACA,SAAA;AAAA,EACA,WAAA;AAAA,EAEjB,YAAY,OAAkB,EAAA;AAC5B,IAAA,IAAA,CAAK,eAAe,OAAQ,CAAA,YAAA;AAC5B,IAAA,IAAA,CAAK,YAAY,OAAQ,CAAA,SAAA;AACzB,IAAA,IAAA,CAAK,cAAc,OAAQ,CAAA,WAAA;AAAA;AAC7B,EAEA,MAAc,UAAa,GAAA;AACzB,IAAA,MAAM,SACJ,GAAA,IAAA,CAAK,SAAU,CAAA,iBAAA,CAAkB,wBAAwB,CACzD,IAAA,kBAAA;AACF,IAAO,OAAA,CAAA,EAAG,MAAM,IAAK,CAAA,YAAA,CAAa,WAAW,OAAO,CAAC,GAAG,SAAS,CAAA,CAAA;AAAA;AACnE,EAEA,MAAc,QAAQ,GAAa,EAAA;AACjC,IAAA,MAAM,EAAE,KAAO,EAAA,OAAA,KAAY,MAAM,IAAA,CAAK,YAAY,cAAe,EAAA;AACjE,IAAM,MAAA,QAAA,GAAW,MAAM,KAAA,CAAM,GAAK,EAAA;AAAA,MAChC,OAAS,EAAA;AAAA,QACP,cAAgB,EAAA,kBAAA;AAAA,QAChB,GAAI,OAAW,IAAA,EAAE,aAAe,EAAA,CAAA,OAAA,EAAU,OAAO,CAAG,CAAA;AAAA;AACtD,KACD,CAAA;AACD,IAAI,IAAA,CAAC,SAAS,EAAI,EAAA;AAChB,MAAA,MAAM,IAAI,KAAA;AAAA,QACR,CAAgC,6BAAA,EAAA,QAAA,CAAS,MAAM,CAAA,EAAA,EAAK,SAAS,UAAU,CAAA;AAAA,OACzE;AAAA;AAEF,IAAO,OAAA,MAAM,SAAS,IAAK,EAAA;AAAA;AAC7B,EAEA,MAAM,oBAAoB,IAAe,EAAA;AACvC,IAAM,MAAA,QAAA,GAAW,MAAM,IAAA,CAAK,UAAW,EAAA;AACvC,IAAM,MAAA,IAAA,GAAO,MAAM,IAAA,CAAK,OAAQ,CAAA,IAAA,GAAO,GAAG,QAAQ,CAAA,EAAG,IAAI,CAAA,CAAA,GAAK,QAAQ,CAAA;AACtE,IAAO,OAAA,IAAA;AAAA;AAEX;;;;"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import React, { useMemo } from 'react';
|
|
2
|
+
import { Page, Header, Content, EmptyState } from '@backstage/core-components';
|
|
3
|
+
import { useHomePageMountPoints } from '../hooks/useHomePageMountPoints.esm.js';
|
|
4
|
+
import { ReadOnlyGrid } from './ReadOnlyGrid.esm.js';
|
|
5
|
+
|
|
6
|
+
const DynamicHomePage = (props) => {
|
|
7
|
+
const allHomePageMountPoints = useHomePageMountPoints();
|
|
8
|
+
const filteredAndSortedHomePageCards = useMemo(() => {
|
|
9
|
+
if (!allHomePageMountPoints) {
|
|
10
|
+
return [];
|
|
11
|
+
}
|
|
12
|
+
const filteredAndSorted = allHomePageMountPoints.filter(
|
|
13
|
+
(card) => card.enabled !== false && (!card.config?.priority || card.config.priority >= 0)
|
|
14
|
+
);
|
|
15
|
+
filteredAndSorted.sort(
|
|
16
|
+
(a, b) => (a.config?.priority ?? 0) - (b.config?.priority ?? 0)
|
|
17
|
+
);
|
|
18
|
+
return filteredAndSorted;
|
|
19
|
+
}, [allHomePageMountPoints]);
|
|
20
|
+
return /* @__PURE__ */ React.createElement(Page, { themeId: "home" }, /* @__PURE__ */ React.createElement(Header, { title: props.title ?? "Welcome back!" }), /* @__PURE__ */ React.createElement(Content, null, filteredAndSortedHomePageCards.length === 0 ? /* @__PURE__ */ React.createElement(
|
|
21
|
+
EmptyState,
|
|
22
|
+
{
|
|
23
|
+
title: "No home page cards (mount points) configured or found.",
|
|
24
|
+
missing: "content"
|
|
25
|
+
}
|
|
26
|
+
) : /* @__PURE__ */ React.createElement(ReadOnlyGrid, { mountPoints: filteredAndSortedHomePageCards })));
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
export { DynamicHomePage };
|
|
30
|
+
//# sourceMappingURL=DynamicHomePage.esm.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"DynamicHomePage.esm.js","sources":["../../src/components/DynamicHomePage.tsx"],"sourcesContent":["/*\n * Copyright 2024 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nimport React, { useMemo } from 'react';\n\nimport { Content, EmptyState, Header, Page } from '@backstage/core-components';\n\nimport { useHomePageMountPoints } from '../hooks/useHomePageMountPoints';\nimport { ReadOnlyGrid } from './ReadOnlyGrid';\n\n/**\n * @public\n */\nexport interface DynamicHomePageProps {\n title?: string;\n}\n\n/**\n * @public\n */\nexport const DynamicHomePage = (props: DynamicHomePageProps) => {\n const allHomePageMountPoints = useHomePageMountPoints();\n\n const filteredAndSortedHomePageCards = useMemo(() => {\n if (!allHomePageMountPoints) {\n return [];\n }\n\n const filteredAndSorted = allHomePageMountPoints.filter(\n card =>\n card.enabled !== false &&\n (!card.config?.priority || card.config.priority >= 0),\n );\n\n // TODO: check if we want have priories with small or big numbers first...\n filteredAndSorted.sort(\n (a, b) => (a.config?.priority ?? 0) - (b.config?.priority ?? 0),\n );\n\n return filteredAndSorted;\n }, [allHomePageMountPoints]);\n\n return (\n <Page themeId=\"home\">\n <Header title={props.title ?? 'Welcome back!'} />\n <Content>\n {filteredAndSortedHomePageCards.length === 0 ? (\n <EmptyState\n title=\"No home page cards (mount points) configured or found.\"\n missing=\"content\"\n />\n ) : (\n <ReadOnlyGrid mountPoints={filteredAndSortedHomePageCards} />\n )}\n </Content>\n </Page>\n );\n};\n"],"names":[],"mappings":";;;;;AAgCa,MAAA,eAAA,GAAkB,CAAC,KAAgC,KAAA;AAC9D,EAAA,MAAM,yBAAyB,sBAAuB,EAAA;AAEtD,EAAM,MAAA,8BAAA,GAAiC,QAAQ,MAAM;AACnD,IAAA,IAAI,CAAC,sBAAwB,EAAA;AAC3B,MAAA,OAAO,EAAC;AAAA;AAGV,IAAA,MAAM,oBAAoB,sBAAuB,CAAA,MAAA;AAAA,MAC/C,CAAA,IAAA,KACE,IAAK,CAAA,OAAA,KAAY,KAChB,KAAA,CAAC,KAAK,MAAQ,EAAA,QAAA,IAAY,IAAK,CAAA,MAAA,CAAO,QAAY,IAAA,CAAA;AAAA,KACvD;AAGA,IAAkB,iBAAA,CAAA,IAAA;AAAA,MAChB,CAAC,GAAG,CAAO,KAAA,CAAA,CAAA,CAAE,QAAQ,QAAY,IAAA,CAAA,KAAM,CAAE,CAAA,MAAA,EAAQ,QAAY,IAAA,CAAA;AAAA,KAC/D;AAEA,IAAO,OAAA,iBAAA;AAAA,GACT,EAAG,CAAC,sBAAsB,CAAC,CAAA;AAE3B,EAAA,uBACG,KAAA,CAAA,aAAA,CAAA,IAAA,EAAA,EAAK,OAAQ,EAAA,MAAA,EAAA,sCACX,MAAO,EAAA,EAAA,KAAA,EAAO,KAAM,CAAA,KAAA,IAAS,iBAAiB,CAC/C,kBAAA,KAAA,CAAA,aAAA,CAAC,OACE,EAAA,IAAA,EAAA,8BAAA,CAA+B,WAAW,CACzC,mBAAA,KAAA,CAAA,aAAA;AAAA,IAAC,UAAA;AAAA,IAAA;AAAA,MACC,KAAM,EAAA,wDAAA;AAAA,MACN,OAAQ,EAAA;AAAA;AAAA,sBAGT,KAAA,CAAA,aAAA,CAAA,YAAA,EAAA,EAAa,WAAa,EAAA,8BAAA,EAAgC,CAE/D,CACF,CAAA;AAEJ;;;;"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Headline.esm.js","sources":["../../src/components/Headline.tsx"],"sourcesContent":["/*\n * Copyright 2024 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nimport React from 'react';\n\n/**\n * @public\n */\nexport interface HeadlineProps {\n title?: string;\n align?: 'left' | 'center' | 'right';\n}\n\n/**\n * @public\n */\nexport const Headline = (props: HeadlineProps) => {\n return <h1 style={{ textAlign: props.align }}>{props.title}</h1>;\n};\n"],"names":[],"mappings":";;AA4Ba,MAAA,QAAA,GAAW,CAAC,KAAyB,KAAA;AAChD,EAAO,uBAAA,KAAA,CAAA,aAAA,CAAC,QAAG,KAAO,EAAA,EAAE,WAAW,KAAM,CAAA,KAAA,EAAU,EAAA,EAAA,KAAA,CAAM,KAAM,CAAA;AAC7D;;;;"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { MarkdownContent } from '@backstage/core-components';
|
|
3
|
+
import { makeStyles } from 'tss-react/mui';
|
|
4
|
+
|
|
5
|
+
const useStyles = makeStyles()({
|
|
6
|
+
// Make card content scrollable (so that cards don't overlap)
|
|
7
|
+
card: {
|
|
8
|
+
display: "flex",
|
|
9
|
+
flexDirection: "column",
|
|
10
|
+
width: "100%",
|
|
11
|
+
height: "100%"
|
|
12
|
+
},
|
|
13
|
+
content: {
|
|
14
|
+
overflow: "auto"
|
|
15
|
+
}
|
|
16
|
+
});
|
|
17
|
+
const Markdown = (props) => {
|
|
18
|
+
const { classes } = useStyles();
|
|
19
|
+
return /* @__PURE__ */ React.createElement("div", { className: classes.card }, props.title ? /* @__PURE__ */ React.createElement("h1", null, props.title) : null, /* @__PURE__ */ React.createElement(
|
|
20
|
+
MarkdownContent,
|
|
21
|
+
{
|
|
22
|
+
dialect: "gfm",
|
|
23
|
+
content: props.content ?? "",
|
|
24
|
+
className: classes.content
|
|
25
|
+
}
|
|
26
|
+
));
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
export { Markdown };
|
|
30
|
+
//# sourceMappingURL=Markdown.esm.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Markdown.esm.js","sources":["../../src/components/Markdown.tsx"],"sourcesContent":["/*\n * Copyright 2024 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nimport React from 'react';\n\nimport { MarkdownContent } from '@backstage/core-components';\n\nimport { makeStyles } from 'tss-react/mui';\n\n/**\n * @public\n */\nexport interface MarkdownProps {\n title?: string;\n content?: string;\n}\n\nconst useStyles = makeStyles()({\n // Make card content scrollable (so that cards don't overlap)\n card: {\n display: 'flex',\n flexDirection: 'column',\n width: '100%',\n height: '100%',\n },\n content: {\n overflow: 'auto',\n },\n});\n\n/**\n * @public\n */\nexport const Markdown = (props: MarkdownProps) => {\n const { classes } = useStyles();\n return (\n <div className={classes.card}>\n {props.title ? <h1>{props.title}</h1> : null}\n <MarkdownContent\n dialect=\"gfm\"\n content={props.content ?? ''}\n className={classes.content}\n />\n </div>\n );\n};\n"],"names":[],"mappings":";;;;AA6BA,MAAM,SAAA,GAAY,YAAa,CAAA;AAAA;AAAA,EAE7B,IAAM,EAAA;AAAA,IACJ,OAAS,EAAA,MAAA;AAAA,IACT,aAAe,EAAA,QAAA;AAAA,IACf,KAAO,EAAA,MAAA;AAAA,IACP,MAAQ,EAAA;AAAA,GACV;AAAA,EACA,OAAS,EAAA;AAAA,IACP,QAAU,EAAA;AAAA;AAEd,CAAC,CAAA;AAKY,MAAA,QAAA,GAAW,CAAC,KAAyB,KAAA;AAChD,EAAM,MAAA,EAAE,OAAQ,EAAA,GAAI,SAAU,EAAA;AAC9B,EAAA,uBACG,KAAA,CAAA,aAAA,CAAA,KAAA,EAAA,EAAI,SAAW,EAAA,OAAA,CAAQ,IACrB,EAAA,EAAA,KAAA,CAAM,KAAQ,mBAAA,KAAA,CAAA,aAAA,CAAC,IAAI,EAAA,IAAA,EAAA,KAAA,CAAM,KAAM,CAAA,GAAQ,IACxC,kBAAA,KAAA,CAAA,aAAA;AAAA,IAAC,eAAA;AAAA,IAAA;AAAA,MACC,OAAQ,EAAA,KAAA;AAAA,MACR,OAAA,EAAS,MAAM,OAAW,IAAA,EAAA;AAAA,MAC1B,WAAW,OAAQ,CAAA;AAAA;AAAA,GAEvB,CAAA;AAEJ;;;;"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { InfoCard, MarkdownContent } from '@backstage/core-components';
|
|
3
|
+
|
|
4
|
+
const MarkdownCard = (props) => {
|
|
5
|
+
return /* @__PURE__ */ React.createElement(InfoCard, { title: props.title }, /* @__PURE__ */ React.createElement(MarkdownContent, { dialect: "gfm", content: props.content ?? "" }));
|
|
6
|
+
};
|
|
7
|
+
|
|
8
|
+
export { MarkdownCard };
|
|
9
|
+
//# sourceMappingURL=MarkdownCard.esm.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"MarkdownCard.esm.js","sources":["../../src/components/MarkdownCard.tsx"],"sourcesContent":["/*\n * Copyright 2024 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nimport React from 'react';\n\nimport { InfoCard, MarkdownContent } from '@backstage/core-components';\n\n/**\n * @public\n */\nexport interface MarkdownCardProps {\n title?: string;\n content?: string;\n}\n\n/**\n * @public\n */\nexport const MarkdownCard = (props: MarkdownCardProps) => {\n return (\n <InfoCard title={props.title}>\n <MarkdownContent dialect=\"gfm\" content={props.content ?? ''} />\n </InfoCard>\n );\n};\n"],"names":[],"mappings":";;;AA8Ba,MAAA,YAAA,GAAe,CAAC,KAA6B,KAAA;AACxD,EAAA,uBACG,KAAA,CAAA,aAAA,CAAA,QAAA,EAAA,EAAS,KAAO,EAAA,KAAA,CAAM,KACrB,EAAA,kBAAA,KAAA,CAAA,aAAA,CAAC,eAAgB,EAAA,EAAA,OAAA,EAAQ,KAAM,EAAA,OAAA,EAAS,KAAM,CAAA,OAAA,IAAW,IAAI,CAC/D,CAAA;AAEJ;;;;"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { makeStyles } from 'tss-react/mui';
|
|
3
|
+
|
|
4
|
+
const useStyles = makeStyles()({
|
|
5
|
+
centerDebugContent: {
|
|
6
|
+
height: "100%",
|
|
7
|
+
display: "flex",
|
|
8
|
+
alignItems: "center",
|
|
9
|
+
justifyContent: "center"
|
|
10
|
+
},
|
|
11
|
+
// Make card content scrollable (so that cards don't overlap)
|
|
12
|
+
showBorder: {
|
|
13
|
+
border: "1px solid gray",
|
|
14
|
+
width: "100%",
|
|
15
|
+
height: "100%"
|
|
16
|
+
}
|
|
17
|
+
});
|
|
18
|
+
const Placeholder = (props) => {
|
|
19
|
+
const { classes } = useStyles();
|
|
20
|
+
const className = [
|
|
21
|
+
props.debugContent ? classes.centerDebugContent : void 0,
|
|
22
|
+
props.showBorder ? classes.showBorder : void 0
|
|
23
|
+
].filter(Boolean).join(" ");
|
|
24
|
+
return /* @__PURE__ */ React.createElement("div", { "data-testid": "placeholder", className }, props.debugContent);
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
export { Placeholder };
|
|
28
|
+
//# sourceMappingURL=Placeholder.esm.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Placeholder.esm.js","sources":["../../src/components/Placeholder.tsx"],"sourcesContent":["/*\n * Copyright 2024 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nimport React from 'react';\n\nimport { makeStyles } from 'tss-react/mui';\n\n/**\n * @public\n */\nexport interface PlaceholderProps {\n showBorder?: boolean;\n debugContent?: string;\n}\n\nconst useStyles = makeStyles()({\n centerDebugContent: {\n height: '100%',\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n },\n // Make card content scrollable (so that cards don't overlap)\n showBorder: {\n border: '1px solid gray',\n width: '100%',\n height: '100%',\n },\n});\n\n/**\n * @public\n */\nexport const Placeholder = (props: PlaceholderProps) => {\n const { classes } = useStyles();\n const className = [\n props.debugContent ? classes.centerDebugContent : undefined,\n props.showBorder ? classes.showBorder : undefined,\n ]\n .filter(Boolean)\n .join(' ');\n return (\n <div data-testid=\"placeholder\" className={className}>\n {props.debugContent}\n </div>\n );\n};\n"],"names":[],"mappings":";;;AA2BA,MAAM,SAAA,GAAY,YAAa,CAAA;AAAA,EAC7B,kBAAoB,EAAA;AAAA,IAClB,MAAQ,EAAA,MAAA;AAAA,IACR,OAAS,EAAA,MAAA;AAAA,IACT,UAAY,EAAA,QAAA;AAAA,IACZ,cAAgB,EAAA;AAAA,GAClB;AAAA;AAAA,EAEA,UAAY,EAAA;AAAA,IACV,MAAQ,EAAA,gBAAA;AAAA,IACR,KAAO,EAAA,MAAA;AAAA,IACP,MAAQ,EAAA;AAAA;AAEZ,CAAC,CAAA;AAKY,MAAA,WAAA,GAAc,CAAC,KAA4B,KAAA;AACtD,EAAM,MAAA,EAAE,OAAQ,EAAA,GAAI,SAAU,EAAA;AAC9B,EAAA,MAAM,SAAY,GAAA;AAAA,IAChB,KAAA,CAAM,YAAe,GAAA,OAAA,CAAQ,kBAAqB,GAAA,KAAA,CAAA;AAAA,IAClD,KAAA,CAAM,UAAa,GAAA,OAAA,CAAQ,UAAa,GAAA,KAAA;AAAA,GAEvC,CAAA,MAAA,CAAO,OAAO,CAAA,CACd,KAAK,GAAG,CAAA;AACX,EAAA,2CACG,KAAI,EAAA,EAAA,aAAA,EAAY,aAAc,EAAA,SAAA,EAAA,EAC5B,MAAM,YACT,CAAA;AAEJ;;;;"}
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { WarningPanel, CodeSnippet, InfoCard } from '@backstage/core-components';
|
|
3
|
+
import { HomePageToolkit, ComponentAccordion } from '@backstage/plugin-home';
|
|
4
|
+
import CircularProgress from '@mui/material/CircularProgress';
|
|
5
|
+
import { makeStyles } from 'tss-react/mui';
|
|
6
|
+
import { useQuickAccessLinks } from '../hooks/useQuickAccessLinks.esm.js';
|
|
7
|
+
|
|
8
|
+
const useStyles = makeStyles()({
|
|
9
|
+
center: {
|
|
10
|
+
height: "100%",
|
|
11
|
+
display: "flex",
|
|
12
|
+
alignItems: "center",
|
|
13
|
+
justifyContent: "center"
|
|
14
|
+
},
|
|
15
|
+
img: {
|
|
16
|
+
height: "40px",
|
|
17
|
+
width: "auto"
|
|
18
|
+
},
|
|
19
|
+
title: {
|
|
20
|
+
"& div > div > div > div > p": {
|
|
21
|
+
textTransform: "uppercase"
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
});
|
|
25
|
+
const QuickAccessCard = (props) => {
|
|
26
|
+
const { classes } = useStyles();
|
|
27
|
+
const { data, error, isLoading } = useQuickAccessLinks(props.path);
|
|
28
|
+
let content;
|
|
29
|
+
if (isLoading) {
|
|
30
|
+
content = /* @__PURE__ */ React.createElement("div", { className: classes.center }, /* @__PURE__ */ React.createElement(CircularProgress, null));
|
|
31
|
+
} else if (!data) {
|
|
32
|
+
content = /* @__PURE__ */ React.createElement(WarningPanel, { severity: "error", title: "Could not fetch data." }, /* @__PURE__ */ React.createElement(
|
|
33
|
+
CodeSnippet,
|
|
34
|
+
{
|
|
35
|
+
language: "text",
|
|
36
|
+
text: error?.toString() ?? "Unknown error"
|
|
37
|
+
}
|
|
38
|
+
));
|
|
39
|
+
} else {
|
|
40
|
+
content = /* @__PURE__ */ React.createElement(React.Fragment, null, data.map((item) => /* @__PURE__ */ React.createElement(
|
|
41
|
+
HomePageToolkit,
|
|
42
|
+
{
|
|
43
|
+
key: item.title,
|
|
44
|
+
title: item.title,
|
|
45
|
+
tools: item.links.map((link) => ({
|
|
46
|
+
...link,
|
|
47
|
+
icon: /* @__PURE__ */ React.createElement(
|
|
48
|
+
"img",
|
|
49
|
+
{
|
|
50
|
+
className: classes.img,
|
|
51
|
+
src: link.iconUrl,
|
|
52
|
+
alt: link.label
|
|
53
|
+
}
|
|
54
|
+
)
|
|
55
|
+
})),
|
|
56
|
+
Renderer: (renderProps) => /* @__PURE__ */ React.createElement(ComponentAccordion, { expanded: item.isExpanded, ...renderProps })
|
|
57
|
+
}
|
|
58
|
+
)));
|
|
59
|
+
}
|
|
60
|
+
return /* @__PURE__ */ React.createElement(
|
|
61
|
+
InfoCard,
|
|
62
|
+
{
|
|
63
|
+
title: props.title ?? "Quick Access",
|
|
64
|
+
noPadding: true,
|
|
65
|
+
className: classes.title
|
|
66
|
+
},
|
|
67
|
+
content
|
|
68
|
+
);
|
|
69
|
+
};
|
|
70
|
+
|
|
71
|
+
export { QuickAccessCard };
|
|
72
|
+
//# sourceMappingURL=QuickAccessCard.esm.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"QuickAccessCard.esm.js","sources":["../../src/components/QuickAccessCard.tsx"],"sourcesContent":["/*\n * Copyright 2024 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nimport React from 'react';\n\nimport {\n CodeSnippet,\n InfoCard,\n WarningPanel,\n} from '@backstage/core-components';\nimport { ComponentAccordion, HomePageToolkit } from '@backstage/plugin-home';\n\nimport CircularProgress from '@mui/material/CircularProgress';\nimport { makeStyles } from 'tss-react/mui';\n\nimport { useQuickAccessLinks } from '../hooks/useQuickAccessLinks';\n\nconst useStyles = makeStyles()({\n center: {\n height: '100%',\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n },\n img: {\n height: '40px',\n width: 'auto',\n },\n title: {\n '& div > div > div > div > p': {\n textTransform: 'uppercase',\n },\n },\n});\n\n/**\n * @public\n */\nexport interface QuickAccessCardProps {\n title?: string;\n path?: string;\n}\n\n/**\n * @public\n */\nexport const QuickAccessCard = (props: QuickAccessCardProps) => {\n const { classes } = useStyles();\n const { data, error, isLoading } = useQuickAccessLinks(props.path);\n\n let content: React.ReactElement;\n\n if (isLoading) {\n content = (\n <div className={classes.center}>\n <CircularProgress />\n </div>\n );\n } else if (!data) {\n content = (\n <WarningPanel severity=\"error\" title=\"Could not fetch data.\">\n <CodeSnippet\n language=\"text\"\n text={error?.toString() ?? 'Unknown error'}\n />\n </WarningPanel>\n );\n } else {\n content = (\n <>\n {data.map(item => (\n <HomePageToolkit\n key={item.title}\n title={item.title}\n tools={item.links.map(link => ({\n ...link,\n icon: (\n <img\n className={classes.img}\n src={link.iconUrl}\n alt={link.label}\n />\n ),\n }))}\n Renderer={renderProps => (\n <ComponentAccordion expanded={item.isExpanded} {...renderProps} />\n )}\n />\n ))}\n </>\n );\n }\n\n return (\n <InfoCard\n title={props.title ?? 'Quick Access'}\n noPadding\n className={classes.title}\n >\n {content}\n </InfoCard>\n );\n};\n"],"names":[],"mappings":";;;;;;;AA6BA,MAAM,SAAA,GAAY,YAAa,CAAA;AAAA,EAC7B,MAAQ,EAAA;AAAA,IACN,MAAQ,EAAA,MAAA;AAAA,IACR,OAAS,EAAA,MAAA;AAAA,IACT,UAAY,EAAA,QAAA;AAAA,IACZ,cAAgB,EAAA;AAAA,GAClB;AAAA,EACA,GAAK,EAAA;AAAA,IACH,MAAQ,EAAA,MAAA;AAAA,IACR,KAAO,EAAA;AAAA,GACT;AAAA,EACA,KAAO,EAAA;AAAA,IACL,6BAA+B,EAAA;AAAA,MAC7B,aAAe,EAAA;AAAA;AACjB;AAEJ,CAAC,CAAA;AAaY,MAAA,eAAA,GAAkB,CAAC,KAAgC,KAAA;AAC9D,EAAM,MAAA,EAAE,OAAQ,EAAA,GAAI,SAAU,EAAA;AAC9B,EAAA,MAAM,EAAE,IAAM,EAAA,KAAA,EAAO,WAAc,GAAA,mBAAA,CAAoB,MAAM,IAAI,CAAA;AAEjE,EAAI,IAAA,OAAA;AAEJ,EAAA,IAAI,SAAW,EAAA;AACb,IAAA,OAAA,uCACG,KAAI,EAAA,EAAA,SAAA,EAAW,QAAQ,MACtB,EAAA,kBAAA,KAAA,CAAA,aAAA,CAAC,sBAAiB,CACpB,CAAA;AAAA,GAEJ,MAAA,IAAW,CAAC,IAAM,EAAA;AAChB,IAAA,OAAA,mBACG,KAAA,CAAA,aAAA,CAAA,YAAA,EAAA,EAAa,QAAS,EAAA,OAAA,EAAQ,OAAM,uBACnC,EAAA,kBAAA,KAAA,CAAA,aAAA;AAAA,MAAC,WAAA;AAAA,MAAA;AAAA,QACC,QAAS,EAAA,MAAA;AAAA,QACT,IAAA,EAAM,KAAO,EAAA,QAAA,EAAc,IAAA;AAAA;AAAA,KAE/B,CAAA;AAAA,GAEG,MAAA;AACL,IACE,OAAA,mBAAA,KAAA,CAAA,aAAA,CAAA,KAAA,CAAA,QAAA,EAAA,IAAA,EACG,IAAK,CAAA,GAAA,CAAI,CACR,IAAA,qBAAA,KAAA,CAAA,aAAA;AAAA,MAAC,eAAA;AAAA,MAAA;AAAA,QACC,KAAK,IAAK,CAAA,KAAA;AAAA,QACV,OAAO,IAAK,CAAA,KAAA;AAAA,QACZ,KAAO,EAAA,IAAA,CAAK,KAAM,CAAA,GAAA,CAAI,CAAS,IAAA,MAAA;AAAA,UAC7B,GAAG,IAAA;AAAA,UACH,IACE,kBAAA,KAAA,CAAA,aAAA;AAAA,YAAC,KAAA;AAAA,YAAA;AAAA,cACC,WAAW,OAAQ,CAAA,GAAA;AAAA,cACnB,KAAK,IAAK,CAAA,OAAA;AAAA,cACV,KAAK,IAAK,CAAA;AAAA;AAAA;AACZ,SAEF,CAAA,CAAA;AAAA,QACF,QAAA,EAAU,iCACP,KAAA,CAAA,aAAA,CAAA,kBAAA,EAAA,EAAmB,UAAU,IAAK,CAAA,UAAA,EAAa,GAAG,WAAa,EAAA;AAAA;AAAA,KAGrE,CACH,CAAA;AAAA;AAIJ,EACE,uBAAA,KAAA,CAAA,aAAA;AAAA,IAAC,QAAA;AAAA,IAAA;AAAA,MACC,KAAA,EAAO,MAAM,KAAS,IAAA,cAAA;AAAA,MACtB,SAAS,EAAA,IAAA;AAAA,MACT,WAAW,OAAQ,CAAA;AAAA,KAAA;AAAA,IAElB;AAAA,GACH;AAEJ;;;;"}
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
import React, { useMemo } from 'react';
|
|
2
|
+
import { Responsive } from 'react-grid-layout';
|
|
3
|
+
import { ErrorBoundary } from '@backstage/core-components';
|
|
4
|
+
import { makeStyles } from 'tss-react/mui';
|
|
5
|
+
import 'react-grid-layout/css/styles.css';
|
|
6
|
+
import useMeasure from 'react-use/lib/useMeasure';
|
|
7
|
+
|
|
8
|
+
const gridGap = 16;
|
|
9
|
+
const defaultProps = {
|
|
10
|
+
// Aligned with the 1.0-1.2 home page gap.
|
|
11
|
+
margin: [gridGap, gridGap],
|
|
12
|
+
// Same as in home-plugin CustomHomepageGrid
|
|
13
|
+
rowHeight: 60,
|
|
14
|
+
// We use always a 12-column grid, but each cards can define
|
|
15
|
+
// their number of columns (width) and start column (x) per breakpoint.
|
|
16
|
+
breakpoints: {
|
|
17
|
+
xl: 1600,
|
|
18
|
+
lg: 1200,
|
|
19
|
+
md: 996,
|
|
20
|
+
sm: 768,
|
|
21
|
+
xs: 480,
|
|
22
|
+
xxs: 0
|
|
23
|
+
},
|
|
24
|
+
cols: {
|
|
25
|
+
xl: 12,
|
|
26
|
+
lg: 12,
|
|
27
|
+
md: 12,
|
|
28
|
+
sm: 12,
|
|
29
|
+
xs: 12,
|
|
30
|
+
xxs: 12
|
|
31
|
+
},
|
|
32
|
+
isDraggable: false,
|
|
33
|
+
isResizable: false,
|
|
34
|
+
compactType: null
|
|
35
|
+
};
|
|
36
|
+
const useStyles = makeStyles()({
|
|
37
|
+
// Make card content scrollable (so that cards don't overlap)
|
|
38
|
+
cardWrapper: {
|
|
39
|
+
'& > div[class*="MuiCard-root"]': {
|
|
40
|
+
width: "100%",
|
|
41
|
+
height: "100%"
|
|
42
|
+
},
|
|
43
|
+
'& div[class*="MuiCardContent-root"]': {
|
|
44
|
+
overflow: "auto"
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
});
|
|
48
|
+
const ReadOnlyGrid = (props) => {
|
|
49
|
+
const { classes } = useStyles();
|
|
50
|
+
const [measureRef, measureRect] = useMeasure();
|
|
51
|
+
const cards = useMemo(() => {
|
|
52
|
+
return props.mountPoints.map((mountPoint, index) => {
|
|
53
|
+
const id = (index + 1).toString();
|
|
54
|
+
const layouts2 = {};
|
|
55
|
+
if (mountPoint.config?.layouts) {
|
|
56
|
+
for (const [breakpoint, layout] of Object.entries(
|
|
57
|
+
mountPoint.config.layouts
|
|
58
|
+
)) {
|
|
59
|
+
layouts2[breakpoint] = {
|
|
60
|
+
i: id,
|
|
61
|
+
x: layout.x ?? 0,
|
|
62
|
+
y: layout.y ?? 0,
|
|
63
|
+
w: layout.w ?? 12,
|
|
64
|
+
h: layout.h ?? 4,
|
|
65
|
+
isDraggable: false,
|
|
66
|
+
isResizable: false
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
} else {
|
|
70
|
+
["xl", "lg", "md", "sm", "xs", "xxs"].forEach((breakpoint) => {
|
|
71
|
+
layouts2[breakpoint] = {
|
|
72
|
+
i: id,
|
|
73
|
+
x: 0,
|
|
74
|
+
y: 0,
|
|
75
|
+
w: 12,
|
|
76
|
+
h: 4,
|
|
77
|
+
isDraggable: false,
|
|
78
|
+
isResizable: false
|
|
79
|
+
};
|
|
80
|
+
});
|
|
81
|
+
}
|
|
82
|
+
return {
|
|
83
|
+
id,
|
|
84
|
+
Component: mountPoint.Component,
|
|
85
|
+
props: mountPoint.config?.props,
|
|
86
|
+
layouts: layouts2
|
|
87
|
+
};
|
|
88
|
+
});
|
|
89
|
+
}, [props.mountPoints]);
|
|
90
|
+
const layouts = useMemo(() => {
|
|
91
|
+
const result = {};
|
|
92
|
+
for (const card of cards) {
|
|
93
|
+
for (const [breakpoint, layoutPerBreakpoint] of Object.entries(
|
|
94
|
+
card.layouts
|
|
95
|
+
)) {
|
|
96
|
+
if (!result[breakpoint]) {
|
|
97
|
+
result[breakpoint] = [];
|
|
98
|
+
}
|
|
99
|
+
result[breakpoint].push(layoutPerBreakpoint);
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
return result;
|
|
103
|
+
}, [cards]);
|
|
104
|
+
const children = useMemo(() => {
|
|
105
|
+
return cards.map((card) => /* @__PURE__ */ React.createElement(
|
|
106
|
+
"div",
|
|
107
|
+
{
|
|
108
|
+
key: card.id,
|
|
109
|
+
"data-cardid": card.id,
|
|
110
|
+
"data-testid": `home-page card ${card.id}`,
|
|
111
|
+
"data-layout": JSON.stringify(card.layouts),
|
|
112
|
+
className: classes.cardWrapper
|
|
113
|
+
},
|
|
114
|
+
/* @__PURE__ */ React.createElement(ErrorBoundary, null, /* @__PURE__ */ React.createElement(card.Component, { ...card.props }))
|
|
115
|
+
));
|
|
116
|
+
}, [cards, classes.cardWrapper]);
|
|
117
|
+
return /* @__PURE__ */ React.createElement("div", { style: { margin: -gridGap } }, /* @__PURE__ */ React.createElement("div", { ref: measureRef }), measureRect.width ? /* @__PURE__ */ React.createElement(
|
|
118
|
+
Responsive,
|
|
119
|
+
{
|
|
120
|
+
...defaultProps,
|
|
121
|
+
width: measureRect.width,
|
|
122
|
+
layouts
|
|
123
|
+
},
|
|
124
|
+
children
|
|
125
|
+
) : null);
|
|
126
|
+
};
|
|
127
|
+
|
|
128
|
+
export { ReadOnlyGrid };
|
|
129
|
+
//# sourceMappingURL=ReadOnlyGrid.esm.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ReadOnlyGrid.esm.js","sources":["../../src/components/ReadOnlyGrid.tsx"],"sourcesContent":["/*\n * Copyright 2024 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\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 React, { useMemo } from 'react';\nimport {\n Layout,\n Layouts,\n Responsive,\n ResponsiveProps,\n} from 'react-grid-layout';\n\nimport { ErrorBoundary } from '@backstage/core-components';\n\nimport { makeStyles } from 'tss-react/mui';\n\n// Removes the doubled scrollbar\nimport 'react-grid-layout/css/styles.css';\n\nimport useMeasure from 'react-use/lib/useMeasure';\n\nimport { HomePageCardMountPoint } from '../types';\n\ninterface Card {\n id: string;\n Component: React.ComponentType<any>;\n props?: Record<string, any>;\n layouts: Record<string, Layout>;\n}\n\nconst gridGap = 16;\n\nconst defaultProps: ResponsiveProps = {\n // Aligned with the 1.0-1.2 home page gap.\n margin: [gridGap, gridGap],\n // Same as in home-plugin CustomHomepageGrid\n rowHeight: 60,\n\n // We use always a 12-column grid, but each cards can define\n // their number of columns (width) and start column (x) per breakpoint.\n breakpoints: {\n xl: 1600,\n lg: 1200,\n md: 996,\n sm: 768,\n xs: 480,\n xxs: 0,\n },\n cols: {\n xl: 12,\n lg: 12,\n md: 12,\n sm: 12,\n xs: 12,\n xxs: 12,\n },\n\n isDraggable: false,\n isResizable: false,\n compactType: null,\n};\n\nconst useStyles = makeStyles()({\n // Make card content scrollable (so that cards don't overlap)\n cardWrapper: {\n '& > div[class*=\"MuiCard-root\"]': {\n width: '100%',\n height: '100%',\n },\n '& div[class*=\"MuiCardContent-root\"]': {\n overflow: 'auto',\n },\n },\n});\n\n/**\n * @public\n */\nexport interface ReadOnlyGridProps {\n mountPoints: HomePageCardMountPoint[];\n breakpoints?: Record<string, number>;\n cols?: Record<string, number>;\n}\n\n/**\n * @public\n */\nexport const ReadOnlyGrid = (props: ReadOnlyGridProps) => {\n const { classes } = useStyles();\n const [measureRef, measureRect] = useMeasure<HTMLDivElement>();\n\n const cards = useMemo<Card[]>(() => {\n return props.mountPoints.map<Card>((mountPoint, index) => {\n const id = (index + 1).toString();\n const layouts: Record<string, Layout> = {};\n\n if (mountPoint.config?.layouts) {\n for (const [breakpoint, layout] of Object.entries(\n mountPoint.config.layouts,\n )) {\n layouts[breakpoint] = {\n i: id,\n x: layout.x ?? 0,\n y: layout.y ?? 0,\n w: layout.w ?? 12,\n h: layout.h ?? 4,\n isDraggable: false,\n isResizable: false,\n };\n }\n } else {\n // Default layout for cards without a layout configuration\n ['xl', 'lg', 'md', 'sm', 'xs', 'xxs'].forEach(breakpoint => {\n layouts[breakpoint] = {\n i: id,\n x: 0,\n y: 0,\n w: 12,\n h: 4,\n isDraggable: false,\n isResizable: false,\n };\n });\n }\n\n return {\n id,\n Component: mountPoint.Component,\n props: mountPoint.config?.props,\n layouts,\n };\n });\n }, [props.mountPoints]);\n\n const layouts = useMemo<Layouts>(() => {\n const result: Layouts = {};\n for (const card of cards) {\n for (const [breakpoint, layoutPerBreakpoint] of Object.entries(\n card.layouts,\n )) {\n if (!result[breakpoint]) {\n result[breakpoint] = [];\n }\n result[breakpoint].push(layoutPerBreakpoint);\n }\n }\n return result;\n }, [cards]);\n\n const children = useMemo(() => {\n return cards.map(card => (\n <div\n key={card.id}\n data-cardid={card.id}\n data-testid={`home-page card ${card.id}`}\n data-layout={JSON.stringify(card.layouts)}\n className={classes.cardWrapper}\n >\n <ErrorBoundary>\n <card.Component {...card.props} />\n </ErrorBoundary>\n </div>\n ));\n }, [cards, classes.cardWrapper]);\n\n return (\n <div style={{ margin: -gridGap }}>\n <div ref={measureRef} />\n {measureRect.width ? (\n <Responsive\n {...defaultProps}\n width={measureRect.width}\n layouts={layouts}\n >\n {children}\n </Responsive>\n ) : null}\n </div>\n );\n};\n"],"names":["layouts"],"mappings":";;;;;;;AAgDA,MAAM,OAAU,GAAA,EAAA;AAEhB,MAAM,YAAgC,GAAA;AAAA;AAAA,EAEpC,MAAA,EAAQ,CAAC,OAAA,EAAS,OAAO,CAAA;AAAA;AAAA,EAEzB,SAAW,EAAA,EAAA;AAAA;AAAA;AAAA,EAIX,WAAa,EAAA;AAAA,IACX,EAAI,EAAA,IAAA;AAAA,IACJ,EAAI,EAAA,IAAA;AAAA,IACJ,EAAI,EAAA,GAAA;AAAA,IACJ,EAAI,EAAA,GAAA;AAAA,IACJ,EAAI,EAAA,GAAA;AAAA,IACJ,GAAK,EAAA;AAAA,GACP;AAAA,EACA,IAAM,EAAA;AAAA,IACJ,EAAI,EAAA,EAAA;AAAA,IACJ,EAAI,EAAA,EAAA;AAAA,IACJ,EAAI,EAAA,EAAA;AAAA,IACJ,EAAI,EAAA,EAAA;AAAA,IACJ,EAAI,EAAA,EAAA;AAAA,IACJ,GAAK,EAAA;AAAA,GACP;AAAA,EAEA,WAAa,EAAA,KAAA;AAAA,EACb,WAAa,EAAA,KAAA;AAAA,EACb,WAAa,EAAA;AACf,CAAA;AAEA,MAAM,SAAA,GAAY,YAAa,CAAA;AAAA;AAAA,EAE7B,WAAa,EAAA;AAAA,IACX,gCAAkC,EAAA;AAAA,MAChC,KAAO,EAAA,MAAA;AAAA,MACP,MAAQ,EAAA;AAAA,KACV;AAAA,IACA,qCAAuC,EAAA;AAAA,MACrC,QAAU,EAAA;AAAA;AACZ;AAEJ,CAAC,CAAA;AAcY,MAAA,YAAA,GAAe,CAAC,KAA6B,KAAA;AACxD,EAAM,MAAA,EAAE,OAAQ,EAAA,GAAI,SAAU,EAAA;AAC9B,EAAA,MAAM,CAAC,UAAA,EAAY,WAAW,CAAA,GAAI,UAA2B,EAAA;AAE7D,EAAM,MAAA,KAAA,GAAQ,QAAgB,MAAM;AAClC,IAAA,OAAO,KAAM,CAAA,WAAA,CAAY,GAAU,CAAA,CAAC,YAAY,KAAU,KAAA;AACxD,MAAM,MAAA,EAAA,GAAA,CAAM,KAAQ,GAAA,CAAA,EAAG,QAAS,EAAA;AAChC,MAAA,MAAMA,WAAkC,EAAC;AAEzC,MAAI,IAAA,UAAA,CAAW,QAAQ,OAAS,EAAA;AAC9B,QAAA,KAAA,MAAW,CAAC,UAAA,EAAY,MAAM,CAAA,IAAK,MAAO,CAAA,OAAA;AAAA,UACxC,WAAW,MAAO,CAAA;AAAA,SACjB,EAAA;AACD,UAAAA,QAAAA,CAAQ,UAAU,CAAI,GAAA;AAAA,YACpB,CAAG,EAAA,EAAA;AAAA,YACH,CAAA,EAAG,OAAO,CAAK,IAAA,CAAA;AAAA,YACf,CAAA,EAAG,OAAO,CAAK,IAAA,CAAA;AAAA,YACf,CAAA,EAAG,OAAO,CAAK,IAAA,EAAA;AAAA,YACf,CAAA,EAAG,OAAO,CAAK,IAAA,CAAA;AAAA,YACf,WAAa,EAAA,KAAA;AAAA,YACb,WAAa,EAAA;AAAA,WACf;AAAA;AACF,OACK,MAAA;AAEL,QAAC,CAAA,IAAA,EAAM,MAAM,IAAM,EAAA,IAAA,EAAM,MAAM,KAAK,CAAA,CAAE,QAAQ,CAAc,UAAA,KAAA;AAC1D,UAAAA,QAAAA,CAAQ,UAAU,CAAI,GAAA;AAAA,YACpB,CAAG,EAAA,EAAA;AAAA,YACH,CAAG,EAAA,CAAA;AAAA,YACH,CAAG,EAAA,CAAA;AAAA,YACH,CAAG,EAAA,EAAA;AAAA,YACH,CAAG,EAAA,CAAA;AAAA,YACH,WAAa,EAAA,KAAA;AAAA,YACb,WAAa,EAAA;AAAA,WACf;AAAA,SACD,CAAA;AAAA;AAGH,MAAO,OAAA;AAAA,QACL,EAAA;AAAA,QACA,WAAW,UAAW,CAAA,SAAA;AAAA,QACtB,KAAA,EAAO,WAAW,MAAQ,EAAA,KAAA;AAAA,QAC1B,OAAAA,EAAAA;AAAA,OACF;AAAA,KACD,CAAA;AAAA,GACA,EAAA,CAAC,KAAM,CAAA,WAAW,CAAC,CAAA;AAEtB,EAAM,MAAA,OAAA,GAAU,QAAiB,MAAM;AACrC,IAAA,MAAM,SAAkB,EAAC;AACzB,IAAA,KAAA,MAAW,QAAQ,KAAO,EAAA;AACxB,MAAA,KAAA,MAAW,CAAC,UAAA,EAAY,mBAAmB,CAAA,IAAK,MAAO,CAAA,OAAA;AAAA,QACrD,IAAK,CAAA;AAAA,OACJ,EAAA;AACD,QAAI,IAAA,CAAC,MAAO,CAAA,UAAU,CAAG,EAAA;AACvB,UAAO,MAAA,CAAA,UAAU,IAAI,EAAC;AAAA;AAExB,QAAO,MAAA,CAAA,UAAU,CAAE,CAAA,IAAA,CAAK,mBAAmB,CAAA;AAAA;AAC7C;AAEF,IAAO,OAAA,MAAA;AAAA,GACT,EAAG,CAAC,KAAK,CAAC,CAAA;AAEV,EAAM,MAAA,QAAA,GAAW,QAAQ,MAAM;AAC7B,IAAO,OAAA,KAAA,CAAM,IAAI,CACf,IAAA,qBAAA,KAAA,CAAA,aAAA;AAAA,MAAC,KAAA;AAAA,MAAA;AAAA,QACC,KAAK,IAAK,CAAA,EAAA;AAAA,QACV,eAAa,IAAK,CAAA,EAAA;AAAA,QAClB,aAAA,EAAa,CAAkB,eAAA,EAAA,IAAA,CAAK,EAAE,CAAA,CAAA;AAAA,QACtC,aAAa,EAAA,IAAA,CAAK,SAAU,CAAA,IAAA,CAAK,OAAO,CAAA;AAAA,QACxC,WAAW,OAAQ,CAAA;AAAA,OAAA;AAAA,sBAEnB,KAAA,CAAA,aAAA,CAAC,qCACE,KAAA,CAAA,aAAA,CAAA,IAAA,CAAK,WAAL,EAAgB,GAAG,IAAK,CAAA,KAAA,EAAO,CAClC;AAAA,KAEH,CAAA;AAAA,GACA,EAAA,CAAC,KAAO,EAAA,OAAA,CAAQ,WAAW,CAAC,CAAA;AAE/B,EAAA,uBACG,KAAA,CAAA,aAAA,CAAA,KAAA,EAAA,EAAI,KAAO,EAAA,EAAE,QAAQ,CAAC,OAAA,EACrB,EAAA,kBAAA,KAAA,CAAA,aAAA,CAAC,KAAI,EAAA,EAAA,GAAA,EAAK,UAAY,EAAA,CAAA,EACrB,YAAY,KACX,mBAAA,KAAA,CAAA,aAAA;AAAA,IAAC,UAAA;AAAA,IAAA;AAAA,MACE,GAAG,YAAA;AAAA,MACJ,OAAO,WAAY,CAAA,KAAA;AAAA,MACnB;AAAA,KAAA;AAAA,IAEC;AAAA,MAED,IACN,CAAA;AAEJ;;;;"}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import React, { useState, useRef, useCallback } from 'react';
|
|
2
|
+
import { useNavigate } from 'react-router-dom';
|
|
3
|
+
import { SearchBarBase } from '@backstage/plugin-search-react';
|
|
4
|
+
import { makeStyles } from 'tss-react/mui';
|
|
5
|
+
|
|
6
|
+
const useStyles = makeStyles()((theme) => ({
|
|
7
|
+
searchBar: {
|
|
8
|
+
"&&": {
|
|
9
|
+
backgroundColor: theme.palette.mode === "dark" ? "#36373A" : "#FFFFFF",
|
|
10
|
+
boxShadow: "none",
|
|
11
|
+
border: `1px solid ${theme.palette.mode === "dark" ? "#57585a" : "#E4E4E4"}`,
|
|
12
|
+
borderRadius: "50px",
|
|
13
|
+
margin: 0
|
|
14
|
+
}
|
|
15
|
+
},
|
|
16
|
+
notchedOutline: {
|
|
17
|
+
"&&": {
|
|
18
|
+
borderStyle: "none"
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
}));
|
|
22
|
+
const SearchBar = ({ path, queryParam }) => {
|
|
23
|
+
const { classes } = useStyles();
|
|
24
|
+
const [value, setValue] = useState("");
|
|
25
|
+
const ref = useRef(null);
|
|
26
|
+
const navigate = useNavigate();
|
|
27
|
+
const handleSubmit = useCallback(() => {
|
|
28
|
+
const query = ref.current?.value ?? "";
|
|
29
|
+
const url = new URL(window.location.toString());
|
|
30
|
+
url.pathname = path ?? "/search";
|
|
31
|
+
url.searchParams.set(queryParam ?? "query", query);
|
|
32
|
+
const search = url.searchParams.toString();
|
|
33
|
+
navigate(`${url.pathname}${search ? "?" : ""}${search}`);
|
|
34
|
+
}, [navigate, path, queryParam]);
|
|
35
|
+
return /* @__PURE__ */ React.createElement(
|
|
36
|
+
SearchBarBase,
|
|
37
|
+
{
|
|
38
|
+
placeholder: "Search",
|
|
39
|
+
value,
|
|
40
|
+
onChange: setValue,
|
|
41
|
+
onSubmit: handleSubmit,
|
|
42
|
+
inputProps: { ref },
|
|
43
|
+
classes: {
|
|
44
|
+
root: classes.searchBar
|
|
45
|
+
},
|
|
46
|
+
InputProps: {
|
|
47
|
+
classes: {
|
|
48
|
+
notchedOutline: classes.notchedOutline
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
);
|
|
53
|
+
};
|
|
54
|
+
|
|
55
|
+
export { SearchBar };
|
|
56
|
+
//# sourceMappingURL=SearchBar.esm.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SearchBar.esm.js","sources":["../../src/components/SearchBar.tsx"],"sourcesContent":["/*\n * Copyright 2024 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nimport React, { useCallback, useRef, useState } from 'react';\nimport { useNavigate } from 'react-router-dom';\n\nimport { SearchBarBase } from '@backstage/plugin-search-react';\n\nimport { makeStyles } from 'tss-react/mui';\n\nconst useStyles = makeStyles()(theme => ({\n searchBar: {\n '&&': {\n backgroundColor: theme.palette.mode === 'dark' ? '#36373A' : '#FFFFFF',\n boxShadow: 'none',\n border: `1px solid ${\n theme.palette.mode === 'dark' ? '#57585a' : '#E4E4E4'\n }`,\n borderRadius: '50px',\n margin: 0,\n },\n },\n notchedOutline: {\n '&&': {\n borderStyle: 'none',\n },\n },\n}));\n\n/**\n * @public\n */\nexport interface SearchBarProps {\n path?: string;\n queryParam?: string;\n}\n\n/**\n * @public\n */\nexport const SearchBar = ({ path, queryParam }: SearchBarProps) => {\n const { classes } = useStyles();\n const [value, setValue] = useState('');\n const ref = useRef<HTMLInputElement | null>(null);\n const navigate = useNavigate();\n\n // This handler is called when \"enter\" is pressed\n const handleSubmit = useCallback(() => {\n const query = ref.current?.value ?? '';\n\n const url = new URL(window.location.toString());\n url.pathname = path ?? '/search';\n url.searchParams.set(queryParam ?? 'query', query);\n const search = url.searchParams.toString();\n\n navigate(`${url.pathname}${search ? '?' : ''}${search}`);\n }, [navigate, path, queryParam]);\n\n return (\n <SearchBarBase\n placeholder=\"Search\"\n value={value}\n onChange={setValue}\n onSubmit={handleSubmit}\n inputProps={{ ref }}\n classes={{\n root: classes.searchBar,\n }}\n InputProps={{\n classes: {\n notchedOutline: classes.notchedOutline,\n },\n }}\n />\n );\n};\n"],"names":[],"mappings":";;;;;AAsBA,MAAM,SAAA,GAAY,UAAW,EAAA,CAAE,CAAU,KAAA,MAAA;AAAA,EACvC,SAAW,EAAA;AAAA,IACT,IAAM,EAAA;AAAA,MACJ,eAAiB,EAAA,KAAA,CAAM,OAAQ,CAAA,IAAA,KAAS,SAAS,SAAY,GAAA,SAAA;AAAA,MAC7D,SAAW,EAAA,MAAA;AAAA,MACX,QAAQ,CACN,UAAA,EAAA,KAAA,CAAM,QAAQ,IAAS,KAAA,MAAA,GAAS,YAAY,SAC9C,CAAA,CAAA;AAAA,MACA,YAAc,EAAA,MAAA;AAAA,MACd,MAAQ,EAAA;AAAA;AACV,GACF;AAAA,EACA,cAAgB,EAAA;AAAA,IACd,IAAM,EAAA;AAAA,MACJ,WAAa,EAAA;AAAA;AACf;AAEJ,CAAE,CAAA,CAAA;AAaK,MAAM,SAAY,GAAA,CAAC,EAAE,IAAA,EAAM,YAAiC,KAAA;AACjE,EAAM,MAAA,EAAE,OAAQ,EAAA,GAAI,SAAU,EAAA;AAC9B,EAAA,MAAM,CAAC,KAAA,EAAO,QAAQ,CAAA,GAAI,SAAS,EAAE,CAAA;AACrC,EAAM,MAAA,GAAA,GAAM,OAAgC,IAAI,CAAA;AAChD,EAAA,MAAM,WAAW,WAAY,EAAA;AAG7B,EAAM,MAAA,YAAA,GAAe,YAAY,MAAM;AACrC,IAAM,MAAA,KAAA,GAAQ,GAAI,CAAA,OAAA,EAAS,KAAS,IAAA,EAAA;AAEpC,IAAA,MAAM,MAAM,IAAI,GAAA,CAAI,MAAO,CAAA,QAAA,CAAS,UAAU,CAAA;AAC9C,IAAA,GAAA,CAAI,WAAW,IAAQ,IAAA,SAAA;AACvB,IAAA,GAAA,CAAI,YAAa,CAAA,GAAA,CAAI,UAAc,IAAA,OAAA,EAAS,KAAK,CAAA;AACjD,IAAM,MAAA,MAAA,GAAS,GAAI,CAAA,YAAA,CAAa,QAAS,EAAA;AAEzC,IAAS,QAAA,CAAA,CAAA,EAAG,IAAI,QAAQ,CAAA,EAAG,SAAS,GAAM,GAAA,EAAE,CAAG,EAAA,MAAM,CAAE,CAAA,CAAA;AAAA,GACtD,EAAA,CAAC,QAAU,EAAA,IAAA,EAAM,UAAU,CAAC,CAAA;AAE/B,EACE,uBAAA,KAAA,CAAA,aAAA;AAAA,IAAC,aAAA;AAAA,IAAA;AAAA,MACC,WAAY,EAAA,QAAA;AAAA,MACZ,KAAA;AAAA,MACA,QAAU,EAAA,QAAA;AAAA,MACV,QAAU,EAAA,YAAA;AAAA,MACV,UAAA,EAAY,EAAE,GAAI,EAAA;AAAA,MAClB,OAAS,EAAA;AAAA,QACP,MAAM,OAAQ,CAAA;AAAA,OAChB;AAAA,MACA,UAAY,EAAA;AAAA,QACV,OAAS,EAAA;AAAA,UACP,gBAAgB,OAAQ,CAAA;AAAA;AAC1B;AACF;AAAA,GACF;AAEJ;;;;"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { useScalprum } from '@scalprum/react-core';
|
|
2
|
+
|
|
3
|
+
const useHomePageMountPoints = () => {
|
|
4
|
+
const scalprum = useScalprum();
|
|
5
|
+
const homePageMountPoints = scalprum?.api?.dynamicRootConfig?.mountPoints?.["home.page/cards"];
|
|
6
|
+
return homePageMountPoints;
|
|
7
|
+
};
|
|
8
|
+
|
|
9
|
+
export { useHomePageMountPoints };
|
|
10
|
+
//# sourceMappingURL=useHomePageMountPoints.esm.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useHomePageMountPoints.esm.js","sources":["../../src/hooks/useHomePageMountPoints.ts"],"sourcesContent":["/*\n * Copyright 2024 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nimport { useScalprum } from '@scalprum/react-core';\n\nimport { HomePageCardMountPoint } from '../types';\n\ninterface ScalprumState {\n api?: {\n dynamicRootConfig?: {\n mountPoints?: {\n 'home.page/cards': HomePageCardMountPoint[];\n };\n };\n };\n}\n\nexport const useHomePageMountPoints = ():\n | HomePageCardMountPoint[]\n | undefined => {\n const scalprum = useScalprum<ScalprumState>();\n\n const homePageMountPoints =\n scalprum?.api?.dynamicRootConfig?.mountPoints?.['home.page/cards'];\n\n return homePageMountPoints;\n};\n"],"names":[],"mappings":";;AA6BO,MAAM,yBAAyB,MAErB;AACf,EAAA,MAAM,WAAW,WAA2B,EAAA;AAE5C,EAAA,MAAM,mBACJ,GAAA,QAAA,EAAU,GAAK,EAAA,iBAAA,EAAmB,cAAc,iBAAiB,CAAA;AAEnE,EAAO,OAAA,mBAAA;AACT;;;;"}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { useState, useCallback, useEffect } from 'react';
|
|
2
|
+
import useAsync from 'react-use/lib/useAsync';
|
|
3
|
+
import { useApi } from '@backstage/core-plugin-api';
|
|
4
|
+
import { quickAccessApiRef } from '../api/QuickAccessApiClient.esm.js';
|
|
5
|
+
|
|
6
|
+
const useQuickAccessLinks = (path) => {
|
|
7
|
+
const [isLoading, setIsLoading] = useState(true);
|
|
8
|
+
const [data, setData] = useState();
|
|
9
|
+
const [error, setError] = useState();
|
|
10
|
+
const client = useApi(quickAccessApiRef);
|
|
11
|
+
const {
|
|
12
|
+
value,
|
|
13
|
+
error: apiError,
|
|
14
|
+
loading
|
|
15
|
+
} = useAsync(() => {
|
|
16
|
+
return client.getQuickAccessLinks(path);
|
|
17
|
+
});
|
|
18
|
+
const fetchData = useCallback(async () => {
|
|
19
|
+
const res = await fetch("/homepage/data.json");
|
|
20
|
+
const qsData = await res.json();
|
|
21
|
+
setData(qsData);
|
|
22
|
+
setIsLoading(false);
|
|
23
|
+
}, []);
|
|
24
|
+
useEffect(() => {
|
|
25
|
+
if (apiError) {
|
|
26
|
+
setError(apiError);
|
|
27
|
+
fetchData().catch((err) => {
|
|
28
|
+
setError(err);
|
|
29
|
+
setIsLoading(false);
|
|
30
|
+
});
|
|
31
|
+
} else if (!loading && value) {
|
|
32
|
+
setData(value);
|
|
33
|
+
setIsLoading(false);
|
|
34
|
+
}
|
|
35
|
+
}, [apiError, fetchData, loading, setData, value]);
|
|
36
|
+
return { data, error, isLoading };
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
export { useQuickAccessLinks };
|
|
40
|
+
//# sourceMappingURL=useQuickAccessLinks.esm.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useQuickAccessLinks.esm.js","sources":["../../src/hooks/useQuickAccessLinks.ts"],"sourcesContent":["/*\n * Copyright 2024 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nimport { useCallback, useEffect, useState } from 'react';\nimport useAsync from 'react-use/lib/useAsync';\n\nimport { useApi } from '@backstage/core-plugin-api';\n\nimport { quickAccessApiRef } from '../api/QuickAccessApiClient';\nimport { QuickAccessLink } from '../types';\n\nexport const useQuickAccessLinks = (\n path?: string,\n): {\n data: QuickAccessLink[] | undefined;\n error: Error | undefined;\n isLoading: boolean;\n} => {\n const [isLoading, setIsLoading] = useState<boolean>(true);\n const [data, setData] = useState<QuickAccessLink[]>();\n const [error, setError] = useState<Error>();\n const client = useApi(quickAccessApiRef);\n const {\n value,\n error: apiError,\n loading,\n } = useAsync(() => {\n return client.getQuickAccessLinks(path);\n });\n\n const fetchData = useCallback(async () => {\n const res = await fetch('/homepage/data.json');\n const qsData = await res.json();\n setData(qsData);\n setIsLoading(false);\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, []);\n\n useEffect(() => {\n if (apiError) {\n setError(apiError);\n fetchData().catch(err => {\n setError(err);\n setIsLoading(false);\n });\n } else if (!loading && value) {\n setData(value);\n setIsLoading(false);\n }\n }, [apiError, fetchData, loading, setData, value]);\n\n return { data, error, isLoading };\n};\n"],"names":[],"mappings":";;;;;AAuBa,MAAA,mBAAA,GAAsB,CACjC,IAKG,KAAA;AACH,EAAA,MAAM,CAAC,SAAA,EAAW,YAAY,CAAA,GAAI,SAAkB,IAAI,CAAA;AACxD,EAAA,MAAM,CAAC,IAAA,EAAM,OAAO,CAAA,GAAI,QAA4B,EAAA;AACpD,EAAA,MAAM,CAAC,KAAA,EAAO,QAAQ,CAAA,GAAI,QAAgB,EAAA;AAC1C,EAAM,MAAA,MAAA,GAAS,OAAO,iBAAiB,CAAA;AACvC,EAAM,MAAA;AAAA,IACJ,KAAA;AAAA,IACA,KAAO,EAAA,QAAA;AAAA,IACP;AAAA,GACF,GAAI,SAAS,MAAM;AACjB,IAAO,OAAA,MAAA,CAAO,oBAAoB,IAAI,CAAA;AAAA,GACvC,CAAA;AAED,EAAM,MAAA,SAAA,GAAY,YAAY,YAAY;AACxC,IAAM,MAAA,GAAA,GAAM,MAAM,KAAA,CAAM,qBAAqB,CAAA;AAC7C,IAAM,MAAA,MAAA,GAAS,MAAM,GAAA,CAAI,IAAK,EAAA;AAC9B,IAAA,OAAA,CAAQ,MAAM,CAAA;AACd,IAAA,YAAA,CAAa,KAAK,CAAA;AAAA,GAEpB,EAAG,EAAE,CAAA;AAEL,EAAA,SAAA,CAAU,MAAM;AACd,IAAA,IAAI,QAAU,EAAA;AACZ,MAAA,QAAA,CAAS,QAAQ,CAAA;AACjB,MAAU,SAAA,EAAA,CAAE,MAAM,CAAO,GAAA,KAAA;AACvB,QAAA,QAAA,CAAS,GAAG,CAAA;AACZ,QAAA,YAAA,CAAa,KAAK,CAAA;AAAA,OACnB,CAAA;AAAA,KACH,MAAA,IAAW,CAAC,OAAA,IAAW,KAAO,EAAA;AAC5B,MAAA,OAAA,CAAQ,KAAK,CAAA;AACb,MAAA,YAAA,CAAa,KAAK,CAAA;AAAA;AACpB,KACC,CAAC,QAAA,EAAU,WAAW,OAAS,EAAA,OAAA,EAAS,KAAK,CAAC,CAAA;AAEjD,EAAO,OAAA,EAAE,IAAM,EAAA,KAAA,EAAO,SAAU,EAAA;AAClC;;;;"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
import * as _backstage_core_plugin_api from '@backstage/core-plugin-api';
|
|
2
|
+
import React from 'react';
|
|
3
|
+
import { StarredEntitiesProps, VisitedByTypeProps, FeaturedDocsCardProps } from '@backstage/plugin-home';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* @public
|
|
7
|
+
*/
|
|
8
|
+
interface DynamicHomePageProps {
|
|
9
|
+
title?: string;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* @public
|
|
14
|
+
*/
|
|
15
|
+
interface SearchBarProps {
|
|
16
|
+
path?: string;
|
|
17
|
+
queryParam?: string;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* @public
|
|
22
|
+
*/
|
|
23
|
+
interface QuickAccessCardProps {
|
|
24
|
+
title?: string;
|
|
25
|
+
path?: string;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* @public
|
|
30
|
+
*/
|
|
31
|
+
interface HeadlineProps {
|
|
32
|
+
title?: string;
|
|
33
|
+
align?: 'left' | 'center' | 'right';
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* @public
|
|
38
|
+
*/
|
|
39
|
+
interface MarkdownProps {
|
|
40
|
+
title?: string;
|
|
41
|
+
content?: string;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* @public
|
|
46
|
+
*/
|
|
47
|
+
interface MarkdownCardProps {
|
|
48
|
+
title?: string;
|
|
49
|
+
content?: string;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* @public
|
|
54
|
+
*/
|
|
55
|
+
interface PlaceholderProps {
|
|
56
|
+
showBorder?: boolean;
|
|
57
|
+
debugContent?: string;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* Dynamic Home Page Plugin
|
|
62
|
+
* @public
|
|
63
|
+
*/
|
|
64
|
+
declare const dynamicHomePagePlugin: _backstage_core_plugin_api.BackstagePlugin<{
|
|
65
|
+
root: _backstage_core_plugin_api.RouteRef<undefined>;
|
|
66
|
+
}, {}, {}>;
|
|
67
|
+
/**
|
|
68
|
+
* Dynamic Home Page
|
|
69
|
+
* @public
|
|
70
|
+
*/
|
|
71
|
+
declare const DynamicHomePage: React.ComponentType<DynamicHomePageProps>;
|
|
72
|
+
/**
|
|
73
|
+
* @public
|
|
74
|
+
*/
|
|
75
|
+
declare const SearchBar: React.ComponentType<SearchBarProps>;
|
|
76
|
+
/**
|
|
77
|
+
* @public
|
|
78
|
+
*/
|
|
79
|
+
declare const QuickAccessCard: React.ComponentType<QuickAccessCardProps>;
|
|
80
|
+
/**
|
|
81
|
+
* @public
|
|
82
|
+
*/
|
|
83
|
+
declare const Headline: React.ComponentType<HeadlineProps>;
|
|
84
|
+
/**
|
|
85
|
+
* @public
|
|
86
|
+
*/
|
|
87
|
+
declare const Markdown: React.ComponentType<MarkdownProps>;
|
|
88
|
+
/**
|
|
89
|
+
* @public
|
|
90
|
+
*/
|
|
91
|
+
declare const MarkdownCard: React.ComponentType<MarkdownCardProps>;
|
|
92
|
+
/**
|
|
93
|
+
* @public
|
|
94
|
+
*/
|
|
95
|
+
declare const Placeholder: React.ComponentType<PlaceholderProps>;
|
|
96
|
+
/**
|
|
97
|
+
* @public
|
|
98
|
+
*/
|
|
99
|
+
declare const CatalogStarredEntitiesCard: React.ComponentType<StarredEntitiesProps>;
|
|
100
|
+
/**
|
|
101
|
+
* @public
|
|
102
|
+
*/
|
|
103
|
+
declare const RecentlyVisitedCard: React.ComponentType<VisitedByTypeProps>;
|
|
104
|
+
/**
|
|
105
|
+
* @public
|
|
106
|
+
*/
|
|
107
|
+
declare const TopVisitedCard: React.ComponentType<VisitedByTypeProps>;
|
|
108
|
+
/**
|
|
109
|
+
* @public
|
|
110
|
+
*/
|
|
111
|
+
declare const FeaturedDocsCard: React.ComponentType<FeaturedDocsCardProps>;
|
|
112
|
+
/**
|
|
113
|
+
* @public
|
|
114
|
+
*/
|
|
115
|
+
declare const JokeCard: React.ComponentType<{
|
|
116
|
+
defaultCategory?: 'any' | 'programming';
|
|
117
|
+
}>;
|
|
118
|
+
|
|
119
|
+
export { CatalogStarredEntitiesCard, DynamicHomePage, type DynamicHomePageProps, FeaturedDocsCard, Headline, type HeadlineProps, JokeCard, Markdown, MarkdownCard, type MarkdownCardProps, type MarkdownProps, Placeholder, type PlaceholderProps, QuickAccessCard, type QuickAccessCardProps, RecentlyVisitedCard, SearchBar, type SearchBarProps, TopVisitedCard, dynamicHomePagePlugin };
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
export { CatalogStarredEntitiesCard, DynamicHomePage, FeaturedDocsCard, Headline, JokeCard, Markdown, MarkdownCard, Placeholder, QuickAccessCard, RecentlyVisitedCard, SearchBar, TopVisitedCard, dynamicHomePagePlugin } from './plugin.esm.js';
|
|
2
|
+
//# sourceMappingURL=index.esm.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.esm.js","sources":[],"sourcesContent":[],"names":[],"mappings":""}
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
import { createPlugin, createApiFactory, discoveryApiRef, configApiRef, identityApiRef, createRoutableExtension, createComponentExtension } from '@backstage/core-plugin-api';
|
|
2
|
+
import { quickAccessApiRef, QuickAccessApiClient } from './api/QuickAccessApiClient.esm.js';
|
|
3
|
+
import { rootRouteRef } from './routes.esm.js';
|
|
4
|
+
|
|
5
|
+
const dynamicHomePagePlugin = createPlugin({
|
|
6
|
+
id: "dynamic-home-page",
|
|
7
|
+
routes: {
|
|
8
|
+
root: rootRouteRef
|
|
9
|
+
},
|
|
10
|
+
apis: [
|
|
11
|
+
createApiFactory({
|
|
12
|
+
api: quickAccessApiRef,
|
|
13
|
+
deps: {
|
|
14
|
+
discoveryApi: discoveryApiRef,
|
|
15
|
+
configApi: configApiRef,
|
|
16
|
+
identityApi: identityApiRef
|
|
17
|
+
},
|
|
18
|
+
factory: ({ discoveryApi, configApi, identityApi }) => new QuickAccessApiClient({ discoveryApi, configApi, identityApi })
|
|
19
|
+
})
|
|
20
|
+
]
|
|
21
|
+
});
|
|
22
|
+
const DynamicHomePage = dynamicHomePagePlugin.provide(
|
|
23
|
+
createRoutableExtension({
|
|
24
|
+
name: "DynamicHomePage",
|
|
25
|
+
component: () => import('./components/DynamicHomePage.esm.js').then((m) => m.DynamicHomePage),
|
|
26
|
+
mountPoint: rootRouteRef
|
|
27
|
+
})
|
|
28
|
+
);
|
|
29
|
+
const SearchBar = dynamicHomePagePlugin.provide(
|
|
30
|
+
createComponentExtension({
|
|
31
|
+
name: "SearchBar",
|
|
32
|
+
component: {
|
|
33
|
+
lazy: () => import('./components/SearchBar.esm.js').then((m) => m.SearchBar)
|
|
34
|
+
}
|
|
35
|
+
})
|
|
36
|
+
);
|
|
37
|
+
const QuickAccessCard = dynamicHomePagePlugin.provide(
|
|
38
|
+
createComponentExtension({
|
|
39
|
+
name: "QuickAccessCard",
|
|
40
|
+
component: {
|
|
41
|
+
lazy: () => import('./components/QuickAccessCard.esm.js').then((m) => m.QuickAccessCard)
|
|
42
|
+
}
|
|
43
|
+
})
|
|
44
|
+
);
|
|
45
|
+
const Headline = dynamicHomePagePlugin.provide(
|
|
46
|
+
createComponentExtension({
|
|
47
|
+
name: "Headline",
|
|
48
|
+
component: {
|
|
49
|
+
lazy: () => import('./components/Headline.esm.js').then((m) => m.Headline)
|
|
50
|
+
}
|
|
51
|
+
})
|
|
52
|
+
);
|
|
53
|
+
const Markdown = dynamicHomePagePlugin.provide(
|
|
54
|
+
createComponentExtension({
|
|
55
|
+
name: "Markdown",
|
|
56
|
+
component: {
|
|
57
|
+
lazy: () => import('./components/Markdown.esm.js').then((m) => m.Markdown)
|
|
58
|
+
}
|
|
59
|
+
})
|
|
60
|
+
);
|
|
61
|
+
const MarkdownCard = dynamicHomePagePlugin.provide(
|
|
62
|
+
createComponentExtension({
|
|
63
|
+
name: "MarkdownCard",
|
|
64
|
+
component: {
|
|
65
|
+
lazy: () => import('./components/MarkdownCard.esm.js').then((m) => m.MarkdownCard)
|
|
66
|
+
}
|
|
67
|
+
})
|
|
68
|
+
);
|
|
69
|
+
const Placeholder = dynamicHomePagePlugin.provide(
|
|
70
|
+
createComponentExtension({
|
|
71
|
+
name: "MarkdownCard",
|
|
72
|
+
component: {
|
|
73
|
+
lazy: () => import('./components/Placeholder.esm.js').then((m) => m.Placeholder)
|
|
74
|
+
}
|
|
75
|
+
})
|
|
76
|
+
);
|
|
77
|
+
const CatalogStarredEntitiesCard = dynamicHomePagePlugin.provide(
|
|
78
|
+
createComponentExtension({
|
|
79
|
+
name: "CatalogStarredEntitiesCard",
|
|
80
|
+
component: {
|
|
81
|
+
lazy: () => import('@backstage/plugin-home').then((m) => m.HomePageStarredEntities)
|
|
82
|
+
}
|
|
83
|
+
})
|
|
84
|
+
);
|
|
85
|
+
const RecentlyVisitedCard = dynamicHomePagePlugin.provide(
|
|
86
|
+
createComponentExtension({
|
|
87
|
+
name: "RecentlyVisitedCard",
|
|
88
|
+
component: {
|
|
89
|
+
lazy: () => import('@backstage/plugin-home').then((m) => m.HomePageRecentlyVisited)
|
|
90
|
+
}
|
|
91
|
+
})
|
|
92
|
+
);
|
|
93
|
+
const TopVisitedCard = dynamicHomePagePlugin.provide(
|
|
94
|
+
createComponentExtension({
|
|
95
|
+
name: "TopVisitedCard",
|
|
96
|
+
component: {
|
|
97
|
+
lazy: () => import('@backstage/plugin-home').then((m) => m.HomePageTopVisited)
|
|
98
|
+
}
|
|
99
|
+
})
|
|
100
|
+
);
|
|
101
|
+
const FeaturedDocsCard = dynamicHomePagePlugin.provide(
|
|
102
|
+
createComponentExtension({
|
|
103
|
+
name: "FeaturedDocsCard",
|
|
104
|
+
component: {
|
|
105
|
+
lazy: () => import('@backstage/plugin-home').then((m) => m.FeaturedDocsCard)
|
|
106
|
+
}
|
|
107
|
+
})
|
|
108
|
+
);
|
|
109
|
+
const JokeCard = dynamicHomePagePlugin.provide(
|
|
110
|
+
createComponentExtension({
|
|
111
|
+
name: "JokeCard",
|
|
112
|
+
component: {
|
|
113
|
+
lazy: () => import('@backstage/plugin-home').then((m) => m.HomePageRandomJoke)
|
|
114
|
+
}
|
|
115
|
+
})
|
|
116
|
+
);
|
|
117
|
+
|
|
118
|
+
export { CatalogStarredEntitiesCard, DynamicHomePage, FeaturedDocsCard, Headline, JokeCard, Markdown, MarkdownCard, Placeholder, QuickAccessCard, RecentlyVisitedCard, SearchBar, TopVisitedCard, dynamicHomePagePlugin };
|
|
119
|
+
//# sourceMappingURL=plugin.esm.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"plugin.esm.js","sources":["../src/plugin.ts"],"sourcesContent":["/*\n * Copyright 2024 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nimport React from 'react';\n\nimport {\n configApiRef,\n createApiFactory,\n createComponentExtension,\n createPlugin,\n createRoutableExtension,\n discoveryApiRef,\n identityApiRef,\n} from '@backstage/core-plugin-api';\nimport type {\n FeaturedDocsCardProps,\n StarredEntitiesProps,\n VisitedByTypeProps,\n} from '@backstage/plugin-home';\n\nimport { QuickAccessApiClient, quickAccessApiRef } from './api';\nimport { rootRouteRef } from './routes';\n\nimport type { DynamicHomePageProps } from './components/DynamicHomePage';\nimport type { SearchBarProps } from './components/SearchBar';\nimport type { QuickAccessCardProps } from './components/QuickAccessCard';\nimport type { HeadlineProps } from './components/Headline';\nimport type { MarkdownProps } from './components/Markdown';\nimport type { MarkdownCardProps } from './components/MarkdownCard';\nimport type { PlaceholderProps } from './components/Placeholder';\n\nexport type { DynamicHomePageProps } from './components/DynamicHomePage';\nexport type { SearchBarProps } from './components/SearchBar';\nexport type { QuickAccessCardProps } from './components/QuickAccessCard';\nexport type { HeadlineProps } from './components/Headline';\nexport type { MarkdownProps } from './components/Markdown';\nexport type { MarkdownCardProps } from './components/MarkdownCard';\nexport type { PlaceholderProps } from './components/Placeholder';\n\n/**\n * Dynamic Home Page Plugin\n * @public\n */\nexport const dynamicHomePagePlugin = createPlugin({\n id: 'dynamic-home-page',\n routes: {\n root: rootRouteRef,\n },\n apis: [\n createApiFactory({\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/**\n * Dynamic Home Page\n * @public\n */\nexport const DynamicHomePage: React.ComponentType<DynamicHomePageProps> =\n dynamicHomePagePlugin.provide(\n createRoutableExtension({\n name: 'DynamicHomePage',\n component: () =>\n import('./components/DynamicHomePage').then(m => m.DynamicHomePage),\n mountPoint: rootRouteRef,\n }),\n );\n\n/**\n * @public\n */\nexport const SearchBar: React.ComponentType<SearchBarProps> =\n dynamicHomePagePlugin.provide(\n createComponentExtension({\n name: 'SearchBar',\n component: {\n lazy: () => import('./components/SearchBar').then(m => m.SearchBar),\n },\n }),\n );\n\n/**\n * @public\n */\nexport const QuickAccessCard: React.ComponentType<QuickAccessCardProps> =\n dynamicHomePagePlugin.provide(\n createComponentExtension({\n name: 'QuickAccessCard',\n component: {\n lazy: () =>\n import('./components/QuickAccessCard').then(m => m.QuickAccessCard),\n },\n }),\n );\n\n/**\n * @public\n */\nexport const Headline: React.ComponentType<HeadlineProps> =\n dynamicHomePagePlugin.provide(\n createComponentExtension({\n name: 'Headline',\n component: {\n lazy: () => import('./components/Headline').then(m => m.Headline),\n },\n }),\n );\n\n/**\n * @public\n */\nexport const Markdown: React.ComponentType<MarkdownProps> =\n dynamicHomePagePlugin.provide(\n createComponentExtension({\n name: 'Markdown',\n component: {\n lazy: () => import('./components/Markdown').then(m => m.Markdown),\n },\n }),\n );\n\n/**\n * @public\n */\nexport const MarkdownCard: React.ComponentType<MarkdownCardProps> =\n dynamicHomePagePlugin.provide(\n createComponentExtension({\n name: 'MarkdownCard',\n component: {\n lazy: () =>\n import('./components/MarkdownCard').then(m => m.MarkdownCard),\n },\n }),\n );\n\n/**\n * @public\n */\nexport const Placeholder: React.ComponentType<PlaceholderProps> =\n dynamicHomePagePlugin.provide(\n createComponentExtension({\n name: 'MarkdownCard',\n component: {\n lazy: () => import('./components/Placeholder').then(m => m.Placeholder),\n },\n }),\n );\n\n/**\n * @public\n */\nexport const CatalogStarredEntitiesCard: React.ComponentType<StarredEntitiesProps> =\n dynamicHomePagePlugin.provide(\n createComponentExtension({\n name: 'CatalogStarredEntitiesCard',\n component: {\n lazy: () =>\n import('@backstage/plugin-home').then(m => m.HomePageStarredEntities),\n },\n }),\n );\n\n/**\n * @public\n */\nexport const RecentlyVisitedCard: React.ComponentType<VisitedByTypeProps> =\n dynamicHomePagePlugin.provide(\n createComponentExtension({\n name: 'RecentlyVisitedCard',\n component: {\n lazy: () =>\n import('@backstage/plugin-home').then(m => m.HomePageRecentlyVisited),\n },\n }),\n );\n\n/**\n * @public\n */\nexport const TopVisitedCard: React.ComponentType<VisitedByTypeProps> =\n dynamicHomePagePlugin.provide(\n createComponentExtension({\n name: 'TopVisitedCard',\n component: {\n lazy: () =>\n import('@backstage/plugin-home').then(m => m.HomePageTopVisited),\n },\n }),\n );\n\n/**\n * @public\n */\nexport const FeaturedDocsCard: React.ComponentType<FeaturedDocsCardProps> =\n dynamicHomePagePlugin.provide(\n createComponentExtension({\n name: 'FeaturedDocsCard',\n component: {\n lazy: () =>\n import('@backstage/plugin-home').then(m => m.FeaturedDocsCard),\n },\n }),\n );\n\n/**\n * @public\n */\nexport const JokeCard: React.ComponentType<{\n defaultCategory?: 'any' | 'programming';\n}> = dynamicHomePagePlugin.provide(\n createComponentExtension({\n name: 'JokeCard',\n component: {\n lazy: () =>\n import('@backstage/plugin-home').then(m => m.HomePageRandomJoke),\n },\n }),\n);\n"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"routes.esm.js","sources":["../src/routes.ts"],"sourcesContent":["/*\n * Copyright 2024 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nimport { createRouteRef } from '@backstage/core-plugin-api';\n\nexport const rootRouteRef = createRouteRef({\n id: 'dynamic-home-page',\n});\n"],"names":[],"mappings":";;AAiBO,MAAM,eAAe,cAAe,CAAA;AAAA,EACzC,EAAI,EAAA;AACN,CAAC;;;;"}
|
package/package.json
ADDED
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@red-hat-developer-hub/backstage-plugin-dynamic-home-page",
|
|
3
|
+
"version": "0.0.1",
|
|
4
|
+
"main": "dist/index.esm.js",
|
|
5
|
+
"types": "dist/index.d.ts",
|
|
6
|
+
"license": "Apache-2.0",
|
|
7
|
+
"publishConfig": {
|
|
8
|
+
"access": "public",
|
|
9
|
+
"main": "dist/index.esm.js",
|
|
10
|
+
"types": "dist/index.d.ts"
|
|
11
|
+
},
|
|
12
|
+
"repository": {
|
|
13
|
+
"type": "git",
|
|
14
|
+
"url": "https://github.com/redhat-developer/rhdh-plugins",
|
|
15
|
+
"directory": "workspaces/homepage/plugins/dynamic-home-page"
|
|
16
|
+
},
|
|
17
|
+
"backstage": {
|
|
18
|
+
"role": "frontend-plugin",
|
|
19
|
+
"pluginId": "@red-hat-developer-hub/backstage-plugin-dynamic-home-page",
|
|
20
|
+
"pluginPackages": [
|
|
21
|
+
"@red-hat-developer-hub/backstage-plugin-dynamic-home-page"
|
|
22
|
+
]
|
|
23
|
+
},
|
|
24
|
+
"sideEffects": false,
|
|
25
|
+
"scripts": {
|
|
26
|
+
"start": "backstage-cli package start",
|
|
27
|
+
"build": "backstage-cli package build",
|
|
28
|
+
"lint": "backstage-cli package lint",
|
|
29
|
+
"test": "backstage-cli package test",
|
|
30
|
+
"clean": "backstage-cli package clean",
|
|
31
|
+
"prepack": "backstage-cli package prepack",
|
|
32
|
+
"postpack": "backstage-cli package postpack"
|
|
33
|
+
},
|
|
34
|
+
"dependencies": {
|
|
35
|
+
"@backstage/core-components": "0.15.1",
|
|
36
|
+
"@backstage/core-plugin-api": "1.10.0",
|
|
37
|
+
"@backstage/plugin-catalog-react": "1.14.0",
|
|
38
|
+
"@backstage/plugin-home": "0.8.0",
|
|
39
|
+
"@backstage/plugin-home-react": "0.1.18",
|
|
40
|
+
"@backstage/plugin-search": "1.4.18",
|
|
41
|
+
"@backstage/plugin-search-react": "1.8.1",
|
|
42
|
+
"@backstage/theme": "0.6.0",
|
|
43
|
+
"@mui/material": "5.16.7",
|
|
44
|
+
"@mui/styles": "5.16.7",
|
|
45
|
+
"@scalprum/react-core": "0.8.0",
|
|
46
|
+
"react-grid-layout": "1.4.4",
|
|
47
|
+
"react-use": "17.5.1",
|
|
48
|
+
"tss-react": "4.9.12"
|
|
49
|
+
},
|
|
50
|
+
"peerDependencies": {
|
|
51
|
+
"react": "16.13.1 || ^17.0.0 || ^18.2.0",
|
|
52
|
+
"react-router-dom": "6.26.2"
|
|
53
|
+
},
|
|
54
|
+
"devDependencies": {
|
|
55
|
+
"@backstage/cli": "0.28.2",
|
|
56
|
+
"@backstage/core-app-api": "1.15.1",
|
|
57
|
+
"@backstage/dev-utils": "1.1.2",
|
|
58
|
+
"@backstage/test-utils": "1.7.0",
|
|
59
|
+
"@openshift/dynamic-plugin-sdk": "5.0.1",
|
|
60
|
+
"@redhat-developer/red-hat-developer-hub-theme": "0.4.0",
|
|
61
|
+
"@testing-library/jest-dom": "6.6.3",
|
|
62
|
+
"@testing-library/react": "14.3.1",
|
|
63
|
+
"@testing-library/user-event": "14.5.2",
|
|
64
|
+
"@types/react-grid-layout": "1.3.5",
|
|
65
|
+
"msw": "1.3.4",
|
|
66
|
+
"react": "^16.13.1 || ^17.0.0 || ^18.0.0"
|
|
67
|
+
},
|
|
68
|
+
"files": [
|
|
69
|
+
"app-config.dynamic.yaml",
|
|
70
|
+
"dist"
|
|
71
|
+
],
|
|
72
|
+
"module": "./dist/index.esm.js"
|
|
73
|
+
}
|