angular-cn/aio/content/examples/router/stackblitz.no-link.html

2008 lines
63 KiB
HTML
Raw Permalink Normal View History

<html lang="en"><head></head><body>
<form id="mainForm" method="post" action="https://run.stackblitz.com/api/angular/v1?file=src/app/app-routing.module.ts" target="_self"><input type="hidden" name="files[src/app/admin/admin-dashboard/admin-dashboard.component.ts]" value="import { Component, OnInit } from '@angular/core';
import { ActivatedRoute } from '@angular/router';
import { Observable } from 'rxjs';
import { map } from 'rxjs/operators';
import { SelectivePreloadingStrategyService } from '../../selective-preloading-strategy.service';
@Component({
selector: 'app-admin-dashboard',
templateUrl: './admin-dashboard.component.html',
styleUrls: ['./admin-dashboard.component.css']
})
export class AdminDashboardComponent implements OnInit {
sessionId: Observable<string>;
token: Observable<string>;
modules: string[];
constructor(
private route: ActivatedRoute,
preloadStrategy: SelectivePreloadingStrategyService
) {
this.modules = preloadStrategy.preloadedModules;
}
ngOnInit() {
// Capture the session ID if available
this.sessionId = this.route
.queryParamMap
.pipe(map(params => params.get('session_id') || 'None'));
// Capture the fragment if available
this.token = this.route
.fragment
.pipe(map(fragment => fragment || 'None'));
}
}
/*
Copyright Google LLC. All Rights Reserved.
Use of this source code is governed by an MIT-style license that
can be found in the LICENSE file at https://angular.io/license
*/"><input type="hidden" name="files[src/app/admin/admin-routing.module.ts]" value="import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';
import { AdminComponent } from './admin/admin.component';
import { AdminDashboardComponent } from './admin-dashboard/admin-dashboard.component';
import { ManageCrisesComponent } from './manage-crises/manage-crises.component';
import { ManageHeroesComponent } from './manage-heroes/manage-heroes.component';
import { AuthGuard } from '../auth/auth.guard';
const adminRoutes: Routes = [
{
path: '',
component: AdminComponent,
canActivate: [AuthGuard],
children: [
{
path: '',
canActivateChild: [AuthGuard],
children: [
{ path: 'crises', component: ManageCrisesComponent },
{ path: 'heroes', component: ManageHeroesComponent },
{ path: '', component: AdminDashboardComponent }
]
}
]
}
];
@NgModule({
imports: [
RouterModule.forChild(adminRoutes)
],
exports: [
RouterModule
]
})
export class AdminRoutingModule {}
/*
Copyright Google LLC. All Rights Reserved.
Use of this source code is governed by an MIT-style license that
can be found in the LICENSE file at https://angular.io/license
*/"><input type="hidden" name="files[src/app/admin/admin.module.ts]" value="import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { AdminComponent } from './admin/admin.component';
import { AdminDashboardComponent } from './admin-dashboard/admin-dashboard.component';
import { ManageCrisesComponent } from './manage-crises/manage-crises.component';
import { ManageHeroesComponent } from './manage-heroes/manage-heroes.component';
import { AdminRoutingModule } from './admin-routing.module';
@NgModule({
imports: [
CommonModule,
AdminRoutingModule
],
declarations: [
AdminComponent,
AdminDashboardComponent,
ManageCrisesComponent,
ManageHeroesComponent
]
})
export class AdminModule {}
/*
Copyright Google LLC. All Rights Reserved.
Use of this source code is governed by an MIT-style license that
can be found in the LICENSE file at https://angular.io/license
*/"><input type="hidden" name="files[src/app/admin/admin/admin.component.ts]" value="import { Component } from '@angular/core';
@Component({
selector: 'app-admin',
templateUrl: './admin.component.html',
styleUrls: ['./admin.component.css']
})
export class AdminComponent {
}
/*
Copyright Google LLC. All Rights Reserved.
Use of this source code is governed by an MIT-style license that
can be found in the LICENSE file at https://angular.io/license
*/"><input type="hidden" name="files[src/app/admin/manage-crises/manage-crises.component.ts]" value="import { Component } from '@angular/core';
@Component({
selector: 'app-manage-crises',
templateUrl: './manage-crises.component.html',
styleUrls: ['./manage-crises.component.css']
})
export class ManageCrisesComponent { }
/*
Copyright Google LLC. All Rights Reserved.
Use of this source code is governed by an MIT-style license that
can be found in the LICENSE file at https://angular.io/license
*/"><input type="hidden" name="files[src/app/admin/manage-heroes/manage-heroes.component.ts]" value="import { Component } from '@angular/core';
@Component({
selector: 'app-manage-hereos',
templateUrl: './manage-heroes.component.html',
styleUrls: ['./manage-heroes.component.css']
})
export class ManageHeroesComponent { }
/*
Copyright Google LLC. All Rights Reserved.
Use of this source code is governed by an MIT-style license that
can be found in the LICENSE file at https://angular.io/license
*/"><input type="hidden" name="files[src/app/animations.ts]" value="import {
trigger, animateChild, group,
transition, animate, style, query
} from '@angular/animations';
// Routable animations
export const slideInAnimation =
trigger('routeAnimation', [
transition('heroes <=> hero', [
style({ position: 'relative' }),
query(':enter, :leave', [
style({
position: 'absolute',
top: 0,
left: 0,
width: '100%'
})
]),
query(':enter', [
style({ left: '-100%'})
]),
query(':leave', animateChild()),
group([
query(':leave', [
animate('300ms ease-out', style({ left: '100%'}))
]),
query(':enter', [
animate('300ms ease-out', style({ left: '0%'}))
])
]),
query(':enter', animateChild()),
])
]);
/*
Copyright Google LLC. All Rights Reserved.
Use of this source code is governed by an MIT-style license that
can be found in the LICENSE file at https://angular.io/license
*/"><input type="hidden" name="files[src/app/app-routing.module.ts]" value="import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';
import { ComposeMessageComponent } from './compose-message/compose-message.component';
import { PageNotFoundComponent } from './page-not-found/page-not-found.component';
import { AuthGuard } from './auth/auth.guard';
import { SelectivePreloadingStrategyService } from './selective-preloading-strategy.service';
const appRoutes: Routes = [
{
path: 'compose',
component: ComposeMessageComponent,
outlet: 'popup'
},
{
path: 'admin',
loadChildren: () => import('./admin/admin.module').then(m => m.AdminModule),
canLoad: [AuthGuard]
},
{
path: 'crisis-center',
loadChildren: () => import('./crisis-center/crisis-center.module').then(m => m.CrisisCenterModule),
data: { preload: true }
},
{ path: '', redirectTo: '/superheroes', pathMatch: 'full' },
{ path: '**', component: PageNotFoundComponent }
];
@NgModule({
imports: [
RouterModule.forRoot(
appRoutes,
{
enableTracing: false, // <-- debugging purposes only
preloadingStrategy: SelectivePreloadingStrategyService,
}
)
],
exports: [
RouterModule
]
})
export class AppRoutingModule { }
/*
Copyright Google LLC. All Rights Reserved.
Use of this source code is governed by an MIT-style license that
can be found in the LICENSE file at https://angular.io/license
*/"><input type="hidden" name="files[src/app/app.component.ts]" value="import { Component } from '@angular/core';
import { RouterOutlet } from '@angular/router';
import { slideInAnimation } from './animations';
@Component({
selector: 'app-root',
templateUrl: 'app.component.html',
styleUrls: ['app.component.css'],
animations: [ slideInAnimation ]
})
export class AppComponent {
getAnimationData(outlet: RouterOutlet) {
return outlet &amp;&amp; outlet.activatedRouteData &amp;&amp; outlet.activatedRouteData.animation;
}
}
/*
Copyright Google LLC. All Rights Reserved.
Use of this source code is governed by an MIT-style license that
can be found in the LICENSE file at https://angular.io/license
*/"><input type="hidden" name="files[src/app/app.module.ts]" value="import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { FormsModule } from '@angular/forms';
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
import { Router } from '@angular/router';
import { AppComponent } from './app.component';
import { PageNotFoundComponent } from './page-not-found/page-not-found.component';
import { ComposeMessageComponent } from './compose-message/compose-message.component';
import { AppRoutingModule } from './app-routing.module';
import { HeroesModule } from './heroes/heroes.module';
import { AuthModule } from './auth/auth.module';
@NgModule({
imports: [
BrowserModule,
BrowserAnimationsModule,
FormsModule,
HeroesModule,
AuthModule,
AppRoutingModule,
],
declarations: [
AppComponent,
ComposeMessageComponent,
PageNotFoundComponent
],
bootstrap: [ AppComponent ]
})
export class AppModule {
// Diagnostic only: inspect router configuration
constructor(router: Router) {
// Use a custom replacer to display function names in the route configs
// const replacer = (key, value) => (typeof value === 'function') ? value.name : value;
// console.log('Routes: ', JSON.stringify(router.config, replacer, 2));
}
}
/*
Copyright Google LLC. All Rights Reserved.
Use of this source code is governed by an MIT-style license that
can be found in the LICENSE file at https://angular.io/license
*/"><input type="hidden" name="files[src/app/auth/auth-routing.module.ts]" value="import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';
import { AuthGuard } from './auth.guard';
import { AuthService } from './auth.service';
import { LoginComponent } from './login/login.component';
const authRoutes: Routes = [
{ path: 'login', component: LoginComponent }
];
@NgModule({
imports: [
RouterModule.forChild(authRoutes)
],
exports: [
RouterModule
]
})
export class AuthRoutingModule {}
/*
Copyright Google LLC. All Rights Reserved.
Use of this source code is governed by an MIT-style license that
can be found in the LICENSE file at https://angular.io/license
*/"><input type="hidden" name="files[src/app/auth/auth.guard.ts]" value="import { Injectable } from '@angular/core';
import {
CanActivate, Router,
ActivatedRouteSnapshot,
RouterStateSnapshot,
CanActivateChild,
NavigationExtras,
CanLoad, Route
} from '@angular/router';
import { AuthService } from './auth.service';
@Injectable({
providedIn: 'root',
})
export class AuthGuard implements CanActivate, CanActivateChild, CanLoad {
constructor(private authService: AuthService, private router: Router) {}
canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): boolean {
const url: string = state.url;
return this.checkLogin(url);
}
canActivateChild(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): boolean {
return this.canActivate(route, state);
}
canLoad(route: Route): boolean {
const url = `/${route.path}`;
return this.checkLogin(url);
}
checkLogin(url: string): boolean {
if (this.authService.isLoggedIn) { return true; }
// Store the attempted URL for redirecting
this.authService.redirectUrl = url;
// Create a dummy session id
const sessionId = 123456789;
// Set our navigation extras object
// that contains our global query params and fragment
const navigationExtras: NavigationExtras = {
queryParams: { session_id: sessionId },
fragment: 'anchor'
};
// Navigate to the login page with extras
this.router.navigate(['/login'], navigationExtras);
return false;
}
}
/*
Copyright Google LLC. All Rights Reserved.
Use of this source code is governed by an MIT-style license that
can be found in the LICENSE file at https://angular.io/license
*/"><input type="hidden" name="files[src/app/auth/auth.module.ts]" value="import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { FormsModule } from '@angular/forms';
import { LoginComponent } from './login/login.component';
import { AuthRoutingModule } from './auth-routing.module';
@NgModule({
imports: [
CommonModule,
FormsModule,
AuthRoutingModule
],
declarations: [
LoginComponent
]
})
export class AuthModule {}
/*
Copyright Google LLC. All Rights Reserved.
Use of this source code is governed by an MIT-style license that
can be found in the LICENSE file at https://angular.io/license
*/"><input type="hidden" name="files[src/app/auth/auth.service.ts]" value="import { Injectable } from '@angular/core';
import { Observable, of } from 'rxjs';
import { tap, delay } from 'rxjs/operators';
@Injectable({
providedIn: 'root',
})
export class AuthService {
isLoggedIn = false;
// store the URL so we can redirect after logging in
redirectUrl: string;
login(): Observable<boolean> {
return of(true).pipe(
delay(1000),
tap(val => this.isLoggedIn = true)
);
}
logout(): void {
this.isLoggedIn = false;
}
}
/*
Copyright Google LLC. All Rights Reserved.
Use of this source code is governed by an MIT-style license that
can be found in the LICENSE file at https://angular.io/license
*/"><input type="hidden" name="files[src/app/auth/login/login.component.ts]" value="import { Component } from '@angular/core';
import { NavigationExtras, Router } from '@angular/router';
import { AuthService } from '../auth.service';
@Component({
selector: 'app-login',
templateUrl: './login.component.html',
styleUrls: ['./login.component.css']
})
export class LoginComponent {
message: string;
constructor(public authService: AuthService, public router: Router) {
this.setMessage();
}
setMessage() {
this.message = 'Logged ' + (this.authService.isLoggedIn ? 'in' : 'out');
}
login() {
this.message = 'Trying to log in ...';
this.authService.login().subscribe(() => {
this.setMessage();
if (this.authService.isLoggedIn) {
// Usually you would use the redirect URL from the auth service.
// However to keep the example simple, we will always redirect to `/admin`.
const redirectUrl = '/admin';
// Set our navigation extras object
// that passes on our global query params and fragment
const navigationExtras: NavigationExtras = {
queryParamsHandling: 'preserve',
preserveFragment: true
};
// Redirect the user
this.router.navigate([redirectUrl], navigationExtras);
}
});
}
logout() {
this.authService.logout();
this.setMessage();
}
}
/*
Copyright Google LLC. All Rights Reserved.
Use of this source code is governed by an MIT-style license that
can be found in the LICENSE file at https://angular.io/license
*/"><input type="hidden" name="files[src/app/can-deactivate.guard.ts]" value="import { Injectable } from '@angular/core';
import { CanDeactivate } from '@angular/router';
import { Observable } from 'rxjs';
export interface CanComponentDeactivate {
canDeactivate: () => Observable<boolean> | Promise<boolean> | boolean;
}
@Injectable({
providedIn: 'root',
})
export class CanDeactivateGuard implements CanDeactivate<CanComponentDeactivate> {
canDeactivate(component: CanComponentDeactivate) {
return component.canDeactivate ? component.canDeactivate() : true;
}
}
/*
Copyright Google LLC. All Rights Reserved.
Use of this source code is governed by an MIT-style license that
can be found in the LICENSE file at https://angular.io/license
*/"><input type="hidden" name="files[src/app/compose-message/compose-message.component.ts]" value="import { Component, HostBinding } from '@angular/core';
import { Router } from '@angular/router';
@Component({
selector: 'app-compose-message',
templateUrl: './compose-message.component.html',
styleUrls: ['./compose-message.component.css']
})
export class ComposeMessageComponent {
details: string;
message: string;
sending = false;
constructor(private router: Router) {}
send() {
this.sending = true;
this.details = 'Sending Message...';
setTimeout(() => {
this.sending = false;
this.closePopup();
}, 1000);
}
cancel() {
this.closePopup();
}
closePopup() {
// Providing a `null` value to the named outlet
// clears the contents of the named outlet
this.router.navigate([{ outlets: { popup: null }}]);
}
}
/*
Copyright Google LLC. All Rights Reserved.
Use of this source code is governed by an MIT-style license that
can be found in the LICENSE file at https://angular.io/license
*/"><input type="hidden" name="files[src/app/crisis-center/crisis-center-home/crisis-center-home.component.ts]" value="import { Component } from '@angular/core';
@Component({
selector: 'app-crisis-center-home',
templateUrl: './crisis-center-home.component.html',
styleUrls: ['./crisis-center-home.component.css']
})
export class CrisisCenterHomeComponent { }
/*
Copyright Google LLC. All Rights Reserved.
Use of this source code is governed by an MIT-style license that
can be found in the LICENSE file at https://angular.io/license
*/"><input type="hidden" name="files[src/app/crisis-center/crisis-center-routing.module.ts]" value="import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';
import { CrisisCenterHomeComponent } from './crisis-center-home/crisis-center-home.component';
import { CrisisListComponent } from './crisis-list/crisis-list.component';
import { CrisisCenterComponent } from './crisis-center/crisis-center.component';
import { CrisisDetailComponent } from './crisis-detail/crisis-detail.component';
import { CanDeactivateGuard } from '../can-deactivate.guard';
import { CrisisDetailResolverService } from './crisis-detail-resolver.service';
const crisisCenterRoutes: Routes = [
{
path: '',
component: CrisisCenterComponent,
children: [
{
path: '',
component: CrisisListComponent,
children: [
{
path: ':id',
component: CrisisDetailComponent,
canDeactivate: [CanDeactivateGuard],
resolve: {
crisis: CrisisDetailResolverService
}
},
{
path: '',
component: CrisisCenterHomeComponent
}
]
}
]
}
];
@NgModule({
imports: [
RouterModule.forChild(crisisCenterRoutes)
],
exports: [
RouterModule
]
})
export class CrisisCenterRoutingModule { }
/*
Copyright Google LLC. All Rights Reserved.
Use of this source code is governed by an MIT-style license that
can be found in the LICENSE file at https://angular.io/license
*/"><input type="hidden" name="files[src/app/crisis-center/crisis-center.module.ts]" value="import { NgModule } from '@angular/core';
import { FormsModule } from '@angular/forms';
import { CommonModule } from '@angular/common';
import { CrisisCenterHomeComponent } from './crisis-center-home/crisis-center-home.component';
import { CrisisListComponent } from './crisis-list/crisis-list.component';
import { CrisisCenterComponent } from './crisis-center/crisis-center.component';
import { CrisisDetailComponent } from './crisis-detail/crisis-detail.component';
import { CrisisCenterRoutingModule } from './crisis-center-routing.module';
@NgModule({
imports: [
CommonModule,
FormsModule,
CrisisCenterRoutingModule
],
declarations: [
CrisisCenterComponent,
CrisisListComponent,
CrisisCenterHomeComponent,
CrisisDetailComponent
]
})
export class CrisisCenterModule {}
/*
Copyright Google LLC. All Rights Reserved.
Use of this source code is governed by an MIT-style license that
can be found in the LICENSE file at https://angular.io/license
*/"><input type="hidden" name="files[src/app/crisis-center/crisis-center/crisis-center.component.ts]" value="import { Component } from '@angular/core';
@Component({
selector: 'app-crisis-center',
templateUrl: './crisis-center.component.html',
styleUrls: ['./crisis-center.component.css']
})
export class CrisisCenterComponent { }
/*
Copyright Google LLC. All Rights Reserved.
Use of this source code is governed by an MIT-style license that
can be found in the LICENSE file at https://angular.io/license
*/"><input type="hidden" name="files[src/app/crisis-center/crisis-detail-resolver.service.ts]" value="
import { Injectable } from '@angular/core';
import {
Router, Resolve,
RouterStateSnapshot,
ActivatedRouteSnapshot
} from '@angular/router';
import { Observable, of, EMPTY } from 'rxjs';
import { mergeMap, take } from 'rxjs/operators';
import { CrisisService } from './crisis.service';
import { Crisis } from './crisis';
@Injectable({
providedIn: 'root',
})
export class CrisisDetailResolverService implements Resolve<Crisis> {
constructor(private cs: CrisisService, private router: Router) {}
resolve(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<Crisis> | Observable<never> {
const id = route.paramMap.get('id');
return this.cs.getCrisis(id).pipe(
take(1),
mergeMap(crisis => {
if (crisis) {
return of(crisis);
} else { // id not found
this.router.navigate(['/crisis-center']);
return EMPTY;
}
})
);
}
}
/*
Copyright Google LLC. All Rights Reserved.
Use of this source code is governed by an MIT-style license that
can be found in the LICENSE file at https://angular.io/license
*/"><input type="hidden" name="files[src/app/crisis-center/crisis-detail/crisis-detail.component.ts]" value="import { Component, OnInit, HostBinding } from '@angular/core';
import { ActivatedRoute, Router } from '@angular/router';
import { Observable } from 'rxjs';
import { Crisis } from '../crisis';
import { DialogService } from '../../dialog.service';
@Component({
selector: 'app-crisis-detail',
templateUrl: './crisis-detail.component.html',
styleUrls: ['./crisis-detail.component.css']
})
export class CrisisDetailComponent implements OnInit {
crisis: Crisis;
editName: string;
constructor(
private route: ActivatedRoute,
private router: Router,
public dialogService: DialogService
) {}
ngOnInit() {
this.route.data
.subscribe((data: { crisis: Crisis }) => {
this.editName = data.crisis.name;
this.crisis = data.crisis;
});
}
cancel() {
this.gotoCrises();
}
save() {
this.crisis.name = this.editName;
this.gotoCrises();
}
canDeactivate(): Observable<boolean> | boolean {
// Allow synchronous navigation (`true`) if no crisis or the crisis is unchanged
if (!this.crisis || this.crisis.name === this.editName) {
return true;
}
// Otherwise ask the user with the dialog service and return its
// observable which resolves to true or false when the user decides
return this.dialogService.confirm('Discard changes?');
}
gotoCrises() {
const crisisId = this.crisis ? this.crisis.id : null;
// Pass along the crisis id if available
// so that the CrisisListComponent can select that crisis.
// Add a totally useless `foo` parameter for kicks.
// Relative navigation back to the crises
this.router.navigate(['../', { id: crisisId, foo: 'foo' }], { relativeTo: this.route });
}
}
/*
Copyright Google LLC. All Rights Reserved.
Use of this source code is governed by an MIT-style license that
can be found in the LICENSE file at https://angular.io/license
*/"><input type="hidden" name="files[src/app/crisis-center/crisis-list/crisis-list.component.ts]" value="import { Component, OnInit } from '@angular/core';
import { ActivatedRoute } from '@angular/router';
import { CrisisService } from '../crisis.service';
import { Crisis } from '../crisis';
import { Observable } from 'rxjs';
import { switchMap } from 'rxjs/operators';
@Component({
selector: 'app-crisis-list',
templateUrl: './crisis-list.component.html',
styleUrls: ['./crisis-list.component.css']
})
export class CrisisListComponent implements OnInit {
crises$: Observable<Crisis[]>;
selectedId: number;
constructor(
private service: CrisisService,
private route: ActivatedRoute
) {}
ngOnInit() {
this.crises$ = this.route.paramMap.pipe(
switchMap(params => {
this.selectedId = +params.get('id');
return this.service.getCrises();
})
);
}
}
/*
Copyright Google LLC. All Rights Reserved.
Use of this source code is governed by an MIT-style license that
can be found in the LICENSE file at https://angular.io/license
*/"><input type="hidden" name="files[src/app/crisis-center/crisis.service.ts]" value="import { BehaviorSubject } from 'rxjs';
import { map } from 'rxjs/operators';
import { Injectable } from '@angular/core';
import { MessageService } from '../message.service';
import { Crisis } from './crisis';
import { CRISES } from './mock-crises';
@Injectable({
providedIn: 'root',
})
export class CrisisService {
static nextCrisisId = 100;
private crises$: BehaviorSubject<Crisis[]> = new BehaviorSubject<Crisis[]>(CRISES);
constructor(private messageService: MessageService) { }
getCrises() { return this.crises$; }
getCrisis(id: number | string) {
return this.getCrises().pipe(
map(crises => crises.find(crisis => crisis.id === +id))
);
}
addCrisis(name: string) {
name = name.trim();
if (name) {
const crisis = { id: CrisisService.nextCrisisId++, name };
CRISES.push(crisis);
this.crises$.next(CRISES);
}
}
}
/*
Copyright Google LLC. All Rights Reserved.
Use of this source code is governed by an MIT-style license that
can be found in the LICENSE file at https://angular.io/license
*/"><input type="hidden" name="files[src/app/crisis-center/crisis.ts]" value="export class Crisis {
id: number;
name: string;
}
/*
Copyright Google LLC. All Rights Reserved.
Use of this source code is governed by an MIT-style license that
can be found in the LICENSE file at https://angular.io/license
*/"><input type="hidden" name="files[src/app/crisis-center/mock-crises.ts]" value="import { Crisis } from './crisis';
export const CRISES: Crisis[] = [
{ id: 1, name: 'Dragon Burning Cities' },
{ id: 2, name: 'Sky Rains Great White Sharks' },
{ id: 3, name: 'Giant Asteroid Heading For Earth' },
{ id: 4, name: 'Procrastinators Meeting Delayed Again' },
];
/*
Copyright Google LLC. All Rights Reserved.
Use of this source code is governed by an MIT-style license that
can be found in the LICENSE file at https://angular.io/license
*/"><input type="hidden" name="files[src/app/dialog.service.ts]" value="import { Injectable } from '@angular/core';
import { Observable, of } from 'rxjs';
/**
* Async modal dialog service
* DialogService makes this app easier to test by faking this service.
* TODO: better modal implementation that doesn't use window.confirm
*/
@Injectable({
providedIn: 'root',
})
export class DialogService {
/**
* Ask user to confirm an action. `message` explains the action and choices.
* Returns observable resolving to `true`=confirm or `false`=cancel
*/
confirm(message?: string): Observable<boolean> {
const confirmation = window.confirm(message || 'Is it OK?');
return of(confirmation);
}
}
/*
Copyright Google LLC. All Rights Reserved.
Use of this source code is governed by an MIT-style license that
can be found in the LICENSE file at https://angular.io/license
*/"><input type="hidden" name="files[src/app/heroes/hero-detail/hero-detail.component.ts]" value="import { switchMap } from 'rxjs/operators';
import { Component, OnInit } from '@angular/core';
import { Router, ActivatedRoute, ParamMap } from '@angular/router';
import { Observable } from 'rxjs';
import { HeroService } from '../hero.service';
import { Hero } from '../hero';
@Component({
selector: 'app-hero-detail',
templateUrl: './hero-detail.component.html',
styleUrls: ['./hero-detail.component.css']
})
export class HeroDetailComponent implements OnInit {
hero$: Observable<Hero>;
constructor(
private route: ActivatedRoute,
private router: Router,
private service: HeroService
) {}
ngOnInit() {
this.hero$ = this.route.paramMap.pipe(
switchMap((params: ParamMap) =>
this.service.getHero(params.get('id')))
);
}
gotoHeroes(hero: Hero) {
const heroId = hero ? hero.id : null;
// Pass along the hero id if available
// so that the HeroList component can select that hero.
// Include a junk 'foo' property for fun.
this.router.navigate(['/superheroes', { id: heroId, foo: 'foo' }]);
}
}
/*
Copyright Google LLC. All Rights Reserved.
Use of this source code is governed by an MIT-style license that
can be found in the LICENSE file at https://angular.io/license
*/"><input type="hidden" name="files[src/app/heroes/hero-list/hero-list.component.ts]" value="// TODO: Feature Componetized like CrisisCenter
import { Observable } from 'rxjs';
import { switchMap } from 'rxjs/operators';
import { Component, OnInit } from '@angular/core';
import { ActivatedRoute } from '@angular/router';
import { HeroService } from '../hero.service';
import { Hero } from '../hero';
@Component({
selector: 'app-hero-list',
templateUrl: './hero-list.component.html',
styleUrls: ['./hero-list.component.css']
})
export class HeroListComponent implements OnInit {
heroes$: Observable<Hero[]>;
selectedId: number;
constructor(
private service: HeroService,
private route: ActivatedRoute
) {}
ngOnInit() {
this.heroes$ = this.route.paramMap.pipe(
switchMap(params => {
// (+) before `params.get()` turns the string into a number
this.selectedId = +params.get('id');
return this.service.getHeroes();
})
);
}
}
/*
Copyright Google LLC. All Rights Reserved.
Use of this source code is governed by an MIT-style license that
can be found in the LICENSE file at https://angular.io/license
*/"><input type="hidden" name="files[src/app/heroes/hero.service.ts]" value="import { Injectable } from '@angular/core';
import { Observable, of } from 'rxjs';
import { map } from 'rxjs/operators';
import { Hero } from './hero';
import { HEROES } from './mock-heroes';
import { MessageService } from '../message.service';
@Injectable({
providedIn: 'root',
})
export class HeroService {
constructor(private messageService: MessageService) { }
getHeroes(): Observable<Hero[]> {
// TODO: send the message _after_ fetching the heroes
this.messageService.add('HeroService: fetched heroes');
return of(HEROES);
}
getHero(id: number | string) {
return this.getHeroes().pipe(
// (+) before `id` turns the string into a number
map((heroes: Hero[]) => heroes.find(hero => hero.id === +id))
);
}
}
/*
Copyright Google LLC. All Rights Reserved.
Use of this source code is governed by an MIT-style license that
can be found in the LICENSE file at https://angular.io/license
*/"><input type="hidden" name="files[src/app/heroes/hero.ts]" value="export interface Hero {
id: number;
name: string;
}
/*
Copyright Google LLC. All Rights Reserved.
Use of this source code is governed by an MIT-style license that
can be found in the LICENSE file at https://angular.io/license
*/"><input type="hidden" name="files[src/app/heroes/heroes-routing.module.ts]" value="import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';
import { HeroListComponent } from './hero-list/hero-list.component';
import { HeroDetailComponent } from './hero-detail/hero-detail.component';
const heroesRoutes: Routes = [
{ path: 'heroes', redirectTo: '/superheroes' },
{ path: 'hero/:id', redirectTo: '/superhero/:id' },
{ path: 'superheroes', component: HeroListComponent, data: { animation: 'heroes' } },
{ path: 'superhero/:id', component: HeroDetailComponent, data: { animation: 'hero' } }
];
@NgModule({
imports: [
RouterModule.forChild(heroesRoutes)
],
exports: [
RouterModule
]
})
export class HeroesRoutingModule { }
/*
Copyright Google LLC. All Rights Reserved.
Use of this source code is governed by an MIT-style license that
can be found in the LICENSE file at https://angular.io/license
*/"><input type="hidden" name="files[src/app/heroes/heroes.module.ts]" value="import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { FormsModule } from '@angular/forms';
import { HeroListComponent } from './hero-list/hero-list.component';
import { HeroDetailComponent } from './hero-detail/hero-detail.component';
import { HeroesRoutingModule } from './heroes-routing.module';
@NgModule({
imports: [
CommonModule,
FormsModule,
HeroesRoutingModule
],
declarations: [
HeroListComponent,
HeroDetailComponent
]
})
export class HeroesModule {}
/*
Copyright Google LLC. All Rights Reserved.
Use of this source code is governed by an MIT-style license that
can be found in the LICENSE file at https://angular.io/license
*/"><input type="hidden" name="files[src/app/heroes/mock-heroes.ts]" value="import { Hero } from './hero';
export const HEROES: Hero[] = [
{ id: 11, name: 'Dr Nice' },
{ id: 12, name: 'Narco' },
{ id: 13, name: 'Bombasto' },
{ id: 14, name: 'Celeritas' },
{ id: 15, name: 'Magneta' },
{ id: 16, name: 'RubberMan' },
{ id: 17, name: 'Dynama' },
{ id: 18, name: 'Dr IQ' },
{ id: 19, name: 'Magma' },
{ id: 20, name: 'Tornado' }
];
/*
Copyright Google LLC. All Rights Reserved.
Use of this source code is governed by an MIT-style license that
can be found in the LICENSE file at https://angular.io/license
*/"><input type="hidden" name="files[src/app/message.service.ts]" value="import { Injectable } from '@angular/core';
@Injectable({
providedIn: 'root',
})
export class MessageService {
messages: string[] = [];
add(message: string) {
this.messages.push(message);
}
clear() {
this.messages = [];
}
}
/*
Copyright Google LLC. All Rights Reserved.
Use of this source code is governed by an MIT-style license that
can be found in the LICENSE file at https://angular.io/license
*/"><input type="hidden" name="files[src/app/page-not-found/page-not-found.component.ts]" value="import { Component, OnInit } from '@angular/core';
@Component({
selector: 'app-page-not-found',
templateUrl: './page-not-found.component.html',
styleUrls: ['./page-not-found.component.css']
})
export class PageNotFoundComponent implements OnInit {
constructor() { }
ngOnInit() {
}
}
/*
Copyright Google LLC. All Rights Reserved.
Use of this source code is governed by an MIT-style license that
can be found in the LICENSE file at https://angular.io/license
*/"><input type="hidden" name="files[src/app/selective-preloading-strategy.service.ts]" value="import { Injectable } from '@angular/core';
import { PreloadingStrategy, Route } from '@angular/router';
import { Observable, of } from 'rxjs';
@Injectable({
providedIn: 'root',
})
export class SelectivePreloadingStrategyService implements PreloadingStrategy {
preloadedModules: string[] = [];
preload(route: Route, load: () => Observable<any>): Observable<any> {
if (route.data &amp;&amp; route.data.preload) {
// add the route path to the preloaded module array
this.preloadedModules.push(route.path);
// log the route path to the console
console.log('Preloaded: ' + route.path);
return load();
} else {
return of(null);
}
}
}
/*
Copyright Google LLC. All Rights Reserved.
Use of this source code is governed by an MIT-style license that
can be found in the LICENSE file at https://angular.io/license
*/"><input type="hidden" name="files[src/environments/environment.prod.ts]" value="export const environment = {
production: true
};
/*
Copyright Google LLC. All Rights Reserved.
Use of this source code is governed by an MIT-style license that
can be found in the LICENSE file at https://angular.io/license
*/"><input type="hidden" name="files[src/environments/environment.ts]" value="// This file can be replaced during build by using the `fileReplacements` array.
// `ng build --prod` replaces `environment.ts` with `environment.prod.ts`.
// The list of file replacements can be found in `angular.json`.
export const environment = {
production: false
};
/*
* 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.
/*
Copyright Google LLC. All Rights Reserved.
Use of this source code is governed by an MIT-style license that
can be found in the LICENSE file at https://angular.io/license
*/"><input type="hidden" name="files[src/main.ts]" value="import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
import { AppModule } from './app/app.module';
platformBrowserDynamic().bootstrapModule(AppModule);
/*
Copyright Google LLC. All Rights Reserved.
Use of this source code is governed by an MIT-style license that
can be found in the LICENSE file at https://angular.io/license
*/"><input type="hidden" name="files[src/polyfills.ts]" value="/**
* This file includes polyfills needed by Angular and is loaded before the app.
* You can add your own extra polyfills to this file.
*
* This file is divided into 2 sections:
* 1. Browser polyfills. These are applied before loading ZoneJS and are sorted by browsers.
* 2. Application imports. Files imported after ZoneJS that should be loaded before your main
* file.
*
* The current setup is for so-called &quot;evergreen&quot; browsers; the last versions of browsers that
* automatically update themselves. This includes Safari >= 10, Chrome >= 55 (including Opera),
* Edge >= 13 on the desktop, and iOS 10 and Chrome on mobile.
*
* Learn more in https://angular.io/guide/browser-support
*/
/***************************************************************************************************
* BROWSER POLYFILLS
*/
/** IE11 requires the following for NgClass support on SVG elements */
// import 'classlist.js'; // Run `npm install --save classlist.js`.
/**
* Web Animations `@angular/platform-browser/animations`
* Only required if AnimationBuilder is used within the application and using IE/Edge or Safari.
* Standard animation support in Angular DOES NOT require any polyfills (as of Angular 6.0).
*/
// import 'web-animations-js'; // Run `npm install --save web-animations-js`.
/**
* By default, zone.js will patch all possible macroTask and DomEvents
* user can disable parts of macroTask/DomEvents patch by setting following flags
* because those flags need to be set before `zone.js` being loaded, and webpack
* will put import in the top of bundle, so user need to create a separate file
* in this directory (for example: zone-flags.ts), and put the following flags
* into that file, and then add the following code before importing zone.js.
* import './zone-flags';
*
* The flags allowed in zone-flags.ts are listed here.
*
* The following flags will work for all browsers.
*
* (window as any).__Zone_disable_requestAnimationFrame = true; // disable patch
* requestAnimationFrame
* (window as any).__Zone_disable_on_property = true; // disable patch onProperty such as onclick
* (window as any).__zone_symbol__UNPATCHED_EVENTS = ['scroll', 'mousemove']; // disable patch
* specified eventNames
*
* in IE/Edge developer tools, the addEventListener will also be wrapped by zone.js
* with the following flag, it will bypass `zone.js` patch for IE/Edge
*
* (window as any).__Zone_enable_cross_context_check = true;
*
*/
/***************************************************************************************************
* Zone JS is required by default for Angular itself.
*/
import 'zone.js'; // Included with Angular CLI.
/***************************************************************************************************
* APPLICATION IMPORTS
*/
/*
Copyright Google LLC. All Rights Reserved.
Use of this source code is governed by an MIT-style license that
can be found in the LICENSE file at https://angular.io/license
*/"><input type="hidden" name="files[src/app/admin/admin-dashboard/admin-dashboard.component.css]" value="
/*
Copyright Google LLC. All Rights Reserved.
Use of this source code is governed by an MIT-style license that
can be found in the LICENSE file at https://angular.io/license
*/"><input type="hidden" name="files[src/app/admin/admin/admin.component.css]" value="
/*
Copyright Google LLC. All Rights Reserved.
Use of this source code is governed by an MIT-style license that
can be found in the LICENSE file at https://angular.io/license
*/"><input type="hidden" name="files[src/app/admin/manage-crises/manage-crises.component.css]" value="
/*
Copyright Google LLC. All Rights Reserved.
Use of this source code is governed by an MIT-style license that
can be found in the LICENSE file at https://angular.io/license
*/"><input type="hidden" name="files[src/app/admin/manage-heroes/manage-heroes.component.css]" value="
/*
Copyright Google LLC. All Rights Reserved.
Use of this source code is governed by an MIT-style license that
can be found in the LICENSE file at https://angular.io/license
*/"><input type="hidden" name="files[src/app/app.component.css]" value="
/*
Copyright Google LLC. All Rights Reserved.
Use of this source code is governed by an MIT-style license that
can be found in the LICENSE file at https://angular.io/license
*/"><input type="hidden" name="files[src/app/auth/login/login.component.css]" value="
/*
Copyright Google LLC. All Rights Reserved.
Use of this source code is governed by an MIT-style license that
can be found in the LICENSE file at https://angular.io/license
*/"><input type="hidden" name="files[src/app/compose-message/compose-message.component.css]" value=":host {
position: relative; bottom: 10%;
}
/*
Copyright Google LLC. All Rights Reserved.
Use of this source code is governed by an MIT-style license that
can be found in the LICENSE file at https://angular.io/license
*/"><input type="hidden" name="files[src/app/crisis-center/crisis-center-home/crisis-center-home.component.css]" value="
/*
Copyright Google LLC. All Rights Reserved.
Use of this source code is governed by an MIT-style license that
can be found in the LICENSE file at https://angular.io/license
*/"><input type="hidden" name="files[src/app/crisis-center/crisis-center/crisis-center.component.css]" value="
/*
Copyright Google LLC. All Rights Reserved.
Use of this source code is governed by an MIT-style license that
can be found in the LICENSE file at https://angular.io/license
*/"><input type="hidden" name="files[src/app/crisis-center/crisis-detail/crisis-detail.component.css]" value="input {
width: 20em
}
/*
Copyright Google LLC. All Rights Reserved.
Use of this source code is governed by an MIT-style license that
can be found in the LICENSE file at https://angular.io/license
*/"><input type="hidden" name="files[src/app/crisis-center/crisis-list/crisis-list.component.css]" value="/* CrisisListComponent's private CSS styles */
.crises {
margin: 0 0 2em 0;
list-style-type: none;
padding: 0;
width: 24em;
}
.crises li {
position: relative;
cursor: pointer;
background-color: #EEE;
margin: .5em;
padding: .3em 0;
height: 1.6em;
border-radius: 4px;
}
.crises li:hover {
color: #607D8B;
background-color: #DDD;
left: .1em;
}
.crises a {
color: #888;
text-decoration: none;
display: block;
}
.crises a:hover {
color:#607D8B;
}
.crises .badge {
display: inline-block;
font-size: small;
color: white;
padding: 0.8em 0.7em 0 0.7em;
background-color: #607D8B;
line-height: 1em;
position: relative;
left: -1px;
top: -4px;
height: 1.8em;
min-width: 16px;
text-align: right;
margin-right: .8em;
border-radius: 4px 0 0 4px;
}
button {
background-color: #eee;
border: none;
padding: 5px 10px;
border-radius: 4px;
cursor: pointer;
font-family: Arial, sans-serif;
}
button:hover {
background-color: #cfd8dc;
}
button.delete {
position: relative;
left: 194px;
top: -32px;
background-color: gray !important;
color: white;
}
.crises li.selected {
background-color: #CFD8DC;
color: white;
}
.crises li.selected:hover {
background-color: #BBD8DC;
}
/*
Copyright Google LLC. All Rights Reserved.
Use of this source code is governed by an MIT-style license that
can be found in the LICENSE file at https://angular.io/license
*/"><input type="hidden" name="files[src/app/heroes/hero-detail/hero-detail.component.css]" value="
/*
Copyright Google LLC. All Rights Reserved.
Use of this source code is governed by an MIT-style license that
can be found in the LICENSE file at https://angular.io/license
*/"><input type="hidden" name="files[src/app/heroes/hero-list/hero-list.component.css]" value="/* HeroListComponent's private CSS styles */
.heroes {
margin: 0 0 2em 0;
list-style-type: none;
padding: 0;
width: 15em;
}
.heroes li {
position: relative;
cursor: pointer;
background-color: #EEE;
margin: .5em;
padding: .3em 0;
height: 1.6em;
border-radius: 4px;
}
.heroes li:hover {
color: #607D8B;
background-color: #DDD;
left: .1em;
}
.heroes a {
color: #888;
text-decoration: none;
position: relative;
display: block;
}
.heroes a:hover {
color:#607D8B;
}
.heroes .badge {
display: inline-block;
font-size: small;
color: white;
padding: 0.8em 0.7em 0 0.7em;
background-color: #607D8B;
line-height: 1em;
position: relative;
left: -1px;
top: -4px;
height: 1.8em;
min-width: 16px;
text-align: right;
margin-right: .8em;
border-radius: 4px 0 0 4px;
}
button {
background-color: #eee;
border: none;
padding: 5px 10px;
border-radius: 4px;
cursor: pointer;
font-family: Arial, sans-serif;
}
button:hover {
background-color: #cfd8dc;
}
button.delete {
position: relative;
left: 194px;
top: -32px;
background-color: gray !important;
color: white;
}
.heroes li.selected {
background-color: #CFD8DC;
color: white;
}
.heroes li.selected:hover {
background-color: #BBD8DC;
}
/*
Copyright Google LLC. All Rights Reserved.
Use of this source code is governed by an MIT-style license that
can be found in the LICENSE file at https://angular.io/license
*/"><input type="hidden" name="files[src/app/page-not-found/page-not-found.component.css]" value="
/*
Copyright Google LLC. All Rights Reserved.
Use of this source code is governed by an MIT-style license that
can be found in the LICENSE file at https://angular.io/license
*/"><input type="hidden" name="files[src/styles.css]" value="/* Global Styles */
* {
font-family: Arial, Helvetica, sans-serif;
}
h1 {
color: #264D73;
font-size: 2.5rem;
}
h2, h3 {
color: #444;
font-weight: lighter;
}
h3 {
font-size: 1.3rem;
}
body {
padding: .5rem;
max-width: 1000px;
margin: auto;
}
@media (min-width: 600px) {
body {
padding: 2rem;
}
}
body, input[text] {
color: #333;
font-family: Cambria, Georgia, serif;
}
a {
cursor: pointer;
}
button {
background-color: #eee;
border: none;
border-radius: 4px;
cursor: pointer;
color: black;
font-size: 1.2rem;
padding: 1rem;
margin-right: 1rem;
margin-bottom: 1rem;
}
button:hover {
background-color: black;
color: white;
}
button:disabled {
background-color: #eee;
color: #aaa;
cursor: auto;
}
/* Navigation link styles */
nav a {
padding: 5px 10px;
text-decoration: none;
margin-right: 10px;
margin-top: 10px;
display: inline-block;
background-color: #e8e8e8;
color: #3d3d3d;
border-radius: 4px;
}
nav a:hover {
color: white;
background-color: #42545C;
}
nav a.active {
background-color: black;
color: white;
}
hr {
margin: 1.5rem 0;
}
input[type=&quot;text&quot;] {
box-sizing: border-box;
width: 100%;
padding: .5rem;
}
/*
Copyright Google LLC. All Rights Reserved.
Use of this source code is governed by an MIT-style license that
can be found in the LICENSE file at https://angular.io/license
*/"><input type="hidden" name="files[src/app/admin/admin-dashboard/admin-dashboard.component.html]" value="<p>Dashboard</p>
<p>Session ID: {{ sessionId | async }}</p>
<a id=&quot;anchor&quot;></a>
<p>Token: {{ token | async }}</p>
Preloaded Modules
<ul>
<li *ngFor=&quot;let module of modules&quot;>{{ module }}</li>
</ul>
<!--
Copyright Google LLC. All Rights Reserved.
Use of this source code is governed by an MIT-style license that
can be found in the LICENSE file at https://angular.io/license
-->"><input type="hidden" name="files[src/app/admin/admin/admin.component.html]" value="<h3>ADMIN</h3>
<nav>
<a routerLink=&quot;./&quot; routerLinkActive=&quot;active&quot;
[routerLinkActiveOptions]=&quot;{ exact: true }&quot;>Dashboard</a>
<a routerLink=&quot;./crises&quot; routerLinkActive=&quot;active&quot;>Manage Crises</a>
<a routerLink=&quot;./heroes&quot; routerLinkActive=&quot;active&quot;>Manage Heroes</a>
</nav>
<router-outlet></router-outlet>
<!--
Copyright Google LLC. All Rights Reserved.
Use of this source code is governed by an MIT-style license that
can be found in the LICENSE file at https://angular.io/license
-->"><input type="hidden" name="files[src/app/admin/manage-crises/manage-crises.component.html]" value="<p>Manage your crises here</p>
<!--
Copyright Google LLC. All Rights Reserved.
Use of this source code is governed by an MIT-style license that
can be found in the LICENSE file at https://angular.io/license
-->"><input type="hidden" name="files[src/app/admin/manage-heroes/manage-heroes.component.html]" value="<p>Manage your heroes here</p>
<!--
Copyright Google LLC. All Rights Reserved.
Use of this source code is governed by an MIT-style license that
can be found in the LICENSE file at https://angular.io/license
-->"><input type="hidden" name="files[src/app/app.component.html]" value="<h1 class=&quot;title&quot;>Angular Router</h1>
<nav>
<a routerLink=&quot;/crisis-center&quot; routerLinkActive=&quot;active&quot;>Crisis Center</a>
<a routerLink=&quot;/superheroes&quot; routerLinkActive=&quot;active&quot;>Heroes</a>
<a routerLink=&quot;/admin&quot; routerLinkActive=&quot;active&quot;>Admin</a>
<a routerLink=&quot;/login&quot; routerLinkActive=&quot;active&quot;>Login</a>
<a [routerLink]=&quot;[{ outlets: { popup: ['compose'] } }]&quot;>Contact</a>
</nav>
<div [@routeAnimation]=&quot;getAnimationData(routerOutlet)&quot;>
<router-outlet #routerOutlet=&quot;outlet&quot;></router-outlet>
</div>
<router-outlet name=&quot;popup&quot;></router-outlet>
<!--
Copyright Google LLC. All Rights Reserved.
Use of this source code is governed by an MIT-style license that
can be found in the LICENSE file at https://angular.io/license
-->"><input type="hidden" name="files[src/app/auth/login/login.component.html]" value="<h2>LOGIN</h2>
<p>{{message}}</p>
<p>
<button (click)=&quot;login()&quot; *ngIf=&quot;!authService.isLoggedIn&quot;>Login</button>
<button (click)=&quot;logout()&quot; *ngIf=&quot;authService.isLoggedIn&quot;>Logout</button>
</p>
<!--
Copyright Google LLC. All Rights Reserved.
Use of this source code is governed by an MIT-style license that
can be found in the LICENSE file at https://angular.io/license
-->"><input type="hidden" name="files[src/app/compose-message/compose-message.component.html]" value="<h3>Contact Crisis Center</h3>
<div *ngIf=&quot;details&quot;>
{{ details }}
</div>
<div>
<div>
<label>Message: </label>
</div>
<div>
<textarea [(ngModel)]=&quot;message&quot; rows=&quot;10&quot; cols=&quot;35&quot; [disabled]=&quot;sending&quot;></textarea>
</div>
</div>
<p *ngIf=&quot;!sending&quot;>
<button (click)=&quot;send()&quot;>Send</button>
<button (click)=&quot;cancel()&quot;>Cancel</button>
</p>
<!--
Copyright Google LLC. All Rights Reserved.
Use of this source code is governed by an MIT-style license that
can be found in the LICENSE file at https://angular.io/license
-->"><input type="hidden" name="files[src/app/crisis-center/crisis-center-home/crisis-center-home.component.html]" value="<p>Welcome to the Crisis Center</p>
<!--
Copyright Google LLC. All Rights Reserved.
Use of this source code is governed by an MIT-style license that
can be found in the LICENSE file at https://angular.io/license
-->"><input type="hidden" name="files[src/app/crisis-center/crisis-center/crisis-center.component.html]" value="<h2>CRISIS CENTER</h2>
<router-outlet></router-outlet>
<!--
Copyright Google LLC. All Rights Reserved.
Use of this source code is governed by an MIT-style license that
can be found in the LICENSE file at https://angular.io/license
-->"><input type="hidden" name="files[src/app/crisis-center/crisis-detail/crisis-detail.component.html]" value="<div *ngIf=&quot;crisis&quot;>
<h3>&quot;{{ editName }}&quot;</h3>
<div>
<label>Id: </label>{{ crisis.id }}</div>
<div>
<label>Name: </label>
<input [(ngModel)]=&quot;editName&quot; placeholder=&quot;name&quot;/>
</div>
<p>
<button (click)=&quot;save()&quot;>Save</button>
<button (click)=&quot;cancel()&quot;>Cancel</button>
</p>
</div>
<!--
Copyright Google LLC. All Rights Reserved.
Use of this source code is governed by an MIT-style license that
can be found in the LICENSE file at https://angular.io/license
-->"><input type="hidden" name="files[src/app/crisis-center/crisis-list/crisis-list.component.html]" value="<ul class=&quot;crises&quot;>
<li *ngFor=&quot;let crisis of crises$ | async&quot;
[class.selected]=&quot;crisis.id === selectedId&quot;>
<a [routerLink]=&quot;[crisis.id]&quot;>
<span class=&quot;badge&quot;>{{ crisis.id }}</span>{{ crisis.name }}
</a>
</li>
</ul>
<router-outlet></router-outlet>
<!--
Copyright Google LLC. All Rights Reserved.
Use of this source code is governed by an MIT-style license that
can be found in the LICENSE file at https://angular.io/license
-->"><input type="hidden" name="files[src/app/heroes/hero-detail/hero-detail.component.html]" value="<h2>HEROES</h2>
<div *ngIf=&quot;hero$ | async as hero&quot;>
<h3>&quot;{{ hero.name }}&quot;</h3>
<div>
<label>Id: </label>{{ hero.id }}</div>
<div>
<label>Name: </label>
<input [(ngModel)]=&quot;hero.name&quot; placeholder=&quot;name&quot;/>
</div>
<p>
<button (click)=&quot;gotoHeroes(hero)&quot;>Back</button>
</p>
</div>
<!--
Copyright Google LLC. All Rights Reserved.
Use of this source code is governed by an MIT-style license that
can be found in the LICENSE file at https://angular.io/license
-->"><input type="hidden" name="files[src/app/heroes/hero-list/hero-list.component.html]" value="<h2>HEROES</h2>
<ul class=&quot;heroes&quot;>
<li *ngFor=&quot;let hero of heroes$ | async&quot;
[class.selected]=&quot;hero.id === selectedId&quot;>
<a [routerLink]=&quot;['/hero', hero.id]&quot;>
<span class=&quot;badge&quot;>{{ hero.id }}</span>{{ hero.name }}
</a>
</li>
</ul>
<button routerLink=&quot;/sidekicks&quot;>Go to sidekicks</button>
<!--
Copyright Google LLC. All Rights Reserved.
Use of this source code is governed by an MIT-style license that
can be found in the LICENSE file at https://angular.io/license
-->"><input type="hidden" name="files[src/app/page-not-found/page-not-found.component.html]" value="<h2>Page not found</h2>
<!--
Copyright Google LLC. All Rights Reserved.
Use of this source code is governed by an MIT-style license that
can be found in the LICENSE file at https://angular.io/license
-->"><input type="hidden" name="files[src/index.html]" value="<!DOCTYPE html>
<html lang=&quot;en&quot;>
<head>
<!-- Set the base href -->
<base href=&quot;/&quot;>
<title>Angular Router</title>
<meta charset=&quot;UTF-8&quot;>
<meta name=&quot;viewport&quot; content=&quot;width=device-width, initial-scale=1&quot;>
</head>
<body>
<app-root></app-root>
</body>
</html>
<!--
Copyright Google LLC. All Rights Reserved.
Use of this source code is governed by an MIT-style license that
can be found in the LICENSE file at https://angular.io/license
-->"><input type="hidden" name="files[angular.json]" value="{
&quot;$schema&quot;: &quot;./node_modules/@angular/cli/lib/config/schema.json&quot;,
&quot;version&quot;: 1,
&quot;newProjectRoot&quot;: &quot;projects&quot;,
&quot;projects&quot;: {
&quot;angular.io-example&quot;: {
&quot;projectType&quot;: &quot;application&quot;,
&quot;schematics&quot;: {
&quot;@schematics/angular:application&quot;: {
&quot;strict&quot;: true
}
},
&quot;root&quot;: &quot;&quot;,
&quot;sourceRoot&quot;: &quot;src&quot;,
&quot;prefix&quot;: &quot;app&quot;,
&quot;architect&quot;: {
&quot;build&quot;: {
&quot;builder&quot;: &quot;@angular-devkit/build-angular:browser&quot;,
&quot;options&quot;: {
&quot;outputPath&quot;: &quot;dist&quot;,
&quot;index&quot;: &quot;src/index.html&quot;,
&quot;main&quot;: &quot;src/main.ts&quot;,
&quot;polyfills&quot;: &quot;src/polyfills.ts&quot;,
&quot;tsConfig&quot;: &quot;tsconfig.app.json&quot;,
&quot;aot&quot;: true,
&quot;assets&quot;: [
&quot;src/favicon.ico&quot;,
&quot;src/assets&quot;
],
&quot;styles&quot;: [
&quot;src/styles.css&quot;
],
&quot;scripts&quot;: []
},
&quot;configurations&quot;: {
&quot;production&quot;: {
&quot;fileReplacements&quot;: [
{
&quot;replace&quot;: &quot;src/environments/environment.ts&quot;,
&quot;with&quot;: &quot;src/environments/environment.prod.ts&quot;
}
],
&quot;optimization&quot;: true,
&quot;outputHashing&quot;: &quot;all&quot;,
&quot;sourceMap&quot;: false,
&quot;namedChunks&quot;: false,
&quot;extractLicenses&quot;: true,
&quot;vendorChunk&quot;: false,
&quot;buildOptimizer&quot;: true,
&quot;budgets&quot;: [
{
&quot;type&quot;: &quot;initial&quot;,
&quot;maximumWarning&quot;: &quot;500kb&quot;,
&quot;maximumError&quot;: &quot;1mb&quot;
},
{
&quot;type&quot;: &quot;anyComponentStyle&quot;,
&quot;maximumWarning&quot;: &quot;2kb&quot;,
&quot;maximumError&quot;: &quot;4kb&quot;
}
]
}
}
},
&quot;serve&quot;: {
&quot;builder&quot;: &quot;@angular-devkit/build-angular:dev-server&quot;,
&quot;options&quot;: {
&quot;browserTarget&quot;: &quot;angular.io-example:build&quot;
},
&quot;configurations&quot;: {
&quot;production&quot;: {
&quot;browserTarget&quot;: &quot;angular.io-example:build:production&quot;
}
}
},
&quot;extract-i18n&quot;: {
&quot;builder&quot;: &quot;@angular-devkit/build-angular:extract-i18n&quot;,
&quot;options&quot;: {
&quot;browserTarget&quot;: &quot;angular.io-example:build&quot;
}
},
&quot;test&quot;: {
&quot;builder&quot;: &quot;@angular-devkit/build-angular:karma&quot;,
&quot;options&quot;: {
&quot;main&quot;: &quot;src/test.ts&quot;,
&quot;polyfills&quot;: &quot;src/polyfills.ts&quot;,
&quot;tsConfig&quot;: &quot;tsconfig.spec.json&quot;,
&quot;karmaConfig&quot;: &quot;karma.conf.js&quot;,
&quot;assets&quot;: [
&quot;src/favicon.ico&quot;,
&quot;src/assets&quot;
],
&quot;styles&quot;: [
&quot;src/styles.css&quot;
],
&quot;scripts&quot;: []
}
},
&quot;lint&quot;: {
&quot;builder&quot;: &quot;@angular-devkit/build-angular:tslint&quot;,
&quot;options&quot;: {
&quot;tsConfig&quot;: [
&quot;tsconfig.app.json&quot;,
&quot;tsconfig.spec.json&quot;,
&quot;e2e/tsconfig.json&quot;
],
&quot;exclude&quot;: [
&quot;**/node_modules/**&quot;
]
}
},
&quot;e2e&quot;: {
&quot;builder&quot;: &quot;@angular-devkit/build-angular:protractor&quot;,
&quot;options&quot;: {
&quot;protractorConfig&quot;: &quot;e2e/protractor.conf.js&quot;,
&quot;devServerTarget&quot;: &quot;angular.io-example:serve&quot;
},
&quot;configurations&quot;: {
&quot;production&quot;: {
&quot;devServerTarget&quot;: &quot;angular.io-example:serve:production&quot;
}
}
}
}
}
},
&quot;defaultProject&quot;: &quot;angular.io-example&quot;
}
"><input type="hidden" name="files[tsconfig.json]" value="{
&quot;compileOnSave&quot;: false,
&quot;compilerOptions&quot;: {
&quot;baseUrl&quot;: &quot;./&quot;,
&quot;outDir&quot;: &quot;./dist/out-tsc&quot;,
&quot;forceConsistentCasingInFileNames&quot;: true,
&quot;noImplicitReturns&quot;: true,
&quot;noFallthroughCasesInSwitch&quot;: true,
&quot;sourceMap&quot;: true,
&quot;declaration&quot;: false,
&quot;downlevelIteration&quot;: true,
&quot;experimentalDecorators&quot;: true,
&quot;moduleResolution&quot;: &quot;node&quot;,
&quot;importHelpers&quot;: true,
&quot;target&quot;: &quot;es2015&quot;,
&quot;module&quot;: &quot;es2020&quot;,
&quot;lib&quot;: [
&quot;es2018&quot;,
&quot;dom&quot;
]
},
&quot;angularCompilerOptions&quot;: {
&quot;strictInjectionParameters&quot;: true,
&quot;strictInputAccessModifiers&quot;: true,
&quot;strictTemplates&quot;: true,
&quot;enableIvy&quot;: true
}
}"><input type="hidden" name="tags[0]" value="angular"><input type="hidden" name="tags[1]" value="example"><input type="hidden" name="tags[2]" value="router"><input type="hidden" name="description" value="Angular Example - Router"><input type="hidden" name="dependencies" value="{&quot;@angular/animations&quot;:&quot;~11.0.1&quot;,&quot;@angular/common&quot;:&quot;~11.0.1&quot;,&quot;@angular/compiler&quot;:&quot;~11.0.1&quot;,&quot;@angular/core&quot;:&quot;~11.0.1&quot;,&quot;@angular/forms&quot;:&quot;~11.0.1&quot;,&quot;@angular/platform-browser&quot;:&quot;~11.0.1&quot;,&quot;@angular/platform-browser-dynamic&quot;:&quot;~11.0.1&quot;,&quot;@angular/router&quot;:&quot;~11.0.1&quot;,&quot;angular-in-memory-web-api&quot;:&quot;~0.11.0&quot;,&quot;rxjs&quot;:&quot;~6.6.0&quot;,&quot;tslib&quot;:&quot;^2.0.0&quot;,&quot;zone.js&quot;:&quot;~0.11.4&quot;,&quot;jasmine-core&quot;:&quot;~3.6.0&quot;,&quot;jasmine-marbles&quot;:&quot;~0.6.0&quot;}"></form>
<script>
var embedded = 'ctl=1';
var isEmbedded = window.location.search.indexOf(embedded) > -1;
if (isEmbedded) {
var form = document.getElementById('mainForm');
var action = form.action;
var actionHasParams = action.indexOf('?') > -1;
var symbol = actionHasParams ? '&' : '?'
form.action = form.action + symbol + embedded;
}
document.getElementById("mainForm").submit();
</script>
</body></html>