From cdc7161ded1432cc6093cd90beb07361e1caefcb Mon Sep 17 00:00:00 2001 From: Andrew Frueh Date: Mon, 27 Feb 2023 18:11:36 -0700 Subject: [PATCH] fix(tab-set): fix default tab with routing resolve several issues relating to setting the default tab based on url closes #2061 --- .../selected-tab-input-example.component.html | 2 +- .../selected-tab-input-example.component.ts | 31 ++--------- .../src/lib/tabs/tab-set/tab-set.component.ts | 43 +++++++++------ scripts/search-prep.ts | 52 +++---------------- src/app/analytics/analytics.component.html | 2 +- src/app/content/content.component.html | 2 +- .../foundations/foundations.component.html | 2 +- 7 files changed, 42 insertions(+), 92 deletions(-) diff --git a/projects/cashmere-examples/src/lib/selected-tab-input/selected-tab-input-example.component.html b/projects/cashmere-examples/src/lib/selected-tab-input/selected-tab-input-example.component.html index 3a1d9ecac..db196d8ba 100644 --- a/projects/cashmere-examples/src/lib/selected-tab-input/selected-tab-input-example.component.html +++ b/projects/cashmere-examples/src/lib/selected-tab-input/selected-tab-input-example.component.html @@ -24,7 +24,7 @@
Tab Selected: - + diff --git a/projects/cashmere-examples/src/lib/selected-tab-input/selected-tab-input-example.component.ts b/projects/cashmere-examples/src/lib/selected-tab-input/selected-tab-input-example.component.ts index c3b120796..0b05f5ae8 100644 --- a/projects/cashmere-examples/src/lib/selected-tab-input/selected-tab-input-example.component.ts +++ b/projects/cashmere-examples/src/lib/selected-tab-input/selected-tab-input-example.component.ts @@ -1,42 +1,21 @@ -import {Component, OnDestroy, OnInit} from '@angular/core'; +import { Component } from '@angular/core'; import { FormControl } from '@angular/forms'; import { TabChangeEvent } from '@healthcatalyst/cashmere'; -import { Subject } from 'rxjs'; -import { map, takeUntil } from 'rxjs/operators'; @Component({ selector: 'hc-selected-tab-input-example', templateUrl: 'selected-tab-input-example.component.html', - // TODO: delete the SCSS file if you don't need it in the example styleUrls: ['selected-tab-input-example.component.scss'] }) -export class SelectedTabInputExampleComponent implements OnInit, OnDestroy { - +export class SelectedTabInputExampleComponent { tabSelected = new FormControl(1); - currentSelected = 1; - unsubscribe = new Subject(); + currentSelected = 2; selectionChanged(event: TabChangeEvent): void { this.tabSelected.setValue(event.index); } - ngOnInit(): void { - this.tabSelected.valueChanges.pipe( - map(value => { - if (value) { - return Number(value); - } - - return 0; - }), - takeUntil(this.unsubscribe) - ).subscribe(value => { - this.currentSelected = value; - }); - } - - ngOnDestroy(): void { - this.unsubscribe.next(); - this.unsubscribe.complete(); + controlChanged(): void { + this.currentSelected = Number(this.tabSelected.value); } } diff --git a/projects/cashmere/src/lib/tabs/tab-set/tab-set.component.ts b/projects/cashmere/src/lib/tabs/tab-set/tab-set.component.ts index 477aa1f06..031276da4 100644 --- a/projects/cashmere/src/lib/tabs/tab-set/tab-set.component.ts +++ b/projects/cashmere/src/lib/tabs/tab-set/tab-set.component.ts @@ -14,7 +14,7 @@ import type {QueryList} from '@angular/core'; import {EventEmitter, TemplateRef} from '@angular/core'; import {TabComponent} from '../tab/tab.component'; import {ActivatedRoute, Router} from '@angular/router'; -import {Subject, interval, fromEvent, BehaviorSubject, Subscription} from 'rxjs'; +import {Subject, interval, fromEvent, Subscription} from 'rxjs'; import {distinctUntilChanged, filter, take, takeUntil} from 'rxjs/operators'; import {parseBooleanAttribute} from '../../util'; import {HcPopoverAnchorDirective} from '../../pop'; @@ -72,7 +72,7 @@ export class TabSetComponent implements AfterContentInit { private _tabsTotalWidth = 0; public _collapse = false; public _moreList: Array = []; - private _selectedTabSubject = new BehaviorSubject(0); + private _selectedTabSubject = new Subject(); private unsubscribe = new Subject(); /** The content to be displayed for the currently selected tab. @@ -117,7 +117,8 @@ export class TabSetComponent implements AfterContentInit { } /** Zero-based numerical value specifying which tab to select by default, setting to `none` means no tab - * will be immediately selected. Defaults to 0 (the first tab). */ + * will be immediately selected. Defaults to 0 (the first tab). + * For tabs using routing, the default tab will be set by the url and use this value as a fallback if no tab routerLinks match the url. */ @Input() get defaultTab(): string | number { return this._defaultTab; @@ -436,7 +437,8 @@ export class TabSetComponent implements AfterContentInit { } } else { if ( this._routerEnabled ) { - this.router.navigate([activeTab.routerLink], {relativeTo: this.route}); + const routeArray = Array.isArray(activeTab.routerLink) ? activeTab.routerLink : [activeTab.routerLink]; + this.router.navigate(routeArray, {relativeTo: this.route, queryParams: activeTab.queryParams}); } this._setActive(activeTab, shouldEmit, scrollIntoView); } @@ -476,7 +478,10 @@ export class TabSetComponent implements AfterContentInit { // is triggered const tabArray = this._tabs.toArray(); if (tabArray[Number(this.defaultTab)]) { - setTimeout(() => this._setActive(tabArray[Number(this.defaultTab)])); + setTimeout(() => { + this._selectedTab = tabArray[Number(this.defaultTab)]; + this._setActive(tabArray[Number(this.defaultTab)]); + }); } else { invalidDefaultTab(this.defaultTab); } @@ -499,22 +504,28 @@ export class TabSetComponent implements AfterContentInit { } private defaultToFirstRoute() { - const foundRoute = this._tabs - .map(tab => tab.routerLink) - .map(routerLink => this.mapRouterLinkToString(routerLink)) - .find(routerLink => { - const currentRoute = this.router.url; - return currentRoute === routerLink || currentRoute.indexOf(`${routerLink}/`) > -1; - }); + const tabArray = this._tabs.toArray(); + let routeTab = -1; + + for ( let i=0; i < tabArray.length; i++ ) { + const routerLink = this.mapRouterLinkToString(tabArray[i].routerLink); + const currentRoute = this.router.url.split("?")[0]; + if( currentRoute === routerLink || currentRoute.indexOf(`${routerLink}/`) > -1 ) { + routeTab = i; + break; + } + } - if (foundRoute) { + if ( routeTab >= 0 ) { + this._selectedTab = tabArray[routeTab]; return; } - const tabArray = this._tabs.toArray(); if (tabArray[Number(this.defaultTab)]) { - const firstRoute = this.mapRouterLinkToString(tabArray[Number(this.defaultTab)].routerLink); - this.router.navigate([firstRoute], {relativeTo: this.route}); + const firstRouteLink = tabArray[Number(this.defaultTab)].routerLink; + const firstRouteArray = Array.isArray(firstRouteLink) ? firstRouteLink : [firstRouteLink]; + this._selectedTab = tabArray[Number(this.defaultTab)]; + this.router.navigate(firstRouteArray, {relativeTo: this.route, queryParams: tabArray[Number(this.defaultTab)].queryParams}); } } diff --git a/scripts/search-prep.ts b/scripts/search-prep.ts index 053fe24ca..b98d86124 100644 --- a/scripts/search-prep.ts +++ b/scripts/search-prep.ts @@ -200,8 +200,8 @@ function readFoundationsFiles() { // Index the content section which is a combination of markdown and components function readContentFiles() { - // Start by parsing the main content markdown files - glob('guides/content/*.md', function (er, files) { + // Start by parsing the markdown files + glob('{guides/content/*.md,guides/content/*/*.md}', function (er, files) { files .map(file => { const basename = path.basename(file, path.extname(file)); @@ -240,13 +240,16 @@ function readContentFiles() { const endOfLine = element.indexOf( '\n' ); sectionTitle = element.substr( 2, endOfLine - 2); } + const pathParts = mapping.path.split('/'); + pathParts.shift(); + pathParts[pathParts.length - 1] = mapping.basename; const sectionObj = object = ({ // Set id to the sectionTitle in snake case id: changeCase.snakeCase(sectionTitle), title: changeCase.titleCase(sectionTitle) + ' - ' + changeCase.titleCase(mapping.basename), // Remove all the markdown from the file content and set it so we can search through it content: mdGetContent(element), - link: 'content/' + mapping.basename, + link: pathParts.join('/'), category: 'content', // Set displayName to basename for display purposes displayName: mapping.basename, @@ -261,49 +264,6 @@ function readContentFiles() { }); }); - // Then parse the user persona markdown files - glob('guides/content/personas/*.md', function (er, files) { - files - .map(file => { - const basename = path.basename(file, path.extname(file)); - return { - path: file, - basename: basename, - outFile: basename - }; - }) - .forEach(mapping => { - const fileContent = fs.readFileSync(mapping.path, 'utf8'); - // Go through each file and find titles - let matches: RegExpExecArray | null; - let found: string[] = []; - while ((matches = guideTitleRegex.exec(fileContent)) !== null) { - // This is necessary to avoid infinite loops with zero-width matches - if (matches.index === guideTitleRegex.lastIndex) { - guideTitleRegex.lastIndex++; - } - matches.forEach((match: string, groupIndex: number) => { - if (groupIndex === 1) { - found.push(match); - } - }); - } - - const sectionObj = object = ({ - id: changeCase.snakeCase(mapping.basename), - title: changeCase.titleCase(mapping.basename), - content: mdGetContent(fileContent), - link: 'content/personas/' + mapping.basename, - category: 'content', - displayName: mapping.basename, - type: 'persona', - section: changeCase.paramCase(mapping.basename) - }); - - searchArray.push(sectionObj); - }); - }); - // Then parse the content components glob('src/app/content/*/*.html', function (er, files) { files diff --git a/src/app/analytics/analytics.component.html b/src/app/analytics/analytics.component.html index 5cd454bc8..bd083b04a 100644 --- a/src/app/analytics/analytics.component.html +++ b/src/app/analytics/analytics.component.html @@ -33,7 +33,7 @@
- {{tab.data.title}} + {{tab.data.title}}
diff --git a/src/app/content/content.component.html b/src/app/content/content.component.html index 35d1001ee..1fafb8be7 100644 --- a/src/app/content/content.component.html +++ b/src/app/content/content.component.html @@ -33,7 +33,7 @@
- {{tab.data.title}} + {{tab.data.title}}
diff --git a/src/app/foundations/foundations.component.html b/src/app/foundations/foundations.component.html index 31f0aa42b..34be27954 100644 --- a/src/app/foundations/foundations.component.html +++ b/src/app/foundations/foundations.component.html @@ -33,7 +33,7 @@
- {{tab.data.title}} + {{tab.data.title}}