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:
Sebastian Malton authored and GitHub committed 2021-06-18 08:44:28 -04:00
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>
)}
@@ -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;
}
+9 -12
View File
@@ -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>
);
+5 -1
View File
@@ -36,4 +36,8 @@
&.small {
font-size: $font-size-small;
}
}
&.clickable {
cursor: pointer;
}
}
+2 -1
View File
@@ -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();
}
+1 -1
View File
@@ -12,7 +12,7 @@
"textColorPrimary": "#555555",
"textColorSecondary": "#51575d",
"textColorTertiary": "#555555",
"textColorAccent": "#333333",
"textColorAccent": "#222222",
"textColorDimmed": "#5557598c",
"borderColor": "#c9cfd3",
"borderFaintColor": "#dfdfdf",