More FE fixes (#3056)

* tell user to restart server after kiosk chnage

* remove unused import

* dont show tor address on server setup

* chore: address comments

* revert mock

* chore: remove uptime block on mobile

* utiliser le futur proche

* chore: comments

* don't show loading on authorities tab

* chore: fix mobile unions

---------

Co-authored-by: waterplea <alexander@inkin.ru>
Co-authored-by: Aiden McClelland <3732071+dr-bonez@users.noreply.github.com>
This commit is contained in:
Matt Hill
2025-11-25 16:43:19 -07:00
committed by GitHub
parent 6e8a425eb1
commit 009d76ea35
16 changed files with 224 additions and 192 deletions

View File

@@ -10,7 +10,12 @@ import { MarketplacePkgBase } from '../../../types'
selector: 'marketplace-dep-item',
template: `
<div class="outer-container">
<tui-avatar class="dep-img" size="l" [src]="getImage(dep.key)" />
<tui-avatar
appearance="action-grayscale"
class="dep-img"
size="l"
[src]="getImage(dep.key)"
/>
<div>
<tui-line-clamp [linesLimit]="2" [content]="titleContent" />
<ng-template #titleContent>

View File

@@ -21,7 +21,10 @@ import { MarketplacePkg } from '../../types'
[queryParams]="{ id: pkg.id, flavor: pkg.flavor }"
queryParamsHandling="merge"
>
<tui-avatar [src]="pkg.icon | trustUrl" />
<tui-avatar
appearance="action-grayscale"
[src]="pkg.icon | trustUrl"
/>
<span tuiTitle>
{{ pkg.title }}
<span tuiSubtitle>{{ pkg.version }}</span>

View File

@@ -40,7 +40,9 @@ import { HintPipe } from '../pipes/hint.pipe'
[(ngModel)]="selected"
/>
}
<tui-data-list-wrapper *tuiTextfieldDropdown new [items]="items" />
@if (!mobile) {
<tui-data-list-wrapper *tuiTextfieldDropdown new [items]="items" />
}
@if (spec | hint; as hint) {
<tui-icon [tuiTooltip]="hint" />
}

View File

@@ -17,6 +17,7 @@ import {
tuiButtonOptionsProvider,
TuiDataList,
TuiDropdown,
TuiIcon,
TuiTextfield,
} from '@taiga-ui/core'
import { PolymorpheusComponent } from '@taiga-ui/polymorpheus'
@@ -27,13 +28,9 @@ import { InterfaceComponent } from '../interface.component'
selector: 'td[actions]',
template: `
<div class="desktop">
<button
tuiIconButton
appearance="flat-grayscale"
iconStart="@tui.info"
(click)="viewDetails()"
>
<button tuiIconButton appearance="flat-grayscale" (click)="viewDetails()">
{{ 'Address details' | i18n }}
<tui-icon class="info" icon="@tui.info" background="@tui.info-filled" />
</button>
@if (interface.value()?.type === 'ui') {
<a
@@ -113,6 +110,19 @@ import { InterfaceComponent } from '../interface.component'
white-space: nowrap;
}
:host-context(.uncommon-hidden) .desktop {
height: 0;
visibility: hidden;
}
.info {
background: var(--tui-status-info);
&::after {
mask-size: 1.5rem;
}
}
.mobile {
display: none;
}
@@ -127,7 +137,14 @@ import { InterfaceComponent } from '../interface.component'
}
}
`,
imports: [TuiButton, TuiDropdown, TuiDataList, i18nPipe, TuiTextfield],
imports: [
TuiButton,
TuiDropdown,
TuiDataList,
i18nPipe,
TuiTextfield,
TuiIcon,
],
providers: [tuiButtonOptionsProvider({ appearance: 'icon' })],
changeDetection: ChangeDetectionStrategy.OnPush,
})

View File

@@ -1,7 +1,8 @@
import { ChangeDetectionStrategy, Component, input } from '@angular/core'
import { i18nPipe } from '@start9labs/shared'
import { TuiButton } from '@taiga-ui/core'
import { TuiAccordion } from '@taiga-ui/experimental'
import { TuiSkeleton } from '@taiga-ui/kit'
import { TuiElasticContainer, TuiSkeleton } from '@taiga-ui/kit'
import { PlaceholderComponent } from 'src/app/routes/portal/components/placeholder.component'
import { TableComponent } from 'src/app/routes/portal/components/table.component'
@@ -12,91 +13,79 @@ import { InterfaceAddressItemComponent } from './item.component'
selector: 'section[addresses]',
template: `
<header>{{ 'Addresses' | i18n }}</header>
<table [appTable]="['Type', 'Access', 'Gateway', 'URL', null]">
@for (address of addresses()?.common; track $index) {
<tr [address]="address" [isRunning]="isRunning()"></tr>
} @empty {
@if (addresses()) {
<tr>
<td colspan="5">
<app-placeholder icon="@tui.list-x">
{{ 'No addresses' | i18n }}
</app-placeholder>
</td>
</tr>
} @else {
@for (_ of [0, 1]; track $index) {
<tui-elastic-container>
<table [appTable]="['Type', 'Access', 'Gateway', 'URL', null]">
@for (address of addresses()?.common; track $index) {
<tr [address]="address" [isRunning]="isRunning()"></tr>
} @empty {
@if (addresses()) {
<tr>
<td colspan="6">
<div [tuiSkeleton]="true">{{ 'Loading' | i18n }}</div>
<td colspan="5">
<app-placeholder icon="@tui.list-x">
{{ 'No addresses' | i18n }}
</app-placeholder>
</td>
</tr>
} @else {
@for (_ of [0, 1]; track $index) {
<tr>
<td colspan="6">
<div [tuiSkeleton]="true">{{ 'Loading' | i18n }}</div>
</td>
</tr>
}
}
}
}
</table>
@if (addresses()?.uncommon?.length) {
<tui-accordion>
<tui-expand>
<hr />
<table class="g-table">
@for (address of addresses()?.uncommon; track $index) {
<tr [address]="address" [isRunning]="isRunning()"></tr>
}
</table>
</tui-expand>
<button
appearance="secondary-grayscale"
iconEnd=""
[(tuiAccordion)]="uncommon"
>
@if (uncommon) {
Hide uncommon
} @else {
Show uncommon
<tbody [class.uncommon-hidden]="!uncommon">
@if (addresses()?.uncommon?.length && uncommon) {
<tr [style.background]="'var(--tui-background-neutral-1)'">
<td colspan="5"></td>
</tr>
}
</button>
</tui-accordion>
}
@for (address of addresses()?.uncommon; track $index) {
<tr [address]="address" [isRunning]="isRunning()"></tr>
}
</tbody>
@if (addresses()?.uncommon?.length) {
<caption [style.caption-side]="'bottom'">
<button
tuiButton
size="m"
appearance="secondary-grayscale"
(click)="uncommon = !uncommon"
>
@if (uncommon) {
Hide uncommon
} @else {
Show uncommon
}
</button>
</caption>
}
</table>
</tui-elastic-container>
`,
styles: `
tui-accordion {
border-radius: 0;
.g-table:has(caption) {
border-bottom-left-radius: 0;
border-bottom-right-radius: 0;
}
[tuiAccordion],
tui-expand {
box-shadow: none;
padding: 0;
}
[tuiAccordion] {
justify-content: center;
height: 3rem;
border-radius: 0 0 var(--tui-radius-m) var(--tui-radius-m) !important;
}
hr {
margin: 0;
height: 0.25rem;
border-radius: 1rem;
}
:host-context(tui-root._mobile) {
[tuiAccordion] {
margin: 0.5rem 0;
border-radius: var(--tui-radius-m) !important;
}
[tuiButton] {
width: 100%;
border-top-left-radius: 0;
border-top-right-radius: 0;
}
`,
host: { class: 'g-card' },
imports: [
TuiSkeleton,
TuiButton,
TableComponent,
PlaceholderComponent,
i18nPipe,
InterfaceAddressItemComponent,
TuiAccordion,
TuiSkeleton,
TuiElasticContainer,
],
changeDetection: ChangeDetectionStrategy.OnPush,
})

View File

@@ -8,27 +8,31 @@ import { TuiBadge } from '@taiga-ui/kit'
selector: 'tr[address]',
template: `
@if (address(); as address) {
<td>{{ address.type }}</td>
<td>
@if (address.access === 'public') {
<tui-badge size="s" appearance="primary-success">
{{ 'public' | i18n }}
</tui-badge>
} @else if (address.access === 'private') {
<tui-badge size="s" appearance="primary-destructive">
{{ 'private' | i18n }}
</tui-badge>
} @else {
-
}
<div class="wrapper">{{ address.type }}</div>
</td>
<td>
<div class="wrapper">
@if (address.access === 'public') {
<tui-badge size="s" appearance="primary-success">
{{ 'public' | i18n }}
</tui-badge>
} @else if (address.access === 'private') {
<tui-badge size="s" appearance="primary-destructive">
{{ 'private' | i18n }}
</tui-badge>
} @else {
-
}
</div>
</td>
<td [style.order]="-1">
<div [title]="address.gatewayName">
<div class="wrapper" [title]="address.gatewayName">
{{ address.gatewayName || '-' }}
</div>
</td>
<td>
<div [title]="address.url">{{ address.url }}</div>
<div class="wrapper" [title]="address.url">{{ address.url }}</div>
</td>
<td
actions
@@ -48,6 +52,18 @@ import { TuiBadge } from '@taiga-ui/kit'
}
}
:host-context(.uncommon-hidden) {
.wrapper {
height: 0;
visibility: hidden;
}
td {
padding-block: 0;
border: hidden;
}
}
div {
white-space: normal;
word-break: break-all;

View File

@@ -13,6 +13,8 @@ import { i18nKey, i18nPipe } from '@start9labs/shared'
</tr>
</thead>
<tbody><ng-content /></tbody>
<ng-content select="tbody" />
<ng-content select="caption" />
`,
styles: `
:host:has(app-placeholder) thead {

View File

@@ -25,7 +25,7 @@ import { ToManifestPipe } from '../../../pipes/to-manifest'
[queryParams]="services[d.key] ? {} : { search: d.key }"
[class.error]="getError(d.key)"
>
<tui-avatar>
<tui-avatar appearance="action-grayscale">
<img
alt=""
[src]="

View File

@@ -25,7 +25,7 @@ import { getManifest } from 'src/app/utils/get-package-data'
selector: 'tr[task]',
template: `
<td tuiFade class="row">
<tui-avatar size="xs">
<tui-avatar appearance="action-grayscale" size="xs">
<img [src]="pkg()?.icon || fallback()?.icon" alt="" />
</tui-avatar>
<span>{{ title() || fallback()?.title }}</span>

View File

@@ -47,7 +47,9 @@ const INACTIVE: PrimaryStatus[] = [
</div>
<aside class="g-aside">
<header tuiCell routerLink="./">
<tui-avatar><img alt="" [src]="service()?.icon" /></tui-avatar>
<tui-avatar appearance="action-grayscale">
<img alt="" [src]="service()?.icon" />
</tui-avatar>
<span tuiTitle>
<strong tuiFade>{{ manifest()?.title }}</strong>
<span tuiSubtitle>{{ manifest()?.version }}</span>

View File

@@ -1,6 +1,4 @@
import { ChangeDetectionStrategy, Component, inject } from '@angular/core'
import { i18nPipe } from '@start9labs/shared'
import { TuiSkeleton } from '@taiga-ui/kit'
import { TableComponent } from 'src/app/routes/portal/components/table.component'
import { AuthorityItemComponent } from './item.component'
import { AuthorityService } from './authority.service'
@@ -12,15 +10,11 @@ import { AuthorityService } from './authority.service'
<tr [authority]="{ name: 'Local Root CA' }"></tr>
@for (authority of authorityService.authorities(); track $index) {
<tr [authority]="authority"></tr>
} @empty {
<td [attr.colspan]="4">
<div [tuiSkeleton]="true">{{ 'Loading' | i18n }}</div>
</td>
}
</table>
`,
changeDetection: ChangeDetectionStrategy.OnPush,
imports: [TuiSkeleton, i18nPipe, TableComponent, AuthorityItemComponent],
imports: [TableComponent, AuthorityItemComponent],
})
export class AuthoritiesTableComponent {
protected readonly authorityService = inject(AuthorityService)

View File

@@ -18,7 +18,7 @@ import { DataModel } from 'src/app/services/patch-db/data-model'
@for (pkg of pkgs() | keyvalue; track $index) {
@if (backupProgress()?.[pkg.key]; as progress) {
<div tuiCell>
<tui-avatar>
<tui-avatar appearance="action-grayscale">
<img alt="" [src]="pkg.value.icon" />
</tui-avatar>
<span tuiTitle>

View File

@@ -45,7 +45,9 @@ import UpdatesComponent from './updates.component'
<tr (click)="expanded.set(!expanded())">
<td>
<div [style.gap.rem]="0.75" [style.padding-inline-end.rem]="1">
<tui-avatar size="s"><img alt="" [src]="item().icon" /></tui-avatar>
<tui-avatar appearance="action-grayscale" size="s">
<img alt="" [src]="item().icon" />
</tui-avatar>
<span tuiTitle [style.margin]="'-0.125rem 0 0'">
<b tuiFade>{{ item().title }}</b>
<span tuiSubtitle tuiFade class="mobile">

View File

@@ -69,7 +69,7 @@ interface UpdatesData {
[class.g-secondary]="current()?.url !== registry.url"
(click)="current.set(registry)"
>
<tui-avatar>
<tui-avatar appearance="action-grayscale">
<store-icon [url]="registry.url" />
</tui-avatar>
<span tuiTitle>