@backstage/plugin-catalog 1.30.0-next.3 → 1.30.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +29 -0
- package/dist/alpha/pages.esm.js +40 -27
- package/dist/alpha/pages.esm.js.map +1 -1
- package/dist/alpha.d.ts +30 -10
- package/package.json +23 -23
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,34 @@
|
|
|
1
1
|
# @backstage/plugin-catalog
|
|
2
2
|
|
|
3
|
+
## 1.30.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- 970cb48: Show the pagination text for the offset-paginated catalog table, and remove the pagination bar from the top of the `CatalogTable` when pagination is enabled.
|
|
8
|
+
|
|
9
|
+
### Patch Changes
|
|
10
|
+
|
|
11
|
+
- fb58f20: Internal update to use the new `pluginId` option of `createFrontendPlugin`.
|
|
12
|
+
- 2ddbc50: A new `filter` parameter has been added to `EntityContextMenuItemBlueprint` to make it easier to configure which entities a menu item should appear for. The `filter` parameter is a function which accepts an entity and returns a boolean.
|
|
13
|
+
- bf85d37: Fix for missing `routeRef` when using `core-plugin-api` in a dialog context
|
|
14
|
+
- Updated dependencies
|
|
15
|
+
- @backstage/frontend-plugin-api@0.10.2
|
|
16
|
+
- @backstage/core-components@0.17.2
|
|
17
|
+
- @backstage/catalog-model@1.7.4
|
|
18
|
+
- @backstage/core-compat-api@0.4.2
|
|
19
|
+
- @backstage/plugin-search-react@1.9.0
|
|
20
|
+
- @backstage/plugin-catalog-react@1.18.0
|
|
21
|
+
- @backstage/core-plugin-api@1.10.7
|
|
22
|
+
- @backstage/catalog-client@1.10.0
|
|
23
|
+
- @backstage/integration-react@1.2.7
|
|
24
|
+
- @backstage/plugin-permission-react@0.4.34
|
|
25
|
+
- @backstage/errors@1.2.7
|
|
26
|
+
- @backstage/types@1.2.1
|
|
27
|
+
- @backstage/version-bridge@1.0.11
|
|
28
|
+
- @backstage/plugin-catalog-common@1.1.4
|
|
29
|
+
- @backstage/plugin-scaffolder-common@1.5.11
|
|
30
|
+
- @backstage/plugin-search-common@1.2.18
|
|
31
|
+
|
|
3
32
|
## 1.30.0-next.3
|
|
4
33
|
|
|
5
34
|
### Minor Changes
|
package/dist/alpha/pages.esm.js
CHANGED
|
@@ -2,11 +2,10 @@ import { jsx, Fragment } from 'react/jsx-runtime';
|
|
|
2
2
|
import { convertLegacyRouteRef, compatWrapper } from '@backstage/core-compat-api';
|
|
3
3
|
import { PageBlueprint, createExtensionInput, coreExtensionData } from '@backstage/frontend-plugin-api';
|
|
4
4
|
import { entityRouteRef, AsyncEntityProvider } from '@backstage/plugin-catalog-react';
|
|
5
|
-
import { EntityHeaderBlueprint, EntityContentBlueprint, defaultEntityContentGroups } from '@backstage/plugin-catalog-react/alpha';
|
|
5
|
+
import { EntityHeaderBlueprint, EntityContentBlueprint, EntityContextMenuItemBlueprint, defaultEntityContentGroups } from '@backstage/plugin-catalog-react/alpha';
|
|
6
6
|
import { rootRouteRef } from '../routes.esm.js';
|
|
7
7
|
import { useEntityFromUrl } from '../components/CatalogEntityPage/useEntityFromUrl.esm.js';
|
|
8
8
|
import { buildFilterFn } from './filter/FilterWrapper.esm.js';
|
|
9
|
-
import { EntityHeader } from './components/EntityHeader/EntityHeader.esm.js';
|
|
10
9
|
|
|
11
10
|
const catalogPage = PageBlueprint.makeWithOverrides({
|
|
12
11
|
inputs: {
|
|
@@ -42,7 +41,10 @@ const catalogEntityPage = PageBlueprint.makeWithOverrides({
|
|
|
42
41
|
EntityContentBlueprint.dataRefs.filterExpression.optional(),
|
|
43
42
|
EntityContentBlueprint.dataRefs.group.optional()
|
|
44
43
|
]),
|
|
45
|
-
contextMenuItems: createExtensionInput([
|
|
44
|
+
contextMenuItems: createExtensionInput([
|
|
45
|
+
coreExtensionData.reactElement,
|
|
46
|
+
EntityContextMenuItemBlueprint.dataRefs.filterFunction.optional()
|
|
47
|
+
])
|
|
46
48
|
},
|
|
47
49
|
config: {
|
|
48
50
|
schema: {
|
|
@@ -55,12 +57,13 @@ const catalogEntityPage = PageBlueprint.makeWithOverrides({
|
|
|
55
57
|
routeRef: convertLegacyRouteRef(entityRouteRef),
|
|
56
58
|
loader: async () => {
|
|
57
59
|
const { EntityLayout } = await import('./components/EntityLayout/index.esm.js');
|
|
58
|
-
const menuItems = inputs.contextMenuItems.map(
|
|
59
|
-
|
|
60
|
-
|
|
60
|
+
const menuItems = inputs.contextMenuItems.map((item) => ({
|
|
61
|
+
element: item.get(coreExtensionData.reactElement),
|
|
62
|
+
filter: item.get(EntityContextMenuItemBlueprint.dataRefs.filterFunction) ?? (() => true)
|
|
63
|
+
}));
|
|
61
64
|
const header = inputs.header?.get(
|
|
62
65
|
EntityHeaderBlueprint.dataRefs.element
|
|
63
|
-
)
|
|
66
|
+
);
|
|
64
67
|
let groups = Object.entries(defaultEntityContentGroups).reduce(
|
|
65
68
|
(rest, group) => {
|
|
66
69
|
const [groupId, groupValue] = group;
|
|
@@ -92,26 +95,36 @@ const catalogEntityPage = PageBlueprint.makeWithOverrides({
|
|
|
92
95
|
group.items.push(output);
|
|
93
96
|
}
|
|
94
97
|
const Component = () => {
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
98
|
+
const entityFromUrl = useEntityFromUrl();
|
|
99
|
+
const { entity } = entityFromUrl;
|
|
100
|
+
const filteredMenuItems = entity ? menuItems.filter((i) => i.filter(entity)).map((i) => i.element) : [];
|
|
101
|
+
return /* @__PURE__ */ jsx(AsyncEntityProvider, { ...entityFromUrl, children: /* @__PURE__ */ jsx(
|
|
102
|
+
EntityLayout,
|
|
103
|
+
{
|
|
104
|
+
header,
|
|
105
|
+
contextMenuItems: filteredMenuItems,
|
|
106
|
+
children: Object.values(groups).flatMap(
|
|
107
|
+
({ title, items }) => items.map((output) => /* @__PURE__ */ jsx(
|
|
108
|
+
EntityLayout.Route,
|
|
109
|
+
{
|
|
110
|
+
group: title,
|
|
111
|
+
path: output.get(coreExtensionData.routePath),
|
|
112
|
+
title: output.get(EntityContentBlueprint.dataRefs.title),
|
|
113
|
+
if: buildFilterFn(
|
|
114
|
+
output.get(
|
|
115
|
+
EntityContentBlueprint.dataRefs.filterFunction
|
|
116
|
+
),
|
|
117
|
+
output.get(
|
|
118
|
+
EntityContentBlueprint.dataRefs.filterExpression
|
|
119
|
+
)
|
|
120
|
+
),
|
|
121
|
+
children: output.get(coreExtensionData.reactElement)
|
|
122
|
+
},
|
|
123
|
+
output.get(coreExtensionData.routePath)
|
|
124
|
+
))
|
|
125
|
+
)
|
|
126
|
+
}
|
|
127
|
+
) });
|
|
115
128
|
};
|
|
116
129
|
return compatWrapper(/* @__PURE__ */ jsx(Component, {}));
|
|
117
130
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"pages.esm.js","sources":["../../src/alpha/pages.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 compatWrapper,\n convertLegacyRouteRef,\n} from '@backstage/core-compat-api';\nimport {\n coreExtensionData,\n createExtensionInput,\n PageBlueprint,\n} from '@backstage/frontend-plugin-api';\nimport {\n AsyncEntityProvider,\n entityRouteRef,\n} from '@backstage/plugin-catalog-react';\nimport {\n EntityHeaderBlueprint,\n EntityContentBlueprint,\n defaultEntityContentGroups,\n} from '@backstage/plugin-catalog-react/alpha';\nimport { rootRouteRef } from '../routes';\nimport { useEntityFromUrl } from '../components/CatalogEntityPage/useEntityFromUrl';\nimport { buildFilterFn } from './filter/FilterWrapper';\nimport { EntityHeader } from './components/EntityHeader';\n\nexport const catalogPage = PageBlueprint.makeWithOverrides({\n inputs: {\n filters: createExtensionInput([coreExtensionData.reactElement]),\n },\n factory(originalFactory, { inputs }) {\n return originalFactory({\n defaultPath: '/catalog',\n routeRef: convertLegacyRouteRef(rootRouteRef),\n loader: async () => {\n const { BaseCatalogPage } = await import('../components/CatalogPage');\n const filters = inputs.filters.map(filter =>\n filter.get(coreExtensionData.reactElement),\n );\n return compatWrapper(<BaseCatalogPage filters={<>{filters}</>} />);\n },\n });\n },\n});\n\nexport const catalogEntityPage = PageBlueprint.makeWithOverrides({\n name: 'entity',\n inputs: {\n header: createExtensionInput(\n [EntityHeaderBlueprint.dataRefs.element.optional()],\n { singleton: true, optional: true },\n ),\n contents: createExtensionInput([\n coreExtensionData.reactElement,\n coreExtensionData.routePath,\n coreExtensionData.routeRef.optional(),\n EntityContentBlueprint.dataRefs.title,\n EntityContentBlueprint.dataRefs.filterFunction.optional(),\n EntityContentBlueprint.dataRefs.filterExpression.optional(),\n EntityContentBlueprint.dataRefs.group.optional(),\n ]),\n contextMenuItems: createExtensionInput([coreExtensionData.reactElement]),\n },\n config: {\n schema: {\n groups: z =>\n z\n .array(z.record(z.string(), z.object({ title: z.string() })))\n .optional(),\n },\n },\n factory(originalFactory, { config, inputs }) {\n return originalFactory({\n defaultPath: '/catalog/:namespace/:kind/:name',\n routeRef: convertLegacyRouteRef(entityRouteRef),\n loader: async () => {\n const { EntityLayout } = await import('./components/EntityLayout');\n\n const menuItems = inputs.contextMenuItems.map(item =>\n item.get(coreExtensionData.reactElement),\n );\n\n type Groups = Record<\n string,\n { title: string; items: Array<(typeof inputs.contents)[0]> }\n >;\n\n const header = inputs.header?.get(\n EntityHeaderBlueprint.dataRefs.element,\n ) ?? <EntityHeader contextMenuItems={menuItems} />;\n\n let groups = Object.entries(defaultEntityContentGroups).reduce<Groups>(\n (rest, group) => {\n const [groupId, groupValue] = group;\n return {\n ...rest,\n [groupId]: { title: groupValue, items: [] },\n };\n },\n {},\n );\n\n // config groups override default groups\n if (config.groups) {\n groups = config.groups.reduce<Groups>((rest, group) => {\n const [groupId, groupValue] = Object.entries(group)[0];\n return {\n ...rest,\n [groupId]: { title: groupValue.title, items: [] },\n };\n }, {});\n }\n\n for (const output of inputs.contents) {\n const itemId = output.node.spec.id;\n const itemTitle = output.get(EntityContentBlueprint.dataRefs.title);\n const itemGroup = output.get(EntityContentBlueprint.dataRefs.group);\n const group = itemGroup && groups[itemGroup];\n if (!group) {\n groups[itemId] = { title: itemTitle, items: [output] };\n continue;\n }\n group.items.push(output);\n }\n\n const Component = () => {\n return (\n <AsyncEntityProvider {...useEntityFromUrl()}>\n <EntityLayout header={header} contextMenuItems={menuItems}>\n {Object.values(groups).flatMap(({ title, items }) =>\n items.map(output => (\n <EntityLayout.Route\n group={title}\n key={output.get(coreExtensionData.routePath)}\n path={output.get(coreExtensionData.routePath)}\n title={output.get(EntityContentBlueprint.dataRefs.title)}\n if={buildFilterFn(\n output.get(\n EntityContentBlueprint.dataRefs.filterFunction,\n ),\n output.get(\n EntityContentBlueprint.dataRefs.filterExpression,\n ),\n )}\n >\n {output.get(coreExtensionData.reactElement)}\n </EntityLayout.Route>\n )),\n )}\n </EntityLayout>\n </AsyncEntityProvider>\n );\n };\n\n return compatWrapper(<Component />);\n },\n });\n },\n});\n\nexport default [catalogPage, catalogEntityPage];\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"pages.esm.js","sources":["../../src/alpha/pages.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 compatWrapper,\n convertLegacyRouteRef,\n} from '@backstage/core-compat-api';\nimport {\n coreExtensionData,\n createExtensionInput,\n PageBlueprint,\n} from '@backstage/frontend-plugin-api';\nimport {\n AsyncEntityProvider,\n entityRouteRef,\n} from '@backstage/plugin-catalog-react';\nimport {\n EntityHeaderBlueprint,\n EntityContentBlueprint,\n defaultEntityContentGroups,\n EntityContextMenuItemBlueprint,\n} from '@backstage/plugin-catalog-react/alpha';\nimport { rootRouteRef } from '../routes';\nimport { useEntityFromUrl } from '../components/CatalogEntityPage/useEntityFromUrl';\nimport { buildFilterFn } from './filter/FilterWrapper';\n\nexport const catalogPage = PageBlueprint.makeWithOverrides({\n inputs: {\n filters: createExtensionInput([coreExtensionData.reactElement]),\n },\n factory(originalFactory, { inputs }) {\n return originalFactory({\n defaultPath: '/catalog',\n routeRef: convertLegacyRouteRef(rootRouteRef),\n loader: async () => {\n const { BaseCatalogPage } = await import('../components/CatalogPage');\n const filters = inputs.filters.map(filter =>\n filter.get(coreExtensionData.reactElement),\n );\n return compatWrapper(<BaseCatalogPage filters={<>{filters}</>} />);\n },\n });\n },\n});\n\nexport const catalogEntityPage = PageBlueprint.makeWithOverrides({\n name: 'entity',\n inputs: {\n header: createExtensionInput(\n [EntityHeaderBlueprint.dataRefs.element.optional()],\n { singleton: true, optional: true },\n ),\n contents: createExtensionInput([\n coreExtensionData.reactElement,\n coreExtensionData.routePath,\n coreExtensionData.routeRef.optional(),\n EntityContentBlueprint.dataRefs.title,\n EntityContentBlueprint.dataRefs.filterFunction.optional(),\n EntityContentBlueprint.dataRefs.filterExpression.optional(),\n EntityContentBlueprint.dataRefs.group.optional(),\n ]),\n contextMenuItems: createExtensionInput([\n coreExtensionData.reactElement,\n EntityContextMenuItemBlueprint.dataRefs.filterFunction.optional(),\n ]),\n },\n config: {\n schema: {\n groups: z =>\n z\n .array(z.record(z.string(), z.object({ title: z.string() })))\n .optional(),\n },\n },\n factory(originalFactory, { config, inputs }) {\n return originalFactory({\n defaultPath: '/catalog/:namespace/:kind/:name',\n routeRef: convertLegacyRouteRef(entityRouteRef),\n loader: async () => {\n const { EntityLayout } = await import('./components/EntityLayout');\n\n const menuItems = inputs.contextMenuItems.map(item => ({\n element: item.get(coreExtensionData.reactElement),\n filter:\n item.get(EntityContextMenuItemBlueprint.dataRefs.filterFunction) ??\n (() => true),\n }));\n\n type Groups = Record<\n string,\n { title: string; items: Array<(typeof inputs.contents)[0]> }\n >;\n\n const header = inputs.header?.get(\n EntityHeaderBlueprint.dataRefs.element,\n );\n\n let groups = Object.entries(defaultEntityContentGroups).reduce<Groups>(\n (rest, group) => {\n const [groupId, groupValue] = group;\n return {\n ...rest,\n [groupId]: { title: groupValue, items: [] },\n };\n },\n {},\n );\n\n // config groups override default groups\n if (config.groups) {\n groups = config.groups.reduce<Groups>((rest, group) => {\n const [groupId, groupValue] = Object.entries(group)[0];\n return {\n ...rest,\n [groupId]: { title: groupValue.title, items: [] },\n };\n }, {});\n }\n\n for (const output of inputs.contents) {\n const itemId = output.node.spec.id;\n const itemTitle = output.get(EntityContentBlueprint.dataRefs.title);\n const itemGroup = output.get(EntityContentBlueprint.dataRefs.group);\n const group = itemGroup && groups[itemGroup];\n if (!group) {\n groups[itemId] = { title: itemTitle, items: [output] };\n continue;\n }\n group.items.push(output);\n }\n\n const Component = () => {\n const entityFromUrl = useEntityFromUrl();\n const { entity } = entityFromUrl;\n const filteredMenuItems = entity\n ? menuItems.filter(i => i.filter(entity)).map(i => i.element)\n : [];\n\n return (\n <AsyncEntityProvider {...entityFromUrl}>\n <EntityLayout\n header={header}\n contextMenuItems={filteredMenuItems}\n >\n {Object.values(groups).flatMap(({ title, items }) =>\n items.map(output => (\n <EntityLayout.Route\n group={title}\n key={output.get(coreExtensionData.routePath)}\n path={output.get(coreExtensionData.routePath)}\n title={output.get(EntityContentBlueprint.dataRefs.title)}\n if={buildFilterFn(\n output.get(\n EntityContentBlueprint.dataRefs.filterFunction,\n ),\n output.get(\n EntityContentBlueprint.dataRefs.filterExpression,\n ),\n )}\n >\n {output.get(coreExtensionData.reactElement)}\n </EntityLayout.Route>\n )),\n )}\n </EntityLayout>\n </AsyncEntityProvider>\n );\n };\n\n return compatWrapper(<Component />);\n },\n });\n },\n});\n\nexport default [catalogPage, catalogEntityPage];\n"],"names":[],"mappings":"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"}
|
package/dist/alpha.d.ts
CHANGED
|
@@ -481,27 +481,45 @@ declare const _default: _backstage_frontend_plugin_api.FrontendPlugin<{
|
|
|
481
481
|
"entity-context-menu-item:catalog/copy-entity-url": _backstage_frontend_plugin_api.ExtensionDefinition<{
|
|
482
482
|
kind: "entity-context-menu-item";
|
|
483
483
|
name: "copy-entity-url";
|
|
484
|
-
config: {
|
|
485
|
-
|
|
486
|
-
|
|
484
|
+
config: {
|
|
485
|
+
filter: _backstage_plugin_catalog_react_alpha.EntityPredicate | undefined;
|
|
486
|
+
};
|
|
487
|
+
configInput: {
|
|
488
|
+
filter?: _backstage_plugin_catalog_react_alpha.EntityPredicate | undefined;
|
|
489
|
+
};
|
|
490
|
+
output: _backstage_frontend_plugin_api.ConfigurableExtensionDataRef<react.JSX.Element, "core.reactElement", {}> | _backstage_frontend_plugin_api.ConfigurableExtensionDataRef<(entity: _backstage_catalog_model.Entity) => boolean, "catalog.entity-filter-function", {
|
|
491
|
+
optional: true;
|
|
492
|
+
}>;
|
|
487
493
|
inputs: {};
|
|
488
494
|
params: _backstage_plugin_catalog_react_alpha.EntityContextMenuItemParams;
|
|
489
495
|
}>;
|
|
490
496
|
"entity-context-menu-item:catalog/inspect-entity": _backstage_frontend_plugin_api.ExtensionDefinition<{
|
|
491
497
|
kind: "entity-context-menu-item";
|
|
492
498
|
name: "inspect-entity";
|
|
493
|
-
config: {
|
|
494
|
-
|
|
495
|
-
|
|
499
|
+
config: {
|
|
500
|
+
filter: _backstage_plugin_catalog_react_alpha.EntityPredicate | undefined;
|
|
501
|
+
};
|
|
502
|
+
configInput: {
|
|
503
|
+
filter?: _backstage_plugin_catalog_react_alpha.EntityPredicate | undefined;
|
|
504
|
+
};
|
|
505
|
+
output: _backstage_frontend_plugin_api.ConfigurableExtensionDataRef<react.JSX.Element, "core.reactElement", {}> | _backstage_frontend_plugin_api.ConfigurableExtensionDataRef<(entity: _backstage_catalog_model.Entity) => boolean, "catalog.entity-filter-function", {
|
|
506
|
+
optional: true;
|
|
507
|
+
}>;
|
|
496
508
|
inputs: {};
|
|
497
509
|
params: _backstage_plugin_catalog_react_alpha.EntityContextMenuItemParams;
|
|
498
510
|
}>;
|
|
499
511
|
"entity-context-menu-item:catalog/unregister-entity": _backstage_frontend_plugin_api.ExtensionDefinition<{
|
|
500
512
|
kind: "entity-context-menu-item";
|
|
501
513
|
name: "unregister-entity";
|
|
502
|
-
config: {
|
|
503
|
-
|
|
504
|
-
|
|
514
|
+
config: {
|
|
515
|
+
filter: _backstage_plugin_catalog_react_alpha.EntityPredicate | undefined;
|
|
516
|
+
};
|
|
517
|
+
configInput: {
|
|
518
|
+
filter?: _backstage_plugin_catalog_react_alpha.EntityPredicate | undefined;
|
|
519
|
+
};
|
|
520
|
+
output: _backstage_frontend_plugin_api.ConfigurableExtensionDataRef<react.JSX.Element, "core.reactElement", {}> | _backstage_frontend_plugin_api.ConfigurableExtensionDataRef<(entity: _backstage_catalog_model.Entity) => boolean, "catalog.entity-filter-function", {
|
|
521
|
+
optional: true;
|
|
522
|
+
}>;
|
|
505
523
|
inputs: {};
|
|
506
524
|
params: _backstage_plugin_catalog_react_alpha.EntityContextMenuItemParams;
|
|
507
525
|
}>;
|
|
@@ -583,7 +601,9 @@ declare const _default: _backstage_frontend_plugin_api.FrontendPlugin<{
|
|
|
583
601
|
singleton: false;
|
|
584
602
|
optional: false;
|
|
585
603
|
}>;
|
|
586
|
-
contextMenuItems: _backstage_frontend_plugin_api.ExtensionInput<_backstage_frontend_plugin_api.ConfigurableExtensionDataRef<react.JSX.Element, "core.reactElement", {}
|
|
604
|
+
contextMenuItems: _backstage_frontend_plugin_api.ExtensionInput<_backstage_frontend_plugin_api.ConfigurableExtensionDataRef<react.JSX.Element, "core.reactElement", {}> | _backstage_frontend_plugin_api.ConfigurableExtensionDataRef<(entity: _backstage_catalog_model.Entity) => boolean, "catalog.entity-filter-function", {
|
|
605
|
+
optional: true;
|
|
606
|
+
}>, {
|
|
587
607
|
singleton: false;
|
|
588
608
|
optional: false;
|
|
589
609
|
}>;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@backstage/plugin-catalog",
|
|
3
|
-
"version": "1.30.0
|
|
3
|
+
"version": "1.30.0",
|
|
4
4
|
"description": "The Backstage plugin for browsing the Backstage catalog",
|
|
5
5
|
"backstage": {
|
|
6
6
|
"role": "frontend-plugin",
|
|
@@ -70,22 +70,22 @@
|
|
|
70
70
|
"test": "backstage-cli package test"
|
|
71
71
|
},
|
|
72
72
|
"dependencies": {
|
|
73
|
-
"@backstage/catalog-client": "1.10.0
|
|
74
|
-
"@backstage/catalog-model": "1.7.
|
|
75
|
-
"@backstage/core-compat-api": "0.4.2
|
|
76
|
-
"@backstage/core-components": "0.17.2
|
|
77
|
-
"@backstage/core-plugin-api": "1.10.7
|
|
78
|
-
"@backstage/errors": "1.2.7",
|
|
79
|
-
"@backstage/frontend-plugin-api": "0.10.2
|
|
80
|
-
"@backstage/integration-react": "1.2.7
|
|
81
|
-
"@backstage/plugin-catalog-common": "1.1.4
|
|
82
|
-
"@backstage/plugin-catalog-react": "1.18.0
|
|
83
|
-
"@backstage/plugin-permission-react": "0.4.34
|
|
84
|
-
"@backstage/plugin-scaffolder-common": "1.5.11
|
|
85
|
-
"@backstage/plugin-search-common": "1.2.18
|
|
86
|
-
"@backstage/plugin-search-react": "1.9.0
|
|
87
|
-
"@backstage/types": "1.2.1",
|
|
88
|
-
"@backstage/version-bridge": "1.0.11",
|
|
73
|
+
"@backstage/catalog-client": "^1.10.0",
|
|
74
|
+
"@backstage/catalog-model": "^1.7.4",
|
|
75
|
+
"@backstage/core-compat-api": "^0.4.2",
|
|
76
|
+
"@backstage/core-components": "^0.17.2",
|
|
77
|
+
"@backstage/core-plugin-api": "^1.10.7",
|
|
78
|
+
"@backstage/errors": "^1.2.7",
|
|
79
|
+
"@backstage/frontend-plugin-api": "^0.10.2",
|
|
80
|
+
"@backstage/integration-react": "^1.2.7",
|
|
81
|
+
"@backstage/plugin-catalog-common": "^1.1.4",
|
|
82
|
+
"@backstage/plugin-catalog-react": "^1.18.0",
|
|
83
|
+
"@backstage/plugin-permission-react": "^0.4.34",
|
|
84
|
+
"@backstage/plugin-scaffolder-common": "^1.5.11",
|
|
85
|
+
"@backstage/plugin-search-common": "^1.2.18",
|
|
86
|
+
"@backstage/plugin-search-react": "^1.9.0",
|
|
87
|
+
"@backstage/types": "^1.2.1",
|
|
88
|
+
"@backstage/version-bridge": "^1.0.11",
|
|
89
89
|
"@material-ui/core": "^4.12.2",
|
|
90
90
|
"@material-ui/icons": "^4.9.1",
|
|
91
91
|
"@material-ui/lab": "4.0.0-alpha.61",
|
|
@@ -100,12 +100,12 @@
|
|
|
100
100
|
"zen-observable": "^0.10.0"
|
|
101
101
|
},
|
|
102
102
|
"devDependencies": {
|
|
103
|
-
"@backstage/cli": "0.32.1
|
|
104
|
-
"@backstage/core-app-api": "1.17.0
|
|
105
|
-
"@backstage/dev-utils": "1.1.10
|
|
106
|
-
"@backstage/frontend-test-utils": "0.3.2
|
|
107
|
-
"@backstage/plugin-permission-common": "0.9.0
|
|
108
|
-
"@backstage/test-utils": "1.7.8
|
|
103
|
+
"@backstage/cli": "^0.32.1",
|
|
104
|
+
"@backstage/core-app-api": "^1.17.0",
|
|
105
|
+
"@backstage/dev-utils": "^1.1.10",
|
|
106
|
+
"@backstage/frontend-test-utils": "^0.3.2",
|
|
107
|
+
"@backstage/plugin-permission-common": "^0.9.0",
|
|
108
|
+
"@backstage/test-utils": "^1.7.8",
|
|
109
109
|
"@testing-library/dom": "^10.0.0",
|
|
110
110
|
"@testing-library/jest-dom": "^6.0.0",
|
|
111
111
|
"@testing-library/react": "^16.0.0",
|