@backstage/plugin-catalog-react 1.16.0-next.2 → 1.16.1-next.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 CHANGED
@@ -1,5 +1,244 @@
1
1
  # @backstage/plugin-catalog-react
2
2
 
3
+ ## 1.16.1-next.0
4
+
5
+ ### Patch Changes
6
+
7
+ - 186d016: Add `operation` to alpha `defaultEntityContentGroups`.
8
+ - 221ddba: Fix offset pagination to reset when updating filters in `useEntityList`
9
+ - Updated dependencies
10
+ - @backstage/core-compat-api@0.4.1-next.0
11
+ - @backstage/catalog-client@1.9.1
12
+ - @backstage/catalog-model@1.7.3
13
+ - @backstage/core-components@0.17.0
14
+ - @backstage/core-plugin-api@1.10.5
15
+ - @backstage/errors@1.2.7
16
+ - @backstage/frontend-plugin-api@0.10.0
17
+ - @backstage/frontend-test-utils@0.3.0
18
+ - @backstage/integration-react@1.2.5
19
+ - @backstage/types@1.2.1
20
+ - @backstage/version-bridge@1.0.11
21
+ - @backstage/plugin-catalog-common@1.1.3
22
+ - @backstage/plugin-permission-common@0.8.4
23
+ - @backstage/plugin-permission-react@0.4.32
24
+
25
+ ## 1.16.0
26
+
27
+ ### Minor Changes
28
+
29
+ - 7f57365: Add support for a new entity predicate syntax when defining `filter`s related to the blueprints exported via `/alpha` for the new frontend system. For more information, see the [entity filters documentation](https://backstage.io/docs/features/software-catalog/catalog-customization#advanced-customization#entity-filters).
30
+ - ba9649a: Add a new `defaultGroup` parameter to the `EntityContentBlueprint`, here are usage examples:
31
+
32
+ Set a default group while creating the extension:
33
+
34
+ ```diff
35
+ const entityKubernetesContent = EntityContentBlueprint.make({
36
+ name: 'kubernetes',
37
+ params: {
38
+ defaultPath: '/kubernetes',
39
+ defaultTitle: 'Kubernetes',
40
+ + defaultGroup: 'deployment',
41
+ filter: 'kind:component,resource',
42
+ loader: () =>
43
+ import('./KubernetesContentPage').then(m =>
44
+ compatWrapper(<m.KubernetesContentPage />),
45
+ ),
46
+ },
47
+ });
48
+ ```
49
+
50
+ Disassociate an entity content from a default group:
51
+
52
+ ```diff
53
+ # app-config.yaml
54
+ app:
55
+ extensions:
56
+ # Entity page content
57
+ - - entity-content:kubernetes/kubernetes
58
+ + - entity-content:kubernetes/kubernetes:
59
+ + config:
60
+ + group: false
61
+ ```
62
+
63
+ Associate an entity content with a different default or custom group than the one defined in code when the extension was created:
64
+
65
+ ```diff
66
+ # app-config.yaml
67
+ app:
68
+ extensions:
69
+ # Entity page content
70
+ - - entity-content:kubernetes/kubernetes
71
+ + - entity-content:kubernetes/kubernetes:
72
+ + config:
73
+ + group: custom # associating this extension with a custom group id, the group should have previously been created via entity page configuration
74
+
75
+ ```
76
+
77
+ - 247a40b: Introduces a new `EntityHeaderBlueprint` that allows you to override the default entity page header.
78
+
79
+ ```jsx
80
+ import { EntityHeaderBlueprint } from '@backstage/plugin-catalog-react/alpha';
81
+
82
+ EntityHeaderBlueprint.make({
83
+ name: 'my-default-header',
84
+ params: {
85
+ loader: () =>
86
+ import('./MyDefaultHeader').then(m => <m.MyDefaultHeader />),
87
+ },
88
+ });
89
+ ```
90
+
91
+ - a3d93ca: Introduces a new `EntityContentLayoutBlueprint` that creates custom entity content layouts.
92
+
93
+ The layout components receive card elements and can render them as they see fit. Cards is an array of objects with the following properties:
94
+
95
+ - element: `JSx.Element`;
96
+ - type: `"peek" | "info" | "full" | undefined`;
97
+
98
+ ### Usage example
99
+
100
+ Creating a custom overview tab layout:
101
+
102
+ ```tsx
103
+ import {
104
+ EntityContentLayoutProps,
105
+ EntityContentLayoutBlueprint,
106
+ } from '@backstage/plugin-catalog-react/alpha';
107
+ // ...
108
+
109
+ function StickyEntityContentOverviewLayout(props: EntityContentLayoutProps) {
110
+ const { cards } = props;
111
+ const classes = useStyles();
112
+ return (
113
+ <Grid container spacing={3}>
114
+ <Grid
115
+ className={classes.infoArea}
116
+ xs={12}
117
+ md={4}
118
+ item
119
+ >
120
+ <Grid container spacing={3}>
121
+ {cards
122
+ .filter(card => card.type === 'info')
123
+ .map((card, index) => (
124
+ <Grid key={index} xs={12} item>
125
+ {card.element}
126
+ </Grid>
127
+ ))}
128
+ </Grid>
129
+ </Grid>
130
+ <Grid xs={12} md={8} item>
131
+ <Grid container spacing={3}>
132
+ {cards
133
+ .filter(card => card.type === 'peek')
134
+ .map((card, index) => (
135
+ <Grid key={index} className={classes.card} xs={12} md={6} item>
136
+ {card.element}
137
+ </Grid>
138
+ ))}
139
+ {cards
140
+ .filter(card => !card.type || card.type === 'full')
141
+ .map((card, index) => (
142
+ <Grid key={index} className={classes.card} xs={12} md={6} item>
143
+ {card.element}
144
+ </Grid>
145
+ ))}
146
+ </Grid>
147
+ </Grid>
148
+ </Grid>
149
+ );
150
+ }
151
+
152
+ export const customEntityContentOverviewStickyLayoutModule = createFrontendModule({
153
+ pluginId: 'app',
154
+ extensions: [
155
+ EntityContentLayoutBlueprint.make({
156
+ name: 'sticky',
157
+ params: {
158
+ // (optional) defaults the `() => false` filter function
159
+ defaultFilter: 'kind:template'
160
+ loader: async () => StickyEntityContentOverviewLayout,
161
+ },
162
+ }),
163
+ ],
164
+ ```
165
+
166
+ Disabling the custom layout:
167
+
168
+ ```yaml
169
+ # app-config.yaml
170
+ app:
171
+ extensions:
172
+ - entity-content-layout:app/sticky: false
173
+ ```
174
+
175
+ Overriding the custom layout filter:
176
+
177
+ ```yaml
178
+ # app-config.yaml
179
+ app:
180
+ extensions:
181
+ - entity-content-layout:app/sticky:
182
+ config:
183
+ # This layout will be used only with component entities
184
+ filter: 'kind:component'
185
+ ```
186
+
187
+ - d78bb71: Added `hidden` prop to `EntityTagPicker`, `EntityAutocompletePicker` and `UserListPicker`.
188
+ Added `initialFilter` prop to `EntityTagPicker` to set an initial filter for the picker.
189
+ Added `alwaysKeepFilters` prop to `UserListPicker` to prevent filters from resetting when no entities match the initial filters.
190
+ - a3d93ca: Add an optional `type` parameter to `EntityCard` extensions. A card's type determines characteristics such as its expected size and where it will be rendered by the entity content layout.
191
+
192
+ Initially the following three types are supported:
193
+
194
+ - `peek`: small vertical cards that provide information at a glance, for example recent builds, deployments, and service health.
195
+ - `info`: medium size cards with high priority and frequently used information such as common actions, entity metadata, and links.
196
+ - `full`: Large cards that are more feature rich with more information, typically used by plugins that don't quite need the full content view and want to show a card instead.
197
+
198
+ ### Usage examples
199
+
200
+ Defining a default type when creating a card:
201
+
202
+ ```diff
203
+ const myCard = EntityCardBlueprint.make({
204
+ name: 'myCard',
205
+ params: {
206
+ + type: 'info',
207
+ loader: import('./MyCard).then(m => { default: m.MyCard }),
208
+ },
209
+ });
210
+ ```
211
+
212
+ Changing the card type via `app-config.yaml` file:
213
+
214
+ ```diff
215
+ app:
216
+ extensions:
217
+ + - entity-card:myPlugin/myCard:
218
+ + config:
219
+ + type: info
220
+ ```
221
+
222
+ ### Patch Changes
223
+
224
+ - bec1e15: update EntityAutocompletePicker selected options when filter value is changed externally
225
+ - 75a3551: Export CatalogAutocomplete so it can be used externally
226
+ - Updated dependencies
227
+ - @backstage/core-components@0.17.0
228
+ - @backstage/core-plugin-api@1.10.5
229
+ - @backstage/frontend-plugin-api@0.10.0
230
+ - @backstage/frontend-test-utils@0.3.0
231
+ - @backstage/core-compat-api@0.4.0
232
+ - @backstage/integration-react@1.2.5
233
+ - @backstage/plugin-permission-react@0.4.32
234
+ - @backstage/catalog-client@1.9.1
235
+ - @backstage/catalog-model@1.7.3
236
+ - @backstage/errors@1.2.7
237
+ - @backstage/types@1.2.1
238
+ - @backstage/version-bridge@1.0.11
239
+ - @backstage/plugin-catalog-common@1.1.3
240
+ - @backstage/plugin-permission-common@0.8.4
241
+
3
242
  ## 1.16.0-next.2
4
243
 
5
244
  ### Minor Changes
@@ -11,6 +11,7 @@ const defaultEntityContentGroups = {
11
11
  documentation: "Documentation",
12
12
  development: "Development",
13
13
  deployment: "Deployment",
14
+ operation: "Operation",
14
15
  observability: "Observability"
15
16
  };
16
17
  const entityContentGroupDataRef = createExtensionDataRef().with({
@@ -1 +1 @@
1
- {"version":3,"file":"extensionData.esm.js","sources":["../../../src/alpha/blueprints/extensionData.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 { Entity } from '@backstage/catalog-model';\nimport { createExtensionDataRef } from '@backstage/frontend-plugin-api';\n\n/** @internal */\nexport const entityContentTitleDataRef = createExtensionDataRef<string>().with({\n id: 'catalog.entity-content-title',\n});\n\n/** @internal */\nexport const entityFilterFunctionDataRef = createExtensionDataRef<\n (entity: Entity) => boolean\n>().with({ id: 'catalog.entity-filter-function' });\n\n/** @internal */\nexport const entityFilterExpressionDataRef =\n createExtensionDataRef<string>().with({\n id: 'catalog.entity-filter-expression',\n });\n\n/**\n * @alpha\n * Default entity content groups.\n */\nexport const defaultEntityContentGroups = {\n documentation: 'Documentation',\n development: 'Development',\n deployment: 'Deployment',\n observability: 'Observability',\n};\n\n/** @internal */\nexport const entityContentGroupDataRef = createExtensionDataRef<string>().with({\n id: 'catalog.entity-content-group',\n});\n\n/**\n * @internal\n * Available entity card types\n */\nexport const entityCardTypes = [\n 'summary',\n 'info',\n 'content',\n] as const satisfies readonly EntityCardType[];\n\n/** @alpha */\nexport type EntityCardType = 'summary' | 'info' | 'content';\n\n/** @internal */\nexport const entityCardTypeDataRef =\n createExtensionDataRef<EntityCardType>().with({\n id: 'catalog.entity-card-type',\n });\n"],"names":[],"mappings":";;AAoBa,MAAA,yBAAA,GAA4B,sBAA+B,EAAA,CAAE,IAAK,CAAA;AAAA,EAC7E,EAAI,EAAA;AACN,CAAC;AAGM,MAAM,8BAA8B,sBAEzC,EAAA,CAAE,KAAK,EAAE,EAAA,EAAI,kCAAkC;AAGpC,MAAA,6BAAA,GACX,sBAA+B,EAAA,CAAE,IAAK,CAAA;AAAA,EACpC,EAAI,EAAA;AACN,CAAC;AAMI,MAAM,0BAA6B,GAAA;AAAA,EACxC,aAAe,EAAA,eAAA;AAAA,EACf,WAAa,EAAA,aAAA;AAAA,EACb,UAAY,EAAA,YAAA;AAAA,EACZ,aAAe,EAAA;AACjB;AAGa,MAAA,yBAAA,GAA4B,sBAA+B,EAAA,CAAE,IAAK,CAAA;AAAA,EAC7E,EAAI,EAAA;AACN,CAAC;AAMM,MAAM,eAAkB,GAAA;AAAA,EAC7B,SAAA;AAAA,EACA,MAAA;AAAA,EACA;AACF;AAMa,MAAA,qBAAA,GACX,sBAAuC,EAAA,CAAE,IAAK,CAAA;AAAA,EAC5C,EAAI,EAAA;AACN,CAAC;;;;"}
1
+ {"version":3,"file":"extensionData.esm.js","sources":["../../../src/alpha/blueprints/extensionData.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 { Entity } from '@backstage/catalog-model';\nimport { createExtensionDataRef } from '@backstage/frontend-plugin-api';\n\n/** @internal */\nexport const entityContentTitleDataRef = createExtensionDataRef<string>().with({\n id: 'catalog.entity-content-title',\n});\n\n/** @internal */\nexport const entityFilterFunctionDataRef = createExtensionDataRef<\n (entity: Entity) => boolean\n>().with({ id: 'catalog.entity-filter-function' });\n\n/** @internal */\nexport const entityFilterExpressionDataRef =\n createExtensionDataRef<string>().with({\n id: 'catalog.entity-filter-expression',\n });\n\n/**\n * @alpha\n * Default entity content groups.\n */\nexport const defaultEntityContentGroups = {\n documentation: 'Documentation',\n development: 'Development',\n deployment: 'Deployment',\n operation: 'Operation',\n observability: 'Observability',\n};\n\n/** @internal */\nexport const entityContentGroupDataRef = createExtensionDataRef<string>().with({\n id: 'catalog.entity-content-group',\n});\n\n/**\n * @internal\n * Available entity card types\n */\nexport const entityCardTypes = [\n 'summary',\n 'info',\n 'content',\n] as const satisfies readonly EntityCardType[];\n\n/** @alpha */\nexport type EntityCardType = 'summary' | 'info' | 'content';\n\n/** @internal */\nexport const entityCardTypeDataRef =\n createExtensionDataRef<EntityCardType>().with({\n id: 'catalog.entity-card-type',\n });\n"],"names":[],"mappings":";;AAoBa,MAAA,yBAAA,GAA4B,sBAA+B,EAAA,CAAE,IAAK,CAAA;AAAA,EAC7E,EAAI,EAAA;AACN,CAAC;AAGM,MAAM,8BAA8B,sBAEzC,EAAA,CAAE,KAAK,EAAE,EAAA,EAAI,kCAAkC;AAGpC,MAAA,6BAAA,GACX,sBAA+B,EAAA,CAAE,IAAK,CAAA;AAAA,EACpC,EAAI,EAAA;AACN,CAAC;AAMI,MAAM,0BAA6B,GAAA;AAAA,EACxC,aAAe,EAAA,eAAA;AAAA,EACf,WAAa,EAAA,aAAA;AAAA,EACb,UAAY,EAAA,YAAA;AAAA,EACZ,SAAW,EAAA,WAAA;AAAA,EACX,aAAe,EAAA;AACjB;AAGa,MAAA,yBAAA,GAA4B,sBAA+B,EAAA,CAAE,IAAK,CAAA;AAAA,EAC7E,EAAI,EAAA;AACN,CAAC;AAMM,MAAM,eAAkB,GAAA;AAAA,EAC7B,SAAA;AAAA,EACA,MAAA;AAAA,EACA;AACF;AAMa,MAAA,qBAAA,GACX,sBAAuC,EAAA,CAAE,IAAK,CAAA;AAAA,EAC5C,EAAI,EAAA;AACN,CAAC;;;;"}
package/dist/alpha.d.ts CHANGED
@@ -26,6 +26,7 @@ declare const defaultEntityContentGroups: {
26
26
  documentation: string;
27
27
  development: string;
28
28
  deployment: string;
29
+ operation: string;
29
30
  observability: string;
30
31
  };
31
32
  /** @alpha */
@@ -172,13 +172,17 @@ const EntityListProvider = (props) => {
172
172
  useDebounce(refresh, 10, [requestedFilters, cursor, limit, offset]);
173
173
  const updateFilters = useCallback(
174
174
  (update) => {
175
- setCursor(void 0);
175
+ if (paginationMode === "cursor") {
176
+ setCursor(void 0);
177
+ } else if (paginationMode === "offset") {
178
+ setOffset(0);
179
+ }
176
180
  setRequestedFilters((prevFilters) => {
177
181
  const newFilters = typeof update === "function" ? update(prevFilters) : update;
178
182
  return { ...prevFilters, ...newFilters };
179
183
  });
180
184
  },
181
- []
185
+ [paginationMode]
182
186
  );
183
187
  const pageInfo = useMemo(() => {
184
188
  if (paginationMode !== "cursor") {
@@ -1 +1 @@
1
- {"version":3,"file":"useEntityListProvider.esm.js","sources":["../../src/hooks/useEntityListProvider.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 { Entity } from '@backstage/catalog-model';\nimport { compact, isEqual } from 'lodash';\nimport qs from 'qs';\nimport React, {\n createContext,\n PropsWithChildren,\n useCallback,\n useContext,\n useMemo,\n useState,\n} from 'react';\nimport { useLocation } from 'react-router-dom';\nimport useAsyncFn from 'react-use/esm/useAsyncFn';\nimport useDebounce from 'react-use/esm/useDebounce';\nimport useMountedState from 'react-use/esm/useMountedState';\nimport { catalogApiRef } from '../api';\nimport {\n EntityErrorFilter,\n EntityKindFilter,\n EntityLifecycleFilter,\n EntityNamespaceFilter,\n EntityOrphanFilter,\n EntityOwnerFilter,\n EntityTagFilter,\n EntityTextFilter,\n EntityTypeFilter,\n EntityUserFilter,\n UserListFilter,\n} from '../filters';\nimport { EntityFilter, EntityListPagination } from '../types';\nimport {\n reduceBackendCatalogFilters,\n reduceCatalogFilters,\n reduceEntityFilters,\n} from '../utils/filters';\nimport { useApi } from '@backstage/core-plugin-api';\nimport { QueryEntitiesResponse } from '@backstage/catalog-client';\n\n/** @public */\nexport type DefaultEntityFilters = {\n kind?: EntityKindFilter;\n type?: EntityTypeFilter;\n user?: UserListFilter | EntityUserFilter;\n owners?: EntityOwnerFilter;\n lifecycles?: EntityLifecycleFilter;\n tags?: EntityTagFilter;\n text?: EntityTextFilter;\n orphan?: EntityOrphanFilter;\n error?: EntityErrorFilter;\n namespace?: EntityNamespaceFilter;\n};\n\n/** @public */\nexport type PaginationMode = 'cursor' | 'offset' | 'none';\n\n/** @public */\nexport type EntityListContextProps<\n EntityFilters extends DefaultEntityFilters = DefaultEntityFilters,\n> = {\n /**\n * The currently registered filters, adhering to the shape of DefaultEntityFilters or an extension\n * of that default (to add custom filter types).\n */\n filters: EntityFilters;\n\n /**\n * The resolved list of catalog entities, after all filters are applied.\n */\n entities: Entity[];\n\n /**\n * The resolved list of catalog entities, after _only catalog-backend_ filters are applied.\n */\n backendEntities: Entity[];\n\n /**\n * Update one or more of the registered filters. Optional filters can be set to `undefined` to\n * reset the filter.\n */\n updateFilters: (\n filters:\n | Partial<EntityFilters>\n | ((prevFilters: EntityFilters) => Partial<EntityFilters>),\n ) => void;\n\n /**\n * Filter values from query parameters.\n */\n queryParameters: Partial<Record<keyof EntityFilters, string | string[]>>;\n\n loading: boolean;\n error?: Error;\n\n pageInfo?: {\n next?: () => void;\n prev?: () => void;\n };\n totalItems?: number;\n limit: number;\n offset?: number;\n setLimit: (limit: number) => void;\n setOffset?: (offset: number) => void;\n paginationMode: PaginationMode;\n};\n\n/**\n * Creates new context for entity listing and filtering.\n * @public\n */\nexport const EntityListContext = createContext<\n EntityListContextProps<any> | undefined\n>(undefined);\n\ntype OutputState<EntityFilters extends DefaultEntityFilters> = {\n appliedFilters: EntityFilters;\n appliedCursor?: string;\n entities: Entity[];\n backendEntities: Entity[];\n pageInfo?: QueryEntitiesResponse['pageInfo'];\n totalItems?: number;\n offset?: number;\n limit?: number;\n};\n\n/**\n * @public\n */\nexport type EntityListProviderProps = PropsWithChildren<{\n pagination?: EntityListPagination;\n}>;\n\n/**\n * Provides entities and filters for a catalog listing.\n * @public\n */\nexport const EntityListProvider = <EntityFilters extends DefaultEntityFilters>(\n props: EntityListProviderProps,\n) => {\n const isMounted = useMountedState();\n const catalogApi = useApi(catalogApiRef);\n const [requestedFilters, setRequestedFilters] = useState<EntityFilters>(\n {} as EntityFilters,\n );\n\n // We use react-router's useLocation hook so updates from external sources trigger an update to\n // the queryParameters in outputState. Updates from this hook use replaceState below and won't\n // trigger a useLocation change; this would instead come from an external source, such as a manual\n // update of the URL or two catalog sidebar links with different catalog filters.\n const location = useLocation();\n\n const getPaginationMode = (): PaginationMode => {\n if (props.pagination === true) {\n return 'cursor';\n }\n return typeof props.pagination === 'object'\n ? props.pagination.mode ?? 'cursor'\n : 'none';\n };\n\n const paginationMode = getPaginationMode();\n const paginationLimit =\n typeof props.pagination === 'object' ? props.pagination.limit ?? 20 : 20;\n\n const {\n queryParameters,\n cursor: initialCursor,\n offset: initialOffset,\n limit: initialLimit,\n } = useMemo(() => {\n const parsed = qs.parse(location.search, {\n ignoreQueryPrefix: true,\n });\n\n let limit = paginationLimit;\n if (typeof parsed.limit === 'string') {\n const queryLimit = Number.parseInt(parsed.limit, 10);\n if (!isNaN(queryLimit)) {\n limit = queryLimit;\n }\n }\n\n const offset =\n typeof parsed.offset === 'string' && paginationMode === 'offset'\n ? Number.parseInt(parsed.offset, 10)\n : undefined;\n\n return {\n queryParameters: (parsed.filters ?? {}) as Record<\n string,\n string | string[]\n >,\n cursor:\n typeof parsed.cursor === 'string' && paginationMode === 'cursor'\n ? parsed.cursor\n : undefined,\n offset:\n paginationMode === 'offset' && offset && !isNaN(offset)\n ? offset\n : undefined,\n limit,\n };\n }, [paginationMode, location.search, paginationLimit]);\n\n const [cursor, setCursor] = useState(initialCursor);\n const [offset, setOffset] = useState<number | undefined>(initialOffset);\n const [limit, setLimit] = useState(initialLimit);\n\n const [outputState, setOutputState] = useState<OutputState<EntityFilters>>(\n () => {\n return {\n appliedFilters: {} as EntityFilters,\n entities: [],\n backendEntities: [],\n pageInfo: {},\n offset,\n limit,\n };\n },\n );\n\n // The main async filter worker. Note that while it has a lot of dependencies\n // in terms of its implementation, the triggering only happens (debounced)\n // based on the requested filters changing.\n const [{ loading, error }, refresh] = useAsyncFn(\n async () => {\n const compacted = compact(Object.values(requestedFilters));\n\n const queryParams = Object.keys(requestedFilters).reduce(\n (params, key) => {\n const filter = requestedFilters[key as keyof EntityFilters] as\n | EntityFilter\n | undefined;\n if (filter?.toQueryValue) {\n params[key] = filter.toQueryValue();\n }\n return params;\n },\n {} as Record<string, string | string[]>,\n );\n\n if (paginationMode !== 'none') {\n if (cursor) {\n if (cursor !== outputState.appliedCursor) {\n const entityFilter = reduceEntityFilters(compacted);\n const response = await catalogApi.queryEntities({\n cursor,\n limit,\n });\n setOutputState({\n appliedFilters: requestedFilters,\n appliedCursor: cursor,\n backendEntities: response.items,\n entities: response.items.filter(entityFilter),\n pageInfo: response.pageInfo,\n totalItems: response.totalItems,\n });\n }\n } else {\n const entityFilter = reduceEntityFilters(compacted);\n const backendFilter = reduceCatalogFilters(compacted);\n const previousBackendFilter = reduceCatalogFilters(\n compact(Object.values(outputState.appliedFilters)),\n );\n\n if (\n (paginationMode === 'offset' &&\n (outputState.limit !== limit || outputState.offset !== offset)) ||\n !isEqual(previousBackendFilter, backendFilter)\n ) {\n const response = await catalogApi.queryEntities({\n ...backendFilter,\n limit,\n offset,\n orderFields: [{ field: 'metadata.name', order: 'asc' }],\n });\n setOutputState({\n appliedFilters: requestedFilters,\n backendEntities: response.items,\n entities: response.items.filter(entityFilter),\n pageInfo: response.pageInfo,\n totalItems: response.totalItems,\n limit,\n offset,\n });\n }\n }\n } else {\n const entityFilter = reduceEntityFilters(compacted);\n const backendFilter = reduceBackendCatalogFilters(compacted);\n const previousBackendFilter = reduceBackendCatalogFilters(\n compact(Object.values(outputState.appliedFilters)),\n );\n\n // TODO(mtlewis): currently entities will never be requested unless\n // there's at least one filter, we should allow an initial request\n // to happen with no filters.\n if (!isEqual(previousBackendFilter, backendFilter)) {\n // TODO(timbonicus): should limit fields here, but would need filter\n // fields + table columns\n const response = await catalogApi.getEntities({\n filter: backendFilter,\n });\n const entities = response.items.filter(entityFilter);\n setOutputState({\n appliedFilters: requestedFilters,\n backendEntities: response.items,\n entities,\n totalItems: entities.length,\n });\n } else {\n const entities = outputState.backendEntities.filter(entityFilter);\n setOutputState({\n appliedFilters: requestedFilters,\n backendEntities: outputState.backendEntities,\n entities,\n totalItems: entities.length,\n });\n }\n }\n\n if (isMounted()) {\n const oldParams = qs.parse(location.search, {\n ignoreQueryPrefix: true,\n });\n const newParams = qs.stringify(\n { ...oldParams, filters: queryParams, cursor, offset, limit },\n { addQueryPrefix: true, arrayFormat: 'repeat' },\n );\n const newUrl = `${window.location.pathname}${newParams}`;\n // We use direct history manipulation since useSearchParams and\n // useNavigate in react-router-dom cause unnecessary extra rerenders.\n // Also make sure to replace the state rather than pushing, since we\n // don't want there to be back/forward slots for every single filter\n // change.\n window.history?.replaceState(null, document.title, newUrl);\n }\n },\n [\n catalogApi,\n queryParameters,\n requestedFilters,\n outputState,\n cursor,\n paginationMode,\n limit,\n offset,\n ],\n { loading: true },\n );\n\n // Slight debounce on the refresh, since (especially on page load) several\n // filters will be calling this in rapid succession.\n useDebounce(refresh, 10, [requestedFilters, cursor, limit, offset]);\n\n const updateFilters = useCallback(\n (\n update:\n | Partial<EntityFilter>\n | ((prevFilters: EntityFilters) => Partial<EntityFilters>),\n ) => {\n // changing filters will affect pagination, so we need to reset\n // the cursor and start from the first page.\n // TODO(vinzscam): this is currently causing issues at page reload\n // where the state is not kept. Unfortunately we need to rethink\n // the way filters work in order to fix this.\n setCursor(undefined);\n setRequestedFilters(prevFilters => {\n const newFilters =\n typeof update === 'function' ? update(prevFilters) : update;\n return { ...prevFilters, ...newFilters };\n });\n },\n [],\n );\n\n const pageInfo = useMemo(() => {\n if (paginationMode !== 'cursor') {\n return undefined;\n }\n\n const prevCursor = outputState.pageInfo?.prevCursor;\n const nextCursor = outputState.pageInfo?.nextCursor;\n return {\n prev: prevCursor ? () => setCursor(prevCursor) : undefined,\n next: nextCursor ? () => setCursor(nextCursor) : undefined,\n };\n }, [paginationMode, outputState.pageInfo]);\n\n const value = useMemo(\n () => ({\n filters: outputState.appliedFilters,\n entities: outputState.entities,\n backendEntities: outputState.backendEntities,\n updateFilters,\n queryParameters,\n loading,\n error,\n pageInfo,\n totalItems: outputState.totalItems,\n limit,\n offset,\n setLimit,\n setOffset,\n paginationMode,\n }),\n [\n outputState,\n updateFilters,\n queryParameters,\n loading,\n error,\n pageInfo,\n limit,\n offset,\n paginationMode,\n setLimit,\n setOffset,\n ],\n );\n\n return (\n <EntityListContext.Provider value={value}>\n {props.children}\n </EntityListContext.Provider>\n );\n};\n\n/**\n * Hook for interacting with the entity list context provided by the {@link EntityListProvider}.\n * @public\n */\nexport function useEntityList<\n EntityFilters extends DefaultEntityFilters = DefaultEntityFilters,\n>(): EntityListContextProps<EntityFilters> {\n const context = useContext(EntityListContext);\n if (!context)\n throw new Error('useEntityList must be used within EntityListProvider');\n return context;\n}\n"],"names":["limit","offset"],"mappings":"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"}
1
+ {"version":3,"file":"useEntityListProvider.esm.js","sources":["../../src/hooks/useEntityListProvider.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 { Entity } from '@backstage/catalog-model';\nimport { compact, isEqual } from 'lodash';\nimport qs from 'qs';\nimport React, {\n createContext,\n PropsWithChildren,\n useCallback,\n useContext,\n useMemo,\n useState,\n} from 'react';\nimport { useLocation } from 'react-router-dom';\nimport useAsyncFn from 'react-use/esm/useAsyncFn';\nimport useDebounce from 'react-use/esm/useDebounce';\nimport useMountedState from 'react-use/esm/useMountedState';\nimport { catalogApiRef } from '../api';\nimport {\n EntityErrorFilter,\n EntityKindFilter,\n EntityLifecycleFilter,\n EntityNamespaceFilter,\n EntityOrphanFilter,\n EntityOwnerFilter,\n EntityTagFilter,\n EntityTextFilter,\n EntityTypeFilter,\n EntityUserFilter,\n UserListFilter,\n} from '../filters';\nimport { EntityFilter, EntityListPagination } from '../types';\nimport {\n reduceBackendCatalogFilters,\n reduceCatalogFilters,\n reduceEntityFilters,\n} from '../utils/filters';\nimport { useApi } from '@backstage/core-plugin-api';\nimport { QueryEntitiesResponse } from '@backstage/catalog-client';\n\n/** @public */\nexport type DefaultEntityFilters = {\n kind?: EntityKindFilter;\n type?: EntityTypeFilter;\n user?: UserListFilter | EntityUserFilter;\n owners?: EntityOwnerFilter;\n lifecycles?: EntityLifecycleFilter;\n tags?: EntityTagFilter;\n text?: EntityTextFilter;\n orphan?: EntityOrphanFilter;\n error?: EntityErrorFilter;\n namespace?: EntityNamespaceFilter;\n};\n\n/** @public */\nexport type PaginationMode = 'cursor' | 'offset' | 'none';\n\n/** @public */\nexport type EntityListContextProps<\n EntityFilters extends DefaultEntityFilters = DefaultEntityFilters,\n> = {\n /**\n * The currently registered filters, adhering to the shape of DefaultEntityFilters or an extension\n * of that default (to add custom filter types).\n */\n filters: EntityFilters;\n\n /**\n * The resolved list of catalog entities, after all filters are applied.\n */\n entities: Entity[];\n\n /**\n * The resolved list of catalog entities, after _only catalog-backend_ filters are applied.\n */\n backendEntities: Entity[];\n\n /**\n * Update one or more of the registered filters. Optional filters can be set to `undefined` to\n * reset the filter.\n */\n updateFilters: (\n filters:\n | Partial<EntityFilters>\n | ((prevFilters: EntityFilters) => Partial<EntityFilters>),\n ) => void;\n\n /**\n * Filter values from query parameters.\n */\n queryParameters: Partial<Record<keyof EntityFilters, string | string[]>>;\n\n loading: boolean;\n error?: Error;\n\n pageInfo?: {\n next?: () => void;\n prev?: () => void;\n };\n totalItems?: number;\n limit: number;\n offset?: number;\n setLimit: (limit: number) => void;\n setOffset?: (offset: number) => void;\n paginationMode: PaginationMode;\n};\n\n/**\n * Creates new context for entity listing and filtering.\n * @public\n */\nexport const EntityListContext = createContext<\n EntityListContextProps<any> | undefined\n>(undefined);\n\ntype OutputState<EntityFilters extends DefaultEntityFilters> = {\n appliedFilters: EntityFilters;\n appliedCursor?: string;\n entities: Entity[];\n backendEntities: Entity[];\n pageInfo?: QueryEntitiesResponse['pageInfo'];\n totalItems?: number;\n offset?: number;\n limit?: number;\n};\n\n/**\n * @public\n */\nexport type EntityListProviderProps = PropsWithChildren<{\n pagination?: EntityListPagination;\n}>;\n\n/**\n * Provides entities and filters for a catalog listing.\n * @public\n */\nexport const EntityListProvider = <EntityFilters extends DefaultEntityFilters>(\n props: EntityListProviderProps,\n) => {\n const isMounted = useMountedState();\n const catalogApi = useApi(catalogApiRef);\n const [requestedFilters, setRequestedFilters] = useState<EntityFilters>(\n {} as EntityFilters,\n );\n\n // We use react-router's useLocation hook so updates from external sources trigger an update to\n // the queryParameters in outputState. Updates from this hook use replaceState below and won't\n // trigger a useLocation change; this would instead come from an external source, such as a manual\n // update of the URL or two catalog sidebar links with different catalog filters.\n const location = useLocation();\n\n const getPaginationMode = (): PaginationMode => {\n if (props.pagination === true) {\n return 'cursor';\n }\n return typeof props.pagination === 'object'\n ? props.pagination.mode ?? 'cursor'\n : 'none';\n };\n\n const paginationMode = getPaginationMode();\n const paginationLimit =\n typeof props.pagination === 'object' ? props.pagination.limit ?? 20 : 20;\n\n const {\n queryParameters,\n cursor: initialCursor,\n offset: initialOffset,\n limit: initialLimit,\n } = useMemo(() => {\n const parsed = qs.parse(location.search, {\n ignoreQueryPrefix: true,\n });\n\n let limit = paginationLimit;\n if (typeof parsed.limit === 'string') {\n const queryLimit = Number.parseInt(parsed.limit, 10);\n if (!isNaN(queryLimit)) {\n limit = queryLimit;\n }\n }\n\n const offset =\n typeof parsed.offset === 'string' && paginationMode === 'offset'\n ? Number.parseInt(parsed.offset, 10)\n : undefined;\n\n return {\n queryParameters: (parsed.filters ?? {}) as Record<\n string,\n string | string[]\n >,\n cursor:\n typeof parsed.cursor === 'string' && paginationMode === 'cursor'\n ? parsed.cursor\n : undefined,\n offset:\n paginationMode === 'offset' && offset && !isNaN(offset)\n ? offset\n : undefined,\n limit,\n };\n }, [paginationMode, location.search, paginationLimit]);\n\n const [cursor, setCursor] = useState(initialCursor);\n const [offset, setOffset] = useState<number | undefined>(initialOffset);\n const [limit, setLimit] = useState(initialLimit);\n\n const [outputState, setOutputState] = useState<OutputState<EntityFilters>>(\n () => {\n return {\n appliedFilters: {} as EntityFilters,\n entities: [],\n backendEntities: [],\n pageInfo: {},\n offset,\n limit,\n };\n },\n );\n\n // The main async filter worker. Note that while it has a lot of dependencies\n // in terms of its implementation, the triggering only happens (debounced)\n // based on the requested filters changing.\n const [{ loading, error }, refresh] = useAsyncFn(\n async () => {\n const compacted = compact(Object.values(requestedFilters));\n\n const queryParams = Object.keys(requestedFilters).reduce(\n (params, key) => {\n const filter = requestedFilters[key as keyof EntityFilters] as\n | EntityFilter\n | undefined;\n if (filter?.toQueryValue) {\n params[key] = filter.toQueryValue();\n }\n return params;\n },\n {} as Record<string, string | string[]>,\n );\n\n if (paginationMode !== 'none') {\n if (cursor) {\n if (cursor !== outputState.appliedCursor) {\n const entityFilter = reduceEntityFilters(compacted);\n const response = await catalogApi.queryEntities({\n cursor,\n limit,\n });\n setOutputState({\n appliedFilters: requestedFilters,\n appliedCursor: cursor,\n backendEntities: response.items,\n entities: response.items.filter(entityFilter),\n pageInfo: response.pageInfo,\n totalItems: response.totalItems,\n });\n }\n } else {\n const entityFilter = reduceEntityFilters(compacted);\n const backendFilter = reduceCatalogFilters(compacted);\n const previousBackendFilter = reduceCatalogFilters(\n compact(Object.values(outputState.appliedFilters)),\n );\n\n if (\n (paginationMode === 'offset' &&\n (outputState.limit !== limit || outputState.offset !== offset)) ||\n !isEqual(previousBackendFilter, backendFilter)\n ) {\n const response = await catalogApi.queryEntities({\n ...backendFilter,\n limit,\n offset,\n orderFields: [{ field: 'metadata.name', order: 'asc' }],\n });\n setOutputState({\n appliedFilters: requestedFilters,\n backendEntities: response.items,\n entities: response.items.filter(entityFilter),\n pageInfo: response.pageInfo,\n totalItems: response.totalItems,\n limit,\n offset,\n });\n }\n }\n } else {\n const entityFilter = reduceEntityFilters(compacted);\n const backendFilter = reduceBackendCatalogFilters(compacted);\n const previousBackendFilter = reduceBackendCatalogFilters(\n compact(Object.values(outputState.appliedFilters)),\n );\n\n // TODO(mtlewis): currently entities will never be requested unless\n // there's at least one filter, we should allow an initial request\n // to happen with no filters.\n if (!isEqual(previousBackendFilter, backendFilter)) {\n // TODO(timbonicus): should limit fields here, but would need filter\n // fields + table columns\n const response = await catalogApi.getEntities({\n filter: backendFilter,\n });\n const entities = response.items.filter(entityFilter);\n setOutputState({\n appliedFilters: requestedFilters,\n backendEntities: response.items,\n entities,\n totalItems: entities.length,\n });\n } else {\n const entities = outputState.backendEntities.filter(entityFilter);\n setOutputState({\n appliedFilters: requestedFilters,\n backendEntities: outputState.backendEntities,\n entities,\n totalItems: entities.length,\n });\n }\n }\n\n if (isMounted()) {\n const oldParams = qs.parse(location.search, {\n ignoreQueryPrefix: true,\n });\n const newParams = qs.stringify(\n { ...oldParams, filters: queryParams, cursor, offset, limit },\n { addQueryPrefix: true, arrayFormat: 'repeat' },\n );\n const newUrl = `${window.location.pathname}${newParams}`;\n // We use direct history manipulation since useSearchParams and\n // useNavigate in react-router-dom cause unnecessary extra rerenders.\n // Also make sure to replace the state rather than pushing, since we\n // don't want there to be back/forward slots for every single filter\n // change.\n window.history?.replaceState(null, document.title, newUrl);\n }\n },\n [\n catalogApi,\n queryParameters,\n requestedFilters,\n outputState,\n cursor,\n paginationMode,\n limit,\n offset,\n ],\n { loading: true },\n );\n\n // Slight debounce on the refresh, since (especially on page load) several\n // filters will be calling this in rapid succession.\n useDebounce(refresh, 10, [requestedFilters, cursor, limit, offset]);\n\n const updateFilters = useCallback(\n (\n update:\n | Partial<EntityFilter>\n | ((prevFilters: EntityFilters) => Partial<EntityFilters>),\n ) => {\n // changing filters will affect pagination, so we need to reset\n // the cursor and start from the first page.\n // TODO(vinzscam): this is currently causing issues at page reload\n // where the state is not kept. Unfortunately we need to rethink\n // the way filters work in order to fix this.\n if (paginationMode === 'cursor') {\n setCursor(undefined);\n } else if (paginationMode === 'offset') {\n // Same thing with offset\n setOffset(0);\n }\n setRequestedFilters(prevFilters => {\n const newFilters =\n typeof update === 'function' ? update(prevFilters) : update;\n return { ...prevFilters, ...newFilters };\n });\n },\n [paginationMode],\n );\n\n const pageInfo = useMemo(() => {\n if (paginationMode !== 'cursor') {\n return undefined;\n }\n\n const prevCursor = outputState.pageInfo?.prevCursor;\n const nextCursor = outputState.pageInfo?.nextCursor;\n return {\n prev: prevCursor ? () => setCursor(prevCursor) : undefined,\n next: nextCursor ? () => setCursor(nextCursor) : undefined,\n };\n }, [paginationMode, outputState.pageInfo]);\n\n const value = useMemo(\n () => ({\n filters: outputState.appliedFilters,\n entities: outputState.entities,\n backendEntities: outputState.backendEntities,\n updateFilters,\n queryParameters,\n loading,\n error,\n pageInfo,\n totalItems: outputState.totalItems,\n limit,\n offset,\n setLimit,\n setOffset,\n paginationMode,\n }),\n [\n outputState,\n updateFilters,\n queryParameters,\n loading,\n error,\n pageInfo,\n limit,\n offset,\n paginationMode,\n setLimit,\n setOffset,\n ],\n );\n\n return (\n <EntityListContext.Provider value={value}>\n {props.children}\n </EntityListContext.Provider>\n );\n};\n\n/**\n * Hook for interacting with the entity list context provided by the {@link EntityListProvider}.\n * @public\n */\nexport function useEntityList<\n EntityFilters extends DefaultEntityFilters = DefaultEntityFilters,\n>(): EntityListContextProps<EntityFilters> {\n const context = useContext(EntityListContext);\n if (!context)\n throw new Error('useEntityList must be used within EntityListProvider');\n return context;\n}\n"],"names":["limit","offset"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@backstage/plugin-catalog-react",
3
- "version": "1.16.0-next.2",
3
+ "version": "1.16.1-next.0",
4
4
  "description": "A frontend library that helps other Backstage plugins interact with the catalog",
5
5
  "backstage": {
6
6
  "role": "web-library",
@@ -75,16 +75,16 @@
75
75
  "dependencies": {
76
76
  "@backstage/catalog-client": "1.9.1",
77
77
  "@backstage/catalog-model": "1.7.3",
78
- "@backstage/core-compat-api": "0.4.0-next.2",
79
- "@backstage/core-components": "0.16.5-next.1",
80
- "@backstage/core-plugin-api": "1.10.4",
78
+ "@backstage/core-compat-api": "0.4.1-next.0",
79
+ "@backstage/core-components": "0.17.0",
80
+ "@backstage/core-plugin-api": "1.10.5",
81
81
  "@backstage/errors": "1.2.7",
82
- "@backstage/frontend-plugin-api": "0.10.0-next.2",
83
- "@backstage/frontend-test-utils": "0.3.0-next.2",
84
- "@backstage/integration-react": "1.2.5-next.0",
82
+ "@backstage/frontend-plugin-api": "0.10.0",
83
+ "@backstage/frontend-test-utils": "0.3.0",
84
+ "@backstage/integration-react": "1.2.5",
85
85
  "@backstage/plugin-catalog-common": "1.1.3",
86
86
  "@backstage/plugin-permission-common": "0.8.4",
87
- "@backstage/plugin-permission-react": "0.4.31",
87
+ "@backstage/plugin-permission-react": "0.4.32",
88
88
  "@backstage/types": "1.2.1",
89
89
  "@backstage/version-bridge": "1.0.11",
90
90
  "@material-ui/core": "^4.12.2",
@@ -100,11 +100,11 @@
100
100
  "zen-observable": "^0.10.0"
101
101
  },
102
102
  "devDependencies": {
103
- "@backstage/cli": "0.31.0-next.1",
104
- "@backstage/core-app-api": "1.16.0-next.0",
103
+ "@backstage/cli": "0.32.0-next.0",
104
+ "@backstage/core-app-api": "1.16.0",
105
105
  "@backstage/plugin-catalog-common": "1.1.3",
106
- "@backstage/plugin-scaffolder-common": "1.5.10-next.0",
107
- "@backstage/test-utils": "1.7.6-next.0",
106
+ "@backstage/plugin-scaffolder-common": "1.5.10",
107
+ "@backstage/test-utils": "1.7.6",
108
108
  "@testing-library/dom": "^10.0.0",
109
109
  "@testing-library/jest-dom": "^6.0.0",
110
110
  "@testing-library/react": "^16.0.0",