Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
81 changes: 81 additions & 0 deletions lib/public/app.css
Original file line number Diff line number Diff line change
Expand Up @@ -992,6 +992,87 @@ label {
}
}

/*
* The filters buttons and panel, and the header of the overview pages containing them, use a smaller font, as the pagination does.
* The header is the row directly containing the filters buttons, or the header-container used by most of the overview pages
*/
.filters-toolbar,
.filters-panel,
.header-container,
.flex-row:has(> .filters-toolbar) {
font-size: 0.875rem;
}

.filters-panel {
width: var(--ui-component-large);
}

/*
* Filters panel on tablets and phones: the panel is displayed below the navbar on the whole width of the screen
* (the popover position computed in javascript is overridden) and each filter label is displayed above its input
*/
@media screen and (max-width: 1023px) {
/*
* A table wider than the screen scrolls inside its own box instead of widening the whole page: otherwise the layout viewport of the
* phone gets wider than the screen, and the filters panel, positioned against it, is partly displayed out of the screen.
* Tables having their own scroll wrapper (the logs one) are left untouched
*/
table.table:not(.logs-table) {
display: block;
max-width: 100%;
overflow-x: auto;
}

.popover.filters-popover {
position: fixed !important;
top: 56px !important;
left: 8px !important;
right: 8px !important;
width: auto !important;
max-width: none !important;
max-height: 75vh;
}

.filters-panel {
width: 100%;
box-sizing: border-box;
}
}

@media screen and (max-width: 767px) {
/* The filters button, the active filters indicator and the other buttons and quick filters wrap on several lines instead of being squeezed */
.header-container,
.flex-row:has(> .filters-toolbar) {
max-height: none;
flex-wrap: wrap;
row-gap: 8px;
}

.header-container .flex-row,
.flex-row:has(> .filters-toolbar) .flex-row {
flex-wrap: wrap;
row-gap: 8px;
}

.header-container .active-filters-indicator,
.header-container label,
.flex-row:has(> .filters-toolbar) .active-filters-indicator,
.flex-row:has(> .filters-toolbar) label {
white-space: nowrap;
}

.filters-panel .filter-row {
flex-direction: column;
align-items: stretch;
row-gap: 4px;
}

.filters-panel .filter-label,
.filters-panel .filter-input {
width: 100%;
}
}

/* xl */
@media screen and (min-width: 1920px) {
.columns-3-xl {
Expand Down
11 changes: 6 additions & 5 deletions lib/public/components/Filters/common/filtersPanelPopover.js
Original file line number Diff line number Diff line change
Expand Up @@ -90,12 +90,12 @@ export const filtersSection = (filteringModel, filtersConfiguration, { profile:
.map(([columnKey, { name, filterTooltip, filter }]) =>
name
? [
h(`.flex-row.items-baseline.${columnKey}-filter`, [
h('.w-30.f5.flex-row.items-center.g2', [
h(`.flex-row.items-baseline.filter-row.${columnKey}-filter`, [
h('.w-30.f5.flex-row.items-center.g2.filter-label', [
name,
filterTooltip ? tooltip(info(), filterTooltip) : null,
]),
h('.w-70', typeof filter === 'function' ? filter(filteringModel) : filter),
h('.w-70.filter-input', typeof filter === 'function' ? filter(filteringModel) : filter),
]),
]
: typeof filter === 'function' ? filter(filteringModel) : filter),
Expand All @@ -114,7 +114,7 @@ const filtersToggleContent = (
filteringModel,
filtersConfiguration,
configuration = {},
) => h('.w-l.flex-column.p3.g3', [
) => h('.filters-panel.flex-column.p3.g3', [
filtersToggleContentHeader(filteringModel),
filtersSection(filteringModel, filtersConfiguration, configuration),
]);
Expand All @@ -134,6 +134,7 @@ const filtersPanelButton = (filteringModel, filtersConfiguration, configuration)
{
...PopoverTriggerPreConfiguration.click,
anchor: PopoverAnchors.RIGHT_START,
popoverClass: ['filters-popover'],
},
);

Expand Down Expand Up @@ -209,7 +210,7 @@ export const filtersPanelPopover = (filteringModel, filtersConfiguration, config
const hasActiveFilters = filteringModel.isAnyFilterActive();

return h(
'.flex-row.items-center.btn-group',
'.flex-row.items-center.btn-group.filters-toolbar',
[
filtersPanelButton(filteringModel, filtersConfiguration, configuration),
DropdownComponent(
Expand Down
4 changes: 3 additions & 1 deletion test/public/envs/overview.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -220,7 +220,9 @@ module.exports = () => {

// Not running env
envId = 'EIDO13i3D';
await pressElement(page, `tr[id='row${envId}'] .popover-trigger`);
// The popover of the previous environment is still opened: with a real mouse click, depending on the layout, the click could land on
// one of its links (opening an external page in a new tab, which stops the page from rendering and hangs the next tests)
await pressElement(page, `tr[id='row${envId}'] .popover-trigger`, true);
popover = await getPopoverSelector(await page.waitForSelector(`tr[id='row${envId}'] .popover-trigger`));

await expectLink(page, `${popover} :nth-child(1 of .external-link)`, {
Expand Down
41 changes: 41 additions & 0 deletions test/public/logs/overview.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -205,6 +205,47 @@ module.exports = () => {
}
});

it('should display the filters panel on the whole width of small screens', async () => {
const getFiltersPanelLayout = () => page.$eval('.filters-popover', (popover) => {
const { left, right } = popover.getBoundingClientRect();
const filterRow = popover.querySelector('.filter-row');
return {
fitsInViewport: left >= 0 && right <= document.documentElement.clientWidth,
labelIsAboveInput: window.getComputedStyle(filterRow).flexDirection === 'column',
};
});

try {
await page.setViewport({ width: 375, height: 812, deviceScaleFactor: 1 });
await goToPage(page, 'log-overview');
await pressElement(page, '#openFilterToggle');
await page.waitForSelector('.filters-popover .filter-row');
expect(await getFiltersPanelLayout()).to.eql({ fitsInViewport: true, labelIsAboveInput: true });

await page.setViewport({ width: 800, height: 1024, deviceScaleFactor: 1 });
expect(await getFiltersPanelLayout()).to.eql({ fitsInViewport: true, labelIsAboveInput: false });
} finally {
await page.setViewport({ width: 1400, height: 940, deviceScaleFactor: 1 });
}
});

it('should let the header of the page wrap instead of being squeezed on small screens', async () => {
try {
await page.setViewport({ width: 375, height: 812, deviceScaleFactor: 1 });
await goToPage(page, 'log-overview');
await page.waitForSelector('#main-action-bar');

const { overflows, maxHeight, flexWrap } = await page.$eval('#main-action-bar', (header) => ({
overflows: header.scrollWidth > header.clientWidth,
maxHeight: window.getComputedStyle(header).maxHeight,
flexWrap: window.getComputedStyle(header).flexWrap,
}));
expect({ overflows, maxHeight, flexWrap }).to.eql({ overflows: false, maxHeight: 'none', flexWrap: 'wrap' });
} finally {
await page.setViewport({ width: 1400, height: 940, deviceScaleFactor: 1 });
}
});

it('can sort by columns in ascending and descending manners', async () => {
// Close the filter panel
await waitForFirstRowToHaveId(page, 'row119');
Expand Down
Loading