1
0
mirror of https://github.com/bpatrik/pigallery2.git synced 2024-12-23 01:27:14 +02:00

Improving settings UI #569

This commit is contained in:
Patrik J. Braun 2023-01-05 21:39:59 +01:00
parent 36b0a216d6
commit 2350bc780d
7 changed files with 67 additions and 31 deletions

View File

@ -882,6 +882,7 @@ export class ServerMediaConfig extends ClientMediaConfig {
@ConfigProperty({
tags: {
name: $localize`Video`,
uiIcon: 'video',
priority: ConfigPriority.advanced,
uiJob: [
{
@ -895,6 +896,7 @@ export class ServerMediaConfig extends ClientMediaConfig {
@ConfigProperty({
tags: {
name: $localize`Photo`,
uiIcon: 'camera-slr',
priority: ConfigPriority.advanced,
uiJob: [
{
@ -907,6 +909,7 @@ export class ServerMediaConfig extends ClientMediaConfig {
@ConfigProperty({
tags: {
name: $localize`Thumbnail`,
uiIcon: 'grid-three-up',
priority: ConfigPriority.advanced,
uiJob: [{job: DefaultsJobs[DefaultsJobs['Thumbnail Generation']]}]
} as TAGS

View File

@ -1,4 +1,4 @@
import { backendText } from '../../BackendTexts';
import {backendText} from '../../BackendTexts';
export type fieldType = 'string' | 'number' | 'boolean' | 'number-array';
@ -29,6 +29,7 @@ export interface JobDTO {
export const JobDTOUtils = {
getHashName: (jobName: string, config: any = {}) => {
return jobName + '-' + JSON.stringify(config);
const sorted = Object.keys(config).sort().reduce((ret, key) => `${ret},${key}:${JSON.stringify(config[key])}`, '');
return jobName + '-' + JSON.stringify(sorted);
},
};

View File

@ -73,12 +73,21 @@
<div class="card-body text-md-start text-center align-content-md-start align-content-center">
<h5 i18n="title of left card in settings page that contains settings contents" class="card-title">
Menu</h5>
<button class="btn btn-link nav-link text-start py-md-1 px-md-0"
*ngFor="let s of contents; let i=index;"
(click)="scrollTo(i)"
[hidden]="!s.HasAvailableSettings">
<span class="oi oi-{{s.icon}}"></span> {{s.Name}}
</button>
<div class="py-md-1 px-md-0"
*ngFor="let s of contents;"
[hidden]="!s.HasAvailableSettings">
<button class="btn btn-link nav-link text-start p-0"
(click)="viewportScroller.scrollToAnchor(s.ConfigPath)"
>
<span class="oi oi-{{s.icon}}"></span> {{s.Name}}
</button>
<button class="btn btn-link nav-link text-start ms-3 p-0"
*ngFor="let n of s.nestedConfigs;"
[hidden]="!n.visible()"
(click)="viewportScroller.scrollToAnchor(n.id)">
<span class="oi oi-{{n.icon}}"></span> {{n.name}}
</button>
</div>
</div>
</div>
@ -90,6 +99,7 @@
#setting
#tmpl
[ConfigPath]="cp"
[enableNesting]="cp=='Media'"
[hidden]="!tmpl.HasAvailableSettings">
<ng-container
*ngIf="cp=='Indexing'">

View File

@ -4,7 +4,7 @@ import {UserRoles} from '../../../../common/entities/UserDTO';
import {NotificationService} from '../../model/notification.service';
import {NotificationType} from '../../../../common/entities/NotificationDTO';
import {NavigationService} from '../../model/navigation.service';
import {PageHelper} from '../../model/page.helper';
import {ViewportScroller} from '@angular/common';
import {SettingsService} from '../settings/settings.service';
import {ConfigPriority} from '../../../../common/config/public/ClientConfig';
import {WebConfig} from '../../../../common/config/private/WebConfig';
@ -29,6 +29,7 @@ export class AdminComponent implements OnInit, AfterViewInit {
constructor(
private authService: AuthenticationService,
private navigation: NavigationService,
public viewportScroller: ViewportScroller,
public notificationService: NotificationService,
public settingsService: SettingsService,
) {
@ -42,12 +43,6 @@ export class AdminComponent implements OnInit, AfterViewInit {
setTimeout(() => (this.contents = this.settingsComponents.toArray()), 0);
}
scrollTo(i: number): void {
PageHelper.ScrollY =
this.settingsComponentsElemRef
.toArray()[i].nativeElement.getBoundingClientRect().top + PageHelper.ScrollY;
}
ngOnInit(): void {
if (
!this.authService.isAuthenticated() ||

View File

@ -2,5 +2,7 @@ export interface ISettingsComponent {
HasAvailableSettings: boolean;
Name: string;
icon: string;
ConfigPath: string;
Changed: boolean;
nestedConfigs: { id: string, name: string, visible: () => boolean, icon: string }[];
}

View File

@ -1,4 +1,4 @@
<form #settingsForm="ngForm" class="form-horizontal">
<form #settingsForm="ngForm" class="form-horizontal" [id]="ConfigPath">
<div class="card mb-4">
<h5 class="card-header">
<span class="oi oi-{{icon}}"></span> {{Name}}
@ -24,7 +24,7 @@
<div [hidden]="!error" class="alert alert-danger" role="alert"><strong>Error: </strong>{{error}}</div>
<ng-container *ngIf="states.value.enabled !== false">
<ng-container
*ngTemplateOutlet="Recursion; context:{ rStates: states,skipEnabled:true,confPath:ConfigPath,skipJobs:true }"
*ngTemplateOutlet="Recursion; context:{ rStates: states,topLevel:true,confPath:ConfigPath,skipJobs:true }"
></ng-container>
</ng-container>
@ -32,7 +32,7 @@
*ngIf="states.value.enabled === false">
{{Name}} <span i18n>config is not supported with these settings.</span>
</div>
<div class="row">
<div class="row mt-2">
<div class="col" *ngIf="states.tags?.uiJob && !states.tags?.uiJob[0].description">
<ng-container
*ngTemplateOutlet="JobTemplate; context:{ uiJob: states.tags?.uiJob }"
@ -67,7 +67,7 @@
</div>
</div>
<ng-template #Recursion let-rStates="rStates" let-skipEnabled="skipEnabled" let-skipJobs="skipJobs"
<ng-template #Recursion let-rStates="rStates" let-topLevel="topLevel" let-skipJobs="skipJobs"
let-confPath="confPath">
<div class="alert alert-secondary" role="alert" *ngIf="rStates.description">
{{rStates.description}}
@ -75,24 +75,34 @@
<ng-container *ngFor="let ck of getKeys(rStates)">
<ng-container *ngIf="!(rStates.value.__state[ck].shouldHide && rStates.value.__state[ck].shouldHide())">
<app-settings-entry
*ngIf="(ck!=='enabled' || !skipEnabled) && !rStates.value.__state[ck].isConfigType"
*ngIf="(ck!=='enabled' || !topLevel) && !rStates.value.__state[ck].isConfigType"
[name]="confPath+'_'+ck"
[ngModel]="rStates?.value.__state[ck]">
</app-settings-entry>
<ng-container *ngIf="rStates.value.__state[ck].isConfigType">
<div class="row mt-2">
<div class="col-auto">
<h5>{{rStates?.value.__state[ck].tags?.name || ck}}</h5>
</div>
<div class="col">
<hr/>
<div class="card mt-2 mb-2" *ngIf="topLevel && enableNesting" [id]="ConfigPath+'.'+ck">
<div class="card-body">
<h5 class="card-title"><span class="oi oi-{{rStates?.value.__state[ck].tags?.uiIcon}}"></span> {{rStates?.value.__state[ck].tags?.name || ck}}</h5>
<ng-container
*ngTemplateOutlet="Recursion; context:{ rStates: rStates.value.__state[ck], confPath:confPath+'.'+ck }"
></ng-container>
</div>
</div>
<div class="mt-2">
<ng-container
*ngTemplateOutlet="Recursion; context:{ rStates: rStates.value.__state[ck], confPath:confPath+'.'+ck }"
></ng-container>
</div>
<ng-container *ngIf="!topLevel || !enableNesting">
<div class="row mt-2">
<div class="col-auto">
<h5>{{rStates?.value.__state[ck].tags?.name || ck}}</h5>
</div>
<div class="col">
<hr/>
</div>
</div>
<div class="mt-2">
<ng-container
*ngTemplateOutlet="Recursion; context:{ rStates: rStates.value.__state[ck], confPath:confPath+'.'+ck }"
></ng-container>
</div>
</ng-container>
</ng-container>
</ng-container>
</ng-container>

View File

@ -59,6 +59,8 @@ export class TemplateComponent implements OnInit, OnChanges, OnDestroy, ISetting
public icon: string;
@Input() ConfigPath: string;
@Input() enableNesting: boolean;
nestedConfigs: { id: string, name: string, visible: () => boolean,icon:string }[] = [];
@ViewChild('settingsForm', {static: true})
form: FormControl;
@ -90,6 +92,19 @@ export class TemplateComponent implements OnInit, OnChanges, OnDestroy, ISetting
this.setSliceFN(c => c.__state[this.ConfigPath]);
}
this.name = this.states.tags?.name || this.ConfigPath;
this.nestedConfigs = [];
if (this.enableNesting) {
for (const key of this.getKeys(this.states)) {
if (this.states.value.__state[key].isConfigType) {
this.nestedConfigs.push({
id: this.ConfigPath + '.' + key,
name: this.states?.value.__state[key].tags?.name,
icon: this.states?.value.__state[key].tags?.uiIcon,
visible: () => !(this.states.value.__state[key].shouldHide && this.states.value.__state[key].shouldHide())
});
}
}
}
}
ngOnInit(): void {