diff --git a/setup-wizard/.eslintrc.json b/setup-wizard/.eslintrc.json index 58fd208e7..af24a1991 100644 --- a/setup-wizard/.eslintrc.json +++ b/setup-wizard/.eslintrc.json @@ -5,37 +5,11 @@ { "files": ["*.ts"], "parserOptions": { - "project": ["tsconfig.json", "e2e/tsconfig.json"], + "project": ["tsconfig.json"], "createDefaultProgram": true }, - "extends": [ - "plugin:@angular-eslint/ng-cli-compat", - "plugin:@angular-eslint/ng-cli-compat--formatting-add-on", - "plugin:@angular-eslint/template/process-inline-templates" - ], "rules": { - "@angular-eslint/component-class-suffix": [ - "error", - { - "suffixes": ["Page", "Component"] - } - ], - "@angular-eslint/component-selector": [ - "error", - { - "type": "element", - "prefix": "app", - "style": "kebab-case" - } - ], - "@angular-eslint/directive-selector": [ - "error", - { - "type": "attribute", - "prefix": "app", - "style": "camelCase" - } - ] + "semi": [1, "never"] } }, { diff --git a/setup-wizard/.gitignore b/setup-wizard/.gitignore index 416fc4c1f..f974d7023 100644 --- a/setup-wizard/.gitignore +++ b/setup-wizard/.gitignore @@ -12,6 +12,7 @@ Thumbs.db UserInterfaceState.xcuserstate $RECYCLE.BIN/ +/out-tsc *.log log.txt diff --git a/setup-wizard/src/app/app-routing.module.ts b/setup-wizard/src/app/app-routing.module.ts index 611c83da7..c27caee53 100644 --- a/setup-wizard/src/app/app-routing.module.ts +++ b/setup-wizard/src/app/app-routing.module.ts @@ -10,15 +10,6 @@ const routes: Routes = [ path: 'recover', loadChildren: () => import('./pages/recover/recover.module').then( m => m.RecoverPageModule) }, - { - path: 'password', - loadChildren: () => import('./pages/password/password.module').then( m => m.PasswordPageModule) - }, - { - path: '', - redirectTo: 'wizard', - pathMatch: 'full' - }, ]; @NgModule({ diff --git a/setup-wizard/src/app/app.component.html b/setup-wizard/src/app/app.component.html index 16b638002..7137586b3 100644 --- a/setup-wizard/src/app/app.component.html +++ b/setup-wizard/src/app/app.component.html @@ -3,9 +3,6 @@

Connecting to Embassy

- -

{{ error }}

-
- +
diff --git a/setup-wizard/src/app/app.component.ts b/setup-wizard/src/app/app.component.ts index f9fdd1fe7..805795e70 100644 --- a/setup-wizard/src/app/app.component.ts +++ b/setup-wizard/src/app/app.component.ts @@ -1,20 +1,20 @@ -import { Component } from '@angular/core'; -import { NavController, ToastController } from '@ionic/angular'; -import { ApiService } from './services/api/api.service'; -import { StateService } from './services/state.service'; +import { Component, OnInit } from '@angular/core' +import { NavController, ToastController } from '@ionic/angular' +import { ApiService } from './services/api/api.service' +import { StateService } from './services/state.service' @Component({ selector: 'app-root', templateUrl: 'app.component.html', styleUrls: ['app.component.scss'], }) -export class AppComponent { +export class AppComponent implements OnInit { constructor( private readonly apiService: ApiService, private readonly stateService: StateService, private readonly navCtrl: NavController, - public toastController: ToastController + private readonly toastController: ToastController ) { this.apiService.watchError$.subscribe(error => { if(error) { @@ -25,12 +25,10 @@ export class AppComponent { async ngOnInit() { await this.stateService.getState() - if (!this.stateService.selectedDataDrive) { - await this.navCtrl.navigateForward(`/wizard`) - } else if(this.stateService.hasPassword) { - //redirect to embassyOS - } else if (this.stateService.recoveryDrive) { + if (this.stateService.recoveryDrive) { await this.navCtrl.navigateForward(`/recover`) + } else { + await this.navCtrl.navigateForward(`/wizard`) } } @@ -45,9 +43,9 @@ export class AppComponent { role: 'cancel', } ] - }); - await toast.present(); + }) + await toast.present() - await toast.onDidDismiss(); + await toast.onDidDismiss() } } diff --git a/setup-wizard/src/app/pages/home/home.module.ts b/setup-wizard/src/app/pages/home/home.module.ts index a554f017a..8bf044c75 100644 --- a/setup-wizard/src/app/pages/home/home.module.ts +++ b/setup-wizard/src/app/pages/home/home.module.ts @@ -3,6 +3,7 @@ import { CommonModule } from '@angular/common'; import { IonicModule } from '@ionic/angular'; import { FormsModule } from '@angular/forms'; import { HomePage } from './home.page'; +import { PasswordPageModule } from '../password/password.module'; import { HomePageRoutingModule } from './home-routing.module'; @@ -12,7 +13,8 @@ import { HomePageRoutingModule } from './home-routing.module'; CommonModule, FormsModule, IonicModule, - HomePageRoutingModule + HomePageRoutingModule, + PasswordPageModule, ], declarations: [HomePage] }) diff --git a/setup-wizard/src/app/pages/home/home.page.html b/setup-wizard/src/app/pages/home/home.page.html index 4f3fed8d6..ba8e793d1 100644 --- a/setup-wizard/src/app/pages/home/home.page.html +++ b/setup-wizard/src/app/pages/home/home.page.html @@ -6,17 +6,17 @@ -
+

Select Data Drive

- {{drive["logical-name"]}} + {{drive.logicalname}} {{drive.labels}} @@ -26,7 +26,7 @@ Next
-
+
{ - await this.chooseDisk() + await this.chooseDrive() } } ] @@ -59,30 +60,38 @@ export class HomePage { await alert.present(); } - async chooseDisk() { - await this.apiService.selectStorageDisk({logicalName: this.selectedDrive}) - this.stateService.selectedDataDrive = this.selectedDrive + async chooseDrive() { + await this.apiService.selectDataDrive(this.selectedDrive.logicalname) + this.stateService.dataDrive = this.selectedDrive } async presentPasswordModal() { const modal = await this.modalController.create({ component: PasswordPage, - backdropDismiss: false, - componentProps: { - 'version': null, - } + backdropDismiss: false }) modal.onDidDismiss().then(ret => { - if(ret.data.pwValid) { - this.submitPassword(ret.data.password) + const pass = ret.data.password + if (pass) { + this.submitPassword(pass) } }) await modal.present(); } async submitPassword (pw: string) { - await this.apiService.submitPassword(pw) - // @TODO navigate to embassyOS + const loader = await this.loadingCtrl.create({ + message: 'Setting up your Embassy' + }) + await loader.present() + + try { + await this.apiService.submitPassword(pw) + location.reload() + } catch (e) { + } finally { + loader.dismiss() + } } } diff --git a/setup-wizard/src/app/pages/password/password.page.html b/setup-wizard/src/app/pages/password/password.page.html index ce7b497c8..8502de71e 100644 --- a/setup-wizard/src/app/pages/password/password.page.html +++ b/setup-wizard/src/app/pages/password/password.page.html @@ -6,12 +6,12 @@ -
+

Enter Password

Password:
-
+

Create Password

Password: Verify Password: diff --git a/setup-wizard/src/app/pages/password/password.page.ts b/setup-wizard/src/app/pages/password/password.page.ts index 051f0477c..b3185ca8e 100644 --- a/setup-wizard/src/app/pages/password/password.page.ts +++ b/setup-wizard/src/app/pages/password/password.page.ts @@ -1,5 +1,6 @@ import { Component, Input } from '@angular/core' import { ModalController } from '@ionic/angular' +import { RecoveryDrive } from 'src/app/services/api/api.service' @Component({ selector: 'password', @@ -7,9 +8,9 @@ import { ModalController } from '@ionic/angular' styleUrls: ['password.page.scss'], }) export class PasswordPage { - @Input() version: string | null + @Input() recoveryDrive: RecoveryDrive - needsVer = true + needsVer: boolean error = '' password = '' @@ -20,27 +21,20 @@ export class PasswordPage { ) {} ngOnInit() { - this.needsVer = !this.version?.startsWith('0.3') - console.log('needs', this.needsVer) + this.needsVer = !!this.recoveryDrive && !this.recoveryDrive.version.startsWith('0.2') } async submitPassword () { - if (this.needsVer && this.password !== this.passwordVer) { + if (!this.needsVer && this.password !== this.passwordVer) { this.error="*passwords dont match" } else { - this.dismiss(true) + this.modalController.dismiss({ + password: this.password, + }) } } cancel () { - this.dismiss(false) + this.modalController.dismiss() } - - dismiss(submitted: boolean) { - this.modalController.dismiss({ - pwValid: submitted, - pw: this.password - }); - } - } diff --git a/setup-wizard/src/app/pages/recover/recover.module.ts b/setup-wizard/src/app/pages/recover/recover.module.ts index ffd124026..b7e75d02d 100644 --- a/setup-wizard/src/app/pages/recover/recover.module.ts +++ b/setup-wizard/src/app/pages/recover/recover.module.ts @@ -3,6 +3,7 @@ import { CommonModule } from '@angular/common'; import { IonicModule } from '@ionic/angular'; import { FormsModule } from '@angular/forms'; import { RecoverPage } from './recover.page'; +import { PasswordPageModule } from '../password/password.module'; import { RecoverPageRoutingModule } from './recover-routing.module'; @@ -12,7 +13,8 @@ import { RecoverPageRoutingModule } from './recover-routing.module'; CommonModule, FormsModule, IonicModule, - RecoverPageRoutingModule + RecoverPageRoutingModule, + PasswordPageModule, ], declarations: [RecoverPage] }) diff --git a/setup-wizard/src/app/pages/recover/recover.page.html b/setup-wizard/src/app/pages/recover/recover.page.html index b7a6d1c9e..7ea070ea8 100644 --- a/setup-wizard/src/app/pages/recover/recover.page.html +++ b/setup-wizard/src/app/pages/recover/recover.page.html @@ -7,16 +7,16 @@
-

Select Data Drive

+

Select Recovery Drive

- {{drive["logical-name"]}} + {{drive.logicalname}} {{drive.name}} @@ -24,15 +24,15 @@ Currently running {{drive.version}} - Next + Next
-

Progress: {{ 100 * stateService.dataProgress }}%

+

Progress: {{ 100 * stateService.dataProgress }}%

Go To Embassy diff --git a/setup-wizard/src/app/pages/recover/recover.page.ts b/setup-wizard/src/app/pages/recover/recover.page.ts index 730e0a412..3c795d1b6 100644 --- a/setup-wizard/src/app/pages/recover/recover.page.ts +++ b/setup-wizard/src/app/pages/recover/recover.page.ts @@ -1,6 +1,6 @@ import { Component } from '@angular/core' -import { AlertController, ModalController } from '@ionic/angular' -import { ApiService, EmbassyDrive } from 'src/app/services/api/api.service' +import { AlertController, ModalController, LoadingController } from '@ionic/angular' +import { ApiService, RecoveryDrive } from 'src/app/services/api/api.service' import { StateService } from 'src/app/services/state.service' import { PasswordPage } from '../password/password.page' @@ -11,62 +11,33 @@ import { PasswordPage } from '../password/password.page' }) export class RecoverPage { dataDrives = [] - selectedDrive = null - selectedVersion = null + selectedDrive: RecoveryDrive = null constructor( private readonly apiService: ApiService, private readonly stateService: StateService, public alertController: AlertController, private modalController: ModalController, + private readonly loadingCtrl: LoadingController, ) {} async ngOnInit() { if(!this.stateService.recoveryDrive) { - this.dataDrives = await this.apiService.getEmbassyDrives() + this.dataDrives = await this.apiService.getRecoveryDrives() } else { this.stateService.pollDataTransferProgress() } } - selectDrive(disk: EmbassyDrive) { - const name = disk['logical-name'] - const version = disk.version - if (name === this.selectedDrive) { + selectDrive(drive: RecoveryDrive) { + if (drive.logicalname === this.selectedDrive?.logicalname) { this.selectedDrive = null - this.selectedVersion = null } else { - this.selectedDrive = name - this.selectedVersion = version + this.selectedDrive = drive } } - async warn() { - const alert = await this.alertController.create({ - cssClass: 'my-custom-class', - header: 'Warning!', - message: 'Once you select this the recovery process will begin.', - buttons: [ - { - text: 'Cancel', - role: 'cancel', - cssClass: 'secondary', - handler: () => { - this.selectedDrive = null - } - }, { - text: 'Okay', - handler: async () => { - await this.chooseDisk() - } - } - ] - }); - - await alert.present(); - } - - async chooseDisk() { + async chooseDrive() { this.presentPasswordModal() } @@ -75,25 +46,38 @@ export class RecoverPage { component: PasswordPage, backdropDismiss: false, componentProps: { - 'version': this.selectedVersion, + recoveryDrive: this.selectedDrive, } }) modal.onDidDismiss().then(ret => { - if(ret.data.pwValid) { - this.submitPWAndDisk(ret.data.password) + const pass = ret.data.password + if(pass) { + this.submitPWAndDrive(pass) } }) await modal.present(); } - async submitPWAndDisk(pw: string) { - await this.apiService.selectEmbassyDrive({logicalName: this.selectedDrive}, pw) - this.stateService.recoveryDrive = this.selectedDrive - this.stateService.pollDataTransferProgress() + async submitPWAndDrive(pw: string) { + const loader = await this.loadingCtrl.create({ + message: 'Validating password' + }) + await loader.present() + + try { + await this.apiService.selectRecoveryDrive(this.selectedDrive.logicalname, pw) + this.stateService.recoveryDrive = this.selectedDrive + this.stateService.pollDataTransferProgress() + } catch (e) { + } finally { + loader.dismiss() + } + + } async navToEmbassy() { - // @TODO nav to embassy + location.reload() } } diff --git a/setup-wizard/src/app/services/api/api.service.ts b/setup-wizard/src/app/services/api/api.service.ts index c9a77ce00..701d9a299 100644 --- a/setup-wizard/src/app/services/api/api.service.ts +++ b/setup-wizard/src/app/services/api/api.service.ts @@ -1,37 +1,36 @@ -import { Subject } from "rxjs"; +import { Subject } from 'rxjs' export abstract class ApiService { - protected error$: Subject = new Subject() - watchError$ = this.error$.asObservable() - abstract getState (): Promise - abstract getStorageDisks (): Promise - abstract selectStorageDisk (disk: { logicalName: string }): Promise - abstract getEmbassyDrives (): Promise - abstract selectEmbassyDrive (disk: { logicalName: string }, password: string): Promise - abstract getDataTransferProgress () : Promise - abstract submitPassword (password: string) : Promise + protected error$: Subject = new Subject(); + watchError$ = this.error$.asObservable(); + abstract getState (): Promise; + abstract getDataDrives (): Promise; + abstract selectDataDrive (logicalName: string): Promise; + abstract getRecoveryDrives (): Promise; + abstract selectRecoveryDrive (logicalName: string, password: string): Promise; + abstract getDataTransferProgress (): Promise; + abstract submitPassword (password: string): Promise; } export interface State { - 'selected-data-drive': string | null, - 'recovery-drive': string | null, - 'has-password': boolean, + 'data-drive': DataDrive | null; + 'recovery-drive': RecoveryDrive | null; } export interface TransferProgress { - 'bytes-transfered': number - 'total-bytes': number + 'bytes-transfered': number; + 'total-bytes': number; } -export interface StorageDisk { - "logical-name": string - labels: string[] - capacity: number - used: number +export interface DataDrive { + logicalname: string; + labels: string[]; + capacity: number; + used: number; } -export interface EmbassyDrive { - "logical-name": string - version: string - name: string -} \ No newline at end of file +export interface RecoveryDrive { + logicalname: string; + version: string; + name: string; +} diff --git a/setup-wizard/src/app/services/api/mock-api.service.ts b/setup-wizard/src/app/services/api/mock-api.service.ts index ac154acd5..ea9042c2e 100644 --- a/setup-wizard/src/app/services/api/mock-api.service.ts +++ b/setup-wizard/src/app/services/api/mock-api.service.ts @@ -1,26 +1,36 @@ -import { Injectable } from "@angular/core"; -import { pauseFor } from "../state.service"; -import { ApiService } from "./api.service" +import { Injectable } from '@angular/core' +import { pauseFor } from '../state.service' +import { ApiService } from './api.service' @Injectable({ providedIn: 'root' }) export class MockApiService extends ApiService { - constructor () { + constructor() { super() } - async getState () { + async getState() { + await pauseFor(2000) return { - 'selected-data-drive': 'page1', + 'data-drive': null, + // { + // logicalname: 'name1', + // labels: ['label 1', 'label 2'], + // capacity: 1600, + // used: 200, + // }, 'recovery-drive': null, - 'has-password': false, - 'data-transfer-progress': null + // { + // logicalname: 'name1', + // version: '0.3.3', + // name: 'My Embassy' + // } } } - async getDataTransferProgress () { + async getDataTransferProgress() { tries = Math.min(tries + 1, 4) return { 'bytes-transfered': tries, @@ -28,17 +38,17 @@ export class MockApiService extends ApiService { } } - async getStorageDisks () { + async getDataDrives() { await pauseFor(2000) return [ { - "logical-name": 'name1', + logicalname: 'name1', labels: ['label 1', 'label 2'], capacity: 1600, used: 200, }, { - "logical-name": 'name2', + logicalname: 'name2', labels: [], capacity: 1600, used: 0, @@ -46,31 +56,31 @@ export class MockApiService extends ApiService { ] } - async selectStorageDisk(disk) { - await pauseFor(200) + async selectDataDrive(drive) { + await pauseFor(2000) return } - async getEmbassyDrives () { + async getRecoveryDrives() { await pauseFor(2000) return [ { - "logical-name": 'name1', - version: '0.2.3', - name: 'Embassy 0.2.3' + logicalname: 'name1', + version: '0.3.3', + name: 'My Embassy' } ] } - async selectEmbassyDrive(disk) { - await pauseFor(200) + async selectRecoveryDrive(logicalName, password) { + await pauseFor(2000) return } async submitPassword(password) { - await pauseFor(200) + await pauseFor(2000) return } } -let tries = 2 \ No newline at end of file +let tries = 0 diff --git a/setup-wizard/src/app/services/state.service.ts b/setup-wizard/src/app/services/state.service.ts index 81b7badcc..f0fd4a7f2 100644 --- a/setup-wizard/src/app/services/state.service.ts +++ b/setup-wizard/src/app/services/state.service.ts @@ -1,38 +1,37 @@ -import { Injectable } from "@angular/core"; -import { ApiService } from "./api/api.service" +import { Injectable } from '@angular/core' +import { ApiService, DataDrive, RecoveryDrive } from './api/api.service' @Injectable({ providedIn: 'root' }) export class StateService { - loading = true + loading = true; - selectedDataDrive: string - recoveryDrive: string - hasPassword: Boolean - dataTransferProgress: { bytesTransfered: number, totalBytes: number } | null - dataProgress = 0 + dataDrive: DataDrive; + recoveryDrive: RecoveryDrive; + dataTransferProgress: { bytesTransfered: number; totalBytes: number } | null; + dataProgress = 0; - constructor ( + constructor( private readonly apiService: ApiService ) {} - async getState () { + async getState() { const state = await this.apiService.getState() if(state) { - this.selectedDataDrive = state['selected-data-drive'] + this.dataDrive = state['data-drive'] this.recoveryDrive = state['recovery-drive'] - this.hasPassword = state['has-password'] - + this.loading = false } } - async pollDataTransferProgress () { + async pollDataTransferProgress() { if ( - this.dataTransferProgress?.totalBytes && + this.dataTransferProgress?.totalBytes && this.dataTransferProgress.bytesTransfered === this.dataTransferProgress.totalBytes ) {return } + const progress = await this.apiService.getDataTransferProgress() this.dataTransferProgress = { bytesTransfered: progress['bytes-transfered'], @@ -46,6 +45,7 @@ export class StateService { } } -export function pauseFor (ms: number): Promise { - return new Promise(resolve => setTimeout(resolve, ms)) -} \ No newline at end of file +export const pauseFor = (ms: number) => { + const promise = new Promise(resolve => setTimeout(resolve, ms)) + return promise +};