-
-
{{ name }}
-
-
-
-
+
+
+ {{ name }}
+
+ No
+ Yes
+
+
+
diff --git a/frontend/src/app/components/pref-option/pref-option.component.ts b/frontend/src/app/components/pref-option/pref-option.component.ts
index 22dfcdd..6190576 100644
--- a/frontend/src/app/components/pref-option/pref-option.component.ts
+++ b/frontend/src/app/components/pref-option/pref-option.component.ts
@@ -2,7 +2,7 @@ import { Component, Input, OnInit } from '@angular/core';
import { AutoUnsubscribe } from 'ngx-auto-unsubscribe-decorator';
import {
DecodedPref,
- PrefValueType,
+ PrefValueType
} from 'picsur-shared/dist/dto/preferences.dto';
import { AsyncFailable, HasFailed } from 'picsur-shared/dist/types';
import { Subject } from 'rxjs';
@@ -24,9 +24,9 @@ export class PrefOptionComponent implements OnInit {
key: string,
pref: PrefValueType,
) => AsyncFailable
;
- @Input() @Required translator: {
- [key in string]: string;
- };
+ @Input() @Required name: string = '';
+
+ @Input() helpText: string = '';
private updateSubject = new Subject();
@@ -36,10 +36,6 @@ export class PrefOptionComponent implements OnInit {
this.subscribeUpdate();
}
- get name(): string {
- return this.translator[this.pref.key] ?? this.pref.key;
- }
-
get valString(): string {
if (this.pref.type !== 'string') {
throw new Error('Not a string preference');
@@ -76,6 +72,10 @@ export class PrefOptionComponent implements OnInit {
this.update(value);
}
+ booleanUpdateWrapper(e: boolean) {
+ this.update(e);
+ }
+
private async updatePreference(value: PrefValueType) {
const result = await this.updateFunction(this.pref.key, value);
if (!HasFailed(result)) {
diff --git a/frontend/src/app/components/pref-option/pref-option.module.ts b/frontend/src/app/components/pref-option/pref-option.module.ts
index ad069ba..7953791 100644
--- a/frontend/src/app/components/pref-option/pref-option.module.ts
+++ b/frontend/src/app/components/pref-option/pref-option.module.ts
@@ -1,9 +1,11 @@
import { CommonModule } from '@angular/common';
import { NgModule } from '@angular/core';
-import { MatDividerModule } from '@angular/material/divider';
+import { MatButtonModule } from '@angular/material/button';
import { MatFormFieldModule } from '@angular/material/form-field';
+import { MatIconModule } from '@angular/material/icon';
import { MatInputModule } from '@angular/material/input';
-import { MatSlideToggleModule } from '@angular/material/slide-toggle';
+import { MatSelectModule } from '@angular/material/select';
+import { MatTooltipModule } from '@angular/material/tooltip';
import { ErrorManagerModule } from 'src/app/util/error-manager/error-manager.module';
import { PrefOptionComponent } from './pref-option.component';
@@ -12,10 +14,12 @@ import { PrefOptionComponent } from './pref-option.component';
CommonModule,
ErrorManagerModule,
+ MatIconModule,
+ MatTooltipModule,
+ MatButtonModule,
MatFormFieldModule,
MatInputModule,
- MatDividerModule,
- MatSlideToggleModule,
+ MatSelectModule,
],
declarations: [PrefOptionComponent],
exports: [PrefOptionComponent],
diff --git a/frontend/src/app/i18n/sys-pref.i18n.ts b/frontend/src/app/i18n/sys-pref.i18n.ts
index ff3870a..f5e28c6 100644
--- a/frontend/src/app/i18n/sys-pref.i18n.ts
+++ b/frontend/src/app/i18n/sys-pref.i18n.ts
@@ -1,22 +1,83 @@
import { SysPreference } from 'picsur-shared/dist/dto/sys-preferences.enum';
-export const SysPreferenceFriendlyNames: {
- [key in SysPreference]: string;
+export const SysPreferenceUI: {
+ [key in SysPreference]: {
+ name: string;
+ helpText: string;
+ category: string;
+ };
} = {
- [SysPreference.JwtSecret]: 'JWT Secret',
- [SysPreference.JwtExpiresIn]: 'JWT Expiry Time',
- [SysPreference.BCryptStrength]: 'BCrypt Strength',
+ [SysPreference.JwtSecret]: {
+ name: 'JWT Secret',
+ helpText: 'Secret used to sign JWT authentication tokens.',
+ category: 'Authentication',
+ },
+ [SysPreference.JwtExpiresIn]: {
+ name: 'JWT Expiry Time',
+ helpText: 'Time before JWT authentication tokens expire.',
+ category: 'Authentication',
+ },
+ [SysPreference.BCryptStrength]: {
+ name: 'BCrypt Strength',
+ helpText:
+ 'Strength of BCrypt hashing algorithm, 10 is recommended. Reduce this if running on a low powered device.',
+ category: 'Authentication',
+ },
- [SysPreference.RemoveDerivativesAfter]: 'Cached Images Expiry Time',
- [SysPreference.SaveDerivatives]: 'Cache Trancoded Images',
- [SysPreference.AllowEditing]: 'Allow images to be edited (e.g. resize)',
+ [SysPreference.RemoveDerivativesAfter]: {
+ name: 'Cached Images Expiry Time',
+ helpText:
+ 'Time before cached images are deleted. This does not affect the original image. Set to 0 to disable.',
+ category: 'Image Processing',
+ },
+ [SysPreference.SaveDerivatives]: {
+ name: 'Cache Converted Images',
+ helpText:
+ 'Cache converted images, this will reduce the time it takes to load images. It does however use more disk space.',
+ category: 'Image Processing',
+ },
+ [SysPreference.AllowEditing]: {
+ name: 'Allow images to be edited',
+ helpText:
+ 'Allow images to be edited (e.g. resize, flip). Using these features will use more CPU power.',
- [SysPreference.ConversionTimeLimit]: 'Transcode/Edit Time Limit',
- [SysPreference.ConversionMemoryLimit]: 'Transcode/Edit Memory Limit MB',
+ category: 'Image Processing',
+ },
- [SysPreference.EnableTracking]: 'Enable Ackee Web Tracking',
- [SysPreference.TrackingUrl]: 'Ackee tracking URL',
- [SysPreference.TrackingId]: 'Ackee trackign website ID',
+ [SysPreference.ConversionTimeLimit]: {
+ name: 'Convert/Edit Time Limit',
+ helpText:
+ 'Time limit for converting/editing images. You may need to increase this on low powered devices.',
+ category: 'Image Processing',
+ },
+ [SysPreference.ConversionMemoryLimit]: {
+ name: 'Convert/Edit Memory Limit MB',
+ helpText:
+ 'Memory limit for converting/editing images. You only need to increase this if you are storing massive images.',
+ category: 'Image Processing',
+ },
- [SysPreference.EnableTelemetry]: 'Enable System Telemetry',
+ [SysPreference.EnableTracking]: {
+ name: 'Enable Ackee Web Tracking',
+ helpText:
+ 'Enable tracking of the website usage using Ackee. You will need to set the tracking URL and ID.',
+ category: 'Usage',
+ },
+ [SysPreference.TrackingUrl]: {
+ name: 'Ackee tracking URL',
+ helpText: 'URL of the Ackee tracking server.',
+ category: 'Usage',
+ },
+ [SysPreference.TrackingId]: {
+ name: 'Ackee trackign website ID',
+ helpText: 'ID of the website to track.',
+ category: 'Usage',
+ },
+
+ [SysPreference.EnableTelemetry]: {
+ name: 'Enable System Telemetry',
+ helpText:
+ 'Enable system telemetry, this will send anonymous usage data to the developers.',
+ category: 'Usage',
+ },
};
diff --git a/frontend/src/app/i18n/usr-pref.i18n.ts b/frontend/src/app/i18n/usr-pref.i18n.ts
index d2e97d7..cd0ce15 100644
--- a/frontend/src/app/i18n/usr-pref.i18n.ts
+++ b/frontend/src/app/i18n/usr-pref.i18n.ts
@@ -5,3 +5,10 @@ export const UsrPreferenceFriendlyNames: {
} = {
[UsrPreference.KeepOriginal]: 'Keep original file',
};
+
+export const UsrPreferenceHelpText: {
+ [key in UsrPreference]: string;
+} = {
+ [UsrPreference.KeepOriginal]:
+ 'Store the original files you upload to the service, this way no data will be lost. This will also store exif data.',
+};
diff --git a/frontend/src/app/routes/settings/general/settings-general.component.html b/frontend/src/app/routes/settings/general/settings-general.component.html
index d9ad3b5..39a3f04 100644
--- a/frontend/src/app/routes/settings/general/settings-general.component.html
+++ b/frontend/src/app/routes/settings/general/settings-general.component.html
@@ -1,9 +1,13 @@
Settings
-
-
-
+
diff --git a/frontend/src/app/routes/settings/general/settings-general.component.ts b/frontend/src/app/routes/settings/general/settings-general.component.ts
index 7fb7159..5b400b4 100644
--- a/frontend/src/app/routes/settings/general/settings-general.component.ts
+++ b/frontend/src/app/routes/settings/general/settings-general.component.ts
@@ -1,14 +1,26 @@
import { Component } from '@angular/core';
import { DecodedPref } from 'picsur-shared/dist/dto/preferences.dto';
import { Observable } from 'rxjs';
-import { UsrPreferenceFriendlyNames } from 'src/app/i18n/usr-pref.i18n';
+import {
+ UsrPreferenceFriendlyNames,
+ UsrPreferenceHelpText
+} from 'src/app/i18n/usr-pref.i18n';
import { UsrPrefService } from 'src/app/services/api/usr-pref.service';
@Component({
templateUrl: './settings-general.component.html',
})
export class SettingsGeneralComponent {
- public translator = UsrPreferenceFriendlyNames;
+ private readonly translator = UsrPreferenceFriendlyNames;
+ private readonly helpTranslator = UsrPreferenceHelpText;
+
+ public getName(key: string) {
+ return (this.translator as any)[key] ?? key;
+ }
+
+ public getHelpText(key: string) {
+ return (this.helpTranslator as any)[key] ?? '';
+ }
preferences: Observable;
diff --git a/frontend/src/app/routes/settings/sys-pref/settings-sys-pref.component.html b/frontend/src/app/routes/settings/sys-pref/settings-sys-pref.component.html
index ce4bf15..414808e 100644
--- a/frontend/src/app/routes/settings/sys-pref/settings-sys-pref.component.html
+++ b/frontend/src/app/routes/settings/sys-pref/settings-sys-pref.component.html
@@ -1,9 +1,16 @@
System Settings
-
-
+
+ {{ category.category }}
+
diff --git a/frontend/src/app/routes/settings/sys-pref/settings-sys-pref.component.scss b/frontend/src/app/routes/settings/sys-pref/settings-sys-pref.component.scss
new file mode 100644
index 0000000..e69de29
diff --git a/frontend/src/app/routes/settings/sys-pref/settings-sys-pref.component.ts b/frontend/src/app/routes/settings/sys-pref/settings-sys-pref.component.ts
index d2e336e..a22f745 100644
--- a/frontend/src/app/routes/settings/sys-pref/settings-sys-pref.component.ts
+++ b/frontend/src/app/routes/settings/sys-pref/settings-sys-pref.component.ts
@@ -1,18 +1,42 @@
import { Component } from '@angular/core';
import { DecodedPref } from 'picsur-shared/dist/dto/preferences.dto';
-import { Observable } from 'rxjs';
-import { SysPreferenceFriendlyNames } from 'src/app/i18n/sys-pref.i18n';
+import { SysPreference } from 'picsur-shared/dist/dto/sys-preferences.enum';
+import { map, Observable } from 'rxjs';
+import { SysPreferenceUI } from 'src/app/i18n/sys-pref.i18n';
+
+import { makeUnique } from 'picsur-shared/dist/util/unique';
import { SysPrefService } from 'src/app/services/api/sys-pref.service';
@Component({
templateUrl: './settings-sys-pref.component.html',
+ styleUrls: ['./settings-sys-pref.component.scss'],
})
export class SettingsSysprefComponent {
- public readonly translator = SysPreferenceFriendlyNames;
+ private readonly syspreferenceUI = SysPreferenceUI;
- preferences: Observable;
+ public getName(key: string) {
+ return this.syspreferenceUI[key as SysPreference]?.name ?? key;
+ }
+
+ public getHelpText(key: string) {
+ return this.syspreferenceUI[key as SysPreference]?.helpText ?? '';
+ }
+
+ public getCategory(key: string): null | string {
+ return this.syspreferenceUI[key as SysPreference]?.category ?? null;
+ }
+
+ preferences: Observable>;
constructor(public readonly sysPrefService: SysPrefService) {
- this.preferences = sysPrefService.live;
+ this.preferences = sysPrefService.live.pipe(
+ map((prefs) => {
+ const categories = makeUnique(prefs.map((pref) => this.getCategory(pref.key)));
+ return categories.map((category) => ({
+ category,
+ prefs: prefs.filter((pref) => this.getCategory(pref.key) === category),
+ }));
+ }),
+ )
}
}
diff --git a/frontend/src/app/routes/settings/sys-pref/settings-sys-pref.module.ts b/frontend/src/app/routes/settings/sys-pref/settings-sys-pref.module.ts
index 0008e83..835570d 100644
--- a/frontend/src/app/routes/settings/sys-pref/settings-sys-pref.module.ts
+++ b/frontend/src/app/routes/settings/sys-pref/settings-sys-pref.module.ts
@@ -6,6 +6,10 @@ import { SettingsSysprefRoutingModule } from './settings-sys-pref.routing.module
@NgModule({
declarations: [SettingsSysprefComponent],
- imports: [CommonModule, SettingsSysprefRoutingModule, PrefOptionModule],
+ imports: [
+ CommonModule,
+ SettingsSysprefRoutingModule,
+ PrefOptionModule,
+ ],
})
export default class SettingsSysprefRouteModule {}
diff --git a/frontend/src/app/services/usage/usage.service.ts b/frontend/src/app/services/usage/usage.service.ts
index 64fe1c3..525c7cc 100644
--- a/frontend/src/app/services/usage/usage.service.ts
+++ b/frontend/src/app/services/usage/usage.service.ts
@@ -1,10 +1,10 @@
import { Inject, Injectable } from '@angular/core';
-import { LOCATION, NAVIGATOR, WINDOW } from '@ng-web-apis/common';
-import { Logger } from '../logger/logger.service';
-import { InfoService } from '../api/info.service';
+import { NAVIGATOR } from '@ng-web-apis/common';
import type { AckeeInstance, AckeeTrackingReturn } from 'ackee-tracker';
import { AutoUnsubscribe } from 'ngx-auto-unsubscribe-decorator';
import { TrackingState } from 'picsur-shared/dist/dto/tracking-state.enum';
+import { InfoService } from '../api/info.service';
+import { Logger } from '../logger/logger.service';
@Injectable({
providedIn: 'root',
@@ -24,6 +24,11 @@ export class UsageService {
this.doNotTrack =
this.navigator.doNotTrack === '1' || this.navigator.doNotTrack === 'yes';
+ if (this.doNotTrack) {
+ this.logger.verbose('Usage reporting disabled by DNT');
+ return;
+ }
+
this.subscribeInfo();
}
@@ -37,8 +42,7 @@ export class UsageService {
this.stop();
} else {
this.setup(
- info.tracking.state === TrackingState.Detailed &&
- this.doNotTrack === false,
+ info.tracking.state === TrackingState.Detailed,
info.tracking.id,
);
}