Static Asset support in Libraries

High level requirement

High level: We want to support static assets in content libraries.

Less obvious implication: We need to support copying those assets back and forth when copy/pasting between courses and libraries, and when using library content in a course.

Strategy

Overall strategy for managing library <-> course content sharing is that a course gets a copy of the content, with some back-pointer.

So a Component is written in Libraries (backed by Learning Core models), but when it's used in a Course, we make a copy of it and add a bit of OLX to say, "this is where my upstream version is". The idea is that at any point you should be able to take the export of a Course that uses library content, import that Course into a new instance, and everything should still work from the student's point of view (even the backing library doesn't exist any longer, and you can't get new versions).

Static assets take the same philosophy.

So we're copying it into the contentstore for course assets.

Big differences in how Libraries (Learning Core) and Courses (Contentstore) treat static assets are:

  • Library assets are local to a Component. Course assets have a shared Files and Uploads across all Components.

  • Library asset->component relations are explicit, in that there's a database model for it. Course asset->component relationships are interpreted via scanning the content.

  • Library assets are versioned along with the Component, i.e. they obey draft/publish semantics. Course assets are not versioned.

  • Course assets have AssetKeys, Library assets are just relative paths against a particular version of a Component.

Current work in flight

I have a PR in flight that implements static assets on the libraries side: https://github.com/openedx/edx-platform/pull/35557

It requires three other PRs, two of which have merged:

 

The overall strategy:

  • Copy content into the clipboard (content_staging), which will hold the file data and "normalized" name for the asset.

  • When pasting into a course from a library, create the assets in a subdirectory based on the UsageKey.

Longer Term Plans

As a long term thing, we want to serve static assets in a very different way from Learning Core, as outlined in this ADR. But that's out of scope for Sumac. Because we’re copying everything to contentstore anyway, Learning Core backed assets are never getting served directly to students (there’s actually an auth check to make sure people have read rights to the library in question).

Work to be picked up

The one case this PR still doesn't handle is if someone copies from a library into a course, and then copies that thing they just pasted into the course and pastes it again. (i.e. it doesn't know how to convert a path to a course asset in a subdirectory back into the abstract "normal" form to put on the clipboard). I should have this addressed soon.

This PR is dependent on changes to frontend-app-authoring (the last PR listed up there). There are two kinds of changes:

  1. Modify the Files and Uploads UI in various places to show full paths instead of just the file name. (discussions here and here).

  2. Disables the transformation of static URL references in the WYSIWG text editor so that it doesn't mangle the OLX file references.

The work that will be remaining even when those two PRs merge:

  1. The text editor will need to know how to transform URLs for library content (issue).

  2. There is no current support for adding or deleting images in the text editor from the library–you have to use a management command or copy content from a course. That needs to be implemented on both the editor and server side. (my edx-platform PR does the read side of thing)

  3. There's no general way to associate non-image static asset with a Component generally. @Jenna Makowski might have thoughts on what this could look like, e.g. for a capa problem (maybe another tab in the right-hand nav that lets you add files?)