Skip to content

Commit

Permalink
feat(context-list): add context list tool (alpha, add context) (#624)
Browse files Browse the repository at this point in the history
  • Loading branch information
PhilippeLafreniere18 authored and mbarbeau committed May 11, 2020
1 parent b652565 commit d8a1431
Show file tree
Hide file tree
Showing 11 changed files with 265 additions and 54 deletions.
2 changes: 1 addition & 1 deletion demo/src/app/context/context/context.component.html
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
</igo-map-browser>

<igo-panel title="Contexts list">
<igo-context-list igoContextListBinding></igo-context-list>
<igo-context-list igoContextListBinding [map]="map"></igo-context-list>
</igo-panel>

<igo-panel title="Layers">
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Component, Input, Output, EventEmitter } from '@angular/core';
import { Component, Input, Output, EventEmitter, ChangeDetectionStrategy } from '@angular/core';

import { AuthService } from '@igo2/auth';
import { TypePermission } from '../shared/context.enum';
Expand All @@ -7,7 +7,8 @@ import { DetailedContext } from '../shared/context.interface';
@Component({
selector: 'igo-context-item',
templateUrl: './context-item.component.html',
styleUrls: ['./context-item.component.scss']
styleUrls: ['./context-item.component.scss'],
changeDetection: ChangeDetectionStrategy.OnPush
})
export class ContextItemComponent {
public typePermission = TypePermission;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<igo-list [navigation]="true">
<mat-form-field *ngIf="showFilter()" class="contextFilter">
<mat-form-field *ngIf="showFilter()" [ngClass]="auth.authenticated ? 'context-filter-min-width' : 'context-filter-max-width'">
<input
matInput
type="text"
Expand All @@ -13,11 +13,54 @@
*ngIf="term.length"
aria-label="Clear"
color="warn"
(click)="term = ''">
(click)="clearFilter()">
<mat-icon svgIcon="close"></mat-icon>
</button>
</mat-form-field>

<button
*ngIf="!sortedAlpha"
mat-icon-button
[matTooltip]="'igo.context.contextManager.sortAlphabetically' | translate"
matTooltipShowDelay="500"
(click)="toggleSort(true)">
<mat-icon color="primary" svgIcon="sort-alphabetical"></mat-icon>
</button>
<button
*ngIf="sortedAlpha"
mat-icon-button
[matTooltip]="'igo.context.contextManager.sortContextOrder' | translate"
matTooltipShowDelay="500"
(click)="toggleSort(false)">
<mat-icon color="warn" svgIcon="sort-variant-remove"></mat-icon>
</button>

<button *ngIf="auth.authenticated"
mat-icon-button
[matTooltip]="'igo.context.bookmarkButton.create' | translate"
matTooltipShowDelay="500"
(click)="createContext()">
<mat-icon color="primary" svgIcon="star"></mat-icon>
</button>

<!-- <button *ngIf="authenticated"
mat-icon-button
[matTooltip]="'igo.context.contextManager.userAccount' | translate"
matTooltipShowDelay="500"
[matMenuTriggerFor]="accountMenu">
<mat-icon color="primary" svgIcon="account"></mat-icon>
</button>
<mat-menu #accountMenu="matMenu">
<ng-container *ngFor="let user of users">
<mat-checkbox
class="mat-menu-item"
[checked]="true"
(change)="userSelection()">
{{user}}
</mat-checkbox>
</ng-container>
</mat-menu> -->

<ng-template ngFor let-groupContexts [ngForOf]="contexts$ | async | keyvalue">

<igo-collapsible *ngIf="groupContexts.value.length && auth.authenticated" [title]="titleMapping[groupContexts.key] | translate">
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
.contextFilter {
width: calc(100% - 20px);
.context-filter-max-width {
width: calc(100% - 60px);
margin: 5px;
padding-left: 6px;
}

.context-filter-min-width {
width: calc(100% - 95px);
margin: 5px;
padding-left: 6px;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,31 +4,45 @@ import {
Output,
EventEmitter,
ChangeDetectorRef,
OnInit
OnInit,
ChangeDetectionStrategy,
OnDestroy
} from '@angular/core';

import { AuthService } from '@igo2/auth';
import { LanguageService, MessageService } from '@igo2/core';
import { IgoMap } from '@igo2/geo';

import { DetailedContext, ContextsList } from '../shared/context.interface';
import { ContextListControlsEnum } from './context-list.enum';
import { Subscription, BehaviorSubject } from 'rxjs';
import { Subscription, BehaviorSubject, ReplaySubject, EMPTY, timer } from 'rxjs';
import { MatDialog } from '@angular/material';
import { ContextService } from '../shared/context.service';
import { BookmarkDialogComponent } from '../../context-map-button/bookmark-button/bookmark-dialog.component';
import { debounce } from 'rxjs/operators';

@Component({
selector: 'igo-context-list',
templateUrl: './context-list.component.html',
styleUrls: ['./context-list.component.scss']
styleUrls: ['./context-list.component.scss'],
changeDetection: ChangeDetectionStrategy.OnPush
})
export class ContextListComponent implements OnInit {
contexts$: BehaviorSubject<ContextsList> = new BehaviorSubject(undefined);
export class ContextListComponent implements OnInit, OnDestroy {
private contextsInitial: ContextsList = { ours: [] };
contexts$: BehaviorSubject<ContextsList> = new BehaviorSubject(this.contextsInitial);

change$ = new ReplaySubject<void>(1);

private change$$: Subscription;

@Input()
get contexts(): ContextsList {
return this._contexts;
}
set contexts(value: ContextsList) {
this._contexts = value;
this.contexts$.next(value);
this.cdRef.detectChanges();
this.next();
}
private _contexts: ContextsList = { ours: [] };

Expand All @@ -42,6 +56,15 @@ export class ContextListComponent implements OnInit {
}
private _selectedContext: DetailedContext;

@Input()
get map(): IgoMap {
return this._map;
}
set map(value: IgoMap) {
this._map = value;
}
private _map: IgoMap;

@Input()
get defaultContextId(): string {
return this._defaultContextId;
Expand All @@ -67,62 +90,102 @@ export class ContextListComponent implements OnInit {
public: 'igo.context.contextManager.publicContexts'
};

// public users = ['COG', '911', 'Public'];

/**
* Context filter term
*/
@Input()
set term(value: string) {
this.term$.next(value);
this._term = value;
this.next();
}
get term(): string {
return this.term$.value;
return this._term;
}
public _term: string = '';

get sortedAlpha(): boolean {
return this._sortedAlpha;
}
public term$: BehaviorSubject<string> = new BehaviorSubject('');
term$$: Subscription;
set sortedAlpha(value: boolean) {
this._sortedAlpha = value;
this.next();
}
private _sortedAlpha: boolean = undefined;

public showContextFilter = ContextListControlsEnum.default;
public showContextFilter = ContextListControlsEnum.always;

public thresholdToFilter = 5;

constructor(private cdRef: ChangeDetectorRef, public auth: AuthService) {}
constructor(
private cdRef: ChangeDetectorRef,
public auth: AuthService,
private dialog: MatDialog,
private contextService: ContextService,
private languageService: LanguageService,
private messageService: MessageService) {}

ngOnInit() {
this.term$$ = this.term$.subscribe((value) => {
if (value === '') {
this.contexts$.next(this.contexts);
this.change$$ = this.change$
.pipe(
debounce(() => {
return this.contexts.ours.length === 0 ? EMPTY : timer(50);
})
)
.subscribe(() => {
this.contexts$.next(this.filterContextsList(this.contexts));
});
}

private next() {
this.change$.next();
}

private filterContextsList(contexts: ContextsList) {
if (this.term === '') {
if (this.sortedAlpha) {
contexts = this.sortContextsList(contexts);
}
return contexts;
} else {
const ours = contexts.ours.filter((context) => {
const filterNormalized = this.term.toLowerCase().normalize('NFD').replace(/[\u0300-\u036f]/g, '');
const contextTitleNormalized = context.title.toLowerCase().normalize('NFD').replace(/[\u0300-\u036f]/g, '');
return contextTitleNormalized.includes(filterNormalized);
});

let updateContexts: ContextsList = {
ours
};

if (value.length) {
let ours; let publics; let shared;
ours = this.contexts.ours.filter((context) => {
const filterNormalized = value.toLowerCase().normalize('NFD').replace(/[\u0300-\u036f]/g, '');
if (this.contexts.public) {
const publics = contexts.public.filter((context) => {
const filterNormalized = this.term.toLowerCase().normalize('NFD').replace(/[\u0300-\u036f]/g, '');
const contextTitleNormalized = context.title.toLowerCase().normalize('NFD').replace(/[\u0300-\u036f]/g, '');
return contextTitleNormalized.includes(filterNormalized);
});
const updateContexts: ContextsList = {
ours
};

if (this.contexts.public) {
publics = this.contexts.public.filter((context) => {
const filterNormalized = value.toLowerCase().normalize('NFD').replace(/[\u0300-\u036f]/g, '');
const contextTitleNormalized = context.title.toLowerCase().normalize('NFD').replace(/[\u0300-\u036f]/g, '');
return contextTitleNormalized.includes(filterNormalized);
});
updateContexts.public = publics;
}
if (this.contexts.shared) {
shared = this.contexts.shared.filter((context) => {
const filterNormalized = value.toLowerCase().normalize('NFD').replace(/[\u0300-\u036f]/g, '');
const contextTitleNormalized = context.title.toLowerCase().normalize('NFD').replace(/[\u0300-\u036f]/g, '');
return contextTitleNormalized.includes(filterNormalized);
});
updateContexts.shared = shared;
}
updateContexts.public = publics;
}

if (this.contexts.shared) {
const shared = contexts.shared.filter((context) => {
const filterNormalized = this.term.toLowerCase().normalize('NFD').replace(/[\u0300-\u036f]/g, '');
const contextTitleNormalized = context.title.toLowerCase().normalize('NFD').replace(/[\u0300-\u036f]/g, '');
return contextTitleNormalized.includes(filterNormalized);
});
updateContexts.shared = shared;
}

this.contexts$.next(updateContexts);
if (this.sortedAlpha) {
updateContexts = this.sortContextsList(updateContexts);
}
});
return updateContexts;
}
}

ngOnDestroy() {
this.change$$.unsubscribe();
}

public showFilter() {
Expand All @@ -141,4 +204,80 @@ export class ContextListComponent implements OnInit {
return false;
}
}

sortContextsList(contexts: ContextsList) {
if (contexts) {
const contextsList = JSON.parse(JSON.stringify(contexts));
contextsList.ours.sort((a, b) => {
if (a.title < b.title) {
return -1;
}
if (a.title > b.title) {
return 1;
}
return 0;
});

if (contextsList.shared) {
contextsList.shared.sort((a, b) => {
if (a.title < b.title) {
return -1;
}
if (a.title > b.title) {
return 1;
}
return 0;
});
} else if (contextsList.public) {
contextsList.public.sort((a, b) => {
if (a.title < b.title) {
return -1;
}
if (a.title > b.title) {
return 1;
}
return 0;
});
}
return contextsList;
}
}

toggleSort(sortAlpha: boolean) {
this.sortedAlpha = sortAlpha;
}

clearFilter() {
this.term = '';
}

createContext() {
this.dialog
.open(BookmarkDialogComponent, { disableClose: false })
.afterClosed()
.subscribe(title => {
if (title) {
const context = this.contextService.getContextFromMap(this.map);
context.title = title;
this.contextService.create(context).subscribe(() => {
const translate = this.languageService.translate;
const titleD = translate.instant(
'igo.context.bookmarkButton.dialog.createTitle'
);
const message = translate.instant(
'igo.context.bookmarkButton.dialog.createMsg',
{
value: context.title
}
);
this.messageService.success(message, titleD);
this.contextService.loadContext(context.uri);
});
}
});
}

// userSelection() {
// return;
// }
}
Loading

0 comments on commit d8a1431

Please sign in to comment.