diff --git a/docs/releases/v2.8.0.md b/docs/releases/v2.8.0.md index d9923d3492fef8960600f1f6036f039697cd3f79..fe599a52d35d3b5afc05029e2951006b641b20b6 100644 --- a/docs/releases/v2.8.0.md +++ b/docs/releases/v2.8.0.md @@ -2,8 +2,10 @@ ## Features -- More detailed filter for connectivity -- Supports arbitrary layer based on URL parameter +- More detailed filter for connectivity (#1158) +- Supports arbitrary layer based on URL parameter (#1252) +- Mini region search now shows prompt ... and {n} more (#1249) +- Minor update of mini region search UI ## Behind the scenes @@ -13,3 +15,4 @@ ## Bugfix - fixed open cheatsheet/quickstart in new window functionality +- fixed region hierarchy, on hit enter resetting the application (#1240) diff --git a/src/atlasComponents/sapiViews/core/rich/module.ts b/src/atlasComponents/sapiViews/core/rich/module.ts index 8f946335ee020a073f3ff6f74124360513db6123..f8fcc8a936495f8e769e33f0756882dde15f9532 100644 --- a/src/atlasComponents/sapiViews/core/rich/module.ts +++ b/src/atlasComponents/sapiViews/core/rich/module.ts @@ -9,6 +9,7 @@ import { SapiViewsCoreRegionModule } from "../region"; import { HighlightPipe } from "./regionsHierarchy/highlight.pipe"; import { SapiViewsCoreRichRegionsHierarchy } from "./regionsHierarchy/regionsHierarchy.component"; import { SapiViewsCoreRichRegionListSearch } from "./regionsListSearch/regionListSearch.component"; +import { SapiViewsCoreRichRegionListTemplateDirective } from "./regionsListSearch/regionListSearchTmpl.directive"; @NgModule({ imports: [ @@ -24,9 +25,11 @@ import { SapiViewsCoreRichRegionListSearch } from "./regionsListSearch/regionLis SapiViewsCoreRichRegionListSearch, SapiViewsCoreRichRegionsHierarchy, HighlightPipe, + SapiViewsCoreRichRegionListTemplateDirective, ], exports: [ SapiViewsCoreRichRegionListSearch, + SapiViewsCoreRichRegionListTemplateDirective, SapiViewsCoreRichRegionsHierarchy, ] }) diff --git a/src/atlasComponents/sapiViews/core/rich/regionsHierarchy/regionsHierarchy.template.html b/src/atlasComponents/sapiViews/core/rich/regionsHierarchy/regionsHierarchy.template.html index 9c085e07cef508f4de0506fb740705c341616790..f3a4e82d473fcb11a80abf856c560f79e722ac89 100644 --- a/src/atlasComponents/sapiViews/core/rich/regionsHierarchy/regionsHierarchy.template.html +++ b/src/atlasComponents/sapiViews/core/rich/regionsHierarchy/regionsHierarchy.template.html @@ -1,20 +1,18 @@ -<form class="sxplr-custom-cmp text sxplr-w-100"> - <mat-form-field class="sxplr-w-100"> - <input - [placeholder]="placeholderText" - type="text" - matInput - name="searchTerm" - [formControl]="searchFormControl" - autocomplete="off"> +<mat-form-field class="sxplr-custom-cmp text sxplr-w-100"> + <input + [placeholder]="placeholderText" + type="text" + matInput + name="searchTerm" + [formControl]="searchFormControl" + autocomplete="off"> - <!-- search input suffix --> - <div matSuffix> - <ng-content select="[search-input-suffix]"></ng-content> - </div> + <!-- search input suffix --> + <div matSuffix> + <ng-content select="[search-input-suffix]"></ng-content> + </div> - </mat-form-field> -</form> +</mat-form-field> <ng-template #tmplRef let-region> <div class="mat-body sxplr-d-flex sxplr-align-items-center sxplr-h-100 region-tmpl" diff --git a/src/atlasComponents/sapiViews/core/rich/regionsListSearch/regionListSearch.component.ts b/src/atlasComponents/sapiViews/core/rich/regionsListSearch/regionListSearch.component.ts index 86970540a7e41edcca06a35c2b4cb366ae542077..d169eb904f4ce01fe5d9753a95acce50180d326b 100644 --- a/src/atlasComponents/sapiViews/core/rich/regionsListSearch/regionListSearch.component.ts +++ b/src/atlasComponents/sapiViews/core/rich/regionsListSearch/regionListSearch.component.ts @@ -1,9 +1,10 @@ -import { ChangeDetectionStrategy, Component, EventEmitter, Input, Output, TemplateRef } from "@angular/core"; +import { ChangeDetectionStrategy, Component, ContentChild, EventEmitter, Input, Output, TemplateRef } from "@angular/core"; import { SapiRegionModel } from "src/atlasComponents/sapi/type"; import { ARIA_LABELS } from "common/constants" import { UntypedFormControl } from "@angular/forms"; import { debounceTime, distinctUntilChanged, map, startWith } from "rxjs/operators"; import { MatAutocompleteSelectedEvent } from "@angular/material/autocomplete"; +import { SapiViewsCoreRichRegionListTemplateDirective } from "./regionListSearchTmpl.directive"; /** * Filter function, which determines whether the region will be included in the list of autocompleted search. @@ -34,6 +35,8 @@ export class SapiViewsCoreRichRegionListSearch { ARIA_LABELS = ARIA_LABELS + showNOptions = 4 + private _regions: SapiRegionModel[] = [] get regions(){ return this._regions @@ -43,6 +46,9 @@ export class SapiViewsCoreRichRegionListSearch { this._regions = val.filter(filterRegionForListSearch) } + @ContentChild(SapiViewsCoreRichRegionListTemplateDirective) + regionTmplDirective: SapiViewsCoreRichRegionListTemplateDirective + @Input('sxplr-sapiviews-core-rich-regionlistsearch-region-template-ref') regionTemplateRef: TemplateRef<any> @@ -54,18 +60,22 @@ export class SapiViewsCoreRichRegionListSearch { public searchFormControl = new UntypedFormControl() - public autocompleteList$ = this.searchFormControl.valueChanges.pipe( + public searchedList$ = this.searchFormControl.valueChanges.pipe( startWith(''), distinctUntilChanged(), debounceTime(160), map((searchTerm: string | SapiRegionModel) => { if (typeof searchTerm === "string") { - return this.regions.filter(filterRegionViaSearch(searchTerm)).slice(0,5) + return this.regions.filter(filterRegionViaSearch(searchTerm)) } return [] }) ) + public autocompleteList$ = this.searchedList$.pipe( + map(list => list.slice(0, this.showNOptions)) + ) + displayFn(region: SapiRegionModel){ return region?.name || '' } diff --git a/src/atlasComponents/sapiViews/core/rich/regionsListSearch/regionListSearch.stories.ts b/src/atlasComponents/sapiViews/core/rich/regionsListSearch/regionListSearch.stories.ts index 2c63c54de2b32ef0bae180e56ab59639bafa0fa6..872925713ec79672db9a07cff96f03839c24a28e 100644 --- a/src/atlasComponents/sapiViews/core/rich/regionsListSearch/regionListSearch.stories.ts +++ b/src/atlasComponents/sapiViews/core/rich/regionsListSearch/regionListSearch.stories.ts @@ -5,9 +5,10 @@ import { SAPI } from "src/atlasComponents/sapi" import { atlasId, provideDarkTheme, getParcRegions, parcId, spaceId } from "src/atlasComponents/sapi/stories.base" import { SapiViewsCoreRichModule } from "../module" import { SapiViewsCoreRichRegionListSearch } from "./regionListSearch.component" -import { Pipe, PipeTransform, SecurityContext } from "@angular/core" +import { Pipe, PipeTransform } from "@angular/core" import { SapiRegionModel } from "src/atlasComponents/sapi/type" -import { DomSanitizer, SafeHtml } from "@angular/platform-browser" +import { DomSanitizer } from "@angular/platform-browser" +import { SapiViewsCoreRegionModule } from "../../region" @Pipe({ name: 'regionTmplPipe', @@ -38,6 +39,7 @@ export default { imports: [ HttpClientModule, SapiViewsCoreRichModule, + SapiViewsCoreRegionModule, ], providers: [ SAPI, @@ -63,10 +65,8 @@ const Template: Story<SapiViewsCoreRichRegionListSearch> = (args: SapiViewsCoreR tmplRef } = parameters const template = ` - ${tmplRef ? ('<ng-template #tmplref let-region>' + tmplRef + '</ng-template>') : ''} - <sxplr-sapiviews-core-rich-regionlistsearch - ${tmplRef ? '[sxplr-sapiviews-core-rich-regionlistsearch-region-template-ref]="tmplref"' : ''} - > + <sxplr-sapiviews-core-rich-regionlistsearch> + ${tmplRef ? ('<ng-template regionTemplate let-region>' + tmplRef + '</ng-template>') : ''} ${contentProjection || ''} </sxplr-sapiviews-core-rich-regionlistsearch> ` @@ -80,6 +80,9 @@ const Template: Story<SapiViewsCoreRichRegionListSearch> = (args: SapiViewsCoreR }) } Template.loaders = [] +Template.parameters = { + tmplRef: `<span>{{ region.name }}</span>` +} const asyncLoader = async (atlasId: string, parcId: string, spaceId: string) => { const regions = await getParcRegions(atlasId, parcId, spaceId) @@ -97,6 +100,14 @@ const getContentProjection = ({ searchInputSuffix }) => { } export const Default = Template.bind({}) +Default.parameters = { + ...Template.parameters, + tmplRef: ` +<sxplr-sapiviews-core-region-region-list-item + [sxplr-sapiviews-core-region-region]="region"> +</sxplr-sapiviews-core-region-region-list-item> +` +} Default.loaders = [ async () => { const { regions } = await asyncLoader(atlasId.human, parcId.human.jba29, spaceId.human.mni152) @@ -112,6 +123,7 @@ InputSuffix.loaders = [ } ] InputSuffix.parameters = { + ...Template.parameters, contentProjection: getContentProjection({ searchInputSuffix: `SUFFIX` }) @@ -125,7 +137,8 @@ TemplatedRegionSuffix.loaders = [ } ] TemplatedRegionSuffix.parameters = { - tmplRef: `<span [innerHTML]="region | regionTmplPipe"></span>` + ...Template.parameters, + tmplRef: `<span [innerHTML]="region | regionTmplPipe"></span><span>{{ region.name }}</span>` } diff --git a/src/atlasComponents/sapiViews/core/rich/regionsListSearch/regionListSearch.template.html b/src/atlasComponents/sapiViews/core/rich/regionsListSearch/regionListSearch.template.html index 379454ff524357eb9a5717253349a17dac8df6ff..7f381436634978627b83709d6cf3ad40e0a8a6bf 100644 --- a/src/atlasComponents/sapiViews/core/rich/regionsListSearch/regionListSearch.template.html +++ b/src/atlasComponents/sapiViews/core/rich/regionsListSearch/regionListSearch.template.html @@ -32,21 +32,33 @@ *ngFor="let region of autocompleteList$ | async" [value]="region"> - <div class="sxplr-d-flex sxplr-justify-content-space-between"> + <ng-template [ngIf]="regionTmplDirective"> - <sxplr-sapiviews-core-region-region-list-item - [sxplr-sapiviews-core-region-region]="region"> - </sxplr-sapiviews-core-region-region-list-item> - <ng-template - [ngIf]="regionTemplateRef" - [ngTemplateOutlet]="regionTemplateRef" + [ngTemplateOutlet]="regionTmplDirective.tmplRef" [ngTemplateOutletContext]="{ $implicit: region }"> - </ng-template> - </div> + </ng-template> </mat-option> + <ng-template [ngIf]="searchedList$ | async" let-searchedList> + + <mat-option *ngIf="searchedList.length > showNOptions" + [disabled]="true"> + + <ng-template [ngIf]="regionTmplDirective"> + + <ng-template + [ngTemplateOutlet]="regionTmplDirective.tmplRef" + [ngTemplateOutletContext]="{ + $implicit: { + name: '... and ' + (searchedList.length - showNOptions) + ' more' + } + }"> + </ng-template> + </ng-template> + </mat-option> + </ng-template> </mat-autocomplete> \ No newline at end of file diff --git a/src/atlasComponents/sapiViews/core/rich/regionsListSearch/regionListSearchTmpl.directive.ts b/src/atlasComponents/sapiViews/core/rich/regionsListSearch/regionListSearchTmpl.directive.ts new file mode 100644 index 0000000000000000000000000000000000000000..ecc282ee47ba3a328c13444d7890afcd8c62047b --- /dev/null +++ b/src/atlasComponents/sapiViews/core/rich/regionsListSearch/regionListSearchTmpl.directive.ts @@ -0,0 +1,10 @@ +import { Directive, TemplateRef } from "@angular/core"; +import { SapiRegionModel } from "src/atlasComponents/sapi/type"; + +@Directive({ + selector: 'ng-template[region-template],ng-template[regionTemplate]' +}) + +export class SapiViewsCoreRichRegionListTemplateDirective{ + constructor(public tmplRef: TemplateRef<SapiRegionModel>){} +} diff --git a/src/viewerModule/viewerCmp/viewerCmp.template.html b/src/viewerModule/viewerCmp/viewerCmp.template.html index b0e06fdaab9dcdca386cf69563c8334f2313336e..419f3fd1bb60ec2394c6d2c25286f98a15de1af5 100644 --- a/src/viewerModule/viewerCmp/viewerCmp.template.html +++ b/src/viewerModule/viewerCmp/viewerCmp.template.html @@ -515,28 +515,23 @@ <ng-template #autocompleteTmpl let-showTour="showTour"> <div class="sxplr-custom-cmp bg card ml-2 mr-2 mat-elevation-z8 pe-all auto-complete-container"> - <ng-template #selectedRegionCheckTmpl let-region> - <ng-template #fallbackTmpl> - <button mat-icon-button - class="sxplr-mt-a sxplr-mb-a"> - <i class="far fa-square"></i> - </button> - </ng-template> - - <button *ngIf="selectedRegions$ | async | includes : region; else fallbackTmpl" - mat-icon-button - color="primary" - class="sxplr-mt-a sxplr-mb-a"> - <i class="far fa-check-square"></i> - </button> - </ng-template> - <sxplr-sapiviews-core-rich-regionlistsearch [sxplr-sapiviews-core-rich-regionlistsearch-regions]="allAvailableRegions$ | async" [sxplr-sapiviews-core-rich-regionlistsearch-current-search]="selectedRegions$ | async | getProperty : 0 | getProperty : 'name'" - [sxplr-sapiviews-core-rich-regionlistsearch-region-template-ref]="selectedRegionCheckTmpl" (sxplr-sapiviews-core-rich-regionlistsearch-region-select)="selectRoi($event)"> - + <ng-template regionTemplate let-region> + <div class="sxplr-d-flex"> + <button + mat-icon-button + class="sxplr-mt-a sxplr-mb-a"> + <i [ngClass]="(selectedRegions$ | async | includes : region) ? 'fa-circle' : 'fa-none'" class="fas"></i> + </button> + + <sxplr-sapiviews-core-region-region-list-item + [sxplr-sapiviews-core-region-region]="region"> + </sxplr-sapiviews-core-region-region-list-item> + </div> + </ng-template> <button mat-icon-button search-input-suffix *ngIf="selectedRegions$ | async | getProperty : 'length'"