forked from extern/egroupware
Better nm column selection
This commit is contained in:
parent
733770ea36
commit
714ef5d4c9
297
api/js/etemplate/Et2Nextmatch/ColumnSelection.ts
Normal file
297
api/js/etemplate/Et2Nextmatch/ColumnSelection.ts
Normal file
@ -0,0 +1,297 @@
|
||||
/**
|
||||
* Column selector for nextmatch
|
||||
*/
|
||||
import {classMap, css, html, LitElement, PropertyValues, repeat, TemplateResult} from "@lion/core";
|
||||
import {Et2InputWidget} from "../Et2InputWidget/Et2InputWidget";
|
||||
import {et2_nextmatch_customfields} from "../et2_extension_nextmatch";
|
||||
import shoelace from "../Styles/shoelace";
|
||||
import {et2_dataview_column} from "../et2_dataview_model_columns";
|
||||
import {et2_customfields_list} from "../et2_extension_customfields";
|
||||
import Sortable from "sortablejs/modular/sortable.complete.esm";
|
||||
import {cssImage} from "../Et2Widget/Et2Widget";
|
||||
import {SlMenuItem} from "@shoelace-style/shoelace";
|
||||
import {Et2Select} from "../Et2Select/Et2Select";
|
||||
|
||||
export class Et2ColumnSelection extends Et2InputWidget(LitElement)
|
||||
{
|
||||
static get styles()
|
||||
{
|
||||
return [
|
||||
// Parent (SlSelect) returns a single cssResult, not an array
|
||||
super.styles,
|
||||
shoelace,
|
||||
css`
|
||||
:host {
|
||||
height: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
flex: 1 0 auto;
|
||||
--icon-width: 20px;
|
||||
}
|
||||
.title {
|
||||
font-size: var(--sl-font-size-large);
|
||||
color: var(--sl-color-neutral-0);
|
||||
background-color: var(--sl-color-primary-600);
|
||||
}
|
||||
.title sl-icon {
|
||||
vertical-align: middle;
|
||||
cursor: pointer;
|
||||
}
|
||||
sl-menu {
|
||||
flex: 1 1 auto;
|
||||
overflow-y: auto;
|
||||
}
|
||||
/* Drag handle on columns (not individual custom fields or search letter) */
|
||||
sl-menu > .select_row::part(base) {
|
||||
padding-left: 10px;
|
||||
}
|
||||
sl-menu > .column::part(base) {
|
||||
background-image: ${cssImage("splitter_vert")};
|
||||
background-position: 3px 1.5ex;
|
||||
background-repeat: no-repeat;
|
||||
cursor: grab;
|
||||
}
|
||||
/* Change vertical alignment of CF checkbox line to up with title, not middle */
|
||||
.custom_fields::part(base) {
|
||||
align-items: baseline;
|
||||
}
|
||||
`
|
||||
]
|
||||
}
|
||||
|
||||
static get properties()
|
||||
{
|
||||
return {
|
||||
/**
|
||||
* List of currently selected columns
|
||||
*/
|
||||
value: {type: Object},
|
||||
|
||||
autoRefresh: {type: Number}
|
||||
}
|
||||
}
|
||||
|
||||
private __columns = [];
|
||||
private __autoRefresh : number | false = false;
|
||||
private sort : Sortable;
|
||||
|
||||
constructor(...args : any[])
|
||||
{
|
||||
super(...args);
|
||||
|
||||
this.columnClickHandler = this.columnClickHandler.bind(this);
|
||||
this.handleSelectAll = this.handleSelectAll.bind(this);
|
||||
}
|
||||
|
||||
connectedCallback()
|
||||
{
|
||||
super.connectedCallback();
|
||||
|
||||
this.updateComplete.then(() =>
|
||||
{
|
||||
this.sort = Sortable.create(this.shadowRoot.querySelector('sl-menu'), {
|
||||
ghostClass: 'ui-fav-sortable-placeholder',
|
||||
draggable: 'sl-menu-item.column',
|
||||
dataIdAttr: 'value',
|
||||
direction: 'vertical',
|
||||
delay: 25
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
protected firstUpdated(_changedProperties : PropertyValues)
|
||||
{
|
||||
super.firstUpdated(_changedProperties);
|
||||
|
||||
if(this._autoRefreshNode)
|
||||
{
|
||||
this._autoRefreshNode.select_options = {
|
||||
// Cause [unknown] problems with mail
|
||||
30: "30 seconds",
|
||||
//60: "1 Minute",
|
||||
180: "3 Minutes",
|
||||
300: "5 Minutes",
|
||||
900: "15 Minutes",
|
||||
1800: "30 Minutes"
|
||||
};
|
||||
}
|
||||
|
||||
if(this._preferenceNode)
|
||||
{
|
||||
this._preferenceNode.select_options = [
|
||||
{value: 'default', label: 'Default', title: 'Set these columns as the default'},
|
||||
{value: 'reset', label: 'Reset', title: "Reset all user's column preferences"},
|
||||
{value: 'force', label: 'Force', title: 'Force column preference so users cannot change it'}
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
protected render() : TemplateResult
|
||||
{
|
||||
return html`${this.headerTemplate()}
|
||||
<sl-menu @sl-select="${this.columnClickHandler}" part="columns">
|
||||
${repeat(this.__columns, (column) => column.id, (column) => this.rowTemplate(column))}
|
||||
</sl-menu>
|
||||
<et2-hbox class="dialogFooterToolbar">
|
||||
<slot name="buttons"></slot>
|
||||
${this.footerTemplate()}
|
||||
</et2-hbox>`;
|
||||
}
|
||||
|
||||
protected headerTemplate()
|
||||
{
|
||||
return html`
|
||||
<div class="title">
|
||||
<sl-icon name="check-all" @click=${this.handleSelectAll}></sl-icon>
|
||||
${this.egw().lang("Select columns")}
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
|
||||
protected footerTemplate()
|
||||
{
|
||||
let autoRefresh = html`
|
||||
<et2-select id="nm_autorefresh" empty_label="Refresh" statustext="Automatically refresh list"
|
||||
value="${this.__autoRefresh}">
|
||||
</et2-select>
|
||||
`;
|
||||
// Add default checkbox for admins
|
||||
const apps = this.egw().user('apps');
|
||||
|
||||
return html`
|
||||
${this.__autoRefresh !== false ? autoRefresh : ''}
|
||||
${!apps['admin'] ? '' : html`
|
||||
<et2-select id="default_preference" empty_label="${this.egw().lang("Preference")}">
|
||||
</et2-select>`
|
||||
}
|
||||
`;
|
||||
}
|
||||
|
||||
/**
|
||||
* Template for each individual column
|
||||
*
|
||||
* @param column
|
||||
* @returns {TemplateResult}
|
||||
* @protected
|
||||
*/
|
||||
protected rowTemplate(column) : TemplateResult
|
||||
{
|
||||
let isCustom = column.widget?.instanceOf(et2_nextmatch_customfields) || false;
|
||||
/* ?disabled=${column.visibility == et2_dataview_column.ET2_COL_VISIBILITY_DISABLED} */
|
||||
return html`
|
||||
<sl-menu-item
|
||||
value="${column.id}"
|
||||
?checked=${column.visibility == et2_dataview_column.ET2_COL_VISIBILITY_VISIBLE}
|
||||
|
||||
title="${column.title}"
|
||||
class="${classMap({
|
||||
select_row: true,
|
||||
custom_fields: isCustom,
|
||||
column: column.widget
|
||||
})}">
|
||||
${column.caption}
|
||||
<!-- Custom fields get listed separately -->
|
||||
${isCustom ? this.customFieldsTemplate(column) : ''}
|
||||
</sl-menu-item>`;
|
||||
}
|
||||
|
||||
/**
|
||||
* Template for all custom fields
|
||||
* Does not include "Custom fields", it's done as a regular column
|
||||
*
|
||||
* @param column
|
||||
* @returns {TemplateResult}
|
||||
* @protected
|
||||
*/
|
||||
protected customFieldsTemplate(column) : TemplateResult
|
||||
{
|
||||
// Custom fields get listed separately
|
||||
let widget = column.widget;
|
||||
if(jQuery.isEmptyObject((<et2_nextmatch_customfields><unknown>widget).customfields))
|
||||
{
|
||||
// No customfields defined, don't show column
|
||||
return html``;
|
||||
}
|
||||
return html`
|
||||
<sl-divider></sl-divider>
|
||||
${repeat(Object.values(widget.customfields), (field) => field.name, (field) =>
|
||||
{
|
||||
return this.rowTemplate({
|
||||
id: et2_customfields_list.PREFIX + field.name,
|
||||
caption: field.label,
|
||||
visibility: (widget.fields[field.name] ? et2_dataview_column.ET2_COL_VISIBILITY_VISIBLE : false)
|
||||
|
||||
});
|
||||
})}
|
||||
<sl-divider></sl-divider>`;
|
||||
}
|
||||
|
||||
columnClickHandler(event)
|
||||
{
|
||||
const item = event.detail.item;
|
||||
|
||||
// Toggle checked state
|
||||
item.checked = !item.checked;
|
||||
}
|
||||
|
||||
handleSelectAll(event)
|
||||
{
|
||||
let checked = (<SlMenuItem>this.shadowRoot.querySelector("sl-menu-item")).checked || false;
|
||||
this.shadowRoot.querySelectorAll('sl-menu-item').forEach((item) => {item.checked = !checked});
|
||||
}
|
||||
|
||||
set columns(new_columns)
|
||||
{
|
||||
this.__columns = new_columns;
|
||||
this.requestUpdate();
|
||||
}
|
||||
|
||||
get value()
|
||||
{
|
||||
let value = [];
|
||||
|
||||
this.sort.toArray().forEach((val) =>
|
||||
{
|
||||
let column = this.__columns.find((col) => col.id == val);
|
||||
let menuItem = <SlMenuItem>this.shadowRoot.querySelector("[value='" + val + "']");
|
||||
if(column && menuItem)
|
||||
{
|
||||
if(menuItem.checked)
|
||||
{
|
||||
value.push(val);
|
||||
}
|
||||
if(column.widget?.customfields)
|
||||
{
|
||||
menuItem.querySelectorAll("[value][checked]").forEach((cf : SlMenuItem) =>
|
||||
{
|
||||
value.push(cf.value);
|
||||
})
|
||||
}
|
||||
}
|
||||
});
|
||||
return value;
|
||||
}
|
||||
|
||||
private get _autoRefreshNode() : Et2Select
|
||||
{
|
||||
return (<Et2Select>this.shadowRoot?.querySelector("#nm_autorefresh"));
|
||||
}
|
||||
|
||||
private get _preferenceNode() : Et2Select
|
||||
{
|
||||
return (<Et2Select>this.shadowRoot.querySelector("#default_preference"))
|
||||
}
|
||||
|
||||
get autoRefresh() : number
|
||||
{
|
||||
return parseInt(this._autoRefreshNode?.value.toString()) || 0;
|
||||
}
|
||||
|
||||
set autoRefresh(new_value : number)
|
||||
{
|
||||
this.__autoRefresh = new_value;
|
||||
this.requestUpdate("autoRefresh");
|
||||
}
|
||||
}
|
||||
|
||||
customElements.define("et2-nextmatch-columnselection", Et2ColumnSelection);
|
@ -70,13 +70,13 @@ import {et2_template} from "./et2_widget_template";
|
||||
import {egw} from "../jsapi/egw_global";
|
||||
import {et2_compileLegacyJS} from "./et2_core_legacyJSFunctions";
|
||||
import {egwIsMobile} from "../egw_action/egw_action_common.js";
|
||||
import Sortable from 'sortablejs/modular/sortable.complete.esm.js';
|
||||
import {Et2Dialog} from "./Et2Dialog/Et2Dialog";
|
||||
import {Et2Select} from "./Et2Select/Et2Select";
|
||||
import {Et2Button} from "./Et2Button/Et2Button";
|
||||
import {loadWebComponent} from "./Et2Widget/Et2Widget";
|
||||
import {Et2AccountFilterHeader} from "./Nextmatch/Headers/AccountFilterHeader";
|
||||
import {Et2SelectCategory} from "./Et2Select/Et2SelectCategory";
|
||||
import {Et2ColumnSelection} from "./Et2Nextmatch/ColumnSelection";
|
||||
|
||||
//import {et2_selectAccount} from "./et2_widget_SelectAccount";
|
||||
let keep_import : Et2AccountFilterHeader
|
||||
@ -1938,111 +1938,47 @@ export class et2_nextmatch extends et2_DOMWidget implements et2_IResizeable, et2
|
||||
{
|
||||
var col = columnMgr.columns[i];
|
||||
const widget = this.columns[i].widget;
|
||||
|
||||
if(col.visibility == et2_dataview_column.ET2_COL_VISIBILITY_DISABLED ||
|
||||
col.visibility == et2_dataview_column.ET2_COL_VISIBILITY_ALWAYS_NOSELECT)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
if(col.caption)
|
||||
{
|
||||
columns.push({value: col.id, label: col.caption});
|
||||
if(col.visibility == et2_dataview_column.ET2_COL_VISIBILITY_VISIBLE) columns_selected.push(col.id);
|
||||
}
|
||||
// Custom fields get listed separately
|
||||
if(widget.instanceOf(et2_nextmatch_customfields))
|
||||
{
|
||||
if(jQuery.isEmptyObject((<et2_nextmatch_customfields><unknown>widget).customfields))
|
||||
{
|
||||
// No customfields defined, don't show column
|
||||
columns.pop();
|
||||
continue;
|
||||
}
|
||||
for(var field_name in (<et2_nextmatch_customfields><unknown>widget).customfields)
|
||||
{
|
||||
columns.push({
|
||||
value: et2_nextmatch_customfields.PREFIX + field_name, label: " - " +
|
||||
(<et2_nextmatch_customfields><unknown>widget).customfields[field_name].label
|
||||
});
|
||||
if(widget.options.fields[field_name])
|
||||
{
|
||||
columns_selected.push(et2_customfields_list.PREFIX + field_name);
|
||||
}
|
||||
}
|
||||
}
|
||||
columns.push({...col, widget: widget});
|
||||
}
|
||||
|
||||
// Letter search
|
||||
if(this.options.settings.lettersearch)
|
||||
{
|
||||
columns.push({value: LETTERS, label: egw.lang('Search letter')});
|
||||
if(this.header.lettersearch.is(':visible')) columns_selected.push(LETTERS);
|
||||
columns.push({
|
||||
id: LETTERS,
|
||||
caption: this.egw().lang('Search letter'),
|
||||
visibility: (this.header.lettersearch.is(':visible') ? et2_dataview_column.ET2_COL_VISIBILITY_VISIBLE : et2_dataview_column.ET2_COL_VISIBILITY_ALWAYS_NOSELECT)
|
||||
});
|
||||
}
|
||||
|
||||
// Build the popup
|
||||
if(!this.selectPopup)
|
||||
let selectPopup = new Et2ColumnSelection();
|
||||
selectPopup.setParent(this);
|
||||
selectPopup.columns = columns;
|
||||
if(!this.options.disable_autorefresh)
|
||||
{
|
||||
const select = <Et2Select>loadWebComponent("et2-select", {
|
||||
id: "columns",
|
||||
multiple: true,
|
||||
rows: 8,
|
||||
empty_label: this.egw().lang("select columns"),
|
||||
selected_first: false
|
||||
}, this);
|
||||
// Don't let options run through the loading stuff
|
||||
select.select_options = columns;
|
||||
select.value = columns_selected;
|
||||
selectPopup.autoRefresh = parseInt(this._get_autorefresh());
|
||||
}
|
||||
|
||||
let autoRefresh;
|
||||
let sort;
|
||||
if(!this.options.disable_autorefresh)
|
||||
const okButton = <Et2Button>loadWebComponent("et2-button", {
|
||||
image: "check",
|
||||
label: this.egw().lang("ok"),
|
||||
slot: "buttons"
|
||||
}, this);
|
||||
okButton.onclick = function()
|
||||
{
|
||||
// Update visibility
|
||||
const visibility = {};
|
||||
for(var i = 0; i < columnMgr.columns.length; i++)
|
||||
{
|
||||
autoRefresh = <Et2Select>loadWebComponent("et2-select", {
|
||||
empty_label: "Refresh",
|
||||
id: "nm_autorefresh",
|
||||
statustext: egw.lang("Automatically refresh list"),
|
||||
value: this._get_autorefresh()
|
||||
}, this);
|
||||
autoRefresh.select_options = {
|
||||
// Cause [unknown] problems with mail
|
||||
30: "30 seconds",
|
||||
//60: "1 Minute",
|
||||
180: "3 Minutes",
|
||||
300: "5 Minutes",
|
||||
900: "15 Minutes",
|
||||
1800: "30 Minutes"
|
||||
};
|
||||
}
|
||||
|
||||
const defaultCheck = <Et2Select>loadWebComponent("et2-select", {
|
||||
id: "nm_col_preference",
|
||||
empty_label: "Preference",
|
||||
value: this.options.settings.columns_forced ? 'force' : ''
|
||||
}, this);
|
||||
defaultCheck.select_options = [
|
||||
{value: 'default', label: 'Default', title: 'Set these columns as the default'},
|
||||
{value: 'reset', label: 'Reset', title: "Reset all user's column preferences"},
|
||||
{value: 'force', label: 'Force', title: 'Force column preference so users cannot change it'}
|
||||
];
|
||||
|
||||
const okButton = <Et2Button>loadWebComponent("et2-button", {
|
||||
image: "check",
|
||||
label: this.egw().lang("ok")
|
||||
}, this);
|
||||
okButton.onclick = function()
|
||||
{
|
||||
// Update visibility
|
||||
const visibility = {};
|
||||
for(var i = 0; i < columnMgr.columns.length; i++)
|
||||
const col = columnMgr.columns[i];
|
||||
if(col.caption && col.visibility !== et2_dataview_column.ET2_COL_VISIBILITY_ALWAYS_NOSELECT &&
|
||||
col.visibility !== et2_dataview_column.ET2_COL_VISIBILITY_DISABLED)
|
||||
{
|
||||
const col = columnMgr.columns[i];
|
||||
if(col.caption && col.visibility !== et2_dataview_column.ET2_COL_VISIBILITY_ALWAYS_NOSELECT &&
|
||||
col.visibility !== et2_dataview_column.ET2_COL_VISIBILITY_DISABLED)
|
||||
{
|
||||
visibility[col.id] = {visible: false};
|
||||
}
|
||||
}
|
||||
const value = select.value;
|
||||
const value = selectPopup.value;
|
||||
|
||||
// Update & remove letter filter
|
||||
if(self.header.lettersearch)
|
||||
@ -2058,7 +1994,6 @@ export class et2_nextmatch extends et2_DOMWidget implements et2_IResizeable, et2
|
||||
}
|
||||
self._set_lettersearch(show_letters);
|
||||
}
|
||||
|
||||
let column = 0;
|
||||
for(var i = 0; i < value.length; i++)
|
||||
{
|
||||
@ -2097,105 +2032,42 @@ export class et2_nextmatch extends et2_DOMWidget implements et2_IResizeable, et2
|
||||
}
|
||||
columnMgr.setColumnVisibilitySet(visibility);
|
||||
|
||||
this.sortedColumnsList = [];
|
||||
if(sort)
|
||||
{
|
||||
sort.toArray().forEach((data_id) =>
|
||||
{
|
||||
const value = select.getValue();
|
||||
if(data_id.match(/^col_/) && value.indexOf(data_id) != -1)
|
||||
{
|
||||
const col_id = data_id.replace('col_', '');
|
||||
const col_widget = self.columns[col_id].widget;
|
||||
if(col_widget.customfields)
|
||||
{
|
||||
self.sortedColumnsList.push(col_widget.id);
|
||||
for(let field_name in col_widget.customfields)
|
||||
{
|
||||
if(jQuery.isEmptyObject(col_widget.options.fields) || col_widget.options.fields[field_name] == true)
|
||||
{
|
||||
self.sortedColumnsList.push(et2_customfields_list.PREFIX + field_name);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
self.sortedColumnsList.push(self._getColumnName(col_widget));
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Hide popup
|
||||
self.selectPopup.toggle();
|
||||
|
||||
self.dataview.updateColumns();
|
||||
|
||||
// Auto refresh
|
||||
self._set_autorefresh(autoRefresh ? autoRefresh.get_value() : 0);
|
||||
self._set_autorefresh(selectPopup.autoRefresh);
|
||||
|
||||
// Set default or clear forced
|
||||
if(show_letters)
|
||||
{
|
||||
self.activeFilters.selectcols.push('lettersearch');
|
||||
}
|
||||
self.getInstanceManager().submit();
|
||||
|
||||
self.selectPopup = null;
|
||||
};
|
||||
|
||||
const cancelButton = <Et2Button>loadWebComponent("et2-button", {
|
||||
label: this.egw().lang("cancel"),
|
||||
image: "cancel"
|
||||
}, this);
|
||||
cancelButton.onclick = function()
|
||||
// Set default or clear forced
|
||||
if(show_letters)
|
||||
{
|
||||
self.selectPopup.toggle();
|
||||
self.selectPopup = null;
|
||||
};
|
||||
|
||||
select.updateComplete.then(() =>
|
||||
{
|
||||
window.setTimeout(() =>
|
||||
{
|
||||
sort = Sortable.create(select.shadowRoot.querySelector('.select__tags'), {
|
||||
ghostClass: 'ui-fav-sortable-placeholder',
|
||||
draggable: 'et2-tag',
|
||||
dataIdAttr: 'value',
|
||||
direction: 'vertical',
|
||||
delay: 25,
|
||||
|
||||
});
|
||||
}, 100);
|
||||
});
|
||||
|
||||
const $footerWrap = jQuery(document.createElement("div"))
|
||||
.addClass('dialogFooterToolbar')
|
||||
.append(okButton)
|
||||
.append(cancelButton);
|
||||
this.selectPopup = jQuery(document.createElement("div"))
|
||||
.addClass("colselection ui-dialog ui-widget-content")
|
||||
.append(select)
|
||||
.append($footerWrap)
|
||||
.appendTo(this.innerDiv);
|
||||
|
||||
// Add autorefresh
|
||||
if(autoRefresh)
|
||||
{
|
||||
$footerWrap.append(autoRefresh);
|
||||
self.activeFilters.selectcols.push('lettersearch');
|
||||
}
|
||||
self.getInstanceManager().submit();
|
||||
|
||||
// Add default checkbox for admins
|
||||
const apps = this.egw().user('apps');
|
||||
if(apps['admin'])
|
||||
{
|
||||
$footerWrap.append(defaultCheck);
|
||||
}
|
||||
}
|
||||
else
|
||||
self.selectPopup = null;
|
||||
};
|
||||
|
||||
const cancelButton = <Et2Button>loadWebComponent("et2-button", {
|
||||
label: this.egw().lang("cancel"),
|
||||
image: "cancel",
|
||||
slot: "buttons"
|
||||
}, this);
|
||||
cancelButton.onclick = function()
|
||||
{
|
||||
this.selectPopup.toggle();
|
||||
}
|
||||
self.selectPopup.toggle();
|
||||
};
|
||||
|
||||
selectPopup.append(okButton);
|
||||
selectPopup.append(cancelButton);
|
||||
|
||||
this.selectPopup = jQuery(document.createElement("div"))
|
||||
.addClass("colselection ui-dialog ui-widget-content")
|
||||
.append(selectPopup)
|
||||
.appendTo(this.innerDiv);
|
||||
|
||||
const t_position = jQuery(e.target).position();
|
||||
const s_position = this.div.position();
|
||||
const max_height = this.getDOMNode().getElementsByClassName('egwGridView_outer')[0]['tBodies'][0].clientHeight -
|
||||
@ -3791,10 +3663,12 @@ export class et2_nextmatch_header_bar extends et2_DOMWidget implements et2_INext
|
||||
this.nextmatch.applyFilters(set);
|
||||
});
|
||||
}
|
||||
// Sometimes the filter does not display the current value
|
||||
// Call sync to try to get it to display
|
||||
select.updateComplete.then(async() =>
|
||||
{
|
||||
await select.updateComplete;
|
||||
//select.syncValueFromItems();
|
||||
select.syncItemsFromValue();
|
||||
})
|
||||
return select;
|
||||
}
|
||||
|
@ -4003,10 +4003,6 @@ tr.disableIfNoEPL {
|
||||
border: 2px dashed silver;
|
||||
}
|
||||
|
||||
.colselection [id*="columns"]::part(tags) {
|
||||
max-height: 10em;
|
||||
}
|
||||
|
||||
.colselection .dialogFooterToolbar {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
|
Loading…
Reference in New Issue
Block a user