INGInious
INGInious copied to clipboard
[frontend] Changing accessibility and registration data structure
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 :
- a true when always accessible
- a false when never accessible
- a concatenated string containing all the dates separated by a "/"
(ex:
"2023-12-06 09:00:00/2023-12-13 09:00:00/2023-12-13 09:00:00"
)
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 :
- [x] Change datastructure in AccessibleTime class and it's usage
- [X] adapt AccessibleTime
- [X] adapt usage basic INGInious app
- [x] adapt usage in contest plugin
- [x] Change AccessibleTime default parameters and it's use
- [X] Changing init structure
- [X] courses
- [X] tasks
- [x] Adapting forms to new structure
- [X] Transforming datetime objects into strings
- [X] course settings
- [X] task accessibility edit
- [x] task accessibility grouped edit
- [X] Dates as ISODate() objects in MongoDB
- [X] Storing (transform in datetime objects before storing in DB)
- [X] Retrieving
- [X] Correctly handling min and max dates
- [X] Storing dates as timestamps objects in yaml files
- [X] Storing
- [x] Retrieving
- [x] Correctly handling min and max dates
- [x] Automatically change structure in DB and yaml files when switching version
- [x] DB
- ~~[ ] In already existing collections~~ => not needed
- [x] During "courses" collection init in legacy courses import
- [x] During legacy task import in task list edit
- [x] YAML files
- [x] During legacy task import in course template
- [x] DB
Rebase on cf8141c0ad1dace81ea936a07de80d4358e7314b.
Rebase on 1095603.
Rebase on 4de3a172.
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.
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).
Rebase on b3a40952c36933b4741e61ddac83cfe9e2c1083a.