Browse Source

integrated workflow in form

version-14
Rushabh Mehta 12 years ago
parent
commit
3c69a80521
9 changed files with 264 additions and 45 deletions
  1. +1
    -1
      core/doctype/profile/profile.js
  2. +22
    -10
      core/doctype/workflow/workflow.js
  3. +25
    -10
      core/doctype/workflow_document_state/workflow_document_state.txt
  4. +1
    -0
      public/build.json
  5. +29
    -22
      public/js/legacy/widgets/form/form.js
  6. +1
    -0
      public/js/legacy/wn/page_layout.js
  7. +168
    -0
      public/js/wn/form/states.js
  8. +11
    -1
      public/js/wn/misc/utils.js
  9. +6
    -1
      public/js/wn/model/meta.js

+ 1
- 1
core/doctype/profile/profile.js View File

@@ -68,7 +68,7 @@ wn.RoleEditor = Class.extend({
for(var i in this.roles) { for(var i in this.roles) {
$(this.wrapper).append(repl('<div class="user-role" \ $(this.wrapper).append(repl('<div class="user-role" \
data-user-role="%(role)s">\ data-user-role="%(role)s">\
<input type="checkbox"> \
<input type="checkbox" style="margin-top:0px;"> \
<a href="#">%(role)s</a>\ <a href="#">%(role)s</a>\
</div>', {role: this.roles[i]})); </div>', {role: this.roles[i]}));
} }


+ 22
- 10
core/doctype/workflow/workflow.js View File

@@ -3,17 +3,29 @@ wn.provide("wn.core")
wn.core.Workflow = wn.ui.form.Controller.extend({ wn.core.Workflow = wn.ui.form.Controller.extend({
refresh: function(doc) { refresh: function(doc) {
this.frm.set_intro(""); this.frm.set_intro("");
if(doc.is_custom=="No" && !in_list(user_roles, 'Administrator')) {
// make the document read-only
this.frm.perm[0][WRITE] = 0;

this.frm.set_intro('Standard Workflow editable by Administrator only. \
To edit workflow, copy this and create a new Custom workflow for this Document Type')
} else {
if(doc.is_active) {
this.frm.set_intro("This Workflow is active.");
}
if(doc.is_active) {
this.frm.set_intro("This Workflow is active.");
}
this.load_document_type(doc);
},
document_type: function(doc) {
this.load_document_type(doc);
},
load_document_type: function(doc) {
var me = this;
if(!locals.DocType[doc.document_type]) {
wn.model.with_doctype(doc.document_type, function() {
me.update_field_options();
});
} }
},
update_field_options: function() {
var fields = $.map(wn.model.get("DocField", {
parent: this.frm.doc.document_type,
fieldtype: ["not in", wn.model.no_value_type]
}),
function(d) { return d.fieldname; });
wn.meta.get_docfield("Workflow Document State", "update_field").options = fields;
} }
}); });



+ 25
- 10
core/doctype/workflow_document_state/workflow_document_state.txt View File

@@ -4,7 +4,7 @@
"docstatus": 0, "docstatus": 0,
"creation": "2012-12-28 10:49:56", "creation": "2012-12-28 10:49:56",
"modified_by": "Administrator", "modified_by": "Administrator",
"modified": "2012-12-28 11:37:31"
"modified": "2012-12-28 14:06:23"
}, },
{ {
"istable": 1, "istable": 1,
@@ -18,7 +18,6 @@
"name": "__common__", "name": "__common__",
"parent": "Workflow Document State", "parent": "Workflow Document State",
"doctype": "DocField", "doctype": "DocField",
"width": "200px",
"parenttype": "DocType", "parenttype": "DocType",
"permlevel": 0, "permlevel": 0,
"parentfield": "fields" "parentfield": "fields"
@@ -30,29 +29,45 @@
{ {
"doctype": "DocField", "doctype": "DocField",
"label": "State", "label": "State",
"width": "160px",
"fieldname": "state", "fieldname": "state",
"fieldtype": "Link", "fieldtype": "Link",
"reqd": 1, "reqd": 1,
"options": "Workflow State" "options": "Workflow State"
}, },
{
"doctype": "DocField",
"label": "Allow Edit",
"fieldname": "allow_edit",
"fieldtype": "Link",
"reqd": 0,
"options": "Role"
},
{ {
"doctype": "DocField", "doctype": "DocField",
"label": "Doc Status", "label": "Doc Status",
"width": "80px",
"fieldname": "doc_status", "fieldname": "doc_status",
"fieldtype": "Select", "fieldtype": "Select",
"options": "0\n1\n2" "options": "0\n1\n2"
}, },
{
"doctype": "DocField",
"label": "Update Field",
"fieldname": "update_field",
"fieldtype": "Select"
},
{
"doctype": "DocField",
"label": "Update Value",
"fieldname": "update_value",
"fieldtype": "Data"
},
{
"doctype": "DocField",
"label": "Only Allow Edit For",
"width": "160px",
"fieldname": "allow_edit",
"fieldtype": "Link",
"reqd": 1,
"options": "Role"
},
{ {
"doctype": "DocField", "doctype": "DocField",
"label": "Message", "label": "Message",
"width": "160px",
"fieldname": "message", "fieldname": "message",
"fieldtype": "Text", "fieldtype": "Text",
"reqd": 0 "reqd": 0


+ 1
- 0
public/build.json View File

@@ -153,6 +153,7 @@
"lib/public/js/legacy/wn/widgets/form/assign_to.js", "lib/public/js/legacy/wn/widgets/form/assign_to.js",
"lib/public/js/wn/form/attachments.js", "lib/public/js/wn/form/attachments.js",
"lib/public/js/wn/form/linked_with.js", "lib/public/js/wn/form/linked_with.js",
"lib/public/js/wn/form/states.js",
"lib/public/js/wn/print/print_table.js", "lib/public/js/wn/print/print_table.js",


'lib/public/js/lib/jquery/jquery.ui.interactions.min.js', 'lib/public/js/lib/jquery/jquery.ui.interactions.min.js',


+ 29
- 22
public/js/legacy/widgets/form/form.js View File

@@ -185,6 +185,11 @@ _f.Frm.prototype.setup_std_layout = function() {
this.setup_sidebar(); this.setup_sidebar();
} }
// state
this.states = new wn.ui.form.States({
frm: this
});
// watermark // watermark
$('<div style="font-size: 21px; color: #aaa; float: right;\ $('<div style="font-size: 21px; color: #aaa; float: right;\
margin-top: -5px; margin-right: -5px; z-index: 5;">' margin-top: -5px; margin-right: -5px; z-index: 5;">'
@@ -805,34 +810,36 @@ _f.Frm.prototype.runclientscript = function(caller, cdt, cdn) {
validated = false; validated = false;
console.log(e); console.log(e);
} }

if(caller && caller.toLowerCase()=='setup') { if(caller && caller.toLowerCase()=='setup') {
this.setup_client_js();
}
return ret;
}


var doctype = wn.model.get_doc('DocType', this.doctype);
// js
var cs = doctype.__js || (doctype.client_script_core + doctype.client_script);
if(cs) {
try {
var tmp = eval(cs);
} catch(e) {
console.log(e);
}
_f.Frm.prototype.setup_client_js = function(caller, cdt, cdn) {
var doctype = wn.model.get_doc('DocType', this.doctype);
// js
var cs = doctype.__js || (doctype.client_script_core + doctype.client_script);
if(cs) {
try {
var tmp = eval(cs);
} catch(e) {
console.log(e);
} }
}


// css
if(doctype.__css) set_style(doctype.__css)
// ---Client String----
if(doctype.client_string) { // split client string
this.cstring = {};
var elist = doctype.client_string.split('---');
for(var i=1;i<elist.length;i=i+2) {
this.cstring[strip(elist[i])] = elist[i+1];
}
// css
if(doctype.__css) set_style(doctype.__css)

// ---Client String----
if(doctype.client_string) { // split client string
this.cstring = {};
var elist = doctype.client_string.split('---');
for(var i=1;i<elist.length;i=i+2) {
this.cstring[strip(elist[i])] = elist[i+1];
} }
} }
return ret;
} }


_f.Frm.prototype.copy_doc = function(onload, from_amend) { _f.Frm.prototype.copy_doc = function(onload, from_amend) {


+ 1
- 0
public/js/legacy/wn/page_layout.js View File

@@ -39,6 +39,7 @@ wn.PageLayout = function(args) {
this.main = $a(this.wrapper, 'div', 'layout-main-section'); this.main = $a(this.wrapper, 'div', 'layout-main-section');
this.sidebar_area = $a(this.wrapper, 'div', 'layout-side-section'); this.sidebar_area = $a(this.wrapper, 'div', 'layout-side-section');
$a(this.wrapper, 'div', '', {clear:'both'}); $a(this.wrapper, 'div', '', {clear:'both'});
this.body_header = $a(this.main, 'div');
this.body = $a(this.main, 'div'); this.body = $a(this.main, 'div');
this.footer = $a(this.main, 'div'); this.footer = $a(this.main, 'div');
if(this.heading) { if(this.heading) {


+ 168
- 0
public/js/wn/form/states.js View File

@@ -0,0 +1,168 @@
// Copyright (c) 2012 Web Notes Technologies Pvt Ltd (http://erpnext.com)
//
// MIT License (MIT)
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
// PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
// OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//

wn.ui.form.States = Class.extend({
init: function(opts) {
$.extend(this, opts);
this.state_fieldname = wn.meta.get_state_fieldname(this.frm.doctype);
this.make();
this.bind_action();

var me = this;
$(this.frm.wrapper).bind("render_complete", function() {
me.refresh();
})
},
make: function() {
this.$wrapper = $('<div class="states" style="margin-bottom: 11px; height: 26px;">\
<div class="btn-group">\
<button class="btn dropdown-toggle" data-toggle="dropdown">\
<i class="icon-small"></i> <span class="state-text"></span> <span class="caret"></span></button>\
<ul class="dropdown-menu">\
</ul>\
</div>\
</div>').appendTo(this.frm.page_layout.body_header);
},
refresh: function() {
// hide if its not yet saved
if(this.frm.doc.__islocal) {
this.set_default_state();
this.$wrapper.toggle(false);
return;
}
this.$wrapper.toggle(true);
// state text
var state = this.get_state();
if(state) {
// show current state on the button
this.$wrapper.find(".state-text").text(state);
var state_doc = wn.model.get("Workflow State", {name:state})[0];

// set the icon
this.$wrapper.find('.icon-small').removeClass()
.addClass("icon-small icon-white")
.addClass("icon-" + state_doc.icon);

// set the style
this.$wrapper.find(".btn").removeClass()
.addClass("btn btn-small dropdown-toggle")
.addClass("btn-" + state_doc.style.toLowerCase());
// show actions from that state
this.show_actions(state);
// disable if not allowed
} else {
this.$wrapper.toggle(false);
}
},
show_actions: function(state) {
var $ul = this.$wrapper.find("ul");
$ul.empty();
$.each(wn.model.get("Workflow Transition", {
parent: this.frm.doctype,
state: 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
this.$wrapper.find('.btn').attr('disabled', $ul.find("li").length ? false : true);
},

set_default_state: function() {
var d = wn.model.get("Workflow Document State", {
parent: this.frm.doctype,
idx: 1
});
if(d && d.length) {
this.frm.set_value_in_locals(this.frm.doctype, this.frm.docname,
this.state_fieldname, d[0].state);
refresh_field(this.state_fieldname);
}
},
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.$wrapper).on("click", "[data-action]", function() {
var action = $(this).attr("data-action");
var next_state = wn.model.get("Workflow Transition", {
parent: me.frm.doctype,
state: me.frm.doc[me.state_fieldname],
action: action,
})[0].next_state;
me.frm.doc[me.state_fieldname] = next_state;
var new_state = wn.model.get("Workflow Document State", {
parent: me.frm.doctype,
state: next_state
})[0];

var new_docstatus = 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);
}
if(new_docstatus==1 && me.frm.doc.docstatus==0) {
me.frm.savesubmit();
} else if(new_docstatus==0 && me.frm.doc.docstatus==0) {
me.frm.save();
} else if(new_docstatus==1 && me.frm.doc.docstatus==1) {
me.frm.saveupdate();
} else if(new_docstatus==2 && me.frm.doc.docstatus==1) {
me.frm.savecancel();
} else {
msgprint("Docstatus transition from " + me.frm.doc.docstatus + " to" +
new_docstatus + " is not allowed.");
return;
}
// hide dropdown
$(this).parents(".dropdown-menu").prev().dropdown('toggle');
return false;
})
}
});

+ 11
- 1
public/js/wn/misc/utils.js View File

@@ -16,7 +16,17 @@ wn.utils = {
} }
$.each(dict, function(i, d) { $.each(dict, function(i, d) {
for(key in filters) { for(key in filters) {
if(d[key]!=filters[key]) return;
if($.isArray(filters[key])) {
if(filters[key][0]=="in") {
if(filters[key][1].indexOf(d[key])==-1)
return;
} else if(filters[key][0]=="not in") {
if(filters[key][1].indexOf(d[key])!=-1)
return;
}
} else {
if(d[key]!=filters[key]) return;
}
} }
ret.push(d); ret.push(d);
}); });


+ 6
- 1
public/js/wn/model/meta.js View File

@@ -104,5 +104,10 @@ $.extend(wn.meta, {
$.extend(wn._messages, doc.__messages); $.extend(wn._messages, doc.__messages);
} }
}, },

get_state_fieldname: function(doctype) {
var wf = wn.model.get("Workflow", {document_type: doctype});
return wf.length ? wf[0].workflow_state_field : null;
},

}); });

Loading…
Cancel
Save