1
0
Fork 0
mirror of https://github.com/seanmorley15/AdventureLog.git synced 2025-07-22 22:39:36 +02:00

Shared with collaborative editing

This commit is contained in:
Sean Morley 2024-09-09 13:31:00 -04:00
parent f150423c1e
commit ba89f90e53
10 changed files with 38 additions and 28 deletions

View file

@ -4,6 +4,8 @@
**Documentation can be found [here](https://docs.adventurelog.app).** **Documentation can be found [here](https://docs.adventurelog.app).**
**Join the AdventureLog Community Discord Server [here](https://discord.gg/wRbQ9Egr8C).**
# Table of Contents # Table of Contents
- [Installation](#installation) - [Installation](#installation)

View file

@ -1,7 +1,7 @@
<script lang="ts"> <script lang="ts">
import { createEventDispatcher } from 'svelte'; import { createEventDispatcher } from 'svelte';
import { goto } from '$app/navigation'; import { goto } from '$app/navigation';
import type { Adventure, User } from '$lib/types'; import type { Adventure, Collection, User } from '$lib/types';
const dispatch = createEventDispatcher(); const dispatch = createEventDispatcher();
import Launch from '~icons/mdi/launch'; import Launch from '~icons/mdi/launch';
@ -21,8 +21,8 @@
import ImageDisplayModal from './ImageDisplayModal.svelte'; import ImageDisplayModal from './ImageDisplayModal.svelte';
export let type: string; export let type: string;
export let user: User | null; export let user: User | null;
export let collection: Collection | null = null;
let isCollectionModalOpen: boolean = false; let isCollectionModalOpen: boolean = false;
let isWarningModalOpen: boolean = false; let isWarningModalOpen: boolean = false;
@ -209,13 +209,11 @@
</button> </button>
</div> </div>
<div> <div>
{#if adventure.type == 'visited' && user?.pk == adventure.user_id} {#if adventure.type == 'visited'}
<div class="badge badge-primary">Visited</div> <div class="badge badge-primary">Visited</div>
{:else if user?.pk == adventure.user_id && adventure.type == 'planned'} {:else if adventure.type == 'planned'}
<div class="badge badge-secondary">Planned</div> <div class="badge badge-secondary">Planned</div>
{:else if (user?.pk !== adventure.user_id && adventure.type == 'planned') || adventure.type == 'visited'} {:else if adventure.type == 'lodging'}
<div class="badge badge-secondary">Adventure</div>
{:else if user?.pk == adventure.user_id && adventure.type == 'lodging'}
<div class="badge badge-success">Lodging</div> <div class="badge badge-success">Lodging</div>
{:else if adventure.type == 'dining'} {:else if adventure.type == 'dining'}
<div class="badge badge-accent">Dining</div> <div class="badge badge-accent">Dining</div>
@ -254,7 +252,7 @@
<div class="card-actions justify-end mt-2"> <div class="card-actions justify-end mt-2">
<!-- action options dropdown --> <!-- action options dropdown -->
{#if type != 'link'} {#if type != 'link'}
{#if user?.pk == adventure.user_id} {#if adventure.user_id == user?.pk || (collection && user && collection.shared_with.includes(user.uuid))}
<div class="dropdown dropdown-end"> <div class="dropdown dropdown-end">
<div tabindex="0" role="button" class="btn btn-neutral-200"> <div tabindex="0" role="button" class="btn btn-neutral-200">
<DotsHorizontal class="w-6 h-6" /> <DotsHorizontal class="w-6 h-6" />
@ -272,18 +270,18 @@
<button class="btn btn-neutral mb-2" on:click={editAdventure}> <button class="btn btn-neutral mb-2" on:click={editAdventure}>
<FileDocumentEdit class="w-6 h-6" />Edit {keyword} <FileDocumentEdit class="w-6 h-6" />Edit {keyword}
</button> </button>
{#if adventure.type == 'visited'} {#if adventure.type == 'visited' && user?.pk == adventure.user_id}
<button class="btn btn-neutral mb-2" on:click={changeType('planned')} <button class="btn btn-neutral mb-2" on:click={changeType('planned')}
><FormatListBulletedSquare class="w-6 h-6" />Change to Plan</button ><FormatListBulletedSquare class="w-6 h-6" />Change to Plan</button
> >
{/if} {/if}
{#if adventure.type == 'planned'} {#if adventure.type == 'planned' && user?.pk == adventure.user_id}
<button class="btn btn-neutral mb-2" on:click={changeType('visited')} <button class="btn btn-neutral mb-2" on:click={changeType('visited')}
><CheckBold class="w-6 h-6" />Mark Visited</button ><CheckBold class="w-6 h-6" />Mark Visited</button
> >
{/if} {/if}
<!-- remove from adventure --> <!-- remove from adventure -->
{#if adventure.collection && (adventure.type == 'visited' || adventure.type == 'planned')} {#if adventure.collection && (adventure.type == 'visited' || adventure.type == 'planned') && user?.pk == adventure.user_id}
<button class="btn btn-neutral mb-2" on:click={removeFromCollection} <button class="btn btn-neutral mb-2" on:click={removeFromCollection}
><LinkVariantRemove class="w-6 h-6" />Remove from Collection</button ><LinkVariantRemove class="w-6 h-6" />Remove from Collection</button
> >

View file

@ -1,6 +1,6 @@
<script lang="ts"> <script lang="ts">
import { addToast } from '$lib/toasts'; import { addToast } from '$lib/toasts';
import type { Checklist, User } from '$lib/types'; import type { Checklist, Collection, User } from '$lib/types';
import { createEventDispatcher } from 'svelte'; import { createEventDispatcher } from 'svelte';
const dispatch = createEventDispatcher(); const dispatch = createEventDispatcher();
@ -10,6 +10,7 @@
export let checklist: Checklist; export let checklist: Checklist;
export let user: User | null = null; export let user: User | null = null;
export let collection: Collection | null = null;
function editChecklist() { function editChecklist() {
dispatch('edit', checklist); dispatch('edit', checklist);
@ -51,10 +52,10 @@
<!-- <button class="btn btn-neutral mb-2" on:click={() => goto(`/notes/${note.id}`)} <!-- <button class="btn btn-neutral mb-2" on:click={() => goto(`/notes/${note.id}`)}
><Launch class="w-6 h-6" />Open Details</button ><Launch class="w-6 h-6" />Open Details</button
> --> > -->
<button class="btn btn-neutral mb-2" on:click={editChecklist}> <button class="btn btn-neutral-200 mb-2" on:click={editChecklist}>
<Launch class="w-6 h-6" />Open <Launch class="w-6 h-6" />Open
</button> </button>
{#if checklist.user_id == user?.pk} {#if checklist.user_id == user?.pk || (collection && user && collection.shared_with.includes(user.uuid))}
<button <button
id="delete_adventure" id="delete_adventure"
data-umami-event="Delete Checklist" data-umami-event="Delete Checklist"

View file

@ -33,7 +33,7 @@
{ {
name: newItem, name: newItem,
is_checked: newStatus, is_checked: newStatus,
id: 0, id: '',
user_id: 0, user_id: 0,
checklist: 0, checklist: 0,
created_at: '', created_at: '',
@ -135,7 +135,7 @@
<p class="font-semibold text-md mb-2">Editing checklist {initialName}</p> <p class="font-semibold text-md mb-2">Editing checklist {initialName}</p>
{/if} {/if}
{#if (checklist && user?.pk == checklist?.user_id) || !checklist} {#if (checklist && user?.pk == checklist?.user_id) || (user && collection && collection.shared_with.includes(user.uuid)) || !checklist}
<form on:submit|preventDefault> <form on:submit|preventDefault>
<div class="form-control mb-2"> <div class="form-control mb-2">
<label for="name">Name</label> <label for="name">Name</label>

View file

@ -1,7 +1,7 @@
<script lang="ts"> <script lang="ts">
import { goto } from '$app/navigation'; import { goto } from '$app/navigation';
import { addToast } from '$lib/toasts'; import { addToast } from '$lib/toasts';
import type { Note, User } from '$lib/types'; import type { Collection, Note, User } from '$lib/types';
import { createEventDispatcher } from 'svelte'; import { createEventDispatcher } from 'svelte';
const dispatch = createEventDispatcher(); const dispatch = createEventDispatcher();
@ -11,6 +11,7 @@
export let note: Note; export let note: Note;
export let user: User | null = null; export let user: User | null = null;
export let collection: Collection | null = null;
function editNote() { function editNote() {
dispatch('edit', note); dispatch('edit', note);
@ -52,10 +53,10 @@
<!-- <button class="btn btn-neutral mb-2" on:click={() => goto(`/notes/${note.id}`)} <!-- <button class="btn btn-neutral mb-2" on:click={() => goto(`/notes/${note.id}`)}
><Launch class="w-6 h-6" />Open Details</button ><Launch class="w-6 h-6" />Open Details</button
> --> > -->
<button class="btn btn-neutral mb-2" on:click={editNote}> <button class="btn btn-neutral-200 mb-2" on:click={editNote}>
<Launch class="w-6 h-6" />Open <Launch class="w-6 h-6" />Open
</button> </button>
{#if note.user_id == user?.pk} {#if note.user_id == user?.pk || (collection && user && collection.shared_with.includes(user.uuid))}
<button <button
id="delete_adventure" id="delete_adventure"
data-umami-event="Delete Adventure" data-umami-event="Delete Adventure"

View file

@ -4,6 +4,7 @@
import { createEventDispatcher } from 'svelte'; import { createEventDispatcher } from 'svelte';
const dispatch = createEventDispatcher(); const dispatch = createEventDispatcher();
import { onMount } from 'svelte'; import { onMount } from 'svelte';
import ShareModal from './ShareModal.svelte';
let modal: HTMLDialogElement; let modal: HTMLDialogElement;
export let note: Note | null = null; export let note: Note | null = null;
@ -113,7 +114,7 @@
<p class="font-semibold text-md mb-2">Editing note {initialName}</p> <p class="font-semibold text-md mb-2">Editing note {initialName}</p>
{/if} {/if}
{#if (note && user?.pk == note?.user_id) || !note} {#if (note && user?.pk == note?.user_id) || (collection && user && collection.shared_with.includes(user.uuid)) || !note}
<form on:submit|preventDefault> <form on:submit|preventDefault>
<div class="form-control mb-2"> <div class="form-control mb-2">
<label for="name">Name</label> <label for="name">Name</label>

View file

@ -2,7 +2,7 @@
import { createEventDispatcher } from 'svelte'; import { createEventDispatcher } from 'svelte';
import TrashCanOutline from '~icons/mdi/trash-can-outline'; import TrashCanOutline from '~icons/mdi/trash-can-outline';
import FileDocumentEdit from '~icons/mdi/file-document-edit'; import FileDocumentEdit from '~icons/mdi/file-document-edit';
import type { Transportation, User } from '$lib/types'; import type { Collection, Transportation, User } from '$lib/types';
import { addToast } from '$lib/toasts'; import { addToast } from '$lib/toasts';
import ArrowDownThick from '~icons/mdi/arrow-down-thick'; import ArrowDownThick from '~icons/mdi/arrow-down-thick';
@ -11,6 +11,7 @@
export let transportation: Transportation; export let transportation: Transportation;
export let user: User | null = null; export let user: User | null = null;
export let collection: Collection | null = null;
function editTransportation() { function editTransportation() {
dispatch('edit', transportation); dispatch('edit', transportation);
@ -58,7 +59,7 @@
{/if} {/if}
</div> </div>
{#if user?.pk === transportation.user_id} {#if transportation.user_id == user?.pk || (collection && user && collection.shared_with.includes(user.uuid))}
<div class="card-actions justify-end"> <div class="card-actions justify-end">
<button on:click={deleteTransportation} class="btn btn-secondary" <button on:click={deleteTransportation} class="btn btn-secondary"
><TrashCanOutline class="w-5 h-5 mr-1" /></button ><TrashCanOutline class="w-5 h-5 mr-1" /></button

View file

@ -1,5 +1,5 @@
import inspirationalQuotes from './json/quotes.json'; import inspirationalQuotes from './json/quotes.json';
import type { Adventure, Checklist, Collection, Note, Transportation } from './types'; import type { Adventure, Checklist, Collection, Note, Transportation, User } from './types';
export function getRandomQuote() { export function getRandomQuote() {
const quotes = inspirationalQuotes.quotes; const quotes = inspirationalQuotes.quotes;

View file

@ -96,11 +96,13 @@
{/if} {/if}
{#if adventure} {#if adventure}
{#if data.user && data.user.pk == adventure.user_id}
<div class="fixed bottom-4 right-4 z-[999]"> <div class="fixed bottom-4 right-4 z-[999]">
<button class="btn m-1 size-16 btn-primary" on:click={() => (isEditModalOpen = true)} <button class="btn m-1 size-16 btn-primary" on:click={() => (isEditModalOpen = true)}
><ClipboardList class="w-8 h-8" /></button ><ClipboardList class="w-8 h-8" /></button
> >
</div> </div>
{/if}
<div class="flex flex-col min-h-dvh"> <div class="flex flex-col min-h-dvh">
<main class="flex-1"> <main class="flex-1">
<div class="max-w-5xl mx-auto p-4 md:p-6 lg:p-8"> <div class="max-w-5xl mx-auto p-4 md:p-6 lg:p-8">

View file

@ -404,6 +404,7 @@
type={adventure.type} type={adventure.type}
{adventure} {adventure}
on:typeChange={changeType} on:typeChange={changeType}
{collection}
/> />
{/each} {/each}
</div> </div>
@ -423,6 +424,7 @@
transportationToEdit = event.detail; transportationToEdit = event.detail;
isTransportationEditModalOpen = true; isTransportationEditModalOpen = true;
}} }}
{collection}
/> />
{/each} {/each}
</div> </div>
@ -442,6 +444,7 @@
on:delete={(event) => { on:delete={(event) => {
notes = notes.filter((n) => n.id != event.detail); notes = notes.filter((n) => n.id != event.detail);
}} }}
{collection}
/> />
{/each} {/each}
</div> </div>
@ -461,6 +464,7 @@
checklistToEdit = event.detail; checklistToEdit = event.detail;
isShowingChecklistModal = true; isShowingChecklistModal = true;
}} }}
{collection}
/> />
{/each} {/each}
</div> </div>