402 lines
15 KiB
JavaScript
402 lines
15 KiB
JavaScript
flectra.define('web.planner.common', function (require) {
|
|
"use strict";
|
|
|
|
var core = require('web.core');
|
|
var Dialog = require('web.Dialog');
|
|
var dom = require('web.dom');
|
|
var rpc = require('web.rpc');
|
|
var session = require('web.session');
|
|
var utils = require('web.utils');
|
|
var weContext = require('web_editor.context');
|
|
var Widget = require('web.Widget');
|
|
|
|
var QWeb = core.qweb;
|
|
|
|
var _t = core._t;
|
|
|
|
var MIN_PROGRESS = 7;
|
|
|
|
var Page = core.Class.extend({
|
|
init: function (dom, page_index) {
|
|
this.$dom = $(dom);
|
|
this.hide_from_menu = this.$dom.attr('hide-from-menu');
|
|
this.hide_mark_as_done = this.$dom.attr('hide-mark-as-done');
|
|
this.done = false;
|
|
this.menu_item = null;
|
|
this.title = this.$dom.find('[data-menutitle]').data('menutitle');
|
|
this.set_page_id(this.title.replace(/\s/g, '') + page_index);
|
|
},
|
|
set_page_id: function (id) {
|
|
this.id = id;
|
|
this.$dom.attr('id', id);
|
|
},
|
|
get_category_name: function (category_selector) {
|
|
return this.$dom.parents(category_selector).attr('menu-category-id');
|
|
},
|
|
});
|
|
|
|
var PlannerDialog = Dialog.extend({
|
|
template: "PlannerDialog",
|
|
category_selector: "div[menu-category-id]",
|
|
events: {
|
|
"click li a[href^=\"#\"]:not([data-toggle=\"collapse\"])": function (e) {
|
|
e.preventDefault();
|
|
this._display_page($(e.currentTarget).attr("href").replace("#", ""));
|
|
},
|
|
},
|
|
init: function (parent, options, planner) {
|
|
this._super.apply(this, arguments);
|
|
|
|
this.planner = planner;
|
|
this.cookie_name = this.planner.planner_application + '_last_page';
|
|
this.pages = [];
|
|
this.menu_items = [];
|
|
this.currently_shown_page = null;
|
|
this.currently_active_menu_item = null,
|
|
|
|
this.on("change:progress", this, function () {
|
|
this.trigger('planner_progress_changed', this.get('progress'));
|
|
});
|
|
this.set("progress", this.planner.progress || MIN_PROGRESS);
|
|
},
|
|
/**
|
|
* Fetch the planner's rendered template
|
|
*/
|
|
willStart: function() {
|
|
// fallback context for frontend
|
|
var context = session.is_frontend ? weContext.get() : session.user_context;
|
|
var def = rpc.query({
|
|
model: 'web.planner',
|
|
method: 'render',
|
|
args: [this.planner.view_id[0], this.planner.planner_application],
|
|
context: context,
|
|
})
|
|
.then((function (template) {
|
|
this.$template = $(template);
|
|
}).bind(this));
|
|
|
|
return $.when(this._super.apply(this, arguments), def);
|
|
},
|
|
start: function() {
|
|
this.$modal.addClass("o_planner_dialog");
|
|
this.$template.find(".o_planner_page").addBack(".o_planner_page").each((function (index, dom_page) {
|
|
this.pages.push(new Page(dom_page, index));
|
|
}).bind(this));
|
|
|
|
this.$menu = this.$('> .o_planner_menu');
|
|
this.$menu.html(this._render_menu());
|
|
this.menu_items = this.$menu.find("li");
|
|
_.each(this.pages, (function (page) {
|
|
page.menu_item = this._find_menu_item_by_page_id(page.id);
|
|
}).bind(this));
|
|
|
|
this.$el.append(this.$template);
|
|
|
|
// update the planner_data with the new inputs of the view
|
|
var actual_vals = this._get_values();
|
|
this.planner.data = _.defaults(this.planner.data, actual_vals);
|
|
// set the default value
|
|
this._set_values(this.planner.data);
|
|
// show last opened page
|
|
this._show_last_open_page();
|
|
|
|
this.on("planner_progress_changed", this, this._update_title);
|
|
this._update_title();
|
|
|
|
this.prepare_planner_event();
|
|
|
|
return this._super.apply(this, arguments);
|
|
},
|
|
prepare_planner_event: function () {}, // overriden by modules
|
|
toggle_current_page_status: function () {
|
|
this.currently_shown_page.done = !this.currently_shown_page.done;
|
|
this._render_page_status(this.currently_shown_page, true);
|
|
this._update_buttons();
|
|
this._update_planner();
|
|
},
|
|
change_to_next_page: function (ev) {
|
|
ev.preventDefault();
|
|
this._display_page(this._get_next_page_id());
|
|
},
|
|
_update_title: function () {
|
|
this.set_title(core.qweb.render("PlannerDialog.Title", {
|
|
title: this.currently_shown_page.title,
|
|
percent: this.get("progress")
|
|
}));
|
|
},
|
|
_update_buttons: function () {
|
|
var page = this.currently_shown_page;
|
|
var buttons = [];
|
|
if (!page.hide_mark_as_done) {
|
|
buttons.push({
|
|
text: _t("Mark As Done"),
|
|
icon: page.done ? "fa-check-square-o" : "fa-square-o",
|
|
classes: "o_mark_as_done btn-" + (page.done ? "default" : "primary"),
|
|
click: this.toggle_current_page_status
|
|
});
|
|
}
|
|
if (this._get_next_page_id()) {
|
|
buttons.push({
|
|
text: _t("Next Step"),
|
|
icon: "fa-angle-right pull-right mt4",
|
|
classes: "o_next_step btn-" + ((page.done || page.hide_mark_as_done) ? "primary" : "default"),
|
|
click: this.change_to_next_page
|
|
});
|
|
}
|
|
this.set_buttons(buttons);
|
|
},
|
|
_render_page_status: function (page, withAnim) {
|
|
$(page.menu_item).find('span').toggleClass('fa-check', !!page.done);
|
|
if (withAnim && page.done) { // page checked animation
|
|
page.$dom.addClass('marked');
|
|
_.delay(function () {
|
|
page.$dom.removeClass('marked');
|
|
}, 1000);
|
|
}
|
|
},
|
|
_show_last_open_page: function () {
|
|
var last_open_page = utils.get_cookie(this.cookie_name);
|
|
if (!last_open_page) {
|
|
last_open_page = this.planner.data.last_open_page || false;
|
|
}
|
|
|
|
if (last_open_page && this._find_page_by_id(last_open_page)) {
|
|
this._display_page(last_open_page);
|
|
} else {
|
|
this._display_page(this.pages[0].id);
|
|
}
|
|
},
|
|
_render_menu: function() {
|
|
var orphan_pages = [];
|
|
var menu_categories = [];
|
|
var menu_item_page_map = {};
|
|
|
|
// pages with no category
|
|
_.each(this.pages, (function (page) {
|
|
if (!page.hide_from_menu && !page.get_category_name(this.category_selector)) {
|
|
_create_menu_item(page, orphan_pages, menu_item_page_map);
|
|
}
|
|
}).bind(this));
|
|
|
|
// pages with a category
|
|
this.$template.filter(this.category_selector).each((function (index, menu_category) {
|
|
var $menu_category = $(menu_category);
|
|
var menu_category_item = {
|
|
name: $menu_category.attr('menu-category-id'),
|
|
classes: $menu_category.attr('menu-classes'),
|
|
menu_items: [],
|
|
};
|
|
|
|
_.each(this.pages, (function (page) {
|
|
if (!page.hide_from_menu && page.get_category_name(this.category_selector) === menu_category_item.name) {
|
|
_create_menu_item(page, menu_category_item.menu_items, menu_item_page_map);
|
|
}
|
|
}).bind(this));
|
|
|
|
menu_categories.push(menu_category_item);
|
|
|
|
// remove the branding used to separate the pages
|
|
this.$template = this.$template.not($menu_category);
|
|
this.$template = this.$template.add($menu_category.contents());
|
|
}).bind(this));
|
|
|
|
return QWeb.render('PlannerMenu', {
|
|
'orphan_pages': orphan_pages,
|
|
'menu_categories': menu_categories,
|
|
'menu_item_page_map': menu_item_page_map
|
|
});
|
|
|
|
function _create_menu_item(page, menu_items, menu_item_page_map) {
|
|
var $menu_item_element = page.$dom.find('h1[data-menutitle]');
|
|
var menu_title = $menu_item_element.data('menutitle') || $menu_item_element.text();
|
|
|
|
menu_items.push(menu_title);
|
|
menu_item_page_map[menu_title] = page.id;
|
|
}
|
|
},
|
|
_get_next_page_id: function () {
|
|
var currentID = this.currently_shown_page.id;
|
|
var currentIndex = _.findIndex(this.pages, function (page) {
|
|
return page.id === currentID;
|
|
});
|
|
var nextPage = this.pages[currentIndex + 1];
|
|
return nextPage ? nextPage.id : null;
|
|
},
|
|
_find_page_by_id: function (id) {
|
|
return _.find(this.pages, function (page) {
|
|
return page.id === id;
|
|
});
|
|
},
|
|
_find_menu_item_by_page_id: function (page_id) {
|
|
return _.find(this.menu_items, function (menu_item) {
|
|
var $menu_item = $(menu_item);
|
|
return $($menu_item.find('a')).attr('href') === '#' + page_id;
|
|
});
|
|
},
|
|
_display_page: function (page_id) {
|
|
if (!page_id) return;
|
|
|
|
var self = this;
|
|
var page = this._find_page_by_id(page_id);
|
|
if (this.currently_active_menu_item) {
|
|
$(this.currently_active_menu_item).removeClass('active');
|
|
}
|
|
|
|
var menu_item = this._find_menu_item_by_page_id(page_id);
|
|
$(menu_item).addClass('active');
|
|
this.currently_active_menu_item = menu_item;
|
|
|
|
if (this.currently_shown_page) {
|
|
this.currently_shown_page.$dom.removeClass('show');
|
|
}
|
|
|
|
page.$dom.addClass('show');
|
|
this.currently_shown_page = page;
|
|
|
|
this._update_title();
|
|
this._render_page_status(this.currently_shown_page);
|
|
this._update_buttons();
|
|
|
|
this.planner.data.last_open_page = page_id;
|
|
utils.set_cookie(this.cookie_name, page_id, 8*60*60); // create cookie for 8h
|
|
this.$el.scrollTop("0");
|
|
|
|
this.$('textarea').each(function () {
|
|
dom.autoresize($(this), {parent: self});
|
|
});
|
|
},
|
|
// planner data functions
|
|
_get_values: function (page) {
|
|
// if no page_id, take the complete planner
|
|
var base_elem = page ? page.$dom : this.$(".o_planner_page");
|
|
var values = {};
|
|
// get the selector for all the input and mark_button
|
|
// only INPUT (select, textearea, input, checkbox and radio), and BUTTON (.mark_button#) are observed
|
|
var inputs = base_elem.find("textarea[id^='input_element'], input[id^='input_element'], select[id^='input_element'], button[id^='mark_button']");
|
|
_.each(inputs, function(elem){
|
|
var $elem = $(elem);
|
|
var tid = $elem.attr('id');
|
|
if ($elem.prop("tagName") === 'BUTTON'){
|
|
if($elem.hasClass('fa-check-square-o')){
|
|
values[tid] = 'marked';
|
|
}else{
|
|
values[tid] = '';
|
|
}
|
|
}
|
|
if ($elem.prop("tagName") === 'INPUT' || $elem.prop("tagName") === 'TEXTAREA'){
|
|
var ttype = $elem.attr('type');
|
|
if (ttype === 'checkbox' || ttype === 'radio'){
|
|
values[tid] = '';
|
|
if ($elem.is(':checked')){
|
|
values[tid] = 'checked';
|
|
}
|
|
}else{
|
|
values[tid] = $elem.val();
|
|
}
|
|
}
|
|
});
|
|
|
|
this.pages.forEach(function(page) {
|
|
values[page.id] = page.done;
|
|
});
|
|
return values;
|
|
},
|
|
_set_values: function(values){
|
|
var self = this;
|
|
_.each(values, function (val, id) {
|
|
var $elem = self.$('[id="'+id+'"]');
|
|
if ($elem.prop("tagName") === 'BUTTON'){
|
|
if(val === 'marked'){
|
|
$elem.addClass('fa-check-square-o btn-default').removeClass('fa-square-o btn-primary');
|
|
self.$("li a[href=#"+$elem.data('pageid')+"] span").addClass('fa-check');
|
|
}
|
|
}
|
|
if ($elem.prop("tagName") === 'INPUT' || $elem.prop("tagName") === 'TEXTAREA'){
|
|
var ttype = $elem.attr("type");
|
|
if (ttype === 'checkbox' || ttype === 'radio'){
|
|
if (val === 'checked') {
|
|
$elem.attr('checked', 'checked');
|
|
}
|
|
}else{
|
|
$elem.val(val);
|
|
}
|
|
}
|
|
});
|
|
|
|
_.each(this.pages, function (page) {
|
|
page.done = values[page.id];
|
|
self._render_page_status(page);
|
|
});
|
|
},
|
|
_update_planner: function () {
|
|
// update the planner.data with the inputs
|
|
var vals = this._get_values(this.currently_shown_page);
|
|
this.planner.data = _.extend(this.planner.data, vals);
|
|
|
|
// re compute the progress percentage
|
|
var total_pages = 0;
|
|
var done_pages = 0;
|
|
|
|
_.each(this.pages, function (page) {
|
|
if (! page.hide_mark_as_done) {
|
|
total_pages++;
|
|
}
|
|
if (page.done) {
|
|
done_pages++;
|
|
}
|
|
});
|
|
var percent = MIN_PROGRESS + parseInt(done_pages / total_pages * (100 - MIN_PROGRESS), 10);
|
|
this.set('progress', percent);
|
|
|
|
this.planner.progress = percent;
|
|
// save data and progress in database
|
|
this._save_planner_data();
|
|
},
|
|
_save_planner_data: function() {
|
|
return rpc.query({
|
|
model: 'web.planner',
|
|
method: 'write',
|
|
args: [this.planner.id, {'data': JSON.stringify(this.planner.data), 'progress': this.planner.progress}],
|
|
});
|
|
},
|
|
});
|
|
|
|
var PlannerLauncher = Widget.extend({
|
|
template: "PlannerLauncher",
|
|
sequence: 100, // force it to be the left-most item in the systray to prevent flickering as it is not displayed in all apps
|
|
events: {
|
|
"click": "show_dialog"
|
|
},
|
|
start: function () {
|
|
this.$progress = this.$(".progress");
|
|
this.$progressBar = this.$progress.find(".progress-bar");
|
|
this.$progress.tooltip({html: true, placement: 'bottom', delay: {'show': 500}});
|
|
this._loadPlannerDef = this._fetch_planner_data();
|
|
return this._super.apply(this, arguments);
|
|
},
|
|
_fetch_planner_data: function () {},
|
|
show_dialog: function () {
|
|
return this._loadPlannerDef.then((function () {
|
|
this.dialog = new PlannerDialog(this, undefined, this.planner);
|
|
this.dialog.on("planner_progress_changed", this, this._update_parent_progress_bar);
|
|
this.dialog.open();
|
|
}).bind(this));
|
|
},
|
|
_setup_for_planner: function (planner) {
|
|
this.planner = planner;
|
|
this.$progress.attr('data-original-title', this.planner.tooltip_planner);
|
|
this._update_parent_progress_bar(this.planner.progress || MIN_PROGRESS);
|
|
},
|
|
_update_parent_progress_bar: function (percent) {
|
|
this.$progress.toggleClass("o_hidden", percent >= 100);
|
|
this.$progressBar.css('width', percent + "%");
|
|
},
|
|
});
|
|
|
|
return {
|
|
PlannerDialog: PlannerDialog,
|
|
PlannerLauncher: PlannerLauncher
|
|
};
|
|
|
|
});
|