mirror of
https://github.com/lensapp/lens.git
synced 2025-05-20 05:10:56 +00:00
Release/v5.4.5 (#5194)
* Fix mobx error after Edit Resource tab close (#5130) Signed-off-by: Alex Andreev <alex.andreev.email@gmail.com> Signed-off-by: Jim Ehrismann <jehrismann@mirantis.com> * Fix use transparent bg if Avatar contains <img/> inside (#5131) Signed-off-by: Jim Ehrismann <jehrismann@mirantis.com> * Fix exception in KubeStore.watch event buffer handling (#5120) * Fix exception in KubeStore.watch event buffer handling Signed-off-by: Sebastian Malton <sebastian@malton.name> * Fix type error Signed-off-by: Sebastian Malton <sebastian@malton.name> Signed-off-by: Jim Ehrismann <jehrismann@mirantis.com> * Remove HotbarIcon box-shadow artifacts (#5142) Signed-off-by: Alex Andreev <alex.andreev.email@gmail.com> Signed-off-by: Jim Ehrismann <jehrismann@mirantis.com> * Set dock tab contrast bg color (#5143) Signed-off-by: Jim Ehrismann <jehrismann@mirantis.com> * Fix CatalogEntity.status sorting in Catalog (#5147) Signed-off-by: Sebastian Malton <sebastian@malton.name> Signed-off-by: Jim Ehrismann <jehrismann@mirantis.com> * Reset ClusterStatus state when switching clusters (#5149) Signed-off-by: Jim Ehrismann <jehrismann@mirantis.com> * fix bad merge for 'Reset ClusterStatus state when switching clusters (#5149)' Signed-off-by: Jim Ehrismann <jehrismann@mirantis.com> * release v5.4.5 Signed-off-by: Jim Ehrismann <jehrismann@mirantis.com> Co-authored-by: Alex Andreev <alex.andreev.email@gmail.com> Co-authored-by: Sebastian Malton <sebastian@malton.name>
This commit is contained in:
parent
adcf87e939
commit
5dd3896716
@ -3,7 +3,7 @@
|
||||
"productName": "OpenLens",
|
||||
"description": "OpenLens - Open Source IDE for Kubernetes",
|
||||
"homepage": "https://github.com/lensapp/lens",
|
||||
"version": "5.4.4",
|
||||
"version": "5.4.5",
|
||||
"main": "static/build/main.js",
|
||||
"copyright": "© 2021 OpenLens Authors",
|
||||
"license": "MIT",
|
||||
|
||||
@ -655,7 +655,7 @@ export class KubeApi<T extends KubeObject> {
|
||||
if (event.type === "ERROR" && event.object.kind === "Status") {
|
||||
errorReceived = true;
|
||||
|
||||
return callback(null, new KubeStatus(event.object as any));
|
||||
return callback(null, new KubeStatus(event.object));
|
||||
}
|
||||
|
||||
this.modifyWatchEvent(event);
|
||||
|
||||
@ -19,6 +19,7 @@ import type { RequestInit } from "node-fetch";
|
||||
// eslint-disable-next-line import/no-named-as-default
|
||||
import AbortController from "abort-controller";
|
||||
import type { Patch } from "rfc6902";
|
||||
import logger from "../logger";
|
||||
|
||||
export interface KubeObjectStoreLoadingParams {
|
||||
namespaces: string[];
|
||||
@ -456,30 +457,46 @@ export abstract class KubeObjectStore<T extends KubeObject> extends ItemStore<T>
|
||||
protected updateFromEventsBuffer() {
|
||||
const items = this.getItems();
|
||||
|
||||
for (const { type, object } of this.eventsBuffer.clear()) {
|
||||
const index = items.findIndex(item => item.getId() === object.metadata?.uid);
|
||||
const item = items[index];
|
||||
for (const event of this.eventsBuffer.clear()) {
|
||||
if (event.type === "ERROR") {
|
||||
continue;
|
||||
}
|
||||
|
||||
switch (type) {
|
||||
case "ADDED":
|
||||
try {
|
||||
const { type, object } = event;
|
||||
|
||||
// falls through
|
||||
case "MODIFIED": {
|
||||
const newItem = new this.api.objectConstructor(object);
|
||||
|
||||
if (!item) {
|
||||
items.push(newItem);
|
||||
} else {
|
||||
items[index] = newItem;
|
||||
}
|
||||
|
||||
break;
|
||||
if (!object.metadata?.uid) {
|
||||
logger.warn("[KUBE-STORE]: watch event did not have defined .metadata.uid, skipping", { event });
|
||||
// Other parts of the code will break if this happens
|
||||
continue;
|
||||
}
|
||||
case "DELETED":
|
||||
if (item) {
|
||||
items.splice(index, 1);
|
||||
|
||||
const index = items.findIndex(item => item.getId() === object.metadata.uid);
|
||||
const item = items[index];
|
||||
|
||||
switch (type) {
|
||||
case "ADDED":
|
||||
|
||||
// fallthrough
|
||||
case "MODIFIED": {
|
||||
const newItem = new this.api.objectConstructor(object);
|
||||
|
||||
if (!item) {
|
||||
items.push(newItem);
|
||||
} else {
|
||||
items[index] = newItem;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case "DELETED":
|
||||
if (item) {
|
||||
items.splice(index, 1);
|
||||
}
|
||||
break;
|
||||
}
|
||||
} catch (error) {
|
||||
logger.error("[KUBE-STORE]: failed to handle event from watch buffer", { error, event });
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -4,9 +4,13 @@
|
||||
*/
|
||||
|
||||
import type { KubeJsonApiData } from "./kube-json-api";
|
||||
import type { KubeStatusData } from "./kube-object";
|
||||
|
||||
export interface IKubeWatchEvent<T extends KubeJsonApiData> {
|
||||
type: "ADDED" | "MODIFIED" | "DELETED" | "ERROR";
|
||||
object?: T;
|
||||
}
|
||||
export type IKubeWatchEvent<T extends KubeJsonApiData> = {
|
||||
type: "ADDED" | "MODIFIED" | "DELETED";
|
||||
object: T;
|
||||
} | {
|
||||
type: "ERROR";
|
||||
object: KubeStatusData;
|
||||
};
|
||||
|
||||
|
||||
@ -117,5 +117,6 @@ export const defaultCategoryColumns: RegisteredAdditionalCategoryColumn[] = [
|
||||
sortBy: "status",
|
||||
},
|
||||
searchFilter: entity => entity.status.phase,
|
||||
sortCallback: entity => entity.status.phase,
|
||||
},
|
||||
];
|
||||
|
||||
@ -57,10 +57,7 @@ function getLabelFromTitle(title: string) {
|
||||
|
||||
export function Avatar(props: AvatarProps) {
|
||||
const { title, variant = "rounded", size = 32, colorHash, children, background, imgProps, src, className, disabled, ...rest } = props;
|
||||
|
||||
const getBackgroundColor = () => {
|
||||
return background || randomColor({ seed: colorHash, luminosity: "dark" });
|
||||
};
|
||||
const colorFromHash = randomColor({ seed: colorHash, luminosity: "dark" });
|
||||
|
||||
const renderContents = () => {
|
||||
if (src) {
|
||||
@ -77,7 +74,11 @@ export function Avatar(props: AvatarProps) {
|
||||
[styles.rounded]: variant == "rounded",
|
||||
[styles.disabled]: disabled,
|
||||
}, className)}
|
||||
style={{ width: `${size}px`, height: `${size}px`, backgroundColor: getBackgroundColor() }}
|
||||
style={{
|
||||
width: `${size}px`,
|
||||
height: `${size}px`,
|
||||
background: background || (src ? "transparent" : colorFromHash),
|
||||
}}
|
||||
{...rest}
|
||||
>
|
||||
{renderContents()}
|
||||
|
||||
@ -55,6 +55,13 @@ export class ClusterStatus extends React.Component<Props> {
|
||||
]);
|
||||
}
|
||||
|
||||
componentDidUpdate(prevProps: Readonly<Props>): void {
|
||||
if (prevProps.cluster.id !== this.props.cluster.id) {
|
||||
this.isReconnecting = false;
|
||||
this.authOutput = [];
|
||||
}
|
||||
}
|
||||
|
||||
reconnect = async () => {
|
||||
this.authOutput = [];
|
||||
this.isReconnecting = true;
|
||||
|
||||
@ -63,6 +63,7 @@
|
||||
flex: 1;
|
||||
overflow: hidden;
|
||||
transition: flex-basis 25ms ease-in;
|
||||
background: var(--dockInfoBackground);
|
||||
|
||||
&.terminal {
|
||||
background: var(--terminalBackground);
|
||||
|
||||
@ -46,7 +46,7 @@ class NonInjectedEditResource extends React.Component<Props & Dependencies> {
|
||||
const obj = this.resource;
|
||||
|
||||
if (!obj) {
|
||||
if (store.isLoaded) {
|
||||
if (store?.isLoaded) {
|
||||
// auto-close tab when resource removed from store
|
||||
this.props.closeTab(this.props.tab.id);
|
||||
} else if (!store.isLoading) {
|
||||
|
||||
@ -4,7 +4,8 @@
|
||||
*/
|
||||
|
||||
.HotbarIcon {
|
||||
--iconActiveShadow: 0 0 0px 3px var(--clusterMenuBackground), 0 0 0px 6px var(--textColorAccent);
|
||||
--corner: 0px 0px 0px 1px var(--clusterMenuBackground);
|
||||
--iconActiveShadow: var(--corner), var(--corner), 0 0 0px 3px var(--clusterMenuBackground), 0 0 0px 6px var(--textColorAccent);
|
||||
--iconHoverShadow: 0 0 0px 3px var(--clusterMenuBackground), 0 0 0px 6px #ffffff50;
|
||||
|
||||
display: flex;
|
||||
@ -24,6 +25,10 @@
|
||||
|
||||
.avatar {
|
||||
border-radius: 6px;
|
||||
|
||||
&.hasImage {
|
||||
background-color: var(--clusterMenuCellBackground);
|
||||
}
|
||||
}
|
||||
|
||||
.active {
|
||||
|
||||
@ -61,7 +61,7 @@ export const HotbarIcon = observer(({ menuItems = [], size = 40, tooltip, ...pro
|
||||
id={id}
|
||||
title={title}
|
||||
colorHash={`${title}-${source}`}
|
||||
className={cssNames(styles.avatar, { [styles.active]: active })}
|
||||
className={cssNames(styles.avatar, { [styles.active]: active, [styles.hasImage]: !!src })}
|
||||
disabled={disabled}
|
||||
size={size}
|
||||
src={src}
|
||||
|
||||
@ -16,6 +16,7 @@ import { navigate } from "../../navigation";
|
||||
import { Menu, MenuItem } from "../menu";
|
||||
import { ConfirmDialog } from "../confirm-dialog";
|
||||
import { Tooltip } from "../tooltip";
|
||||
import { observer } from "mobx-react";
|
||||
|
||||
const contextMenu: CatalogEntityContextMenuContext = observable({
|
||||
menuItems: [],
|
||||
@ -59,7 +60,7 @@ function renderLoadingSidebarCluster() {
|
||||
);
|
||||
}
|
||||
|
||||
export function SidebarCluster({ clusterEntity }: { clusterEntity: CatalogEntity }) {
|
||||
export const SidebarCluster = observer(({ clusterEntity }: { clusterEntity: CatalogEntity }) => {
|
||||
const [opened, setOpened] = useState(false);
|
||||
|
||||
if (!clusterEntity) {
|
||||
@ -138,4 +139,4 @@ export function SidebarCluster({ clusterEntity }: { clusterEntity: CatalogEntity
|
||||
</Menu>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
Loading…
Reference in New Issue
Block a user