diff --git a/plugins/libkolab/skins/elastic/include/libcalendaring.less b/plugins/libkolab/skins/elastic/include/libcalendaring.less index 43b6d700..d4027778 100644 --- a/plugins/libkolab/skins/elastic/include/libcalendaring.less +++ b/plugins/libkolab/skins/elastic/include/libcalendaring.less @@ -1,634 +1,650 @@ /** * Kolab core library * * This file contains Elastic skin styles for libcalendaring plugin. * * @author Aleksander Machniak * * Copyright (C) 2012-2018, Kolab Systems AG * * 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 . */ .invitebox { & > i.icon { position: absolute; top: 0; padding-top: .5em; } & > span { padding-left: 2.5em; } td { padding: 2px; &.ititle { font-weight: bold; padding-right: 0.5em; } &.label { color: #666; padding-right: 1em; } &.sensitivity { font-weight: bold; } &.recurrence-id { text-transform: uppercase; font-style: italic; } &.date.modified { font-weight: bold; color: @color-error; } em { font-weight: bold; } } .itip-buttons { display: flex; flex-wrap: wrap; input.button { margin: 0 .25rem .25rem 0; } } .rsvp-buttons { width: 100%; padding-top: .25rem; } .itip-reply-controls { margin-top: .25rem; width: 100%; & > label { display: inline; label { line-height: 1; margin-right: .25rem; } } a { margin-left: 1em; white-space: nowrap; } } .rsvp-status { margin: .5rem 0; width: 100%; &.hint { color: #666; font-style: italic; } &:before { line-height: 1.1; color: lighten(@color-black, 25%); } &.loading:before { &:extend(.font-icon-class); .animated-icon-class; content: @fa-var-circle-notch; line-height: 1; } &.declined:before { &:extend(.font-icon-class); content: @fa-var-ban; color: @color-error; } &.tentative:before { &:extend(.font-icon-class); content: @fa-var-check-circle; color: @color-warning; } &.accepted:before { &:extend(.font-icon-class); content: @fa-var-check-circle; color: @color-success; } &.delegated:before { &:extend(.font-icon-class); content: @fa-var-share; } &.needs-action:before { &:extend(.font-icon-class); content: @fa-var-question-circle; } } .folder-select { white-space: nowrap; select { display: initial; width: auto; } } } .attendee { &:after { &:extend(.font-icon-class); content: @fa-var-question-circle; display: inline; float: none; font-size: 1em; margin-left: .3rem; color: @color-black-shade-text; } &.req-participant:after { content: @fa-var-user; } &.opt-participant:after { .font-icon-regular(@fa-var-user); } &.non-participant:after { content: @fa-var-user; color: #999; } &.chair:after { content: @fa-var-user; // todo color: @color-warning; } &.completed:after, &.accepted:after { content: @fa-var-check-circle; color: @color-success; } &.declined:after { content: @fa-var-ban; color: @color-error; } &.tentative:after { content: @fa-var-check-circle; color: @color-warning; } &.delegated:after { content: @fa-var-share; } &.organizer:after { content: @fa-var-briefcase; // TODO: better icon } &.in-process:after { content: @fa-var-cog; } } .attendees-comentbox { label { display: inline; } } #edit-attendees-legend { margin-top: 1rem; } .edit-attendees-table { width: 100%; th, td { width: 1%; text-align: center; } td { border: 0; padding: 0 .3rem; } th { border-bottom: 1px solid #eee !important; } th.name, td.name, th.role, td.role { width: auto; text-align: left; } th.invite { input { display: none; } label { cursor: pointer; } label:before { &:extend(.font-icon-class); content: @fa-var-envelope; display: inline; float: none; margin-left: .25rem; } } td.invite { label:before { line-height: 1.6; height: 1.5em; } } td.name { span { line-height: 2.5; display: flex; & > :first-child { .overflow-ellipsis; // width and flex is required to make overflow working flex: 1; width: 1px; white-space: nowrap; } } } td.availability, td.confirmstate { span { margin: 0; } span:after, span:before { line-height: 2; margin: 0; font-size: 1.2em; height: 2em; width: 2em; } } td.options { a { display: inline-block; height: 2em; &:before { line-height: 1.8; margin: 0; } } } a.expandlink { &:before { content: @fa-var-plus-square; line-height: 2; } } .inner { display: none; } } +html.touch { + .edit-attendees-table { + td.invite { + label:before { + line-height: 1.2; + height: 1.2em; + } + } + } +} + .form-searchbar { display: flex; margin-bottom: .5rem; + input[type=text] { + flex: 1; + } + input[type=button] { margin-left: .5em; + .overflow-ellipsis; } } .attachmentslist li.link { &.message.eml:before { content: @fa-var-envelope; } a.messagelink { .overflow-ellipsis; margin-right: .25rem; } a.delete .inner { display: none; } } .attachmentslist li.ics:before, .attachmentslist li.text.calendar:before, .messagelist tbody .attachment span.ical:before { .font-icon-regular(@fa-var-calendar-alt); } .alarms-input { .edit-alarm-item { display: flex; & + .edit-alarm-item { margin-top: .25rem; } } .edit-alarm-buttons { a { line-height: 1; padding: .375em .25em; margin: 0 .25rem; &:before { margin: 0; width: 1em; } } .inner { display: none; } } .edit-alarm-item.first .delete-alarm { display: none; } .edit-alarm-item:not(.first) .add-alarm { display: none; } .edit-alarm-type { flex: 1; } .edit-alarm-set { display: flex; flex: 1; } .edit-alarm-values { margin-left: .25rem; flex: 5; } .edit-alarm-offset { flex: 5; } .edit-alarm-date, .edit-alarm-time, .edit-alarm-related { flex: 3; } } .recurrence-form { .recurrence-rdates { width: 100%; padding: 0; list-style-type: none; &:empty { margin: 0; } a.delete { margin-left: 2em; &:before { display: inline-block; float: none; } } .inner { display: none; } } .recurrence-onevery { select { width: 35%; display: inline; } } .inputform { display: flex; input.button { margin-left: .25rem; } } div.line { width: 100%; display: flex; margin-bottom: .25rem; label { margin-left: .5em; min-width: 4em; line-height: 2.5; } } .month, .monthday, .weekday { display: inline-block; width: 3.5em; margin-right: .5rem; input { margin-right: .25rem; } } .monthday { width: 2.75em; } .table td { border: 0; padding: 0; &:first-child label { line-height: 2.5; } & label.monthday:first-child { margin-top: .5rem; } } .input-group-append, .input-group-prepend { display: initial; // fixes buggy height of the element } } #event-status-badge { width: 7rem; height: 7rem; position: absolute; top: 0; right: 0; overflow: hidden; span { display: none; text-transform: uppercase; line-height: 20px; position: absolute; left: -2.4rem; top: 2.4rem; width: 13.2rem; text-align: center; font-weight: bold; font-size: .85rem; color: #fff; -webkit-transform: rotate(45deg); transform: rotate(45deg); &:before { &:extend(.font-icon-class); display: inline; float: none; } .status-cancelled & { background-color: darken(@color-error, 10%); display: block; &:before { content: @fa-var-times-circle; } } .sensitivity-private & { background-color: darken(@color-warning, 10%); display: block; &:before { content: @fa-var-lock; } } .sensitivity-confidential & { background-color: darken(@color-error, 10%); display: block; &:before { content: @fa-var-user-secret; } } } } #alarm-display { h3 { font-size: 1.2rem; margin-bottom: .25rem; &:before { &:extend(.font-icon-class); .font-icon-regular(@fa-var-calendar-alt); font-size: 1em; } &.type-task:before { .font-icon-regular(@fa-var-calendar-check); } } .event-section { font-size: .9rem; color: @color-black-shade-text; white-space: nowrap; .overflow-ellipsis; } .alarm-actions { text-align: right; margin-bottom: .25rem; a { &:first-child { margin-right: 1em; } &:before { &:extend(.font-icon-class); display: inline; float: none; } } } a.alarm-action-snooze:before { content: @fa-var-bell-slash; } a.alarm-action-dismiss:before { content: @fa-var-trash-alt; } } #alarm-snooze-dropdown a:before { .font-icon-regular(@fa-var-clock); } .dialog-message { margin: 0; opacity: .95; width: 100%; padding: .75em; margin-top: .25em; color: @color-message; background-color: @color-message-warning-background; & > label { margin: 0; display: block; label:before { line-height: 1.25; margin-right: .25rem; } } } diff --git a/plugins/tasklist/skins/larry/templates/taskedit.html b/plugins/tasklist/skins/larry/templates/taskedit.html index f18f89ac..1091a0e0 100644 --- a/plugins/tasklist/skins/larry/templates/taskedit.html +++ b/plugins/tasklist/skins/larry/templates/taskedit.html @@ -1,112 +1,112 @@
>


 
 
 %

- +

diff --git a/plugins/tasklist/tasklist_ui.php b/plugins/tasklist/tasklist_ui.php index 2ee5866b..6423c6e6 100644 --- a/plugins/tasklist/tasklist_ui.php +++ b/plugins/tasklist/tasklist_ui.php @@ -1,576 +1,576 @@ * * Copyright (C) 2012-2015, Kolab Systems AG * * 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 . */ class tasklist_ui { private $rc; private $plugin; private $ready = false; private $gui_objects = array(); function __construct($plugin) { $this->plugin = $plugin; $this->rc = $plugin->rc; } /** * Calendar UI initialization and requests handlers */ public function init() { if ($this->ready) { 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', 'type' => 'link' ), 'taskbar'); $this->plugin->include_stylesheet($this->plugin->local_skin_path() . '/tasklist.css'); if ($this->rc->task == 'mail' || $this->rc->task == 'tasks') { $this->plugin->include_script('tasklist_base.js'); // copy config to client $this->rc->output->set_env('tasklist_settings', $this->load_settings()); // initialize attendees autocompletion $this->rc->autocomplete_init(); } $this->ready = true; } /** * */ function load_settings() { $settings = array(); $settings['invite_shared'] = (int)$this->rc->config->get('calendar_allow_invite_shared', 0); $settings['itip_notify'] = (int)$this->rc->config->get('calendar_itip_send_option', 3); $settings['sort_col'] = $this->rc->config->get('tasklist_sort_col', ''); $settings['sort_order'] = $this->rc->config->get('tasklist_sort_order', 'asc'); // get user identity to create default attendee foreach ($this->rc->user->list_emails() as $rec) { if (!$identity) $identity = $rec; $identity['emails'][] = $rec['email']; $settings['identities'][$rec['identity_id']] = $rec['email']; } $identity['emails'][] = $this->rc->user->get_username(); $settings['identity'] = array( 'name' => $identity['name'], 'email' => strtolower($identity['email']), 'emails' => ';' . strtolower(join(';', $identity['emails'])) ); if ($list = rcube_utils::get_input_value('_list', rcube_utils::INPUT_GPC)) { $settings['selected_list'] = $list; } if ($list && ($id = rcube_utils::get_input_value('_id', rcube_utils::INPUT_GPC))) { $settings['selected_id'] = $id; // check if the referenced task is completed $task = $this->plugin->driver->get_task(array('id' => $id, 'list' => $list)); if ($task && $this->plugin->driver->is_complete($task)) { $settings['selected_filter'] = 'complete'; } } else if ($filter = rcube_utils::get_input_value('_filter', rcube_utils::INPUT_GPC)) { $settings['selected_filter'] = $filter; } return $settings; } /** * Render a HTML select box for user identity selection */ function identity_select($attrib = array()) { $attrib['name'] = 'identity'; $select = new html_select($attrib); $identities = $this->rc->user->list_emails(); foreach ($identities as $ident) { $select->add(format_email_recipient($ident['email'], $ident['name']), $ident['identity_id']); } return $select->show(null); } /** * 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')); $this->plugin->register_handler('plugin.status_select', array($this, 'status_select')); $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')); $this->plugin->register_handler('plugin.tags_editline', array($this, 'tags_editline')); $this->plugin->register_handler('plugin.alarm_select', array($this, 'alarm_select')); $this->plugin->register_handler('plugin.recurrence_form', array($this->plugin->lib, 'recurrence_form')); $this->plugin->register_handler('plugin.attendees_list', array($this, 'attendees_list')); $this->plugin->register_handler('plugin.attendees_form', array($this, 'attendees_form')); $this->plugin->register_handler('plugin.identity_select', array($this, 'identity_select')); $this->plugin->register_handler('plugin.edit_attendees_notify', array($this, 'edit_attendees_notify')); $this->plugin->register_handler('plugin.task_rsvp_buttons', array($this->plugin->itip, 'itip_rsvp_buttons')); $this->plugin->register_handler('plugin.object_changelog_table', array('libkolab', 'object_changelog_table')); $this->plugin->register_handler('plugin.tasks_export_form', array($this, 'tasks_export_form')); $this->plugin->register_handler('plugin.tasks_import_form', array($this, 'tasks_import_form')); kolab_attachments_handler::ui(); $this->plugin->include_script('tasklist.js'); $this->plugin->api->include_script('libkolab/libkolab.js'); } /** * */ public function tasklists($attrib = array()) { $tree = true; $jsenv = array(); $lists = $this->plugin->driver->get_lists(0, $tree); if (empty($attrib['id'])) { $attrib['id'] = 'rcmtasklistslist'; } // 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->include_script('treelist.js'); $this->rc->output->set_env('source', rcube_utils::get_input_value('source', rcube_utils::INPUT_GET)); $this->rc->output->set_env('tasklists', $jsenv); $this->register_gui_object('tasklistslist', $attrib['id']); return html::tag('ul', $attrib, $html, html::$common_attrib); } /** * Return html for a structured list
    for the folder tree */ public function list_tree_html($node, $data, &$jsenv, $attrib) { $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); } } return $out; } /** * 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']) { unset($prop['user_id']); $prop['alarms'] = $this->plugin->driver->alarms; $prop['undelete'] = $this->plugin->driver->undelete; $prop['sortable'] = $this->plugin->driver->sortable; $prop['attachments'] = $this->plugin->driver->attachments; $prop['attendees'] = $this->plugin->driver->attendees; $prop['caldavurl'] = $this->plugin->driver->tasklist_caldav_url($prop); $jsenv[$id] = $prop; } $classes = array('tasklist'); $title = $prop['title'] ?: ($prop['name'] != $prop['listname'] || strlen($prop['name']) > 25 ? html_entity_decode($prop['name'], ENT_COMPAT, RCUBE_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']) { $label_id = 'tl:' . $id; return html::div(join(' ', $classes), html::a(array('class' => 'listname', 'title' => $title, 'href' => '#', 'id' => $label_id), $prop['listname'] ?: $prop['name']) . ($prop['virtual'] ? '' : html::tag('input', array('type' => 'checkbox', 'name' => '_list[]', 'value' => $id, 'checked' => $prop['active'], 'aria-labelledby' => $label_id)) . html::span('actions', ($prop['removable'] ? html::a(array('href' => '#', 'class' => 'remove', 'title' => $this->plugin->gettext('removelist')), ' ') : '') . 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'), ' ') : '') ) ) ); } return ''; } /** * 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); } /** * Render a HTML select box for list selection */ function tasklist_select($attrib = array()) { if (empty($attrib['name'])) { $attrib['name'] = 'list'; } $attrib['is_escaped'] = true; $select = new html_select($attrib); $default = null; foreach ((array) $attrib['extra'] as $id => $name) { $select->add($name, $id); } foreach ((array)$this->plugin->driver->get_lists() as $id => $prop) { if ($prop['editable'] || strpos($prop['rights'], 'i') !== false) { $select->add($prop['name'], $id); if (!$default || $prop['default']) $default = $id; } } return $select->show($default); } function tasklist_editform($action, $list = array()) { $this->action = $action; $this->list = $list; $this->rc->output->add_handler('tasklistform', array($this, 'tasklistform')); $this->rc->output->send('tasklist.listform'); } function tasklistform($attrib) { $fields = array( 'name' => array( 'id' => 'taskedit-tasklistname', 'label' => $this->plugin->gettext('listname'), 'value' => html::tag('input', array('id' => 'taskedit-tasklistname', 'name' => 'name', 'type' => 'text', 'class' => 'text', 'size' => 40)), ), /* 'color' => array( 'id' => 'taskedit-color', 'label' => $this->plugin->gettext('color'), 'value' => html::tag('input', array('id' => 'taskedit-color', 'name' => 'color', 'type' => 'text', 'class' => 'text colorpicker', 'size' => 6)), ), */ 'showalarms' => array( 'id' => 'taskedit-showalarms', 'label' => $this->plugin->gettext('showalarms'), 'value' => html::tag('input', array('id' => 'taskedit-showalarms', 'name' => 'color', 'type' => 'checkbox')), ), ); return html::tag('form', $attrib + array('action' => "#", 'method' => "post", 'id' => 'tasklisteditform'), $this->plugin->driver->tasklist_edit_form($this->action, $this->list, $fields) ); } /** * Render HTML form for alarm configuration */ function alarm_select($attrib = array()) { $attrib['_type'] = 'task'; return $this->plugin->lib->alarm_select($attrib, $this->plugin->driver->alarm_types, $this->plugin->driver->alarm_absolute); } /** * */ function quickadd_form($attrib) { $attrib += array('action' => $this->rc->url('add'), 'method' => 'post', 'id' => 'quickaddform'); $label = html::label(array('for' => 'quickaddinput', 'class' => 'voice'), $this->plugin->gettext('quickaddinput')); $input = new html_inputfield(array('name' => 'text', 'id' => 'quickaddinput')); $button = html::tag('input', array( 'type' => 'submit', 'value' => '+', 'title' => $this->plugin->gettext('createtask'), 'class' => 'button mainaction' )); $this->register_gui_object('quickaddform', $attrib['id']); return html::tag('form', $attrib, $label . $input->show() . $button); } /** * The result view */ function tasks_resultview($attrib) { $attrib += array('id' => 'rcmtaskslist'); $this->register_gui_object('resultlist', $attrib['id']); unset($attrib['name']); return html::tag('ul', $attrib, ''); } /** * Interactive UI element to add/remove tags */ function tags_editline($attrib) { $attrib += array('id' => 'rcmtasktagsedit'); $this->register_gui_object('edittagline', $attrib['id']); $input = new html_inputfield(array('name' => 'tags[]', 'class' => 'tag', 'size' => $attrib['size'], 'tabindex' => $attrib['tabindex'])); unset($attrib['tabindex']); return html::div($attrib, $input->show('')); } /** * */ function attendees_list($attrib = array()) { // add "noreply" checkbox to attendees table only $invitations = strpos($attrib['id'], 'attend') !== false; $invite = new html_checkbox(array('value' => 1, 'id' => 'edit-attendees-invite')); $table = new html_table(array('cols' => 4 + intval($invitations), 'border' => 0, 'cellpadding' => 0, 'class' => 'rectable')); // $table->add_header('role', $this->plugin->gettext('role')); $table->add_header('name', $this->plugin->gettext($attrib['coltitle'] ?: 'attendee')); $table->add_header('confirmstate', $this->plugin->gettext('confirmstate')); if ($invitations) { $table->add_header(array('class' => 'invite', 'title' => $this->plugin->gettext('sendinvitations')), $invite->show(1) . html::label('edit-attendees-invite', html::span('inner', $this->plugin->gettext('sendinvitations')))); } $table->add_header('options', ''); // hide invite column if disabled by config $itip_notify = (int)$this->rc->config->get('calendar_itip_send_option', 3); if ($invitations && !($itip_notify & 2)) { $css = sprintf('#%s td.invite, #%s th.invite { display:none !important }', $attrib['id'], $attrib['id']); $this->rc->output->add_footer(html::tag('style', array('type' => 'text/css'), $css)); } return $table->show($attrib); } /** * */ function attendees_form($attrib = array()) { - $input = new html_inputfield(array('name' => 'participant', 'id' => 'edit-attendee-name', 'size' => 30, 'class' => 'form-control')); + $input = new html_inputfield(array('name' => 'participant', 'id' => 'edit-attendee-name', 'size' => $attrib['size'], 'class' => 'form-control')); $textarea = new html_textarea(array('name' => 'comment', 'id' => 'edit-attendees-comment', 'rows' => 4, 'cols' => 55, 'title' => $this->plugin->gettext('itipcommenttitle'), 'class' => 'form-control')); return html::div($attrib, html::div('form-searchbar', $input->show() . " " . html::tag('input', array('type' => 'button', 'class' => 'button', 'id' => 'edit-attendee-add', 'value' => $this->plugin->gettext('addattendee'))) // . " " . html::tag('input', array('type' => 'button', 'class' => 'button', 'id' => 'edit-attendee-schedule', 'value' => $this->plugin->gettext('scheduletime').'...')) ) . html::p('attendees-commentbox', html::label('edit-attendees-comment', $this->plugin->gettext('itipcomment')) . $textarea->show()) ); } /** * */ function edit_attendees_notify($attrib = array()) { $checkbox = new html_checkbox(array('name' => '_notify', 'id' => 'edit-attendees-donotify', 'value' => 1, 'class' => 'pretty-checkbox')); return html::div($attrib, html::label(null, $checkbox->show(1) . ' ' . $this->plugin->gettext('sendnotifications'))); } /** * Form for uploading and importing tasks */ function tasks_import_form($attrib = array()) { if (!$attrib['id']) { $attrib['id'] = 'rcmImportForm'; } // Get max filesize, enable upload progress bar $max_filesize = $this->rc->upload_init(); $accept = '.ics, text/calendar, text/x-vcalendar, application/ics'; if (class_exists('ZipArchive', false)) { $accept .= ', .zip, application/zip'; } $input = new html_inputfield(array( 'type' => 'file', 'name' => '_data', 'size' => $attrib['uploadfieldsize'], 'accept' => $accept )); $html = html::div('form-section form-group row', html::label(array('class' => 'col-sm-4 col-form-label', 'for' => 'importfile'), rcube::Q($this->rc->gettext('importfromfile'))) . html::div('col-sm-8', $input->show() . html::div('hint', $this->rc->gettext(array('id' => 'importfile', 'name' => 'maxuploadsize', 'vars' => array('size' => $max_filesize))))) ); $html .= html::div('form-section form-group row', html::label(array('for' => 'task-import-list', 'class' => 'col-sm-4 col-form-label'), $this->plugin->gettext('list')) . html::div('col-sm-8', $this->tasklist_select(array('name' => 'source', 'id' => 'task-import-list', 'editable' => true))) ); $this->rc->output->add_gui_object('importform', $attrib['id']); $this->rc->output->add_label('import', 'importerror'); return html::tag('p', null, $this->plugin->gettext('importtext')) .html::tag('form', array( 'action' => $this->rc->url(array('task' => 'tasklist', 'action' => 'import')), 'method' => 'post', 'enctype' => 'multipart/form-data', 'id' => $attrib['id'], ), $html ); } /** * Form to select options for exporting tasks */ function tasks_export_form($attrib = array()) { if (!$attrib['id']) { $attrib['id'] = 'rcmTaskExportForm'; } $html .= html::div('form-section form-group row', html::label(array('for' => 'task-export-list', 'class' => 'col-sm-4 col-form-label'), $this->plugin->gettext('list')) . html::div('col-sm-8', $this->tasklist_select(array( 'name' => 'source', 'id' => 'task-export-list', 'extra' => array('' => '- ' . $this->plugin->gettext('currentview') . ' -'), ))) ); $checkbox = new html_checkbox(array('name' => 'attachments', 'id' => 'task-export-attachments', 'value' => 1, 'class' => 'form-check-input')); $html .= html::div('form-section form-group row form-check', html::label(array('for' => 'task-export-attachments', 'class' => 'col-sm-4 col-form-label'), $this->plugin->gettext('exportattachments')) . html::div('col-sm-8', $checkbox->show(1)) ); $this->register_gui_object('exportform', $attrib['id']); return html::tag('form', array( 'action' => $this->rc->url(array('task' => 'tasklist', 'action' => 'export')), 'method' => 'post', 'id' => $attrib['id'] ), $html ); } /** * Wrapper for rcube_output_html::add_gui_object() */ function register_gui_object($name, $id) { $this->gui_objects[$name] = $id; $this->rc->output->add_gui_object($name, $id); } /** * Getter for registered gui objects. * (for manual registration when loading the inline UI) */ function get_gui_objects() { return $this->gui_objects; } }