Installed
Update Available
diff --git a/ui/src/app/pages/marketplace-routes/marketplace-list/marketplace-list.page.ts b/ui/src/app/pages/marketplace-routes/marketplace-list/marketplace-list.page.ts
index 5b44b4eba..4146adb77 100644
--- a/ui/src/app/pages/marketplace-routes/marketplace-list/marketplace-list.page.ts
+++ b/ui/src/app/pages/marketplace-routes/marketplace-list/marketplace-list.page.ts
@@ -3,12 +3,12 @@ import { MarketplaceData, MarketplaceEOS, MarketplacePkg } from 'src/app/service
import { wizardModal } from 'src/app/components/install-wizard/install-wizard.component'
import { IonContent, ModalController } from '@ionic/angular'
import { WizardBaker } from 'src/app/components/install-wizard/prebaked-wizards'
-import { PatchDbService } from 'src/app/services/patch-db/patch-db.service'
-import { PackageState } from 'src/app/services/patch-db/data-model'
+import { PackageDataEntry, PackageState } from 'src/app/services/patch-db/data-model'
import { Subscription } from 'rxjs'
import { ErrorToastService } from 'src/app/services/error-toast.service'
import { MarketplaceService } from '../marketplace.service'
import { MarketplaceApiService } from 'src/app/services/api/marketplace/marketplace-api.service'
+import { PatchDbService } from 'src/app/services/patch-db/patch-db.service'
@Component({
selector: 'marketplace-list',
@@ -17,6 +17,8 @@ import { MarketplaceApiService } from 'src/app/services/api/marketplace/marketpl
})
export class MarketplaceListPage {
@ViewChild(IonContent) content: IonContent
+ localPkgs: { [id: string]: PackageDataEntry }
+
pageLoading = true
pkgsLoading = true
@@ -37,7 +39,7 @@ export class MarketplaceListPage {
constructor (
private readonly marketplaceService: MarketplaceService,
- private readonly marketplaceApiService: MarketplaceApiService,
+ private readonly marketplaceApi: MarketplaceApiService,
private readonly modalCtrl: ModalController,
private readonly errToast: ErrorToastService,
private readonly wizardBaker: WizardBaker,
@@ -45,11 +47,16 @@ export class MarketplaceListPage {
) { }
async ngOnInit () {
+ this.subs = [
+ this.patch.watch$('package-data').subscribe(pkgs => {
+ this.localPkgs = pkgs
+ }),
+ ]
try {
const [data, eos] = await Promise.all([
- this.marketplaceApiService.getMarketplaceData({ }),
- this.marketplaceApiService.getEos({ }),
+ this.marketplaceApi.getMarketplaceData({ }),
+ this.marketplaceApi.getEos({ }),
this.getPkgs(),
])
this.eos = eos
@@ -107,7 +114,7 @@ export class MarketplaceListPage {
if (this.pkgs.length) {
this.pkgsLoading = false
}
- await this.marketplaceService.getUpdates(this.patch.data['package-data'])
+ await this.marketplaceService.getUpdates(this.localPkgs)
this.pkgs = this.marketplaceService.updates
} else {
const pkgs = await this.marketplaceService.getPkgs(
diff --git a/ui/src/app/pages/marketplace-routes/marketplace.service.ts b/ui/src/app/pages/marketplace-routes/marketplace.service.ts
index 463b731b2..90b23fbb7 100644
--- a/ui/src/app/pages/marketplace-routes/marketplace.service.ts
+++ b/ui/src/app/pages/marketplace-routes/marketplace.service.ts
@@ -12,32 +12,30 @@ export class MarketplaceService {
updates: MarketplacePkg[] = null
releaseNotes: { [id: string]: {
[version: string]: string
- } }
+ } } = { }
constructor (
- private readonly marketplaceApiService: MarketplaceApiService,
+ private readonly marketplaceApi: MarketplaceApiService,
private readonly emver: Emver,
) { }
- async getUpdates (pkgData: { [id: string]: PackageDataEntry}) : Promise {
- const idAndCurrentVersions = Object.keys(pkgData).map(key => ({ id: key, version: pkgData[key].manifest.version }))
- console.log(JSON.stringify(idAndCurrentVersions))
- const latestPkgs = (await this.marketplaceApiService.getMarketplacePkgs({
+ async getUpdates (localPkgs: { [id: string]: PackageDataEntry }) : Promise {
+ const idAndCurrentVersions = Object.keys(localPkgs).map(key => ({ id: key, version: localPkgs[key].manifest.version }))
+ const latestPkgs = (await this.marketplaceApi.getMarketplacePkgs({
ids: idAndCurrentVersions,
}))
const updates = latestPkgs.filter(latestPkg => {
const latestVersion = latestPkg.manifest.version
- const curVersion = pkgData[latestPkg.manifest.id]?.manifest.version
+ const curVersion = localPkgs[latestPkg.manifest.id]?.manifest.version
return !!curVersion && this.emver.compare(latestVersion, curVersion) === 1
})
this.updates = updates
- return updates
}
async getPkgs (category: string, query: string, page: number, perPage: number) : Promise {
- const pkgs = await this.marketplaceApiService.getMarketplacePkgs({
+ const pkgs = await this.marketplaceApi.getMarketplacePkgs({
category: category !== 'all' ? category : undefined,
query,
page: String(page),
@@ -51,7 +49,10 @@ export class MarketplaceService {
}
async getPkg (id: string, version?: string): Promise {
- const pkg = (await this.marketplaceApiService.getMarketplacePkgs({ ids: [{ id, version }]}))[0]
+ const pkgs = await this.marketplaceApi.getMarketplacePkgs({
+ ids: [{ id, version: version || '*' }],
+ })
+ const pkg = pkgs[0]
if (pkg) {
this.pkgs[id] = pkg
} else {
@@ -60,7 +61,7 @@ export class MarketplaceService {
}
async getReleaseNotes (id: string): Promise {
- this.releaseNotes[id] = await this.marketplaceApiService.getReleaseNotes({ id })
+ this.releaseNotes[id] = await this.marketplaceApi.getReleaseNotes({ id })
}
}
diff --git a/ui/src/app/pages/notifications/notifications.page.ts b/ui/src/app/pages/notifications/notifications.page.ts
index f14657073..0468fab6f 100644
--- a/ui/src/app/pages/notifications/notifications.page.ts
+++ b/ui/src/app/pages/notifications/notifications.page.ts
@@ -20,7 +20,7 @@ export class NotificationsPage {
readonly perPage = 20
constructor (
- private readonly apiService: ApiService,
+ private readonly embassyApi: ApiService,
private readonly loader: LoaderService,
private readonly errToast: ErrorToastService,
private readonly alertCtrl: AlertController,
@@ -48,7 +48,7 @@ export class NotificationsPage {
async getNotifications (): Promise {
let notifications: ServerNotifications = []
try {
- notifications = await this.apiService.getNotifications({ page: this.page, 'per-page': this.perPage })
+ notifications = await this.embassyApi.getNotifications({ page: this.page, 'per-page': this.perPage })
this.needInfinite = notifications.length >= this.perPage
this.page++
} catch (e) {
@@ -65,7 +65,7 @@ export class NotificationsPage {
spinner: 'lines',
cssClass: 'loader',
}).displayDuringP(
- this.apiService.deleteNotification({ id }).then(() => {
+ this.embassyApi.deleteNotification({ id }).then(() => {
this.notifications.splice(index, 1)
}),
).catch(e => {
diff --git a/ui/src/app/pages/server-routes/developer-routes/dev-options/dev-options.page.html b/ui/src/app/pages/server-routes/developer-routes/dev-options/dev-options.page.html
index bfd154b86..45cb062a7 100644
--- a/ui/src/app/pages/server-routes/developer-routes/dev-options/dev-options.page.html
+++ b/ui/src/app/pages/server-routes/developer-routes/dev-options/dev-options.page.html
@@ -7,7 +7,7 @@
-
+
diff --git a/ui/src/app/pages/server-routes/developer-routes/dev-ssh-keys/ssh.service.ts b/ui/src/app/pages/server-routes/developer-routes/dev-ssh-keys/ssh.service.ts
index fff7918e7..ebd200a52 100644
--- a/ui/src/app/pages/server-routes/developer-routes/dev-ssh-keys/ssh.service.ts
+++ b/ui/src/app/pages/server-routes/developer-routes/dev-ssh-keys/ssh.service.ts
@@ -10,7 +10,7 @@ export class SSHService {
private readonly keys$ = new BehaviorSubject({ })
constructor (
- private readonly apiService: ApiService,
+ private readonly embassyApi: ApiService,
) { }
watch$ () {
@@ -18,18 +18,18 @@ export class SSHService {
}
async getKeys (): Promise {
- const keys = await this.apiService.getSshKeys({ })
+ const keys = await this.embassyApi.getSshKeys({ })
this.keys$.next(keys)
}
async add (pubkey: string): Promise {
- const key = await this.apiService.addSshKey({ pubkey })
+ const key = await this.embassyApi.addSshKey({ pubkey })
const keys = this.keys$.getValue()
this.keys$.next({ ...keys, ...key })
}
async delete (hash: string): Promise {
- await this.apiService.deleteSshKey({ hash })
+ await this.embassyApi.deleteSshKey({ hash })
const keys = this.keys$.getValue()
const filtered = Object.keys(keys)
diff --git a/ui/src/app/pages/server-routes/lan/lan.page.ts b/ui/src/app/pages/server-routes/lan/lan.page.ts
index f76b2b6e5..64b3ff3fd 100644
--- a/ui/src/app/pages/server-routes/lan/lan.page.ts
+++ b/ui/src/app/pages/server-routes/lan/lan.page.ts
@@ -26,7 +26,7 @@ export class LANPage {
private readonly toastCtrl: ToastController,
private readonly config: ConfigService,
private readonly loader: LoaderService,
- private readonly apiService: ApiService,
+ private readonly embassyApi: ApiService,
private readonly patch: PatchDbService,
) { }
@@ -54,7 +54,7 @@ export class LANPage {
spinner: 'lines',
cssClass: 'loader',
}).displayDuringAsync( async () => {
- await this.apiService.refreshLan({ })
+ await this.embassyApi.refreshLan({ })
}).catch(e => {
console.error(e)
})
diff --git a/ui/src/app/pages/server-routes/server-backup/server-backup.page.ts b/ui/src/app/pages/server-routes/server-backup/server-backup.page.ts
index e0b4b156d..65ff969f5 100644
--- a/ui/src/app/pages/server-routes/server-backup/server-backup.page.ts
+++ b/ui/src/app/pages/server-routes/server-backup/server-backup.page.ts
@@ -17,7 +17,7 @@ export class ServerBackupPage {
constructor (
private readonly modalCtrl: ModalController,
- private readonly apiService: ApiService,
+ private readonly embassyApi: ApiService,
private readonly loadingCtrl: LoadingController,
) { }
@@ -32,7 +32,7 @@ export class ServerBackupPage {
async getExternalDisks (): Promise {
try {
- this.disks = await this.apiService.getDisks({ })
+ this.disks = await this.embassyApi.getDisks({ })
this.allPartitionsMounted = Object.values(this.disks).every(d => Object.values(d.partitions).every(p => p['is-mounted']))
} catch (e) {
console.error(e)
@@ -70,7 +70,7 @@ export class ServerBackupPage {
await loader.present()
try {
- await this.apiService.createBackup({ logicalname, password })
+ await this.embassyApi.createBackup({ logicalname, password })
} catch (e) {
console.error(e)
this.error = e.message
diff --git a/ui/src/app/pages/server-routes/server-logs/server-logs.page.ts b/ui/src/app/pages/server-routes/server-logs/server-logs.page.ts
index c5b1b1d1d..7e0970320 100644
--- a/ui/src/app/pages/server-routes/server-logs/server-logs.page.ts
+++ b/ui/src/app/pages/server-routes/server-logs/server-logs.page.ts
@@ -15,7 +15,7 @@ export class ServerLogsPage {
constructor (
private readonly errToast: ErrorToastService,
- private readonly apiService: ApiService,
+ private readonly embassyApi: ApiService,
) { }
ngOnInit () {
@@ -26,7 +26,7 @@ export class ServerLogsPage {
this.logs = ''
this.loading = true
try {
- const logs = await this.apiService.getServerLogs({ })
+ const logs = await this.embassyApi.getServerLogs({ })
this.logs = logs.map(l => `${l.timestamp} ${l.log}`).join('\n\n')
setTimeout(async () => await this.content.scrollToBottom(100), 200)
} catch (e) {
diff --git a/ui/src/app/pages/server-routes/server-metrics/server-metrics.page.ts b/ui/src/app/pages/server-routes/server-metrics/server-metrics.page.ts
index 2c3056fbe..acee5718e 100644
--- a/ui/src/app/pages/server-routes/server-metrics/server-metrics.page.ts
+++ b/ui/src/app/pages/server-routes/server-metrics/server-metrics.page.ts
@@ -16,7 +16,7 @@ export class ServerMetricsPage {
constructor (
private readonly errToast: ErrorToastService,
- private readonly apiService: ApiService,
+ private readonly embassyApi: ApiService,
) { }
ngOnInit () {
@@ -41,7 +41,7 @@ export class ServerMetricsPage {
async getMetrics (): Promise {
try {
- this.metrics = await this.apiService.getServerMetrics({ })
+ this.metrics = await this.embassyApi.getServerMetrics({ })
} catch (e) {
console.error(e)
this.errToast.present(e.message)
diff --git a/ui/src/app/pages/server-routes/server-show/server-show.page.ts b/ui/src/app/pages/server-routes/server-show/server-show.page.ts
index 6e04e424e..9ea458d0d 100644
--- a/ui/src/app/pages/server-routes/server-show/server-show.page.ts
+++ b/ui/src/app/pages/server-routes/server-show/server-show.page.ts
@@ -16,7 +16,7 @@ export class ServerShowPage {
constructor (
private readonly alertCtrl: AlertController,
private readonly loader: LoaderService,
- private readonly apiService: ApiService,
+ private readonly embassyApi: ApiService,
private readonly navCtrl: NavController,
private readonly route: ActivatedRoute,
) { }
@@ -73,7 +73,7 @@ export class ServerShowPage {
this.loader
.of(LoadingSpinner(`Restarting...`))
.displayDuringAsync( async () => {
- await this.apiService.restartServer({ })
+ await this.embassyApi.restartServer({ })
})
.catch(console.error)
}
@@ -82,7 +82,7 @@ export class ServerShowPage {
this.loader
.of(LoadingSpinner(`Shutting down...`))
.displayDuringAsync( async () => {
- await this.apiService.shutdownServer({ })
+ await this.embassyApi.shutdownServer({ })
})
.catch(console.error)
}
@@ -91,9 +91,9 @@ export class ServerShowPage {
this.settings = {
'Settings': [
{
- title: 'Preferences',
- icon: 'cog-outline',
- action: () => this.navCtrl.navigateForward(['preferences'], { relativeTo: this.route }),
+ title: 'Privacy and Security',
+ icon: 'shield-checkmark-outline',
+ action: () => this.navCtrl.navigateForward(['privacy'], { relativeTo: this.route }),
},
{
title: 'LAN',
diff --git a/ui/src/app/pages/server-routes/wifi/wifi-add/wifi-add.page.ts b/ui/src/app/pages/server-routes/wifi/wifi-add/wifi-add.page.ts
index 347abe6b2..955d35df8 100644
--- a/ui/src/app/pages/server-routes/wifi/wifi-add/wifi-add.page.ts
+++ b/ui/src/app/pages/server-routes/wifi/wifi-add/wifi-add.page.ts
@@ -19,7 +19,7 @@ export class WifiAddPage {
constructor (
private readonly navCtrl: NavController,
private readonly errToast: ErrorToastService,
- private readonly apiService: ApiService,
+ private readonly embassyApi: ApiService,
private readonly loader: LoaderService,
private readonly wifiService: WifiService,
) { }
@@ -30,7 +30,7 @@ export class WifiAddPage {
spinner: 'lines',
cssClass: 'loader',
}).displayDuringAsync(async () => {
- await this.apiService.addWifi({
+ await this.embassyApi.addWifi({
ssid: this.ssid,
password: this.password,
country: this.countryCode,
@@ -50,7 +50,7 @@ export class WifiAddPage {
spinner: 'lines',
cssClass: 'loader',
}).displayDuringAsync(async () => {
- await this.apiService.addWifi({
+ await this.embassyApi.addWifi({
ssid: this.ssid,
password: this.password,
country: this.countryCode,
diff --git a/ui/src/app/pages/server-routes/wifi/wifi.page.ts b/ui/src/app/pages/server-routes/wifi/wifi.page.ts
index 133a70f72..b92a3f147 100644
--- a/ui/src/app/pages/server-routes/wifi/wifi.page.ts
+++ b/ui/src/app/pages/server-routes/wifi/wifi.page.ts
@@ -18,7 +18,7 @@ export class WifiListPage {
subs: Subscription[] = []
constructor (
- private readonly apiService: ApiService,
+ private readonly embassyApi: ApiService,
private readonly loader: LoaderService,
private readonly errToast: ErrorToastService,
private readonly actionCtrl: ActionSheetController,
@@ -62,7 +62,7 @@ export class WifiListPage {
spinner: 'lines',
cssClass: 'loader',
}).displayDuringAsync(async () => {
- await this.apiService.connectWifi({ ssid })
+ await this.embassyApi.connectWifi({ ssid })
this.wifiService.confirmWifi(ssid)
}).catch(e => {
console.error(e)
@@ -76,7 +76,7 @@ export class WifiListPage {
spinner: 'lines',
cssClass: 'loader',
}).displayDuringAsync(async () => {
- await this.apiService.deleteWifi({ ssid })
+ await this.embassyApi.deleteWifi({ ssid })
}).catch(e => {
console.error(e)
this.errToast.present(e.message)
diff --git a/ui/src/app/pipes/status.pipe.ts b/ui/src/app/pipes/status.pipe.ts
deleted file mode 100644
index f9fe7eb5e..000000000
--- a/ui/src/app/pipes/status.pipe.ts
+++ /dev/null
@@ -1,27 +0,0 @@
-import { Pipe, PipeTransform } from '@angular/core'
-import { combineLatest, Observable } from 'rxjs'
-import { map } from 'rxjs/operators'
-import { PatchDbService } from '../services/patch-db/patch-db.service'
-import { FEStatus, renderPkgStatus } from '../services/pkg-status-rendering.service'
-
-@Pipe({
- name: 'status',
-})
-export class StatusPipe implements PipeTransform {
-
- constructor (
- private readonly patch: PatchDbService,
- ) { }
-
- transform (pkgId: string): Observable {
- return combineLatest([
- this.patch.watch$('package-data', pkgId, 'state'),
- this.patch.watch$('package-data', pkgId, 'installed', 'status'),
- ])
- .pipe(
- map(([state, status]) => {
- return renderPkgStatus(state, status).feStatus
- }),
- )
- }
-}
\ No newline at end of file
diff --git a/ui/src/app/pipes/ui.pipe.ts b/ui/src/app/pipes/ui.pipe.ts
index e2d241700..8c2025a09 100644
--- a/ui/src/app/pipes/ui.pipe.ts
+++ b/ui/src/app/pipes/ui.pipe.ts
@@ -1,6 +1,6 @@
import { Pipe, PipeTransform } from '@angular/core'
-import { PackageDataEntry, Manifest } from '../services/patch-db/data-model'
-import { ConfigService, getManifest, hasUi } from '../services/config.service'
+import { PackageDataEntry } from '../services/patch-db/data-model'
+import { ConfigService, hasUi } from '../services/config.service'
@Pipe({
name: 'hasUi',
@@ -8,7 +8,7 @@ import { ConfigService, getManifest, hasUi } from '../services/config.service'
export class HasUiPipe implements PipeTransform {
transform (pkg: PackageDataEntry): boolean {
- const interfaces = getManifest(pkg).interfaces
+ const interfaces = pkg.manifest.interfaces
return hasUi(interfaces)
}
}
diff --git a/ui/src/app/services/api/api.fixures.ts b/ui/src/app/services/api/api.fixures.ts
index c2cc6315f..70c9d03a8 100644
--- a/ui/src/app/services/api/api.fixures.ts
+++ b/ui/src/app/services/api/api.fixures.ts
@@ -1,4 +1,4 @@
-import { DockerIoFormat, Manifest, PackageDataEntry, PackageMainStatus, PackageState } from 'src/app/services/patch-db/data-model'
+import { DependencyErrorType, DockerIoFormat, Manifest, PackageDataEntry, PackageMainStatus, PackageState } from 'src/app/services/patch-db/data-model'
import { MarketplacePkg, Metric, NotificationLevel, RR, ServerNotifications } from './api.types'
export module Mock {
@@ -1347,56 +1347,56 @@ export module Mock {
// 'install-progress': undefined,
// }
- // export const lnd: PackageDataEntry = {
- // state: PackageState.Installed,
- // 'static-files': {
- // license: 'licenseUrl', // /public/package-data/lnd/0.21.1/LICENSE.md,
- // icon: 'assets/img/service-icons/lnd.png',
- // instructions: 'instructionsUrl', // /public/package-data/lnd/0.21.1/INSTRUCTIONS.md
- // },
- // manifest: MockManifestLnd,
- // installed: {
- // status: {
- // configured: true,
- // main: {
- // status: PackageMainStatus.Stopped,
- // },
- // 'dependency-errors': {
- // 'bitcoin-proxy': {
- // type: DependencyErrorType.NotInstalled,
- // title: Mock.MockManifestBitcoinProxy.title,
- // icon: 'assets/img/service-icons/bitcoin-proxy.png',
- // },
- // },
- // },
- // 'interface-info': {
- // ip: '10.0.0.1',
- // addresses: {
- // rpc: {
- // 'tor-address': 'lnd-rpc-address.onion',
- // 'lan-address': 'lnd-rpc-address.local',
- // },
- // grpc: {
- // 'tor-address': 'lnd-grpc-address.onion',
- // 'lan-address': 'lnd-grpc-address.local',
- // },
- // },
- // },
- // 'system-pointers': [],
- // 'current-dependents': { },
- // 'current-dependencies': {
- // 'bitcoind': {
- // pointers: [],
- // 'health-checks': [],
- // },
- // 'bitcoin-proxy': {
- // pointers: [],
- // 'health-checks': [],
- // },
- // },
- // },
- // 'install-progress': undefined,
- // }
+ export const lnd: PackageDataEntry = {
+ state: PackageState.Installed,
+ 'static-files': {
+ license: 'licenseUrl', // /public/package-data/lnd/0.21.1/LICENSE.md,
+ icon: 'assets/img/service-icons/lnd.png',
+ instructions: 'instructionsUrl', // /public/package-data/lnd/0.21.1/INSTRUCTIONS.md
+ },
+ manifest: MockManifestLnd,
+ installed: {
+ status: {
+ configured: true,
+ main: {
+ status: PackageMainStatus.Stopped,
+ },
+ 'dependency-errors': {
+ 'bitcoin-proxy': {
+ type: DependencyErrorType.NotInstalled,
+ title: Mock.MockManifestBitcoinProxy.title,
+ icon: 'assets/img/service-icons/bitcoin-proxy.png',
+ },
+ },
+ },
+ 'interface-info': {
+ ip: '10.0.0.1',
+ addresses: {
+ rpc: {
+ 'tor-address': 'lnd-rpc-address.onion',
+ 'lan-address': 'lnd-rpc-address.local',
+ },
+ grpc: {
+ 'tor-address': 'lnd-grpc-address.onion',
+ 'lan-address': 'lnd-grpc-address.local',
+ },
+ },
+ },
+ 'system-pointers': [],
+ 'current-dependents': { },
+ 'current-dependencies': {
+ 'bitcoind': {
+ pointers: [],
+ 'health-checks': [],
+ },
+ 'bitcoin-proxy': {
+ pointers: [],
+ 'health-checks': [],
+ },
+ },
+ },
+ 'install-progress': undefined,
+ }
// export const DbDump: RR.GetDumpRes = {
// id: 1,
diff --git a/ui/src/app/services/api/embassy/embassy-mock-api.service.ts b/ui/src/app/services/api/embassy/embassy-mock-api.service.ts
index f384cf0eb..faca35f04 100644
--- a/ui/src/app/services/api/embassy/embassy-mock-api.service.ts
+++ b/ui/src/app/services/api/embassy/embassy-mock-api.service.ts
@@ -2,7 +2,7 @@ import { Injectable } from '@angular/core'
import { pauseFor } from '../../../util/misc.util'
import { ApiService } from './embassy-api.service'
import { Operation, PatchOp } from 'patch-db-client'
-import { PackageDataEntry, PackageMainStatus, PackageState, ServerStatus } from 'src/app/services/patch-db/data-model'
+import { DataModel, InstallProgress, PackageDataEntry, PackageMainStatus, PackageState, ServerStatus } from 'src/app/services/patch-db/data-model'
import { RR, WithRevision } from '../api.types'
import { parsePropertiesPermissive } from 'src/app/util/properties.util'
import { Mock } from '../api.fixures'
@@ -325,18 +325,19 @@ export class MockApiService extends ApiService {
async installPackageRaw (params: RR.InstallPackageReq): Promise {
await pauseFor(2000)
+ const initialProgress: InstallProgress = {
+ size: 120,
+ downloaded: 0,
+ 'download-complete': false,
+ validated: 0,
+ 'validation-complete': false,
+ unpacked: 0,
+ 'unpack-complete': false,
+ }
const pkg: PackageDataEntry = {
- ...Mock.bitcoinproxy,
+ ...Mock[params.id],
state: PackageState.Installing,
- 'install-progress': {
- size: 100,
- downloaded: 10,
- 'download-complete': false,
- validated: 1,
- 'validation-complete': true,
- read: 50,
- 'read-complete': false,
- },
+ 'install-progress': initialProgress,
}
const patch = [
{
@@ -345,7 +346,11 @@ export class MockApiService extends ApiService {
value: pkg,
},
]
- return this.http.rpcRequest>({ method: 'db.patch', params: { patch } })
+ const res = await this.http.rpcRequest>({ method: 'db.patch', params: { patch } })
+ setTimeout(async () => {
+ this.updateProgress(params.id, initialProgress)
+ }, 1000)
+ return res
}
async dryUpdatePackage (params: RR.DryUpdatePackageReq): Promise {
@@ -483,4 +488,45 @@ export class MockApiService extends ApiService {
await pauseFor(2000)
return { }
}
+
+ private async updateProgress (id: string, initialProgress: InstallProgress) {
+ const phases = [
+ { progress: 'downloaded', completion: 'download-complete'},
+ { progress: 'validated', completion: 'validation-complete'},
+ { progress: 'unpacked', completion: 'unpack-complete'},
+ ]
+ for (let phase of phases) {
+ let i = initialProgress[phase.progress]
+ console.log('PHASE', phase)
+ console.log('Initial i', i)
+ while (i < initialProgress.size) {
+ console.log(i)
+ await pauseFor(1000)
+ i = Math.min(i + 40, initialProgress.size)
+ initialProgress[phase.progress] = i
+ if (i === initialProgress.size) {
+ initialProgress[phase.completion] = true
+ }
+ const patch = [
+ {
+ op: PatchOp.REPLACE,
+ path: `/package-data/${id}/install-progress`,
+ value: initialProgress,
+ },
+ ]
+ await this.http.rpcRequest>({ method: 'db.patch', params: { patch } })
+ }
+ }
+
+ setTimeout(() => {
+ const patch = [
+ {
+ op: PatchOp.REPLACE,
+ path: `/package-data/${id}/state`,
+ value: PackageState.Installed,
+ },
+ ]
+ this.http.rpcRequest>({ method: 'db.patch', params: { patch } })
+ }, 1000)
+ }
}
diff --git a/ui/src/app/services/api/marketplace/marketplace-api.service.ts b/ui/src/app/services/api/marketplace/marketplace-api.service.ts
index eeb7f98b5..e8684bb2e 100644
--- a/ui/src/app/services/api/marketplace/marketplace-api.service.ts
+++ b/ui/src/app/services/api/marketplace/marketplace-api.service.ts
@@ -1,14 +1,28 @@
import { RR } from '../api.types'
import { ConfigService } from '../../config.service'
import { PatchDbService } from '../../patch-db/patch-db.service'
+import { ServerInfo } from '../../patch-db/data-model'
+import { AuthState } from '../../auth.service'
+import { takeWhile } from 'rxjs/operators'
export abstract class MarketplaceApiService {
+ private server: ServerInfo
constructor (
readonly config: ConfigService,
readonly patch: PatchDbService,
) { }
+ init (auth: AuthState) {
+ this.patch.watch$('server-info')
+ .pipe(
+ takeWhile(() => auth === AuthState.VERIFIED),
+ )
+ .subscribe(server => {
+ this.server = server
+ })
+ }
+
abstract getEos (params: RR.GetMarketplaceEOSReq): Promise
abstract getMarketplaceData (params: RR.GetMarketplaceDataReq): Promise
@@ -20,11 +34,11 @@ export abstract class MarketplaceApiService {
abstract getLatestVersion (params: RR.GetLatestVersionReq): Promise
getMarketplaceURL (type: 'eos' | 'package', defaultToTor = false): string {
- const packageMarketplace = this.patch.data['server-info']['package-marketplace']
+ const packageMarketplace = this.server['package-marketplace']
if (defaultToTor && !packageMarketplace) {
return this.config.start9Marketplace.tor
}
- const eosMarketplace = this.patch.data['server-info']['eos-marketplace'] || this.config.start9Marketplace.clearnet
+ const eosMarketplace = this.server['eos-marketplace'] || this.config.start9Marketplace.clearnet
if (type === 'eos') {
return eosMarketplace
} else {
diff --git a/ui/src/app/services/auth.service.ts b/ui/src/app/services/auth.service.ts
index 15be57add..12136c207 100644
--- a/ui/src/app/services/auth.service.ts
+++ b/ui/src/app/services/auth.service.ts
@@ -17,7 +17,7 @@ export class AuthService {
private readonly authState$: BehaviorSubject = new BehaviorSubject(AuthState.INITIALIZING)
constructor (
- private readonly api: ApiService,
+ private readonly embassyApi: ApiService,
private readonly storage: Storage,
) { }
@@ -31,7 +31,7 @@ export class AuthService {
}
async login (password: string): Promise {
- await this.api.login({ password })
+ await this.embassyApi.login({ password })
await this.storage.set(this.LOGGED_IN_KEY, true)
this.authState$.next(AuthState.VERIFIED)
}
diff --git a/ui/src/app/services/config.service.ts b/ui/src/app/services/config.service.ts
index 4f8dd8ed2..1f2727448 100644
--- a/ui/src/app/services/config.service.ts
+++ b/ui/src/app/services/config.service.ts
@@ -101,13 +101,6 @@ export function hasUi (interfaces: { [id: string]: InterfaceDef }): boolean {
return hasTorUi(interfaces) || hasLanUi(interfaces)
}
-export function getManifest (pkg: PackageDataEntry): Manifest {
- if (pkg.state === PackageState.Installed) {
- return pkg.manifest
- }
- return pkg['temp-manifest']
-}
-
function removeProtocol (str: string): string {
if (str.startsWith('http://')) return str.slice(7)
if (str.startsWith('https://')) return str.slice(8)
diff --git a/ui/src/app/services/connection.service.ts b/ui/src/app/services/connection.service.ts
index 351e0a2ff..cc2b35454 100644
--- a/ui/src/app/services/connection.service.ts
+++ b/ui/src/app/services/connection.service.ts
@@ -2,8 +2,9 @@ import { Injectable } from '@angular/core'
import { BehaviorSubject, combineLatest, fromEvent, merge, Subscription } from 'rxjs'
import { ConnectionStatus, PatchDbService } from './patch-db/patch-db.service'
import { HttpService, Method } from './http.service'
-import { distinctUntilChanged } from 'rxjs/operators'
+import { distinctUntilChanged, takeWhile } from 'rxjs/operators'
import { ConfigService } from './config.service'
+import { AuthState } from './auth.service'
@Injectable({
providedIn: 'root',
@@ -23,16 +24,35 @@ export class ConnectionService {
return this.connectionFailure$.asObservable()
}
- start () {
+ start (auth: AuthState) {
this.subs = [
merge(fromEvent(window, 'online'), fromEvent(window, 'offline'))
+ .pipe(
+ takeWhile(() => auth === AuthState.VERIFIED),
+ )
.subscribe(event => {
this.networkState$.next(event.type === 'online')
}),
- combineLatest([this.networkState$.pipe(distinctUntilChanged()), this.patch.watchConnection$().pipe(distinctUntilChanged())])
- .subscribe(async ([network, connectionStatus]) => {
- const addrs = this.patch.data['server-info']['connection-addresses']
+ combineLatest([
+ // 1
+ this.networkState$
+ .pipe(
+ distinctUntilChanged(),
+ ),
+ // 2
+ this.patch.watchConnection$()
+ .pipe(
+ distinctUntilChanged(),
+ ),
+ // 3
+ this.patch.watch$('server-info', 'connection-addresses')
+ .pipe(
+ takeWhile(() => auth === AuthState.VERIFIED),
+ distinctUntilChanged(),
+ ),
+ ])
+ .subscribe(async ([network, connectionStatus, addrs]) => {
if (connectionStatus !== ConnectionStatus.Disconnected) {
this.connectionFailure$.next(ConnectionFailure.None)
} else if (!network) {
@@ -61,13 +81,6 @@ export class ConnectionService {
]
}
- stop () {
- this.subs.forEach(sub => {
- sub.unsubscribe()
- })
- this.subs = []
- }
-
private async testAddrs (addrs: string[]): Promise {
if (!addrs.length) return true
diff --git a/ui/src/app/services/http.service.ts b/ui/src/app/services/http.service.ts
index e7c554b99..63a9fbb8c 100644
--- a/ui/src/app/services/http.service.ts
+++ b/ui/src/app/services/http.service.ts
@@ -70,6 +70,12 @@ export class HttpService {
this.fullUrl + httpOpts.url :
httpOpts.url
+ Object.keys(httpOpts.params).forEach(key => {
+ if (httpOpts.params[key] === undefined) {
+ delete httpOpts.params[key]
+ }
+ })
+
return {
observe: 'events',
responseType: 'json',
diff --git a/ui/src/app/services/patch-db/data-model.ts b/ui/src/app/services/patch-db/data-model.ts
index 63b1f1e98..05f66bbe2 100644
--- a/ui/src/app/services/patch-db/data-model.ts
+++ b/ui/src/app/services/patch-db/data-model.ts
@@ -62,8 +62,8 @@ export interface InstallProgress {
'download-complete': boolean
validated: number
'validation-complete': boolean
- read: number
- 'read-complete': boolean
+ unpacked: number
+ 'unpack-complete': boolean
}
export interface InstalledPackageDataEntry {
diff --git a/ui/src/app/services/patch-db/patch-db.factory.ts b/ui/src/app/services/patch-db/patch-db.factory.ts
index 068a0fd25..c58ce7f2b 100644
--- a/ui/src/app/services/patch-db/patch-db.factory.ts
+++ b/ui/src/app/services/patch-db/patch-db.factory.ts
@@ -8,7 +8,7 @@ import { ApiService } from 'src/app/services/api/embassy/embassy-api.service'
export function PatchDbServiceFactory (
config: ConfigService,
bootstrapper: LocalStorageBootstrap,
- apiService: ApiService,
+ embassyApi: ApiService,
): PatchDbService {
const { mocks, patchDb: { poll }, isConsulate } = config
@@ -17,13 +17,13 @@ export function PatchDbServiceFactory (
if (mocks.enabled) {
if (mocks.connection === 'poll') {
- source = new PollSource({ ...poll }, apiService)
+ source = new PollSource({ ...poll }, embassyApi)
} else {
source = new WebsocketSource(`ws://localhost:${config.mocks.wsPort}/db`)
}
} else {
if (isConsulate) {
- source = new PollSource({ ...poll }, apiService)
+ source = new PollSource({ ...poll }, embassyApi)
} else {
const protocol = window.location.protocol === 'http:' ? 'ws' : 'wss'
const host = window.location.host
@@ -31,5 +31,5 @@ export function PatchDbServiceFactory (
}
}
- return new PatchDbService(source, apiService, bootstrapper)
+ return new PatchDbService(source, embassyApi, bootstrapper)
}
\ No newline at end of file
diff --git a/ui/src/app/services/patch-db/patch-db.service.ts b/ui/src/app/services/patch-db/patch-db.service.ts
index a703ee08d..47649cadf 100644
--- a/ui/src/app/services/patch-db/patch-db.service.ts
+++ b/ui/src/app/services/patch-db/patch-db.service.ts
@@ -20,10 +20,11 @@ export enum ConnectionStatus {
})
export class PatchDbService {
connectionStatus$ = new BehaviorSubject(ConnectionStatus.Initializing)
- data: DataModel
private patchDb: PatchDB
private patchSub: Subscription
+ get data () { return this.patchDb.store.cache.data }
+
constructor (
@Inject(PATCH_SOURCE) private readonly source: Source,
@Inject(PATCH_HTTP) private readonly http: ApiService,
@@ -33,7 +34,6 @@ export class PatchDbService {
async init (): Promise {
const cache = await this.bootstrapper.init()
this.patchDb = new PatchDB([this.source, this.http], this.http, cache)
- this.data = this.patchDb.store.cache.data
}
start (): void {
@@ -44,7 +44,7 @@ export class PatchDbService {
.pipe(debounceTime(500))
.subscribe({
next: cache => {
- console.log('saving cacheee: ', cache)
+ console.log('saving cacheee: ', JSON.parse(JSON.stringify(cache)))
this.connectionStatus$.next(ConnectionStatus.Connected)
this.bootstrapper.update(cache)
},
@@ -82,8 +82,9 @@ export class PatchDbService {
watch$: Store['watch$'] = (...args: (string | number)[]): Observable => {
console.log('WATCHING', ...args)
- return this.patchDb.store.watch$(...(args as [])).pipe(
- tap(cache => console.log('CHANGE IN STORE', cache)),
+ return this.patchDb.store.watch$(...(args as []))
+ .pipe(
+ tap(data => console.log('CHANGE IN STORE', data, ...args)),
catchError(e => {
console.error(e)
return of(e.message)
diff --git a/ui/src/app/services/server-config.service.ts b/ui/src/app/services/server-config.service.ts
index 8ef590047..302e56d72 100644
--- a/ui/src/app/services/server-config.service.ts
+++ b/ui/src/app/services/server-config.service.ts
@@ -13,7 +13,7 @@ export class ServerConfigService {
constructor (
private readonly trackingModalCtrl: TrackingModalController,
- private readonly apiService: ApiService,
+ private readonly embassyApi: ApiService,
private readonly sshService: SSHService,
) { }
@@ -35,19 +35,19 @@ export class ServerConfigService {
saveFns: { [key: string]: (val: any) => Promise } = {
autoCheckUpdates: async (value: boolean) => {
- return this.apiService.setDbValue({ pointer: 'ui/auto-check-updates', value })
+ return this.embassyApi.setDbValue({ pointer: 'ui/auto-check-updates', value })
},
ssh: async (pubkey: string) => {
return this.sshService.add(pubkey)
},
eosMarketplace: async (enabled: boolean) => {
- return this.apiService.setEosMarketplace(enabled)
+ return this.embassyApi.setEosMarketplace(enabled)
},
// packageMarketplace: async (url: string) => {
- // return this.apiService.setPackageMarketplace({ url })
+ // return this.embassyApi.setPackageMarketplace({ url })
// },
// password: async (password: string) => {
- // return this.apiService.updatePassword({ password })
+ // return this.embassyApi.updatePassword({ password })
// },
}
}
diff --git a/ui/src/app/services/startup-alerts.service.ts b/ui/src/app/services/startup-alerts.service.ts
index 9e9128103..64af9f4c3 100644
--- a/ui/src/app/services/startup-alerts.service.ts
+++ b/ui/src/app/services/startup-alerts.service.ts
@@ -5,17 +5,21 @@ import { WizardBaker } from '../components/install-wizard/prebaked-wizards'
import { OSWelcomePage } from '../modals/os-welcome/os-welcome.page'
import { displayEmver } from '../pipes/emver.pipe'
import { RR } from './api/api.types'
-import { PatchDbService } from './patch-db/patch-db.service'
import { ConfigService } from './config.service'
import { Emver } from './emver.service'
import { MarketplaceService } from '../pages/marketplace-routes/marketplace.service'
import { MarketplaceApiService } from './api/marketplace/marketplace-api.service'
+import { DataModel, PackageDataEntry } from './patch-db/data-model'
+import { PatchDbService } from './patch-db/patch-db.service'
+import { filter, take } from 'rxjs/operators'
+import { isEmptyObject } from '../util/misc.util'
@Injectable({
providedIn: 'root',
})
export class StartupAlertsService {
private checks: Check[]
+ data: DataModel
constructor (
private readonly alertCtrl: AlertController,
@@ -57,7 +61,14 @@ export class StartupAlertsService {
// Each promise fires more or less concurrently, so each c.check(server) is run concurrently
// Then, since we await previousDisplay before c.display(res), each promise executing gets hung awaiting the display of the previous run
async runChecks (): Promise {
- await this.checks
+ this.patch.watch$()
+ .pipe(
+ filter(data => !isEmptyObject(data)),
+ take(1),
+ )
+ .subscribe(async data => {
+ this.data = data
+ await this.checks
.filter(c => !c.hasRun && c.shouldRun())
// returning true in the below block means to continue to next modal
// returning false means to skip all subsequent modals
@@ -76,18 +87,19 @@ export class StartupAlertsService {
if (!checkRes) return true
if (displayRes) return c.display(checkRes)
}, Promise.resolve(true))
+ })
}
private shouldRunOsWelcome (): boolean {
- return this.patch.data.ui['welcome-ack'] !== this.config.version
+ return this.data.ui['welcome-ack'] !== this.config.version
}
private shouldRunOsUpdateCheck (): boolean {
- return this.patch.data.ui['auto-check-updates']
+ return this.data.ui['auto-check-updates']
}
private shouldRunAppsCheck (): boolean {
- return this.patch.data.ui['auto-check-updates']
+ return this.data.ui['auto-check-updates']
}
private async osUpdateCheck (): Promise {
@@ -101,8 +113,8 @@ export class StartupAlertsService {
}
private async appsCheck (): Promise {
- const updates = await this.marketplaceService.getUpdates(this.patch.data['package-data'])
- return !!updates.length
+ await this.marketplaceService.getUpdates(this.data['package-data'])
+ return !!this.marketplaceService.updates.length
}
private async displayOsWelcome (): Promise {