mirror of
https://github.com/seanmorley15/AdventureLog.git
synced 2025-07-25 15:59:38 +02:00
feat: add Immich integration view and API documentation, enhance error handling, and include SVG asset
This commit is contained in:
parent
15fd15ba40
commit
67f6af8ca3
8 changed files with 209 additions and 35 deletions
|
@ -13,7 +13,7 @@
|
|||
import { addToast } from '$lib/toasts';
|
||||
import { deserialize } from '$app/forms';
|
||||
import { t } from 'svelte-i18n';
|
||||
|
||||
import ImmichLogo from '$lib/assets/immich.svg';
|
||||
export let longitude: number | null = null;
|
||||
export let latitude: number | null = null;
|
||||
export let collection: Collection | null = null;
|
||||
|
@ -180,31 +180,74 @@
|
|||
}
|
||||
|
||||
async function fetchImage() {
|
||||
let res = await fetch(url);
|
||||
let data = await res.blob();
|
||||
if (!data) {
|
||||
imageError = $t('adventures.no_image_url');
|
||||
return;
|
||||
}
|
||||
let file = new File([data], 'image.jpg', { type: 'image/jpeg' });
|
||||
let formData = new FormData();
|
||||
formData.append('image', file);
|
||||
formData.append('adventure', adventure.id);
|
||||
let res2 = await fetch(`/adventures?/image`, {
|
||||
method: 'POST',
|
||||
body: formData
|
||||
});
|
||||
let data2 = await res2.json();
|
||||
console.log(data2);
|
||||
if (data2.type === 'success') {
|
||||
images = [...images, data2];
|
||||
adventure.images = images;
|
||||
addToast('success', $t('adventures.image_upload_success'));
|
||||
} else {
|
||||
try {
|
||||
let res = await fetch(url);
|
||||
let data = await res.blob();
|
||||
if (!data) {
|
||||
imageError = $t('adventures.no_image_url');
|
||||
return;
|
||||
}
|
||||
let file = new File([data], 'image.jpg', { type: 'image/jpeg' });
|
||||
let formData = new FormData();
|
||||
formData.append('image', file);
|
||||
formData.append('adventure', adventure.id);
|
||||
|
||||
let res2 = await fetch(`/adventures?/image`, {
|
||||
method: 'POST',
|
||||
body: formData
|
||||
});
|
||||
let data2 = await res2.json();
|
||||
|
||||
if (data2.type === 'success') {
|
||||
console.log('Response Data:', data2);
|
||||
|
||||
// Deserialize the nested data
|
||||
let rawData = JSON.parse(data2.data); // Parse the data field
|
||||
console.log('Deserialized Data:', rawData);
|
||||
|
||||
// Assuming the first object in the array is the new image
|
||||
let newImage = {
|
||||
id: rawData[0].id,
|
||||
image: rawData[2] // This is the URL for the image
|
||||
};
|
||||
console.log('New Image:', newImage);
|
||||
|
||||
// Update images and adventure
|
||||
images = [...images, newImage];
|
||||
adventure.images = images;
|
||||
|
||||
addToast('success', $t('adventures.image_upload_success'));
|
||||
} else {
|
||||
addToast('error', $t('adventures.image_upload_error'));
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Error in fetchImage:', error);
|
||||
addToast('error', $t('adventures.image_upload_error'));
|
||||
}
|
||||
}
|
||||
|
||||
let immichSearchValue: string = '';
|
||||
let immichError: string = '';
|
||||
|
||||
async function searchImmich() {
|
||||
let res = await fetch(`/api/integrations/immich/search/?query=${immichSearchValue}`);
|
||||
if (!res.ok) {
|
||||
let data = await res.json();
|
||||
let errorMessage = data.message;
|
||||
console.log(errorMessage);
|
||||
immichError = $t(data.code);
|
||||
} else {
|
||||
let data = await res.json();
|
||||
console.log(data);
|
||||
immichError = '';
|
||||
if (data.results && data.results.length > 0) {
|
||||
immichImages = data.results;
|
||||
} else {
|
||||
immichError = $t('immich.no_items_found');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async function fetchWikiImage() {
|
||||
let res = await fetch(`/api/generate/img/?name=${imageSearch}`);
|
||||
let data = await res.json();
|
||||
|
@ -337,6 +380,9 @@
|
|||
const dispatch = createEventDispatcher();
|
||||
let modal: HTMLDialogElement;
|
||||
|
||||
let immichIntegration: boolean = false;
|
||||
let immichImages: any[] = [];
|
||||
|
||||
onMount(async () => {
|
||||
modal = document.getElementById('my_modal_1') as HTMLDialogElement;
|
||||
modal.showModal();
|
||||
|
@ -347,6 +393,16 @@
|
|||
} else {
|
||||
addToast('error', $t('adventures.category_fetch_error'));
|
||||
}
|
||||
// Check for Immich Integration
|
||||
let res = await fetch('/api/integrations');
|
||||
if (!res.ok) {
|
||||
addToast('error', $t('immich.integration_fetch_error'));
|
||||
} else {
|
||||
let data = await res.json();
|
||||
if (data.immich) {
|
||||
immichIntegration = true;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
function close() {
|
||||
|
@ -915,10 +971,10 @@ it would also work to just use on:click on the MapLibre component itself. -->
|
|||
</form>
|
||||
</div>
|
||||
{:else}
|
||||
<p class="text-lg text-gray-600">{$t('adventures.upload_images_here')}</p>
|
||||
<p class="text-lg">{$t('adventures.upload_images_here')}</p>
|
||||
|
||||
<div class="mb-4">
|
||||
<label for="image" class="block font-medium text-gray-700 mb-2">
|
||||
<label for="image" class="block font-medium mb-2">
|
||||
{$t('adventures.image')}
|
||||
</label>
|
||||
<form
|
||||
|
@ -944,7 +1000,7 @@ it would also work to just use on:click on the MapLibre component itself. -->
|
|||
</div>
|
||||
|
||||
<div class="mb-4">
|
||||
<label for="url" class="block font-medium text-gray-700 mb-2">
|
||||
<label for="url" class="block font-medium mb-2">
|
||||
{$t('adventures.url')}
|
||||
</label>
|
||||
<div class="flex gap-2">
|
||||
|
@ -963,7 +1019,7 @@ it would also work to just use on:click on the MapLibre component itself. -->
|
|||
</div>
|
||||
|
||||
<div class="mb-4">
|
||||
<label for="name" class="block font-medium text-gray-700 mb-2">
|
||||
<label for="name" class="block font-medium mb-2">
|
||||
{$t('adventures.wikipedia')}
|
||||
</label>
|
||||
<div class="flex gap-2">
|
||||
|
@ -981,6 +1037,49 @@ it would also work to just use on:click on the MapLibre component itself. -->
|
|||
</div>
|
||||
</div>
|
||||
|
||||
{#if immichIntegration}
|
||||
<div class="mb-4">
|
||||
<label for="immich" class="block font-medium mb-2">
|
||||
{$t('immich.immich')}
|
||||
<img src={ImmichLogo} alt="Immich Logo" class="h-6 w-6 inline-block -mt-1" />
|
||||
</label>
|
||||
<!-- search bar -->
|
||||
<div>
|
||||
<input
|
||||
type="text"
|
||||
placeholder="Type here"
|
||||
bind:value={immichSearchValue}
|
||||
class="input input-bordered w-full max-w-xs"
|
||||
/>
|
||||
<button on:click={searchImmich} class="btn btn-neutral mt-2">Search</button>
|
||||
</div>
|
||||
<p class="text-red-500">{immichError}</p>
|
||||
<div class="flex flex-wrap gap-4 mr-4 mt-2">
|
||||
{#each immichImages as image}
|
||||
<div class="flex flex-col items-center gap-2">
|
||||
<img
|
||||
src={`/immich/${image.id}`}
|
||||
alt="Image from Immich"
|
||||
class="h-24 w-24 object-cover rounded-md"
|
||||
/>
|
||||
<button
|
||||
type="button"
|
||||
class="btn btn-sm btn-primary"
|
||||
on:click={() => {
|
||||
let currentDomain = window.location.origin;
|
||||
let fullUrl = `${currentDomain}/immich/${image.id}`;
|
||||
url = fullUrl;
|
||||
fetchImage();
|
||||
}}
|
||||
>
|
||||
{$t('adventures.upload_image')}
|
||||
</button>
|
||||
</div>
|
||||
{/each}
|
||||
</div>
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
<div class="divider"></div>
|
||||
|
||||
{#if images.length > 0}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue