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:
parent
159c240a80
commit
4eb9a689ba
@ -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}
|
||||||
|
|||||||
@ -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 => ({
|
||||||
|
|||||||
@ -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}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
}),
|
}),
|
||||||
|
|||||||
@ -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(),
|
||||||
|
|||||||
@ -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() },
|
||||||
]}
|
]}
|
||||||
|
|||||||
@ -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(),
|
||||||
]}
|
]}
|
||||||
/>
|
/>
|
||||||
|
|||||||
@ -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;
|
||||||
|
|||||||
@ -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 (
|
||||||
|
|||||||
@ -49,12 +49,6 @@
|
|||||||
position: relative;
|
position: relative;
|
||||||
min-height: 200px;
|
min-height: 200px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.TableCell {
|
|
||||||
&.menu {
|
|
||||||
@include table-cell-action;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.ItemListLayoutVisibilityMenu {
|
.ItemListLayoutVisibilityMenu {
|
||||||
|
|||||||
@ -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;
|
||||||
|
|||||||
@ -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,
|
||||||
});
|
});
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user