mirror of
https://github.com/Start9Labs/start-os.git
synced 2026-03-30 20:14:49 +00:00
alpha.16 (#3068)
* add support for idmapped mounts to start-sdk * misc fixes * misc fixes * add default to textarea * fix iptables masquerade rule * fix textarea types * more fixes * better logging for rsync * fix tty size * fix wg conf generation for android * disable file mounts on dependencies * mostly there, some styling issues (#3069) * mostly there, some styling issues * fix: address comments (#3070) * fix: address comments * fix: fix * show SSL for any address with secure protocol and ssl added * better sorting and messaging --------- Co-authored-by: Alex Inkin <alexander@inkin.ru> * fixes for nextcloud * allow sidebar navigation during service state traansitions * wip: x-forwarded headers * implement x-forwarded-for proxy * lowercase domain names and fix warning popover bug * fix http2 websockets * fix websocket retry behavior * add arch filters to s9pk pack * use docker for start-cli install * add version range to package signer on registry * fix rcs < 0 * fix user information parsing * refactor service interface getters * disable idmaps * build fixes * update docker login action * streamline build * add start-cli workflow * rename * riscv64gc * fix ui packing * no default features on cli * make cli depend on GIT_HASH * more build fixes * more build fixes * interpolate arch within dockerfile * fix tests * add launch ui to service page plus other small improvements (#3075) * add launch ui to service page plus other small improvements * revert translation disable * add spinner to service list if service is health and loading * chore: some visual tune up * chore: update Taiga UI --------- Co-authored-by: waterplea <alexander@inkin.ru> * fix backups * feat: use arm hosted runners and don't fail when apt package does not exist (#3076) --------- Co-authored-by: Matt Hill <mattnine@protonmail.com> Co-authored-by: Shadowy Super Coder <musashidisciple@proton.me> Co-authored-by: Matt Hill <MattDHill@users.noreply.github.com> Co-authored-by: Alex Inkin <alexander@inkin.ru> Co-authored-by: Remco Ros <remcoros@live.nl>
This commit is contained in:
@@ -27,6 +27,7 @@ const allowedStatuses = {
|
||||
'stopping',
|
||||
'starting',
|
||||
'backing-up',
|
||||
'task-required',
|
||||
]),
|
||||
}
|
||||
|
||||
|
||||
@@ -1395,6 +1395,7 @@ export namespace Mock {
|
||||
name: 'Color',
|
||||
required: false,
|
||||
default: null,
|
||||
immutable: true,
|
||||
}),
|
||||
datetime: ISB.Value.datetime({
|
||||
name: 'Datetime',
|
||||
@@ -1481,6 +1482,7 @@ export namespace Mock {
|
||||
description:
|
||||
'<ul><li>determines whether your node is running on testnet or mainnet</li></ul><script src="fake"></script>',
|
||||
warning: 'Chain will have to resync!',
|
||||
immutable: true,
|
||||
}),
|
||||
'object-list': ISB.Value.list(
|
||||
ISB.List.obj(
|
||||
@@ -1598,6 +1600,8 @@ export namespace Mock {
|
||||
option1: 'option1',
|
||||
option2: 'option2',
|
||||
option3: 'option3',
|
||||
option4:
|
||||
'https://qwertyuiopasdfghjklzxcvbnmqwertyuiopasdfghjklzxcvbnm12345.onion',
|
||||
},
|
||||
disabled: ['option2'],
|
||||
})),
|
||||
@@ -1610,6 +1614,7 @@ export namespace Mock {
|
||||
default: 7,
|
||||
integer: false,
|
||||
units: 'BTC',
|
||||
placeholder: 'Is it 237?',
|
||||
min: -100,
|
||||
max: 100,
|
||||
}),
|
||||
|
||||
@@ -1089,7 +1089,7 @@ export class MockApiService extends ApiService {
|
||||
health: {
|
||||
'ephemeral-health-check': {
|
||||
name: 'Ephemeral Health Check',
|
||||
result: 'starting',
|
||||
result: 'success',
|
||||
message: null,
|
||||
},
|
||||
'unnecessary-health-check': {
|
||||
|
||||
@@ -47,6 +47,7 @@ export const mockPatchData: DataModel = {
|
||||
addSsl: {
|
||||
preferredExternalPort: 443,
|
||||
alpn: { specified: ['http/1.1', 'h2'] },
|
||||
addXForwardedHeaders: false,
|
||||
},
|
||||
secure: null,
|
||||
},
|
||||
|
||||
@@ -44,7 +44,7 @@ export interface DependencyErrorTaskRequired {
|
||||
|
||||
export type DependencyErrorHealthChecksFailed = {
|
||||
type: 'healthChecksFailed'
|
||||
check: T.NamedHealthCheckResult
|
||||
check?: T.NamedHealthCheckResult
|
||||
}
|
||||
|
||||
export type DependencyErrorTransitive = {
|
||||
@@ -164,10 +164,10 @@ export class DepErrorService {
|
||||
}
|
||||
|
||||
// health check failure
|
||||
if (depStatus === 'running' && currentDep?.kind === 'running') {
|
||||
if (currentDep?.kind === 'running') {
|
||||
for (let id of currentDep.healthChecks) {
|
||||
const check = dep.statusInfo.health[id]
|
||||
if (check && check?.result !== 'success') {
|
||||
if (check?.result !== 'success') {
|
||||
return {
|
||||
type: 'healthChecksFailed',
|
||||
check,
|
||||
|
||||
@@ -93,8 +93,12 @@ export class FormService {
|
||||
}
|
||||
return this.formBuilder.control(value, stringValidators(spec))
|
||||
case 'textarea':
|
||||
value = currentValue || null
|
||||
return this.formBuilder.control(value, textareaValidators(spec))
|
||||
if (currentValue !== undefined) {
|
||||
value = currentValue
|
||||
} else {
|
||||
value = spec.default || null
|
||||
}
|
||||
return this.formBuilder.control(value, stringValidators(spec))
|
||||
case 'number':
|
||||
if (currentValue !== undefined) {
|
||||
value = currentValue
|
||||
@@ -156,7 +160,7 @@ export class FormService {
|
||||
// }
|
||||
|
||||
function stringValidators(
|
||||
spec: IST.ValueSpecText | IST.ListValueSpecText,
|
||||
spec: IST.ValueSpecText | IST.ValueSpecTextarea | IST.ListValueSpecText,
|
||||
): ValidatorFn[] {
|
||||
const validators: ValidatorFn[] = []
|
||||
|
||||
@@ -173,18 +177,6 @@ function stringValidators(
|
||||
return validators
|
||||
}
|
||||
|
||||
function textareaValidators(spec: IST.ValueSpecTextarea): ValidatorFn[] {
|
||||
const validators: ValidatorFn[] = []
|
||||
|
||||
if (spec.required) {
|
||||
validators.push(Validators.required)
|
||||
}
|
||||
|
||||
validators.push(textLengthInRange(spec.minLength, spec.maxLength))
|
||||
|
||||
return validators
|
||||
}
|
||||
|
||||
function colorValidators({ required }: IST.ValueSpecColor): ValidatorFn[] {
|
||||
const validators: ValidatorFn[] = [Validators.pattern(/^#[0-9a-f]{6}$/i)]
|
||||
|
||||
|
||||
@@ -6,12 +6,9 @@ import {
|
||||
MARKDOWN,
|
||||
} from '@start9labs/shared'
|
||||
import { PatchDB } from 'patch-db-client'
|
||||
import { firstValueFrom, merge, of, shareReplay, Subject } from 'rxjs'
|
||||
import { merge, of, shareReplay, Subject } from 'rxjs'
|
||||
import { REPORT } from 'src/app/components/backup-report.component'
|
||||
import {
|
||||
ServerNotification,
|
||||
ServerNotifications,
|
||||
} from 'src/app/services/api/api.types'
|
||||
import { ServerNotification } from 'src/app/services/api/api.types'
|
||||
import { ApiService } from 'src/app/services/api/embassy-api.service'
|
||||
import { DataModel } from 'src/app/services/patch-db/data-model'
|
||||
|
||||
@@ -28,16 +25,6 @@ export class NotificationService {
|
||||
this.localUnreadCount$,
|
||||
).pipe(shareReplay(1))
|
||||
|
||||
async markSeen(notifications: ServerNotifications) {
|
||||
const ids = notifications.filter(n => !n.seen).map(n => n.id)
|
||||
|
||||
this.updateCount(-ids.length)
|
||||
|
||||
this.api
|
||||
.markSeenNotifications({ ids })
|
||||
.catch(e => this.errorService.handleError(e))
|
||||
}
|
||||
|
||||
async markSeenAll(latestId: number) {
|
||||
this.localUnreadCount$.next(0)
|
||||
|
||||
@@ -46,24 +33,6 @@ export class NotificationService {
|
||||
.catch(e => this.errorService.handleError(e))
|
||||
}
|
||||
|
||||
async markUnseen(notifications: ServerNotifications) {
|
||||
const ids = notifications.filter(n => n.seen).map(n => n.id)
|
||||
|
||||
this.updateCount(ids.length)
|
||||
|
||||
this.api
|
||||
.markUnseenNotifications({ ids })
|
||||
.catch(e => this.errorService.handleError(e))
|
||||
}
|
||||
|
||||
async remove(notifications: ServerNotifications): Promise<void> {
|
||||
this.updateCount(-notifications.filter(n => !n.seen).length)
|
||||
|
||||
this.api
|
||||
.deleteNotifications({ ids: notifications.map(n => n.id) })
|
||||
.catch(e => this.errorService.handleError(e))
|
||||
}
|
||||
|
||||
getColor(notification: ServerNotification<number>): string {
|
||||
switch (notification.level) {
|
||||
case 'info':
|
||||
@@ -95,7 +64,6 @@ export class NotificationService {
|
||||
|
||||
viewModal(notification: ServerNotification<number>, full = false) {
|
||||
const { data, createdAt, code, title, message } = notification
|
||||
this.markSeen([notification])
|
||||
|
||||
if (code === 1) {
|
||||
// Backup Report
|
||||
@@ -116,10 +84,4 @@ export class NotificationService {
|
||||
.subscribe()
|
||||
}
|
||||
}
|
||||
|
||||
private async updateCount(toAdjust: number) {
|
||||
const currentCount = await firstValueFrom(this.unreadCount$)
|
||||
|
||||
this.localUnreadCount$.next(Math.max(currentCount + toAdjust, 0))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { inject, Injectable, InjectionToken } from '@angular/core'
|
||||
import { Dump, Revision, Update } from 'patch-db-client'
|
||||
import { BehaviorSubject, EMPTY, Observable } from 'rxjs'
|
||||
import { BehaviorSubject, EMPTY, Observable, throwError, timer } from 'rxjs'
|
||||
import {
|
||||
bufferTime,
|
||||
catchError,
|
||||
@@ -40,7 +40,7 @@ export class PatchDbSource extends Observable<Update<DataModel>[]> {
|
||||
),
|
||||
),
|
||||
catchError((_, original$) => {
|
||||
this.state.retrigger()
|
||||
this.state.retrigger(false, 2000)
|
||||
|
||||
return this.state.pipe(
|
||||
skip(1), // skipping previous value stored due to shareReplay
|
||||
|
||||
@@ -93,7 +93,9 @@ export class StateService extends Observable<RR.ServerState | null> {
|
||||
super(subscriber => this.stream$.subscribe(subscriber))
|
||||
|
||||
// Retrigger on offline
|
||||
this.network$.pipe(filter(v => !v)).subscribe(() => this.retrigger())
|
||||
this.network$
|
||||
.pipe(filter(v => !v))
|
||||
.subscribe(() => this.retrigger(false, 2000))
|
||||
|
||||
// Show toasts
|
||||
this.trigger$
|
||||
@@ -109,8 +111,8 @@ export class StateService extends Observable<RR.ServerState | null> {
|
||||
.subscribe()
|
||||
}
|
||||
|
||||
retrigger(gracefully = false) {
|
||||
this.trigger$.next(gracefully)
|
||||
retrigger(gracefully: boolean, delay: number) {
|
||||
setTimeout(() => this.trigger$.next(gracefully), delay)
|
||||
}
|
||||
|
||||
private handleState(state: RR.ServerState): void {
|
||||
|
||||
Reference in New Issue
Block a user