Nelze vybrat více než 25 témat Téma musí začínat písmenem nebo číslem, může obsahovat pomlčky („-“) a může být dlouhé až 35 znaků.
 
 
 
 
 
 

387 řádky
11 KiB

  1. // Copyright 2013 Web Notes Technologies Pvt Ltd
  2. // License: MIT. See license.txt
  3. wn.views.get_listview = function(doctype, parent) {
  4. var meta = locals.DocType[doctype];
  5. if(wn.doclistviews[doctype]) {
  6. var listview = new wn.doclistviews[doctype](parent);
  7. } else {
  8. var listview = new wn.views.ListView(parent, doctype);
  9. }
  10. return listview;
  11. }
  12. wn.provide("wn.listview_settings");
  13. wn.views.ListView = Class.extend({
  14. init: function(doclistview, doctype) {
  15. this.doclistview = doclistview;
  16. this.doctype = doctype;
  17. this.settings = wn.listview_settings[this.doctype] || {};
  18. this.set_fields();
  19. this.set_columns();
  20. if(this.settings.group_by)
  21. this.group_by = this.settings.group_by;
  22. },
  23. set_fields: function() {
  24. var me = this;
  25. var t = "`tab"+this.doctype+"`.";
  26. this.fields = [t + 'name', t + 'owner', t + 'docstatus',
  27. t + '_user_tags', t + 'modified', t + 'modified_by'];
  28. this.stats = ['_user_tags'];
  29. $.each(wn.model.get("DocField", {"parent":this.doctype, "in_list_view":1}), function(i,d) {
  30. if(wn.perm.has_perm(me.doctype, d.permlevel, READ)) {
  31. if(d.fieldtype=="Image" && d.options) {
  32. me.fields.push(t + "`" + d.options + "`");
  33. } else {
  34. me.fields.push(t + "`" + d.fieldname + "`");
  35. }
  36. if(d.fieldtype=="Select") {
  37. me.stats.push(d.fieldname);
  38. }
  39. // currency field for symbol (multi-currency)
  40. if(d.fieldtype=="Currency" && d.options) {
  41. if(d.options.indexOf(":")!=-1) {
  42. me.fields.push(t + "`" + d.options.split(":")[1] + "`");
  43. } else {
  44. me.fields.push(t + "`" + d.options + "`");
  45. };
  46. }
  47. }
  48. });
  49. // additional fields
  50. if(this.settings.add_fields) {
  51. $.each(this.settings.add_fields, function(i, d) {
  52. if(me.fields.indexOf(d)==-1)
  53. me.fields.push(d);
  54. });
  55. }
  56. },
  57. set_columns: function() {
  58. this.columns = [];
  59. var me = this;
  60. if(wn.model.can_delete(this.doctype) || this.settings.selectable) {
  61. this.columns.push({width: '4%', content:'check'})
  62. }
  63. this.columns.push({width: '7%', content:'avatar'});
  64. if(wn.model.is_submittable(this.doctype)) {
  65. this.columns.push({width: '3%', content:'docstatus',
  66. css: {"text-align": "center"}});
  67. }
  68. this.columns.push({width: '20%', content:'name'});
  69. // overridden
  70. var overridden = $.map(this.settings.add_columns || [], function(d) {
  71. return d.content;
  72. });
  73. $.each(wn.model.get("DocField", {"parent":this.doctype, "in_list_view":1}),
  74. function(i,d) {
  75. if(in_list(overridden, d.fieldname)) {
  76. return;
  77. }
  78. // field width
  79. var width = "15%";
  80. if(in_list(["Int", "Percent"], d.fieldtype)) {
  81. width = "13%";
  82. } else if(in_list(["Int", "Percent"], d.fieldtype)) {
  83. width = "10%";
  84. } else if(d.fieldtype=="Check" || d.fieldname=="file_list") {
  85. width = "5%";
  86. } else if(d.fieldname=="subject") { // subjects are longer
  87. width = "20%";
  88. }
  89. me.columns.push({width:width, content: d.fieldname,
  90. type:d.fieldtype, df:d, title:wn._(d.label) });
  91. });
  92. // additional columns
  93. if(this.settings.add_columns) {
  94. $.each(this.settings.add_columns, function(i, d) {
  95. me.columns.push(d);
  96. });
  97. }
  98. // tags
  99. this.columns.push({width: '15%', content:'tags', css: {'color':'#aaa'}}),
  100. this.columns.push({width: '15%', content:'modified',
  101. css: {'text-align': 'right', 'color':'#222'}});
  102. },
  103. render: function(row, data) {
  104. var me = this;
  105. this.prepare_data(data);
  106. rowhtml = '';
  107. // make table
  108. $.each(this.columns, function(i, v) {
  109. if(v.content && v.content.substr && v.content.substr(0,6)=="avatar") {
  110. rowhtml += repl('<td style="width: 40px;"></td>');
  111. } else {
  112. rowhtml += repl('<td style="width: %(width)s"></td>', v);
  113. }
  114. });
  115. var tr = $(row).html('<table class="doclist-row"><tbody><tr>' + rowhtml + '</tr></tbody></table>').find('tr').get(0);
  116. // render cells
  117. $.each(this.columns, function(i, v) {
  118. me.render_column(data, $("<div>")
  119. .css({
  120. "overflow":"hidden",
  121. "white-space": "nowrap",
  122. "text-overflow": "ellipsis",
  123. "max-height": "30px",
  124. })
  125. .appendTo(tr.cells[i]).get(0), v);
  126. });
  127. },
  128. render_column: function(data, parent, opts) {
  129. var me = this;
  130. if(opts.type) opts.type= opts.type.toLowerCase();
  131. // style
  132. if(opts.css) {
  133. $.each(opts.css, function(k, v) { $(parent).css(k, v)});
  134. }
  135. // multiple content
  136. if(opts.content.indexOf && opts.content.indexOf('+')!=-1) {
  137. $.map(opts.content.split('+'), function(v) {
  138. me.render_column(data, parent, {content:v, title: opts.title});
  139. });
  140. return;
  141. }
  142. // content
  143. if(typeof opts.content=='function') {
  144. opts.content(parent, data, me);
  145. }
  146. else if(opts.content=='name') {
  147. $("<a>")
  148. .attr("href", "#Form/" + data.doctype + "/" + data.name)
  149. .html(data.name)
  150. .appendTo(parent);
  151. }
  152. else if(opts.content=='avatar' || opts.content=='avatar_modified') {
  153. $(parent).append(wn.avatar(data.owner, false, wn._("Modified by")+": "
  154. + wn.user_info(data.modified_by).fullname));
  155. }
  156. else if(opts.content=='check') {
  157. $('<input class="list-delete" type="checkbox">')
  158. .data('name', data.name)
  159. .data('data', data)
  160. .appendTo(parent)
  161. }
  162. else if(opts.content=='docstatus') {
  163. $(parent).append(repl('<span class="docstatus"> \
  164. <i class="%(docstatus_icon)s" \
  165. title="%(docstatus_title)s"></i></span>', data));
  166. }
  167. else if(opts.content=='enabled') {
  168. data.icon = cint(data.enabled) ? "icon-check" : "icon-check-empty";
  169. data.title = cint(data.enabled) ? wn._("Enabled") : wn._("Disabled");
  170. $(parent).append(repl('<span class="docstatus"> \
  171. <i class="%(icon)s" title="%(title)s"></i></span>', data));
  172. }
  173. else if(opts.content=='disabled') {
  174. data.icon = cint(data.disabled) ? "icon-check-empty" : "icon-check"
  175. data.title = cint(data.disabled) ? wn._("Disabled") : wn._("Enabled");
  176. $(parent).append(repl('<span class="docstatus"> \
  177. <i class="%(icon)s"></i></span>', data));
  178. }
  179. else if(opts.content=='tags') {
  180. this.add_user_tags(parent, data);
  181. }
  182. else if(opts.content=='modified') {
  183. $("<span>")
  184. .html(data.when)
  185. .appendTo(parent)
  186. .attr("title", wn._("Last Modified On"))
  187. .css({"color":"#888"})
  188. }
  189. else if(opts.content=="file_list") {
  190. if(data[opts.content]) {
  191. $("<i class='icon-paper-clip'>").appendTo(parent);
  192. }
  193. }
  194. else if(opts.type=='bar-graph' || opts.type=="percent") {
  195. this.render_bar_graph(parent, data, opts.content, opts.label);
  196. }
  197. else if(opts.type=='link' && (opts.df ? opts.df.options : opts.doctype)) {
  198. var doctype = (opts.df ? opts.df.options : opts.doctype);
  199. $(parent).append(repl('<a href="#Form/'+ doctype +'/'
  200. +data[opts.content]+'">'+data[opts.content]+'</a>', data));
  201. }
  202. else if(opts.template) {
  203. $(parent).append(repl(opts.template, data));
  204. }
  205. else if(opts.type=="date" && data[opts.content]) {
  206. $("<span>")
  207. .html(wn.datetime.str_to_user(data[opts.content]))
  208. .css({"color":"#888"})
  209. .appendTo(parent);
  210. }
  211. else if(opts.type=="image") {
  212. data[opts.content] = data[opts.df.options];
  213. if(data[opts.content])
  214. $("<img>")
  215. .attr("src", wn.utils.get_file_link(data[opts.content]))
  216. .css({
  217. "max-width": "100px",
  218. "max-height": "30px"
  219. })
  220. .appendTo(parent);
  221. }
  222. else if(opts.type=="select" && data[opts.content]) {
  223. var label_class = "";
  224. var style = wn.utils.guess_style(data[opts.content]);
  225. if(style) label_class = "label-" + style;
  226. $("<span class='label'>"
  227. + data[opts.content] + "</span>")
  228. .css({"cursor":"pointer"})
  229. .addClass(label_class)
  230. .attr("data-fieldname", opts.content)
  231. .click(function() {
  232. me.doclistview.set_filter($(this).attr("data-fieldname"),
  233. $(this).text());
  234. })
  235. .appendTo(parent);
  236. }
  237. else if(data[opts.content]) {
  238. $("<span>")
  239. .html(wn.format(data[opts.content], opts.df, null, data))
  240. .appendTo(parent)
  241. }
  242. // finally
  243. if(!$(parent).html()) {
  244. $("<span>-</span>").css({color:"#ccc"}).appendTo(parent);
  245. }
  246. // title
  247. if(!in_list(["avatar", "_user_tags", "check"], opts.content)) {
  248. $(parent).attr("title", (opts.title || opts.content) + ": "
  249. + (data[opts.content] || "Not Set"))
  250. .tooltip();
  251. }
  252. },
  253. show_hide_check_column: function() {
  254. if(!this.doclistview.can_delete) {
  255. this.columns = $.map(this.columns, function(v, i) { if(v.content!='check') return v });
  256. }
  257. },
  258. prepare_data: function(data) {
  259. if(data.modified)
  260. this.prepare_when(data, data.modified);
  261. // docstatus
  262. if(data.docstatus==0 || data.docstatus==null) {
  263. data.docstatus_icon = 'icon-pencil';
  264. data.docstatus_title = wn._('Editable');
  265. } else if(data.docstatus==1) {
  266. data.docstatus_icon = 'icon-lock';
  267. data.docstatus_title = wn._('Submitted');
  268. } else if(data.docstatus==2) {
  269. data.docstatus_icon = 'icon-remove';
  270. data.docstatus_title = wn._('Cancelled');
  271. }
  272. // nulls as strings
  273. for(key in data) {
  274. if(data[key]==null) {
  275. data[key]='';
  276. }
  277. }
  278. // prepare data in settings
  279. if(this.settings.prepare_data)
  280. this.settings.prepare_data(data);
  281. },
  282. prepare_when: function(data, date_str) {
  283. if (!date_str) date_str = data.modified;
  284. // when
  285. data.when = (dateutil.str_to_user(date_str)).split(' ')[0];
  286. var diff = dateutil.get_diff(dateutil.get_today(), date_str.split(' ')[0]);
  287. if(diff==0) {
  288. data.when = dateutil.comment_when(date_str);
  289. }
  290. if(diff == 1) {
  291. data.when = wn._('Yesterday')
  292. }
  293. if(diff == 2) {
  294. data.when = wn._('2 days ago')
  295. }
  296. },
  297. add_user_tags: function(parent, data) {
  298. var me = this;
  299. if(data._user_tags) {
  300. $.each(data._user_tags.split(','), function(i, t) {
  301. if(t) {
  302. $('<span class="label" style="cursor: pointer;">'
  303. + strip(t) + '</span>')
  304. .click(function() {
  305. me.doclistview.set_filter('_user_tags', $(this).text())
  306. })
  307. .appendTo(parent);
  308. }
  309. });
  310. }
  311. },
  312. render_bar_graph: function(parent, data, field, label) {
  313. var args = {
  314. percent: data[field],
  315. fully_delivered: (data[field] > 99 ? 'bar-complete' : ''),
  316. label: label
  317. }
  318. $(parent).append(repl('<span class="bar-outer" style="width: 30px; float: right" \
  319. title="%(percent)s% %(label)s">\
  320. <span class="bar-inner %(fully_delivered)s" \
  321. style="width: %(percent)s%;"></span>\
  322. </span>', args));
  323. },
  324. render_icon: function(parent, icon_class, label) {
  325. var icon_html = "<i class='%(icon_class)s' title='%(label)s'></i>";
  326. $(parent).append(repl(icon_html, {icon_class: icon_class, label: label || ''}));
  327. }
  328. });
  329. // embeddable
  330. wn.provide('wn.views.RecordListView');
  331. wn.views.RecordListView = wn.views.DocListView.extend({
  332. init: function(doctype, wrapper, ListView) {
  333. this.doctype = doctype;
  334. this.wrapper = wrapper;
  335. this.listview = new ListView(this, doctype);
  336. this.listview.parent = this;
  337. this.setup();
  338. },
  339. setup: function() {
  340. var me = this;
  341. me.page_length = 10;
  342. $(me.wrapper).empty();
  343. me.init_list();
  344. },
  345. get_args: function() {
  346. var args = this._super();
  347. $.each((this.default_filters || []), function(i, f) {
  348. args.filters.push(f);
  349. });
  350. args.docstatus = args.docstatus.concat((this.default_docstatus || []));
  351. return args;
  352. },
  353. });