282 lines
10 KiB
HTML
282 lines
10 KiB
HTML
<div class="container">
|
|
<h1 class="d-none d-sm-block h3 mb-3 text-center" i18n>Settings</h1>
|
|
<div class="row">
|
|
<div class="col">
|
|
<div class="align-items-center d-flex py-1">
|
|
<div class="pr-1 w-50">
|
|
<div i18n>Presenter View</div>
|
|
<div class="hint-text text-muted" i18n>
|
|
Protection for sensitive information like absolute performances and
|
|
quantity values
|
|
</div>
|
|
</div>
|
|
<div class="pl-1 w-50">
|
|
<mat-slide-toggle
|
|
color="primary"
|
|
hideIcon="true"
|
|
[checked]="user.settings.isRestrictedView"
|
|
[disabled]="!hasPermissionToUpdateUserSettings"
|
|
(change)="onRestrictedViewChange($event)"
|
|
/>
|
|
</div>
|
|
</div>
|
|
<div class="d-flex mt-4 py-1">
|
|
<form #changeUserSettingsForm="ngForm" class="w-100">
|
|
<div class="d-flex mb-2">
|
|
<div class="align-items-center d-flex pt-1 pt-1 w-50">
|
|
<ng-container i18n>Base Currency</ng-container>
|
|
</div>
|
|
<div class="pl-1 w-50">
|
|
<mat-form-field appearance="outline" class="w-100 without-hint">
|
|
<mat-select
|
|
name="baseCurrency"
|
|
[disabled]="!hasPermissionToUpdateUserSettings"
|
|
[value]="user.settings.baseCurrency"
|
|
(selectionChange)="
|
|
onChangeUserSetting('baseCurrency', $event.value)
|
|
"
|
|
>
|
|
@for (currency of currencies; track currency) {
|
|
<mat-option [value]="currency">{{ currency }}</mat-option>
|
|
}
|
|
</mat-select>
|
|
</mat-form-field>
|
|
</div>
|
|
</div>
|
|
<div class="align-items-center d-flex mb-2">
|
|
<div class="pr-1 w-50">
|
|
<div i18n>Language</div>
|
|
@if (isCommunityLanguage()) {
|
|
<div class="hint-text text-muted" i18n>
|
|
If a translation is missing, kindly support us in extending it
|
|
<a
|
|
href="https://github.com/ghostfolio/ghostfolio/blob/main/apps/client/src/locales/messages.{{
|
|
language
|
|
}}.xlf"
|
|
target="_blank"
|
|
>here</a
|
|
>.
|
|
</div>
|
|
}
|
|
</div>
|
|
<div class="pl-1 w-50">
|
|
<mat-form-field appearance="outline" class="w-100 without-hint">
|
|
<mat-select
|
|
name="language"
|
|
[disabled]="!hasPermissionToUpdateUserSettings"
|
|
[value]="language"
|
|
(selectionChange)="
|
|
onChangeUserSetting('language', $event.value)
|
|
"
|
|
>
|
|
<mat-option [value]="null" />
|
|
<mat-option value="de">Deutsch</mat-option>
|
|
<mat-option value="en">English</mat-option>
|
|
@if (user?.settings?.isExperimentalFeatures) {
|
|
<mat-option value="zh"
|
|
>Chinese (<ng-container i18n>Community</ng-container
|
|
>)</mat-option
|
|
>
|
|
}
|
|
<mat-option value="es"
|
|
>Español (<ng-container i18n>Community</ng-container
|
|
>)</mat-option
|
|
>
|
|
<mat-option value="fr"
|
|
>Français (<ng-container i18n>Community</ng-container
|
|
>)</mat-option
|
|
>
|
|
<mat-option value="it"
|
|
>Italiano (<ng-container i18n>Community</ng-container
|
|
>)</mat-option
|
|
>
|
|
<mat-option value="nl"
|
|
>Nederlands (<ng-container i18n>Community</ng-container
|
|
>)</mat-option
|
|
>
|
|
@if (user?.settings?.isExperimentalFeatures) {
|
|
<mat-option value="pl"
|
|
>Polski (<ng-container i18n>Community</ng-container
|
|
>)</mat-option
|
|
>
|
|
}
|
|
<mat-option value="pt"
|
|
>Português (<ng-container i18n>Community</ng-container
|
|
>)</mat-option
|
|
>
|
|
<mat-option value="tr"
|
|
>Türkçe (<ng-container i18n>Community</ng-container
|
|
>)</mat-option
|
|
>
|
|
</mat-select>
|
|
</mat-form-field>
|
|
</div>
|
|
</div>
|
|
<div class="align-items-center d-flex mb-2">
|
|
<div class="pr-1 w-50">
|
|
<div i18n>Locale</div>
|
|
<div class="hint-text text-muted">
|
|
<ng-container i18n>Date and number format</ng-container>
|
|
</div>
|
|
</div>
|
|
<div class="pl-1 w-50">
|
|
<mat-form-field appearance="outline" class="w-100 without-hint">
|
|
<mat-select
|
|
name="locale"
|
|
[disabled]="!hasPermissionToUpdateUserSettings"
|
|
[value]="user.settings.locale"
|
|
(selectionChange)="
|
|
onChangeUserSetting('locale', $event.value)
|
|
"
|
|
>
|
|
<mat-option [value]="null" />
|
|
@for (locale of locales; track locale) {
|
|
<mat-option [value]="locale">{{ locale }}</mat-option>
|
|
}
|
|
</mat-select>
|
|
</mat-form-field>
|
|
</div>
|
|
</div>
|
|
<div class="d-flex">
|
|
<div class="align-items-center d-flex pr-1 pt-1 w-50">
|
|
<ng-container i18n>Appearance</ng-container>
|
|
</div>
|
|
<div class="pl-1 w-50">
|
|
<mat-form-field appearance="outline" class="w-100 without-hint">
|
|
<mat-select
|
|
class="with-placeholder-as-option"
|
|
name="colorScheme"
|
|
[disabled]="!hasPermissionToUpdateUserSettings"
|
|
[placeholder]="appearancePlaceholder"
|
|
[value]="user?.settings?.colorScheme"
|
|
(selectionChange)="
|
|
onChangeUserSetting('colorScheme', $event.value)
|
|
"
|
|
>
|
|
<mat-option i18n [value]="null">Auto</mat-option>
|
|
<mat-option i18n value="LIGHT">Light</mat-option>
|
|
<mat-option i18n value="DARK">Dark</mat-option>
|
|
</mat-select>
|
|
</mat-form-field>
|
|
</div>
|
|
</div>
|
|
</form>
|
|
</div>
|
|
<div class="d-flex mt-4 py-1">
|
|
<div class="pr-1 w-50">
|
|
<div i18n>Zen Mode</div>
|
|
<div class="hint-text text-muted" i18n>
|
|
Distraction-free experience for turbulent times
|
|
</div>
|
|
</div>
|
|
<div class="pl-1 w-50">
|
|
<mat-slide-toggle
|
|
color="primary"
|
|
hideIcon="true"
|
|
[checked]="user.settings.viewMode === 'ZEN'"
|
|
[disabled]="!hasPermissionToUpdateViewMode"
|
|
(change)="onViewModeChange($event)"
|
|
/>
|
|
</div>
|
|
</div>
|
|
<div class="align-items-center d-flex mt-4 py-1">
|
|
<div class="pr-1 w-50">
|
|
<div i18n>Biometric Authentication</div>
|
|
<div class="hint-text text-muted" i18n>Sign in with fingerprint</div>
|
|
</div>
|
|
<div class="pl-1 w-50">
|
|
<mat-slide-toggle
|
|
color="primary"
|
|
hideIcon="true"
|
|
[checked]="isWebAuthnEnabled === true"
|
|
[disabled]="
|
|
!hasPermissionToUpdateUserSettings || !isFingerprintSupported
|
|
"
|
|
(change)="onSignInWithFingerprintChange($event)"
|
|
/>
|
|
</div>
|
|
</div>
|
|
<div class="align-items-center d-flex mt-4 py-1">
|
|
<div class="pr-1 w-50">
|
|
<div i18n>Experimental Features</div>
|
|
<div class="hint-text text-muted" i18n>
|
|
Sneak peek at upcoming functionality
|
|
</div>
|
|
</div>
|
|
<div class="pl-1 w-50">
|
|
<mat-slide-toggle
|
|
color="primary"
|
|
hideIcon="true"
|
|
[checked]="user.settings.isExperimentalFeatures"
|
|
[disabled]="!hasPermissionToUpdateUserSettings"
|
|
(change)="onExperimentalFeaturesChange($event)"
|
|
/>
|
|
</div>
|
|
</div>
|
|
<div class="align-items-center d-flex mt-4 py-1">
|
|
<div class="pr-1 w-50">
|
|
Ghostfolio <ng-container i18n>User ID</ng-container>
|
|
</div>
|
|
<div class="pl-1 text-monospace w-50">{{ user?.id }}</div>
|
|
</div>
|
|
<div class="align-items-center d-flex py-1">
|
|
<div class="pr-1 w-50"></div>
|
|
<div class="pl-1 text-monospace w-50">
|
|
<button color="primary" mat-flat-button (click)="onExport()">
|
|
<span i18n>Export Data</span>
|
|
</button>
|
|
</div>
|
|
</div>
|
|
@if (hasPermissionToDeleteOwnUser) {
|
|
<hr class="mt-5" />
|
|
<form
|
|
class="w-100"
|
|
[formGroup]="deleteOwnUserForm"
|
|
(ngSubmit)="onCloseAccount()"
|
|
>
|
|
<div class="d-flex py-1">
|
|
<div class="pr-1 text-danger w-50" i18n>Danger Zone</div>
|
|
<div class="pl-1 w-50">
|
|
<mat-form-field
|
|
appearance="outline"
|
|
class="without-hint w-100"
|
|
[hideRequiredMarker]="true"
|
|
>
|
|
<mat-label i18n>Security Token</mat-label>
|
|
<input
|
|
formControlName="accessToken"
|
|
matInput
|
|
[type]="isAccessTokenHidden ? 'password' : 'text'"
|
|
/>
|
|
<button
|
|
mat-button
|
|
matSuffix
|
|
type="button"
|
|
(click)="isAccessTokenHidden = !isAccessTokenHidden"
|
|
>
|
|
<ion-icon
|
|
[name]="
|
|
isAccessTokenHidden ? 'eye-outline' : 'eye-off-outline'
|
|
"
|
|
/>
|
|
</button>
|
|
</mat-form-field>
|
|
<button
|
|
class="mt-2"
|
|
color="warn"
|
|
mat-flat-button
|
|
type="submit"
|
|
[disabled]="
|
|
!(deleteOwnUserForm.dirty && deleteOwnUserForm.valid)
|
|
"
|
|
>
|
|
<span i18n>Close Account</span>
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</form>
|
|
}
|
|
</div>
|
|
</div>
|
|
</div>
|