2012-06-08 14:57:16 +02:00
|
|
|
<?php
|
|
|
|
/**
|
|
|
|
* User Interface class for the Tasklist plugin
|
|
|
|
*
|
|
|
|
* @version @package_version@
|
|
|
|
* @author Thomas Bruederli <bruederli@kolabsys.com>
|
|
|
|
*
|
|
|
|
* Copyright (C) 2012, Kolab Systems AG <contact@kolabsys.com>
|
|
|
|
*
|
|
|
|
* This program is free software: you can redistribute it and/or modify
|
|
|
|
* it under the terms of the GNU Affero General Public License as
|
|
|
|
* published by the Free Software Foundation, either version 3 of the
|
|
|
|
* License, or (at your option) any later version.
|
|
|
|
*
|
|
|
|
* This program is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
* GNU Affero General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU Affero General Public License
|
|
|
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
class tasklist_ui
|
|
|
|
{
|
|
|
|
private $rc;
|
|
|
|
private $plugin;
|
|
|
|
private $ready = false;
|
|
|
|
|
|
|
|
function __construct($plugin)
|
|
|
|
{
|
|
|
|
$this->plugin = $plugin;
|
|
|
|
$this->rc = $plugin->rc;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Calendar UI initialization and requests handlers
|
|
|
|
*/
|
|
|
|
public function init()
|
|
|
|
{
|
|
|
|
if ($this->ready) // already done
|
|
|
|
return;
|
|
|
|
|
|
|
|
// add taskbar button
|
|
|
|
$this->plugin->add_button(array(
|
|
|
|
'command' => 'tasks',
|
|
|
|
'class' => 'button-tasklist',
|
|
|
|
'classsel' => 'button-tasklist button-selected',
|
|
|
|
'innerclass' => 'button-inner',
|
|
|
|
'label' => 'tasklist.navtitle',
|
|
|
|
), 'taskbar');
|
|
|
|
|
2012-07-29 11:29:34 +02:00
|
|
|
$this->plugin->include_stylesheet($this->plugin->local_skin_path() . '/tasklist.css');
|
2012-07-29 17:20:19 +02:00
|
|
|
$this->plugin->include_script('tasklist_base.js');
|
|
|
|
|
|
|
|
// copy config to client
|
2012-08-16 08:57:25 +02:00
|
|
|
// $this->rc->output->set_env('tasklist_settings', $settings);
|
2012-07-29 17:20:19 +02:00
|
|
|
|
2012-06-08 14:57:16 +02:00
|
|
|
$this->ready = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Register handler methods for the template engine
|
|
|
|
*/
|
|
|
|
public function init_templates()
|
|
|
|
{
|
|
|
|
$this->plugin->register_handler('plugin.tasklists', array($this, 'tasklists'));
|
|
|
|
$this->plugin->register_handler('plugin.tasklist_select', array($this, 'tasklist_select'));
|
2014-05-19 18:20:23 +02:00
|
|
|
$this->plugin->register_handler('plugin.status_select', array($this, 'status_select'));
|
2012-06-08 14:57:16 +02:00
|
|
|
$this->plugin->register_handler('plugin.searchform', array($this->rc->output, 'search_form'));
|
|
|
|
$this->plugin->register_handler('plugin.quickaddform', array($this, 'quickadd_form'));
|
|
|
|
$this->plugin->register_handler('plugin.tasks', array($this, 'tasks_resultview'));
|
2012-07-11 20:34:29 +02:00
|
|
|
$this->plugin->register_handler('plugin.tagslist', array($this, 'tagslist'));
|
2012-07-12 22:31:53 +02:00
|
|
|
$this->plugin->register_handler('plugin.tags_editline', array($this, 'tags_editline'));
|
2012-08-03 14:07:58 +02:00
|
|
|
$this->plugin->register_handler('plugin.alarm_select', array($this, 'alarm_select'));
|
2014-04-24 19:44:21 +02:00
|
|
|
$this->plugin->register_handler('plugin.recurrence_form', array($this->plugin->lib, 'recurrence_form'));
|
2012-08-01 15:52:28 +02:00
|
|
|
$this->plugin->register_handler('plugin.attachments_form', array($this, 'attachments_form'));
|
|
|
|
$this->plugin->register_handler('plugin.attachments_list', array($this, 'attachments_list'));
|
|
|
|
$this->plugin->register_handler('plugin.filedroparea', array($this, 'file_drop_area'));
|
|
|
|
|
2012-07-12 22:31:53 +02:00
|
|
|
$this->plugin->include_script('jquery.tagedit.js');
|
2012-06-08 14:57:16 +02:00
|
|
|
$this->plugin->include_script('tasklist.js');
|
2014-05-21 13:04:18 +02:00
|
|
|
$this->rc->output->include_script('treelist.js');
|
|
|
|
|
|
|
|
// include kolab folderlist widget if available
|
|
|
|
if (is_readable($this->plugin->api->dir . 'libkolab/js/folderlist.js')) {
|
|
|
|
$this->plugin->api->include_script('libkolab/js/folderlist.js');
|
|
|
|
}
|
2014-03-27 19:17:18 +01:00
|
|
|
|
|
|
|
$this->plugin->include_stylesheet($this->plugin->local_skin_path() . '/tagedit.css');
|
2012-06-08 14:57:16 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
*
|
|
|
|
*/
|
2014-05-21 13:04:18 +02:00
|
|
|
public function tasklists($attrib = array())
|
|
|
|
{
|
|
|
|
$tree = true;
|
|
|
|
$jsenv = array();
|
|
|
|
$lists = $this->plugin->driver->get_lists($tree);
|
|
|
|
|
|
|
|
// walk folder tree
|
|
|
|
if (is_object($tree)) {
|
|
|
|
$html = $this->list_tree_html($tree, $lists, $jsenv, $attrib);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
// fall-back to flat folder listing
|
|
|
|
$attrib['class'] .= ' flat';
|
|
|
|
|
|
|
|
$html = '';
|
|
|
|
foreach ((array)$lists as $id => $prop) {
|
|
|
|
if ($attrib['activeonly'] && !$prop['active'])
|
|
|
|
continue;
|
|
|
|
|
|
|
|
$html .= html::tag('li', array(
|
|
|
|
'id' => 'rcmlitasklist' . rcube_utils::html_identifier($id),
|
|
|
|
'class' => $prop['group'],
|
|
|
|
),
|
|
|
|
$this->tasklist_list_item($id, $prop, $jsenv, $attrib['activeonly'])
|
|
|
|
);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
$this->rc->output->set_env('tasklists', $jsenv);
|
|
|
|
$this->rc->output->add_gui_object('tasklistslist', $attrib['id']);
|
|
|
|
|
|
|
|
return html::tag('ul', $attrib, $html, html::$common_attrib);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Return html for a structured list <ul> for the folder tree
|
|
|
|
*/
|
|
|
|
public function list_tree_html($node, $data, &$jsenv, $attrib)
|
2012-06-08 14:57:16 +02:00
|
|
|
{
|
2014-05-21 13:04:18 +02:00
|
|
|
$out = '';
|
|
|
|
foreach ($node->children as $folder) {
|
|
|
|
$id = $folder->id;
|
|
|
|
$prop = $data[$id];
|
|
|
|
$is_collapsed = false; // TODO: determine this somehow?
|
|
|
|
|
|
|
|
$content = $this->tasklist_list_item($id, $prop, $jsenv, $attrib['activeonly']);
|
|
|
|
|
|
|
|
if (!empty($folder->children)) {
|
|
|
|
$content .= html::tag('ul', array('style' => ($is_collapsed ? "display:none;" : null)),
|
|
|
|
$this->list_tree_html($folder, $data, $jsenv, $attrib));
|
|
|
|
}
|
|
|
|
|
|
|
|
if (strlen($content)) {
|
|
|
|
$out .= html::tag('li', array(
|
|
|
|
'id' => 'rcmlitasklist' . rcube_utils::html_identifier($id),
|
|
|
|
'class' => $prop['group'] . ($prop['virtual'] ? ' virtual' : ''),
|
|
|
|
),
|
|
|
|
$content);
|
|
|
|
}
|
|
|
|
}
|
2012-06-08 14:57:16 +02:00
|
|
|
|
2014-05-21 13:04:18 +02:00
|
|
|
return $out;
|
|
|
|
}
|
2012-06-08 14:57:16 +02:00
|
|
|
|
2014-05-21 13:04:18 +02:00
|
|
|
/**
|
|
|
|
* Helper method to build a tasklist item (HTML content and js data)
|
|
|
|
*/
|
|
|
|
public function tasklist_list_item($id, $prop, &$jsenv, $activeonly = false)
|
|
|
|
{
|
|
|
|
// enrich list properties with settings from the driver
|
|
|
|
if (!$prop['virtual']) {
|
2012-06-08 14:57:16 +02:00
|
|
|
unset($prop['user_id']);
|
|
|
|
$prop['alarms'] = $this->plugin->driver->alarms;
|
|
|
|
$prop['undelete'] = $this->plugin->driver->undelete;
|
|
|
|
$prop['sortable'] = $this->plugin->driver->sortable;
|
2012-08-01 15:52:28 +02:00
|
|
|
$prop['attachments'] = $this->plugin->driver->attachments;
|
2014-05-21 13:04:18 +02:00
|
|
|
$jsenv[$id] = $prop;
|
2012-06-08 14:57:16 +02:00
|
|
|
}
|
|
|
|
|
2014-05-21 13:04:18 +02:00
|
|
|
$classes = array('tasklist');
|
|
|
|
$title = $prop['title'] ?: ($prop['name'] != $prop['listname'] || strlen($prop['name']) > 25 ?
|
|
|
|
html_entity_decode($prop['name'], ENT_COMPAT, RCMAIL_CHARSET) : '');
|
|
|
|
|
|
|
|
if ($prop['virtual'])
|
|
|
|
$classes[] = 'virtual';
|
|
|
|
else if (!$prop['editable'])
|
|
|
|
$classes[] = 'readonly';
|
|
|
|
if ($prop['subscribed'])
|
|
|
|
$classes[] = 'subscribed';
|
|
|
|
if ($prop['class'])
|
|
|
|
$classes[] = $prop['class'];
|
|
|
|
|
|
|
|
if (!$activeonly || $prop['active']) {
|
2014-06-20 15:12:11 +02:00
|
|
|
$label_id = 'tl:' . $id;
|
2014-05-21 13:04:18 +02:00
|
|
|
return html::div(join(' ', $classes),
|
2014-06-20 15:12:11 +02:00
|
|
|
html::span(array('class' => 'listname', 'title' => $title, 'id' => $label_id), $prop['listname'] ?: $prop['name']) .
|
2014-05-21 13:04:18 +02:00
|
|
|
($prop['virtual'] ? '' :
|
2014-06-20 15:12:11 +02:00
|
|
|
html::tag('input', array('type' => 'checkbox', 'name' => '_list[]', 'value' => $id, 'checked' => $prop['active'], 'aria-labelledby' => $label_id)) .
|
|
|
|
html::a(array('href' => '#', 'class' => 'quickview', 'title' => $this->plugin->gettext('focusview'), 'role' => 'checkbox', 'aria-checked' => 'false'), ' ') .
|
|
|
|
(isset($prop['subscribed']) ? html::a(array('href' => '#', 'class' => 'subscribed', 'title' => $this->plugin->gettext('tasklistsubscribe'), 'role' => 'checkbox', 'aria-checked' => $prop['subscribed'] ? 'true' : 'false'), ' ') : '')
|
2014-05-21 13:04:18 +02:00
|
|
|
)
|
|
|
|
);
|
|
|
|
}
|
2012-06-08 14:57:16 +02:00
|
|
|
|
2014-05-21 13:04:18 +02:00
|
|
|
return '';
|
2012-06-08 14:57:16 +02:00
|
|
|
}
|
|
|
|
|
2014-05-19 18:20:23 +02:00
|
|
|
/**
|
|
|
|
* Render HTML form for task status selector
|
|
|
|
*/
|
|
|
|
function status_select($attrib = array())
|
|
|
|
{
|
|
|
|
$attrib['name'] = 'status';
|
|
|
|
$select = new html_select($attrib);
|
|
|
|
$select->add('---', '');
|
|
|
|
$select->add($this->plugin->gettext('status-needs-action'), 'NEEDS-ACTION');
|
|
|
|
$select->add($this->plugin->gettext('status-in-process'), 'IN-PROCESS');
|
|
|
|
$select->add($this->plugin->gettext('status-completed'), 'COMPLETED');
|
|
|
|
$select->add($this->plugin->gettext('status-cancelled'), 'CANCELLED');
|
|
|
|
|
|
|
|
return $select->show(null);
|
|
|
|
}
|
2012-06-08 14:57:16 +02:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Render a HTML select box for list selection
|
|
|
|
*/
|
|
|
|
function tasklist_select($attrib = array())
|
|
|
|
{
|
2012-10-29 20:41:50 +01:00
|
|
|
$attrib['name'] = 'list';
|
|
|
|
$attrib['is_escaped'] = true;
|
2012-06-08 14:57:16 +02:00
|
|
|
$select = new html_select($attrib);
|
2012-10-29 20:41:50 +01:00
|
|
|
|
2012-06-08 14:57:16 +02:00
|
|
|
foreach ((array)$this->plugin->driver->get_lists() as $id => $prop) {
|
2012-09-06 17:52:14 +02:00
|
|
|
if ($prop['editable'])
|
2012-06-08 14:57:16 +02:00
|
|
|
$select->add($prop['name'], $id);
|
|
|
|
}
|
|
|
|
|
|
|
|
return $select->show(null);
|
|
|
|
}
|
|
|
|
|
2012-06-21 21:59:47 +02:00
|
|
|
|
2014-04-09 11:12:50 +02:00
|
|
|
function tasklist_editform($action, $list = array())
|
2012-06-21 21:59:47 +02:00
|
|
|
{
|
|
|
|
$fields = array(
|
|
|
|
'name' => array(
|
2012-08-03 14:07:58 +02:00
|
|
|
'id' => 'taskedit-tasklistame',
|
2012-06-21 21:59:47 +02:00
|
|
|
'label' => $this->plugin->gettext('listname'),
|
2012-08-03 14:07:58 +02:00
|
|
|
'value' => html::tag('input', array('id' => 'taskedit-tasklistame', 'name' => 'name', 'type' => 'text', 'class' => 'text', 'size' => 40)),
|
2012-06-21 21:59:47 +02:00
|
|
|
),
|
|
|
|
/*
|
|
|
|
'color' => array(
|
2012-08-03 14:07:58 +02:00
|
|
|
'id' => 'taskedit-color',
|
2012-06-21 21:59:47 +02:00
|
|
|
'label' => $this->plugin->gettext('color'),
|
2012-08-03 14:07:58 +02:00
|
|
|
'value' => html::tag('input', array('id' => 'taskedit-color', 'name' => 'color', 'type' => 'text', 'class' => 'text colorpicker', 'size' => 6)),
|
2012-06-21 21:59:47 +02:00
|
|
|
),
|
2012-08-03 14:07:58 +02:00
|
|
|
*/
|
2012-06-21 21:59:47 +02:00
|
|
|
'showalarms' => array(
|
2012-08-03 14:07:58 +02:00
|
|
|
'id' => 'taskedit-showalarms',
|
2012-06-21 21:59:47 +02:00
|
|
|
'label' => $this->plugin->gettext('showalarms'),
|
2012-08-03 14:07:58 +02:00
|
|
|
'value' => html::tag('input', array('id' => 'taskedit-showalarms', 'name' => 'color', 'type' => 'checkbox')),
|
2012-06-21 21:59:47 +02:00
|
|
|
),
|
|
|
|
);
|
|
|
|
|
|
|
|
return html::tag('form', array('action' => "#", 'method' => "post", 'id' => 'tasklisteditform'),
|
2014-04-09 11:12:50 +02:00
|
|
|
$this->plugin->driver->tasklist_edit_form($action, $list, $fields)
|
2012-06-21 21:59:47 +02:00
|
|
|
);
|
|
|
|
}
|
|
|
|
|
2012-06-08 14:57:16 +02:00
|
|
|
/**
|
2012-08-03 14:07:58 +02:00
|
|
|
* Render HTML form for alarm configuration
|
2012-06-08 14:57:16 +02:00
|
|
|
*/
|
2012-08-03 14:07:58 +02:00
|
|
|
function alarm_select($attrib = array())
|
2012-06-08 14:57:16 +02:00
|
|
|
{
|
2012-11-15 15:03:00 +01:00
|
|
|
return $this->plugin->lib->alarm_select($attrib, $this->plugin->driver->alarm_types, $this->plugin->driver->alarm_absolute);
|
2012-06-08 14:57:16 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
function quickadd_form($attrib)
|
|
|
|
{
|
|
|
|
$attrib += array('action' => $this->rc->url('add'), 'method' => 'post', 'id' => 'quickaddform');
|
|
|
|
|
2014-06-20 15:12:11 +02:00
|
|
|
$label = html::label(array('for' => 'quickaddinput', 'class' => 'voice'), $this->plugin->gettext('quickaddinput'));
|
2012-10-18 12:23:17 +02:00
|
|
|
$input = new html_inputfield(array('name' => 'text', 'id' => 'quickaddinput'));
|
2014-06-20 15:12:11 +02:00
|
|
|
$button = html::tag('input', array('type' => 'submit', 'value' => '+', 'title' => $this->plugin->gettext('createtask'), 'class' => 'button mainaction'));
|
2012-06-08 14:57:16 +02:00
|
|
|
|
|
|
|
$this->rc->output->add_gui_object('quickaddform', $attrib['id']);
|
2014-06-20 15:12:11 +02:00
|
|
|
return html::tag('form', $attrib, $label . $input->show() . $button);
|
2012-06-08 14:57:16 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* The result view
|
|
|
|
*/
|
|
|
|
function tasks_resultview($attrib)
|
|
|
|
{
|
|
|
|
$attrib += array('id' => 'rcmtaskslist');
|
|
|
|
|
|
|
|
$this->rc->output->add_gui_object('resultlist', $attrib['id']);
|
|
|
|
|
|
|
|
unset($attrib['name']);
|
|
|
|
return html::tag('ul', $attrib, '');
|
|
|
|
}
|
|
|
|
|
2012-07-12 22:31:53 +02:00
|
|
|
/**
|
|
|
|
* Container for a tags cloud
|
|
|
|
*/
|
2012-07-11 20:34:29 +02:00
|
|
|
function tagslist($attrib)
|
|
|
|
{
|
2012-08-03 14:07:58 +02:00
|
|
|
$attrib += array('id' => 'rcmtasktagslist');
|
2012-07-11 20:34:29 +02:00
|
|
|
unset($attrib['name']);
|
|
|
|
|
|
|
|
$this->rc->output->add_gui_object('tagslist', $attrib['id']);
|
|
|
|
return html::tag('ul', $attrib, '');
|
|
|
|
}
|
2012-06-08 14:57:16 +02:00
|
|
|
|
2012-07-12 22:31:53 +02:00
|
|
|
/**
|
|
|
|
* Interactive UI element to add/remove tags
|
|
|
|
*/
|
|
|
|
function tags_editline($attrib)
|
|
|
|
{
|
2012-08-03 14:07:58 +02:00
|
|
|
$attrib += array('id' => 'rcmtasktagsedit');
|
2012-07-12 22:31:53 +02:00
|
|
|
$this->rc->output->add_gui_object('edittagline', $attrib['id']);
|
|
|
|
|
|
|
|
$input = new html_inputfield(array('name' => 'tags[]', 'class' => 'tag', 'size' => $attrib['size'], 'tabindex' => $attrib['tabindex']));
|
2014-06-20 15:12:11 +02:00
|
|
|
unset($attrib['tabindex']);
|
2012-07-12 22:31:53 +02:00
|
|
|
return html::div($attrib, $input->show(''));
|
|
|
|
}
|
|
|
|
|
2012-08-01 15:52:28 +02:00
|
|
|
/**
|
|
|
|
* Generate HTML element for attachments list
|
|
|
|
*/
|
|
|
|
function attachments_list($attrib = array())
|
|
|
|
{
|
|
|
|
if (!$attrib['id'])
|
2012-08-03 14:07:58 +02:00
|
|
|
$attrib['id'] = 'rcmtaskattachmentlist';
|
2012-08-01 15:52:28 +02:00
|
|
|
|
|
|
|
$this->rc->output->add_gui_object('attachmentlist', $attrib['id']);
|
|
|
|
|
|
|
|
return html::tag('ul', $attrib, '', html::$common_attrib);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Generate the form for event attachments upload
|
|
|
|
*/
|
|
|
|
function attachments_form($attrib = array())
|
|
|
|
{
|
|
|
|
// add ID if not given
|
|
|
|
if (!$attrib['id'])
|
2012-08-03 14:07:58 +02:00
|
|
|
$attrib['id'] = 'rcmtaskuploadform';
|
2012-08-01 15:52:28 +02:00
|
|
|
|
|
|
|
// Get max filesize, enable upload progress bar
|
|
|
|
$max_filesize = rcube_upload_init();
|
|
|
|
|
|
|
|
$button = new html_inputfield(array('type' => 'button'));
|
|
|
|
$input = new html_inputfield(array(
|
|
|
|
'type' => 'file',
|
|
|
|
'name' => '_attachments[]',
|
|
|
|
'multiple' => 'multiple',
|
|
|
|
'size' => $attrib['attachmentfieldsize'],
|
|
|
|
));
|
|
|
|
|
|
|
|
return html::div($attrib,
|
|
|
|
html::div(null, $input->show()) .
|
|
|
|
html::div('formbuttons', $button->show(rcube_label('upload'), array('class' => 'button mainaction',
|
|
|
|
'onclick' => JS_OBJECT_NAME . ".upload_file(this.form)"))) .
|
|
|
|
html::div('hint', rcube_label(array('name' => 'maxuploadsize', 'vars' => array('size' => $max_filesize))))
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Register UI object for HTML5 drag & drop file upload
|
|
|
|
*/
|
|
|
|
function file_drop_area($attrib = array())
|
|
|
|
{
|
|
|
|
if ($attrib['id']) {
|
|
|
|
$this->rc->output->add_gui_object('filedrop', $attrib['id']);
|
|
|
|
$this->rc->output->set_env('filedrop', array('action' => 'upload', 'fieldname' => '_attachments'));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-06-08 14:57:16 +02:00
|
|
|
}
|