diff --git a/src/atlasViewer/atlasViewer.component.ts b/src/atlasViewer/atlasViewer.component.ts index 1cabf4fea761c7c24d20fff42d21f526cea73558..82dfd13665bda5129da783a3a326588474ddc327 100644 --- a/src/atlasViewer/atlasViewer.component.ts +++ b/src/atlasViewer/atlasViewer.component.ts @@ -39,8 +39,7 @@ const filterFn = (segment) => typeof segment.segment !== 'string' export class AtlasViewer implements OnDestroy, OnInit, AfterViewInit { @ViewChild('floatingMouseContextualContainer', { read: ViewContainerRef }) floatingMouseContextualContainer: ViewContainerRef - @ViewChild('helpComponent', {read: TemplateRef}) helpComponent : TemplateRef<any> - @ViewChild('signinModalComponent', {read: TemplateRef}) signinModalComponent : TemplateRef<any> + @ViewChild('cookieAgreementComponent', {read: TemplateRef}) cookieAgreementComponent : TemplateRef<any> @ViewChild('kgToS', {read: TemplateRef}) kgTosComponent: TemplateRef<any> @ViewChild(LayoutMainSide) layoutMainSide: LayoutMainSide @@ -68,7 +67,6 @@ export class AtlasViewer implements OnDestroy, OnInit, AfterViewInit { public selectedRegions$: Observable<any[]> public selectedPOI$ : Observable<any[]> - private showHelp$: Observable<any> private snackbarRef: MatSnackBarRef<any> public snackbarMessage$: Observable<string> @@ -150,10 +148,6 @@ export class AtlasViewer implements OnDestroy, OnInit, AfterViewInit { map(state => state.sidePanelOpen) ) - this.showHelp$ = this.constantsService.showHelpSubject$.pipe( - debounceTime(170) - ) - this.selectedRegions$ = this.store.pipe( select('viewerState'), filter(state=>isDefined(state)&&isDefined(state.regionsSelected)), @@ -277,8 +271,6 @@ export class AtlasViewer implements OnDestroy, OnInit, AfterViewInit { private cookieDialogRef: MatDialogRef<any> private kgTosDialogRef: MatDialogRef<any> - private helpDialogRef: MatDialogRef<any> - private loginDialogRef: MatDialogRef<any> ngOnInit() { this.meetsRequirement = this.meetsRequirements() @@ -323,25 +315,6 @@ export class AtlasViewer implements OnDestroy, OnInit, AfterViewInit { }) ) - this.subscriptions.push( - this.showHelp$.subscribe(() => { - this.helpDialogRef = this.matDialog.open(this.helpComponent, { - autoFocus: false, - panelClass: ['col-12','col-sm-12','col-md-8','col-lg-6','col-xl-4'] - }) - }) - ) - - this.subscriptions.push( - this.constantsService.showSigninSubject$.pipe( - debounceTime(160) - ).subscribe(user => { - this.loginDialogRef = this.matDialog.open(this.signinModalComponent, { - autoFocus: false - }) - }) - ) - /** * TODO deprecated */ @@ -544,16 +517,6 @@ export class AtlasViewer implements OnDestroy, OnInit, AfterViewInit { }) } - closeModal(mode){ - if (mode === 'help') { - this.helpDialogRef && this.helpDialogRef.close() - } - - if (mode === 'login') { - this.loginDialogRef && this.loginDialogRef.close() - } - } - closeMenuWithSwipe(documentToSwipe: ElementRef) { if (documentToSwipe && documentToSwipe.nativeElement) { const swipeDistance = 150; // swipe distance diff --git a/src/atlasViewer/atlasViewer.constantService.service.ts b/src/atlasViewer/atlasViewer.constantService.service.ts index a31da6c69cb8e42ef432c99688439c00493eb66d..6a6fe0615d2fb1e03441bb69c8428e68d3ffb1d3 100644 --- a/src/atlasViewer/atlasViewer.constantService.service.ts +++ b/src/atlasViewer/atlasViewer.constantService.service.ts @@ -157,19 +157,10 @@ Interactive atlas viewer requires **webgl2.0**, and the \`EXT_color_buffer_float */ public toggleMessage: string = 'double click to toggle select, right click to search' - /** - * observable for showing login modal - */ - public showSigninSubject$: Subject<any> = new Subject() - /** * Observable for showing config modal */ public showConfigTitle: String = 'Settings' - /** - * Observable for showing help modal - */ - public showHelpSubject$: Subject<null> = new Subject() private showHelpGeneralMobile = [ ['hold 🌠+ ↕', 'change oblique slice mode'], diff --git a/src/atlasViewer/atlasViewer.template.html b/src/atlasViewer/atlasViewer.template.html index f8e201915ac1ca601a0af44a66aa6121c9bf0e72..6a67f8a11f9113e3b7ddce2e6ba20c949913a26e 100644 --- a/src/atlasViewer/atlasViewer.template.html +++ b/src/atlasViewer/atlasViewer.template.html @@ -4,45 +4,6 @@ </ng-container> </ng-container> -<ng-template #helpComponent> - <h2 mat-dialog-title>About Interactive Viewer</h2> - <mat-dialog-content> - <mat-tab-group> - <mat-tab label="Help"> - <help-component> - </help-component> - </mat-tab> - <mat-tab label="Privacy Policy"> - <!-- TODO make tab container scrollable --> - <cookie-agreement> - </cookie-agreement> - </mat-tab> - <mat-tab label="Terms of Use"> - <kgtos-component> - </kgtos-component> - </mat-tab> - </mat-tab-group> - </mat-dialog-content> - - <mat-dialog-actions class="justify-content-center"> - <button - mat-flat-button - (click)="closeModal('help')" - cdkFocusInitial> - close - </button> - </mat-dialog-actions> -</ng-template> - -<!-- signin --> -<ng-template #signinModalComponent> - <h2 mat-dialog-title>Sign in</h2> - <mat-dialog-content> - <signin-modal> - </signin-modal> - </mat-dialog-content> -</ng-template> - <!-- kg tos --> <ng-template #kgToS> <h2 mat-dialog-title>Knowldge Graph ToS</h2> @@ -83,7 +44,7 @@ <!-- atlas template --> <ng-template #viewerBody> - <div class="atlas-container" (drag-drop)="localFileService.handleFileDrop($event)" helpdirective> + <div class="atlas-container" (drag-drop)="localFileService.handleFileDrop($event)"> <ui-nehuba-container (contextmenu)="$event.stopPropagation(); $event.preventDefault();"> <!--nehubaClickHandler($event)--> </ui-nehuba-container> diff --git a/src/atlasViewer/atlasViewer.urlService.service.ts b/src/atlasViewer/atlasViewer.urlService.service.ts index 72a5ed8886d1d34c518ec48a674d32b9c9c9d388..a5a9dc5c3f325d125d7a6844832dc8d272404428 100644 --- a/src/atlasViewer/atlasViewer.urlService.service.ts +++ b/src/atlasViewer/atlasViewer.urlService.service.ts @@ -6,8 +6,8 @@ import { Observable,combineLatest } from "rxjs"; import { filter, map, scan, distinctUntilChanged, skipWhile, take } from "rxjs/operators"; import { PluginServices } from "./atlasViewer.pluginService.service"; import { AtlasViewerConstantsServices, encodeNumber, separator, decodeToNumber } from "./atlasViewer.constantService.service"; -import { ToastService } from "src/services/toastService.service"; import { SELECT_REGIONS_WITH_ID } from "src/services/state/viewerState.store"; +import { UIService } from "src/services/uiService.service"; declare var window @@ -24,7 +24,7 @@ export class AtlasViewerURLService{ private store : Store<ViewerStateInterface>, private pluginService : PluginServices, private constantService:AtlasViewerConstantsServices, - private toastService: ToastService + private uiService:UIService ){ this.pluginState$ = this.store.pipe( @@ -113,10 +113,10 @@ export class AtlasViewerURLService{ const templateToLoad = fetchedTemplates.find(template=>template.name === searchedTemplatename) if (!templateToLoad) { - this.toastService.showToast( + this.uiService.showMessage( this.constantService.incorrectTemplateNameSearchParam(searchedTemplatename), { - timeout: 5000 + duration: 5000 } ) const urlString = window.location.href @@ -133,10 +133,10 @@ export class AtlasViewerURLService{ const parcellationToLoad = templateToLoad.parcellations.find(parcellation=>parcellation.name === searchedParcellationName) if (!parcellationToLoad) { - this.toastService.showToast( + this.uiService.showMessage( this.constantService.incorrectParcellationNameSearchParam(searchedParcellationName), { - timeout: 5000 + duration: 5000 } ) } diff --git a/src/main.module.ts b/src/main.module.ts index 5ff36abd47c75578875e104d477360f7490c74e2..b4ffa246b99054600f4814e50b572fd03d2fca47 100644 --- a/src/main.module.ts +++ b/src/main.module.ts @@ -24,9 +24,7 @@ import { ToastComponent } from "./components/toast/toast.component"; import { AtlasViewerAPIServices } from "./atlasViewer/atlasViewer.apiService.service"; import { PluginUnit } from "./atlasViewer/pluginUnit/pluginUnit.component"; import { NewViewerDisctinctViewToLayer } from "./util/pipes/newViewerDistinctViewToLayer.pipe"; -import { ToastService } from "./services/toastService.service"; import { AtlasWorkerService } from "./atlasViewer/atlasViewer.workerService.service"; -import { HelpDirective } from "./util/directives/help.directive"; import { DockedContainerDirective } from "./util/directives/dockedContainer.directive"; import { FloatingContainerDirective } from "./util/directives/floatingContainer.directive"; import { PluginFactoryDirective } from "./util/directives/pluginFactory.directive"; @@ -50,6 +48,7 @@ import { NgViewerUseEffect } from "./services/state/ngViewerState.store"; import { DatabrowserModule } from "./ui/databrowserModule/databrowser.module"; import 'hammerjs' +import { UIService } from "./services/uiService.service"; @NgModule({ imports : [ @@ -98,7 +97,6 @@ import 'hammerjs' fasTooltipQuestionSignDirective, fasTooltipRemoveDirective, fasTooltipRemoveSignDirective, - HelpDirective, DockedContainerDirective, FloatingContainerDirective, PluginFactoryDirective, @@ -125,11 +123,11 @@ import 'hammerjs' WidgetServices, AtlasViewerURLService, AtlasViewerAPIServices, - ToastService, AtlasWorkerService, AuthService, LocalFileService, DialogService, + UIService, /** * TODO diff --git a/src/res/css/extra_styles.css b/src/res/css/extra_styles.css index 9cf78dfc850529cc07f5353100fc1a7a941d0263..cb86ba171285962fa0cc59b0f14bb51d9b4e6a37 100644 --- a/src/res/css/extra_styles.css +++ b/src/res/css/extra_styles.css @@ -629,3 +629,9 @@ mat-icon[fontset="far"] { min-height: 4rem; } + +/* overwrite bootstrap default focus styling */ +*:focus +{ + outline: none!important; +} diff --git a/src/services/auth.service.ts b/src/services/auth.service.ts index 20a8f38d1fe204320dff0061d34d24497866783a..a74df4bd375db71a5f62e15d3c67dc3ab0f5e7a3 100644 --- a/src/services/auth.service.ts +++ b/src/services/auth.service.ts @@ -1,4 +1,7 @@ -import { Injectable } from "@angular/core"; +import { Injectable, OnDestroy } from "@angular/core"; +import { Observable, of, Subscription } from "rxjs"; +import { HttpClient } from "@angular/common/http"; +import { catchError, shareReplay } from "rxjs/operators"; const IV_REDIRECT_TOKEN = `IV_REDIRECT_TOKEN` @@ -6,9 +9,9 @@ const IV_REDIRECT_TOKEN = `IV_REDIRECT_TOKEN` providedIn: 'root' }) -export class AuthService{ +export class AuthService implements OnDestroy{ public user: User | null - + public user$: Observable<any> public logoutHref: String = 'logout' /** @@ -19,14 +22,23 @@ export class AuthService{ href: 'hbp-oidc/auth' }] - constructor() { - fetch('user') - .then(res => res.json()) - .then(user => this.user = user) - .catch(e => { - if (!PRODUCTION) - console.log(`auth failed`, e) - }) + constructor(private httpClient: HttpClient) { + this.user$ = this.httpClient.get('user').pipe( + catchError(err => { + return of(null) + }), + shareReplay(1) + ) + + this.subscription.push( + this.user$.subscribe(user => this.user = user) + ) + } + + private subscription: Subscription[] = [] + + ngOnDestroy(){ + while (this.subscription.length > 0) this.subscription.pop().unsubscribe() } authSaveState() { diff --git a/src/services/toastService.service.ts b/src/services/toastService.service.ts deleted file mode 100644 index 35ac359717662d07cb3172c5d37542f7e1ec9596..0000000000000000000000000000000000000000 --- a/src/services/toastService.service.ts +++ /dev/null @@ -1,20 +0,0 @@ -import { Injectable, TemplateRef } from "@angular/core"; -import { ToastHandler } from "src/util/pluginHandlerClasses/toastHandler"; - -@Injectable({ - providedIn : 'root' -}) -export class ToastService{ - showToast: (message: string | TemplateRef<any>, config?: Partial<ToastConfig>)=>()=>void - getToastHandler: () => ToastHandler -} - -export interface ToastConfig{ - dismissable: boolean - timeout: number -} - -export const defaultToastConfig : ToastConfig = { - dismissable: true, - timeout : 2000 -} \ No newline at end of file diff --git a/src/services/uiService.service.ts b/src/services/uiService.service.ts new file mode 100644 index 0000000000000000000000000000000000000000..749ae353bb255da52b4a2542b1efe2e700a28004 --- /dev/null +++ b/src/services/uiService.service.ts @@ -0,0 +1,37 @@ +import { Injectable } from "@angular/core"; +import { MatSnackBar, MatSnackBarConfig } from "@angular/material"; +import { AtlasViewerAPIServices } from "src/atlasViewer/atlasViewer.apiService.service"; +import { ToastHandler } from "src/util/pluginHandlerClasses/toastHandler"; + +@Injectable({ + providedIn: 'root' +}) + +export class UIService{ + constructor( + private snackbar: MatSnackBar, + private apiService: AtlasViewerAPIServices + ){ + this.apiService.interactiveViewer.uiHandle.getToastHandler = () => { + const toasthandler = new ToastHandler() + let handle + toasthandler.show = () => { + handle = this.showMessage(toasthandler.message, { + duration: toasthandler.timeout, + }) + + } + + toasthandler.hide = () => { + handle && handle.dismiss() + handle = null + } + + return toasthandler + } + } + + showMessage(message: string, config?: Partial<MatSnackBarConfig>){ + return this.snackbar.open(message, 'Dismiss', config) + } +} \ No newline at end of file diff --git a/src/ui/pluginBanner/pluginBanner.component.ts b/src/ui/pluginBanner/pluginBanner.component.ts index 0b4fe404a110a3d82cfdade361e894e0a2aeb92e..02d92bce45410ea55a3ccbfa9b81ad6c5058e7b5 100644 --- a/src/ui/pluginBanner/pluginBanner.component.ts +++ b/src/ui/pluginBanner/pluginBanner.component.ts @@ -17,15 +17,6 @@ export class PluginBannerUI{ } clickPlugin(plugin:PluginManifest){ - if(this.pluginEnabledFlag) - this.pluginServices.launchPlugin(plugin) - else - return - } - - get pluginEnabledFlag(){ - return true || PLUGINDEV || BUNDLEDPLUGINS.length > 0 - ? true - : false + this.pluginServices.launchPlugin(plugin) } } \ No newline at end of file diff --git a/src/ui/pluginBanner/pluginBanner.style.css b/src/ui/pluginBanner/pluginBanner.style.css index 2bb0a1504f1dc55fb60862cb95908e844d4c7993..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 100644 --- a/src/ui/pluginBanner/pluginBanner.style.css +++ b/src/ui/pluginBanner/pluginBanner.style.css @@ -1,33 +0,0 @@ -:host -{ - display:block; - margin:0.5em 1em; -} - -.btn -{ - border-radius: 0px; - border:none; -} - -.btn -{ - opacity : 0.9; - transition: opacity 0.3s ease, transform 0.3s ease; - box-shadow : rgba(5, 5, 5, 0.1) 0px 4px 6px 0px; -} - -.btn-default -{ - background-color:rgba(255,255,255,0.8); -} - -.btn:hover -{ - cursor: default; -} - -.btn.btn-disabled.btn.btn-disabled.btn.btn-disabled.btn.btn-disabled -{ - opacity:0.5; -} \ No newline at end of file diff --git a/src/ui/pluginBanner/pluginBanner.template.html b/src/ui/pluginBanner/pluginBanner.template.html index b79ca60cccb56c912f2fb0bb00ea5bbbd52f0c02..d349c6f7cc8d4b3b46ac7a8d6517fa119faebc19 100644 --- a/src/ui/pluginBanner/pluginBanner.template.html +++ b/src/ui/pluginBanner/pluginBanner.template.html @@ -1,9 +1,8 @@ -<div - placement = "bottom" - [matTooltip] = "pluginEnabledFlag ? null : 'coming soon'" - *ngFor = "let plugin of pluginServices.fetchedPluginManifests" - (click) = "clickPlugin(plugin)" - [ngClass] = "{'btn-disabled' : !pluginEnabledFlag}" - class = "btn btn-default"> - {{ plugin.displayName ? plugin.displayName : plugin.name }} -</div> \ No newline at end of file +<mat-action-list> + <button mat-list-item + *ngFor="let plugin of pluginServices.fetchedPluginManifests" + (click)="clickPlugin(plugin)"> + + {{ plugin.displayName ? plugin.displayName : plugin.name }} + </button> +</mat-action-list> diff --git a/src/ui/signinBanner/signinBanner.components.ts b/src/ui/signinBanner/signinBanner.components.ts index 97a23101bf3b107bb8dfa74ef68e5d0fb3db5d8b..809daa23f80cb3588fcb49ab6a0bedf03d2f5cd4 100644 --- a/src/ui/signinBanner/signinBanner.components.ts +++ b/src/ui/signinBanner/signinBanner.components.ts @@ -1,7 +1,8 @@ import {Component, ChangeDetectionStrategy, Input, TemplateRef } from "@angular/core"; -import { AtlasViewerConstantsServices } from "src/atlasViewer/atlasViewer.constantService.service"; import { AuthService, User } from "src/services/auth.service"; -import { MatDialog } from "@angular/material"; +import { MatDialog, MatDialogRef } from "@angular/material"; +import { Observable } from "rxjs"; +import { map } from "rxjs/operators"; @Component({ @@ -18,37 +19,30 @@ export class SigninBanner{ @Input() darktheme: boolean + public user$: Observable<User> + public userBtnTooltip$: Observable<string> + constructor( - private constantService: AtlasViewerConstantsServices, private authService: AuthService, private dialog: MatDialog ){ - } + this.user$ = this.authService.user$ - /** - * move the templates to signin banner when pluginprettify is merged - */ - showHelp() { - this.constantService.showHelpSubject$.next() + this.userBtnTooltip$ = this.user$.pipe( + map(user => user + ? `Logged in as ${(user && user.name) ? user.name : 'Unknown name'}` + : `Not logged in`) + ) } - /** - * move the templates to signin banner when pluginprettify is merged - */ - showSetting(settingTemplate:TemplateRef<any>){ - this.dialog.open(settingTemplate, { - autoFocus: false - }) - } + private dialogRef: MatDialogRef<any> - /** - * move the templates to signin banner when pluginprettify is merged - */ - showSignin() { - this.constantService.showSigninSubject$.next(this.user) - } + openTmplWithDialog(tmpl: TemplateRef<any>){ + this.dialogRef && this.dialogRef.close() - get user() : User | null { - return this.authService.user + if (tmpl) this.dialogRef = this.dialog.open(tmpl, { + autoFocus: false, + panelClass: ['col-12','col-sm-12','col-md-8','col-lg-6','col-xl-4'] + }) } } \ No newline at end of file diff --git a/src/ui/signinBanner/signinBanner.template.html b/src/ui/signinBanner/signinBanner.template.html index cf0945cfcf66166e2c434b53ad7f02d91ebd8094..ff6d2736ca6083aba5b8d4d8445e749089770db8 100644 --- a/src/ui/signinBanner/signinBanner.template.html +++ b/src/ui/signinBanner/signinBanner.template.html @@ -1,39 +1,15 @@ -<div class="d-flex"> - - <!-- help btn --> - <div class="btnWrapper"> - <button - matTooltip="About" - matTooltipPosition="below" - (click)="showHelp()" - mat-icon-button - color="primary"> - <i class="fas fa-question"></i> - </button> - </div> - - <!-- setting btn --> - <div class="btnWrapper"> - <button - #settingBtn - matTooltip="Settings" - matTooltipPosition="below" - (click)="showSetting(settingTemplate)" - mat-icon-button - color="primary"> - <i class="fas fa-cog"></i> - </button> - </div> +<div class="d-flex" + (helpdirective)="!menuOpen ? openTmplWithDialog(helpComponent) : null"> <!-- signin --> <div class="btnWrapper"> <button - [matTooltip]="user && user.name ? ('Logged in as ' + (user && user.name)) : 'Not logged in'" + [matTooltip]="userBtnTooltip$ | async" matTooltipPosition="below" - (click)="showSignin()" mat-icon-button + [matMenuTriggerFor]="dropdownMenu" color="primary"> - <i *ngIf="!user; else userInitialTempl" class="fas fa-user"></i> + <i *ngIf="!(user$ | async) as user; else userInitialTempl" class="fas fa-user"></i> <ng-template #userInitialTempl> {{ (user && user.name || 'Unnamed User').slice(0,1) }} </ng-template> @@ -41,6 +17,72 @@ </div> </div> +<!-- drop down menu --> +<mat-menu #dropdownMenu> + <mat-card> + <mat-card-content> + <signin-modal> + </signin-modal> + </mat-card-content> + </mat-card> + + <mat-divider></mat-divider> + + <button (click)="openTmplWithDialog(pluginTmpl)" mat-menu-item> + <mat-icon fontSet="fas" fontIcon="fa-cube"></mat-icon> + Plugins + </button> + + <button mat-menu-item + (click)="openTmplWithDialog(settingTemplate)"> + <mat-icon fontSet="fas" fontIcon="fa-cog"></mat-icon> + Setting + </button> + + <button mat-menu-item + (click)="openTmplWithDialog(helpComponent)"> + <mat-icon fontSet="fas" fontIcon="fa-info"></mat-icon> + About + </button> +</mat-menu> + +<ng-template #pluginTmpl> + <h2 mat-dialog-title>Plugins</h2> + <mat-dialog-content> + <plugin-banner (click)="openTmplWithDialog(null)"></plugin-banner> + </mat-dialog-content> +</ng-template> + +<ng-template #helpComponent> + <h2 mat-dialog-title>About Interactive Viewer</h2> + <mat-dialog-content> + <mat-tab-group> + <mat-tab label="Help"> + <help-component> + </help-component> + </mat-tab> + <mat-tab label="Privacy Policy"> + <!-- TODO make tab container scrollable --> + <cookie-agreement> + </cookie-agreement> + </mat-tab> + <mat-tab label="Terms of Use"> + <kgtos-component> + </kgtos-component> + </mat-tab> + </mat-tab-group> + </mat-dialog-content> + + <mat-dialog-actions class="justify-content-center"> + <button + mat-flat-button + [mat-dialog-close] + cdkFocusInitial> + close + </button> + </mat-dialog-actions> +</ng-template> + <ng-template #settingTemplate> <h2 mat-dialog-title>Settings</h2> <mat-dialog-content> diff --git a/src/ui/signinModal/signinModal.template.html b/src/ui/signinModal/signinModal.template.html index 92feed3d10578773b41cc7c24ede52debef857f4..e2ab8fe9f88393075d7597edaec26356b2d1b309 100644 --- a/src/ui/signinModal/signinModal.template.html +++ b/src/ui/signinModal/signinModal.template.html @@ -12,18 +12,16 @@ </div> <ng-template #notLoggedIn> - <div> - Not logged in. Login via: - - <a *ngFor="let m of loginMethods" - [href]="m.href"> - <button - (click)="loginBtnOnclick()" - mat-raised-button - color="primary"> - <i class="fas fa-sign-in-alt"></i> {{ m.name }} - </button> - </a> - - </div> + <span> + Login via + </span> + <a *ngFor="let m of loginMethods" + [href]="m.href"> + <button + (click)="loginBtnOnclick()" + mat-raised-button + color="primary"> + <i class="fas fa-sign-in-alt"></i> {{ m.name }} + </button> + </a> </ng-template> \ No newline at end of file diff --git a/src/ui/ui.module.ts b/src/ui/ui.module.ts index adf230be016e508378d737106634ffb63c09b6f3..d7dbd2d39fd60f50ebd8a1498c6c3c13efdeef4f 100644 --- a/src/ui/ui.module.ts +++ b/src/ui/ui.module.ts @@ -27,7 +27,6 @@ import { DownloadDirective } from "../util/directives/download.directive"; import { LogoContainer } from "./logoContainer/logoContainer.component"; import { TemplateParcellationCitationsContainer } from "./templateParcellationCitations/templateParcellationCitations.component"; import { MobileOverlay } from "./nehubaContainer/mobileOverlay/mobileOverlay.component"; -import { ShowToastDirective } from "../util/directives/showToast.directive"; import { HelpComponent } from "./help/help.component"; import { ConfigComponent } from './config/config.component' import { FlatmapArrayPipe } from "src/util/pipes/flatMapArray.pipe"; @@ -72,6 +71,7 @@ import { RegionHierarchy } from './viewerStateController/regionHierachy/regionHi import { CurrentlySelectedRegions } from './viewerStateController/regionsListView/currentlySelectedRegions/currentlySelectedRegions.component' import { RegionTextSearchAutocomplete } from "./viewerStateController/regionSearch/regionSearch.component"; import { RegionsListView } from "./viewerStateController/regionsListView/simpleRegionsListView/regionListView.component"; +import { HelpDirective } from "src/util/directives/help.directive"; @NgModule({ imports : [ @@ -147,9 +147,9 @@ import { RegionsListView } from "./viewerStateController/regionsListView/simpleR /* directive */ DownloadDirective, - ShowToastDirective, TouchSideClass, - ElementOutClickDirective + ElementOutClickDirective, + HelpDirective ], entryComponents : [ diff --git a/src/ui/viewerStateController/viewerState.base.ts b/src/ui/viewerStateController/viewerState.base.ts index 4eacc8515f9121bdc397e85c0af42a076dc9f047..72d3b99c7c4302e525d7258781ce50307f8f7581 100644 --- a/src/ui/viewerStateController/viewerState.base.ts +++ b/src/ui/viewerStateController/viewerState.base.ts @@ -3,7 +3,6 @@ import { Store, select } from "@ngrx/store"; import { Observable, Subscription } from "rxjs"; import { distinctUntilChanged, shareReplay, filter } from "rxjs/operators"; import { SELECT_REGIONS, USER_CONFIG_ACTION_TYPES } from "src/services/stateStore.service"; -import { ToastService } from "src/services/toastService.service"; import { MatSelectChange, MatBottomSheet, MatBottomSheetRef } from "@angular/material"; import { DialogService } from "src/services/dialogService.service"; import { RegionSelection } from "src/services/state/userConfigState.store"; @@ -38,7 +37,6 @@ export class ViewerStateBase implements OnInit{ constructor( private store$: Store<any>, - private toastService: ToastService, private dialogService: DialogService, private bottomSheet: MatBottomSheet ){ diff --git a/src/ui/viewerStateController/viewerState.useEffect.ts b/src/ui/viewerStateController/viewerState.useEffect.ts index 9b1a4b2ce7d2cafe99c6d1c7428c194f79cd0091..3b5e4a625304e0335eec195ee4696730e3d47d3d 100644 --- a/src/ui/viewerStateController/viewerState.useEffect.ts +++ b/src/ui/viewerStateController/viewerState.useEffect.ts @@ -2,11 +2,11 @@ import { Subscription, Observable } from "rxjs"; import { Injectable, OnInit, OnDestroy } from "@angular/core"; import { Actions, ofType, Effect } from "@ngrx/effects"; import { Store, select, Action } from "@ngrx/store"; -import { ToastService } from "src/services/toastService.service"; import { shareReplay, distinctUntilChanged, map, withLatestFrom, filter } from "rxjs/operators"; import { VIEWERSTATE_ACTION_TYPES } from "./viewerState.base"; import { CHANGE_NAVIGATION, SELECT_REGIONS, NEWVIEWER, GENERAL_ACTION_TYPES, SELECT_PARCELLATION, isDefined } from "src/services/stateStore.service"; import { regionFlattener } from "src/util/regionFlattener"; +import { UIService } from "src/services/uiService.service"; @Injectable({ providedIn: 'root' @@ -33,7 +33,7 @@ export class ViewerStateControllerUseEffect implements OnInit, OnDestroy{ constructor( private actions$: Actions, private store$: Store<any>, - private toastService: ToastService + private uiService: UIService ){ const viewerState$ = this.store$.pipe( select('viewerState'), @@ -189,10 +189,7 @@ export class ViewerStateControllerUseEffect implements OnInit, OnDestroy{ } }) } else { - this.toastService.showToast(`${region.name} does not have a position defined`, { - timeout: 5000, - dismissable: true - }) + this.uiService.showMessage(`${region.name} does not have a position defined`) } }) ) diff --git a/src/ui/viewerStateController/viewerStateCFull/viewerState.component.ts b/src/ui/viewerStateController/viewerStateCFull/viewerState.component.ts index b97ae9e5cf8e52b1dc111e0821303314b73792bf..3513dfae1b67fdeab6cc1eeae5da1a0bdb5f9b46 100644 --- a/src/ui/viewerStateController/viewerStateCFull/viewerState.component.ts +++ b/src/ui/viewerStateController/viewerStateCFull/viewerState.component.ts @@ -1,6 +1,5 @@ import { Component } from "@angular/core"; import { Store } from "@ngrx/store"; -import { ToastService } from "src/services/toastService.service"; import { MatBottomSheet } from "@angular/material"; import { DialogService } from "src/services/dialogService.service"; @@ -22,11 +21,10 @@ export class ViewerStateController extends ViewerStateBase{ constructor( store$: Store<any>, - toastService: ToastService, dialogService: DialogService, bottomSheet: MatBottomSheet ){ - super(store$,toastService,dialogService,bottomSheet) + super(store$,dialogService,bottomSheet) } } diff --git a/src/ui/viewerStateController/viewerStateCMini/viewerStateMini.component.ts b/src/ui/viewerStateController/viewerStateCMini/viewerStateMini.component.ts index 11e8f0120be7a892533b184d565ac81b09460dfb..6652e980061961cc1d754acc1adac71da74c4a5d 100644 --- a/src/ui/viewerStateController/viewerStateCMini/viewerStateMini.component.ts +++ b/src/ui/viewerStateController/viewerStateCMini/viewerStateMini.component.ts @@ -1,6 +1,5 @@ import { Component } from "@angular/core"; import { Store } from "@ngrx/store"; -import { ToastService } from "src/services/toastService.service"; import { MatBottomSheet } from "@angular/material"; import { DialogService } from "src/services/dialogService.service"; @@ -18,11 +17,9 @@ export class ViewerStateMini extends ViewerStateBase{ constructor( store$: Store<any>, - toastService: ToastService, dialogService: DialogService, bottomSheet: MatBottomSheet ){ - super(store$,toastService,dialogService,bottomSheet) + super(store$,dialogService,bottomSheet) } - } diff --git a/src/util/directives/help.directive.ts b/src/util/directives/help.directive.ts index 31257ba52dd6b781cc6313020937647f335816d9..e6fd2a921381535fef43455503a65bbc7bb6fe04 100644 --- a/src/util/directives/help.directive.ts +++ b/src/util/directives/help.directive.ts @@ -1,29 +1,22 @@ -import { Directive, ElementRef, Renderer2 } from '@angular/core' -import { AtlasViewerConstantsServices } from '../../atlasViewer/atlasViewer.constantService.service'; +import { Directive, HostListener, Output, EventEmitter} from '@angular/core' + +const HELP_SYMBOL = Symbol('HELP_SYMBOL') @Directive({ - selector : 'div[helpdirective]' + selector : '[helpdirective]' }) export class HelpDirective{ - constructor( - // rd2:Renderer2, - private elementRef:ElementRef, - private constantService:AtlasViewerConstantsServices - ){ - /** - * TODO angular does not currently (7.1.2019) support capture events. when it does, use rd should be more efficient - */ - // rd2.listen(elementRef.nativeElement, 'keydown', this.keydownHandler.bind(this)) - - } + @Output('helpdirective') + callhelp: EventEmitter<KeyboardEvent> = new EventEmitter() + + @HostListener('document:keydown', ['$event']) keydownHandler(ev:KeyboardEvent){ const target = <HTMLElement> ev.target const tagName = target.tagName - if (tagName === 'SELECT' || tagName === 'INPUT' || tagName === 'TEXTAREA') - return + if (tagName === 'SELECT' || tagName === 'INPUT' || tagName === 'TEXTAREA') return if (ev.key === 'h' || ev.key === 'H' || ev.key === '?') { ev.stopPropagation() @@ -31,11 +24,7 @@ export class HelpDirective{ /** * call help modal */ - this.constantService.showHelpSubject$.next() + this.callhelp.emit(ev) } } - - ngAfterViewInit(){ - this.elementRef.nativeElement.addEventListener('keydown', this.keydownHandler.bind(this), true) - } } \ No newline at end of file diff --git a/src/util/directives/showToast.directive.ts b/src/util/directives/showToast.directive.ts deleted file mode 100644 index a4e1756b33569325f19e252379ecf1d9b12cb69d..0000000000000000000000000000000000000000 --- a/src/util/directives/showToast.directive.ts +++ /dev/null @@ -1,48 +0,0 @@ -import { Directive, Input, TemplateRef, HostListener, OnDestroy } from "@angular/core"; -import { ToastService } from "../../services/toastService.service"; - -@Directive({ - selector: '[showToast]' -}) - -export class ShowToastDirective implements OnDestroy{ - @Input() - showToast : string | TemplateRef<any> = null - - private _toastLength: number = 1000 - - @Input() - set toastLength(input:any){ - if(typeof input === 'number'){ - this._toastLength = input - return - } - - const parsedNumber = Number(input) - if(!Number.isNaN(parsedNumber)){ - this._toastLength = parsedNumber - } - } - - get toastLength(){ - return this._toastLength - } - - private dismissHandler : () => void - - @HostListener('click', ['$event.target']) - click(ev:MouseEvent){ - if(this.dismissHandler) this.dismissHandler() - this.dismissHandler = this.toastService.showToast(this.showToast, { - dismissable: true, - timeout: this.toastLength - }) - } - - constructor(private toastService:ToastService){ - } - - ngOnDestroy(){ - if(this.dismissHandler) this.dismissHandler() - } -} \ No newline at end of file diff --git a/src/util/pluginHandlerClasses/toastHandler.ts b/src/util/pluginHandlerClasses/toastHandler.ts index ed468840fa13ed4c09a73fcffe05ae14f50144db..5452dc78f492b9b7af2f927335910a18e2f48ec1 100644 --- a/src/util/pluginHandlerClasses/toastHandler.ts +++ b/src/util/pluginHandlerClasses/toastHandler.ts @@ -1,7 +1,5 @@ -import { TemplateRef } from "@angular/core"; - export class ToastHandler{ - message : string | TemplateRef<any> = 'handler.body' + message : string = 'Toast message' timeout : number = 3000 dismissable : boolean = true show : () => void