seitime-frappe/public/js/wn/form/workflow.js

186 lines
5.5 KiB
JavaScript

// Copyright (c) 2013, Web Notes Technologies Pvt. Ltd.
// MIT License. See license.txt
wn.ui.form.States = Class.extend({
init: function(opts) {
$.extend(this, opts);
this.state_fieldname = wn.workflow.get_state_fieldname(this.frm.doctype);
// no workflow?
if(!this.state_fieldname)
return;
this.update_fields = wn.workflow.get_update_fields(this.frm.doctype);
var me = this;
$(this.frm.wrapper).bind("render_complete", function() {
me.refresh();
})
},
make: function() {
this.parent = this.frm.appframe.parent
.find(".workflow-button-area")
.empty()
.removeClass("hide");
this.workflow_button = $('<button class="btn btn-default dropdown-toggle">\
<i class="icon-small"></i> <span class="state-text"></span>\
<span class="caret"></span></button>')
.appendTo(this.parent).dropdown();
this.dropdown = $('<ul class="dropdown-menu">').insertAfter(this.workflow_button);
this.help_btn = $('<button class="btn btn-default"><i class="icon-question-sign"></i></button').
insertBefore(this.workflow_button);
this.setup_help();
this.bind_action();
},
setup_help: function() {
var me = this;
this.help_btn.click(function() {
wn.workflow.setup(me.frm.doctype);
var state = me.get_state();
var d = new wn.ui.Dialog({
title: "Workflow: "
+ wn.workflow.workflows[me.frm.doctype].name
})
var next_html = $.map(wn.workflow.get_transitions(me.frm.doctype, state),
function(d) {
return d.action.bold() + wn._(" by Role ") + d.allowed;
}).join(", ") || wn._("None: End of Workflow").bold();
$(d.body).html("<p>"+wn._("Current status")+": " + state.bold() + "</p>"
+ "<p>"+wn._("Document is only editable by users of role")+": "
+ wn.workflow.get_document_state(me.frm.doctype,
state).allow_edit.bold() + "</p>"
+ "<p>"+wn._("Next actions")+": "+ next_html +"</p>"
+ (me.frm.doc.__islocal ? ("<div class='alert alert-info'>"
+wn._("Workflow will start after saving.")+"</div>") : "")
+ "<p class='help'>"+wn._("Note: Other permission rules may also apply")+"</p>"
).css({padding: '15px'});
d.show();
});
},
refresh: function() {
// hide if its not yet saved
if(this.frm.doc.__islocal) {
this.set_default_state();
this.parent.toggle(false);
return;
}
this.make();
// state text
var state = this.get_state();
if(state) {
// show current state on the button
this.workflow_button.find(".state-text").text(state);
var state_doc = wn.model.get("Workflow State", {name:state})[0];
// set the icon
this.workflow_button.find('i').removeClass()
.addClass("icon-white")
.addClass("icon-" + state_doc.icon);
// set the style
this.workflow_button.removeClass().addClass("btn btn-default dropdown-toggle")
if(state_doc && state_doc.style)
this.workflow_button.addClass("btn-" + state_doc.style.toLowerCase());
// show actions from that state
this.show_actions(state);
if(this.frm.doc.__islocal) {
this.workflow_button.prop('disabled', true);
}
}
},
show_actions: function(state) {
var $ul = this.dropdown;
$ul.empty();
$.each(wn.workflow.get_transitions(this.frm.doctype, state), function(i, d) {
if(in_list(user_roles, d.allowed)) {
d.icon = wn.model.get("Workflow State", {name:d.next_state})[0].icon;
$(repl('<li><a href="#" data-action="%(action)s">\
<i class="icon icon-%(icon)s"></i> %(action)s</a></li>', d))
.appendTo($ul);
}
});
// disable the button if user cannot change state
var is_final = !$ul.find("li").length;
this.workflow_button
.prop('disabled', is_final);
this.workflow_button.find(".caret").toggle(is_final ? false : true)
},
set_default_state: function() {
var default_state = wn.workflow.get_default_state(this.frm.doctype);
if(default_state) {
this.frm.set_value(this.state_fieldname, default_state);
}
},
get_state: function() {
if(!this.frm.doc[this.state_fieldname]) {
this.set_default_state();
}
return this.frm.doc[this.state_fieldname];
},
bind_action: function() {
var me = this;
this.dropdown.on("click", "[data-action]", function() {
var action = $(this).attr("data-action");
// capture current state
var doc_before_action = copy_dict(me.frm.doc);
// set new state
var next_state = wn.workflow.get_next_state(me.frm.doctype,
me.frm.doc[me.state_fieldname], action);
me.frm.doc[me.state_fieldname] = next_state;
var new_state = wn.workflow.get_document_state(me.frm.doctype, next_state);
var new_docstatus = cint(new_state.doc_status);
// update field and value
if(new_state.update_field) {
me.frm.set_value(new_state.update_field, new_state.update_value);
}
// revert state on error
var on_error = function() {
// reset in locals
locals[me.frm.doctype][me.frm.docname] = doc_before_action;
me.frm.refresh();
}
if(new_docstatus==1 && me.frm.doc.docstatus==0) {
me.frm.savesubmit(null, on_error);
} else if(new_docstatus==0 && me.frm.doc.docstatus==0) {
me.frm.save("Save", null, null, on_error);
} else if(new_docstatus==1 && me.frm.doc.docstatus==1) {
me.frm.save("Update", null, null, on_error);
} else if(new_docstatus==2 && me.frm.doc.docstatus==1) {
me.frm.savecancel(null, on_error);
} else {
msgprint(wn._("Document Status transition from ") + me.frm.doc.docstatus + " "
+ wn._("to") +
new_docstatus + " " + wn._("is not allowed."));
return false;
}
// hide dropdown
$(this).parents(".dropdown-menu:first").prev().dropdown('toggle');
return false;
})
}
});