[MERGE] Merge all work from branch trunk-survey_reporting-pga due to new survey parent branch

bzr revid: pga@tinyerp.com-20140123112107-s1nvv160v3zoevlq
This commit is contained in:
Parth Gajjar (Open ERP) 2014-01-23 16:51:07 +05:30
parent 6b00de93c1
commit 918ee43f9a
8 changed files with 23975 additions and 0 deletions

View File

@ -42,6 +42,7 @@ sent mails with personal token for the invitation of the survey.
'security/ir.model.access.csv',
'views/survey_views.xml',
'views/survey_templates.xml',
'views/survey_result.xml',
'wizard/survey_email_compose_message.xml',
'data/survey_cron.xml'
],

View File

@ -29,6 +29,9 @@ from openerp.addons.web import http
from openerp.addons.web.http import request
#from openerp.addons.website.models import website
from openerp.addons.website.controllers.main import Website as controllers
import itertools
import math
from collections import Counter
controllers = controllers()
@ -286,6 +289,78 @@ class WebsiteSurvey(http.Controller):
'token': token,
'page_nr': 0})
@http.route(['/survey/results/<model("survey.survey"):survey>'],type='http', auth='user', multilang=True, website=True)
def survey_reporting(self, survey, token=None, **post):
return request.website.render('survey.result',
{'survey': survey,
'prepare_result':self.prepare_result,
'get_input_summary':self.get_input_summary,
'get_graph_data':self.get_graph_data,
'page_range':self.page_range
})
def page_range(self, total_record):
total = math.ceil( total_record/5.0 )
return range(1, int( total+1 ))
def prepare_result(self, question):
if question.type in ['simple_choice', 'multiple_choice'] :
result_summary = {}
[ result_summary.update({ label.id : {'text':label.value, 'count':0} }) for label in question.labels_ids ]
for input_line in question.user_input_line_ids:
if result_summary.get(input_line.value_suggested.id) and not input_line.skipped:
result_summary[input_line.value_suggested.id]['count'] += 1
result_summary = result_summary.values()
if question.type == 'matrix':
rows, answers, res = {}, {}, {}
[ rows.update({ label.id : label.value}) for label in question.labels_ids_2 ]
[ answers.update({label.id: label.value}) for label in question.labels_ids ]
for cell in itertools.product(rows.keys(), answers.keys()):
res[cell] = 0
for input_line in question.user_input_line_ids:
if not input_line.skipped:
res[(input_line.value_suggested_row.id,input_line.value_suggested.id)] += 1
result_summary= {'answers':answers,'rows':rows,'result':res}
if question.type == 'numerical_box':
result_summary = {}
all_inputs = []
for input_line in question.user_input_line_ids:
if not input_line.skipped:
all_inputs.append(input_line.value_number)
result_summary.update({
'average':round(sum(all_inputs)/len(all_inputs),2),
'max':round(max(all_inputs),2),
'min':round(min(all_inputs),2),
'most_comman':Counter(all_inputs).most_common(5),
})
return result_summary
def get_graph_data(self, question):
result = []
if question.type in ['simple_choice', 'multiple_choice']:
result.append({'key':str(question.question),
'values':self.prepare_result(question)})
if question.type == 'matrix':
data = self.prepare_result(question)
for answer in data['answers']:
values = []
for res in data['result']:
if res[1] == answer:
values.append({'text': data['rows'][res[0]], 'count': data['result'][res]})
result.append({'key':data['answers'].get(answer),'values':values})
return json.dumps(result)
def get_input_summary(self, question):
result = {}
if question.page_id.survey_id.user_input_ids:
result['total_inputs'] = len(question.page_id.survey_id.user_input_ids)
question_input_ids = []
for user_input in question.user_input_line_ids:
if not user_input.skipped:
question_input_ids.append(user_input.user_input_id.id)
result['answered'] = len(set(question_input_ids))
result['skipped'] = result['total_inputs'] - result['answered']
return result
def dict_soft_update(dictionary, key, value):
''' Insert the pair <key>: <value> into the <dictionary>. If <key> is

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,768 @@
/********************
* HTML CSS
*/
.chartWrap {
margin: 0;
padding: 0;
overflow: hidden;
}
/********************
Box shadow and border radius styling
*/
.nvtooltip.with-3d-shadow, .with-3d-shadow .nvtooltip {
-moz-box-shadow: 0 5px 10px rgba(0,0,0,.2);
-webkit-box-shadow: 0 5px 10px rgba(0,0,0,.2);
box-shadow: 0 5px 10px rgba(0,0,0,.2);
-webkit-border-radius: 6px;
-moz-border-radius: 6px;
border-radius: 6px;
}
/********************
* TOOLTIP CSS
*/
.nvtooltip {
position: absolute;
background-color: rgba(255,255,255,1.0);
padding: 1px;
border: 1px solid rgba(0,0,0,.2);
z-index: 10000;
font-family: Arial;
font-size: 13px;
text-align: left;
pointer-events: none;
white-space: nowrap;
-webkit-touch-callout: none;
-webkit-user-select: none;
-khtml-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
}
/*Give tooltips that old fade in transition by
putting a "with-transitions" class on the container div.
*/
.nvtooltip.with-transitions, .with-transitions .nvtooltip {
transition: opacity 250ms linear;
-moz-transition: opacity 250ms linear;
-webkit-transition: opacity 250ms linear;
transition-delay: 250ms;
-moz-transition-delay: 250ms;
-webkit-transition-delay: 250ms;
}
.nvtooltip.x-nvtooltip,
.nvtooltip.y-nvtooltip {
padding: 8px;
}
.nvtooltip h3,.nvtooltip h5 {
margin: 0;
line-height: 18px;
font-weight: bold;
background-color: rgba(247,247,247,0.75);
text-align: center;
border-bottom: 1px solid #ebebeb;
-webkit-border-radius: 5px 5px 0 0;
-moz-border-radius: 5px 5px 0 0;
border-radius: 5px 5px 0 0;
}
.nvtooltip p {
margin: 0;
padding: 5px 14px;
text-align: center;
}
.nvtooltip span {
display: inline-block;
margin: 2px 0;
}
.nvtooltip table {
margin: 6px;
border-spacing:0;
}
.nvtooltip table td {
padding: 2px 9px 2px 0;
vertical-align: middle;
}
.nvtooltip table td.key {
font-weight:normal;
}
.nvtooltip table td.value {
text-align: right;
font-weight: bold;
}
.nvtooltip table tr.highlight td {
padding: 1px 9px 1px 0;
border-bottom-style: solid;
border-bottom-width: 1px;
border-top-style: solid;
border-top-width: 1px;
}
.nvtooltip table td.legend-color-guide div {
width: 8px;
height: 8px;
vertical-align: middle;
}
.nvtooltip .footer {
padding: 3px;
text-align: center;
}
.nvtooltip-pending-removal {
position: absolute;
pointer-events: none;
}
/********************
* SVG CSS
*/
svg {
-webkit-touch-callout: none;
-webkit-user-select: none;
-khtml-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
/* Trying to get SVG to act like a greedy block in all browsers */
display: block;
width:100%;
height:100%;
}
svg text {
font: normal 12px Arial;
}
svg .title {
font: bold 14px Arial;
}
.nvd3 .nv-background {
fill: white;
fill-opacity: 0;
/*
pointer-events: none;
*/
}
.nvd3.nv-noData {
font-size: 18px;
font-weight: bold;
}
/**********
* Brush
*/
.nv-brush .extent {
fill-opacity: .125;
shape-rendering: crispEdges;
}
/**********
* Legend
*/
.nvd3 .nv-legend .nv-series {
cursor: pointer;
}
.nvd3 .nv-legend .disabled circle {
fill-opacity: 0;
}
/**********
* Axes
*/
.nvd3 .nv-axis {
pointer-events:none;
}
.nvd3 .nv-axis path {
fill: none;
stroke: #000;
stroke-opacity: .75;
shape-rendering: crispEdges;
}
.nvd3 .nv-axis path.domain {
stroke-opacity: .75;
}
.nvd3 .nv-axis.nv-x path.domain {
stroke-opacity: 0;
}
.nvd3 .nv-axis line {
fill: none;
stroke: #e5e5e5;
shape-rendering: crispEdges;
}
.nvd3 .nv-axis .zero line,
/*this selector may not be necessary*/ .nvd3 .nv-axis line.zero {
stroke-opacity: .75;
}
.nvd3 .nv-axis .nv-axisMaxMin text {
font-weight: bold;
}
.nvd3 .x .nv-axis .nv-axisMaxMin text,
.nvd3 .x2 .nv-axis .nv-axisMaxMin text,
.nvd3 .x3 .nv-axis .nv-axisMaxMin text {
text-anchor: middle
}
/**********
* Brush
*/
.nv-brush .resize path {
fill: #eee;
stroke: #666;
}
/**********
* Bars
*/
.nvd3 .nv-bars .negative rect {
zfill: brown;
}
.nvd3 .nv-bars rect {
zfill: steelblue;
fill-opacity: .75;
transition: fill-opacity 250ms linear;
-moz-transition: fill-opacity 250ms linear;
-webkit-transition: fill-opacity 250ms linear;
}
.nvd3 .nv-bars rect.hover {
fill-opacity: 1;
}
.nvd3 .nv-bars .hover rect {
fill: lightblue;
}
.nvd3 .nv-bars text {
fill: rgba(0,0,0,0);
}
.nvd3 .nv-bars .hover text {
fill: rgba(0,0,0,1);
}
/**********
* Bars
*/
.nvd3 .nv-multibar .nv-groups rect,
.nvd3 .nv-multibarHorizontal .nv-groups rect,
.nvd3 .nv-discretebar .nv-groups rect {
stroke-opacity: 0;
transition: fill-opacity 250ms linear;
-moz-transition: fill-opacity 250ms linear;
-webkit-transition: fill-opacity 250ms linear;
}
.nvd3 .nv-multibar .nv-groups rect:hover,
.nvd3 .nv-multibarHorizontal .nv-groups rect:hover,
.nvd3 .nv-discretebar .nv-groups rect:hover {
fill-opacity: 1;
}
.nvd3 .nv-discretebar .nv-groups text,
.nvd3 .nv-multibarHorizontal .nv-groups text {
font-weight: bold;
fill: rgba(0,0,0,1);
stroke: rgba(0,0,0,0);
}
/***********
* Pie Chart
*/
.nvd3.nv-pie path {
stroke-opacity: 0;
transition: fill-opacity 250ms linear, stroke-width 250ms linear, stroke-opacity 250ms linear;
-moz-transition: fill-opacity 250ms linear, stroke-width 250ms linear, stroke-opacity 250ms linear;
-webkit-transition: fill-opacity 250ms linear, stroke-width 250ms linear, stroke-opacity 250ms linear;
}
.nvd3.nv-pie .nv-slice text {
stroke: #000;
stroke-width: 0;
}
.nvd3.nv-pie path {
stroke: #fff;
stroke-width: 1px;
stroke-opacity: 1;
}
.nvd3.nv-pie .hover path {
fill-opacity: .7;
}
.nvd3.nv-pie .nv-label {
pointer-events: none;
}
.nvd3.nv-pie .nv-label rect {
fill-opacity: 0;
stroke-opacity: 0;
}
/**********
* Lines
*/
.nvd3 .nv-groups path.nv-line {
fill: none;
stroke-width: 1.5px;
/*
stroke-linecap: round;
shape-rendering: geometricPrecision;
transition: stroke-width 250ms linear;
-moz-transition: stroke-width 250ms linear;
-webkit-transition: stroke-width 250ms linear;
transition-delay: 250ms
-moz-transition-delay: 250ms;
-webkit-transition-delay: 250ms;
*/
}
.nvd3 .nv-groups path.nv-line.nv-thin-line {
stroke-width: 1px;
}
.nvd3 .nv-groups path.nv-area {
stroke: none;
/*
stroke-linecap: round;
shape-rendering: geometricPrecision;
stroke-width: 2.5px;
transition: stroke-width 250ms linear;
-moz-transition: stroke-width 250ms linear;
-webkit-transition: stroke-width 250ms linear;
transition-delay: 250ms
-moz-transition-delay: 250ms;
-webkit-transition-delay: 250ms;
*/
}
.nvd3 .nv-line.hover path {
stroke-width: 6px;
}
/*
.nvd3.scatter .groups .point {
fill-opacity: 0.1;
stroke-opacity: 0.1;
}
*/
.nvd3.nv-line .nvd3.nv-scatter .nv-groups .nv-point {
fill-opacity: 0;
stroke-opacity: 0;
}
.nvd3.nv-scatter.nv-single-point .nv-groups .nv-point {
fill-opacity: .5 !important;
stroke-opacity: .5 !important;
}
.with-transitions .nvd3 .nv-groups .nv-point {
transition: stroke-width 250ms linear, stroke-opacity 250ms linear;
-moz-transition: stroke-width 250ms linear, stroke-opacity 250ms linear;
-webkit-transition: stroke-width 250ms linear, stroke-opacity 250ms linear;
}
.nvd3.nv-scatter .nv-groups .nv-point.hover,
.nvd3 .nv-groups .nv-point.hover {
stroke-width: 7px;
fill-opacity: .95 !important;
stroke-opacity: .95 !important;
}
.nvd3 .nv-point-paths path {
stroke: #aaa;
stroke-opacity: 0;
fill: #eee;
fill-opacity: 0;
}
.nvd3 .nv-indexLine {
cursor: ew-resize;
}
/**********
* Distribution
*/
.nvd3 .nv-distribution {
pointer-events: none;
}
/**********
* Scatter
*/
/* **Attempting to remove this for useVoronoi(false), need to see if it's required anywhere
.nvd3 .nv-groups .nv-point {
pointer-events: none;
}
*/
.nvd3 .nv-groups .nv-point.hover {
stroke-width: 20px;
stroke-opacity: .5;
}
.nvd3 .nv-scatter .nv-point.hover {
fill-opacity: 1;
}
/*
.nv-group.hover .nv-point {
fill-opacity: 1;
}
*/
/**********
* Stacked Area
*/
.nvd3.nv-stackedarea path.nv-area {
fill-opacity: .7;
/*
stroke-opacity: .65;
fill-opacity: 1;
*/
stroke-opacity: 0;
transition: fill-opacity 250ms linear, stroke-opacity 250ms linear;
-moz-transition: fill-opacity 250ms linear, stroke-opacity 250ms linear;
-webkit-transition: fill-opacity 250ms linear, stroke-opacity 250ms linear;
/*
transition-delay: 500ms;
-moz-transition-delay: 500ms;
-webkit-transition-delay: 500ms;
*/
}
.nvd3.nv-stackedarea path.nv-area.hover {
fill-opacity: .9;
/*
stroke-opacity: .85;
*/
}
/*
.d3stackedarea .groups path {
stroke-opacity: 0;
}
*/
.nvd3.nv-stackedarea .nv-groups .nv-point {
stroke-opacity: 0;
fill-opacity: 0;
}
/*
.nvd3.nv-stackedarea .nv-groups .nv-point.hover {
stroke-width: 20px;
stroke-opacity: .75;
fill-opacity: 1;
}*/
/**********
* Line Plus Bar
*/
.nvd3.nv-linePlusBar .nv-bar rect {
fill-opacity: .75;
}
.nvd3.nv-linePlusBar .nv-bar rect:hover {
fill-opacity: 1;
}
/**********
* Bullet
*/
.nvd3.nv-bullet { font: 10px sans-serif; }
.nvd3.nv-bullet .nv-measure { fill-opacity: .8; }
.nvd3.nv-bullet .nv-measure:hover { fill-opacity: 1; }
.nvd3.nv-bullet .nv-marker { stroke: #000; stroke-width: 2px; }
.nvd3.nv-bullet .nv-markerTriangle { stroke: #000; fill: #fff; stroke-width: 1.5px; }
.nvd3.nv-bullet .nv-tick line { stroke: #666; stroke-width: .5px; }
.nvd3.nv-bullet .nv-range.nv-s0 { fill: #eee; }
.nvd3.nv-bullet .nv-range.nv-s1 { fill: #ddd; }
.nvd3.nv-bullet .nv-range.nv-s2 { fill: #ccc; }
.nvd3.nv-bullet .nv-title { font-size: 14px; font-weight: bold; }
.nvd3.nv-bullet .nv-subtitle { fill: #999; }
.nvd3.nv-bullet .nv-range {
fill: #bababa;
fill-opacity: .4;
}
.nvd3.nv-bullet .nv-range:hover {
fill-opacity: .7;
}
/**********
* Sparkline
*/
.nvd3.nv-sparkline path {
fill: none;
}
.nvd3.nv-sparklineplus g.nv-hoverValue {
pointer-events: none;
}
.nvd3.nv-sparklineplus .nv-hoverValue line {
stroke: #333;
stroke-width: 1.5px;
}
.nvd3.nv-sparklineplus,
.nvd3.nv-sparklineplus g {
pointer-events: all;
}
.nvd3 .nv-hoverArea {
fill-opacity: 0;
stroke-opacity: 0;
}
.nvd3.nv-sparklineplus .nv-xValue,
.nvd3.nv-sparklineplus .nv-yValue {
/*
stroke: #666;
*/
stroke-width: 0;
font-size: .9em;
font-weight: normal;
}
.nvd3.nv-sparklineplus .nv-yValue {
stroke: #f66;
}
.nvd3.nv-sparklineplus .nv-maxValue {
stroke: #2ca02c;
fill: #2ca02c;
}
.nvd3.nv-sparklineplus .nv-minValue {
stroke: #d62728;
fill: #d62728;
}
.nvd3.nv-sparklineplus .nv-currentValue {
/*
stroke: #444;
fill: #000;
*/
font-weight: bold;
font-size: 1.1em;
}
/**********
* historical stock
*/
.nvd3.nv-ohlcBar .nv-ticks .nv-tick {
stroke-width: 2px;
}
.nvd3.nv-ohlcBar .nv-ticks .nv-tick.hover {
stroke-width: 4px;
}
.nvd3.nv-ohlcBar .nv-ticks .nv-tick.positive {
stroke: #2ca02c;
}
.nvd3.nv-ohlcBar .nv-ticks .nv-tick.negative {
stroke: #d62728;
}
.nvd3.nv-historicalStockChart .nv-axis .nv-axislabel {
font-weight: bold;
}
.nvd3.nv-historicalStockChart .nv-dragTarget {
fill-opacity: 0;
stroke: none;
cursor: move;
}
.nvd3 .nv-brush .extent {
/*
cursor: ew-resize !important;
*/
fill-opacity: 0 !important;
}
.nvd3 .nv-brushBackground rect {
stroke: #000;
stroke-width: .4;
fill: #fff;
fill-opacity: .7;
}
/**********
* Indented Tree
*/
/**
* TODO: the following 3 selectors are based on classes used in the example. I should either make them standard and leave them here, or move to a CSS file not included in the library
*/
.nvd3.nv-indentedtree .name {
margin-left: 5px;
}
.nvd3.nv-indentedtree .clickable {
color: #08C;
cursor: pointer;
}
.nvd3.nv-indentedtree span.clickable:hover {
color: #005580;
text-decoration: underline;
}
.nvd3.nv-indentedtree .nv-childrenCount {
display: inline-block;
margin-left: 5px;
}
.nvd3.nv-indentedtree .nv-treeicon {
cursor: pointer;
/*
cursor: n-resize;
*/
}
.nvd3.nv-indentedtree .nv-treeicon.nv-folded {
cursor: pointer;
/*
cursor: s-resize;
*/
}
/**********
* Parallel Coordinates
*/
.nvd3 .background path {
fill: none;
stroke: #ccc;
stroke-opacity: .4;
shape-rendering: crispEdges;
}
.nvd3 .foreground path {
fill: none;
stroke: steelblue;
stroke-opacity: .7;
}
.nvd3 .brush .extent {
fill-opacity: .3;
stroke: #fff;
shape-rendering: crispEdges;
}
.nvd3 .axis line, .axis path {
fill: none;
stroke: #000;
shape-rendering: crispEdges;
}
.nvd3 .axis text {
text-shadow: 0 1px 0 #fff;
}
/****
Interactive Layer
*/
.nvd3 .nv-interactiveGuideLine {
pointer-events:none;
}
.nvd3 line.nv-guideline {
stroke: #ccc;
}

File diff suppressed because it is too large Load Diff

View File

@ -98,6 +98,15 @@ class survey_survey(osv.Model):
% survey_browse.id)
return res
def _get_result_url(self, cr, uid, ids, name, arg, context=None):
""" Computes a result URL for the survey """
res = dict((id, 0) for id in ids)
base_url = self.pool.get('ir.config_parameter').get_param(cr, uid,
'web.base.url')
for survey_browse in self.browse(cr, uid, ids, context=context):
res[survey_browse.id] = urljoin(base_url, "survey/results/%s/"
% survey_browse.id)
return res
# Model fields #
_columns = {
@ -132,6 +141,8 @@ class survey_survey(osv.Model):
'User responses', readonly=1),
'public_url': fields.function(_get_public_url,
string="Public link", type="char"),
'result_url': fields.function(_get_result_url,
string="Result link", type="char"),
'email_template_id': fields.many2one('email.template',
'Email Template', ondelete='set null'),
'thank_you_message': fields.html('Thank you message', translate=True,
@ -426,6 +437,8 @@ class survey_question(osv.Model):
oldname='minimum_req_ans'),
'constr_error_msg': fields.char("Error message",
oldname='req_error_msg'),
'user_input_line_ids': fields.one2many('survey.user_input_line',
'question_id', 'Answers',domain=[('skipped','=',False)]),
}
_defaults = {
'page_id': lambda s, cr, uid, c: c.get('page_id'),

View File

@ -0,0 +1,316 @@
<?xml version="1.0" encoding="utf-8"?>
<openerp>
<data>
<template id="result" name="Survey Result">
<t t-call="website.layout">
<div class="container">
<link href="/survey/static/src/lib/nvd3/nv.d3.css" rel="stylesheet" type="text/css"></link>
<script src="/survey/static/src/lib/nvd3/lib/d3.v3.js"></script>
<script src="/survey/static/src/lib/nvd3/nv.d3.js"></script>
<style>
.only_left_radius{
border-top-right-radius:2em;
border-bottom-right-radius:2em;
}
.only_right_radius{
border-top-left-radius:2em;
border-bottom-left-radius:2em;
}
</style>
<h1>Survey Result</h1>
<h2><span t-field='survey.title'></span></h2>
<div t-foreach='survey.page_ids' t-as='page' class="panel panel-primary">
<div class="panel-heading"><h3 class="panel-title" t-field='page.title'></h3></div>
<div class="row">
<div class="col-md-10 col-md-offset-1">
<div t-foreach='page.question_ids' t-as='question' class="panel panel-default mt16">
<t t-set="input_summary" t-value="get_input_summary(question)"/>
<div class="panel-heading">
<h3 class="panel-title">
<b>Question </b>
<span t-field='question.question'></span>
<span class="pull-right">
<span class="label label-success"><span t-esc="input_summary['answered']"></span> Answered</span>
<span class="label label-danger"><span t-esc="input_summary['skipped']"></span> Skipped</span>
</span>
</h3>
</div>
<t t-if="question.type in ['textbox', 'free_text']">
<t t-call="survey.result_text"></t>
</t>
<t t-if="question.type in ['simple_choice', 'multiple_choice']">
<t t-call="survey.result_choice"></t>
</t>
<t t-if="question.type == 'matrix'">
<t t-call="survey.result_matrix"></t>
</t>
<t t-if="question.type == 'numerical_box'">
<t t-call="survey.result_number"></t>
</t>
</div>
</div>
</div>
</div>
</div>
</t>
</template>
<!-- Result for free_text and textbox -->
<template id="result_text" name="Text Result">
<table class="table table-hover" t-att-id="'table_question_'+str(question.id)">
<thead>
<tr>
<th>#</th>
<th>User Responses</th>
</tr>
</thead>
<tbody>
<tr class="hidden" t-foreach="question.user_input_line_ids" t-as="user_input">
<td><t t-esc="user_input_index+1"></t></td>
<t t-if="question.type == 'free_text'">
<td>
<span t-field="user_input.value_free_text"></span><br/>
<small><p t-field="user_input.date_create" class="fa fa-calendar oe_date text-muted"></p></small>
</td>
</t>
<t t-if="question.type == 'textbox'">
<td>
<span t-field="user_input.value_text"></span><br/>
<small><p t-field="user_input.date_create" class="fa fa-calendar oe_date text-muted"></p></small>
</td>
</t>
</tr>
</tbody>
</table>
<!-- Pagination Element -->
<ul t-att-id="'pagination_'+str(question.id)" class="pagination" >
<t t-if="len(question.user_input_line_ids) > 5">
<li t-foreach="page_range(len(question.user_input_line_ids))" t-as="num">
<a href="#" t-esc="num"></a>
</li>
</t>
</ul>
<!-- Dynamic Script for Pagination Element -->
<script>
$( document ).ready(function() {
$('#table_question_<t t-esc="question.id"></t> tbody tr:lt(5)').removeClass('hidden');
$('#<t t-esc="'pagination_'+str(question.id)"></t> li:first').addClass('active');
$('#<t t-esc="'pagination_'+str(question.id)"></t> li a').click(function(event){
event.preventDefault();
$('#<t t-esc="'pagination_'+str(question.id)"></t> li').removeClass('active');
$(this).parent('li').addClass('active');
$('#table_question_<t t-esc="question.id"></t> tbody tr').addClass('hidden');
var num = $(this).text();
min = (5 * (num-1))-1;
if (min == -1){
$('#table_question_<t t-esc="question.id"></t> tbody tr:lt('+5 * num+')').removeClass('hidden');
}
else{
$('#table_question_<t t-esc="question.id"></t> tbody tr:lt('+5 * num+'):gt('+min+')').removeClass('hidden');
}
});
});
</script>
</template>
<!-- Result for simple_choice and multiple_choice -->
<template id="result_choice" name="Choice Result">
<div>
<!-- Tabs -->
<ul class="nav nav-tabs">
<li class="active">
<a t-att-href="'#graph_question_'+str(question.id)" data-toggle="tab">
<i class="fa fa-bar-chart-o"></i> Graph
</a>
</li>
<li>
<a t-att-href="'#data_question_'+str(question.id)" data-toggle="tab">
<i class="fa fa-list-alt"></i> Data
</a>
</li>
</ul>
<div class="tab-content">
<div class="tab-pane active" t-att-id="'graph_question_'+str(question.id)">
<!-- Dynamic script for single bar chart -->
<script>
var question_<t t-esc="question.id"></t> = <t t-esc="get_graph_data(question)"></t>;
nv.addGraph(function() {
var chart = nv.models.discreteBarChart()
.x(function(d) { return d.text })
.y(function(d) { return d.count })
.staggerLabels(true)
.tooltips(false)
.showValues(true)
// Custom Tick fuction for replacing long text with '...'
var customtick_function = function(d){
if(this.hasOwnProperty('window') || d.length &lt; 35){
return d;
}
else{
return d.slice(0,35)+'...';
}
}
chart.xAxis
.tickFormat(customtick_function);
chart.yAxis
.tickFormat(d3.format('d'));
d3.select('#graph_question_<t t-esc="question.id"></t> svg')
.datum(question_<t t-esc="question.id"></t>)
.transition().duration(500)
.call(chart);
nv.utils.windowResize(chart.update);
return chart;
});
</script>
<!-- svg element for drawing bar chart -->
<svg style="height:20em"></svg>
</div>
<div class="tab-pane" t-att-id="'data_question_'+str(question.id)">
<table class="table table-hover">
<thead>
<tr>
<th>Answer Choices</th>
<th>User Responses</th>
</tr>
</thead>
<tbody>
<tr t-foreach="prepare_result(question)" t-as="user_input">
<td>
<p t-esc="user_input['text']"></p>
</td>
<td>
<span t-esc="round(user_input['count']*100.0/input_summary['answered'],2)"></span> %
<span t-esc="user_input['count']" class="label label-primary">Vote</span>
</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
</template>
<!-- Result for matrix -->
<template id="result_matrix" name="Matrix Result">
<t t-set="matrix_result" t-value="prepare_result(question)" />
<!-- Tabs -->
<ul class="nav nav-tabs">
<li class="active">
<a t-att-href="'#graph_question_'+str(question.id)" data-toggle="tab">
<i class="fa fa-bar-chart-o"></i>
Graph
</a>
</li>
<li>
<a t-att-href="'#data_question_'+str(question.id)" data-toggle="tab">
<i class="fa fa-list-alt"></i>
Data
</a>
</li>
</ul>
<div class="tab-content">
<div class="tab-pane active with-3d-shadow with-transitions" t-att-id="'graph_question_'+str(question.id)">
<!-- Dynamic script for Multi bar chart -->
<script>
var question_<t t-esc="question.id"></t> = <t t-esc="get_graph_data(question)"></t>;
nv.addGraph(function(){
var chart = nv.models.multiBarChart()
.x(function(d) { return d.text })
.y(function(d) { return d.count })
.staggerLabels(true);
// Replacing Library's Default Tooltip with our Custom One
chart.tooltip(function(key, x, y, e, graph) {
return '<h5 class="panel-primary"><div class="panel-heading">' + x + '</div></h5>' +
'<p>'+ '<b>Responses : </b>' + key + '</p>' +
'<p>' + "<b>Total Vote : </b>" + y + '</p>'
})
// Custom Tick fuction for replacing long text with '...'
var customtick_function = function(d){
if(this.hasOwnProperty('window') || d.length &lt; 25){
return d;
}
else{
return d.slice(0,25)+'...';
}
}
chart.xAxis
.tickFormat(customtick_function);
chart.yAxis
.tickFormat(d3.format('d'));
d3.select('#graph_question_<t t-esc="question.id"></t> svg')
.datum(question_<t t-esc="question.id"></t>)
.transition().duration(500).call(chart);
nv.utils.windowResize(chart.update);
return chart;
});
</script>
<!-- svg element for drawing Multibar chart -->
<svg style="height:20em"></svg>
</div>
<div class="tab-pane" t-att-id="'data_question_'+str(question.id)">
<table class="table table-hover text-right">
<thead>
<tr>
<th></th>
<th class="text-right" t-foreach="matrix_result['answers']" t-as="answer_id">
<span t-esc="matrix_result['answers'][answer_id]"></span>
</th>
</tr>
</thead>
<tbody>
<tr t-foreach="matrix_result['rows']" t-as="row_id">
<td>
<span t-esc="matrix_result['rows'][row_id]"></span>
</td>
<td t-foreach="matrix_result['answers']" t-as="answer_id">
<span t-esc="round(matrix_result['result'][(row_id,answer_id)]*100.0/input_summary['answered'],2)"></span> %
<span class="label label-primary" t-esc="matrix_result['result'][(row_id,answer_id)]"></span>
</td>
</tr>
</tbody>
</table>
</div>
</div>
</template>
<template id="result_number" name="Number Result">
<t t-set="number_result" t-value="prepare_result(question)" />
<span class="pull-right">
<span class="label label-default only_right_radius">Maximum </span> <span class="label label-success only_left_radius" t-esc="number_result['max']"></span>
<span class="label label-default only_right_radius">Minimum </span> <span class="label label-danger only_left_radius" t-esc="number_result['min']"></span>
<span class="label label-default only_right_radius">Average </span> <span class="label label-warning only_left_radius" t-esc="number_result['average']"></span>
</span>
<h3>Most Common <span t-esc="len(number_result['most_comman'])"></span></h3>
<table class="table table-hover">
<thead>
<tr>
<th>User Responce</th>
<th>Occurence</th>
</tr>
</thead>
<tbody>
<tr t-foreach="number_result['most_comman']" t-as="row">
<td>
<span t-esc="row[0]"></span>
</td>
<td>
<span t-esc="row[1]"></span>
</td>
</tr>
</tbody>
</table>
</template>
</data>
</openerp>

View File

@ -130,6 +130,7 @@
<field name="visible_to_user" />
<field name="auth_required" />
<field name="public_url" widget="url" attrs="{'invisible': [('visible_to_user', '=', False)]}"/>
<field name="result_url" widget="url"/>
</group>
<field name="description" />
<notebook>