-
Notifications
You must be signed in to change notification settings - Fork 1
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
Add a BFFE endpoint for Learning Assistant (LA), including information about LA is enabled, LA message history, and LA audit trial. #140
Conversation
06a3033
to
1420f66
Compare
Coverage reportClick to see where and how coverage changed
This report was generated by python-coverage-comment-action |
1420f66
to
e9652ac
Compare
learning_assistant/views.py
Outdated
trial_data['start_date'] = trial.start_date | ||
trial_data['expiration_date'] = trial.expiration_date | ||
|
||
data['trial'] = trial_data |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I currently have the frontend extracting 'audit_trial' and not 'trial' from the GET request data. Wondering if we should name this attribute 'audit_trial', or extract the 'trial' attribute in the frontend. Let me know your thoughts!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Agree on the question. My vote is on audit_trial
for consistency.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sure, no problem. I chose trial
because the trial is available to more than just learners in the audit
track, but it's not an issue to change.
learning_assistant/urls.py
Outdated
re_path( | ||
fr'learning_assistant/v1/course_id/{COURSE_ID_PATTERN}/summary', | ||
LearningAssistantSummaryView.as_view(), | ||
name='summary', | ||
), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we have plans to enable (and integrate) the Unit Summary to Xpert and this /summary
reference could be confusing. Maybe we could use something like /chat
instead?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
To clarify, are you suggesting that I change the URL/name to chat
? I think that would conflict with the chat endpoint, so I would prefer not to do that. I also don't think chat
represents the purpose of this endpoint.
Personally, I think summary
and unit_summary
would be reasonable URLs to coexist, and I wouldn't find them confusing. I don't think we should name the URL for unit summaries summary
.
What about one of these? overview
, details
, or info
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I totally forgot about the existing /chat
one. I think info
fits better, but it's your call.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks great! A few comments and some nits (feel free to disregard those though!).
DAYS_SINCE_UPGRADE_DEADLINE = datetime.now() - upgrade_deadline | ||
if DAYS_SINCE_UPGRADE_DEADLINE >= timedelta(days=0): | ||
return True | ||
default_trial_length_days = 14 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good idea to have a default!
learning_assistant/api.py
Outdated
|
||
# If the upgrade deadline has passed, return True for expired. Upgrade deadline is an optional attribute of a | ||
# CourseMode, so if it's None, then do not return True. | ||
days_since_upgrade_deadline = datetime.now() - upgrade_deadline if upgrade_deadline else None |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit:
days_since_upgrade_deadline = datetime.now() - upgrade_deadline if upgrade_deadline else None | |
days_until_upgrade_deadline = datetime.now() - upgrade_deadline if upgrade_deadline else None |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for the suggestion. I'll make that change.
@@ -13,3 +15,14 @@ class LearningAssistantCourseEnabledData: | |||
|
|||
course_key: CourseKey = field(validator=validators.instance_of(CourseKey)) | |||
enabled: bool = field(validator=validators.instance_of(bool)) | |||
|
|||
|
|||
@frozen |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
question: does this just mean that this cannot be changed?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes. The frozen
decorator makes LearningAssistantAuditTrialData
class immutable, so once an instance of this class is created, its attributes cannot be changed.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
... just let it go.
* 200: OK | ||
* 400: Malformed Request - Course ID is not a valid course ID. | ||
* 403: Forbidden - Learning assistant not enabled for course or learner does not have a valid enrollment or is | ||
not staff. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: I'm not sure if it's just how it's rendered here, but is this spacing intended?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not sure if you're seeing something different than what I'm seeing, but I tend to align subsequent lines of paragraphs to the beginning character of the paragraph, because I find it easier to read. Would you prefer a different indentation?
learning_assistant/views.py
Outdated
@@ -271,3 +288,125 @@ def get(self, request, course_run_id): | |||
message_history = get_message_history(courserun_key, user, message_count) | |||
data = MessageSerializer(message_history, many=True).data | |||
return Response(status=http_status.HTTP_200_OK, data=data) | |||
|
|||
|
|||
class LearningAssistantSummaryView(APIView): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nice!
""" | ||
Given a course run ID, return all the data necessary for the Learning Assistant to fuction. | ||
|
||
The response will be in the following format. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nice, I like this format!
""" | ||
Test suite for get_audit_trial_expiration_date. | ||
""" | ||
@ddt.data( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These cases look pretty complete to me!
trial_length_days = default_trial_length_days | ||
|
||
# If LEARNING_ASSISTANT_AUDIT_TRIAL_LENGTH_DAYS is set to a negative number, assume it should be 0. | ||
# pylint: disable=consider-using-max-builtin |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
pylint told me to "consider" doing trial_length_days = max(trial_length_days, 0)
instead, which I thought was less readable, so I didn't. Interesting that it forces me to address something it tells me to consider 😄.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
"I'm asking telling you to consider, and I won't take a NO for an answer.." 🤌
@@ -95,13 +95,6 @@ def setUp(self): | |||
) | |||
self.patcher.start() | |||
|
|||
@patch('learning_assistant.views.learning_assistant_enabled') |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not sure why this test is here. It tests the enabled
endpoint. Copypasta? I removed it.
@@ -264,13 +261,6 @@ def setUp(self): | |||
super().setUp() | |||
self.course_id = 'course-v1:edx+test+23' | |||
|
|||
@patch('learning_assistant.views.learning_assistant_enabled') |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not sure why this test is here. It tests the enabled
endpoint. Copypasta? I removed it.
return expiration_datetime | ||
|
||
|
||
def get_audit_trial(user): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I had to create a get
and a get_or_create
method because when we make a POST
call to the /chat
endpoint, we want to create a trial if one doesn't exist, but when we make a GET
call to the /summary
endpoint, we do not.
learning_assistant/api.py
Outdated
|
||
# If the upgrade deadline has passed, return True for expired. Upgrade deadline is an optional attribute of a | ||
# CourseMode, so if it's None, then do not return True. | ||
days_since_upgrade_deadline = datetime.now() - upgrade_deadline if upgrade_deadline else None |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I had to rewrite Isaac's original function a bit, so I don't want this change to get lost in the diff. The expiration_datetime
field of the CourseMode
model may be None
, so I've added handling for that here.
@@ -38,51 +43,28 @@ | |||
class CourseChatView(APIView): | |||
""" | |||
View to retrieve chat response. | |||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I added some missing documentation.
learning_assistant/urls.py
Outdated
re_path( | ||
fr'learning_assistant/v1/course_id/{COURSE_ID_PATTERN}/summary', | ||
LearningAssistantSummaryView.as_view(), | ||
name='summary', | ||
), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
To clarify, are you suggesting that I change the URL/name to chat
? I think that would conflict with the chat endpoint, so I would prefer not to do that. I also don't think chat
represents the purpose of this endpoint.
Personally, I think summary
and unit_summary
would be reasonable URLs to coexist, and I wouldn't find them confusing. I don't think we should name the URL for unit summaries summary
.
What about one of these? overview
, details
, or info
?
learning_assistant/views.py
Outdated
trial_data['start_date'] = trial.start_date | ||
trial_data['expiration_date'] = trial.expiration_date | ||
|
||
data['trial'] = trial_data |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sure, no problem. I chose trial
because the trial is available to more than just learners in the audit
track, but it's not an issue to change.
learning_assistant/views.py
Outdated
|
||
Accepts: [GET] | ||
|
||
Path: /learning_assistant/v1/course_id/{course_run_id}/ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: Shouldn't this path include the /summary
part (or whatever variant you choose for it)?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes! Thank you for noticing that - very observant 😀.
efc1002
to
45e0393
Compare
…ata to function This commit adds a back-end-for-frontend (BFFE) endpoint for the Learning Assistant to get all the necessary data it needs to function. The response from this endpoint includes the following information. * whether the Learning Assistant is enabled * message history information, if the learner is eligible to use the Learning Assistant * audit trial information
45e0393
to
1fc3972
Compare
This pull request adds a back-end-for-frontend (BFFE) endpoint for the Learning Assistant to get all the necessary data it needs to function.
The response from this endpoint includes the following information.