1
0
mirror of https://github.com/lensapp/lens.git synced 2025-05-20 05:10:56 +00:00

Allow to scroll table columns with labels (badges) (#4358)

This commit is contained in:
Roman 2021-11-16 21:05:14 +02:00 committed by GitHub
parent 159c240a80
commit 4eb9a689ba
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 45 additions and 22 deletions

View File

@ -76,6 +76,7 @@ export class CatalogEntityItem<T extends CatalogEntity> implements ItemObject {
return this.labels return this.labels
.map(label => ( .map(label => (
<Badge <Badge
scrollable
className={styles.badge} className={styles.badge}
key={label} key={label}
label={label} label={label}

View File

@ -264,7 +264,7 @@ export class Catalog extends React.Component<Props> {
{ title: "Name", className: styles.entityName, sortBy: sortBy.name, id: "name" }, { title: "Name", className: styles.entityName, sortBy: sortBy.name, id: "name" },
!activeCategory && { title: "Kind", sortBy: sortBy.kind, id: "kind" }, !activeCategory && { title: "Kind", sortBy: sortBy.kind, id: "kind" },
{ title: "Source", className: styles.sourceCell, sortBy: sortBy.source, id: "source" }, { title: "Source", className: styles.sourceCell, sortBy: sortBy.source, id: "source" },
{ title: "Labels", className: styles.labelsCell, id: "labels" }, { title: "Labels", className: `${styles.labelsCell} scrollable`, id: "labels" },
{ title: "Status", className: styles.statusCell, sortBy: sortBy.status, id: "status" }, { title: "Status", className: styles.statusCell, sortBy: sortBy.status, id: "status" },
].filter(Boolean)} ].filter(Boolean)}
customizeTableRowProps={item => ({ customizeTableRowProps={item => ({

View File

@ -87,7 +87,7 @@ export class HorizontalPodAutoscalers extends React.Component<Props> {
{ title: "Max Pods", className: "max-pods", sortBy: columnId.maxPods, id: columnId.maxPods }, { title: "Max Pods", className: "max-pods", sortBy: columnId.maxPods, id: columnId.maxPods },
{ title: "Replicas", className: "replicas", sortBy: columnId.replicas, id: columnId.replicas }, { title: "Replicas", className: "replicas", sortBy: columnId.replicas, id: columnId.replicas },
{ title: "Age", className: "age", sortBy: columnId.age, id: columnId.age }, { title: "Age", className: "age", sortBy: columnId.age, id: columnId.age },
{ title: "Status", className: "status", id: columnId.status }, { title: "Status", className: "status scrollable", id: columnId.status },
]} ]}
renderTableContents={hpa => [ renderTableContents={hpa => [
hpa.getName(), hpa.getName(),
@ -108,6 +108,7 @@ export class HorizontalPodAutoscalers extends React.Component<Props> {
tooltip={tooltip} tooltip={tooltip}
className={cssNames(type.toLowerCase())} className={cssNames(type.toLowerCase())}
expandable={false} expandable={false}
scrollable={true}
/> />
); );
}), }),

View File

@ -69,7 +69,7 @@ export class Secrets extends React.Component<Props> {
{ title: "Name", className: "name", sortBy: columnId.name, id: columnId.name }, { title: "Name", className: "name", sortBy: columnId.name, id: columnId.name },
{ className: "warning", showWithColumn: columnId.name }, { className: "warning", showWithColumn: columnId.name },
{ title: "Namespace", className: "namespace", sortBy: columnId.namespace, id: columnId.namespace }, { title: "Namespace", className: "namespace", sortBy: columnId.namespace, id: columnId.namespace },
{ title: "Labels", className: "labels", sortBy: columnId.labels, id: columnId.labels }, { title: "Labels", className: "labels scrollable", sortBy: columnId.labels, id: columnId.labels },
{ title: "Keys", className: "keys", sortBy: columnId.keys, id: columnId.keys }, { title: "Keys", className: "keys", sortBy: columnId.keys, id: columnId.keys },
{ title: "Type", className: "type", sortBy: columnId.type, id: columnId.type }, { title: "Type", className: "type", sortBy: columnId.type, id: columnId.type },
{ title: "Age", className: "age", sortBy: columnId.age, id: columnId.age }, { title: "Age", className: "age", sortBy: columnId.age, id: columnId.age },
@ -78,7 +78,7 @@ export class Secrets extends React.Component<Props> {
secret.getName(), secret.getName(),
<KubeObjectStatusIcon key="icon" object={secret} />, <KubeObjectStatusIcon key="icon" object={secret} />,
secret.getNs(), secret.getNs(),
secret.getLabels().map(label => <Badge key={label} label={label} expandable={false}/>), secret.getLabels().map(label => <Badge scrollable key={label} label={label} expandable={false}/>),
secret.getKeys().join(", "), secret.getKeys().join(", "),
secret.type, secret.type,
secret.getAge(), secret.getAge(),

View File

@ -64,14 +64,14 @@ export class Namespaces extends React.Component<Props> {
renderTableHeader={[ renderTableHeader={[
{ title: "Name", className: "name", sortBy: columnId.name, id: columnId.name }, { title: "Name", className: "name", sortBy: columnId.name, id: columnId.name },
{ className: "warning", showWithColumn: columnId.name }, { className: "warning", showWithColumn: columnId.name },
{ title: "Labels", className: "labels", sortBy: columnId.labels, id: columnId.labels }, { title: "Labels", className: "labels scrollable", sortBy: columnId.labels, id: columnId.labels },
{ title: "Age", className: "age", sortBy: columnId.age, id: columnId.age }, { title: "Age", className: "age", sortBy: columnId.age, id: columnId.age },
{ title: "Status", className: "status", sortBy: columnId.status, id: columnId.status }, { title: "Status", className: "status", sortBy: columnId.status, id: columnId.status },
]} ]}
renderTableContents={item => [ renderTableContents={item => [
item.getName(), item.getName(),
<KubeObjectStatusIcon key="icon" object={item} />, <KubeObjectStatusIcon key="icon" object={item} />,
item.getLabels().map(label => <Badge key={label} label={label}/>), item.getLabels().map(label => <Badge scrollable key={label} label={label}/>),
item.getAge(), item.getAge(),
{ title: item.getStatus(), className: item.getStatus().toLowerCase() }, { title: item.getStatus(), className: item.getStatus().toLowerCase() },
]} ]}

View File

@ -50,12 +50,6 @@ export class DaemonSets extends React.Component<Props> {
return daemonSetStore.getChildPods(daemonSet).length; return daemonSetStore.getChildPods(daemonSet).length;
} }
renderNodeSelector(daemonSet: DaemonSet) {
return daemonSet.getNodeSelectors().map(selector => (
<Badge key={selector} label={selector}/>
));
}
render() { render() {
return ( return (
<KubeObjectListLayout <KubeObjectListLayout
@ -79,7 +73,7 @@ export class DaemonSets extends React.Component<Props> {
{ title: "Namespace", className: "namespace", sortBy: columnId.namespace, id: columnId.namespace }, { title: "Namespace", className: "namespace", sortBy: columnId.namespace, id: columnId.namespace },
{ title: "Pods", className: "pods", sortBy: columnId.pods, id: columnId.pods }, { title: "Pods", className: "pods", sortBy: columnId.pods, id: columnId.pods },
{ className: "warning", showWithColumn: columnId.pods }, { className: "warning", showWithColumn: columnId.pods },
{ title: "Node Selector", className: "labels", id: columnId.labels }, { title: "Node Selector", className: "labels scrollable", id: columnId.labels },
{ title: "Age", className: "age", sortBy: columnId.age, id: columnId.age }, { title: "Age", className: "age", sortBy: columnId.age, id: columnId.age },
]} ]}
renderTableContents={daemonSet => [ renderTableContents={daemonSet => [
@ -87,7 +81,9 @@ export class DaemonSets extends React.Component<Props> {
daemonSet.getNs(), daemonSet.getNs(),
this.getPodsLength(daemonSet), this.getPodsLength(daemonSet),
<KubeObjectStatusIcon key="icon" object={daemonSet}/>, <KubeObjectStatusIcon key="icon" object={daemonSet}/>,
this.renderNodeSelector(daemonSet), daemonSet.getNodeSelectors().map(selector => (
<Badge key={selector} label={selector} scrollable/>
)),
daemonSet.getAge(), daemonSet.getAge(),
]} ]}
/> />

View File

@ -25,6 +25,18 @@
max-width: 100%; max-width: 100%;
} }
// might be used in a scrollable area with {overflow: auto}
.badge.scrollable {
max-width: unset;
&:not(.isExpanded) {
white-space: unset;
overflow: unset;
text-overflow: unset;
}
}
.badge.interactive:hover { .badge.interactive:hover {
background-color: var(--mainBackground); background-color: var(--mainBackground);
cursor: pointer; cursor: pointer;

View File

@ -34,6 +34,7 @@ export interface BadgeProps extends React.HTMLAttributes<any>, TooltipDecoratorP
label?: React.ReactNode; label?: React.ReactNode;
expandable?: boolean; expandable?: boolean;
disabled?: boolean; disabled?: boolean;
scrollable?: boolean;
} }
// Common handler for all Badge instances // Common handler for all Badge instances
@ -81,7 +82,7 @@ export class Badge extends React.Component<BadgeProps> {
} }
render() { render() {
const { className, label, disabled, small, children, flat, expandable, ...elemProps } = this.props; const { className, label, disabled, scrollable, small, children, flat, expandable, ...elemProps } = this.props;
const clickable = Boolean(this.props.onClick) || this.isExpandable; const clickable = Boolean(this.props.onClick) || this.isExpandable;
const classNames = cssNames(styles.badge, className, { const classNames = cssNames(styles.badge, className, {
[styles.small]: small, [styles.small]: small,
@ -90,6 +91,7 @@ export class Badge extends React.Component<BadgeProps> {
[styles.interactive]: this.isExpandable, [styles.interactive]: this.isExpandable,
[styles.isExpanded]: this.isExpanded, [styles.isExpanded]: this.isExpanded,
[styles.disabled]: disabled, [styles.disabled]: disabled,
[styles.scrollable]: scrollable,
}); });
return ( return (

View File

@ -49,12 +49,6 @@
position: relative; position: relative;
min-height: 200px; min-height: 200px;
} }
.TableCell {
&.menu {
@include table-cell-action;
}
}
} }
.ItemListLayoutVisibilityMenu { .ItemListLayoutVisibilityMenu {

View File

@ -25,6 +25,20 @@
overflow: hidden; overflow: hidden;
text-overflow: ellipsis; text-overflow: ellipsis;
&.menu {
@include table-cell-action;
}
&.scrollable {
@include hidden-scrollbar;
display: flex;
align-items: center;
:not(:last-of-type) {
margin-right: 0.5em;
}
}
&.checkbox { &.checkbox {
display: flex; display: flex;
flex: 0 0 32px !important; flex: 0 0 32px !important;

View File

@ -33,6 +33,7 @@ export interface TableCellProps extends React.DOMAttributes<HTMLDivElement> {
id?: string; // used for configuration visibility of columns id?: string; // used for configuration visibility of columns
className?: string; className?: string;
title?: ReactNode; title?: ReactNode;
scrollable?: boolean; // content inside could be scrolled
checkbox?: boolean; // render cell with a checkbox checkbox?: boolean; // render cell with a checkbox
isChecked?: boolean; // mark checkbox as checked or not isChecked?: boolean; // mark checkbox as checked or not
renderBoolean?: boolean; // show "true" or "false" for all of the children elements are "typeof boolean" renderBoolean?: boolean; // show "true" or "false" for all of the children elements are "typeof boolean"
@ -88,9 +89,11 @@ export class TableCell extends React.Component<TableCellProps> {
} }
render() { render() {
const { className, checkbox, isChecked, sortBy, _sort, _sorting, _nowrap, children, title, renderBoolean: displayBoolean, showWithColumn, ...cellProps } = this.props; const { className, checkbox, isChecked, scrollable, sortBy, _sort, _sorting, _nowrap, children, title, renderBoolean: displayBoolean, showWithColumn, ...cellProps } = this.props;
const classNames = cssNames("TableCell", className, { const classNames = cssNames("TableCell", className, {
checkbox, checkbox,
scrollable,
nowrap: _nowrap, nowrap: _nowrap,
sorting: this.isSortable, sorting: this.isSortable,
}); });