From 45a6a930c983bbb361c1b8135cd2eacf3f3f861e Mon Sep 17 00:00:00 2001 From: Matt Hill Date: Thu, 10 Nov 2022 10:20:52 -0700 Subject: [PATCH] Add guid to partition type (#1932) * add guid to partitions and implement pipe in shared to return guid for any disk * fix bug and clean up --- .../src/app/pages/home/home.module.ts | 6 +- .../src/app/pages/home/home.page.html | 83 +++++++++++-------- .../src/app/services/api/mock-api.service.ts | 29 ++++++- .../src/app/app-routing.module.ts | 5 ++ .../app/pages/attach/attach-routing.module.ts | 16 ++++ .../src/app/pages/attach/attach.module.ts | 21 +++++ .../src/app/pages/attach/attach.page.html | 74 +++++++++++++++++ .../src/app/pages/attach/attach.page.scss | 4 + .../src/app/pages/attach/attach.page.ts | 77 +++++++++++++++++ .../src/app/pages/embassy/embassy.module.ts | 6 +- .../src/app/pages/embassy/embassy.page.ts | 9 +- .../src/app/pages/home/home.page.html | 35 ++++++-- .../src/app/pages/home/home.page.ts | 72 ++-------------- .../src/app/pages/transfer/transfer.module.ts | 6 +- .../src/app/pages/transfer/transfer.page.html | 9 +- .../src/app/pages/transfer/transfer.page.ts | 12 +-- .../src/app/services/api/mock-api.service.ts | 38 +++++++-- .../shared/src/pipes/guid/guid.module.ts | 8 ++ .../shared/src/pipes/guid/guid.pipe.ts | 11 +++ frontend/projects/shared/src/public-api.ts | 2 + frontend/projects/shared/src/types/api.ts | 1 + 21 files changed, 393 insertions(+), 131 deletions(-) create mode 100644 frontend/projects/setup-wizard/src/app/pages/attach/attach-routing.module.ts create mode 100644 frontend/projects/setup-wizard/src/app/pages/attach/attach.module.ts create mode 100644 frontend/projects/setup-wizard/src/app/pages/attach/attach.page.html create mode 100644 frontend/projects/setup-wizard/src/app/pages/attach/attach.page.scss create mode 100644 frontend/projects/setup-wizard/src/app/pages/attach/attach.page.ts create mode 100644 frontend/projects/shared/src/pipes/guid/guid.module.ts create mode 100644 frontend/projects/shared/src/pipes/guid/guid.pipe.ts diff --git a/frontend/projects/install-wizard/src/app/pages/home/home.module.ts b/frontend/projects/install-wizard/src/app/pages/home/home.module.ts index 79afa2ac5..e7cd274f6 100644 --- a/frontend/projects/install-wizard/src/app/pages/home/home.module.ts +++ b/frontend/projects/install-wizard/src/app/pages/home/home.module.ts @@ -5,7 +5,10 @@ import { IonicModule } from '@ionic/angular' import { FormsModule } from '@angular/forms' import { HomePage } from './home.page' import { SwiperModule } from 'swiper/angular' -import { UnitConversionPipesModule } from '@start9labs/shared' +import { + UnitConversionPipesModule, + GuidPipePipesModule, +} from '@start9labs/shared' const routes: Routes = [ { @@ -22,6 +25,7 @@ const routes: Routes = [ RouterModule.forChild(routes), SwiperModule, UnitConversionPipesModule, + GuidPipePipesModule, ], declarations: [HomePage], }) diff --git a/frontend/projects/install-wizard/src/app/pages/home/home.page.html b/frontend/projects/install-wizard/src/app/pages/home/home.page.html index 91e454d99..61d82eebc 100644 --- a/frontend/projects/install-wizard/src/app/pages/home/home.page.html +++ b/frontend/projects/install-wizard/src/app/pages/home/home.page.html @@ -27,6 +27,7 @@ + + + - - - -

- Re-Install embassyOS -

-

Will preserve existing embassyOS data

-
-
- - - -

- {{ !!selectedDisk?.guid ? 'Factory Reset' : 'Install - embassyOS' }} -

-

Will delete existing data on disk

-
-
+ + + + + +

+ Re-Install embassyOS +

+

Will preserve existing embassyOS data

+
+
+ + + + + +

+ + {{ (selectedDisk | guid) ? 'Factory Reset' : 'Install + embassyOS' }} + +

+

Will delete existing data on disk

+
+
+
diff --git a/frontend/projects/install-wizard/src/app/services/api/mock-api.service.ts b/frontend/projects/install-wizard/src/app/services/api/mock-api.service.ts index 9f035d2cd..9caf4f88e 100644 --- a/frontend/projects/install-wizard/src/app/services/api/mock-api.service.ts +++ b/frontend/projects/install-wizard/src/app/services/api/mock-api.service.ts @@ -24,6 +24,7 @@ export class MockApiService implements ApiService { '$argon2d$v=19$m=1024,t=1,p=1$YXNkZmFzZGZhc2RmYXNkZg$Ceev1I901G6UwU+hY0sHrFZ56D+o+LNJ', 'wrapped-key': null, }, + guid: null, }, ], capacity: 123456789123, @@ -40,15 +41,39 @@ export class MockApiService implements ApiService { capacity: 73264762332, used: null, 'embassy-os': { - version: '0.3.1', + version: '0.3.3', full: true, 'password-hash': '$argon2d$v=19$m=1024,t=1,p=1$YXNkZmFzZGZhc2RmYXNkZg$Ceev1I901G6UwU+hY0sHrFZ56D+o+LNJ', 'wrapped-key': null, }, + guid: null, }, ], - capacity: 123456789123, + capacity: 124456789123, + guid: null, + }, + { + logicalname: 'wxyz', + vendor: 'SanDisk', + model: 'Specialness', + partitions: [ + { + logicalname: 'pbcba', + label: null, + capacity: 73264762332, + used: null, + 'embassy-os': { + version: '0.3.2', + full: true, + 'password-hash': + '$argon2d$v=19$m=1024,t=1,p=1$YXNkZmFzZGZhc2RmYXNkZg$Ceev1I901G6UwU+hY0sHrFZ56D+o+LNJ', + 'wrapped-key': null, + }, + guid: 'guid-guid-guid-guid', + }, + ], + capacity: 123459789123, guid: null, }, ] diff --git a/frontend/projects/setup-wizard/src/app/app-routing.module.ts b/frontend/projects/setup-wizard/src/app/app-routing.module.ts index 38f320436..ccc184340 100644 --- a/frontend/projects/setup-wizard/src/app/app-routing.module.ts +++ b/frontend/projects/setup-wizard/src/app/app-routing.module.ts @@ -8,6 +8,11 @@ const routes: Routes = [ loadChildren: () => import('./pages/home/home.module').then(m => m.HomePageModule), }, + { + path: 'attach', + loadChildren: () => + import('./pages/attach/attach.module').then(m => m.AttachPageModule), + }, { path: 'recover', loadChildren: () => diff --git a/frontend/projects/setup-wizard/src/app/pages/attach/attach-routing.module.ts b/frontend/projects/setup-wizard/src/app/pages/attach/attach-routing.module.ts new file mode 100644 index 000000000..8ba45b29c --- /dev/null +++ b/frontend/projects/setup-wizard/src/app/pages/attach/attach-routing.module.ts @@ -0,0 +1,16 @@ +import { NgModule } from '@angular/core' +import { RouterModule, Routes } from '@angular/router' +import { AttachPage } from './attach.page' + +const routes: Routes = [ + { + path: '', + component: AttachPage, + }, +] + +@NgModule({ + imports: [RouterModule.forChild(routes)], + exports: [RouterModule], +}) +export class AttachPageRoutingModule {} diff --git a/frontend/projects/setup-wizard/src/app/pages/attach/attach.module.ts b/frontend/projects/setup-wizard/src/app/pages/attach/attach.module.ts new file mode 100644 index 000000000..486884878 --- /dev/null +++ b/frontend/projects/setup-wizard/src/app/pages/attach/attach.module.ts @@ -0,0 +1,21 @@ +import { NgModule } from '@angular/core' +import { CommonModule } from '@angular/common' +import { IonicModule } from '@ionic/angular' +import { + GuidPipePipesModule, + UnitConversionPipesModule, +} from '@start9labs/shared' +import { AttachPage } from './attach.page' +import { AttachPageRoutingModule } from './attach-routing.module' + +@NgModule({ + declarations: [AttachPage], + imports: [ + CommonModule, + IonicModule, + AttachPageRoutingModule, + UnitConversionPipesModule, + GuidPipePipesModule, + ], +}) +export class AttachPageModule {} diff --git a/frontend/projects/setup-wizard/src/app/pages/attach/attach.page.html b/frontend/projects/setup-wizard/src/app/pages/attach/attach.page.html new file mode 100644 index 000000000..05097f920 --- /dev/null +++ b/frontend/projects/setup-wizard/src/app/pages/attach/attach.page.html @@ -0,0 +1,74 @@ + + + + +
+ +
+ + + + Use Existing Drive + Select the physical drive containing your Embassy + data + + + + + + + + +

Available Drives

+ +

+ No valid Embassy data drives found. Please make sure the drive + is a valid Embassy data drive (not a backup) and is firmly + connected, then refresh the page. +

+ + + + + +

{{ drive.logicalname }}

+

+ {{ drive.vendor || 'Unknown Vendor' }} - {{ drive.model || + 'Unknown Model' }} +

+

Capacity: {{ drive.capacity | convertBytes }}

+
+
+
+ + + Refresh + +
+
+
+
+
+
+
diff --git a/frontend/projects/setup-wizard/src/app/pages/attach/attach.page.scss b/frontend/projects/setup-wizard/src/app/pages/attach/attach.page.scss new file mode 100644 index 000000000..687b91ecf --- /dev/null +++ b/frontend/projects/setup-wizard/src/app/pages/attach/attach.page.scss @@ -0,0 +1,4 @@ +.target-label { + font-weight: bold; + padding-bottom: 6px; +} diff --git a/frontend/projects/setup-wizard/src/app/pages/attach/attach.page.ts b/frontend/projects/setup-wizard/src/app/pages/attach/attach.page.ts new file mode 100644 index 000000000..a6fd69a09 --- /dev/null +++ b/frontend/projects/setup-wizard/src/app/pages/attach/attach.page.ts @@ -0,0 +1,77 @@ +import { Component } from '@angular/core' +import { + LoadingController, + ModalController, + NavController, +} from '@ionic/angular' +import { ApiService } from 'src/app/services/api/api.service' +import { DiskInfo, ErrorToastService } from '@start9labs/shared' +import { StateService } from 'src/app/services/state.service' +import { PasswordPage } from 'src/app/modals/password/password.page' + +@Component({ + selector: 'app-attach', + templateUrl: 'attach.page.html', + styleUrls: ['attach.page.scss'], +}) +export class AttachPage { + loading = true + drives: DiskInfo[] = [] + + constructor( + private readonly apiService: ApiService, + private readonly navCtrl: NavController, + private readonly errToastService: ErrorToastService, + private readonly stateService: StateService, + private readonly modalCtrl: ModalController, + private readonly loadingCtrl: LoadingController, + ) {} + + async ngOnInit() { + await this.getDrives() + } + + async refresh() { + this.loading = true + await this.getDrives() + } + + async getDrives() { + try { + const drives = await this.apiService.getDrives() + this.drives = drives.filter(d => d.partitions.length) + } catch (e: any) { + this.errToastService.present(e) + } finally { + this.loading = false + } + } + + async select(guid: string) { + const modal = await this.modalCtrl.create({ + component: PasswordPage, + componentProps: { storageDrive: true }, + }) + modal.onDidDismiss().then(res => { + if (res.data && res.data.password) { + this.attachDrive(guid, res.data.password) + } + }) + await modal.present() + } + + private async attachDrive(guid: string, password: string) { + const loader = await this.loadingCtrl.create({ + message: 'Attaching Drive', + }) + await loader.present() + try { + await this.stateService.importDrive(guid, password) + await this.navCtrl.navigateForward(`/success`) + } catch (e: any) { + this.errToastService.present(e) + } finally { + loader.dismiss() + } + } +} diff --git a/frontend/projects/setup-wizard/src/app/pages/embassy/embassy.module.ts b/frontend/projects/setup-wizard/src/app/pages/embassy/embassy.module.ts index a49e06c9c..7a7594b41 100644 --- a/frontend/projects/setup-wizard/src/app/pages/embassy/embassy.module.ts +++ b/frontend/projects/setup-wizard/src/app/pages/embassy/embassy.module.ts @@ -2,7 +2,10 @@ import { NgModule } from '@angular/core' import { CommonModule } from '@angular/common' import { IonicModule } from '@ionic/angular' import { FormsModule } from '@angular/forms' -import { UnitConversionPipesModule } from '@start9labs/shared' +import { + GuidPipePipesModule, + UnitConversionPipesModule, +} from '@start9labs/shared' import { EmbassyPage } from './embassy.page' import { PasswordPageModule } from '../../modals/password/password.module' import { EmbassyPageRoutingModule } from './embassy-routing.module' @@ -15,6 +18,7 @@ import { EmbassyPageRoutingModule } from './embassy-routing.module' EmbassyPageRoutingModule, PasswordPageModule, UnitConversionPipesModule, + GuidPipePipesModule, ], declarations: [EmbassyPage], }) diff --git a/frontend/projects/setup-wizard/src/app/pages/embassy/embassy.page.ts b/frontend/projects/setup-wizard/src/app/pages/embassy/embassy.page.ts index 4dcc2f13d..029787118 100644 --- a/frontend/projects/setup-wizard/src/app/pages/embassy/embassy.page.ts +++ b/frontend/projects/setup-wizard/src/app/pages/embassy/embassy.page.ts @@ -10,7 +10,7 @@ import { BackupRecoverySource, DiskRecoverySource, } from 'src/app/services/api/api.service' -import { DiskInfo, ErrorToastService } from '@start9labs/shared' +import { DiskInfo, ErrorToastService, GuidPipe } from '@start9labs/shared' import { StateService } from 'src/app/services/state.service' import { PasswordPage } from '../../modals/password/password.page' import { ActivatedRoute } from '@angular/router' @@ -19,6 +19,7 @@ import { ActivatedRoute } from '@angular/router' selector: 'app-embassy', templateUrl: 'embassy.page.html', styleUrls: ['embassy.page.scss'], + providers: [GuidPipe], }) export class EmbassyPage { storageDrives: DiskInfo[] = [] @@ -32,6 +33,7 @@ export class EmbassyPage { private readonly stateService: StateService, private readonly loadingCtrl: LoadingController, private readonly errorToastService: ErrorToastService, + private readonly guidPipe: GuidPipe, private route: ActivatedRoute, ) {} @@ -71,7 +73,10 @@ export class EmbassyPage { } async chooseDrive(drive: DiskInfo) { - if (!!drive.partitions.find(p => p.used) || !!drive.guid) { + if ( + this.guidPipe.transform(drive) || + !!drive.partitions.find(p => p.used) + ) { const alert = await this.alertCtrl.create({ header: 'Warning', subHeader: 'Drive contains data!', diff --git a/frontend/projects/setup-wizard/src/app/pages/home/home.page.html b/frontend/projects/setup-wizard/src/app/pages/home/home.page.html index 5cb8175b1..8037bedc3 100644 --- a/frontend/projects/setup-wizard/src/app/pages/home/home.page.html +++ b/frontend/projects/setup-wizard/src/app/pages/home/home.page.html @@ -1,4 +1,4 @@ - + @@ -6,7 +6,7 @@ - + - + + + Get started with a brand new Embassy

+ +
+ + + Restore From Backup -

Recover an Embassy from an encrypted backup

+

Restore an Embassy from an encrypted backup

- + + + Use Existing Drive -

Attach and use a valid Embassy data drive

+

+ Use an existing, valid Embassy data drive (not a backup) +

+ + Transfer

- Transfer data to a new drive
(e.g. upgrade to a - larger drive or an Embassy Pro) + Transfer data from an existing, valid Embassy data drive + (not a backup) to a new drive
(e.g. in order to + transfer data to another device)

diff --git a/frontend/projects/setup-wizard/src/app/pages/home/home.page.ts b/frontend/projects/setup-wizard/src/app/pages/home/home.page.ts index bf25183a6..94712abca 100644 --- a/frontend/projects/setup-wizard/src/app/pages/home/home.page.ts +++ b/frontend/projects/setup-wizard/src/app/pages/home/home.page.ts @@ -1,14 +1,6 @@ import { Component } from '@angular/core' -import { - AlertController, - IonicSlides, - LoadingController, - ModalController, - NavController, -} from '@ionic/angular' -import { PasswordPage } from 'src/app/modals/password/password.page' +import { IonicSlides } from '@ionic/angular' import { ApiService } from 'src/app/services/api/api.service' -import { StateService } from 'src/app/services/state.service' import SwiperCore, { Swiper } from 'swiper' import { ErrorToastService } from '@start9labs/shared' @@ -21,35 +13,26 @@ SwiperCore.use([IonicSlides]) }) export class HomePage { swiper?: Swiper - guid?: string | null error = false - loaded = false + loading = true constructor( private readonly api: ApiService, - private readonly modalCtrl: ModalController, - private readonly alertCtrl: AlertController, - private readonly loadingCtrl: LoadingController, - private readonly stateService: StateService, - private readonly navCtrl: NavController, private readonly errToastService: ErrorToastService, ) {} - async ngOnInit() { + async ionViewDidEnter() { + if (this.swiper) { + this.swiper.allowTouchMove = false + } + try { await this.api.getPubKey() - const disks = await this.api.getDrives() - this.guid = disks.find(d => !!d.guid)?.guid } catch (e: any) { this.error = true this.errToastService.present(e) - } - } - - async ionViewDidEnter() { - this.loaded = true // needed to accommodate autoHight="true" on swiper. Otherwise Swiper height might be 0 when navigating *to* this page from later page. Happens on refresh. - if (this.swiper) { - this.swiper.allowTouchMove = false + } finally { + this.loading = false } } @@ -64,41 +47,4 @@ export class HomePage { previous() { this.swiper?.slidePrev(500) } - - async import() { - if (this.guid) { - const modal = await this.modalCtrl.create({ - component: PasswordPage, - componentProps: { storageDrive: true }, - }) - modal.onDidDismiss().then(res => { - if (res.data && res.data.password) { - this.importDrive(res.data.password) - } - }) - await modal.present() - } else { - const alert = await this.alertCtrl.create({ - header: 'Drive Not Found', - message: - 'Please make sure the drive is a valid Embassy data drive (not a backup) and is firmly connected, then refresh the page.', - }) - await alert.present() - } - } - - private async importDrive(password: string) { - const loader = await this.loadingCtrl.create({ - message: 'Importing Drive', - }) - await loader.present() - try { - await this.stateService.importDrive(this.guid!, password) - await this.navCtrl.navigateForward(`/success`) - } catch (e: any) { - this.errToastService.present(e) - } finally { - loader.dismiss() - } - } } diff --git a/frontend/projects/setup-wizard/src/app/pages/transfer/transfer.module.ts b/frontend/projects/setup-wizard/src/app/pages/transfer/transfer.module.ts index e4169d50a..2dfd57b20 100644 --- a/frontend/projects/setup-wizard/src/app/pages/transfer/transfer.module.ts +++ b/frontend/projects/setup-wizard/src/app/pages/transfer/transfer.module.ts @@ -1,7 +1,10 @@ import { NgModule } from '@angular/core' import { CommonModule } from '@angular/common' import { IonicModule } from '@ionic/angular' -import { UnitConversionPipesModule } from '@start9labs/shared' +import { + GuidPipePipesModule, + UnitConversionPipesModule, +} from '@start9labs/shared' import { TransferPage } from './transfer.page' import { TransferPageRoutingModule } from './transfer-routing.module' @@ -12,6 +15,7 @@ import { TransferPageRoutingModule } from './transfer-routing.module' IonicModule, TransferPageRoutingModule, UnitConversionPipesModule, + GuidPipePipesModule, ], }) export class TransferPageModule {} diff --git a/frontend/projects/setup-wizard/src/app/pages/transfer/transfer.page.html b/frontend/projects/setup-wizard/src/app/pages/transfer/transfer.page.html index 3b533857e..e24fecc18 100644 --- a/frontend/projects/setup-wizard/src/app/pages/transfer/transfer.page.html +++ b/frontend/projects/setup-wizard/src/app/pages/transfer/transfer.page.html @@ -10,7 +10,7 @@ Transfer Select the physical drive containing your previous Embassy + >Select the physical drive containing your Embassy data @@ -28,7 +28,12 @@

Available Drives

- + d.partitions.length && d.guid) + const drives = await this.apiService.getDrives() + this.drives = drives.filter(d => d.partitions.length) } catch (e: any) { this.errToastService.present(e) } finally { @@ -41,11 +41,7 @@ export class TransferPage { } } - async select(target: DiskInfo) { - const { logicalname, guid } = target - - if (!logicalname) return - + async select(guid: string) { const alert = await this.alertCtrl.create({ header: 'Warning', message: @@ -60,7 +56,7 @@ export class TransferPage { handler: () => { this.stateService.recoverySource = { type: 'migrate', - guid: guid!, + guid, } this.navCtrl.navigateForward(`/embassy`, { queryParams: { action: 'transfer' }, diff --git a/frontend/projects/setup-wizard/src/app/services/api/mock-api.service.ts b/frontend/projects/setup-wizard/src/app/services/api/mock-api.service.ts index 475aa79c0..7f016ca87 100644 --- a/frontend/projects/setup-wizard/src/app/services/api/mock-api.service.ts +++ b/frontend/projects/setup-wizard/src/app/services/api/mock-api.service.ts @@ -24,9 +24,8 @@ export class MockApiService extends ApiService { async getPubKey() { await pauseFor(1000) - const keystore = jose.JWK.createKeyStore() - // randomly generated + // const keystore = jose.JWK.createKeyStore() // this.pubkey = await keystore.generate('EC', 'P-256') // generated from backend @@ -58,6 +57,7 @@ export class MockApiService extends ApiService { '$argon2d$v=19$m=1024,t=1,p=1$YXNkZmFzZGZhc2RmYXNkZg$Ceev1I901G6UwU+hY0sHrFZ56D+o+LNJ', 'wrapped-key': null, }, + guid: null, }, ], capacity: 123456789123, @@ -65,8 +65,8 @@ export class MockApiService extends ApiService { }, { logicalname: 'dcba', - vendor: 'Samsung', - model: 'T5', + vendor: 'Crucial', + model: 'MX500', partitions: [ { logicalname: 'pbcba', @@ -74,16 +74,40 @@ export class MockApiService extends ApiService { capacity: 73264762332, used: null, 'embassy-os': { - version: '0.3.1', + version: '0.3.3', full: true, 'password-hash': '$argon2d$v=19$m=1024,t=1,p=1$YXNkZmFzZGZhc2RmYXNkZg$Ceev1I901G6UwU+hY0sHrFZ56D+o+LNJ', 'wrapped-key': null, }, + guid: null, }, ], - capacity: 123456789123, - guid: 'uuid-uuid-uuid-uuid', + capacity: 124456789123, + guid: null, + }, + { + logicalname: 'wxyz', + vendor: 'SanDisk', + model: 'Specialness', + partitions: [ + { + logicalname: 'pbcba', + label: null, + capacity: 73264762332, + used: null, + 'embassy-os': { + version: '0.3.2', + full: true, + 'password-hash': + '$argon2d$v=19$m=1024,t=1,p=1$YXNkZmFzZGZhc2RmYXNkZg$Ceev1I901G6UwU+hY0sHrFZ56D+o+LNJ', + 'wrapped-key': null, + }, + guid: 'guid-guid-guid-guid', + }, + ], + capacity: 123459789123, + guid: null, }, ] } diff --git a/frontend/projects/shared/src/pipes/guid/guid.module.ts b/frontend/projects/shared/src/pipes/guid/guid.module.ts new file mode 100644 index 000000000..bd4e22f5f --- /dev/null +++ b/frontend/projects/shared/src/pipes/guid/guid.module.ts @@ -0,0 +1,8 @@ +import { NgModule } from '@angular/core' +import { GuidPipe } from './guid.pipe' + +@NgModule({ + declarations: [GuidPipe], + exports: [GuidPipe], +}) +export class GuidPipePipesModule {} diff --git a/frontend/projects/shared/src/pipes/guid/guid.pipe.ts b/frontend/projects/shared/src/pipes/guid/guid.pipe.ts new file mode 100644 index 000000000..a095bd929 --- /dev/null +++ b/frontend/projects/shared/src/pipes/guid/guid.pipe.ts @@ -0,0 +1,11 @@ +import { Pipe, PipeTransform } from '@angular/core' +import { DiskInfo } from '../../types/api' + +@Pipe({ + name: 'guid', +}) +export class GuidPipe implements PipeTransform { + transform(disk: DiskInfo): string | null { + return disk.guid || disk.partitions.find(p => p.guid)?.guid || null + } +} diff --git a/frontend/projects/shared/src/public-api.ts b/frontend/projects/shared/src/public-api.ts index 0745f5561..a957014ee 100644 --- a/frontend/projects/shared/src/public-api.ts +++ b/frontend/projects/shared/src/public-api.ts @@ -24,6 +24,8 @@ export * from './directives/safe-links/safe-links.module' export * from './pipes/emver/emver.module' export * from './pipes/emver/emver.pipe' +export * from './pipes/guid/guid.module' +export * from './pipes/guid/guid.pipe' export * from './pipes/markdown/markdown.module' export * from './pipes/markdown/markdown.pipe' export * from './pipes/shared/shared.module' diff --git a/frontend/projects/shared/src/types/api.ts b/frontend/projects/shared/src/types/api.ts index 21a869c4c..4726c05cd 100644 --- a/frontend/projects/shared/src/types/api.ts +++ b/frontend/projects/shared/src/types/api.ts @@ -32,6 +32,7 @@ export interface PartitionInfo { capacity: number used: number | null 'embassy-os': EmbassyOSDiskInfo | null + guid: string | null } export type EmbassyOSDiskInfo = {