diff --git a/addons/survey/static/src/js/fields_section_one2many.js b/addons/survey/static/src/js/fields_section_one2many.js
new file mode 100644
index 00000000000..590d98913d8
--- /dev/null
+++ b/addons/survey/static/src/js/fields_section_one2many.js
@@ -0,0 +1,180 @@
+odoo.define('survey.question_page_one2many', function (require){
+"use strict";
+
+var Context = require('web.Context');
+var FieldOne2Many = require('web.relational_fields').FieldOne2Many;
+var FieldRegistry = require('web.field_registry');
+var ListRenderer = require('web.ListRenderer');
+
+var SectionListRenderer = ListRenderer.extend({
+ init: function (parent, state, params) {
+ this.sectionFieldName = "is_page";
+ this._super.apply(this, arguments);
+ },
+ _checkIfRecordIsSection: function (id){
+ var record = this._findRecordById(id);
+ return record && record.data[this.sectionFieldName];
+ },
+ _findRecordById: function (id){
+ return _.find(this.state.data, function (record){
+ return record.id === id;
+ });
+ },
+ /**
+ * Allows to hide specific field in case the record is a section
+ * and, in this case, makes the 'title' field take the space of all the other
+ * fields
+ * @private
+ * @override
+ * @param {*} record
+ * @param {*} node
+ * @param {*} index
+ * @param {*} options
+ */
+ _renderBodyCell: function (record, node, index, options){
+ var $cell = this._super.apply(this, arguments);
+
+ var isSection = record.data[this.sectionFieldName];
+
+ if (isSection){
+ if (node.attrs.widget === "handle"){
+ return $cell;
+ } else if (node.attrs.name === "title"){
+ var nbrColumns = this._getNumberOfCols();
+ if (this.handleField){
+ nbrColumns--;
+ }
+ if (this.addTrashIcon){
+ nbrColumns--;
+ }
+ $cell.attr('colspan', nbrColumns);
+ } else {
+ $cell.removeClass('o_invisible_modifier');
+ return $cell.addClass('o_hidden');
+ }
+ }
+ return $cell;
+ },
+ /**
+ * Adds specific classes to rows that are sections
+ * to apply custom css on them
+ * @private
+ * @override
+ * @param {*} record
+ * @param {*} index
+ */
+ _renderRow: function (record, index){
+ var $row = this._super.apply(this, arguments);
+ if (record.data[this.sectionFieldName]) {
+ $row.addClass("o_is_section");
+ }
+ return $row;
+ },
+ /**
+ * Adding this class after the view is rendered allows
+ * us to limit the custom css scope to this particular case
+ * and no other
+ * @private
+ * @override
+ */
+ _renderView: function (){
+ var def = this._super.apply(this, arguments);
+ var self = this;
+ return def.then(function () {
+ self.$('table.o_list_table').addClass('o_section_list_view');
+ });
+ },
+ // Handlers
+ /**
+ * Overriden to allow different behaviours depending on
+ * the row the user clicked on.
+ * If the row is a section: edit inline
+ * else use a normal modal
+ * @private
+ * @override
+ * @param {*} ev
+ */
+ _onRowClicked: function (ev){
+ var parent = this.getParent();
+ var recordId = $(ev.currentTarget).data('id');
+ var is_section = this._checkIfRecordIsSection(recordId);
+ if (is_section && parent.mode === "edit"){
+ this.editable = "bottom";
+ } else {
+ this.editable = null;
+ }
+ this._super.apply(this, arguments);
+ },
+ /**
+ * Overriden to allow different behaviours depending on
+ * the cell the user clicked on.
+ * If the cell is part of a section: edit inline
+ * else use a normal edit modal
+ * @private
+ * @override
+ * @param {*} ev
+ */
+ _onCellClick: function (ev){
+ var parent = this.getParent();
+ var recordId = $(ev.currentTarget.parentElement).data('id');
+ var is_section = this._checkIfRecordIsSection(recordId);
+ if (is_section && parent.mode === "edit"){
+ this.editable = "bottom";
+ } else {
+ this.editable = null;
+ this.unselectRow();
+ }
+ this._super.apply(this, arguments);
+ },
+ /**
+ * In this case, navigating in the list caused issues.
+ * For example, editing a section then pressing enter would trigger
+ * the inline edition of the next element in the list. Which is not desired
+ * if the next element ends up being a question and not a section
+ * @override
+ * @param {*} ev
+ */
+ _onNavigationMove: function (ev){
+ this.unselectRow();
+ },
+});
+
+var SectionFieldOne2Many = FieldOne2Many.extend({
+ init: function (parent, name, record, options){
+ this._super.apply(this, arguments);
+ this.sectionFieldName = "is_page";
+ this.rendered = false;
+ },
+ /**
+ * Overriden to use our custom renderer
+ * @private
+ * @override
+ */
+ _getRenderer: function (){
+ if (this.view.arch.tag === 'tree'){
+ return SectionListRenderer;
+ }
+ return this._super.apply(this, arguments);
+ },
+ /**
+ * Overriden to allow different behaviours depending on
+ * the object we want to add. Adding a section would be done inline
+ * while adding a question would render a modal.
+ * @private
+ * @override
+ * @param {*} ev
+ */
+ _onAddRecord: function (ev) {
+ var context_str = ev.data.context && ev.data.context[0];
+ var context = new Context(context_str).eval();
+ if (context['default_' + this.sectionFieldName]){
+ this.editable = "bottom";
+ } else {
+ this.editable = null;
+ }
+ this._super.apply(this, arguments);
+ },
+});
+
+FieldRegistry.add('question_page_one2many', SectionFieldOne2Many);
+});
\ No newline at end of file
diff --git a/addons/survey/static/src/scss/survey_views.scss b/addons/survey/static/src/scss/survey_views.scss
index 92f4dd73a31..520efd97799 100644
--- a/addons/survey/static/src/scss/survey_views.scss
+++ b/addons/survey/static/src/scss/survey_views.scss
@@ -3,3 +3,10 @@
font-size: 20px;
}
}
+
+table.o_section_list_view tr.o_data_row.o_is_section {
+ font-weight: bold;
+ background-color: #DDD;
+ border-top: 1px solid #BBB;
+ border-bottom: 1px solid #BBB;
+}
diff --git a/addons/survey/views/assets.xml b/addons/survey/views/assets.xml
index 59dd9448fd6..b4b042a61e1 100644
--- a/addons/survey/views/assets.xml
+++ b/addons/survey/views/assets.xml
@@ -25,6 +25,7 @@
+
diff --git a/addons/survey/views/survey_question_views.xml b/addons/survey/views/survey_question_views.xml
index caeadc3d839..6a7a93a5916 100644
--- a/addons/survey/views/survey_question_views.xml
+++ b/addons/survey/views/survey_question_views.xml
@@ -12,11 +12,10 @@