mirror of
https://github.com/lensapp/lens.git
synced 2025-05-20 05:10:56 +00:00
Add CatalogCategory filter to the extension API (#3718)
* Add CatalogCategory filter to the extension API. Signed-off-by: Panu Horsmalahti <phorsmalahti@mirantis.com> * Fix test. Signed-off-by: Panu Horsmalahti <phorsmalahti@mirantis.com>
This commit is contained in:
parent
e2b096fae1
commit
936927af98
@ -72,4 +72,34 @@ describe("CatalogCategoryRegistry", () => {
|
|||||||
d2();
|
d2();
|
||||||
expect(registry.items.length).toBe(0);
|
expect(registry.items.length).toBe(0);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("doesn't return items that are filtered out", () => {
|
||||||
|
const registry = new TestCatalogCategoryRegistry();
|
||||||
|
|
||||||
|
registry.add(new TestCatalogCategory());
|
||||||
|
registry.add(new TestCatalogCategory2());
|
||||||
|
|
||||||
|
expect(registry.items.length).toBe(2);
|
||||||
|
expect(registry.filteredItems.length).toBe(2);
|
||||||
|
|
||||||
|
const disposer = registry.addCatalogCategoryFilter(category => category.metadata.name === "Test Category");
|
||||||
|
|
||||||
|
expect(registry.items.length).toBe(2);
|
||||||
|
expect(registry.filteredItems.length).toBe(1);
|
||||||
|
|
||||||
|
const disposer2 = registry.addCatalogCategoryFilter(category => category.metadata.name === "foo");
|
||||||
|
|
||||||
|
expect(registry.items.length).toBe(2);
|
||||||
|
expect(registry.filteredItems.length).toBe(0);
|
||||||
|
|
||||||
|
disposer();
|
||||||
|
|
||||||
|
expect(registry.items.length).toBe(2);
|
||||||
|
expect(registry.filteredItems.length).toBe(0);
|
||||||
|
|
||||||
|
disposer2();
|
||||||
|
|
||||||
|
expect(registry.items.length).toBe(2);
|
||||||
|
expect(registry.filteredItems.length).toBe(2);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@ -20,12 +20,18 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import { action, computed, observable, makeObservable } from "mobx";
|
import { action, computed, observable, makeObservable } from "mobx";
|
||||||
import { Disposer, ExtendedMap } from "../utils";
|
import { Disposer, ExtendedMap, iter } from "../utils";
|
||||||
import { CatalogCategory, CatalogEntityData, CatalogEntityKindData } from "./catalog-entity";
|
import { CatalogCategory, CatalogEntityData, CatalogEntityKindData } from "./catalog-entity";
|
||||||
|
import { once } from "lodash";
|
||||||
|
|
||||||
|
export type CategoryFilter = (category: CatalogCategory) => any;
|
||||||
|
|
||||||
export class CatalogCategoryRegistry {
|
export class CatalogCategoryRegistry {
|
||||||
protected categories = observable.set<CatalogCategory>();
|
protected categories = observable.set<CatalogCategory>();
|
||||||
protected groupKinds = new ExtendedMap<string, ExtendedMap<string, CatalogCategory>>();
|
protected groupKinds = new ExtendedMap<string, ExtendedMap<string, CatalogCategory>>();
|
||||||
|
protected filters = observable.set<CategoryFilter>([], {
|
||||||
|
deep: false,
|
||||||
|
});
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
makeObservable(this);
|
makeObservable(this);
|
||||||
@ -47,6 +53,17 @@ export class CatalogCategoryRegistry {
|
|||||||
return Array.from(this.categories);
|
return Array.from(this.categories);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@computed get filteredItems() {
|
||||||
|
return Array.from(
|
||||||
|
iter.reduce(
|
||||||
|
this.filters,
|
||||||
|
iter.filter,
|
||||||
|
this.items,
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
getForGroupKind<T extends CatalogCategory>(group: string, kind: string): T | undefined {
|
getForGroupKind<T extends CatalogCategory>(group: string, kind: string): T | undefined {
|
||||||
return this.groupKinds.get(group)?.get(kind) as T;
|
return this.groupKinds.get(group)?.get(kind) as T;
|
||||||
}
|
}
|
||||||
@ -80,6 +97,17 @@ export class CatalogCategoryRegistry {
|
|||||||
getByName(name: string) {
|
getByName(name: string) {
|
||||||
return this.items.find(category => category.metadata?.name == name);
|
return this.items.find(category => category.metadata?.name == name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add a new filter to the set of category filters
|
||||||
|
* @param fn The function that should return a truthy value if that category should be displayed
|
||||||
|
* @returns A function to remove that filter
|
||||||
|
*/
|
||||||
|
addCatalogCategoryFilter(fn: CategoryFilter): Disposer {
|
||||||
|
this.filters.add(fn);
|
||||||
|
|
||||||
|
return once(() => void this.filters.delete(fn));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export const catalogCategoryRegistry = new CatalogCategoryRegistry();
|
export const catalogCategoryRegistry = new CatalogCategoryRegistry();
|
||||||
|
|||||||
@ -26,6 +26,7 @@ import { getExtensionPageUrl } from "./registries/page-registry";
|
|||||||
import type { CatalogEntity } from "../common/catalog";
|
import type { CatalogEntity } from "../common/catalog";
|
||||||
import type { Disposer } from "../common/utils";
|
import type { Disposer } from "../common/utils";
|
||||||
import { catalogEntityRegistry, EntityFilter } from "../renderer/api/catalog-entity-registry";
|
import { catalogEntityRegistry, EntityFilter } from "../renderer/api/catalog-entity-registry";
|
||||||
|
import { catalogCategoryRegistry, CategoryFilter } from "../renderer/api/catalog-category-registry";
|
||||||
|
|
||||||
export class LensRendererExtension extends LensExtension {
|
export class LensRendererExtension extends LensExtension {
|
||||||
globalPages: registries.PageRegistration[] = [];
|
globalPages: registries.PageRegistration[] = [];
|
||||||
@ -63,8 +64,8 @@ export class LensRendererExtension extends LensExtension {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add a filtering function for the catalog. This will be removed if the extension is disabled.
|
* Add a filtering function for the catalog entities. This will be removed if the extension is disabled.
|
||||||
* @param fn The function which should return a truthy value for those entities which should be kepted
|
* @param fn The function which should return a truthy value for those entities which should be kept.
|
||||||
* @returns A function to clean up the filter
|
* @returns A function to clean up the filter
|
||||||
*/
|
*/
|
||||||
addCatalogFilter(fn: EntityFilter): Disposer {
|
addCatalogFilter(fn: EntityFilter): Disposer {
|
||||||
@ -74,4 +75,17 @@ export class LensRendererExtension extends LensExtension {
|
|||||||
|
|
||||||
return dispose;
|
return dispose;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add a filtering function for the catalog catogries. This will be removed if the extension is disabled.
|
||||||
|
* @param fn The function which should return a truthy value for those categories which should be kept.
|
||||||
|
* @returns A function to clean up the filter
|
||||||
|
*/
|
||||||
|
addCatalogCategoryFilter(fn: CategoryFilter): Disposer {
|
||||||
|
const dispose = catalogCategoryRegistry.addCatalogCategoryFilter(fn);
|
||||||
|
|
||||||
|
this[Disposers].push(dispose);
|
||||||
|
|
||||||
|
return dispose;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -20,3 +20,4 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
export { catalogCategoryRegistry } from "../../common/catalog";
|
export { catalogCategoryRegistry } from "../../common/catalog";
|
||||||
|
export type { CategoryFilter } from "../../common/catalog";
|
||||||
|
|||||||
@ -29,6 +29,7 @@ import { Icon } from "../icon";
|
|||||||
import { StylesProvider } from "@material-ui/core";
|
import { StylesProvider } from "@material-ui/core";
|
||||||
import { cssNames } from "../../utils";
|
import { cssNames } from "../../utils";
|
||||||
import type { CatalogCategory } from "../../api/catalog-entity";
|
import type { CatalogCategory } from "../../api/catalog-entity";
|
||||||
|
import { observer } from "mobx-react";
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
activeItem: string;
|
activeItem: string;
|
||||||
@ -36,7 +37,7 @@ type Props = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
function getCategories() {
|
function getCategories() {
|
||||||
return catalogCategoryRegistry.items;
|
return catalogCategoryRegistry.filteredItems;
|
||||||
}
|
}
|
||||||
|
|
||||||
function getCategoryIcon(category: CatalogCategory) {
|
function getCategoryIcon(category: CatalogCategory) {
|
||||||
@ -53,7 +54,7 @@ function Item(props: TreeItemProps) {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function CatalogMenu(props: Props) {
|
export const CatalogMenu = observer((props: Props) => {
|
||||||
return (
|
return (
|
||||||
// Overwrite Material UI styles with injectFirst https://material-ui.com/guides/interoperability/#controlling-priority-4
|
// Overwrite Material UI styles with injectFirst https://material-ui.com/guides/interoperability/#controlling-priority-4
|
||||||
<StylesProvider injectFirst>
|
<StylesProvider injectFirst>
|
||||||
@ -88,4 +89,4 @@ export function CatalogMenu(props: Props) {
|
|||||||
</div>
|
</div>
|
||||||
</StylesProvider>
|
</StylesProvider>
|
||||||
);
|
);
|
||||||
}
|
});
|
||||||
|
|||||||
@ -90,8 +90,8 @@ export class Catalog extends React.Component<Props> {
|
|||||||
previousActiveTab.set(this.routeActiveTab);
|
previousActiveTab.set(this.routeActiveTab);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await when(() => (routeTab === "" || !!catalogCategoryRegistry.items.find(i => i.getId() === routeTab)), { timeout: 5_000 }); // we need to wait because extensions might take a while to load
|
await when(() => (routeTab === "" || !!catalogCategoryRegistry.filteredItems.find(i => i.getId() === routeTab)), { timeout: 5_000 }); // we need to wait because extensions might take a while to load
|
||||||
const item = catalogCategoryRegistry.items.find(i => i.getId() === routeTab);
|
const item = catalogCategoryRegistry.filteredItems.find(i => i.getId() === routeTab);
|
||||||
|
|
||||||
runInAction(() => {
|
runInAction(() => {
|
||||||
this.activeTab = routeTab;
|
this.activeTab = routeTab;
|
||||||
@ -103,6 +103,20 @@ export class Catalog extends React.Component<Props> {
|
|||||||
}
|
}
|
||||||
}, {fireImmediately: true}),
|
}, {fireImmediately: true}),
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
// If active category is filtered out, automatically switch to the first category
|
||||||
|
disposeOnUnmount(this, reaction(() => catalogCategoryRegistry.filteredItems, () => {
|
||||||
|
if (!catalogCategoryRegistry.filteredItems.find(item => item.getId() === this.catalogEntityStore.activeCategory.getId())) {
|
||||||
|
const item = catalogCategoryRegistry.filteredItems[0];
|
||||||
|
|
||||||
|
runInAction(() => {
|
||||||
|
if (item) {
|
||||||
|
this.activeTab = item.getId();
|
||||||
|
this.catalogEntityStore.activeCategory = item;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}));
|
||||||
}
|
}
|
||||||
addToHotbar(item: CatalogEntityItem<CatalogEntity>): void {
|
addToHotbar(item: CatalogEntityItem<CatalogEntity>): void {
|
||||||
HotbarStore.getInstance().addToHotbar(item.entity);
|
HotbarStore.getInstance().addToHotbar(item.entity);
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user