spacedeck_spaces.js 28 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960
  1. /*
  2. SpacedeckSpaces
  3. This module contains functions dealing with Spaces UI.
  4. */
  5. var SpacedeckSpaces = {
  6. data: {
  7. active_space: {advanced:{}},
  8. active_space_loaded: false,
  9. active_space_role: "viewer",
  10. active_space_version_dirty: true,
  11. active_space_messages: [],
  12. active_space_memberships: [],
  13. active_folder_history_items: [],
  14. active_space_users: [],
  15. active_space_artifacts: [],
  16. active_space_path: [],
  17. access_settings_space: null,
  18. access_settings_memberships: [],
  19. duplicate_folders: [],
  20. duplicate_folder_id: "",
  21. pending_pdf_files: [],
  22. meta_visible: false,
  23. meta_unseen: 0,
  24. present_mode: false,
  25. space_editing_title: false,
  26. create_space_title: "",
  27. folder_reverse: 1,
  28. embedded: false,
  29. remix_cta: "Create Reply",
  30. publish_cta: "Publish",
  31. remix_copying: true,
  32. remix_style: "",
  33. guest_signup_enabled: false,
  34. space_embed_html: "",
  35. share_base: location.origin,
  36. share_base_url: location.origin+"/spaces/",
  37. share_base_url_enc: encodeURIComponent(location.origin+"/spaces/"),
  38. social_bar: true,
  39. can_add_comment: false,
  40. space_info_section: "access",
  41. editors_section: "list",
  42. selected_member: null,
  43. invite_member_role: 'viewer',
  44. invite_email_error: null,
  45. invite_email: "",
  46. invite_message: "",
  47. active_join_link: "",
  48. join_link_role: "viewer",
  49. mouse_state: "idle",
  50. // folders
  51. active_folder: null,
  52. folder_sorting: "updated_at",
  53. folder_spaces_filter: null,
  54. active_path_length : 0,
  55. space_comment: "",
  56. folder_spaces_search: "",
  57. // map of artifact IDs to medium rich text editor objects
  58. medium_for_object: {},
  59. },
  60. methods: {
  61. search_spaces: function() {
  62. var query = this.folder_spaces_search;
  63. load_spaces_search(query, function(spaces) {
  64. this.active_profile_spaces = spaces;
  65. }.bind(this));
  66. },
  67. guest_logout: function() {
  68. if ("localStorage" in window && localStorage) {
  69. delete localStorage['guest_nickname'];
  70. }
  71. this.guest_nickname = "";
  72. location.reload();
  73. },
  74. ask_guestname: function(dft, cb) {
  75. smoke.prompt(__('what_is_your_name', "Spacedeck") , function(content) {
  76. if (!content || (content.length === 0)) {
  77. this.ask_guestname(dft, cb);
  78. } else {
  79. this.guest_nickname = content;
  80. if ("localStorage" in window && localStorage) {
  81. try {
  82. localStorage['guest_nickname'] = this.guest_nickname;
  83. } catch(e) {
  84. console.error(e);
  85. }
  86. }
  87. if (cb) cb();
  88. }
  89. }.bind(this), {value: dft || "Guest "+parseInt(10000*Math.random()), ok: __("ok"), cancel: __("cancel")});
  90. },
  91. load_space: function(space_id, on_success, on_error) {
  92. console.log("load space: ", space_id);
  93. this.folder_spaces_filter="";
  94. this.folder_spaces_search="";
  95. space_auth = get_query_param("spaceAuth");
  96. var userReady = function() {
  97. if (get_query_param("embedded")) {
  98. this.embedded = true;
  99. this.guest_signup_enabled = true;
  100. if (get_query_param("publish_cta")) {
  101. this.publish_cta = get_query_param("publish_cta");
  102. }
  103. if (get_query_param("nosocial")) {
  104. this.social_bar = false;
  105. }
  106. }
  107. if (get_query_param("confirm") && this.logged_in) {
  108. var token = get_query_param("confirm");
  109. confirm_user(this.user, token, function() {
  110. this.redirect_to("/spaces/"+space_id+"?show_access=1");
  111. }.bind(this), function() {
  112. alert("An error occured confirming your email with the given token.");
  113. });
  114. return;
  115. }
  116. this.close_dropdown();
  117. this.active_space_loaded = false;
  118. this.viewport_zoom = 1;
  119. this.viewport_zoom_percent = 100;
  120. this.loading_space_id = space_id;
  121. this.present_mode = false;
  122. this.active_space_is_readonly = true;
  123. this.opened_dialog = "none";
  124. this.open_space_dialog = "none";
  125. this.selected_artifacts_dict = {};
  126. this.update_selection_metrics();
  127. this.can_add_comment = false;
  128. var is_home = false;
  129. if (this.user) {
  130. is_home = (space_id == this.user.home_folder_id);
  131. }
  132. document.title = "Loading… | Spacedeck";
  133. load_space(space_id, function(space, role) {
  134. document.title = space.name;
  135. this.active_space_role = role || "viewer"; //via req header from backend
  136. this.space_embed_html = "<iframe width=\"1024\" height=\"768\" seamless src=\""+ENV.webEndpoint+"/spaces/"+space._id+"?embedded=1\"></iframe>";
  137. if (!is_home) {
  138. load_members(space, function(members) {
  139. this.active_space_memberships = members;
  140. }.bind(this));
  141. }
  142. console.log("[websocket] auth start");
  143. if (space.space_type == "folder") {
  144. this.active_space = {advanced:{}};
  145. document.title = "Spacedeck";
  146. load_spaces(space_id, is_home, function(spaces) {
  147. space.children = spaces;
  148. this.loading_space_id = null;
  149. this.active_profile_spaces = space.children;
  150. this.active_folder = space;
  151. this.access_settings_space = space;
  152. this.auth_websocket(this.active_folder);
  153. this.load_space_path(this.active_folder);
  154. if (is_home) {
  155. this.root_folder = space;
  156. }
  157. load_history(space, function(history) {
  158. console.log("loaded digest", history);
  159. this.active_folder_history_items = history;
  160. this.meta_unseen = 0;
  161. if ("localStorage" in window && localStorage) {
  162. var last_seen = parseInt(localStorage[this.meta_last_seen_key()], 10);
  163. } else {
  164. var last_seen = 0;
  165. }
  166. for (var i=0; i<history.length; i++) {
  167. var item = history[i];
  168. var t = new Date(item.last_action).getTime();
  169. var my_own = false;
  170. if (item.users.length==1 && item.users[0]=="you") {
  171. my_own = true;
  172. }
  173. if (t>last_seen && !my_own) this.meta_unseen++;
  174. }
  175. }.bind(this));
  176. this.active_view = "folders";
  177. }.bind(this));
  178. if ("localStorage" in window) {
  179. var key = "folder_sorting_"+space_id;
  180. var key2 = "folder_reverse_"+space_id;
  181. if (localStorage[key] && localStorage[key2]) {
  182. this.folder_sorting = localStorage[key];
  183. this.folder_reverse = parseInt(localStorage[key2]);
  184. console.log("loaded folder sorting: ",this.folder_sorting,this.folder_reverse);
  185. }
  186. }
  187. // legacy fix
  188. if (this.folder_sorting == "opened_at") {
  189. this.folder_sorting = "name";
  190. }
  191. } else if (space.space_type == "space") {
  192. this.artifacts = [];
  193. this.loading_space_id = null;
  194. document.title = space.name;
  195. if (space_auth || this.logged_in) {
  196. this.can_add_comment = true;
  197. }
  198. this.setup_watches();
  199. load_artifacts(space._id, function(artifacts) {
  200. // FIXME: how to cleanly handle this error?
  201. if (!artifacts) {
  202. artifacts = [];
  203. }
  204. // FIXME: remove kludge
  205. for (var i=0; i<artifacts.length; i++) {
  206. this.update_board_artifact_viewmodel(artifacts[i]);
  207. }
  208. this.active_space_artifacts = artifacts;
  209. this.$set("active_space", space);
  210. this.active_space = space;
  211. this.auth_websocket(this.active_space);
  212. this.active_view = "space";
  213. this.fixup_space_size();
  214. if (space._id != this.active_space._id) {
  215. this.present_mode = true;
  216. this.active_space_is_readonly = true;
  217. } else {
  218. this.active_space_is_readonly = false;
  219. }
  220. this.discover_zones();
  221. //window.setTimeout(function() {
  222. // this.zoom_to_fit();
  223. //}.bind(this),10);
  224. if (on_success) {
  225. on_success();
  226. }
  227. this.active_space_loaded = true;
  228. this.extract_properties_from_selection(); // populates zones etc
  229. load_comments(space._id, function(messages) {
  230. if (!messages) messages = [];
  231. this.active_space_messages = messages;
  232. this.refresh_space_comments();
  233. }.bind(this), function(xhr) { console.error(xhr); });
  234. }.bind(this));
  235. if (this.active_space_role == "editor" || this.active_space_role == "admin") {
  236. this.present_mode = false;
  237. this.active_space_is_readonly = false;
  238. }
  239. // FIXME
  240. this.active_join_link = "";
  241. this.join_link_role = "viewer";
  242. // FIXME
  243. if (this.active_space_role == "admin") {
  244. this.space_info_section="access";
  245. } else if (this.active_space_role == "editor") {
  246. //this.space_info_section="versions";
  247. } else {
  248. this.space_info_section="info";
  249. }
  250. }
  251. }.bind(this), function(xhr) {
  252. if (on_error) {
  253. return on_error(xhr);
  254. }
  255. if (xhr.status == 403) {
  256. if (!this.logged_in) {
  257. this.redirect_to("/login?space_id="+space_id);
  258. } else {
  259. this.redirect_to("/");
  260. }
  261. } else {
  262. this.redirect_to("/not_found");
  263. console.error(xhr);
  264. }
  265. }.bind(this));
  266. }.bind(this);
  267. var default_guest = "";
  268. if (("localStorage" in window && localStorage) && localStorage['guest_nickname']) {
  269. this.guest_nickname = localStorage['guest_nickname'];
  270. default_guest = this.guest_nickname;
  271. userReady();
  272. }
  273. if (space_auth) {
  274. if (this.guest_nickname) {
  275. userReady();
  276. } else {
  277. this.ask_guestname(default_guest, function() {
  278. userReady();
  279. });
  280. }
  281. } else {
  282. this.guest_nickname = "";
  283. userReady();
  284. }
  285. },
  286. refresh_space_comments: function() {
  287. this.meta_unseen = 0;
  288. var messages = this.active_space_messages;
  289. var last_seen = 0;
  290. if ("localStorage" in window && localStorage) {
  291. last_seen = parseInt(localStorage[this.meta_last_seen_key()], 10);
  292. }
  293. for (var i=0; i<messages.length; i++) {
  294. var item = messages[i];
  295. var t = new Date(item.updated_at).getTime();
  296. var my_own = false;
  297. if (this.user && this.user._id!=item.user_id && !item.editor_name) {
  298. my_own = true;
  299. }
  300. if (t>last_seen && !my_own) this.meta_unseen++;
  301. }
  302. },
  303. go_to_next_space: function() {
  304. var space_ids = this.active_folder.children.map(function(s){return s._id});
  305. var idx = space_ids.indexOf(this.active_space._id);
  306. console.log("index: ",idx);
  307. var cur_idx = idx;
  308. var done = false;
  309. while (!done) {
  310. var next = this.active_folder.children[(idx+1)%space_ids.length];
  311. if (next.space_type == "folder") {
  312. done = false;
  313. idx++;
  314. } else {
  315. done = true;
  316. }
  317. if (cur_idx == idx) done = true; // wraparound
  318. }
  319. this.load_space(next._id);
  320. },
  321. go_to_previous_space: function() {
  322. var space_ids = this.active_folder.children.map(function(s){return s._id});
  323. var idx = space_ids.indexOf(this.active_space._id);
  324. console.log("index: ",idx);
  325. var cur_idx = idx;
  326. var done = false;
  327. while (!done) {
  328. var idx = (idx<1?space_ids.length:idx)-1;
  329. var prev = this.active_folder.children[idx];
  330. if (prev.space_type == "folder") {
  331. done = false;
  332. idx--;
  333. } else {
  334. done = true;
  335. }
  336. if (cur_idx == idx) done = true; // wraparound
  337. }
  338. this.load_space(prev._id);
  339. },
  340. filtered_folder_children: function(type){
  341. var type = type || "space";
  342. return _.filter(this.active_folder.children, function(s){
  343. return s.space_type == type;
  344. })
  345. },
  346. load_space_path: function(space) {
  347. if (!space) return [];
  348. load_space_path(space._id, function(path) {
  349. this.active_space_path = path;
  350. }.bind(this), function() { console.log("could not load folder path")});
  351. },
  352. is_active_space_role: function(rolename) {
  353. if(!this.active_space) return false;
  354. return this.active_space_role == rolename;
  355. },
  356. create_space: function(space_type) {
  357. if (!this.active_folder) return;
  358. this.close_modal();
  359. this.folder_spaces_filter="";
  360. if (!this.active_folder.children) {
  361. this.active_folder.children = [];
  362. }
  363. if (!space_type) space_type = "space";
  364. var s = {
  365. name: space_type == "space" ? __("untitled_space") : __("untitled_folder") ,
  366. artifacts: [],
  367. space_type: space_type,
  368. parent_space_id: this.active_folder._id
  369. };
  370. if (this.create_space_title.length) {
  371. s.name = this.create_space_title;
  372. }
  373. save_space(s, function(saved_space) {
  374. this.active_folder.children.push(saved_space);
  375. if (space_type != "folder") {
  376. this.redirect_to("/"+saved_space.space_type+"s/"+saved_space._id, function(succ) {
  377. });
  378. } else {
  379. this.rename_folder(saved_space);
  380. }
  381. }.bind(this), function(xhr) {
  382. alert("Error: Could not create Space ("+xhr.status+").");
  383. }.bind(this));
  384. },
  385. save_space: function(s) {
  386. save_space(s);
  387. },
  388. create_space_version: function() {
  389. if (!this.is_pro(this.user)) {
  390. // pro feature
  391. smoke.confirm(__("spacedeck_pro_ad_versions"), function(confirmed) {
  392. if (confirmed) this.show_upgrade_modal();
  393. }.bind(this));
  394. return;
  395. }
  396. this.version_saving = true;
  397. this.present_mode = false;
  398. var s = this.active_space.draft_space;
  399. console.log("create_space_version:", s);
  400. duplicate_space(s, null, function(new_version_space) {
  401. load_spaces(this.active_space._id, false, function(space) {
  402. this.version_saving = false;
  403. this.activate_space_version(space, space.draft_space);
  404. alert("Version saved.");
  405. }.bind(this));
  406. }.bind(this), function(xhr){
  407. console.error(xhr);
  408. }.bind(this));
  409. },
  410. finalize_folder_profile_edit: function() {
  411. save_space(this.active_folder, function(saved_space) {
  412. this.close_modal();
  413. }.bind(this));
  414. },
  415. finalize_space_profile_edit: function() {
  416. save_space(this.active_space, function(saved_space) {
  417. this.close_modal();
  418. }.bind(this));
  419. },
  420. delete_space: function(space) {
  421. smoke.confirm("Really delete "+space.name+"?", function(confirmed) {
  422. if (!confirmed) return;
  423. var idx = this.active_folder.children.indexOf(space);
  424. delete_space(space, function() {
  425. if (space.parent_space_id){
  426. this.redirect_to("/folders/"+space.parent_space_id, function(succ) {});
  427. } else {
  428. this.redirect_to("/spaces", function(succ) {});
  429. }
  430. this.close_modal();
  431. this.active_folder.children.splice(idx,1);
  432. }.bind(this));
  433. }.bind(this));
  434. },
  435. duplicate_space: function(space) {
  436. duplicate_space(space, null, function(new_space) {
  437. //alert("Space duplicated.");
  438. this.active_folder.children.push(new_space);
  439. }.bind(this), function(xhr){
  440. console.error(xhr);
  441. }.bind(this));
  442. },
  443. remove_avatar: function(space) {
  444. remove_avatar_file("space", space, function(s) {
  445. this.active_space = s;
  446. }.bind(this));
  447. },
  448. rename_space: function(space) {
  449. this.close_dropdown();
  450. if (space.space_type == "folder") return this.rename_folder(space);
  451. smoke.prompt(__("new_space_title"), function(title) {
  452. if (title && title.length) {
  453. space.name = title;
  454. save_space(space);
  455. }
  456. }.bind(this), {value: space.name});
  457. },
  458. rename_folder: function(folder) {
  459. this.close_dropdown();
  460. smoke.prompt(__("new_folder_title"), function(title) {
  461. if (title && title.length) {
  462. folder.name = title;
  463. save_space(folder);
  464. }
  465. }.bind(this), {value: folder.name});
  466. },
  467. edit_space_title: function() {
  468. this.close_dropdown();
  469. if (this.active_space_role=="editor" || this.active_space_role=="admin") {
  470. this.space_editing_title = true;
  471. $("#space-title").focus();
  472. }
  473. },
  474. save_space_title: function(name) {
  475. this.active_space.name = name;
  476. save_space(this.active_space, function() {
  477. this.space_editing_title = false;
  478. }.bind(this));
  479. },
  480. save_space_keydown: function($event) {
  481. if ($event) {
  482. if ($event.keyCode != 13) {
  483. this.space_editing_title = true;
  484. return;
  485. }
  486. $event.preventDefault();
  487. $event.stopPropagation();
  488. $event.target.blur();
  489. }
  490. save_space(this.active_space, function(updated_space) {
  491. this.active_space.edit_slug = updated_space.edit_slug;
  492. this.space_editing_title = false;
  493. }.bind(this));
  494. },
  495. save_space_description: function($event) {
  496. $event.preventDefault();
  497. $event.stopPropagation();
  498. var val = $event.target.innerText;
  499. $event.target.blur();
  500. this.active_space.description = val;
  501. save_space(this.active_space);
  502. },
  503. save_space_domain: function($event) {
  504. $event.preventDefault();
  505. $event.stopPropagation();
  506. var val = $event.target.innerText;
  507. $event.target.blur();
  508. this.active_space.domain = val;
  509. save_space(this.active_space);
  510. },
  511. download_space: function() {
  512. smoke.quiz(__("download_space"), function(e, test) {
  513. if (e == "PDF") {
  514. this.download_space_as_pdf(this.active_space);
  515. } else if (e == "ZIP") {
  516. this.download_space_as_zip(this.active_space);
  517. }
  518. }.bind(this), {
  519. button_1: "PDF",
  520. button_2: "ZIP",
  521. button_cancel:__("cancel")
  522. });
  523. },
  524. download_space_as_png: function(space) {
  525. window.open(ENV.apiEndpoint + "/api/spaces/" + space._id + "/png");
  526. },
  527. download_space_as_pdf: function(space) {
  528. this.global_spinner = true;
  529. get_resource("/spaces/" + space._id + "/pdf", function(o) {
  530. this.global_spinner = false;
  531. location.href = o.url;
  532. }.bind(this), function(xhr) {
  533. this.global_spinner = false;
  534. alert("PDF export problem (" + xhr.status + ").");
  535. }.bind(this));
  536. },
  537. download_space_as_zip: function(space) {
  538. this.global_spinner = true;
  539. get_resource("/spaces/" + space._id + "/zip", function(o) {
  540. this.global_spinner = false;
  541. location.href = o.url;
  542. }.bind(this), function(xhr) {
  543. this.global_spinner = false;
  544. alert("ZIP export problem (" + xhr.status + ").");
  545. }.bind(this));
  546. },
  547. download_space_as_list: function(space) {
  548. this.global_spinner = true;
  549. location.href = "/api/spaces/" + space._id + "/list";
  550. },
  551. duplicate_space_into_folder: function() {
  552. load_writable_folders( function(folders){
  553. this.duplicate_folders = _.sortBy(folders, function (folder) { return folder.name; });
  554. }.bind(this), function(xhr) {
  555. console.error(xhr);
  556. });
  557. },
  558. duplicate_folder_confirm: function() {
  559. var folderId = this.duplicate_folder_id;
  560. var idx = _.findIndex(this.duplicate_folders, function(s) { return s._id == folderId;});
  561. if (idx<0) idx = 0;
  562. var folder = this.duplicate_folders[idx];
  563. console.log("df f",folder);
  564. if (!folder) return;
  565. duplicate_space(this.active_space, folder._id, function(new_space) {
  566. this.duplicate_folders = [];
  567. this.duplicate_folder = null;
  568. smoke.quiz(__("duplicate_success", this.active_space.name, folder.name), function(e, test){
  569. if (e == __("goto_space", new_space.name)){
  570. this.redirect_to("/spaces/" + new_space._id);
  571. }else if (e == __("goto_folder", folder.name)){
  572. this.redirect_to("/folders/" + folder._id);
  573. }
  574. }.bind(this), {
  575. button_1: __("goto_space", new_space.name),
  576. button_2: __("goto_folder", folder.name),
  577. button_cancel:__("stay_here")
  578. });
  579. }.bind(this), function(xhr){
  580. console.error(xhr);
  581. smoke.prompt("error: " + xhr.statusText);
  582. }.bind(this));
  583. },
  584. toggle_follow_mode: function() {
  585. this.deselect();
  586. this.follow_mode = !this.follow_mode;
  587. },
  588. toggle_present_mode: function() {
  589. this.deselect();
  590. this.present_mode = !this.present_mode;
  591. if (this.present_mode) {
  592. //this.go_to_first_zone();
  593. }
  594. },
  595. meta_last_seen_key: function() {
  596. var seen_key = "meta-seen-";
  597. if (this.active_view == 'space') {
  598. if (!this.active_space) return "invalid";
  599. seen_key += this.active_space._id;
  600. } else if (this.active_view == 'folders') {
  601. if (!this.active_folder) return "invalid";
  602. seen_key += this.active_folder._id;
  603. }
  604. return seen_key;
  605. },
  606. toggle_meta: function() {
  607. this.meta_visible = !this.meta_visible;
  608. if (this.meta_visible) {
  609. var seen_key = this.meta_last_seen_key();
  610. if ("localStorage" in window && localStorage) {
  611. localStorage[seen_key] = new Date().getTime();
  612. console.log("seen_key: ",seen_key,localStorage[seen_key]);
  613. this.meta_last_seen = localStorage[seen_key];
  614. }
  615. this.meta_unseen = 0;
  616. }
  617. },
  618. toggle_space_access_mode: function() {
  619. this.access_settings_space.access_mode = (this.access_settings_space.access_mode=="public")?"private":"public";
  620. save_space(this.access_settings_space);
  621. },
  622. save_space_access_mode: function(evt) {
  623. // FIXME really bad that i have to do this manually. why is the
  624. // value not already updated when v-on="change" is fired?!
  625. this.access_settings_space.access_mode = evt.currentTarget.value;
  626. save_space(this.access_settings_space);
  627. },
  628. save_space_editors_locking: function(evt) {
  629. // FIXME same issue as above
  630. this.access_settings_space.editors_locking = evt.currentTarget.checked;
  631. save_space(this.access_settings_space);
  632. },
  633. create_join_link: function() {
  634. create_join_link(this.active_space._id, this.join_link_role, function(result) {
  635. this.active_join_link = "https://"+location.host+"/invitations/"+result.code+"/accept";
  636. }.bind(this));
  637. },
  638. delete_join_link: function() {
  639. get_join_link(this.active_space._id, function(result) {
  640. if (result && result.length) {
  641. delete_join_link(result[result.length-1]._id, function() {
  642. this.active_join_link = "";
  643. }.bind(this));
  644. }
  645. }.bind(this));
  646. },
  647. invite_member: function(space, emails_text, txt, role) {
  648. this.invite_email_error = null;
  649. var emails = emails_text.split(",");
  650. var displayed_success = false;
  651. _.each(emails, function(email) {
  652. email = email.trim();
  653. if (!validateEmail(email)) {
  654. this.invite_email_error = "Please enter a valid address."
  655. return;
  656. }
  657. var m = {
  658. email_invited: email,
  659. personal_message: txt,
  660. role: role
  661. }
  662. create_membership(space, m, function(m) {
  663. this.access_settings_memberships.push(m);
  664. console.log("membership created:", m);
  665. this.editors_section="list";
  666. if (!displayed_success) {
  667. displayed_success = true;
  668. smoke.alert("Invitation(s) sent.");
  669. this.invite_email = "";
  670. this.invite_message = "";
  671. }
  672. }.bind(this), function(xhr){
  673. text = JSON.stringify(xhr.responseText);
  674. smoke.alert("Error: "+text);
  675. }.bind(this));
  676. }.bind(this));
  677. },
  678. update_member: function(space, m, role) {
  679. m.role = role;
  680. save_membership(space, m, function() {
  681. console.log("saved")
  682. }.bind(this), function(xhr) {
  683. console.error(xhr);
  684. }.bind(this));
  685. },
  686. // revoke
  687. remove_member: function(space, m) {
  688. delete_membership(space, m, function() {
  689. this.access_settings_memberships.splice(this.access_settings_memberships.indexOf(m), 1);
  690. }.bind(this), function(xhr) {
  691. console.error(xhr);
  692. }.bind(this));
  693. },
  694. history_back: function() {
  695. window.history.back();
  696. },
  697. create_space_comment: function(comment) {
  698. if (!comment.length) return;
  699. var data = {
  700. space: this.active_space._id,
  701. message: comment,
  702. editor_name: this.guest_nickname,
  703. user: this.user
  704. };
  705. save_comment(this.active_space._id, data, function(comment) {
  706. console.log("comment saved: ",comment.created_at);
  707. this.active_space_messages.push(comment);
  708. this.space_comment = "";
  709. }.bind(this), function(xhr){
  710. console.error(xhr);
  711. }.bind(this));
  712. },
  713. remove_space_comment: function(comment) {
  714. delete_comment(this.active_space._id, comment._id, function() {
  715. console.log("comment id:",comment._id);
  716. this.active_space_messages = _.filter(this.active_space_messages, function(c){return c._id!=comment._id;});
  717. }.bind(this), function(xhr){
  718. console.error(xhr);
  719. }.bind(this));
  720. },
  721. emojified_comment: function(comment) {
  722. return twemoji.parse(comment);
  723. },
  724. set_folder_sorting: function(key,reverse) {
  725. this.folder_sorting = key;
  726. this.folder_reverse = reverse?-1:1;
  727. console.log(key, reverse);
  728. if ("localStorage" in window) {
  729. localStorage["folder_sorting_"+this.active_folder._id] = this.folder_sorting;
  730. localStorage["folder_reverse_"+this.active_folder._id] = this.folder_reverse;
  731. }
  732. },
  733. activate_space_info_section: function(id) {
  734. this.space_info_section = id;
  735. this.editors_section = "list";
  736. if (id == "versions") {
  737. // load space versions
  738. load_spaces(this.active_space._id, null, function(space_with_children) {
  739. this.active_space.children = space_with_children.children;
  740. console.log("loaded: ",space_with_children);
  741. }.bind(this));
  742. } else if (id == "info") {
  743. // load replies
  744. }
  745. },
  746. handle_folder_drop: function(evt, dest) {
  747. try {
  748. var source = JSON.parse(evt.dataTransfer.getData("application/json"));
  749. } catch (e) {
  750. return;
  751. }
  752. if (!source || !source._id || !source.parent_space_id || !dest._id) return;
  753. if (source._id==dest._id) return;
  754. if (dest.space_type!="folder") {
  755. alert("Spaces can only be moved into folders.");
  756. return;
  757. }
  758. source.parent_space_id = dest._id;
  759. save_space(source, function() {
  760. var idx = _.findIndex(this.active_folder.children, function(s) { return s._id == source._id;});
  761. if (idx>=0) {
  762. this.active_folder.children.splice(idx,1);
  763. console.log("spliced: ",idx);
  764. }
  765. }.bind(this));
  766. },
  767. activate_access: function() {
  768. this.activate_modal("access");
  769. //this.meta_visible = false;
  770. if (this.active_space._id) {
  771. this.access_settings_space = this.active_space;
  772. } else if (this.active_folder && this.active_folder._id) {
  773. this.access_settings_space = this.active_folder;
  774. } else {
  775. return;
  776. }
  777. this.access_settings_memberships = this.active_space_memberships;
  778. },
  779. close_access: function() {
  780. this.close_modal();
  781. },
  782. show_offline_help: function() {
  783. smoke.confirm(__('was_offline'), function(confirmed) {
  784. if (!confirmed) return;
  785. location.reload();
  786. });
  787. }
  788. }
  789. }