Skip to content

Commit

Permalink
Merge pull request #27 from kreuzerk/feature/shift-selection-problems
Browse files Browse the repository at this point in the history
Feature/shift selection problems
  • Loading branch information
nivekcode authored Mar 2, 2020
2 parents f395389 + 6795d60 commit cf063c6
Show file tree
Hide file tree
Showing 4 changed files with 80 additions and 24 deletions.
Original file line number Diff line number Diff line change
@@ -1,17 +1,24 @@
import createSpyObj = jasmine.createSpyObj;
import createSpy = jasmine.createSpy;

import {NgsgSelectionService} from './ngsg-selection.service';
import {NgsgClassService} from '../helpers/class/ngsg-class.service';
import {NgsgStoreService} from '../store/ngsg-store.service';
import {NgsgElementsHelper} from '../helpers/element/ngsg-elements.helper';
import { NgsgSelectionService } from './ngsg-selection.service';
import { NgsgClassService } from '../helpers/class/ngsg-class.service';
import { NgsgStoreService } from '../store/ngsg-store.service';
import { NgsgElementsHelper } from '../helpers/element/ngsg-elements.helper';

describe('NgsgSelectionService', () => {

const ngsgClassService = createSpyObj<NgsgClassService>('classService',
['addSelectedClass', 'addSelectedClass', 'removeSelectedClass']);
const ngsgStore = createSpyObj<NgsgStoreService>('ngsgStore',
['addSelectedItem', 'hasSelectedItems', 'removeSelectedItem']);
const ngsgClassService = createSpyObj<NgsgClassService>('classService', [
'addSelectedClass',
'addSelectedClass',
'removeSelectedClass'
]);
const ngsgStore = createSpyObj<NgsgStoreService>('ngsgStore', [
'addSelectedItem',
'getSelectedItems',
'hasSelectedItems',
'removeSelectedItem',
'resetSelectedItems'
]);
let sut: NgsgSelectionService;

beforeEach(() => {
Expand All @@ -24,7 +31,6 @@ describe('NgsgSelectionService', () => {
});

describe('selectElementIfNoSelection', () => {

it('should call hasSelectedItems with the group', () => {
ngsgStore.hasSelectedItems.and.returnValue(true);
const dragedElement = 'Cool element' as any;
Expand Down Expand Up @@ -57,14 +63,13 @@ describe('NgsgSelectionService', () => {

expect(findIndexSpy).toHaveBeenCalledWith(dragedElement);
expect(ngsgStore.addSelectedItem).toHaveBeenCalledWith(group, {
node: dragedElement, originalIndex
node: dragedElement,
originalIndex
});
});

describe('Selection change', () => {

it('should add the selectedItem if the Meta key is pressed and the item is clicked', () => {

const event = new KeyboardEvent('keydown', {
key: 'Meta'
});
Expand All @@ -77,11 +82,10 @@ describe('NgsgSelectionService', () => {
window.dispatchEvent(event);
sut.updateSelectedDragItem(group, item, selected);

expect(ngsgStore.addSelectedItem).toHaveBeenCalledWith(group, {node: item, originalIndex: index});
expect(ngsgStore.addSelectedItem).toHaveBeenCalledWith(group, { node: item, originalIndex: index });
});

it('should remove the selectedItem if the Meta key is pressed and the selected item is clicked', () => {

const event = new KeyboardEvent('keydown', {
key: 'Meta'
});
Expand All @@ -99,7 +103,6 @@ describe('NgsgSelectionService', () => {

it(`should remove the selected class from the selected item if the Meta key is pressed
and the selected item is clicked`, () => {

const event = new KeyboardEvent('keydown', {
key: 'Meta'
});
Expand All @@ -114,7 +117,28 @@ describe('NgsgSelectionService', () => {

expect(ngsgClassService.removeSelectedClass).toHaveBeenCalledWith(item);
});
});

it(`should reset the selected items if we click on an item without holding the shift key`, () => {
const event = new KeyboardEvent('keyup', {
key: 'Meta'
});
const itemOne = { node: 'Foo' };
const itemTwo = { node: 'Bar' };
const items = [itemOne, itemTwo];
const group = 'groupOne';
const item = 'Some element' as any;
const selected = false;
const index = 2;

NgsgElementsHelper.findIndex = () => index;
ngsgStore.getSelectedItems.and.returnValue(items);
window.dispatchEvent(event);
sut.updateSelectedDragItem(group, item, selected);

expect(ngsgClassService.removeSelectedClass).toHaveBeenCalledWith(itemOne.node);
expect(ngsgClassService.removeSelectedClass).toHaveBeenCalledWith(itemTwo.node);
expect(ngsgStore.resetSelectedItems).toHaveBeenCalledWith(group);
});
});
});
});
21 changes: 15 additions & 6 deletions projects/ng-sortgrid/src/lib/mutliselect/ngsg-selection.service.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { Injectable } from '@angular/core';
import { fromEvent, merge, NEVER, Observable, Subject } from 'rxjs';
import { filter, mapTo, switchMap } from 'rxjs/operators';
import {Injectable} from '@angular/core';
import {fromEvent, merge, NEVER, Observable, Subject} from 'rxjs';
import {filter, mapTo, switchMap, withLatestFrom} from 'rxjs/operators';
import {NgsgClassService} from '../helpers/class/ngsg-class.service';
import {NgsgStoreService} from '../store/ngsg-store.service';
import {NgsgElementsHelper} from '../helpers/element/ngsg-elements.helper';
Expand All @@ -27,9 +27,18 @@ export class NgsgSelectionService {

constructor(private classService: NgsgClassService, private ngsgStore: NgsgStoreService) {
const selectionKeyPressed$ = this.selectionKeyPressed();
selectionKeyPressed$
.pipe(switchMap(pressed => (pressed ? this.selectionChange$ : NEVER)))
.subscribe((selectionChange: SelectionChange) => this.handleSelectionChange(selectionChange));
this.selectionChange$
.pipe(withLatestFrom(selectionKeyPressed$))
.subscribe(([selectionChange, selectionKeyPressed]) => {
selectionKeyPressed
? this.handleSelectionChange(selectionChange)
: this.resetSelectedItems(selectionChange.key);
});
}

private resetSelectedItems(group: string): void {
this.ngsgStore.getSelectedItems(group).forEach(item => this.classService.removeSelectedClass(item.node));
this.ngsgStore.resetSelectedItems(group);
}

private handleSelectionChange(selectionChange: SelectionChange): void {
Expand Down
16 changes: 16 additions & 0 deletions projects/ng-sortgrid/src/lib/ngsg-item.directive.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import {NgsgReflectService} from './sort/reflection/ngsg-reflect.service';
import {NgsgStoreService} from './store/ngsg-store.service';
import {NgsgEventsService} from './shared/ngsg-events.service';
import {NgsgOrderChange} from './shared/ngsg-order-change.model';
import {NgsgElementsHelper} from './helpers/element/ngsg-elements.helper';

describe('NgsgItemDirective', () => {
let sut: NgsgItemDirective;
Expand All @@ -22,6 +23,7 @@ describe('NgsgItemDirective', () => {
const ngsgStore = createSpyObj<NgsgStoreService>('ngsgStore', [
'initState',
'hasSelectedItems',
'getSelectedItems',
'resetSelectedItems',
'hasGroup',
'hasItems',
Expand Down Expand Up @@ -169,12 +171,26 @@ describe('NgsgItemDirective', () => {

it('should call the selctionservice with the host if the event occured on the host', () => {
const group = 'test-group';
NgsgElementsHelper.findIndex = () => 0;
ngsgStore.getSelectedItems.and.returnValue([]);
sut.ngSortGridGroup = group;

sut.clicked();
expect(ngsgSelectionService.updateSelectedDragItem).toHaveBeenCalledWith(group, elementRef.nativeElement, true);
});

it('should call the selection service with false if the item is selected', () => {
const originalIndex = 0;
const group = 'test-group';
const element = {originalIndex};
NgsgElementsHelper.findIndex = () => originalIndex;
ngsgStore.getSelectedItems.and.returnValue([element]);
sut.ngSortGridGroup = group;

sut.clicked();
expect(ngsgSelectionService.updateSelectedDragItem).toHaveBeenCalledWith(group, elementRef.nativeElement, false);
});

it(`should init the state with empty items if group has yet not been
initialized and the currentValue is null`, () => {
const group = 'test-group';
Expand Down
9 changes: 8 additions & 1 deletion projects/ng-sortgrid/src/lib/ngsg-item.directive.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import {NgsgStoreService} from './store/ngsg-store.service';
import {NgsgEventsService} from './shared/ngsg-events.service';
import {ScrollHelperService} from './helpers/scroll/scroll-helper.service';
import {NgsgOrderChange} from './shared/ngsg-order-change.model';
import {NgsgElementsHelper} from './helpers/element/ngsg-elements.helper';

const selector = '[ngSortgridItem]';

Expand Down Expand Up @@ -135,10 +136,16 @@ export class NgsgItemDirective implements OnInit, OnChanges, AfterViewInit, OnDe

@HostListener('click', ['$event'])
clicked(): void {
this.selected = !this.selected;
this.selected = !this.isItemCurrentlySelected();
this.selectionService.updateSelectedDragItem(this.ngSortGridGroup, this.el.nativeElement, this.selected);
}

private isItemCurrentlySelected(): boolean {
const index = NgsgElementsHelper.findIndex(this.el.nativeElement);
return !!this.ngsgStore.getSelectedItems(this.ngSortGridGroup)
.find(element => element.originalIndex === index);
}

private occuredOnHost(event): boolean {
return event.target.matches(selector);
}
Expand Down

0 comments on commit cf063c6

Please sign in to comment.