5
* Copyright 2011-2013 Horde LLC (http://www.horde.org/)
7
* See the enclosed file LICENSE for license information (BSD). If you did not
8
* did not receive this file, see http://www.horde.org/licenses/bsdl.php.
10
* @author Michael J Rubinsky <mrubinsk@horde.org>
30
* Flag to indicate whether or not to show the tag browser
34
protected $_showTagBrowser = true;
44
* Share representing the current smarlist (if being viewed).
46
* @var Horde_Share_Object_Base
48
protected $_smartShare;
53
* @var Horde_Variables
60
* @param Horde_Variables $vars Variables for the view.
62
* @return Nag_View_List
64
public function __construct($vars)
67
$this->_title = _("My Tasks");
68
$this->_browser = $GLOBALS['injector']
69
->getInstance('Nag_Factory_TagBrowser')
71
$this->_checkSortValue();
72
$this->_handleActions();
78
* @param Horde_PageOutput $output The output object.
80
* @return string The HTML needed to render the view.
82
public function render($output)
84
global $injector, $prefs;
86
$output->addScriptFile('tooltips.js', 'horde');
87
$output->addScriptFile('scriptaculous/effects.js', 'horde');
88
$output->addScriptFile('quickfinder.js', 'horde');
89
$output->header(array(
90
'title' => $this->_title
93
$tabs = new Horde_Core_Ui_Tabs('tab_name', $this->_vars);
94
if (!$GLOBALS['prefs']->isLocked('show_completed')) {
95
$listurl = Horde::url('list.php');
96
$tabs->addTab(_("_All tasks"), $listurl->add('show_completed', Nag::VIEW_ALL), Nag::VIEW_ALL);
97
$tabs->addTab(_("Incom_plete tasks"), $listurl->add('show_completed', Nag::VIEW_INCOMPLETE), Nag::VIEW_INCOMPLETE);
98
$tabs->addTab(_("_Future tasks"), $listurl->add('show_completed', Nag::VIEW_FUTURE), Nag::VIEW_FUTURE);
99
$tabs->addTab(_("_Completed tasks"), $listurl->add('show_completed', Nag::VIEW_COMPLETE), Nag::VIEW_COMPLETE);
102
foreach (Nag::listTasklists() as $list) {
103
if ($list->get('issmart')) {
106
$listurl->add(array('actionID' => 'smart', 'list' => $list->getName())),
107
array('img' => 'search.png', 'tabname' => $list->getName()));
112
$view = $GLOBALS['injector']->createInstance('Horde_View');
113
$view->addHelper(new Nag_View_Helper_List($view));
114
$view->tasks = $this->_tasks;
115
$view->tabs = $tabs->render($this->_vars->get('tab_name', $prefs->getValue('show_completed')));
116
$view->browser = empty($this->_smartShare) && $this->_showTagBrowser ? $this->_getRelatedTags() . $this->_getTagTrail() : '';
117
$view->title = $this->_title;
118
$view->sortby = $prefs->getValue('sortby');
119
$view->sortdir = $prefs->getValue('sortdir');
120
$view->sortdirclass = $view->sortdir ? 'sortup' : 'sortdown';
121
$view->dateFormat = $prefs->getValue('date_format');
122
$view->columns = @unserialize($prefs->getValue('tasklist_columns'));
123
$view->smartShare = $this->_smartShare;
124
if (empty($view->columns)) {
125
$view->columns = array();
127
$view->dynamic_sort = true;
129
$view->baseurl = Horde::url('list.php');
130
if ($this->_vars->actionID == 'search_tasks') {
132
array('actionID' => 'search_tasks',
133
'search_pattern' => $search_pattern,
134
'search_name' => $search_name ? 'on' : 'off',
135
'search_desc' => $search_desc ? 'on' : 'off')
139
$view->tasks->reset();
140
Horde::startBuffer();
142
echo $view->render('list');
145
return Horde::endBuffer();
149
* Helper to check/update the sort prefs
151
protected function _checkSortValue()
155
// First check for any passed in sorting value changes.
156
if ($this->_vars->exists('sortby')) {
157
$prefs->setValue('sortby', $this->_vars->sortby);
159
if ($this->_vars->exists('sortdir')) {
160
$prefs->setValue('sortdir', $this->_vars->sortdir);
162
if ($this->_vars->exists('show_completed')) {
163
$prefs->setValue('show_completed', $this->_vars->get('show_completed'));
165
$this->_vars->set('show_completed', $prefs->getValue('show_completed'));
170
* Helper to handle any incoming actions.
172
protected function _handleActions($action = null)
175
if (is_null($action)) {
176
$action = $this->_vars->actionID;
180
if ($this->_vars->deletebutton) {
181
$this->_doDeleteSmartList();
182
$this->_handleActions(false);
188
case 'browse_remove':
190
// The tag to add|remove from the browse search.
191
$tag = trim($this->_vars->get('tag'));
193
if ($this->_vars->actionID == 'browse_add') {
194
$this->_browser->addTag($tag);
196
$this->_browser->removeTag($tag);
198
$this->_browser->save();
200
if ($this->_browser->tagCount() < 1) {
201
$this->_browser->clearSearch();
204
$this->_browser->setFilter($this->_vars->show_completed);
205
$this->_tasks = $this->_browser->getSlice();
209
$lists = array($this->_vars->get('list'));
210
$list = $GLOBALS['nag_shares']->getShare($this->_vars->get('list'));
211
$this->_title = $list->get('name');
212
$this->_smartShare = $list;
213
$this->_loadTasks($lists);
216
// If we have an active tag browse, use it.
217
if ($this->_browser->tagCount() >= 1) {
218
$this->_handleActions('browse');
220
$this->_loadTasks($lists);
227
* Load the full, sorted task list.
229
protected function _loadTasks($lists = null)
232
$this->_tasks = Nag::listTasks(array(
233
'tasklists' => $lists,
234
'include_tags' => true,
235
'completed' => $this->_vars->show_completed,
236
'include_history' => false)
238
} catch (Nag_Exception $e) {
239
$GLOBALS['notification']->push($e, 'horde.error');
240
$this->_tasks = new Nag_Task();
245
* Performs a Task search. self::_tasks is populated with the results.
247
* @throws Nag_Exception
249
protected function _doSearch()
251
// Clear the tag browser in case we have an active browse set.
252
$this->_browser->clearSearch();
254
// Don't show the tag browser.
255
$this->_showTagBrowser = false;
257
$form = new Nag_Form_Search($this->_vars);
258
if ($form->validate($this->_vars, true)) {
259
$form->getInfo($this->_vars, $info);
261
throw new Nag_Exception(current($form->getErrors()));
265
$search_pattern = $this->_vars->search_pattern;
266
$search_in = empty($this->_vars->search_in) ? array() : $this->_vars->search_in;
267
$search_name = in_array('search_name', $search_in) ? Nag_Search::MASK_NAME : 0;
268
$search_desc = in_array('search_desc', $search_in) ? Nag_Search::MASK_DESC : 0;
269
$search_tags = !empty($this->_vars->search_tags) ? Nag_Search::MASK_TAGS : 0;
270
$search_completed = $this->_vars->search_completed;
272
$this->_vars->set('show_completed', $search_completed);
273
$mask = $search_name | $search_desc | $search_tags;
276
$date = $info['due_date'];
281
// Prepare the search
282
$search = new Nag_Search(
286
'completed' => $search_completed,
288
'tags' => empty($this->_vars->search_tags) ? array() : $GLOBALS['injector']->getInstance('Nag_Tagger')->split($this->_vars->search_tags))
291
$tasks = $search->getSlice();
292
} catch (Nag_Exception $e) {
293
$GLOBALS['notification']->push($tasks, 'horde.error');
294
$tasks = new Nag_Task();
297
// Save as a smart list?
298
if ($id = $this->_vars->get('smart_id')) {
300
$smartlist = $GLOBALS['nag_shares']->getShare($id);
304
'name' => $this->_vars->get('smartlist_name'),
305
'search' => serialize($search))
307
$this->_title = $smartlist->get('name');
308
$this->_smartShare = $smartlist;
309
} elseif ($this->_vars->get('save_smartlist')) {
310
$this->_smartShare = Nag::addTasklist(
311
array('name' => $this->_vars->get('smartlist_name'),
312
'search' => serialize($search)),
315
$this->_title = $this->_vars->get('smartlist_name');
317
// Build a page title based on criteria.
318
$this->_title = sprintf(_("Search: Results for"));
320
if (!empty($search_pattern)) {
322
$this->_title .= ' "' . $search_pattern . '" ';
324
$this->_title .= ' ' . _("tasks") . ' ';
328
$this->_title .= _("and") . ' ';
330
$this->_title .= _("with") . ' ';
333
$this->_title .= sprintf(_("due date within %d days of %s"), $date[0], $date[1]) . ' ';
335
if (!empty($search_tags)) {
337
$this->_title .= _("and") . ' ';
339
$this->_title .= _("with") . ' ';
341
$this->_title .= sprintf(_("and tagged with %s"), $this->_vars->search_tags);
345
$this->_tasks = $tasks;
349
* Delete a SmartList.
352
protected function _doDeleteSmartList()
355
$sl = $GLOBALS['nag_shares']->getShare($this->_vars->smart_id);
356
Nag::deleteTasklist($sl);
357
} catch (Horde_Exception $e) {
358
$GLOBALS['notification']->push($e->getMessage(), 'horde.error');
359
Horde::url('list.php')->redirect();
362
$GLOBALS['notification']->push(_("Smart List deleted successfully"), 'horde.success');
366
* Get HTML to display the related tags links.
370
protected function _getRelatedTags()
372
$this->_tasks->reset();
374
while ($t = $this->_tasks->each()) {
377
$rtags = $this->_browser->getRelatedTags($ids);
379
$html = '<div class="nag-tags-related">'
380
. Horde::img('tags.png')
381
. ' <ul class="horde-tags">';
382
foreach ($rtags as $id => $taginfo) {
384
. $this->_linkAddTag($taginfo['tag_name'])->link()
385
. htmlspecialchars($taginfo['tag_name']) . '</a></li>';
387
return $html . '</ul></div>';
394
* Get HTML to represent the currently selected tags.
398
protected function _getTagTrail()
400
if ($this->_browser->tagCount() >= 1) {
401
$html = '<div class="nag-tags-browsing">' . Horde::img('filter.png') . '<ul class="horde-tags">';
402
foreach ($this->_browser->getTags() as $tag => $id) {
403
$html .= '<li>' . htmlspecialchars($tag)
404
. $this->_linkRemoveTag($tag)->link()
405
. Horde::img('delete-small.png', _("Remove from search"))
408
return $html .= '</ul></div>';
415
* Get HTML for a link to remove a tag from the current search.
417
* @param string $tag The tag we want the link for.
421
protected function _linkRemoveTag($tag)
423
return Horde::url('list.php')
424
->add(array('actionID' => 'browse_remove', 'tag' => $tag));
428
* Get HTML for a link to add a new tag to the current search.
430
* @param string $tag The tag we want to add.
434
protected function _linkAddTag($tag)
436
return Horde::url('list.php')->add(array('actionID' => 'browse_add', 'tag' => $tag));