]> git.wh0rd.org - tt-rss.git/blob - classes/dlg.php
tweak dialog topmost notices; add an explanation for the batch feed editor
[tt-rss.git] / classes / dlg.php
1 <?php
2 class Dlg extends Protected_Handler {
3 private $param;
4
5 function before() {
6 if (parent::before()) {
7 header("Content-Type: text/xml; charset=utf-8");
8 $this->param = db_escape_string($_REQUEST["param"]);
9 print "<dlg>";
10 return true;
11 }
12 return false;
13 }
14
15 function after() {
16 print "</dlg>";
17 }
18
19 function exportData() {
20
21 print "<p style='text-align : center' id='export_status_message'>You need to prepare exported data first by clicking the button below.</p>";
22
23 print "<div align='center'>";
24 print "<button dojoType=\"dijit.form.Button\"
25 onclick=\"dijit.byId('dataExportDlg').prepare()\">".
26 __('Prepare data')."</button>";
27
28 print "<button dojoType=\"dijit.form.Button\"
29 onclick=\"dijit.byId('dataExportDlg').hide()\">".
30 __('Close this window')."</button>";
31
32 print "</div>";
33
34
35 }
36
37 function importOpml() {
38 header("Content-Type: text/html"); # required for iframe
39
40 print __("If you have imported labels and/or filters, you might need to reload preferences to see your new data.") . "</p>";
41
42 print "<div class=\"prefFeedOPMLHolder\">";
43 $owner_uid = $_SESSION["uid"];
44
45 db_query($this->link, "BEGIN");
46
47 /* create Imported feeds category just in case */
48
49 $result = db_query($this->link, "SELECT id FROM
50 ttrss_feed_categories WHERE title = 'Imported feeds' AND
51 owner_uid = '$owner_uid' LIMIT 1");
52
53 if (db_num_rows($result) == 0) {
54 db_query($this->link, "INSERT INTO ttrss_feed_categories
55 (title,owner_uid)
56 VALUES ('Imported feeds', '$owner_uid')");
57 }
58
59 db_query($this->link, "COMMIT");
60
61 /* Handle OPML import by DOMXML/DOMDocument */
62
63 print "<ul class='nomarks'>";
64 require_once "opml.php";
65 opml_import_domdoc($this->link, $owner_uid);
66 print "</ul>";
67 print "</div>";
68
69 print "<div align='center'>";
70 print "<button dojoType=\"dijit.form.Button\"
71 onclick=\"dijit.byId('opmlImportDlg').execute()\">".
72 __('Close this window')."</button>";
73 print "</div>";
74
75 print "</div>";
76
77 //return;
78 }
79
80 function editPrefProfiles() {
81 print "<div dojoType=\"dijit.Toolbar\">";
82
83 print "<div dojoType=\"dijit.form.DropDownButton\">".
84 "<span>" . __('Select')."</span>";
85 print "<div dojoType=\"dijit.Menu\" style=\"display: none;\">";
86 print "<div onclick=\"selectTableRows('prefFeedProfileList', 'all')\"
87 dojoType=\"dijit.MenuItem\">".__('All')."</div>";
88 print "<div onclick=\"selectTableRows('prefFeedProfileList', 'none')\"
89 dojoType=\"dijit.MenuItem\">".__('None')."</div>";
90 print "</div></div>";
91
92 print "<div style=\"float : right\">";
93
94 print "<input name=\"newprofile\" dojoType=\"dijit.form.ValidationTextBox\"
95 required=\"1\">
96 <button dojoType=\"dijit.form.Button\"
97 onclick=\"dijit.byId('profileEditDlg').addProfile()\">".
98 __('Create profile')."</button></div>";
99
100 print "</div>";
101
102 $result = db_query($this->link, "SELECT title,id FROM ttrss_settings_profiles
103 WHERE owner_uid = ".$_SESSION["uid"]." ORDER BY title");
104
105 print "<div class=\"prefFeedCatHolder\">";
106
107 print "<form id=\"profile_edit_form\" onsubmit=\"return false\">";
108
109 print "<table width=\"100%\" class=\"prefFeedProfileList\"
110 cellspacing=\"0\" id=\"prefFeedProfileList\">";
111
112 print "<tr class=\"placeholder\" id=\"FCATR-0\">"; #odd
113
114 print "<td width='5%' align='center'><input
115 id='FCATC-0'
116 onclick='toggleSelectRow2(this);'
117 dojoType=\"dijit.form.CheckBox\"
118 type=\"checkbox\"></td>";
119
120 if (!$_SESSION["profile"]) {
121 $is_active = __("(active)");
122 } else {
123 $is_active = "";
124 }
125
126 print "<td><span>" .
127 __("Default profile") . " $is_active</span></td>";
128
129 print "</tr>";
130
131 $lnum = 1;
132
133 while ($line = db_fetch_assoc($result)) {
134
135 $class = ($lnum % 2) ? "even" : "odd";
136
137 $profile_id = $line["id"];
138 $this_row_id = "id=\"FCATR-$profile_id\"";
139
140 print "<tr class=\"placeholder\" $this_row_id>";
141
142 $edit_title = htmlspecialchars($line["title"]);
143
144 print "<td width='5%' align='center'><input
145 onclick='toggleSelectRow2(this);'
146 id='FCATC-$profile_id'
147 dojoType=\"dijit.form.CheckBox\"
148 type=\"checkbox\"></td>";
149
150 if ($_SESSION["profile"] == $line["id"]) {
151 $is_active = __("(active)");
152 } else {
153 $is_active = "";
154 }
155
156 print "<td><span dojoType=\"dijit.InlineEditBox\"
157 width=\"300px\" autoSave=\"false\"
158 profile-id=\"$profile_id\">" . $edit_title .
159 "<script type=\"dojo/method\" event=\"onChange\" args=\"item\">
160 var elem = this;
161 dojo.xhrPost({
162 url: 'backend.php',
163 content: {op: 'rpc', method: 'saveprofile',
164 value: this.value,
165 id: this.srcNodeRef.getAttribute('profile-id')},
166 load: function(response) {
167 elem.attr('value', response);
168 }
169 });
170 </script>
171 </span> $is_active</td>";
172
173 print "</tr>";
174
175 ++$lnum;
176 }
177
178 print "</table>";
179 print "</form>";
180 print "</div>";
181
182 print "<div class='dlgButtons'>
183 <div style='float : left'>
184 <button dojoType=\"dijit.form.Button\" onclick=\"dijit.byId('profileEditDlg').removeSelected()\">".
185 __('Remove selected profiles')."</button>
186 <button dojoType=\"dijit.form.Button\" onclick=\"dijit.byId('profileEditDlg').activateProfile()\">".
187 __('Activate profile')."</button>
188 </div>";
189
190 print "<button dojoType=\"dijit.form.Button\" onclick=\"dijit.byId('profileEditDlg').hide()\">".
191 __('Close this window')."</button>";
192 print "</div>";
193
194 }
195
196 function pubOPMLUrl() {
197 print "<title>".__('Public OPML URL')."</title>";
198 print "<content><![CDATA[";
199
200 $url_path = opml_publish_url($this->link);
201
202 print __("Your Public OPML URL is:");
203
204 print "<div class=\"tagCloudContainer\">";
205 print "<a id='pub_opml_url' href='$url_path' target='_blank'>$url_path</a>";
206 print "</div>";
207
208 print "<div align='center'>";
209
210 print "<button dojoType=\"dijit.form.Button\" onclick=\"return opmlRegenKey()\">".
211 __('Generate new URL')."</button> ";
212
213 print "<button dojoType=\"dijit.form.Button\" onclick=\"return closeInfoBox()\">".
214 __('Close this window')."</button>";
215
216 print "</div>";
217 print "]]></content>";
218
219 //return;
220 }
221
222 function explainError() {
223 print "<title>".__('Notice')."</title>";
224 print "<content><![CDATA[";
225
226 print "<div class=\"errorExplained\">";
227
228 if ($this->param == 1) {
229 print __("Update daemon is enabled in configuration, but daemon process is not running, which prevents all feeds from updating. Please start the daemon process or contact instance owner.");
230
231 $stamp = (int) file_get_contents(LOCK_DIRECTORY . "/update_daemon.stamp");
232
233 print "<p>" . __("Last update:") . " " . date("Y.m.d, G:i", $stamp);
234
235 }
236
237 if ($this->param == 3) {
238 print __("Update daemon is taking too long to perform a feed update. This could indicate a problem like crash or a hang. Please check the daemon process or contact instance owner.");
239
240 $stamp = (int) file_get_contents(LOCK_DIRECTORY . "/update_daemon.stamp");
241
242 print "<p>" . __("Last update:") . " " . date("Y.m.d, G:i", $stamp);
243
244 }
245
246 print "</div>";
247
248 print "<div align='center'>";
249
250 print "<button onclick=\"return closeInfoBox()\">".
251 __('Close this window')."</button>";
252
253 print "</div>";
254 print "]]></content>";
255
256 //return;
257 }
258
259 function quickAddFeed() {
260 print "<input dojoType=\"dijit.form.TextBox\" style=\"display : none\" name=\"op\" value=\"rpc\">";
261 print "<input dojoType=\"dijit.form.TextBox\" style=\"display : none\" name=\"method\" value=\"addfeed\">";
262
263 print "<div class=\"dlgSec\">".__("Feed")."</div>";
264 print "<div class=\"dlgSecCont\">";
265
266 print "<input style=\"font-size : 16px; width : 20em;\"
267 placeHolder=\"".__("Feed URL")."\"
268 dojoType=\"dijit.form.ValidationTextBox\" required=\"1\" name=\"feed\" id=\"feedDlg_feedUrl\">";
269
270 print "<hr/>";
271
272 if (get_pref($this->link, 'ENABLE_FEED_CATS')) {
273 print __('Place in category:') . " ";
274 print_feed_cat_select($this->link, "cat", false, 'dojoType="dijit.form.Select"');
275 }
276
277 print "</div>";
278
279 print '<div id="feedDlg_feedsContainer" style="display : none">
280
281 <div class="dlgSec">' . __('Available feeds') . '</div>
282 <div class="dlgSecCont">'.
283 '<select id="feedDlg_feedContainerSelect"
284 dojoType="dijit.form.Select" size="3">
285 <script type="dojo/method" event="onChange" args="value">
286 dijit.byId("feedDlg_feedUrl").attr("value", value);
287 </script>
288 </select>'.
289 '</div></div>';
290
291 print "<div id='feedDlg_loginContainer' style='display : none'>
292
293 <div class=\"dlgSec\">".__("Authentication")."</div>
294 <div class=\"dlgSecCont\">".
295
296 " <input dojoType=\"dijit.form.TextBox\" name='login'\"
297 placeHolder=\"".__("Login")."\"
298 style=\"width : 10em;\"> ".
299 " <input
300 placeHolder=\"".__("Password")."\"
301 dojoType=\"dijit.form.TextBox\" type='password'
302 style=\"width : 10em;\" name='pass'\">".
303 " <p class='insensitive'>".__("OAuth will be used automatically for Twitter feeds.")."</p>
304 </div></div>";
305
306
307 print "<div style=\"clear : both\">
308 <input type=\"checkbox\" name=\"need_auth\" dojoType=\"dijit.form.CheckBox\" id=\"feedDlg_loginCheck\"
309 onclick='checkboxToggleElement(this, \"feedDlg_loginContainer\")'>
310 <label for=\"feedDlg_loginCheck\">".
311 __('This feed requires authentication.')."</div>";
312
313 print "</form>";
314
315 print "<div class=\"dlgButtons\">
316 <button dojoType=\"dijit.form.Button\" onclick=\"return dijit.byId('feedAddDlg').execute()\">".__('Subscribe')."</button>
317 <button dojoType=\"dijit.form.Button\" onclick=\"return feedBrowser()\">".__('More feeds')."</button>
318 <button dojoType=\"dijit.form.Button\" onclick=\"return dijit.byId('feedAddDlg').hide()\">".__('Cancel')."</button>
319 </div>";
320
321 //return;
322 }
323
324 function feedBrowser() {
325 $browser_search = db_escape_string($_REQUEST["search"]);
326
327 print "<input dojoType=\"dijit.form.TextBox\" style=\"display : none\" name=\"op\" value=\"rpc\">";
328 print "<input dojoType=\"dijit.form.TextBox\" style=\"display : none\" name=\"method\" value=\"updateFeedBrowser\">";
329
330 print "<div dojoType=\"dijit.Toolbar\">
331 <div style='float : right'>
332 <img style='display : none'
333 id='feed_browser_spinner' src='".
334 theme_image($this->link, 'images/indicator_white.gif')."'>
335 <input name=\"search\" dojoType=\"dijit.form.TextBox\" size=\"20\" type=\"search\"
336 onchange=\"dijit.byId('feedBrowserDlg').update()\" value=\"$browser_search\">
337 <button dojoType=\"dijit.form.Button\" onclick=\"dijit.byId('feedBrowserDlg').update()\">".__('Search')."</button>
338 </div>";
339
340 print " <select name=\"mode\" dojoType=\"dijit.form.Select\" onchange=\"dijit.byId('feedBrowserDlg').update()\">
341 <option value='1'>" . __('Popular feeds') . "</option>
342 <option value='2'>" . __('Feed archive') . "</option>
343 </select> ";
344
345 print __("limit:");
346
347 print " <select dojoType=\"dijit.form.Select\" name=\"limit\" onchange=\"dijit.byId('feedBrowserDlg').update()\">";
348
349 foreach (array(25, 50, 100, 200) as $l) {
350 $issel = ($l == $limit) ? "selected=\"1\"" : "";
351 print "<option $issel value=\"$l\">$l</option>";
352 }
353
354 print "</select> ";
355
356 print "</div>";
357
358 $owner_uid = $_SESSION["uid"];
359
360 print "<ul class='browseFeedList' id='browseFeedList'>";
361 print make_feed_browser($this->link, $search, 25);
362 print "</ul>";
363
364 print "<div align='center'>
365 <button dojoType=\"dijit.form.Button\" onclick=\"dijit.byId('feedBrowserDlg').execute()\">".__('Subscribe')."</button>
366 <button dojoType=\"dijit.form.Button\" style='display : none' id='feed_archive_remove' onclick=\"dijit.byId('feedBrowserDlg').removeFromArchive()\">".__('Remove')."</button>
367 <button dojoType=\"dijit.form.Button\" onclick=\"dijit.byId('feedBrowserDlg').hide()\" >".__('Cancel')."</button></div>";
368
369 }
370
371 function search() {
372 $this->params = explode(":", db_escape_string($_REQUEST["param"]), 2);
373
374 $active_feed_id = sprintf("%d", $this->params[0]);
375 $is_cat = $this->params[1] != "false";
376
377 print "<div class=\"dlgSec\">".__('Look for')."</div>";
378
379 print "<div class=\"dlgSecCont\">";
380
381 if (!SPHINX_ENABLED) {
382
383 print "<input dojoType=\"dijit.form.ValidationTextBox\"
384 style=\"font-size : 16px; width : 12em;\"
385 required=\"1\" name=\"query\" type=\"search\" value=''>";
386
387 print " " . __('match on')." ";
388
389 $search_fields = array(
390 "title" => __("Title"),
391 "content" => __("Content"),
392 "both" => __("Title or content"));
393
394 print_select_hash("match_on", 3, $search_fields,
395 'dojoType="dijit.form.Select"');
396 } else {
397 print "<input dojoType=\"dijit.form.ValidationTextBox\"
398 style=\"font-size : 16px; width : 20em;\"
399 required=\"1\" name=\"query\" type=\"search\" value=''>";
400 }
401
402
403 print "<hr/>".__('Limit search to:')." ";
404
405 print "<select name=\"search_mode\" dojoType=\"dijit.form.Select\">
406 <option value=\"all_feeds\">".__('All feeds')."</option>";
407
408 $feed_title = getFeedTitle($this->link, $active_feed_id);
409
410 if (!$is_cat) {
411 $feed_cat_title = getFeedCatTitle($this->link, $active_feed_id);
412 } else {
413 $feed_cat_title = getCategoryTitle($this->link, $active_feed_id);
414 }
415
416 if ($active_feed_id && !$is_cat) {
417 print "<option selected=\"1\" value=\"this_feed\">$feed_title</option>";
418 } else {
419 print "<option disabled=\"1\" value=\"false\">".__('This feed')."</option>";
420 }
421
422 if ($is_cat) {
423 $cat_preselected = "selected=\"1\"";
424 }
425
426 if (get_pref($this->link, 'ENABLE_FEED_CATS') && ($active_feed_id > 0 || $is_cat)) {
427 print "<option $cat_preselected value=\"this_cat\">$feed_cat_title</option>";
428 } else {
429 //print "<option disabled>".__('This category')."</option>";
430 }
431
432 print "</select>";
433
434 print "</div>";
435
436 print "<div class=\"dlgButtons\">";
437
438 if (!SPHINX_ENABLED) {
439 print "<div style=\"float : left\">
440 <a class=\"visibleLink\" target=\"_blank\" href=\"http://tt-rss.org/redmine/wiki/tt-rss/SearchSyntax\">Search syntax</a>
441 </div>";
442 }
443
444 print "<button dojoType=\"dijit.form.Button\" onclick=\"dijit.byId('searchDlg').execute()\">".__('Search')."</button>
445 <button dojoType=\"dijit.form.Button\" onclick=\"dijit.byId('searchDlg').hide()\">".__('Cancel')."</button>
446 </div>";
447 }
448
449 function quickAddFilter() {
450 $active_feed_id = db_escape_string($_REQUEST["param"]);
451
452 print "<input dojoType=\"dijit.form.TextBox\" style=\"display : none\" name=\"op\" value=\"pref-filters\">";
453 print "<input dojoType=\"dijit.form.TextBox\" style=\"display : none\" name=\"quiet\" value=\"1\">";
454 print "<input dojoType=\"dijit.form.TextBox\" style=\"display : none\" name=\"method\" value=\"add\">";
455 print "<input dojoType=\"dijit.form.TextBox\" style=\"display : none\" name=\"csrf_token\" value=\"".$_SESSION['csrf_token']."\">";
456
457 $result = db_query($this->link, "SELECT id,description
458 FROM ttrss_filter_types ORDER BY description");
459
460 $filter_types = array();
461
462 while ($line = db_fetch_assoc($result)) {
463 //array_push($filter_types, $line["description"]);
464 $filter_types[$line["id"]] = __($line["description"]);
465 }
466
467 print "<div class=\"dlgSec\">".__("Match")."</div>";
468
469 print "<div class=\"dlgSecCont\">";
470
471 print "<span id=\"filterDlg_dateModBox\" style=\"display : none\">";
472
473 $filter_params = array(
474 "before" => __("before"),
475 "after" => __("after"));
476
477 print_select_hash("filter_date_modifier", "before",
478 $filter_params, 'dojoType="dijit.form.Select"');
479
480 print "&nbsp;</span>";
481
482 print "<input dojoType=\"dijit.form.ValidationTextBox\"
483 required=\"true\" id=\"filterDlg_regExp\"
484 style=\"font-size : 16px\"
485 name=\"reg_exp\" value=\"$reg_exp\"/>";
486
487 print "<span id=\"filterDlg_dateChkBox\" style=\"display : none\">";
488 print "&nbsp;<button dojoType=\"dijit.form.Button\"
489 onclick=\"return filterDlgCheckDate()\">".
490 __('Check it')."</button>";
491 print "</span>";
492
493 print "<hr/>" . __("on field") . " ";
494 print_select_hash("filter_type", 1, $filter_types,
495 'onchange="filterDlgCheckType(this)" dojoType="dijit.form.Select"');
496
497 print "<hr/>";
498
499 print __("in") . " ";
500
501 print "<span id='filterDlg_feeds'>";
502 print_feed_select($this->link, "feed_id", $active_feed_id,
503 'dojoType="dijit.form.FilteringSelect"');
504 print "</span>";
505
506 print "<span id='filterDlg_cats' style='display : none'>";
507 print_feed_cat_select($this->link, "cat_id", $active_cat_id,
508 'dojoType="dijit.form.FilteringSelect"');
509 print "</span>";
510
511 print "</div>";
512
513 print "<div class=\"dlgSec\">".__("Perform Action")."</div>";
514
515 print "<div class=\"dlgSecCont\">";
516
517 print "<select name=\"action_id\" dojoType=\"dijit.form.Select\"
518 onchange=\"filterDlgCheckAction(this)\">";
519
520 $result = db_query($this->link, "SELECT id,description FROM ttrss_filter_actions
521 ORDER BY name");
522
523 while ($line = db_fetch_assoc($result)) {
524 printf("<option value='%d'>%s</option>", $line["id"], __($line["description"]));
525 }
526
527 print "</select>";
528
529 print "<span id=\"filterDlg_paramBox\" style=\"display : none\">";
530 print " " . __("with parameters:") . " ";
531 print "<input dojoType=\"dijit.form.TextBox\"
532 id=\"filterDlg_actionParam\"
533 name=\"action_param\">";
534
535 print_label_select($this->link, "action_param_label", $action_param,
536 'id="filterDlg_actionParamLabel" dojoType="dijit.form.Select"');
537
538 print "</span>";
539
540 print "&nbsp;"; // tiny layout hack
541
542 print "</div>";
543
544 print "<div class=\"dlgSec\">".__("Options")."</div>";
545 print "<div class=\"dlgSecCont\">";
546
547 print "<input dojoType=\"dijit.form.CheckBox\" type=\"checkbox\" name=\"enabled\" id=\"enabled\" checked=\"1\">
548 <label for=\"enabled\">".__('Enabled')."</label><hr/>";
549
550 print "<input dojoType=\"dijit.form.CheckBox\" type=\"checkbox\" name=\"inverse\" id=\"inverse\">
551 <label for=\"inverse\">".__('Inverse match')."</label><hr/>";
552
553 print "<input dojoType=\"dijit.form.CheckBox\" type=\"checkbox\" name=\"cat_filter\" id=\"cat_filter\" onchange=\"filterDlgCheckCat(this)\">
554 <label for=\"cat_filter\">".__('Apply to category')."</label><hr/>";
555
556
557 print "</div>";
558
559 print "<div class=\"dlgButtons\">";
560
561 print "<button dojoType=\"dijit.form.Button\" onclick=\"return dijit.byId('filterEditDlg').test()\">".
562 __('Test')."</button> ";
563
564 print "<button dojoType=\"dijit.form.Button\" onclick=\"return dijit.byId('filterEditDlg').execute()\">".
565 __('Create')."</button> ";
566
567 print "<button dojoType=\"dijit.form.Button\" onclick=\"return dijit.byId('filterEditDlg').hide()\">".
568 __('Cancel')."</button>";
569
570 print "</div>";
571 }
572
573 function inactiveFeeds() {
574
575 if (DB_TYPE == "pgsql") {
576 $interval_qpart = "NOW() - INTERVAL '3 months'";
577 } else {
578 $interval_qpart = "DATE_SUB(NOW(), INTERVAL 3 MONTH)";
579 }
580
581 $result = db_query($this->link, "SELECT ttrss_feeds.title, ttrss_feeds.site_url,
582 ttrss_feeds.feed_url, ttrss_feeds.id, MAX(updated) AS last_article
583 FROM ttrss_feeds, ttrss_entries, ttrss_user_entries WHERE
584 (SELECT MAX(updated) FROM ttrss_entries, ttrss_user_entries WHERE
585 ttrss_entries.id = ref_id AND
586 ttrss_user_entries.feed_id = ttrss_feeds.id) < $interval_qpart
587 AND ttrss_feeds.owner_uid = ".$_SESSION["uid"]." AND
588 ttrss_user_entries.feed_id = ttrss_feeds.id AND
589 ttrss_entries.id = ref_id
590 GROUP BY ttrss_feeds.title, ttrss_feeds.id, ttrss_feeds.site_url, ttrss_feeds.feed_url
591 ORDER BY last_article");
592
593 print "<div class=\"dialogNotice\">" . __("These feeds have not been updated with new content for 3 months (oldest first):") . "</div>";
594
595 print "<div dojoType=\"dijit.Toolbar\">";
596 print "<div dojoType=\"dijit.form.DropDownButton\">".
597 "<span>" . __('Select')."</span>";
598 print "<div dojoType=\"dijit.Menu\" style=\"display: none;\">";
599 print "<div onclick=\"selectTableRows('prefInactiveFeedList', 'all')\"
600 dojoType=\"dijit.MenuItem\">".__('All')."</div>";
601 print "<div onclick=\"selectTableRows('prefInactiveFeedList', 'none')\"
602 dojoType=\"dijit.MenuItem\">".__('None')."</div>";
603 print "</div></div>";
604 print "</div>"; #toolbar
605
606 print "<div class=\"inactiveFeedHolder\">";
607
608 print "<table width=\"100%\" cellspacing=\"0\" id=\"prefInactiveFeedList\">";
609
610 $lnum = 1;
611
612 while ($line = db_fetch_assoc($result)) {
613
614 $class = ($lnum % 2) ? "even" : "odd";
615 $feed_id = $line["id"];
616 $this_row_id = "id=\"FUPDD-$feed_id\"";
617
618 # class needed for selectTableRows()
619 print "<tr class=\"placeholder\" $this_row_id>";
620
621 $edit_title = htmlspecialchars($line["title"]);
622
623 # id needed for selectTableRows()
624 print "<td width='5%' align='center'><input
625 onclick='toggleSelectRow2(this);' dojoType=\"dijit.form.CheckBox\"
626 type=\"checkbox\" id=\"FUPDC-$feed_id\"></td>";
627 print "<td>";
628
629 print "<a class=\"visibleLink\" href=\"#\" ".
630 "title=\"".__("Click to edit feed")."\" ".
631 "onclick=\"editFeed(".$line["id"].")\">".
632 htmlspecialchars($line["title"])."</a>";
633
634 print "</td><td class=\"insensitive\" align='right'>";
635 print make_local_datetime($this->link, $line['last_article'], false);
636 print "</td>";
637 print "</tr>";
638
639 ++$lnum;
640 }
641
642 print "</table>";
643 print "</div>";
644
645 print "<div class='dlgButtons'>";
646 print "<div style='float : left'>";
647 print "<button dojoType=\"dijit.form.Button\" onclick=\"dijit.byId('inactiveFeedsDlg').removeSelected()\">"
648 .__('Unsubscribe from selected feeds')."</button> ";
649 print "</div>";
650
651 print "<button dojoType=\"dijit.form.Button\" onclick=\"dijit.byId('inactiveFeedsDlg').hide()\">".
652 __('Close this window')."</button>";
653
654 print "</div>";
655
656 }
657
658 function feedsWithErrors() {
659 print "<div class=\"dialogNotice\">" . __("These feeds have not been updated because of errors:") . "</div>";
660
661 $result = db_query($this->link, "SELECT id,title,feed_url,last_error,site_url
662 FROM ttrss_feeds WHERE last_error != '' AND owner_uid = ".$_SESSION["uid"]);
663
664 print "<div dojoType=\"dijit.Toolbar\">";
665 print "<div dojoType=\"dijit.form.DropDownButton\">".
666 "<span>" . __('Select')."</span>";
667 print "<div dojoType=\"dijit.Menu\" style=\"display: none;\">";
668 print "<div onclick=\"selectTableRows('prefErrorFeedList', 'all')\"
669 dojoType=\"dijit.MenuItem\">".__('All')."</div>";
670 print "<div onclick=\"selectTableRows('prefErrorFeedList', 'none')\"
671 dojoType=\"dijit.MenuItem\">".__('None')."</div>";
672 print "</div></div>";
673 print "</div>"; #toolbar
674
675 print "<div class=\"inactiveFeedHolder\">";
676
677 print "<table width=\"100%\" cellspacing=\"0\" id=\"prefErrorFeedList\">";
678
679 $lnum = 1;
680
681 while ($line = db_fetch_assoc($result)) {
682
683 $class = ($lnum % 2) ? "even" : "odd";
684 $feed_id = $line["id"];
685 $this_row_id = "id=\"FUPDD-$feed_id\"";
686
687 # class needed for selectTableRows()
688 print "<tr class=\"placeholder\" $this_row_id>";
689
690 $edit_title = htmlspecialchars($line["title"]);
691
692 # id needed for selectTableRows()
693 print "<td width='5%' align='center'><input
694 onclick='toggleSelectRow2(this);' dojoType=\"dijit.form.CheckBox\"
695 type=\"checkbox\" id=\"FUPDC-$feed_id\"></td>";
696 print "<td>";
697
698 print "<a class=\"visibleLink\" href=\"#\" ".
699 "title=\"".__("Click to edit feed")."\" ".
700 "onclick=\"editFeed(".$line["id"].")\">".
701 htmlspecialchars($line["title"])."</a>: ";
702
703 print "<span class=\"insensitive\">";
704 print htmlspecialchars($line["last_error"]);
705 print "</span>";
706
707 print "</td>";
708 print "</tr>";
709
710 ++$lnum;
711 }
712
713 print "</table>";
714 print "</div>";
715
716 print "<div class='dlgButtons'>";
717 print "<div style='float : left'>";
718 print "<button dojoType=\"dijit.form.Button\" onclick=\"dijit.byId('errorFeedsDlg').removeSelected()\">"
719 .__('Unsubscribe from selected feeds')."</button> ";
720 print "</div>";
721
722 print "<button dojoType=\"dijit.form.Button\" onclick=\"dijit.byId('errorFeedsDlg').hide()\">".
723 __('Close this window')."</button>";
724
725 print "</div>";
726 }
727
728 function editArticleTags() {
729
730 print __("Tags for this article (separated by commas):")."<br>";
731
732 $tags = get_article_tags($this->link, $this->param);
733
734 $tags_str = join(", ", $tags);
735
736 print "<input dojoType=\"dijit.form.TextBox\" style=\"display : none\" name=\"id\" value=\"$this->param\">";
737 print "<input dojoType=\"dijit.form.TextBox\" style=\"display : none\" name=\"op\" value=\"rpc\">";
738 print "<input dojoType=\"dijit.form.TextBox\" style=\"display : none\" name=\"method\" value=\"setArticleTags\">";
739
740 print "<table width='100%'><tr><td>";
741
742 print "<textarea dojoType=\"dijit.form.SimpleTextarea\" rows='4'
743 style='font-size : 12px; width : 100%' id=\"tags_str\"
744 name='tags_str'>$tags_str</textarea>
745 <div class=\"autocomplete\" id=\"tags_choices\"
746 style=\"display:none\"></div>";
747
748 print "</td></tr></table>";
749
750 print "<div class='dlgButtons'>";
751
752 print "<button dojoType=\"dijit.form.Button\"
753 onclick=\"dijit.byId('editTagsDlg').execute()\">".__('Save')."</button> ";
754 print "<button dojoType=\"dijit.form.Button\"
755 onclick=\"dijit.byId('editTagsDlg').hide()\">".__('Cancel')."</button>";
756 print "</div>";
757
758 }
759
760 function printTagCloud() {
761 print "<title>".__('Tag Cloud')."</title>";
762 print "<content><![CDATA[";
763
764 print "<div class=\"tagCloudContainer\">";
765
766 // from here: http://www.roscripts.com/Create_tag_cloud-71.html
767
768 $query = "SELECT tag_name, COUNT(post_int_id) AS count
769 FROM ttrss_tags WHERE owner_uid = ".$_SESSION["uid"]."
770 GROUP BY tag_name ORDER BY count DESC LIMIT 50";
771
772 $result = db_query($this->link, $query);
773
774 $tags = array();
775
776 while ($line = db_fetch_assoc($result)) {
777 $tags[$line["tag_name"]] = $line["count"];
778 }
779
780 if( count($tags) == 0 ){ return; }
781
782 ksort($tags);
783
784 $max_size = 32; // max font size in pixels
785 $min_size = 11; // min font size in pixels
786
787 // largest and smallest array values
788 $max_qty = max(array_values($tags));
789 $min_qty = min(array_values($tags));
790
791 // find the range of values
792 $spread = $max_qty - $min_qty;
793 if ($spread == 0) { // we don't want to divide by zero
794 $spread = 1;
795 }
796
797 // set the font-size increment
798 $step = ($max_size - $min_size) / ($spread);
799
800 // loop through the tag array
801 foreach ($tags as $key => $value) {
802 // calculate font-size
803 // find the $value in excess of $min_qty
804 // multiply by the font-size increment ($size)
805 // and add the $min_size set above
806 $size = round($min_size + (($value - $min_qty) * $step));
807
808 $key_escaped = str_replace("'", "\\'", $key);
809
810 echo "<a href=\"javascript:viewfeed('$key_escaped') \" style=\"font-size: " .
811 $size . "px\" title=\"$value articles tagged with " .
812 $key . '">' . $key . '</a> ';
813 }
814
815
816
817 print "</div>";
818
819 print "<div align='center'>";
820 print "<button dojoType=\"dijit.form.Button\"
821 onclick=\"return closeInfoBox()\">".
822 __('Close this window')."</button>";
823 print "</div>";
824
825 print "]]></content>";
826 }
827
828 function printTagSelect() {
829
830 print "<title>" . __('Select item(s) by tags') . "</title>";
831 print "<content><![CDATA[";
832
833 print __("Match:"). "&nbsp;" .
834 "<input class=\"noborder\" dojoType=\"dijit.form.RadioButton\" type=\"radio\" checked value=\"any\" name=\"tag_mode\">&nbsp;Any&nbsp;";
835 print "<input class=\"noborder\" dojoType=\"dijit.form.RadioButton\" type=\"radio\" value=\"all\" name=\"tag_mode\">&nbsp;All&nbsp;";
836 print "&nbsp;tags.";
837
838 print "<select id=\"all_tags\" name=\"all_tags\" title=\"" . __('Which Tags?') . "\" multiple=\"multiple\" size=\"10\" style=\"width : 100%\">";
839 $result = db_query($this->link, "SELECT DISTINCT tag_name FROM ttrss_tags WHERE owner_uid = ".$_SESSION['uid']."
840 AND LENGTH(tag_name) <= 30 ORDER BY tag_name ASC");
841
842 while ($row = db_fetch_assoc($result)) {
843 $tmp = htmlspecialchars($row["tag_name"]);
844 print "<option value=\"" . str_replace(" ", "%20", $tmp) . "\">$tmp</option>";
845 }
846
847 print "</select>";
848
849 print "<div align='right'>";
850 print "<button dojoType=\"dijit.form.Button\" onclick=\"viewfeed(get_all_tags($('all_tags')),
851 get_radio_checked($('tag_mode')));\">" . __('Display entries') . "</button>";
852 print "&nbsp;";
853 print "<button dojoType=\"dijit.form.Button\"
854 onclick=\"return closeInfoBox()\">" .
855 __('Close this window') . "</button>";
856 print "</div>";
857
858 print "]]></content>";
859 }
860
861 function generatedFeed() {
862
863 print "<title>".__('View as RSS')."</title>";
864 print "<content><![CDATA[";
865
866 $this->params = explode(":", $this->param, 3);
867 $feed_id = db_escape_string($this->params[0]);
868 $is_cat = (bool) $this->params[1];
869
870 $key = get_feed_access_key($this->link, $feed_id, $is_cat);
871
872 $url_path = htmlspecialchars($this->params[2]) . "&key=" . $key;
873
874 print "<div class=\"dialogNotice\">" . __("You can view this feed as RSS using the following URL:") . "</div>";
875
876 print "<div class=\"tagCloudContainer\">";
877 print "<a id='gen_feed_url' href='$url_path' target='_blank'>$url_path</a>";
878 print "</div>";
879
880 print "<div align='center'>";
881
882 print "<button dojoType=\"dijit.form.Button\" onclick=\"return genUrlChangeKey('$feed_id', '$is_cat')\">".
883 __('Generate new URL')."</button> ";
884
885 print "<button dojoType=\"dijit.form.Button\" onclick=\"return closeInfoBox()\">".
886 __('Close this window')."</button>";
887
888 print "</div>";
889 print "]]></content>";
890
891 //return;
892 }
893
894 function newVersion() {
895
896 $version_data = check_for_update($this->link);
897 $version = $version_data['version'];
898 $id = $version_data['version_id'];
899
900 print "<div class='tagCloudContainer'>";
901
902 print T_sprintf("New version of Tiny Tiny RSS is available (%s).",
903 "<b>$version</b>");
904
905 print "</div>";
906
907 $details = "http://tt-rss.org/redmine/versions/show/$id";
908 $download = "http://tt-rss.org/#Download";
909
910 print "<div style='text-align : center'>";
911 print "<button dojoType=\"dijit.form.Button\"
912 onclick=\"return window.open('$details')\">".__("Details")."</button>";
913 print "<button dojoType=\"dijit.form.Button\"
914 onclick=\"return window.open('$download')\">".__("Download")."</button>";
915 print "<button dojoType=\"dijit.form.Button\"
916 onclick=\"return dijit.byId('newVersionDlg').hide()\">".
917 __('Close this window')."</button>";
918 print "</div>";
919
920 }
921
922 function customizeCSS() {
923 $value = get_pref($this->link, "USER_STYLESHEET");
924
925 $value = str_replace("<br/>", "\n", $value);
926
927 print "<div class=\"dialogNotice\">";
928 print T_sprintf("You can override colors, fonts and layout of your currently selected theme with custom CSS declarations here. <a target=\"_blank\" class=\"visibleLink\" href=\"%s\">This file</a> can be used as a baseline.", "tt-rss.css");
929 print "</div>";
930
931 print "<input dojoType=\"dijit.form.TextBox\" style=\"display : none\" name=\"op\" value=\"rpc\">";
932 print "<input dojoType=\"dijit.form.TextBox\" style=\"display : none\" name=\"method\" value=\"setpref\">";
933 print "<input dojoType=\"dijit.form.TextBox\" style=\"display : none\" name=\"key\" value=\"USER_STYLESHEET\">";
934
935 print "<table width='100%'><tr><td>";
936 print "<textarea dojoType=\"dijit.form.SimpleTextarea\"
937 style='font-size : 12px; width : 100%; height: 200px;'
938 placeHolder='body#ttrssMain { font-size : 14px; };'
939 name='value'>$value</textarea>";
940 print "</td></tr></table>";
941
942 print "<div class='dlgButtons'>";
943 print "<button dojoType=\"dijit.form.Button\"
944 onclick=\"dijit.byId('cssEditDlg').execute()\">".__('Save')."</button> ";
945 print "<button dojoType=\"dijit.form.Button\"
946 onclick=\"dijit.byId('cssEditDlg').hide()\">".__('Cancel')."</button>";
947 print "</div>";
948
949 }
950
951 function addInstance() {
952 print "<input dojoType=\"dijit.form.TextBox\" style=\"display : none\" name=\"op\" value=\"pref-instances\">";
953 print "<input dojoType=\"dijit.form.TextBox\" style=\"display : none\" name=\"method\" value=\"add\">";
954
955 print "<div class=\"dlgSec\">".__("Instance")."</div>";
956
957 print "<div class=\"dlgSecCont\">";
958
959 /* URL */
960
961 print __("URL:") . " ";
962
963 print "<input dojoType=\"dijit.form.ValidationTextBox\" required=\"1\"
964 placeHolder=\"".__("Instance URL")."\"
965 regExp='^(http|https)://.*'
966 style=\"font-size : 16px; width: 20em\" name=\"access_url\">";
967
968 print "<hr/>";
969
970 $access_key = sha1(uniqid(rand(), true));
971
972 /* Access key */
973
974 print __("Access key:") . " ";
975
976 print "<input dojoType=\"dijit.form.ValidationTextBox\" required=\"1\"
977 placeHolder=\"".__("Access key")."\" regExp='\w{40}'
978 style=\"width: 20em\" name=\"access_key\" id=\"instance_add_key\"
979 value=\"$access_key\">";
980
981 print "<p class='insensitive'>" . __("Use one access key for both linked instances.");
982
983 print "</div>";
984
985 print "<div class=\"dlgButtons\">
986 <div style='float : left'>
987 <button dojoType=\"dijit.form.Button\"
988 onclick=\"return dijit.byId('instanceAddDlg').regenKey()\">".
989 __('Generate new key')."</button>
990 </div>
991 <button dojoType=\"dijit.form.Button\"
992 onclick=\"return dijit.byId('instanceAddDlg').execute()\">".
993 __('Create link')."</button>
994 <button dojoType=\"dijit.form.Button\"
995 onclick=\"return dijit.byId('instanceAddDlg').hide()\"\">".
996 __('Cancel')."</button></div>";
997
998 return;
999 }
1000
1001 function dataImport() {
1002 header("Content-Type: text/html"); # required for iframe
1003
1004 print "<div style='text-align : center'>";
1005
1006 if (is_file($_FILES['export_file']['tmp_name'])) {
1007
1008 perform_data_import($this->link, $_FILES['export_file']['tmp_name'], $_SESSION['uid']);
1009
1010 } else {
1011 print "<p>" . T_sprintf("Could not upload file. You might need to adjust upload_max_filesize
1012 in PHP.ini (current value = %s)", ini_get("upload_max_filesize")) . " or use CLI import tool.</p>";
1013
1014 }
1015
1016 print "<button dojoType=\"dijit.form.Button\"
1017 onclick=\"dijit.byId('dataImportDlg').hide()\">".
1018 __('Close this window')."</button>";
1019
1020 print "</div>";
1021
1022 }
1023
1024 function batchSubscribe() {
1025 print "<input dojoType=\"dijit.form.TextBox\" style=\"display : none\" name=\"op\" value=\"rpc\">";
1026 print "<input dojoType=\"dijit.form.TextBox\" style=\"display : none\" name=\"method\" value=\"batchaddfeeds\">";
1027
1028 print "<table width='100%'><tr><td>
1029 ".__("Add one valid RSS feed per line (no feed detection is done)")."
1030 </td><td align='right'>";
1031 if (get_pref($this->link, 'ENABLE_FEED_CATS')) {
1032 print __('Place in category:') . " ";
1033 print_feed_cat_select($this->link, "cat", false, 'dojoType="dijit.form.Select"');
1034 }
1035 print "</td></tr><tr><td colspan='2'>";
1036 print "<textarea
1037 style='font-size : 12px; width : 100%; height: 200px;'
1038 placeHolder=\"".__("Feeds to subscribe, One per line")."\"
1039 dojoType=\"dijit.form.SimpleTextarea\" required=\"1\" name=\"feeds\"></textarea>";
1040
1041 print "</td></tr><tr><td colspan='2'>";
1042
1043 print "<div id='feedDlg_loginContainer' style='display : none'>
1044 " .
1045 " <input dojoType=\"dijit.form.TextBox\" name='login'\"
1046 placeHolder=\"".__("Login")."\"
1047 style=\"width : 10em;\"> ".
1048 " <input
1049 placeHolder=\"".__("Password")."\"
1050 dojoType=\"dijit.form.TextBox\" type='password'
1051 style=\"width : 10em;\" name='pass'\">".
1052 " <p class='insensitive'>".__("OAuth will be used automatically for Twitter feeds.")."</p>
1053 </div>";
1054
1055 print "</td></tr><tr><td colspan='2'>";
1056
1057 print "<div style=\"clear : both\">
1058 <input type=\"checkbox\" name=\"need_auth\" dojoType=\"dijit.form.CheckBox\" id=\"feedDlg_loginCheck\"
1059 onclick='checkboxToggleElement(this, \"feedDlg_loginContainer\")'>
1060 <label for=\"feedDlg_loginCheck\">".
1061 __('Feeds require authentication.')."</div>";
1062
1063 print "</form>";
1064
1065 print "</td></tr></table>";
1066
1067 print "<div class=\"dlgButtons\">
1068 <button dojoType=\"dijit.form.Button\" onclick=\"return dijit.byId('batchSubDlg').execute()\">".__('Subscribe')."</button>
1069 <button dojoType=\"dijit.form.Button\" onclick=\"return dijit.byId('batchSubDlg').hide()\">".__('Cancel')."</button>
1070 </div>";
1071 }
1072
1073 }
1074 ?>