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ů.

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