mirror of
https://github.com/Start9Labs/start-os.git
synced 2026-03-30 04:01:58 +00:00
Misc (#3087)
* help ios downlaod .crt and add begin add masked for addresses * only require and show CA for public domain if addSsl * fix type and revert i18n const * feat: add address masking and adjust design (#3088) * feat: add address masking and adjust design * update lockfile * chore: move eye button to actions * chore: refresh notifications and handle action error * static width for health check name --------- Co-authored-by: Matt Hill <mattnine@protonmail.com> * hide certificate authorities tab * alpha.17 * add waiting health check status * remove "on" from waiting message * reject on abort in `.watch` * id migration: nostr -> nostr-rs-relay * health check waiting state * use interface type for launch button * better wording for masked * cleaner * sdk improvements * fix type error * fix notification badge issue --------- Co-authored-by: Alex Inkin <alexander@inkin.ru> Co-authored-by: Aiden McClelland <me@drbonez.dev>
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
import { AsyncPipe } from '@angular/common'
|
||||
import { Component, ElementRef, inject, input } from '@angular/core'
|
||||
import { Component, ElementRef, inject } from '@angular/core'
|
||||
import {
|
||||
INTERSECTION_ROOT,
|
||||
WA_INTERSECTION_ROOT,
|
||||
WaIntersectionObserver,
|
||||
} from '@ng-web-apis/intersection-observer'
|
||||
import { WaMutationObserver } from '@ng-web-apis/mutation-observer'
|
||||
@@ -36,12 +36,7 @@ import { SetupLogsService } from '../../services/setup-logs.service'
|
||||
NgDompurifyPipe,
|
||||
TuiScrollbar,
|
||||
],
|
||||
providers: [
|
||||
{
|
||||
provide: INTERSECTION_ROOT,
|
||||
useExisting: ElementRef,
|
||||
},
|
||||
],
|
||||
providers: [{ provide: WA_INTERSECTION_ROOT, useExisting: ElementRef }],
|
||||
})
|
||||
export class LogsWindowComponent {
|
||||
readonly logs$ = inject(SetupLogsService)
|
||||
|
||||
@@ -40,7 +40,9 @@ import { i18nKey } from '../i18n/i18n.providers'
|
||||
class="button"
|
||||
[iconStart]="masked ? '@tui.eye' : '@tui.eye-off'"
|
||||
(click)="masked = !masked"
|
||||
></button>
|
||||
>
|
||||
{{ 'Reveal/Hide' | i18n }}
|
||||
</button>
|
||||
}
|
||||
</tui-textfield>
|
||||
<footer class="g-buttons">
|
||||
|
||||
@@ -1,25 +1,22 @@
|
||||
import { Directive, inject, DOCUMENT } from '@angular/core'
|
||||
import { Directive, DOCUMENT, inject } from '@angular/core'
|
||||
import { takeUntilDestroyed } from '@angular/core/rxjs-interop'
|
||||
import {
|
||||
MutationObserverService,
|
||||
provideMutationObserverInit,
|
||||
WaMutationObserverService,
|
||||
} from '@ng-web-apis/mutation-observer'
|
||||
import { tuiInjectElement } from '@taiga-ui/cdk'
|
||||
|
||||
@Directive({
|
||||
selector: '[safeLinks]',
|
||||
providers: [
|
||||
MutationObserverService,
|
||||
provideMutationObserverInit({
|
||||
childList: true,
|
||||
subtree: true,
|
||||
}),
|
||||
WaMutationObserverService,
|
||||
provideMutationObserverInit({ childList: true, subtree: true }),
|
||||
],
|
||||
})
|
||||
export class SafeLinksDirective {
|
||||
private readonly doc = inject(DOCUMENT)
|
||||
private readonly el = tuiInjectElement()
|
||||
private readonly sub = inject(MutationObserverService)
|
||||
private readonly sub = inject(WaMutationObserverService)
|
||||
.pipe(takeUntilDestroyed())
|
||||
.subscribe(() => {
|
||||
Array.from(this.doc.links)
|
||||
|
||||
@@ -90,6 +90,9 @@ export default {
|
||||
90: 'Root-CA ist vertrauenswürdig!',
|
||||
91: 'Installierte Dienste',
|
||||
92: 'Diagnosen für den Tor-Daemon auf diesem Server',
|
||||
93: 'Fingerabdruck kopieren',
|
||||
94: 'Warten',
|
||||
95: 'Warten auf',
|
||||
96: 'Öffentliche Domain hinzufügen',
|
||||
97: 'Wird entfernt',
|
||||
100: 'Nicht gespeicherte Änderungen',
|
||||
@@ -578,7 +581,7 @@ export default {
|
||||
611: 'Keine Service-Schnittstellen',
|
||||
612: 'Grund',
|
||||
613: 'Private Gateways für die StartOS-Benutzeroberfläche können nicht deaktiviert werden',
|
||||
614: 'CA-Fingerabdruck',
|
||||
614: 'Root-CA',
|
||||
615: 'DHCP-Server',
|
||||
616: 'DHCP-Server können nicht bearbeitet werden',
|
||||
617: 'Statisch',
|
||||
@@ -592,4 +595,5 @@ export default {
|
||||
625: 'Eine andere Version auswählen',
|
||||
626: 'Hochladen',
|
||||
627: 'UI öffnen',
|
||||
628: 'In Zwischenablage kopiert',
|
||||
} satisfies i18n
|
||||
|
||||
@@ -89,6 +89,9 @@ export const ENGLISH = {
|
||||
'Root CA Trusted!': 90,
|
||||
'Installed services': 91, // as in, software services installed on this computer
|
||||
'Diagnostics for the Tor daemon on this server': 92,
|
||||
'Copy fingerprint': 93, // as in the fingerprint of a root certificate authority
|
||||
'Waiting': 94,
|
||||
'Waiting on': 95, // as in "awaiting"
|
||||
'Add public domain': 96,
|
||||
'Removing': 97,
|
||||
'Unsaved changes': 100,
|
||||
@@ -577,7 +580,7 @@ export const ENGLISH = {
|
||||
'No service interfaces': 611, // as in, there are no available interfaces (API, UI, etc) for this software application
|
||||
'Reason': 612, // as in, an explanation for something
|
||||
'Cannot disable private gateways for StartOS UI': 613,
|
||||
'CA fingerprint': 614, // as in, the unique, fixed-length digital identifier generated from a certificate's data using a cryptographic hash function
|
||||
'Root CA': 614, // as in, the unique, fixed-length digital identifier generated from a certificate's data using a cryptographic hash function
|
||||
'DHCP Servers': 615,
|
||||
'Cannot edit DHCP servers': 616,
|
||||
'Static': 617, // as in, unchanging
|
||||
@@ -591,4 +594,5 @@ export const ENGLISH = {
|
||||
'Select another version': 625,
|
||||
'Upload': 626, // as in, upload a file
|
||||
'Open UI': 627, // as in, upload a file
|
||||
'Copied to clipboard': 628,
|
||||
} as const
|
||||
|
||||
@@ -90,6 +90,9 @@ export default {
|
||||
90: '¡CA raíz confiable!',
|
||||
91: 'Servicios instalados',
|
||||
92: 'Diagnósticos para el demonio Tor en este servidor',
|
||||
93: 'Copiar huella digital',
|
||||
94: 'Esperando',
|
||||
95: 'En espera de',
|
||||
96: 'Agregar dominio público',
|
||||
97: 'Eliminando',
|
||||
100: 'Cambios no guardados',
|
||||
@@ -578,7 +581,7 @@ export default {
|
||||
611: 'Sin interfaces de servicio',
|
||||
612: 'Razón',
|
||||
613: 'No se pueden deshabilitar las puertas de enlace privadas para la interfaz de usuario de StartOS',
|
||||
614: 'Huella digital de la CA',
|
||||
614: 'CA raíz',
|
||||
615: 'Servidores DHCP',
|
||||
616: 'No se pueden editar los servidores DHCP',
|
||||
617: 'Estático',
|
||||
@@ -592,4 +595,5 @@ export default {
|
||||
625: 'Seleccionar otra versión',
|
||||
626: 'Subir',
|
||||
627: 'Abrir UI',
|
||||
628: 'Copiado al portapapeles',
|
||||
} satisfies i18n
|
||||
|
||||
@@ -90,6 +90,9 @@ export default {
|
||||
90: 'Certificat racine approuvé !',
|
||||
91: 'Services installés',
|
||||
92: 'Diagnostics pour le service Tor sur ce serveur',
|
||||
93: 'Copier l’empreinte',
|
||||
94: 'En attente',
|
||||
95: 'En attente de',
|
||||
96: 'Ajouter un domaine public',
|
||||
97: 'Suppression',
|
||||
100: 'Modifications non enregistrées',
|
||||
@@ -578,7 +581,7 @@ export default {
|
||||
611: 'Aucune interface de service',
|
||||
612: 'Raison',
|
||||
613: "Impossible de désactiver les passerelles privées pour l'interface utilisateur StartOS",
|
||||
614: 'Empreinte de l’AC',
|
||||
614: 'CA racine',
|
||||
615: 'Serveurs DHCP',
|
||||
616: 'Impossible de modifier les serveurs DHCP',
|
||||
617: 'Statique',
|
||||
@@ -592,4 +595,5 @@ export default {
|
||||
625: 'Sélectionner une autre version',
|
||||
626: 'Téléverser',
|
||||
627: 'Ouvrir UI',
|
||||
628: 'Copié dans le presse-papiers',
|
||||
} satisfies i18n
|
||||
|
||||
@@ -90,6 +90,9 @@ export default {
|
||||
90: 'Główny certyfikat CA zaufany!',
|
||||
91: 'Zainstalowane usługi',
|
||||
92: 'Diagnostyka demona Tor na tym serwerze',
|
||||
93: 'Kopiuj odcisk palca',
|
||||
94: 'Oczekiwanie',
|
||||
95: 'Oczekiwanie na',
|
||||
96: 'Dodaj domenę publiczną',
|
||||
97: 'Usuwanie',
|
||||
100: 'Niezapisane zmiany',
|
||||
@@ -578,7 +581,7 @@ export default {
|
||||
611: 'Brak interfejsów usług',
|
||||
612: 'Powód',
|
||||
613: 'Nie można wyłączyć prywatnych bram dla interfejsu użytkownika StartOS',
|
||||
614: 'Odcisk palca CA',
|
||||
614: 'głównego CA',
|
||||
615: 'Serwery DHCP',
|
||||
616: 'Nie można edytować serwerów DHCP',
|
||||
617: 'Statyczny',
|
||||
@@ -592,4 +595,5 @@ export default {
|
||||
625: 'Wybierz inną wersję',
|
||||
626: 'Prześlij',
|
||||
627: 'Otwórz UI',
|
||||
628: 'Skopiowano do schowka',
|
||||
} satisfies i18n
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { forwardRef, signal } from '@angular/core'
|
||||
import { tuiCreateToken, tuiProvide } from '@taiga-ui/cdk'
|
||||
import { forwardRef, InjectionToken, signal } from '@angular/core'
|
||||
import { tuiProvide } from '@taiga-ui/cdk'
|
||||
import {
|
||||
TuiLanguageName,
|
||||
tuiLanguageSwitcher,
|
||||
@@ -11,12 +11,19 @@ import { i18nService } from './i18n.service'
|
||||
export type i18nKey = keyof typeof ENGLISH
|
||||
export type i18n = Record<(typeof ENGLISH)[i18nKey], string>
|
||||
|
||||
export const I18N = tuiCreateToken(signal<i18n | null>(null))
|
||||
export const I18N_LOADER =
|
||||
tuiCreateToken<(lang: TuiLanguageName) => Promise<i18n>>()
|
||||
export const I18N_STORAGE = tuiCreateToken<
|
||||
export const I18N = new InjectionToken('', {
|
||||
factory: () => signal<i18n | null>(null),
|
||||
})
|
||||
|
||||
export const I18N_LOADER = new InjectionToken<
|
||||
(lang: TuiLanguageName) => Promise<i18n>
|
||||
>('')
|
||||
|
||||
export const I18N_STORAGE = new InjectionToken<
|
||||
(lang: TuiLanguageName) => Promise<void>
|
||||
>(() => Promise.resolve())
|
||||
>('', {
|
||||
factory: () => () => Promise.resolve(),
|
||||
})
|
||||
|
||||
export const I18N_PROVIDERS = [
|
||||
tuiLanguageSwitcher(async (language: TuiLanguageName): Promise<unknown> => {
|
||||
|
||||
@@ -50,7 +50,6 @@ export * from './tokens/relative-url'
|
||||
|
||||
export * from './util/base-64'
|
||||
export * from './util/convert-ansi'
|
||||
export * from './util/copy-to-clipboard'
|
||||
export * from './util/format-progress'
|
||||
export * from './util/get-new-entries'
|
||||
export * from './util/get-pkg-id'
|
||||
|
||||
@@ -1,16 +1,20 @@
|
||||
import { inject, Injectable } from '@angular/core'
|
||||
import { Clipboard } from '@angular/cdk/clipboard'
|
||||
import { TuiAlertService } from '@taiga-ui/core'
|
||||
import { copyToClipboard } from '../util/copy-to-clipboard'
|
||||
|
||||
import { i18nPipe } from '../i18n/i18n.pipe'
|
||||
|
||||
@Injectable({ providedIn: 'root' })
|
||||
export class CopyService {
|
||||
private readonly clipboard = inject(Clipboard)
|
||||
private readonly i18n = inject(i18nPipe)
|
||||
private readonly alerts = inject(TuiAlertService)
|
||||
|
||||
async copy(text: string) {
|
||||
const success = await copyToClipboard(text)
|
||||
const success = this.clipboard.copy(text)
|
||||
const message = success ? 'Copied to clipboard' : 'Failed'
|
||||
const appearance = success ? 'positive' : 'negative'
|
||||
|
||||
this.alerts
|
||||
.open(success ? 'Copied to clipboard!' : 'Failed to copy to clipboard.')
|
||||
.subscribe()
|
||||
this.alerts.open(this.i18n.transform(message), { appearance }).subscribe()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,7 +17,9 @@ export class DownloadHTMLService {
|
||||
const elem = this.document.createElement('a')
|
||||
elem.setAttribute(
|
||||
'href',
|
||||
'data:text/plain;charset=utf-8,' + encodeURIComponent(html),
|
||||
URL.createObjectURL(
|
||||
new Blob([html], { type: 'application/octet-stream' }),
|
||||
),
|
||||
)
|
||||
elem.setAttribute('download', filename)
|
||||
elem.style.display = 'none'
|
||||
|
||||
@@ -16,7 +16,6 @@ import {
|
||||
HttpAngularOptions,
|
||||
HttpOptions,
|
||||
LocalHttpResponse,
|
||||
Method,
|
||||
} from '../types/http.types'
|
||||
import { RPCResponse, RPCOptions } from '../types/rpc.types'
|
||||
import { RELATIVE_URL } from '../tokens/relative-url'
|
||||
@@ -42,7 +41,7 @@ export class HttpService {
|
||||
const { method, headers, params, timeout } = opts
|
||||
|
||||
return this.httpRequest<RPCResponse<T>>({
|
||||
method: Method.POST,
|
||||
method: 'POST',
|
||||
url: fullUrl || this.relativeUrl,
|
||||
headers,
|
||||
body: { method, params },
|
||||
@@ -73,7 +72,7 @@ export class HttpService {
|
||||
}
|
||||
|
||||
let req: Observable<LocalHttpResponse<T>>
|
||||
if (method === Method.GET) {
|
||||
if (method === 'GET') {
|
||||
req = this.http.get(url, options as any) as any
|
||||
} else {
|
||||
req = this.http.post(url, body, options as any) as any
|
||||
|
||||
@@ -1,9 +1,6 @@
|
||||
import { HttpHeaders, HttpResponse } from '@angular/common/http'
|
||||
|
||||
export enum Method {
|
||||
GET = 'GET',
|
||||
POST = 'POST',
|
||||
}
|
||||
export type Method = 'GET' | 'POST'
|
||||
|
||||
type ParamPrimitive = string | number | boolean
|
||||
|
||||
|
||||
@@ -1,19 +0,0 @@
|
||||
export async function copyToClipboard(str: string): Promise<boolean> {
|
||||
if (window.isSecureContext) {
|
||||
return navigator.clipboard
|
||||
.writeText(str)
|
||||
.then(() => true)
|
||||
.catch(() => false)
|
||||
}
|
||||
|
||||
const el = document.createElement('textarea')
|
||||
el.value = str
|
||||
el.setAttribute('readonly', '')
|
||||
el.style.position = 'absolute'
|
||||
el.style.left = '-9999px'
|
||||
document.body.appendChild(el)
|
||||
el.select()
|
||||
const didCopy = document.execCommand('copy')
|
||||
document.body.removeChild(el)
|
||||
return didCopy
|
||||
}
|
||||
Reference in New Issue
Block a user