plugins/calendar plugins/kolab_notes
Thomas Brüderli
bruederli at kolabsys.com
Sat Apr 12 21:44:02 CEST 2014
plugins/calendar/calendar.php | 1
plugins/kolab_notes/kolab_notes.php | 62 ++++++++++++-
plugins/kolab_notes/kolab_notes_ui.php | 56 ++++++++----
plugins/kolab_notes/localization/en_US.inc | 2
plugins/kolab_notes/notes.js | 134 ++++++++++++++++++++++++++---
plugins/kolab_notes/skins/larry/notes.css | 37 +++++++-
6 files changed, 257 insertions(+), 35 deletions(-)
New commits:
commit 49f9771ed437488aab2b21f9a7482d8587af57bd
Author: Thomas Bruederli <bruederli at kolabsys.com>
Date: Sat Apr 12 21:43:44 2014 +0200
Add function to create a note from mail view with a link to the selected message (link not saved yet)
diff --git a/plugins/calendar/calendar.php b/plugins/calendar/calendar.php
index 2857ee3..2666d3c 100644
--- a/plugins/calendar/calendar.php
+++ b/plugins/calendar/calendar.php
@@ -2168,7 +2168,6 @@ class calendar extends rcube_plugin
foreach ($p['messages'] as $i => $header) {
$part = new StdClass;
$part->mimetype = $header->ctype;
- $part->filename = '';
if ($this->is_vcalendar($part)) {
$header->list_flags['attachmentClass'] = 'ical';
}
diff --git a/plugins/kolab_notes/kolab_notes.php b/plugins/kolab_notes/kolab_notes.php
index cdf61bd..3be3ab9 100644
--- a/plugins/kolab_notes/kolab_notes.php
+++ b/plugins/kolab_notes/kolab_notes.php
@@ -64,7 +64,7 @@ class kolab_notes extends rcube_plugin
}
// load localizations
- $this->add_texts('localization/', $args['task'] == 'notes' && !$args['action']);
+ $this->add_texts('localization/', $args['task'] == 'notes' && (!$args['action'] || $args['action'] == 'dialog-ui'));
$this->rc->load_language($_SESSION['language'], array('notes.notes' => $this->gettext('navtitle'))); // add label for task title
if ($args['task'] == 'notes') {
@@ -74,12 +74,31 @@ class kolab_notes extends rcube_plugin
$this->register_action('get', array($this, 'note_record'));
$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'));
}
else if ($args['task'] == 'mail') {
$this->add_hook('message_compose', array($this, 'mail_message_compose'));
+ $this->add_hook('template_object_messagebody', array($this, 'mail_messagebody_html'));
+
+ // add 'Append note' item to message menu
+ if ($this->api->output->type == 'html' && $_REQUEST['_rel'] != 'note') {
+ $this->api->add_content(html::tag('li', null,
+ $this->api->output->button(array(
+ 'command' => 'append-kolab-note',
+ 'label' => 'kolab_notes.appendnote',
+ 'type' => 'link',
+ 'classact' => 'icon appendnote active',
+ 'class' => 'icon appendnote',
+ 'innerclass' => 'icon note',
+ ))),
+ 'messagemenu');
+
+ $this->api->output->add_label('kolab_notes.appendnote', 'save', 'cancel');
+ $this->include_script('notes_mail.js');
+ }
}
- if (!$this->rc->output->ajax_call && (!$this->rc->output->env['framed'] || $args['action'] == 'folder-acl')) {
+ if (!$this->rc->output->ajax_call && (!$this->rc->output->env['framed'] || in_array($args['action'], array('folder-acl','dialog-ui')))) {
require_once($this->home . '/kolab_notes_ui.php');
$this->ui = new kolab_notes_ui($this);
$this->ui->init();
@@ -208,6 +227,32 @@ class kolab_notes extends rcube_plugin
}
/**
+ * Deliver a rediced UI for inline (dialog)
+ */
+ public function dialog_view()
+ {
+ // resolve message reference
+ if ($msgref = rcube_utils::get_input_value('_msg', RCUBE_INPUT_GPC, true)) {
+ $storage = $this->rc->get_storage();
+ $storage->set_options(array('all_headers' => true));
+ list($uid, $folder) = explode('-', $msgref, 2);
+ if ($message = $storage->get_message_headers($msgref)) {
+ $this->rc->output->set_env('kolab_notes_template', array(
+ 'title' => $message->get('subject'),
+ 'links' => array(array(
+ 'uri' => $this->get_message_uri($message, $folder),
+ 'message_id' => $message->get('message-id'),
+ 'subject' => $message->get('subject'),
+ )),
+ ));
+ }
+ }
+
+ $this->ui->init_templates();
+ $this->rc->output->send('kolab_notes.dialogview');
+ }
+
+ /**
* Handler to retrieve note records for the given list and/or search query
*/
public function notes_fetch()
@@ -635,6 +680,14 @@ class kolab_notes extends rcube_plugin
}
/**
+ * Handler for 'messagebody_html' hooks
+ */
+ public function mail_messagebody_html($args)
+ {
+
+ }
+
+ /**
* Determine whether the given note is HTML formatted
*/
private function is_html($note)
@@ -682,6 +735,11 @@ class kolab_notes extends rcube_plugin
return $message->getMessage();
}
+ private function get_message_uri($headers, $folder)
+ {
+ return sprintf('imap://%s/%s#%s', $headers->folder ?: $folder, $headers->uid, urlencode($headers->messageID));
+ }
+
/**
* Process the given note data (submitted by the client) before saving it
*/
diff --git a/plugins/kolab_notes/kolab_notes_ui.php b/plugins/kolab_notes/kolab_notes_ui.php
index ce8bb97..bbb3ca7 100644
--- a/plugins/kolab_notes/kolab_notes_ui.php
+++ b/plugins/kolab_notes/kolab_notes_ui.php
@@ -50,6 +50,7 @@ class kolab_notes_ui
$this->plugin->register_handler('plugin.editform', array($this, 'editform'));
$this->plugin->register_handler('plugin.notetitle', array($this, 'notetitle'));
$this->plugin->register_handler('plugin.detailview', array($this, 'detailview'));
+ $this->plugin->register_handler('plugin.attachments_list', array($this, 'attachments_list'));
$this->rc->output->include_script('list.js');
$this->rc->output->include_script('treelist.js');
@@ -64,8 +65,11 @@ class kolab_notes_ui
'print_template' => $this->rc->url('print'),
);
- if (!empty($_REQUEST['_list'])) {
- $settings['selected_list'] = rcube_utils::get_input_value('_list', RCUBE_INPUT_GPC);
+ if ($list = rcube_utils::get_input_value('_list', RCUBE_INPUT_GPC)) {
+ $settings['selected_list'] = $list;
+ }
+ if ($uid = rcube_utils::get_input_value('_id', RCUBE_INPUT_GPC)) {
+ $settings['selected_uid'] = $uid;
}
// TinyMCE uses two-letter lang codes, with exception of Chinese
@@ -92,6 +96,10 @@ class kolab_notes_ui
{
$attrib += array('id' => 'rcmkolabnotebooks');
+ if ($attrib['type'] == 'select') {
+ $select = new html_select($attrib);
+ }
+
$jsenv = array();
$items = '';
foreach ($this->plugin->get_lists() as $prop) {
@@ -102,26 +110,33 @@ class kolab_notes_ui
if (!$prop['virtual'])
$jsenv[$id] = $prop;
- $html_id = rcube_utils::html_identifier($id);
- $title = $prop['name'] != $prop['listname'] ? html_entity_decode($prop['name'], ENT_COMPAT, RCMAIL_CHARSET) : '';
-
- if ($prop['virtual'])
- $class .= ' virtual';
- else if (!$prop['editable'])
- $class .= ' readonly';
- if ($prop['class_name'])
- $class .= ' '.$prop['class_name'];
-
- $items .= html::tag('li', array('id' => 'rcmliknb' . $html_id, 'class' => trim($class)),
- html::span(array('class' => 'listname', 'title' => $title), $prop['listname']) .
- html::span(array('class' => 'count'), '')
- );
+ if ($attrib['type'] == 'select') {
+ if ($prop['editable']) {
+ $select->add($prop['name'], $prop['id']);
+ }
+ }
+ else {
+ $html_id = rcube_utils::html_identifier($id);
+ $title = $prop['name'] != $prop['listname'] ? html_entity_decode($prop['name'], ENT_COMPAT, RCMAIL_CHARSET) : '';
+
+ if ($prop['virtual'])
+ $class .= ' virtual';
+ else if (!$prop['editable'])
+ $class .= ' readonly';
+ if ($prop['class_name'])
+ $class .= ' '.$prop['class_name'];
+
+ $items .= html::tag('li', array('id' => 'rcmliknb' . $html_id, 'class' => trim($class)),
+ html::span(array('class' => 'listname', 'title' => $title), $prop['listname']) .
+ html::span(array('class' => 'count'), '')
+ );
+ }
}
$this->rc->output->set_env('kolab_notebooks', $jsenv);
$this->rc->output->add_gui_object('notebooks', $attrib['id']);
- return html::tag('ul', $attrib, $items, html::$common_attrib);
+ return $attrib['type'] == 'select' ? $select->show() : html::tag('ul', $attrib, $items, html::$common_attrib);
}
public function listing($attrib)
@@ -175,6 +190,13 @@ class kolab_notes_ui
return html::div($attrib, $html);
}
+ public function attachments_list($attrib)
+ {
+ $attrib += array('id' => 'rcmkolabnotesattachmentslist');
+ $this->rc->output->add_gui_object('notesattachmentslist', $attrib['id']);
+ return html::tag('ul', $attrib, '', html::$common_attrib);
+ }
+
/**
* Render edit for notes lists (folders)
*/
diff --git a/plugins/kolab_notes/localization/en_US.inc b/plugins/kolab_notes/localization/en_US.inc
index 66545c0..ccb737d 100644
--- a/plugins/kolab_notes/localization/en_US.inc
+++ b/plugins/kolab_notes/localization/en_US.inc
@@ -24,6 +24,8 @@ $labels['tabsharing'] = 'Sharing';
$labels['discard'] = 'Discard';
$labels['abort'] = 'Abort';
$labels['unsavedchanges'] = 'Unsaved Changes!';
+$labels['appendnote'] = 'Add a note';
+$labels['savein'] = 'Save in';
$labels['savingdata'] = 'Saving data...';
$labels['recordnotfound'] = 'Record not found';
diff --git a/plugins/kolab_notes/notes.js b/plugins/kolab_notes/notes.js
index ef8262c..c05be5a 100644
--- a/plugins/kolab_notes/notes.js
+++ b/plugins/kolab_notes/notes.js
@@ -222,7 +222,64 @@ function rcube_kolab_notes_ui(settings)
return false;
});
- // initialize tinyMCE editor
+ init_editor();
+
+ if (settings.selected_list) {
+ notebookslist.select(settings.selected_list)
+ }
+ }
+ this.init = init;
+
+ /**
+ *
+ */
+ function init_dialog()
+ {
+ rcmail.register_command('save', save_note, true);
+ rcmail.addEventListener('plugin.update_note', function(data){
+ data.id = rcmail.html_identifier_encode(data.uid);
+ notesdata[data.id] = data;
+ render_note(data);
+ });
+ rcmail.addEventListener('plugin.unlock_saving', function(){
+ if (saving_lock) {
+ rcmail.set_busy(false, null, saving_lock);
+ }
+ if (rcmail.gui_objects.noteseditform) {
+ rcmail.lock_form(rcmail.gui_objects.noteseditform, false);
+ }
+ });
+
+ var id;
+ for (id in me.notebooks) {
+ if (me.notebooks[id].editable) {
+ me.selected_list = id;
+ break;
+ }
+ }
+
+ init_editor();
+ setTimeout(function(){
+ me.selected_note = $.extend({
+ list: me.selected_list,
+ uid: null,
+ title: rcmail.gettext('newnote','kolab_notes'),
+ description: '',
+ categories: [],
+ created: rcmail.gettext('now', 'kolab_notes'),
+ changed: rcmail.gettext('now', 'kolab_notes')
+ }, rcmail.env.kolab_notes_template || {});
+ render_note(me.selected_note);
+
+ }, 100);
+ }
+ this.init_dialog = init_dialog;
+
+ /**
+ * initialize tinyMCE editor
+ */
+ function init_editor()
+ {
var editor_conf = {
mode: 'textareas',
elements: 'notecontent',
@@ -260,11 +317,21 @@ function rcube_kolab_notes_ui(settings)
tinyMCE.init(editor_conf);
- if (settings.selected_list) {
- notebookslist.select(settings.selected_list)
- }
+ // register click handler for message links
+ $(rcmail.gui_objects.notesattachmentslist).on('click', 'li a.messagelink', function(){
+ var uri = $(this).attr('rel');
+ if (uri && uri.match(/imap:\/\/.+/)) {
+ var path = uri.split('#')[0].substr(7).split('/'),
+ uid = path.pop(),
+ folder = path.join('/');
+ if (folder && uid) {
+ rcmail.open_window(rcmail.url('mail/show', { _mbox: folder, _uid: uid, _rel: 'note' }));
+ }
+ }
+
+ return false;
+ });
}
- this.init = init;
/**
* Quote HTML entities
@@ -288,7 +355,8 @@ function rcube_kolab_notes_ui(settings)
function edit_note(uid, action)
{
if (!uid) {
- noteslist.clear_selection();
+ if (noteslist)
+ noteslist.clear_selection();
me.selected_note = {
list: me.selected_list,
uid: null,
@@ -554,6 +622,7 @@ function rcube_kolab_notes_ui(settings)
noteslist.clear(true);
notesdata = {};
tagsfilter = [];
+ update_state();
}
function filter_notes()
@@ -625,9 +694,9 @@ function rcube_kolab_notes_ui(settings)
if (data.data.length == 1) {
noteslist.select(data.data[0].id);
}
- else if (settings.selected_id) {
- noteslist.select(settings.selected_id);
- delete settings.selected_id;
+ else if (settings.selected_uid) {
+ noteslist.select(rcmail.html_identifier_encode(settings.selected_uid));
+ delete settings.selected_uid;
}
else if (me.selected_note && notesdata[me.selected_note.id]) {
noteslist.select(me.selected_note.id);
@@ -648,7 +717,8 @@ function rcube_kolab_notes_ui(settings)
var list = me.notebooks[data.list] || me.notebooks[me.selected_list];
content = $('#notecontent').val(data.description),
- readonly = data.readonly || !list.editable;
+ readonly = data.readonly || !list.editable,
+ attachmentslist = $(rcmail.gui_objects.notesattachmentslist).html('');
$('.notetitle', rcmail.gui_objects.noteviewtitle).val(data.title).prop('disabled', readonly);
$('.dates .notecreated', rcmail.gui_objects.noteviewtitle).html(Q(data.created || ''));
$('.dates .notechanged', rcmail.gui_objects.noteviewtitle).html(Q(data.changed || ''));
@@ -679,7 +749,21 @@ function rcube_kolab_notes_ui(settings)
checkNewEntriesCaseSensitive: false,
autocompleteOptions: { source: tags, minLength: 0, noCheck: true },
texts: { removeLinkTitle: rcmail.gettext('removetag', 'kolab_notes') }
- })
+ });
+
+ if (data.links) {
+ $.each(data.links, function(i, link){
+ $('<li>').addClass('link')
+ .addClass('message eml')
+ .append($('<a>')
+ .attr('href', '#show')
+ .attr('rel', link.uri)
+ .addClass('messagelink')
+ .html(Q(link.subject || link.message_id || link.uri))
+ )
+ .appendTo(attachmentslist);
+ });
+ }
if (!readonly) {
$('.tagedit-list', rcmail.gui_objects.noteviewtitle)
@@ -922,6 +1006,10 @@ function rcube_kolab_notes_ui(settings)
var savedata = get_save_data();
+ // copy links as they're yet immutable
+ if (me.selected_note.links)
+ savedata.links = me.selected_note.links;
+
// do some input validation
if (savedata.title == '') {
alert(rcmail.gettext('entertitle', 'kolab_notes'));
@@ -1101,6 +1189,23 @@ function rcube_kolab_notes_ui(settings)
}
}
+ /**
+ * update browser location to remember current view
+ */
+ function update_state()
+ {
+ var query = { _list: me.selected_list }
+
+ if (settings.selected_uid) {
+ query._id = settings.selected_uid;
+ }
+
+ if (window.history.replaceState) {
+ window.history.replaceState({}, document.title, rcmail.url('', query));
+ }
+ }
+
+
/* Helper functions for drag & drop functionality of tags */
function tag_draggable_helper()
@@ -1200,7 +1305,10 @@ jQuery.fn.sortElements = (function(){
/* notes plugin UI initialization */
var kolabnotes;
window.rcmail && rcmail.addEventListener('init', function(evt) {
- kolabnotes = new rcube_kolab_notes_ui(rcmail.env.kolab_notes_settings);
- kolabnotes.init();
+ kolabnotes = new rcube_kolab_notes_ui(rcmail.env.kolab_notes_settings);
+ if (rcmail.env.action == 'dialog-ui')
+ kolabnotes.init_dialog();
+ else
+ kolabnotes.init();
});
diff --git a/plugins/kolab_notes/skins/larry/notes.css b/plugins/kolab_notes/skins/larry/notes.css
index 97a7421..96d283b 100644
--- a/plugins/kolab_notes/skins/larry/notes.css
+++ b/plugins/kolab_notes/skins/larry/notes.css
@@ -114,6 +114,10 @@
bottom: 0px;
}
+.notesdialog #notedetailsbox {
+ left: 0;
+}
+
.notesview #notedetailsbox .formbuttons {
position: absolute;
bottom: 0;
@@ -133,6 +137,10 @@
width: 100%;
}
+.notesdialog #noteform {
+ bottom: 30px;
+}
+
.notesview #notedetails {
padding: 8px;
-webkit-box-sizing: border-box;
@@ -207,14 +215,16 @@
}
.notesview #notedetailstitle .dates,
-.notesview #notedetailstitle .tagline {
+.notesview #notedetailstitle .tagline,
+.notesdialog .notebookselect label {
color: #999;
font-weight: normal;
font-size: 0.9em;
margin-top: 6px;
}
-.notesview #notedetailstitle .dates {
+.notesview #notedetailstitle .dates,
+.notesview #notedetailstitle .notebookselect {
margin-top: 4px;
margin-bottom: 4px;
}
@@ -252,6 +262,16 @@
color: #777;
}
+.notesview #notereferences {
+ position: absolute;
+ left: 0;
+ right: 0;
+ bottom: 0;
+ height: 27px;
+ background: #fff;
+ padding-left: 10px;
+}
+
.notesview #notebooks li {
margin: 0;
height: 20px;
@@ -336,4 +356,17 @@
.notesview .uidialog .propform #noteslist-name {
width: 20em;
+}
+
+.notesdialog #notesdialogheader {
+ height: auto;
+}
+
+#kolabnotesinlinegui {
+ border: 0;
+ padding: 0;
+ -webkit-box-sizing: border-box;
+ -moz-box-sizing: border-box;
+ -ms-box-sizing: border-box;
+ box-sizing: border-box;
}
\ No newline at end of file
More information about the commits
mailing list