Skip to content
This repository has been archived by the owner on Oct 21, 2024. It is now read-only.

Commit

Permalink
refactor: bug fixes
Browse files Browse the repository at this point in the history
  • Loading branch information
johanlahti committed Sep 26, 2023
1 parent e66aa62 commit ef85b3b
Show file tree
Hide file tree
Showing 4 changed files with 114 additions and 37 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,12 @@
import { IListboxResource } from '../../hooks/types';
import { IColumn } from './interfaces';

export const isSadItem = (item: IListboxResource) => !!(item?.alwaysExpanded && !item?.expand);

export const getSadItems = (items: IListboxResource[]) => items.filter((item) => isSadItem(item));

export function getSadItem(column: IColumn) {
const sadItem = column.items?.filter((item) => item.alwaysExpanded && !item.expand)[0];
const sadItem = getSadItems(column?.items || []).pop(); // return the last item, if many
return sadItem;
}

Expand All @@ -14,25 +18,25 @@ export function moveOverflowItemToColumn(columnItems: IListboxResource[], overfl
const overflowIndex = newOverflowing.findIndex((itm: IListboxResource) => !itm.alwaysExpanded);
if (overflowIndex > -1) {
const itemToColumn = newOverflowing.splice(overflowIndex, 1)[0];
newColumnItems.splice(0, 0, itemToColumn);
newColumnItems.push(itemToColumn);
}
return {
columnItems: newColumnItems as IListboxResource[],
overflowing: newOverflowing as IListboxResource[],
};
}

export function moveSadItemToOverflow(sadItem: IListboxResource, parentColumn: IColumn, overflowing: IListboxResource[]) {
const sadItemIndex = parentColumn.items?.indexOf(sadItem) as number;
if (sadItemIndex === -1) {
export function moveItemToOverflow(itemToMove: IListboxResource, parentColumn: IColumn, overflowing: IListboxResource[]) {
const itemToMoveIndex = parentColumn.items?.indexOf(itemToMove) as number;
if (itemToMoveIndex === -1) {
return {
parentColumnItems: parentColumn.items as IListboxResource[],
columnItems: parentColumn.items as IListboxResource[],
overflowing: overflowing as IListboxResource[],
};
}
parentColumn.items?.splice(sadItemIndex, 1); // remove from parent column
parentColumn.items?.splice(itemToMoveIndex, 1); // remove from parent column
return {
columnItems: parentColumn.items as IListboxResource[],
overflowing: [...overflowing, { ...sadItem, expand: false }] as IListboxResource[],
overflowing: [{ ...itemToMove, expand: false }, ...overflowing] as IListboxResource[],
};
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { IListboxResource, ListboxResourcesArr } from '../../hooks/types';
import { getSadItem, moveOverflowItemToColumn, moveSadItemToOverflow } from './distribute-always-expanded';
import { getSadItem, moveOverflowItemToColumn, moveItemToOverflow } from './distribute-always-expanded';
import {
countListBoxes,
doAllFit,
Expand All @@ -19,6 +19,17 @@ import { ExpandProps, IColumn, ISize } from './interfaces';

/* eslint-disable no-param-reassign */

export function sortColumnItemsByFieldOrder(columns: IColumn[], resources: IListboxResource[]) {
const dataOrder = resources.map((item) => item?.id);
columns.forEach((column) => {
column.items?.sort((a, b) => {
const aIx = dataOrder.indexOf(a.id);
const bIx = dataOrder.indexOf(b.id);
return aIx - bIx;
});
});
}

export const hasHeader = (resource?: IListboxResource) => (!!resource?.layout && resource.layout.title !== '' && resource.layout.showTitle !== false);

export function calculateColumns(size: ISize, columns: IColumn[], isSmallDevice: boolean, expandProps: ExpandProps, resources: ListboxResourcesArr = []) {
Expand Down Expand Up @@ -120,6 +131,8 @@ export function assignListboxesToColumns(columns: IColumn[], resources: IListbox
column.items = resourcesTail.slice(0, column.itemCount);
resourcesTail = resourcesTail.slice(column.itemCount);
});

sortColumnItemsByFieldOrder(columns, resources);
return { columns, overflowing: resourcesTail };
}

Expand All @@ -135,10 +148,17 @@ function expandUntilFull(sortedItems: IListboxResource[] | undefined, initialLef
if (!sortedItems) return;
let i;
let item;
let itemFits;
let fitsExpanded;
let expandedHeight;
let leftOverHeight = initialLeftOverHeight;

// sortedItems.forEach((itm) => {
// if (!itm.alwaysExpanded) {
// itm.expand = false;
// itm.height = DEFAULT_CSS_HEIGHT;
// }
// });

for (i = 0; i < sortedItems.length; i++) {
item = sortedItems[i];
if (item.cardinal && !item.fullyExpanded) {
Expand All @@ -147,9 +167,9 @@ function expandUntilFull(sortedItems: IListboxResource[] | undefined, initialLef
const itemsSliced = [...sortedItems.slice(0, i), ...sortedItems.slice(i + 1)];
leftOverHeight = initialLeftOverHeight - estimateColumnHeight({ items: itemsSliced, hiddenItems });
expandedHeight = getListBoxMaxHeight(item) + ITEM_SPACING;
itemFits = leftOverHeight >= expandedHeight;
item.fits = itemFits; // fits fully expanded
if (itemFits && !item.neverExpanded) {
fitsExpanded = leftOverHeight >= expandedHeight;
item.fitsExpanded = fitsExpanded; // fits fully expanded (or collapsed, if neverExpanded is true)
if (fitsExpanded && !item.neverExpanded) {
item.expand = true;
setFullyExpanded(item);
} else if (item.neverExpanded) {
Expand Down Expand Up @@ -259,7 +279,7 @@ export const calculateExpandPriority = (columns: IColumn[], size: ISize, expandP
item.height = `${size.height - estimateColumnHeight({ items: collapsedItems }) - spacing}px`;
}
}
item.expand = item.expand || !!(item.alwaysExpanded && item.fits);
item.expand = item.expand || !!(item.alwaysExpanded && item.fitsExpanded);
setFullyExpanded(item);
}
}
Expand All @@ -276,6 +296,21 @@ export const calculateExpandPriority = (columns: IColumn[], size: ISize, expandP
return { columns, expandedItemsCount: allExpandedItems.length };
};

export function adjustOverflowColumn(overflowColumn: IColumn, size: ISize, overflowing: IListboxResource[] = []) {
// Is there enough room for the newly added overflow dropdown?
// If not, move one item in the overflow column into the dropdown.
// const newOverflowing = [...overflowing];
const tooBig = (size.height < estimateColumnHeight(overflowColumn)) && overflowColumn.items?.length;
const itemToMove = overflowColumn.items?.[overflowColumn.items.length - 1];
if (tooBig && itemToMove) {
const movedItemsObj = moveItemToOverflow(itemToMove, overflowColumn, overflowing);
overflowing.length = 0;
overflowing.push(...movedItemsObj.overflowing);
overflowColumn.items = movedItemsObj.columnItems;
overflowColumn.itemCount = overflowColumn.items?.length ?? 0;
}
}

export function moveAlwaysExpandedToOverflow(columns: IColumn[], overflowing: IListboxResource[], size: ISize) {
const newColumns = [...columns];
const newOverflowing = [...overflowing];
Expand All @@ -284,35 +319,23 @@ export function moveAlwaysExpandedToOverflow(columns: IColumn[], overflowing: IL
const sadBecameHappy = newColumns.some((column) => {
const sadItem = getSadItem(column);
if (sadItem) {
let changedItems = moveSadItemToOverflow(sadItem, column, newOverflowing);
let changedItemsObj = moveItemToOverflow(sadItem, column, newOverflowing);
// Move one overflow item which is not alwaysExpanded (if any) to the
// column where we previously found the sad item.
changedItems = moveOverflowItemToColumn(changedItems.columnItems || [], changedItems.overflowing);
column.items = changedItems.columnItems;
changedItemsObj = moveOverflowItemToColumn(changedItemsObj.columnItems || [], changedItemsObj.overflowing);
column.items = changedItemsObj.columnItems;
newOverflowing.length = 0;
newOverflowing.push(...changedItems.overflowing);
newOverflowing.push(...changedItemsObj.overflowing);
column.itemCount = column.items?.length ?? 0;
return true; // this breaks the loop
}
return false;
});

if (newOverflowing.length > overflowing.length) {
if (!overflowColumn.hiddenItems) {
overflowColumn.hiddenItems = true;

// Is there enough room for the newly added overflow dropdown?
// If not, move one item in the overflow column into the dropdown.
const tooBig = size.height < estimateColumnHeight(overflowColumn) && overflowColumn.items?.length;
const itemToMove = overflowColumn.items?.[overflowColumn.items.length - 1];
if (tooBig && itemToMove) {
const movedItems = moveSadItemToOverflow(itemToMove, overflowColumn, newOverflowing);
newOverflowing.length = 0;
newOverflowing.push(...movedItems.overflowing);
overflowColumn.items = movedItems.columnItems;
overflowColumn.itemCount = overflowColumn.items?.length ?? 0;
}
}
if (sadBecameHappy) {
// if (!overflowColumn.hiddenItems) {
overflowColumn.hiddenItems = true;
adjustOverflowColumn(overflowColumn, size, newOverflowing);
}

return {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,14 @@ import {
setDefaultValues, balanceColumns, calculateColumns, calculateExpandPriority, assignListboxesToColumns,
hasHeader,
moveAlwaysExpandedToOverflow,
adjustOverflowColumn,
} from './distribute-resources';
import { ExpandProps, IColumn, ISize } from './interfaces';
import { IEnv } from '../../types/types';
import { IListboxResource } from '../../hooks/types';
import { IStore } from '../../store';
import { getSadItems, moveItemToOverflow } from './distribute-always-expanded';
import { estimateColumnHeight } from './distribute-resources-counting';

const prepareRenderTracker = (listboxCount: number, renderTracker?: RenderTrackerService) => {
renderTracker?.setNumberOfListboxes(listboxCount);
Expand Down Expand Up @@ -57,15 +60,56 @@ export default function useHandleResize({
alwaysExpanded: resources[0].layout?.layoutOptions?.collapseMode === 'never',
};

let columnsTemp;
let overflowing;
let columnsTemp: IColumn[];
let overflowing: IListboxResource[];
let expandedItemsCount = 0;

columnsTemp = calculateColumns(size, [], isSmallDevice, expandProps, resources);
columnsTemp = balanceColumns(size, columnsTemp, resources, isSmallDevice, expandProps);

({ columns: columnsTemp, overflowing } = assignListboxesToColumns(columnsTemp, resources, isSmallDevice));
({ columns: columnsTemp, expandedItemsCount } = calculateExpandPriority(columnsTemp, size, expandProps, isSmallDevice));

// If there is one or more always expanded listboxes which cannot expand (i.e. a "sad" item), move the last
// collapsable listbox to the overflow menu until either a) all sad items are happy, or b) all collapsable
// items have been moved. Only after that, we will start moving always expanded listboxes to overflow.
const overflowColumn = columnsTemp[columnsTemp.length - 1];
const isSingleColumn = columnsTemp.length === 1;
if (isSingleColumn) {
columnsTemp[0].expand = true;
}

[...columnsTemp].reverse().slice(0).forEach((column: IColumn) => {
const { items = [] } = column;
[...items].some(() => {
const sadItems = getSadItems(column.items || []);
const columnHasSadItems = sadItems.length > 0;
const lastCollapsable = [...items].reverse().find((itm: IListboxResource) => !itm.alwaysExpanded && !overflowing.includes(itm));
if (!columnHasSadItems || !lastCollapsable) {
return true; // nothing more we can do, break loop
}
const movedItemsObj = moveItemToOverflow(lastCollapsable, column, overflowing);
overflowing = [...movedItemsObj.overflowing];
const columnIndex = columnsTemp.indexOf(column);
columnsTemp[columnIndex].items = movedItemsObj.columnItems;
columnsTemp[columnIndex].itemCount = movedItemsObj.columnItems.length;
overflowColumn.hiddenItems = true;

sadItems[0].expand = true;
const tooBig = estimateColumnHeight(column) > size.height;
if (tooBig) {
sadItems[0].expand = false;
}

columnsTemp = balanceColumns(size, columnsTemp, resources, isSmallDevice, expandProps);
({ columns: columnsTemp, expandedItemsCount } = calculateExpandPriority(columnsTemp, size, expandProps, isSmallDevice));
return false;
});
});

columnsTemp = balanceColumns(size, columnsTemp, resources, isSmallDevice, expandProps);
({ columns: columnsTemp, expandedItemsCount } = calculateExpandPriority(columnsTemp, size, expandProps, isSmallDevice));

// Move listboxes which should always be expanded, but do not have room to expand; into the overflow dropdown.
// This is done iteratively by:
// 1. Moving one listbox to overflow
Expand All @@ -80,6 +124,12 @@ export default function useHandleResize({
break;
}
}

if (!isSingleColumn) {
// Ensure the overflow column adjusts for the overflow dropdown button, if any.
adjustOverflowColumn(columnsTemp[columnsTemp.length - 1], size, overflowing);
}

columnsTemp = balanceColumns(size, columnsTemp, resources, isSmallDevice, expandProps);
({ columns: columnsTemp, expandedItemsCount } = calculateExpandPriority(columnsTemp, size, expandProps, isSmallDevice));

Expand Down
2 changes: 1 addition & 1 deletion packages/sn-filter-pane/src/hooks/types/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ export interface IListboxResource {
dense: boolean;
neverExpanded: boolean;
alwaysExpanded: boolean;
fits: boolean;
fitsExpanded: boolean;
hasHeader: boolean;
}

Expand Down

0 comments on commit ef85b3b

Please sign in to comment.