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
+
+