Implement creation and deletion of notes; create icons for Larry theme
This commit is contained in:
parent
aa4d0e2b94
commit
91e3227e64
6 changed files with 133 additions and 37 deletions
|
@ -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;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -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'))
|
||||
);
|
||||
|
|
|
@ -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?';
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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 {
|
||||
|
|
BIN
plugins/kolab_notes/skins/larry/sprites.png
Normal file
BIN
plugins/kolab_notes/skins/larry/sprites.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 2 KiB |
Loading…
Add table
Reference in a new issue