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
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408
  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. 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='row doclist-row'></div>")
  127. .appendTo(row).css({"padding": "5px 0px",
  128. "padding-bottom": "0px",
  129. "margin-bottom": "5px",
  130. "border-bottom": "1px solid #eee"
  131. }),
  132. colspans = 0,
  133. me = this;
  134. // make table
  135. $.each(this.columns, function(i, v) {
  136. var colspan = v.colspan || 2;
  137. colspans = colspans + flt(colspan)
  138. if(colspans <= 6) {
  139. var col = me.make_column(body, flt(colspan) * 2, true).addClass("visible-sm");
  140. me.render_column(data, col, v);
  141. }
  142. if(colspans <= 12) {
  143. var col = me.make_column(body, colspan)
  144. .addClass("hidden-sm");
  145. me.render_column(data, col, v);
  146. }
  147. });
  148. // row #2
  149. var row2 = $('<div class="col col-lg-12">\
  150. <div class="row">\
  151. <div class="col col-lg-7 col-offset-3">\
  152. <div class="list-tag hidden-sm"></div></div>\
  153. <div class="col col-lg-2 timestamp" style="font-size: 90%; padding-right: 4px;\
  154. color: #aaa; margin-top: -3px; text-align: right;">\
  155. </div>\
  156. </div>\
  157. </div>').appendTo(body);
  158. // modified
  159. row2.find(".timestamp").html(comment_when(data.modified));
  160. // add tags
  161. var tag_editor = new wn.ui.TagEditor({
  162. parent: row2.find(".list-tag"),
  163. doctype: this.doctype,
  164. docname: data.name,
  165. user_tags: data._user_tags
  166. });
  167. tag_editor.$w.on("click", ".tagit-label", function() {
  168. me.doclistview.set_filter("_user_tags",
  169. $(this).text());
  170. });
  171. },
  172. make_column: function(body, colspan, is_small) {
  173. var col = $("<div>")
  174. .appendTo(body)
  175. .addClass(is_small ? ("col col-sm-" + cint(colspan)) : ("col col-lg-" + cint(colspan)))
  176. .css({
  177. "white-space": "nowrap",
  178. "text-overflow": "ellipsis",
  179. "max-height": "30px",
  180. "padding-right": "0px"
  181. })
  182. return col;
  183. },
  184. render_column: function(data, parent, opts) {
  185. var me = this;
  186. if(opts.type) opts.type= opts.type.toLowerCase();
  187. // style
  188. if(opts.css) {
  189. $.each(opts.css, function(k, v) { $(parent).css(k, v)});
  190. }
  191. // multiple content
  192. if(opts.content.indexOf && opts.content.indexOf('+')!=-1) {
  193. $.map(opts.content.split('+'), function(v) {
  194. me.render_column(data, parent, {content:v, title: opts.title});
  195. });
  196. return;
  197. }
  198. // content
  199. if(typeof opts.content=='function') {
  200. opts.content(parent, data, me);
  201. }
  202. else if(opts.content=='name') {
  203. if(wn.model.is_submittable(this.doctype)) {
  204. $(parent).append(repl('<span class="docstatus" style="margin-right: 3px;"> \
  205. <i class="%(docstatus_icon)s" \
  206. title="%(docstatus_title)s"></i></span>', data));
  207. }
  208. $("<a>")
  209. .attr("href", "#Form/" + data.doctype + "/" + encodeURIComponent(data.name))
  210. .html(data.name)
  211. .appendTo(parent.css({"overflow":"hidden"}));
  212. }
  213. else if(opts.content=='avatar' || opts.content=='avatar_modified') {
  214. if(wn.model.can_delete(this.doctype) || this.settings.selectable) {
  215. $('<input class="list-delete" type="checkbox">')
  216. .data('name', data.name)
  217. .data('data', data)
  218. .css({"margin-right": "5px", "margin-left": "-2px"})
  219. .appendTo(parent)
  220. }
  221. $(parent).append(wn.avatar(data.modified_by, false, wn._("Modified by")+": "
  222. + wn.user_info(data.modified_by).fullname))
  223. .css({"margin-top": "-5px"});
  224. }
  225. else if(opts.content=='check') {
  226. }
  227. else if(opts.type=='bar-graph' || opts.type=="percent") {
  228. this.render_bar_graph(parent, data, opts.content, opts.label);
  229. }
  230. else if(opts.template) {
  231. $(parent).append(repl(opts.template, data));
  232. }
  233. else if(opts.type=="date" && data[opts.content]) {
  234. $("<span>")
  235. .html(wn.datetime.str_to_user(data[opts.content]))
  236. .css({"color":"#888"})
  237. .appendTo(parent);
  238. }
  239. else if(opts.type=="image") {
  240. data[opts.content] = data[opts.df.options];
  241. if(data[opts.content])
  242. $("<img>")
  243. .attr("src", wn.utils.get_file_link(data[opts.content]))
  244. .css({
  245. "max-width": "100px",
  246. "max-height": "30px"
  247. })
  248. .appendTo(parent);
  249. }
  250. else if(opts.type=="select" && data[opts.content]) {
  251. var label_class = "";
  252. var style = wn.utils.guess_style(data[opts.content]);
  253. if(style) label_class = "label-" + style;
  254. $("<span class='label'>"
  255. + data[opts.content] + "</span>")
  256. .css({"cursor":"pointer"})
  257. .addClass(label_class)
  258. .attr("data-fieldname", opts.content)
  259. .click(function() {
  260. me.doclistview.set_filter($(this).attr("data-fieldname"),
  261. $(this).text());
  262. })
  263. .appendTo(parent.css({"overflow":"hidden"}));
  264. }
  265. else if(data[opts.content]) {
  266. $("<span>")
  267. .html(wn.format(data[opts.content], opts.df, null, data))
  268. .appendTo(parent.css({"overflow":"hidden"}))
  269. }
  270. // finally
  271. if(!$(parent).html()) {
  272. $("<span>-</span>").css({color:"#ccc"}).appendTo(parent);
  273. }
  274. // title
  275. if(!in_list(["avatar", "_user_tags", "check"], opts.content)) {
  276. if($(parent).attr("title")==undefined) {
  277. $(parent).attr("title", (opts.title || opts.content) + ": "
  278. + (data[opts.content] || "Not Set"))
  279. }
  280. $(parent).tooltip();
  281. }
  282. },
  283. show_hide_check_column: function() {
  284. if(!this.doclistview.can_delete) {
  285. this.columns = $.map(this.columns, function(v, i) { if(v.content!='check') return v });
  286. }
  287. },
  288. prepare_data: function(data) {
  289. if(data.modified)
  290. this.prepare_when(data, data.modified);
  291. // docstatus
  292. if(data.docstatus==0 || data.docstatus==null) {
  293. data.docstatus_icon = 'icon-check-empty';
  294. data.docstatus_title = wn._('Editable');
  295. } else if(data.docstatus==1) {
  296. data.docstatus_icon = 'icon-lock';
  297. data.docstatus_title = wn._('Submitted');
  298. } else if(data.docstatus==2) {
  299. data.docstatus_icon = 'icon-remove';
  300. data.docstatus_title = wn._('Cancelled');
  301. }
  302. // nulls as strings
  303. for(key in data) {
  304. if(data[key]==null) {
  305. data[key]='';
  306. }
  307. }
  308. // prepare data in settings
  309. if(this.settings.prepare_data)
  310. this.settings.prepare_data(data);
  311. },
  312. prepare_when: function(data, date_str) {
  313. if (!date_str) date_str = data.modified;
  314. // when
  315. data.when = (dateutil.str_to_user(date_str)).split(' ')[0];
  316. var diff = dateutil.get_diff(dateutil.get_today(), date_str.split(' ')[0]);
  317. if(diff==0) {
  318. data.when = dateutil.comment_when(date_str);
  319. }
  320. if(diff == 1) {
  321. data.when = wn._('Yesterday')
  322. }
  323. if(diff == 2) {
  324. data.when = wn._('2 days ago')
  325. }
  326. },
  327. render_bar_graph: function(parent, data, field, label) {
  328. var args = {
  329. percent: data[field],
  330. label: label
  331. }
  332. $(parent).append(repl('<span class="progress" style="width: 100%; float: left;"> \
  333. <span class="progress-bar" title="%(percent)s% %(label)s" \
  334. style="width: %(percent)s%;"></span>\
  335. </span>', args));
  336. },
  337. render_icon: function(parent, icon_class, label) {
  338. var icon_html = "<i class='%(icon_class)s' title='%(label)s'></i>";
  339. $(parent).append(repl(icon_html, {icon_class: icon_class, label: label || ''}));
  340. }
  341. });
  342. // embeddable
  343. wn.provide('wn.views.RecordListView');
  344. wn.views.RecordListView = wn.views.DocListView.extend({
  345. init: function(doctype, wrapper, ListView) {
  346. this.doctype = doctype;
  347. this.wrapper = wrapper;
  348. this.listview = new ListView(this, doctype);
  349. this.listview.parent = this;
  350. this.setup();
  351. },
  352. setup: function() {
  353. var me = this;
  354. me.page_length = 10;
  355. $(me.wrapper).empty();
  356. me.init_list();
  357. },
  358. get_args: function() {
  359. var args = this._super();
  360. $.each((this.default_filters || []), function(i, f) {
  361. args.filters.push(f);
  362. });
  363. args.docstatus = args.docstatus.concat((this.default_docstatus || []));
  364. return args;
  365. },
  366. });