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