@backstage/plugin-catalog-react 1.14.2 → 1.14.3-next.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,19 +1,41 @@
1
1
  # @backstage/plugin-catalog-react
2
2
 
3
- ## 1.14.2
3
+ ## 1.14.3-next.1
4
4
 
5
5
  ### Patch Changes
6
6
 
7
+ - d97a2cd: Fixed an issue causing the `EntityOwnerPicker` to reset scrolling when more elements are loaded.
7
8
  - Updated dependencies
8
- - @backstage/frontend-plugin-api@0.9.2
9
- - @backstage/catalog-client@1.8.0
9
+ - @backstage/catalog-client@1.9.0-next.1
10
+ - @backstage/core-components@0.16.2-next.1
10
11
  - @backstage/catalog-model@1.7.1
11
- - @backstage/core-compat-api@0.3.3
12
- - @backstage/core-components@0.16.1
12
+ - @backstage/core-compat-api@0.3.4-next.1
13
13
  - @backstage/core-plugin-api@1.10.1
14
14
  - @backstage/errors@1.2.5
15
- - @backstage/frontend-test-utils@0.2.3
16
- - @backstage/integration-react@1.2.1
15
+ - @backstage/frontend-plugin-api@0.9.3-next.1
16
+ - @backstage/frontend-test-utils@0.2.4-next.1
17
+ - @backstage/integration-react@1.2.2-next.0
18
+ - @backstage/types@1.2.0
19
+ - @backstage/version-bridge@1.0.10
20
+ - @backstage/plugin-catalog-common@1.1.1
21
+ - @backstage/plugin-permission-common@0.8.2
22
+ - @backstage/plugin-permission-react@0.4.28
23
+
24
+ ## 1.14.3-next.0
25
+
26
+ ### Patch Changes
27
+
28
+ - f18c67d: Fix catalog filtering to allow searching entities by display name
29
+ - Updated dependencies
30
+ - @backstage/frontend-plugin-api@0.9.3-next.0
31
+ - @backstage/catalog-client@1.8.1-next.0
32
+ - @backstage/catalog-model@1.7.1
33
+ - @backstage/core-compat-api@0.3.4-next.0
34
+ - @backstage/core-components@0.16.2-next.0
35
+ - @backstage/core-plugin-api@1.10.1
36
+ - @backstage/errors@1.2.5
37
+ - @backstage/frontend-test-utils@0.2.4-next.0
38
+ - @backstage/integration-react@1.2.2-next.0
17
39
  - @backstage/types@1.2.0
18
40
  - @backstage/version-bridge@1.0.10
19
41
  - @backstage/plugin-catalog-common@1.1.1
@@ -121,7 +121,7 @@ const EntityOwnerPicker = (props) => {
121
121
  return /* @__PURE__ */ React.createElement(Box, { className: classes.root, pb: 1, pt: 1 }, /* @__PURE__ */ React.createElement(Typography, { className: classes.label, variant: "button", component: "label" }, t("entityOwnerPicker.title"), /* @__PURE__ */ React.createElement(
122
122
  Autocomplete,
123
123
  {
124
- PopperComponent: (popperProps) => /* @__PURE__ */ React.createElement("div", { ...popperProps }, popperProps.children),
124
+ PopperComponent: Popper,
125
125
  multiple: true,
126
126
  disableCloseOnSelect: true,
127
127
  loading,
@@ -184,6 +184,9 @@ const EntityOwnerPicker = (props) => {
184
184
  }
185
185
  )));
186
186
  };
187
+ function Popper({ children }) {
188
+ return /* @__PURE__ */ React.createElement("div", null, children);
189
+ }
187
190
 
188
191
  export { EntityOwnerPicker };
189
192
  //# sourceMappingURL=EntityOwnerPicker.esm.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"EntityOwnerPicker.esm.js","sources":["../../../src/components/EntityOwnerPicker/EntityOwnerPicker.tsx"],"sourcesContent":["/*\n * Copyright 2021 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport {\n Entity,\n parseEntityRef,\n stringifyEntityRef,\n} from '@backstage/catalog-model';\nimport Box from '@material-ui/core/Box';\nimport Checkbox from '@material-ui/core/Checkbox';\nimport FormControlLabel from '@material-ui/core/FormControlLabel';\nimport TextField from '@material-ui/core/TextField';\nimport Typography from '@material-ui/core/Typography';\nimport Tooltip from '@material-ui/core/Tooltip';\nimport { createStyles, makeStyles, Theme } from '@material-ui/core/styles';\nimport CheckBoxIcon from '@material-ui/icons/CheckBox';\nimport CheckBoxOutlineBlankIcon from '@material-ui/icons/CheckBoxOutlineBlank';\nimport ExpandMoreIcon from '@material-ui/icons/ExpandMore';\nimport Autocomplete from '@material-ui/lab/Autocomplete';\nimport React, { useEffect, useMemo, useState, ReactNode } from 'react';\nimport { useEntityList } from '../../hooks/useEntityListProvider';\nimport { EntityOwnerFilter } from '../../filters';\nimport { useDebouncedEffect } from '@react-hookz/web';\nimport PersonIcon from '@material-ui/icons/Person';\nimport GroupIcon from '@material-ui/icons/Group';\nimport { humanizeEntity, humanizeEntityRef } from '../EntityRefLink/humanize';\nimport { useFetchEntities } from './useFetchEntities';\nimport { withStyles } from '@material-ui/core/styles';\nimport { useEntityPresentation } from '../../apis';\nimport { catalogReactTranslationRef } from '../../translation';\nimport { useTranslationRef } from '@backstage/core-plugin-api/alpha';\n\n/** @public */\nexport type CatalogReactEntityOwnerPickerClassKey = 'input';\n\nconst useStyles = makeStyles(\n (theme: Theme) =>\n createStyles({\n root: {},\n label: {\n textTransform: 'none',\n fontWeight: 'bold',\n },\n input: {\n backgroundColor: theme.palette.background.paper,\n },\n fullWidth: { width: '100%' },\n boxLabel: {\n width: '100%',\n textOverflow: 'ellipsis',\n overflow: 'hidden',\n },\n }),\n { name: 'CatalogReactEntityOwnerPicker' },\n);\n\n/** @public */\nexport type FixedWidthFormControlLabelClassKey = 'label' | 'root';\n\nconst FixedWidthFormControlLabel = withStyles(\n _theme => ({\n label: {\n width: '100%',\n },\n root: {\n width: '90%',\n },\n }),\n { name: 'FixedWidthFormControlLabel' },\n)(FormControlLabel);\n\nconst icon = <CheckBoxOutlineBlankIcon fontSize=\"small\" />;\nconst checkedIcon = <CheckBoxIcon fontSize=\"small\" />;\n\n/**\n * @public\n */\nexport type EntityOwnerPickerProps = {\n mode?: 'owners-only' | 'all';\n};\n\nfunction RenderOptionLabel(props: { entity: Entity; isSelected: boolean }) {\n const classes = useStyles();\n const isGroup = props.entity.kind.toLocaleLowerCase('en-US') === 'group';\n const { primaryTitle: title } = useEntityPresentation(props.entity);\n return (\n <Box className={classes.fullWidth}>\n <FixedWidthFormControlLabel\n className={classes.fullWidth}\n control={\n <Checkbox\n icon={icon}\n checkedIcon={checkedIcon}\n checked={props.isSelected}\n />\n }\n onClick={event => event.preventDefault()}\n label={\n <Tooltip title={title}>\n <Box display=\"flex\" alignItems=\"center\">\n {isGroup ? (\n <GroupIcon fontSize=\"small\" />\n ) : (\n <PersonIcon fontSize=\"small\" />\n )}\n &nbsp;\n <Box className={classes.boxLabel}>\n <Typography noWrap>{title}</Typography>\n </Box>\n </Box>\n </Tooltip>\n }\n />\n </Box>\n );\n}\n\n/** @public */\nexport const EntityOwnerPicker = (props?: EntityOwnerPickerProps) => {\n const classes = useStyles();\n const { mode = 'owners-only' } = props || {};\n const {\n updateFilters,\n filters,\n queryParameters: { owners: ownersParameter },\n } = useEntityList();\n\n const [text, setText] = useState('');\n const { t } = useTranslationRef(catalogReactTranslationRef);\n\n const queryParamOwners = useMemo(\n () => [ownersParameter].flat().filter(Boolean) as string[],\n [ownersParameter],\n );\n\n const [selectedOwners, setSelectedOwners] = useState(\n queryParamOwners.length ? queryParamOwners : filters.owners?.values ?? [],\n );\n\n const [{ value, loading }, handleFetch, cache] = useFetchEntities({\n mode,\n initialSelectedOwnersRefs: selectedOwners,\n });\n useDebouncedEffect(() => handleFetch({ text }), [text, handleFetch], 250);\n\n const availableOwners = value?.items || [];\n\n // Set selected owners on query parameter updates; this happens at initial page load and from\n // external updates to the page location.\n useEffect(() => {\n if (queryParamOwners.length) {\n const filter = new EntityOwnerFilter(queryParamOwners);\n setSelectedOwners(filter.values);\n }\n }, [queryParamOwners]);\n\n useEffect(() => {\n updateFilters({\n owners: selectedOwners.length\n ? new EntityOwnerFilter(selectedOwners)\n : undefined,\n });\n }, [selectedOwners, updateFilters]);\n\n if (\n ['user', 'group'].includes(\n filters.kind?.value.toLocaleLowerCase('en-US') || '',\n )\n ) {\n return null;\n }\n\n return (\n <Box className={classes.root} pb={1} pt={1}>\n <Typography className={classes.label} variant=\"button\" component=\"label\">\n {t('entityOwnerPicker.title')}\n <Autocomplete\n PopperComponent={popperProps => (\n <div {...popperProps}>{popperProps.children as ReactNode}</div>\n )}\n multiple\n disableCloseOnSelect\n loading={loading}\n options={availableOwners}\n value={selectedOwners as unknown as Entity[]}\n getOptionSelected={(o, v) => {\n if (typeof v === 'string') {\n return stringifyEntityRef(o) === v;\n }\n return o === v;\n }}\n getOptionLabel={o => {\n const entity =\n typeof o === 'string'\n ? cache.getEntity(o) ||\n parseEntityRef(o, {\n defaultKind: 'group',\n defaultNamespace: 'default',\n })\n : o;\n return humanizeEntity(entity, humanizeEntityRef(entity));\n }}\n onChange={(_: object, owners) => {\n setText('');\n setSelectedOwners(\n owners.map(e => {\n const entityRef =\n typeof e === 'string' ? e : stringifyEntityRef(e);\n\n if (typeof e !== 'string') {\n cache.setEntity(e);\n }\n return entityRef;\n }),\n );\n }}\n filterOptions={x => x}\n renderOption={(entity, { selected }) => {\n return <RenderOptionLabel entity={entity} isSelected={selected} />;\n }}\n size=\"small\"\n popupIcon={<ExpandMoreIcon data-testid=\"owner-picker-expand\" />}\n renderInput={params => (\n <TextField\n {...params}\n className={classes.input}\n onChange={e => {\n setText(e.currentTarget.value);\n }}\n variant=\"outlined\"\n />\n )}\n ListboxProps={{\n onScroll: (e: React.MouseEvent) => {\n const element = e.currentTarget;\n const hasReachedEnd =\n Math.abs(\n element.scrollHeight -\n element.clientHeight -\n element.scrollTop,\n ) < 1;\n\n if (hasReachedEnd && value?.cursor) {\n handleFetch({ items: value.items, cursor: value.cursor });\n }\n },\n 'data-testid': 'owner-picker-listbox',\n }}\n />\n </Typography>\n </Box>\n );\n};\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"EntityOwnerPicker.esm.js","sources":["../../../src/components/EntityOwnerPicker/EntityOwnerPicker.tsx"],"sourcesContent":["/*\n * Copyright 2021 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport {\n Entity,\n parseEntityRef,\n stringifyEntityRef,\n} from '@backstage/catalog-model';\nimport Box from '@material-ui/core/Box';\nimport Checkbox from '@material-ui/core/Checkbox';\nimport FormControlLabel from '@material-ui/core/FormControlLabel';\nimport TextField from '@material-ui/core/TextField';\nimport Typography from '@material-ui/core/Typography';\nimport Tooltip from '@material-ui/core/Tooltip';\nimport { createStyles, makeStyles, Theme } from '@material-ui/core/styles';\nimport CheckBoxIcon from '@material-ui/icons/CheckBox';\nimport CheckBoxOutlineBlankIcon from '@material-ui/icons/CheckBoxOutlineBlank';\nimport ExpandMoreIcon from '@material-ui/icons/ExpandMore';\nimport Autocomplete from '@material-ui/lab/Autocomplete';\nimport React, { useEffect, useMemo, useState, ReactNode } from 'react';\nimport { useEntityList } from '../../hooks/useEntityListProvider';\nimport { EntityOwnerFilter } from '../../filters';\nimport { useDebouncedEffect } from '@react-hookz/web';\nimport PersonIcon from '@material-ui/icons/Person';\nimport GroupIcon from '@material-ui/icons/Group';\nimport { humanizeEntity, humanizeEntityRef } from '../EntityRefLink/humanize';\nimport { useFetchEntities } from './useFetchEntities';\nimport { withStyles } from '@material-ui/core/styles';\nimport { useEntityPresentation } from '../../apis';\nimport { catalogReactTranslationRef } from '../../translation';\nimport { useTranslationRef } from '@backstage/core-plugin-api/alpha';\nimport { PopperProps } from '@material-ui/core/Popper';\n\n/** @public */\nexport type CatalogReactEntityOwnerPickerClassKey = 'input';\n\nconst useStyles = makeStyles(\n (theme: Theme) =>\n createStyles({\n root: {},\n label: {\n textTransform: 'none',\n fontWeight: 'bold',\n },\n input: {\n backgroundColor: theme.palette.background.paper,\n },\n fullWidth: { width: '100%' },\n boxLabel: {\n width: '100%',\n textOverflow: 'ellipsis',\n overflow: 'hidden',\n },\n }),\n { name: 'CatalogReactEntityOwnerPicker' },\n);\n\n/** @public */\nexport type FixedWidthFormControlLabelClassKey = 'label' | 'root';\n\nconst FixedWidthFormControlLabel = withStyles(\n _theme => ({\n label: {\n width: '100%',\n },\n root: {\n width: '90%',\n },\n }),\n { name: 'FixedWidthFormControlLabel' },\n)(FormControlLabel);\n\nconst icon = <CheckBoxOutlineBlankIcon fontSize=\"small\" />;\nconst checkedIcon = <CheckBoxIcon fontSize=\"small\" />;\n\n/**\n * @public\n */\nexport type EntityOwnerPickerProps = {\n mode?: 'owners-only' | 'all';\n};\n\nfunction RenderOptionLabel(props: { entity: Entity; isSelected: boolean }) {\n const classes = useStyles();\n const isGroup = props.entity.kind.toLocaleLowerCase('en-US') === 'group';\n const { primaryTitle: title } = useEntityPresentation(props.entity);\n return (\n <Box className={classes.fullWidth}>\n <FixedWidthFormControlLabel\n className={classes.fullWidth}\n control={\n <Checkbox\n icon={icon}\n checkedIcon={checkedIcon}\n checked={props.isSelected}\n />\n }\n onClick={event => event.preventDefault()}\n label={\n <Tooltip title={title}>\n <Box display=\"flex\" alignItems=\"center\">\n {isGroup ? (\n <GroupIcon fontSize=\"small\" />\n ) : (\n <PersonIcon fontSize=\"small\" />\n )}\n &nbsp;\n <Box className={classes.boxLabel}>\n <Typography noWrap>{title}</Typography>\n </Box>\n </Box>\n </Tooltip>\n }\n />\n </Box>\n );\n}\n\n/** @public */\nexport const EntityOwnerPicker = (props?: EntityOwnerPickerProps) => {\n const classes = useStyles();\n const { mode = 'owners-only' } = props || {};\n const {\n updateFilters,\n filters,\n queryParameters: { owners: ownersParameter },\n } = useEntityList();\n\n const [text, setText] = useState('');\n const { t } = useTranslationRef(catalogReactTranslationRef);\n\n const queryParamOwners = useMemo(\n () => [ownersParameter].flat().filter(Boolean) as string[],\n [ownersParameter],\n );\n\n const [selectedOwners, setSelectedOwners] = useState(\n queryParamOwners.length ? queryParamOwners : filters.owners?.values ?? [],\n );\n\n const [{ value, loading }, handleFetch, cache] = useFetchEntities({\n mode,\n initialSelectedOwnersRefs: selectedOwners,\n });\n useDebouncedEffect(() => handleFetch({ text }), [text, handleFetch], 250);\n\n const availableOwners = value?.items || [];\n\n // Set selected owners on query parameter updates; this happens at initial page load and from\n // external updates to the page location.\n useEffect(() => {\n if (queryParamOwners.length) {\n const filter = new EntityOwnerFilter(queryParamOwners);\n setSelectedOwners(filter.values);\n }\n }, [queryParamOwners]);\n\n useEffect(() => {\n updateFilters({\n owners: selectedOwners.length\n ? new EntityOwnerFilter(selectedOwners)\n : undefined,\n });\n }, [selectedOwners, updateFilters]);\n\n if (\n ['user', 'group'].includes(\n filters.kind?.value.toLocaleLowerCase('en-US') || '',\n )\n ) {\n return null;\n }\n\n return (\n <Box className={classes.root} pb={1} pt={1}>\n <Typography className={classes.label} variant=\"button\" component=\"label\">\n {t('entityOwnerPicker.title')}\n <Autocomplete\n PopperComponent={Popper}\n multiple\n disableCloseOnSelect\n loading={loading}\n options={availableOwners}\n value={selectedOwners as unknown as Entity[]}\n getOptionSelected={(o, v) => {\n if (typeof v === 'string') {\n return stringifyEntityRef(o) === v;\n }\n return o === v;\n }}\n getOptionLabel={o => {\n const entity =\n typeof o === 'string'\n ? cache.getEntity(o) ||\n parseEntityRef(o, {\n defaultKind: 'group',\n defaultNamespace: 'default',\n })\n : o;\n return humanizeEntity(entity, humanizeEntityRef(entity));\n }}\n onChange={(_: object, owners) => {\n setText('');\n setSelectedOwners(\n owners.map(e => {\n const entityRef =\n typeof e === 'string' ? e : stringifyEntityRef(e);\n\n if (typeof e !== 'string') {\n cache.setEntity(e);\n }\n return entityRef;\n }),\n );\n }}\n filterOptions={x => x}\n renderOption={(entity, { selected }) => {\n return <RenderOptionLabel entity={entity} isSelected={selected} />;\n }}\n size=\"small\"\n popupIcon={<ExpandMoreIcon data-testid=\"owner-picker-expand\" />}\n renderInput={params => (\n <TextField\n {...params}\n className={classes.input}\n onChange={e => {\n setText(e.currentTarget.value);\n }}\n variant=\"outlined\"\n />\n )}\n ListboxProps={{\n onScroll: (e: React.MouseEvent) => {\n const element = e.currentTarget;\n const hasReachedEnd =\n Math.abs(\n element.scrollHeight -\n element.clientHeight -\n element.scrollTop,\n ) < 1;\n\n if (hasReachedEnd && value?.cursor) {\n handleFetch({ items: value.items, cursor: value.cursor });\n }\n },\n 'data-testid': 'owner-picker-listbox',\n }}\n />\n </Typography>\n </Box>\n );\n};\n\nfunction Popper({ children }: PopperProps) {\n return <div>{children as ReactNode}</div>;\n}\n"],"names":[],"mappings":"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"}
@@ -50,7 +50,8 @@ class EntityTextFilter {
50
50
  const exactMatch = this.toUpperArray([entity.metadata.tags]);
51
51
  const partialMatch = this.toUpperArray([
52
52
  entity.metadata.name,
53
- entity.metadata.title
53
+ entity.metadata.title,
54
+ entity.spec?.profile?.displayName
54
55
  ]);
55
56
  for (const word of words) {
56
57
  if (exactMatch.every((m) => m !== word) && partialMatch.every((m) => !m.includes(word))) {
@@ -1 +1 @@
1
- {"version":3,"file":"filters.esm.js","sources":["../src/filters.ts"],"sourcesContent":["/*\n * Copyright 2021 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport {\n Entity,\n parseEntityRef,\n RELATION_OWNED_BY,\n stringifyEntityRef,\n} from '@backstage/catalog-model';\nimport { AlphaEntity } from '@backstage/catalog-model/alpha';\nimport { EntityFilter, UserListFilterKind } from './types';\nimport { getEntityRelations } from './utils';\n\n/**\n * Filter entities based on Kind.\n * @public\n */\nexport class EntityKindFilter implements EntityFilter {\n constructor(readonly value: string) {}\n\n getCatalogFilters(): Record<string, string | string[]> {\n return { kind: this.value };\n }\n\n toQueryValue(): string {\n return this.value;\n }\n}\n\n/**\n * Filters entities based on type\n * @public\n */\nexport class EntityTypeFilter implements EntityFilter {\n constructor(readonly value: string | string[]) {}\n\n // Simplify `string | string[]` for consumers, always returns an array\n getTypes(): string[] {\n return Array.isArray(this.value) ? this.value : [this.value];\n }\n\n getCatalogFilters(): Record<string, string | string[]> {\n return { 'spec.type': this.getTypes() };\n }\n\n toQueryValue(): string[] {\n return this.getTypes();\n }\n}\n\n/**\n * Filters entities based on tag.\n * @public\n */\nexport class EntityTagFilter implements EntityFilter {\n constructor(readonly values: string[]) {}\n\n filterEntity(entity: Entity): boolean {\n return this.values.every(v => (entity.metadata.tags ?? []).includes(v));\n }\n\n getCatalogFilters(): Record<string, string | string[]> {\n return { 'metadata.tags': this.values };\n }\n\n toQueryValue(): string[] {\n return this.values;\n }\n}\n\n/**\n * Filters entities where the text matches spec, title or tags.\n * @public\n */\nexport class EntityTextFilter implements EntityFilter {\n constructor(readonly value: string) {}\n\n filterEntity(entity: Entity): boolean {\n const words = this.toUpperArray(this.value.split(/\\s/));\n const exactMatch = this.toUpperArray([entity.metadata.tags]);\n const partialMatch = this.toUpperArray([\n entity.metadata.name,\n entity.metadata.title,\n ]);\n\n for (const word of words) {\n if (\n exactMatch.every(m => m !== word) &&\n partialMatch.every(m => !m.includes(word))\n ) {\n return false;\n }\n }\n\n return true;\n }\n\n getFullTextFilters() {\n return {\n term: this.value,\n // Update this to be more dynamic based on table columns.\n fields: ['metadata.name', 'metadata.title', 'spec.profile.displayName'],\n };\n }\n\n toQueryValue() {\n return this.value;\n }\n\n private toUpperArray(\n value: Array<string | string[] | undefined>,\n ): Array<string> {\n return value\n .flat()\n .filter((m): m is string => Boolean(m))\n .map(m => m.toLocaleUpperCase('en-US'));\n }\n}\n\n/**\n * Filter matching entities that are owned by group.\n * @public\n *\n * CAUTION: This class may contain both full and partial entity refs.\n */\nexport class EntityOwnerFilter implements EntityFilter {\n readonly values: string[];\n constructor(values: string[]) {\n this.values = values.reduce((fullRefs, ref) => {\n // Attempt to remove bad entity references here.\n try {\n fullRefs.push(\n stringifyEntityRef(parseEntityRef(ref, { defaultKind: 'Group' })),\n );\n return fullRefs;\n } catch (err) {\n return fullRefs;\n }\n }, [] as string[]);\n }\n\n getCatalogFilters(): Record<string, string | string[]> {\n return { 'relations.ownedBy': this.values };\n }\n\n filterEntity(entity: Entity): boolean {\n return this.values.some(v =>\n getEntityRelations(entity, RELATION_OWNED_BY).some(\n o => stringifyEntityRef(o) === v,\n ),\n );\n }\n\n /**\n * Get the URL query parameter value. May be a mix of full and humanized entity refs.\n * @returns list of entity refs.\n */\n toQueryValue(): string[] {\n return this.values;\n }\n}\n\n/**\n * Filters entities on lifecycle.\n * @public\n */\nexport class EntityLifecycleFilter implements EntityFilter {\n constructor(readonly values: string[]) {}\n\n getCatalogFilters(): Record<string, string | string[]> {\n return { 'spec.lifecycle': this.values };\n }\n\n filterEntity(entity: Entity): boolean {\n return this.values.some(v => entity.spec?.lifecycle === v);\n }\n\n toQueryValue(): string[] {\n return this.values;\n }\n}\n\n/**\n * Filters entities to those within the given namespace(s).\n * @public\n */\nexport class EntityNamespaceFilter implements EntityFilter {\n constructor(readonly values: string[]) {}\n\n getCatalogFilters(): Record<string, string | string[]> {\n return { 'metadata.namespace': this.values };\n }\n filterEntity(entity: Entity): boolean {\n return this.values.some(v => entity.metadata.namespace === v);\n }\n\n toQueryValue(): string[] {\n return this.values;\n }\n}\n\n/**\n * @public\n */\nexport class EntityUserFilter implements EntityFilter {\n private constructor(\n readonly value: UserListFilterKind,\n readonly refs?: string[],\n ) {}\n\n static owned(ownershipEntityRefs: string[]) {\n return new EntityUserFilter('owned', ownershipEntityRefs);\n }\n\n static all() {\n return new EntityUserFilter('all');\n }\n\n static starred(starredEntityRefs: string[]) {\n return new EntityUserFilter('starred', starredEntityRefs);\n }\n\n getCatalogFilters(): Record<string, string[]> {\n if (this.value === 'owned') {\n return { 'relations.ownedBy': this.refs ?? [] };\n }\n if (this.value === 'starred') {\n return {\n 'metadata.name': this.refs?.map(e => parseEntityRef(e).name) ?? [],\n };\n }\n return {};\n }\n\n filterEntity(entity: Entity) {\n if (this.value === 'starred') {\n return this.refs?.includes(stringifyEntityRef(entity)) ?? true;\n }\n // used only for retro-compatibility with non paginated data.\n // This is supposed to return always true for paginated\n // owned entities, since the filters are applied server side.\n if (this.value === 'owned') {\n const relations = getEntityRelations(entity, RELATION_OWNED_BY);\n\n return (\n this.refs?.some(v =>\n relations.some(o => stringifyEntityRef(o) === v),\n ) ?? false\n );\n }\n return true;\n }\n\n toQueryValue(): string {\n return this.value;\n }\n}\n\n/**\n * Filters entities based on whatever the user has starred or owns them.\n * @deprecated use EntityUserFilter\n * @public\n */\nexport class UserListFilter implements EntityFilter {\n constructor(\n readonly value: UserListFilterKind,\n readonly isOwnedEntity: (entity: Entity) => boolean,\n readonly isStarredEntity: (entity: Entity) => boolean,\n ) {}\n\n filterEntity(entity: Entity): boolean {\n switch (this.value) {\n case 'owned':\n return this.isOwnedEntity(entity);\n case 'starred':\n return this.isStarredEntity(entity);\n default:\n return true;\n }\n }\n\n toQueryValue(): string {\n return this.value;\n }\n}\n\n/**\n * Filters entities based if it is an orphan or not.\n * @public\n */\nexport class EntityOrphanFilter implements EntityFilter {\n constructor(readonly value: boolean) {}\n\n getCatalogFilters(): Record<string, string | string[]> {\n if (this.value) {\n return { 'metadata.annotations.backstage.io/orphan': String(this.value) };\n }\n return {};\n }\n\n filterEntity(entity: Entity): boolean {\n const orphan = entity.metadata.annotations?.['backstage.io/orphan'];\n return orphan !== undefined && this.value.toString() === orphan;\n }\n}\n\n/**\n * Filters entities based on if it has errors or not.\n * @public\n */\nexport class EntityErrorFilter implements EntityFilter {\n constructor(readonly value: boolean) {}\n\n filterEntity(entity: Entity): boolean {\n const error =\n ((entity as AlphaEntity)?.status?.items?.length as number) > 0;\n return error !== undefined && this.value === error;\n }\n}\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"filters.esm.js","sources":["../src/filters.ts"],"sourcesContent":["/*\n * Copyright 2021 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport {\n Entity,\n parseEntityRef,\n RELATION_OWNED_BY,\n stringifyEntityRef,\n} from '@backstage/catalog-model';\nimport { AlphaEntity } from '@backstage/catalog-model/alpha';\nimport { EntityFilter, UserListFilterKind } from './types';\nimport { getEntityRelations } from './utils';\n\n/**\n * Filter entities based on Kind.\n * @public\n */\nexport class EntityKindFilter implements EntityFilter {\n constructor(readonly value: string) {}\n\n getCatalogFilters(): Record<string, string | string[]> {\n return { kind: this.value };\n }\n\n toQueryValue(): string {\n return this.value;\n }\n}\n\n/**\n * Filters entities based on type\n * @public\n */\nexport class EntityTypeFilter implements EntityFilter {\n constructor(readonly value: string | string[]) {}\n\n // Simplify `string | string[]` for consumers, always returns an array\n getTypes(): string[] {\n return Array.isArray(this.value) ? this.value : [this.value];\n }\n\n getCatalogFilters(): Record<string, string | string[]> {\n return { 'spec.type': this.getTypes() };\n }\n\n toQueryValue(): string[] {\n return this.getTypes();\n }\n}\n\n/**\n * Filters entities based on tag.\n * @public\n */\nexport class EntityTagFilter implements EntityFilter {\n constructor(readonly values: string[]) {}\n\n filterEntity(entity: Entity): boolean {\n return this.values.every(v => (entity.metadata.tags ?? []).includes(v));\n }\n\n getCatalogFilters(): Record<string, string | string[]> {\n return { 'metadata.tags': this.values };\n }\n\n toQueryValue(): string[] {\n return this.values;\n }\n}\n\n/**\n * Filters entities where the text matches spec, title or tags.\n * @public\n */\nexport class EntityTextFilter implements EntityFilter {\n constructor(readonly value: string) {}\n\n filterEntity(entity: Entity): boolean {\n const words = this.toUpperArray(this.value.split(/\\s/));\n const exactMatch = this.toUpperArray([entity.metadata.tags]);\n const partialMatch = this.toUpperArray([\n entity.metadata.name,\n entity.metadata.title,\n (entity.spec?.profile as { displayName?: string })?.displayName,\n ]);\n\n for (const word of words) {\n if (\n exactMatch.every(m => m !== word) &&\n partialMatch.every(m => !m.includes(word))\n ) {\n return false;\n }\n }\n\n return true;\n }\n\n getFullTextFilters() {\n return {\n term: this.value,\n // Update this to be more dynamic based on table columns.\n fields: ['metadata.name', 'metadata.title', 'spec.profile.displayName'],\n };\n }\n\n toQueryValue() {\n return this.value;\n }\n\n private toUpperArray(\n value: Array<string | string[] | undefined>,\n ): Array<string> {\n return value\n .flat()\n .filter((m): m is string => Boolean(m))\n .map(m => m.toLocaleUpperCase('en-US'));\n }\n}\n\n/**\n * Filter matching entities that are owned by group.\n * @public\n *\n * CAUTION: This class may contain both full and partial entity refs.\n */\nexport class EntityOwnerFilter implements EntityFilter {\n readonly values: string[];\n constructor(values: string[]) {\n this.values = values.reduce((fullRefs, ref) => {\n // Attempt to remove bad entity references here.\n try {\n fullRefs.push(\n stringifyEntityRef(parseEntityRef(ref, { defaultKind: 'Group' })),\n );\n return fullRefs;\n } catch (err) {\n return fullRefs;\n }\n }, [] as string[]);\n }\n\n getCatalogFilters(): Record<string, string | string[]> {\n return { 'relations.ownedBy': this.values };\n }\n\n filterEntity(entity: Entity): boolean {\n return this.values.some(v =>\n getEntityRelations(entity, RELATION_OWNED_BY).some(\n o => stringifyEntityRef(o) === v,\n ),\n );\n }\n\n /**\n * Get the URL query parameter value. May be a mix of full and humanized entity refs.\n * @returns list of entity refs.\n */\n toQueryValue(): string[] {\n return this.values;\n }\n}\n\n/**\n * Filters entities on lifecycle.\n * @public\n */\nexport class EntityLifecycleFilter implements EntityFilter {\n constructor(readonly values: string[]) {}\n\n getCatalogFilters(): Record<string, string | string[]> {\n return { 'spec.lifecycle': this.values };\n }\n\n filterEntity(entity: Entity): boolean {\n return this.values.some(v => entity.spec?.lifecycle === v);\n }\n\n toQueryValue(): string[] {\n return this.values;\n }\n}\n\n/**\n * Filters entities to those within the given namespace(s).\n * @public\n */\nexport class EntityNamespaceFilter implements EntityFilter {\n constructor(readonly values: string[]) {}\n\n getCatalogFilters(): Record<string, string | string[]> {\n return { 'metadata.namespace': this.values };\n }\n filterEntity(entity: Entity): boolean {\n return this.values.some(v => entity.metadata.namespace === v);\n }\n\n toQueryValue(): string[] {\n return this.values;\n }\n}\n\n/**\n * @public\n */\nexport class EntityUserFilter implements EntityFilter {\n private constructor(\n readonly value: UserListFilterKind,\n readonly refs?: string[],\n ) {}\n\n static owned(ownershipEntityRefs: string[]) {\n return new EntityUserFilter('owned', ownershipEntityRefs);\n }\n\n static all() {\n return new EntityUserFilter('all');\n }\n\n static starred(starredEntityRefs: string[]) {\n return new EntityUserFilter('starred', starredEntityRefs);\n }\n\n getCatalogFilters(): Record<string, string[]> {\n if (this.value === 'owned') {\n return { 'relations.ownedBy': this.refs ?? [] };\n }\n if (this.value === 'starred') {\n return {\n 'metadata.name': this.refs?.map(e => parseEntityRef(e).name) ?? [],\n };\n }\n return {};\n }\n\n filterEntity(entity: Entity) {\n if (this.value === 'starred') {\n return this.refs?.includes(stringifyEntityRef(entity)) ?? true;\n }\n // used only for retro-compatibility with non paginated data.\n // This is supposed to return always true for paginated\n // owned entities, since the filters are applied server side.\n if (this.value === 'owned') {\n const relations = getEntityRelations(entity, RELATION_OWNED_BY);\n\n return (\n this.refs?.some(v =>\n relations.some(o => stringifyEntityRef(o) === v),\n ) ?? false\n );\n }\n return true;\n }\n\n toQueryValue(): string {\n return this.value;\n }\n}\n\n/**\n * Filters entities based on whatever the user has starred or owns them.\n * @deprecated use EntityUserFilter\n * @public\n */\nexport class UserListFilter implements EntityFilter {\n constructor(\n readonly value: UserListFilterKind,\n readonly isOwnedEntity: (entity: Entity) => boolean,\n readonly isStarredEntity: (entity: Entity) => boolean,\n ) {}\n\n filterEntity(entity: Entity): boolean {\n switch (this.value) {\n case 'owned':\n return this.isOwnedEntity(entity);\n case 'starred':\n return this.isStarredEntity(entity);\n default:\n return true;\n }\n }\n\n toQueryValue(): string {\n return this.value;\n }\n}\n\n/**\n * Filters entities based if it is an orphan or not.\n * @public\n */\nexport class EntityOrphanFilter implements EntityFilter {\n constructor(readonly value: boolean) {}\n\n getCatalogFilters(): Record<string, string | string[]> {\n if (this.value) {\n return { 'metadata.annotations.backstage.io/orphan': String(this.value) };\n }\n return {};\n }\n\n filterEntity(entity: Entity): boolean {\n const orphan = entity.metadata.annotations?.['backstage.io/orphan'];\n return orphan !== undefined && this.value.toString() === orphan;\n }\n}\n\n/**\n * Filters entities based on if it has errors or not.\n * @public\n */\nexport class EntityErrorFilter implements EntityFilter {\n constructor(readonly value: boolean) {}\n\n filterEntity(entity: Entity): boolean {\n const error =\n ((entity as AlphaEntity)?.status?.items?.length as number) > 0;\n return error !== undefined && this.value === error;\n }\n}\n"],"names":[],"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.14.2",
3
+ "version": "1.14.3-next.1",
4
4
  "description": "A frontend library that helps other Backstage plugins interact with the catalog",
5
5
  "backstage": {
6
6
  "role": "web-library",
@@ -73,20 +73,20 @@
73
73
  "test": "backstage-cli package test"
74
74
  },
75
75
  "dependencies": {
76
- "@backstage/catalog-client": "^1.8.0",
77
- "@backstage/catalog-model": "^1.7.1",
78
- "@backstage/core-compat-api": "^0.3.3",
79
- "@backstage/core-components": "^0.16.1",
80
- "@backstage/core-plugin-api": "^1.10.1",
81
- "@backstage/errors": "^1.2.5",
82
- "@backstage/frontend-plugin-api": "^0.9.2",
83
- "@backstage/frontend-test-utils": "^0.2.3",
84
- "@backstage/integration-react": "^1.2.1",
85
- "@backstage/plugin-catalog-common": "^1.1.1",
86
- "@backstage/plugin-permission-common": "^0.8.2",
87
- "@backstage/plugin-permission-react": "^0.4.28",
88
- "@backstage/types": "^1.2.0",
89
- "@backstage/version-bridge": "^1.0.10",
76
+ "@backstage/catalog-client": "1.9.0-next.1",
77
+ "@backstage/catalog-model": "1.7.1",
78
+ "@backstage/core-compat-api": "0.3.4-next.1",
79
+ "@backstage/core-components": "0.16.2-next.1",
80
+ "@backstage/core-plugin-api": "1.10.1",
81
+ "@backstage/errors": "1.2.5",
82
+ "@backstage/frontend-plugin-api": "0.9.3-next.1",
83
+ "@backstage/frontend-test-utils": "0.2.4-next.1",
84
+ "@backstage/integration-react": "1.2.2-next.0",
85
+ "@backstage/plugin-catalog-common": "1.1.1",
86
+ "@backstage/plugin-permission-common": "0.8.2",
87
+ "@backstage/plugin-permission-react": "0.4.28",
88
+ "@backstage/types": "1.2.0",
89
+ "@backstage/version-bridge": "1.0.10",
90
90
  "@material-ui/core": "^4.12.2",
91
91
  "@material-ui/icons": "^4.9.1",
92
92
  "@material-ui/lab": "4.0.0-alpha.61",
@@ -100,11 +100,11 @@
100
100
  "zen-observable": "^0.10.0"
101
101
  },
102
102
  "devDependencies": {
103
- "@backstage/cli": "^0.29.2",
104
- "@backstage/core-app-api": "^1.15.2",
105
- "@backstage/plugin-catalog-common": "^1.1.1",
106
- "@backstage/plugin-scaffolder-common": "^1.5.7",
107
- "@backstage/test-utils": "^1.7.2",
103
+ "@backstage/cli": "0.29.3-next.1",
104
+ "@backstage/core-app-api": "1.15.3-next.0",
105
+ "@backstage/plugin-catalog-common": "1.1.1",
106
+ "@backstage/plugin-scaffolder-common": "1.5.8-next.0",
107
+ "@backstage/test-utils": "1.7.3-next.0",
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",