UCL-INGI / INGInious

INGInious is a secure and automated exercises assessment platform using your own tests, also providing a pluggable interface with your existing LMS.
http://www.inginious.org
Other
202 stars 139 forks source link

[frontend] Changing accessibility and registration data structure #985

Open AlexandreDoneux opened 9 months ago

AlexandreDoneux commented 9 months ago

This pull request has as goal the change of accessibility and registration data structure in in the code as well as for the storage in DB and yaml files. The objective is also to store the dates as ISO dates in the database and yaml files. This concerns course accessibility, course registration period and task accessibility.

These accessibilities where previously a single value (accessible/registration for courses and accessibility for tasks) and were structured as follows :

We will now only use the dates and use minimal and maximal dates to define the cases where the the courses and tasks are always or never accessible. Those minimal and maximal dates are also used in a custom accessibility when certain dates are not defined. You can for example only define a start date in the form and INGInious will then assume there is no end date to the task and it will always be accessible after the given start date.

TO DO :

AlexandreDoneux commented 8 months ago

Rebase on cf8141c0ad1dace81ea936a07de80d4358e7314b.

AlexandreDoneux commented 8 months ago

Rebase on 1095603.

AlexandreDoneux commented 6 months ago

Rebase on 4de3a172.

AlexandreDoneux commented 4 months ago

Some code might need to be rewritten in settings.py :

https://github.com/UCL-INGI/INGInious/blob/2306071d8b71701cfa2187a9afd03067558c60ec/inginious/frontend/pages/course_admin/settings.py#L24-L51

The data of the course is accessed through the course_factory : https://github.com/UCL-INGI/INGInious/blob/2306071d8b71701cfa2187a9afd03067558c60ec/inginious/frontend/pages/course_admin/settings.py#L32

However, the course is retrieved at the start of the method. We could rewrite a bit to use the course instead of self.course_factory.get_course_descriptor_content(courseid).

There is also the use of a protected member to use the min and max dates instead of datetime.min and datetime.max.replace(microsecond=0). A method on course retrieving the content would allow us acces to those values.

AlexandreDoneux commented 4 months ago

Keeping support for the legacy access format and changing the format on saving the settings of a course or task is not as easy as we thought for the moment.

As you suggested we can add support in the AccessibleTime init. For a course accessibility and registration period it only needs some tweaks. However task accessibility is more difficult as the accessibility of a task for the edit pages (taskset template and course tasks) is not passed through AccessibleTime.

For example in toc.py, task_config is passed to the jinja template and contains the data of the different tasks.

    def render_edit(self, template_helper, element, task_data, task_errors):
        """ Returns the formatted task list edition form """
        config_fields = {
            "closed": SectionConfigItem(_("Closed by default"), "checkbox", False),
            "hidden_if_empty": SectionConfigItem(_("Hidden if empty"),"checkbox",False)
        }

        taskset = element if isinstance(element, inginious.frontend.tasksets.Taskset) else None
        course = element if isinstance(element, inginious.frontend.courses.Course) else None
        task_config = dict_data_datetimes_to_str(self._task_config)

        return template_helper.render("task_dispensers_admin/toc.html", element=element, course=course, taskset=taskset,
                                      dispenser_structure=self._toc, dispenser_config=task_config, tasks=task_data,
                                      task_errors=task_errors, config_fields=config_fields)

However, when tracing back from where the data comes from we can see it is retrieved from the database here, in course_factory.py, and is never processed by AccessibleTime :

    def get_course_descriptor_content(self, courseid):
        return self._database.courses.find_one({"_id": courseid})

Edit: I changed the access structure change to be applied when importing legacy tasks. The has_legacy_tasks() method has been modified to detect if tasks have the old access structure. The legacy tasks import button will be displayed if it's the case (in task_list.html and template.html).

AlexandreDoneux commented 4 months ago

Rebase on b3a40952c36933b4741e61ddac83cfe9e2c1083a.