You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

333 lines
9.6 KiB

  1. // Copyright 2013 Web Notes Technologies Pvt Ltd
  2. // License: MIT. See license.txt
  3. // opts - parent, list, doc, email
  4. wn.views.CommunicationList = Class.extend({
  5. init: function(opts) {
  6. this.comm_list = [];
  7. $.extend(this, opts);
  8. if(this.doc.__islocal) {
  9. $(this.parent).empty();
  10. return;
  11. }
  12. var sortfn = function (a, b) { return (b.creation > a.creation) ? 1 : -1; }
  13. this.list = this.list.sort(sortfn);
  14. this.make();
  15. },
  16. make: function() {
  17. var me = this;
  18. this.make_body();
  19. if(this.list && this.list.length) {
  20. $.each(this.list, function(i, d) {
  21. me.prepare(d);
  22. me.make_line(d);
  23. });
  24. // show first
  25. this.comm_list[0].find('.comm-content').toggle(true);
  26. } else {
  27. this.clear_list()
  28. }
  29. },
  30. clear_list: function() {
  31. this.body.remove();
  32. $("<div class='alert'>" + wn._("No Communication tagged with this ")
  33. + this.doc.doctype +" yet.</div>").appendTo(this.wrapper);
  34. },
  35. make_body: function() {
  36. $(this.parent)
  37. .empty()
  38. .css({"margin":"10px 0px"});
  39. this.wrapper = $("<div><h4>"+wn._("Communication History")+"</h4>\
  40. <div style='margin-bottom: 8px;'>\
  41. <button class='btn' \
  42. onclick='cur_frm.communication_view.add_reply()'>\
  43. <i class='icon-plus'></i> "+wn._("Add Message")+"</button></div>\
  44. </div>")
  45. .appendTo(this.parent);
  46. this.body = $("<table class='table table-bordered table-hover table-striped'>")
  47. .appendTo(this.wrapper);
  48. },
  49. add_reply: function() {
  50. var subject = this.doc.subject;
  51. if(!subject && this.list.length) {
  52. // get subject from previous message
  53. subject = this.list[0].subject || "[No Subject]";
  54. if(strip(subject.toLowerCase().split(":")[0])!="re") {
  55. subject = "Re: " + subject;
  56. }
  57. }
  58. new wn.views.CommunicationComposer({
  59. doc: this.doc,
  60. subject: subject,
  61. recipients: this.recipients
  62. })
  63. },
  64. prepare: function(doc) {
  65. //doc.when = comment_when(this.doc.modified);
  66. doc.when = doc.modified;
  67. if(!doc.content) doc.content = "[no content]";
  68. if(doc.content.indexOf("<br>")== -1 && doc.content.indexOf("<p>")== -1) {
  69. doc.content = doc.content.replace(/\n/g, "<br>");
  70. }
  71. if(!doc.sender) doc.sender = "[unknown sender]";
  72. doc._sender = doc.sender.replace(/</, "&lt;").replace(/>/, "&gt;");
  73. doc.content = doc.content.split("-----"+wn._("In response to")+"-----")[0];
  74. doc.content = doc.content.split("-----"+wn._("Original Message")+"-----")[0];
  75. },
  76. make_line: function(doc) {
  77. var me = this;
  78. var comm = $(repl('<tr><td>\
  79. <a href="#Form/Communication/%(name)s" class="show-details" style="font-size: 90%; float: right;">'
  80. +wn._('Show Details')+'</a>\
  81. <p class="comm-header" title="'+wn._('Click to Expand / Collapse')+'">\
  82. <b>%(_sender)s on %(when)s</b></p>\
  83. <div class="comm-content" style="border-top: 1px solid #ddd; \
  84. padding: 10px; overflow-x: auto; display: none;"></div>\
  85. </td></tr>', doc))
  86. .appendTo(this.body);
  87. if(!doc.name) {
  88. comm.find(".show-details").toggle(false);
  89. }
  90. comm.find(".comm-header")
  91. .css({"cursor":"pointer"})
  92. .click(function() {
  93. $(this).parent().find(".comm-content").toggle();
  94. });
  95. this.comm_list.push(comm);
  96. comm.find(".comm-content").html(doc.content);
  97. }
  98. });
  99. wn.views.CommunicationComposer = Class.extend({
  100. init: function(opts) {
  101. $.extend(this, opts)
  102. this.make();
  103. this.dialog.show();
  104. },
  105. make: function() {
  106. this.dialog = new wn.ui.Dialog({
  107. width: 640,
  108. title: wn._("Add Reply") + ": " + (this.subject || ""),
  109. no_submit_on_enter: true,
  110. fields: [
  111. {label:wn._("To"), fieldtype:"Data", reqd: 1, fieldname:"recipients",
  112. description:wn._("Email addresses, separted by commas")},
  113. {label:wn._("Subject"), fieldtype:"Data", reqd: 1,
  114. fieldname:"subject"},
  115. {label:wn._("Send"), fieldtype:"Button",
  116. fieldname:"send"},
  117. {label:wn._("Message"), fieldtype:"Text Editor", reqd: 1,
  118. fieldname:"content"},
  119. {label:wn._("Send Email"), fieldtype:"Check",
  120. fieldname:"send_email"},
  121. {label:wn._("Send Me A Copy"), fieldtype:"Check",
  122. fieldname:"send_me_a_copy"},
  123. {label:wn._("Attach Document Print"), fieldtype:"Check",
  124. fieldname:"attach_document_print"},
  125. {label:wn._("Select Print Format"), fieldtype:"Select",
  126. fieldname:"select_print_format"},
  127. {label:wn._("Select Attachments"), fieldtype:"HTML",
  128. fieldname:"select_attachments"}
  129. ]
  130. });
  131. this.prepare();
  132. },
  133. prepare: function() {
  134. this.setup_print();
  135. this.setup_attach();
  136. this.setup_email();
  137. this.setup_autosuggest();
  138. $(this.dialog.fields_dict.recipients.input).val(this.recipients || "").change();
  139. $(this.dialog.fields_dict.subject.input).val(this.subject || "").change();
  140. this.setup_earlier_reply();
  141. },
  142. setup_print: function() {
  143. // print formats
  144. var fields = this.dialog.fields_dict;
  145. // toggle print format
  146. $(fields.attach_document_print.input).click(function() {
  147. $(fields.select_print_format.wrapper).toggle($(this).is(":checked"));
  148. });
  149. // select print format
  150. $(fields.select_print_format.wrapper).toggle(false);
  151. $(fields.select_print_format.input)
  152. .empty()
  153. .add_options(cur_frm.print_formats)
  154. .val(cur_frm.print_formats[0]);
  155. },
  156. setup_attach: function() {
  157. var fields = this.dialog.fields_dict;
  158. var attach = $(fields.select_attachments.wrapper);
  159. var files = cur_frm.get_files();
  160. if(files.length) {
  161. $("<p><b>"+wn._("Add Attachments")+":</b></p>").appendTo(attach);
  162. $.each(files, function(i, f) {
  163. $(repl("<p><input type='checkbox' \
  164. data-file-name='%(file)s'> %(file)s</p>", {file:f})).appendTo(attach)
  165. });
  166. }
  167. },
  168. setup_email: function() {
  169. // email
  170. var me = this;
  171. var fields = this.dialog.fields_dict;
  172. if(this.attach_document_print) {
  173. $(fields.send_me_a_copy.input).click();
  174. $(fields.attach_document_print.input).click();
  175. $(fields.select_print_format.wrapper).toggle(true);
  176. }
  177. $(fields.send_email.input).attr("checked", "checked")
  178. $(fields.send.input).click(function() {
  179. var btn = this;
  180. var form_values = me.dialog.get_values();
  181. if(!form_values) return;
  182. var selected_attachments = $.map($(me.dialog.wrapper)
  183. .find("[data-file-name]:checked"), function(element) {
  184. return $(element).attr("data-file-name");
  185. })
  186. _p.build(form_values.select_print_format || "", function(print_format_html) {
  187. if(form_values.attach_document_print) {
  188. var print_html = print_format_html
  189. if(cint(wn.boot.send_print_in_body_and_attachment)) {
  190. form_values.content = form_values.content
  191. + "<p></p><hr>" + print_html;
  192. } else {
  193. form_values.content = form_values.content + "<p>"
  194. + "Please see attachment for document details.</p>"
  195. }
  196. } else {
  197. print_html = "";
  198. }
  199. wn.call({
  200. method:"core.doctype.communication.communication.make",
  201. args: {
  202. sender: wn.user_info(user).fullname + " <" + wn.boot.profile.email + ">",
  203. recipients: form_values.recipients,
  204. subject: form_values.subject,
  205. content: form_values.content,
  206. doctype: me.doc.doctype,
  207. name: me.doc.name,
  208. lead: me.doc.lead,
  209. contact: me.doc.contact,
  210. company: me.doc.company || sys_defaults.company,
  211. send_me_a_copy: form_values.send_me_a_copy,
  212. send_email: form_values.send_email,
  213. print_html: print_html,
  214. attachments: selected_attachments
  215. },
  216. btn: btn,
  217. callback: function(r) {
  218. if(!r.exc) {
  219. if(form_values.send_email)
  220. msgprint("Email sent to " + form_values.recipients);
  221. me.dialog.hide();
  222. cur_frm.reload_doc();
  223. } else {
  224. msgprint("There were errors while sending email. Please try again.")
  225. }
  226. }
  227. });
  228. })
  229. });
  230. },
  231. setup_earlier_reply: function() {
  232. var fields = this.dialog.fields_dict;
  233. var comm_list = cur_frm.communication_view
  234. ? cur_frm.communication_view.list
  235. : [];
  236. var signature = wn.boot.profile.email_signature || "";
  237. if(signature.indexOf("<br>")==-1 && signature.indexOf("<p")==-1
  238. && signature.indexOf("<img")==-1 && signature.indexOf("<div")==-1) {
  239. signature = signature.replace(/\n/g, "<br>");
  240. }
  241. if(this.real_name) {
  242. this.message = '<p>'+wn._('Dear') +' ' + this.real_name + ",</p>" + (this.message || "");
  243. }
  244. if(comm_list.length > 0) {
  245. fields.content.input.set_input((this.message || "") +
  246. "<p></p>"
  247. + signature
  248. +"<p></p>"
  249. +"-----"+wn._("In response to")+"-----<p></p>"
  250. + comm_list[0].content);
  251. } else {
  252. fields.content.input.set_input((this.message || "")
  253. + "<p></p>" + signature)
  254. }
  255. },
  256. setup_autosuggest: function() {
  257. var me = this;
  258. function split( val ) {
  259. return val.split( /,\s*/ );
  260. }
  261. function extractLast( term ) {
  262. return split(term).pop();
  263. }
  264. $(this.dialog.fields_dict.recipients.input)
  265. .bind( "keydown", function(event) {
  266. if (event.keyCode === $.ui.keyCode.TAB &&
  267. $(this).data( "autocomplete" ).menu.active ) {
  268. event.preventDefault();
  269. }
  270. })
  271. .autocomplete({
  272. source: function(request, response) {
  273. wn.call({
  274. method:'webnotes.utils.email_lib.get_contact_list',
  275. args: {
  276. 'select': "email_id",
  277. 'from': "Contact",
  278. 'where': "email_id",
  279. 'txt': extractLast(request.term).value || '%'
  280. },
  281. callback: function(r) {
  282. response($.ui.autocomplete.filter(
  283. r.cl || [], extractLast(request.term)));
  284. }
  285. });
  286. },
  287. focus: function() {
  288. // prevent value inserted on focus
  289. return false;
  290. },
  291. select: function( event, ui ) {
  292. var terms = split( this.value );
  293. // remove the current input
  294. terms.pop();
  295. // add the selected item
  296. terms.push( ui.item.value );
  297. // add placeholder to get the comma-and-space at the end
  298. terms.push( "" );
  299. this.value = terms.join( ", " );
  300. return false;
  301. }
  302. });
  303. }
  304. });