From ff7d700bca441c842f0dc25a2820d95e27acefea Mon Sep 17 00:00:00 2001 From: Xiao Gui <xgui3783@gmail.com> Date: Wed, 19 Jul 2023 17:49:56 +0200 Subject: [PATCH] feat: add spatial search badge when min tray closed feat: align jumbo chip icon to chip, not to line feat: introduce opacity to jumbo chip --- .../pureDumb/pureATPSelector.components.ts | 69 ++++++++++++++- .../pureDumb/pureATPSelector.style.scss | 14 +++ .../pureDumb/pureATPSelector.template.html | 23 +++-- .../component/smartChip.component.ts | 11 ++- .../smartChip/component/smartChip.style.scss | 87 ++++++++++++------- .../component/smartChip.template.html | 33 ++++--- src/components/smartChip/module.ts | 3 + .../smartChip/smartChip.action.directive.ts | 9 ++ src/features/guards.ts | 7 +- src/util/util.module.ts | 2 +- .../viewerCmp/viewerCmp.template.html | 26 ++++-- 11 files changed, 217 insertions(+), 67 deletions(-) create mode 100644 src/components/smartChip/smartChip.action.directive.ts diff --git a/src/atlasComponents/sapiViews/core/rich/ATPSelector/pureDumb/pureATPSelector.components.ts b/src/atlasComponents/sapiViews/core/rich/ATPSelector/pureDumb/pureATPSelector.components.ts index ef1976937..04b217ef5 100644 --- a/src/atlasComponents/sapiViews/core/rich/ATPSelector/pureDumb/pureATPSelector.components.ts +++ b/src/atlasComponents/sapiViews/core/rich/ATPSelector/pureDumb/pureATPSelector.components.ts @@ -1,6 +1,9 @@ -import { ChangeDetectionStrategy, Component, EventEmitter, Input, OnChanges, Output, SimpleChanges } from "@angular/core"; +import { AfterViewInit, ChangeDetectionStrategy, Component, EventEmitter, HostBinding, Input, OnChanges, OnDestroy, Output, QueryList, SimpleChanges, ViewChildren } from "@angular/core"; +import { BehaviorSubject, Subscription, combineLatest, concat, merge, of } from "rxjs"; +import { map, switchMap } from "rxjs/operators"; import { SxplrAtlas, SxplrParcellation, SxplrTemplate } from "src/atlasComponents/sapi/sxplrTypes"; import { FilterGroupedParcellationPipe, GroupedParcellation } from "src/atlasComponents/sapiViews/core/parcellation"; +import { SmartChip } from "src/components/smartChip"; export const darkThemePalette = [ "#141414", @@ -40,7 +43,9 @@ const pipe = new FilterGroupedParcellationPipe() changeDetection: ChangeDetectionStrategy.OnPush, }) -export class PureATPSelector implements OnChanges{ +export class PureATPSelector implements OnChanges, AfterViewInit, OnDestroy{ + + #subscriptions: Subscription[] = [] @Input('sxplr-pure-atp-selector-color-palette') colorPalette: string[] = darkThemePalette @@ -67,6 +72,15 @@ export class PureATPSelector implements OnChanges{ @Output('sxplr-pure-atp-selector-on-select') selectLeafEmitter = new EventEmitter<Partial<ATP>>() + @ViewChildren(SmartChip) + smartChips: QueryList<SmartChip<object>> + + #menuOpen$ = new BehaviorSubject<{ some: boolean, all: boolean, none: boolean }>({ some: false, all: false, none: false }) + menuOpen$ = this.#menuOpen$.asObservable() + + @HostBinding('attr.data-menu-open') + menuOpen: 'some'|'all'|'none' = null + getChildren(parc: GroupedParcellation|SxplrParcellation){ return (parc as GroupedParcellation).parcellations || [] } @@ -98,4 +112,55 @@ export class PureATPSelector implements OnChanges{ } } } + + ngAfterViewInit(): void { + this.#subscriptions.push( + concat( + of(null), + this.smartChips.changes, + ).pipe( + switchMap(() => + combineLatest( + Array.from(this.smartChips).map(chip => + concat( + of(false), + merge( + chip.menuOpened.pipe( + map(() => true) + ), + chip.menuClosed.pipe( + map(() => false) + ) + ) + ) + ) + ) + ), + ).subscribe(arr => { + const newVal = { + some: arr.some(val => val), + all: arr.every(val => val), + none: arr.every(val => !val), + } + this.#menuOpen$.next(newVal) + + this.menuOpen = null + if (newVal.none) { + this.menuOpen = 'none' + } + if (newVal.all) { + this.menuOpen = 'all' + } + if (newVal.some) { + this.menuOpen = 'some' + } + }) + ) + } + + ngOnDestroy(): void { + while (this.#subscriptions.length > 0) { + this.#subscriptions.pop().unsubscribe() + } + } } diff --git a/src/atlasComponents/sapiViews/core/rich/ATPSelector/pureDumb/pureATPSelector.style.scss b/src/atlasComponents/sapiViews/core/rich/ATPSelector/pureDumb/pureATPSelector.style.scss index cc3249fac..3bd40c266 100644 --- a/src/atlasComponents/sapiViews/core/rich/ATPSelector/pureDumb/pureATPSelector.style.scss +++ b/src/atlasComponents/sapiViews/core/rich/ATPSelector/pureDumb/pureATPSelector.style.scss @@ -1,3 +1,17 @@ +:host-context([experimental="true"]) :host +{ + opacity: 0.5; + transition: opacity ease-in-out 160ms; + + &:hover, + &[data-menu-open="some"], + &[data-menu-open="all"] + { + opacity: 1; + } +} + + :host { display: inline-flex; diff --git a/src/atlasComponents/sapiViews/core/rich/ATPSelector/pureDumb/pureATPSelector.template.html b/src/atlasComponents/sapiViews/core/rich/ATPSelector/pureDumb/pureATPSelector.template.html index f8ed4de44..9aaf8f964 100644 --- a/src/atlasComponents/sapiViews/core/rich/ATPSelector/pureDumb/pureATPSelector.template.html +++ b/src/atlasComponents/sapiViews/core/rich/ATPSelector/pureDumb/pureATPSelector.template.html @@ -19,14 +19,9 @@ </span> </ng-template> - <ng-template sxplrSmartChipContent> - <span class="chip-text"> - {{ ATP.parcellation.shortName }} - </span> - <ng-content select="[parcellation-chip-suffix]"> - </ng-content> - - <button iav-stop="mousedown click" + <ng-template sxplrSmartChipAction> + <button + iav-stop="mousedown click" class="icons" mat-icon-button sxplr-dialog @@ -39,6 +34,18 @@ <i class="fas fa-info"></i> </button> </ng-template> + + <ng-template sxplrSmartChipAction> + <ng-content select="[parcellation-chip-suffix]"> + </ng-content> + </ng-template> + + <ng-template sxplrSmartChipContent> + <span class="chip-text"> + {{ ATP.parcellation.shortName }} + </span> + + </ng-template> <ng-template sxplrSmartChipMenu let-parc> <ng-container *ngTemplateOutlet="optionTmpl; context: { diff --git a/src/components/smartChip/component/smartChip.component.ts b/src/components/smartChip/component/smartChip.component.ts index 99eed1198..a6dac2d1a 100644 --- a/src/components/smartChip/component/smartChip.component.ts +++ b/src/components/smartChip/component/smartChip.component.ts @@ -1,8 +1,9 @@ -import { ChangeDetectionStrategy, Component, ContentChild, EventEmitter, HostBinding, Input, OnChanges, Output, SimpleChanges } from "@angular/core"; +import { ChangeDetectionStrategy, Component, ContentChild, ContentChildren, EventEmitter, HostBinding, Input, OnChanges, Output, QueryList, SimpleChanges } from "@angular/core"; import { SmartChipContent } from "../smartChip.content.directive" import { SmartChipMenu } from "../smartChip.menu.directive"; import { rgbToHsl, hexToRgb } from 'common/util' import { SmartChipHeader } from "../smartChip.header.directive"; +import { SmartChipAction } from "../smartChip.action.directive"; const cssColorToHsl = (input: string) => { if (/rgb/i.test(input)) { @@ -66,6 +67,14 @@ export class SmartChip<T extends object> implements OnChanges{ @Output('itemClicked') itemClicked = new EventEmitter<T>() + @Output('menuOpened') + menuOpened = new EventEmitter() + @Output('menuClosed') + menuClosed = new EventEmitter() + + @ContentChildren(SmartChipAction) + actionTmpls: QueryList<SmartChipAction> + @ContentChild(SmartChipContent) contentTmpl: SmartChipContent diff --git a/src/components/smartChip/component/smartChip.style.scss b/src/components/smartChip/component/smartChip.style.scss index f6d54f007..df88b7eed 100644 --- a/src/components/smartChip/component/smartChip.style.scss +++ b/src/components/smartChip/component/smartChip.style.scss @@ -6,42 +6,65 @@ position: relative; } -:host-context([experimental=true]) :host -{ - min-height: 44px; -} -:host-context([experimental=true]) .smart-chip +:host-context([experimental=true]) { - display: inline-flex; - flex-direction: column!important; - border-radius: 22px; - align-items: center; - justify-content: start; -} + :host + { + min-height: 44px; + } -:host-context([experimental=true]) .header -{ - font-size: 80%; - margin-top:-0.5rem; - margin-bottom:0.3rem; - flex-basis: 1rem; -} + .smart-chip + { + display: inline-flex; + flex-direction: row; + border-radius: 22px; + justify-content: center; -:host-context([experimental=true]) .body -{ - width: 100%; - flex: 1 1 0; - display: flex; - align-items: start; -} -:host-context([experimental=true]) .body>.body-content-wrapper -{ - height: 1px; - width: 100%; - overflow: visible; - display: flex; - align-items: center; + >.text + { + height: 0px; + overflow: visible; + display: inline-flex; + flex-direction: column; + justify-content: center; + } + + >.icons + { + height: 0px; + overflow: visible; + display: inline-flex; + flex-direction: row; + align-items: center; + } + } + + .header + { + + font-size: 80%; + margin-top:-0.5rem; + margin-bottom:0.3rem; + flex-basis: 1rem; + } + + .body + { + width: 100%; + flex: 1 1 0; + display: flex; + align-items: start; + + >.body-content-wrapper + { + height: 1px; + width: 100%; + overflow: visible; + display: flex; + align-items: center; + } + } } .smart-chip diff --git a/src/components/smartChip/component/smartChip.template.html b/src/components/smartChip/component/smartChip.template.html index 659c02630..e057e1501 100644 --- a/src/components/smartChip/component/smartChip.template.html +++ b/src/components/smartChip/component/smartChip.template.html @@ -6,24 +6,35 @@ <div [style.background-color]="color" [matMenuTriggerFor]="noMenuFlag ? null : mainMenu" + (menuOpened)="menuOpened.emit()" + (menuClosed)="menuClosed.emit()" matRipple [matRippleDisabled]="noMenuFlag" [ngClass]="smartChipClass" - class="mat-body smart-chip body sxplr-custom-cmp text"> + class="mat-body smart-chip sxplr-custom-cmp text"> - <!-- header component --> + <!-- text component --> - <ng-template [ngIf]="headerTmpl?.templateRef" let-tmpl> - <div class="mat-body sxplr-custom-cmp text header"> - <ng-template [ngTemplateOutlet]="tmpl"> - </ng-template> + <div class="text"> + <ng-template [ngIf]="headerTmpl?.templateRef" let-tmpl> + <div class="mat-body sxplr-custom-cmp text header"> + <ng-template [ngTemplateOutlet]="tmpl"> + </ng-template> + </div> + </ng-template> + <div class="body"> + <div class="body-content-wrapper"> + <ng-template [ngTemplateOutlet]="contentTmpl?.templateRef || fallbackContentTmpl"> + </ng-template> + </div> </div> - </ng-template> - <div class="body"> - <div class="body-content-wrapper"> - <ng-template [ngTemplateOutlet]="contentTmpl?.templateRef || fallbackContentTmpl"> + </div> + + <div class="icons"> + <ng-template ngFor [ngForOf]="actionTmpls" let-actionTmpl> + <ng-template [ngTemplateOutlet]="actionTmpl.templateRef"> </ng-template> - </div> + </ng-template> </div> </div> diff --git a/src/components/smartChip/module.ts b/src/components/smartChip/module.ts index e5c9616ad..58c8a2930 100644 --- a/src/components/smartChip/module.ts +++ b/src/components/smartChip/module.ts @@ -9,6 +9,7 @@ import { SmartChipContent } from "./smartChip.content.directive"; import { SmartChipHeader } from "./smartChip.header.directive"; import { SmartChipMenu } from "./smartChip.menu.directive"; import { ExperimentalModule } from "src/experimental/experimental.module"; +import { SmartChipAction } from "./smartChip.action.directive"; @NgModule({ imports: [ @@ -22,6 +23,7 @@ import { ExperimentalModule } from "src/experimental/experimental.module"; SmartChipMenu, SmartChipContent, SmartChipHeader, + SmartChipAction, SmartChip, HasSubMenuPipe, ], @@ -29,6 +31,7 @@ import { ExperimentalModule } from "src/experimental/experimental.module"; SmartChipMenu, SmartChipContent, SmartChipHeader, + SmartChipAction, SmartChip, ] }) diff --git a/src/components/smartChip/smartChip.action.directive.ts b/src/components/smartChip/smartChip.action.directive.ts new file mode 100644 index 000000000..011965520 --- /dev/null +++ b/src/components/smartChip/smartChip.action.directive.ts @@ -0,0 +1,9 @@ +import { Directive, Inject, TemplateRef } from "@angular/core"; + +@Directive({ + selector: `ng-template[sxplrSmartChipAction]` +}) + +export class SmartChipAction { + constructor(@Inject(TemplateRef) public templateRef: TemplateRef<unknown>){} +} diff --git a/src/features/guards.ts b/src/features/guards.ts index fefbc7a0b..eff1ea272 100644 --- a/src/features/guards.ts +++ b/src/features/guards.ts @@ -8,11 +8,6 @@ export function isVoiData(feature: unknown): feature is VoiFeature { return !!feature['bbox'] } -export function notQuiteRight(feature: unknown): string[] { - if (feature['name'].includes("Cellular level 3D reconstructed volumes at 1µm resolution")) { - return [ - "This volume is currently not displayed correctly. We are working to restore the functionality." - ] - } +export function notQuiteRight(_feature: unknown): string[] { return [] } diff --git a/src/util/util.module.ts b/src/util/util.module.ts index d40b143f7..53355b1f5 100644 --- a/src/util/util.module.ts +++ b/src/util/util.module.ts @@ -77,7 +77,7 @@ import { PrettyPresentPipe } from './pretty-present.pipe'; IncludesPipe, SidePanelComponent, DfToDsPipe, - PrettyPresentPipe + PrettyPresentPipe, ] }) diff --git a/src/viewerModule/viewerCmp/viewerCmp.template.html b/src/viewerModule/viewerCmp/viewerCmp.template.html index cd5c8600e..b39b4115c 100644 --- a/src/viewerModule/viewerCmp/viewerCmp.template.html +++ b/src/viewerModule/viewerCmp/viewerCmp.template.html @@ -293,14 +293,28 @@ #minTray="sxplrExperimentalFlag" [ngIf]="minTray.show$ | async"> <div class="tab-toggle-container"> + + <div [ngClass]="(minTrayVisSwitch.switchState$ | async) ? '' : 'd-none'"> + + <ng-template [ngTemplateOutlet]="tabTmpl_defaultTmpl" [ngTemplateOutletContext]="{ + fontIcon: 'fas fa-chevron-left', + matColor: null, + click: minTrayVisSwitch.toggle.bind(minTrayVisSwitch) + }"> + </ng-template> + </div> - <ng-template [ngTemplateOutlet]="tabTmpl_defaultTmpl" [ngTemplateOutletContext]="{ - fontIcon: (minTrayVisSwitch.switchState$ | async) ? 'fas fa-chevron-left' : 'fas fa-search', - matColor: (minTrayVisSwitch.switchState$ | async) ? null : 'primary', - click: minTrayVisSwitch.toggle.bind(minTrayVisSwitch) - }"> + <div [ngClass]="(minTrayVisSwitch.switchState$ | async) ? 'd-none' : ''"> + + <ng-template [ngTemplateOutlet]="tabTmpl_defaultTmpl" [ngTemplateOutletContext]="{ + fontIcon: 'fas fa-search', + matColor: 'primary', + click: minTrayVisSwitch.toggle.bind(minTrayVisSwitch), + badge: voiFeatureEntryCmp.totals$ | async + }"> + </ng-template> + </div> - </ng-template> </div> </ng-template> -- GitLab