mirror of
https://github.com/KevinMidboe/immich.git
synced 2026-01-15 05:36:08 +00:00
feat(server,web): server config (#4006)
* feat: server config * chore: open api * fix: redirect /map to /photos when disabled
This commit is contained in:
@@ -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: '© <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: '© <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}
|
||||
|
||||
@@ -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');
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user