您最多选择25个主题 主题必须以字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符

website_group.js 16 KiB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564
  1. // Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors
  2. // MIT License. See license.txt
  3. wn.provide("website");
  4. $.extend(website, {
  5. toggle_permitted: function() {
  6. if(website.access) {
  7. // hide certain views
  8. $('li[data-view="add"]').toggleClass("hide", !website.access.write);
  9. $('li[data-view="settings"]').toggleClass("hide", !website.access.admin);
  10. $('li[data-view="edit"]').toggleClass("hide", website.view!=="edit");
  11. // show message
  12. if(!website.access.write) {
  13. var sid = wn.get_cookie("sid");
  14. if(!sid || sid==="Guest") {
  15. $(".post-list-help").html("Please login to post");
  16. } else {
  17. $(".post-list-help").html("You do not have permission to post");
  18. }
  19. } else {
  20. $(".post-list-help").html("");
  21. }
  22. }
  23. },
  24. setup_pagination: function() {
  25. var $btn = $(".btn-more")
  26. .removeClass("hide")
  27. .on("click", function() {
  28. wn.call({
  29. btn: $btn,
  30. type: "GET",
  31. args: {
  32. cmd: "webnotes.templates.website_group.forum.get_post_list_html",
  33. limit_start: $(".post").length,
  34. limit_length: 20,
  35. group: website.group,
  36. view: website.view,
  37. pathname: website.pathname
  38. },
  39. callback: function(data) {
  40. $(".post-list").append(data.message);
  41. $btn.toggleClass("hide", !(data.message && data.message.length===opts.args.limit_length));
  42. website.toggle_upvote();
  43. }
  44. })
  45. });
  46. },
  47. bind_add_post: function() {
  48. $(".btn-post-add").on("click", website.add_post);
  49. $pic_input = $(".control-post-add-picture").on("change", website.add_picture);
  50. $(".btn-post-add-picture").on("click", function() {
  51. $pic_input.click();
  52. });
  53. },
  54. add_post: function() {
  55. if(website.post) {
  56. wn.msgprint("Post already exists. Cannot add again!");
  57. return;
  58. }
  59. website._update_post(this, "webnotes.templates.website_group.post.add_post");
  60. },
  61. bind_save_post: function() {
  62. $(".btn-post-add").addClass("hide");
  63. $(".btn-post-save").removeClass("hide").on("click", website.save_post);
  64. $(".post-picture").toggleClass("hide", !$(".post-picture").attr("src"));
  65. },
  66. save_post: function() {
  67. if(!website.post) {
  68. wn.msgprint("Post does not exist. Please add post!");
  69. return;
  70. }
  71. website._update_post(this, "webnotes.templates.website_group.post.save_post");
  72. },
  73. _update_post: function(btn, cmd) {
  74. var values = website.get_editor_values();
  75. if(!values) {
  76. return;
  77. }
  78. wn.call({
  79. btn: btn,
  80. type: "POST",
  81. args: $.extend({
  82. cmd: cmd,
  83. group: website.group,
  84. post: website.post || undefined,
  85. }, values),
  86. callback: function(data) {
  87. var url = window.location.pathname + "?view=post&name=" + data.message;
  88. window.location.href = url;
  89. }
  90. });
  91. },
  92. get_editor_values: function() {
  93. var values = {};
  94. $.each($('.post-editor [data-fieldname]'), function(i, ele) {
  95. var $ele = $(ele);
  96. values[$ele.attr("data-fieldname")] = $ele.val();
  97. });
  98. values.parent_post = $(".post-editor").attr("data-parent-post");
  99. values.picture_name = $(".control-post-add-picture").val() || null;
  100. var dataurl = $(".post-picture img").attr("src");
  101. values.picture = dataurl ? dataurl.split(",")[1] : ""
  102. // validations
  103. if(!values.parent_post && !values.title) {
  104. wn.msgprint("Please enter title!");
  105. return;
  106. } else if(!values.content) {
  107. wn.msgprint("Please enter some text!");
  108. return;
  109. } else if($('.post-editor [data-fieldname="event_datetime"]').length && !values.event_datetime) {
  110. wn.msgprint("Please enter Event's Date and Time!");
  111. return;
  112. }
  113. // post process
  114. // convert links in content
  115. values.content = website.process_external_links(values.content);
  116. return values;
  117. },
  118. process_external_links: function(content) {
  119. return content.replace(/([^\s]*)(http|https|ftp):\/\/[^\s\[\]\(\)]+/g, function(match, p1) {
  120. // mimicing look behind! should not have anything in p1
  121. // replace(/match/g)
  122. // replace(/(p1)(p2)/g)
  123. // so, when there is a character before http://, it shouldn't be replaced!
  124. if(p1) return match;
  125. return "["+match+"]("+match+")";
  126. });
  127. },
  128. add_picture: function() {
  129. if (this.type === 'file' && this.files && this.files.length > 0) {
  130. $.each(this.files, function (idx, fileobj) {
  131. if (/^image\//.test(fileobj.type)) {
  132. $.canvasResize(fileobj, {
  133. width: 500,
  134. height: 0,
  135. crop: false,
  136. quality: 80,
  137. callback: function(data, width, height) {
  138. $(".post-picture").removeClass("hide").find("img").attr("src", data);
  139. }
  140. });
  141. }
  142. });
  143. }
  144. return false;
  145. },
  146. setup_tasks_editor: function() {
  147. // assign events
  148. var $post_editor = $(".post-editor");
  149. var $control_assign = $post_editor.find('.control-assign');
  150. var bind_close = function() {
  151. var close = $post_editor.find("a.close")
  152. if(close.length) {
  153. close.on("click", function() {
  154. // clear assignment
  155. $post_editor.find(".assigned-to").addClass("hide");
  156. $post_editor.find(".assigned-profile").html("");
  157. $post_editor.find('[data-fieldname="assigned_to"]').val(null);
  158. $control_assign.val(null);
  159. });
  160. }
  161. }
  162. if($control_assign.length) {
  163. website.setup_autosuggest({
  164. $control: $control_assign,
  165. select: function(value, item) {
  166. var $assigned_to = $post_editor.find(".assigned-to").removeClass("hide");
  167. $assigned_to.find(".assigned-profile").html(item.profile_html);
  168. $post_editor.find('[data-fieldname="assigned_to"]').val(value);
  169. bind_close();
  170. },
  171. method: "webnotes.templates.website_group.post.suggest_user"
  172. });
  173. bind_close();
  174. }
  175. },
  176. setup_event_editor: function() {
  177. var $post_editor = $(".post-editor");
  178. var $control_event = $post_editor.find('.control-event').empty();
  179. var $event_field = $post_editor.find('[data-fieldname="event_datetime"]');
  180. var set_event = function($control) {
  181. var datetime = website.datetimepicker.obj_to_str($control_event.datepicker("getDate"));
  182. if($event_field.val() !== datetime) {
  183. $event_field.val(datetime);
  184. }
  185. };
  186. website.setup_datepicker({
  187. $control: $control_event,
  188. onClose: function() { set_event($control_event) }
  189. });
  190. if($event_field.val()) {
  191. $control_event.val(website.datetimepicker.format_datetime($event_field.val()));
  192. }
  193. },
  194. format_event_timestamps: function() {
  195. var get_day = function(num) {
  196. return ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday",
  197. "Friday", "Saturday"][num];
  198. }
  199. var get_month = function(num) {
  200. return ["January", "February", "March", "April", "May", "June",
  201. "July", "August", "September", "October", "November", "December"][num-1];
  202. }
  203. var format = function(datetime) {
  204. if(!datetime) return "";
  205. var date = datetime.split(" ")[0].split("-");
  206. var time = datetime.split(" ")[1].split(":");
  207. var tt = "am";
  208. if(time[0] >= 12) {
  209. time[0] = parseInt(time[0]) - 12;
  210. tt = "pm";
  211. }
  212. if(!parseInt(time[0])) {
  213. time[0] = 12;
  214. }
  215. var hhmm = [time[0], time[1]].join(":")
  216. // DD, d MM, yy hh:mm tt
  217. var dateobj = new Date(date[0], date[1], date[2])
  218. return repl("%(day)s, %(date)s %(month)s, %(year)s %(time)s", {
  219. day: get_day(dateobj.getDay()),
  220. date: date[2],
  221. month: get_month(dateobj.getMonth()),
  222. year: date[0],
  223. time: hhmm + " " + tt
  224. })
  225. }
  226. $(".event-timestamp").each(function() {
  227. $(this).html(format($(this).attr("data-timestamp")));
  228. })
  229. },
  230. toggle_earlier_replies: function() {
  231. var $earlier_replies = $(".child-post").slice(0, $(".child-post").length - 2);
  232. var $btn = $(".btn-earlier-replies").on("click", function() {
  233. if($earlier_replies.hasClass("hide")) {
  234. $earlier_replies.removeClass("hide");
  235. $(".btn-earlier-label").html("Hide");
  236. } else {
  237. $earlier_replies.addClass("hide");
  238. $(".btn-earlier-label").html("Show");
  239. }
  240. });
  241. if($earlier_replies.length) {
  242. $btn.toggleClass("hide", false).click();
  243. }
  244. },
  245. toggle_edit: function(only_owner) {
  246. if(only_owner) {
  247. var user = wn.get_cookie("user_id");
  248. $(".edit-post").each(function() {
  249. $(this).toggleClass("hide", !(website.access.write && $(this).attr("data-owner")===user));
  250. });
  251. } else {
  252. $(".edit-post").toggleClass("hide", !website.access.write);
  253. }
  254. },
  255. toggle_upvote: function() {
  256. if(!website.access.read || !website.upvote) {
  257. $(".upvote").remove();
  258. }
  259. },
  260. toggle_post_editor: function() {
  261. $(".post-editor").toggleClass("hide", !website.access.write);
  262. },
  263. setup_upvote: function() {
  264. if(window.website.setup_upvote_done) return;
  265. window.website.setup_upvote_done = true;
  266. $(document).on("click", ".post-list .upvote a, .parent-post .upvote a", function() {
  267. console.log("clicked");
  268. var sid = wn.get_cookie("sid");
  269. if(!sid || sid==="Guest") {
  270. wn.msgprint("Please login to Upvote!");
  271. return;
  272. }
  273. var $post = $(this).parents(".post");
  274. var post = $post.attr("data-name");
  275. var $btn = $(this).prop("disabled", true);
  276. $.ajax({
  277. url: "/",
  278. type: "POST",
  279. data: {
  280. cmd: "webnotes.website.doctype.user_vote.user_vote.set_vote",
  281. ref_doctype: "Post",
  282. ref_name: post
  283. },
  284. statusCode: {
  285. 200: function(data) {
  286. if(data.exc) {
  287. console.log(data.exc);
  288. } else {
  289. var text_class = data.message === "ok" ? "text-success" : "text-danger";
  290. if(data.message==="ok") {
  291. var count = parseInt($post.find(".upvote-count").text());
  292. $post.find(".upvote-count").text(count + 1).removeClass("hide");
  293. }
  294. $btn.addClass(text_class);
  295. setTimeout(function() { $btn.removeClass(text_class); }, 2000);
  296. }
  297. }
  298. }
  299. }).always(function() {
  300. $btn.prop("disabled", false);
  301. });
  302. return false;
  303. });
  304. },
  305. setup_autosuggest: function(opts) {
  306. if(opts.$control.hasClass("ui-autocomplete-input")) return;
  307. wn.require("/assets/webnotes/js/lib/jquery/jquery.ui.min.js");
  308. wn.require("/assets/webnotes/js/lib/jquery/bootstrap_theme/jquery-ui.selected.css");
  309. var $user_suggest = opts.$control.autocomplete({
  310. source: function(request, response) {
  311. $.ajax({
  312. url: "/",
  313. data: {
  314. cmd: opts.method,
  315. term: request.term,
  316. group: website.group
  317. },
  318. success: function(data) {
  319. if(data.exc) {
  320. console.log(data.exc);
  321. } else {
  322. response(data.message);
  323. }
  324. }
  325. });
  326. },
  327. select: function(event, ui) {
  328. opts.$control.val("");
  329. opts.select(ui.item.profile, ui.item);
  330. }
  331. });
  332. $user_suggest.data( "ui-autocomplete" )._renderItem = function(ul, item) {
  333. return $("<li>").html("<a style='padding: 5px;'>" + item.profile_html + "</a>")
  334. .css("padding", "5px")
  335. .appendTo(ul);
  336. };
  337. return opts.$control
  338. },
  339. setup_datepicker: function(opts) {
  340. if(opts.$control.hasClass("hasDatetimepicker")) return;
  341. // libs required for datetime picker
  342. wn.require("/assets/webnotes/js/lib/jquery/jquery.ui.min.js");
  343. wn.require("/assets/webnotes/js/lib/jquery/bootstrap_theme/jquery-ui.selected.css");
  344. wn.require("/assets/webnotes/js/lib/jquery/jquery.ui.slider.min.js");
  345. wn.require("/assets/webnotes/js/lib/jquery/jquery.ui.sliderAccess.js");
  346. wn.require("/assets/webnotes/js/lib/jquery/jquery.ui.timepicker-addon.css");
  347. wn.require("/assets/webnotes/js/lib/jquery/jquery.ui.timepicker-addon.js");
  348. opts.$control.datetimepicker({
  349. timeFormat: "hh:mm tt",
  350. dateFormat: 'DD, d MM, yy',
  351. changeYear: true,
  352. yearRange: "-70Y:+10Y",
  353. stepMinute: 5,
  354. hour: 10,
  355. onClose: opts.onClose
  356. });
  357. website.setup_datetime_functions();
  358. return opts.$control;
  359. },
  360. setup_datetime_functions: function() {
  361. // requires datetime picker
  362. wn.provide("website.datetimepicker");
  363. website.datetimepicker.str_to_obj = function(datetime_str) {
  364. return $.datepicker.parseDateTime("yy-mm-dd", "HH:mm:ss", datetime_str);
  365. };
  366. website.datetimepicker.obj_to_str = function(datetime) {
  367. if(!datetime) {
  368. return "";
  369. }
  370. // requires datepicker
  371. var date_str = $.datepicker.formatDate("yy-mm-dd", datetime)
  372. var time_str = $.datepicker.formatTime("HH:mm:ss", {
  373. hour: datetime.getHours(),
  374. minute: datetime.getMinutes(),
  375. second: datetime.getSeconds()
  376. })
  377. return date_str + " " + time_str;
  378. };
  379. website.datetimepicker.format_datetime = function(datetime) {
  380. if (typeof(datetime)==="string") {
  381. datetime = website.datetimepicker.str_to_obj(datetime);
  382. }
  383. var date_str = $.datepicker.formatDate("DD, d MM, yy", datetime)
  384. var time_str = $.datepicker.formatTime("hh:mm tt", {
  385. hour: datetime.getHours(),
  386. minute: datetime.getMinutes(),
  387. second: datetime.getSeconds()
  388. })
  389. return date_str + " " + time_str;
  390. }
  391. },
  392. setup_settings: function() {
  393. // autosuggest
  394. website.setup_autosuggest({
  395. $control: $(".add-user-control"),
  396. select: function(value) {
  397. website.add_sitemap_permission(value);
  398. },
  399. method: "webnotes.templates.website_group.settings.suggest_user"
  400. });
  401. // trigger for change permission
  402. $(".permission-editor-area").on("click", ".sitemap-permission [type='checkbox']",
  403. website.update_permission);
  404. $(".permission-editor-area").find(".btn-add-group").on("click", website.add_group);
  405. $(".btn-settings").parent().addClass("active");
  406. // disabled public_write if not public_read
  407. var control_public_read = $(".control-add-group-public_read").click(function() {
  408. if(!$(this).prop("checked")) {
  409. $(".control-add-group-public_write").prop("checked", false).prop("disabled", true);
  410. } else {
  411. $(".control-add-group-public_write").prop("disabled", false);
  412. }
  413. }).trigger("click").trigger("click"); // hack
  414. },
  415. add_group: function() {
  416. var $control = $(".control-add-group"),
  417. $btn = $(".btn-add-group");
  418. if($control.val()) {
  419. $btn.prop("disabled", true);
  420. $.ajax({
  421. url:"/",
  422. type:"POST",
  423. data: {
  424. cmd:"webnotes.templates.website_group.settings.add_website_group",
  425. group: website.group,
  426. new_group: $control.val(),
  427. group_type: $(".control-add-group-type").val(),
  428. public_read: $(".control-add-group-public_read").is(":checked") ? 1 : 0,
  429. public_write: $(".control-add-group-public_write").is(":checked") ? 1 : 0
  430. },
  431. statusCode: {
  432. 403: function() {
  433. wn.msgprint("Name Not Permitted");
  434. },
  435. 200: function(data) {
  436. if(data.exc) {
  437. console.log(data.exc);
  438. if(data._server_messages) wn.msgprint(data._server_messages);
  439. } else {
  440. wn.msgprint("Group Added, refreshing...");
  441. setTimeout(function() { window.location.reload(); }, 1000)
  442. }
  443. }
  444. }
  445. }).always(function() {
  446. $btn.prop("disabled",false);
  447. $control.val("");
  448. })
  449. }
  450. },
  451. update_permission: function() {
  452. var $chk = $(this);
  453. var $tr = $chk.parents("tr:first");
  454. $chk.prop("disabled", true);
  455. $.ajax({
  456. url: "/",
  457. type: "POST",
  458. data: {
  459. cmd: "webnotes.templates.website_group.settings.update_permission",
  460. profile: $tr.attr("data-profile"),
  461. perm: $chk.attr("data-perm"),
  462. value: $chk.prop("checked") ? "1" : "0",
  463. group: website.group
  464. },
  465. statusCode: {
  466. 403: function() {
  467. wn.msgprint("Not Allowed");
  468. },
  469. 200: function(data) {
  470. $chk.prop("disabled", false);
  471. if(data.exc) {
  472. $chk.prop("checked", !$chk.prop("checked"));
  473. console.log(data.exc);
  474. } else {
  475. if(!$tr.find(":checked").length) $tr.remove();
  476. }
  477. }
  478. },
  479. });
  480. },
  481. add_sitemap_permission: function(profile) {
  482. $.ajax({
  483. url: "/",
  484. type: "POST",
  485. data: {
  486. cmd: "webnotes.templates.website_group.settings.add_sitemap_permission",
  487. profile: profile,
  488. group: website.group
  489. },
  490. success: function(data) {
  491. $(".add-user-control").val("");
  492. if(data.exc) {
  493. console.log(data.exc);
  494. } else {
  495. $(data.message).prependTo($(".permission-editor tbody"));
  496. }
  497. }
  498. });
  499. },
  500. update_group_description: function() {
  501. $(".btn-update-description").prop("disabled", true);
  502. $.ajax({
  503. url: "/",
  504. type: "POST",
  505. data: {
  506. cmd: "webnotes.templates.website_group.settings.update_description",
  507. description: $(".control-description").val() || "",
  508. group: website.group
  509. },
  510. success: function(data) {
  511. window.location.reload();
  512. }
  513. }).always(function() { $(".btn-update-description").prop("disabled", false); });
  514. }
  515. });
  516. $(document).on("apply_permissions", function() {
  517. website.toggle_permitted();
  518. });