]> git.wh0rd.org - tt-rss.git/blame - js/prefs.js
editSelectedFeeds: fix missing unset checkboxes properly
[tt-rss.git] / js / prefs.js
CommitLineData
4508e310
AD
1/* global dijit, __ */
2
8572e010
AD
3let hotkey_prefix = false;
4let hotkey_prefix_pressed = false;
7a09510c 5
8572e010 6let seq = "";
a998dbef 7
66665fba
AD
8function notify_callback2(transport, sticky) {
9 notify_info(transport.responseText, sticky);
60715b53
AD
10}
11
05185108 12function updateFeedList() {
16270276 13
424e28db
AD
14 const user_search = $("feed_search");
15 let search = "";
16270276
AD
16 if (user_search) { search = user_search.value; }
17
ef129fed
AD
18 xhrPost("backend.php", { op: "pref-feeds", search: search }, (transport) => {
19 dijit.byId('feedConfigTab').attr('content', transport.responseText);
20 selectTab("feedConfig", true);
21 notify("");
22 });
007bda35
AD
23}
24
f9c1f8b0 25function checkInactiveFeeds() {
ef129fed
AD
26 xhrPost("backend.php", { op: "pref-feeds", method: "getinactivefeeds" }, (transport) => {
27 if (parseInt(transport.responseText) > 0) {
28 Element.show(dijit.byId("pref_feeds_inactive_btn").domNode);
1bfe1d7b
AD
29 }
30 });
f9c1f8b0 31}
373266eb 32
79ec0f2f 33function updateUsersList(sort_key) {
424e28db 34 const user_search = $("user_search");
ef129fed 35 const search = user_search ? user_search.value : "";
fb5662de 36
ef129fed 37 const query = { op: "pref-users", sort: sort_key, search: search };
e6cb77a0 38
ef129fed
AD
39 xhrPost("backend.php", query, (transport) => {
40 dijit.byId('userConfigTab').attr('content', transport.responseText);
41 selectTab("userConfig", true)
42 notify("");
1bfe1d7b 43 });
e6cb77a0
AD
44}
45
e6cb77a0 46function addUser() {
424e28db 47 const login = prompt(__("Please enter login:"), "");
e6cb77a0 48
1bfe1d7b
AD
49 if (login == null) {
50 return false;
51 }
fb5662de 52
1bfe1d7b
AD
53 if (login == "") {
54 alert(__("Can't create user: no login specified."));
55 return false;
56 }
fb5662de 57
1bfe1d7b 58 notify_progress("Adding user...");
fb5662de 59
ef129fed
AD
60 xhrPost("backend.php", { op: "pref-users", method: "add", login: login }, (transport) => {
61 notify_callback2(transport);
62 updateUsersList();
63 });
e6cb77a0 64
e6cb77a0
AD
65}
66
05185108 67function editUser(id) {
e6cb77a0 68
424e28db 69 const query = "backend.php?op=pref-users&method=edit&id=" +
1bfe1d7b 70 param_escape(id);
222a61c2 71
1bfe1d7b
AD
72 if (dijit.byId("userEditDlg"))
73 dijit.byId("userEditDlg").destroyRecursive();
222a61c2 74
9dc5524d 75 const dialog = new dijit.Dialog({
1bfe1d7b
AD
76 id: "userEditDlg",
77 title: __("User Editor"),
78 style: "width: 600px",
79 execute: function () {
80 if (this.validate()) {
81 notify_progress("Saving data...", true);
222a61c2 82
ef129fed
AD
83 xhrPost("backend.php", dojo.formToObject("user_edit_form"), (transport) => {
84 dialog.hide();
85 updateUsersList();
86 });
1bfe1d7b
AD
87 }
88 },
89 href: query
90 });
fb5662de 91
1bfe1d7b 92 dialog.show();
e6cb77a0
AD
93}
94
261226a3 95function editFilter(id) {
261226a3 96
424e28db 97 const query = "backend.php?op=pref-filters&method=edit&id=" + param_escape(id);
261226a3 98
1bfe1d7b
AD
99 if (dijit.byId("feedEditDlg"))
100 dijit.byId("feedEditDlg").destroyRecursive();
261226a3 101
1bfe1d7b
AD
102 if (dijit.byId("filterEditDlg"))
103 dijit.byId("filterEditDlg").destroyRecursive();
ec630524 104
9dc5524d 105 const dialog = new dijit.Dialog({
1bfe1d7b
AD
106 id: "filterEditDlg",
107 title: __("Edit Filter"),
108 style: "width: 600px",
ec630524 109
1bfe1d7b 110 test: function () {
424e28db 111 const query = "backend.php?" + dojo.formToQuery("filter_edit_form") + "&savemode=test";
fb5662de 112
1bfe1d7b
AD
113 editFilterTest(query);
114 },
115 selectRules: function (select) {
116 $$("#filterDlg_Matches input[type=checkbox]").each(function (e) {
117 e.checked = select;
118 if (select)
119 e.parentNode.addClassName("Selected");
120 else
121 e.parentNode.removeClassName("Selected");
122 });
123 },
124 selectActions: function (select) {
125 $$("#filterDlg_Actions input[type=checkbox]").each(function (e) {
126 e.checked = select;
90e4e726 127
1bfe1d7b
AD
128 if (select)
129 e.parentNode.addClassName("Selected");
130 else
131 e.parentNode.removeClassName("Selected");
fb5662de 132
1bfe1d7b
AD
133 });
134 },
135 editRule: function (e) {
424e28db
AD
136 const li = e.parentNode;
137 const rule = li.getElementsByTagName("INPUT")[1].value;
1bfe1d7b
AD
138 addFilterRule(li, rule);
139 },
140 editAction: function (e) {
424e28db
AD
141 const li = e.parentNode;
142 const action = li.getElementsByTagName("INPUT")[1].value;
1bfe1d7b
AD
143 addFilterAction(li, action);
144 },
145 removeFilter: function () {
424e28db 146 const msg = __("Remove filter?");
1bfe1d7b
AD
147
148 if (confirm(msg)) {
149 this.hide();
90e4e726 150
1bfe1d7b 151 notify_progress("Removing filter...");
90e4e726 152
ef129fed 153 const query = { op: "pref-filters", method: "remove", ids: this.attr('value').id };
141fb6e3 154
ef129fed
AD
155 xhrPost("backend.php", query, () => {
156 updateFilterList();
1bfe1d7b
AD
157 });
158 }
159 },
160 addAction: function () {
161 addFilterAction();
162 },
163 addRule: function () {
164 addFilterRule();
165 },
166 deleteAction: function () {
167 $$("#filterDlg_Actions li[class*=Selected]").each(function (e) {
168 e.parentNode.removeChild(e)
169 });
170 },
171 deleteRule: function () {
172 $$("#filterDlg_Matches li[class*=Selected]").each(function (e) {
173 e.parentNode.removeChild(e)
174 });
175 },
176 execute: function () {
177 if (this.validate()) {
141fb6e3 178
1bfe1d7b 179 notify_progress("Saving data...", true);
6aff7845 180
ef129fed
AD
181 xhrPost("backend.php", dojo.formToObject("filter_edit_form"), () => {
182 dialog.hide();
183 updateFilterList();
1bfe1d7b
AD
184 });
185 }
186 },
187 href: query
188 });
a0d53889 189
1bfe1d7b 190 dialog.show();
a0d53889
AD
191}
192
1bfe1d7b 193
91ff844a 194function getSelectedLabels() {
424e28db
AD
195 const tree = dijit.byId("labelTree");
196 const items = tree.model.getCheckedItems();
197 const rv = [];
fb8b2153
AD
198
199 items.each(function(item) {
200 rv.push(tree.model.store.getValue(item, 'bare_id'));
201 });
202
203 return rv;
91ff844a 204}
48f0adb0 205
91ff844a 206function getSelectedUsers() {
e69fb880 207 return getSelectedTableRowIds("prefUserList");
a0d53889
AD
208}
209
83fe4d6d 210function getSelectedFeeds() {
424e28db
AD
211 const tree = dijit.byId("feedTree");
212 const items = tree.model.getCheckedItems();
213 const rv = [];
1985a5e0
AD
214
215 items.each(function(item) {
7c227bb3
AD
216 if (item.id[0].match("FEED:"))
217 rv.push(tree.model.store.getValue(item, 'bare_id'));
1985a5e0
AD
218 });
219
220 return rv;
91ff844a 221}
331900c6 222
fd26d5bf 223function getSelectedCategories() {
424e28db
AD
224 const tree = dijit.byId("feedTree");
225 const items = tree.model.getCheckedItems();
226 const rv = [];
fd26d5bf
AD
227
228 items.each(function(item) {
229 if (item.id[0].match("CAT:"))
230 rv.push(tree.model.store.getValue(item, 'bare_id'));
231 });
232
233 return rv;
234}
235
91ff844a 236function getSelectedFilters() {
424e28db
AD
237 const tree = dijit.byId("filterTree");
238 const items = tree.model.getCheckedItems();
239 const rv = [];
a740f4b5
AD
240
241 items.each(function(item) {
242 rv.push(tree.model.store.getValue(item, 'bare_id'));
243 });
244
245 return rv;
246
91ff844a 247}
331900c6 248
48f0adb0
AD
249function removeSelectedLabels() {
250
424e28db 251 const sel_rows = getSelectedLabels();
48f0adb0
AD
252
253 if (sel_rows.length > 0) {
254
424e28db 255 const ok = confirm(__("Remove selected labels?"));
48f0adb0 256
69668465 257 if (ok) {
42c32916 258 notify_progress("Removing selected labels...");
fb5662de 259
ef129fed
AD
260 const query = { op: "pref-labels", method: "remove",
261 ids: sel_rows.toString() };
a796bfc1 262
ef129fed
AD
263 xhrPost("backend.php", query, () => {
264 updateLabelList();
265 });
69668465 266 }
48f0adb0 267 } else {
89cb787e 268 alert(__("No labels are selected."));
48f0adb0 269 }
90ac84df
AD
270
271 return false;
48f0adb0
AD
272}
273
e6cb77a0
AD
274function removeSelectedUsers() {
275
424e28db 276 const sel_rows = getSelectedUsers();
fb5662de 277
1bfe1d7b 278 if (sel_rows.length > 0) {
fb5662de 279
424e28db 280 const ok = confirm(__("Remove selected users? Neither default admin nor your account will be removed."));
fb5662de 281
1bfe1d7b
AD
282 if (ok) {
283 notify_progress("Removing selected users...");
fb5662de 284
ef129fed
AD
285 const query = { op: "pref-users", method: "remove",
286 ids: sel_rows.toString() };
fb5662de 287
ef129fed
AD
288 xhrPost("backend.php", query, () => {
289 updateUsersList();
1bfe1d7b 290 });
69668465 291 }
e6cb77a0 292
1bfe1d7b
AD
293 } else {
294 alert(__("No users are selected."));
e6cb77a0 295 }
90ac84df
AD
296
297 return false;
e6cb77a0
AD
298}
299
48f0adb0
AD
300function removeSelectedFilters() {
301
424e28db 302 const sel_rows = getSelectedFilters();
fb5662de 303
1bfe1d7b 304 if (sel_rows.length > 0) {
fb5662de 305
424e28db 306 const ok = confirm(__("Remove selected filters?"));
fb5662de 307
1bfe1d7b
AD
308 if (ok) {
309 notify_progress("Removing selected filters...");
fb5662de 310
ef129fed
AD
311 const query = { op: "pref-filters", method: "remove",
312 ids: sel_rows.toString() };
fb5662de 313
ef129fed
AD
314 xhrPost("backend.php", query, () => {
315 updateFilterList();
1bfe1d7b 316 });
69668465 317 }
1bfe1d7b
AD
318 } else {
319 alert(__("No filters are selected."));
48f0adb0 320 }
90ac84df
AD
321
322 return false;
48f0adb0
AD
323}
324
83fe4d6d
AD
325function removeSelectedFeeds() {
326
424e28db 327 const sel_rows = getSelectedFeeds();
fb5662de 328
1bfe1d7b 329 if (sel_rows.length > 0) {
fb5662de 330
424e28db 331 const ok = confirm(__("Unsubscribe from selected feeds?"));
fb5662de 332
1bfe1d7b 333 if (ok) {
fb5662de 334
1bfe1d7b 335 notify_progress("Unsubscribing from selected feeds...", true);
b6a6e262 336
ef129fed
AD
337 const query = { op: "pref-feeds", method: "remove",
338 ids: sel_rows.toString() };
fb5662de 339
ef129fed
AD
340 xhrPost("backend.php", query, () => {
341 updateFeedList();
1bfe1d7b 342 });
69668465 343 }
71ad3959 344
1bfe1d7b
AD
345 } else {
346 alert(__("No feeds are selected."));
71ad3959 347 }
fb5662de 348
90ac84df 349 return false;
71ad3959 350}
007bda35 351
e6cb77a0 352function editSelectedUser() {
424e28db 353 const rows = getSelectedUsers();
e6cb77a0
AD
354
355 if (rows.length == 0) {
f3977cf5 356 alert(__("No users are selected."));
e6cb77a0
AD
357 return;
358 }
359
360 if (rows.length > 1) {
f3977cf5 361 alert(__("Please select only one user."));
e6cb77a0
AD
362 return;
363 }
364
dbd9e2f1
AD
365 notify("");
366
e6cb77a0
AD
367 editUser(rows[0]);
368}
369
370function resetSelectedUserPass() {
e6cb77a0 371
424e28db 372 const rows = getSelectedUsers();
fb5662de 373
1bfe1d7b
AD
374 if (rows.length == 0) {
375 alert(__("No users are selected."));
376 return;
377 }
fb5662de 378
1bfe1d7b
AD
379 if (rows.length > 1) {
380 alert(__("Please select only one user."));
381 return;
382 }
fb5662de 383
424e28db 384 const ok = confirm(__("Reset password of selected user?"));
fb5662de 385
1bfe1d7b
AD
386 if (ok) {
387 notify_progress("Resetting password for selected user...");
fb5662de 388
424e28db 389 const id = rows[0];
fb5662de 390
ef129fed
AD
391 xhrPost("backend.php", { op: "pref-users", method: "resetPass", id: id }, (transport) => {
392 notify_info(transport.responseText, true);
1bfe1d7b 393 });
fbf7d545 394
69668465 395 }
e6cb77a0
AD
396}
397
717f5e64 398function selectedUserDetails() {
e6cb77a0 399
424e28db 400 const rows = getSelectedUsers();
fb5662de 401
1bfe1d7b
AD
402 if (rows.length == 0) {
403 alert(__("No users are selected."));
404 return;
405 }
fb5662de 406
1bfe1d7b
AD
407 if (rows.length > 1) {
408 alert(__("Please select only one user."));
409 return;
410 }
fb5662de 411
ef129fed 412 const query = "backend.php?op=pref-users&method=userdetails&id=" + param_escape(rows[0]);
d9afd9b2 413
1bfe1d7b
AD
414 if (dijit.byId("userDetailsDlg"))
415 dijit.byId("userDetailsDlg").destroyRecursive();
d9afd9b2 416
9dc5524d 417 const dialog = new dijit.Dialog({
1bfe1d7b
AD
418 id: "userDetailsDlg",
419 title: __("User details"),
420 style: "width: 600px",
421 execute: function () {
422 dialog.hide();
423 },
424 href: query
425 });
717f5e64 426
1bfe1d7b 427 dialog.show();
c6c3a07f
AD
428}
429
a0d53889
AD
430
431function editSelectedFilter() {
424e28db 432 const rows = getSelectedFilters();
a0d53889
AD
433
434 if (rows.length == 0) {
f3977cf5 435 alert(__("No filters are selected."));
a0d53889
AD
436 return;
437 }
438
439 if (rows.length > 1) {
f3977cf5 440 alert(__("Please select only one filter."));
a0d53889
AD
441 return;
442 }
443
dbd9e2f1
AD
444 notify("");
445
a0d53889
AD
446 editFilter(rows[0]);
447
448}
449
6aff7845 450function joinSelectedFilters() {
424e28db 451 const rows = getSelectedFilters();
6aff7845
AD
452
453 if (rows.length == 0) {
454 alert(__("No filters are selected."));
455 return;
456 }
457
424e28db 458 const ok = confirm(__("Combine selected filters?"));
6aff7845
AD
459
460 if (ok) {
461 notify_progress("Joining filters...");
462
ef129fed
AD
463 xhrPost("backend.php", { op: "pref-filters", method: "join", ids: rows.toString() }, () => {
464 updateFilterList();
465 });
6aff7845
AD
466 }
467}
a0d53889 468
508a81e1 469function editSelectedFeed() {
424e28db 470 const rows = getSelectedFeeds();
508a81e1
AD
471
472 if (rows.length == 0) {
f3977cf5 473 alert(__("No feeds are selected."));
508a81e1
AD
474 return;
475 }
476
477 if (rows.length > 1) {
1e5548db 478 return editSelectedFeeds();
508a81e1
AD
479 }
480
dbd9e2f1
AD
481 notify("");
482
951906dc 483 editFeed(rows[0], {});
91ff844a
AD
484
485}
486
758e1c4a 487function editSelectedFeeds() {
424e28db 488 const rows = getSelectedFeeds();
758e1c4a 489
1bfe1d7b
AD
490 if (rows.length == 0) {
491 alert(__("No feeds are selected."));
492 return;
493 }
05acc0d6 494
1bfe1d7b 495 notify_progress("Loading, please wait...");
05acc0d6 496
424e28db 497 const query = "backend.php?op=pref-feeds&method=editfeeds&ids=" +
1bfe1d7b 498 param_escape(rows.toString());
755c8f95 499
1bfe1d7b 500 console.log(query);
755c8f95 501
1bfe1d7b
AD
502 if (dijit.byId("feedEditDlg"))
503 dijit.byId("feedEditDlg").destroyRecursive();
755c8f95 504
1bfe1d7b
AD
505 new Ajax.Request("backend.php", {
506 parameters: query,
507 onComplete: function (transport) {
755c8f95 508
1bfe1d7b 509 notify("");
fb5662de 510
9dc5524d 511 const dialog = new dijit.Dialog({
1bfe1d7b
AD
512 id: "feedEditDlg",
513 title: __("Edit Multiple Feeds"),
514 style: "width: 600px",
515 getChildByName: function (name) {
424e28db 516 let rv = null;
1bfe1d7b
AD
517 this.getChildren().each(
518 function (child) {
519 if (child.name == name) {
520 rv = child;
521 return;
755c8f95 522 }
1bfe1d7b
AD
523 });
524 return rv;
525 },
526 toggleField: function (checkbox, elem, label) {
527 this.getChildByName(elem).attr('disabled', !checkbox.checked);
528
529 if ($(label))
530 if (checkbox.checked)
531 $(label).removeClassName('insensitive');
532 else
533 $(label).addClassName('insensitive');
534
535 },
536 execute: function () {
537 if (this.validate() && confirm(__("Save changes to selected feeds?"))) {
ef129fed
AD
538 const query = this.attr('value');
539
24c618dd 540 /* normalize unchecked checkboxes because [] is not serialized */
1bfe1d7b 541
24c618dd
AD
542 Object.keys(query).each((key) => {
543 let val = query[key];
1bfe1d7b 544
24c618dd
AD
545 if (typeof val == "object" && val.length == 0)
546 query[key] = ["off"];
547 });
05acc0d6 548
1bfe1d7b 549 notify_progress("Saving data...", true);
758e1c4a 550
ef129fed
AD
551 xhrPost("backend.php", query, () => {
552 dialog.hide();
553 updateFeedList();
1bfe1d7b
AD
554 });
555 }
556 },
557 content: transport.responseText
558 });
758e1c4a 559
1bfe1d7b 560 dialog.show();
e1218480 561
1bfe1d7b
AD
562 }
563 });
564}
e1218480 565
1bfe1d7b
AD
566function opmlImportComplete(iframe) {
567 if (!iframe.contentDocument.body.innerHTML) return false;
568
569 Element.show(iframe);
570
571 notify('');
572
573 if (dijit.byId('opmlImportDlg'))
574 dijit.byId('opmlImportDlg').destroyRecursive();
575
424e28db 576 const content = iframe.contentDocument.body.innerHTML;
1bfe1d7b 577
424e28db 578 const dialog = new dijit.Dialog({
1bfe1d7b
AD
579 id: "opmlImportDlg",
580 title: __("OPML Import"),
581 style: "width: 600px",
582 onCancel: function () {
12b7b90c 583 window.location.reload();
1bfe1d7b
AD
584 },
585 execute: function () {
12b7b90c 586 window.location.reload();
1bfe1d7b
AD
587 },
588 content: content
589 });
e1218480 590
1bfe1d7b 591 dialog.show();
e1218480
AD
592}
593
b6a6e262 594function opmlImport() {
fb5662de 595
424e28db 596 const opml_file = $("opml_file");
9f311df6
AD
597
598 if (opml_file.value.length == 0) {
d2d75353 599 alert(__("Please choose an OPML file first."));
9f311df6
AD
600 return false;
601 } else {
4d7cd9ed 602 notify_progress("Importing, please wait...", true);
55f34b81
AD
603
604 Element.show("upload_iframe");
605
9f311df6
AD
606 return true;
607 }
608}
609
55f34b81 610
05acc0d6 611function updateFilterList() {
424e28db
AD
612 const user_search = $("filter_search");
613 let search = "";
310fa2dd
AD
614 if (user_search) { search = user_search.value; }
615
05acc0d6 616 new Ajax.Request("backend.php", {
310fa2dd 617 parameters: "?op=pref-filters&search=" + param_escape(search),
05acc0d6 618 onComplete: function(transport) {
66665fba
AD
619 dijit.byId('filterConfigTab').attr('content', transport.responseText);
620 notify("");
05acc0d6 621 } });
a0d53889
AD
622}
623
05acc0d6
AD
624function updateLabelList() {
625 new Ajax.Request("backend.php", {
626 parameters: "?op=pref-labels",
627 onComplete: function(transport) {
cbe50c80
AD
628 dijit.byId('labelConfigTab').attr('content', transport.responseText);
629 notify("");
05acc0d6 630 } });
48f0adb0
AD
631}
632
4255b24c 633function updatePrefsList() {
b4e75b2a 634 new Ajax.Request("backend.php", {
05acc0d6 635 parameters: "?op=pref-prefs",
fb5662de 636 onComplete: function(transport) {
cbe50c80
AD
637 dijit.byId('genConfigTab').attr('content', transport.responseText);
638 notify("");
e9802ead 639 } });
4255b24c
AD
640}
641
2cbdc95b
AD
642function updateSystemList() {
643 new Ajax.Request("backend.php", {
644 parameters: "?op=pref-system",
645 onComplete: function(transport) {
646 dijit.byId('systemConfigTab').attr('content', transport.responseText);
647 notify("");
648 } });
649}
650
05185108 651function selectTab(id, noupdate) {
1bfe1d7b
AD
652 if (!noupdate) {
653 notify_progress("Loading, please wait...");
d62796de 654
1bfe1d7b
AD
655 if (id == "feedConfig") {
656 updateFeedList();
657 } else if (id == "filterConfig") {
658 updateFilterList();
659 } else if (id == "labelConfig") {
660 updateLabelList();
661 } else if (id == "genConfig") {
662 updatePrefsList();
663 } else if (id == "userConfig") {
664 updateUsersList();
665 } else if (id == "systemConfig") {
666 updateSystemList();
f5a50b25 667 }
fb5662de 668
424e28db 669 const tab = dijit.byId(id + "Tab");
1bfe1d7b
AD
670 dijit.byId("pref-tabs").selectChild(tab);
671
a7565293 672 }
a7565293
AD
673}
674
a7565293 675function init_second_stage() {
1bfe1d7b
AD
676 document.onkeydown = pref_hotkey_handler;
677 loading_set_progress(50);
678 notify("");
b01b1b38 679
424e28db 680 let tab = getURLParam('tab');
b01b1b38 681
1bfe1d7b
AD
682 if (tab) {
683 tab = dijit.byId(tab + "Tab");
684 if (tab) dijit.byId("pref-tabs").selectChild(tab);
685 }
b01b1b38 686
424e28db 687 const method = getURLParam('method');
556e5b46 688
1bfe1d7b 689 if (method == 'editFeed') {
424e28db 690 const param = getURLParam('methodparam');
78935092 691
1bfe1d7b 692 window.setTimeout(function() { editFeed(param) }, 100);
b2caf812 693 }
1bfe1d7b
AD
694
695 setTimeout(hotkey_prefix_timeout, 5*1000);
a0d53889
AD
696}
697
007bda35 698function init() {
1bfe1d7b
AD
699 window.onerror = function (message, filename, lineno, colno, error) {
700 report_error(message, filename, lineno, colno, error);
701 };
702
703 require(["dojo/_base/kernel",
704 "dojo/ready",
705 "dojo/parser",
706 "dojo/_base/loader",
707 "dojo/_base/html",
708 "dijit/ColorPalette",
709 "dijit/Dialog",
710 "dijit/form/Button",
711 "dijit/form/CheckBox",
712 "dijit/form/DropDownButton",
713 "dijit/form/FilteringSelect",
12b7b90c 714 "dijit/form/MultiSelect",
1bfe1d7b
AD
715 "dijit/form/Form",
716 "dijit/form/RadioButton",
717 "dijit/form/ComboButton",
718 "dijit/form/Select",
719 "dijit/form/SimpleTextarea",
720 "dijit/form/TextBox",
721 "dijit/form/ValidationTextBox",
722 "dijit/InlineEditBox",
723 "dijit/layout/AccordionContainer",
724 "dijit/layout/AccordionPane",
725 "dijit/layout/BorderContainer",
726 "dijit/layout/ContentPane",
727 "dijit/layout/TabContainer",
728 "dijit/Menu",
729 "dijit/ProgressBar",
730 "dijit/Toolbar",
731 "dijit/Tree",
732 "dijit/tree/dndSource",
733 "dojo/data/ItemFileWriteStore",
a3e2f1a9
AD
734 "lib/CheckBoxStoreModel",
735 "lib/CheckBoxTree",
736 "fox/PrefFeedStore",
737 "fox/PrefFilterStore",
1bfe1d7b
AD
738 "fox/PrefFeedTree",
739 "fox/PrefFilterTree",
740 "fox/PrefLabelTree"], function (dojo, ready, parser) {
741
742 ready(function () {
743 try {
744 parser.parse();
745
746 loading_set_progress(50);
747
424e28db 748 const clientTzOffset = new Date().getTimezoneOffset() * 60;
e2ec66a8 749
1bfe1d7b
AD
750 new Ajax.Request("backend.php", {
751 parameters: {
752 op: "rpc", method: "sanityCheck",
753 clientTzOffset: clientTzOffset
754 },
755 onComplete: function (transport) {
756 backend_sanity_check_callback(transport);
757 }
fd539f28 758 });
1bfe1d7b
AD
759 } catch (e) {
760 exception_error(e);
761 }
762 });
763 });
007bda35 764}
b1895692 765
b652c1b7 766
1bfe1d7b 767function validatePrefsReset() {
424e28db 768 const ok = confirm(__("Reset to defaults?"));
b652c1b7 769
1bfe1d7b 770 if (ok) {
b652c1b7 771
424e28db 772 const query = "?op=pref-prefs&method=resetconfig";
1bfe1d7b 773 console.log(query);
e9802ead 774
1bfe1d7b
AD
775 new Ajax.Request("backend.php", {
776 parameters: query,
777 onComplete: function(transport) {
778 updatePrefsList();
779 notify_info(transport.responseText);
780 } });
b652c1b7 781
b652c1b7
AD
782 }
783
784 return false;
785
69668465 786}
f9cb39ac 787
d437c8cf 788function pref_hotkey_handler(e) {
b8cb4d08 789
1bfe1d7b 790 if (e.target.nodeName == "INPUT" || e.target.nodeName == "TEXTAREA") return;
18606807 791
424e28db
AD
792 let keycode = false;
793 let shift_key = false;
746dcf42 794
424e28db 795 const cmdline = $('cmdline');
78935092 796
1bfe1d7b
AD
797 try {
798 shift_key = e.shiftKey;
799 } catch (e) {
746dcf42 800
1bfe1d7b 801 }
746dcf42 802
1bfe1d7b
AD
803 if (window.event) {
804 keycode = window.event.keyCode;
805 } else if (e) {
806 keycode = e.which;
807 }
746dcf42 808
424e28db 809 let keychar = String.fromCharCode(keycode);
eec498c3 810
1bfe1d7b
AD
811 if (keycode == 27) { // escape
812 hotkey_prefix = false;
813 }
746dcf42 814
1bfe1d7b
AD
815 if (keycode == 16) return; // ignore lone shift
816 if (keycode == 17) return; // ignore lone ctrl
746dcf42 817
1bfe1d7b 818 if (!shift_key) keychar = keychar.toLowerCase();
b8cb4d08 819
1bfe1d7b 820 var hotkeys = getInitParam("hotkeys");
b8cb4d08 821
1bfe1d7b 822 if (!hotkey_prefix && hotkeys[0].indexOf(keychar) != -1) {
78935092 823
424e28db
AD
824 const date = new Date();
825 const ts = Math.round(date.getTime() / 1000);
78935092 826
1bfe1d7b
AD
827 hotkey_prefix = keychar;
828 hotkey_prefix_pressed = ts;
78935092 829
1bfe1d7b
AD
830 cmdline.innerHTML = keychar;
831 Element.show(cmdline);
78935092 832
1bfe1d7b
AD
833 return true;
834 }
746dcf42 835
1bfe1d7b 836 Element.hide(cmdline);
78935092 837
424e28db 838 let hotkey = keychar.search(/[a-zA-Z0-9]/) != -1 ? keychar : "(" + keycode + ")";
1bfe1d7b
AD
839 hotkey = hotkey_prefix ? hotkey_prefix + " " + hotkey : hotkey;
840 hotkey_prefix = false;
8d727bfc 841
424e28db 842 let hotkey_action = false;
1bfe1d7b 843 var hotkeys = getInitParam("hotkeys");
746dcf42 844
424e28db 845 for (const sequence in hotkeys[1]) {
1bfe1d7b
AD
846 if (sequence == hotkey) {
847 hotkey_action = hotkeys[1][sequence];
848 break;
746dcf42 849 }
1bfe1d7b 850 }
746dcf42 851
1bfe1d7b 852 switch (hotkey_action) {
b8cb4d08
AD
853 case "feed_subscribe":
854 quickAddFeed();
4ba1f8bb 855 return false;
b8cb4d08
AD
856 case "create_label":
857 addLabel();
4ba1f8bb 858 return false;
b8cb4d08
AD
859 case "create_filter":
860 quickAddFilter();
4ba1f8bb 861 return false;
b8cb4d08
AD
862 case "help_dialog":
863 //helpDialog("prefs");
864 return false;
865 default:
866 console.log("unhandled action: " + hotkey_action + "; hotkey: " + hotkey);
d437c8cf
AD
867 }
868}
869
5ef071e0 870function removeCategory(id, item) {
350468d0 871
424e28db 872 const ok = confirm(__("Remove category %s? Any nested feeds would be placed into Uncategorized.").replace("%s", item.name));
da1f74c9 873
1bfe1d7b 874 if (ok) {
424e28db 875 const query = "?op=pref-feeds&method=removeCat&ids=" +
1bfe1d7b 876 param_escape(id);
fb5662de 877
1bfe1d7b 878 notify_progress("Removing category...");
fb5662de 879
1bfe1d7b
AD
880 new Ajax.Request("backend.php", {
881 parameters: query,
882 onComplete: function (transport) {
883 notify('');
884 updateFeedList();
5ef071e0 885 }
1bfe1d7b 886 });
5ef071e0
AD
887 }
888}
fb5662de 889
fd26d5bf
AD
890function removeSelectedCategories() {
891
424e28db 892 const sel_rows = getSelectedCategories();
fd26d5bf
AD
893
894 if (sel_rows.length > 0) {
895
424e28db 896 const ok = confirm(__("Remove selected categories?"));
fd26d5bf
AD
897
898 if (ok) {
899 notify_progress("Removing selected categories...");
900
424e28db 901 const query = "?op=pref-feeds&method=removeCat&ids="+
fd26d5bf
AD
902 param_escape(sel_rows.toString());
903
904 new Ajax.Request("backend.php", {
905 parameters: query,
906 onComplete: function(transport) {
907 updateFeedList();
908 } });
909
910 }
911 } else {
912 alert(__("No categories are selected."));
913 }
914
915 return false;
916}
917
5ef071e0 918function createCategory() {
424e28db 919 const title = prompt(__("Category title:"));
fb5662de 920
1bfe1d7b 921 if (title) {
da1f74c9 922
1bfe1d7b 923 notify_progress("Creating category...");
da1f74c9 924
424e28db 925 const query = "?op=pref-feeds&method=addCat&cat=" +
1bfe1d7b 926 param_escape(title);
da1f74c9 927
1bfe1d7b
AD
928 new Ajax.Request("backend.php", {
929 parameters: query,
930 onComplete: function (transport) {
931 notify('');
932 updateFeedList();
933 }
934 });
a349077c 935 }
9c483746 936}
a3656a41 937
8ffd2011 938function showInactiveFeeds() {
424e28db 939 const query = "backend.php?op=pref-feeds&method=inactiveFeeds";
8ffd2011 940
1bfe1d7b
AD
941 if (dijit.byId("inactiveFeedsDlg"))
942 dijit.byId("inactiveFeedsDlg").destroyRecursive();
8ffd2011 943
9dc5524d 944 const dialog = new dijit.Dialog({
1bfe1d7b
AD
945 id: "inactiveFeedsDlg",
946 title: __("Feeds without recent updates"),
947 style: "width: 600px",
948 getSelectedFeeds: function () {
949 return getSelectedTableRowIds("prefInactiveFeedList");
950 },
951 removeSelected: function () {
424e28db 952 const sel_rows = this.getSelectedFeeds();
8ffd2011 953
1bfe1d7b 954 console.log(sel_rows);
8ffd2011 955
1bfe1d7b 956 if (sel_rows.length > 0) {
424e28db 957 const ok = confirm(__("Remove selected feeds?"));
8ffd2011 958
1bfe1d7b
AD
959 if (ok) {
960 notify_progress("Removing selected feeds...", true);
8ffd2011 961
424e28db 962 const query = "?op=pref-feeds&method=remove&ids=" +
1bfe1d7b 963 param_escape(sel_rows.toString());
8ffd2011 964
1bfe1d7b
AD
965 new Ajax.Request("backend.php", {
966 parameters: query,
967 onComplete: function (transport) {
968 notify('');
969 dialog.hide();
970 updateFeedList();
971 }
972 });
8ffd2011 973 }
8ffd2011 974
1bfe1d7b
AD
975 } else {
976 alert(__("No feeds are selected."));
977 }
978 },
979 execute: function () {
980 if (this.validate()) {
981 }
982 },
983 href: query
984 });
8ffd2011 985
1bfe1d7b 986 dialog.show();
8ffd2011
AD
987}
988
ef7b7bbd 989function opmlRegenKey() {
424e28db 990 const ok = confirm(__("Replace current OPML publishing address with a new one?"));
ef7b7bbd 991
1bfe1d7b 992 if (ok) {
fb5662de 993
1bfe1d7b 994 notify_progress("Trying to change address...", true);
fb5662de 995
424e28db 996 const query = "?op=pref-feeds&method=regenOPMLKey";
fb5662de 997
1bfe1d7b
AD
998 new Ajax.Request("backend.php", {
999 parameters: query,
1000 onComplete: function (transport) {
424e28db 1001 const reply = JSON.parse(transport.responseText);
91d16ff1 1002
424e28db 1003 const new_link = reply.link;
fb5662de 1004
424e28db 1005 const e = $('pub_opml_url');
fb5662de 1006
1bfe1d7b
AD
1007 if (new_link) {
1008 e.href = new_link;
1009 e.innerHTML = new_link;
fb5662de 1010
1bfe1d7b 1011 new Effect.Highlight(e);
ef7b7bbd 1012
1bfe1d7b 1013 notify('');
fb5662de 1014
1bfe1d7b
AD
1015 } else {
1016 notify_error("Could not change feed URL.");
1017 }
1018 }
1019 });
ef7b7bbd
MK
1020 }
1021 return false;
1022}
c4a36709 1023
b8776a07 1024function labelColorReset() {
424e28db 1025 const labels = getSelectedLabels();
b8776a07 1026
1bfe1d7b 1027 if (labels.length > 0) {
424e28db 1028 const ok = confirm(__("Reset selected labels to default colors?"));
b8776a07 1029
1bfe1d7b 1030 if (ok) {
424e28db 1031 const query = "?op=pref-labels&method=colorreset&ids=" +
1bfe1d7b 1032 param_escape(labels.toString());
f695cdb2 1033
1bfe1d7b
AD
1034 new Ajax.Request("backend.php", {
1035 parameters: query,
1036 onComplete: function (transport) {
1037 updateLabelList();
1038 }
1039 });
b8776a07
AD
1040 }
1041
1bfe1d7b
AD
1042 } else {
1043 alert(__("No labels are selected."));
b8776a07
AD
1044 }
1045}
1046
a5819bb3
AD
1047function inPreferences() {
1048 return true;
1049}
d9084cf2
AD
1050
1051function editProfiles() {
22988692 1052
1bfe1d7b
AD
1053 if (dijit.byId("profileEditDlg"))
1054 dijit.byId("profileEditDlg").destroyRecursive();
22988692 1055
424e28db 1056 const query = "backend.php?op=pref-prefs&method=editPrefProfiles";
22988692 1057
9dc5524d 1058 const dialog = new dijit.Dialog({
1bfe1d7b
AD
1059 id: "profileEditDlg",
1060 title: __("Settings Profiles"),
1061 style: "width: 600px",
1062 getSelectedProfiles: function () {
1063 return getSelectedTableRowIds("prefFeedProfileList");
1064 },
1065 removeSelected: function () {
424e28db 1066 const sel_rows = this.getSelectedProfiles();
fb5662de 1067
1bfe1d7b 1068 if (sel_rows.length > 0) {
424e28db 1069 const ok = confirm(__("Remove selected profiles? Active and default profiles will not be removed."));
fb5662de 1070
1bfe1d7b
AD
1071 if (ok) {
1072 notify_progress("Removing selected profiles...", true);
fb5662de 1073
ef129fed
AD
1074 const query = { op: "rpc", method: "remprofiles",
1075 ids: sel_rows.toString() };
fb5662de 1076
ef129fed
AD
1077 xhrPost("backend.php", query, () => {
1078 notify('');
1079 editProfiles();
1bfe1d7b 1080 });
22988692 1081 }
fb5662de 1082
1bfe1d7b
AD
1083 } else {
1084 alert(__("No profiles are selected."));
1085 }
1086 },
1087 activateProfile: function () {
424e28db 1088 const sel_rows = this.getSelectedProfiles();
fb5662de 1089
1bfe1d7b 1090 if (sel_rows.length == 1) {
fb5662de 1091
424e28db 1092 const ok = confirm(__("Activate selected profile?"));
fb5662de 1093
1bfe1d7b
AD
1094 if (ok) {
1095 notify_progress("Loading, please wait...");
fb5662de 1096
ef129fed
AD
1097 xhrPost("backend.php", { op: "rpc", method: "setprofile", id: sel_rows.toString() }, () => {
1098 window.location.reload();
1099 });
fb5662de 1100 }
22988692 1101
1bfe1d7b
AD
1102 } else {
1103 alert(__("Please choose a profile to activate."));
1104 }
1105 },
1106 addProfile: function () {
1107 if (this.validate()) {
1108 notify_progress("Creating profile...", true);
22988692 1109
ef129fed 1110 const query = { op: "rpc", method: "addprofile", title: dialog.attr('value').newprofile };
22988692 1111
ef129fed
AD
1112 xhrPost("backend.php", query, () => {
1113 notify('');
1114 editProfiles();
1bfe1d7b 1115 });
22988692 1116
1bfe1d7b
AD
1117 }
1118 },
1119 execute: function () {
1120 if (this.validate()) {
1121 }
1122 },
1123 href: query
1124 });
1125
1126 dialog.show();
d9084cf2
AD
1127}
1128
ef129fed 1129/*
d9084cf2
AD
1130function activatePrefProfile() {
1131
424e28db 1132 const sel_rows = getSelectedFeedCats();
d9084cf2
AD
1133
1134 if (sel_rows.length == 1) {
1135
424e28db 1136 const ok = confirm(__("Activate selected profile?"));
d9084cf2
AD
1137
1138 if (ok) {
1139 notify_progress("Loading, please wait...");
fb5662de 1140
ef129fed
AD
1141 xhrPost("backend.php", { op: "rpc", method: "setprofile", id: sel_rows.toString() }, () => {
1142 window.location.reload();
1143 });
d9084cf2
AD
1144 }
1145
1146 } else {
1147 alert(__("Please choose a profile to activate."));
1148 }
1149
1150 return false;
ef129fed 1151} */
d9084cf2 1152
8d86f15f
AD
1153function clearFeedAccessKeys() {
1154
424e28db 1155 const ok = confirm(__("This will invalidate all previously generated feed URLs. Continue?"));
8d86f15f
AD
1156
1157 if (ok) {
1158 notify_progress("Clearing URLs...");
1159
ef129fed
AD
1160 xhrPost("backend.php", { op: "pref-feeds", method: "clearKeys" }, () => {
1161 notify_info("Generated URLs cleared.");
1162 });
8d86f15f 1163 }
fb5662de 1164
8d86f15f
AD
1165 return false;
1166}
1167
a86ba0a6 1168function resetFilterOrder() {
1bfe1d7b 1169 notify_progress("Loading, please wait...");
a86ba0a6 1170
ef129fed
AD
1171 xhrPost("backend.php", { op: "pref-filters", method: "filtersortreset" }, () => {
1172 updateFilterList();
1173 });
a86ba0a6
AD
1174}
1175
1176
1bfe1d7b
AD
1177function resetFeedOrder() {
1178 notify_progress("Loading, please wait...");
7b8a143f 1179
ef129fed
AD
1180 xhrPost("backend.php", { op: "pref-feeds", method: "feedsortreset" }, () => {
1181 updateFeedList();
1182 });
7b8a143f
AD
1183}
1184
1185function resetCatOrder() {
1bfe1d7b 1186 notify_progress("Loading, please wait...");
7b8a143f 1187
ef129fed
AD
1188 xhrPost("backend.php", { op: "pref-feeds", method: "catsortreset" }, () => {
1189 updateFeedList();
1bfe1d7b 1190 });
7b8a143f
AD
1191}
1192
05185108 1193function editCat(id, item) {
424e28db 1194 const new_name = prompt(__('Rename category to:'), item.name);
7b8a143f 1195
1bfe1d7b 1196 if (new_name && new_name != item.name) {
7b8a143f 1197
1bfe1d7b 1198 notify_progress("Loading, please wait...");
7b8a143f 1199
ef129fed
AD
1200 xhrPost("backend.php", { op: 'pref-feeds', method: 'renamecat', id: id, title: new_name }, () => {
1201 updateFeedList();
1bfe1d7b 1202 });
7b8a143f
AD
1203 }
1204}
fb8b2153 1205
05185108 1206function editLabel(id) {
424e28db 1207 const query = "backend.php?op=pref-labels&method=edit&id=" +
1bfe1d7b
AD
1208 param_escape(id);
1209
1210 if (dijit.byId("labelEditDlg"))
1211 dijit.byId("labelEditDlg").destroyRecursive();
1212
424e28db 1213 const dialog = new dijit.Dialog({
1bfe1d7b
AD
1214 id: "labelEditDlg",
1215 title: __("Label Editor"),
1216 style: "width: 600px",
1217 setLabelColor: function (id, fg, bg) {
1218
424e28db
AD
1219 let kind = '';
1220 let color = '';
1bfe1d7b
AD
1221
1222 if (fg && bg) {
1223 kind = 'both';
1224 } else if (fg) {
1225 kind = 'fg';
1226 color = fg;
1227 } else if (bg) {
1228 kind = 'bg';
1229 color = bg;
1230 }
fb5662de 1231
424e28db 1232 const e = $("LICID-" + id);
fb5662de 1233
1bfe1d7b
AD
1234 if (e) {
1235 if (fg) e.style.color = fg;
1236 if (bg) e.style.backgroundColor = bg;
1237 }
05acc0d6 1238
ef129fed
AD
1239 const query = { op: "pref-labels", method: "colorset", kind: kind,
1240 ids: id, fg: fg, bg: bg, color: color };
1241
1242 xhrPost("backend.php", query, () => {
1243 updateFilterList(); // maybe there's labels in there
1244 });
48b05a29 1245
1bfe1d7b
AD
1246 },
1247 execute: function () {
1248 if (this.validate()) {
424e28db
AD
1249 const caption = this.attr('value').caption;
1250 const fg_color = this.attr('value').fg_color;
1251 const bg_color = this.attr('value').bg_color;
48b05a29 1252
1bfe1d7b
AD
1253 dijit.byId('labelTree').setNameById(id, caption);
1254 this.setLabelColor(id, fg_color, bg_color);
1255 this.hide();
fb8b2153 1256
ef129fed
AD
1257 xhrPost("backend.php", this.attr('value'), () => {
1258 updateFilterList(); // maybe there's labels in there
1bfe1d7b
AD
1259 });
1260 }
1261 },
1262 href: query
1263 });
fb8b2153 1264
1bfe1d7b 1265 dialog.show();
fb8b2153 1266}
018caf6f 1267
88e4e597
AD
1268
1269function customizeCSS() {
424e28db 1270 const query = "backend.php?op=pref-prefs&method=customizeCSS";
88e4e597 1271
1bfe1d7b
AD
1272 if (dijit.byId("cssEditDlg"))
1273 dijit.byId("cssEditDlg").destroyRecursive();
88e4e597 1274
424e28db 1275 const dialog = new dijit.Dialog({
1bfe1d7b
AD
1276 id: "cssEditDlg",
1277 title: __("Customize stylesheet"),
1278 style: "width: 600px",
1279 execute: function () {
1280 notify_progress('Saving data...', true);
ef129fed
AD
1281
1282 xhrPost("backend.php", this.attr('value'), () => {
1283 window.location.reload();
1bfe1d7b 1284 });
88e4e597 1285
1bfe1d7b
AD
1286 },
1287 href: query
1288 });
88e4e597 1289
1bfe1d7b 1290 dialog.show();
88e4e597 1291}
3d72afa1
AD
1292
1293function insertSSLserial(value) {
1bfe1d7b 1294 dijit.byId("SSL_CERT_SERIAL").attr('value', value);
3d72afa1 1295}
373266eb 1296
41f68571 1297function gotoExportOpml(filename, settings) {
424e28db 1298 const tmp = settings ? 1 : 0;
d75409bf 1299 document.location.href = "backend.php?op=opml&method=export&filename=" + filename + "&settings=" + tmp;
41f68571
AD
1300}
1301
1302
33f0fdd0 1303function batchSubscribe() {
424e28db 1304 const query = "backend.php?op=pref-feeds&method=batchSubscribe";
33f0fdd0 1305
1bfe1d7b
AD
1306 // overlapping widgets
1307 if (dijit.byId("batchSubDlg")) dijit.byId("batchSubDlg").destroyRecursive();
1308 if (dijit.byId("feedAddDlg")) dijit.byId("feedAddDlg").destroyRecursive();
33f0fdd0 1309
9dc5524d 1310 const dialog = new dijit.Dialog({
1bfe1d7b
AD
1311 id: "batchSubDlg",
1312 title: __("Batch subscribe"),
1313 style: "width: 600px",
1314 execute: function () {
1315 if (this.validate()) {
1bfe1d7b 1316 notify_progress(__("Subscribing to feeds..."), true);
33f0fdd0 1317
ef129fed
AD
1318 xhrPost("backend.php", this.attr('value'), () => {
1319 notify("");
1320 updateFeedList();
1321 dialog.hide();
1bfe1d7b
AD
1322 });
1323 }
1324 },
1325 href: query
1326 });
33f0fdd0 1327
1bfe1d7b 1328 dialog.show();
33f0fdd0 1329}
55f34b81 1330
1bfe1d7b
AD
1331function clearPluginData(name) {
1332 if (confirm(__("Clear stored data for this plugin?"))) {
f9ebb32c
AD
1333 notify_progress("Loading, please wait...");
1334
ef129fed
AD
1335 xhrPost("backend.php", { op: "pref-prefs", method: "clearplugindata", name: name }, () => {
1336 notify('');
1337 updatePrefsList();
1338 });
5d9abb1e
AD
1339 }
1340}
52e7b5a0
AD
1341
1342function clearSqlLog() {
1343
1344 if (confirm(__("Clear all messages in the error log?"))) {
1345
1346 notify_progress("Loading, please wait...");
52e7b5a0 1347
ef129fed
AD
1348 xhrPost("backend.php", { op: "pref-system", method: "clearLog" }, () => {
1349 updateSystemList();
1350 });
52e7b5a0
AD
1351
1352 }
1353}
1354
ab235fc5
AD
1355function updateSelectedPrompt() {
1356 // no-op shim for toggleSelectedRow()
1357}
e2e24799 1358