Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ and this project adheres to

### Added

- ✨(backend) add documents/all endpoint with descendants #1553
- ✨(frontend) create skeleton component for DocEditor #1491
- ✨(frontend) add an EmojiPicker in the document tree and title #1381

Expand Down
55 changes: 55 additions & 0 deletions src/backend/core/api/viewsets.py
Original file line number Diff line number Diff line change
Expand Up @@ -368,6 +368,7 @@ class DocumentViewSet(
queryset = models.Document.objects.select_related("creator").all()
serializer_class = serializers.DocumentSerializer
ai_translate_serializer_class = serializers.AITranslateSerializer
all_serializer_class = serializers.ListDocumentSerializer
children_serializer_class = serializers.ListDocumentSerializer
descendants_serializer_class = serializers.ListDocumentSerializer
list_serializer_class = serializers.ListDocumentSerializer
Expand Down Expand Up @@ -837,6 +838,60 @@ def children(self, request, *args, **kwargs):
},
)

@drf.decorators.action(
detail=False,
methods=["get"],
)
def all(self, request, *args, **kwargs):
"""
Returns all documents (including descendants) that the user has access to.

Unlike the list endpoint which only returns top-level documents, this endpoint
returns all documents including children, grandchildren, etc.
"""
user = self.request.user

accessible_documents = self.get_queryset()
accessible_paths = list(accessible_documents.values_list("path", flat=True))

if not accessible_paths:
return self.get_response_for_queryset(self.queryset.none())

# Build query to include all descendants using path prefix matching
descendants_clause = db.Q()
for path in accessible_paths:
descendants_clause |= db.Q(path__startswith=path)

queryset = self.queryset.filter(
descendants_clause, ancestors_deleted_at__isnull=True
)

# Apply existing filters
filterset = ListDocumentFilter(
self.request.GET, queryset=queryset, request=self.request
)
if not filterset.is_valid():
raise drf.exceptions.ValidationError(filterset.errors)
filter_data = filterset.form.cleaned_data

# Filter as early as possible on fields that are available on the model
for field in ["is_creator_me", "title"]:
queryset = filterset.filters[field].filter(queryset, filter_data[field])

queryset = queryset.annotate_user_roles(user)

# Annotate favorite status and filter if applicable as late as possible
queryset = queryset.annotate_is_favorite(user)
for field in ["is_favorite", "is_masked"]:
queryset = filterset.filters[field].filter(queryset, filter_data[field])

# Apply ordering only now that everything is filtered and annotated
queryset = filters.OrderingFilter().filter_queryset(
self.request, queryset, self
)

return self.get_response_for_queryset(queryset)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You will have a "flat view". Do you wan't something looking what is made on the tree endpoint ? Each children sideloaded in its parent ?

Copy link
Contributor

@berrydenhartog berrydenhartog Dec 9, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@lunika christopher is on holiday until beginning of january

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We want to be able to list all documents that are available to a user, irrelevant of the location. We want it sorted on date, where the last edited or last created document is listed first.

We also want to search all documents on title string, and when docs supports content search, we want to start searching on content, listing the most relevant document first.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Then in that case I think it is ok to merge it as it.
i will do it tomorrow probably. If not ping me again here...


@drf.decorators.action(
detail=True,
methods=["get"],
Expand Down
Loading