From 9d6d87a7aef53b1e4f9a1917adc9d91fb075dc16 Mon Sep 17 00:00:00 2001 From: Xiao Gui <xgui3783@gmail.com> Date: Wed, 27 May 2020 14:50:15 +0200 Subject: [PATCH] chore: sort modalities alphabetically chore: use constant for aria labels --- common/constants.js | 5 +++ docs/releases/v2.2.2.md | 5 +++ .../browsingForDatasets.prod.e2e-spec.js | 31 ++++++++++++++- .../scrollDatasetContainer.prod.e2e-spec.js | 19 +++------- e2e/src/util.js | 17 +++++++++ mkdocs.yml | 1 + .../databrowserModule/databrowser.module.ts | 3 +- .../databrowser/databrowser.component.ts | 5 +++ .../databrowser/databrowser.template.html | 5 ++- .../modalityPicker.component.spec.ts | 38 +++++++++++++++++++ .../modalityPicker.component.ts | 15 +++++++- .../modalityPicker.template.html | 2 +- .../searchSideNav/searchSideNav.component.ts | 4 ++ .../searchSideNav/searchSideNav.template.html | 2 +- 14 files changed, 131 insertions(+), 21 deletions(-) create mode 100644 docs/releases/v2.2.2.md create mode 100644 src/ui/databrowserModule/modalityPicker/modalityPicker.component.spec.ts diff --git a/common/constants.js b/common/constants.js index c5f7c0567..8981be7c4 100644 --- a/common/constants.js +++ b/common/constants.js @@ -1,6 +1,11 @@ (function(exports){ exports.ARIA_LABELS = { + // dataset specific + TOGGLE_EXPLORE_PANEL: `Toggle explore panel`, + MODALITY_FILTER: `Toggle dataset modality filter`, + LIST_OF_DATASETS: `List of datasets`, + // overlay specific CONTEXT_MENU: `Viewer context menu`, diff --git a/docs/releases/v2.2.2.md b/docs/releases/v2.2.2.md new file mode 100644 index 000000000..c46eed59a --- /dev/null +++ b/docs/releases/v2.2.2.md @@ -0,0 +1,5 @@ +# v2.2.2 + +## Bugfixes + +- Modal filters are now sorted alphabetically (#523) \ No newline at end of file diff --git a/e2e/src/advanced/browsingForDatasets.prod.e2e-spec.js b/e2e/src/advanced/browsingForDatasets.prod.e2e-spec.js index b5cb270a7..7850abac0 100644 --- a/e2e/src/advanced/browsingForDatasets.prod.e2e-spec.js +++ b/e2e/src/advanced/browsingForDatasets.prod.e2e-spec.js @@ -1,4 +1,6 @@ const { AtlasPage } = require('../util') +const { ARIA_LABELS } = require('../../../common/constants') +const { TOGGLE_EXPLORE_PANEL, MODALITY_FILTER } = ARIA_LABELS const templates = [ 'MNI Colin 27', @@ -121,4 +123,31 @@ describe('> dataset previews', () => { const modalHasImage = await iavPage.modalHasChild('div[data-img-src]') expect(modalHasImage).toEqual(true) }) -}) \ No newline at end of file +}) + +describe('> modality picker', () => { + let iavPage + beforeAll(async () => { + iavPage = new AtlasPage() + await iavPage.init() + await iavPage.goto() + }) + it('> sorted alphabetically', async () => { + await iavPage.selectTitleCard(templates[1]) + await iavPage.wait(500) + await iavPage.waitUntilAllChunksLoaded() + await iavPage.click(`[aria-label="${TOGGLE_EXPLORE_PANEL}"]`) + await iavPage.wait(500) + await iavPage.clearAlerts() + await iavPage.click(`[aria-label="${MODALITY_FILTER}"]`) + await iavPage.wait(500) + const modalities = await iavPage.getModalities() + for (let i = 1; i < modalities.length; i ++) { + expect( + modalities[i].charCodeAt(0) + ).toBeGreaterThanOrEqual( + modalities[i - 1].charCodeAt(0) + ) + } + }) +}) diff --git a/e2e/src/layout/scrollDatasetContainer.prod.e2e-spec.js b/e2e/src/layout/scrollDatasetContainer.prod.e2e-spec.js index 198be8f23..0643817f7 100644 --- a/e2e/src/layout/scrollDatasetContainer.prod.e2e-spec.js +++ b/e2e/src/layout/scrollDatasetContainer.prod.e2e-spec.js @@ -1,11 +1,12 @@ const { AtlasPage } = require('../util') - +const { ARIA_LABELS } = require('../../../common/constants') describe('> scroll dataset container', () => { let iavPage beforeEach(async () => { iavPage = new AtlasPage() await iavPage.init() + }) it('> can scroll to the end', async () => { @@ -14,23 +15,13 @@ describe('> scroll dataset container', () => { await iavPage.wait(1000) await iavPage.waitForAsync() - const btnCssSelector = `[aria-label="Toggle explore panel"]` - // const btnCssSelector = `button[mat-stroked-button].m-1.flex-grow-1.overflow-hidden` - - // TODO use .clickByCss method in future - // TODO import aria label from common/constant.js in future - await iavPage._browser - .findElement( By.css(btnCssSelector) ) - .click() + await iavPage.click(`[aria-label="${ARIA_LABELS.TOGGLE_EXPLORE_PANEL}"]`) await iavPage.clearAlerts() - const scrollContainerCssSelector = '[aria-label="List of datasets"]' - // const scrollContainerCssSelector = 'cdk-virtual-scroll-viewport' - let countdown = 100 do { - await iavPage.scrollElementBy(scrollContainerCssSelector, { + await iavPage.scrollElementBy(`[aria-label="${ARIA_LABELS.LIST_OF_DATASETS}"]`, { delta: [0, 100] }) await iavPage.wait(100) @@ -39,7 +30,7 @@ describe('> scroll dataset container', () => { await iavPage.wait(500) - const val = await iavPage.getScrollStatus(scrollContainerCssSelector) + const val = await iavPage.getScrollStatus(`[aria-label="${ARIA_LABELS.LIST_OF_DATASETS}"]`) expect(val).toBeGreaterThanOrEqual(10000) }) }) \ No newline at end of file diff --git a/e2e/src/util.js b/e2e/src/util.js index 134ca978f..a279f3e49 100644 --- a/e2e/src/util.js +++ b/e2e/src/util.js @@ -772,6 +772,23 @@ class WdIavPage extends WdLayoutPage{ } } + _getModalityListView(){ + return this._browser + .findElement( By.tagName('modality-picker') ) + .findElements( By.tagName('mat-checkbox') ) + } + + async getModalities(){ + const els = await this._getModalityListView() + const returnArr = [] + for (const el of els) { + returnArr.push( + await el.getText() + ) + } + return returnArr + } + _getSingleDatasetListView(){ return this._browser .findElement( By.tagName('data-browser') ) diff --git a/mkdocs.yml b/mkdocs.yml index 25324af62..351f3d914 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -40,6 +40,7 @@ pages: - Fetching datasets: 'advanced/datasets.md' - Display non-atlas volumes: 'advanced/otherVolumes.md' - Release notes: + - v2.2.2: 'releases/v2.2.2.md' - v2.2.1: 'releases/v2.2.1.md' - v2.2.0: 'releases/v2.2.0.md' - v2.1.3: 'releases/v2.1.3.md' diff --git a/src/ui/databrowserModule/databrowser.module.ts b/src/ui/databrowserModule/databrowser.module.ts index 422d9cb01..dbbcd361d 100644 --- a/src/ui/databrowserModule/databrowser.module.ts +++ b/src/ui/databrowserModule/databrowser.module.ts @@ -7,7 +7,7 @@ import { DoiParserPipe } from "src/util/pipes/doiPipe.pipe"; import { UtilModule } from "src/util/util.module"; import { DataBrowser } from "./databrowser/databrowser.component"; import { KgSingleDatasetService } from "./kgSingleDatasetService.service" -import { ModalityPicker } from "./modalityPicker/modalityPicker.component"; +import { ModalityPicker, SortModalityAlphabeticallyPipe } from "./modalityPicker/modalityPicker.component"; import { SingleDatasetView } from './singleDataset/detailedView/singleDataset.component' import { AggregateArrayIntoRootPipe } from "./util/aggregateArrayIntoRoot.pipe"; import { CopyPropertyPipe } from "./util/copyProperty.pipe"; @@ -115,6 +115,7 @@ const previewEmitFactory = (store: Store<any>, previewDisplayed: (file,dataset) PreviewFileVisibleInSelectedReferenceTemplatePipe, UnavailableTooltip, TransformDatasetToIdPipe, + SortModalityAlphabeticallyPipe ], exports: [ DataBrowser, diff --git a/src/ui/databrowserModule/databrowser/databrowser.component.ts b/src/ui/databrowserModule/databrowser/databrowser.component.ts index 94167944c..75daf7070 100644 --- a/src/ui/databrowserModule/databrowser/databrowser.component.ts +++ b/src/ui/databrowserModule/databrowser/databrowser.component.ts @@ -4,6 +4,9 @@ import { LoggingService } from "src/logging"; import { IDataEntry } from "src/services/stateStore.service"; import { CountedDataModality, DatabrowserService } from "../databrowser.service"; import { ModalityPicker } from "../modalityPicker/modalityPicker.component"; +import { ARIA_LABELS } from 'common/constants.js' + +const { MODALITY_FILTER, LIST_OF_DATASETS } = ARIA_LABELS @Component({ selector : 'data-browser', @@ -17,6 +20,8 @@ import { ModalityPicker } from "../modalityPicker/modalityPicker.component"; export class DataBrowser implements OnChanges, OnDestroy, OnInit { + public MODALITY_FILTER_ARIA_LABEL = MODALITY_FILTER + public LIST_OF_DATASETS_ARIA_LABEL = LIST_OF_DATASETS @Input() public regions: any[] = [] diff --git a/src/ui/databrowserModule/databrowser/databrowser.template.html b/src/ui/databrowserModule/databrowser/databrowser.template.html index 007409078..72c51396a 100644 --- a/src/ui/databrowserModule/databrowser/databrowser.template.html +++ b/src/ui/databrowserModule/databrowser/databrowser.template.html @@ -70,7 +70,7 @@ <mat-card-content class="dataset-container w-100 overflow-hidden"> <!-- TODO export aria labels to common/constants --> <cdk-virtual-scroll-viewport - [attr.aria-label]="'List of datasets'" + [attr.aria-label]="LIST_OF_DATASETS_ARIA_LABEL" class="h-100" minBufferPx="200" maxBufferPx="400" @@ -103,7 +103,8 @@ <!-- Filters --> <mat-expansion-panel hideToggle> - <mat-expansion-panel-header class="align-items-center"> + <mat-expansion-panel-header class="align-items-center" + [attr.aria-label]="MODALITY_FILTER_ARIA_LABEL"> <mat-panel-title class="d-inline-flex align-items-center"> <div class="flex-grow-1 flex-shrink-1 d-flex flex-column"> <span> diff --git a/src/ui/databrowserModule/modalityPicker/modalityPicker.component.spec.ts b/src/ui/databrowserModule/modalityPicker/modalityPicker.component.spec.ts new file mode 100644 index 000000000..f7313420c --- /dev/null +++ b/src/ui/databrowserModule/modalityPicker/modalityPicker.component.spec.ts @@ -0,0 +1,38 @@ +import { SortModalityAlphabeticallyPipe } from "./modalityPicker.component" +import { CountedDataModality } from "../databrowser.service" + +describe('> modalityPicker.component.ts', () => { + describe('> ModalityPicker', () => { + // TODO + }) + + describe('> SortModalityAlphabeticallyPipe', () => { + + const mods: CountedDataModality[] = [{ + name: 'bbb', + occurance: 0, + visible: false + }, { + name: 'AAA', + occurance: 1, + visible: false + }, { + name: '007', + occurance: 17, + visible: false + }] + const beforeInput = [...mods] + const pipe = new SortModalityAlphabeticallyPipe() + + const output = pipe.transform(mods) + + it('> does not mutate', () => { + expect(mods).toEqual(beforeInput) + }) + it('> should sort modalities as expected', () => { + expect(output).toEqual([ + mods[2], mods[1], mods[0] + ]) + }) + }) +}) diff --git a/src/ui/databrowserModule/modalityPicker/modalityPicker.component.ts b/src/ui/databrowserModule/modalityPicker/modalityPicker.component.ts index f7505efcd..b6a897adb 100644 --- a/src/ui/databrowserModule/modalityPicker/modalityPicker.component.ts +++ b/src/ui/databrowserModule/modalityPicker/modalityPicker.component.ts @@ -1,4 +1,4 @@ -import { Component, EventEmitter, Input, OnChanges, Output } from "@angular/core"; +import { Component, EventEmitter, Input, OnChanges, Output, Pipe, PipeTransform } from "@angular/core"; import { CountedDataModality } from "../databrowser.service"; @Component({ @@ -61,3 +61,16 @@ export class ModalityPicker implements OnChanges { ) } } + +const sortByFn = (a: CountedDataModality, b: CountedDataModality) => (a.name || '0').charCodeAt(0) - (b.name || '0').charCodeAt(0) + +@Pipe({ + name: 'sortModalityAlphabetically', + pure: true +}) + +export class SortModalityAlphabeticallyPipe implements PipeTransform{ + public transform(arr: CountedDataModality[]): CountedDataModality[]{ + return [...arr].sort(sortByFn) + } +} diff --git a/src/ui/databrowserModule/modalityPicker/modalityPicker.template.html b/src/ui/databrowserModule/modalityPicker/modalityPicker.template.html index 0a84ce45d..e0bcaa540 100644 --- a/src/ui/databrowserModule/modalityPicker/modalityPicker.template.html +++ b/src/ui/databrowserModule/modalityPicker/modalityPicker.template.html @@ -2,6 +2,6 @@ [checked]="datamodality.visible" (change)="toggleModality(datamodality)" [ngClass]="{'muted': datamodality.occurance === 0}" - *ngFor="let datamodality of countedDataM"> + *ngFor="let datamodality of countedDataM | sortModalityAlphabetically"> {{ datamodality.name }} <span class="text-muted">({{ datamodality.occurance }})</span> </mat-checkbox> \ No newline at end of file diff --git a/src/ui/searchSideNav/searchSideNav.component.ts b/src/ui/searchSideNav/searchSideNav.component.ts index fe9bcb9dc..ca50684e1 100644 --- a/src/ui/searchSideNav/searchSideNav.component.ts +++ b/src/ui/searchSideNav/searchSideNav.component.ts @@ -13,6 +13,9 @@ import { IavRootStoreInterface, SELECT_REGIONS } from "src/services/stateStore.s import { trackRegionBy } from '../viewerStateController/regionHierachy/regionHierarchy.component' import { MatDialog, MatDialogRef } from "@angular/material/dialog"; import { MatSnackBar } from "@angular/material/snack-bar"; +import { ARIA_LABELS } from 'common/constants.js' + +const { TOGGLE_EXPLORE_PANEL } = ARIA_LABELS @Component({ selector: 'search-side-nav', @@ -23,6 +26,7 @@ import { MatSnackBar } from "@angular/material/snack-bar"; }) export class SearchSideNav implements OnDestroy { + public TOGGLE_EXPLORE_PANEL_ARIA_LABEL = TOGGLE_EXPLORE_PANEL public availableDatasets: number = 0 private subscriptions: Subscription[] = [] diff --git a/src/ui/searchSideNav/searchSideNav.template.html b/src/ui/searchSideNav/searchSideNav.template.html index 5335dd861..d9f0f5b8a 100644 --- a/src/ui/searchSideNav/searchSideNav.template.html +++ b/src/ui/searchSideNav/searchSideNav.template.html @@ -14,7 +14,7 @@ <div class="d-flex flex-row justify-content-center" card-footer> <!-- TODO export all aria labels to common/constants.js in future patch --> <button mat-stroked-button - aria-label="Toggle explore panel" + [attr.aria-label]="TOGGLE_EXPLORE_PANEL_ARIA_LABEL" *ngIf="!(sidePanelExploreCurrentViewIsOpen$ | async)" (click)="expandSidePanelCurrentView()" [disabled]="!(viewerStateController.parcellationSelected$ | async)" -- GitLab