Implement notes folder management, including ACL settings
This commit is contained in:
parent
6b22e05444
commit
684964282a
8 changed files with 466 additions and 8 deletions
|
@ -71,14 +71,14 @@ class kolab_notes extends rcube_plugin
|
|||
$this->register_action('fetch', array($this, 'notes_fetch'));
|
||||
$this->register_action('get', array($this, 'note_record'));
|
||||
$this->register_action('action', array($this, 'note_action'));
|
||||
$this->register_action('list', array($this, 'list_action'));
|
||||
}
|
||||
|
||||
if (!$this->rc->output->ajax_call && !$this->rc->output->env['framed']) {
|
||||
if (!$this->rc->output->ajax_call && (!$this->rc->output->env['framed'] || $args['action'] == 'folder-acl')) {
|
||||
require_once($this->home . '/kolab_notes_ui.php');
|
||||
$this->ui = new kolab_notes_ui($this);
|
||||
$this->ui->init();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -516,6 +516,89 @@ class kolab_notes extends rcube_plugin
|
|||
return $folder->delete($note['uid'], $force);
|
||||
}
|
||||
|
||||
/**
|
||||
* Handler for client requests to list (aka folder) actions
|
||||
*/
|
||||
public function list_action()
|
||||
{
|
||||
$action = rcube_utils::get_input_value('_do', RCUBE_INPUT_GPC);
|
||||
$list = rcube_utils::get_input_value('_list', RCUBE_INPUT_GPC, true);
|
||||
$success = $update_cmd = false;
|
||||
|
||||
switch ($action) {
|
||||
case 'form-new':
|
||||
case 'form-edit':
|
||||
$this->_read_lists();
|
||||
echo $this->ui->list_editform($action, $this->lists[$list['id']], $this->folders[$list['id']]);
|
||||
exit;
|
||||
|
||||
case 'new':
|
||||
$list['type'] = 'note';
|
||||
$list['subscribed'] = true;
|
||||
$folder = kolab_storage::folder_update($list);
|
||||
|
||||
if ($folder === false) {
|
||||
$save_error = $this->gettext(kolab_storage::$last_error);
|
||||
}
|
||||
else {
|
||||
$success = true;
|
||||
$update_cmd = 'plugin.update_list';
|
||||
$list['id'] = kolab_storage::folder_id($folder);
|
||||
$list['_reload'] = true;
|
||||
}
|
||||
break;
|
||||
|
||||
case 'edit':
|
||||
$this->_read_lists();
|
||||
$oldparent = $this->lists[$list['id']]['parentfolder'];
|
||||
$newfolder = kolab_storage::folder_update($list);
|
||||
|
||||
if ($newfolder === false) {
|
||||
$save_error = $this->gettext(kolab_storage::$last_error);
|
||||
}
|
||||
else {
|
||||
$success = true;
|
||||
$update_cmd = 'plugin.update_list';
|
||||
$list['newid'] = kolab_storage::folder_id($newfolder);
|
||||
$list['_reload'] = $list['parent'] != $oldparent;
|
||||
|
||||
// compose the new display name
|
||||
$delim = $this->rc->get_storage()->get_hierarchy_delimiter();
|
||||
$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(' ', count($path_imap)) . '» ' . $list['editname'];
|
||||
}
|
||||
break;
|
||||
|
||||
case 'delete':
|
||||
$this->_read_lists();
|
||||
$folder = $this->folders[$list['id']];
|
||||
if ($folder && kolab_storage::folder_delete($folder->name)) {
|
||||
$success = true;
|
||||
$update_cmd = 'plugin.destroy_list';
|
||||
}
|
||||
else {
|
||||
$save_error = $this->gettext(kolab_storage::$last_error);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
$this->rc->output->command('plugin.unlock_saving');
|
||||
|
||||
if ($success) {
|
||||
$this->rc->output->show_message('successfullysaved', 'confirmation');
|
||||
|
||||
if ($update_cmd) {
|
||||
$this->rc->output->command($update_cmd, $list);
|
||||
}
|
||||
}
|
||||
else {
|
||||
$error_msg = $this->gettext('errorsaving') . ($save_error ? ': ' . $save_error :'');
|
||||
$this->rc->output->show_message($error_msg, 'error');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine whether the given note is HTML formatted
|
||||
*/
|
||||
|
|
|
@ -31,6 +31,8 @@ class kolab_notes_ui
|
|||
|
||||
$this->plugin->include_stylesheet($this->plugin->local_skin_path() . '/notes.css');
|
||||
|
||||
$this->plugin->register_action('folder-acl', array($this, 'folder_acl'));
|
||||
|
||||
$this->ready = true;
|
||||
}
|
||||
|
||||
|
@ -58,6 +60,10 @@ class kolab_notes_ui
|
|||
// TODO: load config options and user prefs relevant for the UI
|
||||
$settings = array();
|
||||
|
||||
if (!empty($_REQUEST['_list'])) {
|
||||
$settings['selected_list'] = rcube_utils::get_input_value('_list', RCUBE_INPUT_GPC);
|
||||
}
|
||||
|
||||
// TinyMCE uses two-letter lang codes, with exception of Chinese
|
||||
$lang = strtolower($_SESSION['language']);
|
||||
$lang = strpos($lang, 'zh_') === 0 ? str_replace('_', '-', $lang) : substr($lang, 0, 2);
|
||||
|
@ -74,6 +80,8 @@ class kolab_notes_ui
|
|||
);
|
||||
|
||||
$this->rc->output->set_env('kolab_notes_settings', $settings);
|
||||
|
||||
$this->rc->output->add_label('save','cancel');
|
||||
}
|
||||
|
||||
public function folders($attrib)
|
||||
|
@ -162,5 +170,138 @@ class kolab_notes_ui
|
|||
|
||||
return html::div($attrib, $html);
|
||||
}
|
||||
|
||||
/**
|
||||
* Render edit for notes lists (folders)
|
||||
*/
|
||||
public function list_editform($action, $list, $folder)
|
||||
{
|
||||
if (is_object($folder)) {
|
||||
$folder_name = $folder->name; // UTF7
|
||||
}
|
||||
else {
|
||||
$folder_name = '';
|
||||
}
|
||||
|
||||
$hidden_fields[] = array('name' => 'oldname', 'value' => $folder_name);
|
||||
|
||||
$storage = $this->rc->get_storage();
|
||||
$delim = $storage->get_hierarchy_delimiter();
|
||||
$form = array();
|
||||
|
||||
if (strlen($folder_name)) {
|
||||
$options = $storage->folder_info($folder_name);
|
||||
|
||||
$path_imap = explode($delim, $folder_name);
|
||||
array_pop($path_imap); // pop off name part
|
||||
$path_imap = implode($path_imap, $delim);
|
||||
}
|
||||
else {
|
||||
$path_imap = '';
|
||||
$options = array();
|
||||
}
|
||||
|
||||
// General tab
|
||||
$form['properties'] = array(
|
||||
'name' => $this->rc->gettext('properties'),
|
||||
'fields' => array(),
|
||||
);
|
||||
|
||||
// folder name (default field)
|
||||
$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']))),
|
||||
'id' => 'folder-name',
|
||||
);
|
||||
|
||||
// prevent user from moving folder
|
||||
if (!empty($options) && ($options['norename'] || $options['protected'])) {
|
||||
$hidden_fields[] = array('name' => 'parent', 'value' => $path_imap);
|
||||
}
|
||||
else {
|
||||
$select = kolab_storage::folder_selector('note', array('name' => 'parent'), $folder_name);
|
||||
$form['properties']['fields']['path'] = array(
|
||||
'label' => $this->plugin->gettext('parentfolder'),
|
||||
'value' => $select->show(strlen($folder_name) ? $path_imap : ''),
|
||||
);
|
||||
}
|
||||
|
||||
// add folder ACL tab
|
||||
if ($action != 'form-new') {
|
||||
$form['sharing'] = array(
|
||||
'name' => 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'),
|
||||
'')
|
||||
);
|
||||
}
|
||||
|
||||
$form_html = '';
|
||||
if (is_array($hidden_fields)) {
|
||||
foreach ($hidden_fields as $field) {
|
||||
$hiddenfield = new html_hiddenfield($field);
|
||||
$form_html .= $hiddenfield->show() . "\n";
|
||||
}
|
||||
}
|
||||
|
||||
// create form output
|
||||
foreach ($form as $tab) {
|
||||
if (is_array($tab['fields']) && empty($tab['content'])) {
|
||||
$table = new html_table(array('cols' => 2));
|
||||
foreach ($tab['fields'] as $col => $colprop) {
|
||||
$colprop['id'] = '_'.$col;
|
||||
$label = !empty($colprop['label']) ? $colprop['label'] : $this->plugin->gettext($col);
|
||||
|
||||
$table->add('title', html::label($colprop['id'], Q($label)));
|
||||
$table->add(null, $colprop['value']);
|
||||
}
|
||||
$content = $table->show();
|
||||
}
|
||||
else {
|
||||
$content = $tab['content'];
|
||||
}
|
||||
|
||||
if (!empty($content)) {
|
||||
$form_html .= html::tag('fieldset', null, html::tag('legend', null, Q($tab['name'])) . $content) . "\n";
|
||||
}
|
||||
}
|
||||
|
||||
return html::tag('form', 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
|
||||
*/
|
||||
public function folder_acl_form()
|
||||
{
|
||||
$folder = rcube_utils::get_input_value('_folder', RCUBE_INPUT_GPC);
|
||||
|
||||
if (strlen($folder)) {
|
||||
$storage = $this->rc->get_storage();
|
||||
$options = $storage->folder_info($folder);
|
||||
|
||||
// get sharing UI from acl plugin
|
||||
$acl = $this->rc->plugins->exec_hook('folder_form',
|
||||
array('form' => array(), 'options' => $options, 'name' => $folder));
|
||||
}
|
||||
|
||||
return $acl['form']['sharing']['content'] ?: html::div('hint', $this->plugin->gettext('aclnorights'));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -12,8 +12,16 @@ $labels['removetag'] = 'Remove tag';
|
|||
$labels['created'] = 'Created';
|
||||
$labels['changed'] = 'Last Modified';
|
||||
$labels['now'] = 'Now';
|
||||
$labels['createlist'] = 'New Notebook';
|
||||
$labels['editlist'] = 'Edit Notebook';
|
||||
$labels['listname'] = 'Name';
|
||||
$labels['tabsharing'] = 'Sharing';
|
||||
|
||||
$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?';
|
||||
$labels['deletenotebookconfirm'] = 'Do you really want to delete this notebook with all its notes? This action cannot be undone.';
|
||||
$labels['invalidlistproperties'] = 'Invalid notebook properties! Please set a valid name.';
|
||||
$labels['aclnorights'] = 'You do not have administrator rights for this notebook.';
|
||||
|
||||
|
|
|
@ -36,8 +36,8 @@ function rcube_kolab_notes_ui(settings)
|
|||
var me = this;
|
||||
|
||||
/* public members */
|
||||
this.selected_list;
|
||||
this.selected_note;
|
||||
this.selected_list = settings.selected_list;
|
||||
this.selected_note = settings.selected_id;
|
||||
this.notebooks = rcmail.env.kolab_notebooks || {};
|
||||
|
||||
/**
|
||||
|
@ -47,7 +47,7 @@ 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); }, 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);
|
||||
rcmail.register_command('list-remove', function(){ list_remove(me.selected_list); }, false);
|
||||
rcmail.register_command('save', save_note, true);
|
||||
|
@ -59,6 +59,8 @@ function rcube_kolab_notes_ui(settings)
|
|||
rcmail.addEventListener('plugin.data_ready', data_ready);
|
||||
rcmail.addEventListener('plugin.render_note', render_note);
|
||||
rcmail.addEventListener('plugin.update_note', update_note);
|
||||
rcmail.addEventListener('plugin.update_list', list_update);
|
||||
rcmail.addEventListener('plugin.destroy_list', list_destroy);
|
||||
rcmail.addEventListener('plugin.unlock_saving', function(){
|
||||
if (saving_lock) {
|
||||
rcmail.set_busy(false, null, saving_lock);
|
||||
|
@ -80,7 +82,8 @@ function rcube_kolab_notes_ui(settings)
|
|||
id_prefix: 'rcmliknb',
|
||||
selectable: true,
|
||||
check_droptarget: function(node) {
|
||||
return !node.virtual && node.id != me.selected_list;
|
||||
var list = me.notebooks[node.id];
|
||||
return !node.virtual && list.editable && node.id != me.selected_list;
|
||||
}
|
||||
});
|
||||
notebookslist.addEventListener('select', function(node) {
|
||||
|
@ -264,15 +267,156 @@ function rcube_kolab_notes_ui(settings)
|
|||
*/
|
||||
function list_edit_dialog(id)
|
||||
{
|
||||
|
||||
if (!rcmail.gui_containers.notebookeditform) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// 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 };
|
||||
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) })
|
||||
.dialog('option', 'position', ['center', 'center']); // only works in a separate call (!?)
|
||||
|
||||
name = $('#noteslist-name').prop('disabled', !list.editable).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;
|
||||
|
||||
// do some input validation
|
||||
if (!name.val() || name.val().length < 2) {
|
||||
alert(rcmail.gettext('invalidlistproperties', 'kolab_notes'));
|
||||
name.select();
|
||||
return;
|
||||
}
|
||||
|
||||
// post data to server
|
||||
var 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');
|
||||
};
|
||||
|
||||
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' : 'createlist'), '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();
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Callback from server after changing list properties
|
||||
*/
|
||||
function list_update(prop)
|
||||
{
|
||||
if (prop._reload) {
|
||||
rcmail.redirect(rcmail.url('', { _list: (prop.newid || prop.id) }));
|
||||
}
|
||||
else if (prop.newid && prop.newid != prop.id) {
|
||||
var book = $.extend({}, me.notebooks[prop.id]);
|
||||
book.id = prop.newid;
|
||||
book.name = prop.name;
|
||||
book.listname = prop.listname;
|
||||
book.editname = prop.editname || prop.name;
|
||||
|
||||
me.notebooks[prop.newid] = book;
|
||||
delete me.notebooks[prop.id];
|
||||
|
||||
// update treelist item
|
||||
var li = $(notebookslist.get_item(prop.id));
|
||||
$('.listname', li).html(prop.listname);
|
||||
notebookslist.update(prop.id, { id:book.id, html:li.html() });
|
||||
|
||||
// link all loaded note records to the new list id
|
||||
if (me.selected_list == prop.id) {
|
||||
me.selected_list = prop.newid;
|
||||
for (var k in notesdata) {
|
||||
if (notesdata[k].list == prop.id) {
|
||||
notesdata[k].list = book.id;
|
||||
}
|
||||
}
|
||||
notebookslist.select(prop.newid);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
function list_remove(id)
|
||||
{
|
||||
|
||||
var list = me.notebooks[id];
|
||||
if (list && confirm(rcmail.gettext('deletenotebookconfirm', 'kolab_notes'))) {
|
||||
saving_lock = rcmail.set_busy(true, 'kolab_notes.savingdata');
|
||||
rcmail.http_post('list', { _do: 'delete', _list: { id: list.id } });
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Callback from server on list delete command
|
||||
*/
|
||||
function list_destroy(prop)
|
||||
{
|
||||
if (!me.notebooks[prop.id]) {
|
||||
return;
|
||||
}
|
||||
|
||||
notebookslist.remove(prop.id);
|
||||
delete me.notebooks[prop.id];
|
||||
|
||||
if (me.selected_list == prop.id) {
|
||||
for (id in me.notebooks) {
|
||||
if (me.notebooks[id]) {
|
||||
notebookslist.select(id);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
29
plugins/kolab_notes/skins/larry/editor.css
Normal file
29
plugins/kolab_notes/skins/larry/editor.css
Normal file
|
@ -0,0 +1,29 @@
|
|||
/* This file contains the CSS data for the editable area(iframe) of TinyMCE */
|
||||
|
||||
body, td, pre {
|
||||
font-family: "Lucida Grande", Verdana, Arial, Helvetica, sans-serif;
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
body {
|
||||
background-color: #FFF;
|
||||
margin: 6px;
|
||||
}
|
||||
|
||||
pre
|
||||
{
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
white-space: -moz-pre-wrap !important;
|
||||
white-space: pre-wrap !important;
|
||||
white-space: pre;
|
||||
word-wrap: break-word; /* IE (and Safari) */
|
||||
}
|
||||
|
||||
blockquote
|
||||
{
|
||||
padding-left: 5px;
|
||||
border-left: #1010ff 2px solid;
|
||||
margin-left: 5px;
|
||||
width: 100%;
|
||||
}
|
|
@ -83,6 +83,8 @@
|
|||
.notesview #kolabnoteslist .title {
|
||||
display: block;
|
||||
padding: 4px 8px;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
.notesview #kolabnoteslist .date {
|
||||
|
@ -303,3 +305,19 @@
|
|||
.notesview #notebooks li.selected > a {
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
.notesview .uidialog .tabbed {
|
||||
margin-top: -12px;
|
||||
}
|
||||
|
||||
.notesview .uidialog .propform fieldset.tab {
|
||||
display: block;
|
||||
background: #efefef;
|
||||
margin-top: 0.5em;
|
||||
padding: 0.5em 1em;
|
||||
min-height: 290px;
|
||||
}
|
||||
|
||||
.notesview .uidialog .propform #noteslist-name {
|
||||
width: 20em;
|
||||
}
|
26
plugins/kolab_notes/skins/larry/templates/kolabacl.html
Normal file
26
plugins/kolab_notes/skins/larry/templates/kolabacl.html
Normal file
|
@ -0,0 +1,26 @@
|
|||
<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>
|
|
@ -74,6 +74,11 @@
|
|||
</ul>
|
||||
</div>
|
||||
|
||||
<div id="notebookeditform" class="uidialog">
|
||||
<roundcube:container name="notebookeditform" id="notebookeditform" />
|
||||
<roundcube:label name="loading" />
|
||||
</div>
|
||||
|
||||
|
||||
<script type="text/javascript">
|
||||
|
||||
|
@ -83,6 +88,10 @@ var UI = new rcube_mail_ui();
|
|||
$(document).ready(function(e){
|
||||
UI.init();
|
||||
|
||||
rcmail.addEventListener('kolab_notes_editform_load', function(e){
|
||||
UI.init_tabs($('#notebookeditform > form').addClass('propform tabbed'));
|
||||
})
|
||||
|
||||
new rcube_splitter({ id:'notesviewsplitter', p1:'#sidebar', p2:'#mainview-right',
|
||||
orientation:'v', relative:true, start:240, min:180, size:16, offset:2, render:layout_view }).init();
|
||||
new rcube_splitter({ id:'noteslistsplitter2', p1:'#noteslistbox', p2:'#notedetailsbox',
|
||||
|
|
Loading…
Add table
Reference in a new issue