mirror of
https://github.com/Start9Labs/start-os.git
synced 2026-03-30 12:11:56 +00:00
fixing things up
This commit is contained in:
2
setup-wizard/.gitignore
vendored
2
setup-wizard/.gitignore
vendored
@@ -30,3 +30,5 @@ npm-debug.log*
|
|||||||
/platforms
|
/platforms
|
||||||
/plugins
|
/plugins
|
||||||
/www
|
/www
|
||||||
|
|
||||||
|
config.json
|
||||||
|
|||||||
25
setup-wizard/README.md
Normal file
25
setup-wizard/README.md
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
# Embassy Setup Wizard
|
||||||
|
|
||||||
|
## Instructions for running locally
|
||||||
|
|
||||||
|
**Make sure you have git, node, and npm installed**
|
||||||
|
|
||||||
|
Install Ionic
|
||||||
|
|
||||||
|
`npm i -g @ionic/cli`
|
||||||
|
|
||||||
|
Clone this repository
|
||||||
|
|
||||||
|
`git clone https://github.com/Start9Labs/embassy-os.git`
|
||||||
|
|
||||||
|
`cd embassy-os/setup-wizard`
|
||||||
|
|
||||||
|
Install dependencies
|
||||||
|
|
||||||
|
`npm i`
|
||||||
|
|
||||||
|
Copy `config-sample.json` to new file `config.json`
|
||||||
|
|
||||||
|
Start the server
|
||||||
|
|
||||||
|
`ionic serve`
|
||||||
3
setup-wizard/config-sample.json
Normal file
3
setup-wizard/config-sample.json
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
{
|
||||||
|
"useMocks": true
|
||||||
|
}
|
||||||
2760
setup-wizard/package-lock.json
generated
2760
setup-wizard/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@@ -18,7 +18,7 @@
|
|||||||
"@angular/platform-browser": "^12.2.1",
|
"@angular/platform-browser": "^12.2.1",
|
||||||
"@angular/platform-browser-dynamic": "^12.2.1",
|
"@angular/platform-browser-dynamic": "^12.2.1",
|
||||||
"@angular/router": "^12.2.1",
|
"@angular/router": "^12.2.1",
|
||||||
"@ionic/angular": "^5.6.13",
|
"@ionic/angular": "^5.7.0",
|
||||||
"rxjs": "^6.6.7",
|
"rxjs": "^6.6.7",
|
||||||
"tslib": "^2.3.1",
|
"tslib": "^2.3.1",
|
||||||
"zone.js": "^0.11.4"
|
"zone.js": "^0.11.4"
|
||||||
@@ -34,7 +34,7 @@
|
|||||||
"@angular/compiler-cli": "^12.2.1",
|
"@angular/compiler-cli": "^12.2.1",
|
||||||
"@angular/language-service": "^12.2.1",
|
"@angular/language-service": "^12.2.1",
|
||||||
"@ionic/angular-toolkit": "^4.0.0",
|
"@ionic/angular-toolkit": "^4.0.0",
|
||||||
"@types/node": "^16.6.0",
|
"@types/node": "^16.9.1",
|
||||||
"@typescript-eslint/eslint-plugin": "^4.29.1",
|
"@typescript-eslint/eslint-plugin": "^4.29.1",
|
||||||
"@typescript-eslint/parser": "^4.29.1",
|
"@typescript-eslint/parser": "^4.29.1",
|
||||||
"eslint": "^7.32.0",
|
"eslint": "^7.32.0",
|
||||||
|
|||||||
@@ -1,17 +1,15 @@
|
|||||||
import { NgModule } from '@angular/core';
|
import { NgModule } from '@angular/core'
|
||||||
import { BrowserModule } from '@angular/platform-browser';
|
import { BrowserModule } from '@angular/platform-browser'
|
||||||
import { RouteReuseStrategy } from '@angular/router';
|
import { RouteReuseStrategy } from '@angular/router'
|
||||||
import { HttpClientModule } from '@angular/common/http';
|
import { HttpClientModule } from '@angular/common/http'
|
||||||
import { ApiService } from './services/api/api.service'
|
import { ApiService } from './services/api/api.service'
|
||||||
import { MockApiService } from './services/api/mock-api.service'
|
import { MockApiService } from './services/api/mock-api.service'
|
||||||
import { LiveApiService } from './services/api/live-api.service'
|
import { LiveApiService } from './services/api/live-api.service'
|
||||||
import { HttpService } from './services/api/http.service'
|
import { HttpService } from './services/api/http.service'
|
||||||
|
import { IonicModule, IonicRouteStrategy, iosTransitionAnimation } from '@ionic/angular'
|
||||||
import { IonicModule, IonicRouteStrategy, iosTransitionAnimation } from '@ionic/angular';
|
import { AppComponent } from './app.component'
|
||||||
import * as config from './config/config'
|
import { AppRoutingModule } from './app-routing.module'
|
||||||
import { AppComponent } from './app.component';
|
const useMocks = require('../../config.json').useMocks as boolean
|
||||||
import { AppRoutingModule } from './app-routing.module';
|
|
||||||
|
|
||||||
|
|
||||||
@NgModule({
|
@NgModule({
|
||||||
declarations: [AppComponent],
|
declarations: [AppComponent],
|
||||||
@@ -30,7 +28,7 @@ import { AppRoutingModule } from './app-routing.module';
|
|||||||
{
|
{
|
||||||
provide: ApiService ,
|
provide: ApiService ,
|
||||||
useFactory: (http: HttpService) => {
|
useFactory: (http: HttpService) => {
|
||||||
if(config.config.useMocks) {
|
if (useMocks) {
|
||||||
return new MockApiService()
|
return new MockApiService()
|
||||||
} else {
|
} else {
|
||||||
return new LiveApiService(http)
|
return new LiveApiService(http)
|
||||||
|
|||||||
@@ -1,7 +0,0 @@
|
|||||||
export const config: Config = {
|
|
||||||
"useMocks": true
|
|
||||||
}
|
|
||||||
|
|
||||||
interface Config {
|
|
||||||
useMocks: boolean
|
|
||||||
}
|
|
||||||
@@ -4,9 +4,8 @@ import { IonicModule } from '@ionic/angular';
|
|||||||
import { FormsModule } from '@angular/forms';
|
import { FormsModule } from '@angular/forms';
|
||||||
import { EmbassyPage } from './embassy.page';
|
import { EmbassyPage } from './embassy.page';
|
||||||
import { PasswordPageModule } from '../password/password.module';
|
import { PasswordPageModule } from '../password/password.module';
|
||||||
|
|
||||||
import { EmbassyPageRoutingModule } from './embassy-routing.module';
|
import { EmbassyPageRoutingModule } from './embassy-routing.module';
|
||||||
|
import { PipesModule } from 'src/app/pipes/pipe.module'
|
||||||
|
|
||||||
@NgModule({
|
@NgModule({
|
||||||
imports: [
|
imports: [
|
||||||
@@ -15,6 +14,7 @@ import { EmbassyPageRoutingModule } from './embassy-routing.module';
|
|||||||
IonicModule,
|
IonicModule,
|
||||||
EmbassyPageRoutingModule,
|
EmbassyPageRoutingModule,
|
||||||
PasswordPageModule,
|
PasswordPageModule,
|
||||||
|
PipesModule,
|
||||||
],
|
],
|
||||||
declarations: [EmbassyPage]
|
declarations: [EmbassyPage]
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -9,19 +9,15 @@
|
|||||||
|
|
||||||
<ion-card color="dark">
|
<ion-card color="dark">
|
||||||
<ion-card-header class="ion-text-center" style="padding-bottom: 8px;">
|
<ion-card-header class="ion-text-center" style="padding-bottom: 8px;">
|
||||||
<ion-card-title>{{ loading ? 'Loading Embassy Drives' : 'Select Embassy Drive'}}</ion-card-title>
|
<ion-card-title>{{ loading ? 'Loading Drives' : 'Select Storage Drive'}}</ion-card-title>
|
||||||
<ion-card-subtitle>Select the drive where all your Embassy data will be stored.</ion-card-subtitle>
|
<ion-card-subtitle>Select the drive where all your Embassy data will be stored.</ion-card-subtitle>
|
||||||
</ion-card-header>
|
</ion-card-header>
|
||||||
|
|
||||||
<ion-card-content class="ion-margin">
|
<ion-card-content class="ion-margin">
|
||||||
<ng-container *ngIf="!loading && !embassyDrives.length">
|
<ng-container *ngIf="!loading && !storageDrives.length">
|
||||||
<h2 color="light">No Embassy drives found</h2>
|
<h2 color="light">No drives found</h2>
|
||||||
<p color="light">Please connect an Embassy drive to your embassy and refresh the page.</p>
|
<p color="light">Please connect an storage drive to your Embassy and refresh the page.</p>
|
||||||
<ion-button
|
<ion-button style="margin-top: 25px;" (click)="window.location.reload()" color="light">
|
||||||
(click)="window.location.reload()"
|
|
||||||
style="text-align:center"
|
|
||||||
class="claim-button"
|
|
||||||
>
|
|
||||||
Refresh
|
Refresh
|
||||||
</ion-button>
|
</ion-button>
|
||||||
</ng-container>
|
</ng-container>
|
||||||
@@ -39,13 +35,16 @@
|
|||||||
</ion-label>
|
</ion-label>
|
||||||
</ion-item>
|
</ion-item>
|
||||||
</ng-container>
|
</ng-container>
|
||||||
<ng-container *ngIf="embassyDrives.length">
|
<ng-container *ngIf="storageDrives.length">
|
||||||
<ion-item (click)="chooseDrive(drive)" class="ion-margin-bottom" button color="light" lines="none" *ngFor="let drive of embassyDrives">
|
<ion-item (click)="chooseDrive(drive)" class="ion-margin-bottom" button color="light" lines="none" *ngFor="let drive of storageDrives">
|
||||||
<ion-icon slot="start" name="save-outline"></ion-icon>
|
<ion-icon slot="start" name="save-outline"></ion-icon>
|
||||||
<ion-label class="ion-text-wrap">
|
<ion-label class="ion-text-wrap">
|
||||||
<h1>{{ drive.logicalname }}</h1>
|
<h1>{{ drive.logicalname }} - {{ drive.capacity | convertBytes }}</h1>
|
||||||
<h2 style="min-height: 19px;">{{ getLabel(drive) }}</h2>
|
<h2 *ngIf="drive.vendor || drive.model">
|
||||||
<p> Using {{ getUsage(drive) }} of {{drive.capacity.toFixed(2)}} GiB</p>
|
{{ drive.vendor }}
|
||||||
|
<span *ngIf="drive.vendor && drive.model"> - </span>
|
||||||
|
{{ drive.model }}
|
||||||
|
</h2>
|
||||||
</ion-label>
|
</ion-label>
|
||||||
</ion-item>
|
</ion-item>
|
||||||
</ng-container>
|
</ng-container>
|
||||||
|
|||||||
@@ -7,38 +7,4 @@ ion-card-title {
|
|||||||
font-family: 'Montserrat';
|
font-family: 'Montserrat';
|
||||||
font-size: x-large;
|
font-size: x-large;
|
||||||
--color: var(--ion-color-light);
|
--color: var(--ion-color-light);
|
||||||
}
|
|
||||||
|
|
||||||
// ion-item {
|
|
||||||
// --border-radius: 4px;
|
|
||||||
// --border-style: solid;
|
|
||||||
// --border-width: 1px;
|
|
||||||
// --border-color: var(--ion-color-light);
|
|
||||||
// }
|
|
||||||
|
|
||||||
.input-label {
|
|
||||||
text-align: left;
|
|
||||||
padding-bottom: 2px;
|
|
||||||
font-size: small;
|
|
||||||
color: var(--ion-color-light);
|
|
||||||
font-weight: bold;
|
|
||||||
}
|
|
||||||
|
|
||||||
.claim-button {
|
|
||||||
margin-inline-start: 0;
|
|
||||||
margin-inline-end: 0;
|
|
||||||
margin-top: 24px;
|
|
||||||
height: 48px;
|
|
||||||
--background: linear-gradient(45deg, var(--ion-color-light) 16%, var(--ion-color-medium) 150%);
|
|
||||||
}
|
|
||||||
|
|
||||||
.card-footer {
|
|
||||||
text-align: left;
|
|
||||||
--background: rgb(222, 222, 222);
|
|
||||||
border-top: solid;
|
|
||||||
border-width: 1px;
|
|
||||||
border-color: var(--ion-color-medium);
|
|
||||||
ion-item {
|
|
||||||
--border-color: var(--ion-color-medium);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
import { Component } from '@angular/core'
|
import { Component } from '@angular/core'
|
||||||
import { iosTransitionAnimation, LoadingController, ModalController, NavController } from '@ionic/angular'
|
import { AlertController, iosTransitionAnimation, LoadingController, ModalController, NavController } from '@ionic/angular'
|
||||||
import { ApiService, DiskInfo } from 'src/app/services/api/api.service'
|
import { ApiService, DiskInfo } from 'src/app/services/api/api.service'
|
||||||
import { StateService } from 'src/app/services/state.service'
|
import { StateService } from 'src/app/services/state.service'
|
||||||
import { PasswordPage } from '../password/password.page'
|
import { PasswordPage } from '../password/password.page'
|
||||||
@@ -10,7 +10,7 @@ import { PasswordPage } from '../password/password.page'
|
|||||||
styleUrls: ['embassy.page.scss'],
|
styleUrls: ['embassy.page.scss'],
|
||||||
})
|
})
|
||||||
export class EmbassyPage {
|
export class EmbassyPage {
|
||||||
embassyDrives = []
|
storageDrives = []
|
||||||
selectedDrive: DiskInfo = null
|
selectedDrive: DiskInfo = null
|
||||||
loading = true
|
loading = true
|
||||||
window = window
|
window = window
|
||||||
@@ -18,23 +18,48 @@ export class EmbassyPage {
|
|||||||
constructor(
|
constructor(
|
||||||
private readonly apiService: ApiService,
|
private readonly apiService: ApiService,
|
||||||
private readonly navCtrl: NavController,
|
private readonly navCtrl: NavController,
|
||||||
private modalController: ModalController,
|
private readonly modalController: ModalController,
|
||||||
private stateService: StateService,
|
private readonly alertCtrl: AlertController,
|
||||||
private loadingCtrl: LoadingController
|
private readonly stateService: StateService,
|
||||||
) {}
|
private readonly loadingCtrl: LoadingController,
|
||||||
|
) { }
|
||||||
|
|
||||||
async ngOnInit() {
|
async ngOnInit () {
|
||||||
const drives = (await this.apiService.getDrives()).filter(d => !d['embassy_os'])
|
this.storageDrives = await this.apiService.getDrives()
|
||||||
this.embassyDrives = (await this.apiService.getDrives()).filter(d => !d['embassy_os'])
|
|
||||||
this.loading = false
|
this.loading = false
|
||||||
}
|
}
|
||||||
|
|
||||||
async chooseDrive(drive: DiskInfo) {
|
async chooseDrive (drive: DiskInfo) {
|
||||||
|
if (!!drive.partitions.find(p => p.used)) {
|
||||||
|
const alert = await this.alertCtrl.create({
|
||||||
|
header: 'Warning',
|
||||||
|
subHeader: 'Drive contains data!',
|
||||||
|
message: 'All data stored on this drive will be permanently deleted.',
|
||||||
|
buttons: [
|
||||||
|
{
|
||||||
|
role: 'cancel',
|
||||||
|
text: 'Cancel',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
text: 'Continue',
|
||||||
|
handler: () => {
|
||||||
|
this.presentModalPassword(drive)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
})
|
||||||
|
await alert.present()
|
||||||
|
} else {
|
||||||
|
this.presentModalPassword(drive)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private async presentModalPassword (drive: DiskInfo): Promise<void> {
|
||||||
const modal = await this.modalController.create({
|
const modal = await this.modalController.create({
|
||||||
component: PasswordPage,
|
component: PasswordPage,
|
||||||
componentProps: {
|
componentProps: {
|
||||||
embassyDrive: drive
|
storageDrive: drive
|
||||||
}
|
},
|
||||||
})
|
})
|
||||||
modal.onDidDismiss().then(async ret => {
|
modal.onDidDismiss().then(async ret => {
|
||||||
if (!ret.data || !ret.data.password) return
|
if (!ret.data || !ret.data.password) return
|
||||||
@@ -45,13 +70,13 @@ export class EmbassyPage {
|
|||||||
|
|
||||||
await loader.present()
|
await loader.present()
|
||||||
|
|
||||||
this.stateService.embassyDrive = drive
|
this.stateService.storageDrive = drive
|
||||||
this.stateService.embassyPassword = ret.data.password
|
this.stateService.embassyPassword = ret.data.password
|
||||||
|
|
||||||
try {
|
try {
|
||||||
this.stateService.torAddress = (await this.stateService.setupEmbassy()).torAddress
|
this.stateService.torAddress = (await this.stateService.setupEmbassy()).torAddress
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.log(e.message)
|
console.error(e.message)
|
||||||
} finally {
|
} finally {
|
||||||
loader.dismiss()
|
loader.dismiss()
|
||||||
if(!!this.stateService.recoveryDrive) {
|
if(!!this.stateService.recoveryDrive) {
|
||||||
@@ -61,21 +86,6 @@ export class EmbassyPage {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
await modal.present();
|
await modal.present()
|
||||||
}
|
|
||||||
|
|
||||||
getLabel(drive: DiskInfo) {
|
|
||||||
const labels = drive.partitions.map(p => p.label).filter(l => !!l)
|
|
||||||
return labels.length ? labels.join(' / ') : 'unnamed'
|
|
||||||
}
|
|
||||||
|
|
||||||
getUsage(drive: DiskInfo) {
|
|
||||||
let usage = 0
|
|
||||||
drive.partitions.forEach(par => {
|
|
||||||
if(par.used) {
|
|
||||||
usage += par.used
|
|
||||||
}
|
|
||||||
})
|
|
||||||
return usage.toFixed(2)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,31 +13,4 @@ ion-item {
|
|||||||
--border-style: solid;
|
--border-style: solid;
|
||||||
--border-width: 1px;
|
--border-width: 1px;
|
||||||
--border-color: var(--ion-color-light);
|
--border-color: var(--ion-color-light);
|
||||||
}
|
|
||||||
|
|
||||||
.input-label {
|
|
||||||
text-align: left;
|
|
||||||
padding-bottom: 2px;
|
|
||||||
font-size: small;
|
|
||||||
color: var(--ion-color-light);
|
|
||||||
font-weight: bold;
|
|
||||||
}
|
|
||||||
|
|
||||||
.claim-button {
|
|
||||||
margin-inline-start: 0;
|
|
||||||
margin-inline-end: 0;
|
|
||||||
margin-top: 24px;
|
|
||||||
height: 48px;
|
|
||||||
--background: linear-gradient(45deg, var(--ion-color-light) 16%, var(--ion-color-medium) 150%);
|
|
||||||
}
|
|
||||||
|
|
||||||
.card-footer {
|
|
||||||
text-align: left;
|
|
||||||
--background: rgb(222, 222, 222);
|
|
||||||
border-top: solid;
|
|
||||||
border-width: 1px;
|
|
||||||
border-color: var(--ion-color-medium);
|
|
||||||
ion-item {
|
|
||||||
--border-color: var(--ion-color-medium);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
@@ -13,31 +13,4 @@ ion-item {
|
|||||||
--border-style: solid;
|
--border-style: solid;
|
||||||
--border-width: 1px;
|
--border-width: 1px;
|
||||||
--border-color: var(--ion-color-light);
|
--border-color: var(--ion-color-light);
|
||||||
}
|
|
||||||
|
|
||||||
.input-label {
|
|
||||||
text-align: left;
|
|
||||||
padding-bottom: 2px;
|
|
||||||
font-size: small;
|
|
||||||
color: var(--ion-color-light);
|
|
||||||
font-weight: bold;
|
|
||||||
}
|
|
||||||
|
|
||||||
.claim-button {
|
|
||||||
margin-inline-start: 0;
|
|
||||||
margin-inline-end: 0;
|
|
||||||
margin-top: 24px;
|
|
||||||
height: 48px;
|
|
||||||
--background: linear-gradient(45deg, var(--ion-color-light) 16%, var(--ion-color-medium) 150%);
|
|
||||||
}
|
|
||||||
|
|
||||||
.card-footer {
|
|
||||||
text-align: left;
|
|
||||||
--background: rgb(222, 222, 222);
|
|
||||||
border-top: solid;
|
|
||||||
border-width: 1px;
|
|
||||||
border-color: var(--ion-color-medium);
|
|
||||||
ion-item {
|
|
||||||
--border-color: var(--ion-color-medium);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
@@ -1,25 +1,29 @@
|
|||||||
<ion-header>
|
<ion-header>
|
||||||
<ion-toolbar color="light">
|
<ion-toolbar color="light">
|
||||||
<ion-title>
|
<ion-title>
|
||||||
<span *ngIf="!!recoveryDrive">Unlock Drive</span>
|
{{ !!storageDrive ? 'Set Password' : 'Unlock Drive' }}
|
||||||
<span *ngIf="!recoveryDrive">Set Password</span>
|
|
||||||
</ion-title>
|
</ion-title>
|
||||||
</ion-toolbar>
|
</ion-toolbar>
|
||||||
</ion-header>
|
</ion-header>
|
||||||
|
|
||||||
<ion-content color="light">
|
<ion-content color="light">
|
||||||
<form (ngSubmit)="!!recoveryDrive ? verifyPw() : submitPw()">
|
<form (ngSubmit)="!!storageDrive ? submitPw() : verifyPw()">
|
||||||
<div style="padding: 8px 24px;">
|
<div style="padding: 8px 24px;">
|
||||||
<p *ngIf="!!embassyDrive">Choose a password for your embassy. You will need it every time you log in. If you lose it you will be permanently locked out of your embassy.</p>
|
<div style="padding-bottom: 16px;">
|
||||||
<p *ngIf="embassyDrive && getUsage(embassyDrive) > 0" style="padding-bottom: 15px;color: var(--ion-color-warning);"><b>Warning:</b> After submit, any data currently stored on <b>{{ getLabel(embassyDrive) }}</b> will be wiped.</p>
|
<ng-container *ngIf="!!storageDrive">
|
||||||
|
<h3>Choose a password for your Embassy. Make it good. Write it down. If you lose this password, you may be permanently locked out of your Embassy.</h3>
|
||||||
|
<p *ngIf="hasData" style="color: var(--ion-color-warning);"><b>Warning:</b> data on this drive will be permanently deleted.</p>
|
||||||
|
</ng-container>
|
||||||
|
<p *ngIf="!storageDrive">Enter the password that was used to encrypt this drive.</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
<h4 class="input-label">
|
<h4 class="password-input" *ngIf="!!storageDrive">
|
||||||
Password:
|
Password:
|
||||||
</h4>
|
</h4>
|
||||||
|
|
||||||
<ion-item
|
<ion-item
|
||||||
color="dark"
|
color="dark"
|
||||||
[class]="pwError ? 'error-border' : password && !recoveryDrive ? 'success-border' : ''"
|
[class]="pwError ? 'error-border' : password && !!storageDrive ? 'success-border' : ''"
|
||||||
>
|
>
|
||||||
<ion-input
|
<ion-input
|
||||||
[(ngModel)]="password"
|
[(ngModel)]="password"
|
||||||
@@ -34,9 +38,9 @@
|
|||||||
<ion-icon slot="icon-only" [name]="unmasked1 ? 'eye-off-outline' : 'eye-outline'" size="small"></ion-icon>
|
<ion-icon slot="icon-only" [name]="unmasked1 ? 'eye-off-outline' : 'eye-outline'" size="small"></ion-icon>
|
||||||
</ion-button>
|
</ion-button>
|
||||||
</ion-item>
|
</ion-item>
|
||||||
<p style="color: var(--ion-color-danger);">{{pwError}}</p>
|
<p style="color: var(--ion-color-danger);">{{ pwError }}</p>
|
||||||
<ng-container *ngIf="!recoveryDrive">
|
<ng-container *ngIf="!!storageDrive">
|
||||||
<h4 class="input-label">
|
<h4 class="password-input">
|
||||||
Verify Password:
|
Verify Password:
|
||||||
</h4>
|
</h4>
|
||||||
|
|
||||||
@@ -63,14 +67,14 @@
|
|||||||
|
|
||||||
<ion-footer>
|
<ion-footer>
|
||||||
<ion-toolbar color="light">
|
<ion-toolbar color="light">
|
||||||
<ion-buttons slot="end" class="ion-padding-end">
|
<!-- <ion-buttons slot="end" class="ion-padding-end"> -->
|
||||||
<ion-button color="dark" class="claim-button" (click)="cancel()">
|
<ion-button class="ion-padding-end" slot="end" color="dark" fill="clear" (click)="cancel()">
|
||||||
Cancel
|
Cancel
|
||||||
</ion-button>
|
</ion-button>
|
||||||
<ion-button color="dark" class="claim-button" (click)="!!recoveryDrive ? verifyPw() : submitPw()">
|
<ion-button class="ion-padding-end" slot="end" color="dark" fill="clear" strong="true" (click)="!!storageDrive ? submitPw() : verifyPw()">
|
||||||
{{ !!recoveryDrive ? 'Unlock' : 'Submit' }}
|
{{ !!storageDrive ? 'Finish' : 'Unlock' }}
|
||||||
</ion-button>
|
</ion-button>
|
||||||
</ion-buttons>
|
<!-- </ion-buttons> -->
|
||||||
</ion-toolbar>
|
</ion-toolbar>
|
||||||
</ion-footer>
|
</ion-footer>
|
||||||
|
|
||||||
|
|||||||
@@ -1,13 +1,5 @@
|
|||||||
.claim-button {
|
.password-input {
|
||||||
margin-inline-start: 0;
|
|
||||||
margin-inline-end: 0;
|
|
||||||
margin: 6px;
|
|
||||||
height: 48px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.input-label {
|
|
||||||
color: var(--ion-color-dark);
|
color: var(--ion-color-dark);
|
||||||
// padding-top: 10px;
|
|
||||||
margin-bottom: 6px;
|
margin-bottom: 6px;
|
||||||
font-size: medium;
|
font-size: medium;
|
||||||
font-weight: 500;
|
font-weight: 500;
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
import { Component, Input } from '@angular/core'
|
import { Component, Input } from '@angular/core'
|
||||||
import { LoadingController, ModalController } from '@ionic/angular'
|
import { LoadingController, ModalController } from '@ionic/angular'
|
||||||
import { ApiService, DiskInfo } from 'src/app/services/api/api.service'
|
import { ApiService, DiskInfo } from 'src/app/services/api/api.service'
|
||||||
import { StateService } from 'src/app/services/state.service'
|
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-password',
|
selector: 'app-password',
|
||||||
@@ -10,7 +9,7 @@ import { StateService } from 'src/app/services/state.service'
|
|||||||
})
|
})
|
||||||
export class PasswordPage {
|
export class PasswordPage {
|
||||||
@Input() recoveryDrive: DiskInfo
|
@Input() recoveryDrive: DiskInfo
|
||||||
@Input() embassyDrive: DiskInfo
|
@Input() storageDrive: DiskInfo
|
||||||
|
|
||||||
pwError = ''
|
pwError = ''
|
||||||
password = ''
|
password = ''
|
||||||
@@ -20,18 +19,22 @@ export class PasswordPage {
|
|||||||
passwordVer = ''
|
passwordVer = ''
|
||||||
unmasked2 = false
|
unmasked2 = false
|
||||||
|
|
||||||
|
hasData: boolean
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
private modalController: ModalController,
|
private modalController: ModalController,
|
||||||
private apiService: ApiService,
|
private apiService: ApiService,
|
||||||
private loadingCtrl: LoadingController,
|
private loadingCtrl: LoadingController,
|
||||||
private stateService: StateService
|
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
ngOnInit() { }
|
ngOnInit() {
|
||||||
|
if (this.storageDrive && this.storageDrive.partitions.find(p => p.used)) {
|
||||||
|
this.hasData = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
async verifyPw () {
|
async verifyPw () {
|
||||||
|
if (!this.recoveryDrive) this.pwError = 'No recovery drive' // unreachable
|
||||||
if(!this.recoveryDrive) this.pwError = 'No recovery drive' // unreachable
|
|
||||||
const loader = await this.loadingCtrl.create({
|
const loader = await this.loadingCtrl.create({
|
||||||
message: 'Verifying Password'
|
message: 'Verifying Password'
|
||||||
})
|
})
|
||||||
@@ -79,23 +82,7 @@ export class PasswordPage {
|
|||||||
this.verError = this.password !== this.passwordVer ? "*passwords do not match" : ''
|
this.verError = this.password !== this.passwordVer ? "*passwords do not match" : ''
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
cancel () {
|
cancel () {
|
||||||
this.modalController.dismiss()
|
this.modalController.dismiss()
|
||||||
}
|
}
|
||||||
|
|
||||||
getLabel(drive: DiskInfo) {
|
|
||||||
const labels = drive.partitions.map(p => p.label).filter(l => !!l)
|
|
||||||
return labels.length ? labels.join(' / ') : 'unnamed'
|
|
||||||
}
|
|
||||||
|
|
||||||
getUsage(drive: DiskInfo) {
|
|
||||||
let usage = 0
|
|
||||||
drive.partitions.forEach(par => {
|
|
||||||
if(par.used) {
|
|
||||||
usage += par.used
|
|
||||||
}
|
|
||||||
})
|
|
||||||
return usage
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -24,7 +24,7 @@
|
|||||||
<p *ngIf="error" style="padding-top: 4px"><ion-text color="danger">*{{ error }}</ion-text></p>
|
<p *ngIf="error" style="padding-top: 4px"><ion-text color="danger">*{{ error }}</ion-text></p>
|
||||||
</div>
|
</div>
|
||||||
</ion-item-group>
|
</ion-item-group>
|
||||||
<ion-button style="margin-top: 25px;" type="submit" color="light">
|
<ion-button type="submit" color="light" class="claim-button">
|
||||||
Submit
|
Submit
|
||||||
</ion-button>
|
</ion-button>
|
||||||
</form>
|
</form>
|
||||||
|
|||||||
@@ -13,31 +13,4 @@ ion-item {
|
|||||||
--border-style: solid;
|
--border-style: solid;
|
||||||
--border-width: 1px;
|
--border-width: 1px;
|
||||||
--border-color: var(--ion-color-light);
|
--border-color: var(--ion-color-light);
|
||||||
}
|
|
||||||
|
|
||||||
.input-label {
|
|
||||||
text-align: left;
|
|
||||||
padding-bottom: 2px;
|
|
||||||
font-size: small;
|
|
||||||
color: var(--ion-color-light);
|
|
||||||
font-weight: bold;
|
|
||||||
}
|
|
||||||
|
|
||||||
.claim-button {
|
|
||||||
margin-inline-start: 0;
|
|
||||||
margin-inline-end: 0;
|
|
||||||
margin-top: 24px;
|
|
||||||
height: 48px;
|
|
||||||
--background: linear-gradient(45deg, var(--ion-color-light) 16%, var(--ion-color-medium) 150%);
|
|
||||||
}
|
|
||||||
|
|
||||||
.card-footer {
|
|
||||||
text-align: left;
|
|
||||||
--background: rgb(222, 222, 222);
|
|
||||||
border-top: solid;
|
|
||||||
border-width: 1px;
|
|
||||||
border-color: var(--ion-color-medium);
|
|
||||||
ion-item {
|
|
||||||
--border-color: var(--ion-color-medium);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
@@ -4,8 +4,8 @@ import { IonicModule } from '@ionic/angular';
|
|||||||
import { FormsModule } from '@angular/forms';
|
import { FormsModule } from '@angular/forms';
|
||||||
import { RecoverPage } from './recover.page';
|
import { RecoverPage } from './recover.page';
|
||||||
import { PasswordPageModule } from '../password/password.module';
|
import { PasswordPageModule } from '../password/password.module';
|
||||||
|
|
||||||
import { RecoverPageRoutingModule } from './recover-routing.module';
|
import { RecoverPageRoutingModule } from './recover-routing.module';
|
||||||
|
import { PipesModule } from 'src/app/pipes/pipe.module';
|
||||||
|
|
||||||
|
|
||||||
@NgModule({
|
@NgModule({
|
||||||
@@ -15,6 +15,7 @@ import { RecoverPageRoutingModule } from './recover-routing.module';
|
|||||||
IonicModule,
|
IonicModule,
|
||||||
RecoverPageRoutingModule,
|
RecoverPageRoutingModule,
|
||||||
PasswordPageModule,
|
PasswordPageModule,
|
||||||
|
PipesModule,
|
||||||
],
|
],
|
||||||
declarations: [RecoverPage]
|
declarations: [RecoverPage]
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -10,13 +10,14 @@
|
|||||||
<ion-card color="dark">
|
<ion-card color="dark">
|
||||||
<ion-card-header class="ion-text-center" style="padding-bottom: 8px;">
|
<ion-card-header class="ion-text-center" style="padding-bottom: 8px;">
|
||||||
<ion-card-title>{{ loading ? 'Loading Recovery Drives' : 'Select Recovery Drive'}}</ion-card-title>
|
<ion-card-title>{{ loading ? 'Loading Recovery Drives' : 'Select Recovery Drive'}}</ion-card-title>
|
||||||
|
<ion-card-subtitle>Select the drive containing the Embassy you want to recover.</ion-card-subtitle>
|
||||||
</ion-card-header>
|
</ion-card-header>
|
||||||
|
|
||||||
|
|
||||||
<ion-card-content class="ion-margin">
|
<ion-card-content class="ion-margin">
|
||||||
<ng-container *ngIf="!loading && !recoveryDrives.length">
|
<ng-container *ngIf="!loading && !recoveryDrives.length">
|
||||||
<h2 color="light">No recovery drives found</h2>
|
<h2 color="light">No recovery drives found</h2>
|
||||||
<p color="light">Please connect a recovery drive to your embassy and refresh the page.</p>
|
<p color="light">Please connect a recovery drive to your Embassy and refresh the page.</p>
|
||||||
<ion-button
|
<ion-button
|
||||||
(click)="window.location.reload()"
|
(click)="window.location.reload()"
|
||||||
style="text-align:center"
|
style="text-align:center"
|
||||||
@@ -43,22 +44,27 @@
|
|||||||
<ion-item (click)="chooseDrive(drive)" class="ion-margin-bottom" button color="light" lines="none" *ngFor="let drive of recoveryDrives" [ngClass]="drive.logicalname === selectedDrive?.logicalname ? 'selected' : null">
|
<ion-item (click)="chooseDrive(drive)" class="ion-margin-bottom" button color="light" lines="none" *ngFor="let drive of recoveryDrives" [ngClass]="drive.logicalname === selectedDrive?.logicalname ? 'selected' : null">
|
||||||
<ion-icon slot="start" name="save-outline"></ion-icon>
|
<ion-icon slot="start" name="save-outline"></ion-icon>
|
||||||
<ion-label class="ion-text-wrap">
|
<ion-label class="ion-text-wrap">
|
||||||
<h1>{{ drive.logicalname }}</h1>
|
<h1>{{ drive.logicalname }} - {{ drive.capacity | convertBytes }}</h1>
|
||||||
<h2>{{ drive.model }}</h2>
|
<h2 *ngIf="drive.vendor || drive.model">
|
||||||
<p> Embassy version: {{drive['embassy_os'].version}}</p>
|
{{ drive.vendor }}
|
||||||
|
<span *ngIf="drive.vendor && drive.model"> - </span>
|
||||||
|
{{ drive.model }}
|
||||||
|
</h2>
|
||||||
|
<h2> Embassy version: {{drive['embassy_os'].version}}</h2>
|
||||||
</ion-label>
|
</ion-label>
|
||||||
<ion-icon *ngIf="drive['embassy_os'].version.startsWith('0.2') || passwords[drive.logicalname]" color="success" slot="end" name="lock-open-outline"></ion-icon>
|
<ion-icon *ngIf="drive['embassy_os'].version.startsWith('0.2') || passwords[drive.logicalname]" color="success" slot="end" name="lock-open-outline"></ion-icon>
|
||||||
<ion-icon *ngIf="!drive['embassy_os'].version.startsWith('0.2') && !passwords[drive.logicalname]" color="danger" slot="end" name="lock-closed-outline"></ion-icon>
|
<ion-icon *ngIf="!drive['embassy_os'].version.startsWith('0.2') && !passwords[drive.logicalname]" color="danger" slot="end" name="lock-closed-outline"></ion-icon>
|
||||||
|
|
||||||
</ion-item>
|
</ion-item>
|
||||||
</ng-container>
|
</ng-container>
|
||||||
<ion-button
|
<ion-button
|
||||||
(click)="selectRecoveryDrive()"
|
(click)="selectRecoveryDrive()"
|
||||||
[disabled]="!selectedDrive || (!passwords[selectedDrive.logicalname] && !selectedDrive['embassy_os'].version.startsWith('0.2'))"
|
color="light"
|
||||||
class="claim-button"
|
[disabled]="!selectedDrive || (!passwords[selectedDrive.logicalname] && !selectedDrive['embassy_os'].version.startsWith('0.2'))"
|
||||||
>
|
class="claim-button"
|
||||||
Next
|
>
|
||||||
</ion-button>
|
Next
|
||||||
|
</ion-button>
|
||||||
</ion-item-group>
|
</ion-item-group>
|
||||||
</ion-card-content>
|
</ion-card-content>
|
||||||
</ion-card>
|
</ion-card>
|
||||||
|
|||||||
@@ -16,31 +16,4 @@ ion-item {
|
|||||||
--border-style: solid;
|
--border-style: solid;
|
||||||
--border-width: 1px;
|
--border-width: 1px;
|
||||||
--border-color: var(--ion-color-light);
|
--border-color: var(--ion-color-light);
|
||||||
}
|
|
||||||
|
|
||||||
.input-label {
|
|
||||||
text-align: left;
|
|
||||||
padding-bottom: 2px;
|
|
||||||
font-size: small;
|
|
||||||
color: var(--ion-color-light);
|
|
||||||
font-weight: bold;
|
|
||||||
}
|
|
||||||
|
|
||||||
.claim-button {
|
|
||||||
margin-inline-start: 0;
|
|
||||||
margin-inline-end: 0;
|
|
||||||
margin-top: 24px;
|
|
||||||
height: 48px;
|
|
||||||
--background: linear-gradient(45deg, var(--ion-color-light) 16%, var(--ion-color-medium) 150%);
|
|
||||||
}
|
|
||||||
|
|
||||||
.card-footer {
|
|
||||||
text-align: left;
|
|
||||||
--background: rgb(222, 222, 222);
|
|
||||||
border-top: solid;
|
|
||||||
border-width: 1px;
|
|
||||||
border-color: var(--ion-color-medium);
|
|
||||||
ion-item {
|
|
||||||
--border-color: var(--ion-color-medium);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
@@ -19,8 +19,8 @@ export class RecoverPage {
|
|||||||
constructor(
|
constructor(
|
||||||
private readonly apiService: ApiService,
|
private readonly apiService: ApiService,
|
||||||
private readonly navCtrl: NavController,
|
private readonly navCtrl: NavController,
|
||||||
private modalController: ModalController,
|
private readonly modalController: ModalController,
|
||||||
private stateService: StateService
|
private readonly stateService: StateService
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
async ngOnInit() {
|
async ngOnInit() {
|
||||||
@@ -43,7 +43,8 @@ export class RecoverPage {
|
|||||||
component: PasswordPage,
|
component: PasswordPage,
|
||||||
componentProps: {
|
componentProps: {
|
||||||
recoveryDrive: this.selectedDrive
|
recoveryDrive: this.selectedDrive
|
||||||
}
|
},
|
||||||
|
cssClass: 'alertlike-modal',
|
||||||
})
|
})
|
||||||
modal.onDidDismiss().then(async ret => {
|
modal.onDidDismiss().then(async ret => {
|
||||||
if (!ret.data) {
|
if (!ret.data) {
|
||||||
|
|||||||
@@ -13,7 +13,7 @@
|
|||||||
</ion-card-header>
|
</ion-card-header>
|
||||||
<div class="divider"></div>
|
<div class="divider"></div>
|
||||||
<ion-card-content class="ion-margin">
|
<ion-card-content class="ion-margin">
|
||||||
<p class="input-label">Tor Address:</p>
|
<p class="addr-label">Tor Address:</p>
|
||||||
<ion-item style="--border-radius: 8px 8px 0 0 !important;" color="light">
|
<ion-item style="--border-radius: 8px 8px 0 0 !important;" color="light">
|
||||||
<ion-label>
|
<ion-label>
|
||||||
<p>{{ stateService.torAddress }}</p>
|
<p>{{ stateService.torAddress }}</p>
|
||||||
|
|||||||
@@ -15,35 +15,16 @@ ion-item {
|
|||||||
--border-color: var(--ion-color-light);
|
--border-color: var(--ion-color-light);
|
||||||
}
|
}
|
||||||
|
|
||||||
.input-label {
|
|
||||||
text-align: left;
|
|
||||||
padding-bottom: 2px;
|
|
||||||
font-size: medium;
|
|
||||||
color: var(--ion-color-light);
|
|
||||||
font-weight: bold;
|
|
||||||
}
|
|
||||||
|
|
||||||
.claim-button {
|
|
||||||
margin-inline-start: 0;
|
|
||||||
margin-inline-end: 0;
|
|
||||||
margin-top: 24px;
|
|
||||||
height: 48px;
|
|
||||||
--background: linear-gradient(45deg, var(--ion-color-light) 16%, var(--ion-color-medium) 150%);
|
|
||||||
}
|
|
||||||
|
|
||||||
.card-footer {
|
|
||||||
text-align: left;
|
|
||||||
--background: rgb(222, 222, 222);
|
|
||||||
border-top: solid;
|
|
||||||
border-width: 1px;
|
|
||||||
border-color: var(--ion-color-medium);
|
|
||||||
ion-item {
|
|
||||||
--border-color: var(--ion-color-medium);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.divider {
|
.divider {
|
||||||
margin: 0;
|
margin: 0;
|
||||||
background: linear-gradient(90deg,var(--ion-color-dark) 0,var(--ion-color-medium) 50%,var(--ion-color-dark) 100%);
|
background: linear-gradient(90deg,var(--ion-color-dark) 0,var(--ion-color-medium) 50%,var(--ion-color-dark) 100%);
|
||||||
height: 1px;
|
height: 1px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.addr-label {
|
||||||
|
text-align: left;
|
||||||
|
padding-bottom: 2px;
|
||||||
|
font-size: small;
|
||||||
|
color: var(--ion-color-light);
|
||||||
|
font-weight: bold;
|
||||||
}
|
}
|
||||||
18
setup-wizard/src/app/pipes/convert-bytes.pipe.ts
Normal file
18
setup-wizard/src/app/pipes/convert-bytes.pipe.ts
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
import { Pipe, PipeTransform } from '@angular/core'
|
||||||
|
|
||||||
|
// converts bytes to gigabytes
|
||||||
|
@Pipe({
|
||||||
|
name: 'convertBytes',
|
||||||
|
})
|
||||||
|
export class ConvertBytesPipe implements PipeTransform {
|
||||||
|
transform (bytes: number): string {
|
||||||
|
if (bytes === 0) return '0 Bytes'
|
||||||
|
|
||||||
|
const k = 1024
|
||||||
|
const sizes = ['Bytes', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB']
|
||||||
|
|
||||||
|
const i = Math.floor(Math.log(bytes) / Math.log(k))
|
||||||
|
|
||||||
|
return parseFloat((bytes / Math.pow(k, i)).toFixed(1)) + ' ' + sizes[i]
|
||||||
|
}
|
||||||
|
}
|
||||||
10
setup-wizard/src/app/pipes/pipe.module.ts
Normal file
10
setup-wizard/src/app/pipes/pipe.module.ts
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
import { NgModule } from '@angular/core';
|
||||||
|
import { ConvertBytesPipe } from './convert-bytes.pipe';
|
||||||
|
|
||||||
|
@NgModule({
|
||||||
|
declarations: [ConvertBytesPipe],
|
||||||
|
imports: [],
|
||||||
|
exports: [ConvertBytesPipe],
|
||||||
|
})
|
||||||
|
|
||||||
|
export class PipesModule {}
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
import { Injectable } from '@angular/core'
|
import { Injectable } from '@angular/core'
|
||||||
import { pauseFor } from '../state.service'
|
import { pauseFor } from '../state.service'
|
||||||
import { ApiService, DiskInfo } from './api.service'
|
import { ApiService } from './api.service'
|
||||||
|
|
||||||
@Injectable({
|
@Injectable({
|
||||||
providedIn: 'root'
|
providedIn: 'root'
|
||||||
@@ -30,69 +30,75 @@ export class MockApiService extends ApiService {
|
|||||||
async getDrives() {
|
async getDrives() {
|
||||||
return [
|
return [
|
||||||
{
|
{
|
||||||
vendor: 'vendor',
|
vendor: 'Vendor',
|
||||||
model: 'model',
|
model: 'Model',
|
||||||
logicalname: 'Name1',
|
logicalname: '/dev/sda',
|
||||||
partitions: [{
|
partitions: [
|
||||||
logicalname: 'Name1',
|
{
|
||||||
|
logicalname: 'sda1',
|
||||||
label: 'label 1',
|
label: 'label 1',
|
||||||
capacity: 100000,
|
capacity: 100000,
|
||||||
used: 200.1255312
|
used: 200.1255312
|
||||||
}, {
|
},
|
||||||
logicalname: 'Name1',
|
{
|
||||||
label: 'label 2',
|
logicalname: 'sda2',
|
||||||
capacity: 50000,
|
label: 'label 2',
|
||||||
used: 200.1255312
|
capacity: 50000,
|
||||||
}],
|
used: 200.1255312
|
||||||
|
}
|
||||||
|
],
|
||||||
capacity: 150000,
|
capacity: 150000,
|
||||||
'embassy_os': null
|
'embassy_os': null
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
vendor: 'vendor',
|
vendor: 'Vendor',
|
||||||
model: 'model',
|
model: 'Model',
|
||||||
logicalname: 'Name2',
|
logicalname: 'dev/sdb',
|
||||||
partitions: [{
|
partitions: [
|
||||||
logicalname: 'Name2',
|
// {
|
||||||
label: null,
|
// logicalname: 'sdb1',
|
||||||
capacity: 1600.01234,
|
// label: null,
|
||||||
used: 0.00,
|
// capacity: 1600.01234,
|
||||||
}],
|
// used: 0.00,
|
||||||
|
// }
|
||||||
|
],
|
||||||
capacity: 1600.01234,
|
capacity: 1600.01234,
|
||||||
'embassy_os': null
|
'embassy_os': null
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
vendor: 'vendor',
|
vendor: 'Vendor',
|
||||||
model: 'model',
|
model: 'Model',
|
||||||
logicalname: 'Name3',
|
logicalname: 'dev/sdc',
|
||||||
partitions: [{
|
partitions: [
|
||||||
logicalname: 'Name3',
|
{
|
||||||
|
logicalname: 'sdc1',
|
||||||
label: 'label 1',
|
label: 'label 1',
|
||||||
capacity: null,
|
capacity: null,
|
||||||
used: null
|
used: null
|
||||||
}],
|
}
|
||||||
|
],
|
||||||
capacity: 100000,
|
capacity: 100000,
|
||||||
'embassy_os': {
|
'embassy_os': {
|
||||||
version: '0.3.3',
|
version: '0.3.3',
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
vendor: 'vendor',
|
vendor: 'Vendor',
|
||||||
model: 'model',
|
model: 'Model',
|
||||||
logicalname: 'Name4',
|
logicalname: '/dev/sdd',
|
||||||
partitions: [{
|
partitions: [
|
||||||
logicalname: 'Name4',
|
{
|
||||||
|
logicalname: 'sdd1',
|
||||||
label: null,
|
label: null,
|
||||||
capacity: 10000,
|
capacity: 10000,
|
||||||
used: null
|
used: null
|
||||||
}],
|
}
|
||||||
|
],
|
||||||
capacity: 10000,
|
capacity: 10000,
|
||||||
'embassy_os': {
|
'embassy_os': {
|
||||||
version: '0.2.7',
|
version: '0.2.7',
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ import { ApiService, DiskInfo } from './api/api.service'
|
|||||||
export class StateService {
|
export class StateService {
|
||||||
polling = false
|
polling = false
|
||||||
|
|
||||||
embassyDrive: DiskInfo;
|
storageDrive: DiskInfo;
|
||||||
embassyPassword: string
|
embassyPassword: string
|
||||||
recoveryDrive: DiskInfo;
|
recoveryDrive: DiskInfo;
|
||||||
recoveryPassword: string
|
recoveryPassword: string
|
||||||
@@ -45,7 +45,7 @@ export class StateService {
|
|||||||
|
|
||||||
async setupEmbassy () : Promise<{ torAddress: string }> {
|
async setupEmbassy () : Promise<{ torAddress: string }> {
|
||||||
const ret = await this.apiService.setupEmbassy({
|
const ret = await this.apiService.setupEmbassy({
|
||||||
'embassy-logicalname': this.embassyDrive.logicalname,
|
'embassy-logicalname': this.storageDrive.logicalname,
|
||||||
'embassy-password': this.embassyPassword,
|
'embassy-password': this.embassyPassword,
|
||||||
'recovery-logicalname': this.recoveryDrive?.logicalname,
|
'recovery-logicalname': this.recoveryDrive?.logicalname,
|
||||||
'recovery-password': this.recoveryPassword
|
'recovery-password': this.recoveryPassword
|
||||||
|
|||||||
@@ -25,65 +25,39 @@
|
|||||||
@import "~@ionic/angular/css/text-transformation.css";
|
@import "~@ionic/angular/css/text-transformation.css";
|
||||||
@import "~@ionic/angular/css/flex-utils.css";
|
@import "~@ionic/angular/css/flex-utils.css";
|
||||||
|
|
||||||
.input-label {
|
|
||||||
text-align: left;
|
|
||||||
padding-bottom: 2px;
|
|
||||||
font-size: small;
|
|
||||||
color: var(--ion-color-light);
|
|
||||||
font-weight: bold;
|
|
||||||
}
|
|
||||||
|
|
||||||
.alert-error .alert-title {
|
|
||||||
color: var(--ion-color-danger) !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.loader {
|
|
||||||
--spinner-color: var(--ion-color-light) !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
ion-avatar {
|
ion-avatar {
|
||||||
width: 27px;
|
width: 27px;
|
||||||
height: 27px;
|
height: 27px;
|
||||||
}
|
}
|
||||||
|
|
||||||
ion-action-sheet {
|
|
||||||
--backdrop-opacity: 0.75 !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
ion-alert {
|
|
||||||
--backdrop-opacity: 0.75 !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
ion-loading {
|
|
||||||
--backdrop-opacity: 0.75 !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
ion-item {
|
ion-item {
|
||||||
--highlight-color-valid: transparent;
|
--highlight-color-valid: transparent;
|
||||||
--highlight-color-invalid: transparent;
|
--highlight-color-invalid: transparent;
|
||||||
--highlight-color-focused: var(--ion-color-light);
|
--highlight-color-focused: var(--ion-color-light);
|
||||||
}
|
}
|
||||||
|
|
||||||
.divider {
|
.claim-button {
|
||||||
margin: 50px 0;
|
margin-inline-start: 0;
|
||||||
height: 2px;
|
margin-inline-end: 0;
|
||||||
background: linear-gradient(90deg,rgba(255,255,255,0) 0,rgba(255, 255, 255, 0.31) 50%,rgba(255,255,255,0) 100%);
|
margin-top: 24px;
|
||||||
|
min-width: 140px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.footer {
|
.alertlike-modal {
|
||||||
margin-bottom: 24px;
|
.modal-wrapper {
|
||||||
ion-icon {
|
max-height: 380px !important;
|
||||||
font-size: 28px;
|
top: 25% !important;
|
||||||
margin-right: 10px;
|
width: 90% !important;
|
||||||
|
left: 5% !important;
|
||||||
|
--box-shadow: none !important;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.success-alert .alert-wrapper {
|
@media (min-width:1000px) {
|
||||||
box-shadow: 4px 4px 30px var(--ion-color-light);
|
.alertlike-modal {
|
||||||
border: 1px solid rgba(255,255,255,.3);
|
.modal-wrapper {
|
||||||
background: var(--ion-color-light);
|
width: 40% !important;
|
||||||
}
|
left: 30% !important;
|
||||||
|
}
|
||||||
.success-alert .alert-title {
|
}
|
||||||
color: var(--ion-color-success);
|
|
||||||
}
|
}
|
||||||
@@ -3,9 +3,6 @@
|
|||||||
|
|
||||||
/** Ionic CSS Variables **/
|
/** Ionic CSS Variables **/
|
||||||
:root {
|
:root {
|
||||||
--ion-text-color: var(--ion-color-dark);
|
|
||||||
--ion-text-color-rgb: var(--ion-color-dark-rgb);
|
|
||||||
|
|
||||||
--ion-font-family: 'Benton Sans';
|
--ion-font-family: 'Benton Sans';
|
||||||
/** primary **/
|
/** primary **/
|
||||||
--ion-color-primary: #428cff;
|
--ion-color-primary: #428cff;
|
||||||
|
|||||||
@@ -4,7 +4,6 @@
|
|||||||
"compilerOptions": {
|
"compilerOptions": {
|
||||||
"baseUrl": "./",
|
"baseUrl": "./",
|
||||||
"outDir": "./out-tsc/app",
|
"outDir": "./out-tsc/app",
|
||||||
"types": [],
|
|
||||||
"sourceMap": true,
|
"sourceMap": true,
|
||||||
"declaration": false,
|
"declaration": false,
|
||||||
"downlevelIteration": true,
|
"downlevelIteration": true,
|
||||||
@@ -16,11 +15,18 @@
|
|||||||
"lib": ["es2018", "dom"]
|
"lib": ["es2018", "dom"]
|
||||||
},
|
},
|
||||||
"angularCompilerOptions": {
|
"angularCompilerOptions": {
|
||||||
"enableI18nLegacyMessageIdFormat": false,
|
|
||||||
"strictInjectionParameters": true,
|
"strictInjectionParameters": true,
|
||||||
|
"enableI18nLegacyMessageIdFormat": false,
|
||||||
"strictInputAccessModifiers": true,
|
"strictInputAccessModifiers": true,
|
||||||
"strictTemplates": true
|
"strictTemplates": true
|
||||||
},
|
},
|
||||||
|
"typeRoots": [
|
||||||
|
"node_modules/@types"
|
||||||
|
],
|
||||||
|
"lib": [
|
||||||
|
"es2018",
|
||||||
|
"dom"
|
||||||
|
],
|
||||||
"files": [
|
"files": [
|
||||||
"src/main.ts",
|
"src/main.ts",
|
||||||
"src/polyfills.ts"
|
"src/polyfills.ts"
|
||||||
|
|||||||
Reference in New Issue
Block a user