Set default advanced modules list for courses

Hello everyone,

I am trying to setup a default list of advanced modules in order to save course creators the hustle of setting the list themselves manually every time they create a course.

I have taken a look to the following relevant topics:

Yet none of them have posted anything about the plugin that will achieve this or at least how it should be structured.
I have managed to create the following plugin:

from tutor import hooks

# --- 1. Set default ADVANCED_PROBLEM_TYPES ---
ADVANCED_MODULES = [
    "edx_sga",
    "lti",
    "scorm",
    "library_content",
    "annotatable",
    "poll",
    "survey",
    "h5pxblock",
    "pdf"
]

advanced_problem_types = "\n".join(
    f"    {{'component': '{component}', 'boilerplate_name': None}}," for component in ADVANCED_MODULES
)

hooks.Filters.ENV_PATCHES.add_item(
    (
        "openedx-cms-common-settings",
        f"""
ADVANCED_PROBLEM_TYPES = [
{advanced_problem_types}
]
"""
    )
)

# --- 2. Add extra pip requirements ---
EXTRA_PIP_REQUIREMENTS = [
    "h5p-xblock",
    "git+https://github.com/blazejwiecha/xblock-pdf.git"
]

pip_lines = "\n".join(f"RUN pip install {req}" for req in EXTRA_PIP_REQUIREMENTS)

hooks.Filters.ENV_PATCHES.add_item(
    (
        "openedx-dockerfile-post-python-requirements",
        pip_lines
    )
)

Upon rebuilding the openedx image, I can verify the insertion of the patched setting in the relevant files (assuming common.py should not include the patched setting):

app@43dfbb27f64c:~/edx-platform/cms/envs$ grep -rnw './' -e 'ADVANCED_PROBLEM_TYPES' -A 10
./common.py:2050:ADVANCED_PROBLEM_TYPES = [
./common.py-2051-    {
./common.py-2052-        'component': 'drag-and-drop-v2',
./common.py-2053-        'boilerplate_name': None
./common.py-2054-    },
./common.py-2055-    {
./common.py-2056-        'component': 'staffgradedxblock',
./common.py-2057-        'boilerplate_name': None
./common.py-2058-    }
./common.py-2059-]
./common.py-2060-
grep: ./__pycache__/common.cpython-311.pyc: binary file matches
--
./tutor/production.py:285:ADVANCED_PROBLEM_TYPES = [
./tutor/production.py-286-    {'component': 'edx_sga', 'boilerplate_name': None},
./tutor/production.py-287-    {'component': 'lti', 'boilerplate_name': None},
./tutor/production.py-288-    {'component': 'scorm', 'boilerplate_name': None},
./tutor/production.py-289-    {'component': 'library_content', 'boilerplate_name': None},
./tutor/production.py-290-    {'component': 'annotatable', 'boilerplate_name': None},
./tutor/production.py-291-    {'component': 'poll', 'boilerplate_name': None},
./tutor/production.py-292-    {'component': 'survey', 'boilerplate_name': None},
./tutor/production.py-293-    {'component': 'h5pxblock', 'boilerplate_name': None},
./tutor/production.py-294-    {'component': 'pdf', 'boilerplate_name': None},
./tutor/production.py-295-]
--
./tutor/development.py:285:ADVANCED_PROBLEM_TYPES = [
./tutor/development.py-286-    {'component': 'edx_sga', 'boilerplate_name': None},
./tutor/development.py-287-    {'component': 'lti', 'boilerplate_name': None},
./tutor/development.py-288-    {'component': 'scorm', 'boilerplate_name': None},
./tutor/development.py-289-    {'component': 'library_content', 'boilerplate_name': None},
./tutor/development.py-290-    {'component': 'annotatable', 'boilerplate_name': None},
./tutor/development.py-291-    {'component': 'poll', 'boilerplate_name': None},
./tutor/development.py-292-    {'component': 'survey', 'boilerplate_name': None},
./tutor/development.py-293-    {'component': 'h5pxblock', 'boilerplate_name': None},
./tutor/development.py-294-    {'component': 'pdf', 'boilerplate_name': None},
./tutor/development.py-295-]

Yet whenever I create a new course the "Advanced’ option in the insert component area does not show up and the advanced module list in the advanced settings is empty.

Any help on achieving this would be greatly appreciated.

tutor, version 19.0.2

@Maksim_Sokolskiy would someone on your team who worked on the visual configuration for xblocks in Teak maybe have an idea of how to do this on Sumac?

Hi @Retr0 @sarina ,
It’s not currently possible in Open edX/Tutor to automatically have XBlocks appear in the Advanced section of the unit right when a new course is created.
The ADVANCED_PROBLEM_TYPES.append(…) setting you’ve patched doesn’t control that list in Studio’s “Advanced” component — it only affects the internal Advanced section inside the problem component of unit.It adds the xblock into that list of all courses
Up until the most recent releases (including Sumac), there’s no config, hook, or plugin in Tutor that will auto-populate the Advanced component list for new courses.

1 Like

did you find this solution?

Hello, if you read the reply right above yours you will see that it is not possible as specified by Abdul.

2 Likes

hello @Abdul_Muqadim this is my patch. But in the advanced problem it is not appear. Whats wrong?

```
hooks.Filters.ENV_PATCHES.add_item((

"openedx-cms-common-settings",

“”"

ADVANCED_PROBLEM_TYPES.append({

'component': 'negativemarkingxblock',

'boilerplate_name': None

})

“”"

))
```

Anyway.. for set advanced modules list, I can suggest to doing this. The goal is ensure our expected xblock will be listed in advanced module.

# signals.py
from django.db.models.signals import post_save
from django.dispatch import receiver
from openedx.core.djangoapps.content.course_overviews.models import CourseOverview
from xmodule.modulestore.django import modulestore

@receiver(post_save, sender=CourseOverview)
def add_negativemarking_to_new_courses(sender, instance, created, **kwargs):
    """
    Ensure every new course gets negativemarking XBlock in advanced_modules.
    """
    if created:
        store = modulestore()
        with store.bulk_operations(instance.id):
            course = store.get_course(instance.id)
            if 'negativemarking' not in course.advanced_modules:
                course.advanced_modules.append('negativemarking')
                store.update_item(course, course.published_by)

I create also

# apps.py
from django.apps import AppConfig

class NegativeMarkingXBlockConfig(AppConfig):
    name = "negativemarking"

    def ready(self):
        # This ensures signals.py is imported at Django startup
        import negativemarking.signals

and from setup.py we can add this entrypoint

entry_points={
        ... ,
        "django.apps": [
            "negativemarkingxblock = negativemarkingxblock.apps.NegativeMarkingXBlockConfig",
        ],

Hi,

Regarding adding your XBlock to the advanced problem types, you can do it with the following patch:

from tutor import hooks

hooks.Filters.ENV_PATCHES.add_item(
    (
        "openedx-cms-common-settings",
        """
# Append additional advanced problem types
ADVANCED_PROBLEM_TYPES.append(
    {
        'component': 'h5pxblock',
        'boilerplate_name': None
    }
)
        """,
    )
)

Also, don’t forget to add your XBlock in the OPENEDX_EXTRA_PIP_REQUIREMENTS setting as well.I was abel to add it through these steps

1 Like