🔧 Import Eldarya Enhancement's ESLint

merge-requests/9/head
Nato Boram 2022-03-11 00:30:44 -05:00
parent 4497bf7ce7
commit 7980719b9a
No known key found for this signature in database
GPG Key ID: 478E3C64BF88AFFA
21 changed files with 321 additions and 206 deletions

View File

@ -1,5 +1,8 @@
{ {
"root": true, "root": true,
"env": {
"browser": true
},
"ignorePatterns": [ "ignorePatterns": [
"projects/**/*" "projects/**/*"
], ],
@ -17,6 +20,7 @@
}, },
"extends": [ "extends": [
"plugin:@angular-eslint/all", "plugin:@angular-eslint/all",
"plugin:@angular-eslint/recommended--extra",
"plugin:@angular-eslint/template/process-inline-templates" "plugin:@angular-eslint/template/process-inline-templates"
], ],
"rules": { "rules": {
@ -35,8 +39,94 @@
"prefix": "app", "prefix": "app",
"style": "kebab-case" "style": "kebab-case"
} }
] ],
// Custom rules // Custom rules
// @typescript-eslint
"@typescript-eslint/array-type": "error",
"@typescript-eslint/class-literal-property-style": "error",
"@typescript-eslint/consistent-indexed-object-style": "error",
"@typescript-eslint/consistent-type-assertions": [
"error",
{
"assertionStyle": "as",
"objectLiteralTypeAssertions": "never"
}
],
"@typescript-eslint/consistent-type-definitions": "error",
"@typescript-eslint/consistent-type-imports": "error",
"@typescript-eslint/dot-notation": "error",
"@typescript-eslint/explicit-function-return-type": "error",
"@typescript-eslint/explicit-member-accessibility": [
"error",
{
"accessibility": "no-public"
}
],
"@typescript-eslint/member-delimiter-style": [
"error",
{
"multiline": {
"delimiter": "none",
"requireLast": true
}
}
],
"@typescript-eslint/method-signature-style": "error",
"@typescript-eslint/no-base-to-string": "error",
"@typescript-eslint/no-confusing-non-null-assertion": "error",
"@typescript-eslint/no-confusing-void-expression": [
"error",
{
"ignoreArrowShorthand": true,
"ignoreVoidOperator": true
}
],
"@typescript-eslint/no-dynamic-delete": "error",
"@typescript-eslint/no-empty-function": [
"error",
{
"allow": [
"private-constructors",
"protected-constructors"
]
}
],
"@typescript-eslint/no-extra-parens": [
"error",
"functions"
],
"@typescript-eslint/no-implicit-any-catch": "error",
"@typescript-eslint/no-invalid-void-type": "error",
"@typescript-eslint/no-non-null-assertion": "error",
"@typescript-eslint/no-unnecessary-boolean-literal-compare": "error",
"@typescript-eslint/no-unnecessary-condition": "error",
"@typescript-eslint/no-unnecessary-qualifier": "error",
"@typescript-eslint/no-unnecessary-type-arguments": "error",
"@typescript-eslint/no-unnecessary-type-constraint": "error",
"@typescript-eslint/no-unsafe-argument": "error",
"@typescript-eslint/no-unsafe-assignment": "error",
"@typescript-eslint/no-var-requires": "error",
"@typescript-eslint/non-nullable-type-assertion-style": "error",
"@typescript-eslint/prefer-for-of": "error",
"@typescript-eslint/prefer-function-type": "error",
"@typescript-eslint/prefer-includes": "error",
"@typescript-eslint/prefer-nullish-coalescing": "error",
"@typescript-eslint/prefer-optional-chain": "error",
"@typescript-eslint/prefer-readonly": "error",
"@typescript-eslint/prefer-reduce-type-parameter": "error",
"@typescript-eslint/prefer-return-this-type": "error",
"@typescript-eslint/prefer-string-starts-ends-with": "error",
"@typescript-eslint/prefer-ts-expect-error": "error",
"@typescript-eslint/promise-function-async": "error",
"@typescript-eslint/require-array-sort-compare": "error",
"@typescript-eslint/semi": [
"error",
"never"
],
"@typescript-eslint/sort-type-union-intersection-members": "error",
"@typescript-eslint/switch-exhaustiveness-check": "error",
"@typescript-eslint/type-annotation-spacing": "error",
"@typescript-eslint/unified-signatures": "error"
} }
}, },
{ {

View File

@ -24,11 +24,16 @@ build:
paths: paths:
- dist/angular - dist/angular
test: lint:
stage: test stage: test
script: script:
- pnpm run lint - pnpm run lint
test:
stage: test
script:
- pnpm run test
pages: pages:
stage: deploy stage: deploy
script: script:

View File

@ -1,11 +1,12 @@
import { NgModule } from '@angular/core'; import { NgModule } from '@angular/core'
import { RouterModule, Routes } from '@angular/router'; import type { Routes } from '@angular/router'
import { environment } from '../environments/environment'; import { RouterModule } from '@angular/router'
import { environment } from '../environments/environment'
const routes: Routes = [{ const routes: Routes = [{
path: '', path: '',
loadChildren: () => import('./pages/pages.module').then(m => m.PagesModule), loadChildren: async () => import('./pages/pages.module').then(m => m.PagesModule),
}]; }]
@NgModule({ @NgModule({
imports: [RouterModule.forRoot(routes, { useHash: environment.useHash, relativeLinkResolution: 'legacy' })], imports: [RouterModule.forRoot(routes, { useHash: environment.useHash, relativeLinkResolution: 'legacy' })],

View File

@ -1,35 +1,45 @@
import { TestBed, waitForAsync } from '@angular/core/testing'; import { TestBed, waitForAsync } from '@angular/core/testing'
import { RouterTestingModule } from '@angular/router/testing'; import { RouterTestingModule } from '@angular/router/testing'
import { AppComponent } from './app.component'; import { AppComponent } from './app.component'
describe('AppComponent', (): void => { describe('AppComponent', (): void => {
beforeEach(waitForAsync((): void => { beforeEach(waitForAsync((): void => {
TestBed.configureTestingModule({ TestBed.configureTestingModule({
imports: [ imports: [
RouterTestingModule RouterTestingModule,
], ],
declarations: [ declarations: [
AppComponent AppComponent
], ],
}).compileComponents(); }).compileComponents()
})); }))
it('should create the app', (): void => { it('should create the app', (): void => {
const fixture = TestBed.createComponent(AppComponent); const fixture = TestBed.createComponent(AppComponent)
const app = fixture.debugElement.componentInstance; if (!(fixture.debugElement.componentInstance instanceof AppComponent)) throw new Error("Expected AppComponent")
expect(app).toBeTruthy();
});
it(`should have as title 'public-gateway-cacher'`, (): void => { const app: AppComponent = fixture.debugElement.componentInstance
const fixture = TestBed.createComponent(AppComponent); expect(app).toBeTruthy()
const app = fixture.debugElement.componentInstance; })
expect(app.title).toEqual('public-gateway-cacher');
}); it(`should have a themeService`, (): void => {
const fixture = TestBed.createComponent(AppComponent)
if (!(fixture.debugElement.componentInstance instanceof AppComponent)) throw new Error("Expected AppComponent")
const app: AppComponent = fixture.debugElement.componentInstance
expect(app.themeService).toBeTruthy()
})
it('should render title', (): void => { it('should render title', (): void => {
const fixture = TestBed.createComponent(AppComponent); const fixture = TestBed.createComponent(AppComponent)
fixture.detectChanges(); fixture.detectChanges()
const compiled = fixture.debugElement.nativeElement; if (!isHTMLElement(fixture.debugElement.nativeElement)) throw new Error("Expected HTMLElement")
expect(compiled.querySelector('.content span').textContent).toContain('public-gateway-cacher app is running!');
}); const compiled: HTMLElement = fixture.debugElement.nativeElement
}); expect(compiled.querySelector('h1')?.textContent).toContain('Public Gateway Cacher')
})
})
function isHTMLElement(element: any): element is HTMLElement {
return element.__proto__ instanceof HTMLElement
}

View File

@ -1,5 +1,5 @@
import { ChangeDetectionStrategy, Component } from '@angular/core'; import { ChangeDetectionStrategy, Component, Inject } from '@angular/core'
import { ThemeService } from './services/theme.service'; import { ThemeService } from './services/theme.service'
@Component({ @Component({
selector: 'app-root', selector: 'app-root',
@ -9,6 +9,6 @@ import { ThemeService } from './services/theme.service';
}) })
export class AppComponent { export class AppComponent {
constructor( constructor(
public readonly themeService: ThemeService @Inject(ThemeService) readonly themeService: ThemeService
) { } ) { }
} }

View File

@ -1,14 +1,14 @@
import { CommonModule } from '@angular/common'; import { CommonModule } from '@angular/common'
import { HttpClientModule } from '@angular/common/http'; import { HttpClientModule } from '@angular/common/http'
import { NgModule } from '@angular/core'; import { NgModule } from '@angular/core'
import { FlexLayoutModule } from '@angular/flex-layout'; import { FlexLayoutModule } from '@angular/flex-layout'
import { MatButtonModule } from '@angular/material/button'; import { MatButtonModule } from '@angular/material/button'
import { MatIconModule } from '@angular/material/icon'; import { MatIconModule } from '@angular/material/icon'
import { MatToolbarModule } from '@angular/material/toolbar'; import { MatToolbarModule } from '@angular/material/toolbar'
import { BrowserModule } from '@angular/platform-browser'; import { BrowserModule } from '@angular/platform-browser'
import { BrowserAnimationsModule } from '@angular/platform-browser/animations'; import { BrowserAnimationsModule } from '@angular/platform-browser/animations'
import { AppRoutingModule } from './app-routing.module'; import { AppRoutingModule } from './app-routing.module'
import { AppComponent } from './app.component'; import { AppComponent } from './app.component'
@NgModule({ @NgModule({
declarations: [ declarations: [

View File

@ -1,5 +1,5 @@
export interface Environment { export interface Environment {
production: boolean; production: boolean
base_href?: string; base_href?: string
useHash: boolean; useHash: boolean
} }

View File

@ -1,11 +1,12 @@
import { NgModule } from '@angular/core'; import { NgModule } from '@angular/core'
import { RouterModule, Routes } from '@angular/router'; import type { Routes } from '@angular/router'
import { PagesComponent } from './pages.component'; import { RouterModule } from '@angular/router'
import { PagesComponent } from './pages.component'
const routes: Routes = [{ const routes: Routes = [{
path: '', path: '',
component: PagesComponent, component: PagesComponent,
}]; }]
@NgModule({ @NgModule({
imports: [RouterModule.forChild(routes)], imports: [RouterModule.forChild(routes)],

View File

@ -1,24 +1,27 @@
import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing'; import { HttpClientTestingModule } from '@angular/common/http/testing'
import { PagesComponent } from './pages.component'; import type { ComponentFixture } from '@angular/core/testing'
import { TestBed, waitForAsync } from '@angular/core/testing'
import { PagesComponent } from './pages.component'
describe('PagesComponent', (): void => { describe('PagesComponent', (): void => {
let component: PagesComponent; let component: PagesComponent
let fixture: ComponentFixture<PagesComponent>; let fixture: ComponentFixture<PagesComponent>
beforeEach(waitForAsync((): void => { beforeEach(waitForAsync((): void => {
TestBed.configureTestingModule({ TestBed.configureTestingModule({
imports: [HttpClientTestingModule],
declarations: [PagesComponent] declarations: [PagesComponent]
}) })
.compileComponents(); .compileComponents()
})); }))
beforeEach((): void => { beforeEach((): void => {
fixture = TestBed.createComponent(PagesComponent); fixture = TestBed.createComponent(PagesComponent)
component = fixture.componentInstance; component = fixture.componentInstance
fixture.detectChanges(); fixture.detectChanges()
}); })
it('should create', (): void => { it('should create', (): void => {
expect(component).toBeTruthy(); expect(component).toBeTruthy()
}); })
}); })

View File

@ -1,14 +1,15 @@
import { HttpErrorResponse } from '@angular/common/http'; import type { HttpErrorResponse } from '@angular/common/http'
import { ChangeDetectionStrategy, Component, EventEmitter, OnDestroy, OnInit, ViewChild } from '@angular/core'; import type { OnDestroy, OnInit } from '@angular/core'
import { ThemePalette } from '@angular/material/core'; import { ChangeDetectionStrategy, Component, EventEmitter, Inject, ViewChild } from '@angular/core'
import { MatTable, MatTableDataSource } from '@angular/material/table'; import type { ThemePalette } from '@angular/material/core'
import { Subscription } from 'rxjs'; import { MatTable, MatTableDataSource } from '@angular/material/table'
import { takeUntil } from 'rxjs/operators'; import type { Subscription } from 'rxjs'
import { environment } from '../../environments/environment'; import { takeUntil } from 'rxjs/operators'
import { Protocol } from '../enums/protocol.enum'; import { environment } from '../../environments/environment'
import { Theme } from '../enums/theme.enum'; import { Protocol } from '../enums/protocol.enum'
import { GatewayService } from '../services/gateway.service'; import { Theme } from '../enums/theme.enum'
import { ThemeService } from '../services/theme.service'; import { GatewayService } from '../services/gateway.service'
import { ThemeService } from '../services/theme.service'
@Component({ @Component({
selector: 'app-pages', selector: 'app-pages',
@ -18,64 +19,64 @@ import { ThemeService } from '../services/theme.service';
}) })
export class PagesComponent implements OnInit, OnDestroy { export class PagesComponent implements OnInit, OnDestroy {
@ViewChild(MatTable) matTable!: MatTable<Result>; @ViewChild(MatTable) matTable!: MatTable<Result>
gateways!: string[]; gateways!: string[]
inputColour: ThemePalette = 'primary'; inputColour: ThemePalette = 'primary'
ipfs = ''; ipfs = ''
ipns = ''; ipns = ''
readonly dataSource = new MatTableDataSource<Result>([]); readonly dataSource = new MatTableDataSource<Result>([])
readonly displayedColumns: ['icon', 'gateway'] = ['icon', 'gateway']; readonly displayedColumns: ['icon', 'gateway'] = ['icon', 'gateway']
readonly subscriptions: Subscription[] = []; readonly subscriptions: Subscription[] = []
private readonly destroy$ = new EventEmitter<void>(); private readonly destroy$ = new EventEmitter<void>()
constructor( constructor(
private readonly gatewayService: GatewayService, @Inject(GatewayService) private readonly gatewayService: GatewayService,
private readonly themeService: ThemeService @Inject(ThemeService) private readonly themeService: ThemeService
) { } ) { }
ngOnInit(): void { ngOnInit(): void {
this.gatewayService.list().subscribe((gateways): void => { this.gateways = gateways; }); this.gatewayService.list().subscribe((gateways): void => { this.gateways = gateways })
// Theme // Theme
this.setColours(this.themeService.current); this.setColours(this.themeService.current)
this.themeService.valueChanges.pipe( this.themeService.valueChanges.pipe(
takeUntil(this.destroy$) takeUntil(this.destroy$)
).subscribe((theme): void => { ).subscribe((theme): void => {
this.setColours(theme); this.setColours(theme)
}); })
} }
ngOnDestroy(): void { ngOnDestroy(): void {
this.destroy$.complete(); this.destroy$.complete()
} }
cacheIPFS(): void { cacheIPFS(): void {
this.ipfs = this.ipfs.trim(); this.ipfs = this.ipfs.trim()
this.cache(Protocol.IPFS, this.ipfs); this.cache(Protocol.IPFS, this.ipfs)
} }
cacheIPNS(): void { cacheIPNS(): void {
this.ipns = this.ipns.trim(); this.ipns = this.ipns.trim()
this.cache(Protocol.IPNS, this.ipns); this.cache(Protocol.IPNS, this.ipns)
} }
cache(protocol: Protocol, hashpath: string): void { cache(protocol: Protocol, hashpath: string): void {
// Clear subscriptions // Clear subscriptions
while (this.subscriptions.length) { while (this.subscriptions.length) {
const sub = this.subscriptions.pop(); const sub = this.subscriptions.pop()
if (sub && !sub.closed) { if (sub && !sub.closed) {
sub.unsubscribe(); sub.unsubscribe()
} }
} }
// Clear table // Clear table
this.dataSource.data = []; this.dataSource.data = []
this.matTable.renderRows(); this.matTable.renderRows()
console.clear(); console.clear()
this.gateways.forEach((gateway): void => { this.gateways.forEach((gateway): void => {
this.subscriptions.push( this.subscriptions.push(
@ -85,50 +86,50 @@ export class PagesComponent implements OnInit, OnDestroy {
message: resp.statusText, message: resp.statusText,
icon: this.getIcon(resp.status), icon: this.getIcon(resp.status),
ok: resp.ok, ok: resp.ok,
}); })
this.matTable.renderRows(); this.matTable.renderRows()
}, (error: HttpErrorResponse): void => { }, (error: HttpErrorResponse): void => {
this.dataSource.data.push({ this.dataSource.data.push({
gateway: this.gatewayService.url(gateway, protocol, hashpath), gateway: this.gatewayService.url(gateway, protocol, hashpath),
message: error.statusText, message: error.statusText,
icon: this.getIcon(error.status), icon: this.getIcon(error.status),
ok: error.ok, ok: error.ok,
});
this.matTable.renderRows();
}) })
); this.matTable.renderRows()
}); })
)
})
} }
private setColours(theme: Theme): void { private setColours(theme: Theme): void {
switch (theme) { switch (theme) {
case Theme.Light: case Theme.Light:
this.inputColour = 'primary'; this.inputColour = 'primary'
break; break
case Theme.Dark: case Theme.Dark:
this.inputColour = 'accent'; this.inputColour = 'accent'
break; break
default: default:
break; break
} }
} }
private getIcon(status: number): string { private getIcon(status: number): string {
if (status >= 200 && status < 300) { return '✅'; } if (status >= 200 && status < 300) { return '✅' }
switch (status) { switch (status) {
case 0: return '❌'; case 0: return '❌'
case 403: return '⛔'; case 403: return '⛔'
case 404: return '❓'; case 404: return '❓'
case 500: return '❗'; case 500: return '❗'
default: return environment.production ? '❌' : '❔'; default: return environment.production ? '❌' : '❔'
} }
} }
} }
interface Result { interface Result {
gateway: string; gateway: string
message: string; message: string
icon: string; icon: string
ok: boolean; ok: boolean
} }

View File

@ -1,15 +1,15 @@
import { CommonModule } from '@angular/common'; import { CommonModule } from '@angular/common'
import { NgModule } from '@angular/core'; import { NgModule } from '@angular/core'
import { FlexLayoutModule } from '@angular/flex-layout'; import { FlexLayoutModule } from '@angular/flex-layout'
import { FormsModule } from '@angular/forms'; import { FormsModule } from '@angular/forms'
import { MatButtonModule } from '@angular/material/button'; import { MatButtonModule } from '@angular/material/button'
import { MatInputModule } from '@angular/material/input'; import { MatInputModule } from '@angular/material/input'
import { MatProgressBarModule } from '@angular/material/progress-bar'; import { MatProgressBarModule } from '@angular/material/progress-bar'
import { MatSortModule } from '@angular/material/sort'; import { MatSortModule } from '@angular/material/sort'
import { MatTableModule } from '@angular/material/table'; import { MatTableModule } from '@angular/material/table'
import { MatTooltipModule } from '@angular/material/tooltip'; import { MatTooltipModule } from '@angular/material/tooltip'
import { PagesRoutingModule } from './pages-routing.module'; import { PagesRoutingModule } from './pages-routing.module'
import { PagesComponent } from './pages.component'; import { PagesComponent } from './pages.component'
@NgModule({ @NgModule({
declarations: [PagesComponent], declarations: [PagesComponent],

View File

@ -1,11 +1,15 @@
import { TestBed, TestBedStatic } from '@angular/core/testing'; import { HttpClientTestingModule } from '@angular/common/http/testing'
import { GatewayService } from './gateway.service'; import type { TestBedStatic } from '@angular/core/testing'
import { TestBed } from '@angular/core/testing'
import { GatewayService } from './gateway.service'
describe('GatewayService', (): void => { describe('GatewayService', (): void => {
beforeEach((): TestBedStatic => TestBed.configureTestingModule({})); beforeEach((): TestBedStatic => TestBed.configureTestingModule({
imports: [HttpClientTestingModule]
}))
it('should be created', (): void => { it('should be created', (): void => {
const service: GatewayService = TestBed.inject(GatewayService); const service: GatewayService = TestBed.inject(GatewayService)
expect(service).toBeTruthy(); expect(service).toBeTruthy()
}); })
}); })

View File

@ -1,8 +1,9 @@
import { HttpClient, HttpResponse } from '@angular/common/http'; import type { HttpResponse } from '@angular/common/http'
import { Injectable } from '@angular/core'; import { HttpClient } from '@angular/common/http'
import { Observable } from 'rxjs'; import { Inject, Injectable } from '@angular/core'
import { environment } from '../../environments/environment'; import type { Observable } from 'rxjs'
import { Protocol } from '../enums/protocol.enum'; import { environment } from '../../environments/environment'
import type { Protocol } from '../enums/protocol.enum'
@Injectable({ @Injectable({
providedIn: 'root' providedIn: 'root'
@ -10,7 +11,7 @@ import { Protocol } from '../enums/protocol.enum';
export class GatewayService { export class GatewayService {
constructor( constructor(
private readonly http: HttpClient @Inject(HttpClient) private readonly http: HttpClient
) { } ) { }
list(): Observable<string[]> { list(): Observable<string[]> {
@ -18,20 +19,20 @@ export class GatewayService {
environment.base_href && environment.base_href !== '/' environment.base_href && environment.base_href !== '/'
? `${environment.base_href}/assets/json/gateways.json` ? `${environment.base_href}/assets/json/gateways.json`
: `${document.querySelector('base')?.href}assets/json/gateways.json` : `${document.querySelector('base')?.href}assets/json/gateways.json`
); )
} }
get(gateway: string, protocol: Protocol, hashpath: string): Observable<HttpResponse<string>> { get(gateway: string, protocol: Protocol, hashpath: string): Observable<HttpResponse<string>> {
return this.http.get(`${this.url(gateway, protocol, hashpath)}#x-ipfs-companion-no-redirect`, { return this.http.get(`${this.url(gateway, protocol, hashpath)}#x-ipfs-companion-no-redirect`, {
observe: 'response', observe: 'response',
responseType: 'text', responseType: 'text',
}); })
} }
url(gateway: string, protocol: Protocol, hashpath: string): string { url(gateway: string, protocol: Protocol, hashpath: string): string {
const splits: string[] = hashpath.split('/'); const splits: string[] = hashpath.split('/')
const url: string = gateway.replace(':type', protocol).replace(':hash', splits.shift() || ''); const url: string = gateway.replace(':type', protocol).replace(':hash', splits.shift() ?? '')
return splits.length ? [url, splits.join('/')].join('/') : url; return splits.length ? [url, splits.join('/')].join('/') : url
} }
} }

View File

@ -1,15 +1,15 @@
import { TestBed } from '@angular/core/testing'; import { TestBed } from '@angular/core/testing'
import { ThemeService } from './theme.service'; import { ThemeService } from './theme.service'
describe('ThemeService', (): void => { describe('ThemeService', (): void => {
let service: ThemeService; let service: ThemeService
beforeEach((): void => { beforeEach((): void => {
TestBed.configureTestingModule({}); TestBed.configureTestingModule({})
service = TestBed.inject(ThemeService); service = TestBed.inject(ThemeService)
}); })
it('should be created', (): void => { it('should be created', (): void => {
expect(service).toBeTruthy(); expect(service).toBeTruthy()
}); })
}); })

View File

@ -1,9 +1,10 @@
import { Injectable } from '@angular/core'; import { Injectable } from '@angular/core'
import { Observable, Subject } from 'rxjs'; import type { Observable } from 'rxjs'
import { Theme } from '../enums/theme.enum'; import { Subject } from 'rxjs'
import { Theme } from '../enums/theme.enum'
function enumGuard<T>(enumeration: T): (token: unknown) => token is T[keyof T] { function enumGuard<T>(enumeration: T): (token: unknown) => token is T[keyof T] {
return (token: unknown): token is T[keyof T] => Object.values(enumeration).includes(token); return (token: unknown): token is T[keyof T] => Object.values(enumeration).includes(token)
} }
@Injectable({ @Injectable({
@ -11,39 +12,39 @@ function enumGuard<T>(enumeration: T): (token: unknown) => token is T[keyof T] {
}) })
export class ThemeService { export class ThemeService {
current = Theme.Light; current = Theme.Light
icon = 'brightness_low'; icon = 'brightness_low'
readonly valueChanges: Observable<Theme>; readonly valueChanges: Observable<Theme>
private readonly subject$ = new Subject<Theme>(); private readonly subject$ = new Subject<Theme>()
constructor() { constructor() {
const stored = localStorage.getItem('theme'); const stored = localStorage.getItem('theme')
if (enumGuard(Theme)(stored)) { if (enumGuard(Theme)(stored)) {
this.setTheme(stored); this.setTheme(stored)
} }
this.valueChanges = this.subject$.asObservable(); this.valueChanges = this.subject$.asObservable()
} }
switchTheme(): void { switchTheme(): void {
this.setTheme(this.current === Theme.Light ? Theme.Dark : Theme.Light); this.setTheme(this.current === Theme.Light ? Theme.Dark : Theme.Light)
} }
setTheme(theme: Theme): void { setTheme(theme: Theme): void {
document.querySelector('body')?.classList.remove(this.current); document.querySelector('body')?.classList.remove(this.current)
document.querySelector('body')?.classList.add(theme); document.querySelector('body')?.classList.add(theme)
this.current = theme; this.current = theme
this.icon = this.getIcon(theme); this.icon = this.getIcon(theme)
this.subject$.next(theme); this.subject$.next(theme)
localStorage.setItem('theme', theme); localStorage.setItem('theme', theme)
} }
getIcon(theme: Theme): string { getIcon(theme: Theme): string {
switch (theme) { switch (theme) {
case Theme.Dark: return 'brightness_high'; case Theme.Dark: return 'brightness_high'
case Theme.Light: case Theme.Light:
default: return 'brightness_low'; default: return 'brightness_low'
} }
} }
} }

View File

@ -1,7 +1,7 @@
import { Environment } from '../app/interfaces/environment'; import type { Environment } from '../app/interfaces/environment'
export const environment: Environment = { export const environment: Environment = {
production: true, production: true,
base_href: '/public-gateway-cacher', base_href: '/public-gateway-cacher',
useHash: false, useHash: false,
}; }

View File

@ -1,6 +1,6 @@
import { Environment } from '../app/interfaces/environment'; import type { Environment } from '../app/interfaces/environment'
export const environment: Environment = { export const environment: Environment = {
production: true, production: true,
useHash: true, useHash: true,
}; }

View File

@ -1,7 +1,7 @@
import { Environment } from '../app/interfaces/environment'; import type { Environment } from '../app/interfaces/environment'
export const environment: Environment = { export const environment: Environment = {
production: true, production: true,
base_href: '/', base_href: '/',
useHash: false, useHash: false,
}; }

View File

@ -1,4 +1,4 @@
import { Environment } from '../app/interfaces/environment'; import type { Environment } from '../app/interfaces/environment'
// This file can be replaced during build by using the `fileReplacements` array. // This file can be replaced during build by using the `fileReplacements` array.
// `ng build --prod` replaces `environment.ts` with `environment.prod.ts`. // `ng build --prod` replaces `environment.ts` with `environment.prod.ts`.
@ -8,7 +8,7 @@ export const environment: Environment = {
production: false, production: false,
base_href: '/', base_href: '/',
useHash: false, useHash: false,
}; }
/* /*
* For easier debugging in development mode, you can import the following file * For easier debugging in development mode, you can import the following file

View File

@ -1,11 +1,11 @@
import { enableProdMode } from '@angular/core'; import { enableProdMode } from '@angular/core'
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic'; import { platformBrowserDynamic } from '@angular/platform-browser-dynamic'
import { AppModule } from './app/app.module'; import { AppModule } from './app/app.module'
import { environment } from './environments/environment'; import { environment } from './environments/environment'
if (environment.production) { if (environment.production) {
enableProdMode(); enableProdMode()
} }
platformBrowserDynamic().bootstrapModule(AppModule) platformBrowserDynamic().bootstrapModule(AppModule)
.catch((err): void => console.error(err)); .catch((err): void => console.error(err))

View File

@ -1,22 +1,20 @@
/* eslint-disable @typescript-eslint/no-unsafe-assignment */
// This file is required by karma.conf.js and loads recursively all the .spec and framework files // This file is required by karma.conf.js and loads recursively all the .spec and framework files
import { getTestBed } from '@angular/core/testing'
import { BrowserDynamicTestingModule, platformBrowserDynamicTesting } from '@angular/platform-browser-dynamic/testing'
import 'zone.js/testing'
import { getTestBed } from '@angular/core/testing'; declare const require: any
import {
BrowserDynamicTestingModule,
platformBrowserDynamicTesting
} from '@angular/platform-browser-dynamic/testing';
import 'zone.js/testing';
declare const require: any;
// First, initialize the Angular testing environment. // First, initialize the Angular testing environment.
getTestBed().initTestEnvironment( getTestBed().initTestEnvironment(
BrowserDynamicTestingModule, BrowserDynamicTestingModule,
platformBrowserDynamicTesting(), { platformBrowserDynamicTesting(),
teardown: { destroyAfterEach: false } { teardown: { destroyAfterEach: false } }
} )
);
// Then we find all the tests. // Then we find all the tests.
const context = require.context('./', true, /\.spec\.ts$/); const context = require.context('./', true, /\.spec\.ts$/)
// And load the modules. // And load the modules.
context.keys().map(context); context.keys().map(context)