Skip to content

Commit

Permalink
chore: refactor interfaces and remove UI routes (#2560)
Browse files Browse the repository at this point in the history
  • Loading branch information
waterplea authored Feb 16, 2024
1 parent 513fb34 commit c0a5514
Show file tree
Hide file tree
Showing 295 changed files with 465 additions and 13,902 deletions.
1 change: 0 additions & 1 deletion web/projects/ui/src/app/app.component.html
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,6 @@
(click)="onResize(drawer)"
></button>
</div>
<widgets *ngIf="drawer.open" [wide]="drawer.width === 600" />
</ion-menu>

<ion-router-outlet
Expand Down
2 changes: 0 additions & 2 deletions web/projects/ui/src/app/app.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@ import {
TuiRootModule,
TuiThemeNightModule,
} from '@taiga-ui/core'
import { WidgetsPageModule } from 'src/app/apps/ui/pages/widgets/widgets.module'
import { environment } from '../environments/environment'
import { AppComponent } from './app.component'
import { APP_PROVIDERS } from './app.providers'
Expand Down Expand Up @@ -58,7 +57,6 @@ import { RoutingModule } from './routing.module'
TuiAlertModule,
TuiModeModule,
TuiThemeNightModule,
WidgetsPageModule,
ResponsiveColViewportDirective,
DarkThemeModule,
LightThemeModule,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,157 @@
import { NgIf } from '@angular/common'
import {
ChangeDetectionStrategy,
Component,
inject,
Input,
} from '@angular/core'
import { ErrorService, LoadingService } from '@start9labs/shared'
import { TuiDialogOptions, TuiDialogService } from '@taiga-ui/core'
import { TuiButtonModule } from '@taiga-ui/experimental'
import { TUI_PROMPT } from '@taiga-ui/kit'
import { filter } from 'rxjs'
import {
FormComponent,
FormContext,
} from 'src/app/apps/portal/components/form.component'
import {
getClearnetSpec,
REMOVE,
} from 'src/app/apps/portal/components/interfaces/interface.utils'
import { ApiService } from 'src/app/services/api/embassy-api.service'
import { FormDialogService } from 'src/app/services/form-dialog.service'
import { DomainInfo, NetworkInfo } from 'src/app/services/patch-db/data-model'
import { getClearnetAddress } from 'src/app/util/clearnetAddress'
import { InterfaceComponent } from './interface.component'
import { InterfacesComponent } from './interfaces.component'

type ClearnetForm = {
domain: string
subdomain: string | null
}

@Component({
standalone: true,
selector: 'app-interface-clearnet',
template: `
<em>
Add clearnet to expose this interface to the public Internet.
<a
href="https://docs.start9.com/latest/user-manual/interface-addresses#clearnet"
target="_blank"
rel="noreferrer"
>
<strong>View instructions</strong>
</a>
</em>
<ng-container
*ngIf="interfaces.addressInfo.domainInfo as domainInfo; else noClearnet"
>
<app-interface
label="Clearnet"
[hostname]="getClearnet(domainInfo)"
[isUi]="interfaces.isUi"
/>
<div [style.display]="'flex'" [style.gap.rem]="1">
<button tuiButton size="s" (click)="add()">Update</button>
<button tuiButton size="s" appearance="danger-solid" (click)="remove()">
Remove
</button>
</div>
</ng-container>
<ng-template #noClearnet>
<button
tuiButton
iconLeft="tuiIconPlus"
[style.align-self]="'flex-start'"
(click)="add()"
>
Add Clearnet
</button>
</ng-template>
`,
imports: [InterfaceComponent, NgIf, TuiButtonModule],
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class InterfaceClearnetComponent {
private readonly formDialog = inject(FormDialogService)
private readonly loader = inject(LoadingService)
private readonly errorService = inject(ErrorService)
private readonly api = inject(ApiService)
private readonly dialogs = inject(TuiDialogService)
readonly interfaces = inject(InterfacesComponent)

@Input({ required: true }) network!: NetworkInfo

getClearnet(clearnet: DomainInfo): string {
return getClearnetAddress('https', clearnet)
}

async add() {
const { domainInfo } = this.interfaces.addressInfo
const { domain = '', subdomain = '' } = domainInfo || {}
const options: Partial<TuiDialogOptions<FormContext<ClearnetForm>>> = {
label: 'Select Domain/Subdomain',
data: {
value: { domain, subdomain },
spec: await getClearnetSpec(this.network),
buttons: [
{
text: 'Manage domains',
link: 'portal/system/settings/domains',
},
{
text: 'Save',
handler: async value => this.save(value),
},
],
},
}
this.formDialog.open(FormComponent, options)
}

remove() {
this.dialogs
.open(TUI_PROMPT, REMOVE)
.pipe(filter(Boolean))
.subscribe(async () => {
const loader = this.loader.open('Removing...').subscribe()

try {
if (this.interfaces.packageContext) {
await this.api.setInterfaceClearnetAddress({
...this.interfaces.packageContext,
domainInfo: null,
})
} else {
await this.api.setServerClearnetAddress({ domainInfo: null })
}
} catch (e: any) {
this.errorService.handleError(e)
} finally {
loader.unsubscribe()
}
})
}

private async save(domainInfo: ClearnetForm): Promise<boolean> {
const loader = this.loader.open('Saving...').subscribe()

try {
if (this.interfaces.packageContext) {
await this.api.setInterfaceClearnetAddress({
...this.interfaces.packageContext,
domainInfo,
})
} else {
await this.api.setServerClearnetAddress({ domainInfo })
}
return true
} catch (e: any) {
this.errorService.handleError(e)
return false
} finally {
loader.unsubscribe()
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
import { CommonModule } from '@angular/common'
import { ChangeDetectionStrategy, Component, inject } from '@angular/core'
import { TuiButtonModule } from '@taiga-ui/experimental'
import { InterfacesComponent } from './interfaces.component'
import { InterfaceComponent } from './interface.component'

@Component({
standalone: true,
selector: 'app-interface-local',
template: `
<em>
Local addresses can only be accessed while connected to the same Local
Area Network (LAN) as your server, either directly or using a VPN.
<a
href="https://docs.start9.com/latest/user-manual/interface-addresses#local"
target="_blank"
rel="noreferrer"
>
<strong>View instructions</strong>
</a>
</em>
<a
*ngIf="!interfaces.packageContext"
tuiButton
iconLeft="tuiIconDownload"
href="/public/eos/local.crt"
[download]="interfaces.addressInfo.lanHostname + '.crt'"
[style.align-self]="'flex-start'"
>
Download Root CA
</a>
<app-interface
label="Local"
[hostname]="interfaces.addressInfo.lanHostname"
[isUi]="interfaces.isUi"
></app-interface>
<ng-container
*ngFor="let iface of interfaces.addressInfo.ipInfo | keyvalue"
>
<app-interface
*ngIf="iface.value.ipv4 as ipv4"
[label]="iface.key + ' (IPv4)'"
[hostname]="ipv4"
[isUi]="interfaces.isUi"
></app-interface>
<app-interface
*ngIf="iface.value.ipv6 as ipv6"
[label]="iface.key + ' (IPv6)'"
[hostname]="ipv6"
[isUi]="interfaces.isUi"
></app-interface>
</ng-container>
`,
imports: [InterfaceComponent, CommonModule, TuiButtonModule],
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class InterfaceLocalComponent {
readonly interfaces = inject(InterfacesComponent)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import { ChangeDetectionStrategy, Component, inject } from '@angular/core'
import { InterfaceComponent } from './interface.component'
import { InterfacesComponent } from './interfaces.component'

@Component({
standalone: true,
selector: 'app-interface-tor',
template: `
<em>
Use a Tor-enabled browser to access this address. Tor connections can be
slow and unreliable.
<a
href="https://docs.start9.com/latest/user-manual/interface-addresses#tor"
target="_blank"
rel="noreferrer"
>
<strong>View instructions</strong>
</a>
</em>
<app-interface
label="Tor"
[hostname]="interfaces.addressInfo.torHostname"
[isUi]="interfaces.isUi"
></app-interface>
`,
imports: [InterfaceComponent],
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class InterfaceTorComponent {
readonly interfaces = inject(InterfacesComponent)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
import { NgIf } from '@angular/common'
import {
ChangeDetectionStrategy,
Component,
inject,
Input,
} from '@angular/core'
import { WINDOW } from '@ng-web-apis/common'
import { CopyService } from '@start9labs/shared'
import { TuiDialogService } from '@taiga-ui/core'
import {
TuiButtonModule,
TuiCellModule,
TuiTitleModule,
} from '@taiga-ui/experimental'
import { PolymorpheusComponent } from '@tinkoff/ng-polymorpheus'
import { QRComponent } from 'src/app/common/qr/qr.component'

@Component({
standalone: true,
selector: 'app-interface',
template: `
<div tuiCell>
<h3 tuiTitle>
{{ label }}
<span tuiSubtitle>{{ hostname }}</span>
</h3>
<button
*ngIf="isUi"
tuiIconButton
iconLeft="tuiIconExternalLink"
appearance="icon"
(click)="launch(hostname)"
>
Launch
</button>
<button
tuiIconButton
iconLeft="tuiIconGrid"
appearance="icon"
(click)="showQR(hostname)"
>
Show QR code
</button>
<button
tuiIconButton
iconLeft="tuiIconCopy"
appearance="icon"
(click)="copyService.copy(hostname)"
>
Copy QR code
</button>
</div>
`,
imports: [NgIf, TuiCellModule, TuiTitleModule, TuiButtonModule],
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class InterfaceComponent {
private readonly window = inject(WINDOW)
private readonly dialogs = inject(TuiDialogService)
readonly copyService = inject(CopyService)

@Input({ required: true }) label = ''
@Input({ required: true }) hostname = ''
@Input({ required: true }) isUi = false

launch(url: string): void {
this.window.open(url, '_blank', 'noreferrer')
}

showQR(data: string) {
this.dialogs
.open(new PolymorpheusComponent(QRComponent), {
size: 'auto',
data,
})
.subscribe()
}
}
Loading

0 comments on commit c0a5514

Please sign in to comment.