Skip to content

Commit

Permalink
[REF] website_slides: replace slide.category by slide with is_categor…
Browse files Browse the repository at this point in the history
…y flag

PURPOSE

Like already done for sale order, invoice of survey, purpose of this commit
is to remove category model and replace by a flagged line (slide). It allows
to easily reorder slides in an embedded list view.

SPECIFICATIONS

Instead of having a fully fledged slide.category model, slide.slide will serve
that purpose with a is_category flag. This will allow to drag and drop slides
and sections in the channel form view.

This change had an impact on the way slides were added/sorted on the front-end.
In fact, whenever a slide is added from the front-end, a resequencing of all
the slides in the course has to be triggered.

Category of a slide is now a computed field based on the sequence. Order
of slides is based on sequence, with categories splitting the slide list based
on is_category flag.

In this commit tests are added. Some cleaning in tests is also performed to
speedup a bit tests (savepointcase) and some cleaning / renaming to ease
their understanding.

Future commit will add JS necessary to manage slides in the section list view.

LINKS

TaskID: 1978731
PR: #33255
  • Loading branch information
qmo-odoo authored and tde-banana-odoo committed Aug 8, 2019
1 parent 5f4c7c5 commit b180c66
Show file tree
Hide file tree
Showing 23 changed files with 435 additions and 395 deletions.
84 changes: 38 additions & 46 deletions addons/website_slides/controllers/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -137,19 +137,29 @@ def _get_slide_quiz_data(self, slide):
values.update(self._get_slide_quiz_partner_info(slide))
return values

def _get_new_slide_category_values(self, channel, name):
return {
'name': name,
'channel_id': channel.id,
'is_category': True,
'is_published': True,
'sequence': channel.slide_ids[-1]['sequence'] + 1 if channel.slide_id else 1,
}

# CHANNEL UTILITIES
# --------------------------------------------------

def _get_channel_slides_base_domain(self, channel):
""" base domain when fetching slide list data related to a given channel
* website related domain, and restricted to the channel;
* website related domain, and restricted to the channel and is not a
category slide (behavior is different from classic slide);
* if publisher: everything is ok;
* if not publisher but has user: either slide is published, either
current user is the one that uploaded it;
* if not publisher and public: published;
"""
base_domain = expression.AND([request.website.website_domain(), [('channel_id', '=', channel.id)]])
base_domain = expression.AND([request.website.website_domain(), ['&', ('channel_id', '=', channel.id), ('is_category', '=', False)]])
if not channel.can_publish:
if request.website.is_public_user():
base_domain = expression.AND([base_domain, [('website_published', '=', True)]])
Expand Down Expand Up @@ -331,8 +341,8 @@ def _get_top3_users(self):
'/slides/<model("slide.channel"):channel>/page/<int:page>',
'/slides/<model("slide.channel"):channel>/tag/<model("slide.tag"):tag>',
'/slides/<model("slide.channel"):channel>/tag/<model("slide.tag"):tag>/page/<int:page>',
'/slides/<model("slide.channel"):channel>/category/<model("slide.category"):category>',
'/slides/<model("slide.channel"):channel>/category/<model("slide.category"):category>/page/<int:page>'
'/slides/<model("slide.channel"):channel>/category/<model("slide.slide"):category>',
'/slides/<model("slide.channel"):channel>/category/<model("slide.slide"):category>/page/<int:page>'
], type='http', auth="public", website=True, sitemap=sitemap_slide)
def channel(self, channel, category=None, tag=None, page=1, slide_type=None, uncategorized=False, sorting=None, search=None, **kw):
if not channel.can_access_from_current_website():
Expand Down Expand Up @@ -486,24 +496,6 @@ def slide_channel_join(self, channel_id):
return {'error': 'join_done'}
return success

@http.route('/slides/channel/resequence', type="json", website=True, auth="user")
def resequence_slides(self, channel_id, slides_data):
"""" Reorder the slides within the channel by reassigning their 'sequence' field.
This method also handles slides that are put in a new category (or uncategorized). """
channel = request.env['slide.channel'].browse(int(channel_id))
if not channel.can_publish:
return {'error': 'Only the publishers of the channel can edit it'}

slides = request.env['slide.slide'].search([
('id', 'in', [int(key) for key in slides_data.keys()]),
('channel_id', '=', channel.id)
])

for slide in slides:
slide_key = str(slide.id)
slide.sequence = slides_data[slide_key]['sequence']
slide.category_id = slides_data[slide_key]['category_id'] if 'category_id' in slides_data[slide_key] else False

@http.route(['/slides/channel/tag/search_read'], type='json', auth='user', methods=['POST'], website=True)
def slide_channel_tag_search_read(self, fields, domain):
can_create = request.env['slide.channel.tag'].check_access_rights('create', raise_exception=False)
Expand Down Expand Up @@ -738,30 +730,23 @@ def slide_quiz_submit(self, slide_id, answer_ids):

@http.route(['/slides/category/search_read'], type='json', auth='user', methods=['POST'], website=True)
def slide_category_search_read(self, fields, domain):
can_create = request.env['slide.category'].check_access_rights('create', raise_exception=False)
category_slide_domain = domain if domain else []
category_slide_domain = expression.AND([category_slide_domain, [('is_category', '=', True)]])
can_create = request.env['slide.slide'].check_access_rights('create', raise_exception=False)
return {
'read_results': request.env['slide.category'].search_read(domain, fields),
'read_results': request.env['slide.slide'].search_read(category_slide_domain, fields),
'can_create': can_create,
}

@http.route('/slides/category/add', type="http", website=True, auth="user")
def slide_category_add(self, channel_id, name):
""" Adds a category to the specified channel. If categories already exist
within this channel, it will be added at the bottom (sequence+1) """
""" Adds a category to the specified channel. Slide is added at the end
of slide list based on sequence. """
channel = request.env['slide.channel'].browse(int(channel_id))
if not channel.can_upload or not channel.can_publish:
raise werkzeug.exceptions.NotFound()

values = {
'name': name,
'channel_id': channel.id
}

latest_category = request.env['slide.category'].search_read([
('channel_id', '=', channel.id)
], ["sequence"], order="sequence desc", limit=1)
if latest_category:
values['sequence'] = latest_category[0]['sequence'] + 1

request.env['slide.category'].create(values)
request.env['slide.slide'].create(self._get_new_slide_category_values(channel, name))

return werkzeug.utils.redirect("/slides/%s" % (slug(channel)))

Expand Down Expand Up @@ -797,14 +782,6 @@ def create_slide(self, *args, **post):

values = dict((fname, post[fname]) for fname in self._get_valid_slide_post_values() if post.get(fname))

if post.get('category_id'):
if post['category_id'][0] == 0:
values['category_id'] = request.env['slide.category'].create({
'name': post['category_id'][1]['name'],
'channel_id': values.get('channel_id')}).id
else:
values['category_id'] = post['category_id'][0]

# handle exception during creation of slide and sent error notification to the client
# otherwise client slide create dialog box continue processing even server fail to create a slide
try:
Expand All @@ -818,6 +795,18 @@ def create_slide(self, *args, **post):
if not can_upload:
return {'error': _('You cannot upload on this channel.')}

# handle creation of new categories on the fly
if post.get('category_id'):
if post['category_id'][0] == 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
else:
values.update({
'category_id': post['category_id'][0],
})

# create slide itself
try:
values['user_id'] = request.env.uid
values['is_published'] = values.get('is_published', False) and can_publish
Expand All @@ -829,6 +818,9 @@ def create_slide(self, *args, **post):
_logger.error(e)
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)

redirect_url = "/slides/slide/%s" % (slide.id)
if channel.channel_type == "training" and not slide.slide_type == "webpage":
redirect_url = "/slides/%s" % (slug(channel))
Expand Down
45 changes: 0 additions & 45 deletions addons/website_slides/data/slide_channel_demo.xml
Original file line number Diff line number Diff line change
Expand Up @@ -32,16 +32,6 @@
<field name="description">Learn how to take care of your favorite trees. Learn when to plant, how to manage potted trees, ...</field>
<field name="create_date" eval="DateTime.now() - relativedelta(days=7)"/>
</record>
<record id="slide_category_demo_1_0" model="slide.category">
<field name="name">Interesting Facts</field>
<field name="channel_id" ref="website_slides.slide_channel_demo_1_gard1"/>
<field name="sequence">10</field>
</record>
<record id="slide_category_demo_1_1" model="slide.category">
<field name="name">Methods</field>
<field name="channel_id" ref="website_slides.slide_channel_demo_1_gard1"/>
<field name="sequence">20</field>
</record>

<record id="slide_channel_demo_2_gard2" model="slide.channel">
<field name="name">Trees, Wood and Gardens</field>
Expand All @@ -60,16 +50,6 @@
<field name="description">A lot of nice documentation: trees, wood, gardens. A gold mine for references.</field>
<field name="create_date" eval="DateTime.now() - relativedelta(days=6)"/>
</record>
<record id="slide_category_demo_2_0" model="slide.category">
<field name="name">Trees</field>
<field name="channel_id" ref="website_slides.slide_channel_demo_2_gard2"/>
<field name="sequence">10</field>
</record>
<record id="slide_category_demo_2_1" model="slide.category">
<field name="name">Wood</field>
<field name="channel_id" ref="website_slides.slide_channel_demo_2_gard2"/>
<field name="sequence">20</field>
</record>

<record id="slide_channel_demo_3_furn0" model="slide.channel">
<field name="name">Choose your wood !</field>
Expand All @@ -89,11 +69,6 @@
will learn the basics of wood characteristics.</field>
<field name="create_date" eval="DateTime.now() - relativedelta(days=5)"/>
</record>
<record id="slide_category_demo_3_0" model="slide.category">
<field name="name">Introduction</field>
<field name="channel_id" ref="website_slides.slide_channel_demo_3_furn0"/>
<field name="sequence">10</field>
</record>

<record id="slide_channel_demo_4_furn1" model="slide.channel">
<field name="name">Furniture Technical Specifications</field>
Expand All @@ -109,11 +84,6 @@ will learn the basics of wood characteristics.</field>
<field name="description">If you are looking for technical specifications, have a look at this documentation.</field>
<field name="create_date" eval="DateTime.now() - relativedelta(days=4)"/>
</record>
<record id="slide_category_demo_4_0" model="slide.category">
<field name="name">Introduction</field>
<field name="channel_id" ref="website_slides.slide_channel_demo_4_furn1"/>
<field name="sequence">10</field>
</record>

<record id="slide_channel_demo_5_furn2" model="slide.channel">
<field name="name">Basics of Furniture Creation</field>
Expand All @@ -131,21 +101,6 @@ will learn the basics of wood characteristics.</field>
<field name="description">All you need to know about furniture creation.</field>
<field name="create_date" eval="DateTime.now() - relativedelta(days=3)"/>
</record>
<record id="slide_category_demo_5_0" model="slide.category">
<field name="name">Tools and Methods</field>
<field name="channel_id" ref="website_slides.slide_channel_demo_5_furn2"/>
<field name="sequence">10</field>
</record>
<record id="slide_category_demo_5_1" model="slide.category">
<field name="name">Hand on !</field>
<field name="channel_id" ref="website_slides.slide_channel_demo_5_furn2"/>
<field name="sequence">20</field>
</record>
<record id="slide_category_demo_5_2" model="slide.category">
<field name="name">Test Yourself</field>
<field name="channel_id" ref="website_slides.slide_channel_demo_5_furn2"/>
<field name="sequence">30</field>
</record>

<!-- This channel will be set on payment and receive certifications capabilities -->
<record id="slide_channel_demo_6_furn3" model="slide.channel">
Expand Down
Loading

0 comments on commit b180c66

Please sign in to comment.