feat: implement attachment management with upload, delete, and permission checks; update serializers and models
This commit is contained in:
@@ -76,5 +76,21 @@ export const actions: Actions = {
|
||||
});
|
||||
let data = await res.json();
|
||||
return data;
|
||||
},
|
||||
attachment: async (event) => {
|
||||
let formData = await event.request.formData();
|
||||
let csrfToken = await fetchCSRFToken();
|
||||
let sessionId = event.cookies.get('sessionid');
|
||||
let res = await fetch(`${serverEndpoint}/api/attachments/`, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
Cookie: `csrftoken=${csrfToken}; sessionid=${sessionId}`,
|
||||
'X-CSRFToken': csrfToken,
|
||||
Referer: event.url.origin // Include Referer header
|
||||
},
|
||||
body: formData
|
||||
});
|
||||
let data = await res.json();
|
||||
return data;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -12,6 +12,12 @@
|
||||
return marked(markdown);
|
||||
};
|
||||
|
||||
function deleteAttachment(event: CustomEvent<string>) {
|
||||
adventure.attachments = adventure.attachments.filter(
|
||||
(attachment) => attachment.id !== event.detail
|
||||
);
|
||||
}
|
||||
|
||||
export let data: PageData;
|
||||
console.log(data);
|
||||
|
||||
@@ -30,6 +36,7 @@
|
||||
import ClipboardList from '~icons/mdi/clipboard-list';
|
||||
import AdventureModal from '$lib/components/AdventureModal.svelte';
|
||||
import ImageDisplayModal from '$lib/components/ImageDisplayModal.svelte';
|
||||
import AttachmentCard from '$lib/components/AttachmentCard.svelte';
|
||||
|
||||
onMount(() => {
|
||||
if (data.props.adventure) {
|
||||
@@ -380,6 +387,52 @@
|
||||
</MapLibre>
|
||||
{/if}
|
||||
</div>
|
||||
{#if adventure.attachments && adventure.attachments.length > 0}
|
||||
<div>
|
||||
<!-- attachments -->
|
||||
<h2 class="text-2xl font-bold mt-4">{$t('adventures.attachments')}</h2>
|
||||
<div class="grid gap-4 mt-4">
|
||||
{#if adventure.attachments && adventure.attachments.length > 0}
|
||||
<div class="grid gap-4 sm:grid-cols-2 lg:grid-cols-3">
|
||||
{#each adventure.attachments as attachment}
|
||||
<AttachmentCard {attachment} on:delete={deleteAttachment} />
|
||||
{/each}
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
</div>
|
||||
{/if}
|
||||
{#if adventure.images && adventure.images.length > 0}
|
||||
<div>
|
||||
<h2 class="text-2xl font-bold mt-4">{$t('adventures.images')}</h2>
|
||||
<div class="grid gap-4 mt-4">
|
||||
{#if adventure.images && adventure.images.length > 0}
|
||||
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4">
|
||||
{#each adventure.images as image}
|
||||
<div class="relative">
|
||||
<!-- svelte-ignore a11y-no-static-element-interactions -->
|
||||
<!-- svelte-ignore a11y-missing-attribute -->
|
||||
<!-- svelte-ignore a11y-missing-content -->
|
||||
<!-- svelte-ignore a11y-click-events-have-key-events -->
|
||||
<div
|
||||
class="w-full h-48 bg-cover bg-center rounded-lg"
|
||||
style="background-image: url({image.image})"
|
||||
on:click={() => (image_url = image.image)}
|
||||
></div>
|
||||
{#if image.is_primary}
|
||||
<div
|
||||
class="absolute top-0 right-0 bg-primary text-white px-2 py-1 rounded-bl-lg"
|
||||
>
|
||||
{$t('adventures.primary')}
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
{/each}
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
x: -50, // Smaller movement for quicker animation
|
||||
duration: 0.6, // Quicker animation duration
|
||||
stagger: 0.1, // Faster staggering
|
||||
ease: 'power2.out'
|
||||
ease: 'power2.out' // Slightly sharper easing for quicker feel
|
||||
});
|
||||
|
||||
// Stat values with faster reveal and snappier effect
|
||||
@@ -30,8 +30,8 @@
|
||||
scale: 0.8, // Slightly less scaling for a snappier effect
|
||||
duration: 1, // Shorter duration
|
||||
stagger: 0.2, // Faster staggering
|
||||
ease: 'power2.out', // Snappier easing
|
||||
delay: 0.3 // Faster delay for quicker sequencing
|
||||
ease: 'elastic.out(0.75, 0.5)', // Slightly snappier bounce
|
||||
delay: 0 // Faster delay for quicker sequencing
|
||||
});
|
||||
|
||||
// Adventure card animations with quicker reveal
|
||||
@@ -41,7 +41,7 @@
|
||||
duration: 0.8, // Quicker duration
|
||||
stagger: 0.1, // Faster staggering
|
||||
ease: 'power2.out',
|
||||
delay: 0.6 // Shorter delay for quicker appearance
|
||||
delay: 0 // Shorter delay for quicker appearance
|
||||
});
|
||||
|
||||
// Inspiration section with faster bounce effect
|
||||
@@ -50,7 +50,7 @@
|
||||
scale: 0.7, // Less scale for snappier effect
|
||||
duration: 1, // Slightly quicker duration
|
||||
ease: 'elastic.out(0.75, 0.5)', // Snappier bounce
|
||||
delay: 1 // Reduced delay for quicker animation
|
||||
delay: 0 // Reduced delay for quicker animation
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
Reference in New Issue
Block a user