From 3560ebd80884c12f1c62867c4668e71c0e30d2c8 Mon Sep 17 00:00:00 2001 From: btroncone Date: Tue, 19 Dec 2017 13:39:08 -0500 Subject: [PATCH 1/4] feat(operators): add support for vendor specific examples in operator docs --- package.json | 3 +- src/app/material/material.module.ts | 9 +- src/app/operators/_operator-theme.scss | 67 +++++++++++++-- .../operator-examples.component.html | 18 ++-- .../operator-examples.component.scss | 17 ---- .../operator-extras.component.scss | 16 ---- .../operator-general.component.html | 34 ++++++++ .../operator-general.component.scss | 1 + .../operator-general.component.ts | 61 +++++++++++++ .../operator-header.component.scss | 6 +- .../operator-vendor-examples.component.html | 13 +++ .../operator-vendor-examples.component.scss | 6 ++ .../operator-vendor-examples.component.ts | 35 ++++++++ .../operator/operator.component.html | 58 +++++-------- .../operator/operator.component.scss | 18 ---- .../components/operator/operator.component.ts | 85 +++++-------------- src/app/operators/operators-routing.module.ts | 14 ++- src/app/operators/operators.module.ts | 4 + src/operator-docs/operator.model.ts | 17 ++-- src/styles.scss | 1 + src/styles/_general.scss | 15 ++++ tsconfig.json | 9 +- 22 files changed, 321 insertions(+), 186 deletions(-) create mode 100644 src/app/operators/components/operator-general/operator-general.component.html create mode 100644 src/app/operators/components/operator-general/operator-general.component.scss create mode 100644 src/app/operators/components/operator-general/operator-general.component.ts create mode 100644 src/app/operators/components/operator-vendor-examples/operator-vendor-examples.component.html create mode 100644 src/app/operators/components/operator-vendor-examples/operator-vendor-examples.component.scss create mode 100644 src/app/operators/components/operator-vendor-examples/operator-vendor-examples.component.ts create mode 100644 src/styles/_general.scss diff --git a/package.json b/package.json index 5225b37a..09724d50 100644 --- a/package.json +++ b/package.json @@ -32,7 +32,7 @@ "@angular/common": "5.1.1", "@angular/compiler": "5.1.1", "@angular/core": "5.1.1", - "@angular/flex-layout": "2.0.0-beta.10-4905443", + "@angular/flex-layout": "2.0.0-beta.12", "@angular/forms": "5.1.1", "@angular/http": "5.1.1", "@angular/material": "5.0.1", @@ -55,7 +55,6 @@ "@types/jasmine": "2.5.53", "@types/jasminewd2": "2.0.2", "@types/lodash": "4.14.77", - "@types/node": "6.0.60", "angular2-template-loader": "0.6.2", "codelyzer": "4.0.2", "commitizen": "^2.9.6", diff --git a/src/app/material/material.module.ts b/src/app/material/material.module.ts index d762a596..9044cdf0 100644 --- a/src/app/material/material.module.ts +++ b/src/app/material/material.module.ts @@ -12,7 +12,8 @@ import { MatInputModule, MatMenuModule, MatTooltipModule, - MatSnackBarModule + MatSnackBarModule, + MatTabsModule } from '@angular/material'; @NgModule({ @@ -28,7 +29,8 @@ import { MatInputModule, MatMenuModule, MatTooltipModule, - MatSnackBarModule + MatSnackBarModule, + MatTabsModule ], exports: [ MatToolbarModule, @@ -41,7 +43,8 @@ import { MatInputModule, MatMenuModule, MatTooltipModule, - MatSnackBarModule + MatSnackBarModule, + MatTabsModule ] }) export class MaterialModule {} diff --git a/src/app/operators/_operator-theme.scss b/src/app/operators/_operator-theme.scss index bcdfda12..0e64ad33 100644 --- a/src/app/operators/_operator-theme.scss +++ b/src/app/operators/_operator-theme.scss @@ -19,13 +19,53 @@ $link-color: #2196f3; } } - app-operator a { - text-decoration: none; - color: $link-color; + app-operator-general, + app-operator-vendor-examples { + .main-operator-container { + padding: 5px; + display: flex; + flex-direction: column; + padding: 0 16px; + margin-bottom: 32px; + } + + .short-description { + margin: 16px 0 32px; + } + + a { + text-decoration: none; + color: $link-color; + + &:hover { + text-decoration: underline; + } + } + + .extra-tip { + display: flex; + } + + h3 { + display: inline-block; + vertical-align: middle; + padding-left: 10px; + } + + .tip-warning { + color: rgb(244, 67, 54); + } + + .tip-info { + color: rgb(33, 150, 243); + } } - app-operator a:hover { - text-decoration: underline; + .operator-section-tabs { + .mat-ink-bar { + background-color: $accent !important; + height: 3px; + } } .operator-list { @@ -56,4 +96,21 @@ $link-color: #2196f3; } } } + + .code-block { + position: relative; + + pre { + margin-top: 0; + padding-top: 0; + } + } + + .frame-wrapper { + iframe { + border: none; + width: 100%; + height: 350px; + } + } } diff --git a/src/app/operators/components/operator-examples/operator-examples.component.html b/src/app/operators/components/operator-examples/operator-examples.component.html index 021b9499..5abf053b 100644 --- a/src/app/operators/components/operator-examples/operator-examples.component.html +++ b/src/app/operators/components/operator-examples/operator-examples.component.html @@ -1,14 +1,22 @@

Examples

-
+
-
-
-
- +
+
diff --git a/src/app/operators/components/operator-examples/operator-examples.component.scss b/src/app/operators/components/operator-examples/operator-examples.component.scss index ae9fda53..c3312554 100644 --- a/src/app/operators/components/operator-examples/operator-examples.component.scss +++ b/src/app/operators/components/operator-examples/operator-examples.component.scss @@ -1,12 +1,3 @@ -.code-block { - position: relative; - - pre { - margin-top: 0; - padding-top: 0; - } -} - .menu-button { position: absolute; right: 0; @@ -36,11 +27,3 @@ .code-example { margin-bottom: 16px; } - -.bin-wrapper { - iframe { - border: none; - width: 100%; - height: 350px; - } -} diff --git a/src/app/operators/components/operator-extras/operator-extras.component.scss b/src/app/operators/components/operator-extras/operator-extras.component.scss index 100097d3..8b137891 100644 --- a/src/app/operators/components/operator-extras/operator-extras.component.scss +++ b/src/app/operators/components/operator-extras/operator-extras.component.scss @@ -1,17 +1 @@ -.extra-tip { - display: flex; -} -h3 { - display: inline-block; - vertical-align: middle; - padding-left: 10px; -} - -.tip-warning { - color: rgb(244, 67, 54); -} - -.tip-info { - color: rgb(33, 150, 243); -} diff --git a/src/app/operators/components/operator-general/operator-general.component.html b/src/app/operators/components/operator-general/operator-general.component.html new file mode 100644 index 00000000..a1352d3a --- /dev/null +++ b/src/app/operators/components/operator-general/operator-general.component.html @@ -0,0 +1,34 @@ +
+

+

+ + + + + + + + + + + + + + + + +
diff --git a/src/app/operators/components/operator-general/operator-general.component.scss b/src/app/operators/components/operator-general/operator-general.component.scss new file mode 100644 index 00000000..8b137891 --- /dev/null +++ b/src/app/operators/components/operator-general/operator-general.component.scss @@ -0,0 +1 @@ + diff --git a/src/app/operators/components/operator-general/operator-general.component.ts b/src/app/operators/components/operator-general/operator-general.component.ts new file mode 100644 index 00000000..3b5530d3 --- /dev/null +++ b/src/app/operators/components/operator-general/operator-general.component.ts @@ -0,0 +1,61 @@ +import { + Component, + Input, + OnInit, + OnDestroy, + ViewEncapsulation +} from '@angular/core'; +import { OperatorDoc, ALL_OPERATORS } from '../../../../operator-docs'; +import { CopierService } from '../../../core/services/copier.service'; +import { MatSnackBar } from '@angular/material'; +import { OperatorComponent } from '../operator/operator.component'; +import { ActivatedRoute } from '@angular/router'; +import { takeUntil } from 'rxjs/operators/takeUntil'; +import { Subject } from 'rxjs/Subject'; + +@Component({ + selector: 'app-operator-general', + templateUrl: './operator-general.component.html', + styleUrls: ['./operator-general.component.scss'], + encapsulation: ViewEncapsulation.None +}) +export class OperatorGeneralComponent implements OnInit, OnDestroy { + public operator: OperatorDoc; + private _onDestroy = new Subject(); + private readonly baseSourceUrl = 'https://github.com/ReactiveX/rxjs/blob/master/src/operators/'; + private readonly baseSpecUrl = 'http://reactivex.io/rxjs/test-file/spec-js/operators'; + + constructor( + private _operatorComponent: OperatorComponent, + private _activateRoute: ActivatedRoute, + private _copierService: CopierService, + private _snackBar: MatSnackBar + ) {} + + ngOnInit() { + this._activateRoute.params.pipe(takeUntil(this._onDestroy)).subscribe(_ => { + this.operator = this._operatorComponent.operator; + }); + } + + copyToClipboard(code: string) { + this._copierService.copyText(code); + this._snackBar.open( + 'The example has been copied to your clipboard!', + null, + { duration: 3000 } + ); + } + + get sourceUrl() { + return `${this.baseSourceUrl}/${this.operator.name}.ts`; + } + + get specsUrl() { + return `${this.baseSpecUrl}/${this.operator.name}-spec.js.html`; + } + + ngOnDestroy() { + this._onDestroy.next(); + } +} diff --git a/src/app/operators/components/operator-header/operator-header.component.scss b/src/app/operators/components/operator-header/operator-header.component.scss index 23fec756..36245c4b 100644 --- a/src/app/operators/components/operator-header/operator-header.component.scss +++ b/src/app/operators/components/operator-header/operator-header.component.scss @@ -1,11 +1,7 @@ @import '../../operator-theme'; .operator-name { - font-size:30px; -} - -.signature { - margin-bottom: 24px; + font-size: 30px; } mat-toolbar { diff --git a/src/app/operators/components/operator-vendor-examples/operator-vendor-examples.component.html b/src/app/operators/components/operator-vendor-examples/operator-vendor-examples.component.html new file mode 100644 index 00000000..e5ab7a37 --- /dev/null +++ b/src/app/operators/components/operator-vendor-examples/operator-vendor-examples.component.html @@ -0,0 +1,13 @@ +
+
+

{{ example.name }}

+

{{ example.description }}

+
+
+ +
+
+
+
diff --git a/src/app/operators/components/operator-vendor-examples/operator-vendor-examples.component.scss b/src/app/operators/components/operator-vendor-examples/operator-vendor-examples.component.scss new file mode 100644 index 00000000..eaabd511 --- /dev/null +++ b/src/app/operators/components/operator-vendor-examples/operator-vendor-examples.component.scss @@ -0,0 +1,6 @@ +$stackblitz-blue: #0077cf; +$stackblitz-grey: #353535; + +.frame-wrapper { + background-color: $stackblitz-blue; +} diff --git a/src/app/operators/components/operator-vendor-examples/operator-vendor-examples.component.ts b/src/app/operators/components/operator-vendor-examples/operator-vendor-examples.component.ts new file mode 100644 index 00000000..9710bb91 --- /dev/null +++ b/src/app/operators/components/operator-vendor-examples/operator-vendor-examples.component.ts @@ -0,0 +1,35 @@ +import { Component, OnInit, OnDestroy, Input } from '@angular/core'; +import { ActivatedRoute } from '@angular/router'; +import { OperatorComponent } from '../operator/operator.component'; +import { Subject } from 'rxjs/Subject'; +import { takeUntil } from 'rxjs/operators/takeUntil'; +import { VendorExample } from '../../../../operator-docs'; + +@Component({ + selector: 'app-operator-vendor-examples', + templateUrl: './operator-vendor-examples.component.html', + styleUrls: ['./operator-vendor-examples.component.scss'] +}) +export class OperatorVendorExamplesComponent implements OnInit, OnDestroy { + public examples: VendorExample[] = []; + private _onDestroy = new Subject(); + + constructor( + private _operatorComponent: OperatorComponent, + private _activedRoute: ActivatedRoute + ) {} + + ngOnInit() { + this._activedRoute.params.pipe(takeUntil(this._onDestroy)).subscribe(p => { + this.examples = this._operatorComponent.operator.vendorExamples.filter( + e => { + return e.vendorName === p['vendor']; + } + ); + }); + } + + ngOnDestroy() { + this._onDestroy.next(); + } +} diff --git a/src/app/operators/components/operator/operator.component.html b/src/app/operators/components/operator/operator.component.html index 6bb46994..dc57973b 100644 --- a/src/app/operators/components/operator/operator.component.html +++ b/src/app/operators/components/operator/operator.component.html @@ -1,39 +1,25 @@ - -
-

-

- - - - - - - - - - - - - - - - -
+ + diff --git a/src/app/operators/components/operator/operator.component.scss b/src/app/operators/components/operator/operator.component.scss index 621798a0..8b137891 100644 --- a/src/app/operators/components/operator/operator.component.scss +++ b/src/app/operators/components/operator/operator.component.scss @@ -1,19 +1 @@ -.main-operator-container { - padding: 5px; - display: flex; - flex-direction: column; - padding: 0 16px; - margin-bottom: 32px; -} -.short-description { - margin: 16px 0 32px; -} - -.margin-bottom-32 { - margin-bottom: 32px; -} - -.margin-bottom-16 { - margin-bottom: 16px; -} diff --git a/src/app/operators/components/operator/operator.component.ts b/src/app/operators/components/operator/operator.component.ts index 9b3e9a6d..fced9f20 100644 --- a/src/app/operators/components/operator/operator.component.ts +++ b/src/app/operators/components/operator/operator.component.ts @@ -11,7 +11,7 @@ import { MatSnackBar } from '@angular/material'; import { pluck } from 'rxjs/operators'; import { CopierService } from '../../../core/services/copier.service'; import { SeoService } from '../../../core/services/seo.service'; -import { OperatorDoc } from '../../../../operator-docs/operator.model'; +import { OperatorDoc, VendorExample } from '../../../../operator-docs'; export const OPERATOR_TOKEN = new InjectionToken('operators'); @@ -23,9 +23,8 @@ export const OPERATOR_TOKEN = new InjectionToken('operators'); export class OperatorComponent implements OnInit { public operator: OperatorDoc; public operatorsMap = new Map(); - - private readonly baseSourceUrl = 'https://github.com/ReactiveX/rxjs/blob/master/src/operators/'; - private readonly baseSpecUrl = 'http://reactivex.io/rxjs/test-file/spec-js/operators'; + public vendorExamples: string[]; + public isVendor: boolean; constructor( private _router: Router, @@ -45,6 +44,8 @@ export class OperatorComponent implements OnInit { .subscribe((name: string) => { if (this.operatorsMap.has(name)) { this.operator = this.operatorsMap.get(name); + this.vendorExamples = this.compileVendorTabs(this.operator); + this.isVendor = this.isVendorRoute(this._router.url); this.scrollToTop(); } else { this.notfound(); @@ -67,74 +68,26 @@ export class OperatorComponent implements OnInit { } } - copyToClipboard(code: string) { - this._copierService.copyText(code); - this._snackBar.open( - 'The example has been copied to your clipboard!', - null, - { duration: 3000 } - ); - } - - get operatorName() { - return this.operator.name; - } - - get signature() { - return this.operator.signature || 'Signature Placeholder'; - } - - get marbleUrl() { - return this.operator.marbleUrl; - } - - get useInteractiveMarbles() { - return this.operator.useInteractiveMarbles; - } - - get shortDescription() { - return ( - this.operator.shortDescription && - this.operator.shortDescription.description - ); + compileVendorTabs(operator: OperatorDoc) { + return operator.vendorExamples + ? operator.vendorExamples.reduce((acc: string[], curr: VendorExample) => { + if (!acc.includes(curr.vendorName)) { + return [...acc, curr.vendorName]; + } + return acc; + }, []) + : []; } - get shortDescriptionExtras() { + isVendorRoute(url: string) { + // make this dynamic in future return ( - this.operator.shortDescription && this.operator.shortDescription.extras + this._router.url.includes('Angular') || this._router.url.includes('React') ); } - get walkthrough() { - return this.operator.walkthrough && this.operator.walkthrough.description; - } - - get walkthroughExtras() { - return this.operator.walkthrough && this.operator.walkthrough.extras; - } - - get parameters() { - return this.operator.parameters || []; - } - - get examples() { - return this.operator.examples || []; - } - - get relatedOperators() { - return this.operator.relatedOperators || []; - } - - get sourceUrl() { - return `${this.baseSourceUrl}/${this.operatorName}.ts`; - } - - get specsUrl() { - return `${this.baseSpecUrl}/${this.operatorName}-spec.js.html`; - } - - get additionalResources() { - return this.operator.additionalResources || []; + get signature() { + return this.operator.signature || 'Signature Placeholder'; } private notfound() { diff --git a/src/app/operators/operators-routing.module.ts b/src/app/operators/operators-routing.module.ts index 7f349125..30f24f19 100644 --- a/src/app/operators/operators-routing.module.ts +++ b/src/app/operators/operators-routing.module.ts @@ -3,7 +3,9 @@ import { Routes, RouterModule } from '@angular/router'; import { OperatorsComponent } from './operators.component'; import { OperatorComponent } from './components/operator/operator.component'; +import { OperatorGeneralComponent } from './components/operator-general/operator-general.component'; import { ALL_OPERATORS } from '../../operator-docs'; +import { OperatorVendorExamplesComponent } from './components/operator-vendor-examples/operator-vendor-examples.component'; const routes: Routes = [ { @@ -13,7 +15,17 @@ const routes: Routes = [ children: [ { path: ':operator', - component: OperatorComponent + component: OperatorComponent, + children: [ + { + path: '', + component: OperatorGeneralComponent + }, + { + path: ':vendor', + component: OperatorVendorExamplesComponent + } + ] }, { path: '', diff --git a/src/app/operators/operators.module.ts b/src/app/operators/operators.module.ts index c1ff69c0..6906e8c9 100644 --- a/src/app/operators/operators.module.ts +++ b/src/app/operators/operators.module.ts @@ -21,6 +21,8 @@ import { OperatorExtrasComponent } from './components/operator-extras/operator-e import { AdditionalResourcesComponent } from './components/additional-resources/additional-resources.component'; import { MarbleDiagramComponent } from './components/marble-diagram/marble-diagram.component'; import { WalkthroughComponent } from './components/walkthrough/walkthrough.component'; +import { OperatorGeneralComponent } from './components/operator-general/operator-general.component'; +import { OperatorVendorExamplesComponent } from './components/operator-vendor-examples/operator-vendor-examples.component'; import { HighlightJsDirective } from './directives/highlight-js.directive'; import { SafeUrlPipe } from './pipes/safe-url.pipe'; import { MaterialModule } from '../material/material.module'; @@ -32,6 +34,8 @@ import { MaterialModule } from '../material/material.module'; OperatorHeaderComponent, OperatorParametersComponent, OperatorExamplesComponent, + OperatorGeneralComponent, + OperatorVendorExamplesComponent, RelatedOperatorsComponent, OperatorExtrasComponent, AdditionalResourcesComponent, diff --git a/src/operator-docs/operator.model.ts b/src/operator-docs/operator.model.ts index 51b95b55..ac53aa15 100644 --- a/src/operator-docs/operator.model.ts +++ b/src/operator-docs/operator.model.ts @@ -1,4 +1,5 @@ -export type OperatorType = 'combination' +export type OperatorType = + | 'combination' | 'conditional' | 'creation' | 'error handling' @@ -14,7 +15,7 @@ export interface OperatorReference { } export interface ExternalLink { - platform: 'JSBin' | 'JSFiddle'; + platform: 'JSBin' | 'JSFiddle' | 'Stackblitz'; url: string; } @@ -27,10 +28,15 @@ export interface OperatorParameters { export interface OperatorExample { name: string; - code: string; + code?: string; externalLink: ExternalLink; } +export interface VendorExample extends OperatorExample { + vendorName: 'Angular' | 'React'; + description: string; +} + export interface OperatorExtra { type: 'Tip' | 'Warning'; text: string; @@ -45,13 +51,14 @@ export interface OperatorDoc { readonly parameters?: OperatorParameters[]; readonly shortDescription?: { description: string; - extras?: OperatorExtra[] + extras?: OperatorExtra[]; }; readonly walkthrough?: { description: string; - extras?: OperatorExtra[] + extras?: OperatorExtra[]; }; readonly examples?: OperatorExample[]; + readonly vendorExamples?: VendorExample[]; readonly additionalResources?: OperatorReference[]; readonly relatedOperators?: string[]; } diff --git a/src/styles.scss b/src/styles.scss index 5030d9c6..f2e57c35 100644 --- a/src/styles.scss +++ b/src/styles.scss @@ -1,6 +1,7 @@ @import '~@angular/material/theming'; @import './app/operators/operator-theme'; @import './styles/code-helpers'; +@import './styles/general'; @include mat-core(); // Define the theme. diff --git a/src/styles/_general.scss b/src/styles/_general.scss new file mode 100644 index 00000000..501c61ce --- /dev/null +++ b/src/styles/_general.scss @@ -0,0 +1,15 @@ +.margin-bottom-32 { + margin-bottom: 32px; +} + +.margin-top-32 { + margin-top: 32px; +} + +.margin-top-16 { + margin-bottom: 16px; +} + +.margin-bottom-16 { + margin-bottom: 16px; +} diff --git a/tsconfig.json b/tsconfig.json index a6c016bf..affc9fc8 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -8,12 +8,7 @@ "emitDecoratorMetadata": true, "experimentalDecorators": true, "target": "es5", - "typeRoots": [ - "node_modules/@types" - ], - "lib": [ - "es2017", - "dom" - ] + "typeRoots": ["node_modules/@types"], + "lib": ["es2017", "dom"] } } From bea6aff983406f4847454f53acc1184304fc5b5b Mon Sep 17 00:00:00 2001 From: btroncone Date: Tue, 19 Dec 2017 14:26:02 -0500 Subject: [PATCH 2/4] fix(operators): remove unused property from template --- .../operator-general/operator-general.component.html | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/app/operators/components/operator-general/operator-general.component.html b/src/app/operators/components/operator-general/operator-general.component.html index a1352d3a..69bfa823 100644 --- a/src/app/operators/components/operator-general/operator-general.component.html +++ b/src/app/operators/components/operator-general/operator-general.component.html @@ -16,13 +16,13 @@ class="margin-bottom-16"> + *ngIf="operator?.parameters?.length"> From 250cde00b1f6e55c89c4c1c678fe4c39008ff482 Mon Sep 17 00:00:00 2001 From: btroncone Date: Fri, 22 Dec 2017 15:01:05 -0500 Subject: [PATCH 3/4] fix(operators): fixed typo in operators template --- .../components/operator-general/operator-general.component.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/app/operators/components/operator-general/operator-general.component.html b/src/app/operators/components/operator-general/operator-general.component.html index 69bfa823..4ff2a914 100644 --- a/src/app/operators/components/operator-general/operator-general.component.html +++ b/src/app/operators/components/operator-general/operator-general.component.html @@ -22,7 +22,7 @@ [operatorWalkthrough]="operator?.walkthrough?.description"> From 6ce690f565c7ab6492b7be2114521a9c0ffc7403 Mon Sep 17 00:00:00 2001 From: btroncone Date: Fri, 26 Jan 2018 07:53:09 -0500 Subject: [PATCH 4/4] style(material): added missing comma to material module --- src/app/material/material.module.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/app/material/material.module.ts b/src/app/material/material.module.ts index d308709d..dfdfa991 100644 --- a/src/app/material/material.module.ts +++ b/src/app/material/material.module.ts @@ -29,7 +29,7 @@ import { MatInputModule, MatMenuModule, MatTooltipModule, - MatTabsModule + MatTabsModule, FlexLayoutModule, MatSnackBarModule ], @@ -44,7 +44,7 @@ import { MatInputModule, MatMenuModule, MatTooltipModule, - MatTabsModule + MatTabsModule, FlexLayoutModule, MatSnackBarModule ]