@@ -68,7 +68,7 @@ wn.RoleEditor = Class.extend({ | |||
for(var i in this.roles) { | |||
$(this.wrapper).append(repl('<div class="user-role" \ | |||
data-user-role="%(role)s">\ | |||
<input type="checkbox"> \ | |||
<input type="checkbox" style="margin-top:0px;"> \ | |||
<a href="#">%(role)s</a>\ | |||
</div>', {role: this.roles[i]})); | |||
} | |||
@@ -3,17 +3,29 @@ wn.provide("wn.core") | |||
wn.core.Workflow = wn.ui.form.Controller.extend({ | |||
refresh: function(doc) { | |||
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; | |||
} | |||
}); | |||
@@ -4,7 +4,7 @@ | |||
"docstatus": 0, | |||
"creation": "2012-12-28 10:49:56", | |||
"modified_by": "Administrator", | |||
"modified": "2012-12-28 11:37:31" | |||
"modified": "2012-12-28 14:06:23" | |||
}, | |||
{ | |||
"istable": 1, | |||
@@ -18,7 +18,6 @@ | |||
"name": "__common__", | |||
"parent": "Workflow Document State", | |||
"doctype": "DocField", | |||
"width": "200px", | |||
"parenttype": "DocType", | |||
"permlevel": 0, | |||
"parentfield": "fields" | |||
@@ -30,29 +29,45 @@ | |||
{ | |||
"doctype": "DocField", | |||
"label": "State", | |||
"width": "160px", | |||
"fieldname": "state", | |||
"fieldtype": "Link", | |||
"reqd": 1, | |||
"options": "Workflow State" | |||
}, | |||
{ | |||
"doctype": "DocField", | |||
"label": "Allow Edit", | |||
"fieldname": "allow_edit", | |||
"fieldtype": "Link", | |||
"reqd": 0, | |||
"options": "Role" | |||
}, | |||
{ | |||
"doctype": "DocField", | |||
"label": "Doc Status", | |||
"width": "80px", | |||
"fieldname": "doc_status", | |||
"fieldtype": "Select", | |||
"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", | |||
"label": "Message", | |||
"width": "160px", | |||
"fieldname": "message", | |||
"fieldtype": "Text", | |||
"reqd": 0 | |||
@@ -153,6 +153,7 @@ | |||
"lib/public/js/legacy/wn/widgets/form/assign_to.js", | |||
"lib/public/js/wn/form/attachments.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/lib/jquery/jquery.ui.interactions.min.js', | |||
@@ -185,6 +185,11 @@ _f.Frm.prototype.setup_std_layout = function() { | |||
this.setup_sidebar(); | |||
} | |||
// state | |||
this.states = new wn.ui.form.States({ | |||
frm: this | |||
}); | |||
// watermark | |||
$('<div style="font-size: 21px; color: #aaa; float: right;\ | |||
margin-top: -5px; margin-right: -5px; z-index: 5;">' | |||
@@ -805,34 +810,36 @@ _f.Frm.prototype.runclientscript = function(caller, cdt, cdn) { | |||
validated = false; | |||
console.log(e); | |||
} | |||
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) { | |||
@@ -39,6 +39,7 @@ wn.PageLayout = function(args) { | |||
this.main = $a(this.wrapper, 'div', 'layout-main-section'); | |||
this.sidebar_area = $a(this.wrapper, 'div', 'layout-side-section'); | |||
$a(this.wrapper, 'div', '', {clear:'both'}); | |||
this.body_header = $a(this.main, 'div'); | |||
this.body = $a(this.main, 'div'); | |||
this.footer = $a(this.main, 'div'); | |||
if(this.heading) { | |||
@@ -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; | |||
}) | |||
} | |||
}); |
@@ -16,7 +16,17 @@ wn.utils = { | |||
} | |||
$.each(dict, function(i, d) { | |||
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); | |||
}); | |||
@@ -104,5 +104,10 @@ $.extend(wn.meta, { | |||
$.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; | |||
}, | |||
}); |