Skip to content
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

feat: add trial days remaining banner #72

Merged
merged 25 commits into from
Dec 17, 2024
Merged

Conversation

ilee2u
Copy link
Member

@ilee2u ilee2u commented Dec 10, 2024

https://2u-internal.atlassian.net/browse/COSMO-572

Video Demo, showing varying days remaining (fyi the admin page for audit trials is something I did locally, would need to make a PR for it):

Screen.Recording.2024-12-10.at.4.23.55.PM.2.mov

Copy link
Member

@varshamenon4 varshamenon4 left a comment

Choose a reason for hiding this comment

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

Looks great so far! Just a couple suggestions. Also this may be an unrelated bug (in which case we could create a separate ticket), but I noticed that, in the demo, the "bubble" that contains the message seems to be missing for the response message. Is that just the way you're testing/mocking out the xpert chatgpt prompt logic?

src/components/Sidebar/index.jsx Outdated Show resolved Hide resolved
src/components/Sidebar/index.jsx Outdated Show resolved Hide resolved
src/data/thunks.js Show resolved Hide resolved
@@ -70,6 +70,9 @@ export function getChatResponse(courseId, unitId, promptExperimentVariationKey =

dispatch(setApiIsLoading(false));
dispatch(addChatMessage(message.role, message.content, courseId, promptExperimentVariationKey));
if (message.audit_trial_created) {
Copy link
Member

Choose a reason for hiding this comment

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

Where is audit_trial_created coming from? Are you planning to add it to the backend API? Do we have a ticket for that? If so, make a note of that here, please.

Copy link
Member

Choose a reason for hiding this comment

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

I think it would make sense to sync up with Marcos to see how he plans to incorporate getChatResponse into this work, since his work may affect how this function is called.

As an alternative to message.audit_trial_created, it may also make sense to pass a variable to this thunk (e.g. rehydrateChatSummary) so that the frontend can control when to re-fetch this data. For example, we may know when a learner is posting a message from the audit trial CTA, depending on Marcos's approach. This approach would allow us to avoid also needing to change the backend API.

Copy link
Member Author

Choose a reason for hiding this comment

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

Ah, I was experimenting with sending a new value from the backend, and forgot to put this back to its original state. I'm going to change this such that the chat-summary endpoint is called every time a message is sent so that this works while I decide on a more efficient solution.

Copy link
Member Author

Choose a reason for hiding this comment

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

To follow up on this, I added this code to the backend only on my local setup to make this work:

                response = self._get_next_message(request, courserun_key, course_run_id)

                # Temp for testing
                audit_trial_created = True
                if audit_trial_created:
                    # TODO: Determine if this is something we should send to gate the extra calls to chat summary
                    response.data['audit_trial_created'] = True
                return response

I'll leave this as is for now until we're all on the same page on how/when to rehydrate the chat summary related state variables in the frontend.

Copy link
Member Author

@ilee2u ilee2u Dec 12, 2024

Choose a reason for hiding this comment

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

Ok, reverting back to not having a audit_trial_created value in the frontend or backend to keep things simple as agreed upon. We will just call chat-summary with every message received. We can add this feature later if we have performance issues.

Copy link
Member Author

@ilee2u ilee2u Dec 12, 2024

Choose a reason for hiding this comment

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

NOTE: Ignore my replies above to this thread, this is what I'm doing for now:

Per our Slack discussion, I decided on an approach where we will only refresh the chat-summary after the first message is sent. This isn't "optimal", but it at least prevents us from calling the chat-summary endpoint w/ every message.

Copy link
Member Author

Choose a reason for hiding this comment

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

Demo video for that feature:

Screen.Recording.2024-12-12.at.1.10.24.PM.mov

const oneDay = 24 * 60 * 60 * 1000; // hours*minutes*seconds*milliseconds
const daysRemaining = Math.ceil((auditTrialExpirationDate - Date.now()) / oneDay);

if (daysRemaining > 1) {
Copy link
Member

Choose a reason for hiding this comment

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

Although I'm not familiar with it, we should consider Marcos's suggestion of Intl.RelativeTimeFormat to better internationalize these strings. Although, we don't internationalize this feature anyway.

Copy link
Member Author

Choose a reason for hiding this comment

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

Tried this out, seems like using this means we'd have to change the banner text for this as, at least in English, the RelativeTimeFormat spits out "in X days", with no way to change the exact wording. Wondering if that's worth doing given that we aren't intl'ing right now.

src/components/Sidebar/index.jsx Outdated Show resolved Hide resolved
src/components/Sidebar/index.jsx Outdated Show resolved Hide resolved
// Get this to work
const getDaysRemainingMessage = () => {
// if enrollment mode is NOT upgrade eligible, there's no audit trial data
if (!isUpgradeEligible) {
Copy link
Member

Choose a reason for hiding this comment

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

I started a thread in Slack, but I don't think isUpgradeEligible is computed the same way on the backend, which will lead to issues. I don't think that's an issue for your code changes, but I wanted to flag that. We can chat in Slack.

Copy link
Member Author

Choose a reason for hiding this comment

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

Note: This is being addressed in https://2u-internal.atlassian.net/browse/COSMO-612

src/widgets/Xpert.jsx Outdated Show resolved Hide resolved
src/components/Sidebar/Sidebar.scss Show resolved Hide resolved
@ilee2u
Copy link
Member Author

ilee2u commented Dec 12, 2024

Demo of the now-operational upgrade URL:

Screen.Recording.2024-12-12.at.11.59.12.AM.mov

@ilee2u ilee2u force-pushed the ilee2u/days-remaining-banner branch from bf41221 to 27d4b79 Compare December 12, 2024 17:39
src/data/thunks.js Outdated Show resolved Hide resolved
@ilee2u ilee2u marked this pull request as ready for review December 13, 2024 18:40
@ilee2u ilee2u force-pushed the ilee2u/days-remaining-banner branch 4 times, most recently from 22dfc95 to d366bc0 Compare December 16, 2024 20:11
@ilee2u
Copy link
Member Author

ilee2u commented Dec 16, 2024

Demo of how this looks after rebasing onto Marcos' PR with the Disclosure: #73 (review)

Screen.Recording.2024-12-16.at.3.12.06.PM.mov

Copy link
Member

@MichaelRoytman MichaelRoytman left a comment

Choose a reason for hiding this comment

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

I won't have time to review this today, but I wanted to leave this comment. If the PR still needs a review tomorrow, I'll take a look then.

@@ -68,6 +110,12 @@ export function getChatResponse(courseId, unitId, promptExperimentVariationKey =
const customQueryParams = promptExperimentVariationKey ? { responseVariation: promptExperimentVariationKey } : {};
const message = await fetchChatResponse(courseId, messageList, unitId, customQueryParams);

// Refresh chat summary only on the first message so we can tell if the user has initiated an audit trial
// NOTE: This is a bit of a hacky solution that may be refined later
if (messageList.length === 1) {
Copy link
Member

Choose a reason for hiding this comment

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

I think this is fine to have as a POC, but I don't think we should merge this. This is going to make an API call for everyone after they send their first message, which is a lot of extraneous API calls. At a minimum, we should only make this call when the learner is eligible for an audit trial.

Copy link
Member Author

Choose a reason for hiding this comment

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

Noted, added a condition to only show this to upgrade eligible learners as well.

@ilee2u ilee2u force-pushed the ilee2u/days-remaining-banner branch from 045ba42 to 27104c2 Compare December 16, 2024 21:05
Copy link
Member

@alangsto alangsto left a comment

Choose a reason for hiding this comment

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

A few nits, but otherwise this looks good!

src/hooks/use-course-upgrade.js Outdated Show resolved Hide resolved
src/setupTest.js Outdated Show resolved Hide resolved
@@ -3,7 +3,7 @@ import { getOptimizely } from '../data/optimizely';
const trackChatBotMessageOptimizely = (userId, userAttributes = {}) => {
const optimizelyInstance = getOptimizely();

if (!optimizelyInstance) { return; }
if (!optimizelyInstance || Object.keys(optimizelyInstance).length === 0) { return; }
Copy link
Member

Choose a reason for hiding this comment

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

Was this line causing issues?

Copy link
Member Author

Choose a reason for hiding this comment

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

This line was causing issues on my local setup, not sure if it was due to something missing on my end. I can put this back if that's preferred.

Copy link
Member

Choose a reason for hiding this comment

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

I think you probably need to add { moduleName: '@optimizely/react-sdk', dir: '../src/frontend-plugin-advertisements/src/mocks/optimizely', dist: '.' }, to your frontend-app-learning module.config.js file

Copy link
Member Author

Choose a reason for hiding this comment

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

That line is in my config file so I'm not sure what's up there...

module.exports = {
  /*
  Modules you want to use from local source code.  Adding a module here means that when this app
  runs its build, it'll resolve the source from peer directories of this app.

  moduleName: the name you use to import code from the module.
  dir: The relative path to the module's source code.
  dist: The sub-directory of the source code where it puts its build artifact.  Often "dist".
  */
  localModules: [
    { moduleName: '@edx/frontend-lib-special-exams', dir: '../src/frontend-lib-special-exams', dist: 'src' },
    { moduleName: '@edx/frontend-plugin-advertisements', dir: '../src/frontend-plugin-advertisements', dist: 'src' },
    { moduleName: '@optimizely/react-sdk', dir: '../src/frontend-plugin-advertisements/src/mocks/optimizely', dist: '.' },
    { moduleName: '@edx/frontend-lib-learning-assistant', dir: '../src/frontend-lib-learning-assistant', dist: 'src' },
  ],
};

When I debugged this I found that the optomizelyInstance had a value of {} so that's why I inserted this condition.

Copy link
Member

Choose a reason for hiding this comment

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

What's the issue you're running into? I was not running into issues locally with optimizely so just trying to help narrow down what could be going wrong

Copy link
Member

@varshamenon4 varshamenon4 left a comment

Choose a reason for hiding this comment

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

Just reviewed the sidebar, but let me know if other areas need review! Happy to take another look. Just had a few questions/nits so far, but looking good!

src/components/Sidebar/index.jsx Outdated Show resolved Hide resolved
src/components/Sidebar/index.jsx Outdated Show resolved Hide resolved
src/components/Sidebar/index.test.jsx Outdated Show resolved Hide resolved
src/components/Sidebar/index.test.jsx Show resolved Hide resolved
@ilee2u ilee2u force-pushed the ilee2u/days-remaining-banner branch from 27104c2 to d0a8ae5 Compare December 16, 2024 21:47
Copy link
Member

@rijuma rijuma left a comment

Choose a reason for hiding this comment

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

LGTM, but please before merging check my nit comment on the tracking for the upgrade link and remove the "Your trial has expired" message since that would never be shown, it will render the paywall instead. (as suggested by Alison and Varsha)

Copy link
Member

@varshamenon4 varshamenon4 left a comment

Choose a reason for hiding this comment

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

lgtm! I think there are a couple of outstanding comments to be addressed but otherwise looks great.

@ilee2u ilee2u force-pushed the ilee2u/days-remaining-banner branch from e7b9f01 to 1ac0c54 Compare December 17, 2024 18:45
@ilee2u ilee2u force-pushed the ilee2u/days-remaining-banner branch from 5547942 to 0352c85 Compare December 17, 2024 19:22
@ilee2u ilee2u merged commit daaa1cb into main Dec 17, 2024
4 checks passed
@ilee2u ilee2u deleted the ilee2u/days-remaining-banner branch December 17, 2024 19:26
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants