mirror of
https://github.com/Start9Labs/start-os.git
synced 2026-03-26 02:11:53 +00:00
remove share-stats, cosmetic improvements
This commit is contained in:
committed by
Keagan McClelland
parent
5326de9b84
commit
20acd8efea
@@ -15,9 +15,10 @@
|
||||
"build:setup-wizard": "ng run setup-wizard:build",
|
||||
"build:ui": "ng run ui:build && tsc projects/ui/postprocess.ts && node projects/ui/postprocess.js && git log | head -n1 > dist/ui/git-hash.txt",
|
||||
"build:all": "npm run build:deps && npm run build:diagnostic-ui && npm run build:setup-wizard && npm run build:ui",
|
||||
"start:diagnostic-ui": "ionic serve --project diagnostic-ui",
|
||||
"start:setup-wizard": "ionic serve --project setup-wizard",
|
||||
"start:ui": "ionic serve --project ui"
|
||||
"start:diagnostic-ui": "npm run copy-git-hash && ionic serve --project diagnostic-ui",
|
||||
"start:setup-wizard": "npm run copy-git-hash && ionic serve --project setup-wizard",
|
||||
"start:ui": "npm run copy-git-hash && ionic serve --project ui",
|
||||
"copy-git-hash": "./update-git-hash.sh"
|
||||
},
|
||||
"dependencies": {
|
||||
"@angular/animations": "^13.2.0",
|
||||
|
||||
@@ -49,7 +49,7 @@
|
||||
<ion-icon
|
||||
*ngIf="eosService.updateAvailable$ | async"
|
||||
color="success"
|
||||
name="repeat"
|
||||
name="rocket-outline"
|
||||
></ion-icon>
|
||||
</ng-container>
|
||||
<ion-badge
|
||||
@@ -162,7 +162,7 @@
|
||||
<ion-icon name="reload"></ion-icon>
|
||||
<ion-icon name="remove"></ion-icon>
|
||||
<ion-icon name="remove-circle-outline"></ion-icon>
|
||||
<ion-icon name="repeat"></ion-icon>
|
||||
<ion-icon name="rocket-outline"></ion-icon>
|
||||
<ion-icon name="save-outline"></ion-icon>
|
||||
<ion-icon name="shield-checkmark-outline"></ion-icon>
|
||||
<ion-icon name="storefront-outline"></ion-icon>
|
||||
|
||||
@@ -13,6 +13,7 @@ import {
|
||||
AlertController,
|
||||
IonicSafeString,
|
||||
LoadingController,
|
||||
ModalController,
|
||||
ToastController,
|
||||
} from '@ionic/angular'
|
||||
import { Emver } from './services/emver.service'
|
||||
@@ -24,7 +25,6 @@ import {
|
||||
ConnectionFailure,
|
||||
ConnectionService,
|
||||
} from './services/connection.service'
|
||||
import { StartupAlertsService } from './services/startup-alerts.service'
|
||||
import { ConfigService } from './services/config.service'
|
||||
import { debounce, isEmptyObject } from './util/misc.util'
|
||||
import { ErrorToastService } from './services/error-toast.service'
|
||||
@@ -32,6 +32,7 @@ import { Subscription } from 'rxjs'
|
||||
import { LocalStorageService } from './services/local-storage.service'
|
||||
import { EOSService } from './services/eos.service'
|
||||
import { MarketplaceService } from './pages/marketplace-routes/marketplace.service'
|
||||
import { OSWelcomePage } from './modals/os-welcome/os-welcome.page'
|
||||
|
||||
@Component({
|
||||
selector: 'app-root',
|
||||
@@ -95,7 +96,7 @@ export class AppComponent {
|
||||
private readonly loadingCtrl: LoadingController,
|
||||
private readonly emver: Emver,
|
||||
private readonly connectionService: ConnectionService,
|
||||
private readonly startupAlertsService: StartupAlertsService,
|
||||
private readonly modalCtrl: ModalController,
|
||||
private readonly marketplaceService: MarketplaceService,
|
||||
private readonly toastCtrl: ToastController,
|
||||
private readonly errToast: ErrorToastService,
|
||||
@@ -146,6 +147,8 @@ export class AppComponent {
|
||||
.subscribe(data => {
|
||||
// check for updates to EOS
|
||||
this.checkForEosUpdate(data.ui)
|
||||
// show eos welcome message
|
||||
this.showEosWelcome(data.ui['ack-welcome'])
|
||||
|
||||
this.subscriptions = this.subscriptions.concat([
|
||||
// watch status to present toast for updated state
|
||||
@@ -158,8 +161,6 @@ export class AppComponent {
|
||||
this.watchNotifications(),
|
||||
// watch marketplace URL for changes
|
||||
this.marketplaceService.init(),
|
||||
// run startup alerts
|
||||
this.startupAlertsService.runChecks(),
|
||||
])
|
||||
})
|
||||
// UNVERIFIED
|
||||
@@ -214,9 +215,27 @@ export class AppComponent {
|
||||
await alert.present()
|
||||
}
|
||||
|
||||
private async checkForEosUpdate (ui: UIData): Promise<void> {
|
||||
private checkForEosUpdate(ui: UIData): void {
|
||||
if (ui['auto-check-updates']) {
|
||||
await this.eosService.getEOS()
|
||||
this.eosService.getEOS()
|
||||
}
|
||||
}
|
||||
|
||||
private async showEosWelcome(ackVersion: string): Promise<void> {
|
||||
if (!this.config.skipStartupAlerts && ackVersion !== this.config.version) {
|
||||
const modal = await this.modalCtrl.create({
|
||||
component: OSWelcomePage,
|
||||
presentingElement: await this.modalCtrl.getTop(),
|
||||
componentProps: {
|
||||
version: this.config.version,
|
||||
},
|
||||
})
|
||||
modal.onWillDismiss().then(() => {
|
||||
this.embassyApi
|
||||
.setDbValue({ pointer: '/ack-welcome', value: this.config.version })
|
||||
.catch()
|
||||
})
|
||||
modal.present()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -15,16 +15,6 @@
|
||||
<ion-note slot="end">{{ patch.data.ui.name || defaultName }}</ion-note>
|
||||
</ion-item>
|
||||
|
||||
<ion-item
|
||||
button
|
||||
(click)="serverConfig.presentAlert('share-stats', server['share-stats'])"
|
||||
>
|
||||
<ion-label>Auto Report Bugs</ion-label>
|
||||
<ion-note slot="end"
|
||||
>{{ server['share-stats'] ? 'Enabled' : 'Disabled' }}</ion-note
|
||||
>
|
||||
</ion-item>
|
||||
|
||||
<ion-item-divider>Marketplace</ion-item-divider>
|
||||
<ion-item
|
||||
button
|
||||
|
||||
@@ -28,9 +28,9 @@ export class PreferencesPage {
|
||||
private readonly loadingCtrl: LoadingController,
|
||||
private readonly modalCtrl: ModalController,
|
||||
private readonly api: ApiService,
|
||||
public readonly serverConfig: ServerConfigService,
|
||||
private readonly toastCtrl: ToastController,
|
||||
private readonly localStorageService: LocalStorageService,
|
||||
public readonly serverConfig: ServerConfigService,
|
||||
public readonly patch: PatchDbService,
|
||||
) {}
|
||||
|
||||
|
||||
@@ -59,19 +59,21 @@
|
||||
</span>
|
||||
</ng-container>
|
||||
</p>
|
||||
|
||||
<!-- "Software Update" button only -->
|
||||
<p *ngIf="button.title === 'Software Update'">
|
||||
<ng-container
|
||||
*ngIf="eosService.updateAvailable$ | async; else check"
|
||||
>
|
||||
<ion-text class="inline" color="success">
|
||||
<ion-icon name="repeat"></ion-icon>
|
||||
<ion-icon name="rocket-outline"></ion-icon>
|
||||
Update Available
|
||||
</ion-text>
|
||||
</ng-container>
|
||||
<ng-template #check>
|
||||
<i>Check for updates</i>
|
||||
<ion-text class="inline" color="dark">
|
||||
<ion-icon name="refresh"></ion-icon>
|
||||
Check for updates
|
||||
</ion-text>
|
||||
</ng-template>
|
||||
</p>
|
||||
</ion-label>
|
||||
|
||||
@@ -204,7 +204,10 @@ export class ServerShowPage {
|
||||
await loader.present()
|
||||
|
||||
try {
|
||||
await this.eosService.getEOS()
|
||||
const updateAvailable = await this.eosService.getEOS()
|
||||
if (updateAvailable) {
|
||||
this.updateEos()
|
||||
}
|
||||
} catch (e) {
|
||||
this.errToast.present(e)
|
||||
} finally {
|
||||
|
||||
@@ -28,9 +28,6 @@ export module RR {
|
||||
|
||||
// server
|
||||
|
||||
export type SetShareStatsReq = WithExpire<{ value: boolean }> // server.config.share-stats
|
||||
export type SetShareStatsRes = WithRevision<null>
|
||||
|
||||
export type GetServerLogsReq = {
|
||||
cursor?: string
|
||||
before_flag?: boolean
|
||||
|
||||
@@ -51,12 +51,6 @@ export abstract class ApiService implements Source<DataModel>, Http<DataModel> {
|
||||
|
||||
// server
|
||||
|
||||
protected abstract setShareStatsRaw(
|
||||
params: RR.SetShareStatsReq,
|
||||
): Promise<RR.SetShareStatsRes>
|
||||
setShareStats = (params: RR.SetShareStatsReq) =>
|
||||
this.syncResponse(() => this.setShareStatsRaw(params))()
|
||||
|
||||
abstract getServerLogs(
|
||||
params: RR.GetServerLogsReq,
|
||||
): Promise<RR.GetServerLogsRes>
|
||||
|
||||
@@ -57,12 +57,6 @@ export class LiveApiService extends ApiService {
|
||||
|
||||
// server
|
||||
|
||||
async setShareStatsRaw(
|
||||
params: RR.SetShareStatsReq,
|
||||
): Promise<RR.SetShareStatsRes> {
|
||||
return this.http.rpcRequest({ method: 'server.config.share-stats', params })
|
||||
}
|
||||
|
||||
async getServerLogs(
|
||||
params: RR.GetServerLogsReq,
|
||||
): Promise<RR.GetServerLogsRes> {
|
||||
|
||||
@@ -90,21 +90,6 @@ export class MockApiService extends ApiService {
|
||||
|
||||
// server
|
||||
|
||||
async setShareStatsRaw (
|
||||
params: RR.SetShareStatsReq,
|
||||
): Promise<RR.SetShareStatsRes> {
|
||||
await pauseFor(2000)
|
||||
const patch = [
|
||||
{
|
||||
op: PatchOp.REPLACE,
|
||||
path: '/server-info/share-stats',
|
||||
value: params.value,
|
||||
},
|
||||
]
|
||||
|
||||
return this.withRevision(patch)
|
||||
}
|
||||
|
||||
async getServerLogs(
|
||||
params: RR.GetServerLogsReq,
|
||||
): Promise<RR.GetServerLogsRes> {
|
||||
|
||||
@@ -15,7 +15,6 @@ export const mockPatchData: DataModel = {
|
||||
'auto-check-updates': true,
|
||||
'pkg-order': [],
|
||||
'ack-welcome': '1.0.0',
|
||||
'ack-share-stats': false,
|
||||
marketplace: undefined,
|
||||
},
|
||||
'server-info': {
|
||||
@@ -25,9 +24,6 @@ export const mockPatchData: DataModel = {
|
||||
status: ServerStatus.Running,
|
||||
'lan-address': 'https://embassy-abcdefgh.local',
|
||||
'tor-address': 'http://myveryownspecialtoraddress.onion',
|
||||
'eos-marketplace': 'https://beta-registry-0-3.start9labs.com',
|
||||
'package-marketplace': null,
|
||||
'share-stats': false,
|
||||
'unread-notification-count': 4,
|
||||
'password-hash':
|
||||
'$argon2d$v=19$m=1024,t=1,p=1$YXNkZmFzZGZhc2RmYXNkZg$Ceev1I901G6UwU+hY0sHrFZ56D+o+LNJ',
|
||||
|
||||
@@ -18,7 +18,7 @@ export class EOSService {
|
||||
private readonly patch: PatchDbService,
|
||||
) {}
|
||||
|
||||
async getEOS(): Promise<void> {
|
||||
async getEOS(): Promise<boolean> {
|
||||
this.eos = await this.api.getEos({
|
||||
'eos-version-compat':
|
||||
this.patch.getData()['server-info']['eos-version-compat'],
|
||||
@@ -29,5 +29,6 @@ export class EOSService {
|
||||
this.patch.data['server-info'].version,
|
||||
) === 1
|
||||
this.updateAvailable$.next(updateAvailable)
|
||||
return updateAvailable
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,7 +12,6 @@ export interface UIData {
|
||||
'auto-check-updates': boolean
|
||||
'pkg-order': string[]
|
||||
'ack-welcome': string // EOS version
|
||||
'ack-share-stats': boolean
|
||||
marketplace: UIMarketplaceData
|
||||
}
|
||||
|
||||
@@ -33,9 +32,6 @@ export interface ServerInfo {
|
||||
'lan-address': URL
|
||||
'tor-address': URL
|
||||
status: ServerStatus
|
||||
'eos-marketplace': URL
|
||||
'package-marketplace': URL | null // uses EOS marketplace if null
|
||||
'share-stats': boolean
|
||||
'unread-notification-count': number
|
||||
'update-progress'?: {
|
||||
size: number
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { Injectable } from '@angular/core'
|
||||
import { AlertInput, AlertButton, IonicSafeString } from '@ionic/core'
|
||||
import { AlertInput, AlertButton } from '@ionic/core'
|
||||
import { ApiService } from './api/embassy-api.service'
|
||||
import { ConfigSpec } from '../pkg-config/config-types'
|
||||
import { AlertController, LoadingController } from '@ionic/angular'
|
||||
@@ -104,9 +104,6 @@ export class ServerConfigService {
|
||||
value: enabled,
|
||||
})
|
||||
},
|
||||
'share-stats': async (enabled: boolean) => {
|
||||
return this.embassyApi.setShareStats({ value: enabled })
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
@@ -115,15 +112,7 @@ export const serverConfig: ConfigSpec = {
|
||||
type: 'boolean',
|
||||
name: 'Auto Check for Updates',
|
||||
description:
|
||||
'If enabled, EmbassyOS will automatically check for updates of itself and any installed services. Updating will still require your approval and action. Updates will never be performed automatically.',
|
||||
'If enabled, EmbassyOS will automatically check for updates of itself. Updating will still require your approval and action. Updates will never be performed automatically.',
|
||||
default: true,
|
||||
},
|
||||
'share-stats': {
|
||||
type: 'boolean',
|
||||
name: 'Report Bugs',
|
||||
description: new IonicSafeString(
|
||||
`If enabled, generic error codes will be anonymously transmitted over Tor to the Start9 team. This helps us identify and fix bugs quickly. <a href="https://docs.start9.com/user-manual/general/user-preferences/report-bugs.html" target="_blank" rel="noreferrer">Read more</a> `,
|
||||
) as any,
|
||||
default: false,
|
||||
},
|
||||
}
|
||||
|
||||
@@ -1,125 +0,0 @@
|
||||
import { Injectable } from '@angular/core'
|
||||
import { ModalController } from '@ionic/angular'
|
||||
import { WizardBaker } from '../components/install-wizard/prebaked-wizards'
|
||||
import { OSWelcomePage } from '../modals/os-welcome/os-welcome.page'
|
||||
import { ConfigService } from './config.service'
|
||||
import { PatchDbService } from './patch-db/patch-db.service'
|
||||
import { filter, take } from 'rxjs/operators'
|
||||
import { isEmptyObject } from '../util/misc.util'
|
||||
import { ApiService } from './api/embassy-api.service'
|
||||
import { Subscription } from 'rxjs'
|
||||
import { ServerConfigService } from './server-config.service'
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root',
|
||||
})
|
||||
export class StartupAlertsService {
|
||||
private checks: Check<any>[]
|
||||
|
||||
constructor(
|
||||
private readonly config: ConfigService,
|
||||
private readonly modalCtrl: ModalController,
|
||||
private readonly api: ApiService,
|
||||
private readonly wizardBaker: WizardBaker,
|
||||
private readonly patch: PatchDbService,
|
||||
private readonly serverConfig: ServerConfigService,
|
||||
) {
|
||||
const osWelcome: Check<boolean> = {
|
||||
name: 'osWelcome',
|
||||
shouldRun: () => this.shouldRunOsWelcome(),
|
||||
display: () => this.displayOsWelcome(),
|
||||
}
|
||||
const shareStats: Check<boolean> = {
|
||||
name: 'shareStats',
|
||||
shouldRun: () => this.shouldRunShareStats(),
|
||||
display: () => this.displayShareStats(),
|
||||
}
|
||||
this.checks = [osWelcome, shareStats]
|
||||
}
|
||||
|
||||
// This takes our three checks and filters down to those that should run.
|
||||
// Then, the reduce fires, quickly iterating through yielding a promise (previousDisplay) to the next element
|
||||
// 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
|
||||
runChecks(): Subscription {
|
||||
return this.patch
|
||||
.watch$()
|
||||
.pipe(
|
||||
filter(data => !isEmptyObject(data)),
|
||||
take(1),
|
||||
)
|
||||
.subscribe(async () => {
|
||||
await this.checks
|
||||
.filter(c => !this.config.skipStartupAlerts && c.shouldRun())
|
||||
// returning true in the below block means to continue to next modal
|
||||
// returning false means to skip all subsequent modals
|
||||
.reduce(async (previousDisplay, c) => {
|
||||
const displayRes = await previousDisplay
|
||||
if (displayRes) return c.display()
|
||||
}, Promise.resolve(true))
|
||||
})
|
||||
}
|
||||
|
||||
// ** should run **
|
||||
|
||||
private shouldRunOsWelcome(): boolean {
|
||||
return this.patch.getData().ui['ack-welcome'] !== this.config.version
|
||||
}
|
||||
private shouldRunShareStats(): boolean {
|
||||
return !this.patch.getData().ui['ack-share-stats']
|
||||
}
|
||||
|
||||
private shouldRunOsUpdateCheck(): boolean {
|
||||
return this.patch.getData().ui['auto-check-updates']
|
||||
}
|
||||
|
||||
// ** display **
|
||||
|
||||
private async displayOsWelcome(): Promise<boolean> {
|
||||
return new Promise(async resolve => {
|
||||
const modal = await this.modalCtrl.create({
|
||||
component: OSWelcomePage,
|
||||
presentingElement: await this.modalCtrl.getTop(),
|
||||
componentProps: {
|
||||
version: this.config.version,
|
||||
},
|
||||
})
|
||||
modal.onWillDismiss().then(() => {
|
||||
this.api
|
||||
.setDbValue({ pointer: '/ack-welcome', value: this.config.version })
|
||||
.catch()
|
||||
return resolve(true)
|
||||
})
|
||||
await modal.present()
|
||||
})
|
||||
}
|
||||
|
||||
private async displayShareStats(): Promise<boolean> {
|
||||
return new Promise(async resolve => {
|
||||
const alert = await this.serverConfig.presentAlert(
|
||||
'share-stats',
|
||||
this.patch.getData()['server-info']['share-stats'],
|
||||
)
|
||||
|
||||
alert.onDidDismiss().then(() => {
|
||||
this.api
|
||||
.setDbValue({
|
||||
pointer: '/ack-share-stats',
|
||||
value: this.config.version,
|
||||
})
|
||||
.catch()
|
||||
return resolve(true)
|
||||
})
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
type Check<T> = {
|
||||
// validates whether a check should run based on server properties
|
||||
shouldRun: () => boolean
|
||||
// display an alert based on the result of the check.
|
||||
// return false if subsequent modals should not be displayed
|
||||
display: () => Promise<boolean>
|
||||
// for logging purposes
|
||||
name: string
|
||||
}
|
||||
7
frontend/update-git-hash.sh
Executable file
7
frontend/update-git-hash.sh
Executable file
@@ -0,0 +1,7 @@
|
||||
#!/bin/bash
|
||||
|
||||
cd "$(dirname "$0")"
|
||||
|
||||
TMP_FILE=$(mktemp)
|
||||
|
||||
jq ".gitHash = \"$(git rev-parse HEAD)\"" config.json > $TMP_FILE && mv $TMP_FILE config.json
|
||||
Reference in New Issue
Block a user