Skip to content

Conversation

@owi92
Copy link
Member

@owi92 owi92 commented Oct 17, 2025

We already harvest playlist data from Opencast and it has been possible to add playlist blocks pages in Tobira for a while.
This adds the necessary API and the following pages for playlist management:

  • My playlists (list all playlists the user has write access for)
  • Playlist details (includes delete button, playlist metadata and interfaces to edit title, description and playlist content)
  • Playlist access control (to edit playlist ACL)
  • Create playlist (with interfaces for adding title, description, entries and ACL)

Like series and events, any C(R)UD operation will call the respective external Opencast API. When the response is OK, the operation is also performed in Tobira's DB, so users do not have to wait for the next sync in order to see results.

Right now all most dummy users are allowed to create playlists, but this is generally tied to a dedicated role, which can be configured.

Closes #1312

Can be reviewed commit by commit

@github-actions github-actions bot added the status:conflicts This PR has conflicts that need to be resolved label Oct 17, 2025
@github-actions

This comment was marked as resolved.

@github-actions github-actions bot removed the status:conflicts This PR has conflicts that need to be resolved label Oct 17, 2025
@github-actions github-actions bot temporarily deployed to test-deployment-pr1588 October 17, 2025 17:08 Destroyed
@owi92 owi92 added the changelog:user User facing changes label Oct 20, 2025
@github-actions github-actions bot temporarily deployed to test-deployment-pr1588 October 20, 2025 15:05 Destroyed
@github-actions github-actions bot temporarily deployed to test-deployment-pr1588 October 20, 2025 16:15 Destroyed
Copy link
Member

@LukasKalbertodt LukasKalbertodt left a comment

Choose a reason for hiding this comment

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

Backend review: I did not yet test it or look at any frontend code.

@github-actions

This comment has been minimized.

@github-actions github-actions bot temporarily deployed to test-deployment-pr1588 November 24, 2025 13:25 Destroyed
@github-actions github-actions bot added the status:conflicts This PR has conflicts that need to be resolved label Nov 26, 2025
@github-actions

This comment was marked as resolved.

Works the same as creating events or series in
the sense that we send the request to Opencast
and insert the playlist in our DB without waiting
for sync.
Authorization will be added in a later commit.
Unlike series/video metadata and acl updating,
this uses a single endpoint for both (which is how
it is done in Opencast). That means that besides the
playlist id, each parameter is optional and will only
be updated when it is `Some`.

Calling this API will update the Playlist in Tobira's
Database without waiting for sync.
This utilizes the generic `delete_opencast_thing`
endpoint that is also used for series and events.
The corresponding playlist endpoint in Opencast
however works a little different: There are no
workflows or other magic background operations
involved. When we get a 200 response, it simply
means that the playlist has been deleted in Opencast.

This in turn lets us avoid having to create yet
another table/view that tracks "deleted" playlists
(which we have for series and events). We can
simply go ahead and delete the playlist directly
in our DB, no need for a `pending` limbo state and
no fear of sync concflicts.
Something something consistent naming.
**Logic of mutations remains untouched**

Since `model/playlist` is a folder rather than a
single file and it already has a `mod.rs` file, I
think it's nicer to also have the mutations in a
separate file and not cram everything in `mod.rs`.
I don't know about best practices for this,
and `series` and `events` do do everything in one
file. I personally prefer separation of concerns
(at least in this case).
@github-actions github-actions bot removed the status:conflicts This PR has conflicts that need to be resolved label Nov 28, 2025
@github-actions

This comment has been minimized.

@github-actions github-actions bot temporarily deployed to test-deployment-pr1588 November 28, 2025 13:17 Destroyed
@github-actions

This comment has been minimized.

@github-actions github-actions bot temporarily deployed to test-deployment-pr1588 November 28, 2025 14:01 Destroyed
@owi92
Copy link
Member Author

owi92 commented Nov 28, 2025

You can ignore the above warning. Mounting series still works with that change.

owi92 added 2 commits December 1, 2025 11:43
This is the table overview analogous to
"my videos" and "my series". It is missing
some stuff like thumbnails for now, that will
be added in a later commit.
These are basically just the same
as series thumbnail stacks with a
different query, reusing most of
the other relevant code.
owi92 added 10 commits December 1, 2025 12:15
I didn't do this before because I wasn't
sure what to do about the playlist's state/status.
But as far as I can tell, playlists do not need
that, since their API works a little different.
Creating, updating and deleting will either succeed
or fail, and we get that result as an immediate
response from Opencast. So when it fails, we just
don't update it. This means that it should always
be in sync.
This is mainly in preparation for the next
few commits that will add the remaining
management routes.

This commit adds the shared route building function,
the necessary graphQL query and the navigation component
for single playlists.
For now this has only the share menu
and the delete button and function.
I'd rather add the mutations and interfaces
one by one to keep these commits in a reasonable
size.
This had to adjust the way metadata
is passed to the API. Instead of having
both title and description optional, it
now uses the `BasicMetadata` struct again,
which necessary for the frontend component
and where the title is required.

That component is used for both creating and
editing metadata, and while the title is
technically optional when editing, it is
mandatory for creation.
This adds the interface to add and remove
videos to/from playlists. The backend and
API needed a slight adjustment, because
OC needs the `opencast_id` of the entries.
We could either pass them from frontend
(which would need some query adjustments)
or load them in backend (which is what I
do here now).
Previously they just weren't shown, and worse:
Any entries that are unknown to Tobira were
just dropped and lost upon using the `update`
endpoint.

This commit adds (1): a note to playlist editing
with the count of unknown videos, and
(2): some code in backend that adds these
entries back to the mutation.
Caveat: They will get new ids (the `entry_id`,
which is given by opencast, NOT the `opencast_id`,
that remains the same of course). But I don't think
that is an issue.
Also removed some french translations
related to series and video ACL editing.
The translator also supplied version that
are count agnostic, which I believe we should
prefer whenever possible.
Again, mostly copied from already existing
series stuff, so this could probably be
generalized.
On the other hand, I will be adding the option
to choose initial entries as a feature for
playlist creation in the next commit,
so a generalization might not be worth
the added complexity.
@github-actions

This comment has been minimized.

@github-actions github-actions bot temporarily deployed to test-deployment-pr1588 December 1, 2025 17:31 Destroyed
owi92 added 9 commits December 2, 2025 00:14
It is now possible to set initial entries
when creating a playlist. I reused some
code from `EditVideoList` and factor out
some code to prevent duplication.
This has a small side effect: When adding
or removing videos with that component (before
submitting the form), the event count
above the interface will now update at the
same time and reflect the number of events
that is currently displayed. Previously, this
was using the count from the DB entry and
was only updated when the user submitted
the form.

Another thing: I wasn't sure whether to
integrate the events thing to react hook
form. State management is easier when it's
not integrated, and it is not necessary to
do any form validation on the entries field
(since that can also be left empty).
On the other hand, integration would be nice
at the very least for consistency.
Users shouldn't need write access
for events they want to remove from
their playlist.
So it's not just typed as String everywhere.
Still behaves like a String though.

Pretty sure this commit doesn't catch all occurences,
since it's not always called `opencast_id` or `oc_id`.
Sometimes it's just `id` or something else.
This should prevent unnecessary errors in case
of missing/not loaded thumbnails. Instead we
just show placeholders.
Unfortunately, GraphQL doesn't know that an OpencastId
is just a String in disguise, and we can't tell it
either. So to keep things backwards compatible with
Opencast (which also uses these `by_opencast_id`
queries), this has to stick with the explicit `String`
type.

Note on playlists: Opencast and the Admin UI don't have
any Playlist features yet that could talk with the
respective endpoint, but I expect this will come in the
future. While we could in theory say "use our special
type and deal with it", I think it's nicer if it can
mirror the existing series and event endpoints.
@github-actions
Copy link

github-actions bot commented Dec 1, 2025

🚨🚨🚨 This PR changes APIs used by the Opencast Admin UI integration 🚨🚨🚨

Detected the following changes (1) between schemas:

✖  Input field NewSeries.opencastId changed type from String! to OpencastId!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

changelog:user User facing changes

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add "My playlists"

2 participants