mirror of
https://github.com/Start9Labs/start-os.git
synced 2026-04-04 14:29:45 +00:00
Feature/shared refactor (#1176)
* refactor: move most of the shared entities to @start8labs/shared library
This commit is contained in:
@@ -3,7 +3,7 @@ import { CommonModule } from '@angular/common'
|
||||
import { Routes, RouterModule } from '@angular/router'
|
||||
import { IonicModule } from '@ionic/angular'
|
||||
import { LANPage } from './lan.page'
|
||||
import { SharingModule } from 'src/app/modules/sharing.module'
|
||||
import { SharedPipesModule } from '@start9labs/shared'
|
||||
|
||||
const routes: Routes = [
|
||||
{
|
||||
@@ -17,8 +17,8 @@ const routes: Routes = [
|
||||
CommonModule,
|
||||
IonicModule,
|
||||
RouterModule.forChild(routes),
|
||||
SharingModule,
|
||||
SharedPipesModule,
|
||||
],
|
||||
declarations: [LANPage],
|
||||
})
|
||||
export class LANPageModule { }
|
||||
export class LANPageModule {}
|
||||
|
||||
@@ -3,7 +3,7 @@ import { CommonModule } from '@angular/common'
|
||||
import { IonicModule } from '@ionic/angular'
|
||||
import { RouterModule, Routes } from '@angular/router'
|
||||
import { MarketplacesPage } from './marketplaces.page'
|
||||
import { SharingModule } from 'src/app/modules/sharing.module'
|
||||
import { SharedPipesModule } from '@start9labs/shared'
|
||||
|
||||
const routes: Routes = [
|
||||
{
|
||||
@@ -17,7 +17,7 @@ const routes: Routes = [
|
||||
CommonModule,
|
||||
IonicModule,
|
||||
RouterModule.forChild(routes),
|
||||
SharingModule,
|
||||
SharedPipesModule,
|
||||
],
|
||||
declarations: [MarketplacesPage],
|
||||
})
|
||||
|
||||
@@ -3,7 +3,7 @@ import { CommonModule } from '@angular/common'
|
||||
import { IonicModule } from '@ionic/angular'
|
||||
import { PreferencesPage } from './preferences.page'
|
||||
import { Routes, RouterModule } from '@angular/router'
|
||||
import { SharingModule } from 'src/app/modules/sharing.module'
|
||||
import { SharedPipesModule } from '@start9labs/shared'
|
||||
|
||||
const routes: Routes = [
|
||||
{
|
||||
@@ -17,10 +17,8 @@ const routes: Routes = [
|
||||
CommonModule,
|
||||
IonicModule,
|
||||
RouterModule.forChild(routes),
|
||||
SharingModule,
|
||||
],
|
||||
declarations: [
|
||||
PreferencesPage,
|
||||
SharedPipesModule,
|
||||
],
|
||||
declarations: [PreferencesPage],
|
||||
})
|
||||
export class PreferencesPageModule { }
|
||||
export class PreferencesPageModule {}
|
||||
|
||||
@@ -24,7 +24,7 @@ export class PreferencesPage {
|
||||
defaultName: string
|
||||
clicks = 0
|
||||
|
||||
constructor(
|
||||
constructor (
|
||||
private readonly loadingCtrl: LoadingController,
|
||||
private readonly modalCtrl: ModalController,
|
||||
private readonly api: ApiService,
|
||||
@@ -32,17 +32,17 @@ export class PreferencesPage {
|
||||
private readonly localStorageService: LocalStorageService,
|
||||
public readonly serverConfig: ServerConfigService,
|
||||
public readonly patch: PatchDbService,
|
||||
) {}
|
||||
) { }
|
||||
|
||||
ngOnInit() {
|
||||
ngOnInit () {
|
||||
this.defaultName = `Embassy-${this.patch.getData()['server-info'].id}`
|
||||
}
|
||||
|
||||
ngAfterViewInit() {
|
||||
ngAfterViewInit () {
|
||||
this.content.scrollToPoint(undefined, 1)
|
||||
}
|
||||
|
||||
async presentModalName(): Promise<void> {
|
||||
async presentModalName (): Promise<void> {
|
||||
const options: GenericInputOptions = {
|
||||
title: 'Edit Device Name',
|
||||
message: 'This is for your reference only.',
|
||||
@@ -66,7 +66,7 @@ export class PreferencesPage {
|
||||
await modal.present()
|
||||
}
|
||||
|
||||
async setDbValue(key: string, value: any): Promise<void> {
|
||||
private async setDbValue (key: string, value: string): Promise<void> {
|
||||
const loader = await this.loadingCtrl.create({
|
||||
spinner: 'lines',
|
||||
message: 'Saving...',
|
||||
@@ -81,7 +81,7 @@ export class PreferencesPage {
|
||||
}
|
||||
}
|
||||
|
||||
async addClick() {
|
||||
async addClick () {
|
||||
this.clicks++
|
||||
if (this.clicks >= 5) {
|
||||
this.clicks = 0
|
||||
|
||||
@@ -3,7 +3,7 @@ import { RouterModule, Routes } from '@angular/router'
|
||||
import { CommonModule } from '@angular/common'
|
||||
import { IonicModule } from '@ionic/angular'
|
||||
import { RestorePage } from './restore.component'
|
||||
import { SharingModule } from 'src/app/modules/sharing.module'
|
||||
import { SharedPipesModule } from '@start9labs/shared'
|
||||
import { BackupDrivesComponentModule } from 'src/app/components/backup-drives/backup-drives.component.module'
|
||||
import { AppRecoverSelectPageModule } from 'src/app/modals/app-recover-select/app-recover-select.module'
|
||||
|
||||
@@ -19,12 +19,10 @@ const routes: Routes = [
|
||||
CommonModule,
|
||||
IonicModule,
|
||||
RouterModule.forChild(routes),
|
||||
SharingModule,
|
||||
SharedPipesModule,
|
||||
BackupDrivesComponentModule,
|
||||
AppRecoverSelectPageModule,
|
||||
],
|
||||
declarations: [
|
||||
RestorePage,
|
||||
],
|
||||
declarations: [RestorePage],
|
||||
})
|
||||
export class RestorePageModule { }
|
||||
export class RestorePageModule {}
|
||||
|
||||
@@ -1,9 +1,16 @@
|
||||
import { Component } from '@angular/core'
|
||||
import { ModalController, NavController } from '@ionic/angular'
|
||||
import { ApiService } from 'src/app/services/api/embassy-api.service'
|
||||
import { GenericInputComponent, GenericInputOptions } from 'src/app/modals/generic-input/generic-input.component'
|
||||
import { MappedBackupTarget } from 'src/app/util/misc.util'
|
||||
import { BackupInfo, CifsBackupTarget, DiskBackupTarget } from 'src/app/services/api/api.types'
|
||||
import {
|
||||
GenericInputComponent,
|
||||
GenericInputOptions,
|
||||
} from 'src/app/modals/generic-input/generic-input.component'
|
||||
import { MappedBackupTarget } from 'src/app/types/mapped-backup-target'
|
||||
import {
|
||||
BackupInfo,
|
||||
CifsBackupTarget,
|
||||
DiskBackupTarget,
|
||||
} from 'src/app/services/api/api.types'
|
||||
import { AppRecoverSelectPage } from 'src/app/modals/app-recover-select/app-recover-select.page'
|
||||
import { PatchDbService } from 'src/app/services/patch-db/patch-db.service'
|
||||
import * as argon2 from '@start9labs/argon2'
|
||||
@@ -14,18 +21,20 @@ import * as argon2 from '@start9labs/argon2'
|
||||
styleUrls: ['./restore.component.scss'],
|
||||
})
|
||||
export class RestorePage {
|
||||
|
||||
constructor (
|
||||
constructor(
|
||||
private readonly modalCtrl: ModalController,
|
||||
private readonly navCtrl: NavController,
|
||||
private readonly embassyApi: ApiService,
|
||||
private readonly patch: PatchDbService,
|
||||
) { }
|
||||
) {}
|
||||
|
||||
async presentModalPassword (target: MappedBackupTarget<CifsBackupTarget | DiskBackupTarget>): Promise<void> {
|
||||
async presentModalPassword(
|
||||
target: MappedBackupTarget<CifsBackupTarget | DiskBackupTarget>,
|
||||
): Promise<void> {
|
||||
const options: GenericInputOptions = {
|
||||
title: 'Master Password Required',
|
||||
message: 'Enter your master password. On the next screen, you will select the individual services you want to restore.',
|
||||
message:
|
||||
'Enter your master password. On the next screen, you will select the individual services you want to restore.',
|
||||
label: 'Master Password',
|
||||
placeholder: 'Enter master password',
|
||||
useMask: true,
|
||||
@@ -43,7 +52,10 @@ export class RestorePage {
|
||||
await modal.present()
|
||||
}
|
||||
|
||||
private async decryptDrive (target: MappedBackupTarget<CifsBackupTarget | DiskBackupTarget>, password: string): Promise<void> {
|
||||
private async decryptDrive(
|
||||
target: MappedBackupTarget<CifsBackupTarget | DiskBackupTarget>,
|
||||
password: string,
|
||||
): Promise<void> {
|
||||
const passwordHash = this.patch.getData()['server-info']['password-hash']
|
||||
argon2.verify(passwordHash, password)
|
||||
|
||||
@@ -55,15 +67,20 @@ export class RestorePage {
|
||||
}
|
||||
}
|
||||
|
||||
private async presentModalOldPassword (target: MappedBackupTarget<CifsBackupTarget | DiskBackupTarget>, password: string): Promise<void> {
|
||||
private async presentModalOldPassword(
|
||||
target: MappedBackupTarget<CifsBackupTarget | DiskBackupTarget>,
|
||||
password: string,
|
||||
): Promise<void> {
|
||||
const options: GenericInputOptions = {
|
||||
title: 'Original Password Needed',
|
||||
message: 'This backup was created with a different password. Enter the ORIGINAL password that was used to encrypt this backup.',
|
||||
message:
|
||||
'This backup was created with a different password. Enter the ORIGINAL password that was used to encrypt this backup.',
|
||||
label: 'Original Password',
|
||||
placeholder: 'Enter original password',
|
||||
useMask: true,
|
||||
buttonText: 'Restore From Backup',
|
||||
submitFn: (oldPassword: string) => this.restoreFromBackup(target, password, oldPassword),
|
||||
submitFn: (oldPassword: string) =>
|
||||
this.restoreFromBackup(target, password, oldPassword),
|
||||
}
|
||||
|
||||
const m = await this.modalCtrl.create({
|
||||
@@ -76,7 +93,11 @@ export class RestorePage {
|
||||
await m.present()
|
||||
}
|
||||
|
||||
private async restoreFromBackup (target: MappedBackupTarget<CifsBackupTarget | DiskBackupTarget>, password: string, oldPassword?: string): Promise<void> {
|
||||
private async restoreFromBackup(
|
||||
target: MappedBackupTarget<CifsBackupTarget | DiskBackupTarget>,
|
||||
password: string,
|
||||
oldPassword?: string,
|
||||
): Promise<void> {
|
||||
const backupInfo = await this.embassyApi.getBackupInfo({
|
||||
'target-id': target.id,
|
||||
password,
|
||||
@@ -84,7 +105,12 @@ export class RestorePage {
|
||||
this.presentModalSelect(target.id, backupInfo, password, oldPassword)
|
||||
}
|
||||
|
||||
private async presentModalSelect (id: string, backupInfo: BackupInfo, password: string, oldPassword?: string): Promise<void> {
|
||||
private async presentModalSelect(
|
||||
id: string,
|
||||
backupInfo: BackupInfo,
|
||||
password: string,
|
||||
oldPassword?: string,
|
||||
): Promise<void> {
|
||||
const modal = await this.modalCtrl.create({
|
||||
componentProps: {
|
||||
id,
|
||||
|
||||
@@ -4,7 +4,7 @@ import { IonicModule } from '@ionic/angular'
|
||||
import { ServerBackupPage } from './server-backup.page'
|
||||
import { RouterModule, Routes } from '@angular/router'
|
||||
import { BackupDrivesComponentModule } from 'src/app/components/backup-drives/backup-drives.component.module'
|
||||
import { SharingModule } from 'src/app/modules/sharing.module'
|
||||
import { SharedPipesModule } from '@start9labs/shared'
|
||||
|
||||
const routes: Routes = [
|
||||
{
|
||||
@@ -18,11 +18,9 @@ const routes: Routes = [
|
||||
CommonModule,
|
||||
IonicModule,
|
||||
RouterModule.forChild(routes),
|
||||
SharingModule,
|
||||
SharedPipesModule,
|
||||
BackupDrivesComponentModule,
|
||||
],
|
||||
declarations: [
|
||||
ServerBackupPage,
|
||||
],
|
||||
declarations: [ServerBackupPage],
|
||||
})
|
||||
export class ServerBackupPageModule { }
|
||||
export class ServerBackupPageModule {}
|
||||
|
||||
@@ -10,14 +10,13 @@ import {
|
||||
GenericInputOptions,
|
||||
} from 'src/app/modals/generic-input/generic-input.component'
|
||||
import { PatchDbService } from 'src/app/services/patch-db/patch-db.service'
|
||||
import { Subscription } from 'rxjs'
|
||||
import { take } from 'rxjs/operators'
|
||||
import { MappedBackupTarget } from 'src/app/types/mapped-backup-target'
|
||||
import {
|
||||
PackageDataEntry,
|
||||
PackageMainStatus,
|
||||
ServerStatus,
|
||||
} from 'src/app/services/patch-db/data-model'
|
||||
import { Subscription } from 'rxjs'
|
||||
import { take } from 'rxjs/operators'
|
||||
import { MappedBackupTarget } from 'src/app/util/misc.util'
|
||||
import * as argon2 from '@start9labs/argon2'
|
||||
import {
|
||||
CifsBackupTarget,
|
||||
|
||||
@@ -3,7 +3,7 @@ import { CommonModule } from '@angular/common'
|
||||
import { Routes, RouterModule } from '@angular/router'
|
||||
import { IonicModule } from '@ionic/angular'
|
||||
import { ServerLogsPage } from './server-logs.page'
|
||||
import { SharingModule } from 'src/app/modules/sharing.module'
|
||||
import { SharedPipesModule } from '@start9labs/shared'
|
||||
import { LogsPageModule } from 'src/app/components/logs/logs.module'
|
||||
|
||||
const routes: Routes = [
|
||||
@@ -18,9 +18,9 @@ const routes: Routes = [
|
||||
CommonModule,
|
||||
IonicModule,
|
||||
RouterModule.forChild(routes),
|
||||
SharingModule,
|
||||
SharedPipesModule,
|
||||
LogsPageModule,
|
||||
],
|
||||
declarations: [ServerLogsPage],
|
||||
})
|
||||
export class ServerLogsPageModule { }
|
||||
export class ServerLogsPageModule {}
|
||||
|
||||
@@ -4,7 +4,7 @@ import { Routes, RouterModule } from '@angular/router'
|
||||
import { IonicModule } from '@ionic/angular'
|
||||
import { ServerMetricsPage } from './server-metrics.page'
|
||||
import { SkeletonListComponentModule } from 'src/app/components/skeleton-list/skeleton-list.component.module'
|
||||
import { SharingModule } from 'src/app/modules/sharing.module'
|
||||
import { SharedPipesModule } from '@start9labs/shared'
|
||||
|
||||
const routes: Routes = [
|
||||
{
|
||||
@@ -19,8 +19,8 @@ const routes: Routes = [
|
||||
IonicModule,
|
||||
RouterModule.forChild(routes),
|
||||
SkeletonListComponentModule,
|
||||
SharingModule,
|
||||
SharedPipesModule,
|
||||
],
|
||||
declarations: [ServerMetricsPage],
|
||||
})
|
||||
export class ServerMetricsPageModule { }
|
||||
export class ServerMetricsPageModule {}
|
||||
|
||||
@@ -2,7 +2,7 @@ import { Component } from '@angular/core'
|
||||
import { Metrics } from 'src/app/services/api/api.types'
|
||||
import { ApiService } from 'src/app/services/api/embassy-api.service'
|
||||
import { ErrorToastService } from 'src/app/services/error-toast.service'
|
||||
import { pauseFor } from 'src/app/util/misc.util'
|
||||
import { pauseFor } from '@start9labs/shared'
|
||||
|
||||
@Component({
|
||||
selector: 'server-metrics',
|
||||
@@ -12,14 +12,14 @@ import { pauseFor } from 'src/app/util/misc.util'
|
||||
export class ServerMetricsPage {
|
||||
loading = true
|
||||
going = false
|
||||
metrics: Metrics = { }
|
||||
metrics: Metrics = {}
|
||||
|
||||
constructor (
|
||||
constructor(
|
||||
private readonly errToast: ErrorToastService,
|
||||
private readonly embassyApi: ApiService,
|
||||
) { }
|
||||
) {}
|
||||
|
||||
async ngOnInit () {
|
||||
async ngOnInit() {
|
||||
await this.getMetrics()
|
||||
let headersCount = 0
|
||||
let rowsCount = 0
|
||||
@@ -36,11 +36,11 @@ export class ServerMetricsPage {
|
||||
this.loading = false
|
||||
}
|
||||
|
||||
ngOnDestroy () {
|
||||
ngOnDestroy() {
|
||||
this.stopDaemon()
|
||||
}
|
||||
|
||||
private async startDaemon (): Promise<void> {
|
||||
private async startDaemon(): Promise<void> {
|
||||
this.going = true
|
||||
while (this.going) {
|
||||
const startTime = Date.now()
|
||||
@@ -49,20 +49,20 @@ export class ServerMetricsPage {
|
||||
}
|
||||
}
|
||||
|
||||
private stopDaemon () {
|
||||
private stopDaemon() {
|
||||
this.going = false
|
||||
}
|
||||
|
||||
private async getMetrics (): Promise<void> {
|
||||
private async getMetrics(): Promise<void> {
|
||||
try {
|
||||
this.metrics = await this.embassyApi.getServerMetrics({ })
|
||||
this.metrics = await this.embassyApi.getServerMetrics({})
|
||||
} catch (e) {
|
||||
this.errToast.present(e)
|
||||
this.stopDaemon()
|
||||
}
|
||||
}
|
||||
|
||||
asIsOrder (a: any, b: any) {
|
||||
asIsOrder(a: any, b: any) {
|
||||
return 0
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,9 +3,8 @@ import { CommonModule } from '@angular/common'
|
||||
import { IonicModule } from '@ionic/angular'
|
||||
import { RouterModule, Routes } from '@angular/router'
|
||||
import { ServerShowPage } from './server-show.page'
|
||||
import { StatusComponentModule } from 'src/app/components/status/status.component.module'
|
||||
import { FormsModule } from '@angular/forms'
|
||||
import { SharingModule } from 'src/app/modules/sharing.module'
|
||||
import { TextSpinnerComponentModule } from '@start9labs/shared'
|
||||
import { BadgeMenuComponentModule } from 'src/app/components/badge-menu-button/badge-menu.component.module'
|
||||
|
||||
const routes: Routes = [
|
||||
@@ -19,12 +18,11 @@ const routes: Routes = [
|
||||
imports: [
|
||||
CommonModule,
|
||||
FormsModule,
|
||||
StatusComponentModule,
|
||||
IonicModule,
|
||||
RouterModule.forChild(routes),
|
||||
SharingModule,
|
||||
TextSpinnerComponentModule,
|
||||
BadgeMenuComponentModule,
|
||||
],
|
||||
declarations: [ServerShowPage],
|
||||
})
|
||||
export class ServerShowPageModule { }
|
||||
export class ServerShowPageModule {}
|
||||
|
||||
@@ -10,13 +10,13 @@ import { ApiService } from 'src/app/services/api/embassy-api.service'
|
||||
import { ActivatedRoute } from '@angular/router'
|
||||
import { ErrorToastService } from 'src/app/services/error-toast.service'
|
||||
import { PatchDbService } from 'src/app/services/patch-db/patch-db.service'
|
||||
import { ServerStatus } from 'src/app/services/patch-db/data-model'
|
||||
import { Observable, of } from 'rxjs'
|
||||
import { filter, map, take } from 'rxjs/operators'
|
||||
import { WizardBaker } from 'src/app/components/install-wizard/prebaked-wizards'
|
||||
import { wizardModal } from 'src/app/components/install-wizard/install-wizard.component'
|
||||
import { exists, isEmptyObject } from 'src/app/util/misc.util'
|
||||
import { exists, isEmptyObject } from '@start9labs/shared'
|
||||
import { EOSService } from 'src/app/services/eos.service'
|
||||
import { ServerStatus } from 'src/app/services/patch-db/data-model'
|
||||
|
||||
@Component({
|
||||
selector: 'server-show',
|
||||
|
||||
@@ -3,7 +3,7 @@ import { CommonModule } from '@angular/common'
|
||||
import { Routes, RouterModule } from '@angular/router'
|
||||
import { IonicModule } from '@ionic/angular'
|
||||
import { ServerSpecsPage } from './server-specs.page'
|
||||
import { SharingModule } from 'src/app/modules/sharing.module'
|
||||
import { EmverPipesModule } from '@start9labs/shared'
|
||||
|
||||
const routes: Routes = [
|
||||
{
|
||||
@@ -17,8 +17,8 @@ const routes: Routes = [
|
||||
CommonModule,
|
||||
IonicModule,
|
||||
RouterModule.forChild(routes),
|
||||
SharingModule,
|
||||
EmverPipesModule,
|
||||
],
|
||||
declarations: [ServerSpecsPage],
|
||||
})
|
||||
export class ServerSpecsPageModule { }
|
||||
export class ServerSpecsPageModule {}
|
||||
|
||||
@@ -3,7 +3,7 @@ import { CommonModule } from '@angular/common'
|
||||
import { IonicModule } from '@ionic/angular'
|
||||
import { RouterModule, Routes } from '@angular/router'
|
||||
import { SessionsPage } from './sessions.page'
|
||||
import { SharingModule } from 'src/app/modules/sharing.module'
|
||||
import { SharedPipesModule } from '@start9labs/shared'
|
||||
|
||||
const routes: Routes = [
|
||||
{
|
||||
@@ -17,8 +17,8 @@ const routes: Routes = [
|
||||
CommonModule,
|
||||
IonicModule,
|
||||
RouterModule.forChild(routes),
|
||||
SharingModule,
|
||||
SharedPipesModule,
|
||||
],
|
||||
declarations: [SessionsPage],
|
||||
})
|
||||
export class SessionsPageModule { }
|
||||
export class SessionsPageModule {}
|
||||
|
||||
@@ -3,7 +3,7 @@ import { CommonModule } from '@angular/common'
|
||||
import { IonicModule } from '@ionic/angular'
|
||||
import { RouterModule, Routes } from '@angular/router'
|
||||
import { SSHKeysPage } from './ssh-keys.page'
|
||||
import { SharingModule } from 'src/app/modules/sharing.module'
|
||||
import { SharedPipesModule } from '@start9labs/shared'
|
||||
|
||||
const routes: Routes = [
|
||||
{
|
||||
@@ -17,8 +17,8 @@ const routes: Routes = [
|
||||
CommonModule,
|
||||
IonicModule,
|
||||
RouterModule.forChild(routes),
|
||||
SharingModule,
|
||||
SharedPipesModule,
|
||||
],
|
||||
declarations: [SSHKeysPage],
|
||||
})
|
||||
export class SSHKeysPageModule { }
|
||||
export class SSHKeysPageModule {}
|
||||
|
||||
@@ -3,7 +3,7 @@ import { CommonModule } from '@angular/common'
|
||||
import { IonicModule } from '@ionic/angular'
|
||||
import { RouterModule, Routes } from '@angular/router'
|
||||
import { WifiPage } from './wifi.page'
|
||||
import { SharingModule } from 'src/app/modules/sharing.module'
|
||||
import { SharedPipesModule } from '@start9labs/shared'
|
||||
|
||||
const routes: Routes = [
|
||||
{
|
||||
@@ -17,8 +17,8 @@ const routes: Routes = [
|
||||
CommonModule,
|
||||
IonicModule,
|
||||
RouterModule.forChild(routes),
|
||||
SharingModule,
|
||||
SharedPipesModule,
|
||||
],
|
||||
declarations: [WifiPage],
|
||||
})
|
||||
export class WifiPageModule { }
|
||||
export class WifiPageModule {}
|
||||
|
||||
@@ -12,7 +12,7 @@ import { ActionSheetButton } from '@ionic/core'
|
||||
import { ErrorToastService } from 'src/app/services/error-toast.service'
|
||||
import { ValueSpecObject } from 'src/app/pkg-config/config-types'
|
||||
import { RR } from 'src/app/services/api/api.types'
|
||||
import { pauseFor } from 'src/app/util/misc.util'
|
||||
import { pauseFor } from '@start9labs/shared'
|
||||
import { GenericFormPage } from 'src/app/modals/generic-form/generic-form.page'
|
||||
import { ConfigService } from 'src/app/services/config.service'
|
||||
|
||||
|
||||
Reference in New Issue
Block a user