🔧 Import Eldarya Enhancement's ESLint
parent
4497bf7ce7
commit
7980719b9a
|
@ -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"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|
|
@ -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:
|
||||||
|
|
|
@ -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' })],
|
||||||
|
|
|
@ -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
|
||||||
|
}
|
||||||
|
|
|
@ -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
|
||||||
) { }
|
) { }
|
||||||
}
|
}
|
||||||
|
|
|
@ -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: [
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
export interface Environment {
|
export interface Environment {
|
||||||
production: boolean;
|
production: boolean
|
||||||
base_href?: string;
|
base_href?: string
|
||||||
useHash: boolean;
|
useHash: boolean
|
||||||
}
|
}
|
||||||
|
|
|
@ -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)],
|
||||||
|
|
|
@ -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()
|
||||||
});
|
})
|
||||||
});
|
})
|
||||||
|
|
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
|
@ -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],
|
||||||
|
|
|
@ -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()
|
||||||
});
|
})
|
||||||
});
|
})
|
||||||
|
|
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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()
|
||||||
});
|
})
|
||||||
});
|
})
|
||||||
|
|
|
@ -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'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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,
|
||||||
};
|
}
|
||||||
|
|
|
@ -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,
|
||||||
};
|
}
|
||||||
|
|
|
@ -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,
|
||||||
};
|
}
|
||||||
|
|
|
@ -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
|
||||||
|
|
12
src/main.ts
12
src/main.ts
|
@ -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))
|
||||||
|
|
26
src/test.ts
26
src/test.ts
|
@ -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)
|
||||||
|
|
Loading…
Reference in New Issue