feat(server,web): server config (#4006)

* feat: server config

* chore: open api

* fix: redirect /map to /photos when disabled
This commit is contained in:
Jason Rasmussen
2023-09-08 22:51:46 -04:00
committed by GitHub
parent 3edade6761
commit f1db257628
48 changed files with 1103 additions and 162 deletions

View File

@@ -1,16 +1,19 @@
<script lang="ts">
import { goto } from '$app/navigation';
import AssetViewer from '$lib/components/asset-viewer/asset-viewer.svelte';
import UserPageLayout from '$lib/components/layouts/user-page-layout.svelte';
import MapSettingsModal from '$lib/components/map-page/map-settings-modal.svelte';
import Portal from '$lib/components/shared-components/portal/portal.svelte';
import { AppRoute } from '$lib/constants';
import { assetViewingStore } from '$lib/stores/asset-viewing.store';
import { mapSettings } from '$lib/stores/preferences.store';
import { featureFlags, serverConfig } from '$lib/stores/server-config.store';
import { MapMarkerResponseDto, api } from '@api';
import { isEqual, omit } from 'lodash-es';
import { DateTime, Duration } from 'luxon';
import { onDestroy, onMount } from 'svelte';
import Cog from 'svelte-material-icons/Cog.svelte';
import type { PageData } from './$types';
import { DateTime, Duration } from 'luxon';
import { assetViewingStore } from '$lib/stores/asset-viewing.store';
export let data: PageData;
@@ -29,12 +32,12 @@
});
onDestroy(() => {
if (abortController) {
abortController.abort();
}
abortController?.abort();
assetViewingStore.showAssetViewer(false);
});
$: $featureFlags.map || goto(AppRoute.PHOTOS);
async function loadMapMarkers() {
if (abortController) {
abortController.abort();
@@ -98,70 +101,72 @@
}
</script>
<UserPageLayout user={data.user} title={data.meta.title}>
<div class="isolate h-full w-full">
{#if leaflet}
{@const { Map, TileLayer, AssetMarkerCluster, Control } = leaflet}
<Map
center={[30, 0]}
zoom={3}
allowDarkMode={$mapSettings.allowDarkMode}
options={{
maxBounds: [
[-90, -180],
[90, 180],
],
minZoom: 2,
}}
>
<TileLayer
urlTemplate={'https://tile.openstreetmap.org/{z}/{x}/{y}.png'}
{#if $featureFlags.loaded && $featureFlags.map}
<UserPageLayout user={data.user} title={data.meta.title}>
<div class="isolate h-full w-full">
{#if leaflet}
{@const { Map, TileLayer, AssetMarkerCluster, Control } = leaflet}
<Map
center={[30, 0]}
zoom={3}
allowDarkMode={$mapSettings.allowDarkMode}
options={{
attribution: '&copy; <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a>',
maxBounds: [
[-90, -180],
[90, 180],
],
minZoom: 2,
}}
/>
<AssetMarkerCluster
markers={mapMarkers}
on:view={({ detail }) => onViewAssets(detail.assetIds, detail.activeAssetIndex)}
/>
<Control>
<button
class="flex h-8 w-8 items-center justify-center rounded-sm border-2 border-black/20 bg-white font-bold text-black/70 hover:bg-gray-50 focus:bg-gray-50"
title="Open map settings"
on:click={() => (showSettingsModal = true)}
>
<Cog size="100%" class="p-1" />
</button>
</Control>
</Map>
{/if}
</div>
</UserPageLayout>
>
<TileLayer
urlTemplate={$serverConfig.mapTileUrl}
options={{
attribution: '&copy; <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a>',
}}
/>
<AssetMarkerCluster
markers={mapMarkers}
on:view={({ detail }) => onViewAssets(detail.assetIds, detail.activeAssetIndex)}
/>
<Control>
<button
class="flex h-8 w-8 items-center justify-center rounded-sm border-2 border-black/20 bg-white font-bold text-black/70 hover:bg-gray-50 focus:bg-gray-50"
title="Open map settings"
on:click={() => (showSettingsModal = true)}
>
<Cog size="100%" class="p-1" />
</button>
</Control>
</Map>
{/if}
</div>
</UserPageLayout>
<Portal target="body">
{#if $showAssetViewer}
<AssetViewer
asset={$viewingAsset}
showNavigation={viewingAssets.length > 1}
on:next={navigateNext}
on:previous={navigatePrevious}
on:close={() => assetViewingStore.showAssetViewer(false)}
<Portal target="body">
{#if $showAssetViewer}
<AssetViewer
asset={$viewingAsset}
showNavigation={viewingAssets.length > 1}
on:next={navigateNext}
on:previous={navigatePrevious}
on:close={() => assetViewingStore.showAssetViewer(false)}
/>
{/if}
</Portal>
{#if showSettingsModal}
<MapSettingsModal
settings={{ ...$mapSettings }}
on:close={() => (showSettingsModal = false)}
on:save={async ({ detail }) => {
const shouldUpdate = !isEqual(omit(detail, 'allowDarkMode'), omit($mapSettings, 'allowDarkMode'));
showSettingsModal = false;
$mapSettings = detail;
if (shouldUpdate) {
mapMarkers = await loadMapMarkers();
}
}}
/>
{/if}
</Portal>
{#if showSettingsModal}
<MapSettingsModal
settings={{ ...$mapSettings }}
on:close={() => (showSettingsModal = false)}
on:save={async ({ detail }) => {
const shouldUpdate = !isEqual(omit(detail, 'allowDarkMode'), omit($mapSettings, 'allowDarkMode'));
showSettingsModal = false;
$mapSettings = detail;
if (shouldUpdate) {
mapMarkers = await loadMapMarkers();
}
}}
/>
{/if}

View File

@@ -14,7 +14,7 @@
import AppleHeader from '$lib/components/shared-components/apple-header.svelte';
import FaviconHeader from '$lib/components/shared-components/favicon-header.svelte';
import { onMount } from 'svelte';
import { loadFeatureFlags } from '$lib/stores/feature-flags.store';
import { loadConfig } from '$lib/stores/server-config.store';
import { handleError } from '$lib/utils/handle-error';
import { dragAndDropFilesStore } from '$lib/stores/drag-and-drop-files.store';
import { api } from '@api';
@@ -37,9 +37,9 @@
onMount(async () => {
try {
await loadFeatureFlags();
await loadConfig();
} catch (error) {
handleError(error, 'Unable to load feature flags');
handleError(error, 'Unable to connect to server');
}
});

View File

@@ -3,6 +3,7 @@
import FFmpegSettings from '$lib/components/admin-page/settings/ffmpeg/ffmpeg-settings.svelte';
import JobSettings from '$lib/components/admin-page/settings/job-settings/job-settings.svelte';
import MachineLearningSettings from '$lib/components/admin-page/settings/machine-learning-settings/machine-learning-settings.svelte';
import MapSettings from '$lib/components/admin-page/settings/map-settings/map-settings.svelte';
import OAuthSettings from '$lib/components/admin-page/settings/oauth/oauth-settings.svelte';
import PasswordLoginSettings from '$lib/components/admin-page/settings/password-login/password-login-settings.svelte';
import SettingAccordion from '$lib/components/admin-page/settings/setting-accordion.svelte';
@@ -11,7 +12,7 @@
import Button from '$lib/components/elements/buttons/button.svelte';
import LoadingSpinner from '$lib/components/shared-components/loading-spinner.svelte';
import { downloadManager } from '$lib/stores/download';
import { featureFlags } from '$lib/stores/feature-flags.store';
import { featureFlags } from '$lib/stores/server-config.store';
import { downloadBlob } from '$lib/utils/asset-utils';
import { SystemConfigDto, api, copyToClipboard } from '@api';
import Alert from 'svelte-material-icons/Alert.svelte';
@@ -57,20 +58,6 @@
<span class="pl-2">Export as JSON</span>
</Button>
</div>
<SettingAccordion title="Thumbnail Settings" subtitle="Manage the resolution of thumbnail sizes">
<ThumbnailSettings disabled={$featureFlags.configFile} thumbnailConfig={configs.thumbnail} />
</SettingAccordion>
<SettingAccordion
title="Video Transcoding Settings"
subtitle="Manage the resolution and encoding information of the video files"
>
<FFmpegSettings disabled={$featureFlags.configFile} ffmpegConfig={configs.ffmpeg} />
</SettingAccordion>
<SettingAccordion title="Machine Learning Settings" subtitle="Manage model settings">
<MachineLearningSettings disabled={$featureFlags.configFile} machineLearningConfig={configs.machineLearning} />
</SettingAccordion>
<SettingAccordion
title="Job Settings"
@@ -80,14 +67,22 @@
<JobSettings disabled={$featureFlags.configFile} jobConfig={configs.job} />
</SettingAccordion>
<SettingAccordion title="Password Authentication" subtitle="Manage login with password settings">
<PasswordLoginSettings disabled={$featureFlags.configFile} passwordLoginConfig={configs.passwordLogin} />
<SettingAccordion title="Machine Learning Settings" subtitle="Manage model settings">
<MachineLearningSettings disabled={$featureFlags.configFile} machineLearningConfig={configs.machineLearning} />
</SettingAccordion>
<SettingAccordion title="Map Settings" subtitle="Manage map settings">
<MapSettings disabled={$featureFlags.configFile} mapConfig={configs.map} />
</SettingAccordion>
<SettingAccordion title="OAuth Authentication" subtitle="Manage the login with OAuth settings">
<OAuthSettings disabled={$featureFlags.configFile} oauthConfig={configs.oauth} />
</SettingAccordion>
<SettingAccordion title="Password Authentication" subtitle="Manage login with password settings">
<PasswordLoginSettings disabled={$featureFlags.configFile} passwordLoginConfig={configs.passwordLogin} />
</SettingAccordion>
<SettingAccordion
title="Storage Template"
subtitle="Manage the folder structure and file name of the upload asset"
@@ -99,5 +94,16 @@
user={data.user}
/>
</SettingAccordion>
<SettingAccordion title="Thumbnail Settings" subtitle="Manage the resolution of thumbnail sizes">
<ThumbnailSettings disabled={$featureFlags.configFile} thumbnailConfig={configs.thumbnail} />
</SettingAccordion>
<SettingAccordion
title="Video Transcoding Settings"
subtitle="Manage the resolution and encoding information of the video files"
>
<FFmpegSettings disabled={$featureFlags.configFile} ffmpegConfig={configs.ffmpeg} />
</SettingAccordion>
{/await}
</section>

View File

@@ -3,18 +3,17 @@
import LoginForm from '$lib/components/forms/login-form.svelte';
import FullscreenContainer from '$lib/components/shared-components/fullscreen-container.svelte';
import { AppRoute } from '$lib/constants';
import { loginPageMessage } from '$lib/constants';
import { featureFlags } from '$lib/stores/feature-flags.store';
import { featureFlags, serverConfig } from '$lib/stores/server-config.store';
import type { PageData } from './$types';
export let data: PageData;
</script>
{#if $featureFlags.loaded}
<FullscreenContainer title={data.meta.title} showMessage={!!loginPageMessage}>
<FullscreenContainer title={data.meta.title} showMessage={!!$serverConfig.loginPageMessage}>
<p slot="message">
<!-- eslint-disable-next-line svelte/no-at-html-tags -->
{@html loginPageMessage}
{@html $serverConfig.loginPageMessage}
</p>
<LoginForm