55693: Working store interaction for selecting items

This commit is contained in:
Kristof De Langhe
2018-09-27 11:09:36 +02:00
parent 5040d230fb
commit 09a84edb09
7 changed files with 45 additions and 12 deletions

View File

@@ -59,7 +59,8 @@
"collection": "Collection", "collection": "Collection",
"author": "Author", "author": "Author",
"title": "Title" "title": "Title"
} },
"confirm": "Confirm selected"
} }
}, },
"nav": { "nav": {

View File

@@ -30,7 +30,7 @@
<ngb-tab title="{{'collection.item-mapper.tabs.map' | translate}}"> <ngb-tab title="{{'collection.item-mapper.tabs.map' | translate}}">
<ng-template ngbTabContent> <ng-template ngbTabContent>
<div class="mt-2"> <div class="mt-2">
<ds-item-select class="mt-2" [itemsRD$]="mappingItemsRD$" [paginationOptions]="(searchOptions$ | async)?.pagination"></ds-item-select> <ds-item-select class="mt-2" [itemsRD$]="mappingItemsRD$" [paginationOptions]="(searchOptions$ | async)?.pagination" (confirm)="mapItems($event)"></ds-item-select>
</div> </div>
</ng-template> </ng-template>
</ngb-tab> </ngb-tab>

View File

@@ -70,6 +70,10 @@ export class CollectionItemMapperComponent implements OnInit {
); );
} }
mapItems(ids: string[]) {
console.log(ids);
}
getCurrentUrl(): string { getCurrentUrl(): string {
const urlTree = this.router.parseUrl(this.router.url); const urlTree = this.router.parseUrl(this.router.url);
const g: UrlSegmentGroup = urlTree.root.children[PRIMARY_OUTLET]; const g: UrlSegmentGroup = urlTree.root.children[PRIMARY_OUTLET];

View File

@@ -17,7 +17,7 @@
</thead> </thead>
<tbody> <tbody>
<tr *ngFor="let item of (itemsRD$ | async)?.payload?.page"> <tr *ngFor="let item of (itemsRD$ | async)?.payload?.page">
<td><input [ngModel]="getSelected(item.id) | async" (change)="switch(item.id)" type="checkbox"></td> <td><input [ngModel]="getSelected(item.id) | async" (change)="switch(item.id)" type="checkbox" name="{{item.id}}"></td>
<td><a [routerLink]="['/items', item.id]">{{(item.owningCollection | async)?.payload?.name}}</a></td> <td><a [routerLink]="['/items', item.id]">{{(item.owningCollection | async)?.payload?.name}}</a></td>
<td><a *ngIf="item.filterMetadata(['dc.contributor.author', 'dc.creator', 'dc.contributor.*']).length > 0" [routerLink]="['/items', item.id]">{{item.filterMetadata(['dc.contributor.author', 'dc.creator', 'dc.contributor.*'])[0].value}}</a></td> <td><a *ngIf="item.filterMetadata(['dc.contributor.author', 'dc.creator', 'dc.contributor.*']).length > 0" [routerLink]="['/items', item.id]">{{item.filterMetadata(['dc.contributor.author', 'dc.creator', 'dc.contributor.*'])[0].value}}</a></td>
<td><a [routerLink]="['/items', item.id]">{{item.findMetadata("dc.title")}}</a></td> <td><a [routerLink]="['/items', item.id]">{{item.findMetadata("dc.title")}}</a></td>
@@ -26,3 +26,4 @@
</table> </table>
</div> </div>
</ds-pagination> </ds-pagination>
<button class="btn btn-outline-secondary" (click)="confirmSelected()">{{'item.select.confirm' | translate}}</button>

View File

@@ -1,4 +1,4 @@
import { Component, EventEmitter, Input, OnInit, Output } from '@angular/core'; import { Component, EventEmitter, Input, OnDestroy, OnInit, Output } from '@angular/core';
import { ItemDataService } from '../../core/data/item-data.service'; import { ItemDataService } from '../../core/data/item-data.service';
import { PaginatedList } from '../../core/data/paginated-list'; import { PaginatedList } from '../../core/data/paginated-list';
import { RemoteData } from '../../core/data/remote-data'; import { RemoteData } from '../../core/data/remote-data';
@@ -21,13 +21,16 @@ export class ItemSelectComponent implements OnInit {
@Input() @Input()
paginationOptions: PaginationComponentOptions; paginationOptions: PaginationComponentOptions;
checked: boolean[] = []; @Output()
confirm: EventEmitter<string[]> = new EventEmitter<string[]>();
selectedIds$: Observable<string[]>;
constructor(private itemSelectService: ItemSelectService) { constructor(private itemSelectService: ItemSelectService) {
} }
ngOnInit(): void { ngOnInit(): void {
this.itemsRD$.subscribe((value) => console.log(value)); this.selectedIds$ = this.itemSelectService.getAllSelected();
} }
switch(id: string) { switch(id: string) {
@@ -38,4 +41,10 @@ export class ItemSelectComponent implements OnInit {
return this.itemSelectService.getSelected(id); return this.itemSelectService.getSelected(id);
} }
confirmSelected() {
this.selectedIds$.subscribe((ids: string[]) => {
this.confirm.emit(ids);
});
}
} }

View File

@@ -68,7 +68,7 @@ export function itemSelectionReducer(state = initialState, action: ItemSelection
case ItemSelectionActionTypes.SWITCH: { case ItemSelectionActionTypes.SWITCH: {
return Object.assign({}, state, { return Object.assign({}, state, {
[action.id]: { [action.id]: {
checked: !state.checked checked: (isEmpty(state) || isEmpty(state[action.id])) ? true : !state[action.id].checked
} }
}); });
} }

View File

@@ -9,8 +9,11 @@ import {
} from './item-select.actions'; } from './item-select.actions';
import { Observable } from 'rxjs/Observable'; import { Observable } from 'rxjs/Observable';
import { hasValue } from '../empty.util'; import { hasValue } from '../empty.util';
import { map } from 'rxjs/operators';
import { AppState } from '../../app.reducer';
const selectionStateSelector = (state: ItemSelectionsState) => state.selectionItem; const selectionStateSelector = (state: ItemSelectionsState) => state.itemSelection;
const itemSelectionsStateSelector = (state: AppState) => state.itemSelection;
/** /**
* Service that takes care of selecting and deselecting items * Service that takes care of selecting and deselecting items
@@ -18,7 +21,10 @@ const selectionStateSelector = (state: ItemSelectionsState) => state.selectionIt
@Injectable() @Injectable()
export class ItemSelectService { export class ItemSelectService {
constructor(private store: Store<ItemSelectionsState>) { constructor(
private store: Store<ItemSelectionsState>,
private appStore: Store<AppState>
) {
} }
/** /**
@@ -27,14 +33,26 @@ export class ItemSelectService {
* @returns {Observable<boolean>} Emits the current selection state of the given item, if it's unavailable, return false * @returns {Observable<boolean>} Emits the current selection state of the given item, if it's unavailable, return false
*/ */
getSelected(id: string): Observable<boolean> { getSelected(id: string): Observable<boolean> {
return this.store.select(selectionByIdSelector(id)) return this.store.select(selectionByIdSelector(id)).pipe(
.map((object: ItemSelectionState) => { map((object: ItemSelectionState) => {
if (object) { if (object) {
return object.checked; return object.checked;
} else { } else {
return false; return false;
} }
}); })
);
}
/**
* Request the current selection of a given item
* @param {string} id The UUID of the item
* @returns {Observable<boolean>} Emits the current selection state of the given item, if it's unavailable, return false
*/
getAllSelected(): Observable<string[]> {
return this.appStore.select(itemSelectionsStateSelector).pipe(
map((state: ItemSelectionsState) => Object.keys(state).filter((key) => state[key].checked))
);
} }
/** /**