diff --git a/addons/website_slides/controllers/main.py b/addons/website_slides/controllers/main.py index b271560a6b4..8691313dc88 100644 --- a/addons/website_slides/controllers/main.py +++ b/addons/website_slides/controllers/main.py @@ -1024,19 +1024,18 @@ class WebsiteSlides(WebsiteProfile): # minutes to hours conversion values['completion_time'] = int(post['duration']) / 60 + category_id = False # handle creation of new categories on the fly if post.get('category_id'): - if post['category_id'][0] == 0: + category_id = post['category_id'][0] + if category_id == 0: category = request.env['slide.slide'].create(self._get_new_slide_category_values(channel, post['category_id'][1]['name'])) - values['category_id'] = category.id values['sequence'] = category.sequence + 1 + category_id = category.id else: values.update({ - 'category_id': post['category_id'][0], 'sequence': request.env['slide.slide'].browse(post['category_id'][0]).sequence + 1 }) - else: - values['sequence'] = -1 # create slide itself try: @@ -1051,7 +1050,7 @@ class WebsiteSlides(WebsiteProfile): return {'error': _('Internal server error, please try again later or contact administrator.\nHere is the error message: %s') % e} # ensure correct ordering by re sequencing slides in front-end (backend should be ok thanks to list view) - channel._resequence_slides(slide) + channel._resequence_slides(slide, category_id) redirect_url = "/slides/slide/%s" % (slide.id) if channel.channel_type == "training" and not slide.slide_type == "webpage": diff --git a/addons/website_slides/models/slide_channel.py b/addons/website_slides/models/slide_channel.py index 214a2025f2c..cb6ea814a18 100644 --- a/addons/website_slides/models/slide_channel.py +++ b/addons/website_slides/models/slide_channel.py @@ -593,13 +593,26 @@ class Channel(models.Model): def _get_categorized_slides(self, base_domain, order, force_void=True, limit=False, offset=False): """ Return an ordered structure of slides by categories within a given - base_domain that must fulfill slides. """ + base_domain that must fulfill slides. As a course structure is based on + its slides sequences, uncategorized slides must have the lowest sequences. + + Example + * category 1 (sequence 1), category 2 (sequence 3) + * slide 1 (sequence 0), slide 2 (sequence 2) + * course structure is: slide 1, category 1, slide 2, category 2 + * slide 1 is uncategorized, + * category 1 has one slide : Slide 2 + * category 2 is empty. + + Backend and frontend ordering is the same, uncategorized first. It + eases resequencing based on DOM / displayed order, notably when + drag n drop is involved. """ self.ensure_one() all_categories = self.env['slide.slide'].sudo().search([('channel_id', '=', self.id), ('is_category', '=', True)]) all_slides = self.env['slide.slide'].sudo().search(base_domain, order=order) category_data = [] - # First add all categories by natural order + # Prepare all categories by natural order for category in all_categories: category_slides = all_slides.filtered(lambda slide: slide.category_id == category) if not category_slides and not force_void: @@ -610,15 +623,17 @@ class Channel(models.Model): 'total_slides': len(category_slides), 'slides': category_slides[(offset or 0):(limit + offset or len(category_slides))], }) - # Then add uncategorized slides + + # Add uncategorized slides in first position uncategorized_slides = all_slides.filtered(lambda slide: not slide.category_id) if uncategorized_slides or force_void: - category_data.append({ + category_data.insert(0, { 'category': False, 'id': False, 'name': _('Uncategorized'), 'slug_name': _('Uncategorized'), 'total_slides': len(uncategorized_slides), 'slides': uncategorized_slides[(offset or 0):(offset + limit or len(uncategorized_slides))], }) + return category_data def _resequence_slides(self, slide, force_category=False): diff --git a/addons/website_slides/tests/test_slide_utils.py b/addons/website_slides/tests/test_slide_utils.py index 489f2de0d0f..b4e58b0bbfd 100644 --- a/addons/website_slides/tests/test_slide_utils.py +++ b/addons/website_slides/tests/test_slide_utils.py @@ -5,6 +5,25 @@ from odoo.addons.website_slides.tests import common as slides_common from odoo.tests.common import users +class TestSlidesManagement(slides_common.SlidesCase): + + @users('user_officer') + def test_get_categorized_slides(self): + new_category = self.env['slide.slide'].create({ + 'name': 'Cooking Tips for Cooking Humans', + 'channel_id': self.channel.id, + 'is_category': True, + 'sequence': 5, + }) + order = self.env['slide.slide']._order_by_strategy['sequence'] + categorized_slides = self.channel._get_categorized_slides([], order) + self.assertEqual(categorized_slides[0]['category'], False) + self.assertEqual(categorized_slides[1]['category'], self.category) + self.assertEqual(categorized_slides[1]['total_slides'], 2) + self.assertEqual(categorized_slides[2]['total_slides'], 0) + self.assertEqual(categorized_slides[2]['category'], new_category) + + class TestSequencing(slides_common.SlidesCase): @users('user_officer') diff --git a/addons/website_slides/views/website_slides_templates_course.xml b/addons/website_slides/views/website_slides_templates_course.xml index bbdf666ea7e..53e57546ed8 100644 --- a/addons/website_slides/views/website_slides_templates_course.xml +++ b/addons/website_slides/views/website_slides_templates_course.xml @@ -366,7 +366,7 @@