mirror of
https://github.com/immich-app/immich.git
synced 2025-06-01 04:36:19 -04:00
fix(web): Handle duplicate library settings gracefully (#6950)
* don't add duplicate import paths * improve library import paths form * same for exclusion patterns * remove newline
This commit is contained in:
parent
90a7f16817
commit
b67fddf4b8
@ -4,11 +4,22 @@
|
|||||||
import FullScreenModal from '../shared-components/full-screen-modal.svelte';
|
import FullScreenModal from '../shared-components/full-screen-modal.svelte';
|
||||||
import Icon from '$lib/components/elements/icon.svelte';
|
import Icon from '$lib/components/elements/icon.svelte';
|
||||||
import { mdiFolderRemove } from '@mdi/js';
|
import { mdiFolderRemove } from '@mdi/js';
|
||||||
|
import { onMount } from 'svelte';
|
||||||
|
|
||||||
export let exclusionPattern: string;
|
export let exclusionPattern: string;
|
||||||
export let canDelete = false;
|
export let exclusionPatterns: string[] = [];
|
||||||
|
export let isEditing = false;
|
||||||
export let submitText = 'Submit';
|
export let submitText = 'Submit';
|
||||||
|
|
||||||
|
onMount(() => {
|
||||||
|
if (isEditing) {
|
||||||
|
exclusionPatterns = exclusionPatterns.filter((pattern) => pattern !== exclusionPattern);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
$: isDuplicate = exclusionPattern !== null && exclusionPatterns.includes(exclusionPattern);
|
||||||
|
$: canSubmit = exclusionPattern !== '' && exclusionPattern !== null && !exclusionPatterns.includes(exclusionPattern);
|
||||||
|
|
||||||
const dispatch = createEventDispatcher<{
|
const dispatch = createEventDispatcher<{
|
||||||
cancel: void;
|
cancel: void;
|
||||||
submit: { excludePattern: string };
|
submit: { excludePattern: string };
|
||||||
@ -49,11 +60,16 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="mt-8 flex w-full gap-4 px-4">
|
<div class="mt-8 flex w-full gap-4 px-4">
|
||||||
<Button color="gray" fullwidth on:click={() => handleCancel()}>Cancel</Button>
|
<Button color="gray" fullwidth on:click={() => handleCancel()}>Cancel</Button>
|
||||||
{#if canDelete}
|
{#if isEditing}
|
||||||
<Button color="red" fullwidth on:click={() => dispatch('delete')}>Delete</Button>
|
<Button color="red" fullwidth on:click={() => dispatch('delete')}>Delete</Button>
|
||||||
{/if}
|
{/if}
|
||||||
|
|
||||||
<Button type="submit" fullwidth>{submitText}</Button>
|
<Button type="submit" disabled={!canSubmit} fullwidth>{submitText}</Button>
|
||||||
|
</div>
|
||||||
|
<div class="mt-8 flex w-full gap-4 px-4">
|
||||||
|
{#if isDuplicate}
|
||||||
|
<p class="text-red-500 text-sm">This exclusion pattern already exists.</p>
|
||||||
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
|
@ -4,16 +4,27 @@
|
|||||||
import Button from '../elements/buttons/button.svelte';
|
import Button from '../elements/buttons/button.svelte';
|
||||||
import FullScreenModal from '../shared-components/full-screen-modal.svelte';
|
import FullScreenModal from '../shared-components/full-screen-modal.svelte';
|
||||||
import { mdiFolderSync } from '@mdi/js';
|
import { mdiFolderSync } from '@mdi/js';
|
||||||
|
import { onMount } from 'svelte';
|
||||||
|
|
||||||
export let importPath: string;
|
export let importPath: string | null;
|
||||||
|
export let importPaths: string[] = [];
|
||||||
export let title = 'Import path';
|
export let title = 'Import path';
|
||||||
export let cancelText = 'Cancel';
|
export let cancelText = 'Cancel';
|
||||||
export let submitText = 'Save';
|
export let submitText = 'Save';
|
||||||
export let canDelete = false;
|
export let isEditing = false;
|
||||||
|
|
||||||
|
onMount(() => {
|
||||||
|
if (isEditing) {
|
||||||
|
importPaths = importPaths.filter((path) => path !== importPath);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
$: isDuplicate = importPath !== null && importPaths.includes(importPath);
|
||||||
|
$: canSubmit = importPath !== '' && importPath !== null && !importPaths.includes(importPath);
|
||||||
|
|
||||||
const dispatch = createEventDispatcher<{
|
const dispatch = createEventDispatcher<{
|
||||||
cancel: void;
|
cancel: void;
|
||||||
submit: { importPath: string };
|
submit: { importPath: string | null };
|
||||||
delete: void;
|
delete: void;
|
||||||
}>();
|
}>();
|
||||||
const handleCancel = () => dispatch('cancel');
|
const handleCancel = () => dispatch('cancel');
|
||||||
@ -47,11 +58,17 @@
|
|||||||
|
|
||||||
<div class="mt-8 flex w-full gap-4 px-4">
|
<div class="mt-8 flex w-full gap-4 px-4">
|
||||||
<Button color="gray" fullwidth on:click={() => handleCancel()}>{cancelText}</Button>
|
<Button color="gray" fullwidth on:click={() => handleCancel()}>{cancelText}</Button>
|
||||||
{#if canDelete}
|
{#if isEditing}
|
||||||
<Button color="red" fullwidth on:click={() => dispatch('delete')}>Delete</Button>
|
<Button color="red" fullwidth on:click={() => dispatch('delete')}>Delete</Button>
|
||||||
{/if}
|
{/if}
|
||||||
|
|
||||||
<Button type="submit" fullwidth>{submitText}</Button>
|
<Button type="submit" disabled={!canSubmit} fullwidth>{submitText}</Button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="mt-8 flex w-full gap-4 px-4">
|
||||||
|
{#if isDuplicate}
|
||||||
|
<p class="text-red-500 text-sm">This import path already exists.</p>
|
||||||
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
|
@ -13,7 +13,7 @@
|
|||||||
let addImportPath = false;
|
let addImportPath = false;
|
||||||
let editImportPath: number | null = null;
|
let editImportPath: number | null = null;
|
||||||
|
|
||||||
let importPathToAdd: string;
|
let importPathToAdd: string | null = null;
|
||||||
let editedImportPath: string;
|
let editedImportPath: string;
|
||||||
|
|
||||||
let importPaths: string[] = [];
|
let importPaths: string[] = [];
|
||||||
@ -39,7 +39,7 @@
|
|||||||
};
|
};
|
||||||
|
|
||||||
const handleAddImportPath = async () => {
|
const handleAddImportPath = async () => {
|
||||||
if (!addImportPath) {
|
if (!addImportPath || !importPathToAdd) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -48,12 +48,16 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
library.importPaths.push(importPathToAdd);
|
// Check so that import path isn't duplicated
|
||||||
importPaths = library.importPaths;
|
if (!library.importPaths.includes(importPathToAdd)) {
|
||||||
|
library.importPaths.push(importPathToAdd);
|
||||||
|
importPaths = library.importPaths;
|
||||||
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
handleError(error, 'Unable to remove import path');
|
handleError(error, 'Unable to add import path');
|
||||||
} finally {
|
} finally {
|
||||||
addImportPath = false;
|
addImportPath = false;
|
||||||
|
importPathToAdd = null;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -67,8 +71,13 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
library.importPaths[editImportPath] = editedImportPath;
|
// Check so that import path isn't duplicated
|
||||||
importPaths = library.importPaths;
|
|
||||||
|
if (!library.importPaths.includes(editedImportPath)) {
|
||||||
|
// Update import path
|
||||||
|
library.importPaths[editImportPath] = editedImportPath;
|
||||||
|
importPaths = library.importPaths;
|
||||||
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
editImportPath = null;
|
editImportPath = null;
|
||||||
handleError(error, 'Unable to edit import path');
|
handleError(error, 'Unable to edit import path');
|
||||||
@ -103,9 +112,11 @@
|
|||||||
title="Add Import Path"
|
title="Add Import Path"
|
||||||
submitText="Add"
|
submitText="Add"
|
||||||
bind:importPath={importPathToAdd}
|
bind:importPath={importPathToAdd}
|
||||||
|
{importPaths}
|
||||||
on:submit={handleAddImportPath}
|
on:submit={handleAddImportPath}
|
||||||
on:cancel={() => {
|
on:cancel={() => {
|
||||||
addImportPath = false;
|
addImportPath = false;
|
||||||
|
importPathToAdd = null;
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
{/if}
|
{/if}
|
||||||
@ -114,8 +125,9 @@
|
|||||||
<LibraryImportPathForm
|
<LibraryImportPathForm
|
||||||
title="Edit Import Path"
|
title="Edit Import Path"
|
||||||
submitText="Save"
|
submitText="Save"
|
||||||
canDelete={true}
|
isEditing={true}
|
||||||
bind:importPath={editedImportPath}
|
bind:importPath={editedImportPath}
|
||||||
|
{importPaths}
|
||||||
on:submit={handleEditImportPath}
|
on:submit={handleEditImportPath}
|
||||||
on:delete={handleDeleteImportPath}
|
on:delete={handleDeleteImportPath}
|
||||||
on:cancel={() => {
|
on:cancel={() => {
|
||||||
@ -157,7 +169,11 @@
|
|||||||
: 'bg-immich-bg dark:bg-immich-dark-gray/50'
|
: 'bg-immich-bg dark:bg-immich-dark-gray/50'
|
||||||
}`}
|
}`}
|
||||||
>
|
>
|
||||||
<td class="w-4/5 text-ellipsis px-4 text-sm" />
|
<td class="w-4/5 text-ellipsis px-4 text-sm">
|
||||||
|
{#if importPaths.length === 0}
|
||||||
|
No paths added
|
||||||
|
{/if}</td
|
||||||
|
>
|
||||||
<td class="w-1/5 text-ellipsis px-4 text-sm"
|
<td class="w-1/5 text-ellipsis px-4 text-sm"
|
||||||
><Button
|
><Button
|
||||||
type="button"
|
type="button"
|
||||||
|
@ -48,13 +48,16 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
library.exclusionPatterns.push(exclusionPatternToAdd);
|
// Check so that exclusion pattern isn't duplicated
|
||||||
exclusionPatternToAdd = '';
|
if (!library.exclusionPatterns.includes(exclusionPatternToAdd)) {
|
||||||
|
library.exclusionPatterns.push(exclusionPatternToAdd);
|
||||||
exclusionPatterns = library.exclusionPatterns;
|
exclusionPatterns = library.exclusionPatterns;
|
||||||
addExclusionPattern = false;
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
handleError(error, 'Unable to add exclude pattern');
|
handleError(error, 'Unable to add exclusion pattern');
|
||||||
|
} finally {
|
||||||
|
exclusionPatternToAdd = '';
|
||||||
|
addExclusionPattern = false;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -102,6 +105,7 @@
|
|||||||
<LibraryExclusionPatternForm
|
<LibraryExclusionPatternForm
|
||||||
submitText="Add"
|
submitText="Add"
|
||||||
bind:exclusionPattern={exclusionPatternToAdd}
|
bind:exclusionPattern={exclusionPatternToAdd}
|
||||||
|
{exclusionPatterns}
|
||||||
on:submit={handleAddExclusionPattern}
|
on:submit={handleAddExclusionPattern}
|
||||||
on:cancel={() => {
|
on:cancel={() => {
|
||||||
addExclusionPattern = false;
|
addExclusionPattern = false;
|
||||||
@ -112,8 +116,9 @@
|
|||||||
{#if editExclusionPattern != undefined}
|
{#if editExclusionPattern != undefined}
|
||||||
<LibraryExclusionPatternForm
|
<LibraryExclusionPatternForm
|
||||||
submitText="Save"
|
submitText="Save"
|
||||||
canDelete={true}
|
isEditing={true}
|
||||||
bind:exclusionPattern={editedExclusionPattern}
|
bind:exclusionPattern={editedExclusionPattern}
|
||||||
|
{exclusionPatterns}
|
||||||
on:submit={handleEditExclusionPattern}
|
on:submit={handleEditExclusionPattern}
|
||||||
on:delete={handleDeleteExclusionPattern}
|
on:delete={handleDeleteExclusionPattern}
|
||||||
on:cancel={() => {
|
on:cancel={() => {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user