1
0
mirror of https://github.com/lensapp/lens.git synced 2025-05-20 05:10:56 +00:00

Merge remote-tracking branch 'origin/master' into mobx6-migration

# Conflicts:
#	src/main/catalog-pusher.ts
#	src/main/index.ts
#	src/renderer/api/catalog-entity-registry.ts
#	src/renderer/components/+catalog/catalog.tsx
This commit is contained in:
Roman 2021-05-20 17:38:49 +03:00
commit f648597266
8 changed files with 76 additions and 51 deletions

View File

@ -19,41 +19,15 @@
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/ */
import { autorun } from "mobx"; import { reaction, toJS } from "mobx";
import { broadcastMessage, subscribeToBroadcast, unsubscribeFromBroadcast } from "../common/ipc"; import { broadcastMessage } from "../common/ipc";
import type { CatalogEntityRegistry } from "./catalog"; import type { CatalogEntityRegistry} from "./catalog";
import "../common/catalog-entities/kubernetes-cluster"; import "../common/catalog-entities/kubernetes-cluster";
import { Disposer, disposer } from "../common/utils";
import logger from "./logger";
export class CatalogPusher { export function pushCatalogToRenderer(catalog: CatalogEntityRegistry) {
static logPrefix = `[CatalogPusher]`; return reaction(() => toJS(catalog.items, { recurseEverything: true }), (items) => {
broadcastMessage("catalog:items", items);
static init(catalog: CatalogEntityRegistry) { }, {
return new CatalogPusher(catalog).init(); fireImmediately: true,
} });
private constructor(private catalog: CatalogEntityRegistry) {
}
private init(): Disposer {
logger.info(`${CatalogPusher.logPrefix}: init`);
const dispose = disposer();
const broadcastItems = () => {
logger.info(`${CatalogPusher.logPrefix}: broadcasting entities`);
broadcastMessage("catalog:items", this.catalog.items);
};
// broadcast entities when catalog items gets updated
dispose.push(autorun(broadcastItems));
// broadcast entities from IPC-event request
const listener = subscribeToBroadcast("catalog:broadcast", broadcastItems);
dispose.push(() => unsubscribeFromBroadcast("catalog:broadcast", listener));
return dispose;
}
} }

View File

@ -45,11 +45,11 @@ import type { LensExtensionId } from "../extensions/lens-extension";
import { FilesystemProvisionerStore } from "./extension-filesystem"; import { FilesystemProvisionerStore } from "./extension-filesystem";
import { installDeveloperTools } from "./developer-tools"; import { installDeveloperTools } from "./developer-tools";
import { LensProtocolRouterMain } from "./protocol-handler"; import { LensProtocolRouterMain } from "./protocol-handler";
import { getAppVersion, getAppVersionFromProxyServer } from "../common/utils"; import { disposer, getAppVersion, getAppVersionFromProxyServer } from "../common/utils";
import { bindBroadcastHandlers } from "../common/ipc"; import { bindBroadcastHandlers } from "../common/ipc";
import { startUpdateChecking } from "./app-updater"; import { startUpdateChecking } from "./app-updater";
import { IpcRendererNavigationEvents } from "../renderer/navigation/events"; import { IpcRendererNavigationEvents } from "../renderer/navigation/events";
import { CatalogPusher } from "./catalog-pusher"; import { pushCatalogToRenderer } from "./catalog-pusher";
import { catalogEntityRegistry } from "./catalog"; import { catalogEntityRegistry } from "./catalog";
import { HotbarStore } from "../common/hotbar-store"; import { HotbarStore } from "../common/hotbar-store";
import { HelmRepoManager } from "./helm/helm-repo-manager"; import { HelmRepoManager } from "./helm/helm-repo-manager";
@ -58,6 +58,7 @@ import { handleWsUpgrade } from "./proxy/ws-upgrade";
import configurePackages from "../common/configure-packages"; import configurePackages from "../common/configure-packages";
const workingDir = path.join(app.getPath("appData"), appName); const workingDir = path.join(app.getPath("appData"), appName);
const cleanup = disposer();
app.setName(appName); app.setName(appName);
@ -144,6 +145,7 @@ app.on("ready", async () => {
const lensProxy = LensProxy.createInstance(handleWsUpgrade); const lensProxy = LensProxy.createInstance(handleWsUpgrade);
ClusterManager.createInstance(); ClusterManager.createInstance();
KubeconfigSyncManager.createInstance();
try { try {
logger.info("🔌 Starting LensProxy"); logger.info("🔌 Starting LensProxy");
@ -188,8 +190,8 @@ app.on("ready", async () => {
} }
ipcMain.on(IpcRendererNavigationEvents.LOADED, () => { ipcMain.on(IpcRendererNavigationEvents.LOADED, () => {
KubeconfigSyncManager.createInstance().startSync(); cleanup.push(pushCatalogToRenderer(catalogEntityRegistry));
CatalogPusher.init(catalogEntityRegistry); KubeconfigSyncManager.getInstance().startSync();
startUpdateChecking(); startUpdateChecking();
LensProtocolRouterMain.getInstance().rendererLoaded = true; LensProtocolRouterMain.getInstance().rendererLoaded = true;
}); });
@ -249,6 +251,7 @@ app.on("will-quit", (event) => {
appEventBus.emit({name: "app", action: "close"}); appEventBus.emit({name: "app", action: "close"});
ClusterManager.getInstance(false)?.stop(); // close cluster connections ClusterManager.getInstance(false)?.stop(); // close cluster connections
KubeconfigSyncManager.getInstance(false)?.stopSync(); KubeconfigSyncManager.getInstance(false)?.stopSync();
cleanup();
if (blockQuit) { if (blockQuit) {
event.preventDefault(); // prevent app's default shutdown (e.g. required for telemetry, etc.) event.preventDefault(); // prevent app's default shutdown (e.g. required for telemetry, etc.)

View File

@ -20,7 +20,7 @@
*/ */
import { computed, observable, makeObservable } from "mobx"; import { computed, observable, makeObservable } from "mobx";
import { broadcastMessage, subscribeToBroadcast } from "../../common/ipc"; import { subscribeToBroadcast } from "../../common/ipc";
import { CatalogCategory, CatalogEntity, CatalogEntityData, catalogCategoryRegistry, CatalogCategoryRegistry, CatalogEntityKindData } from "../../common/catalog"; import { CatalogCategory, CatalogEntity, CatalogEntityData, catalogCategoryRegistry, CatalogCategoryRegistry, CatalogEntityKindData } from "../../common/catalog";
import "../../common/catalog-entities"; import "../../common/catalog-entities";
import { iter } from "../utils"; import { iter } from "../utils";
@ -37,7 +37,6 @@ export class CatalogEntityRegistry {
subscribeToBroadcast("catalog:items", (ev, items: (CatalogEntityData & CatalogEntityKindData)[]) => { subscribeToBroadcast("catalog:items", (ev, items: (CatalogEntityData & CatalogEntityKindData)[]) => {
this.rawItems.replace(items); this.rawItems.replace(items);
}); });
broadcastMessage("catalog:broadcast");
} }
set activeEntity(entity: CatalogEntity) { set activeEntity(entity: CatalogEntity) {

View File

@ -22,8 +22,12 @@
import type { RouteProps } from "react-router"; import type { RouteProps } from "react-router";
import { buildURL } from "../../../common/utils/buildUrl"; import { buildURL } from "../../../common/utils/buildUrl";
export interface ICatalogViewRouteParam {
group?: string;
kind?: string;
}
export const catalogRoute: RouteProps = { export const catalogRoute: RouteProps = {
path: "/catalog" path: "/catalog/:group?/:kind?"
}; };
export const catalogURL = buildURL(catalogRoute.path); export const catalogURL = buildURL<ICatalogViewRouteParam>(catalogRoute.path);

View File

@ -23,7 +23,7 @@ import "./catalog.scss";
import React from "react"; import React from "react";
import { disposeOnUnmount, observer } from "mobx-react"; import { disposeOnUnmount, observer } from "mobx-react";
import { ItemListLayout } from "../item-object-list"; import { ItemListLayout } from "../item-object-list";
import { computed, makeObservable, observable, reaction } from "mobx"; import { computed, makeObservable, observable, reaction, when } from "mobx";
import { CatalogEntityItem, CatalogEntityStore } from "./catalog-entity.store"; import { CatalogEntityItem, CatalogEntityStore } from "./catalog-entity.store";
import { navigate } from "../../navigation"; import { navigate } from "../../navigation";
import { kebabCase } from "lodash"; import { kebabCase } from "lodash";
@ -37,6 +37,9 @@ import { ConfirmDialog } from "../confirm-dialog";
import { Tab, Tabs } from "../tabs"; import { Tab, Tabs } from "../tabs";
import { catalogCategoryRegistry } from "../../../common/catalog"; import { catalogCategoryRegistry } from "../../../common/catalog";
import { CatalogAddButton } from "./catalog-add-button"; import { CatalogAddButton } from "./catalog-add-button";
import type { RouteComponentProps } from "react-router";
import type { ICatalogViewRouteParam } from "./catalog.route";
import { Notifications } from "../notifications";
enum sortBy { enum sortBy {
name = "name", name = "name",
@ -44,8 +47,16 @@ enum sortBy {
status = "status" status = "status"
} }
interface Props extends RouteComponentProps<ICatalogViewRouteParam> {
}
@observer @observer
export class Catalog extends React.Component { export class Catalog extends React.Component<Props> {
constructor(props: Props) {
super(props);
makeObservable(this);
}
private catalogEntityStore = new CatalogEntityStore(); private catalogEntityStore = new CatalogEntityStore();
private contextMenu: CatalogEntityContextMenuContext = { private contextMenu: CatalogEntityContextMenuContext = {
@ -67,9 +78,14 @@ export class Catalog extends React.Component {
return this.catalogEntityStore.getEntities(this.activeCategory); return this.catalogEntityStore.getEntities(this.activeCategory);
} }
constructor(props: {}) { get routeActiveTab(): string | undefined {
super(props); const { group, kind } = this.props.match.params ?? {};
makeObservable(this);
if (group && kind) {
return `${group}/${kind}`;
}
return undefined;
} }
componentDidMount() { componentDidMount() {
@ -77,7 +93,18 @@ export class Catalog extends React.Component {
// autofill catalog entities into store // autofill catalog entities into store
reaction(() => this.items, items => this.catalogEntityStore.loadItems(items), { reaction(() => this.items, items => this.catalogEntityStore.loadItems(items), {
fireImmediately: true, fireImmediately: true,
}) }),
when(() => catalogCategoryRegistry.items.length > 0, () => {
const item = catalogCategoryRegistry.items.find(i => i.getId() === this.routeActiveTab);
if (item || this.routeActiveTab === undefined) {
this.activeTab = this.routeActiveTab;
this.catalogEntityStore.activeCategory = item;
} else {
Notifications.error(<p>Unknown category: {this.routeActiveTab}</p>);
}
}),
]); ]);
} }

View File

@ -93,6 +93,10 @@ export const HotbarIcon = observer(({menuItems = [], ...props}: Props) => {
}; };
const getIconString = () => { const getIconString = () => {
if (!title) {
return "??";
}
const [rawFirst, rawSecond, rawThird] = getNameParts(title); const [rawFirst, rawSecond, rawThird] = getNameParts(title);
const splitter = new GraphemeSplitter(); const splitter = new GraphemeSplitter();
const first = splitter.iterateGraphemes(rawFirst); const first = splitter.iterateGraphemes(rawFirst);
@ -108,7 +112,7 @@ export const HotbarIcon = observer(({menuItems = [], ...props}: Props) => {
return ( return (
<div className={cssNames("HotbarIcon flex inline", className, { disabled })}> <div className={cssNames("HotbarIcon flex inline", className, { disabled })}>
<MaterialTooltip title={`${title} (${source})`} placement="right"> <MaterialTooltip title={`${title || "unknown"} (${source || "unknown"})`} placement="right">
<div id={id}> <div id={id}>
<Avatar <Avatar
{...rest} {...rest}

View File

@ -28,7 +28,7 @@ import { HotbarEntityIcon } from "./hotbar-entity-icon";
import { cssNames, IClassName } from "../../utils"; import { cssNames, IClassName } from "../../utils";
import { catalogEntityRegistry } from "../../api/catalog-entity-registry"; import { catalogEntityRegistry } from "../../api/catalog-entity-registry";
import { defaultHotbarCells, HotbarItem, HotbarStore } from "../../../common/hotbar-store"; import { defaultHotbarCells, HotbarItem, HotbarStore } from "../../../common/hotbar-store";
import { CatalogEntity, catalogEntityRunContext } from "../../api/catalog-entity"; import { CatalogEntity, CatalogEntityContextMenu, catalogEntityRunContext } from "../../api/catalog-entity";
import { DragDropContext, Draggable, Droppable, DropResult } from "react-beautiful-dnd"; import { DragDropContext, Draggable, Droppable, DropResult } from "react-beautiful-dnd";
import { HotbarSelector } from "./hotbar-selector"; import { HotbarSelector } from "./hotbar-selector";
import { HotbarCell } from "./hotbar-cell"; import { HotbarCell } from "./hotbar-cell";
@ -111,6 +111,12 @@ export class HotbarMenu extends React.Component<Props> {
renderGrid() { renderGrid() {
return this.items.map((item, index) => { return this.items.map((item, index) => {
const entity = this.getEntity(item); const entity = this.getEntity(item);
const disabledMenuItems: CatalogEntityContextMenu[] = [
{
title: "Unpin from Hotbar",
onClick: () => this.removeItem(item.entity.uid)
}
];
return ( return (
<Droppable droppableId={`${index}`} key={index}> <Droppable droppableId={`${index}`} key={index}>
@ -157,6 +163,7 @@ export class HotbarMenu extends React.Component<Props> {
uid={item.entity.uid} uid={item.entity.uid}
title={item.entity.name} title={item.entity.name}
source={item.entity.source} source={item.entity.source}
menuItems={disabledMenuItems}
disabled disabled
/> />
)} )}

View File

@ -43,6 +43,13 @@ export function bindProtocolAddRouteHandlers() {
.addInternalHandler("/landing", () => { .addInternalHandler("/landing", () => {
navigate(catalogURL()); navigate(catalogURL());
}) })
.addInternalHandler("/landing/view/:group/:kind", ({ pathname: { group, kind } }) => {
navigate(catalogURL({
params: {
group, kind
}
}));
})
.addInternalHandler("/cluster", () => { .addInternalHandler("/cluster", () => {
navigate(addClusterURL()); navigate(addClusterURL());
}) })