Implement creation and deletion of notes; create icons for Larry theme

This commit is contained in:
Thomas Bruederli 2014-03-31 19:03:29 +02:00
parent aa4d0e2b94
commit 91e3227e64
6 changed files with 133 additions and 37 deletions

View file

@ -32,6 +32,7 @@ class kolab_notes extends rcube_plugin
private $ui;
private $lists;
private $folders;
private $cache = array();
/**
* Required startup method of a Roundcube plugin
@ -202,7 +203,7 @@ class kolab_notes extends rcube_plugin
}
/**
*
* Handler to retrieve note records for the given list and/or search query
*/
public function notes_fetch()
{
@ -214,7 +215,7 @@ class kolab_notes extends rcube_plugin
}
/**
*
* Convert the given note records for delivery to the client
*/
protected function notes_data($records, &$tags)
{
@ -234,7 +235,7 @@ class kolab_notes extends rcube_plugin
}
/**
*
* Read note records for the given list from the storage backend
*/
protected function list_notes($list_id, $search = null)
{
@ -261,6 +262,9 @@ class kolab_notes extends rcube_plugin
return $results;
}
/**
* Handler for delivering a full note record to the client
*/
public function note_record()
{
$data = $this->get_note(array(
@ -276,6 +280,9 @@ class kolab_notes extends rcube_plugin
$this->rc->output->command('plugin.render_note', $data);
}
/**
* Get the full note record identified by the given UID + Lolder identifier
*/
public function get_note($note)
{
if (is_array($note)) {
@ -286,6 +293,12 @@ class kolab_notes extends rcube_plugin
$uid = $note;
}
// deliver from in-memory cache
$key = $list_id . ':' . $uid;
if ($this->cache[$key]) {
return $this->cache[$key];
}
$this->_read_lists();
if ($list_id) {
if ($folder = $this->folders[$list_id]) {
@ -306,7 +319,7 @@ class kolab_notes extends rcube_plugin
}
/**
*
* Helper method to encode the given note record for use in the client
*/
private function _client_encode(&$note)
{
@ -331,6 +344,9 @@ class kolab_notes extends rcube_plugin
return $note;
}
/**
* Handler for client-initiated actions on a single note record
*/
public function note_action()
{
$action = rcube_utils::get_input_value('_do', RCUBE_INPUT_POST);
@ -347,6 +363,17 @@ class kolab_notes extends rcube_plugin
$refresh['tempid'] = $temp_id;
}
break;
case 'delete':
$uids = explode(',', $note['uid']);
foreach ($uids as $uid) {
$note['uid'] = $uid;
if (!($success = $this->delete_note($note))) {
$refresh = $this->get_note($note);
break;
}
}
break;
}
// show confirmation/error message
@ -354,7 +381,7 @@ class kolab_notes extends rcube_plugin
$this->rc->output->show_message('successfullysaved', 'confirmation');
}
else {
$this->rc->output->show_message('kolab_notes.errorsaving', 'error');
$this->rc->output->show_message('errorsaving', 'error');
}
// unlock client
@ -368,10 +395,10 @@ class kolab_notes extends rcube_plugin
/**
* Update an note record with the given data
*
* @param array Hash array with note properties
* @param array Hash array with note properties (id, list)
* @return boolean True on success, False on error
*/
private function save_note($note)
private function save_note(&$note)
{
$this->_read_lists();
@ -413,12 +440,33 @@ class kolab_notes extends rcube_plugin
else {
$note = $object;
$note['list'] = $list_id;
// TODO: cache this in memory for later read
// cache this in memory for later read
$key = $list_id . ':' . $note['uid'];
$this->cache[$key] = $note;
}
return $saved;
}
/**
* Remove a single note record from the backend
*
* @param array Hash array with note properties (id, list)
* @param boolean Remove record irreversible (mark as deleted otherwise)
* @return boolean True on success, False on error
*/
public function delete_note($note, $force = true)
{
$this->_read_lists();
$list_id = $note['list'];
if (!$list_id || !($folder = $this->folders[$list_id]))
return false;
return $folder->delete($note['uid'], $force);
}
/**
* Process the given note data (submitted by the client) before saving it
@ -431,6 +479,7 @@ class kolab_notes extends rcube_plugin
// clean up HTML content
$object['description'] = $this->_wash_html($note['description']);
$is_html = true;
// try to be smart and convert to plain-text if no real formatting is detected
if (preg_match('!<body><pre>(.*)</pre></body>!ims', $object['description'], $m)) {
@ -438,9 +487,16 @@ class kolab_notes extends rcube_plugin
// $converter = new rcube_html2text($m[1], false, true, 0);
// $object['description'] = rtrim($converter->get_text());
$object['description'] = preg_replace('!<br(\s+/)>!', "\n", $m[1]);
$is_html = false;
}
}
// Add proper HTML header, otherwise Kontact renders it as plain text
if ($is_html) {
$object['description'] = '<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd">'."\n" .
str_replace('<head>', '<head><meta name="qrichtext" content="1" />', $object['description']);
}
// copy meta data (starting with _) from old object
foreach ((array)$old as $key => $val) {
if (!isset($object[$key]) && $key[0] == '_')
@ -461,13 +517,13 @@ class kolab_notes extends rcube_plugin
. '<meta http-equiv="Content-Type" content="text/html; charset='.RCUBE_CHARSET.'" />'
. '</head><body>' . $html . '</body></html>';
// clean HTML with washhtml by Frederic Motte
// clean HTML with washtml by Frederic Motte
$wash_opts = array(
'show_washed' => false,
'allow_remote' => 1,
'charset' => RCUBE_CHARSET,
'html_elements' => array('html', 'body', 'link'),
'html_attribs' => array('rel', 'type'),
'html_elements' => array('html', 'head', 'meta', 'body', 'link'),
'html_attribs' => array('rel', 'type', 'name', 'http-equiv'),
);
// initialize HTML washer
@ -476,7 +532,7 @@ class kolab_notes extends rcube_plugin
//$washer->add_callback('form', 'rcmail_washtml_callback');
//$washer->add_callback('style', 'rcmail_washtml_callback');
// Remove non-UTF8 characters (#1487813)
// Remove non-UTF8 characters
$html = rcube_charset::clean($html);
$html = $washer->wash($html);
@ -486,6 +542,6 @@ class kolab_notes extends rcube_plugin
return $html;
}
}

View file

@ -67,7 +67,7 @@ class kolab_notes_ui
$settings['editor'] = array(
'lang' => $lang,
'editor_css' => $this->plugin->url() . $this->plugin->local_skin_path() . '/editor.css',
'editor_css' => $this->plugin->url($this->plugin->local_skin_path() . '/editor.css'),
'spellcheck' => intval($this->rc->config->get('enable_spellcheck')),
'spelldict' => intval($this->rc->config->get('spellcheck_dictionary'))
);

View file

@ -15,3 +15,4 @@ $labels['changed'] = 'Last Modified';
$labels['savingdata'] = 'Saving data...';
$labels['recordnotfound'] = 'Record not found';
$labels['entertitle'] = 'Please enter a title for this note!';
$labels['deletenotesconfirm'] = 'Do you really want to delete the selected notes?';

View file

@ -43,11 +43,11 @@ function rcube_kolab_notes_ui(settings)
{
// register button commands
rcmail.register_command('createnote', function(){ edit_note(null, 'new'); }, false);
rcmail.register_command('list-create', function(){ list_edit_dialog(null); }, true);
rcmail.register_command('list-create', function(){ list_edit_dialog(null); }, false);
rcmail.register_command('list-edit', function(){ list_edit_dialog(me.selected_list); }, false);
rcmail.register_command('list-remove', function(){ list_remove(me.selected_list); }, false);
rcmail.register_command('save', save_note, true);
rcmail.register_command('delete', delete_note, true);
rcmail.register_command('delete', delete_note, false);
rcmail.register_command('search', quicksearch, true);
rcmail.register_command('reset-search', reset_search, true);
@ -87,6 +87,8 @@ function rcube_kolab_notes_ui(settings)
else {
reset_view();
}
rcmail.enable_command('delete', me.notebooks[me.selected_list] && me.notebooks[me.selected_list].editable && list.selection.length > 0);
})
.init();
}
@ -293,7 +295,7 @@ function rcube_kolab_notes_ui(settings)
tr = noteslist.rows[id].obj;
note = notesdata[id];
match = note.categories && note.categories.length;
for (var i=0; match && i < tagsfilter.length; i++) {
for (var i=0; match && note && i < tagsfilter.length; i++) {
if ($.inArray(tagsfilter[i], note.categories) < 0)
match = false;
}
@ -306,7 +308,8 @@ function rcube_kolab_notes_ui(settings)
}
if (me.selected_note && me.selected_note.uid == note.uid && !match) {
reset_view();
noteslist.clear_selection();
// reset_view();
}
}
}
@ -389,7 +392,8 @@ function rcube_kolab_notes_ui(settings)
.on('click', function(){ $('.tagline .placeholder').hide(); });
me.selected_note = data;
rcmail.enable_command('save', 'delete', list.editable && !data.readonly);
me.selected_note.id = rcmail.html_identifier_encode(data.uid);
rcmail.enable_command('save', list.editable && !data.readonly);
var html, node, editor = tinyMCE.get('notecontent');
if (editor) {
@ -495,12 +499,25 @@ function rcube_kolab_notes_ui(settings)
function update_note(data)
{
data.id = rcmail.html_identifier_encode(data.uid);
var row, is_new = notesdata[data.id] == undefined
notesdata[data.id] = data;
render_note(data);
// add list item on top
if (is_new) {
noteslist.insert_row({
id: 'rcmrow' + data.id,
cols: [
{ className:'title', innerHTML:Q(data.title) },
{ className:'date', innerHTML:Q(data.changed || '') }
]
}, true);
noteslist.select(data.id);
}
// update list item
var row = noteslist.rows[data.id];
if (row) {
else if (row = noteslist.rows[data.id]) {
$('.title', row.obj).html(Q(data.title));
$('.date', row.obj).html(Q(data.changed || ''));
// TODO: move to top
@ -515,11 +532,10 @@ function rcube_kolab_notes_ui(settings)
function reset_view()
{
me.selected_note = null;
noteslist.clear_selection();
$('.notetitle', rcmail.gui_objects.noteviewtitle).val('');
$('.tagline, .dates', rcmail.gui_objects.noteviewtitle).hide();
$(rcmail.gui_objects.noteseditform).hide();
rcmail.enable_command('save', 'delete', false);
rcmail.enable_command('save', false);
}
/**
@ -564,12 +580,29 @@ function rcube_kolab_notes_ui(settings)
function delete_note()
{
if (!me.selected_note) {
if (!noteslist.selection.length) {
return false;
}
alert(me.selected_note.title)
reset_view();
if (confirm(rcmail.gettext('deletenotesconfirm','kolab_notes'))) {
var rec, id, uids = [];
for (var i=0; i < noteslist.selection.length; i++) {
id = noteslist.selection[i];
rec = notesdata[id];
if (rec) {
noteslist.remove_row(id);
uids.push(rec.uid);
delete notesdata[id];
}
}
saving_lock = rcmail.set_busy(true, 'kolab_notes.savingdata');
rcmail.http_post('action', { _data: { uid: uids.join(','), list: me.selected_list }, _do: 'delete' }, true);
reset_view();
update_tagcloud();
}
}
}

View file

@ -10,6 +10,18 @@
* See http://creativecommons.org/licenses/by-sa/3.0/ for details.
*/
#taskbar a.button-notes span.button-inner {
background-image: url('sprites.png');
background-position: 0 0;
}
#taskbar a.button-notes:hover span.button-inner,
#taskbar a.button-notes.button-selected span.button-inner {
background-image: url('sprites.png');
background-position: 0 -26px;
}
.notesview #sidebar {
position: absolute;
top: 42px;
@ -28,15 +40,8 @@
}
.notesview #notestoolbar a.button.createnote {
}
.notesview #taskbar a.button-notes span.button-inner {
}
.notesview #taskbar a.button-notes.button-selected span.button-inner {
background-image: url('sprites.png');
background-position: center -54px;
}
.notesview #quicksearchbar {
@ -146,7 +151,7 @@
}
.notesview #notedetailstitle {
height: 68px;
height: auto;
}
.notesview #notedetailstitle .tagedit-list,
@ -180,7 +185,8 @@
}
.notesview #notedetailstitle .dates {
margin-top: 0;
margin-top: 4px;
margin-bottom: 4px;
}
.notesview #notedetailstitle .tagline {

Binary file not shown.

After

Width:  |  Height:  |  Size: 2 KiB