mirror of
https://github.com/Start9Labs/start-os.git
synced 2026-03-26 10:21:52 +00:00
fix bugs
This commit is contained in:
@@ -25,6 +25,7 @@ import {
|
||||
ServerNotifications,
|
||||
} from 'src/app/services/api/api.types'
|
||||
import { NotificationService } from '../../services/notification.service'
|
||||
import { ToManifestPipe } from '../../pipes/to-manifest'
|
||||
|
||||
@Component({
|
||||
selector: 'header-notifications',
|
||||
@@ -47,7 +48,11 @@ import { NotificationService } from '../../services/notification.service'
|
||||
[notification]="not"
|
||||
>
|
||||
<ng-container *ngIf="not.packageId as pkgId">
|
||||
{{ $any(packageData[pkgId])?.manifest.title || pkgId }}
|
||||
{{
|
||||
packageData[pkgId]
|
||||
? (packageData[pkgId] | toManifest).title
|
||||
: pkgId
|
||||
}}
|
||||
</ng-container>
|
||||
<button
|
||||
style="align-self: flex-start; flex-shrink: 0;"
|
||||
@@ -98,6 +103,7 @@ import { NotificationService } from '../../services/notification.service'
|
||||
TuiCellModule,
|
||||
TuiAvatarStackModule,
|
||||
TuiTitleModule,
|
||||
ToManifestPipe,
|
||||
],
|
||||
})
|
||||
export class HeaderNotificationsComponent {
|
||||
|
||||
@@ -9,6 +9,7 @@ import { WINDOW } from '@ng-web-apis/common'
|
||||
import { CopyService } from '@start9labs/shared'
|
||||
import { TuiDialogService } from '@taiga-ui/core'
|
||||
import {
|
||||
TuiBadgeModule,
|
||||
TuiButtonModule,
|
||||
TuiCellModule,
|
||||
TuiTitleModule,
|
||||
@@ -22,12 +23,12 @@ import { mask } from 'src/app/util/mask'
|
||||
selector: 'app-interface-address',
|
||||
template: `
|
||||
<div tuiCell>
|
||||
<h3 tuiTitle>
|
||||
<span tuiSubtitle>{{ isMasked ? mask : address }}</span>
|
||||
</h3>
|
||||
<tui-badge appearance="success">
|
||||
{{ label }}
|
||||
</tui-badge>
|
||||
<h3 tuiTitle>
|
||||
<span tuiSubtitle>{{ isMasked ? mask : address }}</span>
|
||||
</h3>
|
||||
<button
|
||||
*ngIf="isUi"
|
||||
tuiIconButton
|
||||
@@ -51,11 +52,25 @@ import { mask } from 'src/app/util/mask'
|
||||
appearance="icon"
|
||||
(click)="copyService.copy(address)"
|
||||
>
|
||||
Copy QR code
|
||||
Copy URL
|
||||
</button>
|
||||
<button
|
||||
tuiIconButton
|
||||
iconLeft="tuiIconTrash"
|
||||
appearance="icon"
|
||||
(click)="destroy()"
|
||||
>
|
||||
Destroy
|
||||
</button>
|
||||
</div>
|
||||
`,
|
||||
imports: [NgIf, TuiCellModule, TuiTitleModule, TuiButtonModule],
|
||||
imports: [
|
||||
NgIf,
|
||||
TuiCellModule,
|
||||
TuiTitleModule,
|
||||
TuiButtonModule,
|
||||
TuiBadgeModule,
|
||||
],
|
||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
})
|
||||
export class InterfaceAddressComponent {
|
||||
@@ -84,4 +99,6 @@ export class InterfaceAddressComponent {
|
||||
})
|
||||
.subscribe()
|
||||
}
|
||||
|
||||
destroy() {}
|
||||
}
|
||||
|
||||
@@ -43,26 +43,17 @@ type ClearnetForm = {
|
||||
<strong>View instructions</strong>
|
||||
</a>
|
||||
</em>
|
||||
<ng-container
|
||||
*ngIf="
|
||||
interface.serviceInterface.addresses.clearnet as addresses;
|
||||
else empty
|
||||
"
|
||||
>
|
||||
@for (
|
||||
address of interface.serviceInterface.addresses.clearnet;
|
||||
track $index
|
||||
) {
|
||||
<app-interface-address
|
||||
*ngFor="let address of addresses"
|
||||
[label]="address.label"
|
||||
[address]="address.url"
|
||||
[isMasked]="interface.serviceInterface.masked"
|
||||
[isUi]="interface.serviceInterface.type === 'ui'"
|
||||
/>
|
||||
<div [style.display]="'flex'" [style.gap.rem]="1">
|
||||
<button tuiButton size="s" appearance="danger-solid" (click)="remove()">
|
||||
Remove
|
||||
</button>
|
||||
</div>
|
||||
</ng-container>
|
||||
<ng-template #empty>
|
||||
} @empty {
|
||||
<button
|
||||
tuiButton
|
||||
iconLeft="tuiIconPlus"
|
||||
@@ -71,7 +62,7 @@ type ClearnetForm = {
|
||||
>
|
||||
Add Address
|
||||
</button>
|
||||
</ng-template>
|
||||
}
|
||||
`,
|
||||
imports: [NgForOf, InterfaceAddressComponent, NgIf, TuiButtonModule],
|
||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
|
||||
@@ -20,26 +20,14 @@ import { InterfaceAddressComponent } from './interface-addresses.component'
|
||||
</a>
|
||||
</em>
|
||||
|
||||
<ng-container
|
||||
*ngIf="
|
||||
interface.serviceInterface.addresses.local as addresses;
|
||||
else empty
|
||||
"
|
||||
>
|
||||
@for (address of interface.serviceInterface.addresses.local; track $index) {
|
||||
<app-interface-address
|
||||
*ngFor="let address of addresses"
|
||||
[label]="address.label"
|
||||
[address]="address.url"
|
||||
[isMasked]="interface.serviceInterface.masked"
|
||||
[isUi]="interface.serviceInterface.type === 'ui'"
|
||||
/>
|
||||
<div [style.display]="'flex'" [style.gap.rem]="1">
|
||||
<button tuiButton size="s" appearance="danger-solid" (click)="remove()">
|
||||
Remove
|
||||
</button>
|
||||
</div>
|
||||
</ng-container>
|
||||
<ng-template #empty>
|
||||
} @empty {
|
||||
<button
|
||||
tuiButton
|
||||
iconLeft="tuiIconPlus"
|
||||
@@ -48,7 +36,7 @@ import { InterfaceAddressComponent } from './interface-addresses.component'
|
||||
>
|
||||
Add Address
|
||||
</button>
|
||||
</ng-template>
|
||||
}
|
||||
`,
|
||||
imports: [NgForOf, NgIf, InterfaceAddressComponent, TuiButtonModule],
|
||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
|
||||
@@ -2,6 +2,7 @@ import { ChangeDetectionStrategy, Component, inject } from '@angular/core'
|
||||
import { InterfaceAddressComponent } from './interface-addresses.component'
|
||||
import { InterfaceComponent } from './interface.component'
|
||||
import { NgForOf, NgIf } from '@angular/common'
|
||||
import { TuiButtonModule } from '@taiga-ui/experimental'
|
||||
|
||||
@Component({
|
||||
standalone: true,
|
||||
@@ -19,23 +20,14 @@ import { NgForOf, NgIf } from '@angular/common'
|
||||
</a>
|
||||
</em>
|
||||
|
||||
<ng-container
|
||||
*ngIf="interface.serviceInterface.addresses.tor as addresses; else empty"
|
||||
>
|
||||
@for (address of interface.serviceInterface.addresses.tor; track $index) {
|
||||
<app-interface-address
|
||||
*ngFor="let address of addresses"
|
||||
[label]="address.label"
|
||||
[address]="address.url"
|
||||
[isMasked]="interface.serviceInterface.masked"
|
||||
[isUi]="interface.serviceInterface.type === 'ui'"
|
||||
/>
|
||||
<div [style.display]="'flex'" [style.gap.rem]="1">
|
||||
<button tuiButton size="s" appearance="danger-solid" (click)="remove()">
|
||||
Remove
|
||||
</button>
|
||||
</div>
|
||||
</ng-container>
|
||||
<ng-template #empty>
|
||||
} @empty {
|
||||
<button
|
||||
tuiButton
|
||||
iconLeft="tuiIconPlus"
|
||||
@@ -44,17 +36,9 @@ import { NgForOf, NgIf } from '@angular/common'
|
||||
>
|
||||
Add Address
|
||||
</button>
|
||||
</ng-template>
|
||||
|
||||
<app-interface-address
|
||||
*ngFor="let address of interface.serviceInterface.addresses.tor"
|
||||
[label]="address.label"
|
||||
[address]="address.url"
|
||||
[isMasked]="interface.serviceInterface.masked"
|
||||
[isUi]="interface.serviceInterface.type === 'ui'"
|
||||
/>
|
||||
}
|
||||
`,
|
||||
imports: [NgForOf, NgIf, InterfaceAddressComponent],
|
||||
imports: [NgForOf, NgIf, InterfaceAddressComponent, TuiButtonModule],
|
||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
})
|
||||
export class InterfaceTorComponent {
|
||||
|
||||
@@ -40,10 +40,10 @@ import { Manifest } from '@start9labs/marketplace'
|
||||
</button>
|
||||
} @else {
|
||||
<button
|
||||
*tuiLet="hasUnmet(pkg) | async as hasUnmet"
|
||||
*tuiLet="hasUnmet() | async as hasUnmet"
|
||||
tuiIconButton
|
||||
iconLeft="tuiIconPlay"
|
||||
[disabled]="!this.pkg.status.configured"
|
||||
[disabled]="!pkg.status.configured"
|
||||
(click)="actions.start(manifest, !!hasUnmet)"
|
||||
>
|
||||
Start
|
||||
@@ -77,11 +77,11 @@ export class ControlsComponent {
|
||||
readonly actions = inject(ActionsService)
|
||||
|
||||
@tuiPure
|
||||
hasUnmet(pkg: PackageDataEntry): Observable<boolean> {
|
||||
const id = getManifest(pkg).id
|
||||
hasUnmet(): Observable<boolean> {
|
||||
const id = this.manifest.id
|
||||
return this.errors.getPkgDepErrors$(id).pipe(
|
||||
map(errors =>
|
||||
Object.keys(pkg.currentDependencies)
|
||||
Object.keys(this.pkg.currentDependencies)
|
||||
.map(id => !!(errors[id] as any)?.[id]) // @TODO fix
|
||||
.some(Boolean),
|
||||
),
|
||||
|
||||
@@ -28,7 +28,7 @@ import { getManifest } from 'src/app/util/get-package-data'
|
||||
<fieldset
|
||||
appControls
|
||||
[disabled]="
|
||||
this.pkg.stateInfo.state !== 'installed' || !(connected$ | async)
|
||||
pkg.stateInfo.state !== 'installed' || !(connected$ | async)
|
||||
"
|
||||
[pkg]="pkg"
|
||||
></fieldset>
|
||||
|
||||
@@ -54,7 +54,7 @@ export class StatusComponent {
|
||||
}
|
||||
|
||||
get loading(): boolean {
|
||||
return !!this.pkg.stateInfo || this.color === 'var(--tui-info-fill)'
|
||||
return this.color === 'var(--tui-info-fill)'
|
||||
}
|
||||
|
||||
@tuiPure
|
||||
@@ -94,10 +94,6 @@ export class StatusComponent {
|
||||
}
|
||||
|
||||
get color(): string {
|
||||
if (this.pkg.stateInfo.installingInfo) {
|
||||
return 'var(--tui-info-fill)'
|
||||
}
|
||||
|
||||
switch (this.getStatus(this.pkg).primary) {
|
||||
case PrimaryStatus.Running:
|
||||
return 'var(--tui-success-fill)'
|
||||
|
||||
@@ -84,7 +84,6 @@ import { InstallingProgressPipe } from 'src/app/apps/portal/routes/service/pipes
|
||||
<service-interface-list
|
||||
[pkg]="service.pkg"
|
||||
[status]="service.status"
|
||||
]
|
||||
/>
|
||||
|
||||
@if (
|
||||
|
||||
@@ -27,7 +27,7 @@ import { Domain } from 'src/app/services/patch-db/data-model'
|
||||
<tbody>
|
||||
<tr *ngFor="let domain of domains">
|
||||
<td>{{ domain.value }}</td>
|
||||
<td>{{ domain.createdAt | date : 'short' }}</td>
|
||||
<td>{{ domain.createdAt | date: 'short' }}</td>
|
||||
<td>{{ domain.provider }}</td>
|
||||
<td>{{ getStrategy(domain) }}</td>
|
||||
<td>
|
||||
@@ -69,11 +69,7 @@ export class DomainsTableComponent {
|
||||
readonly delete = new EventEmitter<Domain>()
|
||||
|
||||
getStrategy(domain: any) {
|
||||
return (
|
||||
domain.networkStrategy.ipStrategy ||
|
||||
domain.networkStrategy.proxyId ||
|
||||
'Primary Proxy'
|
||||
)
|
||||
return domain.networkStrategy.ipStrategy || domain.networkStrategy.proxy
|
||||
}
|
||||
|
||||
onUsedBy({ value, usedBy }: Domain) {
|
||||
|
||||
@@ -45,12 +45,6 @@ export class SettingsService {
|
||||
icon: 'tuiIconKey',
|
||||
action: () => this.promptNewPassword(),
|
||||
},
|
||||
{
|
||||
title: 'Experimental Features',
|
||||
description: 'Try out new and potentially unstable new features',
|
||||
icon: 'tuiIconThermometer',
|
||||
routerLink: 'experimental',
|
||||
},
|
||||
],
|
||||
Network: [
|
||||
{
|
||||
@@ -134,7 +128,7 @@ export class SettingsService {
|
||||
.open(TUI_PROMPT, {
|
||||
label: this.isTor ? 'Warning' : 'Confirm',
|
||||
data: {
|
||||
content: '',
|
||||
content: '@TODO how to display a checkbox in here?',
|
||||
yes: 'Reset',
|
||||
no: 'Cancel',
|
||||
},
|
||||
|
||||
@@ -6,7 +6,6 @@ import {
|
||||
PackageDataEntry,
|
||||
UpdatingState,
|
||||
} from 'src/app/services/patch-db/data-model'
|
||||
import { hasCurrentDeps } from 'src/app/util/has-deps'
|
||||
|
||||
@Pipe({
|
||||
name: 'filterUpdates',
|
||||
|
||||
@@ -6,7 +6,7 @@ import {
|
||||
} from '@start9labs/marketplace'
|
||||
import { TuiAvatarModule, TuiCellModule } from '@taiga-ui/experimental'
|
||||
import { PatchDB } from 'patch-db-client'
|
||||
import { combineLatest, map } from 'rxjs'
|
||||
import { combineLatest, map, scan } from 'rxjs'
|
||||
import { MarketplaceService } from 'src/app/services/marketplace.service'
|
||||
import {
|
||||
DataModel,
|
||||
@@ -79,9 +79,10 @@ export default class UpdatesComponent {
|
||||
.watch$('packageData')
|
||||
.pipe(
|
||||
map(pkgs =>
|
||||
Object.values(pkgs).reduce(
|
||||
(acc, curr) => {
|
||||
if (isInstalled(curr) || isUpdating(curr)) return { ...acc, curr }
|
||||
Object.entries(pkgs).reduce(
|
||||
(acc, [id, val]) => {
|
||||
if (isInstalled(val) || isUpdating(val))
|
||||
return { ...acc, [id]: val }
|
||||
return acc
|
||||
},
|
||||
{} as Record<
|
||||
|
||||
@@ -63,8 +63,9 @@ export class BadgeService {
|
||||
(list, [_, store]) =>
|
||||
store?.packages.reduce(
|
||||
(result, { manifest: { id, version } }) =>
|
||||
this.emver.compare(version, getManifest(local[id])?.version) ===
|
||||
1
|
||||
local[id] &&
|
||||
this.emver.compare(version, getManifest(local[id]).version) ===
|
||||
1
|
||||
? result.add(id)
|
||||
: result,
|
||||
list,
|
||||
@@ -72,6 +73,7 @@ export class BadgeService {
|
||||
new Set<string>(),
|
||||
).size,
|
||||
),
|
||||
// @TODO shareReplay is preventing the badge from decrementing
|
||||
shareReplay(1),
|
||||
)
|
||||
|
||||
|
||||
@@ -340,7 +340,7 @@ export class MockApiService extends ApiService {
|
||||
const patch = [
|
||||
{
|
||||
op: PatchOp.REPLACE,
|
||||
path: '/server-info/ui/domainInfo',
|
||||
path: '/serverInfo/ui/domainInfo',
|
||||
value: params.domainInfo,
|
||||
},
|
||||
]
|
||||
@@ -430,7 +430,7 @@ export class MockApiService extends ApiService {
|
||||
const patch = [
|
||||
{
|
||||
op: PatchOp.REPLACE,
|
||||
path: '/server-info/network/outboundProxy',
|
||||
path: '/serverInfo/network/outboundProxy',
|
||||
value: params.proxy,
|
||||
},
|
||||
]
|
||||
@@ -526,7 +526,7 @@ export class MockApiService extends ApiService {
|
||||
const patch = [
|
||||
{
|
||||
op: PatchOp.REPLACE,
|
||||
path: '/server-info/network/proxies',
|
||||
path: '/serverInfo/network/proxies',
|
||||
value: [
|
||||
{
|
||||
id: 'abcd-efgh-ijkl-mnop',
|
||||
@@ -553,7 +553,7 @@ export class MockApiService extends ApiService {
|
||||
const patch = [
|
||||
{
|
||||
op: PatchOp.REPLACE,
|
||||
path: `/server-info/network/proxies/0/name`,
|
||||
path: `/serverInfo/network/proxies/0/name`,
|
||||
value: params.name,
|
||||
},
|
||||
]
|
||||
@@ -567,7 +567,7 @@ export class MockApiService extends ApiService {
|
||||
const patch = [
|
||||
{
|
||||
op: PatchOp.REPLACE,
|
||||
path: '/server-info/network/proxies',
|
||||
path: '/serverInfo/network/proxies',
|
||||
value: [],
|
||||
},
|
||||
]
|
||||
@@ -586,7 +586,7 @@ export class MockApiService extends ApiService {
|
||||
const patch = [
|
||||
{
|
||||
op: PatchOp.REPLACE,
|
||||
path: '/server-info/network/start9ToSubdomain',
|
||||
path: '/serverInfo/network/start9ToSubdomain',
|
||||
value: {
|
||||
value: 'xyz',
|
||||
createdAt: new Date(),
|
||||
@@ -607,7 +607,7 @@ export class MockApiService extends ApiService {
|
||||
const patch = [
|
||||
{
|
||||
op: PatchOp.REPLACE,
|
||||
path: '/server-info/network/start9ToSubdomain',
|
||||
path: '/serverInfo/network/start9ToSubdomain',
|
||||
value: null,
|
||||
},
|
||||
]
|
||||
@@ -622,7 +622,7 @@ export class MockApiService extends ApiService {
|
||||
const patch = [
|
||||
{
|
||||
op: PatchOp.REPLACE,
|
||||
path: '/server-info/network/domains',
|
||||
path: '/serverInfo/network/domains',
|
||||
value: [
|
||||
{
|
||||
value: params.hostname,
|
||||
@@ -644,7 +644,7 @@ export class MockApiService extends ApiService {
|
||||
const patch = [
|
||||
{
|
||||
op: PatchOp.REPLACE,
|
||||
path: '/server-info/network/domains',
|
||||
path: '/serverInfo/network/domains',
|
||||
value: [],
|
||||
},
|
||||
]
|
||||
@@ -663,7 +663,7 @@ export class MockApiService extends ApiService {
|
||||
const patch = [
|
||||
{
|
||||
op: PatchOp.REPLACE,
|
||||
path: '/server-info/network/wanConfig/forwards/0/override',
|
||||
path: '/serverInfo/network/wanConfig/forwards/0/override',
|
||||
value: params.port,
|
||||
},
|
||||
]
|
||||
@@ -679,7 +679,7 @@ export class MockApiService extends ApiService {
|
||||
const patch = [
|
||||
{
|
||||
op: PatchOp.REPLACE,
|
||||
path: '/server-info/network/wifi/enabled',
|
||||
path: '/serverInfo/network/wifi/enabled',
|
||||
value: params.enable,
|
||||
},
|
||||
]
|
||||
@@ -722,7 +722,7 @@ export class MockApiService extends ApiService {
|
||||
const patch = [
|
||||
{
|
||||
op: PatchOp.REPLACE,
|
||||
path: '/server-info/smtp',
|
||||
path: '/serverInfo/smtp',
|
||||
value: params,
|
||||
},
|
||||
]
|
||||
@@ -969,8 +969,6 @@ export class MockApiService extends ApiService {
|
||||
this.updateProgress(params.id)
|
||||
}, 1000)
|
||||
|
||||
const manifest = Mock.LocalPkgs[params.id].stateInfo.manifest
|
||||
|
||||
const patch: Operation<
|
||||
PackageDataEntry<InstallingState | UpdatingState>
|
||||
>[] = [
|
||||
@@ -981,15 +979,15 @@ export class MockApiService extends ApiService {
|
||||
...Mock.LocalPkgs[params.id],
|
||||
stateInfo: {
|
||||
// if installing
|
||||
state: PackageState.Installing,
|
||||
// state: PackageState.Installing,
|
||||
|
||||
// if updating
|
||||
// state: PackageState.Updating,
|
||||
// manifest,
|
||||
state: PackageState.Updating,
|
||||
manifest: mockPatchData.packageData[params.id].stateInfo.manifest!,
|
||||
|
||||
// both
|
||||
installingInfo: {
|
||||
newManifest: manifest,
|
||||
newManifest: Mock.LocalPkgs[params.id].stateInfo.manifest,
|
||||
progress: PROGRESS,
|
||||
},
|
||||
},
|
||||
@@ -1285,7 +1283,7 @@ export class MockApiService extends ApiService {
|
||||
const patch = [
|
||||
{
|
||||
op: PatchOp.REPLACE,
|
||||
path: `/package-data/${params.packageId}/installed/interfaceInfo/${params.interfaceId}/addressInfo/domainInfo`,
|
||||
path: `/packageData/${params.packageId}/installed/interfaceInfo/${params.interfaceId}/addressInfo/domainInfo`,
|
||||
value: params.domainInfo,
|
||||
},
|
||||
]
|
||||
@@ -1301,7 +1299,7 @@ export class MockApiService extends ApiService {
|
||||
const patch = [
|
||||
{
|
||||
op: PatchOp.REPLACE,
|
||||
path: `/package-data/${params.packageId}/installed/outboundProxy`,
|
||||
path: `/packageData/${params.packageId}/installed/outboundProxy`,
|
||||
value: params.proxy,
|
||||
},
|
||||
]
|
||||
|
||||
Reference in New Issue
Block a user