@backstage/plugin-catalog-react 0.0.0-nightly-20219132255 → 0.0.0-nightly-202191822546

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,14 +1,25 @@
1
1
  # @backstage/plugin-catalog-react
2
2
 
3
- ## 0.0.0-nightly-20219132255
3
+ ## 0.6.0
4
+
5
+ ### Minor Changes
6
+
7
+ - 82fbda923e: Introduce a new `StarredEntitiesApi` that is used in the `useStarredEntities` hook.
8
+ The `@backstage/plugin-catalog` installs a default implementation that is backed by the `StorageApi`, but one can also override the `starredEntitiesApiRef`.
9
+
10
+ This change also updates the storage format from a custom string to an entity reference and moves the location in the local storage.
11
+ A migration will convert the previously starred entities to the location on the first load of Backstage.
4
12
 
5
13
  ### Patch Changes
6
14
 
15
+ - 0366c9b667: Introduce a `useStarredEntity` hook to check if a single entity is starred.
16
+ It provides a more efficient implementation compared to the `useStarredEntities` hook, because the rendering is only triggered if the selected entity is starred, not if _any_ entity is starred.
7
17
  - 4aca84f86b: Support `material-ui` overrides in plugin-catalog-react components
8
18
  - b03b9f19e0: added sorting in entity `Name` column by `metadata.title` if present
9
19
  - Updated dependencies
10
- - @backstage/core-app-api@0.0.0-nightly-20219132255
11
- - @backstage/core-components@0.0.0-nightly-20219132255
20
+ - @backstage/integration@0.6.8
21
+ - @backstage/core-app-api@0.1.17
22
+ - @backstage/core-components@0.7.0
12
23
 
13
24
  ## 0.5.2
14
25
 
package/dist/index.cjs.js CHANGED
@@ -4,13 +4,14 @@ Object.defineProperty(exports, '__esModule', { value: true });
4
4
 
5
5
  var catalogClient = require('@backstage/catalog-client');
6
6
  var corePluginApi = require('@backstage/core-plugin-api');
7
+ var ObservableImpl = require('zen-observable');
8
+ var catalogModel = require('@backstage/catalog-model');
9
+ var lodash = require('lodash');
7
10
  var React = require('react');
8
11
  var lab = require('@material-ui/lab');
9
12
  var versionBridge = require('@backstage/version-bridge');
10
13
  var reactRouter = require('react-router');
11
14
  var reactUse = require('react-use');
12
- var catalogModel = require('@backstage/catalog-model');
13
- var lodash = require('lodash');
14
15
  var qs = require('qs');
15
16
  var coreComponents = require('@backstage/core-components');
16
17
  var core = require('@material-ui/core');
@@ -21,13 +22,14 @@ var ExpandMoreIcon = require('@material-ui/icons/ExpandMore');
21
22
  var Clear = require('@material-ui/icons/Clear');
22
23
  var Search = require('@material-ui/icons/Search');
23
24
  var capitalize = require('lodash/capitalize');
24
- var StarBorder = require('@material-ui/icons/StarBorder');
25
25
  var Star = require('@material-ui/icons/Star');
26
+ var StarBorder = require('@material-ui/icons/StarBorder');
26
27
  var Alert = require('@material-ui/lab/Alert');
27
28
  var SettingsIcon = require('@material-ui/icons/Settings');
28
29
 
29
30
  function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
30
31
 
32
+ var ObservableImpl__default = /*#__PURE__*/_interopDefaultLegacy(ObservableImpl);
31
33
  var React__default = /*#__PURE__*/_interopDefaultLegacy(React);
32
34
  var qs__default = /*#__PURE__*/_interopDefaultLegacy(qs);
33
35
  var jwtDecoder__default = /*#__PURE__*/_interopDefaultLegacy(jwtDecoder);
@@ -37,8 +39,8 @@ var ExpandMoreIcon__default = /*#__PURE__*/_interopDefaultLegacy(ExpandMoreIcon)
37
39
  var Clear__default = /*#__PURE__*/_interopDefaultLegacy(Clear);
38
40
  var Search__default = /*#__PURE__*/_interopDefaultLegacy(Search);
39
41
  var capitalize__default = /*#__PURE__*/_interopDefaultLegacy(capitalize);
40
- var StarBorder__default = /*#__PURE__*/_interopDefaultLegacy(StarBorder);
41
42
  var Star__default = /*#__PURE__*/_interopDefaultLegacy(Star);
43
+ var StarBorder__default = /*#__PURE__*/_interopDefaultLegacy(StarBorder);
42
44
  var Alert__default = /*#__PURE__*/_interopDefaultLegacy(Alert);
43
45
  var SettingsIcon__default = /*#__PURE__*/_interopDefaultLegacy(SettingsIcon);
44
46
 
@@ -46,6 +48,69 @@ const catalogApiRef = corePluginApi.createApiRef({
46
48
  id: "plugin.catalog.service"
47
49
  });
48
50
 
51
+ async function performMigrationToTheNewBucket({
52
+ storageApi
53
+ }) {
54
+ var _a;
55
+ const source = storageApi.forBucket("settings");
56
+ const target = storageApi.forBucket("starredEntities");
57
+ const oldStarredEntities = source.get("starredEntities");
58
+ if (!lodash.isArray(oldStarredEntities)) {
59
+ return;
60
+ }
61
+ const targetEntities = new Set((_a = target.get("entityRefs")) != null ? _a : []);
62
+ oldStarredEntities.filter(lodash.isString).map((old) => old.split(":")).filter((split) => split.length === 4 && split[0] === "entity").map(([_, kind, namespace, name]) => catalogModel.stringifyEntityRef({kind, namespace, name})).forEach((e) => targetEntities.add(e));
63
+ await target.set("entityRefs", Array.from(targetEntities));
64
+ await source.remove("starredEntities");
65
+ }
66
+
67
+ class DefaultStarredEntitiesApi {
68
+ constructor(opts) {
69
+ this.subscribers = new Set();
70
+ this.observable = new ObservableImpl__default['default']((subscriber) => {
71
+ subscriber.next(this.starredEntities);
72
+ this.subscribers.add(subscriber);
73
+ return () => {
74
+ this.subscribers.delete(subscriber);
75
+ };
76
+ });
77
+ var _a;
78
+ performMigrationToTheNewBucket(opts).then();
79
+ this.settingsStore = opts.storageApi.forBucket("starredEntities");
80
+ this.starredEntities = new Set((_a = this.settingsStore.get("entityRefs")) != null ? _a : []);
81
+ this.settingsStore.observe$("entityRefs").subscribe({
82
+ next: (next) => {
83
+ var _a2;
84
+ this.starredEntities = new Set((_a2 = next.newValue) != null ? _a2 : []);
85
+ this.notifyChanges();
86
+ }
87
+ });
88
+ }
89
+ async toggleStarred(entityRef) {
90
+ if (this.starredEntities.has(entityRef)) {
91
+ this.starredEntities.delete(entityRef);
92
+ } else {
93
+ this.starredEntities.add(entityRef);
94
+ }
95
+ await this.settingsStore.set("entityRefs", Array.from(this.starredEntities));
96
+ }
97
+ starredEntitie$() {
98
+ return this.observable;
99
+ }
100
+ isStarred(entityRef) {
101
+ return this.starredEntities.has(entityRef);
102
+ }
103
+ notifyChanges() {
104
+ for (const subscription of this.subscribers) {
105
+ subscription.next(this.starredEntities);
106
+ }
107
+ }
108
+ }
109
+
110
+ const starredEntitiesApiRef = corePluginApi.createApiRef({
111
+ id: "catalog-react.starred-entities"
112
+ });
113
+
49
114
  const NoIcon = () => null;
50
115
  const rootRoute = corePluginApi.createRouteRef({
51
116
  icon: NoIcon,
@@ -598,43 +663,43 @@ function useRelatedEntities(entity, {type, kind}) {
598
663
  };
599
664
  }
600
665
 
601
- const buildEntityKey = (component) => {
602
- var _a;
603
- return `entity:${component.kind}:${(_a = component.metadata.namespace) != null ? _a : "default"}:${component.metadata.name}`;
604
- };
605
- const useStarredEntities = () => {
606
- var _a;
607
- const storageApi = corePluginApi.useApi(corePluginApi.storageApiRef);
608
- const settingsStore = storageApi.forBucket("settings");
609
- const rawStarredEntityKeys = (_a = settingsStore.get("starredEntities")) != null ? _a : [];
610
- const [starredEntities, setStarredEntities] = React.useState(new Set(rawStarredEntityKeys));
611
- const observedItems = reactUse.useObservable(settingsStore.observe$("starredEntities"));
612
- React.useEffect(() => {
613
- var _a2;
614
- if (observedItems == null ? void 0 : observedItems.newValue) {
615
- const currentValue = (_a2 = observedItems == null ? void 0 : observedItems.newValue) != null ? _a2 : [];
616
- setStarredEntities(new Set(currentValue));
617
- }
618
- }, [observedItems == null ? void 0 : observedItems.newValue]);
619
- const toggleStarredEntity = React.useCallback((entity) => {
620
- const entityKey = buildEntityKey(entity);
621
- if (starredEntities.has(entityKey)) {
622
- starredEntities.delete(entityKey);
623
- } else {
624
- starredEntities.add(entityKey);
625
- }
626
- settingsStore.set("starredEntities", Array.from(starredEntities));
627
- }, [starredEntities, settingsStore]);
628
- const isStarredEntity = React.useCallback((entity) => {
629
- const entityKey = buildEntityKey(entity);
630
- return starredEntities.has(entityKey);
631
- }, [starredEntities]);
666
+ function getEntityRef$1(entityOrRef) {
667
+ return typeof entityOrRef === "string" ? entityOrRef : catalogModel.stringifyEntityRef(entityOrRef);
668
+ }
669
+ function useStarredEntities() {
670
+ const starredEntitiesApi = corePluginApi.useApi(starredEntitiesApiRef);
671
+ const starredEntities = reactUse.useObservable(starredEntitiesApi.starredEntitie$(), new Set());
672
+ const isStarredEntity = React.useCallback((entityOrRef) => starredEntities.has(getEntityRef$1(entityOrRef)), [starredEntities]);
673
+ const toggleStarredEntity = React.useCallback((entityOrRef) => starredEntitiesApi.toggleStarred(getEntityRef$1(entityOrRef)).then(), [starredEntitiesApi]);
632
674
  return {
633
675
  starredEntities,
634
676
  toggleStarredEntity,
635
677
  isStarredEntity
636
678
  };
637
- };
679
+ }
680
+
681
+ function getEntityRef(entityOrRef) {
682
+ return typeof entityOrRef === "string" ? entityOrRef : catalogModel.stringifyEntityRef(entityOrRef);
683
+ }
684
+ function useStarredEntity(entityOrRef) {
685
+ const starredEntitiesApi = corePluginApi.useApi(starredEntitiesApiRef);
686
+ const [isStarredEntity, setIsStarredEntity] = React.useState(false);
687
+ React.useEffect(() => {
688
+ const subscription = starredEntitiesApi.starredEntitie$().subscribe({
689
+ next(starredEntities) {
690
+ setIsStarredEntity(starredEntities.has(getEntityRef(entityOrRef)));
691
+ }
692
+ });
693
+ return () => {
694
+ subscription.unsubscribe();
695
+ };
696
+ }, [entityOrRef, starredEntitiesApi]);
697
+ const toggleStarredEntity = React.useCallback(() => starredEntitiesApi.toggleStarred(getEntityRef(entityOrRef)).then(), [entityOrRef, starredEntitiesApi]);
698
+ return {
699
+ toggleStarredEntity,
700
+ isStarredEntity
701
+ };
702
+ }
638
703
 
639
704
  function extendUserId(id) {
640
705
  try {
@@ -1159,15 +1224,14 @@ const YellowStar = core.withStyles({
1159
1224
  const favoriteEntityTooltip = (isStarred) => isStarred ? "Remove from favorites" : "Add to favorites";
1160
1225
  const favoriteEntityIcon = (isStarred) => isStarred ? /* @__PURE__ */ React__default['default'].createElement(YellowStar, null) : /* @__PURE__ */ React__default['default'].createElement(StarBorder__default['default'], null);
1161
1226
  const FavoriteEntity = (props) => {
1162
- const {toggleStarredEntity, isStarredEntity} = useStarredEntities();
1163
- const isStarred = isStarredEntity(props.entity);
1227
+ const {toggleStarredEntity, isStarredEntity} = useStarredEntity(props.entity);
1164
1228
  return /* @__PURE__ */ React__default['default'].createElement(core.IconButton, {
1165
1229
  color: "inherit",
1166
1230
  ...props,
1167
- onClick: () => toggleStarredEntity(props.entity)
1231
+ onClick: () => toggleStarredEntity()
1168
1232
  }, /* @__PURE__ */ React__default['default'].createElement(core.Tooltip, {
1169
- title: favoriteEntityTooltip(isStarred)
1170
- }, favoriteEntityIcon(isStarred)));
1233
+ title: favoriteEntityTooltip(isStarredEntity)
1234
+ }, favoriteEntityIcon(isStarredEntity)));
1171
1235
  };
1172
1236
 
1173
1237
  function useUnregisterEntityDialogState(entity) {
@@ -1518,6 +1582,7 @@ Object.defineProperty(exports, 'CATALOG_FILTER_EXISTS', {
1518
1582
  }
1519
1583
  });
1520
1584
  exports.AsyncEntityProvider = AsyncEntityProvider;
1585
+ exports.DefaultStarredEntitiesApi = DefaultStarredEntitiesApi;
1521
1586
  exports.EntityContext = EntityContext;
1522
1587
  exports.EntityKindFilter = EntityKindFilter;
1523
1588
  exports.EntityKindPicker = EntityKindPicker;
@@ -1558,6 +1623,7 @@ exports.isOwnerOf = isOwnerOf;
1558
1623
  exports.reduceCatalogFilters = reduceCatalogFilters;
1559
1624
  exports.reduceEntityFilters = reduceEntityFilters;
1560
1625
  exports.rootRoute = rootRoute;
1626
+ exports.starredEntitiesApiRef = starredEntitiesApiRef;
1561
1627
  exports.useEntity = useEntity;
1562
1628
  exports.useEntityCompoundName = useEntityCompoundName;
1563
1629
  exports.useEntityFromUrl = useEntityFromUrl;
@@ -1568,4 +1634,5 @@ exports.useEntityTypeFilter = useEntityTypeFilter;
1568
1634
  exports.useOwnUser = useOwnUser;
1569
1635
  exports.useRelatedEntities = useRelatedEntities;
1570
1636
  exports.useStarredEntities = useStarredEntities;
1637
+ exports.useStarredEntity = useStarredEntity;
1571
1638
  //# sourceMappingURL=index.cjs.js.map