Skip to content

Commit

Permalink
[REF] survey: refactor page management controllers and code
Browse files Browse the repository at this point in the history
Purpose of this commit is to relocate code used in controllers where it
belongs and simplify it. This commit cleans next / previous page computation.
  • Loading branch information
tde-banana-odoo committed Jan 16, 2019
1 parent 3ea2a6e commit 27dcf40
Show file tree
Hide file tree
Showing 5 changed files with 77 additions and 83 deletions.
54 changes: 28 additions & 26 deletions addons/survey/controllers/main.py
Expand Up @@ -177,31 +177,29 @@ def survey_display_page(self, survey_id, token, prev=None):

survey_sudo, answer_sudo = access_data['survey_sudo'], access_data['answer_sudo']

# Select the right page
if answer_sudo.state == 'new': # First page
page, page_nr, last = survey_sudo.next_page(answer_sudo, 0, go_back=False)
data = {'survey': survey_sudo, 'page': page, 'page_nr': page_nr, 'token': answer_sudo.token, 'test_entry': answer_sudo.test_entry}
if last:
data.update({'last': True})
return request.render('survey.survey', data)
elif answer_sudo.state == 'done': # Display success message
return request.render('survey.sfinished', {'survey': survey_sudo,
'token': token,
'user_input': answer_sudo})
elif answer_sudo.state == 'skip':
flag = (True if prev and prev == 'prev' else False)
page, page_nr, last = survey_sudo.next_page(answer_sudo, answer_sudo.last_displayed_page_id.id, go_back=flag)

#special case if you click "previous" from the last page, then leave the survey, then reopen it from the URL, avoid crash
if not page:
page, page_nr, last = survey_sudo.next_page(answer_sudo, answer_sudo.last_displayed_page_id.id, go_back=True)

data = {'survey': survey_sudo, 'page': page, 'page_nr': page_nr, 'token': answer_sudo.token, 'test_entry': answer_sudo.test_entry}
if last:
data.update({'last': True})
return request.render('survey.survey', data)
if prev and prev == 'prev':
next_page = answer_sudo.get_previous_page()
else:
return request.render("survey.403", {'survey': survey_sudo})
next_page = answer_sudo.get_next_page()
if not next_page:
return request.render('survey.sfinished', {
'survey': survey,
'token': token,
'user_input': answer_sudo,
'test_entry': answer_sudo.test_entry,
})

page_data = {
'survey': survey,
'user_input': answer_sudo,
'test_entry': answer_sudo.test_entry,
'page': next_page,
'page_nbr': next_page._get_pagination()[0],
'page_count': next_page._get_pagination()[1],
'page_is_first': next_page._is_first(),
'page_is_last': next_page._is_last(),
}
return request.render('survey.survey_page', page_data)

@http.route('/survey/prefill/<int:survey_id>/<string:token>', type='http', auth='public', website=True)
def survey_get_answers(self, survey_id, token, page_id=None):
Expand Down Expand Up @@ -294,9 +292,13 @@ def survey_submit(self, survey_id, token, **post):
request.env['survey.user_input_line'].sudo().save_lines(answer_sudo.id, question, post, answer_tag)

go_back = post['button_submit'] == 'previous'
next_page, _, last = request.env['survey.survey'].next_page(answer_sudo, page_id, go_back=go_back)
if go_back:
next_page = answer_sudo.get_previous_page()
else:
next_page = answer_sudo.get_next_page()

vals = {'last_displayed_page_id': page_id}
if next_page is None and not go_back:
if not next_page and not go_back:
vals.update({'state': 'done'})
else:
vals.update({'state': 'skip'})
Expand Down
12 changes: 11 additions & 1 deletion addons/survey/models/survey_page.py
Expand Up @@ -16,4 +16,14 @@ class SurveyPage(models.Model):
survey_id = fields.Many2one('survey.survey', string='Survey', ondelete='cascade', required=True)
question_ids = fields.One2many('survey.question', 'page_id', string='Questions', copy=True)
sequence = fields.Integer('Page number', default=10)
description = fields.Html('Description', translate=True, oldname="note", help="An introductory text to your page")
description = fields.Html('Description', translate=True, oldname="note", help="An introductory text to your page")

def _is_first(self):
return self.sequence == self.survey_id.page_ids[0].sequence

def _is_last(self):
return self.sequence == self.survey_id.page_ids[-1].sequence

def _get_pagination(self):
sequences = self.survey_id.page_ids.mapped('sequence')
return (sequences.index(self.sequence) + 1, len(sequences))
41 changes: 0 additions & 41 deletions addons/survey/models/survey_survey.py
Expand Up @@ -153,47 +153,6 @@ def _check_answer_creation(self, user, partner, email, test_entry=False):
if self.access_mode == 'internal' and (not user or not user.has_group('base.group_user')):
raise UserError(_('Creating token for anybody else than employees is not allowed for internal surveys.'))

@api.model
def next_page(self, user_input, page_id, go_back=False):
""" The next page to display to the user, knowing that page_id is the id
of the last displayed page.
If page_id == 0, it will always return the first page of the survey.
If all the pages have been displayed and go_back == False, it will
return None
If go_back == True, it will return the *previous* page instead of the
next page.
.. note::
It is assumed here that a careful user will not try to set go_back
to True if she knows that the page to display is the first one!
(doing this will probably cause a giant worm to eat her house)
"""
survey = user_input.survey_id
pages = list(enumerate(survey.page_ids))

# First page
if page_id == 0:
return (pages[0][1], 0, len(pages) == 1)

current_page_index = pages.index(next(p for p in pages if p[1].id == page_id))

# All the pages have been displayed
if current_page_index == len(pages) - 1 and not go_back:
return (None, -1, False)
# Let's get back, baby!
elif go_back and survey.users_can_go_back:
return (pages[current_page_index - 1][1], current_page_index - 1, False)
else:
# This will show the last page
if current_page_index == len(pages) - 2:
return (pages[current_page_index + 1][1], current_page_index + 1, True)
# This will show a regular page
else:
return (pages[current_page_index + 1][1], current_page_index + 1, False)

@api.multi
def filter_input_ids(self, filters, finished=False):
"""If user applies any filters, then this function returns list of
Expand Down
22 changes: 22 additions & 0 deletions addons/survey/models/survey_user.py
Expand Up @@ -58,6 +58,28 @@ def _compute_quizz_score(self):
('unique_token', 'UNIQUE (token)', 'A token must be unique!'),
]

@api.multi
def get_next_page(self):
""" Return next survey page based on last displayed page stored on user answxer. """
self.ensure_one()

current_page = self.last_displayed_page_id
if not current_page:
return self.survey_id.page_ids[0]
next_page = next((page for page in self.survey_id.page_ids if page.sequence > current_page.sequence), False)
return next_page

@api.multi
def get_previous_page(self):
""" Return previous survey page based on last displayed page stored on user answxer. """
self.ensure_one()

current_page = self.last_displayed_page_id
if not current_page:
return self.survey_id.page_ids[-1]
previous_page = next((page for page in reversed(self.survey_id.page_ids) if page.sequence < current_page.sequence), False)
return previous_page

@api.model
def do_clean_emptys(self):
""" Remove empty user inputs that have been created manually
Expand Down
31 changes: 16 additions & 15 deletions addons/survey/views/survey_templates.xml
Expand Up @@ -168,40 +168,41 @@
</template>

<!-- A survey -->
<template id="survey" name="Survey">
<template id="survey_page" name="Survey Page">
<t t-call="survey.layout">
<div class="wrap">
<div class="oe_structure" id="oe_structure_survey_survey_1"/>
<div class="oe_structure"/>
<div class="container">
<t t-call="survey.back" />
<t t-call="survey.page" />
<t t-call="survey.back"/>
<t t-call="survey.survey_page_content"/>
</div>
<div class="oe_structure" id="oe_structure_survey_survey_2"/>
<div class="oe_structure"/>
</div>
</t>
</template>

<!-- SUB TEMPLATES TO DISPLAY SPECIFIC SURVEY PARTS -->

<!-- A page -->
<template id="page" name="Page">
<template id="survey_page_content" name="Survey Page Content">
<div class="o_page_header">
<div class="alert alert-danger text-center no_print" t-if="test_entry">
<span>This is a test survey. Your answer will not be registered in the answers. </span>
</div>
<p class="float-right">Page <span t-raw='page_nr + 1'/> of <span t-raw="len(survey.page_ids)"/></p>
<h1 t-field='page.title' />
<p class="float-right">Page <span t-raw='page_nbr'/> of <span t-raw="page_count"/></p>
<h1 t-field='page.title'/>
<div t-field='page.description' class="oe_no_empty"/>
</div>

<form role="form" method="post" class="js_surveyform" t-att-name="'%s_%s' % (survey.id, page.id)"
t-att-action="'/survey/fill/%s/%s' % (survey.id, token)"
t-att-data-prefill="'/survey/prefill/%s/%s?page_id=%s' % (survey.id, token, page.id)"
<form role="form" method="post" class="js_surveyform"
t-att-name="'%s_%s' % (survey.id, page.id)"
t-att-action="'/survey/fill/%s/%s' % (survey.id, user_input.token)"
t-att-data-prefill="'/survey/prefill/%s/%s?page_id=%s' % (survey.id, user_input.token, page.id)"
t-att-data-validate="'/survey/validate/%s/%s' % (survey.id, token)"
t-att-data-submit="'/survey/submit/%s/%s' % (survey.id, token)">
<input type="hidden" name="csrf_token" t-att-value="request.csrf_token()"/>
<input type="hidden" name="page_id" t-att-value="page.id" />
<input type="hidden" name="token" t-att-value="token" />
<input type="hidden" name="token" t-att-value="user_input.token" />
<t t-foreach='page.question_ids' t-as='question'>
<t t-set="prefix" t-value="'%s_%s_%s' % (survey.id, page.id, question.id)" />
<div class="js_question-wrapper" t-att-id="prefix">
Expand All @@ -221,9 +222,9 @@
</div>
</t>
<div class="text-center mt16 mb16">
<button t-if="survey.users_can_go_back and page_nr > 0" type="submit" class="btn btn-secondary" name="button_submit" value="previous">Previous page</button>
<button t-if="not last" type="submit" class="btn btn-primary" name="button_submit" value="next">Next page</button>
<button t-if="last" type="submit" class="btn btn-primary" name="button_submit" value="finish">Submit survey</button>
<button t-if="survey.users_can_go_back and not page_is_first" type="submit" class="btn btn-secondary" name="button_submit" value="previous">Previous page</button>
<button t-if="not page_is_last" type="submit" class="btn btn-primary" name="button_submit" value="next">Next page</button>
<button t-if="page_is_last" type="submit" class="btn btn-primary" name="button_submit" value="finish">Submit survey</button>
</div>
</form>

Expand Down

0 comments on commit 27dcf40

Please sign in to comment.