mirror of
https://github.com/seanmorley15/AdventureLog.git
synced 2026-04-05 06:55:04 -04:00
feat(collection): enhance collection sharing logic and improve data handling on invite acceptance
This commit is contained in:
@@ -93,7 +93,7 @@ class CollectionViewSet(viewsets.ModelViewSet):
|
||||
if self.action == 'destroy':
|
||||
return Collection.objects.filter(user=self.request.user.id)
|
||||
|
||||
if self.action in ['update', 'partial_update']:
|
||||
if self.action in ['update', 'partial_update', 'leave']:
|
||||
return Collection.objects.filter(
|
||||
Q(user=self.request.user.id) | Q(shared_with=self.request.user)
|
||||
).distinct()
|
||||
@@ -115,9 +115,9 @@ class CollectionViewSet(viewsets.ModelViewSet):
|
||||
Q(is_public=True) | Q(user=self.request.user.id) | Q(shared_with=self.request.user)
|
||||
).distinct()
|
||||
|
||||
# For list action, include collections owned by the user or shared with the user, that are not archived
|
||||
# For list action and default base queryset, return collections owned by the user (exclude shared)
|
||||
return Collection.objects.filter(
|
||||
(Q(user=self.request.user.id) | Q(shared_with=self.request.user)) & Q(is_archived=False)
|
||||
Q(user=self.request.user.id) & Q(is_archived=False)
|
||||
).distinct()
|
||||
|
||||
def get_queryset(self):
|
||||
@@ -131,8 +131,10 @@ class CollectionViewSet(viewsets.ModelViewSet):
|
||||
if not request.user.is_authenticated:
|
||||
return Response({"error": "User is not authenticated"}, status=400)
|
||||
|
||||
# List should only return collections owned by the requesting user (shared collections are available
|
||||
# via the `shared` action).
|
||||
queryset = Collection.objects.filter(
|
||||
(Q(user=request.user.id) | Q(shared_with=request.user)) & Q(is_archived=False)
|
||||
Q(user=request.user.id) & Q(is_archived=False)
|
||||
).distinct().select_related('user').prefetch_related(
|
||||
Prefetch(
|
||||
'locations__images',
|
||||
|
||||
@@ -210,11 +210,37 @@
|
||||
});
|
||||
|
||||
if (res.ok) {
|
||||
// Try to parse returned collection data
|
||||
let data: any = null;
|
||||
try {
|
||||
data = await res.json();
|
||||
} catch (e) {
|
||||
data = null;
|
||||
}
|
||||
|
||||
// Remove invite from list
|
||||
invites = invites.filter((i) => i.id !== invite.id);
|
||||
addToast('success', `${$t('invites.accepted')} "${invite.name}"`);
|
||||
// Optionally refresh shared collections
|
||||
await goto(window.location.pathname, { invalidateAll: true });
|
||||
|
||||
// If API returned the accepted collection, add it to sharedCollections immediately
|
||||
if (data && (data.collection || data.result || data.id)) {
|
||||
// Normalize expected shapes: {collection: {...}} or collection object directly
|
||||
const newCollection = data.collection ? data.collection : data;
|
||||
// Prepend so it's visible at top
|
||||
sharedCollections = [newCollection as SlimCollection, ...sharedCollections];
|
||||
} else {
|
||||
// Fallback: refresh shared collections from API
|
||||
try {
|
||||
const sharedRes = await fetch(`/api/collections/shared/?nested=true`);
|
||||
if (sharedRes.ok) {
|
||||
const sharedData = await sharedRes.json();
|
||||
// Prefer results if paginated
|
||||
sharedCollections = sharedData.results ? sharedData.results : sharedData;
|
||||
}
|
||||
} catch (e) {
|
||||
// ignore fallback errors; user already got success toast
|
||||
}
|
||||
}
|
||||
} else {
|
||||
const error = await res.json();
|
||||
addToast('error', error.error || $t('invites.accept_failed'));
|
||||
|
||||
Reference in New Issue
Block a user