mirror of
https://github.com/lensapp/lens.git
synced 2025-05-20 05:10:56 +00:00
auto-refresh menu, no-clusters page + navigation fixes
Signed-off-by: Roman <ixrock@gmail.com>
This commit is contained in:
parent
408f64c184
commit
fe06643a8e
@ -77,10 +77,6 @@ export class ClusterStore extends BaseStore<ClusterStoreModel> {
|
|||||||
@observable removedClusters = observable.map<ClusterId, Cluster>();
|
@observable removedClusters = observable.map<ClusterId, Cluster>();
|
||||||
@observable clusters = observable.map<ClusterId, Cluster>();
|
@observable clusters = observable.map<ClusterId, Cluster>();
|
||||||
|
|
||||||
@computed get activeCluster(): Cluster | null {
|
|
||||||
return this.getById(this.activeClusterId);
|
|
||||||
}
|
|
||||||
|
|
||||||
@computed get clustersList(): Cluster[] {
|
@computed get clustersList(): Cluster[] {
|
||||||
return Array.from(this.clusters.values());
|
return Array.from(this.clusters.values());
|
||||||
}
|
}
|
||||||
|
|||||||
@ -6,7 +6,7 @@ import { bundledKubectl, Kubectl } from "./kubectl"
|
|||||||
import logger from "./logger"
|
import logger from "./logger"
|
||||||
|
|
||||||
export interface KubeAuthProxyResponse {
|
export interface KubeAuthProxyResponse {
|
||||||
data: string; // stream=stdout
|
data: string;
|
||||||
error?: boolean; // stream=stderr
|
error?: boolean; // stream=stderr
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1,5 +1,6 @@
|
|||||||
import type { WindowManager } from "./window-manager";
|
import type { WindowManager } from "./window-manager";
|
||||||
import { app, BrowserWindow, dialog, Menu, MenuItem, MenuItemConstructorOptions, shell, webContents } from "electron"
|
import { app, BrowserWindow, dialog, Menu, MenuItem, MenuItemConstructorOptions, shell, webContents } from "electron"
|
||||||
|
import { autorun } from "mobx";
|
||||||
import { broadcastIpc } from "../common/ipc";
|
import { broadcastIpc } from "../common/ipc";
|
||||||
import { appName, isMac, issuesTrackerUrl, isWindows, slackUrl } from "../common/vars";
|
import { appName, isMac, issuesTrackerUrl, isWindows, slackUrl } from "../common/vars";
|
||||||
import { clusterStore } from "../common/cluster-store";
|
import { clusterStore } from "../common/cluster-store";
|
||||||
@ -7,20 +8,26 @@ import { addClusterURL } from "../renderer/components/+add-cluster/add-cluster.r
|
|||||||
import { preferencesURL } from "../renderer/components/+preferences/preferences.route";
|
import { preferencesURL } from "../renderer/components/+preferences/preferences.route";
|
||||||
import { whatsNewURL } from "../renderer/components/+whats-new/whats-new.route";
|
import { whatsNewURL } from "../renderer/components/+whats-new/whats-new.route";
|
||||||
import { clusterSettingsURL } from "../renderer/components/+cluster-settings/cluster-settings.route";
|
import { clusterSettingsURL } from "../renderer/components/+cluster-settings/cluster-settings.route";
|
||||||
|
import logger from "./logger";
|
||||||
|
|
||||||
export function initMenu(windowManager: WindowManager) {
|
export function initMenu(windowManager: WindowManager) {
|
||||||
const menuItems: MenuItemConstructorOptions[] = [];
|
autorun(() => {
|
||||||
|
logger.debug(`[MENU]: refreshing menu, cluster=${clusterStore.activeClusterId}`);
|
||||||
|
buildMenu(windowManager);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function buildMenu(windowManager: WindowManager) {
|
||||||
|
const hasClusters = clusterStore.hasClusters();
|
||||||
|
const activeClusterId = clusterStore.activeClusterId;
|
||||||
|
const clusterView = windowManager.getClusterView(activeClusterId);
|
||||||
|
|
||||||
function navigate(url: string) {
|
function navigate(url: string) {
|
||||||
const activeClusterId = clusterStore.activeClusterId;
|
broadcastIpc({
|
||||||
const view = windowManager.getClusterView(activeClusterId);
|
channel: "menu:navigate",
|
||||||
if (view) {
|
webContentId: clusterView ? clusterView.id : undefined /*no-clusters*/,
|
||||||
broadcastIpc({
|
args: [url],
|
||||||
channel: "menu:navigate",
|
});
|
||||||
webContentId: view.id,
|
|
||||||
args: [url],
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function macOnly(menuItems: MenuItemConstructorOptions[]): MenuItemConstructorOptions[] {
|
function macOnly(menuItems: MenuItemConstructorOptions[]): MenuItemConstructorOptions[] {
|
||||||
@ -28,8 +35,7 @@ export function initMenu(windowManager: WindowManager) {
|
|||||||
return menuItems;
|
return menuItems;
|
||||||
}
|
}
|
||||||
|
|
||||||
// "File" submenu
|
const fileMenu: MenuItemConstructorOptions = {
|
||||||
menuItems.push({
|
|
||||||
label: isMac ? app.getName() : "File",
|
label: isMac ? app.getName() : "File",
|
||||||
submenu: [
|
submenu: [
|
||||||
{
|
{
|
||||||
@ -38,12 +44,12 @@ export function initMenu(windowManager: WindowManager) {
|
|||||||
navigate(addClusterURL())
|
navigate(addClusterURL())
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
...(hasClusters ? [{
|
||||||
label: 'Cluster Settings',
|
label: 'Cluster Settings',
|
||||||
click() {
|
click() {
|
||||||
navigate(clusterSettingsURL())
|
navigate(clusterSettingsURL())
|
||||||
}
|
}
|
||||||
},
|
}] : []),
|
||||||
{ type: 'separator' },
|
{ type: 'separator' },
|
||||||
{
|
{
|
||||||
label: 'Preferences',
|
label: 'Preferences',
|
||||||
@ -62,10 +68,9 @@ export function initMenu(windowManager: WindowManager) {
|
|||||||
{ type: 'separator' },
|
{ type: 'separator' },
|
||||||
{ role: 'quit' }
|
{ role: 'quit' }
|
||||||
]
|
]
|
||||||
});
|
};
|
||||||
|
|
||||||
// "Edit" submenu
|
const editMenu: MenuItemConstructorOptions = {
|
||||||
menuItems.push({
|
|
||||||
label: 'Edit',
|
label: 'Edit',
|
||||||
submenu: [
|
submenu: [
|
||||||
{ role: 'undo' },
|
{ role: 'undo' },
|
||||||
@ -78,10 +83,9 @@ export function initMenu(windowManager: WindowManager) {
|
|||||||
{ type: 'separator' },
|
{ type: 'separator' },
|
||||||
{ role: 'selectAll' },
|
{ role: 'selectAll' },
|
||||||
]
|
]
|
||||||
});
|
};
|
||||||
|
|
||||||
// "View" submenu
|
const viewMenu: MenuItemConstructorOptions = {
|
||||||
menuItems.push({
|
|
||||||
label: 'View',
|
label: 'View',
|
||||||
submenu: [
|
submenu: [
|
||||||
{
|
{
|
||||||
@ -113,10 +117,9 @@ export function initMenu(windowManager: WindowManager) {
|
|||||||
{ type: 'separator' },
|
{ type: 'separator' },
|
||||||
{ role: 'togglefullscreen' }
|
{ role: 'togglefullscreen' }
|
||||||
]
|
]
|
||||||
})
|
};
|
||||||
|
|
||||||
// "Help" submenu
|
const helpMenu: MenuItemConstructorOptions = {
|
||||||
menuItems.push({
|
|
||||||
role: 'help',
|
role: 'help',
|
||||||
submenu: [
|
submenu: [
|
||||||
{
|
{
|
||||||
@ -162,8 +165,9 @@ export function initMenu(windowManager: WindowManager) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
});
|
};
|
||||||
|
|
||||||
const menu = Menu.buildFromTemplate(menuItems);
|
Menu.setApplicationMenu(Menu.buildFromTemplate([
|
||||||
Menu.setApplicationMenu(menu);
|
fileMenu, editMenu, viewMenu, helpMenu
|
||||||
|
]));
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
import { autorun, reaction } from "mobx";
|
import { reaction } from "mobx";
|
||||||
import { BrowserWindow, shell } from "electron"
|
import { BrowserWindow, shell } from "electron"
|
||||||
import windowStateKeeper from "electron-window-state"
|
import windowStateKeeper from "electron-window-state"
|
||||||
import type { ClusterId } from "../common/cluster-store";
|
import type { ClusterId } from "../common/cluster-store";
|
||||||
@ -29,8 +29,12 @@ export class WindowManager {
|
|||||||
|
|
||||||
// Manage reactive state
|
// Manage reactive state
|
||||||
this.disposers.push(
|
this.disposers.push(
|
||||||
// show and hide "no-clusters" window when necessary
|
// auto-show/hide "no-clusters" window when necessary
|
||||||
autorun(this.handleNoClustersView),
|
reaction(() => clusterStore.hasClusters(), hasClusters => {
|
||||||
|
this.handleNoClustersView({ activate: !hasClusters });
|
||||||
|
}, {
|
||||||
|
fireImmediately: true
|
||||||
|
}),
|
||||||
|
|
||||||
// auto-show active cluster window and subscribe for push-events
|
// auto-show active cluster window and subscribe for push-events
|
||||||
reaction(() => clusterStore.activeClusterId, this.activateView, {
|
reaction(() => clusterStore.activeClusterId, this.activateView, {
|
||||||
@ -48,10 +52,12 @@ export class WindowManager {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected handleNoClustersView = async () => {
|
protected handleNoClustersView = async ({ activate = false } = {}) => {
|
||||||
this.noClustersWindow = this.initClusterView(null);
|
if (!this.noClustersWindow) {
|
||||||
await this.noClustersWindow.loadURL(`http://no-clusters.localhost:${this.proxyPort}`).catch(Function);
|
this.noClustersWindow = this.initClusterView(null);
|
||||||
if (!clusterStore.hasClusters()) {
|
await this.noClustersWindow.loadURL(`http://no-clusters.localhost:${this.proxyPort}`);
|
||||||
|
}
|
||||||
|
if (activate) {
|
||||||
this.activeView = this.noClustersWindow;
|
this.activeView = this.noClustersWindow;
|
||||||
this.noClustersWindow.show();
|
this.noClustersWindow.show();
|
||||||
this.hideSplash();
|
this.hideSplash();
|
||||||
@ -69,8 +75,8 @@ export class WindowManager {
|
|||||||
resizable: false,
|
resizable: false,
|
||||||
show: false,
|
show: false,
|
||||||
});
|
});
|
||||||
|
await this.splashWindow.loadURL("static://splash.html");
|
||||||
}
|
}
|
||||||
await this.splashWindow.loadURL("static://splash.html").catch(Function)
|
|
||||||
this.splashWindow.show();
|
this.splashWindow.show();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -8,7 +8,7 @@ import type { KubeObjectStore } from "../kube-object.store";
|
|||||||
import { KubeApi } from "./kube-api";
|
import { KubeApi } from "./kube-api";
|
||||||
import { apiManager } from "./api-manager";
|
import { apiManager } from "./api-manager";
|
||||||
import { apiPrefix, isDevelopment } from "../../common/vars";
|
import { apiPrefix, isDevelopment } from "../../common/vars";
|
||||||
import { clusterStore } from "../../common/cluster-store";
|
import { getHostedCluster } from "../../common/cluster-store";
|
||||||
|
|
||||||
export interface IKubeWatchEvent<T = any> {
|
export interface IKubeWatchEvent<T = any> {
|
||||||
type: "ADDED" | "MODIFIED" | "DELETED";
|
type: "ADDED" | "MODIFIED" | "DELETED";
|
||||||
@ -61,7 +61,7 @@ export class KubeWatchApi {
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected getQuery(): Partial<IKubeWatchRouteQuery> {
|
protected getQuery(): Partial<IKubeWatchRouteQuery> {
|
||||||
const { isAdmin, allowedNamespaces } = clusterStore.activeCluster;
|
const { isAdmin, allowedNamespaces } = getHostedCluster();
|
||||||
return {
|
return {
|
||||||
api: this.activeApis.map(api => {
|
api: this.activeApis.map(api => {
|
||||||
if (isAdmin) return api.getWatchUrl();
|
if (isAdmin) return api.getWatchUrl();
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
import { clusterStore } from "../../common/cluster-store";
|
import { getHostedCluster } from "../../common/cluster-store";
|
||||||
|
|
||||||
// todo: refactor / move to cluster-store.ts?
|
// todo: refactor / move to cluster-store.ts?
|
||||||
|
|
||||||
@ -6,7 +6,7 @@ export function isAllowedResource(resources: string | string[]) {
|
|||||||
if (!Array.isArray(resources)) {
|
if (!Array.isArray(resources)) {
|
||||||
resources = [resources];
|
resources = [resources];
|
||||||
}
|
}
|
||||||
const allowedResources = clusterStore.activeCluster?.allowedResources || [];
|
const { allowedResources } = getHostedCluster();
|
||||||
for (const resource of resources) {
|
for (const resource of resources) {
|
||||||
if (!allowedResources.includes(resource)) {
|
if (!allowedResources.includes(resource)) {
|
||||||
return false;
|
return false;
|
||||||
|
|||||||
@ -5,7 +5,7 @@ import { HelmRelease, helmReleasesApi, IReleaseCreatePayload, IReleaseUpdatePayl
|
|||||||
import { ItemStore } from "../../item.store";
|
import { ItemStore } from "../../item.store";
|
||||||
import { Secret } from "../../api/endpoints";
|
import { Secret } from "../../api/endpoints";
|
||||||
import { secretsStore } from "../+config-secrets/secrets.store";
|
import { secretsStore } from "../+config-secrets/secrets.store";
|
||||||
import { clusterStore } from "../../../common/cluster-store";
|
import { getHostedCluster } from "../../../common/cluster-store";
|
||||||
|
|
||||||
@autobind()
|
@autobind()
|
||||||
export class ReleaseStore extends ItemStore<HelmRelease> {
|
export class ReleaseStore extends ItemStore<HelmRelease> {
|
||||||
@ -58,7 +58,7 @@ export class ReleaseStore extends ItemStore<HelmRelease> {
|
|||||||
this.isLoading = true;
|
this.isLoading = true;
|
||||||
let items;
|
let items;
|
||||||
try {
|
try {
|
||||||
const { isAdmin, allowedNamespaces } = clusterStore.activeCluster;
|
const { isAdmin, allowedNamespaces } = getHostedCluster();
|
||||||
items = await this.loadItems(!isAdmin ? allowedNamespaces : null);
|
items = await this.loadItems(!isAdmin ? allowedNamespaces : null);
|
||||||
} finally {
|
} finally {
|
||||||
if (items) {
|
if (items) {
|
||||||
|
|||||||
@ -4,6 +4,7 @@
|
|||||||
position: relative;
|
position: relative;
|
||||||
opacity: .75;
|
opacity: .75;
|
||||||
border-radius: $radius;
|
border-radius: $radius;
|
||||||
|
user-select: none;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
|
|
||||||
&.active, &.interactive:hover {
|
&.active, &.interactive:hover {
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
import "./app.scss";
|
import "./app.scss";
|
||||||
import React from "react";
|
import React from "react";
|
||||||
import { disposeOnUnmount, observer } from "mobx-react";
|
import { disposeOnUnmount, observer } from "mobx-react";
|
||||||
import { autorun, computed, observable } from "mobx";
|
import { observable, reaction } from "mobx";
|
||||||
import { Redirect, Route, Switch } from "react-router";
|
import { Redirect, Route, Switch } from "react-router";
|
||||||
import { Notifications } from "./notifications";
|
import { Notifications } from "./notifications";
|
||||||
import { NotFound } from "./+404";
|
import { NotFound } from "./+404";
|
||||||
@ -28,7 +28,7 @@ import { CustomResources } from "./+custom-resources/custom-resources";
|
|||||||
import { crdRoute } from "./+custom-resources";
|
import { crdRoute } from "./+custom-resources";
|
||||||
import { isAllowedResource } from "../api/rbac";
|
import { isAllowedResource } from "../api/rbac";
|
||||||
import { AddCluster, addClusterRoute } from "./+add-cluster";
|
import { AddCluster, addClusterRoute } from "./+add-cluster";
|
||||||
import { LandingPage, landingRoute } from "./+landing-page";
|
import { LandingPage, landingRoute, landingURL } from "./+landing-page";
|
||||||
import { ClusterSettings, clusterSettingsRoute } from "./+cluster-settings";
|
import { ClusterSettings, clusterSettingsRoute } from "./+cluster-settings";
|
||||||
import { Workspaces, workspacesRoute } from "./+workspaces";
|
import { Workspaces, workspacesRoute } from "./+workspaces";
|
||||||
import { ErrorBoundary } from "./error-boundary";
|
import { ErrorBoundary } from "./error-boundary";
|
||||||
@ -44,36 +44,41 @@ import { navigate, navigation } from "../navigation";
|
|||||||
export class App extends React.Component {
|
export class App extends React.Component {
|
||||||
@observable isReady = false;
|
@observable isReady = false;
|
||||||
|
|
||||||
@computed get clusterReady(): boolean {
|
get cluster() {
|
||||||
const cluster = getHostedCluster();
|
return getHostedCluster()
|
||||||
if (cluster) {
|
|
||||||
return cluster.initialized && cluster.accessible;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async componentDidMount() {
|
async componentDidMount() {
|
||||||
await clusterIpc.activate.invokeFromRenderer(); // refresh state, reconnect, etc.
|
if (this.cluster) {
|
||||||
this.isReady = true;
|
await clusterIpc.activate.invokeFromRenderer(); // refresh state, reconnect, etc.
|
||||||
|
}
|
||||||
disposeOnUnmount(this, [
|
disposeOnUnmount(this, [
|
||||||
autorun(() => {
|
reaction(() => this.startURL, this.onStartUrlChange, {
|
||||||
if (!this.clusterReady) {
|
fireImmediately: true
|
||||||
navigate(clusterStatusURL());
|
|
||||||
} else if (clusterStatusURL() == navigation.getPath()) {
|
|
||||||
navigate("/"); // redirect when cluster accessible
|
|
||||||
}
|
|
||||||
})
|
})
|
||||||
])
|
])
|
||||||
|
this.isReady = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected onStartUrlChange = (startURL: string) => {
|
||||||
|
const path = navigation.getPath();
|
||||||
|
const redirectRequired = ["/", clusterStatusURL()].includes(path);
|
||||||
|
if (redirectRequired || !this.cluster?.accessible) {
|
||||||
|
navigate(startURL);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
get startURL() {
|
get startURL() {
|
||||||
if (!this.clusterReady) {
|
if (this.cluster) {
|
||||||
return clusterStatusURL();
|
if (!this.cluster.accessible) {
|
||||||
|
return clusterStatusURL();
|
||||||
|
}
|
||||||
|
if (isAllowedResource(["events", "nodes", "pods"])) {
|
||||||
|
return clusterURL();
|
||||||
|
}
|
||||||
|
return workloadsURL();
|
||||||
}
|
}
|
||||||
if (isAllowedResource(["events", "nodes", "pods"])) {
|
return landingURL();
|
||||||
return clusterURL();
|
|
||||||
}
|
|
||||||
return workloadsURL();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
@ -87,19 +92,23 @@ export class App extends React.Component {
|
|||||||
<Route component={Preferences} {...preferencesRoute}/>
|
<Route component={Preferences} {...preferencesRoute}/>
|
||||||
<Route component={Workspaces} {...workspacesRoute}/>
|
<Route component={Workspaces} {...workspacesRoute}/>
|
||||||
<Route component={AddCluster} {...addClusterRoute}/>
|
<Route component={AddCluster} {...addClusterRoute}/>
|
||||||
<Route component={Cluster} {...clusterRoute}/>
|
{this.cluster && (
|
||||||
<Route component={ClusterStatus} {...clusterStatusRoute}/>
|
<>
|
||||||
<Route component={ClusterSettings} {...clusterSettingsRoute}/>
|
<Route component={Cluster} {...clusterRoute}/>
|
||||||
<Route component={Nodes} {...nodesRoute}/>
|
<Route component={ClusterStatus} {...clusterStatusRoute}/>
|
||||||
<Route component={Workloads} {...workloadsRoute}/>
|
<Route component={ClusterSettings} {...clusterSettingsRoute}/>
|
||||||
<Route component={Config} {...configRoute}/>
|
<Route component={Nodes} {...nodesRoute}/>
|
||||||
<Route component={Network} {...networkRoute}/>
|
<Route component={Workloads} {...workloadsRoute}/>
|
||||||
<Route component={Storage} {...storageRoute}/>
|
<Route component={Config} {...configRoute}/>
|
||||||
<Route component={Namespaces} {...namespacesRoute}/>
|
<Route component={Network} {...networkRoute}/>
|
||||||
<Route component={Events} {...eventRoute}/>
|
<Route component={Storage} {...storageRoute}/>
|
||||||
<Route component={CustomResources} {...crdRoute}/>
|
<Route component={Namespaces} {...namespacesRoute}/>
|
||||||
<Route component={UserManagement} {...usersManagementRoute}/>
|
<Route component={Events} {...eventRoute}/>
|
||||||
<Route component={Apps} {...appsRoute}/>
|
<Route component={CustomResources} {...crdRoute}/>
|
||||||
|
<Route component={UserManagement} {...usersManagementRoute}/>
|
||||||
|
<Route component={Apps} {...appsRoute}/>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
<Redirect exact from="/" to={this.startURL}/>
|
<Redirect exact from="/" to={this.startURL}/>
|
||||||
<Route component={NotFound}/>
|
<Route component={NotFound}/>
|
||||||
</Switch>
|
</Switch>
|
||||||
|
|||||||
@ -21,13 +21,16 @@ export class ClusterStatus extends React.Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@computed get cluster() {
|
@computed get cluster() {
|
||||||
return getHostedCluster()
|
return getHostedCluster();
|
||||||
}
|
}
|
||||||
|
|
||||||
async componentDidMount() {
|
async componentDidMount() {
|
||||||
this.authOutput = [{ data: "Connecting ...\n" }];
|
this.authOutput = [{ data: "Connecting..." }];
|
||||||
ipcRenderer.on(`kube-auth:${this.cluster.id}`, (evt, res) => {
|
ipcRenderer.on(`kube-auth:${this.cluster.id}`, (evt, res: KubeAuthProxyResponse) => {
|
||||||
this.authOutput.push(res);
|
this.authOutput.push({
|
||||||
|
data: res.data.trimRight(),
|
||||||
|
error: res.error,
|
||||||
|
});
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -36,7 +39,7 @@ export class ClusterStatus extends React.Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
reconnect = async () => {
|
reconnect = async () => {
|
||||||
this.authOutput = [{ data: "Reconnecting ...\n" }];
|
this.authOutput = [{ data: "Reconnecting..." }];
|
||||||
this.isReconnecting = true;
|
this.isReconnecting = true;
|
||||||
await clusterIpc.activate.invokeFromRenderer();
|
await clusterIpc.activate.invokeFromRenderer();
|
||||||
this.isReconnecting = false;
|
this.isReconnecting = false;
|
||||||
|
|||||||
@ -56,8 +56,8 @@ export class ClustersMenu extends React.Component<Props> {
|
|||||||
menu.append(new MenuItem({
|
menu.append(new MenuItem({
|
||||||
label: _i18n._(t`Disconnect`),
|
label: _i18n._(t`Disconnect`),
|
||||||
click: async () => {
|
click: async () => {
|
||||||
await clusterIpc.disconnect.invokeFromRenderer();
|
|
||||||
navigate(clusterStatusURL());
|
navigate(clusterStatusURL());
|
||||||
|
await clusterIpc.disconnect.invokeFromRenderer();
|
||||||
}
|
}
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
|
|||||||
@ -11,7 +11,7 @@ import { ErrorBoundary } from "../error-boundary";
|
|||||||
import { Dock } from "../dock";
|
import { Dock } from "../dock";
|
||||||
import { navigate, navigation } from "../../navigation";
|
import { navigate, navigation } from "../../navigation";
|
||||||
import { themeStore } from "../../theme.store";
|
import { themeStore } from "../../theme.store";
|
||||||
import { clusterStore } from "../../../common/cluster-store";
|
import { getHostedCluster } from "../../../common/cluster-store";
|
||||||
|
|
||||||
export interface TabRoute extends RouteProps {
|
export interface TabRoute extends RouteProps {
|
||||||
title: React.ReactNode;
|
title: React.ReactNode;
|
||||||
@ -47,7 +47,7 @@ export class MainLayout extends React.Component<Props> {
|
|||||||
|
|
||||||
render() {
|
render() {
|
||||||
const { className, contentClass, headerClass, tabs, footer, footerClass, children } = this.props;
|
const { className, contentClass, headerClass, tabs, footer, footerClass, children } = this.props;
|
||||||
const clusterName = clusterStore.activeCluster?.contextName;
|
const { contextName: clusterName } = getHostedCluster();
|
||||||
const routePath = navigation.location.pathname;
|
const routePath = navigation.location.pathname;
|
||||||
return (
|
return (
|
||||||
<div className={cssNames("MainLayout", className, themeStore.activeTheme.type)}>
|
<div className={cssNames("MainLayout", className, themeStore.activeTheme.type)}>
|
||||||
|
|||||||
@ -6,7 +6,7 @@ import { ItemStore } from "./item.store";
|
|||||||
import { apiManager } from "./api/api-manager";
|
import { apiManager } from "./api/api-manager";
|
||||||
import { IKubeApiQueryParams, KubeApi } from "./api/kube-api";
|
import { IKubeApiQueryParams, KubeApi } from "./api/kube-api";
|
||||||
import { KubeJsonApiData } from "./api/kube-json-api";
|
import { KubeJsonApiData } from "./api/kube-json-api";
|
||||||
import { clusterStore } from "../common/cluster-store";
|
import { getHostedCluster } from "../common/cluster-store";
|
||||||
|
|
||||||
@autobind()
|
@autobind()
|
||||||
export abstract class KubeObjectStore<T extends KubeObject = any> extends ItemStore<T> {
|
export abstract class KubeObjectStore<T extends KubeObject = any> extends ItemStore<T> {
|
||||||
@ -76,7 +76,7 @@ export abstract class KubeObjectStore<T extends KubeObject = any> extends ItemSt
|
|||||||
this.isLoading = true;
|
this.isLoading = true;
|
||||||
let items: T[];
|
let items: T[];
|
||||||
try {
|
try {
|
||||||
const { isAdmin, allowedNamespaces } = clusterStore.activeCluster;
|
const { isAdmin, allowedNamespaces } = getHostedCluster();
|
||||||
items = await this.loadItems(!isAdmin ? allowedNamespaces : null);
|
items = await this.loadItems(!isAdmin ? allowedNamespaces : null);
|
||||||
items = this.filterItemsOnLoad(items);
|
items = this.filterItemsOnLoad(items);
|
||||||
} finally {
|
} finally {
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user