Skip to content

Commit

Permalink
Merge branch 'sgratzl/cypress' of github.com:lineupjs/lineupjs into s…
Browse files Browse the repository at this point in the history
…gratzl/cypress
  • Loading branch information
sgratzl committed Apr 7, 2020
2 parents 137024e + 5dd1c16 commit 4a0f059
Show file tree
Hide file tree
Showing 10 changed files with 86 additions and 17 deletions.
19 changes: 15 additions & 4 deletions src/renderer/HistogramCellRenderer.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import {normalizedStatsBuilder, IStatistics, getNumberOfBins} from '../internal';
import {Column, IDataRow, IOrderedGroup, INumberColumn, INumbersColumn, isNumberColumn, isNumbersColumn, IMapAbleColumn, isMapAbleColumn, INumberFilter} from '../model';
import {Column, IDataRow, IOrderedGroup, INumberColumn, INumbersColumn, isNumberColumn, isNumbersColumn, IMapAbleColumn, isMapAbleColumn, Ranking} from '../model';
import InputNumberDialog from '../ui/dialogs/InputNumberDialog';
import {colorOf} from './impose';
import {IRenderContext, ERenderMode, ICellRendererFactory, IImposer, IRenderTasks, ICellRenderer, IGroupCellRenderer, ISummaryRenderer} from './interfaces';
Expand Down Expand Up @@ -142,13 +142,12 @@ export function createNumberFilter(col: INumberColumn & IMapAbleColumn, parent:

const updateFilter = initFilter(summaryNode, fContext);

const rerender = (filter?: INumberFilter) => {
const rerender = () => {
const ready = context.tasks.summaryNumberStats(col).then((r) => {
if (typeof r === 'symbol') {
return;
}
const {summary, data} = r;
currentFilter = createFilterInfo(col, filter);
updateFilter(data ? data.missing : (summary ? summary.missing : 0), currentFilter);
summaryNode.classList.toggle(cssClass('missing'), !summary);
if (!summary) {
Expand All @@ -164,11 +163,23 @@ export function createNumberFilter(col: INumberColumn & IMapAbleColumn, parent:
summaryNode.classList.remove(engineCssClass('loading'));
});
};

const ranking = col.findMyRanker()!;

if (ranking) {
ranking.on(`${Ranking.EVENT_ORDER_CHANGED}.numberFilter`, () => rerender());
}
rerender();

return {
cleanUp() {
if (ranking) {
ranking.on(`${Ranking.EVENT_ORDER_CHANGED}.numberFilter`, null);
}
},
reset() {
rerender(noNumberFilter());
currentFilter = createFilterInfo(col, noNumberFilter());
rerender();
},
submit() {
applyFilter(currentFilter.filterMissing, currentFilter.filterMin, currentFilter.filterMax);
Expand Down
2 changes: 2 additions & 0 deletions src/styles/_vars.scss
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,8 @@ $lu_hist_color: #c1c1c1;

$lu_engine_grip_gap: 5px !default;
$lu_engine_row_outline_width: 2px !default;
$lu_engine_resize_space: 50px !default;
$lu_engine_resize_animation_duration: 1000ms !default;

$lu_missing_dash_height: 3px !default;
$lu_missing_dash_width: 10px !default;
Expand Down
4 changes: 4 additions & 0 deletions src/styles/engine/_header.scss
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,10 @@
}
}

.#{$lu_css_prefix}-resizing {
cursor: col-resize !important;
}

// FIXME
.#{$lu_css_prefix}-dialog-sub-nested > section {
margin-bottom: $lu_engine_grip_gap + 15px;
Expand Down
17 changes: 14 additions & 3 deletions src/styles/engine/_index.scss
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,21 @@
box-sizing: border-box;
}

.le-footer {

.#{$engine_css_prefix}-footer {
// extra space to the right using a width for easier last column resizing
width: 50px;
width: $lu_engine_resize_space;
}

.#{$lu_css_prefix}-resize-helper {
display: none;
}

.#{$lu_css_prefix}-resize-helper.#{$lu_css_prefix}-resize-animated {
transition: transform $lu_engine_resize_animation_duration linear !important;
}

.#{$lu_css_prefix}-resize-helper.#{$lu_css_prefix}-resizing {
display: unset;
}

@import './header';
Expand Down
5 changes: 5 additions & 0 deletions src/styles/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,11 @@ export const CSS_PREFIX = getStyle('lu_css_prefix', 'lu');
/** @internal */
export const ENGINE_CSS_PREFIX = 'le';

/** @internal */
export const RESIZE_SPACE = parseInt(getStyle('lu_engine_resize_space', '50px'), 10);
/** @internal */
export const RESIZE_ANIMATION_DURATION = parseInt(getStyle('lu_engine_resize_animation_duration', '1000ms'), 10);

/** @internal */
export function cssClass(suffix?: string) {
return suffix? `${CSS_PREFIX}-${suffix}` : CSS_PREFIX;
Expand Down
10 changes: 9 additions & 1 deletion src/ui/EngineRenderer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import {DataProvider} from '../provider';
import {isSummaryGroup, groupEndLevel} from '../provider/internal';
import {IImposer, IRenderContext} from '../renderer';
import {chooseGroupRenderer, chooseRenderer, chooseSummaryRenderer, getPossibleRenderer} from '../renderer/renderers';
import {cssClass} from '../styles';
import {cssClass, engineCssClass} from '../styles';
import DialogManager from './dialogs/DialogManager';
import domElementCache from './domElementCache';
import EngineRanking, {IEngineRankingContext} from './EngineRanking';
Expand Down Expand Up @@ -123,6 +123,14 @@ export default class EngineRenderer extends AEventDispatcher {

this.table = new MultiTableRowRenderer(this.node, this.idPrefix);

{
// helper object for better resizing experience
const footer = this.table.node.querySelector(`.${engineCssClass('body')} .${engineCssClass('footer')}`)!;
const copy = <HTMLElement>footer.cloneNode(true);
copy.classList.add(cssClass('resize-helper'));
footer!.insertAdjacentElement('afterend', copy);
}

//apply rules
{

Expand Down
6 changes: 4 additions & 2 deletions src/ui/dialogs/GroupDialog.ts
Original file line number Diff line number Diff line change
Expand Up @@ -90,12 +90,14 @@ function sortOrder(node: HTMLElement, column: Column, idPrefix: string): IToolba
elems: `input[name=grouped], #${id}P`,
submit() {
const enabled = node.querySelector<HTMLInputElement>('input[name=grouped]:checked')!.value === 'true';
const order = Number.parseInt(node.querySelector<HTMLInputElement>(`#${id}P`)!.value, 10);
const order = Number.parseInt(node.querySelector<HTMLInputElement>(`#${id}P`)!.value, 10) - 1;
ranking.groupBy(column, !enabled ? -1 : order);
return true;
},
reset() {
// things need to be done?
node.querySelector<HTMLInputElement>('input[name=grouped][value=false]')!.checked = true;
node.querySelector<HTMLInputElement>(`#${id}P`)!.value = (current.length + (!enabled ? 1 : 0)).toString();
updateDisabled(true);
},
cancel() {
ranking.groupBy(column, current.indexOf(column));
Expand Down
9 changes: 7 additions & 2 deletions src/ui/dialogs/NumberFilterDialog.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import ADialog, {IDialogContext} from './ADialog';
/** @internal */
export default class NumberFilterDialog extends ADialog {
private readonly before: INumberFilter;
private handler: {reset: () => void, submit: () => void} | null = null;
private handler: {reset: () => void, submit: () => void, cleanUp: () => void} | null = null;

constructor(private readonly column: IMapAbleColumn, dialog: IDialogContext, private readonly ctx: IRankingHeaderContext) {
super(dialog, {
Expand All @@ -23,10 +23,15 @@ export default class NumberFilterDialog extends ADialog {
this.handler = createNumberFilter(this.column, node, {
dialogManager: this.ctx.dialogManager,
idPrefix: this.ctx.idPrefix,
tasks: this.ctx.provider.getTaskExecutor()
tasks: this.ctx.provider.getTaskExecutor(),
}, this.showLivePreviews());
}

cleanUp(action: 'cancel' | 'confirm' | 'handled') {
super.cleanUp(action);
this.handler!.cleanUp();
}

protected reset() {
this.handler!.reset();
}
Expand Down
6 changes: 4 additions & 2 deletions src/ui/dialogs/SortDialog.ts
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ function sortOrder(node: HTMLElement, column: Column, idPrefix: string, groupSor
elems: `input[name=sortorder], #${id}P`,
submit() {
const asc = node.querySelector<HTMLInputElement>('input[name=sortorder]:checked')!.value;
const priority = Number.parseInt(node.querySelector<HTMLInputElement>(`#${id}P`)!.value, 10);
const priority = Number.parseInt(node.querySelector<HTMLInputElement>(`#${id}P`)!.value, 10) - 1;

if (groupSortBy) {
ranking.groupSortBy(column, asc === 'asc', asc === 'none' ? -1 : priority);
Expand All @@ -97,7 +97,9 @@ function sortOrder(node: HTMLElement, column: Column, idPrefix: string, groupSor
return true;
},
reset() {
// things need to be done?
node.querySelector<HTMLInputElement>('input[name=sortorder][value=none]')!.checked = true;
node.querySelector<HTMLInputElement>(`#${id}P`)!.value = (current.length + (order.priority === undefined ? 1 : 0)).toString();
updateDisabled(true);
},
cancel() {
if (groupSortBy) {
Expand Down
25 changes: 22 additions & 3 deletions src/ui/header.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import {MIN_LABEL_WIDTH} from '../constants';
import {equalArrays, dragAble, dropAble, hasDnDType, IDropResult} from '../internal';
import {categoryOf, getSortType} from '../model';
import {createNestedDesc, createReduceDesc, createStackDesc, IColumnDesc, isArrayColumn, isBoxPlotColumn, isCategoricalColumn, isMapColumn, isNumberColumn, isNumbersColumn, Column, ImpositionCompositeColumn, ImpositionCompositesColumn, createImpositionDesc, createImpositionsDesc, ImpositionBoxPlotColumn, createImpositionBoxPlotDesc, CompositeColumn, IMultiLevelColumn, isMultiLevelColumn} from '../model';
import {aria, cssClass} from '../styles';
import {aria, cssClass, engineCssClass, RESIZE_ANIMATION_DURATION, RESIZE_SPACE} from '../styles';
import MoreColumnOptionsDialog from './dialogs/MoreColumnOptionsDialog';
import {IRankingHeaderContext, IToolbarAction, IOnClickHandler} from './interfaces';
import {getToolbar} from './toolbar';
Expand Down Expand Up @@ -288,22 +288,30 @@ function toggleToolbarIcons(node: HTMLElement, col: Column, defaultVisibleClient
*/
export function dragWidth(col: Column, node: HTMLElement) {
let ueberElement: HTMLElement;
let sizeHelper: HTMLElement;
let currentFooterTransformation = '';
const handle = <HTMLElement>node.getElementsByClassName(cssClass('handle'))[0];


let start = 0;
let originalWidth = 0;
const mouseMove = (evt: MouseEvent) => {
evt.stopPropagation();
evt.preventDefault();
const end = evt.clientX;
const delta = end - start;
const width = Math.max(0, col.getWidth() + delta);

if (Math.abs(start - end) < 2) {
//ignore
return;
}
start = end;
const width = Math.max(0, col.getWidth() + delta);

sizeHelper.classList.toggle(cssClass('resize-animated'), width < originalWidth);
// no idea why shifted by the size compared to the other footer element
sizeHelper.style.transform = `${currentFooterTransformation} translate(${width - originalWidth - RESIZE_SPACE}px, 0px)`;

node.style.width = `${width}px`;
col.setWidth(width);
toggleToolbarIcons(node, col);
Expand All @@ -318,7 +326,11 @@ export function dragWidth(col: Column, node: HTMLElement) {
ueberElement.removeEventListener('mousemove', mouseMove);
ueberElement.removeEventListener('mouseup', mouseUp);
ueberElement.removeEventListener('mouseleave', mouseUp);
ueberElement.classList.remove(cssClass('resizing'));
node.style.width = null;
setTimeout(() => {
sizeHelper.classList.remove(cssClass('resizing'), cssClass('resize-animated'));
}, RESIZE_ANIMATION_DURATION * 1.2); // after animation ended

if (Math.abs(start - end) < 2) {
//ignore
Expand All @@ -334,11 +346,18 @@ export function dragWidth(col: Column, node: HTMLElement) {
evt.preventDefault();
node.classList.add(cssClass('change-width'));

originalWidth = col.getWidth();
start = evt.clientX;
ueberElement = <HTMLElement>node.closest('header')!;
ueberElement = <HTMLElement>node.closest('body') || <HTMLElement>node.closest(`.${cssClass()}`)!; // take the whole body or root lineup
ueberElement.addEventListener('mousemove', mouseMove);
ueberElement.addEventListener('mouseup', mouseUp);
ueberElement.addEventListener('mouseleave', mouseUp);
ueberElement.classList.add(cssClass('resizing'));

sizeHelper = <HTMLElement>node.closest(`.${engineCssClass()}`)!.querySelector<HTMLElement>(`.${cssClass('resize-helper')}`);
currentFooterTransformation = (<HTMLElement>sizeHelper.previousElementSibling!).style.transform!;
sizeHelper.style.transform = `${currentFooterTransformation} translate(${-RESIZE_SPACE}px, 0px)`;
sizeHelper.classList.add(cssClass('resizing'));
};
handle.onclick = (evt) => {
// avoid resorting
Expand Down

0 comments on commit 4a0f059

Please sign in to comment.