Nie możesz wybrać więcej, niż 25 tematów Tematy muszą się zaczynać od litery lub cyfry, mogą zawierać myślniki ('-') i mogą mieć do 35 znaków.
 
 
 
 
 
 

188 wiersze
5.5 KiB

  1. // Copyright (c) 2013, Web Notes Technologies Pvt. Ltd.
  2. // MIT License. See license.txt
  3. wn.ui.form.States = Class.extend({
  4. init: function(opts) {
  5. $.extend(this, opts);
  6. this.state_fieldname = wn.workflow.get_state_fieldname(this.frm.doctype);
  7. // no workflow?
  8. if(!this.state_fieldname)
  9. return;
  10. this.update_fields = wn.workflow.get_update_fields(this.frm.doctype);
  11. var me = this;
  12. $(this.frm.wrapper).bind("render_complete", function() {
  13. me.refresh();
  14. })
  15. },
  16. make: function() {
  17. this.parent = this.frm.appframe.$w
  18. .find(".title-button-area-1")
  19. .empty()
  20. .toggle(true)
  21. .css({"margin-right":"5px"});
  22. this.workflow_button = $('<button class="btn btn-default dropdown-toggle">\
  23. <i class="icon-small"></i> <span class="state-text"></span>\
  24. <span class="caret"></span></button>')
  25. .appendTo(this.parent).dropdown();
  26. this.dropdown = $('<ul class="dropdown-menu">').insertAfter(this.workflow_button);
  27. this.help_btn = $('<button class="btn btn-default"><i class="icon-question-sign"></i></button').
  28. insertBefore(this.workflow_button);
  29. this.setup_help();
  30. this.bind_action();
  31. },
  32. setup_help: function() {
  33. var me = this;
  34. this.help_btn.click(function() {
  35. wn.workflow.setup(me.frm.doctype);
  36. var state = me.get_state();
  37. var d = new wn.ui.Dialog({
  38. title: "Workflow: "
  39. + wn.workflow.workflows[me.frm.doctype].name
  40. })
  41. var next_html = $.map(wn.workflow.get_transitions(me.frm.doctype, state),
  42. function(d) {
  43. return d.action.bold() + wn._(" by Role ") + d.allowed;
  44. }).join(", ") || wn._("None: End of Workflow").bold();
  45. $(d.body).html("<p>"+wn._("Current status")+": " + state.bold() + "</p>"
  46. + "<p>"+wn._("Document is only editable by users of role")+": "
  47. + wn.workflow.get_document_state(me.frm.doctype,
  48. state).allow_edit.bold() + "</p>"
  49. + "<p>"+wn._("Next actions")+": "+ next_html +"</p>"
  50. + (me.frm.doc.__islocal ? ("<div class='alert'>"
  51. +wn._("Workflow will start after saving.")+"</div>") : "")
  52. + "<p class='help'>"+wn._("Note: Other permission rules may also apply")+"</p>"
  53. ).css({padding: '15px'});
  54. d.show();
  55. });
  56. },
  57. refresh: function() {
  58. // hide if its not yet saved
  59. if(this.frm.doc.__islocal) {
  60. this.set_default_state();
  61. this.parent.toggle(false);
  62. return;
  63. }
  64. this.make();
  65. // state text
  66. var state = this.get_state();
  67. if(state) {
  68. // show current state on the button
  69. this.workflow_button.find(".state-text").text(state);
  70. var state_doc = wn.model.get("Workflow State", {name:state})[0];
  71. // set the icon
  72. this.workflow_button.find('i').removeClass()
  73. .addClass("icon-white")
  74. .addClass("icon-" + state_doc.icon);
  75. // set the style
  76. this.workflow_button.removeClass().addClass("btn btn-default dropdown-toggle")
  77. if(state_doc && state_doc.style)
  78. this.workflow_button.addClass("btn-" + state_doc.style.toLowerCase());
  79. // show actions from that state
  80. this.show_actions(state);
  81. if(this.frm.doc.__islocal) {
  82. this.workflow_button.attr('disabled', true);
  83. }
  84. }
  85. },
  86. show_actions: function(state) {
  87. var $ul = this.dropdown;
  88. $ul.empty();
  89. $.each(wn.workflow.get_transitions(this.frm.doctype, state), function(i, d) {
  90. if(in_list(user_roles, d.allowed)) {
  91. d.icon = wn.model.get("Workflow State", {name:d.next_state})[0].icon;
  92. $(repl('<li><a href="#" data-action="%(action)s">\
  93. <i class="icon icon-%(icon)s"></i> %(action)s</a></li>', d))
  94. .appendTo($ul);
  95. }
  96. });
  97. // disable the button if user cannot change state
  98. var is_final = !$ul.find("li").length;
  99. this.workflow_button
  100. .attr('disabled', is_final);
  101. this.workflow_button.find(".caret").toggle(is_final ? false : true)
  102. },
  103. set_default_state: function() {
  104. var default_state = wn.workflow.get_default_state(this.frm.doctype);
  105. if(default_state) {
  106. this.frm.set_value(this.state_fieldname, default_state);
  107. }
  108. },
  109. get_state: function() {
  110. if(!this.frm.doc[this.state_fieldname]) {
  111. this.set_default_state();
  112. }
  113. return this.frm.doc[this.state_fieldname];
  114. },
  115. bind_action: function() {
  116. var me = this;
  117. this.dropdown.on("click", "[data-action]", function() {
  118. var action = $(this).attr("data-action");
  119. // capture current state
  120. var doc_before_action = copy_dict(me.frm.doc);
  121. // set new state
  122. var next_state = wn.workflow.get_next_state(me.frm.doctype,
  123. me.frm.doc[me.state_fieldname], action);
  124. me.frm.doc[me.state_fieldname] = next_state;
  125. var new_state = wn.workflow.get_document_state(me.frm.doctype, next_state);
  126. var new_docstatus = cint(new_state.doc_status);
  127. // update field and value
  128. if(new_state.update_field) {
  129. me.frm.set_value(new_state.update_field, new_state.update_value);
  130. }
  131. // revert state on error
  132. var on_error = function() {
  133. // reset in locals
  134. locals[me.frm.doctype][me.frm.docname] = doc_before_action;
  135. me.frm.refresh();
  136. }
  137. if(new_docstatus==1 && me.frm.doc.docstatus==0) {
  138. me.frm.savesubmit(null, on_error);
  139. } else if(new_docstatus==0 && me.frm.doc.docstatus==0) {
  140. me.frm.save("Save", null, null, on_error);
  141. } else if(new_docstatus==1 && me.frm.doc.docstatus==1) {
  142. me.frm.save("Update", null, null, on_error);
  143. } else if(new_docstatus==2 && me.frm.doc.docstatus==1) {
  144. me.frm.savecancel(null, on_error);
  145. } else {
  146. msgprint(wn._("Document Status transition from ") + me.frm.doc.docstatus + " "
  147. + wn._("to") +
  148. new_docstatus + " " + wn._("is not allowed."));
  149. return false;
  150. }
  151. // hide dropdown
  152. $(this).parents(".dropdown-menu:first").prev().dropdown('toggle');
  153. return false;
  154. })
  155. }
  156. });