-
Notifications
You must be signed in to change notification settings - Fork 17
feat/collections resource #64
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
7 commits
Select commit
Hold shift + click to select a range
9473ad2
feat: add Collections resource client
sunder-ch 78a0304
fix(tests): assert sub-page via parent_id filter — unfiltered collect…
sunder-ch 34b66b7
Merge branch 'main' into feat/collections-resource
sunder-ch 3518c3c
bumpup version to 0.2.21
sunder-ch 0ca4459
resolve review comments
sunder-ch 0a7f620
resolve coderabbit comments
sunder-ch 9ffc4f3
test: drop unsupported sub-page nesting assertions
sunder-ch File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,3 @@ | ||
| from .base import Collections | ||
|
|
||
| __all__ = ["Collections"] |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,84 @@ | ||
| from __future__ import annotations | ||
|
|
||
| from typing import Any | ||
|
|
||
| from plane.api.base_resource import BaseResource | ||
| from plane.api.collections.members import CollectionMembers | ||
| from plane.api.collections.pages import CollectionPages | ||
| from plane.models.collections import ( | ||
| Collection, | ||
| CreateCollection, | ||
| UpdateCollection, | ||
| ) | ||
|
|
||
|
|
||
| class Collections(BaseResource): | ||
| def __init__(self, config: Any) -> None: | ||
| super().__init__(config, "/workspaces/") | ||
|
|
||
| # Initialize sub-resources | ||
| self.pages = CollectionPages(config) | ||
| self.members = CollectionMembers(config) | ||
|
|
||
| def list(self, workspace_slug: str) -> list[Collection]: | ||
| """List all collections in a workspace. | ||
|
|
||
| Args: | ||
| workspace_slug: The workspace slug identifier | ||
| """ | ||
| response = self._get(f"{workspace_slug}/collections") | ||
| return [Collection.model_validate(item) for item in response] | ||
|
|
||
| def create(self, workspace_slug: str, data: CreateCollection) -> Collection: | ||
| """Create a new collection in a workspace. | ||
|
|
||
| Args: | ||
| workspace_slug: The workspace slug identifier | ||
| data: Collection data | ||
| """ | ||
| response = self._post(f"{workspace_slug}/collections", data.model_dump(exclude_none=True)) | ||
| return Collection.model_validate(response) | ||
|
|
||
| def retrieve(self, workspace_slug: str, collection_id: str) -> Collection: | ||
| """Retrieve a collection by ID. | ||
|
|
||
| Args: | ||
| workspace_slug: The workspace slug identifier | ||
| collection_id: UUID of the collection | ||
| """ | ||
| response = self._get(f"{workspace_slug}/collections/{collection_id}") | ||
| return Collection.model_validate(response) | ||
|
|
||
| def update(self, workspace_slug: str, collection_id: str, data: UpdateCollection) -> Collection: | ||
| """Update a collection's name, logo, or sort order. | ||
|
|
||
| Args: | ||
| workspace_slug: The workspace slug identifier | ||
| collection_id: UUID of the collection | ||
| data: Fields to update (access cannot be changed after creation) | ||
| """ | ||
| response = self._patch( | ||
| f"{workspace_slug}/collections/{collection_id}", | ||
| data.model_dump(exclude_none=True), | ||
| ) | ||
| return Collection.model_validate(response) | ||
|
|
||
| def delete( | ||
| self, | ||
| workspace_slug: str, | ||
| collection_id: str, | ||
| archive_pages: bool | None = None, | ||
| ) -> None: | ||
| """Delete a collection. | ||
|
|
||
| Args: | ||
| workspace_slug: The workspace slug identifier | ||
| collection_id: UUID of the collection | ||
| archive_pages: Whether to archive the collection's pages instead of | ||
| leaving them unfiled. Omit to use the server's default (True). | ||
| Private collections always archive their pages regardless. | ||
| """ | ||
| params = None | ||
| if archive_pages is not None: | ||
| params = {"archive_pages": "true" if archive_pages else "false"} | ||
| return self._delete(f"{workspace_slug}/collections/{collection_id}", params=params) | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,72 @@ | ||
| from __future__ import annotations | ||
|
|
||
| from typing import Any | ||
|
|
||
| from plane.api.base_resource import BaseResource | ||
| from plane.models.collections import ( | ||
| CollectionMember, | ||
| CreateCollectionMember, | ||
| UpdateCollectionMember, | ||
| ) | ||
|
|
||
|
|
||
| class CollectionMembers(BaseResource): | ||
| def __init__(self, config: Any) -> None: | ||
| super().__init__(config, "/workspaces/") | ||
|
|
||
| def list(self, workspace_slug: str, collection_id: str) -> list[CollectionMember]: | ||
| """List members of a (typically private) collection. | ||
|
|
||
| Args: | ||
| workspace_slug: The workspace slug identifier | ||
| collection_id: UUID of the collection | ||
| """ | ||
| response = self._get(f"{workspace_slug}/collections/{collection_id}/members") | ||
| return [CollectionMember.model_validate(item) for item in response] | ||
|
|
||
| def add( | ||
| self, workspace_slug: str, collection_id: str, data: CreateCollectionMember | ||
| ) -> CollectionMember: | ||
| """Add a member to a collection. | ||
|
|
||
| Args: | ||
| workspace_slug: The workspace slug identifier | ||
| collection_id: UUID of the collection | ||
| data: Member user id and access level | ||
| """ | ||
| response = self._post( | ||
| f"{workspace_slug}/collections/{collection_id}/members", | ||
| data.model_dump(exclude_none=True), | ||
| ) | ||
| return CollectionMember.model_validate(response) | ||
|
|
||
| def update( | ||
| self, | ||
| workspace_slug: str, | ||
| collection_id: str, | ||
| member_id: str, | ||
| data: UpdateCollectionMember, | ||
| ) -> CollectionMember: | ||
| """Update a collection member's access level. | ||
|
|
||
| Args: | ||
| workspace_slug: The workspace slug identifier | ||
| collection_id: UUID of the collection | ||
| member_id: UUID of the CollectionMember row (not the user id) | ||
| data: New access level | ||
| """ | ||
| response = self._patch( | ||
| f"{workspace_slug}/collections/{collection_id}/members/{member_id}", | ||
| data.model_dump(exclude_none=True), | ||
| ) | ||
| return CollectionMember.model_validate(response) | ||
|
|
||
| def remove(self, workspace_slug: str, collection_id: str, member_id: str) -> None: | ||
| """Remove a member from a collection. | ||
|
|
||
| Args: | ||
| workspace_slug: The workspace slug identifier | ||
| collection_id: UUID of the collection | ||
| member_id: UUID of the CollectionMember row (not the user id) | ||
| """ | ||
| return self._delete(f"{workspace_slug}/collections/{collection_id}/members/{member_id}") | ||
|
sunder-ch marked this conversation as resolved.
|
||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,104 @@ | ||
| from __future__ import annotations | ||
|
|
||
| from typing import Any | ||
|
|
||
| from plane.api.base_resource import BaseResource | ||
| from plane.models.collections import ( | ||
| AddCollectionPages, | ||
| CollectionPage, | ||
| CollectionPageSearchResult, | ||
| PaginatedCollectionPageResponse, | ||
| UpdateCollectionPage, | ||
| ) | ||
| from plane.models.query_params import CollectionPageQueryParams | ||
|
|
||
|
|
||
| class CollectionPages(BaseResource): | ||
| def __init__(self, config: Any) -> None: | ||
| super().__init__(config, "/workspaces/") | ||
|
|
||
| def list( | ||
| self, | ||
| workspace_slug: str, | ||
| collection_id: str, | ||
| params: CollectionPageQueryParams | None = None, | ||
| ) -> PaginatedCollectionPageResponse: | ||
| """List pages that belong to a collection. | ||
|
|
||
| Args: | ||
| workspace_slug: The workspace slug identifier | ||
| collection_id: UUID of the collection | ||
| params: Optional search/parent_id/pagination filters | ||
| """ | ||
| query_params = params.model_dump(exclude_none=True) if params else None | ||
| response = self._get( | ||
| f"{workspace_slug}/collections/{collection_id}/pages", params=query_params | ||
| ) | ||
| return PaginatedCollectionPageResponse.model_validate(response) | ||
|
|
||
| def add( | ||
| self, workspace_slug: str, collection_id: str, data: AddCollectionPages | ||
| ) -> list[CollectionPage]: | ||
| """Add existing page(s) to a collection. | ||
|
|
||
| Args: | ||
| workspace_slug: The workspace slug identifier | ||
| collection_id: UUID of the collection | ||
| data: Page IDs to add, with optional sort_orders/placement | ||
| """ | ||
| response = self._post( | ||
| f"{workspace_slug}/collections/{collection_id}/pages", | ||
| data.model_dump(exclude_none=True), | ||
| ) | ||
| return [CollectionPage.model_validate(item) for item in response] | ||
|
|
||
| def search( | ||
| self, workspace_slug: str, collection_id: str, search: str | None = None | ||
| ) -> list[CollectionPageSearchResult]: | ||
| """Search pages that are not yet in a collection, to add them. | ||
|
|
||
| Args: | ||
| workspace_slug: The workspace slug identifier | ||
| collection_id: UUID of the collection | ||
| search: Optional case-insensitive substring filter on page name | ||
| """ | ||
| query_params = {"search": search} if search else None | ||
| response = self._get( | ||
| f"{workspace_slug}/collections/{collection_id}/pages-search", | ||
| params=query_params, | ||
| ) | ||
| return [CollectionPageSearchResult.model_validate(item) for item in response] | ||
|
sunder-ch marked this conversation as resolved.
|
||
|
|
||
| def update( | ||
| self, | ||
| workspace_slug: str, | ||
| collection_id: str, | ||
| page_collection_id: str, | ||
| data: UpdateCollectionPage, | ||
| ) -> CollectionPage: | ||
| """Move a page to a different collection, or reorder it within the current one. | ||
|
|
||
| Args: | ||
| workspace_slug: The workspace slug identifier | ||
| collection_id: UUID of the page's current collection | ||
| page_collection_id: UUID of the page-collection membership row | ||
| data: `collection` to move (omit/leave unset to just reorder), | ||
| and/or `sort_order`/`placement` to reorder | ||
| """ | ||
| response = self._patch( | ||
| f"{workspace_slug}/collections/{collection_id}/pages/{page_collection_id}", | ||
| data.model_dump(exclude_none=True), | ||
| ) | ||
| return CollectionPage.model_validate(response) | ||
|
|
||
| def remove(self, workspace_slug: str, collection_id: str, page_collection_id: str) -> None: | ||
| """Remove a page from a collection (does not delete the page itself). | ||
|
|
||
| Args: | ||
| workspace_slug: The workspace slug identifier | ||
| collection_id: UUID of the collection | ||
| page_collection_id: UUID of the page-collection membership row | ||
| """ | ||
| return self._delete( | ||
| f"{workspace_slug}/collections/{collection_id}/pages/{page_collection_id}" | ||
| ) | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.