Skip to content

Commit

Permalink
Issue/525 eportfolio endpoint (ucfopen#536)
Browse files Browse the repository at this point in the history
* Create new classes, add user methods

Create the `EPortfolio` and `EPortfolioPage` classes to match
Canvas docs.

Add relevant ePortfolio methods to `User` class.

* Remove ID arg from all methods

The module is to work with single eportfolios already retrieved
through the `Canvas` object. The IDs were redundant and were removed.

* EPortfolio module tests

Added fixutres for `EPortfolio` module. All tests passing.

* Add `get_eportfolio` method

The ePortfolio endpoint isn't linked to a specific course, so adding it
to the Canvas module made sense. There is another route for users to
retrieve their own ePortfolios in a `PaginatedList`.

Test added and passing.

* fix accidental formatting of json file

* Add string method tests

All tests passing.

* fix flake8, isort errors

* fix isort error

* Docstring fixes. Add eportfolio ref

* reformat eport json

* Fix markdown typo

Co-authored-by: Matthew Emond <[email protected]>
  • Loading branch information
bennettscience and Thetwam authored Aug 9, 2022
1 parent 6e2af8b commit 340879f
Show file tree
Hide file tree
Showing 12 changed files with 420 additions and 3 deletions.
1 change: 1 addition & 0 deletions AUTHORS.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ Patches and Suggestions
- Ashutosh Saxena [@Xx-Ashutosh-xX](https://github.com/Xx-Ashutosh-xX)
- Ben Liblit [@liblit](https://github.com/liblit)
- Bill Wrbican [@wjw27](https://github.com/wjw27)
- [@Birdmaaan4](https://github.com/Birdmaaan4)
- [@blepabyte](https://github.com/blepabyte)
- Bradford Lynch [@bradfordlynch](https://github.com/bradfordlynch)
- Brian Bennett [@bennettscience](https://github.com/bennettscience)
Expand Down
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
- Grade Change Log for Assignments, Courses, and Users (Thanks, [@matthewf-ucsd](https://github.com/matthewf-ucsd))
- Content Migrations: List items for selective import (Thanks, [@matthewf-ucsd](https://github.com/matthewf-ucsd))
- List observers of a User (Thanks, [@bennettscience](https://github.com/bennettscience))
- ePortfolio endpoints (Thanks, [@Birdmaaan4](https://github.com/Birdmaaan4) and [@bennettscience](https://github.com/bennettscience))

### General

Expand Down
22 changes: 22 additions & 0 deletions canvasapi/canvas.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
from canvasapi.course import Course
from canvasapi.course_epub_export import CourseEpubExport
from canvasapi.current_user import CurrentUser
from canvasapi.eportfolio import EPortfolio
from canvasapi.exceptions import RequiredFieldMissing
from canvasapi.file import File
from canvasapi.folder import Folder
Expand Down Expand Up @@ -771,6 +772,27 @@ def get_current_user(self):
"""
return CurrentUser(self.__requester)

def get_eportfolio(self, eportfolio, **kwargs):
"""
Get an eportfolio by ID.
:param eportfolio: The object or ID of the eportfolio to retrieve.
:type eportfolio: :class: `canvasapi.eportfolio.EPortfolio` or int
:calls: `GET /api/v1/eportfolios/:id` \
`<https://canvas.instructure.com/doc/api/e_portfolios.html#method.eportfolios_api.show>`_
:rtype: :class:`canvasapi.eportfolio.EPortfolio`
"""
eportfolio_id = obj_or_id(eportfolio, "eportfolio", (EPortfolio,))
response = self.__requester.request(
"GET",
"eportfolios/{}".format(eportfolio_id),
_kwargs=combine_kwargs(**kwargs),
)

return EPortfolio(self.__requester, response.json())

def get_epub_exports(self, **kwargs):
"""
Return a list of epub exports for the associated course.
Expand Down
86 changes: 86 additions & 0 deletions canvasapi/eportfolio.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
from canvasapi.canvas_object import CanvasObject
from canvasapi.paginated_list import PaginatedList
from canvasapi.util import combine_kwargs


class EPortfolio(CanvasObject):
def __str__(self):
return "{}".format(self.name)

def delete(self, **kwargs):
"""
Delete an ePortfolio.
:calls: `DELETE /api/v1/eportfolios/:id \
<https://canvas.instructure.com/doc/api/e_portfolios.html#method.eportfolios_api.delete>`_
:returns: ePortfolio with deleted date set.
:rtype: :class:`canvasapi.eportfolio.EPortfolio`
"""
response = self._requester.request(
"DELETE", "eportfolios/{}".format(self.id), _kwargs=combine_kwargs(**kwargs)
)
return EPortfolio(self._requester, response.json())

def get_eportfolio_pages(self, **kwargs):
"""
Return a list of pages for an ePortfolio.
:calls: `GET /api/v1/eportfolios/:eportfolio_id/pages \
<https://canvas.instructure.com/doc/api/e_portfolios.html#method.eportfolios_api.pages>`_
:returns: List of ePortfolio pages.
:rtype: :class:`canvasapi.paginated_list.PaginatedList` of
:class:`canvasapi.eportfolio.EPortfolioPage`
"""

return PaginatedList(
EPortfolioPage,
self._requester,
"GET",
"eportfolios/{}/pages".format(self.id),
_kwargs=combine_kwargs(**kwargs),
)

def moderate_eportfolio(self, **kwargs):
"""
Update the spam_status of an eportfolio.
Only available to admins who can `moderate_user_content`.
:calls: `PUT /api/v1/eportfolios/:eportfolio_id/moderate \
<https://canvas.instructure.com/doc/api/e_portfolios.html#method.eportfolios_api.moderate>`_
:returns: Updated ePortfolio.
:rtype: :class:`canvasapi.eportfolio.EPortfolio`
"""
response = self._requester.request(
"PUT",
"eportfolios/{}/moderate".format(self.id),
_kwargs=combine_kwargs(**kwargs),
)

return EPortfolio(self._requester, response.json())

def restore(self, **kwargs):
"""
Restore an ePortfolio back to active that was previously deleted.
Only available to admins who can moderate_user_content.
:calls: `PUT /api/v1/eportfolios/:eportfolio_id/restore \
<https://canvas.instructure.com/doc/api/e_portfolios.html#method.eportfolios_api.restore>`_
:returns: Updated ePortfolio.
:rtype: :class:`canvasapi.eportfolio.EPortfolio`
"""
response = self._requester.request(
"PUT",
"eportfolios/{}/restore".format(self.id),
_kwargs=combine_kwargs(**kwargs),
)

return EPortfolio(self._requester, response.json())


class EPortfolioPage(CanvasObject):
def __str__(self):
return "{}. {}".format(self.position, self.name)
50 changes: 47 additions & 3 deletions canvasapi/user.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ def add_observee(self, observee_id, **kwargs):
:param observee_id: The login id for the user to observe.
:type observee_id: int
:rtype: :class: `canvasapi.user.User`
:rtype: :class:`canvasapi.user.User`
"""

response = self._requester.request(
Expand Down Expand Up @@ -490,6 +490,25 @@ def get_enrollments(self, **kwargs):
_kwargs=combine_kwargs(**kwargs),
)

def get_eportfolios(self, **kwargs):
"""
Returns a list of ePortfolios for a user.
:calls: `GET /api/v1/users/:user_id/eportfolios \
<https://canvas.instructure.com/doc/api/e_portfolios.html#method.eportfolios_api.index>`_
:rtype: :class:`canvasapi.paginated_list.PaginatedList` of
:class:`canvasapi.eportfolio.EPortfolio`
"""
from canvasapi.eportfolio import EPortfolio

return PaginatedList(
EPortfolio,
self._requester,
"GET",
"users/{}/eportfolios".format(self.id),
_kwargs=combine_kwargs(**kwargs),
)

def get_feature_flag(self, feature, **kwargs):
"""
Returns the feature flag that applies to the given user.
Expand Down Expand Up @@ -866,6 +885,31 @@ def merge_into(self, destination_user, **kwargs):
super(User, self).set_attributes(response.json())
return self

def moderate_all_eportfolios(self, **kwargs):
"""
Update the spam_status for all active eportfolios of a user.
Only available to admins who can moderate_user_content.
:param eportfolio: The object or ID of the ePortfolio to retrieve.
:type eportfolio: :class:`canvasapi.eportfolio.EPortfolio` or int
:calls: `PUT /api/v1/users/:user_id/eportfolios \
<https://canvas.instructure.com/doc/api/e_portfolios.html#method.eportfolios_api.moderate_all>`_
:returns: A list of all user ePortfolios.
:rtype: :class:`canvasapi.paginated_list.PaginatedList` of
:class:`canvasapi.eportfolio.EPortfolio`
"""
from canvasapi.eportfolio import EPortfolio

return PaginatedList(
EPortfolio,
self._requester,
"PUT",
"users/{}/eportfolios".format(self.id),
_kwargs=combine_kwargs(**kwargs),
)

def remove_observee(self, observee_id, **kwargs):
"""
Unregisters a user as being observed by the given user.
Expand All @@ -875,7 +919,7 @@ def remove_observee(self, observee_id, **kwargs):
:param observee_id: The login id for the user to observe.
:type observee_id: int
:rtype: :class: `canvasapi.user.User`
:rtype: :class:`canvasapi.user.User`
"""

response = self._requester.request(
Expand Down Expand Up @@ -963,7 +1007,7 @@ def show_observee(self, observee_id, **kwargs):
:param observee_id: The login id for the user to observe.
:type observee_id: int
:rtype: :class: `canvasapi.user.User`
:rtype: :class:`canvasapi.user.User`
"""

response = self._requester.request(
Expand Down
1 change: 1 addition & 0 deletions docs/class-reference.rst
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ Class Reference
discussion-topic-ref
enrollment-ref
enrollment-term-ref
eportfolio-ref
external-tool-ref
favorite-ref
feature-ref
Expand Down
13 changes: 13 additions & 0 deletions docs/eportfolio-ref.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
==========
EPortfolio
==========

.. autoclass:: canvasapi.eportfolio.EPortfolio
:members:

==============
EPortfolioPage
==============

.. autoclass:: canvasapi.eportfolio.EPortfolioPage
:members:
75 changes: 75 additions & 0 deletions tests/fixtures/eportfolio.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
{
"delete_eportfolio": {
"method": "DELETE",
"endpoint": "eportfolios/1",
"data": {
"id": 1,
"name": "ePortfolio 1",
"workflow_state": "deleted",
"description": "Delete this ePortfolio",
"deleted_at": "2022-07-05T21:00:00Z"
},
"status_code": 200
},
"get_eportfolio_by_id": {
"method": "GET",
"endpoint": "eportfolios/1",
"data": {
"id": 1,
"user_id": 1,
"workflow_state": "active",
"name": "ePortfolio 1",
"deleted_at": "null",
"spam_status": "null"
},
"status_code": 200
},
"get_eportfolio_pages": {
"method": "GET",
"endpoint": "eportfolios/1/pages",
"data": [
{
"id": 1,
"eportfolio_id": 1,
"position": 1,
"name": "ePortfolio 1",
"content": "This is the page of content",
"created_at": "2022-07-01T18:00:00Z",
"updated_at": "2021-07-04T18:00:00Z"
},
{
"id": 2,
"eportfolio_id": 1,
"position": 2,
"name": "ePortfolio 1",
"content": "This is the second page of content",
"created_at": "2022-07-02T18:00:00Z",
"updated_at": "2021-07-02T18:00:00Z"
}
],
"status_code": 200
},
"moderate_eportfolio_as_spam": {
"method": "PUT",
"endpoint": "eportfolios/1/moderate",
"data": {
"id": 1,
"user_id": 1,
"workflow_state": "active",
"name": "ePortfolio 1",
"deleted_at": "null",
"spam_status": "marked_as_spam"
}
},
"restore_deleted_eportfolio": {
"method": "PUT",
"endpoint": "eportfolios/1/restore",
"data": {
"id": 1,
"user_id": 1,
"workflow_state": "active",
"name": "ePortfolio 1",
"deleted_at": "null"
}
}
}
56 changes: 56 additions & 0 deletions tests/fixtures/user.json
Original file line number Diff line number Diff line change
Expand Up @@ -544,6 +544,24 @@
],
"status_code": 200
},
"moderate_user_eportfolios": {
"method": "PUT",
"endpoint": "users/1/eportfolios",
"data": [
{
"name": "ePortfolio 1",
"workflow_state": "active",
"created_at": "2022-07-05T21:00:00Z",
"spam_status": "marked_as_spam"
},
{
"name": "ePortfolio 2",
"workflow_state": "active",
"created_at": "2022-07-05T21:00:00Z",
"spam_status": "marked_as_spam"
}
]
},
"page_views": {
"method": "GET",
"endpoint": "users/1/page_views",
Expand Down Expand Up @@ -1055,6 +1073,44 @@
},
"status_code": 200
},
"get_eportfolios": {
"method": "GET",
"endpoint": "users/1/eportfolios",
"data": [
{
"name": "ePortfolio 1",
"workflow_state": "active",
"created_at": "2022-07-05T21:00:00Z"
},
{
"name": "ePortfolio 2",
"workflow_state": "active",
"created_at": "2022-07-05T21:00:00Z"
}
]
},
"get_eportfolios_include_deleted": {
"method": "GET",
"endpoint": "users/1/eportfolios",
"data": [
{
"name": "ePortfolio 1",
"workflow_state": "active",
"created_at": "2022-07-05T21:00:00Z"
},
{
"name": "ePortfolio 2",
"workflow_state": "active",
"created_at": "2022-07-05T21:00:00Z"
},
{
"name": "ePortfolio 3",
"workflow_state": "deleted",
"created_at": "2022-07-05T21:00:00Z",
"deleted_at": "2022-07-06T18:00:00Z"
}
]
},
"get_features": {
"method": "GET",
"endpoint": "users/1/features",
Expand Down
Loading

0 comments on commit 340879f

Please sign in to comment.