diff --git a/plugins/kolab_files/config.inc.php.dist b/plugins/kolab_files/config.inc.php.dist index fcad5a5c..29ec6f09 100644 --- a/plugins/kolab_files/config.inc.php.dist +++ b/plugins/kolab_files/config.inc.php.dist @@ -3,4 +3,13 @@ // URL of kolab-chwala installation $rcmail_config['kolab_files_url'] = 'https://localhost/kolab-chwala/public_html'; +// List of files list columns. Available are: name, size, mtime, type +$rcmail_config['kolab_files_list_cols'] = array('name', 'mtime', 'size'); + +// Name of the column to sort files list by +$rcmail_config['kolab_files_sort_col'] = 'name'; + +// Order of the files list sort +$rcmail_config['kolab_files_sort_order'] = 'asc'; + ?> diff --git a/plugins/kolab_files/kolab_files.js b/plugins/kolab_files/kolab_files.js index 3198802d..677731fd 100644 --- a/plugins/kolab_files/kolab_files.js +++ b/plugins/kolab_files/kolab_files.js @@ -12,16 +12,34 @@ window.rcmail && rcmail.addEventListener('init', function() { var elem = $('#compose-attachments > div'), input = $(''); - input.val(rcmail.gettext('kolab_files.fromcloud')) - .click(function() { kolab_files_selector_dialog(); }) - .appendTo(elem); + input.val(rcmail.gettext('kolab_files.fromcloud')) + .click(function() { kolab_files_selector_dialog(); }) + .appendTo(elem); + + if (rcmail.gui_objects.filelist) { + rcmail.file_list = new rcube_list_widget(rcmail.gui_objects.filelist, { + multiselect: true, +// draggable: true, + keyboard: true, + column_movable: false, + dblclick_time: rcmail.dblclick_time + }); + rcmail.file_list.addEventListener('select', function(o) { kolab_files_list_select(o); }); + rcmail.file_list.addEventListener('listupdate', function(e) { rcmail.triggerEvent('listupdate', e); }); + + rcmail.gui_objects.filelist.parentNode.onmousedown = function(e){ return kolab_files_click_on_list(e); }; + rcmail.enable_command('files-sort', 'files-search', 'files-search-reset', true); + + rcmail.file_list.init(); + kolab_files_list_coltypes(); + } } // mail preview else if (rcmail.env.action == 'show' || rcmail.env.action == 'preview') { var attachment_list = $('#attachment-list'); if ($('li', attachment_list).length) { - var link = $('') + var link = $('') .text(rcmail.gettext('kolab_files.saveall')) .click(function() { kolab_directory_selector_dialog(); }) .appendTo(attachment_list); @@ -30,6 +48,42 @@ window.rcmail && rcmail.addEventListener('init', function() { kolab_files_init(); } + else if (rcmail.task == 'files') { + if (rcmail.gui_objects.filelist) { + rcmail.file_list = new rcube_list_widget(rcmail.gui_objects.filelist, { + multiselect: true, + draggable: true, + keyboard: true, + column_movable: rcmail.env.col_movable, + dblclick_time: rcmail.dblclick_time + }); +/* + rcmail.file_list.row_init = function(o){ kolab_files_init_file_row(o); }; + rcmail.file_list.addEventListener('dblclick', function(o){ p.msglist_dbl_click(o); }); + rcmail.file_list.addEventListener('click', function(o){ p.msglist_click(o); }); + rcmail.file_list.addEventListener('keypress', function(o){ p.msglist_keypress(o); }); +*/ + rcmail.file_list.addEventListener('select', function(o){ kolab_files_list_select(o); }); +/* + rcmail.file_list.addEventListener('dragstart', function(o){ p.drag_start(o); }); + rcmail.file_list.addEventListener('dragmove', function(e){ p.drag_move(e); }); + rcmail.file_list.addEventListener('dragend', function(e){ p.drag_end(e); }); +*/ + rcmail.file_list.addEventListener('column_replace', function(e){ kolab_files_set_coltypes(e); }); + rcmail.file_list.addEventListener('listupdate', function(e){ rcmail.triggerEvent('listupdate', e); }); + +// document.onmouseup = function(e){ return p.doc_mouse_up(e); }; + rcmail.gui_objects.filelist.parentNode.onmousedown = function(e){ return kolab_files_click_on_list(e); }; + + rcmail.enable_command('menu-open', 'menu-save', 'files-sort', 'files-search', 'files-search-reset', true); + + rcmail.file_list.init(); + kolab_files_list_coltypes(); + } + + kolab_files_init(); + file_api.folder_list(); + } }); function kolab_files_init() @@ -46,8 +100,22 @@ function kolab_files_init() sort_column: 'name', sort_reverse: 0 }); + + file_api.translations = rcmail.labels; }; +function kolab_files_token() +{ + // consider the token from parent window more reliable (fresher) than in framed window + // it's because keep-alive is not requested in frames + return (window.parent && parent.rcmail && parent.rcmail.env.files_token) || rcmail.env.files_token; +}; + + +/**********************************************************/ +/********* Plugin functionality in other tasks **********/ +/**********************************************************/ + function kolab_directory_selector_dialog() { var dialog = $('#files-dialog'), buttons = {}; @@ -68,19 +136,22 @@ function kolab_directory_selector_dialog() // show dialog window dialog.dialog({ - modal: false, + modal: true, resizable: !bw.ie6, closeOnEscape: (!bw.ie6 && !bw.ie7), // disable for performance reasons title: rcmail.gettext('kolab_files.saveall'), // close: function() { rcmail.dialog_close(); }, buttons: buttons, - minWidth: 400, + minWidth: 250, minHeight: 300, - height: 300, - width: 350 + height: 350, + width: 300 }).show(); - file_api.folder_selector(); + if (!rcmail.env.folders_loaded) { + file_api.folder_list(); + rcmail.env.folders_loaded = true; + } }; function kolab_files_selector_dialog() @@ -118,28 +189,199 @@ function kolab_files_selector_dialog() // show dialog window dialog.dialog({ - modal: false, + modal: true, resizable: !bw.ie6, closeOnEscape: (!bw.ie6 && !bw.ie7), // disable for performance reasons title: rcmail.gettext('kolab_files.selectfiles'), // close: function() { rcmail.dialog_close(); }, buttons: buttons, - minWidth: 400, + minWidth: 500, minHeight: 300, - width: 600, - height: 400 + width: 700, + height: 500 }).show(); - file_api.folder_selector(); + if (!rcmail.env.files_loaded) { + file_api.folder_list(); + rcmail.env.files_loaded = true; + } + else + rcmail.file_list.clear_selection(); }; -function kolab_files_token() + +/***********************************************************/ +/********** Main functionality **********/ +/***********************************************************/ + +// for reordering column array (Konqueror workaround) +// and for setting some message list global variables +kolab_files_list_coltypes = function() { - // consider the token from parent window more reliable (fresher) than in framed window - // it's because keep-alive is not requested in frames - return (window.parent && parent.rcmail && parent.rcmail.env.files_token) || rcmail.env.files_token; + var n, list = rcmail.file_list; + + rcmail.env.subject_col = null; + + if ((n = $.inArray('name', rcmail.env.coltypes)) >= 0) { + rcmail.env.subject_col = n; + list.subject_col = n; + } + + list.init_header(); }; +kolab_files_set_list_options = function(cols, sort_col, sort_order) +{ + var update = 0, i, idx, name, newcols = [], oldcols = rcmail.env.coltypes; + + if (sort_col === undefined) + sort_col = rcmail.env.sort_col; + if (!sort_order) + sort_order = rcmail.env.sort_order; + + if (rcmail.env.sort_col != sort_col || rcmail.env.sort_order != sort_order) { + update = 1; + rcmail.set_list_sorting(sort_col, sort_order); + } + + if (cols && cols.length) { + // make sure new columns are added at the end of the list + for (i=0; i= 0) +// rcmail.env.subject_col = found; + rcmail.env.subject_col = list.subject_col; + + rcmail.http_post('files/prefs', {kolab_files_list_cols: rcmail.env.coltypes}); +}; + +kolab_files_click_on_list = function(e) +{ + if (rcmail.gui_objects.qsearchbox) + rcmail.gui_objects.qsearchbox.blur(); + + if (rcmail.file_list) + rcmail.file_list.focus(); + + return true; +}; + +kolab_files_list_select = function(list) +{ + var selected = list.selection.length; +// this.enable_command(this.env.message_commands, selected != null); + + // Multi-message commands +// this.enable_command('delete', 'moveto', 'copy', list.selection.length > 0); + + // reset all-pages-selection +// if (list.selection.length && list.selection.length != list.rowcount) +// rcmail.select_all_mode = false; +}; + +rcube_webmail.prototype.files_sort = function(props) +{ + var params = {}, + sort_order = this.env.sort_order, + sort_col = !this.env.disabled_sort_col ? props : this.env.sort_col; + + if (!this.env.disabled_sort_order) + sort_order = this.env.sort_col == sort_col && sort_order == 'ASC' ? 'DESC' : 'ASC'; + + // set table header and update env + this.set_list_sorting(sort_col, sort_order); + + this.http_post('files/prefs', {kolab_files_sort_col: sort_col, kolab_files_sort_order: sort_order}); + + params.sort = sort_col; + params.reverse = sort_order == 'DESC'; + + file_api.file_list(params); +}; + +rcube_webmail.prototype.files_search = function() +{ + var value = $(this.gui_objects.filesearchbox).val(); + + if (value) + file_api.file_search(value); + else + file_api.file_search_reset(); +}; + +rcube_webmail.prototype.files_search_reset = function() +{ + $(this.gui_objects.filesearchbox).val(''); + + file_api.file_search_reset(); +}; + +rcube_webmail.prototype.files_folder_delete = function() +{ + if (confirm(this.get_label('deletefolderconfirm'))) + file_api.folder_delete(file_api.env.folder); +}; + +rcube_webmail.prototype.files_upload = function(form) +{ + if (form) + file_api.file_upload(form); +}; + +rcube_webmail.prototype.files_list_update = function(head) +{ + var list = this.file_list; + + list.clear(); + $('thead', list.list).html(head); + kolab_files_list_coltypes(); + file_api.file_list(); +}; + + +/**********************************************************/ +/********* Files API handler **********/ +/**********************************************************/ + function kolab_files_ui() { /* @@ -175,44 +417,30 @@ function kolab_files_ui() rcmail.http_error(request, status, err); }; - this.file_list = function(params) - { - if (rcmail.task != 'kolab_files') - this.file_selector(params); - }; - - this.folder_list = function(params) - { - if (rcmail.task != 'kolab_files') - this.folder_selector(params); - }; - - this.folder_selector = function() + this.folder_list = function() { this.req = this.set_busy(true, 'loading'); - this.get('folder_list', {}, 'folder_selector_response'); + this.get('folder_list', {}, 'folder_list_response'); }; // folder list response handler - this.folder_selector_response = function(response) + this.folder_list_response = function(response) { if (!this.response(response)) return; - var first, elem = $('#files-folder-selector'), - table = $(''); + var first, elem = $('#files-folder-list'), + list = $(''); - elem.html('').append(table); + elem.html('').append(list); this.env.folders = this.folder_list_parse(response.result); - table.empty(); - $.each(this.env.folders, function(i, f) { - var row = $(''), - span = $('span.name', row); + var row = $('
  • '), + link = $('a', row); - span.text(f.name); + link.text(f.name); row.attr('id', f.id); if (f.depth) @@ -221,42 +449,39 @@ function kolab_files_ui() if (f.virtual) row.addClass('virtual'); else - span.click(function() { file_api.selector_select(i); }); + link.click(function() { file_api.folder_select(i); }); -// if (i == file_api.env.folder) -// row.addClass('selected'); - - table.append(row); + list.append(row); if (!first) first = i; }); // select first folder? -// if (first) -// this.selector_select(first); + if (this.env.folder || first) + this.folder_select(this.env.folder ? this.env.folder : first); // add tree icons this.folder_list_tree(this.env.folders); }; - this.selector_select = function(i) + this.folder_select = function(i) { - var list = $('#files-folder-selector > table'); - $('tr.selected', list).removeClass('selected'); + var list = $('#files-folder-list > ul'); + $('li.selected', list).removeClass('selected'); $('#' + this.env.folders[i].id, list).addClass('selected'); this.env.folder = i; + rcmail.enable_command('files-folder-delete', 'files-upload', true); + // list files in selected folder - if (rcmail.env.action == 'compose') { - this.file_selector(); - } + this.file_list(); }; - this.file_selector = function(params) + this.file_list = function(params) { - if (!this.env.folder) + if (!this.env.folder || !rcmail.gui_objects.filelist) return; if (!params) @@ -275,31 +500,55 @@ function kolab_files_ui() this.env.sort_reverse = params.reverse; this.req = this.set_busy(true, 'loading'); - this.get('file_list', params, 'file_selector_response'); + + rcmail.file_list.clear(); + + this.get('file_list', params, 'file_list_response'); }; // file list response handler - this.file_selector_response = function(response) + this.file_list_response = function(response) { if (!this.response(response)) return; - var table = $('#filelist'); + var i = 0, table = $('#filelist'); $('tbody', table).empty(); $.each(response.result, function(key, data) { - var row = $('' - + /* '' */ ''), - link = $('').text(key); + var c, row = '', col; - $('td.filename', row).addClass(file_api.file_type_class(data.type)).append(link); -// $('td.filemtime', row).text(data.mtime); - $('td.filesize', row).text(file_api.file_size(data.size)); - row.attr('data-file', urlencode(key)) - .click(function(e) { file_api.file_select(e, this); }); + i++; - table.append(row); + for (c in rcmail.env.coltypes) { + c = rcmail.env.coltypes[c]; + if (c == 'name') { + if (rcmail.env.task == 'files') + col = ''; + else + col = ''; + } + else if (c == 'mtime') + col = ''; + else if (c == 'size') + col = ''; + else if (c == 'options') + col = ''; + else + col = ''; + + row += col; + } + + row = $('') + .html(row) + .attr({id: 'rcmrow' + i, 'data-file': urlencode(key)}); + +// table.append(row); + rcmail.file_list.insert_row(row.get([0])); }); }; @@ -313,7 +562,7 @@ function kolab_files_ui() // folder create request this.folder_create = function(folder) { - this.req = this.set_busy(true, 'creating'); + this.req = this.set_busy(true, 'kolab_files.foldercreating'); this.get('folder_create', {folder: folder}, 'folder_create_response'); }; @@ -324,16 +573,31 @@ function kolab_files_ui() return; // refresh folders list - if (rcmail.task == 'kolab_files') - this.folder_list(); - else - this.folder_selector(); + this.folder_list(); }; - this.search = function() + // folder delete request + this.folder_delete = function(folder) { - var value = $(rcmail.gui_objects.filesearchbox).val(); + this.req = this.set_busy(true, 'folderdeleting'); + this.get('folder_delete', {folder: folder}, 'folder_delete_response'); + }; + // folder delete response handler + this.folder_delete_response = function(response) + { + if (!this.response(response)) + return; + + this.env.folder = null; + rcmail.enable_command('files-folder-delete', 'files-folder-rename', false); + + // refresh folders list + this.folder_list(); + }; + + this.file_search = function(value) + { if (value) { this.env.search = {name: value}; this.file_list({search: this.env.search}); @@ -342,13 +606,87 @@ function kolab_files_ui() this.search_reset(); }; - this.search_reset = function() + this.file_search_reset = function() { - $(rcmail.gui_objects.filesearchbox).val(''); - if (this.env.search) { this.env.search = null; this.file_list(); } }; + + // file upload request + this.file_upload = function(form) + { + var form = $(form), + field = $('input[type=file]', form).get(0), + files = field.files ? field.files.length : field.value ? 1 : 0; + + if (files) { + // submit form and read server response + this.async_upload_form(form, 'file_create', function(event) { + var doc, response; + try { + doc = this.contentDocument ? this.contentDocument : this.contentWindow.document; + response = doc.body.innerHTML; + // response may be wrapped in
     tag
    +          if (response.slice(0, 5).toLowerCase() == '
    ' && response.slice(-6).toLowerCase() == '
    ') { + response = doc.body.firstChild.firstChild.nodeValue; + } + response = eval('(' + response + ')'); + } catch (err) { + response = {status: 'ERROR'}; + } + + rcmail.hide_message(event.data.ts); + + // refresh the list on upload success + if (file_api.response_parse(response)) + file_api.file_list(); + }); + } + }; + + // post the given form to a hidden iframe + this.async_upload_form = function(form, action, onload) + { + var ts = rcmail.display_message(rcmail.get_label('kolab_files.uploading'), 'loading', 1000), + frame_name = 'fileupload'+ts; +/* + // upload progress support + if (this.env.upload_progress_name) { + var fname = this.env.upload_progress_name, + field = $('input[name='+fname+']', form); + + if (!field.length) { + field = $('').attr({type: 'hidden', name: fname}); + field.prependTo(form); + } + field.val(ts); + } +*/ + // have to do it this way for IE + // otherwise the form will be posted to a new window + if (document.all) { + var html = ''; + document.body.insertAdjacentHTML('BeforeEnd', html); + } + // for standards-compliant browsers + else + $('
    ' + key + '' + + '' + key + '' + data.mtime + '' + file_api.file_size(data.size) + '' + + '