Repository navigation
Release 0.81.9 - #4060
Open
odlbot wants to merge 6 commits into
Open
Release 0.81.9#4060odlbot wants to merge 6 commits into
odlbot wants to merge 6 commits into
Conversation
* fix(dashboard): rely on the API's contract scoping when picking a run On a contract page the courses API already limits each course's runs to that contract, counting runs attached through the run's contract list as well as its b2b_contract field. getBestRun then filtered again on b2b_contract alone, which dropped runs whose b2b_contract is blank, so the card showed no run at all. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * fix(dashboard): show staff enrollments in contract runs with no b2b_contract An enrollment's b2b_contract_id mirrors its run's b2b_contract, which is left blank on contract runs learners must not enroll in themselves. The contract page dropped those enrollments, so a staff-enrolled learner saw a disabled Start instead of Continue. Keep a null-contract enrollment on a contract page when its run is one the API returned for that contract. EnrolledCourseCard now takes the page's contractId, like UnenrolledCourseCard, so these cards still read "Module" and never offer a certificate upgrade. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * fix(dashboard): keep contract enrollments off My Learning My Learning treated any enrollment with a null b2b_contract_id as a personal one. A contract run with a blank b2b_contract (staff-enrolled only) produces exactly that, so it showed up as a "Course" card with a certificate upgrade banner. Ask the enrollments API for exclude_b2b, which filters on the run's b2b_contracts list. The filtered list gets its own query key that extends the shared one, so existing invalidations still refresh it, and the unenroll mutation's optimistic removal now updates every variant. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * revert(dashboard): drop the exclude_b2b query for My Learning Since mitodl/mitxonline#4084, the enrollments API's exclude_b2b and an enrollment's b2b_contract_id both come from the enrollment's own contract, so isNonContractEnrollment already does what exclude_b2b did. Home goes back to the shared enrollments query. This reverts commit a2205ed. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * docs(dashboard): describe b2b_contract_id as the enrollment's own contract Since mitodl/mitxonline#4084 an enrollment's b2b_contract_id comes from the enrollment, not its run. Update the filterEnrollmentsForContract comment and the test names that still said otherwise. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…le (#4028) * Infer the SEO title and description, overridable The fields were plain optional text: blank meant the page head fell back on the frontend, nothing else saw a resolved value, and #4009 then made both compulsory -- so every author had to retype words the content already had. They are now inferred and overridable, the way Medium does it. The columns are renamed to `seo_title_override` and `seo_description_override`, and the serializer resolves `seo_title` and `seo_description` read-only: the override where there is one, otherwise the content's own title and the line under its headline. Storing the override rather than the resolved value is the whole point -- rename an article and its search title follows, until somebody decides otherwise. The drawer shows what will be used as each field's placeholder rather than pre-filling it, which is what keeps "unset" apart from "set to the same words": pre-filled text would be saved as an override on the next press and quietly stop tracking. Clearing an override hands the field back to the content. Required now means the *resolved* value is empty -- no override and nothing to infer from, so an untitled draft or a body with no subheading. Blank fields are the ordinary case and publish fine. That also fixes a real bug in the resume path: it tested the overrides, so a publish held back for topics never resumed once the SEO values came from inference. The counters measure the resolved value, since that is what a search result will show. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * Address review on the inferred SEO fields Three fixes from the review: A subheading with any formatting in it was truncated to its first word. ProseMirror splits a line on every mark boundary, so "A **complex** article with *various* elements." is five text nodes and both helpers read only the first -- resolving "A". Every inline node is now joined, with nothing between them, since they are contiguous characters that differ only by their marks. Fixed on both sides, because the API resolves saved content and the editor infers from the document in hand. The test factory could emit a response the serializer cannot produce: it defaulted the resolved values independently of the overrides, so a fixture supplying only `seo_description_override` claimed a blank resolved description alongside it. They are now derived from whatever overrides the caller passed, with an explicit resolved value still winning. Both fields were marked `required` whenever the rule was on, so a field whose blank the save accepts -- because the content supplies a value -- still carried an asterisk and `aria-required`. Required now means what the save means: only where nothing can stand in. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Address Chris's review: expand-then-contract, draft-saveable drawer The migration is now the expand half of expand-then-contract. Deploys are rolling, so for a few minutes old and new code run against the same database: renaming the columns would take `seo_title` away from pods still selecting it, and those 500 until they restart. 0010 adds the override columns and backfills them, leaving the old pair in place for the old code to keep reading. Dropping them is a separate PR once every pod is on the new code. The legacy fields stay on the model for that window, unread. The drawer's save is no longer refused on a draft. A draft is worked on in pieces -- topics now, a description once it is written -- and refusing until everything resolves makes that impossible, which is not what the requirement is for. The new `mustResolve` gate is true once the content is public and while a publish is waiting on the drawer, and false for a draft the editor simply opened; the asterisks follow it, so no field claims to be required where the save accepts blank. The publish-waiting case is what still stops a held-back press being saved away. Also: the two route comments no longer describe a fallback that lives in the API now, two doc comments state their constraint rather than the shape they replaced, and the misplaced test that had been inserted between a comment and the test it documents is moved back. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * Keep the old SEO columns out of this release's queries Migrations run as a pre-deploy Job, so pods on the previous release query the migrated schema until the rollout replaces them. Two gaps remained: - AddField drops its default after backfilling, leaving the new columns NOT NULL with nothing to fall back on, so inserts from the previous release -- which does not know the columns -- would fail. They get a db_default. - Leaving `seo_title` and `seo_description` in the model meant this release kept selecting them, which only moved the breakage to the contracting PR: dropping the columns there would 500 every pod still on this release. SeparateDatabaseAndState removes the two fields from Django's state while leaving the columns in place, so this release stops referencing them and the previous release can still read them. The columns also get a db_default, for the same reason as the new ones. A later migration can then drop them with no deployed code referring to them. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * Correct three comments the SEO rework left behind The publish gate's comment described falling back to the title and subheading as the failure it guards against, when that fallback is the intended behaviour and what it actually requires is a resolved value. The length cap names `seo_title_override`, in its comment and in the test that pins it. `seo_title` is the resolved, read-only field now, and off the model entirely; the 255 characters are the override's. `extractWebsiteContentDescription` returned absent rather than blank for `getMetadataAsync` to default. The page head reads the resolved `seo_description` from the API instead, and the one caller left turned the absence straight back into a blank, so it returns the string it found. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * Ask only for the SEO field that cannot resolve The two resolve separately, so most often only one of them holds a publish back -- a piece of content with a title but no line under the headline resolves its SEO title and not its description, which is the common case. The section asked for both regardless, sending the author to a field that was already fine and that the asterisks correctly left unmarked. It also closed with an invitation to leave them blank, "each one follows your article -- the title, and the line under the headline". For whichever field is missing that is the opposite of the advice needed: blank is what is blocking the publish, because the thing it would fall back to is the thing the content does not have. Where something is missing the section now says which, and why it cannot be inferred; the invitation stands where both resolve and nothing is blocked. Three tests pinned the old wording, each in a state where only the description was missing -- one of them with a comment already noting that the title is never missing here. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Ahtesham Quraish <ahtesham.quraish@arbisoft.com> Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com> Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
* Show the API's 400 detail on enrollment surfaces
MITx Online answers a rejected enrollment with a 400 whose detail is
written for the learner, but Learn discarded the body and rendered the
same generic "please try again" for every failure — including ones that
cannot succeed on retry.
Adds badRequestDetail/badRequestDetailOr, which read a detail only from
a 400 and return undefined otherwise, so a 500 or a detail-less 400
keeps today's copy. The enroll hooks now expose the error object rather
than an isError boolean, and the enroll areas, header CTA, enrollment
dialog, and dashboard toasts prefer the server's string over their own.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
* slim down chatty claude code comments
* Link users to support alongside enrollment error copy
An enrollment 400 detail is often only actionable by a human ("Error code:
CS_700"), but no enrollment error surface offered a way to reach support.
Add ErrorMessageWithSupport, which appends a "Contact Support" link to a
message, and use it on every enrollment failure surface: the product page
InfoBox and header alerts, both enrollment dialog alerts, and - via a new
opt-in `meta.contactSupport` read by the global mutation-error handler - the
dashboard enrollment toast.
The link points at the support site's request form (new urls.SUPPORT_REQUEST)
rather than the mailto: used by the dashboard's upgrade banners, which are
left as they are.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
OpenAPI Changes128 changes: 0 error, 24 warning, 104 info Unexpected changes? Ensure your branch is up-to-date with |
This branch has not been deployed
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
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
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.
Nathan Levesque
Ahtesham Quraish
Carey P Gumaer
Anastasia Beglova