Skip to content

ESoCC: Add a channel to the community library once its submission has been approved #5171

@AlexVelezLl

Description

@AlexVelezLl

This issue is not open for contribution. Visit Contributing guidelines to learn about the contributing process and how to find suitable issues.

Requires #5170

Overview

As part of this issue we will finally transfer a channel to be part of the Community Library. From the technical implementation perspective, Community Library channels will be identified as channel records in the kolibri_public app models where the public field is set to false. This means that the approved channel version will be mapped to a channel within the kolibri_public application models.

Prerrequisites

  • Understand the Studio channel publishing workflow.
  • Understand how channel databases are stored in Studio.
  • Understand how a channel is made public.
  • Understand how the channel changes mechanism works.

Technical requirements

Upon approval of a submission, a new asynchronous task should be enqueued to map the approved channel version's database to the kolibri_public models.

To handle this new asynchronous task, we will leverage our existing changes architecture and integrate this process as a new channel change type, named ADDED_TO_COMMUNITY_LIBRARY.

  1. We will add a new ADDED_TO_COMMUNITY_LIBRARY change type in the sync/constants.py file, and include this new change in the ALL_CHANGES array.
  2. This new ADDED_TO_COMMUNITY_LIBRARY change will be enqueued immediately after an admin has approved a submission in the resolution action in the Community Library Submission Viewset. To enqueue this task, we can:
    • Create a new generate_add_to_community_library_event function in viewsets/sync/utils.py that receives the key, the channel_version, and an optional categories and countries arguments. These optional arguments will then be populated with data from the approved submission.
    • Within the submission viewset action, we can then create a new ADDED_TO_COMMUNITY_LIBRARY change using the Change.create_change method where the change will be the one returned from the generate_add_to_community_library_event function, and its author will be set to the user who approved the submission.
    • Finally we will call the apply_channel_changes_task.fetch_or_enqueue method that will enqueue the apply_channel_changes_task for this change to be applied. In the publish channel api you can see an example of how to create a new event and subsequently enqueue this task.
  3. This new change will just be allowed to be created on the server side. So adding a new ADDED_TO_COMMUNITY_LIBRARY change through the sync viewset should not be allowed.
    • We can achieve this by adding a new SERVER_ONLY_CHANGES constant in the viewsets/sync/constants.py file. Any change included in SERVER_ONLY_CHANGES arriving via the sync endpoint will then be rejected.
  4. Now, to support the new metadata introduced by CommunityLibrarySubmission. We will need to create two new fields in the ChannelMetadata model of the kolibri_public app: categories and countries.
    • To enable filtering by categories, we will need to add bitmap fields to the ChannelMetadata model. However, this will be part of a subsequent issue; let's not focus on it for now.
  5. In the ChannelViewset we will add a new add_to_community_library_from_changes method that will call an add_to_community_library method (description of this method below) for each change. Then we will map the new ADDED_TO_COMMUNITY_LIBRARY change to the add_to_community_library_from_changes method in the apply_changes function event handlers. With this, we will be able to apply ADDED_TO_COMMUNITY_LIBRARY changes.
  6. The add_to_community_library method should receive the channel ID, the channel version to be added to the Community Library, and the categories and countries that will be added to the community library, the categories and the countries that will be added to the kolibri_public ChannelMetadata instance.
    • To export the channel to the kolibri_public models, we will reuse the logic that we have in the _export_channel method of the export_channels_to_kolibri_public command.
    • To reuse this _export_channel method across the command and the sync changes task, we will move this logic to a new export_channel_to_kolibri_public file in the kolibri_public/utils folder, which will define the export_channel_to_kolibri_public function.
    • We should modify this export_channel_to_kolibri_public function to accommodate the new requirements for adding a channel to the Community Library. Specifically, this function should now receive channel_id as a required argument, and channel_version=None, public=True, categories=None, and countries=None as optional arguments. Subsequently, we should modify the ChannelMapper class to receive all these new values as optional arguments in its constructor method.
    • Within the ChannelMapper's run method we call the set_channel_metadata_fields util function to annotate additional metadata that this channel will have in the ChannelMetadata model. As we are now introducing categories and countries to this model, we should modify the set_channel_metadata_fields function to :
      • Add the calculation of the categories field taking into account both: the included channel categories (i.e. querying the categories of all channel contentnodes, similar to what we do for included languages), and the categories obtained from the submission. Included categories can also be obtained from the published_data content curation channel field, but this field will not be available for older channels, so lets replicate what we do for the included_languages field.
      • Add the countries list to the channel.
    • The export_channels_to_kolibri_public command should use this utility function in its handler method, calling it just passing the channel_id parameter.
    • The add_to_community_library channel viewset method should call this utility function with all optional parameters set.
  7. Finally, unit tests should be added to cover at least the following scenarios:
    • After a submission has been approved, a new change event is created in the changes model, and the apply channel changes task has been enqueued.
    • If a submission is rejected, no new change event is created in the changes model.
    • Test that the new ADDED_TO_COMMUNITY_LIBRARY is not applied if we send it through the sync endpoint.
    • Test that the channel apply changes task is instantiating the ChannelMapper object with the correct arguments, and its calling the channelMapper.run afterwards.
    • Test that a exception is thrown if we try adding a ADDED_TO_COMMUNITY_LIBRARY change with a non-existing channel version database.
    • Add new tests to the ChannelMapper test case to test that the categories field is being set correctly to the kolibri_public channel.
    • Add new tests to the ChannelMapper test case to test that the countries field is being set correctly to the kolibri_public channel.

Acceptance criteria

  • New ADDED_TO_COMMUNITY_LIBRARY change is enqueued after the submission was approved.
  • New categories and countries fields have been added to the kolibri_public's ChannelMetadata model.
  • add_to_community_library_from_changes method is added to the channel viewset and mapped to the apply changes event handlers.
  • A new export_channel_to_kolibri_public function is created to support the apply changes task, and the existing export_channels_to_kolibri_public command.
  • The specific channel version records are present in the kolibri_public models after the task was run.
  • Described unit tests have been added.

Metadata

Metadata

Assignees

Labels

P0 - criticalPriority: Release blocker or regression

Type

Projects

No projects

Relationships

None yet

Development

No branches or pull requests

Issue actions