@backstage/plugin-catalog-react 1.12.4-next.1 → 1.13.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,61 @@
1
1
  # @backstage/plugin-catalog-react
2
2
 
3
+ ## 1.13.0
4
+
5
+ ### Minor Changes
6
+
7
+ - 78475c3: Allow offset mode paging in entity list provider
8
+
9
+ ### Patch Changes
10
+
11
+ - c891b69: Add `FavoriteToggle` in `core-components` to standardise favorite marking
12
+ - fec8b57: Updated exports to use the new type parameters for extensions and extension blueprints.
13
+ - b537bd7: Allow custom star icons to be provided via the `star` and `unstarred` icon overrides. See how to override existing icons in the [Backstage documentation](https://backstage.io/docs/getting-started/app-custom-theme/#custom-icons).
14
+ - 836127c: Updated dependency `@testing-library/react` to `^16.0.0`.
15
+ - 5446061: The `/alpha` export no longer export extension creators for the new frontend system, existing usage should be switched to use the equivalent extension blueprint instead. For more information see the [new frontend system 1.30 migration documentation](https://backstage.io/docs/frontend-system/architecture/migrations#130).
16
+ - a159180: Added missing items to `overridableComponents`
17
+ - ae9b6cb: Small internal fix to better work with recent `lodash` versions
18
+ - Updated dependencies
19
+ - @backstage/core-components@0.15.0
20
+ - @backstage/frontend-plugin-api@0.8.0
21
+ - @backstage/core-compat-api@0.3.0
22
+ - @backstage/integration-react@1.1.31
23
+ - @backstage/catalog-model@1.7.0
24
+ - @backstage/catalog-client@1.7.0
25
+ - @backstage/plugin-catalog-common@1.1.0
26
+ - @backstage/core-plugin-api@1.9.4
27
+ - @backstage/version-bridge@1.0.9
28
+ - @backstage/plugin-permission-react@0.4.26
29
+ - @backstage/errors@1.2.4
30
+ - @backstage/types@1.1.1
31
+ - @backstage/plugin-permission-common@0.8.1
32
+
33
+ ## 1.13.0-next.2
34
+
35
+ ### Minor Changes
36
+
37
+ - 78475c3: Allow offset mode paging in entity list provider
38
+
39
+ ### Patch Changes
40
+
41
+ - c891b69: Add `FavoriteToggle` in `core-components` to standardise favorite marking
42
+ - b537bd7: Allow custom star icons to be provided via the `star` and `unstarred` icon overrides. See how to override existing icons in the [Backstage documentation](https://backstage.io/docs/getting-started/app-custom-theme/#custom-icons).
43
+ - 836127c: Updated dependency `@testing-library/react` to `^16.0.0`.
44
+ - Updated dependencies
45
+ - @backstage/core-components@0.14.11-next.1
46
+ - @backstage/integration-react@1.1.31-next.0
47
+ - @backstage/catalog-client@1.7.0-next.1
48
+ - @backstage/core-compat-api@0.3.0-next.2
49
+ - @backstage/core-plugin-api@1.9.4-next.0
50
+ - @backstage/frontend-plugin-api@0.8.0-next.2
51
+ - @backstage/version-bridge@1.0.9-next.0
52
+ - @backstage/plugin-permission-react@0.4.26-next.0
53
+ - @backstage/catalog-model@1.6.0
54
+ - @backstage/errors@1.2.4
55
+ - @backstage/types@1.1.1
56
+ - @backstage/plugin-catalog-common@1.0.26
57
+ - @backstage/plugin-permission-common@0.8.1
58
+
3
59
  ## 1.12.4-next.1
4
60
 
5
61
  ### Patch Changes
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@backstage/plugin-catalog-react__alpha",
3
- "version": "1.12.4-next.1",
3
+ "version": "1.13.0",
4
4
  "main": "../dist/alpha.esm.js",
5
5
  "module": "../dist/alpha.esm.js",
6
6
  "types": "../dist/alpha.d.ts"
@@ -9,9 +9,7 @@ const useStyles = makeStyles(
9
9
  {
10
10
  input: {}
11
11
  },
12
- {
13
- name: "CatalogReactEntityLifecyclePicker"
14
- }
12
+ { name: "CatalogReactEntityLifecyclePicker" }
15
13
  );
16
14
  const EntityLifecyclePicker = (props) => {
17
15
  const { initialFilter = [] } = props;
@@ -1 +1 @@
1
- {"version":3,"file":"EntityLifecyclePicker.esm.js","sources":["../../../src/components/EntityLifecyclePicker/EntityLifecyclePicker.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 { makeStyles } from '@material-ui/core/styles';\nimport React from 'react';\nimport { EntityLifecycleFilter } from '../../filters';\nimport { EntityAutocompletePicker } from '../EntityAutocompletePicker';\nimport { catalogReactTranslationRef } from '../../translation';\nimport { useTranslationRef } from '@backstage/core-plugin-api/alpha';\n\n/** @public */\nexport type CatalogReactEntityLifecyclePickerClassKey = 'input';\n\nconst useStyles = makeStyles(\n {\n input: {},\n },\n {\n name: 'CatalogReactEntityLifecyclePicker',\n },\n);\n\n/** @public */\nexport const EntityLifecyclePicker = (props: { initialFilter?: string[] }) => {\n const { initialFilter = [] } = props;\n const classes = useStyles();\n const { t } = useTranslationRef(catalogReactTranslationRef);\n\n return (\n <EntityAutocompletePicker\n label={t('entityLifecyclePicker.title')}\n name=\"lifecycles\"\n path=\"spec.lifecycle\"\n Filter={EntityLifecycleFilter}\n InputProps={{ className: classes.input }}\n initialSelectedOptions={initialFilter}\n />\n );\n};\n"],"names":[],"mappings":";;;;;;;AA0BA,MAAM,SAAY,GAAA,UAAA;AAAA,EAChB;AAAA,IACE,OAAO,EAAC;AAAA,GACV;AAAA,EACA;AAAA,IACE,IAAM,EAAA,mCAAA;AAAA,GACR;AACF,CAAA,CAAA;AAGa,MAAA,qBAAA,GAAwB,CAAC,KAAwC,KAAA;AAC5E,EAAA,MAAM,EAAE,aAAA,GAAgB,EAAC,EAAM,GAAA,KAAA,CAAA;AAC/B,EAAA,MAAM,UAAU,SAAU,EAAA,CAAA;AAC1B,EAAA,MAAM,EAAE,CAAA,EAAM,GAAA,iBAAA,CAAkB,0BAA0B,CAAA,CAAA;AAE1D,EACE,uBAAA,KAAA,CAAA,aAAA;AAAA,IAAC,wBAAA;AAAA,IAAA;AAAA,MACC,KAAA,EAAO,EAAE,6BAA6B,CAAA;AAAA,MACtC,IAAK,EAAA,YAAA;AAAA,MACL,IAAK,EAAA,gBAAA;AAAA,MACL,MAAQ,EAAA,qBAAA;AAAA,MACR,UAAY,EAAA,EAAE,SAAW,EAAA,OAAA,CAAQ,KAAM,EAAA;AAAA,MACvC,sBAAwB,EAAA,aAAA;AAAA,KAAA;AAAA,GAC1B,CAAA;AAEJ;;;;"}
1
+ {"version":3,"file":"EntityLifecyclePicker.esm.js","sources":["../../../src/components/EntityLifecyclePicker/EntityLifecyclePicker.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 { makeStyles } from '@material-ui/core/styles';\nimport React from 'react';\nimport { EntityLifecycleFilter } from '../../filters';\nimport { EntityAutocompletePicker } from '../EntityAutocompletePicker';\nimport { catalogReactTranslationRef } from '../../translation';\nimport { useTranslationRef } from '@backstage/core-plugin-api/alpha';\n\n/** @public */\nexport type CatalogReactEntityLifecyclePickerClassKey = 'input';\n\nconst useStyles = makeStyles(\n {\n input: {},\n },\n { name: 'CatalogReactEntityLifecyclePicker' },\n);\n\n/** @public */\nexport const EntityLifecyclePicker = (props: { initialFilter?: string[] }) => {\n const { initialFilter = [] } = props;\n const classes = useStyles();\n const { t } = useTranslationRef(catalogReactTranslationRef);\n\n return (\n <EntityAutocompletePicker\n label={t('entityLifecyclePicker.title')}\n name=\"lifecycles\"\n path=\"spec.lifecycle\"\n Filter={EntityLifecycleFilter}\n InputProps={{ className: classes.input }}\n initialSelectedOptions={initialFilter}\n />\n );\n};\n"],"names":[],"mappings":";;;;;;;AA0BA,MAAM,SAAY,GAAA,UAAA;AAAA,EAChB;AAAA,IACE,OAAO,EAAC;AAAA,GACV;AAAA,EACA,EAAE,MAAM,mCAAoC,EAAA;AAC9C,CAAA,CAAA;AAGa,MAAA,qBAAA,GAAwB,CAAC,KAAwC,KAAA;AAC5E,EAAA,MAAM,EAAE,aAAA,GAAgB,EAAC,EAAM,GAAA,KAAA,CAAA;AAC/B,EAAA,MAAM,UAAU,SAAU,EAAA,CAAA;AAC1B,EAAA,MAAM,EAAE,CAAA,EAAM,GAAA,iBAAA,CAAkB,0BAA0B,CAAA,CAAA;AAE1D,EACE,uBAAA,KAAA,CAAA,aAAA;AAAA,IAAC,wBAAA;AAAA,IAAA;AAAA,MACC,KAAA,EAAO,EAAE,6BAA6B,CAAA;AAAA,MACtC,IAAK,EAAA,YAAA;AAAA,MACL,IAAK,EAAA,gBAAA;AAAA,MACL,MAAQ,EAAA,qBAAA;AAAA,MACR,UAAY,EAAA,EAAE,SAAW,EAAA,OAAA,CAAQ,KAAM,EAAA;AAAA,MACvC,sBAAwB,EAAA,aAAA;AAAA,KAAA;AAAA,GAC1B,CAAA;AAEJ;;;;"}
@@ -38,9 +38,7 @@ const useStyles = makeStyles(
38
38
  overflow: "hidden"
39
39
  }
40
40
  },
41
- {
42
- name: "CatalogReactEntityOwnerPicker"
43
- }
41
+ { name: "CatalogReactEntityOwnerPicker" }
44
42
  );
45
43
  const FixedWidthFormControlLabel = withStyles(
46
44
  (_theme) => ({
@@ -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 { makeStyles } 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 {\n root: {},\n label: {},\n input: {},\n fullWidth: { width: '100%' },\n boxLabel: {\n width: '100%',\n textOverflow: 'ellipsis',\n overflow: 'hidden',\n },\n },\n {\n name: 'CatalogReactEntityOwnerPicker',\n },\n);\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 { makeStyles } 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 {\n root: {},\n label: {},\n input: {},\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":";;;;;;;;;;;;;;;;;;;;;;;;;;;;AAgDA,MAAM,SAAY,GAAA,UAAA;AAAA,EAChB;AAAA,IACE,MAAM,EAAC;AAAA,IACP,OAAO,EAAC;AAAA,IACR,OAAO,EAAC;AAAA,IACR,SAAA,EAAW,EAAE,KAAA,EAAO,MAAO,EAAA;AAAA,IAC3B,QAAU,EAAA;AAAA,MACR,KAAO,EAAA,MAAA;AAAA,MACP,YAAc,EAAA,UAAA;AAAA,MACd,QAAU,EAAA,QAAA;AAAA,KACZ;AAAA,GACF;AAAA,EACA,EAAE,MAAM,+BAAgC,EAAA;AAC1C,CAAA,CAAA;AAKA,MAAM,0BAA6B,GAAA,UAAA;AAAA,EACjC,CAAW,MAAA,MAAA;AAAA,IACT,KAAO,EAAA;AAAA,MACL,KAAO,EAAA,MAAA;AAAA,KACT;AAAA,IACA,IAAM,EAAA;AAAA,MACJ,KAAO,EAAA,KAAA;AAAA,KACT;AAAA,GACF,CAAA;AAAA,EACA,EAAE,MAAM,4BAA6B,EAAA;AACvC,CAAA,CAAE,gBAAgB,CAAA,CAAA;AAElB,MAAM,IAAO,mBAAA,KAAA,CAAA,aAAA,CAAC,wBAAyB,EAAA,EAAA,QAAA,EAAS,OAAQ,EAAA,CAAA,CAAA;AACxD,MAAM,WAAc,mBAAA,KAAA,CAAA,aAAA,CAAC,YAAa,EAAA,EAAA,QAAA,EAAS,OAAQ,EAAA,CAAA,CAAA;AASnD,SAAS,kBAAkB,KAAgD,EAAA;AACzE,EAAA,MAAM,UAAU,SAAU,EAAA,CAAA;AAC1B,EAAA,MAAM,UAAU,KAAM,CAAA,MAAA,CAAO,IAAK,CAAA,iBAAA,CAAkB,OAAO,CAAM,KAAA,OAAA,CAAA;AACjE,EAAA,MAAM,EAAE,YAAc,EAAA,KAAA,EAAU,GAAA,qBAAA,CAAsB,MAAM,MAAM,CAAA,CAAA;AAClE,EAAA,uBACG,KAAA,CAAA,aAAA,CAAA,GAAA,EAAA,EAAI,SAAW,EAAA,OAAA,CAAQ,SACtB,EAAA,kBAAA,KAAA,CAAA,aAAA;AAAA,IAAC,0BAAA;AAAA,IAAA;AAAA,MACC,WAAW,OAAQ,CAAA,SAAA;AAAA,MACnB,OACE,kBAAA,KAAA,CAAA,aAAA;AAAA,QAAC,QAAA;AAAA,QAAA;AAAA,UACC,IAAA;AAAA,UACA,WAAA;AAAA,UACA,SAAS,KAAM,CAAA,UAAA;AAAA,SAAA;AAAA,OACjB;AAAA,MAEF,OAAA,EAAS,CAAS,KAAA,KAAA,KAAA,CAAM,cAAe,EAAA;AAAA,MACvC,KACE,kBAAA,KAAA,CAAA,aAAA,CAAC,OAAQ,EAAA,EAAA,KAAA,EAAA,sCACN,GAAI,EAAA,EAAA,OAAA,EAAQ,MAAO,EAAA,UAAA,EAAW,YAC5B,OACC,mBAAA,KAAA,CAAA,aAAA,CAAC,SAAU,EAAA,EAAA,QAAA,EAAS,SAAQ,CAE5B,mBAAA,KAAA,CAAA,aAAA,CAAC,UAAW,EAAA,EAAA,QAAA,EAAS,OAAQ,EAAA,CAAA,EAC7B,MAEF,kBAAA,KAAA,CAAA,aAAA,CAAC,OAAI,SAAW,EAAA,OAAA,CAAQ,QACtB,EAAA,kBAAA,KAAA,CAAA,aAAA,CAAC,cAAW,MAAM,EAAA,IAAA,EAAA,EAAE,KAAM,CAC5B,CACF,CACF,CAAA;AAAA,KAAA;AAAA,GAGN,CAAA,CAAA;AAEJ,CAAA;AAGa,MAAA,iBAAA,GAAoB,CAAC,KAAmC,KAAA;AACnE,EAAA,MAAM,UAAU,SAAU,EAAA,CAAA;AAC1B,EAAA,MAAM,EAAE,IAAA,GAAO,aAAc,EAAA,GAAI,SAAS,EAAC,CAAA;AAC3C,EAAM,MAAA;AAAA,IACJ,aAAA;AAAA,IACA,OAAA;AAAA,IACA,eAAA,EAAiB,EAAE,MAAA,EAAQ,eAAgB,EAAA;AAAA,MACzC,aAAc,EAAA,CAAA;AAElB,EAAA,MAAM,CAAC,IAAA,EAAM,OAAO,CAAA,GAAI,SAAS,EAAE,CAAA,CAAA;AACnC,EAAA,MAAM,EAAE,CAAA,EAAM,GAAA,iBAAA,CAAkB,0BAA0B,CAAA,CAAA;AAE1D,EAAA,MAAM,gBAAmB,GAAA,OAAA;AAAA,IACvB,MAAM,CAAC,eAAe,EAAE,IAAK,EAAA,CAAE,OAAO,OAAO,CAAA;AAAA,IAC7C,CAAC,eAAe,CAAA;AAAA,GAClB,CAAA;AAEA,EAAM,MAAA,CAAC,cAAgB,EAAA,iBAAiB,CAAI,GAAA,QAAA;AAAA,IAC1C,iBAAiB,MAAS,GAAA,gBAAA,GAAmB,OAAQ,CAAA,MAAA,EAAQ,UAAU,EAAC;AAAA,GAC1E,CAAA;AAEA,EAAM,MAAA,CAAC,EAAE,KAAO,EAAA,OAAA,IAAW,WAAa,EAAA,KAAK,IAAI,gBAAiB,CAAA;AAAA,IAChE,IAAA;AAAA,IACA,yBAA2B,EAAA,cAAA;AAAA,GAC5B,CAAA,CAAA;AACD,EAAmB,kBAAA,CAAA,MAAM,WAAY,CAAA,EAAE,IAAK,EAAC,GAAG,CAAC,IAAA,EAAM,WAAW,CAAA,EAAG,GAAG,CAAA,CAAA;AAExE,EAAM,MAAA,eAAA,GAAkB,KAAO,EAAA,KAAA,IAAS,EAAC,CAAA;AAIzC,EAAA,SAAA,CAAU,MAAM;AACd,IAAA,IAAI,iBAAiB,MAAQ,EAAA;AAC3B,MAAM,MAAA,MAAA,GAAS,IAAI,iBAAA,CAAkB,gBAAgB,CAAA,CAAA;AACrD,MAAA,iBAAA,CAAkB,OAAO,MAAM,CAAA,CAAA;AAAA,KACjC;AAAA,GACF,EAAG,CAAC,gBAAgB,CAAC,CAAA,CAAA;AAErB,EAAA,SAAA,CAAU,MAAM;AACd,IAAc,aAAA,CAAA;AAAA,MACZ,QAAQ,cAAe,CAAA,MAAA,GACnB,IAAI,iBAAA,CAAkB,cAAc,CACpC,GAAA,KAAA,CAAA;AAAA,KACL,CAAA,CAAA;AAAA,GACA,EAAA,CAAC,cAAgB,EAAA,aAAa,CAAC,CAAA,CAAA;AAElC,EACE,IAAA,CAAC,MAAQ,EAAA,OAAO,CAAE,CAAA,QAAA;AAAA,IAChB,OAAQ,CAAA,IAAA,EAAM,KAAM,CAAA,iBAAA,CAAkB,OAAO,CAAK,IAAA,EAAA;AAAA,GAEpD,EAAA;AACA,IAAO,OAAA,IAAA,CAAA;AAAA,GACT;AAEA,EACE,uBAAA,KAAA,CAAA,aAAA,CAAC,OAAI,SAAW,EAAA,OAAA,CAAQ,MAAM,EAAI,EAAA,CAAA,EAAG,IAAI,CACvC,EAAA,kBAAA,KAAA,CAAA,aAAA,CAAC,cAAW,SAAW,EAAA,OAAA,CAAQ,OAAO,OAAQ,EAAA,QAAA,EAAS,WAAU,OAC9D,EAAA,EAAA,CAAA,CAAE,yBAAyB,CAC5B,kBAAA,KAAA,CAAA,aAAA;AAAA,IAAC,YAAA;AAAA,IAAA;AAAA,MACC,iBAAiB,CACf,WAAA,qBAAA,KAAA,CAAA,aAAA,CAAC,SAAK,GAAG,WAAA,EAAA,EAAc,YAAY,QAAsB,CAAA;AAAA,MAE3D,QAAQ,EAAA,IAAA;AAAA,MACR,oBAAoB,EAAA,IAAA;AAAA,MACpB,OAAA;AAAA,MACA,OAAS,EAAA,eAAA;AAAA,MACT,KAAO,EAAA,cAAA;AAAA,MACP,iBAAA,EAAmB,CAAC,CAAA,EAAG,CAAM,KAAA;AAC3B,QAAI,IAAA,OAAO,MAAM,QAAU,EAAA;AACzB,UAAO,OAAA,kBAAA,CAAmB,CAAC,CAAM,KAAA,CAAA,CAAA;AAAA,SACnC;AACA,QAAA,OAAO,CAAM,KAAA,CAAA,CAAA;AAAA,OACf;AAAA,MACA,gBAAgB,CAAK,CAAA,KAAA;AACnB,QAAM,MAAA,MAAA,GACJ,OAAO,CAAM,KAAA,QAAA,GACT,MAAM,SAAU,CAAA,CAAC,CACjB,IAAA,cAAA,CAAe,CAAG,EAAA;AAAA,UAChB,WAAa,EAAA,OAAA;AAAA,UACb,gBAAkB,EAAA,SAAA;AAAA,SACnB,CACD,GAAA,CAAA,CAAA;AACN,QAAA,OAAO,cAAe,CAAA,MAAA,EAAQ,iBAAkB,CAAA,MAAM,CAAC,CAAA,CAAA;AAAA,OACzD;AAAA,MACA,QAAA,EAAU,CAAC,CAAA,EAAW,MAAW,KAAA;AAC/B,QAAA,OAAA,CAAQ,EAAE,CAAA,CAAA;AACV,QAAA,iBAAA;AAAA,UACE,MAAA,CAAO,IAAI,CAAK,CAAA,KAAA;AACd,YAAA,MAAM,YACJ,OAAO,CAAA,KAAM,QAAW,GAAA,CAAA,GAAI,mBAAmB,CAAC,CAAA,CAAA;AAElD,YAAI,IAAA,OAAO,MAAM,QAAU,EAAA;AACzB,cAAA,KAAA,CAAM,UAAU,CAAC,CAAA,CAAA;AAAA,aACnB;AACA,YAAO,OAAA,SAAA,CAAA;AAAA,WACR,CAAA;AAAA,SACH,CAAA;AAAA,OACF;AAAA,MACA,eAAe,CAAK,CAAA,KAAA,CAAA;AAAA,MACpB,YAAc,EAAA,CAAC,MAAQ,EAAA,EAAE,UAAe,KAAA;AACtC,QAAA,uBAAQ,KAAA,CAAA,aAAA,CAAA,iBAAA,EAAA,EAAkB,MAAgB,EAAA,UAAA,EAAY,QAAU,EAAA,CAAA,CAAA;AAAA,OAClE;AAAA,MACA,IAAK,EAAA,OAAA;AAAA,MACL,SAAW,kBAAA,KAAA,CAAA,aAAA,CAAC,cAAe,EAAA,EAAA,aAAA,EAAY,qBAAsB,EAAA,CAAA;AAAA,MAC7D,aAAa,CACX,MAAA,qBAAA,KAAA,CAAA,aAAA;AAAA,QAAC,SAAA;AAAA,QAAA;AAAA,UACE,GAAG,MAAA;AAAA,UACJ,WAAW,OAAQ,CAAA,KAAA;AAAA,UACnB,UAAU,CAAK,CAAA,KAAA;AACb,YAAQ,OAAA,CAAA,CAAA,CAAE,cAAc,KAAK,CAAA,CAAA;AAAA,WAC/B;AAAA,UACA,OAAQ,EAAA,UAAA;AAAA,SAAA;AAAA,OACV;AAAA,MAEF,YAAc,EAAA;AAAA,QACZ,QAAA,EAAU,CAAC,CAAwB,KAAA;AACjC,UAAA,MAAM,UAAU,CAAE,CAAA,aAAA,CAAA;AAClB,UAAA,MAAM,gBACJ,IAAK,CAAA,GAAA;AAAA,YACH,OAAQ,CAAA,YAAA,GACN,OAAQ,CAAA,YAAA,GACR,OAAQ,CAAA,SAAA;AAAA,WACR,GAAA,CAAA,CAAA;AAEN,UAAI,IAAA,aAAA,IAAiB,OAAO,MAAQ,EAAA;AAClC,YAAA,WAAA,CAAY,EAAE,KAAO,EAAA,KAAA,CAAM,OAAO,MAAQ,EAAA,KAAA,CAAM,QAAQ,CAAA,CAAA;AAAA,WAC1D;AAAA,SACF;AAAA,QACA,aAAe,EAAA,sBAAA;AAAA,OACjB;AAAA,KAAA;AAAA,GAEJ,CACF,CAAA,CAAA;AAEJ;;;;"}
@@ -32,9 +32,7 @@ const useStyles = makeStyles(
32
32
  input: {},
33
33
  label: {}
34
34
  },
35
- {
36
- name: "CatalogReactEntityProcessingStatusPickerPicker"
37
- }
35
+ { name: "CatalogReactEntityProcessingStatusPickerPicker" }
38
36
  );
39
37
  const icon = /* @__PURE__ */ React.createElement(CheckBoxOutlineBlankIcon, { fontSize: "small" });
40
38
  const checkedIcon = /* @__PURE__ */ React.createElement(CheckBoxIcon, { fontSize: "small" });
@@ -1 +1 @@
1
- {"version":3,"file":"EntityProcessingStatusPicker.esm.js","sources":["../../../src/components/EntityProcessingStatusPicker/EntityProcessingStatusPicker.tsx"],"sourcesContent":["/*\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 { EntityErrorFilter, EntityOrphanFilter } from '../../filters';\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 { makeStyles } 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 React, { useState, ReactNode } from 'react';\nimport { useEntityList } from '../../hooks';\nimport Autocomplete from '@material-ui/lab/Autocomplete';\nimport { catalogReactTranslationRef } from '../../translation';\nimport { useTranslationRef } from '@backstage/core-plugin-api/alpha';\n\n/** @public */\nexport type CatalogReactEntityProcessingStatusPickerClassKey = 'input';\n\nconst useStyles = makeStyles(\n {\n root: {},\n input: {},\n label: {},\n },\n {\n name: 'CatalogReactEntityProcessingStatusPickerPicker',\n },\n);\n\nconst icon = <CheckBoxOutlineBlankIcon fontSize=\"small\" />;\nconst checkedIcon = <CheckBoxIcon fontSize=\"small\" />;\n\n/** @public */\nexport const EntityProcessingStatusPicker = () => {\n const classes = useStyles();\n const { updateFilters } = useEntityList();\n const { t } = useTranslationRef(catalogReactTranslationRef);\n\n const [selectedAdvancedItems, setSelectedAdvancedItems] = useState<string[]>(\n [],\n );\n\n function orphanChange(value: boolean) {\n updateFilters({\n orphan: value ? new EntityOrphanFilter(value) : undefined,\n });\n }\n\n function errorChange(value: boolean) {\n updateFilters({\n error: value ? new EntityErrorFilter(value) : undefined,\n });\n }\n\n const availableAdvancedItems = ['Is Orphan', 'Has Error'];\n\n return (\n <Box className={classes.root} pb={1} pt={1}>\n <Typography className={classes.label} variant=\"button\" component=\"label\">\n {t('entityProcessingStatusPicker.title')}\n <Autocomplete<string, true>\n PopperComponent={popperProps => (\n <div {...popperProps}>{popperProps.children as ReactNode}</div>\n )}\n multiple\n disableCloseOnSelect\n options={availableAdvancedItems}\n value={selectedAdvancedItems}\n onChange={(_: object, value: string[]) => {\n setSelectedAdvancedItems(value);\n orphanChange(value.includes('Is Orphan'));\n errorChange(value.includes('Has Error'));\n }}\n renderOption={(option, { selected }) => (\n <FormControlLabel\n control={\n <Checkbox\n icon={icon}\n checkedIcon={checkedIcon}\n checked={selected}\n />\n }\n onClick={event => event.preventDefault()}\n label={option}\n />\n )}\n size=\"small\"\n popupIcon={\n <ExpandMoreIcon data-testid=\"processing-status-picker-expand\" />\n }\n renderInput={params => (\n <TextField\n {...params}\n className={classes.input}\n variant=\"outlined\"\n />\n )}\n />\n </Typography>\n </Box>\n );\n};\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"EntityProcessingStatusPicker.esm.js","sources":["../../../src/components/EntityProcessingStatusPicker/EntityProcessingStatusPicker.tsx"],"sourcesContent":["/*\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 { EntityErrorFilter, EntityOrphanFilter } from '../../filters';\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 { makeStyles } 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 React, { useState, ReactNode } from 'react';\nimport { useEntityList } from '../../hooks';\nimport Autocomplete from '@material-ui/lab/Autocomplete';\nimport { catalogReactTranslationRef } from '../../translation';\nimport { useTranslationRef } from '@backstage/core-plugin-api/alpha';\n\n/** @public */\nexport type CatalogReactEntityProcessingStatusPickerClassKey = 'input';\n\nconst useStyles = makeStyles(\n {\n root: {},\n input: {},\n label: {},\n },\n { name: 'CatalogReactEntityProcessingStatusPickerPicker' },\n);\n\nconst icon = <CheckBoxOutlineBlankIcon fontSize=\"small\" />;\nconst checkedIcon = <CheckBoxIcon fontSize=\"small\" />;\n\n/** @public */\nexport const EntityProcessingStatusPicker = () => {\n const classes = useStyles();\n const { updateFilters } = useEntityList();\n const { t } = useTranslationRef(catalogReactTranslationRef);\n\n const [selectedAdvancedItems, setSelectedAdvancedItems] = useState<string[]>(\n [],\n );\n\n function orphanChange(value: boolean) {\n updateFilters({\n orphan: value ? new EntityOrphanFilter(value) : undefined,\n });\n }\n\n function errorChange(value: boolean) {\n updateFilters({\n error: value ? new EntityErrorFilter(value) : undefined,\n });\n }\n\n const availableAdvancedItems = ['Is Orphan', 'Has Error'];\n\n return (\n <Box className={classes.root} pb={1} pt={1}>\n <Typography className={classes.label} variant=\"button\" component=\"label\">\n {t('entityProcessingStatusPicker.title')}\n <Autocomplete<string, true>\n PopperComponent={popperProps => (\n <div {...popperProps}>{popperProps.children as ReactNode}</div>\n )}\n multiple\n disableCloseOnSelect\n options={availableAdvancedItems}\n value={selectedAdvancedItems}\n onChange={(_: object, value: string[]) => {\n setSelectedAdvancedItems(value);\n orphanChange(value.includes('Is Orphan'));\n errorChange(value.includes('Has Error'));\n }}\n renderOption={(option, { selected }) => (\n <FormControlLabel\n control={\n <Checkbox\n icon={icon}\n checkedIcon={checkedIcon}\n checked={selected}\n />\n }\n onClick={event => event.preventDefault()}\n label={option}\n />\n )}\n size=\"small\"\n popupIcon={\n <ExpandMoreIcon data-testid=\"processing-status-picker-expand\" />\n }\n renderInput={params => (\n <TextField\n {...params}\n className={classes.input}\n variant=\"outlined\"\n />\n )}\n />\n </Typography>\n </Box>\n );\n};\n"],"names":[],"mappings":"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"}
@@ -21,9 +21,7 @@ const useStyles = makeStyles(
21
21
  },
22
22
  input: {}
23
23
  }),
24
- {
25
- name: "CatalogReactEntitySearchBar"
26
- }
24
+ { name: "CatalogReactEntitySearchBar" }
27
25
  );
28
26
  const EntitySearchBar = () => {
29
27
  const classes = useStyles();
@@ -1 +1 @@
1
- {"version":3,"file":"EntitySearchBar.esm.js","sources":["../../../src/components/EntitySearchBar/EntitySearchBar.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 FormControl from '@material-ui/core/FormControl';\nimport IconButton from '@material-ui/core/IconButton';\nimport Input from '@material-ui/core/Input';\nimport InputAdornment from '@material-ui/core/InputAdornment';\nimport Toolbar from '@material-ui/core/Toolbar';\nimport { makeStyles } from '@material-ui/core/styles';\nimport Clear from '@material-ui/icons/Clear';\nimport Search from '@material-ui/icons/Search';\nimport React, { useEffect, useMemo, useState } from 'react';\nimport useDebounce from 'react-use/lib/useDebounce';\nimport { useEntityList } from '../../hooks/useEntityListProvider';\nimport { EntityTextFilter } from '../../filters';\nimport { catalogReactTranslationRef } from '../../translation';\nimport { useTranslationRef } from '@backstage/core-plugin-api/alpha';\n\n/** @public */\nexport type CatalogReactEntitySearchBarClassKey = 'searchToolbar' | 'input';\n\nconst useStyles = makeStyles(\n _theme => ({\n searchToolbar: {\n paddingLeft: 0,\n paddingRight: 0,\n },\n input: {},\n }),\n {\n name: 'CatalogReactEntitySearchBar',\n },\n);\n\n/**\n * Renders search bar for filtering the entity list.\n * @public\n */\nexport const EntitySearchBar = () => {\n const classes = useStyles();\n const { t } = useTranslationRef(catalogReactTranslationRef);\n\n const {\n updateFilters,\n queryParameters: { text: textParameter },\n } = useEntityList();\n\n const queryParamTextFilter = useMemo(\n () => [textParameter].flat()[0],\n [textParameter],\n );\n\n const [search, setSearch] = useState(queryParamTextFilter ?? '');\n\n useDebounce(\n () => {\n updateFilters({\n text: search.length ? new EntityTextFilter(search) : undefined,\n });\n },\n 250,\n [search, updateFilters],\n );\n\n useEffect(() => {\n if (queryParamTextFilter) {\n setSearch(queryParamTextFilter);\n }\n }, [queryParamTextFilter]);\n\n return (\n <Toolbar className={classes.searchToolbar}>\n <FormControl>\n <Input\n aria-label=\"search\"\n id=\"input-with-icon-adornment\"\n className={classes.input}\n placeholder={t('entitySearchBar.placeholder')}\n autoComplete=\"off\"\n onChange={event => setSearch(event.target.value)}\n value={search}\n startAdornment={\n <InputAdornment position=\"start\">\n <Search />\n </InputAdornment>\n }\n endAdornment={\n <InputAdornment position=\"end\">\n <IconButton\n aria-label=\"clear search\"\n onClick={() => setSearch('')}\n edge=\"end\"\n disabled={search.length === 0}\n >\n <Clear />\n </IconButton>\n </InputAdornment>\n }\n />\n </FormControl>\n </Toolbar>\n );\n};\n"],"names":[],"mappings":";;;;;;;;;;;;;;;AAkCA,MAAM,SAAY,GAAA,UAAA;AAAA,EAChB,CAAW,MAAA,MAAA;AAAA,IACT,aAAe,EAAA;AAAA,MACb,WAAa,EAAA,CAAA;AAAA,MACb,YAAc,EAAA,CAAA;AAAA,KAChB;AAAA,IACA,OAAO,EAAC;AAAA,GACV,CAAA;AAAA,EACA;AAAA,IACE,IAAM,EAAA,6BAAA;AAAA,GACR;AACF,CAAA,CAAA;AAMO,MAAM,kBAAkB,MAAM;AACnC,EAAA,MAAM,UAAU,SAAU,EAAA,CAAA;AAC1B,EAAA,MAAM,EAAE,CAAA,EAAM,GAAA,iBAAA,CAAkB,0BAA0B,CAAA,CAAA;AAE1D,EAAM,MAAA;AAAA,IACJ,aAAA;AAAA,IACA,eAAA,EAAiB,EAAE,IAAA,EAAM,aAAc,EAAA;AAAA,MACrC,aAAc,EAAA,CAAA;AAElB,EAAA,MAAM,oBAAuB,GAAA,OAAA;AAAA,IAC3B,MAAM,CAAC,aAAa,CAAE,CAAA,IAAA,GAAO,CAAC,CAAA;AAAA,IAC9B,CAAC,aAAa,CAAA;AAAA,GAChB,CAAA;AAEA,EAAA,MAAM,CAAC,MAAQ,EAAA,SAAS,CAAI,GAAA,QAAA,CAAS,wBAAwB,EAAE,CAAA,CAAA;AAE/D,EAAA,WAAA;AAAA,IACE,MAAM;AACJ,MAAc,aAAA,CAAA;AAAA,QACZ,MAAM,MAAO,CAAA,MAAA,GAAS,IAAI,gBAAA,CAAiB,MAAM,CAAI,GAAA,KAAA,CAAA;AAAA,OACtD,CAAA,CAAA;AAAA,KACH;AAAA,IACA,GAAA;AAAA,IACA,CAAC,QAAQ,aAAa,CAAA;AAAA,GACxB,CAAA;AAEA,EAAA,SAAA,CAAU,MAAM;AACd,IAAA,IAAI,oBAAsB,EAAA;AACxB,MAAA,SAAA,CAAU,oBAAoB,CAAA,CAAA;AAAA,KAChC;AAAA,GACF,EAAG,CAAC,oBAAoB,CAAC,CAAA,CAAA;AAEzB,EAAA,2CACG,OAAQ,EAAA,EAAA,SAAA,EAAW,OAAQ,CAAA,aAAA,EAAA,sCACzB,WACC,EAAA,IAAA,kBAAA,KAAA,CAAA,aAAA;AAAA,IAAC,KAAA;AAAA,IAAA;AAAA,MACC,YAAW,EAAA,QAAA;AAAA,MACX,EAAG,EAAA,2BAAA;AAAA,MACH,WAAW,OAAQ,CAAA,KAAA;AAAA,MACnB,WAAA,EAAa,EAAE,6BAA6B,CAAA;AAAA,MAC5C,YAAa,EAAA,KAAA;AAAA,MACb,QAAU,EAAA,CAAA,KAAA,KAAS,SAAU,CAAA,KAAA,CAAM,OAAO,KAAK,CAAA;AAAA,MAC/C,KAAO,EAAA,MAAA;AAAA,MACP,gCACG,KAAA,CAAA,aAAA,CAAA,cAAA,EAAA,EAAe,UAAS,OACvB,EAAA,kBAAA,KAAA,CAAA,aAAA,CAAC,YAAO,CACV,CAAA;AAAA,MAEF,YACE,kBAAA,KAAA,CAAA,aAAA,CAAC,cAAe,EAAA,EAAA,QAAA,EAAS,KACvB,EAAA,kBAAA,KAAA,CAAA,aAAA;AAAA,QAAC,UAAA;AAAA,QAAA;AAAA,UACC,YAAW,EAAA,cAAA;AAAA,UACX,OAAA,EAAS,MAAM,SAAA,CAAU,EAAE,CAAA;AAAA,UAC3B,IAAK,EAAA,KAAA;AAAA,UACL,QAAA,EAAU,OAAO,MAAW,KAAA,CAAA;AAAA,SAAA;AAAA,4CAE3B,KAAM,EAAA,IAAA,CAAA;AAAA,OAEX,CAAA;AAAA,KAAA;AAAA,GAGN,CACF,CAAA,CAAA;AAEJ;;;;"}
1
+ {"version":3,"file":"EntitySearchBar.esm.js","sources":["../../../src/components/EntitySearchBar/EntitySearchBar.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 FormControl from '@material-ui/core/FormControl';\nimport IconButton from '@material-ui/core/IconButton';\nimport Input from '@material-ui/core/Input';\nimport InputAdornment from '@material-ui/core/InputAdornment';\nimport Toolbar from '@material-ui/core/Toolbar';\nimport { makeStyles } from '@material-ui/core/styles';\nimport Clear from '@material-ui/icons/Clear';\nimport Search from '@material-ui/icons/Search';\nimport React, { useEffect, useMemo, useState } from 'react';\nimport useDebounce from 'react-use/lib/useDebounce';\nimport { useEntityList } from '../../hooks/useEntityListProvider';\nimport { EntityTextFilter } from '../../filters';\nimport { catalogReactTranslationRef } from '../../translation';\nimport { useTranslationRef } from '@backstage/core-plugin-api/alpha';\n\n/** @public */\nexport type CatalogReactEntitySearchBarClassKey = 'searchToolbar' | 'input';\n\nconst useStyles = makeStyles(\n _theme => ({\n searchToolbar: {\n paddingLeft: 0,\n paddingRight: 0,\n },\n input: {},\n }),\n { name: 'CatalogReactEntitySearchBar' },\n);\n\n/**\n * Renders search bar for filtering the entity list.\n * @public\n */\nexport const EntitySearchBar = () => {\n const classes = useStyles();\n const { t } = useTranslationRef(catalogReactTranslationRef);\n\n const {\n updateFilters,\n queryParameters: { text: textParameter },\n } = useEntityList();\n\n const queryParamTextFilter = useMemo(\n () => [textParameter].flat()[0],\n [textParameter],\n );\n\n const [search, setSearch] = useState(queryParamTextFilter ?? '');\n\n useDebounce(\n () => {\n updateFilters({\n text: search.length ? new EntityTextFilter(search) : undefined,\n });\n },\n 250,\n [search, updateFilters],\n );\n\n useEffect(() => {\n if (queryParamTextFilter) {\n setSearch(queryParamTextFilter);\n }\n }, [queryParamTextFilter]);\n\n return (\n <Toolbar className={classes.searchToolbar}>\n <FormControl>\n <Input\n aria-label=\"search\"\n id=\"input-with-icon-adornment\"\n className={classes.input}\n placeholder={t('entitySearchBar.placeholder')}\n autoComplete=\"off\"\n onChange={event => setSearch(event.target.value)}\n value={search}\n startAdornment={\n <InputAdornment position=\"start\">\n <Search />\n </InputAdornment>\n }\n endAdornment={\n <InputAdornment position=\"end\">\n <IconButton\n aria-label=\"clear search\"\n onClick={() => setSearch('')}\n edge=\"end\"\n disabled={search.length === 0}\n >\n <Clear />\n </IconButton>\n </InputAdornment>\n }\n />\n </FormControl>\n </Toolbar>\n );\n};\n"],"names":[],"mappings":";;;;;;;;;;;;;;;AAkCA,MAAM,SAAY,GAAA,UAAA;AAAA,EAChB,CAAW,MAAA,MAAA;AAAA,IACT,aAAe,EAAA;AAAA,MACb,WAAa,EAAA,CAAA;AAAA,MACb,YAAc,EAAA,CAAA;AAAA,KAChB;AAAA,IACA,OAAO,EAAC;AAAA,GACV,CAAA;AAAA,EACA,EAAE,MAAM,6BAA8B,EAAA;AACxC,CAAA,CAAA;AAMO,MAAM,kBAAkB,MAAM;AACnC,EAAA,MAAM,UAAU,SAAU,EAAA,CAAA;AAC1B,EAAA,MAAM,EAAE,CAAA,EAAM,GAAA,iBAAA,CAAkB,0BAA0B,CAAA,CAAA;AAE1D,EAAM,MAAA;AAAA,IACJ,aAAA;AAAA,IACA,eAAA,EAAiB,EAAE,IAAA,EAAM,aAAc,EAAA;AAAA,MACrC,aAAc,EAAA,CAAA;AAElB,EAAA,MAAM,oBAAuB,GAAA,OAAA;AAAA,IAC3B,MAAM,CAAC,aAAa,CAAE,CAAA,IAAA,GAAO,CAAC,CAAA;AAAA,IAC9B,CAAC,aAAa,CAAA;AAAA,GAChB,CAAA;AAEA,EAAA,MAAM,CAAC,MAAQ,EAAA,SAAS,CAAI,GAAA,QAAA,CAAS,wBAAwB,EAAE,CAAA,CAAA;AAE/D,EAAA,WAAA;AAAA,IACE,MAAM;AACJ,MAAc,aAAA,CAAA;AAAA,QACZ,MAAM,MAAO,CAAA,MAAA,GAAS,IAAI,gBAAA,CAAiB,MAAM,CAAI,GAAA,KAAA,CAAA;AAAA,OACtD,CAAA,CAAA;AAAA,KACH;AAAA,IACA,GAAA;AAAA,IACA,CAAC,QAAQ,aAAa,CAAA;AAAA,GACxB,CAAA;AAEA,EAAA,SAAA,CAAU,MAAM;AACd,IAAA,IAAI,oBAAsB,EAAA;AACxB,MAAA,SAAA,CAAU,oBAAoB,CAAA,CAAA;AAAA,KAChC;AAAA,GACF,EAAG,CAAC,oBAAoB,CAAC,CAAA,CAAA;AAEzB,EAAA,2CACG,OAAQ,EAAA,EAAA,SAAA,EAAW,OAAQ,CAAA,aAAA,EAAA,sCACzB,WACC,EAAA,IAAA,kBAAA,KAAA,CAAA,aAAA;AAAA,IAAC,KAAA;AAAA,IAAA;AAAA,MACC,YAAW,EAAA,QAAA;AAAA,MACX,EAAG,EAAA,2BAAA;AAAA,MACH,WAAW,OAAQ,CAAA,KAAA;AAAA,MACnB,WAAA,EAAa,EAAE,6BAA6B,CAAA;AAAA,MAC5C,YAAa,EAAA,KAAA;AAAA,MACb,QAAU,EAAA,CAAA,KAAA,KAAS,SAAU,CAAA,KAAA,CAAM,OAAO,KAAK,CAAA;AAAA,MAC/C,KAAO,EAAA,MAAA;AAAA,MACP,gCACG,KAAA,CAAA,aAAA,CAAA,cAAA,EAAA,EAAe,UAAS,OACvB,EAAA,kBAAA,KAAA,CAAA,aAAA,CAAC,YAAO,CACV,CAAA;AAAA,MAEF,YACE,kBAAA,KAAA,CAAA,aAAA,CAAC,cAAe,EAAA,EAAA,QAAA,EAAS,KACvB,EAAA,kBAAA,KAAA,CAAA,aAAA;AAAA,QAAC,UAAA;AAAA,QAAA;AAAA,UACC,YAAW,EAAA,cAAA;AAAA,UACX,OAAA,EAAS,MAAM,SAAA,CAAU,EAAE,CAAA;AAAA,UAC3B,IAAK,EAAA,KAAA;AAAA,UACL,QAAA,EAAU,OAAO,MAAW,KAAA,CAAA;AAAA,SAAA;AAAA,4CAE3B,KAAM,EAAA,IAAA,CAAA;AAAA,OAEX,CAAA;AAAA,KAAA;AAAA,GAGN,CACF,CAAA,CAAA;AAEJ;;;;"}
@@ -1,19 +1,10 @@
1
1
  import { stringifyEntityRef } from '@backstage/catalog-model';
2
- import IconButton from '@material-ui/core/IconButton';
3
- import Tooltip from '@material-ui/core/Tooltip';
4
- import { withStyles } from '@material-ui/core/styles';
5
- import StarIcon from '@material-ui/icons/Star';
6
- import StarBorder from '@material-ui/icons/StarBorder';
7
2
  import React from 'react';
8
3
  import { useStarredEntity } from '../../hooks/useStarredEntity.esm.js';
9
4
  import { catalogReactTranslationRef } from '../../translation.esm.js';
10
5
  import { useTranslationRef } from '@backstage/core-plugin-api/alpha';
6
+ import { FavoriteToggle } from '@backstage/core-components';
11
7
 
12
- const YellowStar = withStyles({
13
- root: {
14
- color: "#f3ba37"
15
- }
16
- })(StarIcon);
17
8
  const FavoriteEntity = (props) => {
18
9
  const { toggleStarredEntity, isStarredEntity } = useStarredEntity(
19
10
  props.entity
@@ -25,15 +16,14 @@ const FavoriteEntity = (props) => {
25
16
  "-"
26
17
  )}`;
27
18
  return /* @__PURE__ */ React.createElement(
28
- IconButton,
19
+ FavoriteToggle,
29
20
  {
30
- "aria-label": title,
21
+ title,
31
22
  id,
32
- color: "inherit",
33
- ...props,
34
- onClick: () => toggleStarredEntity()
35
- },
36
- /* @__PURE__ */ React.createElement(Tooltip, { id, title }, isStarredEntity ? /* @__PURE__ */ React.createElement(YellowStar, null) : /* @__PURE__ */ React.createElement(StarBorder, null))
23
+ isFavorite: isStarredEntity,
24
+ onToggle: toggleStarredEntity,
25
+ ...props
26
+ }
37
27
  );
38
28
  };
39
29
 
@@ -1 +1 @@
1
- {"version":3,"file":"FavoriteEntity.esm.js","sources":["../../../src/components/FavoriteEntity/FavoriteEntity.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, stringifyEntityRef } from '@backstage/catalog-model';\nimport IconButton from '@material-ui/core/IconButton';\nimport Tooltip from '@material-ui/core/Tooltip';\nimport { withStyles } from '@material-ui/core/styles';\nimport Star from '@material-ui/icons/Star';\nimport StarBorder from '@material-ui/icons/StarBorder';\nimport React, { ComponentProps } from 'react';\nimport { useStarredEntity } from '../../hooks/useStarredEntity';\nimport { catalogReactTranslationRef } from '../../translation';\nimport { useTranslationRef } from '@backstage/core-plugin-api/alpha';\n\n/** @public */\nexport type FavoriteEntityProps = ComponentProps<typeof IconButton> & {\n entity: Entity;\n};\n\nconst YellowStar = withStyles({\n root: {\n color: '#f3ba37',\n },\n})(Star);\n\n/**\n * IconButton for showing if a current entity is starred and adding/removing it from the favorite entities\n * @param props - MaterialUI IconButton props extended by required `entity` prop\n * @public\n */\nexport const FavoriteEntity = (props: FavoriteEntityProps) => {\n const { toggleStarredEntity, isStarredEntity } = useStarredEntity(\n props.entity,\n );\n const { t } = useTranslationRef(catalogReactTranslationRef);\n const title = isStarredEntity\n ? t('favoriteEntity.removeFromFavorites')\n : t('favoriteEntity.addToFavorites');\n\n const id = `favorite-${stringifyEntityRef(props.entity).replace(\n /[^a-zA-Z0-9-_]/g,\n '-',\n )}`;\n\n return (\n <IconButton\n aria-label={title}\n id={id}\n color=\"inherit\"\n {...props}\n onClick={() => toggleStarredEntity()}\n >\n <Tooltip id={id} title={title}>\n {isStarredEntity ? <YellowStar /> : <StarBorder />}\n </Tooltip>\n </IconButton>\n );\n};\n"],"names":["Star"],"mappings":";;;;;;;;;;;AAgCA,MAAM,aAAa,UAAW,CAAA;AAAA,EAC5B,IAAM,EAAA;AAAA,IACJ,KAAO,EAAA,SAAA;AAAA,GACT;AACF,CAAC,EAAEA,QAAI,CAAA,CAAA;AAOM,MAAA,cAAA,GAAiB,CAAC,KAA+B,KAAA;AAC5D,EAAM,MAAA,EAAE,mBAAqB,EAAA,eAAA,EAAoB,GAAA,gBAAA;AAAA,IAC/C,KAAM,CAAA,MAAA;AAAA,GACR,CAAA;AACA,EAAA,MAAM,EAAE,CAAA,EAAM,GAAA,iBAAA,CAAkB,0BAA0B,CAAA,CAAA;AAC1D,EAAA,MAAM,QAAQ,eACV,GAAA,CAAA,CAAE,oCAAoC,CAAA,GACtC,EAAE,+BAA+B,CAAA,CAAA;AAErC,EAAA,MAAM,EAAK,GAAA,CAAA,SAAA,EAAY,kBAAmB,CAAA,KAAA,CAAM,MAAM,CAAE,CAAA,OAAA;AAAA,IACtD,iBAAA;AAAA,IACA,GAAA;AAAA,GACD,CAAA,CAAA,CAAA;AAED,EACE,uBAAA,KAAA,CAAA,aAAA;AAAA,IAAC,UAAA;AAAA,IAAA;AAAA,MACC,YAAY,EAAA,KAAA;AAAA,MACZ,EAAA;AAAA,MACA,KAAM,EAAA,SAAA;AAAA,MACL,GAAG,KAAA;AAAA,MACJ,OAAA,EAAS,MAAM,mBAAoB,EAAA;AAAA,KAAA;AAAA,oBAEnC,KAAA,CAAA,aAAA,CAAC,OAAQ,EAAA,EAAA,EAAA,EAAQ,KACd,EAAA,EAAA,eAAA,uCAAmB,UAAW,EAAA,IAAA,CAAA,mBAAM,KAAA,CAAA,aAAA,CAAA,UAAA,EAAA,IAAW,CAClD,CAAA;AAAA,GACF,CAAA;AAEJ;;;;"}
1
+ {"version":3,"file":"FavoriteEntity.esm.js","sources":["../../../src/components/FavoriteEntity/FavoriteEntity.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, stringifyEntityRef } from '@backstage/catalog-model';\nimport IconButton from '@material-ui/core/IconButton';\nimport React, { ComponentProps } from 'react';\nimport { useStarredEntity } from '../../hooks/useStarredEntity';\nimport { catalogReactTranslationRef } from '../../translation';\nimport { useTranslationRef } from '@backstage/core-plugin-api/alpha';\nimport { FavoriteToggle } from '@backstage/core-components';\n\n/** @public */\nexport type FavoriteEntityProps = ComponentProps<typeof IconButton> & {\n entity: Entity;\n};\n\n/**\n * IconButton for showing if a current entity is starred and adding/removing it from the favorite entities\n * @param props - MaterialUI IconButton props extended by required `entity` prop\n * @public\n */\nexport const FavoriteEntity = (props: FavoriteEntityProps) => {\n const { toggleStarredEntity, isStarredEntity } = useStarredEntity(\n props.entity,\n );\n const { t } = useTranslationRef(catalogReactTranslationRef);\n const title = isStarredEntity\n ? t('favoriteEntity.removeFromFavorites')\n : t('favoriteEntity.addToFavorites');\n\n const id = `favorite-${stringifyEntityRef(props.entity).replace(\n /[^a-zA-Z0-9-_]/g,\n '-',\n )}`;\n\n return (\n <FavoriteToggle\n title={title}\n id={id}\n isFavorite={isStarredEntity}\n onToggle={toggleStarredEntity}\n {...props}\n />\n );\n};\n"],"names":[],"mappings":";;;;;;;AAkCa,MAAA,cAAA,GAAiB,CAAC,KAA+B,KAAA;AAC5D,EAAM,MAAA,EAAE,mBAAqB,EAAA,eAAA,EAAoB,GAAA,gBAAA;AAAA,IAC/C,KAAM,CAAA,MAAA;AAAA,GACR,CAAA;AACA,EAAA,MAAM,EAAE,CAAA,EAAM,GAAA,iBAAA,CAAkB,0BAA0B,CAAA,CAAA;AAC1D,EAAA,MAAM,QAAQ,eACV,GAAA,CAAA,CAAE,oCAAoC,CAAA,GACtC,EAAE,+BAA+B,CAAA,CAAA;AAErC,EAAA,MAAM,EAAK,GAAA,CAAA,SAAA,EAAY,kBAAmB,CAAA,KAAA,CAAM,MAAM,CAAE,CAAA,OAAA;AAAA,IACtD,iBAAA;AAAA,IACA,GAAA;AAAA,GACD,CAAA,CAAA,CAAA;AAED,EACE,uBAAA,KAAA,CAAA,aAAA;AAAA,IAAC,cAAA;AAAA,IAAA;AAAA,MACC,KAAA;AAAA,MACA,EAAA;AAAA,MACA,UAAY,EAAA,eAAA;AAAA,MACZ,QAAU,EAAA,mBAAA;AAAA,MACT,GAAG,KAAA;AAAA,KAAA;AAAA,GACN,CAAA;AAEJ;;;;"}
@@ -8,7 +8,7 @@ import MenuItem from '@material-ui/core/MenuItem';
8
8
  import Typography from '@material-ui/core/Typography';
9
9
  import { makeStyles } from '@material-ui/core/styles';
10
10
  import SettingsIcon from '@material-ui/icons/Settings';
11
- import StarIcon from '@material-ui/icons/Star';
11
+ import { StarIcon } from '@backstage/core-components';
12
12
  import React, { useMemo, useState, useEffect, Fragment } from 'react';
13
13
  import { EntityUserFilter } from '../../filters.esm.js';
14
14
  import '../../hooks/useEntity.esm.js';
@@ -53,9 +53,7 @@ const useStyles = makeStyles(
53
53
  margin: theme.spacing(1, 1, 2, 1)
54
54
  }
55
55
  }),
56
- {
57
- name: "CatalogReactUserListPicker"
58
- }
56
+ { name: "CatalogReactUserListPicker" }
59
57
  );
60
58
  function getFilterGroups(orgName, t) {
61
59
  return [
@@ -1 +1 @@
1
- {"version":3,"file":"UserListPicker.esm.js","sources":["../../../src/components/UserListPicker/UserListPicker.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 configApiRef,\n IconComponent,\n useApi,\n} from '@backstage/core-plugin-api';\nimport Card from '@material-ui/core/Card';\nimport List from '@material-ui/core/List';\nimport ListItemIcon from '@material-ui/core/ListItemIcon';\nimport ListItemSecondaryAction from '@material-ui/core/ListItemSecondaryAction';\nimport ListItemText from '@material-ui/core/ListItemText';\nimport MenuItem from '@material-ui/core/MenuItem';\nimport Typography from '@material-ui/core/Typography';\nimport { makeStyles } from '@material-ui/core/styles';\nimport SettingsIcon from '@material-ui/icons/Settings';\nimport StarIcon from '@material-ui/icons/Star';\nimport React, { Fragment, useEffect, useMemo, useState } from 'react';\nimport { EntityUserFilter } from '../../filters';\nimport { useEntityList } from '../../hooks';\nimport { UserListFilterKind } from '../../types';\nimport { useOwnedEntitiesCount } from './useOwnedEntitiesCount';\nimport { useAllEntitiesCount } from './useAllEntitiesCount';\nimport { useStarredEntitiesCount } from './useStarredEntitiesCount';\nimport {\n TranslationFunction,\n useTranslationRef,\n} from '@backstage/core-plugin-api/alpha';\nimport { catalogReactTranslationRef } from '../../translation';\n\n/** @public */\nexport type CatalogReactUserListPickerClassKey =\n | 'root'\n | 'title'\n | 'listIcon'\n | 'menuItem'\n | 'groupWrapper';\n\nconst useStyles = makeStyles(\n theme => ({\n root: {\n backgroundColor: 'rgba(0, 0, 0, .11)',\n boxShadow: 'none',\n margin: theme.spacing(1, 0, 1, 0),\n },\n title: {\n margin: theme.spacing(1, 0, 0, 1),\n textTransform: 'uppercase',\n fontSize: 12,\n fontWeight: 'bold',\n },\n listIcon: {\n minWidth: 30,\n color: theme.palette.text.primary,\n },\n menuItem: {\n minHeight: theme.spacing(6),\n },\n groupWrapper: {\n margin: theme.spacing(1, 1, 2, 1),\n },\n }),\n {\n name: 'CatalogReactUserListPicker',\n },\n);\n\nexport type ButtonGroup = {\n name: string;\n items: {\n id: 'owned' | 'starred' | 'all';\n label: string;\n icon?: IconComponent;\n }[];\n};\n\nfunction getFilterGroups(\n orgName: string,\n t: TranslationFunction<typeof catalogReactTranslationRef.T>,\n): ButtonGroup[] {\n return [\n {\n name: t('userListPicker.personalFilter.title'),\n items: [\n {\n id: 'owned',\n label: t('userListPicker.personalFilter.ownedLabel'),\n icon: SettingsIcon,\n },\n {\n id: 'starred',\n label: t('userListPicker.personalFilter.starredLabel'),\n icon: StarIcon,\n },\n ],\n },\n {\n name: orgName,\n items: [\n {\n id: 'all',\n label: t('userListPicker.orgFilterAllLabel'),\n },\n ],\n },\n ];\n}\n\n/** @public */\nexport type UserListPickerProps = {\n initialFilter?: UserListFilterKind;\n availableFilters?: UserListFilterKind[];\n};\n\n/** @public */\nexport const UserListPicker = (props: UserListPickerProps) => {\n const { initialFilter, availableFilters } = props;\n const classes = useStyles();\n const configApi = useApi(configApiRef);\n const { t } = useTranslationRef(catalogReactTranslationRef);\n const orgName =\n configApi.getOptionalString('organization.name') ??\n t('userListPicker.defaultOrgName');\n const {\n filters,\n updateFilters,\n queryParameters: { kind: kindParameter, user: userParameter },\n } = useEntityList();\n\n // Remove group items that aren't in availableFilters and exclude\n // any now-empty groups.\n const userAndGroupFilterIds = ['starred', 'all'];\n const filterGroups = getFilterGroups(orgName, t)\n .map(filterGroup => ({\n ...filterGroup,\n items: filterGroup.items.filter(({ id }) =>\n // TODO: avoid hardcoding kinds here\n ['group', 'user'].some(kind => kind === kindParameter)\n ? userAndGroupFilterIds.includes(id)\n : !availableFilters || availableFilters.includes(id),\n ),\n }))\n .filter(({ items }) => !!items.length);\n\n const {\n count: ownedEntitiesCount,\n loading: loadingOwnedEntities,\n filter: ownedEntitiesFilter,\n } = useOwnedEntitiesCount();\n const { count: allCount } = useAllEntitiesCount();\n const {\n count: starredEntitiesCount,\n filter: starredEntitiesFilter,\n loading: loadingStarredEntities,\n } = useStarredEntitiesCount();\n\n const queryParamUserFilter = useMemo(\n () => [userParameter].flat()[0],\n [userParameter],\n );\n\n const [selectedUserFilter, setSelectedUserFilter] = useState(\n (queryParamUserFilter as UserListFilterKind) ?? initialFilter,\n );\n\n const filterCounts = useMemo(() => {\n return {\n all: allCount,\n starred: starredEntitiesCount,\n owned: ownedEntitiesCount,\n };\n }, [starredEntitiesCount, ownedEntitiesCount, allCount]);\n\n // Set selected user filter on query parameter updates; this happens at initial page load and from\n // external updates to the page location.\n useEffect(() => {\n if (queryParamUserFilter) {\n setSelectedUserFilter(queryParamUserFilter as UserListFilterKind);\n }\n }, [queryParamUserFilter]);\n\n const loading = loadingOwnedEntities || loadingStarredEntities;\n\n useEffect(() => {\n if (\n !loading &&\n !!selectedUserFilter &&\n selectedUserFilter !== 'all' &&\n filterCounts[selectedUserFilter] === 0\n ) {\n setSelectedUserFilter('all');\n }\n }, [loading, filterCounts, selectedUserFilter, setSelectedUserFilter]);\n\n useEffect(() => {\n if (!selectedUserFilter) {\n return;\n }\n if (loading) {\n return;\n }\n\n const getFilter = () => {\n if (selectedUserFilter === 'owned') {\n return ownedEntitiesFilter;\n }\n if (selectedUserFilter === 'starred') {\n return starredEntitiesFilter;\n }\n return EntityUserFilter.all();\n };\n\n updateFilters({ user: getFilter() });\n }, [\n selectedUserFilter,\n starredEntitiesFilter,\n ownedEntitiesFilter,\n updateFilters,\n\n loading,\n ]);\n\n return (\n <Card className={classes.root}>\n {filterGroups.map(group => (\n <Fragment key={group.name}>\n <Typography\n variant=\"subtitle2\"\n component=\"span\"\n className={classes.title}\n >\n {group.name}\n </Typography>\n <Card className={classes.groupWrapper}>\n <List disablePadding dense role=\"menu\" aria-label={group.name}>\n {group.items.map((item, index) => (\n <MenuItem\n role=\"none presentation\"\n key={item.id}\n divider={index !== group.items.length - 1}\n onClick={() => setSelectedUserFilter(item.id)}\n selected={item.id === filters.user?.value}\n className={classes.menuItem}\n disabled={filterCounts[item.id] === 0}\n data-testid={`user-picker-${item.id}`}\n tabIndex={0}\n ContainerProps={{ role: 'menuitem' }}\n >\n {item.icon && (\n <ListItemIcon className={classes.listIcon}>\n <item.icon fontSize=\"small\" />\n </ListItemIcon>\n )}\n <ListItemText>\n <Typography variant=\"body1\">{item.label} </Typography>\n </ListItemText>\n <ListItemSecondaryAction>\n {filterCounts[item.id] ?? '-'}\n </ListItemSecondaryAction>\n </MenuItem>\n ))}\n </List>\n </Card>\n </Fragment>\n ))}\n </Card>\n );\n};\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"UserListPicker.esm.js","sources":["../../../src/components/UserListPicker/UserListPicker.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 configApiRef,\n IconComponent,\n useApi,\n} from '@backstage/core-plugin-api';\nimport Card from '@material-ui/core/Card';\nimport List from '@material-ui/core/List';\nimport ListItemIcon from '@material-ui/core/ListItemIcon';\nimport ListItemSecondaryAction from '@material-ui/core/ListItemSecondaryAction';\nimport ListItemText from '@material-ui/core/ListItemText';\nimport MenuItem from '@material-ui/core/MenuItem';\nimport Typography from '@material-ui/core/Typography';\nimport { makeStyles } from '@material-ui/core/styles';\nimport SettingsIcon from '@material-ui/icons/Settings';\nimport { StarIcon } from '@backstage/core-components';\nimport React, { Fragment, useEffect, useMemo, useState } from 'react';\nimport { EntityUserFilter } from '../../filters';\nimport { useEntityList } from '../../hooks';\nimport { UserListFilterKind } from '../../types';\nimport { useOwnedEntitiesCount } from './useOwnedEntitiesCount';\nimport { useAllEntitiesCount } from './useAllEntitiesCount';\nimport { useStarredEntitiesCount } from './useStarredEntitiesCount';\nimport {\n TranslationFunction,\n useTranslationRef,\n} from '@backstage/core-plugin-api/alpha';\nimport { catalogReactTranslationRef } from '../../translation';\n\n/** @public */\nexport type CatalogReactUserListPickerClassKey =\n | 'root'\n | 'title'\n | 'listIcon'\n | 'menuItem'\n | 'groupWrapper';\n\nconst useStyles = makeStyles(\n theme => ({\n root: {\n backgroundColor: 'rgba(0, 0, 0, .11)',\n boxShadow: 'none',\n margin: theme.spacing(1, 0, 1, 0),\n },\n title: {\n margin: theme.spacing(1, 0, 0, 1),\n textTransform: 'uppercase',\n fontSize: 12,\n fontWeight: 'bold',\n },\n listIcon: {\n minWidth: 30,\n color: theme.palette.text.primary,\n },\n menuItem: {\n minHeight: theme.spacing(6),\n },\n groupWrapper: {\n margin: theme.spacing(1, 1, 2, 1),\n },\n }),\n { name: 'CatalogReactUserListPicker' },\n);\n\nexport type ButtonGroup = {\n name: string;\n items: {\n id: 'owned' | 'starred' | 'all';\n label: string;\n icon?: IconComponent;\n }[];\n};\n\nfunction getFilterGroups(\n orgName: string,\n t: TranslationFunction<typeof catalogReactTranslationRef.T>,\n): ButtonGroup[] {\n return [\n {\n name: t('userListPicker.personalFilter.title'),\n items: [\n {\n id: 'owned',\n label: t('userListPicker.personalFilter.ownedLabel'),\n icon: SettingsIcon,\n },\n {\n id: 'starred',\n label: t('userListPicker.personalFilter.starredLabel'),\n icon: StarIcon,\n },\n ],\n },\n {\n name: orgName,\n items: [\n {\n id: 'all',\n label: t('userListPicker.orgFilterAllLabel'),\n },\n ],\n },\n ];\n}\n\n/** @public */\nexport type UserListPickerProps = {\n initialFilter?: UserListFilterKind;\n availableFilters?: UserListFilterKind[];\n};\n\n/** @public */\nexport const UserListPicker = (props: UserListPickerProps) => {\n const { initialFilter, availableFilters } = props;\n const classes = useStyles();\n const configApi = useApi(configApiRef);\n const { t } = useTranslationRef(catalogReactTranslationRef);\n const orgName =\n configApi.getOptionalString('organization.name') ??\n t('userListPicker.defaultOrgName');\n const {\n filters,\n updateFilters,\n queryParameters: { kind: kindParameter, user: userParameter },\n } = useEntityList();\n\n // Remove group items that aren't in availableFilters and exclude\n // any now-empty groups.\n const userAndGroupFilterIds = ['starred', 'all'];\n const filterGroups = getFilterGroups(orgName, t)\n .map(filterGroup => ({\n ...filterGroup,\n items: filterGroup.items.filter(({ id }) =>\n // TODO: avoid hardcoding kinds here\n ['group', 'user'].some(kind => kind === kindParameter)\n ? userAndGroupFilterIds.includes(id)\n : !availableFilters || availableFilters.includes(id),\n ),\n }))\n .filter(({ items }) => !!items.length);\n\n const {\n count: ownedEntitiesCount,\n loading: loadingOwnedEntities,\n filter: ownedEntitiesFilter,\n } = useOwnedEntitiesCount();\n const { count: allCount } = useAllEntitiesCount();\n const {\n count: starredEntitiesCount,\n filter: starredEntitiesFilter,\n loading: loadingStarredEntities,\n } = useStarredEntitiesCount();\n\n const queryParamUserFilter = useMemo(\n () => [userParameter].flat()[0],\n [userParameter],\n );\n\n const [selectedUserFilter, setSelectedUserFilter] = useState(\n (queryParamUserFilter as UserListFilterKind) ?? initialFilter,\n );\n\n const filterCounts = useMemo(() => {\n return {\n all: allCount,\n starred: starredEntitiesCount,\n owned: ownedEntitiesCount,\n };\n }, [starredEntitiesCount, ownedEntitiesCount, allCount]);\n\n // Set selected user filter on query parameter updates; this happens at initial page load and from\n // external updates to the page location.\n useEffect(() => {\n if (queryParamUserFilter) {\n setSelectedUserFilter(queryParamUserFilter as UserListFilterKind);\n }\n }, [queryParamUserFilter]);\n\n const loading = loadingOwnedEntities || loadingStarredEntities;\n\n useEffect(() => {\n if (\n !loading &&\n !!selectedUserFilter &&\n selectedUserFilter !== 'all' &&\n filterCounts[selectedUserFilter] === 0\n ) {\n setSelectedUserFilter('all');\n }\n }, [loading, filterCounts, selectedUserFilter, setSelectedUserFilter]);\n\n useEffect(() => {\n if (!selectedUserFilter) {\n return;\n }\n if (loading) {\n return;\n }\n\n const getFilter = () => {\n if (selectedUserFilter === 'owned') {\n return ownedEntitiesFilter;\n }\n if (selectedUserFilter === 'starred') {\n return starredEntitiesFilter;\n }\n return EntityUserFilter.all();\n };\n\n updateFilters({ user: getFilter() });\n }, [\n selectedUserFilter,\n starredEntitiesFilter,\n ownedEntitiesFilter,\n updateFilters,\n\n loading,\n ]);\n\n return (\n <Card className={classes.root}>\n {filterGroups.map(group => (\n <Fragment key={group.name}>\n <Typography\n variant=\"subtitle2\"\n component=\"span\"\n className={classes.title}\n >\n {group.name}\n </Typography>\n <Card className={classes.groupWrapper}>\n <List disablePadding dense role=\"menu\" aria-label={group.name}>\n {group.items.map((item, index) => (\n <MenuItem\n role=\"none presentation\"\n key={item.id}\n divider={index !== group.items.length - 1}\n onClick={() => setSelectedUserFilter(item.id)}\n selected={item.id === filters.user?.value}\n className={classes.menuItem}\n disabled={filterCounts[item.id] === 0}\n data-testid={`user-picker-${item.id}`}\n tabIndex={0}\n ContainerProps={{ role: 'menuitem' }}\n >\n {item.icon && (\n <ListItemIcon className={classes.listIcon}>\n <item.icon fontSize=\"small\" />\n </ListItemIcon>\n )}\n <ListItemText>\n <Typography variant=\"body1\">{item.label} </Typography>\n </ListItemText>\n <ListItemSecondaryAction>\n {filterCounts[item.id] ?? '-'}\n </ListItemSecondaryAction>\n </MenuItem>\n ))}\n </List>\n </Card>\n </Fragment>\n ))}\n </Card>\n );\n};\n"],"names":[],"mappings":"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"}
@@ -18,25 +18,50 @@ const EntityListProvider = (props) => {
18
18
  {}
19
19
  );
20
20
  const location = useLocation();
21
- const enablePagination = props.pagination === true || typeof props.pagination === "object";
22
- const limit = props.pagination && typeof props.pagination === "object" && typeof props.pagination.limit === "number" ? props.pagination.limit : 20;
23
- const { queryParameters, cursor: initialCursor } = useMemo(() => {
21
+ const getPaginationMode = () => {
22
+ if (props.pagination === true) {
23
+ return "cursor";
24
+ }
25
+ return typeof props.pagination === "object" ? props.pagination.mode ?? "cursor" : "none";
26
+ };
27
+ const paginationMode = getPaginationMode();
28
+ const paginationLimit = typeof props.pagination === "object" ? props.pagination.limit ?? 20 : 20;
29
+ const {
30
+ queryParameters,
31
+ cursor: initialCursor,
32
+ offset: initialOffset,
33
+ limit: initialLimit
34
+ } = useMemo(() => {
24
35
  const parsed = qs.parse(location.search, {
25
36
  ignoreQueryPrefix: true
26
37
  });
38
+ let limit2 = paginationLimit;
39
+ if (typeof parsed.limit === "string") {
40
+ const queryLimit = Number.parseInt(parsed.limit, 10);
41
+ if (!isNaN(queryLimit)) {
42
+ limit2 = queryLimit;
43
+ }
44
+ }
45
+ const offset2 = typeof parsed.offset === "string" && paginationMode === "offset" ? Number.parseInt(parsed.offset, 10) : void 0;
27
46
  return {
28
47
  queryParameters: parsed.filters ?? {},
29
- cursor: typeof parsed.cursor === "string" ? parsed.cursor : void 0
48
+ cursor: typeof parsed.cursor === "string" && paginationMode === "cursor" ? parsed.cursor : void 0,
49
+ offset: paginationMode === "offset" && offset2 && !isNaN(offset2) ? offset2 : void 0,
50
+ limit: limit2
30
51
  };
31
- }, [location]);
52
+ }, [paginationMode, location.search, paginationLimit]);
32
53
  const [cursor, setCursor] = useState(initialCursor);
54
+ const [offset, setOffset] = useState(initialOffset);
55
+ const [limit, setLimit] = useState(initialLimit);
33
56
  const [outputState, setOutputState] = useState(
34
57
  () => {
35
58
  return {
36
59
  appliedFilters: {},
37
60
  entities: [],
38
61
  backendEntities: [],
39
- pageInfo: enablePagination ? {} : void 0
62
+ pageInfo: paginationMode === "cursor" ? {} : void 0,
63
+ offset,
64
+ limit
40
65
  };
41
66
  }
42
67
  );
@@ -53,7 +78,7 @@ const EntityListProvider = (props) => {
53
78
  },
54
79
  {}
55
80
  );
56
- if (enablePagination) {
81
+ if (paginationMode !== "none") {
57
82
  if (cursor) {
58
83
  if (cursor !== outputState.appliedCursor) {
59
84
  const entityFilter = reduceEntityFilters(compacted);
@@ -76,10 +101,11 @@ const EntityListProvider = (props) => {
76
101
  const previousBackendFilter = reduceCatalogFilters(
77
102
  compact(Object.values(outputState.appliedFilters))
78
103
  );
79
- if (!isEqual(previousBackendFilter, backendFilter)) {
104
+ if (paginationMode === "offset" || !isEqual(previousBackendFilter, backendFilter)) {
80
105
  const response = await catalogApi.queryEntities({
81
106
  ...backendFilter,
82
107
  limit,
108
+ offset,
83
109
  orderFields: [{ field: "metadata.name", order: "asc" }]
84
110
  });
85
111
  setOutputState({
@@ -87,7 +113,9 @@ const EntityListProvider = (props) => {
87
113
  backendEntities: response.items,
88
114
  entities: response.items.filter(entityFilter),
89
115
  pageInfo: response.pageInfo,
90
- totalItems: response.totalItems
116
+ totalItems: response.totalItems,
117
+ limit,
118
+ offset
91
119
  });
92
120
  }
93
121
  }
@@ -123,7 +151,7 @@ const EntityListProvider = (props) => {
123
151
  ignoreQueryPrefix: true
124
152
  });
125
153
  const newParams = qs.stringify(
126
- { ...oldParams, filters: queryParams, cursor },
154
+ { ...oldParams, filters: queryParams, cursor, offset, limit },
127
155
  { addQueryPrefix: true, arrayFormat: "repeat" }
128
156
  );
129
157
  const newUrl = `${window.location.pathname}${newParams}`;
@@ -136,11 +164,13 @@ const EntityListProvider = (props) => {
136
164
  requestedFilters,
137
165
  outputState,
138
166
  cursor,
139
- enablePagination
167
+ paginationMode,
168
+ limit,
169
+ offset
140
170
  ],
141
171
  { loading: true }
142
172
  );
143
- useDebounce(refresh, 10, [requestedFilters, cursor]);
173
+ useDebounce(refresh, 10, [requestedFilters, cursor, limit, offset]);
144
174
  const updateFilters = useCallback(
145
175
  (update) => {
146
176
  setCursor(void 0);
@@ -152,7 +182,7 @@ const EntityListProvider = (props) => {
152
182
  []
153
183
  );
154
184
  const pageInfo = useMemo(() => {
155
- if (!enablePagination) {
185
+ if (paginationMode !== "cursor") {
156
186
  return void 0;
157
187
  }
158
188
  const prevCursor = outputState.pageInfo?.prevCursor;
@@ -161,7 +191,7 @@ const EntityListProvider = (props) => {
161
191
  prev: prevCursor ? () => setCursor(prevCursor) : void 0,
162
192
  next: nextCursor ? () => setCursor(nextCursor) : void 0
163
193
  };
164
- }, [enablePagination, outputState.pageInfo]);
194
+ }, [paginationMode, outputState.pageInfo]);
165
195
  const value = useMemo(
166
196
  () => ({
167
197
  filters: outputState.appliedFilters,
@@ -172,9 +202,26 @@ const EntityListProvider = (props) => {
172
202
  loading,
173
203
  error,
174
204
  pageInfo,
175
- totalItems: outputState.totalItems
205
+ totalItems: outputState.totalItems,
206
+ limit,
207
+ offset,
208
+ setLimit,
209
+ setOffset,
210
+ paginationMode
176
211
  }),
177
- [outputState, updateFilters, queryParameters, loading, error, pageInfo]
212
+ [
213
+ outputState,
214
+ updateFilters,
215
+ queryParameters,
216
+ loading,
217
+ error,
218
+ pageInfo,
219
+ limit,
220
+ offset,
221
+ paginationMode,
222
+ setLimit,
223
+ setOffset
224
+ ]
178
225
  );
179
226
  return /* @__PURE__ */ React.createElement(EntityListContext.Provider, { value }, props.children);
180
227
  };
@@ -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 EntityOrphanFilter,\n EntityOwnerFilter,\n EntityTagFilter,\n EntityTextFilter,\n EntityTypeFilter,\n UserListFilter,\n EntityNamespaceFilter,\n EntityUserFilter,\n} from '../filters';\nimport { EntityFilter } from '../types';\nimport {\n reduceBackendCatalogFilters,\n reduceCatalogFilters,\n reduceEntityFilters,\n} from '../utils';\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 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\n totalItems?: number;\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};\n\n/**\n * @public\n */\nexport type EntityListProviderProps = PropsWithChildren<{\n pagination?: boolean | { limit?: number };\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 enablePagination =\n props.pagination === true || typeof props.pagination === 'object';\n\n const limit =\n props.pagination &&\n typeof props.pagination === 'object' &&\n typeof props.pagination.limit === 'number'\n ? props.pagination.limit\n : 20;\n\n const { queryParameters, cursor: initialCursor } = useMemo(() => {\n const parsed = qs.parse(location.search, {\n ignoreQueryPrefix: true,\n });\n\n return {\n queryParameters: (parsed.filters ?? {}) as Record<\n string,\n string | string[]\n >,\n cursor: typeof parsed.cursor === 'string' ? parsed.cursor : undefined,\n };\n }, [location]);\n\n const [cursor, setCursor] = useState(initialCursor);\n\n const [outputState, setOutputState] = useState<OutputState<EntityFilters>>(\n () => {\n return {\n appliedFilters: {} as EntityFilters,\n entities: [],\n backendEntities: [],\n pageInfo: enablePagination ? {} : undefined,\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 (enablePagination) {\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 (!isEqual(previousBackendFilter, backendFilter)) {\n const response = await catalogApi.queryEntities({\n ...backendFilter,\n limit,\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 });\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 },\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 enablePagination,\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]);\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 (!enablePagination) {\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 }, [enablePagination, 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 }),\n [outputState, updateFilters, queryParameters, loading, error, pageInfo],\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":[],"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';\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: 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: paginationMode === 'cursor' ? {} : undefined,\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 !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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"}
package/dist/index.d.ts CHANGED
@@ -239,9 +239,20 @@ type EntityFilter = {
239
239
  };
240
240
  /** @public */
241
241
  type UserListFilterKind = 'owned' | 'starred' | 'all';
242
+ /** @public */
243
+ type EntityListPagination = boolean | {
244
+ mode?: 'cursor';
245
+ limit?: number;
246
+ } | {
247
+ mode: 'offset';
248
+ limit?: number;
249
+ offset?: number;
250
+ };
242
251
 
243
252
  /** @public */
244
253
  type CatalogReactEntityOwnerPickerClassKey = 'input';
254
+ /** @public */
255
+ type FixedWidthFormControlLabelClassKey = 'label' | 'root';
245
256
  /**
246
257
  * @public
247
258
  */
@@ -685,6 +696,8 @@ type DefaultEntityFilters = {
685
696
  namespace?: EntityNamespaceFilter;
686
697
  };
687
698
  /** @public */
699
+ type PaginationMode = 'cursor' | 'offset' | 'none';
700
+ /** @public */
688
701
  type EntityListContextProps<EntityFilters extends DefaultEntityFilters = DefaultEntityFilters> = {
689
702
  /**
690
703
  * The currently registered filters, adhering to the shape of DefaultEntityFilters or an extension
@@ -715,6 +728,11 @@ type EntityListContextProps<EntityFilters extends DefaultEntityFilters = Default
715
728
  prev?: () => void;
716
729
  };
717
730
  totalItems?: number;
731
+ limit: number;
732
+ offset?: number;
733
+ setLimit: (limit: number) => void;
734
+ setOffset?: (offset: number) => void;
735
+ paginationMode: PaginationMode;
718
736
  };
719
737
  /**
720
738
  * Creates new context for entity listing and filtering.
@@ -725,9 +743,7 @@ declare const EntityListContext: React__default.Context<EntityListContextProps<a
725
743
  * @public
726
744
  */
727
745
  type EntityListProviderProps = PropsWithChildren<{
728
- pagination?: boolean | {
729
- limit?: number;
730
- };
746
+ pagination?: EntityListPagination;
731
747
  }>;
732
748
  /**
733
749
  * Provides entities and filters for a catalog listing.
@@ -925,8 +941,10 @@ type CatalogReactComponentsNameToClassKey = {
925
941
  CatalogReactEntitySearchBar: CatalogReactEntitySearchBarClassKey;
926
942
  CatalogReactEntityTagPicker: CatalogReactEntityTagPickerClassKey;
927
943
  CatalogReactEntityOwnerPicker: CatalogReactEntityOwnerPickerClassKey;
944
+ CatalogReactFixedWidthFormControlLabel: FixedWidthFormControlLabelClassKey;
928
945
  CatalogReactEntityProcessingStatusPicker: CatalogReactEntityProcessingStatusPickerClassKey;
929
946
  CatalogReactEntityAutocompletePickerClassKey: CatalogReactEntityAutocompletePickerClassKey;
947
+ CatalogReactMissingAnnotationEmptyState: MissingAnnotationEmptyStateClassKey;
930
948
  };
931
949
  /** @public */
932
950
  type BackstageOverrides = Overrides & {
@@ -954,4 +972,4 @@ type EntitySourceLocation = {
954
972
  /** @public */
955
973
  declare function getEntitySourceLocation(entity: Entity, scmIntegrationsApi: typeof scmIntegrationsApiRef.T): EntitySourceLocation | undefined;
956
974
 
957
- export { type AllowedEntityFilters, AsyncEntityProvider, type AsyncEntityProviderProps, type BackstageOverrides, CatalogFilterLayout, type CatalogReactComponentsNameToClassKey, type CatalogReactEntityAutocompletePickerClassKey, type CatalogReactEntityDisplayNameClassKey, type CatalogReactEntityLifecyclePickerClassKey, type CatalogReactEntityNamespacePickerClassKey, type CatalogReactEntityOwnerPickerClassKey, type CatalogReactEntityProcessingStatusPickerClassKey, type CatalogReactEntitySearchBarClassKey, type CatalogReactEntityTagPickerClassKey, type CatalogReactUserListPickerClassKey, type DefaultEntityFilters, DefaultFilters, type DefaultFiltersProps, EntityAutocompletePicker, type EntityAutocompletePickerProps, EntityDisplayName, type EntityDisplayNameProps, EntityErrorFilter, type EntityFilter, EntityKindFilter, EntityKindPicker, type EntityKindPickerProps, EntityLifecycleFilter, EntityLifecyclePicker, EntityListContext, type EntityListContextProps, EntityListProvider, type EntityListProviderProps, type EntityLoadingStatus, EntityNamespaceFilter, EntityNamespacePicker, type EntityNamespacePickerProps, EntityOrphanFilter, EntityOwnerFilter, EntityOwnerPicker, type EntityOwnerPickerProps, EntityPeekAheadPopover, type EntityPeekAheadPopoverProps, type EntityPresentationApi, EntityProcessingStatusPicker, EntityProvider, type EntityProviderProps, EntityRefLink, type EntityRefLinkProps, EntityRefLinks, type EntityRefLinksProps, type EntityRefPresentation, type EntityRefPresentationSnapshot, EntitySearchBar, type EntitySourceLocation, EntityTable, type EntityTableProps, EntityTagFilter, EntityTagPicker, type EntityTagPickerProps, EntityTextFilter, EntityTypeFilter, EntityTypePicker, type EntityTypePickerProps, EntityUserFilter, FavoriteEntity, type FavoriteEntityProps, InspectEntityDialog, MissingAnnotationEmptyState, type MissingAnnotationEmptyStateClassKey, MockEntityListContextProvider, MockStarredEntitiesApi, type StarredEntitiesApi, UnregisterEntityDialog, type UnregisterEntityDialogProps, UserListFilter, type UserListFilterKind, UserListPicker, type UserListPickerProps, catalogApiRef, columnFactories, defaultEntityPresentation, entityPresentationApiRef, entityRouteParams, entityRouteRef, getEntityRelations, getEntitySourceLocation, humanizeEntityRef, starredEntitiesApiRef, useAsyncEntity, useEntity, useEntityList, useEntityOwnership, useEntityPresentation, useEntityTypeFilter, useRelatedEntities, useStarredEntities, useStarredEntity };
975
+ export { type AllowedEntityFilters, AsyncEntityProvider, type AsyncEntityProviderProps, type BackstageOverrides, CatalogFilterLayout, type CatalogReactComponentsNameToClassKey, type CatalogReactEntityAutocompletePickerClassKey, type CatalogReactEntityDisplayNameClassKey, type CatalogReactEntityLifecyclePickerClassKey, type CatalogReactEntityNamespacePickerClassKey, type CatalogReactEntityOwnerPickerClassKey, type CatalogReactEntityProcessingStatusPickerClassKey, type CatalogReactEntitySearchBarClassKey, type CatalogReactEntityTagPickerClassKey, type CatalogReactUserListPickerClassKey, type DefaultEntityFilters, DefaultFilters, type DefaultFiltersProps, EntityAutocompletePicker, type EntityAutocompletePickerProps, EntityDisplayName, type EntityDisplayNameProps, EntityErrorFilter, type EntityFilter, EntityKindFilter, EntityKindPicker, type EntityKindPickerProps, EntityLifecycleFilter, EntityLifecyclePicker, EntityListContext, type EntityListContextProps, type EntityListPagination, EntityListProvider, type EntityListProviderProps, type EntityLoadingStatus, EntityNamespaceFilter, EntityNamespacePicker, type EntityNamespacePickerProps, EntityOrphanFilter, EntityOwnerFilter, EntityOwnerPicker, type EntityOwnerPickerProps, EntityPeekAheadPopover, type EntityPeekAheadPopoverProps, type EntityPresentationApi, EntityProcessingStatusPicker, EntityProvider, type EntityProviderProps, EntityRefLink, type EntityRefLinkProps, EntityRefLinks, type EntityRefLinksProps, type EntityRefPresentation, type EntityRefPresentationSnapshot, EntitySearchBar, type EntitySourceLocation, EntityTable, type EntityTableProps, EntityTagFilter, EntityTagPicker, type EntityTagPickerProps, EntityTextFilter, EntityTypeFilter, EntityTypePicker, type EntityTypePickerProps, EntityUserFilter, FavoriteEntity, type FavoriteEntityProps, type FixedWidthFormControlLabelClassKey, InspectEntityDialog, MissingAnnotationEmptyState, type MissingAnnotationEmptyStateClassKey, MockEntityListContextProvider, MockStarredEntitiesApi, type PaginationMode, type StarredEntitiesApi, UnregisterEntityDialog, type UnregisterEntityDialogProps, UserListFilter, type UserListFilterKind, UserListPicker, type UserListPickerProps, catalogApiRef, columnFactories, defaultEntityPresentation, entityPresentationApiRef, entityRouteParams, entityRouteRef, getEntityRelations, getEntitySourceLocation, humanizeEntityRef, starredEntitiesApiRef, useAsyncEntity, useEntity, useEntityList, useEntityOwnership, useEntityPresentation, useEntityTypeFilter, useRelatedEntities, useStarredEntities, useStarredEntity };
@@ -30,7 +30,13 @@ function MockEntityListContextProvider(props) {
30
30
  loading: value?.loading ?? false,
31
31
  queryParameters: value?.queryParameters ?? defaultValues.queryParameters,
32
32
  error: value?.error,
33
- totalItems: value?.totalItems ?? (value?.entities ?? defaultValues.entities).length
33
+ totalItems: value?.totalItems ?? (value?.entities ?? defaultValues.entities).length,
34
+ limit: value?.limit ?? 20,
35
+ offset: value?.offset,
36
+ setLimit: value?.setLimit ?? (() => {
37
+ }),
38
+ setOffset: value?.setOffset,
39
+ paginationMode: value?.paginationMode ?? "none"
34
40
  }),
35
41
  [value, defaultValues, filters, updateFilters]
36
42
  );
@@ -1 +1 @@
1
- {"version":3,"file":"providers.esm.js","sources":["../../src/testUtils/providers.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 React, {\n PropsWithChildren,\n useCallback,\n useMemo,\n useState,\n} from 'react';\nimport {\n DefaultEntityFilters,\n EntityListContext,\n EntityListContextProps,\n} from '../hooks/useEntityListProvider';\n\n/** @public */\nexport function MockEntityListContextProvider<\n T extends DefaultEntityFilters = DefaultEntityFilters,\n>(\n props: PropsWithChildren<{\n value?: Partial<EntityListContextProps<T>>;\n }>,\n) {\n const { children, value } = props;\n\n // Provides a default implementation that stores filter state, for testing components that\n // reflect filter state.\n const [filters, setFilters] = useState<T>(value?.filters ?? ({} as T));\n\n const updateFilters = useCallback(\n (update: Partial<T> | ((prevFilters: T) => Partial<T>)) => {\n setFilters(prevFilters => {\n const newFilters =\n typeof update === 'function' ? update(prevFilters) : update;\n return { ...prevFilters, ...newFilters };\n });\n },\n [],\n );\n\n // Memoize the default values since pickers have useEffect triggers on these; naively defaulting\n // below with `?? <X>` breaks referential equality on subsequent updates.\n const defaultValues = useMemo(\n () => ({\n entities: [],\n backendEntities: [],\n queryParameters: {},\n }),\n [],\n );\n\n const resolvedValue: EntityListContextProps<T> = useMemo(\n () => ({\n entities: value?.entities ?? defaultValues.entities,\n backendEntities: value?.backendEntities ?? defaultValues.backendEntities,\n updateFilters: value?.updateFilters ?? updateFilters,\n filters,\n loading: value?.loading ?? false,\n queryParameters: value?.queryParameters ?? defaultValues.queryParameters,\n error: value?.error,\n totalItems:\n value?.totalItems ?? (value?.entities ?? defaultValues.entities).length,\n }),\n [value, defaultValues, filters, updateFilters],\n );\n\n return (\n <EntityListContext.Provider value={resolvedValue}>\n {children}\n </EntityListContext.Provider>\n );\n}\n"],"names":[],"mappings":";;;AA6BO,SAAS,8BAGd,KAGA,EAAA;AACA,EAAM,MAAA,EAAE,QAAU,EAAA,KAAA,EAAU,GAAA,KAAA,CAAA;AAI5B,EAAM,MAAA,CAAC,SAAS,UAAU,CAAA,GAAI,SAAY,KAAO,EAAA,OAAA,IAAY,EAAQ,CAAA,CAAA;AAErE,EAAA,MAAM,aAAgB,GAAA,WAAA;AAAA,IACpB,CAAC,MAA0D,KAAA;AACzD,MAAA,UAAA,CAAW,CAAe,WAAA,KAAA;AACxB,QAAA,MAAM,aACJ,OAAO,MAAA,KAAW,UAAa,GAAA,MAAA,CAAO,WAAW,CAAI,GAAA,MAAA,CAAA;AACvD,QAAA,OAAO,EAAE,GAAG,WAAa,EAAA,GAAG,UAAW,EAAA,CAAA;AAAA,OACxC,CAAA,CAAA;AAAA,KACH;AAAA,IACA,EAAC;AAAA,GACH,CAAA;AAIA,EAAA,MAAM,aAAgB,GAAA,OAAA;AAAA,IACpB,OAAO;AAAA,MACL,UAAU,EAAC;AAAA,MACX,iBAAiB,EAAC;AAAA,MAClB,iBAAiB,EAAC;AAAA,KACpB,CAAA;AAAA,IACA,EAAC;AAAA,GACH,CAAA;AAEA,EAAA,MAAM,aAA2C,GAAA,OAAA;AAAA,IAC/C,OAAO;AAAA,MACL,QAAA,EAAU,KAAO,EAAA,QAAA,IAAY,aAAc,CAAA,QAAA;AAAA,MAC3C,eAAA,EAAiB,KAAO,EAAA,eAAA,IAAmB,aAAc,CAAA,eAAA;AAAA,MACzD,aAAA,EAAe,OAAO,aAAiB,IAAA,aAAA;AAAA,MACvC,OAAA;AAAA,MACA,OAAA,EAAS,OAAO,OAAW,IAAA,KAAA;AAAA,MAC3B,eAAA,EAAiB,KAAO,EAAA,eAAA,IAAmB,aAAc,CAAA,eAAA;AAAA,MACzD,OAAO,KAAO,EAAA,KAAA;AAAA,MACd,YACE,KAAO,EAAA,UAAA,IAAA,CAAe,KAAO,EAAA,QAAA,IAAY,cAAc,QAAU,EAAA,MAAA;AAAA,KACrE,CAAA;AAAA,IACA,CAAC,KAAA,EAAO,aAAe,EAAA,OAAA,EAAS,aAAa,CAAA;AAAA,GAC/C,CAAA;AAEA,EAAA,2CACG,iBAAkB,CAAA,QAAA,EAAlB,EAA2B,KAAA,EAAO,iBAChC,QACH,CAAA,CAAA;AAEJ;;;;"}
1
+ {"version":3,"file":"providers.esm.js","sources":["../../src/testUtils/providers.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 React, {\n PropsWithChildren,\n useCallback,\n useMemo,\n useState,\n} from 'react';\nimport {\n DefaultEntityFilters,\n EntityListContext,\n EntityListContextProps,\n} from '../hooks/useEntityListProvider';\n\n/** @public */\nexport function MockEntityListContextProvider<\n T extends DefaultEntityFilters = DefaultEntityFilters,\n>(\n props: PropsWithChildren<{\n value?: Partial<EntityListContextProps<T>>;\n }>,\n) {\n const { children, value } = props;\n\n // Provides a default implementation that stores filter state, for testing components that\n // reflect filter state.\n const [filters, setFilters] = useState<T>(value?.filters ?? ({} as T));\n\n const updateFilters = useCallback(\n (update: Partial<T> | ((prevFilters: T) => Partial<T>)) => {\n setFilters(prevFilters => {\n const newFilters =\n typeof update === 'function' ? update(prevFilters) : update;\n return { ...prevFilters, ...newFilters };\n });\n },\n [],\n );\n\n // Memoize the default values since pickers have useEffect triggers on these; naively defaulting\n // below with `?? <X>` breaks referential equality on subsequent updates.\n const defaultValues = useMemo(\n () => ({\n entities: [],\n backendEntities: [],\n queryParameters: {},\n }),\n [],\n );\n\n const resolvedValue: EntityListContextProps<T> = useMemo(\n () => ({\n entities: value?.entities ?? defaultValues.entities,\n backendEntities: value?.backendEntities ?? defaultValues.backendEntities,\n updateFilters: value?.updateFilters ?? updateFilters,\n filters,\n loading: value?.loading ?? false,\n queryParameters: value?.queryParameters ?? defaultValues.queryParameters,\n error: value?.error,\n totalItems:\n value?.totalItems ?? (value?.entities ?? defaultValues.entities).length,\n limit: value?.limit ?? 20,\n offset: value?.offset,\n setLimit: value?.setLimit ?? (() => {}),\n setOffset: value?.setOffset,\n paginationMode: value?.paginationMode ?? 'none',\n }),\n [value, defaultValues, filters, updateFilters],\n );\n\n return (\n <EntityListContext.Provider value={resolvedValue}>\n {children}\n </EntityListContext.Provider>\n );\n}\n"],"names":[],"mappings":";;;AA6BO,SAAS,8BAGd,KAGA,EAAA;AACA,EAAM,MAAA,EAAE,QAAU,EAAA,KAAA,EAAU,GAAA,KAAA,CAAA;AAI5B,EAAM,MAAA,CAAC,SAAS,UAAU,CAAA,GAAI,SAAY,KAAO,EAAA,OAAA,IAAY,EAAQ,CAAA,CAAA;AAErE,EAAA,MAAM,aAAgB,GAAA,WAAA;AAAA,IACpB,CAAC,MAA0D,KAAA;AACzD,MAAA,UAAA,CAAW,CAAe,WAAA,KAAA;AACxB,QAAA,MAAM,aACJ,OAAO,MAAA,KAAW,UAAa,GAAA,MAAA,CAAO,WAAW,CAAI,GAAA,MAAA,CAAA;AACvD,QAAA,OAAO,EAAE,GAAG,WAAa,EAAA,GAAG,UAAW,EAAA,CAAA;AAAA,OACxC,CAAA,CAAA;AAAA,KACH;AAAA,IACA,EAAC;AAAA,GACH,CAAA;AAIA,EAAA,MAAM,aAAgB,GAAA,OAAA;AAAA,IACpB,OAAO;AAAA,MACL,UAAU,EAAC;AAAA,MACX,iBAAiB,EAAC;AAAA,MAClB,iBAAiB,EAAC;AAAA,KACpB,CAAA;AAAA,IACA,EAAC;AAAA,GACH,CAAA;AAEA,EAAA,MAAM,aAA2C,GAAA,OAAA;AAAA,IAC/C,OAAO;AAAA,MACL,QAAA,EAAU,KAAO,EAAA,QAAA,IAAY,aAAc,CAAA,QAAA;AAAA,MAC3C,eAAA,EAAiB,KAAO,EAAA,eAAA,IAAmB,aAAc,CAAA,eAAA;AAAA,MACzD,aAAA,EAAe,OAAO,aAAiB,IAAA,aAAA;AAAA,MACvC,OAAA;AAAA,MACA,OAAA,EAAS,OAAO,OAAW,IAAA,KAAA;AAAA,MAC3B,eAAA,EAAiB,KAAO,EAAA,eAAA,IAAmB,aAAc,CAAA,eAAA;AAAA,MACzD,OAAO,KAAO,EAAA,KAAA;AAAA,MACd,YACE,KAAO,EAAA,UAAA,IAAA,CAAe,KAAO,EAAA,QAAA,IAAY,cAAc,QAAU,EAAA,MAAA;AAAA,MACnE,KAAA,EAAO,OAAO,KAAS,IAAA,EAAA;AAAA,MACvB,QAAQ,KAAO,EAAA,MAAA;AAAA,MACf,QAAA,EAAU,KAAO,EAAA,QAAA,KAAa,MAAM;AAAA,OAAC,CAAA;AAAA,MACrC,WAAW,KAAO,EAAA,SAAA;AAAA,MAClB,cAAA,EAAgB,OAAO,cAAkB,IAAA,MAAA;AAAA,KAC3C,CAAA;AAAA,IACA,CAAC,KAAA,EAAO,aAAe,EAAA,OAAA,EAAS,aAAa,CAAA;AAAA,GAC/C,CAAA;AAEA,EAAA,2CACG,iBAAkB,CAAA,QAAA,EAAlB,EAA2B,KAAA,EAAO,iBAChC,QACH,CAAA,CAAA;AAEJ;;;;"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@backstage/plugin-catalog-react",
3
- "version": "1.12.4-next.1",
3
+ "version": "1.13.0",
4
4
  "description": "A frontend library that helps other Backstage plugins interact with the catalog",
5
5
  "backstage": {
6
6
  "role": "web-library",
@@ -56,19 +56,19 @@
56
56
  "test": "backstage-cli package test"
57
57
  },
58
58
  "dependencies": {
59
- "@backstage/catalog-client": "^1.6.7-next.0",
60
- "@backstage/catalog-model": "^1.6.0",
61
- "@backstage/core-compat-api": "^0.3.0-next.1",
62
- "@backstage/core-components": "^0.14.11-next.0",
63
- "@backstage/core-plugin-api": "^1.9.3",
59
+ "@backstage/catalog-client": "^1.7.0",
60
+ "@backstage/catalog-model": "^1.7.0",
61
+ "@backstage/core-compat-api": "^0.3.0",
62
+ "@backstage/core-components": "^0.15.0",
63
+ "@backstage/core-plugin-api": "^1.9.4",
64
64
  "@backstage/errors": "^1.2.4",
65
- "@backstage/frontend-plugin-api": "^0.8.0-next.1",
66
- "@backstage/integration-react": "^1.1.30",
67
- "@backstage/plugin-catalog-common": "^1.0.26",
65
+ "@backstage/frontend-plugin-api": "^0.8.0",
66
+ "@backstage/integration-react": "^1.1.31",
67
+ "@backstage/plugin-catalog-common": "^1.1.0",
68
68
  "@backstage/plugin-permission-common": "^0.8.1",
69
- "@backstage/plugin-permission-react": "^0.4.25",
69
+ "@backstage/plugin-permission-react": "^0.4.26",
70
70
  "@backstage/types": "^1.1.1",
71
- "@backstage/version-bridge": "^1.0.8",
71
+ "@backstage/version-bridge": "^1.0.9",
72
72
  "@material-ui/core": "^4.12.2",
73
73
  "@material-ui/icons": "^4.9.1",
74
74
  "@material-ui/lab": "4.0.0-alpha.61",
@@ -83,15 +83,15 @@
83
83
  "zen-observable": "^0.10.0"
84
84
  },
85
85
  "devDependencies": {
86
- "@backstage/cli": "^0.27.1-next.1",
87
- "@backstage/core-app-api": "^1.14.2",
88
- "@backstage/frontend-test-utils": "^0.2.0-next.1",
89
- "@backstage/plugin-catalog-common": "^1.0.26",
90
- "@backstage/plugin-scaffolder-common": "^1.5.5",
91
- "@backstage/test-utils": "^1.6.0-next.0",
86
+ "@backstage/cli": "^0.27.1",
87
+ "@backstage/core-app-api": "^1.15.0",
88
+ "@backstage/frontend-test-utils": "^0.2.0",
89
+ "@backstage/plugin-catalog-common": "^1.1.0",
90
+ "@backstage/plugin-scaffolder-common": "^1.5.6",
91
+ "@backstage/test-utils": "^1.6.0",
92
92
  "@testing-library/dom": "^10.0.0",
93
93
  "@testing-library/jest-dom": "^6.0.0",
94
- "@testing-library/react": "^15.0.0",
94
+ "@testing-library/react": "^16.0.0",
95
95
  "@testing-library/user-event": "^14.0.0",
96
96
  "@types/zen-observable": "^0.8.0",
97
97
  "react-test-renderer": "^16.13.1"