diff --git a/docs_app/src/app/app.component.html b/docs_app/src/app/app.component.html deleted file mode 100644 index 33da86c79e..0000000000 --- a/docs_app/src/app/app.component.html +++ /dev/null @@ -1,86 +0,0 @@ -
- -
- -
- - - - - #BlackLivesMatter - - - - - - Home - Home - - - -
- - View on GitHub -
-
-
- - - - - - - - -
- -
-
- -
- - - - -
-
- -
- -
- - diff --git a/docs_app/src/app/app.component.ts b/docs_app/src/app/app.component.ts index 7d08a66bee..39cab2b4ab 100644 --- a/docs_app/src/app/app.component.ts +++ b/docs_app/src/app/app.component.ts @@ -1,13 +1,4 @@ -import { - Component, - ElementRef, - HostBinding, - HostListener, - OnInit, - QueryList, - ViewChild, - ViewChildren, -} from '@angular/core'; +import { Component, ElementRef, HostBinding, HostListener, OnInit, QueryList, ViewChild, ViewChildren } from '@angular/core'; import { MatSidenav } from '@angular/material/sidenav'; import { CurrentNodes, NavigationService, NavigationNode, VersionInfo } from 'app/navigation/navigation.service'; @@ -30,7 +21,92 @@ const sideNavView = 'SideNav'; @Component({ selector: 'aio-shell', - templateUrl: './app.component.html', + template: `
+ +
+ +
+ + + + + #BlackLivesMatter + + + + + + Home + Home + + + +
+ + View on GitHub +
+
+
+ + + + + + + + +
+ +
+
+ +
+ + + + +
+
+ +
+ +
+ + `, }) export class AppComponent implements OnInit { currentDocument: DocumentContents; @@ -131,9 +207,9 @@ export class AppComponent implements OnInit { /* No need to unsubscribe because this root component never dies */ - this.documentService.currentDocument.subscribe(doc => (this.currentDocument = doc)); + this.documentService.currentDocument.subscribe((doc) => (this.currentDocument = doc)); - this.locationService.currentPath.subscribe(path => { + this.locationService.currentPath.subscribe((path) => { if (path === this.currentPath) { // scroll only if on same page (most likely a change to the hash) this.scrollService.scroll(); @@ -147,36 +223,35 @@ export class AppComponent implements OnInit { } }); - this.navigationService.currentNodes.subscribe(currentNodes => { + this.navigationService.currentNodes.subscribe((currentNodes) => { this.currentNodes = currentNodes; - }); // Compute the version picker list from the current version and the versions in the navigation map combineLatest( this.navigationService.versionInfo, - this.navigationService.navigationViews.pipe(map(views => views['docVersions'])) + this.navigationService.navigationViews.pipe(map((views) => views['docVersions'])) ).subscribe(([versionInfo, versions]) => { this.docVersions = [...versions]; // Find the current version - eithers title matches the current deployment mode // or its title matches the major version of the current version info this.currentDocVersion = this.docVersions.find( - version => version.title === this.deployment.mode || version.title === `v${versionInfo.major}` + (version) => version.title === this.deployment.mode || version.title === `v${versionInfo.major}` )!; this.currentDocVersion.title += ` (v${versionInfo.raw})`; }); - this.navigationService.navigationViews.subscribe(views => { + this.navigationService.navigationViews.subscribe((views) => { this.footerNodes = views['Footer'] || []; this.sideNavNodes = views['SideNav'] || []; this.topMenuNodes = views['TopBar'] || []; this.topMenuNarrowNodes = views['TopBarNarrow'] || this.topMenuNodes; }); - this.navigationService.versionInfo.subscribe(vi => (this.versionInfo = vi)); + this.navigationService.versionInfo.subscribe((vi) => (this.versionInfo = vi)); - const hasNonEmptyToc = this.tocService.tocList.pipe(map(tocList => tocList.length > 0)); + const hasNonEmptyToc = this.tocService.tocList.pipe(map((tocList) => tocList.length > 0)); combineLatest(hasNonEmptyToc, this.showFloatingToc).subscribe( ([hasToc, showFloatingToc]) => (this.hasFloatingToc = hasToc && showFloatingToc) ); @@ -230,13 +305,13 @@ export class AppComponent implements OnInit { } const head = this.dom.getElementsByTagName('head')[0]; - let element: HTMLLinkElement = this.dom.querySelector(`link[rel='canonical']`) || null + let element: HTMLLinkElement = this.dom.querySelector(`link[rel='canonical']`) || null; if (element === null) { element = this.dom.createElement('link') as HTMLLinkElement; head.appendChild(element); } - element.setAttribute('rel', 'canonical') - element.setAttribute('href', `https://rxjs.dev/${this.currentPath}`) + element.setAttribute('rel', 'canonical'); + element.setAttribute('href', `https://rxjs.dev/${this.currentPath}`); this.isTransitioning = false; } @@ -264,7 +339,7 @@ export class AppComponent implements OnInit { @HostListener('click', ['$event.target', '$event.button', '$event.ctrlKey', '$event.metaKey', '$event.altKey']) onClick(eventTarget: HTMLElement, button: number, ctrlKey: boolean, metaKey: boolean, altKey: boolean): boolean { // Hide the search results if we clicked outside both the "search box" and the "search results" - if (!this.searchElements.some(element => element.nativeElement.contains(eventTarget))) { + if (!this.searchElements.some((element) => element.nativeElement.contains(eventTarget))) { this.hideSearchResults(); } @@ -312,20 +387,12 @@ export class AppComponent implements OnInit { const pageClass = `page-${this.pageId}`; const folderClass = `folder-${this.folderId}`; const viewClasses = Object.keys(this.currentNodes) - .map(view => `view-${view}`) + .map((view) => `view-${view}`) .join(' '); const notificationClass = `aio-notification-${this.notification.showNotification}`; const notificationAnimatingClass = this.notificationAnimating ? 'aio-notification-animating' : ''; - this.hostClasses = [ - mode, - sideNavOpen, - pageClass, - folderClass, - viewClasses, - notificationClass, - notificationAnimatingClass, - ].join(' '); + this.hostClasses = [mode, sideNavOpen, pageClass, folderClass, viewClasses, notificationClass, notificationAnimatingClass].join(' '); } updateShell() { diff --git a/docs_app/src/app/custom-elements/api/api-list.component.html b/docs_app/src/app/custom-elements/api/api-list.component.html deleted file mode 100644 index 43fc80920f..0000000000 --- a/docs_app/src/app/custom-elements/api/api-list.component.html +++ /dev/null @@ -1,36 +0,0 @@ -
- - - - - - - -
- -
-
-

{{section.title}}

- -
-
diff --git a/docs_app/src/app/custom-elements/api/api-list.component.ts b/docs_app/src/app/custom-elements/api/api-list.component.ts index 418dbd3951..d0eb89d3cf 100644 --- a/docs_app/src/app/custom-elements/api/api-list.component.ts +++ b/docs_app/src/app/custom-elements/api/api-list.component.ts @@ -1,10 +1,10 @@ /* -* API List & Filter Component -* -* A page that displays a formatted list of the public Angular API entities. -* Clicking on a list item triggers navigation to the corresponding API entity document. -* Can add/remove API entity links based on filter settings. -*/ + * API List & Filter Component + * + * A page that displays a formatted list of the public Angular API entities. + * Clicking on a list item triggers navigation to the corresponding API entity document. + * Can add/remove API entity links based on filter settings. + */ import { Component, ElementRef, OnInit, ViewChild } from '@angular/core'; @@ -17,17 +17,41 @@ import { Option } from 'app/shared/select/select.component'; import { map } from 'rxjs/operators'; class SearchCriteria { - query ? = ''; - status ? = 'all'; - type ? = 'all'; + query? = ''; + status? = 'all'; + type? = 'all'; } @Component({ selector: 'aio-api-list', - templateUrl: './api-list.component.html', + template: `
+ + + +
+ +
+
+

{{ section.title }}

+ +
+
`, }) export class ApiListComponent implements OnInit { - filteredSections: Observable; showStatusMenu = false; @@ -43,7 +67,7 @@ export class ApiListComponent implements OnInit { types: Option[] = [ { value: 'all', title: 'All' }, { value: 'class', title: 'Class' }, - { value: 'const', title: 'Const'}, + { value: 'const', title: 'Const' }, { value: 'enum', title: 'Enum' }, { value: 'function', title: 'Function' }, { value: 'interface', title: 'Interface' }, @@ -53,27 +77,18 @@ export class ApiListComponent implements OnInit { statuses: Option[] = [ { value: 'all', title: 'All' }, { value: 'deprecated', title: 'Deprecated' }, - { value: 'security-risk', title: 'Security Risk' } + { value: 'security-risk', title: 'Security Risk' }, ]; @ViewChild('filter', { static: true }) queryEl: ElementRef; - constructor( - private apiService: ApiService, - private locationService: LocationService) { } + constructor(private apiService: ApiService, private locationService: LocationService) {} ngOnInit() { - this.filteredSections = - combineLatest( - this.apiService.sections, - this.criteriaSubject - ).pipe( - map( results => ({ sections: results[0], criteria: results[1]})), - map( results => ( - results.sections - .map(section => ({ ...section, items: this.filterSection(section, results.criteria) })) - )) - ); + this.filteredSections = combineLatest(this.apiService.sections, this.criteriaSubject).pipe( + map((results) => ({ sections: results[0], criteria: results[1] })), + map((results) => results.sections.map((section) => ({ ...section, items: this.filterSection(section, results.criteria) }))) + ); this.initializeSearchCriteria(); } @@ -81,19 +96,19 @@ export class ApiListComponent implements OnInit { // TODO: may need to debounce as the original did // although there shouldn't be any perf consequences if we don't setQuery(query: string) { - this.setSearchCriteria({query: (query || '').toLowerCase().trim() }); + this.setSearchCriteria({ query: (query || '').toLowerCase().trim() }); } setStatus(status: Option) { this.toggleStatusMenu(); this.status = status; - this.setSearchCriteria({status: status.value}); + this.setSearchCriteria({ status: status.value }); } setType(type: Option) { this.toggleTypeMenu(); this.type = type; - this.setSearchCriteria({type: type.value}); + this.setSearchCriteria({ type: type.value }); } toggleStatusMenu() { @@ -107,19 +122,15 @@ export class ApiListComponent implements OnInit { //////// Private ////////// private filterSection(section: ApiSection, { query, status, type }: SearchCriteria) { - const items = section.items!.filter(item => { + const items = section.items!.filter((item) => { return matchesType() && matchesStatus() && matchesQuery(); function matchesQuery() { - return !query || - section.name.indexOf(query) !== -1 || - item.name.indexOf(query) !== -1; + return !query || section.name.indexOf(query) !== -1 || item.name.indexOf(query) !== -1; } function matchesStatus() { - return status === 'all' || - status === item.stability || - (status === 'security-risk' && item.securityRisk); + return status === 'all' || status === item.stability || (status === 'security-risk' && item.securityRisk); } function matchesType() { @@ -128,35 +139,35 @@ export class ApiListComponent implements OnInit { }); // If there are no items we still return an empty array if the section name matches and the type is 'package' - return items.length ? items : (type === 'package' && (!query || section.name.indexOf(query) !== -1)) ? [] : null; + return items.length ? items : type === 'package' && (!query || section.name.indexOf(query) !== -1) ? [] : null; } // Get initial search criteria from URL search params private initializeSearchCriteria() { - const {query, status, type} = this.locationService.search(); + const { query, status, type } = this.locationService.search(); const q = (query || '').toLowerCase(); // Hack: can't bind to query because input cursor always forced to end-of-line. this.queryEl.nativeElement.value = q; - this.status = this.statuses.find(x => x.value === status) || this.statuses[0]; - this.type = this.types.find(x => x.value === type) || this.types[0]; + this.status = this.statuses.find((x) => x.value === status) || this.statuses[0]; + this.type = this.types.find((x) => x.value === type) || this.types[0]; this.searchCriteria = { query: q, status: this.status.value, - type: this.type.value + type: this.type.value, }; this.criteriaSubject.next(this.searchCriteria); } private setLocationSearch() { - const {query, status, type} = this.searchCriteria; + const { query, status, type } = this.searchCriteria; const params = { - query: query ? query : undefined, + query: query ? query : undefined, status: status !== 'all' ? status : undefined, - type: type !== 'all' ? type : undefined + type: type !== 'all' ? type : undefined, }; this.locationService.setSearch('API Search', params); diff --git a/docs_app/src/app/custom-elements/code/code-tabs.component.ts b/docs_app/src/app/custom-elements/code/code-tabs.component.ts index 249324bbf8..cd6801dd29 100644 --- a/docs_app/src/app/custom-elements/code/code-tabs.component.ts +++ b/docs_app/src/app/custom-elements/code/code-tabs.component.ts @@ -3,13 +3,13 @@ import { AfterViewInit, Component, ElementRef, Input, OnInit, QueryList, ViewChi import { CodeComponent } from './code.component'; export interface TabInfo { - class: string|null; + class: string | null; code: string; - language: string|null; + language: string | null; linenums: any; path: string; region: string; - header: string|null; + header: string | null; } /** @@ -30,12 +30,14 @@ export interface TabInfo { {{ tab.header }} - + @@ -75,7 +77,7 @@ export class CodeTabsComponent implements OnInit, AfterViewInit { linenums: tabContent.getAttribute('linenums') || this.linenums, path: tabContent.getAttribute('path') || '', region: tabContent.getAttribute('region') || '', - header: tabContent.getAttribute('header') + header: tabContent.getAttribute('header'), }; } } diff --git a/docs_app/src/app/custom-elements/code/code.component.ts b/docs_app/src/app/custom-elements/code/code.component.ts index f3c171faf4..a509106681 100644 --- a/docs_app/src/app/custom-elements/code/code.component.ts +++ b/docs_app/src/app/custom-elements/code/code.component.ts @@ -37,7 +37,7 @@ const DEFAULT_LINE_NUMS_COUNT = 10; @Component({ selector: 'aio-code', template: ` -
+    
       
- ` + `, }) export class CodeComponent implements OnChanges { ariaLabelCopy = ''; @@ -71,14 +71,16 @@ export class CodeComponent implements OnChanges { this.formatDisplayedCode(); } } - get code(): string { return this._code; } + get code(): string { + return this._code; + } _code: string; /** Whether the copy button should be shown. */ @Input() hideCopy: boolean; /** Language to render the code (e.g. javascript, dart, typescript). */ - @Input() language: string; + @Input() language: string | null; /** * Whether to display line numbers: @@ -96,13 +98,15 @@ export class CodeComponent implements OnChanges { /** Optional header to be displayed above the code. */ @Input() - set header(header: string) { + set header(header: string | null) { this._header = header; this.ariaLabelCopy = this.header ? `Copy code snippet from ${this.header}` : ''; this.ariaLabelEdit = this.header ? `Edit code snippet from ${this.header} in StackBlitz` : ''; } - get header(): string { return this._header; } - private _header: string; + get header(): string | null { + return this._header; + } + private _header: string | null; @Output() codeFormatted = new EventEmitter(); @@ -114,7 +118,8 @@ export class CodeComponent implements OnChanges { private pretty: PrettyPrinter, private copier: CopierService, private logger: Logger, - private stackblitz: StackblitzService) { } + private stackblitz: StackblitzService + ) {} ngOnChanges() { // If some inputs have changed and there is code displayed, update the view with the latest @@ -130,10 +135,14 @@ export class CodeComponent implements OnChanges { this.codeText = this.getCodeText(); // store the unformatted code as text (for copying) this.pretty - .formatCode(leftAlignedCode, this.language, this.getLinenums(leftAlignedCode)) - .pipe(tap(() => this.codeFormatted.emit())) - .subscribe(c => this.setCodeHtml(c), err => { /* ignore failure to format */ } - ); + .formatCode(leftAlignedCode, this.language ?? '', this.getLinenums(leftAlignedCode)) + .pipe(tap(() => this.codeFormatted.emit())) + .subscribe( + (c) => this.setCodeHtml(c), + (err) => { + /* ignore failure to format */ + } + ); } /** Sets the message showing that the code could not be found. */ @@ -163,9 +172,7 @@ export class CodeComponent implements OnChanges { const pattern = new RegExp('// html: (.*)'); const matches = code.match(pattern); - return matches - ? matches[1] - : ''; + return matches ? matches[1] : ''; } /** Copies the code snippet to the user's clipboard. */ @@ -185,26 +192,29 @@ export class CodeComponent implements OnChanges { editInStackBlitz() { this.stackblitz.openProject({ code: this.codeText, - language: this.language, + language: this.language ?? '', dependencies: { - rxjs: version + rxjs: version, }, - html: this.getHtmlFromCode(this.codeText) + html: this.getHtmlFromCode(this.codeText), }); } /** Gets the calculated value of linenums (boolean/number). */ getLinenums(code: string) { const linenums = - typeof this.linenums === 'boolean' ? this.linenums : - this.linenums === 'true' ? true : - this.linenums === 'false' ? false : - typeof this.linenums === 'string' ? parseInt(this.linenums, 10) : - this.linenums; + typeof this.linenums === 'boolean' + ? this.linenums + : this.linenums === 'true' + ? true + : this.linenums === 'false' + ? false + : typeof this.linenums === 'string' + ? parseInt(this.linenums, 10) + : this.linenums; // if no linenums, enable line numbers if more than one line - return linenums == null || isNaN(linenums as number) ? - (code.match(/\n/g) || []).length > DEFAULT_LINE_NUMS_COUNT : linenums; + return linenums == null || isNaN(linenums as number) ? (code.match(/\n/g) || []).length > DEFAULT_LINE_NUMS_COUNT : linenums; } } @@ -212,12 +222,15 @@ function leftAlign(text: string): string { let indent = Number.MAX_VALUE; const lines = text.split('\n'); - lines.forEach(line => { + lines.forEach((line) => { const lineIndent = line.search(/\S/); if (lineIndent !== -1) { indent = Math.min(lineIndent, indent); } }); - return lines.map(line => line.substr(indent)).join('\n').trim(); + return lines + .map((line) => line.substr(indent)) + .join('\n') + .trim(); } diff --git a/docs_app/src/app/custom-elements/expandable-section/expandable-section.component.html b/docs_app/src/app/custom-elements/expandable-section/expandable-section.component.html deleted file mode 100644 index e0c5017f03..0000000000 --- a/docs_app/src/app/custom-elements/expandable-section/expandable-section.component.html +++ /dev/null @@ -1,7 +0,0 @@ - - - {{title}} - - - - diff --git a/docs_app/src/app/custom-elements/expandable-section/expandable-section.component.ts b/docs_app/src/app/custom-elements/expandable-section/expandable-section.component.ts index 22dfa4b47f..de0496ece2 100644 --- a/docs_app/src/app/custom-elements/expandable-section/expandable-section.component.ts +++ b/docs_app/src/app/custom-elements/expandable-section/expandable-section.component.ts @@ -1,10 +1,16 @@ /* tslint:disable component-selector */ -import {Component, Input} from '@angular/core'; +import { Component, Input } from '@angular/core'; /** Custom element wrapper for the material expansion panel with a title input. */ @Component({ selector: 'aio-expandable-section', - templateUrl: 'expandable-section.component.html', + template: ` + + {{ title }} + + + + `, }) export class ExpandableSectionComponent { @Input() title; diff --git a/docs_app/src/app/custom-elements/live-example/live-example.component.html b/docs_app/src/app/custom-elements/live-example/live-example.component.html deleted file mode 100644 index 6c21e3b6fd..0000000000 --- a/docs_app/src/app/custom-elements/live-example/live-example.component.html +++ /dev/null @@ -1,22 +0,0 @@ - - - - - -
- -
-

- You can also download this example. -

-
- - {{title}} - - - {{title}} - - / download example - - -
diff --git a/docs_app/src/app/custom-elements/live-example/live-example.component.ts b/docs_app/src/app/custom-elements/live-example/live-example.component.ts index d5c6246a3f..8a75739c28 100644 --- a/docs_app/src/app/custom-elements/live-example/live-example.component.ts +++ b/docs_app/src/app/custom-elements/live-example/live-example.component.ts @@ -4,7 +4,6 @@ import { Location } from '@angular/common'; import { CONTENT_URL_PREFIX } from 'app/documents/document.service'; import { AttrMap, boolFromValue, getAttrs, getAttrValue } from 'app/shared/attribute-utils'; - const LIVE_EXAMPLE_BASE = CONTENT_URL_PREFIX + 'live-examples/'; const ZIP_BASE = CONTENT_URL_PREFIX + 'zips/'; @@ -52,10 +51,28 @@ const ZIP_BASE = CONTENT_URL_PREFIX + 'zips/'; */ @Component({ selector: 'live-example', - templateUrl: 'live-example.component.html' + template: ` + + + + + +
+ +
+

You can also download this example.

+
+ + {{ title }} + + + {{ title }} + / download example + +
+ `, }) export class LiveExampleComponent implements AfterContentInit { - readonly mode: 'default' | 'embedded' | 'downloadOnly'; readonly enableDownload: boolean; readonly stackblitz: string; @@ -104,9 +121,7 @@ export class LiveExampleComponent implements AfterContentInit { const downloadOnly = boolFromValue(getAttrValue(attrs, 'downloadOnly')); const isEmbedded = boolFromValue(getAttrValue(attrs, 'embedded')); - return downloadOnly ? 'downloadOnly' - : isEmbedded ? 'embedded' : - 'default'; + return downloadOnly ? 'downloadOnly' : isEmbedded ? 'embedded' : 'default'; } private getStackblitz(exampleDir: string, stackblitzName: string, isEmbedded: boolean) { @@ -137,7 +152,7 @@ export class LiveExampleComponent implements AfterContentInit { @Component({ selector: 'aio-embedded-stackblitz', template: ``, - styles: [ 'iframe { min-height: 400px; }' ] + styles: ['iframe { min-height: 400px; }'], }) export class EmbeddedStackblitzComponent implements AfterViewInit { @Input() src: string; diff --git a/docs_app/src/app/custom-elements/operator-decision-tree/operator-decision-tree.component.html b/docs_app/src/app/custom-elements/operator-decision-tree/operator-decision-tree.component.html deleted file mode 100644 index 9b01897083..0000000000 --- a/docs_app/src/app/custom-elements/operator-decision-tree/operator-decision-tree.component.html +++ /dev/null @@ -1,55 +0,0 @@ -

- Operator Decision Tree -

- -

- {{currentSentence$ | async}} -

- -
- - -
-
-
- - - - - -

- You want the {{option.method}} of the {{option.docType}} - {{option.label}}. -

-

- You want the {{option.docType}} - {{option.label}}. -

-
-
-
-
- - -
-

Oops! There was an issue loading the decision tree.. we're real sorry about that. Please try reloading the page.

-

You can also try submitting an issue on Github.

-
-
\ No newline at end of file diff --git a/docs_app/src/app/custom-elements/operator-decision-tree/operator-decision-tree.component.ts b/docs_app/src/app/custom-elements/operator-decision-tree/operator-decision-tree.component.ts index a3121f158e..c1d904d2a1 100644 --- a/docs_app/src/app/custom-elements/operator-decision-tree/operator-decision-tree.component.ts +++ b/docs_app/src/app/custom-elements/operator-decision-tree/operator-decision-tree.component.ts @@ -1,10 +1,4 @@ -import { - animate, - state, - style, - transition, - trigger -} from '@angular/animations'; +import { animate, state, style, transition, trigger } from '@angular/animations'; import { Component, OnDestroy } from '@angular/core'; import { ScrollService } from 'app/shared/scroll.service'; import { Observable } from 'rxjs'; @@ -13,17 +7,60 @@ import { OperatorDecisionTreeService } from './operator-decision-tree.service'; @Component({ selector: 'aio-operator-decision-tree', - templateUrl: './operator-decision-tree.component.html', + template: ` +

Operator Decision Tree

+ +

+ {{ currentSentence$ | async }} +

+ +
+ + +
+
+
+ + + + + +

+ You want the {{ option.method }} of the {{ option.docType }} + {{ option.label }}. +

+

+ You want the {{ option.docType }} {{ option.label }}. +

+
+
+
+
+ + +
+

Oops! There was an issue loading the decision tree.. we're real sorry about that. Please try reloading the page.

+

+ You can also try + submitting an issue on Github. +

+
+
+ `, styleUrls: ['./operator-decision-tree.component.scss'], animations: [ trigger('flyIn', [ state('in', style({ transform: 'translateX(0)' })), - transition(':enter', [ - style({ transform: 'translateX(-100%)' }), - animate(250) - ]) - ]) - ] + transition(':enter', [style({ transform: 'translateX(-100%)' }), animate(250)]), + ]), + ], }) export class OperatorDecisionTreeComponent implements OnDestroy { currentSentence$: Observable = this.operatorDecisionTreeService.currentSentence$; @@ -31,10 +68,7 @@ export class OperatorDecisionTreeComponent implements OnDestroy { isBeyondInitialQuestion$: Observable = this.operatorDecisionTreeService.isBeyondInitialQuestion$; hasError$: Observable = this.operatorDecisionTreeService.hasError$; - constructor( - private operatorDecisionTreeService: OperatorDecisionTreeService, - private scrollService: ScrollService - ) {} + constructor(private operatorDecisionTreeService: OperatorDecisionTreeService, private scrollService: ScrollService) {} selectOption(optionId: string): void { this.operatorDecisionTreeService.selectOption(optionId); diff --git a/docs_app/src/app/custom-elements/resource/resource-list.component.html b/docs_app/src/app/custom-elements/resource/resource-list.component.html deleted file mode 100644 index e5b861caeb..0000000000 --- a/docs_app/src/app/custom-elements/resource/resource-list.component.html +++ /dev/null @@ -1,28 +0,0 @@ -
-
-
-
- -

{{category.title}}

-
- - -
-
-
diff --git a/docs_app/src/app/custom-elements/resource/resource-list.component.ts b/docs_app/src/app/custom-elements/resource/resource-list.component.ts index 2b424db538..f1331fa72a 100644 --- a/docs_app/src/app/custom-elements/resource/resource-list.component.ts +++ b/docs_app/src/app/custom-elements/resource/resource-list.component.ts @@ -6,32 +6,58 @@ import { ResourceService } from './resource.service'; @Component({ selector: 'aio-resource-list', - templateUrl: 'resource-list.component.html' + template: ` +
+
+
+
+ +

{{ category.title }}

+
+ + +
+
+
+ `, }) export class ResourceListComponent implements OnInit { - categories: Category[]; location: string; scrollPos = 0; - constructor( - location: PlatformLocation, - private resourceService: ResourceService) { + constructor(location: PlatformLocation, private resourceService: ResourceService) { this.location = location.pathname.replace(/^\/+/, ''); } - href(cat: {id: string}) { + href(cat: { id: string }) { return this.location + '#' + cat.id; } ngOnInit() { // Not using async pipe because cats appear twice in template // No need to unsubscribe because categories observable completes. - this.resourceService.categories.subscribe(cats => this.categories = cats); + this.resourceService.categories.subscribe((cats) => (this.categories = cats)); } @HostListener('window:scroll', ['$event.target']) onScroll(target: any) { - this.scrollPos = target ? target.scrollTop || target.body.scrollTop || 0 : 0; + this.scrollPos = target ? target.scrollTop || target.body.scrollTop || 0 : 0; } } diff --git a/docs_app/src/app/custom-elements/toc/toc.component.html b/docs_app/src/app/custom-elements/toc/toc.component.html deleted file mode 100644 index 4aa7b989d6..0000000000 --- a/docs_app/src/app/custom-elements/toc/toc.component.html +++ /dev/null @@ -1,31 +0,0 @@ -
- -
- Contents -
- - - -
    - -
  • - -
  • -
    -
- - -
diff --git a/docs_app/src/app/custom-elements/toc/toc.component.ts b/docs_app/src/app/custom-elements/toc/toc.component.ts index a5908b6de4..f2e4d594cc 100644 --- a/docs_app/src/app/custom-elements/toc/toc.component.ts +++ b/docs_app/src/app/custom-elements/toc/toc.component.ts @@ -9,42 +9,72 @@ type TocType = 'None' | 'Floating' | 'EmbeddedSimple' | 'EmbeddedExpandable'; @Component({ selector: 'aio-toc', - templateUrl: 'toc.component.html', - styles: [] + template: `
+
Contents
+ + + +
    + +
  • + +
  • +
    +
+ + +
`, + styles: [], }) export class TocComponent implements OnInit, AfterViewInit, OnDestroy { - activeIndex: number | null = null; type: TocType = 'None'; isCollapsed = true; isEmbedded = false; @ViewChildren('tocItem') private items: QueryList; private onDestroy = new Subject(); - private primaryMax = 4; + primaryMax = 4; tocList: TocItem[]; - constructor( - private scrollService: ScrollService, - elementRef: ElementRef, - private tocService: TocService) { + constructor(private scrollService: ScrollService, elementRef: ElementRef, private tocService: TocService) { this.isEmbedded = elementRef.nativeElement.className.indexOf('embedded') !== -1; } ngOnInit() { - this.tocService.tocList - .pipe(takeUntil(this.onDestroy)) - .subscribe(tocList => { - this.tocList = tocList; - const itemCount = count(this.tocList, item => item.level !== 'h1'); - - this.type = (itemCount > 0) ? - this.isEmbedded ? - (itemCount > this.primaryMax) ? - 'EmbeddedExpandable' : - 'EmbeddedSimple' : - 'Floating' : - 'None'; - }); + this.tocService.tocList.pipe(takeUntil(this.onDestroy)).subscribe((tocList) => { + this.tocList = tocList; + const itemCount = count(this.tocList, (item) => item.level !== 'h1'); + + this.type = + itemCount > 0 ? (this.isEmbedded ? (itemCount > this.primaryMax ? 'EmbeddedExpandable' : 'EmbeddedSimple') : 'Floating') : 'None'; + }); } ngAfterViewInit() { @@ -53,25 +83,25 @@ export class TocComponent implements OnInit, AfterViewInit, OnDestroy { // which, in turn, are caused by the rendering that happened due to a ChangeDetection. // Without asap, we would be updating the model while still in a ChangeDetection handler, which is disallowed by Angular. combineLatest(this.tocService.activeItemIndex.pipe(subscribeOn(asap)), this.items.changes.pipe(startWith(this.items))) - .pipe(takeUntil(this.onDestroy)) - .subscribe(([index, items]) => { - this.activeIndex = index; - if (index === null || index >= items.length) { - return; - } + .pipe(takeUntil(this.onDestroy)) + .subscribe(([index, items]) => { + this.activeIndex = index; + if (index === null || index >= items.length) { + return; + } - const e = items.toArray()[index].nativeElement; - const p = e.offsetParent; + const e = items.toArray()[index].nativeElement; + const p = e.offsetParent; - const eRect = e.getBoundingClientRect(); - const pRect = p.getBoundingClientRect(); + const eRect = e.getBoundingClientRect(); + const pRect = p.getBoundingClientRect(); - const isInViewport = (eRect.top >= pRect.top) && (eRect.bottom <= pRect.bottom); + const isInViewport = eRect.top >= pRect.top && eRect.bottom <= pRect.bottom; - if (!isInViewport) { - p.scrollTop += (eRect.top - pRect.top) - (p.clientHeight / 2); - } - }); + if (!isInViewport) { + p.scrollTop += eRect.top - pRect.top - p.clientHeight / 2; + } + }); } } @@ -81,7 +111,9 @@ export class TocComponent implements OnInit, AfterViewInit, OnDestroy { toggle(canScroll = true) { this.isCollapsed = !this.isCollapsed; - if (canScroll && this.isCollapsed) { this.toTop(); } + if (canScroll && this.isCollapsed) { + this.toTop(); + } } toTop() { @@ -90,5 +122,5 @@ export class TocComponent implements OnInit, AfterViewInit, OnDestroy { } function count(array: T[], fn: (item: T) => boolean) { - return array.reduce((result, item) => fn(item) ? result + 1 : result, 0); + return array.reduce((result, item) => (fn(item) ? result + 1 : result), 0); } diff --git a/docs_app/src/app/layout/footer/footer.component.html b/docs_app/src/app/layout/footer/footer.component.html deleted file mode 100644 index 68932a456d..0000000000 --- a/docs_app/src/app/layout/footer/footer.component.html +++ /dev/null @@ -1,6 +0,0 @@ -

- Code licensed under an Apache-2.0 License. Documentation licensed under - CC BY 4.0. -

-

Version {{ versionInfo?.full }}.

- diff --git a/docs_app/src/app/layout/footer/footer.component.ts b/docs_app/src/app/layout/footer/footer.component.ts index ad89c7480f..859822d111 100644 --- a/docs_app/src/app/layout/footer/footer.component.ts +++ b/docs_app/src/app/layout/footer/footer.component.ts @@ -4,7 +4,11 @@ import { NavigationNode, VersionInfo } from 'app/navigation/navigation.service'; @Component({ selector: 'aio-footer', - templateUrl: 'footer.component.html' + template: `

+ Code licensed under an Apache-2.0 License. Documentation licensed under + CC BY 4.0. +

+

Version {{ versionInfo?.full }}.

`, }) export class FooterComponent { @Input() nodes: NavigationNode[]; diff --git a/docs_app/src/app/layout/nav-item/nav-item.component.html b/docs_app/src/app/layout/nav-item/nav-item.component.html deleted file mode 100644 index 5e76ec1e46..0000000000 --- a/docs_app/src/app/layout/nav-item/nav-item.component.html +++ /dev/null @@ -1,27 +0,0 @@ - - -
- - {{node.title}} - - - - - -
- -
-
diff --git a/docs_app/src/app/layout/nav-item/nav-item.component.ts b/docs_app/src/app/layout/nav-item/nav-item.component.ts index a62612f834..54aa763f0a 100644 --- a/docs_app/src/app/layout/nav-item/nav-item.component.ts +++ b/docs_app/src/app/layout/nav-item/nav-item.component.ts @@ -1,32 +1,75 @@ -import { Component, Input, OnChanges} from '@angular/core'; +import { Component, Input, OnChanges } from '@angular/core'; import { NavigationNode } from 'app/navigation/navigation.model'; @Component({ selector: 'aio-nav-item', - templateUrl: 'nav-item.component.html', + template: ` + +
+ + {{ node.title }} + + + + + +
+ +
+
`, }) export class NavItemComponent implements OnChanges { @Input() isWide = false; @Input() level = 1; @Input() node: NavigationNode; @Input() isParentExpanded = true; - @Input() selectedNodes: NavigationNode[]; + @Input() selectedNodes: NavigationNode[] | undefined; isExpanded = false; isSelected = false; - classes: {[index: string]: boolean }; + classes: { [index: string]: boolean }; nodeChildren: NavigationNode[]; ngOnChanges() { - this.nodeChildren = this.node && this.node.children ? this.node.children.filter(n => !n.hidden) : []; + this.nodeChildren = this.node && this.node.children ? this.node.children.filter((n) => !n.hidden) : []; if (this.selectedNodes) { const ix = this.selectedNodes.indexOf(this.node); this.isSelected = ix !== -1; // this node is the selected node or its ancestor - this.isExpanded = this.isParentExpanded && + this.isExpanded = + this.isParentExpanded && (this.isSelected || // expand if selected or ... - // preserve expanded state when display is wide; collapse in mobile. - (this.isWide && this.isExpanded)); + // preserve expanded state when display is wide; collapse in mobile. + (this.isWide && this.isExpanded)); } else { this.isSelected = false; } @@ -39,7 +82,7 @@ export class NavItemComponent implements OnChanges { ['level-' + this.level]: true, collapsed: !this.isExpanded, expanded: this.isExpanded, - selected: this.isSelected + selected: this.isSelected, }; } diff --git a/docs_app/src/app/layout/nav-menu/nav-menu.component.ts b/docs_app/src/app/layout/nav-menu/nav-menu.component.ts index 53194f6c96..acc5d5f19f 100644 --- a/docs_app/src/app/layout/nav-menu/nav-menu.component.ts +++ b/docs_app/src/app/layout/nav-menu/nav-menu.component.ts @@ -3,13 +3,14 @@ import { CurrentNode, NavigationNode } from 'app/navigation/navigation.service'; @Component({ selector: 'aio-nav-menu', - template: ` - - ` + template: ` + `, }) export class NavMenuComponent { - @Input() currentNode: CurrentNode; + @Input() currentNode: CurrentNode | undefined; @Input() isWide = false; @Input() nodes: NavigationNode[]; - get filteredNodes() { return this.nodes ? this.nodes.filter(n => !n.hidden) : []; } + get filteredNodes() { + return this.nodes ? this.nodes.filter((n) => !n.hidden) : []; + } } diff --git a/docs_app/src/app/layout/notification/notification.component.html b/docs_app/src/app/layout/notification/notification.component.html deleted file mode 100644 index 58d7b6bc46..0000000000 --- a/docs_app/src/app/layout/notification/notification.component.html +++ /dev/null @@ -1,7 +0,0 @@ - - - - - diff --git a/docs_app/src/app/layout/notification/notification.component.ts b/docs_app/src/app/layout/notification/notification.component.ts index f68ac639a5..ba2381f74c 100644 --- a/docs_app/src/app/layout/notification/notification.component.ts +++ b/docs_app/src/app/layout/notification/notification.component.ts @@ -7,17 +7,23 @@ const LOCAL_STORAGE_NAMESPACE = 'aio-notification/'; @Component({ selector: 'aio-notification', - templateUrl: 'notification.component.html', + template: ` + + + + `, animations: [ trigger('hideAnimation', [ - state('show', style({height: '*'})), - state('hide', style({height: 0})), + state('show', style({ height: '*' })), + state('hide', style({ height: 0 })), // this should be kept in sync with the animation durations in: // - aio/src/styles/2-modules/_notification.scss // - aio/src/app/app.component.ts : notificationDismissed() - transition('show => hide', animate(250)) - ]) - ] + transition('show => hide', animate(250)), + ]), + ], }) export class NotificationComponent implements OnInit { private storage: Storage; @@ -28,12 +34,9 @@ export class NotificationComponent implements OnInit { @Output() dismissed = new EventEmitter(); @HostBinding('@hideAnimation') - showNotification: 'show'|'hide'; + showNotification: 'show' | 'hide'; - constructor( - @Inject(WindowToken) window: Window, - @Inject(CurrentDateToken) private currentDate: Date - ) { + constructor(@Inject(WindowToken) window: Window, @Inject(CurrentDateToken) private currentDate: Date) { try { this.storage = window.localStorage; } catch { @@ -45,7 +48,7 @@ export class NotificationComponent implements OnInit { getItem: () => null, key: () => null, removeItem: () => undefined, - setItem: () => undefined + setItem: () => undefined, }; } } @@ -67,4 +70,4 @@ export class NotificationComponent implements OnInit { this.showNotification = 'hide'; this.dismissed.next(null); } -} \ No newline at end of file +} diff --git a/docs_app/src/app/navigation/navigation.model.ts b/docs_app/src/app/navigation/navigation.model.ts index e54f175977..0739fefd57 100644 --- a/docs_app/src/app/navigation/navigation.model.ts +++ b/docs_app/src/app/navigation/navigation.model.ts @@ -4,13 +4,13 @@ export interface NavigationNode { url?: string; - title?: string; + title: string; tooltip?: string; hidden?: boolean; children?: NavigationNode[]; } -export type NavigationResponse = {__versionInfo: VersionInfo } & { [name: string]: NavigationNode[]|VersionInfo }; +export type NavigationResponse = { __versionInfo: VersionInfo } & { [name: string]: NavigationNode[] | VersionInfo }; export interface NavigationViews { [name: string]: NavigationNode[]; diff --git a/docs_app/src/app/shared/search-results/search-results.component.html b/docs_app/src/app/shared/search-results/search-results.component.html deleted file mode 100644 index fedce7b829..0000000000 --- a/docs_app/src/app/shared/search-results/search-results.component.html +++ /dev/null @@ -1,28 +0,0 @@ -
-
-
- - -

Search Results

-
-

{{area.name}} ({{area.pages.length + area.priorityPages.length}})

- - -
-
- - -

{{notFoundMessage}}

-
diff --git a/docs_app/src/app/shared/search-results/search-results.component.ts b/docs_app/src/app/shared/search-results/search-results.component.ts index 9423fa9556..af064ffd9d 100644 --- a/docs_app/src/app/shared/search-results/search-results.component.ts +++ b/docs_app/src/app/shared/search-results/search-results.component.ts @@ -1,4 +1,4 @@ -import { Component, EventEmitter, Input, OnChanges, Output, SimpleChanges } from '@angular/core'; +import { Component, EventEmitter, Input, OnChanges, Output } from '@angular/core'; import { SearchResult, SearchResults, SearchArea } from 'app/search/interfaces'; /** @@ -6,15 +6,41 @@ import { SearchResult, SearchResults, SearchArea } from 'app/search/interfaces'; */ @Component({ selector: 'aio-search-results', - templateUrl: './search-results.component.html', + template: `
+
+
+ + +

Search Results

+
+

{{ area.name }} ({{ area.pages.length + area.priorityPages.length }})

+ + +
+
+ + +

{{ notFoundMessage }}

+
`, }) export class SearchResultsComponent implements OnChanges { - /** * The results to display */ @Input() - searchResults: SearchResults; + searchResults: SearchResults | null; /** * Emitted when the user selects a search result @@ -27,8 +53,8 @@ export class SearchResultsComponent implements OnChanges { readonly topLevelFolders = ['guide', 'tutorial']; searchAreas: SearchArea[] = []; - ngOnChanges(changes: SimpleChanges) { - this.searchAreas = this.processSearchResults(this.searchResults); + ngOnChanges() { + this.searchAreas = this.searchResults ? this.processSearchResults(this.searchResults) : []; } onResultSelected(page: SearchResult, event: MouseEvent) { @@ -45,14 +71,16 @@ export class SearchResultsComponent implements OnChanges { } this.notFoundMessage = 'No results found.'; const searchAreaMap: { [key: string]: SearchResult[] } = {}; - search.results.forEach(result => { - if (!result.title) { return; } // bad data; should fix + search.results.forEach((result) => { + if (!result.title) { + return; + } // bad data; should fix const areaName = this.computeAreaName(result) || this.defaultArea; - const area = searchAreaMap[areaName] = searchAreaMap[areaName] || []; + const area = (searchAreaMap[areaName] = searchAreaMap[areaName] || []); area.push(result); }); - const keys = Object.keys(searchAreaMap).sort((l, r) => l > r ? 1 : -1); - return keys.map(name => { + const keys = Object.keys(searchAreaMap).sort((l, r) => (l > r ? 1 : -1)); + return keys.map((name) => { let pages: SearchResult[] = searchAreaMap[name]; // Extract the top 5 most relevant results as priorityPages diff --git a/docs_app/src/app/shared/select/select.component.html b/docs_app/src/app/shared/select/select.component.html deleted file mode 100644 index 54974b82c0..0000000000 --- a/docs_app/src/app/shared/select/select.component.html +++ /dev/null @@ -1,16 +0,0 @@ -
- -
    -
  • - {{option.title}} -
  • -
-
diff --git a/docs_app/src/app/shared/select/select.component.ts b/docs_app/src/app/shared/select/select.component.ts index 11bc9913df..7587327387 100644 --- a/docs_app/src/app/shared/select/select.component.ts +++ b/docs_app/src/app/shared/select/select.component.ts @@ -7,7 +7,25 @@ export interface Option { @Component({ selector: 'aio-select', - templateUrl: 'select.component.html' + template: `
+ +
    +
  • + {{ option.title }} +
  • +
+
`, }) export class SelectComponent implements OnInit { @Input() @@ -17,7 +35,7 @@ export class SelectComponent implements OnInit { options: Option[]; @Output() - change = new EventEmitter<{option: Option, index: number}>(); + change = new EventEmitter<{ option: Option; index: number }>(); @Input() showSymbol = false; @@ -43,7 +61,7 @@ export class SelectComponent implements OnInit { select(option: Option, index: number) { this.selected = option; - this.change.emit({option, index}); + this.change.emit({ option, index }); this.hideOptions(); } diff --git a/docs_app/tsconfig.json b/docs_app/tsconfig.json index 456aca1889..9082db4c2c 100644 --- a/docs_app/tsconfig.json +++ b/docs_app/tsconfig.json @@ -23,6 +23,9 @@ ], "module": "esnext" }, + "angularCompilerOptions": { + "strictTemplates": true, + }, "exclude": [ "content", "tools",