Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Pinned rows navigation - draft #591

Open
wants to merge 7 commits into
base: master
Choose a base branch
from
Open
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
1 change: 1 addition & 0 deletions packages/qgrid-core/public-api.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ export { BoolColumn, BoolColumnModel } from './src/column-type/bool.column';
export { CohortColumn, CohortColumnModel } from './src/column-type/cohort.column';
//column-type
export { ColumnModel, ColumnModelCategory, ColumnModelPin, ColumnModelType, ColumnModelWidthMode } from './src/column-type/column.model';
export { RowModelPin } from './src/row/row.model';
export { CurrencyColumn, CurrencyColumnModel } from './src/column-type/currency.column';
export { DataColumnModel } from './src/column-type/data.column.model';
export { DateColumn, DateColumnModel } from './src/column-type/date.column';
Expand Down
2 changes: 1 addition & 1 deletion packages/qgrid-core/src/cell/cell.selector.js
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ export class CellSelector {
}

mapFromCells(items) {
const { table } = this;
const { model, table } = this;
const result = [];
const rows = table.data.rows();
const columns = table.data.columns();
Expand Down
32 changes: 17 additions & 15 deletions packages/qgrid-core/src/dom/selector/selector.factory.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,31 +17,33 @@ export class SelectorFactory {
const entries =
selectorMark
.select()
.map(({ element, rowRange, columnRange }) => ({
.map(({ name, element, rowRange, columnRange }) => ({
name,
matrix: matrix.build(element),
rowRange,
columnRange
}));

const selectorFactory = context => {
return entries.map(entry => ({
invoke: f => {
const unitFactory = new UnitFactory(entry.rowRange, entry.columnRange);
const selector = new Selector(entry.matrix, bag, unitFactory);
return entries.map(entry => ({
invoke: f => {
const unitFactory = new UnitFactory(entry.rowRange, entry.columnRange);
const selector = new Selector(entry.matrix, bag, unitFactory);

const args = [];
args.push(selector);
const args = [];
args.push(selector);

if (context.hasOwnProperty('row')) {
args.push(context.row - entry.rowRange.start);
}
if (context.hasOwnProperty('row')) {
args.push(context.row - entry.rowRange.start);
}

if (context.hasOwnProperty('column')) {
args.push(context.column - entry.columnRange.start);
}
if (context.hasOwnProperty('column')) {
args.push(context.column - entry.columnRange.start);
}

return f(...args);
}
return f(...args);
},
type: entry.name
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Adding this and factory pattern?

}));
};

Expand Down
27 changes: 16 additions & 11 deletions packages/qgrid-core/src/dom/selector/selector.mark.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,30 +10,35 @@ export class SelectorMark {
select() {
const result = [];
const addNext = this.addFactory(result);

addNext('left');
addNext('mid');
addNext('right');

['top', 'mid', 'bottom'].forEach(pos => (['left', 'mid', 'right'].forEach(pin => addNext(pin, pos))));
return result;
}

addFactory(result) {
const { model } = this;
const { rows } = model.scene();
const columnArea = model.scene().column.area;

return pin => {
const name = pin ? `${this.name}-${pin}` : this.name;
return (pinLR, pinTB) => {

const { pinTop, pinBottom } = model.row();
const pinned = new Set([...pinTop, ...pinBottom]);

const rows = pinTB == 'top' ? pinTop : pinTB == 'bottom' ? pinBottom :
(pinned.size ? model.scene().rows.filter(row => !pinned.has(row)) : model.scene().rows);

const name = this.name + ((pinTB && pinTB !== 'mid') ? `-${pinTB}` : '') + (pinLR ? `-${pinLR}` : '');
const element = this.markup[name];
if (element) {
const prev = result[result.length - 1];
const prev = result[result.length - 1] && result[result.length - 1].name === (this.name + ((pinTB == 'top' || pinTB == 'bottom') ? `-${pinTB}` : '')) ?
result[result.length - 1] : null;
const columnStart = prev ? prev.columnRange.end : 0;
const columnCount = columnArea[pin].length;
const rowStart = 0;
const columnCount = columnArea[pinLR].length;
const rowStart = pinTB === 'mid' ? pinTop.length : pinTB === 'bottom' ?
model.scene().rows.length - pinBottom.length : 0;
const rowCount = rows.length;

result.push({
name: this.name + ((pinTB == 'top' || pinTB == 'bottom') ? `-${pinTB}` : ''),
element,
columnRange: new Range(columnStart, columnStart + columnCount),
rowRange: new Range(rowStart, rowStart + rowCount)
Expand Down
8 changes: 6 additions & 2 deletions packages/qgrid-core/src/dom/selector/selector.mediate.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ export class SelectorMediator {
}

columnCount(rowIndex) {
const selectors = this.buildSelectors({ row: rowIndex });
const selectors = this.buildSelectors({ row: rowIndex }).filter(x => x.type === 'body');
if (!selectors.length) {
return 0;
}
Expand All @@ -34,8 +34,12 @@ export class SelectorMediator {
if (!selectors.length) {
return 0;
}

const rowCountTop = max(selectors.filter(x => x.type === 'body-top')?.map(s => s.invoke((s, columnIndex) => s.rowCount(columnIndex)))) ?? 0;
const rowCount = max(selectors.filter(x => x.type === 'body')?.map(s => s.invoke((s, columnIndex) => s.rowCount(columnIndex)))) ?? 0;
const rowCountBottom = max(selectors.filter(x => x.type === 'body-bottom')?.map(s => s.invoke((s, columnIndex) => s.rowCount(columnIndex)))) ?? 0;

return max(selectors.map(s => s.invoke((s, columnIndex) => s.rowCount(columnIndex))));
return rowCountTop + rowCount + rowCountBottom;
}

rows(columnIndex) {
Expand Down
20 changes: 15 additions & 5 deletions packages/qgrid-core/src/dom/view.js
Original file line number Diff line number Diff line change
Expand Up @@ -44,8 +44,9 @@ export class View extends Unit {
}

isFocused() {
return this.getElementsCore('body')
.some(element => this.isFocusedCore(element));
return this.getElementsCore('body').some(element => this.isFocusedCore(element)) ||
this.getElementsCore('body-top').some(element => this.isFocusedCore(element)) ||
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fix formatting, add offset

this.getElementsCore('body-bottom').some(element => this.isFocusedCore(element));
}

addLayer(name) {
Expand Down Expand Up @@ -107,12 +108,12 @@ export class View extends Unit {
bodyMid.scrollLeft = value;
}

const bodyTop = markup['body-top'];
const bodyTop = markup['body-top-mid'];
if (bodyTop) {
bodyTop.scrollLeft = value;
}

const bodyBottom = markup['body-bottom'];
const bodyBottom = markup['body-bottom-mid'];
if (bodyBottom) {
bodyBottom.scrollLeft = value;
}
Expand Down Expand Up @@ -157,7 +158,16 @@ export class View extends Unit {
break;
}
case 'top': {
return true;
target = target.element;
if (target) {
const { markup } = this.context;
const bodyLeft = markup['body-left'];
const bodyMid = markup['body-mid'];
const bodyRight = markup['body-right'];
return (bodyLeft && isParentOf(bodyLeft, target)) ||
(bodyMid && isParentOf(bodyMid, target)) ||
(bodyRight && isParentOf(bodyRight, target));
}
}
}
}
Expand Down
6 changes: 4 additions & 2 deletions packages/qgrid-core/src/navigation/navigation.js
Original file line number Diff line number Diff line change
Expand Up @@ -123,12 +123,14 @@ export class Navigation {
const cell = this.table.body.cell(rowIndex, columnIndex);
const model = cell.model();
if (model) {
const { row, column } = model;
const { row, column, td } = model;
const rowPin = td.pin;
return {
rowIndex,
columnIndex,
row,
column
column,
rowPin
};
}

Expand Down
13 changes: 8 additions & 5 deletions packages/qgrid-core/src/navigation/navigation.let.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,9 @@ export class NavigationLet {
this.plugin = plugin;

const navigation = new Navigation(model, table);
let focusBlurs = [];
let focusBlurs = [];

shortcut.register(navigation.commands);
shortcut.register(navigation.commands);

this.focus = new Command({
source: 'navigation.view',
Expand All @@ -30,12 +30,14 @@ export class NavigationLet {
const td = table.body.cell(rowIndex, columnIndex).model();
if (td) {
const { row, column } = td;
const rowPin = td.td.pin;
model.navigation({
cell: {
rowIndex,
columnIndex,
row,
column
column,
rowPin
}
}, {
source: 'navigation.view',
Expand Down Expand Up @@ -168,10 +170,11 @@ export class NavigationLet {
}

scroll(view, target) {
const { model } = this.plugin;
const { model, table } = this.plugin;
const { scroll } = model;
Fastdom.measure(() => {
const tr = target.rect();
const tr = target.rect();

const vr = view.rect('body-mid');
const state = {};

Expand Down
2 changes: 1 addition & 1 deletion packages/qgrid-core/src/pipe/pagination.pipe.js
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,6 @@ function paginate(model, rows) {
const start = current * size;

model.pagination({ count, current }, { source: 'pagination.pipe', behavior: 'core' });
return mode === 'virtual' ? rows : rows.slice(start, start + size);
return mode === 'virtual' ? rows : pinTop.concat(rows.slice(start, start + size)).concat(pinBottom);
}

8 changes: 8 additions & 0 deletions packages/qgrid-core/src/row/row.model.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
/**
* Indicates if row should be frozen.
* - `'top'` - freeze a row on the grid's top.
* - `'body'` - do not freeze
* - `'bottom'` - freeze a row on the grid's bottom.
*/
export declare type RowModelPin = 'top' | 'body' | 'bottom';

12 changes: 8 additions & 4 deletions packages/qgrid-core/src/scene/render/render.js
Original file line number Diff line number Diff line change
Expand Up @@ -82,15 +82,19 @@ export class Renderer {
};

this.rows = {
left: [],
right: [],
mid: []
top: [],
body: [],
bottom: []
};

const invalidateRows = () => {
const { rows } = model.scene();
let { rows } = model.scene();
const { pinTop, pinBottom } = model.row();

const pinned = new Set([...pinTop, ...pinBottom]);
if (pinned.size) {
rows = rows.filter(row => !pinned.has(row))
}
this.rows = {
top: pinTop,
body: rows,
Expand Down
1 change: 1 addition & 0 deletions packages/qgrid-core/src/scene/view/cell.view.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,5 @@ export interface CellViewPosition {
export interface CellView extends CellViewPosition {
readonly row: any;
readonly column: ColumnModel;
readonly rowPin: string;
}
6 changes: 4 additions & 2 deletions packages/qgrid-core/src/selection/selection.let.js
Original file line number Diff line number Diff line change
Expand Up @@ -427,13 +427,15 @@ export class SelectionLet {

navigateTo(rowIndex, columnIndex) {
const { table, model } = this.plugin;
const { row, column } = table.body.cell(rowIndex, columnIndex).model();
const { row, column, td } = table.body.cell(rowIndex, columnIndex).model();
const rowPin = td.pin;
model.navigation({
cell: {
rowIndex,
columnIndex,
row,
column
column,
rowPin
}
}, { source: 'selection.view' });
}
Expand Down
4 changes: 1 addition & 3 deletions packages/qgrid-core/src/view/view.host.js
Original file line number Diff line number Diff line change
Expand Up @@ -206,14 +206,12 @@ export class ViewHost {
}

const tr = this.findRow(e);
if (tr) {
if (tr) {
const { index } = tr;

if (highlight.row.canExecute(index)) {
rows
.filter(i => i !== index)
.forEach(i => highlight.row.execute(i, false));

highlight.row.execute(index, true);
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@

<mat-menu #menu="matMenu"
class="q-grid-mat-menu">
<mat-card *ngIf="trigger.menuOpen">
<mat-card *ngIf="trigger.menuOpen"
[q-grid-stop-propagate]="['keydown', 'keypress', 'keyup']">
<mat-form-field>
<input id="q-grid-menu-input"
matInput
Expand Down
2 changes: 1 addition & 1 deletion packages/qgrid-ngx/src/lib/body/body-core.component.html
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@
<td *ngFor="let $column of $view.body.render.columns($row, $table.pin, $rowIndex); index as $columnIndex; trackBy: columnId"
[attr.rowspan]="$view.body.render.rowspan($row, $column, $rowIndex, $columnIndex)"
[attr.colspan]="$view.body.render.colspan($row, $column, $rowIndex, $columnIndex)">
<ng-container [q-grid-core-td]="$column"
<ng-container [q-grid-core-td]="$column"
[q-grid-core-label]="$view.body.render.getLabel($row, $column.model, $rowIndex, $columnIndex)"
[q-grid-core-value]="$view.body.render.getValue($row, $column.model, $rowIndex, $columnIndex)">
</ng-container>
Expand Down
14 changes: 9 additions & 5 deletions packages/qgrid-ngx/src/lib/body/body-core.component.ts
Original file line number Diff line number Diff line change
@@ -1,22 +1,24 @@
import { ChangeDetectionStrategy, ChangeDetectorRef, Component, ElementRef, Input, NgZone, OnInit } from '@angular/core';
import { BodyHost, ColumnView, EventListener, EventManager, SelectionState } from '@qgrid/core';
import { BodyHost, ColumnView, EventListener, EventManager, RowModelPin, SelectionState } from '@qgrid/core';
import { GridLet } from '../grid/grid-let';
import { GridModel } from '../grid/grid-model';
import { GridPlugin } from '../plugin/grid-plugin';
import { TableCoreService } from '../table/table-core.service';
@Component({
import { BodyCoreService } from './body-core.service';
@Component({
// tslint:disable-next-line
selector: 'tbody[q-grid-core-body]',
templateUrl: './body-core.component.html',
providers: [GridPlugin],
providers: [GridPlugin, BodyCoreService],
changeDetection: ChangeDetectionStrategy.OnPush
})
export class BodyCoreComponent implements OnInit {
@Input() pin = 'body';
@Input() pin: RowModelPin = 'body';

constructor(
public $view: GridLet,
public $table: TableCoreService,
public $body: BodyCoreService,
private elementRef: ElementRef,
private zone: NgZone,
private cd: ChangeDetectorRef,
Expand All @@ -30,14 +32,16 @@ export class BodyCoreComponent implements OnInit {

const host = new BodyHost(this.plugin);

this.$body.pin = this.pin;

const listener = new EventListener(this.elementRef.nativeElement, new EventManager(this));
this.zone.runOutsideAngular(() => {
const scrollSettings = { passive: true };
disposable.add(
listener.on('scroll', () =>
host.scroll({
scrollLeft: this.$table.pin === 'mid' ? nativeElement.scrollLeft : model.scroll().left,
scrollTop: nativeElement.scrollTop
scrollTop: this.$body.pin === 'body' ? nativeElement.scrollTop : model.scroll().top
}),
scrollSettings
));
Expand Down
Loading