mirror of
https://github.com/lensapp/lens.git
synced 2025-05-20 05:10:56 +00:00
Make CatalogEntity labels clickable (#3075)
- Transition workspace's to be labels - Fix migrations to support multiple migrations for the same version Signed-off-by: Sebastian Malton <sebastian@malton.name>
This commit is contained in:
1 parent
d812e28639
commit
7f51e3addd
30 files changed
+268
-120
No files matched your search
@@ -22,9 +22,9 @@
|
||||
import "./catalog-entity-details.scss";
|
||||
import React, { Component } from "react";
|
||||
import { observer } from "mobx-react";
|
||||
import { Drawer, DrawerItem, DrawerItemLabels } from "../drawer";
|
||||
import { CatalogEntity, catalogEntityRunContext } from "../../api/catalog-entity";
|
||||
import type { CatalogCategory } from "../../../common/catalog";
|
||||
import { Drawer, DrawerItem } from "../drawer";
|
||||
import { catalogEntityRunContext } from "../../api/catalog-entity";
|
||||
import type { CatalogCategory, CatalogEntity } from "../../../common/catalog";
|
||||
import { Icon } from "../icon";
|
||||
import { CatalogEntityDrawerMenu } from "./catalog-entity-drawer-menu";
|
||||
import { CatalogEntityDetailRegistry } from "../../../extensions/registries";
|
||||
@@ -86,10 +86,9 @@ export class CatalogEntityDetails<T extends CatalogEntity> extends Component<Pro
|
||||
<DrawerItem name="Status">
|
||||
{item.phase}
|
||||
</DrawerItem>
|
||||
<DrawerItemLabels
|
||||
name="Labels"
|
||||
labels={item.labels}
|
||||
/>
|
||||
<DrawerItem name="Labels">
|
||||
{...item.getLabelBadges(this.props.hideDetails)}
|
||||
</DrawerItem>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
+29
-9
@@ -19,12 +19,23 @@
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
import styles from "./catalog.module.css";
|
||||
|
||||
import React from "react";
|
||||
import { action, computed, IReactionDisposer, makeObservable, observable, reaction } from "mobx";
|
||||
import { catalogEntityRegistry } from "../../api/catalog-entity-registry";
|
||||
import type { CatalogEntity, CatalogEntityActionContext } from "../../api/catalog-entity";
|
||||
import { ItemObject, ItemStore } from "../../item.store";
|
||||
import { CatalogCategory, catalogCategoryRegistry } from "../../../common/catalog";
|
||||
import { autoBind } from "../../../common/utils";
|
||||
import { Badge } from "../badge";
|
||||
import { navigation } from "../../navigation";
|
||||
import { searchUrlParam } from "../input";
|
||||
import { makeCss } from "../../../common/utils/makeCss";
|
||||
import { KubeObject } from "../../api/kube-object";
|
||||
|
||||
const css = makeCss(styles);
|
||||
|
||||
export class CatalogEntityItem<T extends CatalogEntity> implements ItemObject {
|
||||
constructor(public entity: T) {}
|
||||
|
||||
@@ -61,15 +72,24 @@ export class CatalogEntityItem<T extends CatalogEntity> implements ItemObject {
|
||||
}
|
||||
|
||||
get labels() {
|
||||
const labels: string[] = [];
|
||||
return KubeObject.stringifyLabels(this.entity.metadata.labels);
|
||||
}
|
||||
|
||||
Object.keys(this.entity.metadata.labels).forEach((key) => {
|
||||
const value = this.entity.metadata.labels[key];
|
||||
|
||||
labels.push(`${key}=${value}`);
|
||||
});
|
||||
|
||||
return labels;
|
||||
getLabelBadges(onClick?: React.MouseEventHandler<any>) {
|
||||
return this.labels
|
||||
.map(label => (
|
||||
<Badge
|
||||
className={css.badge}
|
||||
key={label}
|
||||
label={label}
|
||||
title={label}
|
||||
onClick={(event) => {
|
||||
navigation.searchParams.set(searchUrlParam.name, label);
|
||||
onClick?.(event);
|
||||
event.stopPropagation();
|
||||
}}
|
||||
/>
|
||||
));
|
||||
}
|
||||
|
||||
get source() {
|
||||
@@ -82,7 +102,7 @@ export class CatalogEntityItem<T extends CatalogEntity> implements ItemObject {
|
||||
this.id,
|
||||
this.phase,
|
||||
`source=${this.source}`,
|
||||
...this.labels.map((value, key) => `${key}=${value}`)
|
||||
...this.labels,
|
||||
];
|
||||
}
|
||||
|
||||
@@ -63,6 +63,10 @@
|
||||
max-width: unset;
|
||||
}
|
||||
|
||||
.badge:hover {
|
||||
color: var(--textColorAccent);
|
||||
}
|
||||
|
||||
.badge:not(:first-child) {
|
||||
margin-left: 0.5em;
|
||||
}
|
||||
|
||||
@@ -29,7 +29,6 @@ import { CatalogEntityItem, CatalogEntityStore } from "./catalog-entity.store";
|
||||
import { navigate } from "../../navigation";
|
||||
import { MenuItem, MenuActions } from "../menu";
|
||||
import type { CatalogEntityContextMenu, CatalogEntityContextMenuContext } from "../../api/catalog-entity";
|
||||
import { Badge } from "../badge";
|
||||
import { HotbarStore } from "../../../common/hotbar-store";
|
||||
import { ConfirmDialog } from "../confirm-dialog";
|
||||
import { catalogCategoryRegistry, CatalogEntity } from "../../../common/catalog";
|
||||
@@ -208,7 +207,7 @@ export class Catalog extends React.Component<Props> {
|
||||
this.renderIcon(item),
|
||||
item.name,
|
||||
item.source,
|
||||
item.labels.map((label) => <Badge className={css.badge} key={label} label={label} title={label} />),
|
||||
item.getLabelBadges(),
|
||||
{ title: item.phase, className: cssNames(css[item.phase]) }
|
||||
]}
|
||||
onDetails={this.onDetails}
|
||||
@@ -252,7 +251,7 @@ export class Catalog extends React.Component<Props> {
|
||||
item.name,
|
||||
item.kind,
|
||||
item.source,
|
||||
item.labels.map((label) => <Badge className={css.badge} key={label} label={label} title={label} />),
|
||||
item.getLabelBadges(),
|
||||
{ title: item.phase, className: cssNames(css[item.phase]) }
|
||||
]}
|
||||
detailsItem={this.catalogEntityStore.selectedItem}
|
||||
@@ -274,15 +273,13 @@ export class Catalog extends React.Component<Props> {
|
||||
</div>
|
||||
{
|
||||
this.catalogEntityStore.selectedItem
|
||||
? (
|
||||
<CatalogEntityDetails
|
||||
item={this.catalogEntityStore.selectedItem}
|
||||
hideDetails={() => this.catalogEntityStore.selectedItemId = null}
|
||||
/>
|
||||
)
|
||||
: (
|
||||
<CatalogAddButton category = {this.catalogEntityStore.activeCategory} />
|
||||
)
|
||||
? <CatalogEntityDetails
|
||||
item={this.catalogEntityStore.selectedItem}
|
||||
hideDetails={() => this.catalogEntityStore.selectedItemId = null}
|
||||
/>
|
||||
: <CatalogAddButton
|
||||
category={this.catalogEntityStore.activeCategory}
|
||||
/>
|
||||
}
|
||||
</MainLayout>
|
||||
);
|
||||
|
||||
@@ -36,4 +36,8 @@
|
||||
&.small {
|
||||
font-size: $font-size-small;
|
||||
}
|
||||
}
|
||||
|
||||
&.clickable {
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
@@ -35,9 +35,10 @@ export interface BadgeProps extends React.HTMLAttributes<any>, TooltipDecoratorP
|
||||
export class Badge extends React.Component<BadgeProps> {
|
||||
render() {
|
||||
const { className, label, small, flat, children, ...elemProps } = this.props;
|
||||
const clickable = Boolean(this.props.onClick);
|
||||
|
||||
return <>
|
||||
<span className={cssNames("Badge", { small, flat }, className)} {...elemProps}>
|
||||
<span className={cssNames("Badge", { small, flat, clickable }, className)} {...elemProps}>
|
||||
{label}
|
||||
{children}
|
||||
</span>
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
import { computed, observable, reaction, makeObservable } from "mobx";
|
||||
import { computed, observable, reaction, makeObservable, action } from "mobx";
|
||||
import { autoBind } from "../../utils";
|
||||
import { searchUrlParam } from "../input/search-input-url";
|
||||
|
||||
@@ -68,6 +68,7 @@ export class PageFiltersStore {
|
||||
return () => disposers.forEach(dispose => dispose());
|
||||
}
|
||||
|
||||
@action
|
||||
addFilter(filter: Filter, begin = false) {
|
||||
if (begin) this.filters.unshift(filter);
|
||||
else {
|
||||
@@ -75,12 +76,17 @@ export class PageFiltersStore {
|
||||
}
|
||||
}
|
||||
|
||||
@action
|
||||
removeFilter(filter: Filter) {
|
||||
if (!this.filters.remove(filter)) {
|
||||
const filterCopy = this.filters.find(f => f.type === filter.type && f.value === filter.value);
|
||||
|
||||
if (filterCopy) this.filters.remove(filterCopy);
|
||||
}
|
||||
|
||||
if (filter.type === FilterType.SEARCH) {
|
||||
searchUrlParam.clear();
|
||||
}
|
||||
}
|
||||
|
||||
getByType(type: FilterType, value?: any): Filter {
|
||||
@@ -99,19 +105,26 @@ export class PageFiltersStore {
|
||||
return !this.isDisabled.get(type);
|
||||
}
|
||||
|
||||
@action
|
||||
disable(type: FilterType | FilterType[]) {
|
||||
[type].flat().forEach(type => this.isDisabled.set(type, true));
|
||||
|
||||
return () => this.enable(type);
|
||||
}
|
||||
|
||||
@action
|
||||
enable(type: FilterType | FilterType[]) {
|
||||
[type].flat().forEach(type => this.isDisabled.delete(type));
|
||||
|
||||
return () => this.disable(type);
|
||||
}
|
||||
|
||||
@action
|
||||
reset() {
|
||||
if (this.isEnabled(FilterType.SEARCH)) {
|
||||
searchUrlParam.clear();
|
||||
}
|
||||
|
||||
this.filters.length = 0;
|
||||
this.isDisabled.clear();
|
||||
}
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
"textColorPrimary": "#555555",
|
||||
"textColorSecondary": "#51575d",
|
||||
"textColorTertiary": "#555555",
|
||||
"textColorAccent": "#333333",
|
||||
"textColorAccent": "#222222",
|
||||
"textColorDimmed": "#5557598c",
|
||||
"borderColor": "#c9cfd3",
|
||||
"borderFaintColor": "#dfdfdf",
|
||||
|
||||
Reference in new issue
Block a user