Nevar pievienot vairāk kā 25 tēmas Tēmai ir jāsākas ar burtu vai ciparu, tā var saturēt domu zīmes ('-') un var būt līdz 35 simboliem gara.

pirms 12 gadiem
pirms 12 gadiem
pirms 12 gadiem
pirms 12 gadiem
pirms 12 gadiem
pirms 12 gadiem
pirms 12 gadiem
pirms 12 gadiem
pirms 12 gadiem
pirms 12 gadiem
pirms 12 gadiem
pirms 12 gadiem
pirms 12 gadiem
pirms 12 gadiem
pirms 12 gadiem
pirms 12 gadiem
pirms 12 gadiem
pirms 11 gadiem
pirms 12 gadiem
pirms 12 gadiem
pirms 12 gadiem
pirms 12 gadiem
pirms 11 gadiem
pirms 11 gadiem
pirms 11 gadiem
pirms 11 gadiem
pirms 12 gadiem
pirms 11 gadiem
pirms 11 gadiem
pirms 12 gadiem
pirms 11 gadiem
pirms 11 gadiem
pirms 11 gadiem
pirms 11 gadiem
pirms 11 gadiem
pirms 11 gadiem
pirms 11 gadiem
pirms 11 gadiem
pirms 11 gadiem
pirms 11 gadiem
pirms 11 gadiem
pirms 12 gadiem
pirms 12 gadiem
pirms 12 gadiem
pirms 12 gadiem
pirms 12 gadiem
pirms 12 gadiem
pirms 12 gadiem
pirms 12 gadiem
pirms 12 gadiem
pirms 12 gadiem
pirms 12 gadiem
pirms 12 gadiem
pirms 12 gadiem
pirms 12 gadiem
pirms 12 gadiem
pirms 12 gadiem
pirms 12 gadiem
pirms 12 gadiem
pirms 11 gadiem
pirms 12 gadiem
pirms 12 gadiem
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472
  1. // Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors
  2. // MIT License. See license.txt
  3. wn.views.get_listview = function(doctype, parent) {
  4. if(wn.doclistviews[doctype]) {
  5. var listview = new wn.doclistviews[doctype](parent);
  6. } else {
  7. var listview = new wn.views.ListView(parent, doctype);
  8. }
  9. return listview;
  10. }
  11. wn.provide("wn.listview_settings");
  12. wn.views.ListView = Class.extend({
  13. init: function(doclistview, doctype) {
  14. this.doclistview = doclistview;
  15. this.doctype = doctype;
  16. this.settings = wn.listview_settings[this.doctype] || {};
  17. this.set_fields();
  18. this.set_columns();
  19. this.id_list = [];
  20. if(this.settings.group_by)
  21. this.group_by = this.settings.group_by;
  22. var me = this;
  23. this.doclistview.onreset = function() {
  24. me.id_list = [];
  25. }
  26. },
  27. set_fields: function() {
  28. var me = this;
  29. var t = "`tab"+this.doctype+"`.";
  30. this.fields = [];
  31. this.stats = ['_user_tags'];
  32. var add_field = function(fieldname) {
  33. field = t + "`" + fieldname + "`"
  34. if(me.fields.indexOf(field)=== -1)
  35. me.fields.push(field);
  36. }
  37. $.each(['name', 'owner', 'docstatus', '_user_tags', '_comments', 'modified',
  38. 'modified_by'], function(i, fieldname) { add_field(fieldname); })
  39. // add title field
  40. var meta = wn.model.get("DocType", this.doctype)[0];
  41. if(meta.title_field) {
  42. this.title_field = meta.title_field;
  43. add_field(meta.title_field);
  44. }
  45. // add workflow field (as priority)
  46. this.workflow_state_fieldname = wn.workflow.get_state_fieldname(this.doctype);
  47. if(this.workflow_state_fieldname) {
  48. add_field(this.workflow_state_fieldname);
  49. this.stats.push(this.workflow_state_fieldname);
  50. }
  51. $.each(wn.model.get("DocField", {"parent":this.doctype, "in_list_view":1}), function(i,d) {
  52. if(wn.perm.has_perm(me.doctype, d.permlevel, "read")) {
  53. if(d.fieldtype=="Image" && d.options) {
  54. add_field(d.options);
  55. } else {
  56. add_field(d.fieldname);
  57. }
  58. if(d.fieldtype=="Select") {
  59. if(me.stats.indexOf(d.fieldname)===-1) me.stats.push(d.fieldname);
  60. }
  61. // currency field for symbol (multi-currency)
  62. if(d.fieldtype=="Currency" && d.options) {
  63. if(d.options.indexOf(":")!=-1) {
  64. add_field(d.options.split(":")[1]);
  65. } else {
  66. add_field(d.options);
  67. };
  68. }
  69. }
  70. });
  71. // additional fields
  72. if(this.settings.add_fields) {
  73. $.each(this.settings.add_fields, function(i, d) {
  74. if(me.fields.indexOf(d)==-1)
  75. me.fields.push(d);
  76. });
  77. }
  78. },
  79. set_columns: function() {
  80. this.columns = [];
  81. this.total_colspans = 0;
  82. var me = this;
  83. if(this.workflow_state_fieldname) {
  84. this.columns.push({
  85. colspan: 3,
  86. content: this.workflow_state_fieldname,
  87. type:"select"
  88. });
  89. }
  90. // overridden
  91. var overridden = $.map(this.settings.add_columns || [], function(d) {
  92. return d.content;
  93. });
  94. var docfields_in_list_view = wn.model.get("DocField", {"parent":this.doctype,
  95. "in_list_view":1}).sort(function(a, b) { return a.idx - b.idx })
  96. $.each(docfields_in_list_view, function(i,d) {
  97. if(in_list(overridden, d.fieldname) || d.fieldname === me.title_field) {
  98. return;
  99. }
  100. // field width
  101. var colspan = "3";
  102. if(in_list(["Int", "Percent", "Select"], d.fieldtype)) {
  103. colspan = "2";
  104. } else if(d.fieldtype=="Check") {
  105. colspan = "1";
  106. } else if(in_list(["name", "subject", "title"], d.fieldname)) { // subjects are longer
  107. colspan = "4";
  108. } else if(d.fieldtype=="Text Editor" || d.fieldtype=="Text") {
  109. colspan = "4";
  110. }
  111. me.total_colspans += parseInt(colspan);
  112. me.columns.push({colspan: colspan, content: d.fieldname,
  113. type:d.fieldtype, df:d, title:wn._(d.label) });
  114. });
  115. // additional columns
  116. if(this.settings.add_columns) {
  117. $.each(this.settings.add_columns, function(i, d) {
  118. me.columns.push(d);
  119. me.total_colspans += parseInt(d.colspan);
  120. });
  121. }
  122. var empty_cols = flt(12 - this.total_colspans);
  123. this.shift_right = cint(empty_cols * 0.6667);
  124. if(this.shift_right < 0) {
  125. this.shift_right = 0;
  126. } else if (this.shift_right > 1) {
  127. // expand each column so that it fills up empty_cols
  128. $.each(this.columns, function(i, c) {
  129. c.colspan = cint(empty_cols / me.columns.length) + cint(c.colspan);
  130. })
  131. }
  132. },
  133. render: function(row, data) {
  134. this.prepare_data(data);
  135. //$(row).removeClass("list-row");
  136. // maintain id_list to avoid duplication incase
  137. // of filtering by child table
  138. if(in_list(this.id_list, data.name)) {
  139. return;
  140. } else {
  141. this.id_list.push(data.name);
  142. }
  143. var left_cols = 4 + this.shift_right, right_cols = 8 - this.shift_right;
  144. var body = $('<div class="doclist-row row">\
  145. <div class="list-row-id-area col-sm-'+left_cols+'" style="white-space: nowrap;\
  146. text-overflow: ellipsis; max-height: 30px"></div>\
  147. <div class="list-row-content-area col-sm-'+right_cols+'"></div>\
  148. </div>').appendTo($(row).css({"position":"relative"})),
  149. colspans = 0,
  150. me = this;
  151. me.render_avatar_and_id(data, body.find(".list-row-id-area"))
  152. // make table
  153. $.each(this.columns, function(i, v) {
  154. var colspan = v.colspan || 3;
  155. colspans = colspans + flt(colspan)
  156. if(colspans <= 12) {
  157. var col = me.make_column(body.find(".list-row-content-area"), colspan);
  158. me.render_column(data, col, v);
  159. }
  160. });
  161. var comments = data._comments ? JSON.parse(data._comments) : [];
  162. var tags = $.map((data._user_tags || "").split(","), function(v) { return v ? v : null; });
  163. var timestamp_and_comment =
  164. $('<div class="list-timestamp">')
  165. .appendTo(row)
  166. .html(""
  167. + (tags.length ? (
  168. '<span style="margin-right: 10px;" class="list-tag-preview">' + tags.join(", ") + '</span>'
  169. ): "")
  170. + (comments.length ?
  171. ('<a style="margin-right: 10px;" href="#Form/'+
  172. this.doctype + '/' + data.name
  173. +'" title="'+
  174. comments[comments.length-1].comment
  175. +'"><i class="icon-comments"></i> '
  176. + comments.length + " " + (
  177. comments.length===1 ? wn._("comment") : wn._("comments")) + '</a>')
  178. : "")
  179. + comment_when(data.modified));
  180. // row #2
  181. var row2 = $('<div class="row tag-row" style="margin-bottom: 5px;">\
  182. <div class="col-xs-12">\
  183. <div class="col-xs-3"></div>\
  184. <div class="col-xs-7">\
  185. <div class="list-tag xs-hidden"></div>\
  186. <div class="list-last-modified text-muted xs-visible"></div>\
  187. </div>\
  188. </div>\
  189. </div>').appendTo(row);
  190. // modified
  191. body.find(".list-last-modified").html(wn._("Last updated by") + ": " + wn.user_info(data.modified_by).fullname);
  192. if(!me.doclistview.tags_shown) {
  193. row2.addClass("hide");
  194. }
  195. // add tags
  196. var tag_editor = new wn.ui.TagEditor({
  197. parent: row2.find(".list-tag"),
  198. frm: {
  199. doctype: this.doctype,
  200. docname: data.name
  201. },
  202. user_tags: data._user_tags
  203. });
  204. tag_editor.$w.on("click", ".tagit-label", function() {
  205. me.doclistview.set_filter("_user_tags",
  206. $(this).text());
  207. });
  208. },
  209. make_column: function(body, colspan) {
  210. var col = $("<div class='col'>")
  211. .appendTo(body)
  212. .addClass("col-sm-" + cint(colspan))
  213. .css({
  214. "white-space": "nowrap",
  215. "text-overflow": "ellipsis",
  216. "height": "30px",
  217. "padding-top":"3px"
  218. })
  219. return col;
  220. },
  221. render_avatar_and_id: function(data, parent) {
  222. if((wn.model.can_delete(this.doctype) || this.settings.selectable) && !this.no_delete) {
  223. $('<input class="list-delete" type="checkbox">')
  224. .data('name', data.name)
  225. .data('data', data)
  226. .css({"margin-right": "5px"})
  227. .appendTo(parent)
  228. }
  229. var $avatar = $(wn.avatar(data.modified_by, false, wn._("Modified by")+": "
  230. + wn.user_info(data.modified_by).fullname))
  231. .appendTo(parent)
  232. .css({"max-width": "100%"})
  233. if(wn.model.is_submittable(this.doctype)) {
  234. $(parent).append(repl('<span class="docstatus" style="margin-right: 3px;"> \
  235. <i class="%(docstatus_icon)s" \
  236. title="%(docstatus_title)s"></i></span>', data));
  237. }
  238. var title = data[this.title_field || "name"];
  239. $("<a>")
  240. .attr("href", "#Form/" + data.doctype + "/" + encodeURIComponent(data.name))
  241. .html(title)
  242. .appendTo(parent.css({"overflow":"hidden"}));
  243. parent.attr("title", title).tooltip();
  244. },
  245. render_column: function(data, parent, opts) {
  246. var me = this;
  247. if(opts.type) opts.type= opts.type.toLowerCase();
  248. // style
  249. if(opts.css) {
  250. $.each(opts.css, function(k, v) { $(parent).css(k, v)});
  251. }
  252. // multiple content
  253. if(opts.content.indexOf && opts.content.indexOf('+')!=-1) {
  254. $.map(opts.content.split('+'), function(v) {
  255. me.render_column(data, parent, {content:v, title: opts.title});
  256. });
  257. return;
  258. }
  259. // content
  260. if(typeof opts.content=='function') {
  261. opts.content(parent, data, me);
  262. }
  263. else if(opts.content=='check') {
  264. }
  265. else if(opts.type=='bar-graph' || opts.type=="percent") {
  266. this.render_bar_graph(parent, data, opts.content, opts.label);
  267. }
  268. else if(opts.template) {
  269. $(parent).append(repl(opts.template, data));
  270. }
  271. else if(opts.type=="date" && data[opts.content]) {
  272. $("<span>")
  273. .html(wn.datetime.str_to_user(data[opts.content]))
  274. .css({"color":"#888"})
  275. .appendTo(parent);
  276. }
  277. else if(opts.type=="image") {
  278. data[opts.content] = data[opts.df.options];
  279. if(data[opts.content])
  280. $("<img>")
  281. .attr("src", wn.utils.get_file_link(data[opts.content]))
  282. .css({
  283. "max-width": "100%",
  284. "max-height": "30px"
  285. })
  286. .appendTo(parent);
  287. }
  288. else if(opts.type=="select" && data[opts.content]) {
  289. var label_class = "label-default";
  290. var style = wn.utils.guess_style(data[opts.content]);
  291. if(style) label_class = "label-" + style;
  292. $("<span>"
  293. + data[opts.content] + "</span>")
  294. .css({"cursor":"pointer"})
  295. .addClass("label")
  296. .addClass(label_class)
  297. .attr("data-fieldname", opts.content)
  298. .click(function() {
  299. me.doclistview.set_filter($(this).attr("data-fieldname"),
  300. $(this).text());
  301. })
  302. .appendTo(parent.css({"overflow":"hidden"}));
  303. }
  304. else if(opts.type=="link" && data[opts.content]) {
  305. $("<span>")
  306. .html(wn.format(data[opts.content], opts.df, null, data))
  307. .appendTo(parent.css({"overflow":"hidden"}))
  308. .click(function() {
  309. me.doclistview.set_filter($(this).attr("data-fieldname"),
  310. $(this).attr("data-value"));
  311. return false;
  312. })
  313. .attr("data-fieldname", opts.content)
  314. .attr("data-value", data[opts.content])
  315. .find("a").attr("href", "#");
  316. }
  317. else if(data[opts.content]) {
  318. $("<span>")
  319. .html(wn.format(data[opts.content], opts.df, null, data))
  320. .appendTo(parent.css({"overflow":"hidden"}))
  321. }
  322. // finally
  323. if(!$(parent).html()) {
  324. $("<span>-</span>").css({color:"#ccc"}).appendTo(parent);
  325. }
  326. // title
  327. if(!in_list(["avatar", "_user_tags", "check"], opts.content)) {
  328. if($(parent).attr("title")==undefined) {
  329. $(parent).attr("title", (opts.title || opts.content) + ": "
  330. + (data[opts.content] || "Not Set"))
  331. }
  332. $(parent).tooltip();
  333. }
  334. },
  335. show_hide_check_column: function() {
  336. if(!this.doclistview.can_delete) {
  337. this.columns = $.map(this.columns, function(v, i) { if(v.content!='check') return v });
  338. }
  339. },
  340. prepare_data: function(data) {
  341. if(data.modified)
  342. this.prepare_when(data, data.modified);
  343. // docstatus
  344. if(data.docstatus==0 || data.docstatus==null) {
  345. data.docstatus_icon = 'icon-check-empty';
  346. data.docstatus_title = wn._('Editable');
  347. } else if(data.docstatus==1) {
  348. data.docstatus_icon = 'icon-lock';
  349. data.docstatus_title = wn._('Submitted');
  350. } else if(data.docstatus==2) {
  351. data.docstatus_icon = 'icon-remove';
  352. data.docstatus_title = wn._('Cancelled');
  353. }
  354. // nulls as strings
  355. for(key in data) {
  356. if(data[key]==null) {
  357. data[key]='';
  358. }
  359. }
  360. // prepare data in settings
  361. if(this.settings.prepare_data)
  362. this.settings.prepare_data(data);
  363. },
  364. prepare_when: function(data, date_str) {
  365. if (!date_str) date_str = data.modified;
  366. // when
  367. data.when = (dateutil.str_to_user(date_str)).split(' ')[0];
  368. var diff = dateutil.get_diff(dateutil.get_today(), date_str.split(' ')[0]);
  369. if(diff==0) {
  370. data.when = dateutil.comment_when(date_str);
  371. }
  372. if(diff == 1) {
  373. data.when = wn._('Yesterday')
  374. }
  375. if(diff == 2) {
  376. data.when = wn._('2 days ago')
  377. }
  378. },
  379. render_bar_graph: function(parent, data, field, label) {
  380. var args = {
  381. percent: data[field],
  382. label: label
  383. }
  384. $(parent).append(repl('<span class="progress" style="width: 100%; float: left; margin: 5px 0px;"> \
  385. <span class="progress-bar" title="%(percent)s% %(label)s" \
  386. style="width: %(percent)s%;"></span>\
  387. </span>', args));
  388. },
  389. render_icon: function(parent, icon_class, label) {
  390. var icon_html = "<i class='%(icon_class)s' title='%(label)s'></i>";
  391. $(parent).append(repl(icon_html, {icon_class: icon_class, label: label || ''}));
  392. }
  393. });
  394. // embeddable
  395. wn.provide('wn.views.RecordListView');
  396. wn.views.RecordListView = wn.views.DocListView.extend({
  397. init: function(doctype, wrapper, ListView) {
  398. this.doctype = doctype;
  399. this.wrapper = wrapper;
  400. this.listview = new ListView(this, doctype);
  401. this.listview.parent = this;
  402. this.setup();
  403. },
  404. setup: function() {
  405. var me = this;
  406. me.page_length = 10;
  407. $(me.wrapper).empty();
  408. me.init_list();
  409. },
  410. get_args: function() {
  411. var args = this._super();
  412. $.each((this.default_filters || []), function(i, f) {
  413. args.filters.push(f);
  414. });
  415. args.docstatus = args.docstatus.concat((this.default_docstatus || []));
  416. return args;
  417. },
  418. });