mirror of
https://github.com/lensapp/lens.git
synced 2025-05-20 05:10:56 +00:00
Fix hotbar migration of workspaces (#3178)
This commit is contained in:
1 parent
b9dfd20a93
commit
51655884c7
39 files changed
+333
-446
No files matched your search
@@ -42,6 +42,11 @@ import { ExtensionInstallationStateStore } from "./components/+extensions/extens
|
||||
import { DefaultProps } from "./mui-base-theme";
|
||||
import configurePackages from "../common/configure-packages";
|
||||
import * as initializers from "./initializers";
|
||||
import { HotbarStore } from "../common/hotbar-store";
|
||||
import { WeblinkStore } from "../common/weblink-store";
|
||||
import { ExtensionsStore } from "../extensions/extensions-store";
|
||||
import { FilesystemProvisionerStore } from "../main/extension-filesystem";
|
||||
import { ThemeStore } from "./theme.store";
|
||||
|
||||
configurePackages();
|
||||
|
||||
@@ -79,7 +84,13 @@ export async function bootstrap(App: AppComponent) {
|
||||
ExtensionLoader.createInstance().init();
|
||||
ExtensionDiscovery.createInstance().init();
|
||||
|
||||
await initializers.initStores();
|
||||
UserStore.createInstance();
|
||||
await ClusterStore.createInstance().loadInitialOnRenderer();
|
||||
HotbarStore.createInstance();
|
||||
ExtensionsStore.createInstance();
|
||||
FilesystemProvisionerStore.createInstance();
|
||||
ThemeStore.createInstance();
|
||||
WeblinkStore.createInstance();
|
||||
|
||||
ExtensionInstallationStateStore.bindIpcListeners();
|
||||
HelmRepoManager.createInstance(); // initialize the manager
|
||||
|
||||
@@ -30,6 +30,7 @@ import { CatalogEntityDrawerMenu } from "./catalog-entity-drawer-menu";
|
||||
import { CatalogEntityDetailRegistry } from "../../../extensions/registries";
|
||||
import { HotbarIcon } from "../hotbar/hotbar-icon";
|
||||
import type { CatalogEntityItem } from "./catalog-entity.store";
|
||||
import { isDevelopment } from "../../../common/vars";
|
||||
|
||||
interface Props<T extends CatalogEntity> {
|
||||
item: CatalogEntityItem<T> | null | undefined;
|
||||
@@ -91,6 +92,11 @@ export class CatalogEntityDetails<T extends CatalogEntity> extends Component<Pro
|
||||
<DrawerItem name="Labels">
|
||||
{...item.getLabelBadges(this.props.hideDetails)}
|
||||
</DrawerItem>
|
||||
{isDevelopment && (
|
||||
<DrawerItem name="Id">
|
||||
{item.getId()}
|
||||
</DrawerItem>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
@@ -61,7 +61,7 @@ describe("Extensions", () => {
|
||||
ExtensionInstallationStateStore.reset();
|
||||
UserStore.resetInstance();
|
||||
|
||||
await UserStore.createInstance().load();
|
||||
UserStore.createInstance();
|
||||
|
||||
ExtensionDiscovery.resetInstance();
|
||||
ExtensionDiscovery.createInstance().uninstallExtension = jest.fn(() => Promise.resolve());
|
||||
|
||||
@@ -30,10 +30,11 @@ import type { LogTabData } from "../log-tab.store";
|
||||
import { dockerPod, deploymentPod1 } from "./pod.mock";
|
||||
import { ThemeStore } from "../../../theme.store";
|
||||
import { UserStore } from "../../../../common/user-store";
|
||||
import mockFs from "mock-fs";
|
||||
|
||||
jest.mock("electron", () => ({
|
||||
app: {
|
||||
getPath: () => "/foo",
|
||||
getPath: () => "tmp",
|
||||
},
|
||||
}));
|
||||
|
||||
@@ -71,6 +72,9 @@ const getFewPodsTabData = (): LogTabData => {
|
||||
|
||||
describe("<LogResourceSelector />", () => {
|
||||
beforeEach(() => {
|
||||
mockFs({
|
||||
"tmp": {}
|
||||
});
|
||||
UserStore.createInstance();
|
||||
ThemeStore.createInstance();
|
||||
});
|
||||
@@ -78,6 +82,7 @@ describe("<LogResourceSelector />", () => {
|
||||
afterEach(() => {
|
||||
UserStore.resetInstance();
|
||||
ThemeStore.resetInstance();
|
||||
mockFs.restore();
|
||||
});
|
||||
|
||||
it("renders w/o errors", () => {
|
||||
|
||||
@@ -26,6 +26,14 @@ import React from "react";
|
||||
import { ThemeStore } from "../../../theme.store";
|
||||
import { UserStore } from "../../../../common/user-store";
|
||||
import { Notifications } from "../../notifications";
|
||||
import mockFs from "mock-fs";
|
||||
|
||||
jest.mock("electron", () => ({
|
||||
app: {
|
||||
getPath: () => "tmp",
|
||||
setLoginItemSettings: jest.fn(),
|
||||
},
|
||||
}));
|
||||
|
||||
const mockHotbars: {[id: string]: any} = {
|
||||
"1": {
|
||||
@@ -48,6 +56,9 @@ jest.mock("../../../../common/hotbar-store", () => ({
|
||||
|
||||
describe("<HotbarRemoveCommand />", () => {
|
||||
beforeEach(() => {
|
||||
mockFs({
|
||||
"tmp": {}
|
||||
});
|
||||
UserStore.createInstance();
|
||||
ThemeStore.createInstance();
|
||||
});
|
||||
@@ -55,11 +66,12 @@ describe("<HotbarRemoveCommand />", () => {
|
||||
afterEach(() => {
|
||||
UserStore.resetInstance();
|
||||
ThemeStore.resetInstance();
|
||||
mockFs.restore();
|
||||
});
|
||||
|
||||
it("renders w/o errors", () => {
|
||||
const { container } = render(<HotbarRemoveCommand/>);
|
||||
|
||||
|
||||
expect(container).toBeInstanceOf(HTMLElement);
|
||||
});
|
||||
|
||||
@@ -73,4 +85,3 @@ describe("<HotbarRemoveCommand />", () => {
|
||||
spy.mockRestore();
|
||||
});
|
||||
});
|
||||
|
||||
@@ -33,22 +33,14 @@ const uniqueHotbarName: InputValidator = {
|
||||
|
||||
@observer
|
||||
export class HotbarAddCommand extends React.Component {
|
||||
|
||||
onSubmit(name: string) {
|
||||
onSubmit = (name: string) => {
|
||||
if (!name.trim()) {
|
||||
return;
|
||||
}
|
||||
|
||||
const hotbarStore = HotbarStore.getInstance();
|
||||
|
||||
const hotbar = hotbarStore.add({
|
||||
name
|
||||
});
|
||||
|
||||
hotbarStore.activeHotbarId = hotbar.id;
|
||||
|
||||
HotbarStore.getInstance().add({ name }, { setActive: true });
|
||||
CommandOverlay.close();
|
||||
}
|
||||
};
|
||||
|
||||
render() {
|
||||
return (
|
||||
@@ -58,10 +50,11 @@ export class HotbarAddCommand extends React.Component {
|
||||
autoFocus={true}
|
||||
theme="round-black"
|
||||
data-test-id="command-palette-hotbar-add-name"
|
||||
validators={[uniqueHotbarName]}
|
||||
onSubmit={(v) => this.onSubmit(v)}
|
||||
validators={uniqueHotbarName}
|
||||
onSubmit={this.onSubmit}
|
||||
dirty={true}
|
||||
showValidationLine={true} />
|
||||
showValidationLine={true}
|
||||
/>
|
||||
<small className="hint">
|
||||
Please provide a new hotbar name (Press "Enter" to confirm or "Escape" to cancel)
|
||||
</small>
|
||||
|
||||
@@ -27,5 +27,4 @@ export * from "./registries";
|
||||
export * from "./welcome-menu-registry";
|
||||
export * from "./workloads-overview-detail-registry";
|
||||
export * from "./catalog";
|
||||
export * from "./stores";
|
||||
export * from "./ipc";
|
||||
@@ -1,50 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) 2021 OpenLens Authors
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
import { HotbarStore } from "../../common/hotbar-store";
|
||||
import { ClusterStore } from "../../common/cluster-store";
|
||||
import { UserStore } from "../../common/user-store";
|
||||
import { ExtensionsStore } from "../../extensions/extensions-store";
|
||||
import { FilesystemProvisionerStore } from "../../main/extension-filesystem";
|
||||
|
||||
import { ThemeStore } from "../theme.store";
|
||||
import { WeblinkStore } from "../../common/weblink-store";
|
||||
|
||||
export async function initStores() {
|
||||
const userStore = UserStore.createInstance();
|
||||
const clusterStore = ClusterStore.createInstance();
|
||||
const extensionsStore = ExtensionsStore.createInstance();
|
||||
const filesystemStore = FilesystemProvisionerStore.createInstance();
|
||||
const themeStore = ThemeStore.createInstance();
|
||||
const hotbarStore = HotbarStore.createInstance();
|
||||
const weblinkStore = WeblinkStore.createInstance();
|
||||
|
||||
// preload common stores
|
||||
await Promise.all([
|
||||
userStore.load(),
|
||||
hotbarStore.load(),
|
||||
clusterStore.load(),
|
||||
extensionsStore.load(),
|
||||
filesystemStore.load(),
|
||||
themeStore.init(),
|
||||
weblinkStore.load()
|
||||
]);
|
||||
}
|
||||
+18
-50
@@ -20,9 +20,11 @@
|
||||
*/
|
||||
|
||||
import { computed, observable, reaction, makeObservable } from "mobx";
|
||||
import { autoBind, boundMethod, Singleton } from "./utils";
|
||||
import { autoBind, iter, Singleton } from "./utils";
|
||||
import { UserStore } from "../common/user-store";
|
||||
import logger from "../main/logger";
|
||||
import darkTheme from "./themes/lens-dark.json";
|
||||
import lightTheme from "./themes/lens-light.json";
|
||||
|
||||
export type ThemeId = string;
|
||||
|
||||
@@ -32,12 +34,15 @@ export enum ThemeType {
|
||||
}
|
||||
|
||||
export interface Theme {
|
||||
id: ThemeId; // filename without .json-extension
|
||||
type: ThemeType;
|
||||
name?: string;
|
||||
colors?: Record<string, string>;
|
||||
description?: string;
|
||||
author?: string;
|
||||
name: string;
|
||||
colors: Record<string, string>;
|
||||
description: string;
|
||||
author: string;
|
||||
}
|
||||
|
||||
export interface ThemeItems extends Theme {
|
||||
id: string;
|
||||
}
|
||||
|
||||
export class ThemeStore extends Singleton {
|
||||
@@ -45,16 +50,12 @@ export class ThemeStore extends Singleton {
|
||||
|
||||
// bundled themes from `themes/${themeId}.json`
|
||||
private allThemes = observable.map<string, Theme>([
|
||||
["lens-dark", { id: "lens-dark", type: ThemeType.DARK }],
|
||||
["lens-light", { id: "lens-light", type: ThemeType.LIGHT }],
|
||||
["lens-dark", { ...darkTheme, type: ThemeType.DARK }],
|
||||
["lens-light", { ...lightTheme, type: ThemeType.LIGHT }],
|
||||
]);
|
||||
|
||||
@computed get themeIds(): string[] {
|
||||
return Array.from(this.allThemes.keys());
|
||||
}
|
||||
|
||||
@computed get themes(): Theme[] {
|
||||
return Array.from(this.allThemes.values());
|
||||
@computed get themes(): ThemeItems[] {
|
||||
return Array.from(iter.map(this.allThemes, ([id, theme]) => ({ id, ...theme })));
|
||||
}
|
||||
|
||||
@computed get activeThemeId(): string {
|
||||
@@ -62,12 +63,7 @@ export class ThemeStore extends Singleton {
|
||||
}
|
||||
|
||||
@computed get activeTheme(): Theme {
|
||||
const activeTheme = this.allThemes.get(this.activeThemeId) ?? this.allThemes.get("lens-dark");
|
||||
|
||||
return {
|
||||
colors: {},
|
||||
...activeTheme,
|
||||
};
|
||||
return this.allThemes.get(this.activeThemeId) ?? this.allThemes.get("lens-dark");
|
||||
}
|
||||
|
||||
constructor() {
|
||||
@@ -77,9 +73,9 @@ export class ThemeStore extends Singleton {
|
||||
autoBind(this);
|
||||
|
||||
// auto-apply active theme
|
||||
reaction(() => this.activeThemeId, async themeId => {
|
||||
reaction(() => this.activeThemeId, themeId => {
|
||||
try {
|
||||
this.applyTheme(await this.loadTheme(themeId));
|
||||
this.applyTheme(this.getThemeById(themeId));
|
||||
} catch (err) {
|
||||
logger.error(err);
|
||||
UserStore.getInstance().resetTheme();
|
||||
@@ -89,38 +85,10 @@ export class ThemeStore extends Singleton {
|
||||
});
|
||||
}
|
||||
|
||||
async init() {
|
||||
// preload all themes
|
||||
await Promise.all(this.themeIds.map(this.loadTheme));
|
||||
}
|
||||
|
||||
getThemeById(themeId: ThemeId): Theme {
|
||||
return this.allThemes.get(themeId);
|
||||
}
|
||||
|
||||
@boundMethod
|
||||
protected async loadTheme(themeId: ThemeId): Promise<Theme> {
|
||||
try {
|
||||
const existingTheme = this.getThemeById(themeId);
|
||||
|
||||
if (existingTheme) {
|
||||
const theme = await import(
|
||||
/* webpackChunkName: "themes/[name]" */
|
||||
`./themes/${themeId}.json`
|
||||
);
|
||||
|
||||
existingTheme.author = theme.author;
|
||||
existingTheme.colors = theme.colors;
|
||||
existingTheme.description = theme.description;
|
||||
existingTheme.name = theme.name;
|
||||
}
|
||||
|
||||
return existingTheme;
|
||||
} catch (err) {
|
||||
throw new Error(`Can't load theme "${themeId}": ${err}`);
|
||||
}
|
||||
}
|
||||
|
||||
protected applyTheme(theme: Theme) {
|
||||
if (!this.styles) {
|
||||
this.styles = document.createElement("style");
|
||||
|
||||
Reference in new issue
Block a user