feat: add provider type selector to tracking-configs, use IconGridSelect everywhere
- Tracking Configs: add provider type field (was missing entirely) - All 4 config pages: provider type uses IconGridSelect during creation, shown as read-only text during editing (provider type is immutable) - Pages: tracking-configs, command-configs, template-configs, command-template-configs
This commit is contained in:
@@ -12,6 +12,11 @@
|
|||||||
import ConfirmModal from '$lib/components/ConfirmModal.svelte';
|
import ConfirmModal from '$lib/components/ConfirmModal.svelte';
|
||||||
import IconButton from '$lib/components/IconButton.svelte';
|
import IconButton from '$lib/components/IconButton.svelte';
|
||||||
import CrossLink from '$lib/components/CrossLink.svelte';
|
import CrossLink from '$lib/components/CrossLink.svelte';
|
||||||
|
import IconGridSelect from '$lib/components/IconGridSelect.svelte';
|
||||||
|
|
||||||
|
const providerTypeItems = [
|
||||||
|
{ value: 'immich', icon: 'mdiCamera', label: 'Immich' },
|
||||||
|
];
|
||||||
import EntitySelect from '$lib/components/EntitySelect.svelte';
|
import EntitySelect from '$lib/components/EntitySelect.svelte';
|
||||||
import { snackSuccess, snackError } from '$lib/stores/snackbar.svelte';
|
import { snackSuccess, snackError } from '$lib/stores/snackbar.svelte';
|
||||||
import { highlightFromUrl } from '$lib/highlight';
|
import { highlightFromUrl } from '$lib/highlight';
|
||||||
@@ -162,11 +167,12 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
<label for="cfg-provider-type" class="block text-sm font-medium mb-1">{t('commandConfig.providerType')}</label>
|
<label class="block text-sm font-medium mb-1">{t('commandConfig.providerType')}</label>
|
||||||
<select id="cfg-provider-type" bind:value={form.provider_type}
|
{#if !editing}
|
||||||
class="w-full px-3 py-2 border border-[var(--color-border)] rounded-md text-sm bg-[var(--color-background)]">
|
<IconGridSelect items={providerTypeItems} bind:value={form.provider_type} columns={2} />
|
||||||
<option value="immich">Immich</option>
|
{:else}
|
||||||
</select>
|
<p class="text-sm text-[var(--color-muted-foreground)]">{form.provider_type}</p>
|
||||||
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Enabled commands -->
|
<!-- Enabled commands -->
|
||||||
|
|||||||
@@ -12,6 +12,7 @@
|
|||||||
import EmptyState from '$lib/components/EmptyState.svelte';
|
import EmptyState from '$lib/components/EmptyState.svelte';
|
||||||
import ConfirmModal from '$lib/components/ConfirmModal.svelte';
|
import ConfirmModal from '$lib/components/ConfirmModal.svelte';
|
||||||
import IconButton from '$lib/components/IconButton.svelte';
|
import IconButton from '$lib/components/IconButton.svelte';
|
||||||
|
import IconGridSelect from '$lib/components/IconGridSelect.svelte';
|
||||||
import Modal from '$lib/components/Modal.svelte';
|
import Modal from '$lib/components/Modal.svelte';
|
||||||
import JinjaEditor from '$lib/components/JinjaEditor.svelte';
|
import JinjaEditor from '$lib/components/JinjaEditor.svelte';
|
||||||
import { snackSuccess, snackError } from '$lib/stores/snackbar.svelte';
|
import { snackSuccess, snackError } from '$lib/stores/snackbar.svelte';
|
||||||
@@ -50,6 +51,9 @@
|
|||||||
// Provider capabilities
|
// Provider capabilities
|
||||||
let allCapabilities = $state<Record<string, any>>({});
|
let allCapabilities = $state<Record<string, any>>({});
|
||||||
let providerTypes = $derived(Object.keys(allCapabilities));
|
let providerTypes = $derived(Object.keys(allCapabilities));
|
||||||
|
const providerTypeItems = $derived(providerTypes.map(pt => ({
|
||||||
|
value: pt, icon: 'mdiCamera', label: allCapabilities[pt]?.display_name || pt,
|
||||||
|
})));
|
||||||
let commandSlots = $derived<SlotDef[]>(
|
let commandSlots = $derived<SlotDef[]>(
|
||||||
allCapabilities[form.provider_type]?.command_slots || []
|
allCapabilities[form.provider_type]?.command_slots || []
|
||||||
);
|
);
|
||||||
@@ -231,13 +235,8 @@
|
|||||||
|
|
||||||
{#if !editing}
|
{#if !editing}
|
||||||
<div>
|
<div>
|
||||||
<label for="ct-provider" class="block text-sm font-medium mb-1">{t('templateConfig.providerType')}</label>
|
<label class="block text-sm font-medium mb-1">{t('templateConfig.providerType')}</label>
|
||||||
<select id="ct-provider" bind:value={form.provider_type}
|
<IconGridSelect items={providerTypeItems} bind:value={form.provider_type} columns={2} />
|
||||||
class="w-full px-3 py-2 border border-[var(--color-border)] rounded-md text-sm bg-[var(--color-background)]">
|
|
||||||
{#each providerTypes as pt}
|
|
||||||
<option value={pt}>{allCapabilities[pt]?.display_name || pt} ({pt})</option>
|
|
||||||
{/each}
|
|
||||||
</select>
|
|
||||||
</div>
|
</div>
|
||||||
{:else}
|
{:else}
|
||||||
<div>
|
<div>
|
||||||
|
|||||||
@@ -13,6 +13,7 @@
|
|||||||
import ConfirmModal from '$lib/components/ConfirmModal.svelte';
|
import ConfirmModal from '$lib/components/ConfirmModal.svelte';
|
||||||
import Hint from '$lib/components/Hint.svelte';
|
import Hint from '$lib/components/Hint.svelte';
|
||||||
import IconButton from '$lib/components/IconButton.svelte';
|
import IconButton from '$lib/components/IconButton.svelte';
|
||||||
|
import IconGridSelect from '$lib/components/IconGridSelect.svelte';
|
||||||
import Modal from '$lib/components/Modal.svelte';
|
import Modal from '$lib/components/Modal.svelte';
|
||||||
import JinjaEditor from '$lib/components/JinjaEditor.svelte';
|
import JinjaEditor from '$lib/components/JinjaEditor.svelte';
|
||||||
import { snackSuccess, snackError } from '$lib/stores/snackbar.svelte';
|
import { snackSuccess, snackError } from '$lib/stores/snackbar.svelte';
|
||||||
@@ -110,6 +111,9 @@
|
|||||||
// Provider capabilities: loaded dynamically
|
// Provider capabilities: loaded dynamically
|
||||||
let allCapabilities = $state<Record<string, any>>({});
|
let allCapabilities = $state<Record<string, any>>({});
|
||||||
let providerTypes = $derived(Object.keys(allCapabilities));
|
let providerTypes = $derived(Object.keys(allCapabilities));
|
||||||
|
const providerTypeItems = $derived(providerTypes.map(pt => ({
|
||||||
|
value: pt, icon: 'mdiCamera', label: allCapabilities[pt]?.display_name || pt,
|
||||||
|
})));
|
||||||
|
|
||||||
// Dynamic slot definitions based on selected provider_type
|
// Dynamic slot definitions based on selected provider_type
|
||||||
let notificationSlots = $derived<{name: string, description: string}[]>(
|
let notificationSlots = $derived<{name: string, description: string}[]>(
|
||||||
@@ -244,13 +248,8 @@
|
|||||||
|
|
||||||
{#if !editing}
|
{#if !editing}
|
||||||
<div>
|
<div>
|
||||||
<label for="tpc-provider" class="block text-sm font-medium mb-1">{t('templateConfig.providerType')}</label>
|
<label class="block text-sm font-medium mb-1">{t('templateConfig.providerType')}</label>
|
||||||
<select id="tpc-provider" bind:value={form.provider_type}
|
<IconGridSelect items={providerTypeItems} bind:value={form.provider_type} columns={2} />
|
||||||
class="w-full px-3 py-2 border border-[var(--color-border)] rounded-md text-sm bg-[var(--color-background)]">
|
|
||||||
{#each providerTypes as pt}
|
|
||||||
<option value={pt}>{allCapabilities[pt]?.display_name || pt} ({pt})</option>
|
|
||||||
{/each}
|
|
||||||
</select>
|
|
||||||
</div>
|
</div>
|
||||||
{:else}
|
{:else}
|
||||||
<div>
|
<div>
|
||||||
|
|||||||
@@ -13,6 +13,11 @@
|
|||||||
import ConfirmModal from '$lib/components/ConfirmModal.svelte';
|
import ConfirmModal from '$lib/components/ConfirmModal.svelte';
|
||||||
import Hint from '$lib/components/Hint.svelte';
|
import Hint from '$lib/components/Hint.svelte';
|
||||||
import IconButton from '$lib/components/IconButton.svelte';
|
import IconButton from '$lib/components/IconButton.svelte';
|
||||||
|
import IconGridSelect from '$lib/components/IconGridSelect.svelte';
|
||||||
|
|
||||||
|
const providerTypeItems = [
|
||||||
|
{ value: 'immich', icon: 'mdiCamera', label: 'Immich' },
|
||||||
|
];
|
||||||
import { snackSuccess, snackError } from '$lib/stores/snackbar.svelte';
|
import { snackSuccess, snackError } from '$lib/stores/snackbar.svelte';
|
||||||
import { highlightFromUrl } from '$lib/highlight';
|
import { highlightFromUrl } from '$lib/highlight';
|
||||||
import type { TrackingConfig } from '$lib/types';
|
import type { TrackingConfig } from '$lib/types';
|
||||||
@@ -98,6 +103,15 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<label class="block text-sm font-medium mb-1">{t('trackingConfig.providerType')}</label>
|
||||||
|
{#if !editing}
|
||||||
|
<IconGridSelect items={providerTypeItems} bind:value={form.provider_type} columns={2} />
|
||||||
|
{:else}
|
||||||
|
<p class="text-sm text-[var(--color-muted-foreground)]">{form.provider_type}</p>
|
||||||
|
{/if}
|
||||||
|
</div>
|
||||||
|
|
||||||
<!-- Event tracking -->
|
<!-- Event tracking -->
|
||||||
<fieldset class="border border-[var(--color-border)] rounded-md p-3">
|
<fieldset class="border border-[var(--color-border)] rounded-md p-3">
|
||||||
<legend class="text-sm font-medium px-1">{t('trackingConfig.eventTracking')}</legend>
|
<legend class="text-sm font-medium px-1">{t('trackingConfig.eventTracking')}</legend>
|
||||||
|
|||||||
Reference in New Issue
Block a user