Simplify the StarredEntitiesApi interface

Signed-off-by: Dominik Henneke <dominik.henneke@sda-se.com>
This commit is contained in:
Dominik Henneke
2021-10-13 12:14:10 +02:00
parent bd924fece8
commit 1dbaaf7801
6 changed files with 46 additions and 81 deletions
+5 -11
View File
@@ -139,7 +139,7 @@ export class DefaultStarredEntitiesApi implements StarredEntitiesApi {
// (undocumented)
isStarred(entityRef: string): boolean;
// (undocumented)
starredEntitie$(): Observable<StarredEntitiesApiObservable>;
starredEntitie$(): Observable<Set<string>>;
// (undocumented)
toggleStarred(entityRef: string): Promise<void>;
}
@@ -757,16 +757,10 @@ export const rootRoute: RouteRef<undefined>;
// @public
export interface StarredEntitiesApi {
starredEntitie$(): Observable<StarredEntitiesApiObservable>;
starredEntitie$(): Observable<Set<string>>;
toggleStarred(entityRef: string): Promise<void>;
}
// @public (undocumented)
export type StarredEntitiesApiObservable = {
starredEntities: Set<string>;
isStarred: (entityRef: string) => boolean;
};
// @public
export const starredEntitiesApiRef: ApiRef<StarredEntitiesApi>;
@@ -894,10 +888,10 @@ export const UserListPicker: ({
// Warning: (ae-missing-release-tag) "useStarredEntities" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public (undocumented)
export const useStarredEntities: () => {
export function useStarredEntities(): {
starredEntities: Set<string>;
toggleStarredEntity: (entity: Entity) => void;
isStarredEntity: (entity: Entity) => boolean;
toggleStarredEntity: (entityOrRef: Entity | EntityName | string) => void;
isStarredEntity: (entityOrRef: Entity | EntityName | string) => boolean;
};
// Warnings were encountered during analysis:
@@ -85,19 +85,8 @@ describe('DefaultStarredEntitiesApi', () => {
it('should receive updates', async () => {
expect(handler).toBeCalledTimes(2);
expect(handler).toBeCalledWith({
starredEntities: new Set(),
isStarred: expect.any(Function),
});
expect(handler).toBeCalledWith({
starredEntities: new Set(['component:default/mock']),
isStarred: expect.any(Function),
});
});
it('should receive isStarred function that operates on the latest state', async () => {
expect(handler.mock.calls[0][0].isStarred(mockEntityRef)).toBe(true);
expect(handler.mock.calls[1][0].isStarred(mockEntityRef)).toBe(true);
expect(handler).toBeCalledWith(new Set());
expect(handler).toBeCalledWith(new Set(['component:default/mock']));
});
});
});
@@ -16,10 +16,7 @@
import { Observable, StorageApi } from '@backstage/core-plugin-api';
import ObservableImpl from 'zen-observable';
import {
StarredEntitiesApi,
StarredEntitiesApiObservable,
} from './StarredEntitiesApi';
import { StarredEntitiesApi } from './StarredEntitiesApi';
/**
* Default implementation of the StarredEntitiesApi that is backed by the StorageApi.
@@ -58,7 +55,7 @@ export class DefaultStarredEntitiesApi implements StarredEntitiesApi {
);
}
starredEntitie$(): Observable<StarredEntitiesApiObservable> {
starredEntitie$(): Observable<Set<string>> {
return this.observable;
}
@@ -67,29 +64,22 @@ export class DefaultStarredEntitiesApi implements StarredEntitiesApi {
}
private readonly subscribers = new Set<
ZenObservable.SubscriptionObserver<StarredEntitiesApiObservable>
ZenObservable.SubscriptionObserver<Set<string>>
>();
private readonly observable =
new ObservableImpl<StarredEntitiesApiObservable>(subscriber => {
// forward the the latest value
subscriber.next({
starredEntities: this.starredEntities,
isStarred: e => this.isStarred(e),
});
private readonly observable = new ObservableImpl<Set<string>>(subscriber => {
// forward the the latest value
subscriber.next(this.starredEntities);
this.subscribers.add(subscriber);
return () => {
this.subscribers.delete(subscriber);
};
});
this.subscribers.add(subscriber);
return () => {
this.subscribers.delete(subscriber);
};
});
private notifyChanges() {
for (const subscription of this.subscribers) {
subscription.next({
starredEntities: this.starredEntities,
isStarred: e => this.isStarred(e),
});
subscription.next(this.starredEntities);
}
}
}
@@ -25,24 +25,6 @@ export const starredEntitiesApiRef: ApiRef<StarredEntitiesApi> = createApiRef({
id: 'catalog-react.starred-entities',
});
/**
* @public
*/
export type StarredEntitiesApiObservable = {
/**
* A set of entity references that are starred
*/
starredEntities: Set<string>;
/**
* A function to check if an entity is starred.
*
* @param entityRef - an entity reference to check
* @returns true, if the entity is starred.
*/
isStarred: (entityRef: string) => boolean;
};
/**
* An API to store and retrieve starred entities
*
@@ -57,8 +39,7 @@ export interface StarredEntitiesApi {
toggleStarred(entityRef: string): Promise<void>;
/**
* Observe the state of starred entities and receive a handler
* to check the star state of an entity.
* Observe the set of starred entity references.
*/
starredEntitie$(): Observable<StarredEntitiesApiObservable>;
starredEntitie$(): Observable<Set<string>>;
}
@@ -16,7 +16,4 @@
export { DefaultStarredEntitiesApi } from './DefaultStarredEntitiesApi';
export { starredEntitiesApiRef } from './StarredEntitiesApi';
export type {
StarredEntitiesApi,
StarredEntitiesApiObservable,
} from './StarredEntitiesApi';
export type { StarredEntitiesApi } from './StarredEntitiesApi';
@@ -14,29 +14,43 @@
* limitations under the License.
*/
import { Entity, stringifyEntityRef } from '@backstage/catalog-model';
import {
Entity,
EntityName,
stringifyEntityRef,
} from '@backstage/catalog-model';
import { useApi } from '@backstage/core-plugin-api';
import { useCallback } from 'react';
import { useObservable } from 'react-use';
import { starredEntitiesApiRef } from '../apis';
export const useStarredEntities = () => {
function getEntityRef(entityOrRef: Entity | EntityName | string): string {
return typeof entityOrRef === 'string'
? entityOrRef
: stringifyEntityRef(entityOrRef);
}
export function useStarredEntities(): {
starredEntities: Set<string>;
toggleStarredEntity: (entityOrRef: Entity | EntityName | string) => void;
isStarredEntity: (entityOrRef: Entity | EntityName | string) => boolean;
} {
const starredEntitiesApi = useApi(starredEntitiesApiRef);
const { starredEntities, isStarred } = useObservable(
const starredEntities = useObservable(
starredEntitiesApi.starredEntitie$(),
{ starredEntities: new Set<string>(), isStarred: _ => false },
new Set<string>(),
);
const isStarredEntity = useCallback(
(entity: Entity) => isStarred(stringifyEntityRef(entity)),
[isStarred],
(entityOrRef: Entity | EntityName | string) =>
starredEntities.has(getEntityRef(entityOrRef)),
[starredEntities],
);
const toggleStarredEntity = useCallback(
(entity: Entity) => {
starredEntitiesApi.toggleStarred(stringifyEntityRef(entity)).then();
},
(entityOrRef: Entity | EntityName | string) =>
starredEntitiesApi.toggleStarred(getEntityRef(entityOrRef)).then(),
[starredEntitiesApi],
);
@@ -45,4 +59,4 @@ export const useStarredEntities = () => {
toggleStarredEntity,
isStarredEntity,
};
};
}