0.3.05
This commit is contained in:
@@ -757,15 +757,16 @@ export interface GoroutineReport {
|
||||
|
||||
/* ---------- gateway settings ---------- */
|
||||
|
||||
/** GatewaySettings is the operator's overrides. Every field is optional in meaning: an
|
||||
* empty string or a zero means "whatever the container was started with", and -1 means
|
||||
* off for the three that can be switched off. */
|
||||
/** GatewaySettings is the operator's server document. Environment-backed fields use an
|
||||
* empty string or zero for "whatever the container was started with"; notification
|
||||
* display is native to this document and defaults to home only. */
|
||||
export interface GatewaySettings {
|
||||
timezone: string;
|
||||
logLevel: string;
|
||||
sessionIdleDays: number;
|
||||
sonarrAlertMinutes: number;
|
||||
radarrAlertMinutes: number;
|
||||
notificationDisplay: string;
|
||||
embyHealthSeconds: number;
|
||||
slowRequestMillis: number;
|
||||
librarySyncMinutes: number;
|
||||
@@ -781,6 +782,7 @@ export interface GatewaySettingValues {
|
||||
sessionIdleDays: number;
|
||||
sonarrAlertMinutes: number;
|
||||
radarrAlertMinutes: number;
|
||||
notificationDisplay: string;
|
||||
embyHealthSeconds: number;
|
||||
slowRequestMillis: number;
|
||||
librarySyncMinutes: number;
|
||||
@@ -791,6 +793,7 @@ export interface GatewaySettingsResponse {
|
||||
deployed: GatewaySettingValues;
|
||||
effective: GatewaySettingValues;
|
||||
logLevels: string[] | null;
|
||||
notificationDisplays: string[] | null;
|
||||
version: string;
|
||||
}
|
||||
|
||||
|
||||
@@ -13,10 +13,9 @@ import { Banner, Button, Card, Field, KeyValue, Loading, Note, PageHead, Tag } f
|
||||
* has not been switched on. That is why it is reached from the account menu rather than
|
||||
* from the rail: it belongs beside "signed in as", not beside the household's content.
|
||||
*
|
||||
* The whole page is an amendment to `.env`. Every field is blank by default and blank
|
||||
* means "whatever this container was started with", which is printed beside it — so an
|
||||
* operator can always see what they are overriding, and clearing a field is a real undo
|
||||
* rather than a value they have to remember. */
|
||||
* Most fields amend `.env`: blank means "whatever this container was started with", which
|
||||
* is printed beside the field. Notification display is server-native instead and has a
|
||||
* Home-only default. */
|
||||
|
||||
/** OVERRIDE_OFF is the wire value for "switched off", which the three window settings need
|
||||
* to distinguish from an empty field. See store.GatewaySettingsOff. */
|
||||
@@ -46,12 +45,21 @@ function describe(value: number, unit: string): string {
|
||||
return `${value} ${unit}${value === 1 ? '' : 's'}`;
|
||||
}
|
||||
|
||||
function notificationDisplayLabel(value: string): string {
|
||||
switch (value) {
|
||||
case 'everywhere': return 'Everywhere';
|
||||
case 'off': return 'Off';
|
||||
default: return 'Home only';
|
||||
}
|
||||
}
|
||||
|
||||
interface Draft {
|
||||
timezone: string;
|
||||
logLevel: string;
|
||||
sessionIdleDays: string;
|
||||
sonarrAlertMinutes: string;
|
||||
radarrAlertMinutes: string;
|
||||
notificationDisplay: string;
|
||||
embyHealthSeconds: string;
|
||||
slowRequestMillis: string;
|
||||
librarySyncMinutes: string;
|
||||
@@ -64,6 +72,7 @@ function draftFrom(settings: GatewaySettings): Draft {
|
||||
sessionIdleDays: numberFieldValue(settings.sessionIdleDays),
|
||||
sonarrAlertMinutes: numberFieldValue(settings.sonarrAlertMinutes),
|
||||
radarrAlertMinutes: numberFieldValue(settings.radarrAlertMinutes),
|
||||
notificationDisplay: settings.notificationDisplay || 'home_only',
|
||||
embyHealthSeconds: numberFieldValue(settings.embyHealthSeconds),
|
||||
slowRequestMillis: numberFieldValue(settings.slowRequestMillis),
|
||||
librarySyncMinutes: numberFieldValue(settings.librarySyncMinutes),
|
||||
@@ -95,6 +104,7 @@ export function SettingsPage() {
|
||||
sessionIdleDays: parseNumberField(draft.sessionIdleDays, false),
|
||||
sonarrAlertMinutes: parseNumberField(draft.sonarrAlertMinutes, true),
|
||||
radarrAlertMinutes: parseNumberField(draft.radarrAlertMinutes, true),
|
||||
notificationDisplay: draft.notificationDisplay,
|
||||
embyHealthSeconds: parseNumberField(draft.embyHealthSeconds, true),
|
||||
slowRequestMillis: parseNumberField(draft.slowRequestMillis, true),
|
||||
librarySyncMinutes: parseNumberField(draft.librarySyncMinutes, true),
|
||||
@@ -117,9 +127,9 @@ export function SettingsPage() {
|
||||
() => api.post<GatewaySettingsResponse>('/admin/api/gateway-settings', {
|
||||
timezone: '', logLevel: '', sessionIdleDays: 0,
|
||||
sonarrAlertMinutes: 0, radarrAlertMinutes: 0, embyHealthSeconds: 0, slowRequestMillis: 0,
|
||||
librarySyncMinutes: 0,
|
||||
librarySyncMinutes: 0, notificationDisplay: 'home_only',
|
||||
}),
|
||||
'Every setting is back to what this container was deployed with.',
|
||||
'Every setting is back to its deployed or server default.',
|
||||
);
|
||||
if (saved) setDraft(draftFrom(saved.settings));
|
||||
await reload();
|
||||
@@ -128,6 +138,7 @@ export function SettingsPage() {
|
||||
const deployed = data?.deployed;
|
||||
const effective = data?.effective;
|
||||
const levels = data?.logLevels ?? [];
|
||||
const notificationDisplays = data?.notificationDisplays ?? ['everywhere', 'home_only', 'off'];
|
||||
|
||||
return (
|
||||
<>
|
||||
@@ -158,13 +169,14 @@ export function SettingsPage() {
|
||||
{ label: 'Catalogue sweep', value: describe(effective.librarySyncMinutes, 'minute') },
|
||||
{ label: 'Episode alert window', value: describe(effective.sonarrAlertMinutes, 'minute') },
|
||||
{ label: 'Film alert window', value: describe(effective.radarrAlertMinutes, 'minute') },
|
||||
{ label: 'Notification display', value: notificationDisplayLabel(effective.notificationDisplay) },
|
||||
]}
|
||||
/>
|
||||
</Card>
|
||||
|
||||
<Card
|
||||
title="Overrides"
|
||||
intro="Leave a field empty to use the value this container was deployed with, shown beneath it. Changes take effect immediately — nothing here needs a restart."
|
||||
title="Server settings"
|
||||
intro="Environment-backed fields can be left empty to use the deployed value shown beneath them. Changes take effect immediately — nothing here needs a restart."
|
||||
icon="sliders"
|
||||
tone="note"
|
||||
footer={
|
||||
@@ -173,7 +185,7 @@ export function SettingsPage() {
|
||||
Save settings
|
||||
</Button>
|
||||
<Button busy={busy === 'clear'} onClick={() => void clearAll()}>
|
||||
Use deployed values
|
||||
Use defaults
|
||||
</Button>
|
||||
</>
|
||||
}
|
||||
@@ -262,6 +274,22 @@ export function SettingsPage() {
|
||||
</Field>
|
||||
</div>
|
||||
|
||||
<div className="fields">
|
||||
<Field
|
||||
label="Notification display"
|
||||
hint="Controls informational banners for every viewer and television. Everywhere also permits playback overlays; Home only keeps them off active movies, episodes and trailers; Off hides them throughout Memby."
|
||||
>
|
||||
<select
|
||||
value={draft.notificationDisplay}
|
||||
onChange={(event) => set('notificationDisplay', event.target.value)}
|
||||
>
|
||||
{notificationDisplays.map((value) => (
|
||||
<option key={value} value={value}>{notificationDisplayLabel(value)}</option>
|
||||
))}
|
||||
</select>
|
||||
</Field>
|
||||
</div>
|
||||
|
||||
<div className="fields">
|
||||
<Field
|
||||
label="Episode alert window (minutes)"
|
||||
@@ -291,10 +319,9 @@ export function SettingsPage() {
|
||||
</div>
|
||||
|
||||
<Note tone="note">
|
||||
These override the deployed configuration in the database, so they survive a
|
||||
restart — but a deployment rewrites <code>.env</code>, not this, and the two can
|
||||
then disagree. Anything meant to be permanent belongs in <code>.env.example</code>{' '}
|
||||
as well.
|
||||
These settings live in the database and survive a restart. A deployment rewrites
|
||||
<code>.env</code>, not this document, so environment-backed values can then disagree;
|
||||
permanent environment changes belong in <code>.env.example</code> as well.
|
||||
</Note>
|
||||
{data?.settings.updatedBy ? (
|
||||
<Note>
|
||||
|
||||
Reference in New Issue
Block a user