Elastic: Initial kolab_notes support

TODO: printing, tags, and some small style fixes
This commit is contained in:
Aleksander Machniak 2018-01-02 13:21:11 +01:00
parent c3ac8874b3
commit fc8785dac4
17 changed files with 672 additions and 466 deletions

View file

@ -89,7 +89,7 @@ if (window.rcmail) {
// append button to show contact audit trail
if (rcmail.env.action == 'show' && rcmail.env.kolab_audit_trail && rcmail.env.cid) {
$('<a>').attr({href: '#history', 'class': 'btn btn-secondary btn-contact-history', role: 'button', tabindex: 0})
$('<a>').attr({href: '#history', 'class': 'btn btn-secondary history contact-history', role: 'button', tabindex: 0})
.append($('<span class="inner">').text(rcmail.get_label('kolab_addressbook.showhistory')))
.click(function(e) {
var rc = rcmail.is_framed() && parent.rcmail.contact_history_dialog ? parent.rcmail : rcmail;

View file

@ -156,18 +156,18 @@
text-align: center;
}
.formbuttons .btn-contact-history {
.formbuttons .contact-history {
display: inline-block;
padding: 1px;
color: #333;
text-decoration: none;
}
.formbuttons .btn-contact-history:hover {
.formbuttons .contact-history:hover {
text-decoration: underline;
}
.formbuttons .btn-contact-history:before {
.formbuttons .contact-history:before {
content: "";
display: inline-block;
position: relative;

View file

@ -79,6 +79,10 @@ class kolab_notes extends rcube_plugin
$this->register_action('action', array($this, 'note_action'));
$this->register_action('list', array($this, 'list_action'));
$this->register_action('dialog-ui', array($this, 'dialog_view'));
if (!$this->rc->output->ajax_call && in_array($args['action'], array('dialog-ui', 'list'))) {
$this->load_ui();
}
}
else if ($args['task'] == 'mail') {
$this->add_hook('storage_init', array($this, 'storage_init'));
@ -107,7 +111,7 @@ class kolab_notes extends rcube_plugin
}
}
if (!$this->rc->output->ajax_call && (!$this->rc->output->env['framed'] || in_array($args['action'], array('folder-acl','dialog-ui')))) {
if (!$this->rc->output->ajax_call && !$this->rc->output->env['framed']) {
$this->load_ui();
}
@ -132,10 +136,12 @@ class kolab_notes extends rcube_plugin
*/
private function load_ui()
{
if (!$this->ui) {
require_once($this->home . '/kolab_notes_ui.php');
$this->ui = new kolab_notes_ui($this);
$this->ui->init();
}
}
/**
* Read available calendars for the current user and store them internally
@ -1027,7 +1033,7 @@ class kolab_notes extends rcube_plugin
case 'form-new':
case 'form-edit':
$this->_read_lists();
echo $this->ui->list_editform($action, $this->lists[$list['id']], $this->folders[$list['id']]);
$this->ui->list_editform($action, $this->lists[$list['id']], $this->folders[$list['id']]);
exit;
case 'new':
@ -1065,7 +1071,7 @@ class kolab_notes extends rcube_plugin
$path_imap = explode($delim, $newfolder);
$list['name'] = kolab_storage::object_name($newfolder);
$list['editname'] = rcube_charset::convert(array_pop($path_imap), 'UTF7-IMAP');
$list['listname'] = str_repeat('&nbsp;&nbsp;&nbsp;', count($path_imap)) . '&raquo; ' . $list['editname'];
$list['listname'] = (!empty($path_imap) ? str_repeat('&nbsp;&nbsp;&nbsp;', count($path_imap)) . '&raquo; ' : '') . $list['editname'];
}
break;
@ -1098,7 +1104,7 @@ class kolab_notes extends rcube_plugin
}
// report more results available
if ($this->driver->search_more_results) {
$this->rc->output->show_message('autocompletemore', 'info');
$this->rc->output->show_message('autocompletemore', 'notice');
}
$this->rc->output->command('multi_thread_http_response', $results, rcube_utils::get_input_value('_reqid', rcube_utils::INPUT_GPC));
@ -1200,7 +1206,7 @@ class kolab_notes extends rcube_plugin
// prepend note links to message body
if ($html) {
$this->load_ui();
$args['content'] = html::div('kolabmessagenotes', $html) . $args['content'];
$args['content'] = html::div('kolabmessagenotes ui alert', $html) . $args['content'];
}
return $args;

View file

@ -33,7 +33,6 @@ class kolab_notes_ui
$this->plugin->include_stylesheet($this->plugin->local_skin_path() . '/notes.css');
$this->plugin->register_action('print', array($this, 'print_template'));
$this->plugin->register_action('folder-acl', array($this, 'folder_acl'));
$this->ready = true;
}
@ -79,33 +78,10 @@ class kolab_notes_ui
$settings['selected_uid'] = $uid;
}
$lang_codes = array($_SESSION['language']);
$assets_dir = $this->rc->config->get('assets_dir') ?: INSTALL_PATH;
if ($pos = strpos($_SESSION['language'], '_')) {
$lang_codes[] = substr($_SESSION['language'], 0, $pos);
}
foreach ($lang_codes as $code) {
if (file_exists("$assets_dir/program/js/tinymce/langs/$code.js")) {
$lang = $code;
break;
}
}
if (empty($lang)) {
$lang = 'en';
}
$settings['editor'] = array(
'lang' => $lang,
'spellcheck' => intval($this->rc->config->get('enable_spellcheck')),
'spelldict' => intval($this->rc->config->get('spellcheck_dictionary'))
);
$this->rc->html_editor();
$this->rc->output->set_env('kolab_notes_settings', $settings);
$this->rc->output->add_label('save','cancel','delete','close');
$this->rc->output->add_label('save','cancel','delete','close','listoptionstitle');
}
public function folders($attrib)
@ -240,7 +216,7 @@ class kolab_notes_ui
{
$attrib += array('id' => 'rcmkolabnoteslist');
$this->rc->output->add_gui_object('noteslist', $attrib['id']);
return html::tag('ul', $attrib, '', html::$common_attrib);
return html::tag('table', $attrib, '<tbody></tbody>', html::$common_attrib);
}
public function tagslist($attrib)
@ -254,10 +230,17 @@ class kolab_notes_ui
{
$attrib += array('action' => '#', 'id' => 'rcmkolabnoteseditform');
$this->rc->output->add_gui_object('noteseditform', $attrib['id']);
$this->rc->output->include_script('tinymce/tinymce.min.js');
$textarea = new html_textarea(array(
'name' => 'content',
'id' => 'notecontent',
'cols' => 60,
'rows' => 20,
'tabindex' => 0,
'class' => 'mce_editor form-control',
));
$this->rc->output->add_gui_object('noteseditform', $attrib['id']);
$textarea = new html_textarea(array('name' => 'content', 'id' => 'notecontent', 'cols' => 60, 'rows' => 20, 'tabindex' => 0));
return html::tag('form', $attrib, $textarea->show(), array_merge(html::$common_attrib, array('action')));
}
@ -273,15 +256,31 @@ class kolab_notes_ui
$attrib += array('id' => 'rcmkolabnotestitle');
$this->rc->output->add_gui_object('noteviewtitle', $attrib['id']);
$summary = new html_inputfield(array('name' => 'summary', 'class' => 'notetitle inline-edit', 'size' => 60, 'tabindex' => 0));
$summary = new html_inputfield(array(
'name' => 'summary',
'class' => 'notetitle inline-edit form-control',
'size' => 60,
'id' => 'notetitleinput',
'tabindex' => 0
));
$html = $summary->show();
$html .= html::div(array('class' => 'tagline tagedit', 'style' => 'display:none'), '&nbsp;');
$html .= html::div(array('class' => 'dates', 'style' => 'display:none'),
html::label(array(), $this->plugin->gettext('created')) .
html::span('notecreated', '') .
html::label(array(), $this->plugin->gettext('changed')) .
html::span('notechanged', '')
$html = html::div('form-group row',
html::label(array('class' => 'col-sm-2 col-form-label', 'for' => 'notetitleinput'), $this->plugin->gettext('kolab_notes.title'))
. html::span('col-sm-10', $summary->show())
)
. html::div('form-group row',
html::label(array('class' => 'col-sm-2 col-form-label'), $this->plugin->gettext('kolab_notes.tags'))
. html::div(array('class' => 'tagline tagedit col-sm-10', 'style' => 'display:none'), '&nbsp;')
)
. html::div(array('class' => 'dates', 'style' => 'display:none'),
html::div('form-group row',
html::label(array('class' => 'col-sm-2 col-form-label'), $this->plugin->gettext('created'))
. html::span('col-sm-10', html::span('notecreated form-control-plaintext', ''))
)
. html::div('form-group row',
html::label(array('class' => 'col-sm-2 col-form-label'), $this->plugin->gettext('changed'))
. html::span('col-sm-10', html::span('notechanged form-control-plaintext', ''))
)
);
return html::div($attrib, $html);
@ -295,12 +294,24 @@ class kolab_notes_ui
}
/**
* Render edit for notes lists (folders)
* Render create/edit form for notes lists (folders)
*/
public function list_editform($action, $list, $folder)
{
if (is_object($folder)) {
$folder_name = $folder->name; // UTF7
$this->action = $action;
$this->list = $list;
$this->folder = $folder;
$this->rc->output->add_handler('notebookform', array($this, 'notebookform'));
$this->rc->output->send('kolab_notes.listform');
}
/**
* Render create/edit form for notes lists (folders)
*/
public function notebookform($attrib)
{
if (is_object($this->folder)) {
$folder_name = $this->folder->name; // UTF7
}
else {
$folder_name = '';
@ -334,7 +345,7 @@ class kolab_notes_ui
$input_name = new html_inputfield(array('name' => 'name', 'id' => 'noteslist-name', 'size' => 20));
$form['properties']['fields']['name'] = array(
'label' => $this->plugin->gettext('listname'),
'value' => $input_name->show($list['editname'], array('disabled' => ($options['norename'] || $options['protected']))),
'value' => $input_name->show($this->list['editname'], array('disabled' => ($options['norename'] || $options['protected']))),
'id' => 'noteslist-name',
);
@ -352,16 +363,10 @@ class kolab_notes_ui
}
// add folder ACL tab
if ($action != 'form-new') {
if ($this->action != 'form-new') {
$form['sharing'] = array(
'name' => rcube::Q($this->plugin->gettext('tabsharing')),
'content' => html::tag('iframe', array(
'src' => $this->rc->url(array('_action' => 'folder-acl', '_folder' => $folder_name, 'framed' => 1)),
'width' => '100%',
'height' => 280,
'border' => 0,
'style' => 'border:0'),
'')
'content' => $this->folder_acl_form()
);
}
@ -376,7 +381,7 @@ class kolab_notes_ui
// create form output
foreach ($form as $tab) {
if (is_array($tab['fields']) && empty($tab['content'])) {
$table = new html_table(array('cols' => 2));
$table = new html_table(array('cols' => 2, 'class' => 'propform'));
foreach ($tab['fields'] as $col => $colprop) {
$label = !empty($colprop['label']) ? $colprop['label'] : $this->plugin->gettext($col);
@ -394,33 +399,22 @@ class kolab_notes_ui
}
}
return html::tag('form', array('action' => "#", 'method' => "post", 'id' => "noteslistpropform"), $form_html);
return html::tag('form', $attrib + array('action' => '#', 'method' => 'post', 'id' => 'noteslistpropform'), $form_html);
}
/**
* Handler to render ACL form for a notes folder
*/
public function folder_acl()
{
$this->plugin->require_plugin('acl');
$this->rc->output->add_handler('folderacl', array($this, 'folder_acl_form'));
$this->rc->output->send('kolab_notes.kolabacl');
}
/**
* Handler for ACL form template object
* Returns ACL form
*/
public function folder_acl_form()
{
$folder = rcube_utils::get_input_value('_folder', rcube_utils::INPUT_GPC);
if (strlen($folder)) {
if (strlen($this->folder)) {
$this->plugin->require_plugin('acl');
$storage = $this->rc->get_storage();
$options = $storage->folder_info($folder);
$options = $storage->folder_info($this->folder);
// get sharing UI from acl plugin
$acl = $this->rc->plugins->exec_hook('folder_form',
array('form' => array(), 'options' => $options, 'name' => $folder));
array('form' => array(), 'options' => $options, 'name' => $this->folder));
}
return $acl['form']['sharing']['content'] ?: html::div('hint', $this->plugin->gettext('aclnorights'));
@ -436,6 +430,4 @@ class kolab_notes_ui
echo $this->rc->output->parse('kolab_notes.print', false, false);
exit;
}
}

View file

@ -37,12 +37,14 @@ $labels['appendnote'] = 'Add a Note';
$labels['editnote'] = 'Edit Note';
$labels['savein'] = 'Save in';
$labels['foldersubscribe'] = 'List permanently';
$labels['findnotebooks'] = 'Find notebooks...';
$labels['findnotebooks'] = 'Find notebooks';
$labels['findnotes'] = 'Find notes';
$labels['listsearchresults'] = 'Additional notebooks';
$labels['nrnotebooksfound'] = '$nr notebooks found';
$labels['nonotebooksfound'] = 'No notebooks found';
$labels['removelist'] = 'Remove from list';
$labels['removelink'] = 'Remove email reference';
$labels['listactions'] = 'Notebooks list actions';
$labels['savingdata'] = 'Saving data...';
$labels['recordnotfound'] = 'Record not found';
@ -63,5 +65,5 @@ $labels['arialabelnotessortmenu'] = 'Notes list sorting options';
$labels['arialabelnotesoptionsmenu'] = 'Notebook actions menu';
$labels['arialabelnotebookform'] = 'Notebook properties';
$labels['arialabelmessagereferences'] = 'Linked email messages';
$labels['arialabelfolderearchform'] = 'Notebooks search form';
$labels['arialabelfoldersearchform'] = 'Notebooks search form';
$labels['arialabelnoteform'] = 'Note edit form';

View file

@ -2,11 +2,12 @@
* Client scripts for the Kolab Notes plugin
*
* @author Thomas Bruederli <bruederli@kolabsys.com>
* @author Aleksander Machniak <machniak@kolabsys.com>
*
* @licstart The following is the entire license notice for the
* JavaScript code in this file.
*
* Copyright (C) 2014-2015, Kolab Systems AG <contact@kolabsys.com>
* Copyright (C) 2014-2017, 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
@ -47,6 +48,8 @@ function rcube_kolab_notes_ui(settings)
this.selected_list = null;
this.selected_note = null;
this.notebooks = rcmail.env.kolab_notebooks || {};
this.list_set_sort = list_set_sort;
this.settings = settings;
/**
* initialize the notes UI
@ -55,7 +58,7 @@ function rcube_kolab_notes_ui(settings)
{
// register button commands
rcmail.register_command('createnote', function(){
warn_unsaved_changes(function(){ edit_note(null, 'new'); })
warn_unsaved_changes(function(){ edit_note(null, 'new'); });
}, false);
rcmail.register_command('list-create', function(){ list_edit_dialog(null); }, true);
rcmail.register_command('list-edit', function(){ list_edit_dialog(me.selected_list); }, false);
@ -105,7 +108,7 @@ function rcube_kolab_notes_ui(settings)
id_prefix: 'rcmliknb',
save_state: true,
selectable: true,
keyboard: false,
keyboard: true,
searchbox: '#notebooksearch',
search_action: 'notes/list',
search_sources: [ 'folders', 'users' ],
@ -124,6 +127,7 @@ function rcube_kolab_notes_ui(settings)
rcmail.enable_command('list-delete', has_permission(me.notebooks[id], 'xa'));
rcmail.enable_command('list-remove', !me.notebooks[id]['default']);
fetch_notes(id); // sets me.selected_list
rcmail.triggerEvent('show-list', {title: me.notebooks[id].listname}); // Elastic
},
function(){
// restore previous selection
@ -162,9 +166,16 @@ function rcube_kolab_notes_ui(settings)
if (data.length)
rcmail.display_message(rcmail.gettext('nrnotebooksfound','kolab_notes').replace('$nr', data.length), 'voice');
else
rcmail.display_message(rcmail.gettext('nonotebooksfound','kolab_notes'), 'info');
rcmail.display_message(rcmail.gettext('nonotebooksfound','kolab_notes'), 'notice');
});
// Make Elastic checkboxes pretty
if (window.UI && UI.pretty_checkbox) {
notebookslist.addEventListener('add-item', function(prop) {
UI.pretty_checkbox($(prop.li).find('input').addClass('flex-checkbox'));
});
}
$(rcmail.gui_objects.notebooks).on('click', 'div.folder > a.listname', function(e) {
var id = String($(this).closest('li').attr('id')).replace(/^rcmliknb/, '');
notebookslist.select(id);
@ -194,14 +205,14 @@ function rcube_kolab_notes_ui(settings)
// initialize notes list widget
if (rcmail.gui_objects.noteslist) {
noteslist = new rcube_list_widget(rcmail.gui_objects.noteslist,
rcmail.noteslist = noteslist = new rcube_list_widget(rcmail.gui_objects.noteslist,
{ multiselect:true, draggable:true, keyboard:true });
noteslist.addEventListener('select', function(list) {
render_no_focus = rcube_event._last_keyboard_event && $(list.list).has(rcube_event._last_keyboard_event.target);
var selection_changed = list.selection.length != 1 || !me.selected_note || list.selection[0] != me.selected_note.id;
selection_changed && warn_unsaved_changes(function(){
var note;
if (noteslist.selection.length == 1 && (note = notesdata[noteslist.selection[0]])) {
if (!list.multi_selecting && noteslist.selection.length == 1 && (note = notesdata[noteslist.selection[0]])) {
edit_note(note.uid, 'edit');
}
else {
@ -340,23 +351,17 @@ function rcube_kolab_notes_ui(settings)
if (rcmail.gui_objects.noteseditform) {
rcmail.lock_form(rcmail.gui_objects.noteseditform, false);
}
if (rcmail.is_framed()) {
parent.$(parent.kolab_note_dialog_element).dialog('destroy');
}
});
var id;
for (id in me.notebooks) {
if (me.notebooks[id].editable) {
me.selected_list = id;
break;
}
}
init_editor();
var id, callback = function() {
if (settings.selected_uid) {
me.selected_list = settings.selected_list;
edit_note(settings.selected_uid);
}
else {
setTimeout(function(){
me.selected_note = $.extend({
list: me.selected_list,
uid: null,
@ -367,56 +372,31 @@ function rcube_kolab_notes_ui(settings)
changed: rcmail.gettext('now', 'kolab_notes')
}, rcmail.env.kolab_notes_template || {});
render_note(me.selected_note);
}, 100);
}
};
for (id in me.notebooks) {
if (me.notebooks[id].editable) {
me.selected_list = id;
break;
}
}
init_editor(callback);
}
this.init_dialog = init_dialog;
/**
* initialize tinyMCE editor
*/
function init_editor()
function init_editor(callback)
{
var editor_conf = {
selector: '#notecontent',
theme: 'modern',
language: settings.editor.lang,
content_css: rcmail.assets_path('program/js/tinymce/roundcube/content.css?v2'),
plugins: 'autolink charmap code link paste tabfocus searchreplace table textcolor',
toolbar: 'bold italic underline | alignleft aligncenter alignright alignjustify '
+ '| bullist numlist outdent indent blockquote | forecolor backcolor fontselect fontsizeselect '
+ '| link unlink table charmap | code searchreplace undo redo',
menubar: false,
statusbar: false,
toolbar_items_size: 'small',
extended_valid_elements: 'font[face|size|color|style],span[id|class|align|style]',
relative_urls: false,
remove_script_host: false,
convert_urls: false,
image_description: false,
paste_webkit_style: "color font-size font-family",
paste_data_images: true,
//spellchecker_rpc_url: '../../../../../?_task=utils&_action=spell_html&_remote=1',
//spellchecker_language: rcmail.env.spell_lang,
accessibility_focus: false,
tabfocus_elements: [':prev','btn-save-note'],
setup: function(ed) {
// make links open on shift-click
ed.on('click', function(e) {
var link = $(e.target).closest('a');
if (link.length && e.shiftKey) {
if (!bw.mz) window.open(link.get(0).href, '_blank');
return false;
if (callback) {
rcmail.addEventListener('editor-load', callback);
}
});
}
};
// support external configuration settings e.g. from skin
if (window.rcmail_editor_settings)
$.extend(editor_conf, window.rcmail_editor_settings);
tinyMCE.init(editor_conf);
// initialize HTML editor
rcmail.editor_init(rcmail.env.editor_config, 'notecontent');
// register click handler for message links
$(rcmail.gui_objects.notesattachmentslist).on('click', 'li a.messagelink', function() {
@ -433,14 +413,6 @@ function rcube_kolab_notes_ui(settings)
return String(str).replace(/</g, '&lt;').replace(/>/g, '&gt;').replace(/"/g, '&quot;');
}
/**
* Trim whitespace off the given string
*/
function trim(str)
{
return String(str).replace(/\s+$/, '').replace(/^\s+/, '');
}
/**
* Check permissions on the given list object
*/
@ -495,84 +467,45 @@ function rcube_kolab_notes_ui(settings)
*/
function list_edit_dialog(id)
{
if (!rcmail.gui_containers.notebookeditform) {
return false;
}
var list = me.notebooks[id] || { name:'', editable:true, rights: 'riwta' },
title = rcmail.gettext((list.id ? 'editlist' : 'newnotebook'), 'kolab_notes'),
params = {_do: (list.id ? 'form-edit' : 'form-new'), _list: {id: list.id}, _framed: 1},
$dialog = $('<iframe>').attr('src', rcmail.url('list', params)).on('load', function() {
$(this).contents().find('#noteslist-name')
.prop('disabled', !has_permission(list, 'a'))
.val(list.editname || list.name)
.select();
}),
save_func = function() {
var data,
form = $dialog.contents().find('#noteslistpropform'),
name = form.find('#noteslist-name');
// close show dialog first
var $dialog = rcmail.gui_containers.notebookeditform;
if ($dialog.is(':ui-dialog')) {
$dialog.dialog('close');
}
var list = me.notebooks[id] || { name:'', editable:true, rights: 'riwta' };
var form, name;
$dialog.html(rcmail.get_label('loading'));
$.ajax({
type: 'GET',
dataType: 'html',
url: rcmail.url('list'),
data: { _do: (list.id ? 'form-edit' : 'form-new'), _list: { id: list.id } },
success: function(data) {
$dialog.html(data);
rcmail.triggerEvent('kolab_notes_editform_load', list);
// resize and reposition dialog window
form = $('#noteslistpropform');
var win = $(window), w = win.width(), h = win.height();
$dialog.dialog('option', { height: Math.min(h-20, form.height()+130), width: Math.min(w-20, form.width()+50) });
name = $('#noteslist-name').prop('disabled', !has_permission(list, 'a')).val(list.editname || list.name);
name.select();
}
});
// dialog buttons
var buttons = {};
buttons[rcmail.gettext('save')] = function() {
// form is not loaded
if (!form || !form.length)
return;
return false;
// do some input validation
if (!name.val() || name.val().length < 2) {
alert(rcmail.gettext('invalidlistproperties', 'kolab_notes'));
name.select();
return;
return false;
}
// post data to server
var data = form.serializeJSON();
data = form.serializeJSON();
if (list.id)
data.id = list.id;
saving_lock = rcmail.set_busy(true, 'kolab_notes.savingdata');
rcmail.http_post('list', { _do: (list.id ? 'edit' : 'new'), _list: data });
$dialog.dialog('close');
return true;
};
buttons[rcmail.gettext('cancel')] = function() {
$dialog.dialog('close');
};
// open jquery UI dialog
$dialog.dialog({
modal: true,
resizable: true,
closeOnEscape: false,
title: rcmail.gettext((list.id ? 'editlist' : 'newnotebook'), 'kolab_notes'),
open: function() {
$dialog.parent().find('.ui-dialog-buttonset .ui-button').first().addClass('mainaction');
},
close: function() {
$dialog.html('').dialog('destroy').hide();
},
buttons: buttons,
minWidth: 480,
width: 640
}).show();
rcmail.simple_dialog($dialog, title, save_func, {
width: 600,
height: 400
});
}
/**
@ -752,8 +685,8 @@ function rcube_kolab_notes_ui(settings)
function filter_notes()
{
// tagsfilter
var note, tr, match;
for (var id in noteslist.rows) {
var id, note, tr, match;
for (id in noteslist.rows) {
tr = noteslist.rows[id].obj;
note = notesdata[id];
match = note.tags && note.tags.length;
@ -814,11 +747,9 @@ function rcube_kolab_notes_ui(settings)
render_tagslist(data.tags || [], !data.search)
rcmail.set_busy(false, 'loading', ui_loading);
// select the single result
if (data.data.length == 1) {
noteslist.select(data.data[0].id);
}
else if (settings.selected_uid) {
rcmail.triggerEvent('listupdate', {list: noteslist, rowcount:noteslist.rowcount});
if (settings.selected_uid) {
noteslist.select(rcmail.html_identifier_encode(settings.selected_uid));
delete settings.selected_uid;
}
@ -826,7 +757,7 @@ function rcube_kolab_notes_ui(settings)
noteslist.select(me.selected_note.id);
}
else if (!data.data.length) {
rcmail.display_message(rcmail.gettext('norecordsfound','kolab_notes'), 'info');
rcmail.display_message(rcmail.gettext('norecordsfound','kolab_notes'), 'notice');
}
}
@ -846,15 +777,24 @@ function rcube_kolab_notes_ui(settings)
container = rcmail.gui_containers['notedetailview'];
}
// for Elastic
rcmail.triggerEvent('show-content', {
mode: data.uid ? 'edit' : 'add',
title: rcmail.gettext(data.uid ? 'editnote' : 'newnote', 'kolab_notes'),
obj: $('#notedetailsbox').parent(),
scrollElement: $('#notedetailsbox')
});
var list = me.notebooks[data.list] || me.notebooks[me.selected_list] || { rights: 'lrs', editable: false };
content = $('#notecontent').val(data.description),
readonly = data.readonly || !(list.editable || !data.uid && has_permission(list,'i')),
attachmentslist = gui_object('notesattachmentslist', container).html(''),
titlecontainer = container || rcmail.gui_objects.noteviewtitle;
titlecontainer = rcmail.gui_objects.noteviewtitle || container,
is_html = false;
$('.notetitle', titlecontainer).val(data.title).prop('disabled', readonly).show();
$('.dates .notecreated', titlecontainer).html(Q(data.created || ''));
$('.dates .notechanged', titlecontainer).html(Q(data.changed || ''));
$('.dates .notecreated', titlecontainer).text(data.created || '');
$('.dates .notechanged', titlecontainer).text(data.changed || '');
if (data.created || data.changed) {
$('.dates', titlecontainer).show();
}
@ -899,11 +839,12 @@ function rcube_kolab_notes_ui(settings)
.appendTo(attachmentslist);
if (!readonly && !data._from_mail) {
$('<a>')
.attr('href', '#delete')
.attr('title', rcmail.gettext('removelink', 'kolab_notes'))
.addClass('delete')
.html(rcmail.gettext('delete'))
$('<a>').attr({
href: '#delete',
title: rcmail.gettext('removelink', 'kolab_notes'),
label: rcmail.gettext('delete'),
'class': 'delete'
})
.click({ uri:link.uri }, function(e) {
remove_link(this, e.data.uri);
return false;
@ -937,45 +878,24 @@ function rcube_kolab_notes_ui(settings)
html = text2html(html);
}
var node, editor = tinyMCE.get('notecontent'), is_html = false;
retry = retry || 0;
// sometimes the editor instance is not ready yet (FF only)...
if (!readonly && !editor && $('#notecontent').length && retry < 5) {
// ... give it some more time
setTimeout(function() {
gui_object('noteseditform', container).show();
render_note(data, container, temp, retry+1);
}, 200);
return;
}
if (!readonly && editor) {
if (!readonly) {
gui_object('notesdetailview', container).hide();
gui_object('noteseditform', container).show();
editor.setContent(''); // #4781
editor.setContent(html);
node = editor.getContentAreaContainer().childNodes[0];
if (node) node.tabIndex = content.get(0).tabIndex;
if (me.selected_note.uid) {
if (!render_no_focus)
editor.getBody().focus();
}
else
$('.notetitle', titlecontainer).focus().select();
rcmail.editor.set_content(html);
// read possibly re-formatted content back from editor for later comparison
me.selected_note.description = editor.getContent({ format:'html' }).replace(/^\s*(<p><\/p>\n*)?/, '');
me.selected_note.description = rcmail.editor.get_content().replace(/^\s*(<p><\/p>\n*)?/, '');
is_html = true;
if (!me.selected_note.uid)
$('.notetitle', titlecontainer).focus().select();
}
else {
gui_object('noteseditform', container).hide();
gui_object('notesdetailview', container).html(html).show();
}
render_no_focus = false;
// notify subscribers
rcmail.triggerEvent('kolab_notes_render', { data:data, readonly:readonly, html:is_html });
if (rcmail.is_framed())
@ -983,6 +903,10 @@ function rcube_kolab_notes_ui(settings)
// Trigger resize (needed for proper editor resizing)
$(window).resize();
// Elastic
$(container).parents('.watermark').addClass('formcontainer');
$('#notedetailsbox').parent().trigger('loaded');
}
/**
@ -1032,7 +956,7 @@ function rcube_kolab_notes_ui(settings)
$dialog = libkolab_audittrail.object_history_dialog({
module: 'kolab_notes',
container: '#notehistory',
title: rcmail.gettext('objectchangelog','kolab_notes') + ' - ' + rec.title,
title: rcmail.gettext('libkolab.objectchangelog') + ' - ' + rec.title,
// callback function for list actions
listfunc: function(action, rev) {
@ -1066,7 +990,7 @@ function rcube_kolab_notes_ui(settings)
if (data === false || !data.length || !rec) {
// display 'unavailable' message
$('<div class="notfound-message note-dialog-message warning">' + rcmail.gettext('objectchangelognotavailable','kolab_notes') + '</div>')
$('<div class="notfound-message note-dialog-message warning">').text(rcmail.gettext('libkolab.objectchangelognotavailable'))
.insertBefore($dialog.find('.changelog-table').hide());
return;
}
@ -1124,8 +1048,9 @@ function rcube_kolab_notes_ui(settings)
*/
function show_diff(data)
{
var rec = me.selected_note,
$dialog = $('#notediff');
var change_old, change_new,
rec = me.selected_note,
$dialog = $('#notediff').clone();
$dialog.find('div.form-section, h2.note-title-new').hide().data('set', false);
@ -1153,46 +1078,31 @@ function rcube_kolab_notes_ui(settings)
row.children('.diff-text-old, .diff-text-new').hide();
}
else {
if (!html) {
// escape HTML characters
change.old_ = Q(change.old_ || change['old'] || '--')
change.new_ = Q(change.new_ || change['new'] || '--')
}
row.children('.diff-text-old').html(change.old_ || change['old'] || '--').show();
row.children('.diff-text-new').html(change.new_ || change['new'] || '--').show();
change_old = change.old_ || change['old'] || '--';
change_new = change.new_ || change['new'] || '--';
row.children('.diff-text-old')[html ? 'html' : 'text'](change_old).show();
row.children('.diff-text-new')[html ? 'html' : 'text'](change_new).show();
}
row.show().data('set', true);
});
// open jquery UI dialog
$dialog.dialog({
modal: false,
resizable: true,
closeOnEscape: true,
title: rcmail.gettext('objectdiff','kolab_notes').replace('$rev1', data.rev1).replace('$rev2', data.rev2) + ' - ' + rec.title,
open: function() {
$dialog.attr('aria-hidden', 'false');
},
close: function() {
$dialog.dialog('destroy').attr('aria-hidden', 'true').hide();
},
buttons: [
{
text: rcmail.gettext('close'),
click: function() { $dialog.dialog('close'); },
autofocus: true
}
],
rcmail.simple_dialog($dialog,
rcmail.gettext('libkolab.objectdiff').replace('$rev1', data.rev1).replace('$rev2', data.rev2) + ' - ' + rec.title,
null, {
cancel_label: 'close',
minWidth: 400,
width: 480
}).show();
}
);
// set dialog size according to content
libkolab_audittrail.dialog_resize($dialog.get(0), $dialog.height(), rcmail.gui_containers.notedetailview.width() - 40);
}
// close the event history dialog
// close the note history dialog
function close_history_dialog()
{
$('#notehistory, #notediff').each(function(i, elem) {
@ -1235,11 +1145,11 @@ function rcube_kolab_notes_ui(settings)
$(printwin).on('load', function() {
printwin.document.title = data.title;
$('#notetitle', printwin.document).html(Q(data.title));
$('#notetitle', printwin.document).text(data.title);
$('#notebody', printwin.document).html(data.description);
$('#notetags', printwin.document).html('<span class="tag">' + data.tags.join('</span><span class="tag">') + '</span>');
$('#notecreated', printwin.document).html(Q(me.selected_note.created));
$('#notechanged', printwin.document).html(Q(me.selected_note.changed));
$('#notecreated', printwin.document).text(me.selected_note.created);
$('#notechanged', printwin.document).text(me.selected_note.changed);
printwin.print();
});
}
@ -1251,12 +1161,12 @@ function rcube_kolab_notes_ui(settings)
function send_note()
{
var uids = [];
for (var rec, i=0; i < noteslist.selection.length; i++) {
if (rec = notesdata[noteslist.selection[i]]) {
$.each(noteslist.selection, function() {
if (rec = notesdata[this]) {
uids.push(rec.uid);
// TODO: check if rec.uid == me.selected_note.uid and unsaved changes
}
}
});
if (uids.length) {
rcmail.goto_url('mail/compose', { _with_notes: uids.join(','), _notes_list: me.selected_list }, true);
@ -1272,8 +1182,8 @@ function rcube_kolab_notes_ui(settings)
tags = newtags;
}
else {
var append = [];
for (var i=0; i < newtags.length; i++) {
var i, append = [];
for (i=0; i < newtags.length; i++) {
if ($.inArray(newtags[i], tags) < 0)
append.push(newtags[i]);
}
@ -1380,8 +1290,8 @@ function rcube_kolab_notes_ui(settings)
}
// update list item
else if (row = noteslist.rows[data.id]) {
$('.title', row.obj).html(Q(data.title));
$('.date', row.obj).html(Q(data.changed || ''));
$('.title', row.obj).text(data.title);
$('.date', row.obj).text(data.changed || '');
// TODO: move to top
}
}
@ -1395,10 +1305,11 @@ function rcube_kolab_notes_ui(settings)
me.selected_note = null;
$('.notetitle', rcmail.gui_objects.noteviewtitle).val('').hide();
$('.tagline, .dates', rcmail.gui_objects.noteviewtitle).hide();
$(rcmail.gui_objects.noteseditform).hide();
$(rcmail.gui_objects.noteseditform).hide().parents('.watermark').removeClass('formcontainer');
$(rcmail.gui_objects.notesdetailview).hide();
$(rcmail.gui_objects.notesattachmentslist).html('');
rcmail.enable_command('save', false);
rcmail.triggerEvent('show-list');
}
/**
@ -1435,7 +1346,7 @@ function rcube_kolab_notes_ui(settings)
rcmail.http_post('action', {_data: savedata, _do: savedata.uid ? 'edit' : 'new'}, true);
}
else {
rcmail.display_message(rcmail.get_label('nochanges', 'kolab_notes'), 'info');
rcmail.display_message(rcmail.get_label('nochanges', 'kolab_notes'), 'notice');
}
}
@ -1444,11 +1355,10 @@ function rcube_kolab_notes_ui(settings)
*/
function get_save_data()
{
var editor = tinyMCE.get('notecontent'),
listselect = $('option:selected', rcmail.gui_objects.notebooks);
var savedata = {
title: trim($('.notetitle', rcmail.gui_objects.noteviewtitle).val()),
description: editor ? editor.getContent({ format:'html' }).replace(/^\s*(<p><\/p>\n*)?/, '') : $('#notecontent').val(),
var listselect = $('option:selected', rcmail.gui_objects.notebooks),
savedata = {
title: $.trim($('.notetitle', rcmail.gui_objects.noteviewtitle).val()),
description: rcmail.editor.get_content().replace(/^\s*(<p><\/p>\n*)?/, ''),
list: listselect.length ? listselect.val() : me.selected_note.list || me.selected_list,
uid: me.selected_note.uid,
tags: []
@ -1504,17 +1414,9 @@ function rcube_kolab_notes_ui(settings)
if (check_change_state()) {
var dialog, buttons = [];
buttons.push({
text: rcmail.gettext('discard', 'kolab_notes'),
click: function() {
dialog.dialog('close');
ok();
}
});
buttons.push({
text: rcmail.gettext('save'),
'class': 'mainaction',
'class': 'mainaction save',
click: function() {
save_note(beforesave);
dialog.dialog('close');
@ -1523,8 +1425,18 @@ function rcube_kolab_notes_ui(settings)
}
});
buttons.push({
text: rcmail.gettext('discard', 'kolab_notes'),
'class': 'discard',
click: function() {
dialog.dialog('close');
ok();
}
});
buttons.push({
text: rcmail.gettext('abort', 'kolab_notes'),
'class': 'cancel',
click: function() {
dialog.dialog('close');
nok();
@ -1575,8 +1487,8 @@ function rcube_kolab_notes_ui(settings)
}
if (confirm(rcmail.gettext('deletenotesconfirm','kolab_notes'))) {
var rec, id, uids = [];
for (var i=0; i < noteslist.selection.length; i++) {
var i, rec, id, uids = [];
for (i=0; i < noteslist.selection.length; i++) {
id = noteslist.selection[i];
rec = notesdata[id];
if (rec) {
@ -1731,13 +1643,51 @@ jQuery.fn.sortElements = (function(){
})();
/* notes plugin UI initialization */
// List options menu for Elastic
function kolab_notes_options_menu()
{
var content = $('#options-menu'),
width = content.width() + 25,
dialog = content.clone();
// set form values
$('select[name="sort_col"]', dialog).val(kolabnotes.settings.sort_col || '');
$('select[name="sort_ord"]', dialog).val(kolabnotes.settings.sort_order || 'ASC');
// Fix id/for attributes
$('select', dialog).each(function() { this.id = this.id + '-clone'; });
$('label', dialog).each(function() { $(this).attr('for', $(this).attr('for') + '-clone'); });
var save_func = function(e) {
if (rcube_event.is_keyboard(e.originalEvent)) {
$('#listmenulink').focus();
}
var col = $('select[name="sort_col"]', dialog).val(),
ord = $('select[name="sort_ord"]', dialog).val();
kolabnotes.list_set_sort(col, ord);
return true;
};
dialog = rcmail.simple_dialog(dialog, rcmail.gettext('listoptionstitle'), save_func, {
closeOnEscape: true,
open: function(e) {
setTimeout(function() { dialog.find('select').first().focus(); }, 100);
},
minWidth: 400,
width: width
});
};
/* Notes plugin UI initialization */
var kolabnotes;
window.rcmail && rcmail.addEventListener('init', function(evt) {
kolabnotes = new rcube_kolab_notes_ui(rcmail.env.kolab_notes_settings);
if (rcmail.env.action == 'dialog-ui')
kolabnotes.init_dialog();
else
kolabnotes.init();
});

View file

@ -6,7 +6,7 @@
* @licstart The following is the entire license notice for the
* JavaScript code in this file.
*
* Copyright (C) 2014, Kolab Systems AG <contact@kolabsys.com>
* Copyright (C) 2014-2017, 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
@ -25,99 +25,73 @@
* for the JavaScript code in this file.
*/
window.rcmail && rcmail.addEventListener('init', function(evt) {
/**
* Open the notes edit GUI in a jquery UI dialog
*/
function kolab_note_dialog(url)
{
var frame, name, mywin = window, edit = url && url._id,
$dialog = $('#kolabnotesinlinegui');
if (!url) url = {};
url._framed = 1;
function dialog_render(p)
{
var $dialog, frame, buttons = {},
button_classes = ['mainaction save'],
edit = url._id,
title = edit ? rcmail.gettext('kolab_notes.editnote') : rcmail.gettext('kolab_notes.appendnote'),
dialog_render = function(p) {
$dialog.parent().find('.ui-dialog-buttonset .ui-button')
.prop('disabled', p.readonly)
.last().prop('disabled', false);
}
};
// create dialog if not exists
if (!$dialog.length) {
$dialog = $('<iframe>')
.attr('id', 'kolabnotesinlinegui')
.attr('name', 'kolabnotesdialog')
.attr('src', 'about:blank')
.css('min-width', '100%')
.on('load', function(e) {
$dialog = $('<iframe>').attr({
id: 'kolabnotesinlinegui',
name: 'kolabnotesdialog',
src: rcmail.url('notes/dialog-ui', url)
}).on('load', function(e) {
frame = rcmail.get_frame_window('kolabnotesinlinegui');
name = $('.notetitle', frame.rcmail.gui_objects.noteviewtitle);
frame.rcmail.addEventListener('responseafteraction', refresh_mailview);
});
// subscribe event in parent window which is also triggered from iframe
// (probably before the 'load' event from above)
rcmail.addEventListener('kolab_notes_render', dialog_render);
}
// close show dialog first
else if ($dialog.is(':ui-dialog')) {
$dialog.dialog('close');
}
if (!url) url = {};
url._framed = 1;
$dialog.attr('src', rcmail.url('notes/dialog-ui', url));
// dialog buttons
var buttons = {};
buttons[rcmail.gettext('save')] = function() {
// frame is not loaded
if (!frame)
return;
// do some input validation
if (!name.val() || name.val().length < 2) {
alert(rcmail.gettext('entertitle', 'kolab_notes'));
name.select();
return;
}
frame.rcmail.command('save');
};
if (edit) {
button_classes.push('delete');
buttons[rcmail.gettext('delete')] = function() {
if (confirm(rcmail.gettext('deletenotesconfirm','kolab_notes'))) {
rcmail.addEventListener('responseafteraction', refresh_mailview);
rcmail.http_post('notes/action', { _data: { uid: url._id, list: url._list }, _do: 'delete' }, true);
$dialog.dialog('close');
$dialog.dialog('destroy');
}
};
}
button_classes.push('cancel');
buttons[rcmail.gettext(edit ? 'close' : 'cancel')] = function() {
$dialog.dialog('close');
$dialog.dialog('destroy');
};
// open jquery UI dialog
var win = $(window);
$dialog.dialog({
modal: true,
resizable: true,
closeOnEscape: true,
title: edit ? rcmail.gettext('editnote','kolab_notes') : rcmail.gettext('appendnote','kolab_notes'),
open: function() {
$dialog.parent().find('.ui-dialog-buttonset .ui-button').prop('disabled', true).first().addClass('mainaction');
},
window.kolab_note_dialog_element = $dialog = rcmail.show_popup_dialog($dialog, title, buttons, {
button_classes: button_classes,
close: function() {
$dialog.dialog('destroy');
rcmail.removeEventListener('kolab_notes_render', dialog_render);
},
buttons: buttons,
minWidth: 480,
width: 680,
height: Math.min(640, win.height() - 100)
}).show();
minWidth: 500,
width: 600,
height: 500
});
}
/**
@ -125,19 +99,19 @@ window.rcmail && rcmail.addEventListener('init', function(evt) {
*/
function refresh_mailview(e)
{
var win = rcmail.env.contentframe ? rcmail.get_frame_window(rcmail.env.contentframe) : mywin;
var win = rcmail.env.contentframe ? rcmail.get_frame_window(rcmail.env.contentframe) : window;
if (win && e.response) {
win.location.reload();
if (e.response.action == 'action')
$('#kolabnotesinlinegui').dialog('close');
$('#kolabnotesinlinegui').dialog('destroy');
}
}
// register commands
rcmail.register_command('edit-kolab-note', kolab_note_dialog, true);
rcmail.register_command('append-kolab-note', function() {
var uid;
if ((uid = rcmail.get_single_uid())) {
var uid = rcmail.get_single_uid();
if (uid) {
kolab_note_dialog({ _msg: uid + '-' + rcmail.env.mailbox });
}
});

View file

@ -0,0 +1,29 @@
<roundcube:include file="includes/layout.html" />
<div id="notedetailsbox" class="formcontent">
<roundcube:object name="plugin.notetitle" id="notedetailstitle" class="notetitle" />
<div class="notebookselect row form-group" style="display:none">
<label for="kolab-notebook" class="col-sm-2 col-form-label"><roundcube:label name="kolab_notes.savein" /></label>
<div class="col-sm-10">
<roundcube:object name="plugin.notebooks" id="kolab-notebook" type="select" class="form-control" />
</div>
</div>
<roundcube:object name="plugin.editform" id="noteform" class="noteform" />
<roundcube:object name="plugin.detailview" id="notedetails" class="notedetails" />
<div id="notereferences">
<roundcube:object name="plugin.attachments_list" id="attachment-list" class="attachmentslist" />
</div>
</div>
<script type="text/javascript">
// UI startup
$(document).ready(function(e) {
rcmail.addEventListener('kolab_notes_render', function(p) {
$('#notesdialogheader .notebookselect')[p.readonly ? 'hide' : 'show']();
});
});
</script>
<roundcube:include file="includes/footer.html" />

View file

@ -0,0 +1,9 @@
<roundcube:include file="includes/layout.html" />
<h1 class="voice"><roundcube:label name="kolab_notes.notes" /> : <roundcube:label name="kolab_notes.arialabelnotebookform" /></h1>
<div class="formcontent">
<roundcube:object name="notebookform" class="tabbed propform" />
</div>
<roundcube:include file="includes/footer.html" />

View file

@ -0,0 +1,172 @@
<roundcube:include file="includes/layout.html" />
<roundcube:include file="includes/menu.html" />
<h1 class="voice"><roundcube:label name="kolab_notes.navtitle" /></h1>
<!-- notebooks list -->
<div class="sidebar listbox" role="navigation" aria-labelledby="arial-label-notebooks">
<div class="header">
<a class="button icon menu-button" href="#menu"><span class="inner"><roundcube:label name="menu" /></span></a>
<span id="aria-label-notebooks" class="header-title"><roundcube:label name="kolab_notes.lists" /></span>
<div id="notebook-search" class="searchbar toolbar" role="search" aria-labelledby="aria-label-notebooksearchform">
<h2 id="aria-label-label-notebooksearchform" class="voice"><roundcube:label name="kolab_notes.arialabelfoldersearchform" /></h2>
<form name="foldersearchform" onsubmit="return false">
<input id="notebooksearch" type="text" name="q" placeholder="<roundcube:label name="searchplaceholder" />" />
<a class="button reset" href="#" onclick="return rcmail.command(\'reset-listsearch\',null,this,event)" title="<roundcube:label name="resetsearch" />" tabindex="0">
<span class="inner"><roundcube:label name="resetsearch" /></span>
</a>
</form>
<a class="button search" href="#" title="<roundcube:label name="kolab_notes.findnotebooks" />" tabindex="0">
<span class="inner"><roundcube:label name="kolab_notes.findnotebooks" /></span>
</a>
</div>
</div>
<div class="scroller">
<roundcube:object name="plugin.notebooks" id="notebooks" class="listing treelist iconized" />
<!--
<div id="tagsbox" class="uibox listbox">
<h2 class="boxtitle" id="aria-label-tagsbox"><roundcube:label name="kolab_notes.tags" id="taglist" /></h2>
<div class="scroller">
<roundcube:object name="plugin.tagslist" id="tagslist" class="tagcloud" role="region" aria-labelledby="aria-label-tagsbox" aria-controls="kolabnoteslist" />
</div>
</div>
-->
</div>
<div class="footer toolbar" role="toolbar">
<roundcube:button command="list-create" type="link" title="kolab_notes.newnotebook"
class="button create disabled" classAct="button create" innerClass="inner" label="kolab_notes.addnotebook" />
<roundcube:button name="notebookactionsmenu" id="notesoptionsmenulink" type="link"
title="kolab_notes.listactions" class="button actions" data-popup="notebookactions-menu"
innerClass="inner" label="actions" />
</div>
</div>
<!-- notes list -->
<div class="list listbox selected" aria-labelledby="aria-label-noteslist">
<div class="header">
<a class="button icon menu-button" href="#menu"><span class="inner"><roundcube:label name="menu" /></span></a>
<a class="button icon back-sidebar-button" href="#sidebar"><span class="inner"><roundcube:label name="kolab_notes.notebooks" /></span></a>
<span id="aria-label-noteslist" class="header-title"><roundcube:label name="kolab_notes.notes" /></span>
<roundcube:object name="plugin.searchform" id="searchform" wrapper="searchbar toolbar"
label="notesearchform" label-domain="kolab_notes" buttontitle="kolab_notes.findnotes" ariatag="h2" />
<a class="button icon toolbar-menu-button" href="#list-menu"><span class="inner"><roundcube:label name="menu" /></span></a>
</div>
<div class="pagenav toolbar" role="toolbar"></div>
<div class="scroller">
<h2 id="aria-label-noteslist" class="voice"><roundcube:label name="kolab_notes.notes" /></h2>
<roundcube:object name="plugin.listing" id="kolabnoteslist" class="listing" summary="kolab_notes.arialabelnoteslist"
role="listbox" data-list="noteslist" />
</div>
<div class="footer toolbar">
<div id="listcontrols" class="listselectors">
<roundcube:button name="optionsmenu" id="listmenulink" type="link" class="button settings"
label="options" innerClass="inner" onclick="return kolab_notes_options_menu()" />
</div>
</div>
</div>
<!-- contact details frame -->
<div class="content" role="main">
<h2 id="aria-label-toolbar" class="voice"><roundcube:label name="arialabeltoolbar" /></h2>
<div class="header" role="toolbar" aria-labelledby="aria-label-toolbar">
<a class="button icon back-list-button" href="#back"><span class="inner"><roundcube:label name="back" /></span></a>
<span class="header-title"></span>
<!-- toolbar -->
<div id="notestoolbar" class="toolbar">
<roundcube:button command="createnote" type="link"
class="button create disabled" classAct="button create"
label="create" title="kolab_notes.createnote" innerclass="inner" data-fab="true" />
<roundcube:button command="delete" type="link"
class="button delete disabled" classAct="button delete"
title="delete" label="delete" innerClass="inner" />
<span class="spacer"></span>
<roundcube:button command="print" type="link" data-hidden="small"
class="button print disabled" classAct="button print"
label="print" title="print" innerClass="inner" />
<roundcube:button command="sendnote" type="link"
class="button send disabled" classAct="button send"
label="kolab_notes.send" title="kolab_notes.sendnote" innerClass="inner" />
<roundcube:container name="toolbar" id="notestoolbar" />
</div>
</div>
<!-- note content frame -->
<h2 id="aria-label-noteform" class="voice"><roundcube:label name="kolab_notes.arialabelnoteform" /></h2>
<div class="content scroller watermark" role="main" aria-labelledby="aria-label-noteform">
<div id="notedetailsbox" class="formcontent">
<roundcube:object name="plugin.notetitle" id="notedetailstitle" class="notetitle" />
<roundcube:object name="plugin.editform" id="noteform" class="noteform" />
<roundcube:object name="plugin.detailview" id="notedetails" class="notedetails" />
<h3 id="aria-label-messagereferences" class="voice"><roundcube:label name="kolab_notes.arialabelmessagereferences" /></h3>
<div id="notereferences" class="notereferences" role="region" aria-labelledby="aria-label-messagereferences">
<roundcube:object name="plugin.attachments_list" id="attachment-list" class="attachmentslist" />
</div>
<roundcube:container name="notedetailview" id="notedetailsbox" />
</div>
<div class="formbuttons">
<roundcube:button command="save" class="btn btn-primary submit" label="save" id="btn-save-note" />
<roundcube:if condition="config:kolab_bonnie_api" />
<roundcube:button command="history" type="link" label="libkolab.showhistory"
class="btn btn-secondary history note-history disabled" classAct="btn btn-secondary history note-history" />
<roundcube:endif />
</div>
</div>
</div>
<!-- popups and dialogs -->
<roundcube:if condition="config:kolab_bonnie_api" />
<div id="notehistory" class="popupmenu" aria-hidden="true">
<roundcube:object name="plugin.object_changelog_table" class="records-table changelog-table" />
<div class="compare-button"><input type="button" class="button" value="↳ <roundcube:label name='libkolab.compare' />" /></div>
</div>
<div id="notediff" class="popupmenu" aria-hidden="true">
<h2 class="note-title">Note Title</h2>
<h2 class="note-title-new diff-text-new"></h2>
<div class="form-section note-tags">
<span class="diff-text-old"></span> &#8674; <span class="diff-text-new"></span>
</div>
<div class="form-section note-description">
<div class="diff-text-diff" style="white-space:pre-wrap"></div>
<div class="diff-text-old"></div>
<div class="diff-text-new"></div>
</div>
<div class="form-section notereferences">
<div class="diff-text-old"></div>
<div class="diff-text-new"></div>
</div>
</div>
<roundcube:endif />
<div id="notebookactions-menu" class="popupmenu">
<h3 id="aria-label-actionsmenu" class="voice"><roundcube:label name="kolab_notes.arialabelnotesoptionsmenu" /></h3>
<ul class="toolbarmenu listing" role="menu" aria-labelledby="aria-label-actionsmenu">
<roundcube:button type="link-menuitem" command="list-edit" label="edit" class="edit disabled" classAct="edit active" />
<roundcube:button type="link-menuitem" command="list-delete" label="delete" class="delete disabled" classAct="delete active" />
<roundcube:button type="link-menuitem" command="list-remove" label="kolab_notes.removelist" class="remove disabled" classAct="remove active" />
<roundcube:button type="link-menuitem" command="folders" task="settings" label="managefolders" class="folders disabled" classAct="folders active" />
</ul>
</div>
<div id="options-menu" class="popupmenu propform" role="menu" aria-labelledby="aria-label-optionsmenu">
<h3 id="aria-label-optionsmenu" class="voice"><roundcube:label name="kolab_notes.arialabelnotessortmenu" /></h3>
<div class="form-group row">
<label for="listoptions-sortcol" class="col-form-label col-sm-4"><roundcube:label name="listsorting" /></label>
<div class="col-sm-8">
<select id="listoptions-sortcol" name="sort_col" class="form-control">
<option value="changed"><roundcube:label name="kolab_notes.changed" /></option>
<option value="title"><roundcube:label name="kolab_notes.title" /></option>
</select>
</div>
</div>
<div class="form-group row">
<label for="listoptions-sortord" class="col-form-label col-sm-4"><roundcube:label name="listorder" /></label>
<div class="col-sm-8">
<select id="listoptions-sortord" name="sort_ord" class="form-control" disabled>
<option value="ASC"><roundcube:label name="asc" /></option>
<option value="DESC"><roundcube:label name="desc" /></option>
</select>
</div>
</div>
</div>
<roundcube:include file="includes/footer.html" />

View file

@ -0,0 +1,17 @@
<roundcube:include file="includes/layout.html" />
<div class="print-content" role="main">
<div id="notedetailstitle">
<h1 id="notetitle">#Title</h1>
<div id="notetags" class="tagline">#Tags</div>
<div class="dates">
<label><roundcube:label name="kolab_notes.created" /></label>
<span id="notecreated">#Created</span>
<label><roundcube:label name="kolab_notes.changed" /></label>
<span id="notechanged">#Changed</span>
</div>
</div>
<div id="notebody">#Body</div>
</div>
<roundcube:include file="includes/footer.html" />

View file

@ -106,6 +106,7 @@
overflow: hidden;
text-overflow: ellipsis;
outline: none;
border: 0;
}
.notesview #kolabnoteslist .date {
@ -349,6 +350,22 @@
box-sizing: border-box;
}
.notetitle .col-form-label {
display: none;
}
.notetitle .dates div.row {
display: inline;
}
.notetitle .dates .col-form-label {
display: inline;
}
.notebookselect {
clear: both;
}
/* Firefox 3.6 */
_:not(), _:-moz-handler-blocked, .notesview .notetitle .tagedit-list {
min-height: 26px;

View file

@ -1,26 +0,0 @@
<roundcube:object name="doctype" value="html5" />
<html>
<head>
<title><roundcube:object name="pagetitle" /></title>
<roundcube:include file="/includes/links.html" />
<style type="text/css" media="screen">
body.aclform {
background: #efefef;
margin: 0;
}
body.aclform .hint {
margin: 1em;
}
</style>
</head>
<body class="iframe aclform">
<roundcube:object name="folderacl" />
<roundcube:include file="/includes/footer.html" />
</body>
</html>

View file

@ -97,7 +97,7 @@
<roundcube:button command="save" type="input" class="button mainaction" label="save" id="btn-save-note" />
<div class="footerright">
<roundcube:if condition="config:kolab_bonnie_api" />
<roundcube:button command="history" type="link" label="kolab_notes.showhistory" class="btn-note-history" classAct="btn-note-history active" />
<roundcube:button command="history" type="link" label="libkolab.showhistory" class="btn-note-history" classAct="btn-note-history active" />
<roundcube:endif />
</div>
</div>
@ -146,12 +146,6 @@
</ul>
</div>
<div id="notebookeditform" class="uidialog" aria-labelledby="aria-label-editform" aria-hidden="true" role="dialog">
<h3 id="aria-label-editform" class="voice"><roundcube:label name="kolab_notes.arialabelnotebookform" /></h3>
<roundcube:container name="notebookeditform" id="notebookeditform" />
<roundcube:label name="loading" />
</div>
<script type="text/javascript">
// UI startup

View file

@ -279,6 +279,7 @@ class libkolab extends rcube_plugin
'libkolab.actionflagset',
'libkolab.actionflagclear',
'libkolab.objectchangelog',
'libkolab.objectchangelognotavailable',
'close'
);

View file

@ -27,5 +27,4 @@ $labels['actionflagset'] = 'Flag set';
$labels['actionflagclear'] = 'Flag removed';
$labels['showrevision'] = 'Show this version';
$labels['restore'] = 'Restore this version';
$labels['objectchangelognotavailable'] = 'History is not available for this message';
$labels['objectchangelognotavailable'] = 'History is not available for this object.';

View file

@ -68,6 +68,8 @@
&.folder .listname:before {
// TODO: notes folder icon, maybe need to use #notebooks parent
&:extend(.font-icon-class);
content: @fa-var-sticky-note;
}
span.handle {
@ -75,19 +77,15 @@
}
span.actions {
a {
&:extend(.font-icon-class);
a.remove {
display: none;
}
}
a.quickview:before {
content: @fa-var-eye; // TODO: disabled button state
}
a.subscribed:before {
.font-icon-regular(@fa-var-bookmark); // TODO: better icon
}
}
&.focusview {
span.actions {
a.quickview:before {
@ -104,13 +102,19 @@
width: auto;
&:before {
&:extend(.font-icon-class);
.font-icon-regular(@fa-var-bookmark); // TODO: better icon
height: auto;
color: @color-link;
margin-right: .25rem;
}
}
// span.subscribed is used on addressbooks list, a.subscribed in other places
span.subscribed:before {
&:extend(.font-icon-class);
.font-icon-regular(@fa-var-bookmark); // TODO: better icon
}
&.subscribed {
.subscribed:before {
.font-icon-solid(@fa-var-bookmark); // TODO: better icon
@ -233,6 +237,22 @@ html.touch .listing {
}
}
}
a.history:before {
content: @fa-var-history;
}
a.calendarlink:before {
.font-icon-regular(@fa-var-calendar);
}
a.appendnote:before {
.font-icon-regular(@fa-var-sticky-note);
}
a.taskaddlink:before {
content: @fa-var-tasks;
}
}
#taglist {
@ -333,9 +353,59 @@ fieldset.categories .input-group a.button.create {
display: inline;
}
a.btn-contact-history:before {
a.history {
&.disabled {
display: none;
}
&:before {
&:extend(.font-icon-class);
content: @fa-var-history;
display: inline;
float: none;
}
}
// Notes preview frame
.watermark {
& > * {
display: none;
}
&.formcontainer {
background: transparent !important;
& > * {
display: initial;
}
}
}
// Fixes TinyMCE editor height=0 issue
#noteform iframe {
min-height: 10rem;
}
#notereferences {
margin-top: .5rem;
.attachmentslist a.delete {
margin-left: .5rem;
}
}
.kolabmessagenotes {
&:before {
&:extend(.font-icon-class);
color: @color-message-information;
.font-icon-regular(@fa-var-sticky-note);
margin-right: .6rem;
width: 1em;
font-size: 1.5em !important;
line-height: 1;
}
a {
text-decoration: none;
}
}