Skip to content

Commit

Permalink
2022-05-31-part-2-angular-shell-application
Browse files Browse the repository at this point in the history
  • Loading branch information
Bwca committed May 31, 2022
1 parent 5f23628 commit daf1b26
Show file tree
Hide file tree
Showing 17 changed files with 219 additions and 74 deletions.
12 changes: 9 additions & 3 deletions apps/angular-shell-e2e/project.json
Expand Up @@ -17,12 +17,18 @@
},
"lint": {
"executor": "@nrwl/linter:eslint",
"outputs": ["{options.outputFile}"],
"outputs": [
"{options.outputFile}"
],
"options": {
"lintFilePatterns": ["apps/angular-shell-e2e/**/*.{js,ts}"]
"lintFilePatterns": [
"apps/angular-shell-e2e/**/*.{js,ts}"
]
}
}
},
"tags": [],
"implicitDependencies": ["angular-shell"]
"implicitDependencies": [
"angular-shell"
]
}
12 changes: 9 additions & 3 deletions apps/angular-shell/project.json
Expand Up @@ -5,7 +5,9 @@
"targets": {
"build": {
"executor": "@angular-devkit/build-angular:browser",
"outputs": ["{options.outputPath}"],
"outputs": [
"{options.outputPath}"
],
"options": {
"outputPath": "dist/apps/angular-shell",
"index": "apps/angular-shell/src/index.html",
Expand All @@ -17,7 +19,9 @@
"apps/angular-shell/src/favicon.ico",
"apps/angular-shell/src/assets"
],
"styles": ["apps/angular-shell/src/styles.scss"],
"styles": [
"apps/angular-shell/src/styles.scss"
],
"scripts": []
},
"configurations": {
Expand Down Expand Up @@ -82,7 +86,9 @@
},
"test": {
"executor": "@nrwl/jest:jest",
"outputs": ["coverage/apps/angular-shell"],
"outputs": [
"coverage/apps/angular-shell"
],
"options": {
"jestConfig": "apps/angular-shell/jest.config.ts",
"passWithNoTests": true
Expand Down
1 change: 0 additions & 1 deletion apps/angular-shell/src/app/app.component.html

This file was deleted.

Empty file.
34 changes: 0 additions & 34 deletions apps/angular-shell/src/app/app.component.spec.ts

This file was deleted.

7 changes: 2 additions & 5 deletions apps/angular-shell/src/app/app.component.ts
Expand Up @@ -2,9 +2,6 @@ import { Component } from '@angular/core';

@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.scss'],
template: `<router-outlet></router-outlet>`,
})
export class AppComponent {
title = 'angular-shell';
}
export class AppComponent {}
17 changes: 15 additions & 2 deletions apps/angular-shell/src/app/app.module.ts
@@ -1,15 +1,28 @@
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { RouterModule } from '@angular/router';

import { AppComponent } from './app.component';
import { NxWelcomeComponent } from './nx-welcome.component';
import { RouterModule } from '@angular/router';

@NgModule({
declarations: [AppComponent, NxWelcomeComponent],
imports: [
BrowserModule,
RouterModule.forRoot([], { initialNavigation: 'enabledBlocking' }),
RouterModule.forRoot(
[
{
path: 'frame',
loadChildren: () =>
import('./frame/frame.module').then((m) => m.FrameModule),
},
{
path: '**',
redirectTo: 'frame',
},
],
{ initialNavigation: 'enabledBlocking' }
),
],
providers: [],
bootstrap: [AppComponent],
Expand Down
24 changes: 24 additions & 0 deletions apps/angular-shell/src/app/frame/frame.component.spec.ts
@@ -0,0 +1,24 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';

import { FrameComponent } from './frame.component';

describe('FrameComponent', () => {
let component: FrameComponent;
let fixture: ComponentFixture<FrameComponent>;

beforeEach(async () => {
await TestBed.configureTestingModule({
declarations: [FrameComponent],
}).compileComponents();
});

beforeEach(() => {
fixture = TestBed.createComponent(FrameComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});

it('should create', () => {
expect(component).toBeTruthy();
});
});
43 changes: 43 additions & 0 deletions apps/angular-shell/src/app/frame/frame.component.ts
@@ -0,0 +1,43 @@
import {
AfterViewInit,
Component,
ElementRef,
HostListener,
ViewChild,
} from '@angular/core';
import { DomSanitizer } from '@angular/platform-browser';

import { environment } from '../../environments/environment';
import { MessageService } from './services/message.service';

@Component({
template: `<iframe
#childWindow
[src]="iframeUrl"
width="400px"
height="400px"
></iframe>`,
providers: [MessageService],
})
export class FrameComponent implements AfterViewInit {
@ViewChild('childWindow')
public readonly iframe!: ElementRef<HTMLIFrameElement>;

public readonly iframeUrl = this.sanitizer.bypassSecurityTrustResourceUrl(
environment.iframeUrl
);

constructor(
private messageService: MessageService,
private sanitizer: DomSanitizer
) {}

public ngAfterViewInit(): void {
this.messageService.target = this.iframe;
}

@HostListener('window:message', ['$event'])
private message(event: MessageEvent) {
this.messageService.requestActivity(event);
}
}
16 changes: 16 additions & 0 deletions apps/angular-shell/src/app/frame/frame.module.ts
@@ -0,0 +1,16 @@
import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { Routes, RouterModule } from '@angular/router';
import { HttpClientModule } from '@angular/common/http';

import { FrameComponent } from './frame.component';
import { ActivityService } from './services/activity.service';

const routes: Routes = [{ path: '', component: FrameComponent }];

@NgModule({
declarations: [FrameComponent],
imports: [CommonModule, RouterModule.forChild(routes), HttpClientModule],
providers: [ActivityService]
})
export class FrameModule {}
22 changes: 22 additions & 0 deletions apps/angular-shell/src/app/frame/services/activity.service.ts
@@ -0,0 +1,22 @@
import { HttpClient, HttpParams } from '@angular/common/http';
import { Injectable } from '@angular/core';
import { Observable } from 'rxjs';

import { ActivityItem } from '@demo--nx-iframe-microfrontends/models';

@Injectable()
export class ActivityService {
constructor(private http: HttpClient) {
this.getActivity().subscribe(console.log)
}

public getActivity(): Observable<ActivityItem> {
const params = new HttpParams().set('participants', 1);
return this.http.get<ActivityItem>(
'http://www.boredapi.com/api/activity',
{
params,
}
);
}
}
38 changes: 38 additions & 0 deletions apps/angular-shell/src/app/frame/services/message.service.ts
@@ -0,0 +1,38 @@
import { Injectable, ElementRef, OnDestroy } from '@angular/core';
import { debounceTime, Subject, Subscription, switchMap } from 'rxjs';

import { ActivityService } from './activity.service';

@Injectable()
export class MessageService implements OnDestroy {
private incomingMessage$$ = new Subject<MessageEvent>();
private targetWindow: ElementRef<HTMLIFrameElement> | null = null;
private subscription: Subscription | null = null;

constructor(private activityService: ActivityService) {
this.subscribeToMessages();
}

public ngOnDestroy(): void {
this.subscription?.unsubscribe();
}

public set target(targetWindow: ElementRef<HTMLIFrameElement>) {
this.targetWindow = targetWindow;
}

public requestActivity(event: MessageEvent): void {
this.incomingMessage$$.next(event);
}

private subscribeToMessages(): void {
this.subscription = this.incomingMessage$$
.pipe(
debounceTime(100),
switchMap(() => this.activityService.getActivity())
)
.subscribe((v) => {
this.targetWindow?.nativeElement.contentWindow?.postMessage(v, '*');
});
}
}
1 change: 1 addition & 0 deletions apps/angular-shell/src/environments/environment.prod.ts
@@ -1,3 +1,4 @@
export const environment = {
production: true,
iframeUrl: 'http://localhost:4200',
};
14 changes: 1 addition & 13 deletions apps/angular-shell/src/environments/environment.ts
@@ -1,16 +1,4 @@
// This file can be replaced during build by using the `fileReplacements` array.
// `ng build` replaces `environment.ts` with `environment.prod.ts`.
// The list of file replacements can be found in `angular.json`.

export const environment = {
production: false,
iframeUrl: 'http://localhost:4200',
};

/*
* For easier debugging in development mode, you can import the following file
* to ignore zone related error stack frames such as `zone.run`, `zoneDelegate.invokeTask`.
*
* This import should be commented out in production mode because it will have a negative impact
* on performance if an error is thrown.
*/
// import 'zone.js/plugins/zone-error'; // Included with Angular CLI.
12 changes: 9 additions & 3 deletions apps/react-app-e2e/project.json
Expand Up @@ -17,12 +17,18 @@
},
"lint": {
"executor": "@nrwl/linter:eslint",
"outputs": ["{options.outputFile}"],
"outputs": [
"{options.outputFile}"
],
"options": {
"lintFilePatterns": ["apps/react-app-e2e/**/*.{js,ts}"]
"lintFilePatterns": [
"apps/react-app-e2e/**/*.{js,ts}"
]
}
}
},
"tags": [],
"implicitDependencies": ["react-app"]
"implicitDependencies": [
"react-app"
]
}
20 changes: 15 additions & 5 deletions apps/react-app/project.json
Expand Up @@ -5,7 +5,9 @@
"targets": {
"build": {
"executor": "@nrwl/web:webpack",
"outputs": ["{options.outputPath}"],
"outputs": [
"{options.outputPath}"
],
"defaultConfiguration": "production",
"options": {
"compiler": "babel",
Expand All @@ -19,7 +21,9 @@
"apps/react-app/src/favicon.ico",
"apps/react-app/src/assets"
],
"styles": ["apps/react-app/src/styles.scss"],
"styles": [
"apps/react-app/src/styles.scss"
],
"scripts": [],
"webpackConfig": "@nrwl/react/plugins/webpack"
},
Expand Down Expand Up @@ -65,14 +69,20 @@
},
"lint": {
"executor": "@nrwl/linter:eslint",
"outputs": ["{options.outputFile}"],
"outputs": [
"{options.outputFile}"
],
"options": {
"lintFilePatterns": ["apps/react-app/**/*.{ts,tsx,js,jsx}"]
"lintFilePatterns": [
"apps/react-app/**/*.{ts,tsx,js,jsx}"
]
}
},
"test": {
"executor": "@nrwl/jest:jest",
"outputs": ["coverage/apps/react-app"],
"outputs": [
"coverage/apps/react-app"
],
"options": {
"jestConfig": "apps/react-app/jest.config.ts",
"passWithNoTests": true
Expand Down

0 comments on commit daf1b26

Please sign in to comment.