@backstage/plugin-catalog 2.0.9-next.1 → 2.0.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +49 -0
- package/dist/alpha/components/EntityContextMenu/EntityContextMenu.esm.js +1 -1
- package/dist/alpha/components/EntityContextMenu/EntityContextMenu.esm.js.map +1 -1
- package/dist/alpha/components/EntityHeader/EntityHeader.esm.js +2 -2
- package/dist/alpha/components/EntityHeader/EntityHeader.esm.js.map +1 -1
- package/dist/alpha/components/EntityHeader/EntityHeaderBui.esm.js +1 -1
- package/dist/alpha/components/EntityHeader/EntityHeaderBui.esm.js.map +1 -1
- package/dist/alpha/entityCards.esm.js +21 -17
- package/dist/alpha/entityCards.esm.js.map +1 -1
- package/dist/alpha/filter/matchers/createHasMatcher.esm.js +1 -1
- package/dist/alpha/filter/matchers/createHasMatcher.esm.js.map +1 -1
- package/dist/alpha/filter/matchers/createIsMatcher.esm.js +1 -1
- package/dist/alpha/filter/matchers/createIsMatcher.esm.js.map +1 -1
- package/dist/alpha/filter/matchers/createKindMatcher.esm.js +2 -2
- package/dist/alpha/filter/matchers/createKindMatcher.esm.js.map +1 -1
- package/dist/alpha/filter/matchers/createTypeMatcher.esm.js +2 -2
- package/dist/alpha/filter/matchers/createTypeMatcher.esm.js.map +1 -1
- package/dist/apis/EntityPresentationApi/DefaultEntityPresentationApi.esm.js +3 -3
- package/dist/apis/EntityPresentationApi/DefaultEntityPresentationApi.esm.js.map +1 -1
- package/dist/components/AboutCard/AboutContent.esm.js +7 -7
- package/dist/components/AboutCard/AboutContent.esm.js.map +1 -1
- package/dist/components/AboutCard/AboutField.esm.js +2 -1
- package/dist/components/AboutCard/AboutField.esm.js.map +1 -1
- package/dist/components/CatalogKindHeader/CatalogKindHeader.esm.js +2 -2
- package/dist/components/CatalogKindHeader/CatalogKindHeader.esm.js.map +1 -1
- package/dist/components/CatalogKindHeader/kindFilterUtils.esm.js +3 -5
- package/dist/components/CatalogKindHeader/kindFilterUtils.esm.js.map +1 -1
- package/dist/components/CatalogTable/CatalogTable.esm.js +1 -1
- package/dist/components/CatalogTable/CatalogTable.esm.js.map +1 -1
- package/dist/components/CatalogTable/columns.esm.js +3 -3
- package/dist/components/CatalogTable/columns.esm.js.map +1 -1
- package/dist/components/CatalogTable/defaultCatalogTableColumnsFunc.esm.js +1 -1
- package/dist/components/CatalogTable/defaultCatalogTableColumnsFunc.esm.js.map +1 -1
- package/dist/components/EntityLayout/EntityLayout.esm.js +2 -2
- package/dist/components/EntityLayout/EntityLayout.esm.js.map +1 -1
- package/dist/components/EntitySwitch/conditions.esm.js +1 -1
- package/dist/components/EntitySwitch/conditions.esm.js.map +1 -1
- package/dist/index.d.ts +8 -8
- package/dist/plugin.esm.js.map +1 -1
- package/dist/plugins/catalog/package.json.esm.js +1 -1
- package/package.json +26 -26
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,54 @@
|
|
|
1
1
|
# @backstage/plugin-catalog
|
|
2
2
|
|
|
3
|
+
## 2.0.9
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- 8e0e3c4: Fixed a regression where the About card's field labels (OWNER, SYSTEM, TAGS, etc.) lost their vertical gap above the value.
|
|
8
|
+
- e3781a3: Fixed circular dependency warnings when building the catalog plugin.
|
|
9
|
+
- d9a949e: Fixed the About card to safely show and hide filtered icon links when navigating between entities, without initializing hidden links.
|
|
10
|
+
- 736d84e: Use locale-insensitive Unicode casing for consistent string handling across environments.
|
|
11
|
+
- 4611178: Add support for legacy props in catalog entity card exports by widening the public TypeScript prop types. This ensures compatibility for consumers still using legacy properties such as `variant` and `columns`.
|
|
12
|
+
- d421187: Reduced the initial app bundle size by loading page and optional UI implementations only when their extensions render.
|
|
13
|
+
- acc6666: Fixed entity context menus to report errors from contributed items without disrupting the menu.
|
|
14
|
+
- Updated dependencies
|
|
15
|
+
- @backstage/core-components@0.18.14
|
|
16
|
+
- @backstage/plugin-catalog-common@1.2.0
|
|
17
|
+
- @backstage/plugin-scaffolder-common@2.3.0
|
|
18
|
+
- @backstage/ui@0.18.0
|
|
19
|
+
- @backstage/catalog-client@1.16.2
|
|
20
|
+
- @backstage/catalog-model@1.10.1
|
|
21
|
+
- @backstage/plugin-catalog-react@3.2.3
|
|
22
|
+
- @backstage/plugin-techdocs-react@1.3.15
|
|
23
|
+
- @backstage/frontend-plugin-api@0.18.1
|
|
24
|
+
- @backstage/core-compat-api@0.5.15
|
|
25
|
+
- @backstage/core-plugin-api@1.12.10
|
|
26
|
+
- @backstage/integration-react@1.2.22
|
|
27
|
+
- @backstage/plugin-permission-react@0.5.5
|
|
28
|
+
- @backstage/plugin-search-common@1.2.25
|
|
29
|
+
- @backstage/plugin-search-react@1.11.8
|
|
30
|
+
|
|
31
|
+
## 2.0.9-next.2
|
|
32
|
+
|
|
33
|
+
### Patch Changes
|
|
34
|
+
|
|
35
|
+
- 4611178: Add support for legacy props in catalog entity card exports by widening the public TypeScript prop types. This ensures compatibility for consumers still using legacy properties such as `variant` and `columns`.
|
|
36
|
+
- acc6666: Fixed entity context menus to report errors from contributed items without disrupting the menu.
|
|
37
|
+
- Updated dependencies
|
|
38
|
+
- @backstage/plugin-catalog-common@1.2.0-next.0
|
|
39
|
+
- @backstage/ui@0.18.0-next.2
|
|
40
|
+
- @backstage/catalog-client@1.16.2-next.1
|
|
41
|
+
- @backstage/plugin-catalog-react@3.2.3-next.2
|
|
42
|
+
- @backstage/core-components@0.18.14-next.2
|
|
43
|
+
- @backstage/core-plugin-api@1.12.10-next.1
|
|
44
|
+
- @backstage/frontend-plugin-api@0.18.1-next.1
|
|
45
|
+
- @backstage/integration-react@1.2.22-next.1
|
|
46
|
+
- @backstage/plugin-permission-react@0.5.5-next.1
|
|
47
|
+
- @backstage/plugin-techdocs-react@1.3.15-next.2
|
|
48
|
+
- @backstage/plugin-scaffolder-common@2.3.0-next.2
|
|
49
|
+
- @backstage/plugin-search-common@1.2.25-next.0
|
|
50
|
+
- @backstage/plugin-search-react@1.11.8-next.2
|
|
51
|
+
|
|
3
52
|
## 2.0.9-next.1
|
|
4
53
|
|
|
5
54
|
### Patch Changes
|
|
@@ -29,7 +29,7 @@ function EntityContextMenuItemContent(props) {
|
|
|
29
29
|
return /* @__PURE__ */ jsx(MenuItem, { iconStart: icon, onAction, isDisabled: disabled, children: title });
|
|
30
30
|
}
|
|
31
31
|
function EntityContextMenuItem(props) {
|
|
32
|
-
return /* @__PURE__ */ jsx(ExtensionBoundary, { node: props.item.node, children: /* @__PURE__ */ jsx(EntityContextMenuItemContent, { data: props.item.data }) });
|
|
32
|
+
return /* @__PURE__ */ jsx(ExtensionBoundary, { node: props.item.node, errorPresentation: "error-api", children: /* @__PURE__ */ jsx(EntityContextMenuItemContent, { data: props.item.data }) });
|
|
33
33
|
}
|
|
34
34
|
function EntityContextMenu(props) {
|
|
35
35
|
const { UNSTABLE_extraContextMenuItems, contextMenuItems } = props;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"EntityContextMenu.esm.js","sources":["../../../../src/alpha/components/EntityContextMenu/EntityContextMenu.tsx"],"sourcesContent":["/*\n * Copyright 2026 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport {\n type AppNode,\n ExtensionBoundary,\n IconComponent,\n useTranslationRef,\n} from '@backstage/frontend-plugin-api';\nimport type { EntityContextMenuItemData } from '@backstage/plugin-catalog-react/alpha';\nimport {\n ButtonIcon,\n Menu,\n MenuItem,\n MenuSeparator,\n MenuTrigger,\n} from '@backstage/ui';\nimport { RiMore2Line } from '@remixicon/react';\nimport { catalogTranslationRef } from '../../translation';\n\nexport type EntityContextMenuItemDataWithNode = {\n data: EntityContextMenuItemData;\n node: AppNode;\n};\n\nfunction EntityContextMenuItemContent(props: {\n data: EntityContextMenuItemData;\n}) {\n const { icon, useProps } = props.data;\n const { title, disabled, onClick, ...menuItemProps } = useProps();\n const onAction = onClick\n ? () => {\n const result = onClick();\n if (result) {\n // Prevent rejected async actions from becoming unhandled rejections.\n void result.catch(() => {});\n }\n }\n : undefined;\n\n if ('href' in menuItemProps) {\n return (\n <MenuItem\n iconStart={icon}\n href={menuItemProps.href}\n onAction={onAction}\n isDisabled={disabled}\n >\n {title}\n </MenuItem>\n );\n }\n\n return (\n <MenuItem iconStart={icon} onAction={onAction} isDisabled={disabled}>\n {title}\n </MenuItem>\n );\n}\n\nfunction EntityContextMenuItem(props: {\n item: EntityContextMenuItemDataWithNode;\n}) {\n return (\n <ExtensionBoundary node={props.item.node}>\n <EntityContextMenuItemContent data={props.item.data} />\n </ExtensionBoundary>\n );\n}\n\n/** @alpha */\nexport function EntityContextMenu(props: {\n UNSTABLE_extraContextMenuItems?: {\n title: string;\n Icon: IconComponent;\n onClick: () => void;\n }[];\n contextMenuItems?: EntityContextMenuItemDataWithNode[];\n}) {\n const { UNSTABLE_extraContextMenuItems, contextMenuItems } = props;\n const { t } = useTranslationRef(catalogTranslationRef);\n\n return (\n <MenuTrigger>\n <ButtonIcon\n variant=\"secondary\"\n icon={<RiMore2Line />}\n aria-label={t('entityContextMenu.moreButtonAriaLabel')}\n />\n <Menu placement=\"bottom end\">\n {UNSTABLE_extraContextMenuItems?.map((item, index) => (\n <MenuItem\n key={`${item.title}-${index}`}\n iconStart={<item.Icon />}\n onAction={() => item.onClick()}\n >\n {item.title}\n </MenuItem>\n ))}\n {UNSTABLE_extraContextMenuItems?.length && contextMenuItems?.length ? (\n <MenuSeparator />\n ) : null}\n {contextMenuItems?.map(item => (\n <EntityContextMenuItem key={item.node.spec.id} item={item} />\n ))}\n </Menu>\n </MenuTrigger>\n );\n}\n"],"names":[],"mappings":";;;;;;AAsCA,SAAS,6BAA6B,KAAA,EAEnC;AACD,EAAA,MAAM,EAAE,IAAA,EAAM,QAAA,EAAS,GAAI,KAAA,CAAM,IAAA;AACjC,EAAA,MAAM,EAAE,KAAA,EAAO,QAAA,EAAU,SAAS,GAAG,aAAA,KAAkB,QAAA,EAAS;AAChE,EAAA,MAAM,QAAA,GAAW,UACb,MAAM;AACJ,IAAA,MAAM,SAAS,OAAA,EAAQ;AACvB,IAAA,IAAI,MAAA,EAAQ;AAEV,MAAA,KAAK,MAAA,CAAO,MAAM,MAAM;AAAA,MAAC,CAAC,CAAA;AAAA,IAC5B;AAAA,EACF,CAAA,GACA,MAAA;AAEJ,EAAA,IAAI,UAAU,aAAA,EAAe;AAC3B,IAAA,uBACE,GAAA;AAAA,MAAC,QAAA;AAAA,MAAA;AAAA,QACC,SAAA,EAAW,IAAA;AAAA,QACX,MAAM,aAAA,CAAc,IAAA;AAAA,QACpB,QAAA;AAAA,QACA,UAAA,EAAY,QAAA;AAAA,QAEX,QAAA,EAAA;AAAA;AAAA,KACH;AAAA,EAEJ;AAEA,EAAA,2BACG,QAAA,EAAA,EAAS,SAAA,EAAW,MAAM,QAAA,EAAoB,UAAA,EAAY,UACxD,QAAA,EAAA,KAAA,EACH,CAAA;AAEJ;AAEA,SAAS,sBAAsB,KAAA,EAE5B;AACD,EAAA,uBACE,GAAA,CAAC,iBAAA,EAAA,EAAkB,IAAA,EAAM,KAAA,CAAM,IAAA,
|
|
1
|
+
{"version":3,"file":"EntityContextMenu.esm.js","sources":["../../../../src/alpha/components/EntityContextMenu/EntityContextMenu.tsx"],"sourcesContent":["/*\n * Copyright 2026 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport {\n type AppNode,\n ExtensionBoundary,\n IconComponent,\n useTranslationRef,\n} from '@backstage/frontend-plugin-api';\nimport type { EntityContextMenuItemData } from '@backstage/plugin-catalog-react/alpha';\nimport {\n ButtonIcon,\n Menu,\n MenuItem,\n MenuSeparator,\n MenuTrigger,\n} from '@backstage/ui';\nimport { RiMore2Line } from '@remixicon/react';\nimport { catalogTranslationRef } from '../../translation';\n\nexport type EntityContextMenuItemDataWithNode = {\n data: EntityContextMenuItemData;\n node: AppNode;\n};\n\nfunction EntityContextMenuItemContent(props: {\n data: EntityContextMenuItemData;\n}) {\n const { icon, useProps } = props.data;\n const { title, disabled, onClick, ...menuItemProps } = useProps();\n const onAction = onClick\n ? () => {\n const result = onClick();\n if (result) {\n // Prevent rejected async actions from becoming unhandled rejections.\n void result.catch(() => {});\n }\n }\n : undefined;\n\n if ('href' in menuItemProps) {\n return (\n <MenuItem\n iconStart={icon}\n href={menuItemProps.href}\n onAction={onAction}\n isDisabled={disabled}\n >\n {title}\n </MenuItem>\n );\n }\n\n return (\n <MenuItem iconStart={icon} onAction={onAction} isDisabled={disabled}>\n {title}\n </MenuItem>\n );\n}\n\nfunction EntityContextMenuItem(props: {\n item: EntityContextMenuItemDataWithNode;\n}) {\n return (\n <ExtensionBoundary node={props.item.node} errorPresentation=\"error-api\">\n <EntityContextMenuItemContent data={props.item.data} />\n </ExtensionBoundary>\n );\n}\n\n/** @alpha */\nexport function EntityContextMenu(props: {\n UNSTABLE_extraContextMenuItems?: {\n title: string;\n Icon: IconComponent;\n onClick: () => void;\n }[];\n contextMenuItems?: EntityContextMenuItemDataWithNode[];\n}) {\n const { UNSTABLE_extraContextMenuItems, contextMenuItems } = props;\n const { t } = useTranslationRef(catalogTranslationRef);\n\n return (\n <MenuTrigger>\n <ButtonIcon\n variant=\"secondary\"\n icon={<RiMore2Line />}\n aria-label={t('entityContextMenu.moreButtonAriaLabel')}\n />\n <Menu placement=\"bottom end\">\n {UNSTABLE_extraContextMenuItems?.map((item, index) => (\n <MenuItem\n key={`${item.title}-${index}`}\n iconStart={<item.Icon />}\n onAction={() => item.onClick()}\n >\n {item.title}\n </MenuItem>\n ))}\n {UNSTABLE_extraContextMenuItems?.length && contextMenuItems?.length ? (\n <MenuSeparator />\n ) : null}\n {contextMenuItems?.map(item => (\n <EntityContextMenuItem key={item.node.spec.id} item={item} />\n ))}\n </Menu>\n </MenuTrigger>\n );\n}\n"],"names":[],"mappings":";;;;;;AAsCA,SAAS,6BAA6B,KAAA,EAEnC;AACD,EAAA,MAAM,EAAE,IAAA,EAAM,QAAA,EAAS,GAAI,KAAA,CAAM,IAAA;AACjC,EAAA,MAAM,EAAE,KAAA,EAAO,QAAA,EAAU,SAAS,GAAG,aAAA,KAAkB,QAAA,EAAS;AAChE,EAAA,MAAM,QAAA,GAAW,UACb,MAAM;AACJ,IAAA,MAAM,SAAS,OAAA,EAAQ;AACvB,IAAA,IAAI,MAAA,EAAQ;AAEV,MAAA,KAAK,MAAA,CAAO,MAAM,MAAM;AAAA,MAAC,CAAC,CAAA;AAAA,IAC5B;AAAA,EACF,CAAA,GACA,MAAA;AAEJ,EAAA,IAAI,UAAU,aAAA,EAAe;AAC3B,IAAA,uBACE,GAAA;AAAA,MAAC,QAAA;AAAA,MAAA;AAAA,QACC,SAAA,EAAW,IAAA;AAAA,QACX,MAAM,aAAA,CAAc,IAAA;AAAA,QACpB,QAAA;AAAA,QACA,UAAA,EAAY,QAAA;AAAA,QAEX,QAAA,EAAA;AAAA;AAAA,KACH;AAAA,EAEJ;AAEA,EAAA,2BACG,QAAA,EAAA,EAAS,SAAA,EAAW,MAAM,QAAA,EAAoB,UAAA,EAAY,UACxD,QAAA,EAAA,KAAA,EACH,CAAA;AAEJ;AAEA,SAAS,sBAAsB,KAAA,EAE5B;AACD,EAAA,uBACE,GAAA,CAAC,iBAAA,EAAA,EAAkB,IAAA,EAAM,KAAA,CAAM,KAAK,IAAA,EAAM,iBAAA,EAAkB,WAAA,EAC1D,QAAA,kBAAA,GAAA,CAAC,4BAAA,EAAA,EAA6B,IAAA,EAAM,KAAA,CAAM,IAAA,CAAK,MAAM,CAAA,EACvD,CAAA;AAEJ;AAGO,SAAS,kBAAkB,KAAA,EAO/B;AACD,EAAA,MAAM,EAAE,8BAAA,EAAgC,gBAAA,EAAiB,GAAI,KAAA;AAC7D,EAAA,MAAM,EAAE,CAAA,EAAE,GAAI,iBAAA,CAAkB,qBAAqB,CAAA;AAErD,EAAA,4BACG,WAAA,EAAA,EACC,QAAA,EAAA;AAAA,oBAAA,GAAA;AAAA,MAAC,UAAA;AAAA,MAAA;AAAA,QACC,OAAA,EAAQ,WAAA;AAAA,QACR,IAAA,sBAAO,WAAA,EAAA,EAAY,CAAA;AAAA,QACnB,YAAA,EAAY,EAAE,uCAAuC;AAAA;AAAA,KACvD;AAAA,oBACA,IAAA,CAAC,IAAA,EAAA,EAAK,SAAA,EAAU,YAAA,EACb,QAAA,EAAA;AAAA,MAAA,8BAAA,EAAgC,GAAA,CAAI,CAAC,IAAA,EAAM,KAAA,qBAC1C,GAAA;AAAA,QAAC,QAAA;AAAA,QAAA;AAAA,UAEC,SAAA,kBAAW,GAAA,CAAC,IAAA,CAAK,IAAA,EAAL,EAAU,CAAA;AAAA,UACtB,QAAA,EAAU,MAAM,IAAA,CAAK,OAAA,EAAQ;AAAA,UAE5B,QAAA,EAAA,IAAA,CAAK;AAAA,SAAA;AAAA,QAJD,CAAA,EAAG,IAAA,CAAK,KAAK,CAAA,CAAA,EAAI,KAAK,CAAA;AAAA,OAM9B,CAAA;AAAA,MACA,gCAAgC,MAAA,IAAU,gBAAA,EAAkB,MAAA,mBAC3D,GAAA,CAAC,iBAAc,CAAA,GACb,IAAA;AAAA,MACH,gBAAA,EAAkB,GAAA,CAAI,CAAA,IAAA,qBACrB,GAAA,CAAC,qBAAA,EAAA,EAA8C,QAAnB,IAAA,CAAK,IAAA,CAAK,IAAA,CAAK,EAAgB,CAC5D;AAAA,KAAA,EACH;AAAA,GAAA,EACF,CAAA;AAEJ;;;;"}
|
|
@@ -18,10 +18,10 @@ function headerProps(paramKind, paramNamespace, paramName, entity) {
|
|
|
18
18
|
return {
|
|
19
19
|
headerTitle: `${name}${namespace && namespace !== DEFAULT_NAMESPACE ? ` in ${namespace}` : ""}`,
|
|
20
20
|
headerType: (() => {
|
|
21
|
-
let t = kind.
|
|
21
|
+
let t = kind.toLowerCase();
|
|
22
22
|
if (entity && entity.spec && "type" in entity.spec) {
|
|
23
23
|
t += " \u2014 ";
|
|
24
|
-
t += entity.spec.type.
|
|
24
|
+
t += entity.spec.type.toLowerCase();
|
|
25
25
|
}
|
|
26
26
|
return t;
|
|
27
27
|
})()
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"EntityHeader.esm.js","sources":["../../../../src/alpha/components/EntityHeader/EntityHeader.tsx"],"sourcesContent":["/*\n * Copyright 2025 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { useCallback, ComponentProps, ReactNode } from 'react';\nimport { useSearchParams } from 'react-router-dom';\nimport useAsync from 'react-use/esm/useAsync';\n\nimport { makeStyles } from '@material-ui/core/styles';\nimport Box from '@material-ui/core/Box';\n\nimport { Header, Breadcrumbs } from '@backstage/core-components';\nimport { useApi, useRouteRefParams } from '@backstage/core-plugin-api';\nimport { IconComponent } from '@backstage/frontend-plugin-api';\n\nimport {\n Entity,\n EntityRelation,\n DEFAULT_NAMESPACE,\n} from '@backstage/catalog-model';\n\nimport {\n useAsyncEntity,\n entityRouteRef,\n catalogApiRef,\n EntityRefLink,\n InspectEntityDialog,\n EntityDisplayName,\n FavoriteEntity,\n} from '@backstage/plugin-catalog-react';\n\nimport { EntityLabels } from '../EntityLabels';\nimport {\n EntityContextMenu,\n type EntityContextMenuItemDataWithNode,\n} from '../EntityContextMenu';\n\nfunction headerProps(\n paramKind: string | undefined,\n paramNamespace: string | undefined,\n paramName: string | undefined,\n entity: Entity | undefined,\n): { headerTitle: string; headerType: string } {\n const kind = paramKind ?? entity?.kind ?? '';\n const namespace = paramNamespace ?? entity?.metadata.namespace ?? '';\n const name =\n entity?.metadata.title ?? paramName ?? entity?.metadata.name ?? '';\n\n return {\n headerTitle: `${name}${\n namespace && namespace !== DEFAULT_NAMESPACE ? ` in ${namespace}` : ''\n }`,\n headerType: (() => {\n let t = kind.toLocaleLowerCase('en-US');\n if (entity && entity.spec && 'type' in entity.spec) {\n t += ' — ';\n t += (entity.spec as { type: string }).type.toLocaleLowerCase('en-US');\n }\n return t;\n })(),\n };\n}\n\nfunction findParentRelation(\n entityRelations: EntityRelation[] = [],\n relationTypes: string[] = [],\n) {\n for (const type of relationTypes) {\n const foundRelation = entityRelations.find(\n relation => relation.type === type,\n );\n if (foundRelation) {\n return foundRelation; // Return the first found relation and stop\n }\n }\n return null;\n}\n\nconst useStyles = makeStyles(theme => ({\n breadcrumbs: {\n color: theme.page.fontColor,\n fontSize: theme.typography.caption.fontSize,\n textTransform: 'uppercase',\n marginTop: theme.spacing(1),\n opacity: 0.8,\n '& span ': {\n color: theme.page.fontColor,\n textDecoration: 'underline',\n textUnderlineOffset: '3px',\n },\n },\n}));\n\nfunction EntityHeaderTitle() {\n const { entity } = useAsyncEntity();\n const { kind, namespace, name } = useRouteRefParams(entityRouteRef);\n const { headerTitle: title } = headerProps(kind, namespace, name, entity);\n return (\n <Box display=\"inline-flex\" alignItems=\"center\" height=\"1em\" maxWidth=\"100%\">\n <Box\n component=\"span\"\n textOverflow=\"ellipsis\"\n whiteSpace=\"nowrap\"\n overflow=\"hidden\"\n >\n {entity ? <EntityDisplayName entityRef={entity} hideIcon /> : title}\n </Box>\n {entity && <FavoriteEntity entity={entity} />}\n </Box>\n );\n}\n\nfunction EntityHeaderSubtitle(props: { parentEntityRelations?: string[] }) {\n const { parentEntityRelations } = props;\n const classes = useStyles();\n const { entity } = useAsyncEntity();\n const { name } = useRouteRefParams(entityRouteRef);\n const parentEntity = findParentRelation(\n entity?.relations ?? [],\n parentEntityRelations ?? [],\n );\n\n const catalogApi = useApi(catalogApiRef);\n\n const { value: ancestorEntity } = useAsync(async () => {\n if (parentEntity) {\n return findParentRelation(\n (await catalogApi.getEntityByRef(parentEntity?.targetRef))?.relations,\n parentEntityRelations,\n );\n }\n return null;\n }, [parentEntity, catalogApi]);\n\n return parentEntity ? (\n <Breadcrumbs separator=\">\" className={classes.breadcrumbs}>\n {ancestorEntity && (\n <EntityRefLink entityRef={ancestorEntity.targetRef} disableTooltip />\n )}\n <EntityRefLink entityRef={parentEntity.targetRef} disableTooltip />\n {name}\n </Breadcrumbs>\n ) : null;\n}\n\n/** @alpha */\nexport function EntityHeader(props: {\n // NOTE(freben): Intentionally not exported at this point, since it's part of\n // the unstable extra context menu items concept below\n UNSTABLE_extraContextMenuItems?: {\n title: string;\n Icon: IconComponent;\n onClick: () => void;\n }[];\n contextMenuItems?: EntityContextMenuItemDataWithNode[];\n /**\n * An array of relation types used to determine the parent entities in the hierarchy.\n * These relations are prioritized in the order provided, allowing for flexible\n * navigation through entity relationships.\n *\n * For example, use relation types like `[\"partOf\", \"memberOf\", \"ownedBy\"]` to define how the entity is related to\n * its parents in the Entity Catalog.\n *\n * It adds breadcrumbs in the Entity page to enhance user navigation and context awareness.\n */\n parentEntityRelations?: string[];\n title?: ReactNode;\n subtitle?: ReactNode;\n}) {\n const {\n UNSTABLE_extraContextMenuItems,\n contextMenuItems,\n parentEntityRelations,\n title,\n subtitle,\n } = props;\n const { entity } = useAsyncEntity();\n const { kind, namespace, name } = useRouteRefParams(entityRouteRef);\n const { headerTitle: entityFallbackText, headerType: type } = headerProps(\n kind,\n namespace,\n name,\n entity,\n );\n\n const [searchParams, setSearchParams] = useSearchParams();\n const selectedInspectEntityDialogTab = searchParams.get('inspect');\n\n const setInspectEntityDialogTab = useCallback(\n (newTab: string) => setSearchParams(`inspect=${newTab}`),\n [setSearchParams],\n );\n\n const closeInspectEntityDialog = useCallback(\n () => setSearchParams(),\n [setSearchParams],\n );\n\n const inspectDialogOpen = typeof selectedInspectEntityDialogTab === 'string';\n\n return (\n <Header\n pageTitleOverride={entityFallbackText}\n type={type}\n title={title ?? <EntityHeaderTitle />}\n subtitle={\n subtitle ?? (\n <EntityHeaderSubtitle parentEntityRelations={parentEntityRelations} />\n )\n }\n >\n {entity && (\n <>\n <EntityLabels entity={entity} />\n <EntityContextMenu\n UNSTABLE_extraContextMenuItems={UNSTABLE_extraContextMenuItems}\n contextMenuItems={contextMenuItems}\n />\n <InspectEntityDialog\n entity={entity!}\n initialTab={\n (selectedInspectEntityDialogTab as ComponentProps<\n typeof InspectEntityDialog\n >['initialTab']) || undefined\n }\n open={inspectDialogOpen}\n onClose={closeInspectEntityDialog}\n onSelect={setInspectEntityDialogTab}\n />\n </>\n )}\n </Header>\n );\n}\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"EntityHeader.esm.js","sources":["../../../../src/alpha/components/EntityHeader/EntityHeader.tsx"],"sourcesContent":["/*\n * Copyright 2025 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { useCallback, ComponentProps, ReactNode } from 'react';\nimport { useSearchParams } from 'react-router-dom';\nimport useAsync from 'react-use/esm/useAsync';\n\nimport { makeStyles } from '@material-ui/core/styles';\nimport Box from '@material-ui/core/Box';\n\nimport { Header, Breadcrumbs } from '@backstage/core-components';\nimport { useApi, useRouteRefParams } from '@backstage/core-plugin-api';\nimport { IconComponent } from '@backstage/frontend-plugin-api';\n\nimport {\n Entity,\n EntityRelation,\n DEFAULT_NAMESPACE,\n} from '@backstage/catalog-model';\n\nimport {\n useAsyncEntity,\n entityRouteRef,\n catalogApiRef,\n EntityRefLink,\n InspectEntityDialog,\n EntityDisplayName,\n FavoriteEntity,\n} from '@backstage/plugin-catalog-react';\n\nimport { EntityLabels } from '../EntityLabels';\nimport {\n EntityContextMenu,\n type EntityContextMenuItemDataWithNode,\n} from '../EntityContextMenu';\n\nfunction headerProps(\n paramKind: string | undefined,\n paramNamespace: string | undefined,\n paramName: string | undefined,\n entity: Entity | undefined,\n): { headerTitle: string; headerType: string } {\n const kind = paramKind ?? entity?.kind ?? '';\n const namespace = paramNamespace ?? entity?.metadata.namespace ?? '';\n const name =\n entity?.metadata.title ?? paramName ?? entity?.metadata.name ?? '';\n\n return {\n headerTitle: `${name}${\n namespace && namespace !== DEFAULT_NAMESPACE ? ` in ${namespace}` : ''\n }`,\n headerType: (() => {\n let t = kind.toLowerCase();\n if (entity && entity.spec && 'type' in entity.spec) {\n t += ' — ';\n t += (entity.spec as { type: string }).type.toLowerCase();\n }\n return t;\n })(),\n };\n}\n\nfunction findParentRelation(\n entityRelations: EntityRelation[] = [],\n relationTypes: string[] = [],\n) {\n for (const type of relationTypes) {\n const foundRelation = entityRelations.find(\n relation => relation.type === type,\n );\n if (foundRelation) {\n return foundRelation; // Return the first found relation and stop\n }\n }\n return null;\n}\n\nconst useStyles = makeStyles(theme => ({\n breadcrumbs: {\n color: theme.page.fontColor,\n fontSize: theme.typography.caption.fontSize,\n textTransform: 'uppercase',\n marginTop: theme.spacing(1),\n opacity: 0.8,\n '& span ': {\n color: theme.page.fontColor,\n textDecoration: 'underline',\n textUnderlineOffset: '3px',\n },\n },\n}));\n\nfunction EntityHeaderTitle() {\n const { entity } = useAsyncEntity();\n const { kind, namespace, name } = useRouteRefParams(entityRouteRef);\n const { headerTitle: title } = headerProps(kind, namespace, name, entity);\n return (\n <Box display=\"inline-flex\" alignItems=\"center\" height=\"1em\" maxWidth=\"100%\">\n <Box\n component=\"span\"\n textOverflow=\"ellipsis\"\n whiteSpace=\"nowrap\"\n overflow=\"hidden\"\n >\n {entity ? <EntityDisplayName entityRef={entity} hideIcon /> : title}\n </Box>\n {entity && <FavoriteEntity entity={entity} />}\n </Box>\n );\n}\n\nfunction EntityHeaderSubtitle(props: { parentEntityRelations?: string[] }) {\n const { parentEntityRelations } = props;\n const classes = useStyles();\n const { entity } = useAsyncEntity();\n const { name } = useRouteRefParams(entityRouteRef);\n const parentEntity = findParentRelation(\n entity?.relations ?? [],\n parentEntityRelations ?? [],\n );\n\n const catalogApi = useApi(catalogApiRef);\n\n const { value: ancestorEntity } = useAsync(async () => {\n if (parentEntity) {\n return findParentRelation(\n (await catalogApi.getEntityByRef(parentEntity?.targetRef))?.relations,\n parentEntityRelations,\n );\n }\n return null;\n }, [parentEntity, catalogApi]);\n\n return parentEntity ? (\n <Breadcrumbs separator=\">\" className={classes.breadcrumbs}>\n {ancestorEntity && (\n <EntityRefLink entityRef={ancestorEntity.targetRef} disableTooltip />\n )}\n <EntityRefLink entityRef={parentEntity.targetRef} disableTooltip />\n {name}\n </Breadcrumbs>\n ) : null;\n}\n\n/** @alpha */\nexport function EntityHeader(props: {\n // NOTE(freben): Intentionally not exported at this point, since it's part of\n // the unstable extra context menu items concept below\n UNSTABLE_extraContextMenuItems?: {\n title: string;\n Icon: IconComponent;\n onClick: () => void;\n }[];\n contextMenuItems?: EntityContextMenuItemDataWithNode[];\n /**\n * An array of relation types used to determine the parent entities in the hierarchy.\n * These relations are prioritized in the order provided, allowing for flexible\n * navigation through entity relationships.\n *\n * For example, use relation types like `[\"partOf\", \"memberOf\", \"ownedBy\"]` to define how the entity is related to\n * its parents in the Entity Catalog.\n *\n * It adds breadcrumbs in the Entity page to enhance user navigation and context awareness.\n */\n parentEntityRelations?: string[];\n title?: ReactNode;\n subtitle?: ReactNode;\n}) {\n const {\n UNSTABLE_extraContextMenuItems,\n contextMenuItems,\n parentEntityRelations,\n title,\n subtitle,\n } = props;\n const { entity } = useAsyncEntity();\n const { kind, namespace, name } = useRouteRefParams(entityRouteRef);\n const { headerTitle: entityFallbackText, headerType: type } = headerProps(\n kind,\n namespace,\n name,\n entity,\n );\n\n const [searchParams, setSearchParams] = useSearchParams();\n const selectedInspectEntityDialogTab = searchParams.get('inspect');\n\n const setInspectEntityDialogTab = useCallback(\n (newTab: string) => setSearchParams(`inspect=${newTab}`),\n [setSearchParams],\n );\n\n const closeInspectEntityDialog = useCallback(\n () => setSearchParams(),\n [setSearchParams],\n );\n\n const inspectDialogOpen = typeof selectedInspectEntityDialogTab === 'string';\n\n return (\n <Header\n pageTitleOverride={entityFallbackText}\n type={type}\n title={title ?? <EntityHeaderTitle />}\n subtitle={\n subtitle ?? (\n <EntityHeaderSubtitle parentEntityRelations={parentEntityRelations} />\n )\n }\n >\n {entity && (\n <>\n <EntityLabels entity={entity} />\n <EntityContextMenu\n UNSTABLE_extraContextMenuItems={UNSTABLE_extraContextMenuItems}\n contextMenuItems={contextMenuItems}\n />\n <InspectEntityDialog\n entity={entity!}\n initialTab={\n (selectedInspectEntityDialogTab as ComponentProps<\n typeof InspectEntityDialog\n >['initialTab']) || undefined\n }\n open={inspectDialogOpen}\n onClose={closeInspectEntityDialog}\n onSelect={setInspectEntityDialogTab}\n />\n </>\n )}\n </Header>\n );\n}\n"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"EntityHeaderBui.esm.js","sources":["../../../../src/alpha/components/EntityHeader/EntityHeaderBui.tsx"],"sourcesContent":["/*\n * Copyright 2026 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { useMemo } from 'react';\nimport {\n Box,\n ButtonIcon,\n Header,\n HeaderMetadataUsers,\n Link,\n type HeaderMetadataItem,\n type HeaderMetadataUser,\n type HeaderNavTabItem,\n} from '@backstage/ui';\nimport {\n Entity,\n RELATION_OWNED_BY,\n RELATION_PART_OF,\n stringifyEntityRef,\n type CompoundEntityRef,\n} from '@backstage/catalog-model';\nimport { useApi, useRouteRefParams } from '@backstage/core-plugin-api';\nimport { useTranslationRef } from '@backstage/core-plugin-api/alpha';\nimport {\n catalogApiRef,\n catalogReactTranslationRef,\n entityRouteRef,\n getEntityRelations,\n useAsyncEntity,\n useEntityPresentation,\n useEntityRefLink,\n useStarredEntity,\n} from '@backstage/plugin-catalog-react';\nimport { RiStarFill, RiStarLine } from '@remixicon/react';\nimport useAsync from 'react-use/esm/useAsync';\nimport { catalogTranslationRef } from '../../translation';\nimport {\n EntityContextMenu,\n type EntityContextMenuItemDataWithNode,\n} from '../EntityContextMenu';\n\nfunction useOwnerUsers(entity: Entity | undefined): HeaderMetadataUser[] {\n const catalogApi = useApi(catalogApiRef);\n const entityLink = useEntityRefLink();\n const ownerRefs = useMemo(\n () => getEntityRelations(entity, RELATION_OWNED_BY),\n [entity],\n );\n const ownerRefStrings = useMemo(\n () => ownerRefs.map(ref => stringifyEntityRef(ref)),\n [ownerRefs],\n );\n const { value: ownerEntities } = useAsync(async () => {\n if (ownerRefStrings.length === 0) return [];\n return (\n await catalogApi.getEntitiesByRefs({\n entityRefs: ownerRefStrings,\n fields: [\n 'kind',\n 'metadata.name',\n 'metadata.namespace',\n 'metadata.title',\n 'spec.profile',\n ],\n })\n ).items;\n }, [catalogApi, ownerRefStrings]);\n\n return ownerRefs.map((ref, index) => {\n const owner = ownerEntities?.[index];\n const profile = (owner?.spec as { profile?: { picture?: string } })\n ?.profile;\n return {\n name: owner?.metadata.title ?? owner?.metadata.name ?? ref.name,\n src: profile?.picture,\n href: entityLink(ref),\n };\n });\n}\n\nfunction HierarchyLinks(props: { refs: CompoundEntityRef[] }) {\n const entityLink = useEntityRefLink();\n return (\n <Box as=\"ul\" display=\"inline\" m=\"0\" p=\"0\" style={{ listStyle: 'none' }}>\n {props.refs.map((ref, index) => (\n <Box as=\"li\" display=\"inline\" key={stringifyEntityRef(ref)}>\n {index > 0 ? ', ' : null}\n <Link href={entityLink(ref)} standalone>\n {ref.name}\n </Link>\n </Box>\n ))}\n </Box>\n );\n}\n\nfunction hierarchyLabel(\n ref: CompoundEntityRef,\n): 'systemLabel' | 'domainLabel' | 'partOfLabel' {\n switch (ref.kind.toLocaleLowerCase('en-US')) {\n case 'system':\n return 'systemLabel';\n case 'domain':\n return 'domainLabel';\n default:\n return 'partOfLabel';\n }\n}\n\nfunction useMetadata(entity: Entity | undefined): HeaderMetadataItem[] {\n const owners = useOwnerUsers(entity);\n const { t } = useTranslationRef(catalogTranslationRef);\n return useMemo(() => {\n if (!entity) return [];\n const metadata: HeaderMetadataItem[] = [];\n const lifecycle = entity.spec?.lifecycle?.toString();\n if (lifecycle) {\n metadata.push({\n label: t('entityLabels.lifecycleLabel'),\n value: lifecycle,\n });\n }\n if (owners.length > 0) {\n metadata.push({\n label: t('entityLabels.ownerLabel'),\n value: <HeaderMetadataUsers users={owners} />,\n });\n }\n\n const hierarchy = getEntityRelations(entity, RELATION_PART_OF).reduce(\n (groups, ref) => {\n const label = hierarchyLabel(ref);\n groups[label] = [...(groups[label] ?? []), ref];\n return groups;\n },\n {} as Record<string, CompoundEntityRef[]>,\n );\n for (const [label, refs] of Object.entries(hierarchy)) {\n metadata.push({\n label: t(\n `entityLabels.${label}` as\n | 'entityLabels.systemLabel'\n | 'entityLabels.domainLabel'\n | 'entityLabels.partOfLabel',\n ),\n value: <HierarchyLinks refs={refs} />,\n });\n }\n return metadata;\n }, [entity, owners, t]);\n}\n\nfunction FavoriteEntityButton(props: { entity: Entity }) {\n const { t } = useTranslationRef(catalogReactTranslationRef);\n const { isStarredEntity, toggleStarredEntity } = useStarredEntity(\n props.entity,\n );\n return (\n <ButtonIcon\n variant=\"secondary\"\n aria-label={\n isStarredEntity\n ? t('favoriteEntity.removeFromFavorites')\n : t('favoriteEntity.addToFavorites')\n }\n icon={isStarredEntity ? <RiStarFill /> : <RiStarLine />}\n onPress={() => toggleStarredEntity()}\n />\n );\n}\n\nexport function EntityHeaderBui(props: {\n tabs: HeaderNavTabItem[];\n activeTabId?: string;\n contextMenuItems?: EntityContextMenuItemDataWithNode[];\n}) {\n const { entity } = useAsyncEntity();\n const routeParams = useRouteRefParams(entityRouteRef);\n const presentation = useEntityPresentation(entity ?? routeParams);\n const metadata = useMetadata(entity);\n const type = entity?.spec?.type?.toString();\n\n return (\n <Header\n title={presentation.primaryTitle}\n tags={[\n { label: entity?.kind ?? routeParams.kind },\n ...(type ? [{ label: type }] : []),\n ]}\n metadata={metadata}\n tabs={entity ? props.tabs : undefined}\n activeTabId={props.activeTabId}\n customActions={\n entity ? (\n <>\n <FavoriteEntityButton entity={entity} />\n <EntityContextMenu contextMenuItems={props.contextMenuItems} />\n </>\n ) : undefined\n }\n />\n );\n}\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"EntityHeaderBui.esm.js","sources":["../../../../src/alpha/components/EntityHeader/EntityHeaderBui.tsx"],"sourcesContent":["/*\n * Copyright 2026 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { useMemo } from 'react';\nimport {\n Box,\n ButtonIcon,\n Header,\n HeaderMetadataUsers,\n Link,\n type HeaderMetadataItem,\n type HeaderMetadataUser,\n type HeaderNavTabItem,\n} from '@backstage/ui';\nimport {\n Entity,\n RELATION_OWNED_BY,\n RELATION_PART_OF,\n stringifyEntityRef,\n type CompoundEntityRef,\n} from '@backstage/catalog-model';\nimport { useApi, useRouteRefParams } from '@backstage/core-plugin-api';\nimport { useTranslationRef } from '@backstage/core-plugin-api/alpha';\nimport {\n catalogApiRef,\n catalogReactTranslationRef,\n entityRouteRef,\n getEntityRelations,\n useAsyncEntity,\n useEntityPresentation,\n useEntityRefLink,\n useStarredEntity,\n} from '@backstage/plugin-catalog-react';\nimport { RiStarFill, RiStarLine } from '@remixicon/react';\nimport useAsync from 'react-use/esm/useAsync';\nimport { catalogTranslationRef } from '../../translation';\nimport {\n EntityContextMenu,\n type EntityContextMenuItemDataWithNode,\n} from '../EntityContextMenu';\n\nfunction useOwnerUsers(entity: Entity | undefined): HeaderMetadataUser[] {\n const catalogApi = useApi(catalogApiRef);\n const entityLink = useEntityRefLink();\n const ownerRefs = useMemo(\n () => getEntityRelations(entity, RELATION_OWNED_BY),\n [entity],\n );\n const ownerRefStrings = useMemo(\n () => ownerRefs.map(ref => stringifyEntityRef(ref)),\n [ownerRefs],\n );\n const { value: ownerEntities } = useAsync(async () => {\n if (ownerRefStrings.length === 0) return [];\n return (\n await catalogApi.getEntitiesByRefs({\n entityRefs: ownerRefStrings,\n fields: [\n 'kind',\n 'metadata.name',\n 'metadata.namespace',\n 'metadata.title',\n 'spec.profile',\n ],\n })\n ).items;\n }, [catalogApi, ownerRefStrings]);\n\n return ownerRefs.map((ref, index) => {\n const owner = ownerEntities?.[index];\n const profile = (owner?.spec as { profile?: { picture?: string } })\n ?.profile;\n return {\n name: owner?.metadata.title ?? owner?.metadata.name ?? ref.name,\n src: profile?.picture,\n href: entityLink(ref),\n };\n });\n}\n\nfunction HierarchyLinks(props: { refs: CompoundEntityRef[] }) {\n const entityLink = useEntityRefLink();\n return (\n <Box as=\"ul\" display=\"inline\" m=\"0\" p=\"0\" style={{ listStyle: 'none' }}>\n {props.refs.map((ref, index) => (\n <Box as=\"li\" display=\"inline\" key={stringifyEntityRef(ref)}>\n {index > 0 ? ', ' : null}\n <Link href={entityLink(ref)} standalone>\n {ref.name}\n </Link>\n </Box>\n ))}\n </Box>\n );\n}\n\nfunction hierarchyLabel(\n ref: CompoundEntityRef,\n): 'systemLabel' | 'domainLabel' | 'partOfLabel' {\n switch (ref.kind.toLowerCase()) {\n case 'system':\n return 'systemLabel';\n case 'domain':\n return 'domainLabel';\n default:\n return 'partOfLabel';\n }\n}\n\nfunction useMetadata(entity: Entity | undefined): HeaderMetadataItem[] {\n const owners = useOwnerUsers(entity);\n const { t } = useTranslationRef(catalogTranslationRef);\n return useMemo(() => {\n if (!entity) return [];\n const metadata: HeaderMetadataItem[] = [];\n const lifecycle = entity.spec?.lifecycle?.toString();\n if (lifecycle) {\n metadata.push({\n label: t('entityLabels.lifecycleLabel'),\n value: lifecycle,\n });\n }\n if (owners.length > 0) {\n metadata.push({\n label: t('entityLabels.ownerLabel'),\n value: <HeaderMetadataUsers users={owners} />,\n });\n }\n\n const hierarchy = getEntityRelations(entity, RELATION_PART_OF).reduce(\n (groups, ref) => {\n const label = hierarchyLabel(ref);\n groups[label] = [...(groups[label] ?? []), ref];\n return groups;\n },\n {} as Record<string, CompoundEntityRef[]>,\n );\n for (const [label, refs] of Object.entries(hierarchy)) {\n metadata.push({\n label: t(\n `entityLabels.${label}` as\n | 'entityLabels.systemLabel'\n | 'entityLabels.domainLabel'\n | 'entityLabels.partOfLabel',\n ),\n value: <HierarchyLinks refs={refs} />,\n });\n }\n return metadata;\n }, [entity, owners, t]);\n}\n\nfunction FavoriteEntityButton(props: { entity: Entity }) {\n const { t } = useTranslationRef(catalogReactTranslationRef);\n const { isStarredEntity, toggleStarredEntity } = useStarredEntity(\n props.entity,\n );\n return (\n <ButtonIcon\n variant=\"secondary\"\n aria-label={\n isStarredEntity\n ? t('favoriteEntity.removeFromFavorites')\n : t('favoriteEntity.addToFavorites')\n }\n icon={isStarredEntity ? <RiStarFill /> : <RiStarLine />}\n onPress={() => toggleStarredEntity()}\n />\n );\n}\n\nexport function EntityHeaderBui(props: {\n tabs: HeaderNavTabItem[];\n activeTabId?: string;\n contextMenuItems?: EntityContextMenuItemDataWithNode[];\n}) {\n const { entity } = useAsyncEntity();\n const routeParams = useRouteRefParams(entityRouteRef);\n const presentation = useEntityPresentation(entity ?? routeParams);\n const metadata = useMetadata(entity);\n const type = entity?.spec?.type?.toString();\n\n return (\n <Header\n title={presentation.primaryTitle}\n tags={[\n { label: entity?.kind ?? routeParams.kind },\n ...(type ? [{ label: type }] : []),\n ]}\n metadata={metadata}\n tabs={entity ? props.tabs : undefined}\n activeTabId={props.activeTabId}\n customActions={\n entity ? (\n <>\n <FavoriteEntityButton entity={entity} />\n <EntityContextMenu contextMenuItems={props.contextMenuItems} />\n </>\n ) : undefined\n }\n />\n );\n}\n"],"names":[],"mappings":"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"}
|
|
@@ -1,10 +1,20 @@
|
|
|
1
1
|
import { jsx } from 'react/jsx-runtime';
|
|
2
2
|
import { EntityCardBlueprint, EntityIconLinkBlueprint } from '@backstage/plugin-catalog-react/alpha';
|
|
3
3
|
import { createExtensionInput } from '@backstage/frontend-plugin-api';
|
|
4
|
-
import { HeaderIconLinkRow } from '@backstage/core-components';
|
|
4
|
+
import { HeaderIconLinkRow, IconLinkVertical } from '@backstage/core-components';
|
|
5
5
|
import { useEntity } from '@backstage/plugin-catalog-react';
|
|
6
6
|
import { buildFilterFn } from './filter/FilterWrapper.esm.js';
|
|
7
7
|
|
|
8
|
+
function EntityIconLinkItem(props) {
|
|
9
|
+
const { useProps } = props;
|
|
10
|
+
const linkProps = useProps();
|
|
11
|
+
return /* @__PURE__ */ jsx(IconLinkVertical, { ...linkProps });
|
|
12
|
+
}
|
|
13
|
+
function EntityIconLinkRow(props) {
|
|
14
|
+
const { entity } = useEntity();
|
|
15
|
+
const links = props.links.filter((link) => link.filter(entity));
|
|
16
|
+
return links.length ? /* @__PURE__ */ jsx(HeaderIconLinkRow, { links: [], children: links.map((link) => /* @__PURE__ */ jsx(EntityIconLinkItem, { useProps: link.useProps }, link.id)) }) : null;
|
|
17
|
+
}
|
|
8
18
|
const catalogAboutEntityCard = EntityCardBlueprint.makeWithOverrides({
|
|
9
19
|
name: "about",
|
|
10
20
|
inputs: {
|
|
@@ -15,22 +25,16 @@ const catalogAboutEntityCard = EntityCardBlueprint.makeWithOverrides({
|
|
|
15
25
|
])
|
|
16
26
|
},
|
|
17
27
|
factory(originalFactory, { inputs }) {
|
|
28
|
+
const iconLinks = inputs.iconLinks.map((iconLink) => ({
|
|
29
|
+
id: iconLink.node.spec.id,
|
|
30
|
+
filter: buildFilterFn(
|
|
31
|
+
iconLink.get(EntityIconLinkBlueprint.dataRefs.filterFunction),
|
|
32
|
+
iconLink.get(EntityIconLinkBlueprint.dataRefs.filterExpression)
|
|
33
|
+
),
|
|
34
|
+
useProps: iconLink.get(EntityIconLinkBlueprint.dataRefs.useProps)
|
|
35
|
+
}));
|
|
18
36
|
function Subheader() {
|
|
19
|
-
|
|
20
|
-
const links = inputs.iconLinks.reduce((rest, iconLink) => {
|
|
21
|
-
const filter = buildFilterFn(
|
|
22
|
-
iconLink.get(EntityIconLinkBlueprint.dataRefs.filterFunction),
|
|
23
|
-
iconLink.get(EntityIconLinkBlueprint.dataRefs.filterExpression)
|
|
24
|
-
);
|
|
25
|
-
if (filter(entity)) {
|
|
26
|
-
const props = iconLink.get(
|
|
27
|
-
EntityIconLinkBlueprint.dataRefs.useProps
|
|
28
|
-
)();
|
|
29
|
-
return [...rest, props];
|
|
30
|
-
}
|
|
31
|
-
return rest;
|
|
32
|
-
}, new Array());
|
|
33
|
-
return links.length ? /* @__PURE__ */ jsx(HeaderIconLinkRow, { links }) : null;
|
|
37
|
+
return /* @__PURE__ */ jsx(EntityIconLinkRow, { links: iconLinks });
|
|
34
38
|
}
|
|
35
39
|
return originalFactory({
|
|
36
40
|
type: "info",
|
|
@@ -124,5 +128,5 @@ var entityCards = [
|
|
|
124
128
|
catalogHasSystemsEntityCard
|
|
125
129
|
];
|
|
126
130
|
|
|
127
|
-
export { catalogAboutEntityCard, catalogDependsOnComponentsEntityCard, catalogDependsOnResourcesEntityCard, catalogHasComponentsEntityCard, catalogHasResourcesEntityCard, catalogHasSubcomponentsEntityCard, catalogHasSubdomainsEntityCard, catalogHasSystemsEntityCard, catalogLabelsEntityCard, catalogLinksEntityCard, entityCards as default };
|
|
131
|
+
export { EntityIconLinkRow, catalogAboutEntityCard, catalogDependsOnComponentsEntityCard, catalogDependsOnResourcesEntityCard, catalogHasComponentsEntityCard, catalogHasResourcesEntityCard, catalogHasSubcomponentsEntityCard, catalogHasSubdomainsEntityCard, catalogHasSystemsEntityCard, catalogLabelsEntityCard, catalogLinksEntityCard, entityCards as default };
|
|
128
132
|
//# sourceMappingURL=entityCards.esm.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"entityCards.esm.js","sources":["../../src/alpha/entityCards.tsx"],"sourcesContent":["/*\n * Copyright 2023 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport {\n EntityIconLinkBlueprint,\n EntityCardBlueprint,\n} from '@backstage/plugin-catalog-react/alpha';\nimport { createExtensionInput } from '@backstage/frontend-plugin-api';\nimport {\n HeaderIconLinkRow,\n IconLinkVerticalProps,\n} from '@backstage/core-components';\nimport { useEntity } from '@backstage/plugin-catalog-react';\nimport { buildFilterFn } from './filter/FilterWrapper';\n\nexport const catalogAboutEntityCard = EntityCardBlueprint.makeWithOverrides({\n name: 'about',\n inputs: {\n iconLinks: createExtensionInput([\n EntityIconLinkBlueprint.dataRefs.filterFunction.optional(),\n EntityIconLinkBlueprint.dataRefs.filterExpression.optional(),\n EntityIconLinkBlueprint.dataRefs.useProps,\n ]),\n },\n factory(originalFactory, { inputs }) {\n function Subheader() {\n const { entity } = useEntity();\n // The \"useProps\" functions may be calling other hooks, so we need to\n // call them in a component function to avoid breaking the rules of hooks.\n const links = inputs.iconLinks.reduce((rest, iconLink) => {\n const filter = buildFilterFn(\n iconLink.get(EntityIconLinkBlueprint.dataRefs.filterFunction),\n iconLink.get(EntityIconLinkBlueprint.dataRefs.filterExpression),\n );\n if (filter(entity)) {\n const props = iconLink.get(\n EntityIconLinkBlueprint.dataRefs.useProps,\n )();\n return [...rest, props];\n }\n return rest;\n }, new Array<IconLinkVerticalProps>());\n return links.length ? <HeaderIconLinkRow links={links} /> : null;\n }\n return originalFactory({\n type: 'info',\n filter: {\n $not: {\n kind: { $in: ['user', 'group'] },\n },\n },\n async loader() {\n const { InternalAboutCard } = await import(\n '../components/AboutCard/AboutCard'\n );\n return <InternalAboutCard iconLinks={<Subheader />} />;\n },\n });\n },\n});\n\nexport const catalogLinksEntityCard = EntityCardBlueprint.make({\n name: 'links',\n params: {\n type: 'info',\n filter: { 'metadata.links': { $exists: true } },\n loader: async () =>\n import('../components/EntityLinksCard').then(m => <m.EntityLinksCard />),\n },\n});\n\nexport const catalogLabelsEntityCard = EntityCardBlueprint.make({\n name: 'labels',\n params: {\n type: 'info',\n filter: { 'metadata.labels': { $exists: true } },\n loader: async () =>\n import('../components/EntityLabelsCard').then(m => (\n <m.EntityLabelsCard />\n )),\n },\n});\n\nexport const catalogDependsOnComponentsEntityCard = EntityCardBlueprint.make({\n name: 'depends-on-components',\n params: {\n filter: { kind: 'component' },\n loader: async () =>\n import('../components/DependsOnComponentsCard').then(m => (\n <m.DependsOnComponentsCard />\n )),\n },\n});\n\nexport const catalogDependsOnResourcesEntityCard = EntityCardBlueprint.make({\n name: 'depends-on-resources',\n params: {\n filter: { kind: 'component' },\n loader: async () =>\n import('../components/DependsOnResourcesCard').then(m => (\n <m.DependsOnResourcesCard />\n )),\n },\n});\n\nexport const catalogHasComponentsEntityCard = EntityCardBlueprint.make({\n name: 'has-components',\n params: {\n filter: { kind: 'system' },\n loader: async () =>\n import('../components/HasComponentsCard').then(m => (\n <m.HasComponentsCard />\n )),\n },\n});\n\nexport const catalogHasResourcesEntityCard = EntityCardBlueprint.make({\n name: 'has-resources',\n params: {\n filter: { kind: 'system' },\n loader: async () =>\n import('../components/HasResourcesCard').then(m => (\n <m.HasResourcesCard />\n )),\n },\n});\n\nexport const catalogHasSubcomponentsEntityCard = EntityCardBlueprint.make({\n name: 'has-subcomponents',\n params: {\n filter: { kind: 'component' },\n loader: async () =>\n import('../components/HasSubcomponentsCard').then(m => (\n <m.HasSubcomponentsCard />\n )),\n },\n});\n\nexport const catalogHasSubdomainsEntityCard = EntityCardBlueprint.make({\n name: 'has-subdomains',\n params: {\n filter: { kind: 'domain' },\n loader: async () =>\n import('../components/HasSubdomainsCard').then(m => (\n <m.HasSubdomainsCard />\n )),\n },\n});\n\nexport const catalogHasSystemsEntityCard = EntityCardBlueprint.make({\n name: 'has-systems',\n params: {\n filter: { kind: 'domain' },\n loader: async () =>\n import('../components/HasSystemsCard').then(m => <m.HasSystemsCard />),\n },\n});\n\nexport default [\n catalogAboutEntityCard,\n catalogLinksEntityCard,\n catalogLabelsEntityCard,\n catalogDependsOnComponentsEntityCard,\n catalogDependsOnResourcesEntityCard,\n catalogHasComponentsEntityCard,\n catalogHasResourcesEntityCard,\n catalogHasSubcomponentsEntityCard,\n catalogHasSubdomainsEntityCard,\n catalogHasSystemsEntityCard,\n];\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"entityCards.esm.js","sources":["../../src/alpha/entityCards.tsx"],"sourcesContent":["/*\n * Copyright 2023 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport {\n EntityIconLinkBlueprint,\n EntityCardBlueprint,\n} from '@backstage/plugin-catalog-react/alpha';\nimport { createExtensionInput } from '@backstage/frontend-plugin-api';\nimport {\n HeaderIconLinkRow,\n IconLinkVertical,\n IconLinkVerticalProps,\n} from '@backstage/core-components';\nimport { useEntity } from '@backstage/plugin-catalog-react';\nimport { Entity } from '@backstage/catalog-model';\nimport { buildFilterFn } from './filter/FilterWrapper';\n\ntype EntityIconLink = {\n id: string;\n filter: (entity: Entity) => boolean;\n useProps: () => IconLinkVerticalProps;\n};\n\nfunction EntityIconLinkItem(props: Pick<EntityIconLink, 'useProps'>) {\n const { useProps } = props;\n const linkProps = useProps();\n return <IconLinkVertical {...linkProps} />;\n}\n\nexport function EntityIconLinkRow(props: { links: EntityIconLink[] }) {\n const { entity } = useEntity();\n const links = props.links.filter(link => link.filter(entity));\n\n return links.length ? (\n <HeaderIconLinkRow links={[]}>\n {links.map(link => (\n <EntityIconLinkItem key={link.id} useProps={link.useProps} />\n ))}\n </HeaderIconLinkRow>\n ) : null;\n}\n\nexport const catalogAboutEntityCard = EntityCardBlueprint.makeWithOverrides({\n name: 'about',\n inputs: {\n iconLinks: createExtensionInput([\n EntityIconLinkBlueprint.dataRefs.filterFunction.optional(),\n EntityIconLinkBlueprint.dataRefs.filterExpression.optional(),\n EntityIconLinkBlueprint.dataRefs.useProps,\n ]),\n },\n factory(originalFactory, { inputs }) {\n const iconLinks = inputs.iconLinks.map(iconLink => ({\n id: iconLink.node.spec.id,\n filter: buildFilterFn(\n iconLink.get(EntityIconLinkBlueprint.dataRefs.filterFunction),\n iconLink.get(EntityIconLinkBlueprint.dataRefs.filterExpression),\n ),\n useProps: iconLink.get(EntityIconLinkBlueprint.dataRefs.useProps),\n }));\n\n function Subheader() {\n return <EntityIconLinkRow links={iconLinks} />;\n }\n return originalFactory({\n type: 'info',\n filter: {\n $not: {\n kind: { $in: ['user', 'group'] },\n },\n },\n async loader() {\n const { InternalAboutCard } = await import(\n '../components/AboutCard/AboutCard'\n );\n return <InternalAboutCard iconLinks={<Subheader />} />;\n },\n });\n },\n});\n\nexport const catalogLinksEntityCard = EntityCardBlueprint.make({\n name: 'links',\n params: {\n type: 'info',\n filter: { 'metadata.links': { $exists: true } },\n loader: async () =>\n import('../components/EntityLinksCard').then(m => <m.EntityLinksCard />),\n },\n});\n\nexport const catalogLabelsEntityCard = EntityCardBlueprint.make({\n name: 'labels',\n params: {\n type: 'info',\n filter: { 'metadata.labels': { $exists: true } },\n loader: async () =>\n import('../components/EntityLabelsCard').then(m => (\n <m.EntityLabelsCard />\n )),\n },\n});\n\nexport const catalogDependsOnComponentsEntityCard = EntityCardBlueprint.make({\n name: 'depends-on-components',\n params: {\n filter: { kind: 'component' },\n loader: async () =>\n import('../components/DependsOnComponentsCard').then(m => (\n <m.DependsOnComponentsCard />\n )),\n },\n});\n\nexport const catalogDependsOnResourcesEntityCard = EntityCardBlueprint.make({\n name: 'depends-on-resources',\n params: {\n filter: { kind: 'component' },\n loader: async () =>\n import('../components/DependsOnResourcesCard').then(m => (\n <m.DependsOnResourcesCard />\n )),\n },\n});\n\nexport const catalogHasComponentsEntityCard = EntityCardBlueprint.make({\n name: 'has-components',\n params: {\n filter: { kind: 'system' },\n loader: async () =>\n import('../components/HasComponentsCard').then(m => (\n <m.HasComponentsCard />\n )),\n },\n});\n\nexport const catalogHasResourcesEntityCard = EntityCardBlueprint.make({\n name: 'has-resources',\n params: {\n filter: { kind: 'system' },\n loader: async () =>\n import('../components/HasResourcesCard').then(m => (\n <m.HasResourcesCard />\n )),\n },\n});\n\nexport const catalogHasSubcomponentsEntityCard = EntityCardBlueprint.make({\n name: 'has-subcomponents',\n params: {\n filter: { kind: 'component' },\n loader: async () =>\n import('../components/HasSubcomponentsCard').then(m => (\n <m.HasSubcomponentsCard />\n )),\n },\n});\n\nexport const catalogHasSubdomainsEntityCard = EntityCardBlueprint.make({\n name: 'has-subdomains',\n params: {\n filter: { kind: 'domain' },\n loader: async () =>\n import('../components/HasSubdomainsCard').then(m => (\n <m.HasSubdomainsCard />\n )),\n },\n});\n\nexport const catalogHasSystemsEntityCard = EntityCardBlueprint.make({\n name: 'has-systems',\n params: {\n filter: { kind: 'domain' },\n loader: async () =>\n import('../components/HasSystemsCard').then(m => <m.HasSystemsCard />),\n },\n});\n\nexport default [\n catalogAboutEntityCard,\n catalogLinksEntityCard,\n catalogLabelsEntityCard,\n catalogDependsOnComponentsEntityCard,\n catalogDependsOnResourcesEntityCard,\n catalogHasComponentsEntityCard,\n catalogHasResourcesEntityCard,\n catalogHasSubcomponentsEntityCard,\n catalogHasSubdomainsEntityCard,\n catalogHasSystemsEntityCard,\n];\n"],"names":[],"mappings":"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"}
|
|
@@ -10,7 +10,7 @@ const allowedMatchers = {
|
|
|
10
10
|
};
|
|
11
11
|
function createHasMatcher(parameters, onParseError) {
|
|
12
12
|
const matchers = parameters.flatMap((parameter) => {
|
|
13
|
-
const matcher = allowedMatchers[parameter.
|
|
13
|
+
const matcher = allowedMatchers[parameter.toLowerCase()];
|
|
14
14
|
if (!matcher) {
|
|
15
15
|
const known = Object.keys(allowedMatchers).map((m) => `'${m}'`);
|
|
16
16
|
onParseError(
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"createHasMatcher.esm.js","sources":["../../../../src/alpha/filter/matchers/createHasMatcher.ts"],"sourcesContent":["/*\n * Copyright 2023 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { InputError } from '@backstage/errors';\nimport { EntityMatcherFn } from './types';\n\nconst allowedMatchers: Record<string, EntityMatcherFn> = {\n labels: entity => {\n return Object.keys(entity.metadata.labels ?? {}).length > 0;\n },\n links: entity => {\n return (entity.metadata.links ?? []).length > 0;\n },\n};\n\n/**\n * Matches on the non-empty presence of different parts of the entity\n */\nexport function createHasMatcher(\n parameters: string[],\n onParseError: (error: Error) => void,\n): EntityMatcherFn {\n const matchers = parameters.flatMap(parameter => {\n const matcher = allowedMatchers[parameter.
|
|
1
|
+
{"version":3,"file":"createHasMatcher.esm.js","sources":["../../../../src/alpha/filter/matchers/createHasMatcher.ts"],"sourcesContent":["/*\n * Copyright 2023 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { InputError } from '@backstage/errors';\nimport { EntityMatcherFn } from './types';\n\nconst allowedMatchers: Record<string, EntityMatcherFn> = {\n labels: entity => {\n return Object.keys(entity.metadata.labels ?? {}).length > 0;\n },\n links: entity => {\n return (entity.metadata.links ?? []).length > 0;\n },\n};\n\n/**\n * Matches on the non-empty presence of different parts of the entity\n */\nexport function createHasMatcher(\n parameters: string[],\n onParseError: (error: Error) => void,\n): EntityMatcherFn {\n const matchers = parameters.flatMap(parameter => {\n const matcher = allowedMatchers[parameter.toLowerCase()];\n if (!matcher) {\n const known = Object.keys(allowedMatchers).map(m => `'${m}'`);\n onParseError(\n new InputError(\n `'${parameter}' is not a valid parameter for 'has' filter expressions, expected one of ${known}`,\n ),\n );\n return [];\n }\n return [matcher];\n });\n\n return entity =>\n matchers.length ? matchers.some(matcher => matcher(entity)) : true;\n}\n"],"names":[],"mappings":";;AAmBA,MAAM,eAAA,GAAmD;AAAA,EACvD,QAAQ,CAAA,MAAA,KAAU;AAChB,IAAA,OAAO,MAAA,CAAO,KAAK,MAAA,CAAO,QAAA,CAAS,UAAU,EAAE,EAAE,MAAA,GAAS,CAAA;AAAA,EAC5D,CAAA;AAAA,EACA,OAAO,CAAA,MAAA,KAAU;AACf,IAAA,OAAA,CAAQ,MAAA,CAAO,QAAA,CAAS,KAAA,IAAS,IAAI,MAAA,GAAS,CAAA;AAAA,EAChD;AACF,CAAA;AAKO,SAAS,gBAAA,CACd,YACA,YAAA,EACiB;AACjB,EAAA,MAAM,QAAA,GAAW,UAAA,CAAW,OAAA,CAAQ,CAAA,SAAA,KAAa;AAC/C,IAAA,MAAM,OAAA,GAAU,eAAA,CAAgB,SAAA,CAAU,WAAA,EAAa,CAAA;AACvD,IAAA,IAAI,CAAC,OAAA,EAAS;AACZ,MAAA,MAAM,KAAA,GAAQ,OAAO,IAAA,CAAK,eAAe,EAAE,GAAA,CAAI,CAAA,CAAA,KAAK,CAAA,CAAA,EAAI,CAAC,CAAA,CAAA,CAAG,CAAA;AAC5D,MAAA,YAAA;AAAA,QACE,IAAI,UAAA;AAAA,UACF,CAAA,CAAA,EAAI,SAAS,CAAA,yEAAA,EAA4E,KAAK,CAAA;AAAA;AAChG,OACF;AACA,MAAA,OAAO,EAAC;AAAA,IACV;AACA,IAAA,OAAO,CAAC,OAAO,CAAA;AAAA,EACjB,CAAC,CAAA;AAED,EAAA,OAAO,CAAA,MAAA,KACL,SAAS,MAAA,GAAS,QAAA,CAAS,KAAK,CAAA,OAAA,KAAW,OAAA,CAAQ,MAAM,CAAC,CAAA,GAAI,IAAA;AAClE;;;;"}
|
|
@@ -5,7 +5,7 @@ const allowedMatchers = {
|
|
|
5
5
|
};
|
|
6
6
|
function createIsMatcher(parameters, onParseError) {
|
|
7
7
|
const matchers = parameters.flatMap((parameter) => {
|
|
8
|
-
const matcher = allowedMatchers[parameter.
|
|
8
|
+
const matcher = allowedMatchers[parameter.toLowerCase()];
|
|
9
9
|
if (!matcher) {
|
|
10
10
|
const known = Object.keys(allowedMatchers).map((m) => `'${m}'`);
|
|
11
11
|
onParseError(
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"createIsMatcher.esm.js","sources":["../../../../src/alpha/filter/matchers/createIsMatcher.ts"],"sourcesContent":["/*\n * Copyright 2023 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { InputError } from '@backstage/errors';\nimport { EntityMatcherFn } from './types';\n\nconst allowedMatchers: Record<string, EntityMatcherFn> = {\n orphan: entity =>\n Boolean(entity.metadata.annotations?.['backstage.io/orphan']),\n};\n\n/**\n * Matches on different semantic properties of the entity\n */\nexport function createIsMatcher(\n parameters: string[],\n onParseError: (error: Error) => void,\n): EntityMatcherFn {\n const matchers = parameters.flatMap(parameter => {\n const matcher = allowedMatchers[parameter.
|
|
1
|
+
{"version":3,"file":"createIsMatcher.esm.js","sources":["../../../../src/alpha/filter/matchers/createIsMatcher.ts"],"sourcesContent":["/*\n * Copyright 2023 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { InputError } from '@backstage/errors';\nimport { EntityMatcherFn } from './types';\n\nconst allowedMatchers: Record<string, EntityMatcherFn> = {\n orphan: entity =>\n Boolean(entity.metadata.annotations?.['backstage.io/orphan']),\n};\n\n/**\n * Matches on different semantic properties of the entity\n */\nexport function createIsMatcher(\n parameters: string[],\n onParseError: (error: Error) => void,\n): EntityMatcherFn {\n const matchers = parameters.flatMap(parameter => {\n const matcher = allowedMatchers[parameter.toLowerCase()];\n if (!matcher) {\n const known = Object.keys(allowedMatchers).map(m => `'${m}'`);\n onParseError(\n new InputError(\n `'${parameter}' is not a valid parameter for 'is' filter expressions, expected one of ${known}`,\n ),\n );\n return [];\n }\n return [matcher];\n });\n\n return entity =>\n matchers.length ? matchers.some(matcher => matcher(entity)) : true;\n}\n"],"names":[],"mappings":";;AAmBA,MAAM,eAAA,GAAmD;AAAA,EACvD,QAAQ,CAAA,MAAA,KACN,OAAA,CAAQ,OAAO,QAAA,CAAS,WAAA,GAAc,qBAAqB,CAAC;AAChE,CAAA;AAKO,SAAS,eAAA,CACd,YACA,YAAA,EACiB;AACjB,EAAA,MAAM,QAAA,GAAW,UAAA,CAAW,OAAA,CAAQ,CAAA,SAAA,KAAa;AAC/C,IAAA,MAAM,OAAA,GAAU,eAAA,CAAgB,SAAA,CAAU,WAAA,EAAa,CAAA;AACvD,IAAA,IAAI,CAAC,OAAA,EAAS;AACZ,MAAA,MAAM,KAAA,GAAQ,OAAO,IAAA,CAAK,eAAe,EAAE,GAAA,CAAI,CAAA,CAAA,KAAK,CAAA,CAAA,EAAI,CAAC,CAAA,CAAA,CAAG,CAAA;AAC5D,MAAA,YAAA;AAAA,QACE,IAAI,UAAA;AAAA,UACF,CAAA,CAAA,EAAI,SAAS,CAAA,wEAAA,EAA2E,KAAK,CAAA;AAAA;AAC/F,OACF;AACA,MAAA,OAAO,EAAC;AAAA,IACV;AACA,IAAA,OAAO,CAAC,OAAO,CAAA;AAAA,EACjB,CAAC,CAAA;AAED,EAAA,OAAO,CAAA,MAAA,KACL,SAAS,MAAA,GAAS,QAAA,CAAS,KAAK,CAAA,OAAA,KAAW,OAAA,CAAQ,MAAM,CAAC,CAAA,GAAI,IAAA;AAClE;;;;"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
function createKindMatcher(parameters, _onParseError) {
|
|
2
|
-
const items = parameters.map((p) => p.
|
|
3
|
-
return (entity) => items.includes(entity.kind.
|
|
2
|
+
const items = parameters.map((p) => p.toLowerCase());
|
|
3
|
+
return (entity) => items.includes(entity.kind.toLowerCase());
|
|
4
4
|
}
|
|
5
5
|
|
|
6
6
|
export { createKindMatcher };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"createKindMatcher.esm.js","sources":["../../../../src/alpha/filter/matchers/createKindMatcher.ts"],"sourcesContent":["/*\n * Copyright 2023 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { EntityMatcherFn } from './types';\n\n/**\n * Matches on kind\n */\nexport function createKindMatcher(\n parameters: string[],\n _onParseError: (error: Error) => void,\n): EntityMatcherFn {\n const items = parameters.map(p => p.
|
|
1
|
+
{"version":3,"file":"createKindMatcher.esm.js","sources":["../../../../src/alpha/filter/matchers/createKindMatcher.ts"],"sourcesContent":["/*\n * Copyright 2023 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { EntityMatcherFn } from './types';\n\n/**\n * Matches on kind\n */\nexport function createKindMatcher(\n parameters: string[],\n _onParseError: (error: Error) => void,\n): EntityMatcherFn {\n const items = parameters.map(p => p.toLowerCase());\n return entity => items.includes(entity.kind.toLowerCase());\n}\n"],"names":[],"mappings":"AAqBO,SAAS,iBAAA,CACd,YACA,aAAA,EACiB;AACjB,EAAA,MAAM,QAAQ,UAAA,CAAW,GAAA,CAAI,CAAA,CAAA,KAAK,CAAA,CAAE,aAAa,CAAA;AACjD,EAAA,OAAO,YAAU,KAAA,CAAM,QAAA,CAAS,MAAA,CAAO,IAAA,CAAK,aAAa,CAAA;AAC3D;;;;"}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
function createTypeMatcher(parameters, _onParseError) {
|
|
2
|
-
const items = parameters.map((p) => p.
|
|
2
|
+
const items = parameters.map((p) => p.toLowerCase());
|
|
3
3
|
return (entity) => {
|
|
4
4
|
const value = entity.spec?.type;
|
|
5
|
-
return typeof value === "string" && items.includes(value.
|
|
5
|
+
return typeof value === "string" && items.includes(value.toLowerCase());
|
|
6
6
|
};
|
|
7
7
|
}
|
|
8
8
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"createTypeMatcher.esm.js","sources":["../../../../src/alpha/filter/matchers/createTypeMatcher.ts"],"sourcesContent":["/*\n * Copyright 2023 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { EntityMatcherFn } from './types';\n\n/**\n * Matches on spec.type\n */\nexport function createTypeMatcher(\n parameters: string[],\n _onParseError: (error: Error) => void,\n): EntityMatcherFn {\n const items = parameters.map(p => p.
|
|
1
|
+
{"version":3,"file":"createTypeMatcher.esm.js","sources":["../../../../src/alpha/filter/matchers/createTypeMatcher.ts"],"sourcesContent":["/*\n * Copyright 2023 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { EntityMatcherFn } from './types';\n\n/**\n * Matches on spec.type\n */\nexport function createTypeMatcher(\n parameters: string[],\n _onParseError: (error: Error) => void,\n): EntityMatcherFn {\n const items = parameters.map(p => p.toLowerCase());\n return entity => {\n const value = entity.spec?.type;\n return typeof value === 'string' && items.includes(value.toLowerCase());\n };\n}\n"],"names":[],"mappings":"AAqBO,SAAS,iBAAA,CACd,YACA,aAAA,EACiB;AACjB,EAAA,MAAM,QAAQ,UAAA,CAAW,GAAA,CAAI,CAAA,CAAA,KAAK,CAAA,CAAE,aAAa,CAAA;AACjD,EAAA,OAAO,CAAA,MAAA,KAAU;AACf,IAAA,MAAM,KAAA,GAAQ,OAAO,IAAA,EAAM,IAAA;AAC3B,IAAA,OAAO,OAAO,KAAA,KAAU,QAAA,IAAY,MAAM,QAAA,CAAS,KAAA,CAAM,aAAa,CAAA;AAAA,EACxE,CAAA;AACF;;;;"}
|
|
@@ -69,10 +69,10 @@ class DefaultEntityPresentationApi {
|
|
|
69
69
|
const renderer = options.renderer ?? createDefaultRenderer({ async: true });
|
|
70
70
|
const kindIcons = {};
|
|
71
71
|
Object.entries(DEFAULT_ICONS).forEach(([kind, icon]) => {
|
|
72
|
-
kindIcons[kind.
|
|
72
|
+
kindIcons[kind.toLowerCase()] = icon;
|
|
73
73
|
});
|
|
74
74
|
Object.entries(options.kindIcons ?? {}).forEach(([kind, icon]) => {
|
|
75
|
-
kindIcons[kind.
|
|
75
|
+
kindIcons[kind.toLowerCase()] = icon;
|
|
76
76
|
});
|
|
77
77
|
if (renderer.async) {
|
|
78
78
|
if (!options.catalogApi) {
|
|
@@ -228,7 +228,7 @@ class DefaultEntityPresentationApi {
|
|
|
228
228
|
} else if (renderedIcon === false) {
|
|
229
229
|
return false;
|
|
230
230
|
}
|
|
231
|
-
return this.#kindIcons[kind.
|
|
231
|
+
return this.#kindIcons[kind.toLowerCase()];
|
|
232
232
|
}
|
|
233
233
|
}
|
|
234
234
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"DefaultEntityPresentationApi.esm.js","sources":["../../../src/apis/EntityPresentationApi/DefaultEntityPresentationApi.ts"],"sourcesContent":["/*\n * Copyright 2023 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport {\n Entity,\n parseEntityRef,\n stringifyEntityRef,\n} from '@backstage/catalog-model';\nimport { IconComponent } from '@backstage/core-plugin-api';\nimport {\n CatalogApi,\n EntityPresentationApi,\n EntityRefPresentation,\n EntityRefPresentationSnapshot,\n} from '@backstage/plugin-catalog-react';\nimport { durationToMilliseconds, HumanDuration } from '@backstage/types';\nimport DataLoader from 'dataloader';\nimport ObservableImpl from 'zen-observable';\nimport {\n createDefaultRenderer,\n DEFAULT_BATCH_DELAY,\n DEFAULT_CACHE_TTL,\n DEFAULT_ICONS,\n} from './defaults';\n\n/**\n * A custom renderer for the {@link DefaultEntityPresentationApi}.\n *\n * @public\n */\nexport interface DefaultEntityPresentationApiRenderer {\n /**\n * Whether to request the entity from the catalog API asynchronously.\n *\n * @remarks\n *\n * If this is set to true, entity data will be streamed in from the catalog\n * whenever needed, and the render function may be called more than once:\n * first when no entity data existed (or with old cached data), and then again\n * at a later point when data is loaded from the catalog that proved to be\n * different from the old one.\n *\n * @defaultValue true\n */\n async?: boolean;\n\n /**\n * The actual render function.\n *\n * @remarks\n *\n * This function may be called multiple times.\n *\n * The loading flag signals that the framework MAY be trying to load more\n * entity data from the catalog and call the render function again, if it\n * succeeds. In some cases you may want to render a loading state in that\n * case.\n *\n * The entity may or may not be given. If the caller of the presentation API\n * did present an entity upfront, then that's what will be passed in here.\n * Otherwise, it may be a server-side entity that either comes from a local\n * cache or directly from the server.\n *\n * In either case, the renderer should return a presentation that is the most\n * useful possible for the end user, given the data that is available.\n */\n render: (options: {\n entityRef: string;\n loading: boolean;\n entity: Entity | undefined;\n context: {\n defaultKind?: string;\n defaultNamespace?: string;\n };\n }) => {\n snapshot: Omit<EntityRefPresentationSnapshot, 'entityRef'>;\n };\n}\n\n/**\n * Options for the {@link DefaultEntityPresentationApi}.\n *\n * @public\n */\nexport interface DefaultEntityPresentationApiOptions {\n /**\n * The catalog API to use. If you want to use any asynchronous features, you\n * must supply one.\n */\n catalogApi?: CatalogApi;\n\n /**\n * When to expire entities that have been loaded from the catalog API and\n * cached for a while.\n *\n * @defaultValue 10 seconds\n * @remarks\n *\n * The higher this value, the lower the load on the catalog API, but also the\n * higher the risk of users seeing stale data.\n */\n cacheTtl?: HumanDuration;\n\n /**\n * For how long to wait before sending a batch of entity references to the\n * catalog API.\n *\n * @defaultValue 50 milliseconds\n * @remarks\n *\n * The higher this value, the greater the chance of batching up requests from\n * across a page, but also the longer the lag time before displaying accurate\n * information.\n */\n batchDelay?: HumanDuration;\n\n /**\n * A mapping from kinds to icons.\n *\n * @remarks\n *\n * The keys are kinds (case insensitive) that map to icon values to represent\n * kinds by. These are merged with the default set of icons.\n */\n kindIcons?: Record<string, IconComponent>;\n\n /**\n * A custom renderer, if any.\n */\n renderer?: DefaultEntityPresentationApiRenderer;\n}\n\ninterface CacheEntry {\n updatedAt: number;\n entity: Entity | undefined;\n}\n\n// Simple expiry map for the data loader, which only expects a map that implements set, get, and delete and clear\nexport class ExpiryMap<K, V> extends Map<K, V> {\n #ttlMs: number;\n #timestamps: Map<K, number> = new Map();\n\n constructor(ttlMs: number) {\n super();\n this.#ttlMs = ttlMs;\n }\n\n set(key: K, value: V) {\n const result = super.set(key, value);\n this.#timestamps.set(key, Date.now());\n return result;\n }\n\n get(key: K) {\n if (!this.has(key)) {\n return undefined;\n }\n const timestamp = this.#timestamps.get(key)!;\n if (Date.now() - timestamp > this.#ttlMs) {\n this.delete(key);\n return undefined;\n }\n return super.get(key);\n }\n\n delete(key: K) {\n this.#timestamps.delete(key);\n return super.delete(key);\n }\n\n clear() {\n this.#timestamps.clear();\n return super.clear();\n }\n}\n\n/**\n * Default implementation of the {@link @backstage/plugin-catalog-react#EntityPresentationApi}.\n *\n * @public\n */\nexport class DefaultEntityPresentationApi implements EntityPresentationApi {\n /**\n * Creates a new presentation API that does not reach out to the catalog.\n */\n static createLocal(): EntityPresentationApi {\n return new DefaultEntityPresentationApi({\n renderer: createDefaultRenderer({ async: false }),\n });\n }\n\n /**\n * Creates a new presentation API that calls out to the catalog as needed to\n * get additional information about entities.\n */\n static create(\n options: DefaultEntityPresentationApiOptions,\n ): EntityPresentationApi {\n return new DefaultEntityPresentationApi(options);\n }\n\n // This cache holds on to all entity data ever loaded, no matter how old. Each\n // entry is tagged with a timestamp of when it was inserted. We use this map\n // to be able to always render SOME data even though the information is old.\n // Entities change very rarely, so it's likely that the rendered information\n // was perfectly fine in the first place.\n readonly #cache: Map<string, CacheEntry>;\n readonly #cacheTtlMs: number;\n readonly #loader: DataLoader<string, Entity | undefined> | undefined;\n readonly #kindIcons: Record<string, IconComponent>; // lowercased kinds\n readonly #renderer: DefaultEntityPresentationApiRenderer;\n\n private constructor(options: DefaultEntityPresentationApiOptions) {\n const cacheTtl = options.cacheTtl ?? DEFAULT_CACHE_TTL;\n const batchDelay = options.batchDelay ?? DEFAULT_BATCH_DELAY;\n const renderer = options.renderer ?? createDefaultRenderer({ async: true });\n\n const kindIcons: Record<string, IconComponent> = {};\n Object.entries(DEFAULT_ICONS).forEach(([kind, icon]) => {\n kindIcons[kind.toLocaleLowerCase('en-US')] = icon;\n });\n Object.entries(options.kindIcons ?? {}).forEach(([kind, icon]) => {\n kindIcons[kind.toLocaleLowerCase('en-US')] = icon;\n });\n\n if (renderer.async) {\n if (!options.catalogApi) {\n throw new TypeError(`Asynchronous rendering requires a catalog API`);\n }\n this.#loader = this.#createLoader({\n cacheTtl,\n batchDelay,\n renderer,\n catalogApi: options.catalogApi,\n });\n }\n\n this.#cacheTtlMs = durationToMilliseconds(cacheTtl);\n this.#cache = new Map();\n this.#kindIcons = kindIcons;\n this.#renderer = renderer;\n }\n\n /** {@inheritdoc @backstage/plugin-catalog-react#EntityPresentationApi.forEntity} */\n forEntity(\n entityOrRef: Entity | string,\n context?: {\n defaultKind?: string;\n defaultNamespace?: string;\n },\n ): EntityRefPresentation {\n const { entityRef, kind, entity, needsLoad } =\n this.#getEntityForInitialRender(entityOrRef);\n\n // Make a wrapping helper for rendering\n const render = (options: {\n loading: boolean;\n entity?: Entity;\n }): EntityRefPresentationSnapshot => {\n const { snapshot } = this.#renderer.render({\n entityRef: entityRef,\n loading: options.loading,\n entity: options.entity,\n context: context || {},\n });\n return {\n ...snapshot,\n entityRef: entityRef,\n Icon: this.#maybeFallbackIcon(snapshot.Icon, kind),\n };\n };\n\n // First the initial render\n let initialSnapshot: EntityRefPresentationSnapshot;\n try {\n initialSnapshot = render({\n loading: needsLoad,\n entity: entity,\n });\n } catch {\n // This is what gets presented if the renderer throws an error\n initialSnapshot = {\n primaryTitle: entityRef,\n entityRef: entityRef,\n };\n }\n\n if (!needsLoad) {\n return {\n snapshot: initialSnapshot,\n promise: Promise.resolve(initialSnapshot),\n };\n }\n\n // Load the entity and render it\n const maybeUpdatedSnapshot = Promise.resolve()\n .then(() => {\n return this.#loader?.load(entityRef);\n })\n .then(newEntity => {\n // We re-render no matter if we get back a new entity or the old\n // one or nothing, because of the now false loading state - in\n // case the renderer outputs different data depending on that\n return render({\n loading: false,\n entity: newEntity ?? entity,\n });\n })\n .catch(() => {\n // Intentionally ignored - we do not propagate errors to the\n // caller here. The presentation API should be error free and\n // always return SOMETHING that makes sense to render, and we have\n // already ensured above that the initial snapshot was that.\n return undefined;\n });\n\n const observable = new ObservableImpl<EntityRefPresentationSnapshot>(\n subscriber => {\n let aborted = false;\n\n maybeUpdatedSnapshot\n .then(updatedSnapshot => {\n if (updatedSnapshot) {\n subscriber.next(updatedSnapshot);\n }\n })\n .finally(() => {\n if (!aborted) {\n subscriber.complete();\n }\n });\n\n return () => {\n aborted = true;\n };\n },\n );\n\n const promise = maybeUpdatedSnapshot.then(updatedSnapshot => {\n return updatedSnapshot ?? initialSnapshot;\n });\n\n return {\n snapshot: initialSnapshot,\n update$: observable,\n promise: promise,\n };\n }\n\n #getEntityForInitialRender(entityOrRef: Entity | string): {\n entity: Entity | undefined;\n kind: string;\n entityRef: string;\n needsLoad: boolean;\n } {\n // If we were given an entity in the first place, we use it for a single\n // pass of rendering and assume that it's up to date and not partial (i.e.\n // we expect that it wasn't fetched in such a way that the required fields\n // of the renderer were excluded)\n if (typeof entityOrRef !== 'string') {\n return {\n entity: entityOrRef,\n kind: entityOrRef.kind,\n entityRef: stringifyEntityRef(entityOrRef),\n needsLoad: false,\n };\n }\n\n const cached = this.#cache.get(entityOrRef);\n const cachedEntity: Entity | undefined = cached?.entity;\n const cacheNeedsUpdate =\n !cached || Date.now() - cached.updatedAt > this.#cacheTtlMs;\n const needsLoad =\n cacheNeedsUpdate &&\n this.#renderer.async !== false &&\n this.#loader !== undefined;\n\n return {\n entity: cachedEntity,\n kind: parseEntityRef(entityOrRef).kind,\n entityRef: entityOrRef,\n needsLoad,\n };\n }\n\n #createLoader(options: {\n catalogApi: CatalogApi;\n cacheTtl: HumanDuration;\n batchDelay: HumanDuration;\n renderer: DefaultEntityPresentationApiRenderer;\n }): DataLoader<string, Entity | undefined> {\n const cacheTtlMs = durationToMilliseconds(options.cacheTtl);\n const batchDelayMs = durationToMilliseconds(options.batchDelay);\n\n return new DataLoader(\n async (entityRefs: readonly string[]) => {\n const { items } = await options.catalogApi!.getEntitiesByRefs({\n entityRefs: entityRefs as string[],\n fields: [\n 'kind',\n 'metadata.name',\n 'metadata.namespace',\n 'metadata.title',\n 'metadata.description',\n 'spec.profile.displayName',\n 'spec.type',\n ],\n });\n\n const now = Date.now();\n entityRefs.forEach((entityRef, index) => {\n this.#cache.set(entityRef, {\n updatedAt: now,\n entity: items[index],\n });\n });\n\n return items;\n },\n {\n name: 'DefaultEntityPresentationApi',\n // This cache is the one that the data loader uses internally for\n // memoizing requests; essentially what it achieves is that multiple\n // requests for the same entity ref will be batched up into a single\n // request and then the resulting promises are held on to. We put an\n // expiring map here, which makes it so that it re-fetches data with the\n // expiry cadence of that map. Otherwise it would only fetch a given ref\n // once and then never try again. This cache does therefore not fulfill\n // the same purpose as the one that is in the root of the class.\n cacheMap: new ExpiryMap(cacheTtlMs),\n maxBatchSize: 100,\n batchScheduleFn: batchDelayMs\n ? cb => setTimeout(cb, batchDelayMs)\n : undefined,\n },\n );\n }\n\n #maybeFallbackIcon(\n renderedIcon: IconComponent | false | undefined,\n kind: string,\n ): IconComponent | false | undefined {\n if (renderedIcon) {\n return renderedIcon;\n } else if (renderedIcon === false) {\n return false;\n }\n\n return this.#kindIcons[kind.toLocaleLowerCase('en-US')];\n }\n}\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"DefaultEntityPresentationApi.esm.js","sources":["../../../src/apis/EntityPresentationApi/DefaultEntityPresentationApi.ts"],"sourcesContent":["/*\n * Copyright 2023 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport {\n Entity,\n parseEntityRef,\n stringifyEntityRef,\n} from '@backstage/catalog-model';\nimport { IconComponent } from '@backstage/core-plugin-api';\nimport {\n CatalogApi,\n EntityPresentationApi,\n EntityRefPresentation,\n EntityRefPresentationSnapshot,\n} from '@backstage/plugin-catalog-react';\nimport { durationToMilliseconds, HumanDuration } from '@backstage/types';\nimport DataLoader from 'dataloader';\nimport ObservableImpl from 'zen-observable';\nimport {\n createDefaultRenderer,\n DEFAULT_BATCH_DELAY,\n DEFAULT_CACHE_TTL,\n DEFAULT_ICONS,\n} from './defaults';\n\n/**\n * A custom renderer for the {@link DefaultEntityPresentationApi}.\n *\n * @public\n */\nexport interface DefaultEntityPresentationApiRenderer {\n /**\n * Whether to request the entity from the catalog API asynchronously.\n *\n * @remarks\n *\n * If this is set to true, entity data will be streamed in from the catalog\n * whenever needed, and the render function may be called more than once:\n * first when no entity data existed (or with old cached data), and then again\n * at a later point when data is loaded from the catalog that proved to be\n * different from the old one.\n *\n * @defaultValue true\n */\n async?: boolean;\n\n /**\n * The actual render function.\n *\n * @remarks\n *\n * This function may be called multiple times.\n *\n * The loading flag signals that the framework MAY be trying to load more\n * entity data from the catalog and call the render function again, if it\n * succeeds. In some cases you may want to render a loading state in that\n * case.\n *\n * The entity may or may not be given. If the caller of the presentation API\n * did present an entity upfront, then that's what will be passed in here.\n * Otherwise, it may be a server-side entity that either comes from a local\n * cache or directly from the server.\n *\n * In either case, the renderer should return a presentation that is the most\n * useful possible for the end user, given the data that is available.\n */\n render: (options: {\n entityRef: string;\n loading: boolean;\n entity: Entity | undefined;\n context: {\n defaultKind?: string;\n defaultNamespace?: string;\n };\n }) => {\n snapshot: Omit<EntityRefPresentationSnapshot, 'entityRef'>;\n };\n}\n\n/**\n * Options for the {@link DefaultEntityPresentationApi}.\n *\n * @public\n */\nexport interface DefaultEntityPresentationApiOptions {\n /**\n * The catalog API to use. If you want to use any asynchronous features, you\n * must supply one.\n */\n catalogApi?: CatalogApi;\n\n /**\n * When to expire entities that have been loaded from the catalog API and\n * cached for a while.\n *\n * @defaultValue 10 seconds\n * @remarks\n *\n * The higher this value, the lower the load on the catalog API, but also the\n * higher the risk of users seeing stale data.\n */\n cacheTtl?: HumanDuration;\n\n /**\n * For how long to wait before sending a batch of entity references to the\n * catalog API.\n *\n * @defaultValue 50 milliseconds\n * @remarks\n *\n * The higher this value, the greater the chance of batching up requests from\n * across a page, but also the longer the lag time before displaying accurate\n * information.\n */\n batchDelay?: HumanDuration;\n\n /**\n * A mapping from kinds to icons.\n *\n * @remarks\n *\n * The keys are kinds (case insensitive) that map to icon values to represent\n * kinds by. These are merged with the default set of icons.\n */\n kindIcons?: Record<string, IconComponent>;\n\n /**\n * A custom renderer, if any.\n */\n renderer?: DefaultEntityPresentationApiRenderer;\n}\n\ninterface CacheEntry {\n updatedAt: number;\n entity: Entity | undefined;\n}\n\n// Simple expiry map for the data loader, which only expects a map that implements set, get, and delete and clear\nexport class ExpiryMap<K, V> extends Map<K, V> {\n #ttlMs: number;\n #timestamps: Map<K, number> = new Map();\n\n constructor(ttlMs: number) {\n super();\n this.#ttlMs = ttlMs;\n }\n\n set(key: K, value: V) {\n const result = super.set(key, value);\n this.#timestamps.set(key, Date.now());\n return result;\n }\n\n get(key: K) {\n if (!this.has(key)) {\n return undefined;\n }\n const timestamp = this.#timestamps.get(key)!;\n if (Date.now() - timestamp > this.#ttlMs) {\n this.delete(key);\n return undefined;\n }\n return super.get(key);\n }\n\n delete(key: K) {\n this.#timestamps.delete(key);\n return super.delete(key);\n }\n\n clear() {\n this.#timestamps.clear();\n return super.clear();\n }\n}\n\n/**\n * Default implementation of the {@link @backstage/plugin-catalog-react#EntityPresentationApi}.\n *\n * @public\n */\nexport class DefaultEntityPresentationApi implements EntityPresentationApi {\n /**\n * Creates a new presentation API that does not reach out to the catalog.\n */\n static createLocal(): EntityPresentationApi {\n return new DefaultEntityPresentationApi({\n renderer: createDefaultRenderer({ async: false }),\n });\n }\n\n /**\n * Creates a new presentation API that calls out to the catalog as needed to\n * get additional information about entities.\n */\n static create(\n options: DefaultEntityPresentationApiOptions,\n ): EntityPresentationApi {\n return new DefaultEntityPresentationApi(options);\n }\n\n // This cache holds on to all entity data ever loaded, no matter how old. Each\n // entry is tagged with a timestamp of when it was inserted. We use this map\n // to be able to always render SOME data even though the information is old.\n // Entities change very rarely, so it's likely that the rendered information\n // was perfectly fine in the first place.\n readonly #cache: Map<string, CacheEntry>;\n readonly #cacheTtlMs: number;\n readonly #loader: DataLoader<string, Entity | undefined> | undefined;\n readonly #kindIcons: Record<string, IconComponent>; // lowercased kinds\n readonly #renderer: DefaultEntityPresentationApiRenderer;\n\n private constructor(options: DefaultEntityPresentationApiOptions) {\n const cacheTtl = options.cacheTtl ?? DEFAULT_CACHE_TTL;\n const batchDelay = options.batchDelay ?? DEFAULT_BATCH_DELAY;\n const renderer = options.renderer ?? createDefaultRenderer({ async: true });\n\n const kindIcons: Record<string, IconComponent> = {};\n Object.entries(DEFAULT_ICONS).forEach(([kind, icon]) => {\n kindIcons[kind.toLowerCase()] = icon;\n });\n Object.entries(options.kindIcons ?? {}).forEach(([kind, icon]) => {\n kindIcons[kind.toLowerCase()] = icon;\n });\n\n if (renderer.async) {\n if (!options.catalogApi) {\n throw new TypeError(`Asynchronous rendering requires a catalog API`);\n }\n this.#loader = this.#createLoader({\n cacheTtl,\n batchDelay,\n renderer,\n catalogApi: options.catalogApi,\n });\n }\n\n this.#cacheTtlMs = durationToMilliseconds(cacheTtl);\n this.#cache = new Map();\n this.#kindIcons = kindIcons;\n this.#renderer = renderer;\n }\n\n /** {@inheritdoc @backstage/plugin-catalog-react#EntityPresentationApi.forEntity} */\n forEntity(\n entityOrRef: Entity | string,\n context?: {\n defaultKind?: string;\n defaultNamespace?: string;\n },\n ): EntityRefPresentation {\n const { entityRef, kind, entity, needsLoad } =\n this.#getEntityForInitialRender(entityOrRef);\n\n // Make a wrapping helper for rendering\n const render = (options: {\n loading: boolean;\n entity?: Entity;\n }): EntityRefPresentationSnapshot => {\n const { snapshot } = this.#renderer.render({\n entityRef: entityRef,\n loading: options.loading,\n entity: options.entity,\n context: context || {},\n });\n return {\n ...snapshot,\n entityRef: entityRef,\n Icon: this.#maybeFallbackIcon(snapshot.Icon, kind),\n };\n };\n\n // First the initial render\n let initialSnapshot: EntityRefPresentationSnapshot;\n try {\n initialSnapshot = render({\n loading: needsLoad,\n entity: entity,\n });\n } catch {\n // This is what gets presented if the renderer throws an error\n initialSnapshot = {\n primaryTitle: entityRef,\n entityRef: entityRef,\n };\n }\n\n if (!needsLoad) {\n return {\n snapshot: initialSnapshot,\n promise: Promise.resolve(initialSnapshot),\n };\n }\n\n // Load the entity and render it\n const maybeUpdatedSnapshot = Promise.resolve()\n .then(() => {\n return this.#loader?.load(entityRef);\n })\n .then(newEntity => {\n // We re-render no matter if we get back a new entity or the old\n // one or nothing, because of the now false loading state - in\n // case the renderer outputs different data depending on that\n return render({\n loading: false,\n entity: newEntity ?? entity,\n });\n })\n .catch(() => {\n // Intentionally ignored - we do not propagate errors to the\n // caller here. The presentation API should be error free and\n // always return SOMETHING that makes sense to render, and we have\n // already ensured above that the initial snapshot was that.\n return undefined;\n });\n\n const observable = new ObservableImpl<EntityRefPresentationSnapshot>(\n subscriber => {\n let aborted = false;\n\n maybeUpdatedSnapshot\n .then(updatedSnapshot => {\n if (updatedSnapshot) {\n subscriber.next(updatedSnapshot);\n }\n })\n .finally(() => {\n if (!aborted) {\n subscriber.complete();\n }\n });\n\n return () => {\n aborted = true;\n };\n },\n );\n\n const promise = maybeUpdatedSnapshot.then(updatedSnapshot => {\n return updatedSnapshot ?? initialSnapshot;\n });\n\n return {\n snapshot: initialSnapshot,\n update$: observable,\n promise: promise,\n };\n }\n\n #getEntityForInitialRender(entityOrRef: Entity | string): {\n entity: Entity | undefined;\n kind: string;\n entityRef: string;\n needsLoad: boolean;\n } {\n // If we were given an entity in the first place, we use it for a single\n // pass of rendering and assume that it's up to date and not partial (i.e.\n // we expect that it wasn't fetched in such a way that the required fields\n // of the renderer were excluded)\n if (typeof entityOrRef !== 'string') {\n return {\n entity: entityOrRef,\n kind: entityOrRef.kind,\n entityRef: stringifyEntityRef(entityOrRef),\n needsLoad: false,\n };\n }\n\n const cached = this.#cache.get(entityOrRef);\n const cachedEntity: Entity | undefined = cached?.entity;\n const cacheNeedsUpdate =\n !cached || Date.now() - cached.updatedAt > this.#cacheTtlMs;\n const needsLoad =\n cacheNeedsUpdate &&\n this.#renderer.async !== false &&\n this.#loader !== undefined;\n\n return {\n entity: cachedEntity,\n kind: parseEntityRef(entityOrRef).kind,\n entityRef: entityOrRef,\n needsLoad,\n };\n }\n\n #createLoader(options: {\n catalogApi: CatalogApi;\n cacheTtl: HumanDuration;\n batchDelay: HumanDuration;\n renderer: DefaultEntityPresentationApiRenderer;\n }): DataLoader<string, Entity | undefined> {\n const cacheTtlMs = durationToMilliseconds(options.cacheTtl);\n const batchDelayMs = durationToMilliseconds(options.batchDelay);\n\n return new DataLoader(\n async (entityRefs: readonly string[]) => {\n const { items } = await options.catalogApi!.getEntitiesByRefs({\n entityRefs: entityRefs as string[],\n fields: [\n 'kind',\n 'metadata.name',\n 'metadata.namespace',\n 'metadata.title',\n 'metadata.description',\n 'spec.profile.displayName',\n 'spec.type',\n ],\n });\n\n const now = Date.now();\n entityRefs.forEach((entityRef, index) => {\n this.#cache.set(entityRef, {\n updatedAt: now,\n entity: items[index],\n });\n });\n\n return items;\n },\n {\n name: 'DefaultEntityPresentationApi',\n // This cache is the one that the data loader uses internally for\n // memoizing requests; essentially what it achieves is that multiple\n // requests for the same entity ref will be batched up into a single\n // request and then the resulting promises are held on to. We put an\n // expiring map here, which makes it so that it re-fetches data with the\n // expiry cadence of that map. Otherwise it would only fetch a given ref\n // once and then never try again. This cache does therefore not fulfill\n // the same purpose as the one that is in the root of the class.\n cacheMap: new ExpiryMap(cacheTtlMs),\n maxBatchSize: 100,\n batchScheduleFn: batchDelayMs\n ? cb => setTimeout(cb, batchDelayMs)\n : undefined,\n },\n );\n }\n\n #maybeFallbackIcon(\n renderedIcon: IconComponent | false | undefined,\n kind: string,\n ): IconComponent | false | undefined {\n if (renderedIcon) {\n return renderedIcon;\n } else if (renderedIcon === false) {\n return false;\n }\n\n return this.#kindIcons[kind.toLowerCase()];\n }\n}\n"],"names":[],"mappings":"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"}
|
|
@@ -29,13 +29,13 @@ function AboutContent(props) {
|
|
|
29
29
|
const { entity } = props;
|
|
30
30
|
const classes = useStyles();
|
|
31
31
|
const { t } = useTranslationRef(catalogTranslationRef);
|
|
32
|
-
const isSystem = entity.kind.
|
|
33
|
-
const isResource = entity.kind.
|
|
34
|
-
const isComponent = entity.kind.
|
|
35
|
-
const isAPI = entity.kind.
|
|
36
|
-
const isTemplate = entity.kind.
|
|
37
|
-
const isLocation = entity.kind.
|
|
38
|
-
const isGroup = entity.kind.
|
|
32
|
+
const isSystem = entity.kind.toLowerCase() === "system";
|
|
33
|
+
const isResource = entity.kind.toLowerCase() === "resource";
|
|
34
|
+
const isComponent = entity.kind.toLowerCase() === "component";
|
|
35
|
+
const isAPI = entity.kind.toLowerCase() === "api";
|
|
36
|
+
const isTemplate = entity.kind.toLowerCase() === "template";
|
|
37
|
+
const isLocation = entity.kind.toLowerCase() === "location";
|
|
38
|
+
const isGroup = entity.kind.toLowerCase() === "group";
|
|
39
39
|
const partOfSystemRelations = getEntityRelations(entity, RELATION_PART_OF, {
|
|
40
40
|
kind: "system"
|
|
41
41
|
});
|