From 1858790308bc2f8991976a7e3f2363f4c59f264c Mon Sep 17 00:00:00 2001 From: Sean Morley Date: Wed, 7 Aug 2024 13:01:12 -0400 Subject: [PATCH] Archive Collections --- .../migrations/0021_collection_is_archived.py | 18 +++++++ backend/server/adventures/models.py | 1 + backend/server/adventures/serializers.py | 2 +- backend/server/adventures/views.py | 54 +++++++++---------- .../src/lib/components/CollectionCard.svelte | 45 ++++++++++++++-- frontend/src/lib/types.ts | 1 + frontend/src/routes/collections/+page.svelte | 6 +++ .../collections/archived/+page.server.ts | 35 ++++++++++++ .../routes/collections/archived/+page.svelte | 44 +++++++++++++++ 9 files changed, 173 insertions(+), 33 deletions(-) create mode 100644 backend/server/adventures/migrations/0021_collection_is_archived.py create mode 100644 frontend/src/routes/collections/archived/+page.server.ts create mode 100644 frontend/src/routes/collections/archived/+page.svelte diff --git a/backend/server/adventures/migrations/0021_collection_is_archived.py b/backend/server/adventures/migrations/0021_collection_is_archived.py new file mode 100644 index 0000000..fc1811c --- /dev/null +++ b/backend/server/adventures/migrations/0021_collection_is_archived.py @@ -0,0 +1,18 @@ +# Generated by Django 5.0.7 on 2024-08-07 16:20 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('adventures', '0020_checklist_checklistitem'), + ] + + operations = [ + migrations.AddField( + model_name='collection', + name='is_archived', + field=models.BooleanField(default=False), + ), + ] diff --git a/backend/server/adventures/models.py b/backend/server/adventures/models.py index 7c3c0e5..2167631 100644 --- a/backend/server/adventures/models.py +++ b/backend/server/adventures/models.py @@ -72,6 +72,7 @@ class Collection(models.Model): start_date = models.DateField(blank=True, null=True) end_date = models.DateField(blank=True, null=True) updated_at = models.DateTimeField(auto_now=True) + is_archived = models.BooleanField(default=False) # if connected adventures are private and collection is public, raise an error diff --git a/backend/server/adventures/serializers.py b/backend/server/adventures/serializers.py index a2d59ce..56be627 100644 --- a/backend/server/adventures/serializers.py +++ b/backend/server/adventures/serializers.py @@ -205,5 +205,5 @@ class CollectionSerializer(serializers.ModelSerializer): class Meta: model = Collection # fields are all plus the adventures field - fields = ['id', 'description', 'user_id', 'name', 'is_public', 'adventures', 'created_at', 'start_date', 'end_date', 'transportations', 'notes', 'updated_at', 'checklists'] + fields = ['id', 'description', 'user_id', 'name', 'is_public', 'adventures', 'created_at', 'start_date', 'end_date', 'transportations', 'notes', 'updated_at', 'checklists', 'is_archived'] read_only_fields = ['id', 'created_at', 'updated_at', 'user_id'] diff --git a/backend/server/adventures/views.py b/backend/server/adventures/views.py index 93a5c43..4ba7bf8 100644 --- a/backend/server/adventures/views.py +++ b/backend/server/adventures/views.py @@ -209,9 +209,8 @@ class CollectionViewSet(viewsets.ModelViewSet): permission_classes = [IsOwnerOrReadOnly, IsPublicReadOnly] pagination_class = StandardResultsSetPagination - def get_queryset(self): - print(self.request.user.id) - return Collection.objects.filter(user_id=self.request.user.id) + # def get_queryset(self): + # return Collection.objects.filter(Q(user_id=self.request.user.id) & Q(is_archived=False)) def apply_sorting(self, queryset): order_by = self.request.query_params.get('order_by', 'name') @@ -263,6 +262,20 @@ class CollectionViewSet(viewsets.ModelViewSet): return Response(serializer.data) + @action(detail=False, methods=['get']) + def archived(self, request): + if not request.user.is_authenticated: + return Response({"error": "User is not authenticated"}, status=400) + + queryset = Collection.objects.filter( + Q(user_id=request.user.id) & Q(is_archived=True) + ) + + queryset = self.apply_sorting(queryset) + serializer = self.get_serializer(queryset, many=True) + + return Response(serializer.data) + # this make the is_public field of the collection cascade to the adventures @transaction.atomic def update(self, request, *args, **kwargs): @@ -298,36 +311,21 @@ class CollectionViewSet(viewsets.ModelViewSet): return Response(serializer.data) def get_queryset(self): - - adventures = None + if self.action == 'destroy': + return Collection.objects.filter(user_id=self.request.user.id) + + if self.action in ['update', 'partial_update']: + return Collection.objects.filter(user_id=self.request.user.id) if self.action == 'retrieve': - # For individual collection retrieval, include public collections - adventures = Collection.objects.filter( + return Collection.objects.filter( Q(is_public=True) | Q(user_id=self.request.user.id) ) - else: - # For other actions, only include user's own collections - adventures = Collection.objects.filter(user_id=self.request.user.id) - # adventures = adventures.prefetch_related( - # Prefetch('adventure_set', queryset=Adventure.objects.filter( - # Q(is_public=True) | Q(user_id=self.request.user.id) - # )) - # ).prefetch_related( - # Prefetch('transportation_set', queryset=Transportation.objects.filter( - # Q(is_public=True) | Q(user_id=self.request.user.id) - # )) - # ).prefetch_related( - # Prefetch('note_set', queryset=Note.objects.filter( - # Q(is_public=True) | Q(user_id=self.request.user.id) - # )) - # ).prefetch_related( - # Prefetch('checklist_set', queryset=Checklist.objects.filter( - # Q(is_public=True) | Q(user_id=self.request.user.id) - # )) - # ) - return self.apply_sorting(adventures) + # For other actions (like list), only include user's non-archived collections + return Collection.objects.filter( + Q(user_id=self.request.user.id) & Q(is_archived=False) + ) def perform_create(self, serializer): serializer.save(user_id=self.request.user) diff --git a/frontend/src/lib/components/CollectionCard.svelte b/frontend/src/lib/components/CollectionCard.svelte index eaffcee..18dd58f 100644 --- a/frontend/src/lib/components/CollectionCard.svelte +++ b/frontend/src/lib/components/CollectionCard.svelte @@ -5,12 +5,15 @@ import TrashCanOutline from '~icons/mdi/trash-can-outline'; import FileDocumentEdit from '~icons/mdi/file-document-edit'; + import ArchiveArrowDown from '~icons/mdi/archive-arrow-down'; + import ArchiveArrowUp from '~icons/mdi/archive-arrow-up'; import { goto } from '$app/navigation'; import type { Collection } from '$lib/types'; import { addToast } from '$lib/toasts'; import Plus from '~icons/mdi/plus'; + import { json } from '@sveltejs/kit'; const dispatch = createEventDispatcher(); @@ -22,6 +25,24 @@ dispatch('edit', collection); } + async function archiveCollection(is_archived: boolean) { + console.log(JSON.stringify({ is_archived: is_archived })); + let res = await fetch(`/api/collections/${collection.id}/`, { + method: 'PATCH', + headers: { + 'Content-Type': 'application/json' + }, + body: JSON.stringify({ is_archived: is_archived }) + }); + if (res.ok) { + console.log(`Collection ${is_archived ? 'archived' : 'unarchived'}`); + addToast('info', `Adventure ${is_archived ? 'archived' : 'unarchived'} successfully!`); + dispatch('delete', collection.id); + } else { + console.log('Error archiving adventure'); + } + } + export let collection: Collection; async function deleteCollection() { @@ -61,15 +82,22 @@ ) + 1}{' '} days

{/if} -
{collection.is_public ? 'Public' : 'Private'}
+
+
{collection.is_public ? 'Public' : 'Private'}
+ {#if collection.is_archived} +
Archived
+ {/if} +
{#if type != 'link'} - + {#if !collection.is_archived} + + {/if} @@ -79,6 +107,15 @@ {/if} + {#if collection.is_archived} + + {:else} + + {/if}
diff --git a/frontend/src/lib/types.ts b/frontend/src/lib/types.ts index fcbf5e4..fee9bd9 100644 --- a/frontend/src/lib/types.ts +++ b/frontend/src/lib/types.ts @@ -70,6 +70,7 @@ export type Collection = { transportations?: Transportation[]; notes?: Note[]; checklists?: Checklist[]; + is_archived?: boolean; }; export type OpenStreetMapPlace = { diff --git a/frontend/src/routes/collections/+page.svelte b/frontend/src/routes/collections/+page.svelte index f4b4190..df06848 100644 --- a/frontend/src/routes/collections/+page.svelte +++ b/frontend/src/routes/collections/+page.svelte @@ -1,5 +1,6 @@ + +
+
+ +

Archived Collections

+ {#if collections.length === 0} + + {/if} +
+
+ {#each collections as collection} + + {/each} +
+
+
+
+ + + Collections + +