@backstage/plugin-catalog-react 0.0.0-nightly-20231121021721 → 0.0.0-nightly-20231123021445
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 +33 -7
- package/alpha/package.json +1 -1
- package/dist/alpha.esm.js +4 -4
- package/dist/alpha.esm.js.map +1 -1
- package/dist/index.d.ts +14 -2
- package/dist/index.esm.js +100 -35
- package/dist/index.esm.js.map +1 -1
- package/package.json +10 -10
package/CHANGELOG.md
CHANGED
|
@@ -1,19 +1,45 @@
|
|
|
1
1
|
# @backstage/plugin-catalog-react
|
|
2
2
|
|
|
3
|
-
## 0.0.0-nightly-
|
|
3
|
+
## 0.0.0-nightly-20231123021445
|
|
4
4
|
|
|
5
5
|
### Patch Changes
|
|
6
6
|
|
|
7
|
+
- 8587f067d261: Added pagination support to `EntityListProvider`.
|
|
8
|
+
- 08d9e6719969: Add default icon for kind resource.
|
|
7
9
|
- aaa6fb3bc9b1: Minor updates for TypeScript 5.2.2+ compatibility
|
|
10
|
+
- a5a04739e1ba: Internal refactor of alpha exports due to a change in how extension factories are defined.
|
|
8
11
|
- 4d9e3b39e43c: Register component overrides in the global `OverrideComponentNameToClassKeys` provided by `@backstage/theme`. This will in turn will provide component style override types for `createUnifiedTheme`.
|
|
9
12
|
- eee0ff29464d: Fixed a issue where `CatalogPage` wasn't using the chosen `initiallySelectedFilter` as intended.
|
|
10
13
|
- Updated dependencies
|
|
11
|
-
- @backstage/core-plugin-api@0.0.0-nightly-
|
|
12
|
-
- @backstage/
|
|
13
|
-
- @backstage/
|
|
14
|
-
- @backstage/
|
|
15
|
-
- @backstage/integration-react@0.0.0-nightly-
|
|
16
|
-
- @backstage/plugin-permission-react@0.0.0-nightly-
|
|
14
|
+
- @backstage/core-plugin-api@0.0.0-nightly-20231123021445
|
|
15
|
+
- @backstage/frontend-plugin-api@0.0.0-nightly-20231123021445
|
|
16
|
+
- @backstage/core-components@0.0.0-nightly-20231123021445
|
|
17
|
+
- @backstage/theme@0.0.0-nightly-20231123021445
|
|
18
|
+
- @backstage/integration-react@0.0.0-nightly-20231123021445
|
|
19
|
+
- @backstage/plugin-permission-react@0.0.0-nightly-20231123021445
|
|
20
|
+
- @backstage/catalog-client@1.4.6
|
|
21
|
+
- @backstage/catalog-model@1.4.3
|
|
22
|
+
- @backstage/errors@1.2.3
|
|
23
|
+
- @backstage/types@1.1.1
|
|
24
|
+
- @backstage/version-bridge@1.0.7
|
|
25
|
+
- @backstage/plugin-catalog-common@1.0.18
|
|
26
|
+
- @backstage/plugin-permission-common@0.7.10
|
|
27
|
+
|
|
28
|
+
## 1.9.2-next.0
|
|
29
|
+
|
|
30
|
+
### Patch Changes
|
|
31
|
+
|
|
32
|
+
- 8587f067d2: Added pagination support to `EntityListProvider`.
|
|
33
|
+
- aaa6fb3bc9: Minor updates for TypeScript 5.2.2+ compatibility
|
|
34
|
+
- 4d9e3b39e4: Register component overrides in the global `OverrideComponentNameToClassKeys` provided by `@backstage/theme`. This will in turn will provide component style override types for `createUnifiedTheme`.
|
|
35
|
+
- eee0ff2946: Fixed a issue where `CatalogPage` wasn't using the chosen `initiallySelectedFilter` as intended.
|
|
36
|
+
- Updated dependencies
|
|
37
|
+
- @backstage/core-plugin-api@1.8.1-next.0
|
|
38
|
+
- @backstage/core-components@0.13.9-next.0
|
|
39
|
+
- @backstage/theme@0.5.0-next.0
|
|
40
|
+
- @backstage/frontend-plugin-api@0.3.1-next.0
|
|
41
|
+
- @backstage/integration-react@1.1.22-next.0
|
|
42
|
+
- @backstage/plugin-permission-react@0.4.18-next.0
|
|
17
43
|
- @backstage/catalog-client@1.4.6
|
|
18
44
|
- @backstage/catalog-model@1.4.3
|
|
19
45
|
- @backstage/errors@1.2.3
|
package/alpha/package.json
CHANGED
package/dist/alpha.esm.js
CHANGED
|
@@ -101,12 +101,12 @@ function createEntityCardExtension(options) {
|
|
|
101
101
|
).optional()
|
|
102
102
|
})
|
|
103
103
|
),
|
|
104
|
-
factory({ config, inputs,
|
|
104
|
+
factory({ config, inputs, node }) {
|
|
105
105
|
const ExtensionComponent = lazy(
|
|
106
106
|
() => options.loader({ inputs }).then((element) => ({ default: () => element }))
|
|
107
107
|
);
|
|
108
108
|
return {
|
|
109
|
-
element: /* @__PURE__ */ React.createElement(ExtensionBoundary, {
|
|
109
|
+
element: /* @__PURE__ */ React.createElement(ExtensionBoundary, { node }, /* @__PURE__ */ React.createElement(ExtensionComponent, null)),
|
|
110
110
|
filter: buildFilter(config, options.filter)
|
|
111
111
|
};
|
|
112
112
|
}
|
|
@@ -142,7 +142,7 @@ function createEntityContentExtension(options) {
|
|
|
142
142
|
).optional()
|
|
143
143
|
})
|
|
144
144
|
),
|
|
145
|
-
factory({ config, inputs,
|
|
145
|
+
factory({ config, inputs, node }) {
|
|
146
146
|
const ExtensionComponent = lazy(
|
|
147
147
|
() => options.loader({ inputs }).then((element) => ({ default: () => element }))
|
|
148
148
|
);
|
|
@@ -150,7 +150,7 @@ function createEntityContentExtension(options) {
|
|
|
150
150
|
path: config.path,
|
|
151
151
|
title: config.title,
|
|
152
152
|
routeRef: options.routeRef,
|
|
153
|
-
element: /* @__PURE__ */ React.createElement(ExtensionBoundary, {
|
|
153
|
+
element: /* @__PURE__ */ React.createElement(ExtensionBoundary, { node, routable: true }, /* @__PURE__ */ React.createElement(ExtensionComponent, null)),
|
|
154
154
|
filter: buildFilter(config, options.filter)
|
|
155
155
|
};
|
|
156
156
|
}
|
package/dist/alpha.esm.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"alpha.esm.js","sources":["../src/utils/isOwnerOf.ts","../src/hooks/useEntityPermission.ts","../src/alpha.tsx"],"sourcesContent":["/*\n * Copyright 2020 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 getCompoundEntityRef,\n RELATION_MEMBER_OF,\n RELATION_OWNED_BY,\n stringifyEntityRef,\n} from '@backstage/catalog-model';\nimport { getEntityRelations } from './getEntityRelations';\n\n/**\n * Returns true if the `owner` argument is a direct owner on the `entity` argument.\n *\n * @alpha\n * @remarks\n *\n * Note that this ownership is not the same as using the claims in the auth-resolver, it only will take into account ownership as expressed by direct entity relations.\n * It doesn't know anything about the additional groups that a user might belong to which the claims contain.\n */\nexport function isOwnerOf(owner: Entity, entity: Entity) {\n const possibleOwners = new Set(\n [\n ...getEntityRelations(owner, RELATION_MEMBER_OF, { kind: 'group' }),\n ...(owner ? [getCompoundEntityRef(owner)] : []),\n ].map(stringifyEntityRef),\n );\n\n const owners = getEntityRelations(entity, RELATION_OWNED_BY).map(\n stringifyEntityRef,\n );\n\n for (const ownerItem of owners) {\n if (possibleOwners.has(ownerItem)) {\n return true;\n }\n }\n\n return false;\n}\n","/*\n * Copyright 2022 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 { stringifyEntityRef } from '@backstage/catalog-model';\nimport { ResourcePermission } from '@backstage/plugin-permission-common';\nimport { usePermission } from '@backstage/plugin-permission-react';\nimport { useAsyncEntity } from './useEntity';\n\n/**\n * A thin wrapper around the\n * {@link @backstage/plugin-permission-react#usePermission} hook which uses the\n * current entity in context to make an authorization request for the given\n * {@link @backstage/plugin-catalog-common#CatalogEntityPermission}.\n *\n * Note: this hook blocks the permission request until the entity has loaded in\n * context. If you have the entityRef and need concurrent requests, use the\n * `usePermission` hook directly.\n * @alpha\n */\nexport function useEntityPermission(\n // TODO(joeporpeglia) Replace with `CatalogEntityPermission` when the issue described in\n // https://github.com/backstage/backstage/pull/10128 is fixed.\n permission: ResourcePermission<'catalog-entity'>,\n): {\n loading: boolean;\n allowed: boolean;\n error?: Error;\n} {\n const {\n entity,\n loading: loadingEntity,\n error: entityError,\n } = useAsyncEntity();\n const {\n allowed,\n loading: loadingPermission,\n error: permissionError,\n } = usePermission({\n permission,\n resourceRef: entity ? stringifyEntityRef(entity) : undefined,\n });\n\n if (loadingEntity || loadingPermission) {\n return { loading: true, allowed: false };\n }\n if (entityError) {\n return { loading: false, allowed: false, error: entityError };\n }\n return { loading: false, allowed, error: permissionError };\n}\n","/*\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 React, { lazy } from 'react';\nimport {\n AnyExtensionInputMap,\n ExtensionBoundary,\n ExtensionInputValues,\n RouteRef,\n coreExtensionData,\n createExtension,\n createExtensionDataRef,\n createSchemaFromZod,\n} from '@backstage/frontend-plugin-api';\n// eslint-disable-next-line @backstage/no-relative-monorepo-imports\nimport { Expand } from '../../../packages/frontend-plugin-api/src/types';\nimport { Entity } from '@backstage/catalog-model';\n\nexport { isOwnerOf } from './utils';\nexport { useEntityPermission } from './hooks/useEntityPermission';\n\n/** @alpha */\nexport const entityContentTitleExtensionDataRef =\n createExtensionDataRef<string>('plugin.catalog.entity.content.title');\n\n/** @alpha */\nexport const entityFilterExtensionDataRef = createExtensionDataRef<\n (ctx: { entity: Entity }) => boolean\n>('plugin.catalog.entity.filter');\n\nfunction applyFilter(a?: string, b?: string): boolean {\n if (!a) {\n return true;\n }\n return a.toLocaleLowerCase('en-US') === b?.toLocaleLowerCase('en-US');\n}\n\n// TODO: Only two hardcoded isKind and isType filters are available for now\n// This is just an initial config filter implementation and needs to be revisited\nfunction buildFilter(\n config: { filter?: { isKind?: string; isType?: string }[] },\n filterFunc?: (ctx: { entity: Entity }) => boolean,\n) {\n return (ctx: { entity: Entity }) => {\n const configuredFilterMatch = config.filter?.some(filter => {\n const kindMatch = applyFilter(filter.isKind, ctx.entity.kind);\n const typeMatch = applyFilter(\n filter.isType,\n ctx.entity.spec?.type?.toString(),\n );\n return kindMatch && typeMatch;\n });\n if (configuredFilterMatch) {\n return true;\n }\n if (filterFunc) {\n return filterFunc(ctx);\n }\n return true;\n };\n}\n\n// TODO: Figure out how to merge with provided config schema\n/** @alpha */\nexport function createEntityCardExtension<\n TInputs extends AnyExtensionInputMap,\n>(options: {\n id: string;\n attachTo?: { id: string; input: string };\n disabled?: boolean;\n inputs?: TInputs;\n filter?: (ctx: { entity: Entity }) => boolean;\n loader: (options: {\n inputs: Expand<ExtensionInputValues<TInputs>>;\n }) => Promise<JSX.Element>;\n}) {\n const id = `entity.cards.${options.id}`;\n\n return createExtension({\n id,\n attachTo: options.attachTo ?? {\n id: 'entity.content.overview',\n input: 'cards',\n },\n disabled: options.disabled ?? true,\n output: {\n element: coreExtensionData.reactElement,\n filter: entityFilterExtensionDataRef,\n },\n inputs: options.inputs,\n configSchema: createSchemaFromZod(z =>\n z.object({\n filter: z\n .array(\n z.object({\n isKind: z.string().optional(),\n isType: z.string().optional(),\n }),\n )\n .optional(),\n }),\n ),\n factory({ config, inputs, source }) {\n const ExtensionComponent = lazy(() =>\n options\n .loader({ inputs })\n .then(element => ({ default: () => element })),\n );\n\n return {\n element: (\n <ExtensionBoundary id={id} source={source}>\n <ExtensionComponent />\n </ExtensionBoundary>\n ),\n filter: buildFilter(config, options.filter),\n };\n },\n });\n}\n\n/** @alpha */\nexport function createEntityContentExtension<\n TInputs extends AnyExtensionInputMap,\n>(options: {\n id: string;\n attachTo?: { id: string; input: string };\n disabled?: boolean;\n inputs?: TInputs;\n routeRef?: RouteRef;\n defaultPath: string;\n defaultTitle: string;\n filter?: (ctx: { entity: Entity }) => boolean;\n loader: (options: {\n inputs: Expand<ExtensionInputValues<TInputs>>;\n }) => Promise<JSX.Element>;\n}) {\n const id = `entity.content.${options.id}`;\n\n return createExtension({\n id,\n attachTo: options.attachTo ?? {\n id: 'plugin.catalog.page.entity',\n input: 'contents',\n },\n disabled: options.disabled ?? true,\n output: {\n element: coreExtensionData.reactElement,\n path: coreExtensionData.routePath,\n routeRef: coreExtensionData.routeRef.optional(),\n title: entityContentTitleExtensionDataRef,\n filter: entityFilterExtensionDataRef,\n },\n inputs: options.inputs,\n configSchema: createSchemaFromZod(z =>\n z.object({\n path: z.string().default(options.defaultPath),\n title: z.string().default(options.defaultTitle),\n filter: z\n .array(\n z.object({\n isKind: z.string().optional(),\n isType: z.string().optional(),\n }),\n )\n .optional(),\n }),\n ),\n factory({ config, inputs, source }) {\n const ExtensionComponent = lazy(() =>\n options\n .loader({ inputs })\n .then(element => ({ default: () => element })),\n );\n\n return {\n path: config.path,\n title: config.title,\n routeRef: options.routeRef,\n element: (\n <ExtensionBoundary id={id} source={source} routable>\n <ExtensionComponent />\n </ExtensionBoundary>\n ),\n filter: buildFilter(config, options.filter),\n };\n },\n });\n}\n"],"names":["_a"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"alpha.esm.js","sources":["../src/utils/isOwnerOf.ts","../src/hooks/useEntityPermission.ts","../src/alpha.tsx"],"sourcesContent":["/*\n * Copyright 2020 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 getCompoundEntityRef,\n RELATION_MEMBER_OF,\n RELATION_OWNED_BY,\n stringifyEntityRef,\n} from '@backstage/catalog-model';\nimport { getEntityRelations } from './getEntityRelations';\n\n/**\n * Returns true if the `owner` argument is a direct owner on the `entity` argument.\n *\n * @alpha\n * @remarks\n *\n * Note that this ownership is not the same as using the claims in the auth-resolver, it only will take into account ownership as expressed by direct entity relations.\n * It doesn't know anything about the additional groups that a user might belong to which the claims contain.\n */\nexport function isOwnerOf(owner: Entity, entity: Entity) {\n const possibleOwners = new Set(\n [\n ...getEntityRelations(owner, RELATION_MEMBER_OF, { kind: 'group' }),\n ...(owner ? [getCompoundEntityRef(owner)] : []),\n ].map(stringifyEntityRef),\n );\n\n const owners = getEntityRelations(entity, RELATION_OWNED_BY).map(\n stringifyEntityRef,\n );\n\n for (const ownerItem of owners) {\n if (possibleOwners.has(ownerItem)) {\n return true;\n }\n }\n\n return false;\n}\n","/*\n * Copyright 2022 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 { stringifyEntityRef } from '@backstage/catalog-model';\nimport { ResourcePermission } from '@backstage/plugin-permission-common';\nimport { usePermission } from '@backstage/plugin-permission-react';\nimport { useAsyncEntity } from './useEntity';\n\n/**\n * A thin wrapper around the\n * {@link @backstage/plugin-permission-react#usePermission} hook which uses the\n * current entity in context to make an authorization request for the given\n * {@link @backstage/plugin-catalog-common#CatalogEntityPermission}.\n *\n * Note: this hook blocks the permission request until the entity has loaded in\n * context. If you have the entityRef and need concurrent requests, use the\n * `usePermission` hook directly.\n * @alpha\n */\nexport function useEntityPermission(\n // TODO(joeporpeglia) Replace with `CatalogEntityPermission` when the issue described in\n // https://github.com/backstage/backstage/pull/10128 is fixed.\n permission: ResourcePermission<'catalog-entity'>,\n): {\n loading: boolean;\n allowed: boolean;\n error?: Error;\n} {\n const {\n entity,\n loading: loadingEntity,\n error: entityError,\n } = useAsyncEntity();\n const {\n allowed,\n loading: loadingPermission,\n error: permissionError,\n } = usePermission({\n permission,\n resourceRef: entity ? stringifyEntityRef(entity) : undefined,\n });\n\n if (loadingEntity || loadingPermission) {\n return { loading: true, allowed: false };\n }\n if (entityError) {\n return { loading: false, allowed: false, error: entityError };\n }\n return { loading: false, allowed, error: permissionError };\n}\n","/*\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 React, { lazy } from 'react';\nimport {\n AnyExtensionInputMap,\n ExtensionBoundary,\n ExtensionInputValues,\n RouteRef,\n coreExtensionData,\n createExtension,\n createExtensionDataRef,\n createSchemaFromZod,\n} from '@backstage/frontend-plugin-api';\n// eslint-disable-next-line @backstage/no-relative-monorepo-imports\nimport { Expand } from '../../../packages/frontend-plugin-api/src/types';\nimport { Entity } from '@backstage/catalog-model';\n\nexport { isOwnerOf } from './utils';\nexport { useEntityPermission } from './hooks/useEntityPermission';\n\n/** @alpha */\nexport const entityContentTitleExtensionDataRef =\n createExtensionDataRef<string>('plugin.catalog.entity.content.title');\n\n/** @alpha */\nexport const entityFilterExtensionDataRef = createExtensionDataRef<\n (ctx: { entity: Entity }) => boolean\n>('plugin.catalog.entity.filter');\n\nfunction applyFilter(a?: string, b?: string): boolean {\n if (!a) {\n return true;\n }\n return a.toLocaleLowerCase('en-US') === b?.toLocaleLowerCase('en-US');\n}\n\n// TODO: Only two hardcoded isKind and isType filters are available for now\n// This is just an initial config filter implementation and needs to be revisited\nfunction buildFilter(\n config: { filter?: { isKind?: string; isType?: string }[] },\n filterFunc?: (ctx: { entity: Entity }) => boolean,\n) {\n return (ctx: { entity: Entity }) => {\n const configuredFilterMatch = config.filter?.some(filter => {\n const kindMatch = applyFilter(filter.isKind, ctx.entity.kind);\n const typeMatch = applyFilter(\n filter.isType,\n ctx.entity.spec?.type?.toString(),\n );\n return kindMatch && typeMatch;\n });\n if (configuredFilterMatch) {\n return true;\n }\n if (filterFunc) {\n return filterFunc(ctx);\n }\n return true;\n };\n}\n\n// TODO: Figure out how to merge with provided config schema\n/** @alpha */\nexport function createEntityCardExtension<\n TInputs extends AnyExtensionInputMap,\n>(options: {\n id: string;\n attachTo?: { id: string; input: string };\n disabled?: boolean;\n inputs?: TInputs;\n filter?: (ctx: { entity: Entity }) => boolean;\n loader: (options: {\n inputs: Expand<ExtensionInputValues<TInputs>>;\n }) => Promise<JSX.Element>;\n}) {\n const id = `entity.cards.${options.id}`;\n\n return createExtension({\n id,\n attachTo: options.attachTo ?? {\n id: 'entity.content.overview',\n input: 'cards',\n },\n disabled: options.disabled ?? true,\n output: {\n element: coreExtensionData.reactElement,\n filter: entityFilterExtensionDataRef,\n },\n inputs: options.inputs,\n configSchema: createSchemaFromZod(z =>\n z.object({\n filter: z\n .array(\n z.object({\n isKind: z.string().optional(),\n isType: z.string().optional(),\n }),\n )\n .optional(),\n }),\n ),\n factory({ config, inputs, node }) {\n const ExtensionComponent = lazy(() =>\n options\n .loader({ inputs })\n .then(element => ({ default: () => element })),\n );\n\n return {\n element: (\n <ExtensionBoundary node={node}>\n <ExtensionComponent />\n </ExtensionBoundary>\n ),\n filter: buildFilter(config, options.filter),\n };\n },\n });\n}\n\n/** @alpha */\nexport function createEntityContentExtension<\n TInputs extends AnyExtensionInputMap,\n>(options: {\n id: string;\n attachTo?: { id: string; input: string };\n disabled?: boolean;\n inputs?: TInputs;\n routeRef?: RouteRef;\n defaultPath: string;\n defaultTitle: string;\n filter?: (ctx: { entity: Entity }) => boolean;\n loader: (options: {\n inputs: Expand<ExtensionInputValues<TInputs>>;\n }) => Promise<JSX.Element>;\n}) {\n const id = `entity.content.${options.id}`;\n\n return createExtension({\n id,\n attachTo: options.attachTo ?? {\n id: 'plugin.catalog.page.entity',\n input: 'contents',\n },\n disabled: options.disabled ?? true,\n output: {\n element: coreExtensionData.reactElement,\n path: coreExtensionData.routePath,\n routeRef: coreExtensionData.routeRef.optional(),\n title: entityContentTitleExtensionDataRef,\n filter: entityFilterExtensionDataRef,\n },\n inputs: options.inputs,\n configSchema: createSchemaFromZod(z =>\n z.object({\n path: z.string().default(options.defaultPath),\n title: z.string().default(options.defaultTitle),\n filter: z\n .array(\n z.object({\n isKind: z.string().optional(),\n isType: z.string().optional(),\n }),\n )\n .optional(),\n }),\n ),\n factory({ config, inputs, node }) {\n const ExtensionComponent = lazy(() =>\n options\n .loader({ inputs })\n .then(element => ({ default: () => element })),\n );\n\n return {\n path: config.path,\n title: config.title,\n routeRef: options.routeRef,\n element: (\n <ExtensionBoundary node={node} routable>\n <ExtensionComponent />\n </ExtensionBoundary>\n ),\n filter: buildFilter(config, options.filter),\n };\n },\n });\n}\n"],"names":["_a"],"mappings":"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"}
|
package/dist/index.d.ts
CHANGED
|
@@ -678,17 +678,29 @@ type EntityListContextProps<EntityFilters extends DefaultEntityFilters = Default
|
|
|
678
678
|
queryParameters: Partial<Record<keyof EntityFilters, string | string[]>>;
|
|
679
679
|
loading: boolean;
|
|
680
680
|
error?: Error;
|
|
681
|
+
pageInfo?: {
|
|
682
|
+
next?: () => void;
|
|
683
|
+
prev?: () => void;
|
|
684
|
+
};
|
|
681
685
|
};
|
|
682
686
|
/**
|
|
683
687
|
* Creates new context for entity listing and filtering.
|
|
684
688
|
* @public
|
|
685
689
|
*/
|
|
686
690
|
declare const EntityListContext: React.Context<EntityListContextProps<any> | undefined>;
|
|
691
|
+
/**
|
|
692
|
+
* @public
|
|
693
|
+
*/
|
|
694
|
+
type EntityListProviderProps = PropsWithChildren<{
|
|
695
|
+
pagination?: boolean | {
|
|
696
|
+
limit?: number;
|
|
697
|
+
};
|
|
698
|
+
}>;
|
|
687
699
|
/**
|
|
688
700
|
* Provides entities and filters for a catalog listing.
|
|
689
701
|
* @public
|
|
690
702
|
*/
|
|
691
|
-
declare const EntityListProvider: <EntityFilters extends DefaultEntityFilters>(props:
|
|
703
|
+
declare const EntityListProvider: <EntityFilters extends DefaultEntityFilters>(props: EntityListProviderProps) => React.JSX.Element;
|
|
692
704
|
/**
|
|
693
705
|
* Hook for interacting with the entity list context provided by the {@link EntityListProvider}.
|
|
694
706
|
* @public
|
|
@@ -905,4 +917,4 @@ type EntitySourceLocation = {
|
|
|
905
917
|
/** @public */
|
|
906
918
|
declare function getEntitySourceLocation(entity: Entity, scmIntegrationsApi: typeof scmIntegrationsApiRef.T): EntitySourceLocation | undefined;
|
|
907
919
|
|
|
908
|
-
export { AllowedEntityFilters, AsyncEntityProvider, AsyncEntityProviderProps, BackstageOverrides, CatalogFilterLayout, CatalogReactComponentsNameToClassKey, CatalogReactEntityDisplayNameClassKey, CatalogReactEntityLifecyclePickerClassKey, CatalogReactEntityNamespacePickerClassKey, CatalogReactEntityOwnerPickerClassKey, CatalogReactEntityProcessingStatusPickerClassKey, CatalogReactEntitySearchBarClassKey, CatalogReactEntityTagPickerClassKey, CatalogReactUserListPickerClassKey, DefaultEntityFilters, EntityAutocompletePicker, EntityAutocompletePickerProps, EntityDisplayName, EntityDisplayNameProps, EntityErrorFilter, EntityFilter, EntityKindFilter, EntityKindPicker, EntityKindPickerProps, EntityLifecycleFilter, EntityLifecyclePicker, EntityListContext, EntityListContextProps, EntityListProvider, EntityLoadingStatus, EntityNamespaceFilter, EntityNamespacePicker, EntityOrphanFilter, EntityOwnerFilter, EntityOwnerPicker, EntityOwnerPickerProps, EntityPeekAheadPopover, EntityPeekAheadPopoverProps, EntityPresentationApi, EntityProcessingStatusPicker, EntityProvider, EntityProviderProps, EntityRefLink, EntityRefLinkProps, EntityRefLinks, EntityRefLinksProps, EntityRefPresentation, EntityRefPresentationSnapshot, EntitySearchBar, EntitySourceLocation, EntityTable, EntityTableProps, EntityTagFilter, EntityTagPicker, EntityTagPickerProps, EntityTextFilter, EntityTypeFilter, EntityTypePicker, EntityTypePickerProps, EntityUserFilter, FavoriteEntity, FavoriteEntityProps, InspectEntityDialog, MissingAnnotationEmptyState, MissingAnnotationEmptyStateClassKey, MockEntityListContextProvider, MockStarredEntitiesApi, StarredEntitiesApi, UnregisterEntityDialog, UnregisterEntityDialogProps, UserListFilter, UserListFilterKind, UserListPicker, UserListPickerProps, catalogApiRef, columnFactories, defaultEntityPresentation, entityPresentationApiRef, entityRouteParams, entityRouteRef, getEntityRelations, getEntitySourceLocation, humanizeEntityRef, starredEntitiesApiRef, useAsyncEntity, useEntity, useEntityList, useEntityOwnership, useEntityPresentation, useEntityTypeFilter, useRelatedEntities, useStarredEntities, useStarredEntity };
|
|
920
|
+
export { AllowedEntityFilters, AsyncEntityProvider, AsyncEntityProviderProps, BackstageOverrides, CatalogFilterLayout, CatalogReactComponentsNameToClassKey, CatalogReactEntityDisplayNameClassKey, CatalogReactEntityLifecyclePickerClassKey, CatalogReactEntityNamespacePickerClassKey, CatalogReactEntityOwnerPickerClassKey, CatalogReactEntityProcessingStatusPickerClassKey, CatalogReactEntitySearchBarClassKey, CatalogReactEntityTagPickerClassKey, CatalogReactUserListPickerClassKey, DefaultEntityFilters, EntityAutocompletePicker, EntityAutocompletePickerProps, EntityDisplayName, EntityDisplayNameProps, EntityErrorFilter, EntityFilter, EntityKindFilter, EntityKindPicker, EntityKindPickerProps, EntityLifecycleFilter, EntityLifecyclePicker, EntityListContext, EntityListContextProps, EntityListProvider, EntityListProviderProps, EntityLoadingStatus, EntityNamespaceFilter, EntityNamespacePicker, EntityOrphanFilter, EntityOwnerFilter, EntityOwnerPicker, EntityOwnerPickerProps, EntityPeekAheadPopover, EntityPeekAheadPopoverProps, EntityPresentationApi, EntityProcessingStatusPicker, EntityProvider, EntityProviderProps, EntityRefLink, EntityRefLinkProps, EntityRefLinks, EntityRefLinksProps, EntityRefPresentation, EntityRefPresentationSnapshot, EntitySearchBar, EntitySourceLocation, EntityTable, EntityTableProps, EntityTagFilter, EntityTagPicker, EntityTagPickerProps, EntityTextFilter, EntityTypeFilter, EntityTypePicker, EntityTypePickerProps, EntityUserFilter, FavoriteEntity, FavoriteEntityProps, InspectEntityDialog, MissingAnnotationEmptyState, MissingAnnotationEmptyStateClassKey, MockEntityListContextProvider, MockStarredEntitiesApi, StarredEntitiesApi, UnregisterEntityDialog, UnregisterEntityDialogProps, UserListFilter, UserListFilterKind, UserListPicker, UserListPickerProps, catalogApiRef, columnFactories, defaultEntityPresentation, entityPresentationApiRef, entityRouteParams, entityRouteRef, getEntityRelations, getEntitySourceLocation, humanizeEntityRef, starredEntitiesApiRef, useAsyncEntity, useEntity, useEntityList, useEntityOwnership, useEntityPresentation, useEntityTypeFilter, useRelatedEntities, useStarredEntities, useStarredEntity };
|
package/dist/index.esm.js
CHANGED
|
@@ -10,6 +10,7 @@ import LocationOnIcon from '@material-ui/icons/LocationOn';
|
|
|
10
10
|
import MemoryIcon from '@material-ui/icons/Memory';
|
|
11
11
|
import PeopleIcon from '@material-ui/icons/People';
|
|
12
12
|
import PersonIcon from '@material-ui/icons/Person';
|
|
13
|
+
import WorkIcon from '@material-ui/icons/Work';
|
|
13
14
|
import get from 'lodash/get';
|
|
14
15
|
import React, { useState, useEffect, useMemo, createContext, useCallback, useContext, useRef, memo, forwardRef, useLayoutEffect, Fragment } from 'react';
|
|
15
16
|
import ObservableImpl from 'zen-observable';
|
|
@@ -44,7 +45,6 @@ import Clear from '@material-ui/icons/Clear';
|
|
|
44
45
|
import Search from '@material-ui/icons/Search';
|
|
45
46
|
import Star from '@material-ui/icons/Star';
|
|
46
47
|
import StarBorder from '@material-ui/icons/StarBorder';
|
|
47
|
-
import WorkIcon from '@material-ui/icons/Work';
|
|
48
48
|
import HelpOutlineIcon from '@material-ui/icons/HelpOutline';
|
|
49
49
|
import groupBy from 'lodash/groupBy';
|
|
50
50
|
import DialogContentText$1 from '@material-ui/core/DialogContentText';
|
|
@@ -71,6 +71,7 @@ const DEFAULT_ICONS = {
|
|
|
71
71
|
api: ExtensionIcon,
|
|
72
72
|
component: MemoryIcon,
|
|
73
73
|
system: BusinessIcon,
|
|
74
|
+
resource: WorkIcon,
|
|
74
75
|
domain: ApartmentIcon,
|
|
75
76
|
location: LocationOnIcon,
|
|
76
77
|
user: PersonIcon,
|
|
@@ -561,21 +562,26 @@ const EntityListProvider = (props) => {
|
|
|
561
562
|
{}
|
|
562
563
|
);
|
|
563
564
|
const location = useLocation();
|
|
564
|
-
const
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
}
|
|
571
|
-
|
|
572
|
-
|
|
565
|
+
const enablePagination = props.pagination === true || typeof props.pagination === "object";
|
|
566
|
+
const limit = props.pagination && typeof props.pagination === "object" && typeof props.pagination.limit === "number" ? props.pagination.limit : 20;
|
|
567
|
+
const { queryParameters, cursor: initialCursor } = useMemo(() => {
|
|
568
|
+
var _a;
|
|
569
|
+
const parsed = qs.parse(location.search, {
|
|
570
|
+
ignoreQueryPrefix: true
|
|
571
|
+
});
|
|
572
|
+
return {
|
|
573
|
+
queryParameters: (_a = parsed.filters) != null ? _a : {},
|
|
574
|
+
cursor: typeof parsed.cursor === "string" ? parsed.cursor : void 0
|
|
575
|
+
};
|
|
576
|
+
}, [location]);
|
|
577
|
+
const [cursor, setCursor] = useState(initialCursor);
|
|
573
578
|
const [outputState, setOutputState] = useState(
|
|
574
579
|
() => {
|
|
575
580
|
return {
|
|
576
581
|
appliedFilters: {},
|
|
577
582
|
entities: [],
|
|
578
|
-
backendEntities: []
|
|
583
|
+
backendEntities: [],
|
|
584
|
+
pageInfo: enablePagination ? {} : void 0
|
|
579
585
|
};
|
|
580
586
|
}
|
|
581
587
|
);
|
|
@@ -583,11 +589,6 @@ const EntityListProvider = (props) => {
|
|
|
583
589
|
async () => {
|
|
584
590
|
var _a;
|
|
585
591
|
const compacted = compact(Object.values(requestedFilters));
|
|
586
|
-
const entityFilter = reduceEntityFilters(compacted);
|
|
587
|
-
const backendFilter = reduceBackendCatalogFilters(compacted);
|
|
588
|
-
const previousBackendFilter = reduceBackendCatalogFilters(
|
|
589
|
-
compact(Object.values(outputState.appliedFilters))
|
|
590
|
-
);
|
|
591
592
|
const queryParams = Object.keys(requestedFilters).reduce(
|
|
592
593
|
(params, key) => {
|
|
593
594
|
const filter = requestedFilters[key];
|
|
@@ -598,40 +599,91 @@ const EntityListProvider = (props) => {
|
|
|
598
599
|
},
|
|
599
600
|
{}
|
|
600
601
|
);
|
|
601
|
-
if (
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
602
|
+
if (enablePagination) {
|
|
603
|
+
if (cursor) {
|
|
604
|
+
if (cursor !== outputState.appliedCursor) {
|
|
605
|
+
const entityFilter = reduceEntityFilters(compacted);
|
|
606
|
+
const response = await catalogApi.queryEntities({
|
|
607
|
+
cursor,
|
|
608
|
+
limit
|
|
609
|
+
});
|
|
610
|
+
setOutputState({
|
|
611
|
+
appliedFilters: requestedFilters,
|
|
612
|
+
appliedCursor: cursor,
|
|
613
|
+
backendEntities: response.items,
|
|
614
|
+
entities: response.items.filter(entityFilter),
|
|
615
|
+
pageInfo: response.pageInfo
|
|
616
|
+
});
|
|
617
|
+
}
|
|
618
|
+
} else {
|
|
619
|
+
const entityFilter = reduceEntityFilters(compacted);
|
|
620
|
+
const backendFilter = reduceCatalogFilters(compacted);
|
|
621
|
+
const previousBackendFilter = reduceCatalogFilters(
|
|
622
|
+
compact(Object.values(outputState.appliedFilters))
|
|
623
|
+
);
|
|
624
|
+
if (!isEqual(previousBackendFilter, backendFilter)) {
|
|
625
|
+
const response = await catalogApi.queryEntities({
|
|
626
|
+
filter: backendFilter,
|
|
627
|
+
limit,
|
|
628
|
+
orderFields: [{ field: "metadata.name", order: "asc" }]
|
|
629
|
+
});
|
|
630
|
+
setOutputState({
|
|
631
|
+
appliedFilters: requestedFilters,
|
|
632
|
+
backendEntities: response.items,
|
|
633
|
+
entities: response.items.filter(entityFilter),
|
|
634
|
+
pageInfo: response.pageInfo
|
|
635
|
+
});
|
|
636
|
+
}
|
|
637
|
+
}
|
|
610
638
|
} else {
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
639
|
+
const entityFilter = reduceEntityFilters(compacted);
|
|
640
|
+
const backendFilter = reduceBackendCatalogFilters(compacted);
|
|
641
|
+
const previousBackendFilter = reduceBackendCatalogFilters(
|
|
642
|
+
compact(Object.values(outputState.appliedFilters))
|
|
643
|
+
);
|
|
644
|
+
if (!isEqual(previousBackendFilter, backendFilter)) {
|
|
645
|
+
const response = await catalogApi.getEntities({
|
|
646
|
+
filter: backendFilter
|
|
647
|
+
});
|
|
648
|
+
setOutputState({
|
|
649
|
+
appliedFilters: requestedFilters,
|
|
650
|
+
backendEntities: response.items,
|
|
651
|
+
entities: response.items.filter(entityFilter)
|
|
652
|
+
});
|
|
653
|
+
} else {
|
|
654
|
+
setOutputState({
|
|
655
|
+
appliedFilters: requestedFilters,
|
|
656
|
+
backendEntities: outputState.backendEntities,
|
|
657
|
+
entities: outputState.backendEntities.filter(entityFilter)
|
|
658
|
+
});
|
|
659
|
+
}
|
|
616
660
|
}
|
|
617
661
|
if (isMounted()) {
|
|
618
662
|
const oldParams = qs.parse(location.search, {
|
|
619
663
|
ignoreQueryPrefix: true
|
|
620
664
|
});
|
|
621
665
|
const newParams = qs.stringify(
|
|
622
|
-
{ ...oldParams, filters: queryParams },
|
|
666
|
+
{ ...oldParams, filters: queryParams, cursor },
|
|
623
667
|
{ addQueryPrefix: true, arrayFormat: "repeat" }
|
|
624
668
|
);
|
|
625
669
|
const newUrl = `${window.location.pathname}${newParams}`;
|
|
626
670
|
(_a = window.history) == null ? void 0 : _a.replaceState(null, document.title, newUrl);
|
|
627
671
|
}
|
|
628
672
|
},
|
|
629
|
-
[
|
|
673
|
+
[
|
|
674
|
+
catalogApi,
|
|
675
|
+
queryParameters,
|
|
676
|
+
requestedFilters,
|
|
677
|
+
outputState,
|
|
678
|
+
cursor,
|
|
679
|
+
enablePagination
|
|
680
|
+
],
|
|
630
681
|
{ loading: true }
|
|
631
682
|
);
|
|
632
|
-
useDebounce(refresh, 10, [requestedFilters]);
|
|
683
|
+
useDebounce(refresh, 10, [requestedFilters, cursor]);
|
|
633
684
|
const updateFilters = useCallback(
|
|
634
685
|
(update) => {
|
|
686
|
+
setCursor(void 0);
|
|
635
687
|
setRequestedFilters((prevFilters) => {
|
|
636
688
|
const newFilters = typeof update === "function" ? update(prevFilters) : update;
|
|
637
689
|
return { ...prevFilters, ...newFilters };
|
|
@@ -639,6 +691,18 @@ const EntityListProvider = (props) => {
|
|
|
639
691
|
},
|
|
640
692
|
[]
|
|
641
693
|
);
|
|
694
|
+
const pageInfo = useMemo(() => {
|
|
695
|
+
var _a, _b;
|
|
696
|
+
if (!enablePagination) {
|
|
697
|
+
return void 0;
|
|
698
|
+
}
|
|
699
|
+
const prevCursor = (_a = outputState.pageInfo) == null ? void 0 : _a.prevCursor;
|
|
700
|
+
const nextCursor = (_b = outputState.pageInfo) == null ? void 0 : _b.nextCursor;
|
|
701
|
+
return {
|
|
702
|
+
prev: prevCursor ? () => setCursor(prevCursor) : void 0,
|
|
703
|
+
next: nextCursor ? () => setCursor(nextCursor) : void 0
|
|
704
|
+
};
|
|
705
|
+
}, [enablePagination, outputState.pageInfo]);
|
|
642
706
|
const value = useMemo(
|
|
643
707
|
() => ({
|
|
644
708
|
filters: outputState.appliedFilters,
|
|
@@ -647,9 +711,10 @@ const EntityListProvider = (props) => {
|
|
|
647
711
|
updateFilters,
|
|
648
712
|
queryParameters,
|
|
649
713
|
loading,
|
|
650
|
-
error
|
|
714
|
+
error,
|
|
715
|
+
pageInfo
|
|
651
716
|
}),
|
|
652
|
-
[outputState, updateFilters, queryParameters, loading, error]
|
|
717
|
+
[outputState, updateFilters, queryParameters, loading, error, pageInfo]
|
|
653
718
|
);
|
|
654
719
|
return /* @__PURE__ */ React.createElement(EntityListContext.Provider, { value }, props.children);
|
|
655
720
|
};
|