build!: Switch to openedx-core (renamed from openedx-learning)
Instead of installing openedx-learning==0.32.0, we install openedx-core==0.34.1.
We update various class names, function names, docstrings, and comments to
represent the rename:
* We say "openedx-core" when referring to the whole repo or PyPI project
* or occasionally "Open edX Core" if we want it to look nice in the docs.
* We say "openedx_content" to refer to the Content API within openedx-core,
which is actually the thing we have been calling "Learning Core" all along.
* In snake-case code, it's `*_openedx_content_*`.
* In camel-case code, it's `*OpenedXContent*`
For consistency's sake we avoid anything else like oex_core, OeXCore,
OpenEdXCore, OexContent, openedx-content, OpenEdxContent, etc.
There should be no more references to learning_core, learning-core, Learning Core,
Learning-Core, LC, openedx-learning, openedx_learning, etc.
BREAKING CHANGE: for openedx-learning/openedx-core developers:
You may need to uninstall openedx-learning and re-install openedx-core
from your venv. If running tutor, you may need to un-mount openedx-learning,
rename the directory to openedx-core, re-mount it, and re-build.
The code APIs themselves are fully backwards-compatible.
Part of: https://github.com/openedx/openedx-core/issues/470
This is to fix an issue in the following common migration situation:
1. An existing course references content in a legacy content library.
2. The legacy content library is migrated to the new library system.
3. The user clicks on "Update reference" from the Randomized Content
Block in the course.
This action is supposed to update the children of the
LibraryContentBlock (usually ProblemBlocks) so that the "upstream"
attribute is set to point at the UsageKeys of the content in the new
libraries they were migrated to. What was happening instead was that the
upstream entries for these child blocks were left blank, breaking the
upstream/sync connection and making it so that the courses did not
receive any updates from the migrated libraries.
There were two issues:
1. get_forwarding_for_blocks() was being called with the child UsageKeys
in the course, when it should have been called with the v1 library
usage keys instead (since those are the things being forwarded).
2. We were checking that the target_key was a v2 Library key, but really
the upstream target_key is supposed to be a LibraryUsageLocatorV2,
i.e. the key of the specific piece of content, not the library it
ended up in.
Note on testing:
Although there were unit tests for the migration of legacy content
libraries, there were not any unit tests for the migration of legacy
library *blocks*.
This commit adds a minimal test, which would have caught the bug we're
fixing. It would be good to add more comprehensive testing unit testing
for this part of the migration flow.
---------
Co-authored-by: Kyle McCormick <kyle@axim.org>
Adds API to fetch all legacy library content blocks that are ready to be updated to use library v2 and convert to item banks.
Also adds API to update all the references via a user celery task and to fetch its status.
For legacy library_content references in courses, this PR:
- **Removes the spurious sync after updating a reference to a migrated
library**, so that users don't need to "update" their content _after_
updating their reference, _unless_ there were real content edits that
happened since they last synced. We do this by correctly associating a
DraftChangeLogRecord with the ModulestoreBlockSource migration artifact,
and then comparing that version information before offering a sync.
(related issue:
https://github.com/openedx/frontend-app-authoring/issues/2626).
- **Prompts users to update a reference to a migrated library with higher
priority than prompting them to sync legacy content updates for that
reference**, so that users don't end up needing to accept legacy content
updates in order to get a to a point where they can update to V2 content.
- **Ensures the library references in courses always follow the correct
migration,** as defined by the data `forwarded` fields in the data model,
which are populated based on the REST API spec and the stated product UI
requirements.
* For the migration itself, this PR:
- **Allows non-admins to migrate libraries**, fixing:
https://github.com/openedx/edx-platform/issues/37774
- **When triggered via the UI, ensures the migration uses nice title-based
target slugs instead of ugly source-hash-based slugs.** We've had this as an
option for a long time, but preserve_url_slugs defaulted to True instead of
False in the REST API serializer, so we weren't taking advantage of it.
- **Unifies logic between single-source and bulk migration**. These were
implement as two separate code paths, with drift in their implementations. In
particular, the collection update-vs-create-new logic was completely
different for single-souce vs. bulk.
- **When using the Skip or Update strategies for repeats, it consistently
follows mappings established by the latest successful migration** rather than
following mappings across arbitrary previous migrations.
- **We log unexpected exceptions more often**, although there is so much more
room for improvement here.
- **Adds more validation to the REST API** so that client mistakes more often
become 400s with validation messages rather than 500s.
For developers, this PR:
- Adds unit tests to the REST API
- Ensures that all migration business logic now goes through a general-purpose
Python API.
- Ensures that the data model (specifically `forwarded`, and
`change_log_record`) is now populated and respected.
- Adds more type annotations.
The child.save() call while migrating legacy library block to library version 2 fails with `InvalidScopeError` due to presence of `LmsFieldData` in` _bound_field_data` field. Removing this call does not seem to have any adverse affect.
* feat: show item bank ui for migrated legacy library content
* feat: migrate legacy content block to item bank block on view in studio
* fix: duplicate and copy issues
* refactor: migration location and add tests
* fix: lint issues
* fix: item bank and library content children view add button functionality
Newly added blocks from library in children view page of item bank block
and migrated library content block were not displayed automatically.
* fix: lint issues
* fix: lint issues
* feat: only migrate if same version of library is migrated
* refactor: migrate block on request
* fix: component reload on migration
* fix: tests
* refactor: comments and message wordings
* refactor: update alert text
* docs: add context
* fix: component links not being created on migrating legacy blocks
* fix: api docs and types
* refactor: use inheritance and specific parent method call
* fix: imports
* fix: api typing
* fix: upstream_version check
* refactor: rename variables
* refactor: parsing entity keys to usage_keys
This is a new XBlock that presents a random subset of its children. As of this commit, the block
can only be added as an Advanced component. For Sumac, we plan to enable it as part of the
Libraries Relaunch Beta, under the name "Problem Bank (Beta)"
The block does not care if its children are from V1 library, V2 library, or the course itself.
It shares the randomization logic with LegacyLibraryContentBlock. It is also fully backwards-compatible with LegacyLibraryContentBlock. So, once V1 libraries are migrated to V2 libraries (after Teak), we eventually
could point the `library_content` entry point at ItemBankBlock.
Part of: https://github.com/openedx/frontend-app-authoring/issues/1385
The V2 libraries project had a few past iterations which were never
launched. This commit cleans up pieces from those which we don't need
for the real Libraries Relaunch MVP in Sumac:
* Remove ENABLE_LIBRARY_AUTHORING_MICROFRONTEND,
LIBRARY_AUTHORING_FRONTEND_URL, and
REDIRECT_TO_LIBRARY_AUTHORING_MICROFRONTEND, all of which are obsolete
now that library authoring has been merged into
https://github.com/openedx/frontend-app-authoring.
More details on the new Content Libraries configuration settings are
here: https://github.com/openedx/frontend-app-authoring/issues/1334
* Remove dangling support for syncing V2 (learning core-backed) library
content using the LibraryContentBlock. This code was all based on an
older understanding of V2 Content Libraries, where the libraries were
smaller and versioned as a whole rather then versioned by-item.
Reference to V2 libraries will be done on a per-block basis using
the upstream/downstream system, described here:
https://github.com/openedx/edx-platform/blob/master/docs/decisions/0020-upstream-downstream.rst
It's important that we remove this support now so that OLX course
authors don't stuble upon it and use it, which would be buggy and
complicate future migrations.
* Remove the "mode" parameter from LibraryContentBlock. The only
supported mode was and is "random". We will not be adding any further
modes. Going forward for V2, we will have an ItemBank block for
randomizing items (regardless of source), which can be synthesized
with upstream referenced as described above. Existing
LibraryContentBlocks will be migrated.
* Finally, some renamings:
* LibraryContentBlock -> LegacyLibraryContentBlock
* LibraryToolsService -> LegacyLibraryToolsService
* LibrarySummary -> LegacyLibrarySummary
Module names and the old OLX tag (library_content) are unchanged.
Closes: https://github.com/openedx/frontend-app-authoring/issues/1115
* fix: hide view button when block is not configured
* fix: remove script for load timer if no children or library
* fix: remove print message
* fix: NoneType error is tests
Refactors and reworks the LibraryContentBlock so that its
sync-from-library operations are asynchronous and work with
V2 content libraries. This also required us to make
library_content block duplication asynchronous, as that
involves syncing from the source library.
For the sake of clarity, this PR includes two major method renames:
* update_children(...) -> sync_from_library(...)
* refresh_library(...) -> sync_from_library(upgrade_to_latest=True, ...)
an an XBlock HTTP handler rename:
/refresh_children -> /upgrade_and_sync
There are still a couple issues with import or duplication
of library_content blocks referencing V2 libraries other than
latest. These will be resolved in an upcoming PR.
Part of: https://openedx.atlassian.net/wiki/spaces/COMM/pages/3820617729/Spec+Memo+Content+Library+Authoring+Experience+V2
Follow-up work: https://github.com/openedx/edx-platform/issues/33640
Co-authored-by: Connor Haugh <chaugh@2u.com>
Co-authored-by: Eugene Dyudyunov <evgen.dyudyunov@raccoongang.com>
The Webpack configuration file for built-in XBlock JS used to be
generated at build time and git-ignored. It lived at
common/static/xmodule/webpack.xmodule.config.js. It was generated
because the JS that it referred to was also generated at build-time, and
the filenames of those JS modules were not static.
Now that its contents have been made entirely static [1], there is no
reason we need to continue generating this Webpack configuration file.
So, we check it into edx-platform under the name
./webpack.builtinblocks.config.js. We choose to put it in the repo's
root directory because the paths contained in the config file are
relative to the repo's root.
This allows us to behead both the xmodule/static_content.py
(`xmodule_assets`) script andthe `process_xmodule_assets` paver task, a
major step in removing the need for Python in the edx-platform asset
build [2]. It also allows us to delete the `HTMLSnippet` class and all
associated attributes, which were exclusively used by
xmodule/static_content.py..
We leave `xmodule_assets` and `process_xmodule_assets` in as stubs for
now in order to avoid breaking external code (like Tutor) which calls
Paver; the entire pavelib/assets.py function will be eventually removed
soon anyway [3]. Further, to avoid extraneous refactoring, we keep one
method of `HTMLSnippet` around on a few of its former subclasses:
`get_html`. This method was originally part of the XModule framework;
now, it is left over on a few classes as a simple internal helper
method.
References:
1. https://github.com/openedx/edx-platform/pull/32480
2. https://github.com/openedx/edx-platform/issues/31800
3. https://github.com/openedx/edx-platform/issues/31895
Part of: https://github.com/openedx/edx-platform/issues/32481
In ~Palm and earlier, all built-in XBlock Sass was included into LMS and CMS
styles before being compiled. The generated CSS was coupled together with
broader LMS/CMS CSS. This means that comprehensive themes have been able to
modify built-in XBlock appearance by setting certain Sass variables. We say that
built-in XBlock Sass was, and is expected to be, "theme-aware".
Shortly after Palm, we decoupled XBlock Sass from LMS and CMS Sass [1]. Each
built-in block's Sass is now compiled into two separate CSS targets, one for
block editing and one for block display. The CSS, now located at
`common/static/css/xmodule`, is injected into the running Webpack context with
the new `XModuleWebpackLoader`. Built-in XBlocks already used
`add_webpack_to_fragment` in order to add JS Webpack bundles to their view
fragments, so when CSS was added to Webpack, it Just Worked.
This unlocked a slieu of simplifications for static asset processing [2];
however, it accidentally made XBlock Sass theme-*unaware*, or perhaps
theme-confused, since the CSS was targeted at `common/static/css/xmodule`
regardless of the theme. The result of this is that **built-in XBlock views will
use CSS based on the Sass variables _last theme to be compiled._** Sass
variables are only used in a handful of places in XBlocks, so the bug is subtle,
but it is there for those running off of master. For example, using edX.org's
theme on master, we can see that there is a default blue underline in the Studio
sequence nav [3]. With this bugfix, it becomes the standard edX.org
greenish-black [4].
This commit makes several changes, firstly to fix the bug, and secondly to leave
ourselves with a more comprehensible asset setup in the `xmodule/` directory.
* We remove the `XModuleWebpackLoader`, thus taking built-in XBlock Sass back
out of Webpack.
* We compile XBlock Sass not to `common/static/css/xmodule`, but to:
* `[lms|cms]/static/css` for the default theme, and
* `<THEME_ROOT>/[lms|cms]/static/css`, for any custom theme.
This is where the comprehensive theming system expects to find themable
assets. Unfortunately, this does mean that the Sass is compiled twice, both
for LMS and CMS. We would have liked to compile it once to somewhere in the
`common/`, but comprehensive theming does not consider `common/` assets to be
themable.
* We split `add_webpack_to_fragment` into two more specialized functions:
* `add_webpack_js_to_fragment` , for adding *just* JS from a Webpack bundle,
and
* `add_sass_to_fragment`, for adding static links to CSS compiled themable
Sass (not Webpack). Both these functions are moved to a new module
`xmodule/util/builtin_assets.py`, since the original module
(`xmodule/util/xmodule_django.py`) didn't make a ton of sense.
* In an orthogonal bugfix, we merge Sass `CourseInfoBlock`, `StaticTabBlock`,
`AboutBlock` into the `HtmlBlock` Sass files. The first three were never used,
as their styling was handled by `HtmlBlock` (their shared parent class).
* As a refactoring, we change Webpack bundle names and Sass module names to be
less misleading:
* student_view, public_view, and author_view: was `<Name>BlockPreview`, is now
`<Name>BlockDisplay`.
* studio_view: was `<Name>BlockStudio`, is now `<Name>BlockEditor`.
* As a refactoring, we move the contents of `xmodule/static` into the existing
`xmodule/assets` directory, and adopt its simper structure. We now have:
* `xmodule/assets/*.scss`: Top-level compiled Sass modules. These could be
collapsed away in a future refactoring.
* `xmodule/assets/<blocktype>/*`: Resources for each block, including both JS
modules and Sass includes (underscore-prefixed so that they aren't
compiled). This structure maps closely with what externally-defined XBlocks
do.
* `xmodule/js` still exists, but it will soon be folded into the
`xmodule/assets`.
* We add a new README [4] to explain the new structure, and also update a
docstring in `openedx/lib/xblock/utils` which had fallen out of date with
reality.
* Side note: We avoid the term "XModule" in all of this, because that's
(thankfully) become a much less useful/accurate way to describe these blocks.
Instead, we say "built-in XBlocks".
Refs:
1. https://github.com/openedx/edx-platform/pull/32018
2. https://github.com/openedx/edx-platform/issues/32292
3. https://github.com/openedx/edx-platform/assets/3628148/8b44545d-0f71-4357-9385-69d6e1cca86f
4. https://github.com/openedx/edx-platform/assets/3628148/d0b7b309-b8a4-4697-920a-8a520e903e06
5. https://github.com/openedx/edx-platform/tree/master/xmodule/assets#readme
Part of: https://github.com/openedx/edx-platform/issues/32292
`xmodule_assets` generated a series of SCSS "entrypoint"
files, where each entrypoint file imported from the
SCSS "sources" in xmodule/css.
This process was more complicated up until very
recently (see PRs in issue linked below for more
context). Now that the process is simpler, though,
there is no reason to generate the SCSS entrypoints;
we can just commit them to the repository instead!
So, we go from this:
# GENERATED: SCSS entrypoints files for CMS
common/static/xmodule/descriptors:
AboutBlockStudio.scss
AnnotatableBlockStudio.scss
...
# GENERATED: SCSS entrypoints files for LMS
common/static/xmodule/modules:
AboutBlockPreview.scss
AnnotatableBlockPreview.scss
...
# VERSION CONTROLLED: SCSS source files
xmodule/css:
annotatable/...
capa/...
...
to this:
# VERSION CONTROLLED: All XModule SCSS
xmodule/static/sass:
# Source files
include:
annotatable/...
capa/...
...
# CMS entrypoint files
cms:
AboutBlockStudio.scss
AnnotatableBlockStudio.scss
...
# LMS source files
lms:
AboutBlockPreview.scss
AnnotatableBlockPreview.scss
...
Also, we are able to remove all SCSS-related logic from the
`xmodule_assets` script and from the `HTMLSnippet` class.
XModule JS assets still need processing, but we will address
those in a separate series of PRs.
Part of: https://github.com/openedx/edx-platform/issues/32292
For the XBlocks types that use legacy XModule-style assets (specifically, those that
inherit from `HTMLSnippet`), this is small refactor that brings them a bit closer to being like
standard XBlocks.
Given these class attributes:
class SomeXModuleLikeBlock(..., HTMLSnippet, ...):
...
studio_view_css = { ... }
preview_view_css = { ... }
studio_view_js = { ... }
preview_view_js = { ... }
...
we make it so their values are *paths to the resources*
rather than *the actual content of the resources*.
This is a no-op change, but it'll enable future XModule
asset refactorings which require us to operate on asset
paths rather than contents.
Part of: https://github.com/openedx/edx-platform/issues/32292