diff options
Diffstat (limited to 'overlays/spm/frontend/src')
21 files changed, 361 insertions, 0 deletions
diff --git a/overlays/spm/frontend/src/app/app-routing.module.ts b/overlays/spm/frontend/src/app/app-routing.module.ts new file mode 100644 index 00000000..2da97cea --- /dev/null +++ b/overlays/spm/frontend/src/app/app-routing.module.ts | |||
| @@ -0,0 +1,17 @@ | |||
| 1 | import { NgModule } from '@angular/core'; | ||
| 2 | import { RouterModule, Routes } from '@angular/router'; | ||
| 3 | |||
| 4 | import { SpmComponent } from './spm/spm.component'; | ||
| 5 | import { PageNotFoundComponent } from './page-not-found/page-not-found.component'; | ||
| 6 | |||
| 7 | const routes: Routes = [ | ||
| 8 | { path: 'spm', component: SpmComponent }, | ||
| 9 | { path: '', redirectTo: '/spm', pathMatch: 'full' }, | ||
| 10 | { path: '**', component: PageNotFoundComponent } | ||
| 11 | ]; | ||
| 12 | |||
| 13 | @NgModule({ | ||
| 14 | imports: [RouterModule.forRoot(routes)], | ||
| 15 | exports: [RouterModule] | ||
| 16 | }) | ||
| 17 | export class AppRoutingModule { } | ||
diff --git a/overlays/spm/frontend/src/app/app.component.html b/overlays/spm/frontend/src/app/app.component.html new file mode 100644 index 00000000..f9b5b8fc --- /dev/null +++ b/overlays/spm/frontend/src/app/app.component.html | |||
| @@ -0,0 +1,7 @@ | |||
| 1 | <mat-toolbar color="primary"> | ||
| 2 | <div> | ||
| 3 | <a mat-button routerLink="/spm" routerLinkActive="active">spm</a> | ||
| 4 | </div> | ||
| 5 | </mat-toolbar> | ||
| 6 | <!-- The routed views render in the <router-outlet> --> | ||
| 7 | <router-outlet></router-outlet> | ||
diff --git a/overlays/spm/frontend/src/app/app.component.sass b/overlays/spm/frontend/src/app/app.component.sass new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/overlays/spm/frontend/src/app/app.component.sass | |||
diff --git a/overlays/spm/frontend/src/app/app.component.ts b/overlays/spm/frontend/src/app/app.component.ts new file mode 100644 index 00000000..7c231203 --- /dev/null +++ b/overlays/spm/frontend/src/app/app.component.ts | |||
| @@ -0,0 +1,21 @@ | |||
| 1 | import { Component, OnInit, OnDestroy } from '@angular/core'; | ||
| 2 | |||
| 3 | import { ColorSchemeService } from './color-scheme.service'; | ||
| 4 | |||
| 5 | @Component({ | ||
| 6 | selector: 'app-root', | ||
| 7 | templateUrl: './app.component.html', | ||
| 8 | styleUrls: ['./app.component.sass'] | ||
| 9 | }) | ||
| 10 | export class AppComponent implements OnInit, OnDestroy { | ||
| 11 | title = 'spm-frontend'; | ||
| 12 | |||
| 13 | constructor(private colorSchemeService: ColorSchemeService) {} | ||
| 14 | |||
| 15 | ngOnInit() { | ||
| 16 | this.colorSchemeService.init(); | ||
| 17 | } | ||
| 18 | ngOnDestroy() { | ||
| 19 | this.colorSchemeService.destroy(); | ||
| 20 | } | ||
| 21 | } | ||
diff --git a/overlays/spm/frontend/src/app/app.module.ts b/overlays/spm/frontend/src/app/app.module.ts new file mode 100644 index 00000000..914f73a2 --- /dev/null +++ b/overlays/spm/frontend/src/app/app.module.ts | |||
| @@ -0,0 +1,32 @@ | |||
| 1 | import { NgModule } from '@angular/core'; | ||
| 2 | import { BrowserModule } from '@angular/platform-browser'; | ||
| 3 | |||
| 4 | import { AppRoutingModule } from './app-routing.module'; | ||
| 5 | import { AppComponent } from './app.component'; | ||
| 6 | import { SpmComponent } from './spm/spm.component'; | ||
| 7 | import { PageNotFoundComponent } from './page-not-found/page-not-found.component'; | ||
| 8 | import { BrowserAnimationsModule } from '@angular/platform-browser/animations'; | ||
| 9 | import { MatIconModule } from '@angular/material/icon'; | ||
| 10 | import { HttpClientModule } from "@angular/common/http"; | ||
| 11 | import { MatToolbarModule } from '@angular/material/toolbar'; | ||
| 12 | import { MatButtonModule } from '@angular/material/button'; | ||
| 13 | |||
| 14 | @NgModule({ | ||
| 15 | declarations: [ | ||
| 16 | AppComponent, | ||
| 17 | SpmComponent, | ||
| 18 | PageNotFoundComponent | ||
| 19 | ], | ||
| 20 | imports: [ | ||
| 21 | BrowserModule, | ||
| 22 | AppRoutingModule, | ||
| 23 | BrowserAnimationsModule, | ||
| 24 | MatIconModule, | ||
| 25 | HttpClientModule, | ||
| 26 | MatToolbarModule, | ||
| 27 | MatButtonModule | ||
| 28 | ], | ||
| 29 | providers: [], | ||
| 30 | bootstrap: [AppComponent] | ||
| 31 | }) | ||
| 32 | export class AppModule { } | ||
diff --git a/overlays/spm/frontend/src/app/color-scheme.service.ts b/overlays/spm/frontend/src/app/color-scheme.service.ts new file mode 100644 index 00000000..c56e9c23 --- /dev/null +++ b/overlays/spm/frontend/src/app/color-scheme.service.ts | |||
| @@ -0,0 +1,62 @@ | |||
| 1 | import { Injectable, Renderer2, RendererFactory2 } from '@angular/core'; | ||
| 2 | import { MediaMatcher } from '@angular/cdk/layout'; | ||
| 3 | import { LocalStorage } from 'ngx-webstorage'; | ||
| 4 | |||
| 5 | type ColorScheme = "dark" | "light"; | ||
| 6 | |||
| 7 | @Injectable({ | ||
| 8 | providedIn: 'root' | ||
| 9 | }) | ||
| 10 | export class ColorSchemeService { | ||
| 11 | private renderer: Renderer2; | ||
| 12 | matcher!: MediaQueryList; | ||
| 13 | |||
| 14 | @LocalStorage('prefers-color-scheme') | ||
| 15 | public colorSchemeOverride: ColorScheme; | ||
| 16 | |||
| 17 | public activeColorScheme: BehaviorSubject<ColorScheme> = new BehaviorSubject("light"); | ||
| 18 | |||
| 19 | constructor(rendererFactory: RendererFactory2, | ||
| 20 | mediaMatcher: MediaMatcher | ||
| 21 | ) { | ||
| 22 | // Create new renderer from renderFactory, to make it possible to use renderer2 in a service | ||
| 23 | this.renderer = rendererFactory.createRenderer(null, null); | ||
| 24 | this.matcher = mediaMatcher.matchMedia('(prefers-color-scheme: dark)'); | ||
| 25 | |||
| 26 | this._listener = this._listener.bind(this); | ||
| 27 | } | ||
| 28 | |||
| 29 | init() { | ||
| 30 | this.matcher.addEventListener('change', this._listener); | ||
| 31 | this.load(); | ||
| 32 | } | ||
| 33 | |||
| 34 | _listener(event: { matches: any; }) { | ||
| 35 | this.activeColorScheme.next(event.matches ? 'dark' : 'light'); | ||
| 36 | } | ||
| 37 | |||
| 38 | destroy() { | ||
| 39 | this.matcher.removeEventListener('change', this._listener); | ||
| 40 | } | ||
| 41 | |||
| 42 | _getColorScheme() { | ||
| 43 | if (this.colorSchemeOverride) { | ||
| 44 | this.colorSchemeOverride | ||
| 45 | } else { | ||
| 46 | this.matcher.matches ? 'dark' : 'light' | ||
| 47 | } | ||
| 48 | } | ||
| 49 | |||
| 50 | load() { | ||
| 51 | this.activeColorScheme.next(this._getColorScheme()); | ||
| 52 | } | ||
| 53 | |||
| 54 | update(scheme: ColorScheme) { | ||
| 55 | this.colorSchemeOverride = scheme; | ||
| 56 | this.activeColorScheme.next(scheme); | ||
| 57 | } | ||
| 58 | |||
| 59 | currentActive() { | ||
| 60 | return this.colorScheme; | ||
| 61 | } | ||
| 62 | } | ||
diff --git a/overlays/spm/frontend/src/app/page-not-found/page-not-found.component.html b/overlays/spm/frontend/src/app/page-not-found/page-not-found.component.html new file mode 100644 index 00000000..26a283ed --- /dev/null +++ b/overlays/spm/frontend/src/app/page-not-found/page-not-found.component.html | |||
| @@ -0,0 +1,5 @@ | |||
| 1 | <div style="margin: 1rem;"> | ||
| 2 | <h1> | ||
| 3 | No Such Component | ||
| 4 | </h1> | ||
| 5 | </div> | ||
diff --git a/overlays/spm/frontend/src/app/page-not-found/page-not-found.component.sass b/overlays/spm/frontend/src/app/page-not-found/page-not-found.component.sass new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/overlays/spm/frontend/src/app/page-not-found/page-not-found.component.sass | |||
diff --git a/overlays/spm/frontend/src/app/page-not-found/page-not-found.component.ts b/overlays/spm/frontend/src/app/page-not-found/page-not-found.component.ts new file mode 100644 index 00000000..2d1091ce --- /dev/null +++ b/overlays/spm/frontend/src/app/page-not-found/page-not-found.component.ts | |||
| @@ -0,0 +1,15 @@ | |||
| 1 | import { Component, OnInit } from '@angular/core'; | ||
| 2 | |||
| 3 | @Component({ | ||
| 4 | selector: 'app-page-not-found', | ||
| 5 | templateUrl: './page-not-found.component.html', | ||
| 6 | styleUrls: ['./page-not-found.component.sass'] | ||
| 7 | }) | ||
| 8 | export class PageNotFoundComponent implements OnInit { | ||
| 9 | |||
| 10 | constructor() { } | ||
| 11 | |||
| 12 | ngOnInit(): void { | ||
| 13 | } | ||
| 14 | |||
| 15 | } | ||
diff --git a/overlays/spm/frontend/src/app/spm/spm.component.html b/overlays/spm/frontend/src/app/spm/spm.component.html new file mode 100644 index 00000000..d1339d95 --- /dev/null +++ b/overlays/spm/frontend/src/app/spm/spm.component.html | |||
| @@ -0,0 +1,3 @@ | |||
| 1 | <p>spm works!</p> | ||
| 2 | |||
| 3 | <mat-icon aria-hidden="false" aria-label="Thumbs up" svgIcon="thumb_up"></mat-icon> | ||
diff --git a/overlays/spm/frontend/src/app/spm/spm.component.sass b/overlays/spm/frontend/src/app/spm/spm.component.sass new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/overlays/spm/frontend/src/app/spm/spm.component.sass | |||
diff --git a/overlays/spm/frontend/src/app/spm/spm.component.ts b/overlays/spm/frontend/src/app/spm/spm.component.ts new file mode 100644 index 00000000..7d172052 --- /dev/null +++ b/overlays/spm/frontend/src/app/spm/spm.component.ts | |||
| @@ -0,0 +1,24 @@ | |||
| 1 | import { Component, OnInit } from '@angular/core'; | ||
| 2 | import { MatIconRegistry, MatIconModule } from '@angular/material/icon'; | ||
| 3 | import { DomSanitizer } from "@angular/platform-browser"; | ||
| 4 | |||
| 5 | @Component({ | ||
| 6 | selector: 'app-spm', | ||
| 7 | templateUrl: './spm.component.html', | ||
| 8 | styleUrls: ['./spm.component.sass'] | ||
| 9 | }) | ||
| 10 | export class SpmComponent implements OnInit { | ||
| 11 | |||
| 12 | constructor(private matIconRegistry: MatIconRegistry, | ||
| 13 | private domSanitizer: DomSanitizer | ||
| 14 | ) { | ||
| 15 | this.matIconRegistry.addSvgIcon( | ||
| 16 | `thumb_up`, | ||
| 17 | this.domSanitizer.bypassSecurityTrustResourceUrl(`icons/thumb_up/baseline.svg`) | ||
| 18 | ); | ||
| 19 | } | ||
| 20 | |||
| 21 | ngOnInit(): void { | ||
| 22 | } | ||
| 23 | |||
| 24 | } | ||
diff --git a/overlays/spm/frontend/src/assets/.gitkeep b/overlays/spm/frontend/src/assets/.gitkeep new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/overlays/spm/frontend/src/assets/.gitkeep | |||
diff --git a/overlays/spm/frontend/src/custom-theme.scss b/overlays/spm/frontend/src/custom-theme.scss new file mode 100644 index 00000000..5c2d48aa --- /dev/null +++ b/overlays/spm/frontend/src/custom-theme.scss | |||
| @@ -0,0 +1,51 @@ | |||
| 1 | |||
| 2 | // Custom Theming for Angular Material | ||
| 3 | // For more information: https://material.angular.io/guide/theming | ||
| 4 | @use '@angular/material' as mat; | ||
| 5 | // Plus imports for other components in your app. | ||
| 6 | |||
| 7 | // Include the common styles for Angular Material. We include this here so that you only | ||
| 8 | // have to load a single css file for Angular Material in your app. | ||
| 9 | // Be sure that you only ever include this mixin once! | ||
| 10 | @include mat.core(); | ||
| 11 | |||
| 12 | // Define the palettes for your theme using the Material Design palettes available in palette.scss | ||
| 13 | // (imported above). For each palette, you can optionally specify a default, lighter, and darker | ||
| 14 | // hue. Available color palettes: https://material.io/design/color/ | ||
| 15 | $spm-frontend-primary: mat.define-palette(mat.$indigo-palette); | ||
| 16 | $spm-frontend-accent: mat.define-palette(mat.$pink-palette, A200, A100, A400); | ||
| 17 | |||
| 18 | // The warn palette is optional (defaults to red). | ||
| 19 | $spm-frontend-warn: mat.define-palette(mat.$red-palette); | ||
| 20 | |||
| 21 | // Create the theme object. A theme consists of configurations for individual | ||
| 22 | // theming systems such as "color" or "typography". | ||
| 23 | $spm-frontend-light-theme: mat.define-light-theme(( | ||
| 24 | color: ( | ||
| 25 | primary: $spm-frontend-primary, | ||
| 26 | accent: $spm-frontend-accent, | ||
| 27 | warn: $spm-frontend-warn, | ||
| 28 | ) | ||
| 29 | )); | ||
| 30 | |||
| 31 | $spm-frontend-dark-theme: mat.define-dark-theme(( | ||
| 32 | color: ( | ||
| 33 | primary: $spm-frontend-primary, | ||
| 34 | accent: $spm-frontend-accent, | ||
| 35 | warn: $spm-frontend-warn, | ||
| 36 | ) | ||
| 37 | )); | ||
| 38 | |||
| 39 | |||
| 40 | // Include theme styles for core and each component used in your app. | ||
| 41 | // Alternatively, you can import and @include the theme mixins for each component | ||
| 42 | // that you are using. | ||
| 43 | @include mat.all-component-themes($spm-frontend-dark-theme); | ||
| 44 | |||
| 45 | [data-color-scheme="light"] { | ||
| 46 | @include mat.all-component-colors($spm-frontend-light-theme); | ||
| 47 | } | ||
| 48 | |||
| 49 | |||
| 50 | html, body { height: 100%; } | ||
| 51 | body { margin: 0; font-family: Roboto, "Helvetica Neue", sans-serif; } | ||
diff --git a/overlays/spm/frontend/src/environments/environment.prod.ts b/overlays/spm/frontend/src/environments/environment.prod.ts new file mode 100644 index 00000000..3612073b --- /dev/null +++ b/overlays/spm/frontend/src/environments/environment.prod.ts | |||
| @@ -0,0 +1,3 @@ | |||
| 1 | export const environment = { | ||
| 2 | production: true | ||
| 3 | }; | ||
diff --git a/overlays/spm/frontend/src/environments/environment.ts b/overlays/spm/frontend/src/environments/environment.ts new file mode 100644 index 00000000..f56ff470 --- /dev/null +++ b/overlays/spm/frontend/src/environments/environment.ts | |||
| @@ -0,0 +1,16 @@ | |||
| 1 | // This file can be replaced during build by using the `fileReplacements` array. | ||
| 2 | // `ng build` replaces `environment.ts` with `environment.prod.ts`. | ||
| 3 | // The list of file replacements can be found in `angular.json`. | ||
| 4 | |||
| 5 | export const environment = { | ||
| 6 | production: false | ||
| 7 | }; | ||
| 8 | |||
| 9 | /* | ||
| 10 | * For easier debugging in development mode, you can import the following file | ||
| 11 | * to ignore zone related error stack frames such as `zone.run`, `zoneDelegate.invokeTask`. | ||
| 12 | * | ||
| 13 | * This import should be commented out in production mode because it will have a negative impact | ||
| 14 | * on performance if an error is thrown. | ||
| 15 | */ | ||
| 16 | // import 'zone.js/plugins/zone-error'; // Included with Angular CLI. | ||
diff --git a/overlays/spm/frontend/src/index.html b/overlays/spm/frontend/src/index.html new file mode 100644 index 00000000..8bd1bc7f --- /dev/null +++ b/overlays/spm/frontend/src/index.html | |||
| @@ -0,0 +1,12 @@ | |||
| 1 | <!doctype html> | ||
| 2 | <html lang="en"> | ||
| 3 | <head> | ||
| 4 | <meta charset="utf-8"> | ||
| 5 | <title>spm</title> | ||
| 6 | <base href="/"> | ||
| 7 | <meta name="viewport" content="width=device-width, initial-scale=1"> | ||
| 8 | </head> | ||
| 9 | <body class="mat-typography mat-app-background"> | ||
| 10 | <app-root></app-root> | ||
| 11 | </body> | ||
| 12 | </html> | ||
diff --git a/overlays/spm/frontend/src/main.ts b/overlays/spm/frontend/src/main.ts new file mode 100644 index 00000000..c7b673cf --- /dev/null +++ b/overlays/spm/frontend/src/main.ts | |||
| @@ -0,0 +1,12 @@ | |||
| 1 | import { enableProdMode } from '@angular/core'; | ||
| 2 | import { platformBrowserDynamic } from '@angular/platform-browser-dynamic'; | ||
| 3 | |||
| 4 | import { AppModule } from './app/app.module'; | ||
| 5 | import { environment } from './environments/environment'; | ||
| 6 | |||
| 7 | if (environment.production) { | ||
| 8 | enableProdMode(); | ||
| 9 | } | ||
| 10 | |||
| 11 | platformBrowserDynamic().bootstrapModule(AppModule) | ||
| 12 | .catch(err => console.error(err)); | ||
diff --git a/overlays/spm/frontend/src/polyfills.ts b/overlays/spm/frontend/src/polyfills.ts new file mode 100644 index 00000000..429bb9ef --- /dev/null +++ b/overlays/spm/frontend/src/polyfills.ts | |||
| @@ -0,0 +1,53 @@ | |||
| 1 | /** | ||
| 2 | * This file includes polyfills needed by Angular and is loaded before the app. | ||
| 3 | * You can add your own extra polyfills to this file. | ||
| 4 | * | ||
| 5 | * This file is divided into 2 sections: | ||
| 6 | * 1. Browser polyfills. These are applied before loading ZoneJS and are sorted by browsers. | ||
| 7 | * 2. Application imports. Files imported after ZoneJS that should be loaded before your main | ||
| 8 | * file. | ||
| 9 | * | ||
| 10 | * The current setup is for so-called "evergreen" browsers; the last versions of browsers that | ||
| 11 | * automatically update themselves. This includes recent versions of Safari, Chrome (including | ||
| 12 | * Opera), Edge on the desktop, and iOS and Chrome on mobile. | ||
| 13 | * | ||
| 14 | * Learn more in https://angular.io/guide/browser-support | ||
| 15 | */ | ||
| 16 | |||
| 17 | /*************************************************************************************************** | ||
| 18 | * BROWSER POLYFILLS | ||
| 19 | */ | ||
| 20 | |||
| 21 | /** | ||
| 22 | * By default, zone.js will patch all possible macroTask and DomEvents | ||
| 23 | * user can disable parts of macroTask/DomEvents patch by setting following flags | ||
| 24 | * because those flags need to be set before `zone.js` being loaded, and webpack | ||
| 25 | * will put import in the top of bundle, so user need to create a separate file | ||
| 26 | * in this directory (for example: zone-flags.ts), and put the following flags | ||
| 27 | * into that file, and then add the following code before importing zone.js. | ||
| 28 | * import './zone-flags'; | ||
| 29 | * | ||
| 30 | * The flags allowed in zone-flags.ts are listed here. | ||
| 31 | * | ||
| 32 | * The following flags will work for all browsers. | ||
| 33 | * | ||
| 34 | * (window as any).__Zone_disable_requestAnimationFrame = true; // disable patch requestAnimationFrame | ||
| 35 | * (window as any).__Zone_disable_on_property = true; // disable patch onProperty such as onclick | ||
| 36 | * (window as any).__zone_symbol__UNPATCHED_EVENTS = ['scroll', 'mousemove']; // disable patch specified eventNames | ||
| 37 | * | ||
| 38 | * in IE/Edge developer tools, the addEventListener will also be wrapped by zone.js | ||
| 39 | * with the following flag, it will bypass `zone.js` patch for IE/Edge | ||
| 40 | * | ||
| 41 | * (window as any).__Zone_enable_cross_context_check = true; | ||
| 42 | * | ||
| 43 | */ | ||
| 44 | |||
| 45 | /*************************************************************************************************** | ||
| 46 | * Zone JS is required by default for Angular itself. | ||
| 47 | */ | ||
| 48 | import 'zone.js'; // Included with Angular CLI. | ||
| 49 | |||
| 50 | |||
| 51 | /*************************************************************************************************** | ||
| 52 | * APPLICATION IMPORTS | ||
| 53 | */ | ||
diff --git a/overlays/spm/frontend/src/styles.sass b/overlays/spm/frontend/src/styles.sass new file mode 100644 index 00000000..4f2cb82a --- /dev/null +++ b/overlays/spm/frontend/src/styles.sass | |||
| @@ -0,0 +1,2 @@ | |||
| 1 | /* You can add global styles to this file, and also import other style files */ | ||
| 2 | @import @fontsource/roboto | ||
diff --git a/overlays/spm/frontend/src/test.ts b/overlays/spm/frontend/src/test.ts new file mode 100644 index 00000000..00025daf --- /dev/null +++ b/overlays/spm/frontend/src/test.ts | |||
| @@ -0,0 +1,26 @@ | |||
| 1 | // This file is required by karma.conf.js and loads recursively all the .spec and framework files | ||
| 2 | |||
| 3 | import 'zone.js/testing'; | ||
| 4 | import { getTestBed } from '@angular/core/testing'; | ||
| 5 | import { | ||
| 6 | BrowserDynamicTestingModule, | ||
| 7 | platformBrowserDynamicTesting | ||
| 8 | } from '@angular/platform-browser-dynamic/testing'; | ||
| 9 | |||
| 10 | declare const require: { | ||
| 11 | context(path: string, deep?: boolean, filter?: RegExp): { | ||
| 12 | <T>(id: string): T; | ||
| 13 | keys(): string[]; | ||
| 14 | }; | ||
| 15 | }; | ||
| 16 | |||
| 17 | // First, initialize the Angular testing environment. | ||
| 18 | getTestBed().initTestEnvironment( | ||
| 19 | BrowserDynamicTestingModule, | ||
| 20 | platformBrowserDynamicTesting(), | ||
| 21 | ); | ||
| 22 | |||
| 23 | // Then we find all the tests. | ||
| 24 | const context = require.context('./', true, /\.spec\.ts$/); | ||
| 25 | // And load the modules. | ||
| 26 | context.keys().map(context); | ||
