mirror of
https://github.com/lensapp/lens.git
synced 2025-05-20 05:10:56 +00:00
fix clusters staying in previously icon reordered workspaces
Signed-off-by: Sebastian Malton <smalton@mirantis.com>
This commit is contained in:
parent
85a7f1e323
commit
eb1a2a07e0
@ -198,8 +198,8 @@
|
||||
"openid-client": "^3.15.2",
|
||||
"path-to-regexp": "^6.1.0",
|
||||
"proper-lockfile": "^4.1.1",
|
||||
"react-router": "^5.2.0",
|
||||
"react-beautiful-dnd": "^13.0.0",
|
||||
"react-router": "^5.2.0",
|
||||
"request": "^2.88.2",
|
||||
"request-promise-native": "^1.0.8",
|
||||
"semver": "^7.3.2",
|
||||
@ -318,4 +318,4 @@
|
||||
"xterm": "^4.6.0",
|
||||
"xterm-addon-fit": "^0.4.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -11,6 +11,9 @@ import { tracker } from "./tracker";
|
||||
import { dumpConfigYaml } from "./kube-helpers";
|
||||
import { saveToAppFiles } from "./utils/saveToAppFiles";
|
||||
import { KubeConfig } from "@kubernetes/client-node";
|
||||
import _ from "lodash";
|
||||
import move from "array-move";
|
||||
import { is } from "immer/dist/internal";
|
||||
|
||||
export interface ClusterIconUpload {
|
||||
clusterId: string;
|
||||
@ -18,14 +21,9 @@ export interface ClusterIconUpload {
|
||||
path: string;
|
||||
}
|
||||
|
||||
interface ClusterIconOrdering {
|
||||
[workspaceId: string]: ClusterId[]
|
||||
}
|
||||
|
||||
export interface ClusterStoreModel {
|
||||
activeCluster?: ClusterId; // last opened cluster
|
||||
clusters?: ClusterModel[]
|
||||
iconOrder?: ClusterIconOrdering,
|
||||
}
|
||||
|
||||
export type ClusterId = string;
|
||||
@ -53,6 +51,7 @@ export interface ClusterPreferences {
|
||||
prometheusProvider?: {
|
||||
type: string;
|
||||
};
|
||||
iconOrder?: number;
|
||||
icon?: string;
|
||||
httpsProxy?: string;
|
||||
}
|
||||
@ -88,7 +87,6 @@ export class ClusterStore extends BaseStore<ClusterStoreModel> {
|
||||
@observable activeClusterId: ClusterId;
|
||||
@observable removedClusters = observable.map<ClusterId, Cluster>();
|
||||
@observable clusters = observable.map<ClusterId, Cluster>();
|
||||
@observable clusterOrders: ClusterIconOrdering = {};
|
||||
|
||||
@computed get activeCluster(): Cluster | null {
|
||||
return this.getById(this.activeClusterId);
|
||||
@ -107,6 +105,20 @@ export class ClusterStore extends BaseStore<ClusterStoreModel> {
|
||||
this.activeClusterId = id;
|
||||
}
|
||||
|
||||
@action
|
||||
swapIconOrders(workspace: WorkspaceId, from: number, to: number) {
|
||||
const clusters = this.getByWorkspaceId(workspace);
|
||||
if (from < 0 || to < 0 || from >= clusters.length || to >= clusters.length || isNaN(from) || isNaN(to)) {
|
||||
throw new Error(`invalid from<->to arguments`)
|
||||
}
|
||||
|
||||
move.mutate(clusters, from, to);
|
||||
for (const i in clusters) {
|
||||
// This resets the iconOrder to the current display order
|
||||
clusters[i].preferences.iconOrder = +i;
|
||||
}
|
||||
}
|
||||
|
||||
hasClusters() {
|
||||
return this.clusters.size > 0;
|
||||
}
|
||||
@ -120,10 +132,9 @@ export class ClusterStore extends BaseStore<ClusterStoreModel> {
|
||||
}
|
||||
|
||||
getByWorkspaceId(workspaceId: string): Cluster[] {
|
||||
this.clusterOrders[workspaceId] ??= Array.from(this.clusters.values())
|
||||
.filter(cluster => cluster.workspace === workspaceId)
|
||||
.map(cluster => cluster.id);
|
||||
return this.clusterOrders[workspaceId].map(clusterId => this.clusters.get(clusterId));
|
||||
const clusters = Array.from(this.clusters.values())
|
||||
.filter(cluster => cluster.workspace === workspaceId);
|
||||
return _.sortBy(clusters, cluster => cluster.preferences.iconOrder)
|
||||
}
|
||||
|
||||
@action
|
||||
@ -159,13 +170,11 @@ export class ClusterStore extends BaseStore<ClusterStoreModel> {
|
||||
}
|
||||
|
||||
@action
|
||||
protected fromStore({ activeCluster, clusters = [], iconOrder = {} }: ClusterStoreModel = {}) {
|
||||
protected fromStore({ activeCluster, clusters = [] }: ClusterStoreModel = {}) {
|
||||
const currentClusters = this.clusters.toJS();
|
||||
const newClusters = new Map<ClusterId, Cluster>();
|
||||
const removedClusters = new Map<ClusterId, Cluster>();
|
||||
|
||||
this.clusterOrders = iconOrder;
|
||||
|
||||
// update new clusters
|
||||
for (const clusterModel of clusters) {
|
||||
let cluster = currentClusters.get(clusterModel.id);
|
||||
@ -175,13 +184,6 @@ export class ClusterStore extends BaseStore<ClusterStoreModel> {
|
||||
cluster = new Cluster(clusterModel);
|
||||
}
|
||||
newClusters.set(clusterModel.id, cluster);
|
||||
|
||||
if (!this.clusterOrders[cluster.workspace]) {
|
||||
this.clusterOrders[cluster.workspace] = [];
|
||||
}
|
||||
if (!this.clusterOrders[cluster.workspace].includes(cluster.id)) {
|
||||
this.clusterOrders[cluster.workspace].push(cluster.id);
|
||||
}
|
||||
}
|
||||
|
||||
// update removed clusters
|
||||
@ -200,7 +202,6 @@ export class ClusterStore extends BaseStore<ClusterStoreModel> {
|
||||
return toJS({
|
||||
activeCluster: this.activeClusterId,
|
||||
clusters: this.clustersList.map(cluster => cluster.toJSON()),
|
||||
iconOrder: this.clusterOrders,
|
||||
}, {
|
||||
recurseEverything: true
|
||||
})
|
||||
|
||||
@ -93,6 +93,34 @@ describe("empty config", () => {
|
||||
expect(fs.readFileSync(file, "utf8")).toBe("kubeconfig");
|
||||
})
|
||||
|
||||
it("check if reorderring works for same from and to", () => {
|
||||
clusterStore.swapIconOrders("workstation", 1, 1)
|
||||
|
||||
const clusters = clusterStore.getByWorkspaceId("workstation");
|
||||
expect(clusters[0].id).toBe("prod")
|
||||
expect(clusters[0].preferences.iconOrder).toBe(0)
|
||||
expect(clusters[1].id).toBe("dev")
|
||||
expect(clusters[1].preferences.iconOrder).toBe(1)
|
||||
});
|
||||
|
||||
it("check if reorderring works for different from and to", () => {
|
||||
clusterStore.swapIconOrders("workstation", 0, 1)
|
||||
|
||||
const clusters = clusterStore.getByWorkspaceId("workstation");
|
||||
expect(clusters[0].id).toBe("dev")
|
||||
expect(clusters[0].preferences.iconOrder).toBe(0)
|
||||
expect(clusters[1].id).toBe("prod")
|
||||
expect(clusters[1].preferences.iconOrder).toBe(1)
|
||||
});
|
||||
|
||||
it("check if after icon reordering, changing workspaces still works", () => {
|
||||
clusterStore.swapIconOrders("workstation", 1, 1)
|
||||
clusterStore.getById("prod").workspace = "default"
|
||||
|
||||
expect(clusterStore.getByWorkspaceId("workstation").length).toBe(1);
|
||||
expect(clusterStore.getByWorkspaceId("default").length).toBe(2);
|
||||
});
|
||||
|
||||
it("removes cluster from store", async () => {
|
||||
await clusterStore.removeById("foo");
|
||||
expect(clusterStore.getById("foo")).toBeUndefined();
|
||||
|
||||
@ -2,7 +2,7 @@ import type { ClusterId, ClusterModel, ClusterPreferences } from "../common/clus
|
||||
import type { IMetricsReqParams } from "../renderer/api/endpoints/metrics.api";
|
||||
import type { WorkspaceId } from "../common/workspace-store";
|
||||
import type { FeatureStatusMap } from "./feature"
|
||||
import { action, computed, observable, reaction, toJS, when } from "mobx";
|
||||
import { action, computed, intercept, observable, reaction, toJS, when } from "mobx";
|
||||
import { apiKubePrefix } from "../common/vars";
|
||||
import { broadcastIpc } from "../common/ipc";
|
||||
import { ContextHandler } from "./context-handler"
|
||||
|
||||
@ -21,7 +21,6 @@ import { ConfirmDialog } from "../confirm-dialog";
|
||||
import { clusterIpc } from "../../../common/cluster-ipc";
|
||||
import { clusterViewURL, getMatchedClusterId } from "./cluster-view.route";
|
||||
import { DragDropContext, Droppable, Draggable, DropResult, DroppableProvided, DraggableProvided } from "react-beautiful-dnd";
|
||||
import move from "array-move";
|
||||
|
||||
// fixme: allow to rearrange clusters with drag&drop
|
||||
|
||||
@ -93,10 +92,11 @@ export class ClustersMenu extends React.Component<Props> {
|
||||
swapClusterIconOrder(result: DropResult) {
|
||||
if (result.reason === "DROP") {
|
||||
const { currentWorkspaceId } = workspaceStore;
|
||||
const clusters = clusterStore.getByWorkspaceId(currentWorkspaceId);
|
||||
|
||||
move.mutate(clusters, result.source.index, result.destination.index);
|
||||
clusterStore.clusterOrders[currentWorkspaceId] = clusters.map(c => c.id);
|
||||
const {
|
||||
source: { index: from },
|
||||
destination: { index: to },
|
||||
} = result
|
||||
clusterStore.swapIconOrders(currentWorkspaceId, from, to)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
49
yarn.lock
49
yarn.lock
@ -1350,6 +1350,17 @@
|
||||
"@types/yargs" "^15.0.0"
|
||||
chalk "^4.0.0"
|
||||
|
||||
"@jest/types@^26.3.0":
|
||||
version "26.3.0"
|
||||
resolved "https://registry.yarnpkg.com/@jest/types/-/types-26.3.0.tgz#97627bf4bdb72c55346eef98e3b3f7ddc4941f71"
|
||||
integrity sha512-BDPG23U0qDeAvU4f99haztXwdAg3hz4El95LkAM+tHAqqhiVzRpEGHHU8EDxT/AnxOrA65YjLBwDahdJ9pTLJQ==
|
||||
dependencies:
|
||||
"@types/istanbul-lib-coverage" "^2.0.0"
|
||||
"@types/istanbul-reports" "^3.0.0"
|
||||
"@types/node" "*"
|
||||
"@types/yargs" "^15.0.0"
|
||||
chalk "^4.0.0"
|
||||
|
||||
"@kubernetes/client-node@^0.12.0":
|
||||
version "0.12.0"
|
||||
resolved "https://registry.yarnpkg.com/@kubernetes/client-node/-/client-node-0.12.0.tgz#79120311bced206ac8fa36435fb4cc2c1828fff2"
|
||||
@ -1846,6 +1857,21 @@
|
||||
"@types/istanbul-lib-coverage" "*"
|
||||
"@types/istanbul-lib-report" "*"
|
||||
|
||||
"@types/istanbul-reports@^3.0.0":
|
||||
version "3.0.0"
|
||||
resolved "https://registry.yarnpkg.com/@types/istanbul-reports/-/istanbul-reports-3.0.0.tgz#508b13aa344fa4976234e75dddcc34925737d821"
|
||||
integrity sha512-nwKNbvnwJ2/mndE9ItP/zc2TCzw6uuodnF4EHYWD+gCQDVBuRQL5UzbZD0/ezy1iKsFU2ZQiDqg4M9dN4+wZgA==
|
||||
dependencies:
|
||||
"@types/istanbul-lib-report" "*"
|
||||
|
||||
"@types/jest@26.x":
|
||||
version "26.0.13"
|
||||
resolved "https://registry.yarnpkg.com/@types/jest/-/jest-26.0.13.tgz#5a7b9d5312f5dd521a38329c38ee9d3802a0b85e"
|
||||
integrity sha512-sCzjKow4z9LILc6DhBvn5AkIfmQzDZkgtVVKmGwVrs5tuid38ws281D4l+7x1kP487+FlKDh5kfMZ8WSPAdmdA==
|
||||
dependencies:
|
||||
jest-diff "^25.2.1"
|
||||
pretty-format "^25.2.1"
|
||||
|
||||
"@types/jest@^25.2.3":
|
||||
version "25.2.3"
|
||||
resolved "https://registry.yarnpkg.com/@types/jest/-/jest-25.2.3.tgz#33d27e4c4716caae4eced355097a47ad363fdcaf"
|
||||
@ -7144,6 +7170,18 @@ jest-snapshot@^26.0.1:
|
||||
pretty-format "^26.0.1"
|
||||
semver "^7.3.2"
|
||||
|
||||
jest-util@26.x:
|
||||
version "26.3.0"
|
||||
resolved "https://registry.yarnpkg.com/jest-util/-/jest-util-26.3.0.tgz#a8974b191df30e2bf523ebbfdbaeb8efca535b3e"
|
||||
integrity sha512-4zpn6bwV0+AMFN0IYhH/wnzIQzRaYVrz1A8sYnRnj4UXDXbOVtWmlaZkO9mipFqZ13okIfN87aDoJWB7VH6hcw==
|
||||
dependencies:
|
||||
"@jest/types" "^26.3.0"
|
||||
"@types/node" "*"
|
||||
chalk "^4.0.0"
|
||||
graceful-fs "^4.2.4"
|
||||
is-ci "^2.0.0"
|
||||
micromatch "^4.0.2"
|
||||
|
||||
jest-util@^26.0.1:
|
||||
version "26.0.1"
|
||||
resolved "https://registry.yarnpkg.com/jest-util/-/jest-util-26.0.1.tgz#72c4c51177b695fdd795ca072a6f94e3d7cef00a"
|
||||
@ -7903,7 +7941,7 @@ messageformat-parser@^4.1.3:
|
||||
resolved "https://registry.yarnpkg.com/messageformat-parser/-/messageformat-parser-4.1.3.tgz#b824787f57fcda7d50769f5b63e8d4fda68f5b9e"
|
||||
integrity sha512-2fU3XDCanRqeOCkn7R5zW5VQHWf+T3hH65SzuqRvjatBK7r4uyFa5mEX+k6F9Bd04LVM5G4/BHBTUJsOdW7uyg==
|
||||
|
||||
micromatch@4.0.2, micromatch@4.x, micromatch@^4.0.0, micromatch@^4.0.2:
|
||||
micromatch@4.0.2, micromatch@^4.0.0, micromatch@^4.0.2:
|
||||
version "4.0.2"
|
||||
resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-4.0.2.tgz#4fcb0999bf9fbc2fcbdd212f6d629b9a56c39259"
|
||||
integrity sha512-y7FpHSbMUMoyPbYUSzO6PaZ6FyRnQOpHuKwbo1G+Knck95XVU4QAiKdGEnj5wwoS7PlOgthX/09u5iFJ+aYf5Q==
|
||||
@ -11285,17 +11323,18 @@ truncate-utf8-bytes@^1.0.0:
|
||||
utf8-byte-length "^1.0.1"
|
||||
|
||||
ts-jest@^26.1.0:
|
||||
version "26.1.0"
|
||||
resolved "https://registry.yarnpkg.com/ts-jest/-/ts-jest-26.1.0.tgz#e9070fc97b3ea5557a48b67c631c74eb35e15417"
|
||||
integrity sha512-JbhQdyDMYN5nfKXaAwCIyaWLGwevcT2/dbqRPsQeh6NZPUuXjZQZEfeLb75tz0ubCIgEELNm6xAzTe5NXs5Y4Q==
|
||||
version "26.3.0"
|
||||
resolved "https://registry.yarnpkg.com/ts-jest/-/ts-jest-26.3.0.tgz#6b2845045347dce394f069bb59358253bc1338a9"
|
||||
integrity sha512-Jq2uKfx6bPd9+JDpZNMBJMdMQUC3sJ08acISj8NXlVgR2d5OqslEHOR2KHMgwymu8h50+lKIm0m0xj/ioYdW2Q==
|
||||
dependencies:
|
||||
"@types/jest" "26.x"
|
||||
bs-logger "0.x"
|
||||
buffer-from "1.x"
|
||||
fast-json-stable-stringify "2.x"
|
||||
jest-util "26.x"
|
||||
json5 "2.x"
|
||||
lodash.memoize "4.x"
|
||||
make-error "1.x"
|
||||
micromatch "4.x"
|
||||
mkdirp "1.x"
|
||||
semver "7.x"
|
||||
yargs-parser "18.x"
|
||||
|
||||
Loading…
Reference in New Issue
Block a user