Summary: Fixes order of registering hook handlers. Properly propagates the refreshed token to the client-side Reviewers: #roundcube_kolab_plugins_developers, mollekopf Reviewed By: #roundcube_kolab_plugins_developers, mollekopf Subscribers: #roundcube_kolab_plugins_developers Differential Revision: https://git.kolab.org/D5139
4406 lines
132 KiB
JavaScript
4406 lines
132 KiB
JavaScript
/**
|
|
* Kolab files plugin
|
|
*
|
|
* @author Aleksander Machniak <machniak@kolabsys.com>
|
|
*
|
|
* @licstart The following is the entire license notice for the
|
|
* JavaScript code in this file.
|
|
*
|
|
* Copyright (C) 2011-2015, Kolab Systems AG <contact@kolabsys.com>
|
|
*
|
|
* This program is free software: you can redistribute it and/or modify
|
|
* it under the terms of the GNU Affero General Public License as
|
|
* published by the Free Software Foundation, either version 3 of the
|
|
* License, or (at your option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU Affero General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU Affero General Public License
|
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
*
|
|
* @licend The above is the entire license notice
|
|
* for the JavaScript code in this file.
|
|
*/
|
|
|
|
window.rcmail && window.files_api && rcmail.addEventListener('init', function() {
|
|
if (rcmail.task == 'mail') {
|
|
// mail compose
|
|
if (rcmail.env.action == 'compose') {
|
|
kolab_files_from_cloud_widget($('#compose-attachments > div'));
|
|
|
|
// register some commands to skip warning message on compose page
|
|
$.merge(rcmail.env.compose_commands, ['files-list', 'files-sort', 'files-search', 'files-search-reset']);
|
|
}
|
|
// mail preview
|
|
else if (rcmail.env.action == 'show' || rcmail.env.action == 'preview') {
|
|
var attachment_list = $('#attachment-list');
|
|
|
|
if ($('li', attachment_list).length) {
|
|
var link = $('<a href="#" class="button filesaveall">')
|
|
.text(rcmail.gettext('kolab_files.saveall'))
|
|
.click(function() { kolab_directory_selector_dialog(); })
|
|
.insertAfter($('.header-content > .header-links').length ? $('.header-links > a:last') : attachment_list);
|
|
}
|
|
|
|
rcmail.addEventListener('menu-open', kolab_files_attach_menu_open);
|
|
rcmail.enable_command('folder-create', true);
|
|
}
|
|
// attachment preview
|
|
else if (rcmail.env.action == 'get') {
|
|
rcmail.enable_command('folder-create', true);
|
|
}
|
|
|
|
if (!rcmail.env.action || rcmail.env.action == 'show' || rcmail.env.action == 'preview') {
|
|
// add "attach from cloud" button for event/task dialog in mail
|
|
rcmail.addEventListener('plugin.mail2event_dialog', function() {
|
|
if (!$('#calendar-attachment-form a.fromcloud').length)
|
|
kolab_files_from_cloud_widget($('#calendar-attachment-form > div.buttons'));
|
|
});
|
|
}
|
|
}
|
|
else if (rcmail.task == 'calendar') {
|
|
// add "attach from cloud" button for event dialog
|
|
if (!rcmail.env.action)
|
|
kolab_files_from_cloud_widget($('#calendar-attachment-form > div.buttons, #edit-attachments-form'));
|
|
}
|
|
else if (rcmail.task == 'tasks') {
|
|
// add "attach from cloud" button for task dialog
|
|
if (!rcmail.env.action)
|
|
kolab_files_from_cloud_widget($('#taskedit-attachment-form > div.buttons, #taskedit-attachments-form'));
|
|
}
|
|
else if (rcmail.task == 'files') {
|
|
if (rcmail.gui_objects.fileslist) {
|
|
rcmail.fileslist = new rcube_list_widget(rcmail.gui_objects.fileslist, {
|
|
multiselect: true,
|
|
draggable: true,
|
|
keyboard: true,
|
|
column_movable: rcmail.env.files_col_movable,
|
|
dblclick_time: rcmail.dblclick_time
|
|
});
|
|
|
|
rcmail.fileslist.addEventListener('dblclick', function(o) { kolab_files_list_dblclick(o); })
|
|
.addEventListener('select', function(o) { kolab_files_list_select(o); })
|
|
.addEventListener('keypress', function(o) { kolab_files_list_keypress(o); })
|
|
.addEventListener('dragstart', function(e) { kolab_files_drag_start(e); })
|
|
.addEventListener('dragmove', function(e) { kolab_files_drag_move(e); })
|
|
.addEventListener('dragend', function(e) { kolab_files_drag_end(e); })
|
|
.addEventListener('column_replace', function(e) { kolab_files_set_coltypes(e, 'files'); });
|
|
|
|
rcmail.enable_command('menu-open', 'menu-save', 'files-sort', 'files-search', 'files-search-reset', 'folder-create', true);
|
|
|
|
rcmail.fileslist.init();
|
|
kolab_files_list_coltypes('files');
|
|
kolab_files_drag_drop_init($(rcmail.gui_objects.fileslist).parents('.droptarget'));
|
|
}
|
|
|
|
if (rcmail.gui_objects.sessionslist) {
|
|
rcmail.sessionslist = new rcube_list_widget(rcmail.gui_objects.sessionslist, {
|
|
keyboard: true,
|
|
column_movable: rcmail.env.sessions_col_movable,
|
|
dblclick_time: rcmail.dblclick_time
|
|
});
|
|
|
|
rcmail.sessionslist.addEventListener('dblclick', function(o) { kolab_files_sessions_list_dblclick(o); })
|
|
.addEventListener('select', function(o) { kolab_files_sessions_list_select(o); })
|
|
.addEventListener('keypress', function(o) { kolab_files_sessions_list_keypress(o); })
|
|
.addEventListener('column_replace', function(e) { kolab_files_set_coltypes(e, 'sessions'); });
|
|
|
|
rcmail.sessionslist.init();
|
|
kolab_files_list_coltypes('sessions');
|
|
}
|
|
|
|
// "one file only" commands
|
|
rcmail.env.file_commands = ['files-get', 'files-rename'];
|
|
// "one or more file" commands
|
|
rcmail.env.file_commands_all = ['files-delete', 'files-move', 'files-copy'];
|
|
|
|
if (rcmail.env.action == 'open' || rcmail.env.action == 'edit') {
|
|
rcmail.enable_command('files-get', true);
|
|
rcmail.enable_command('files-delete', rcmail.env.file_data.writable);
|
|
}
|
|
else {
|
|
rcmail.enable_command('folder-mount', rcmail.env.external_sources);
|
|
}
|
|
}
|
|
|
|
kolab_files_init();
|
|
|
|
rcmail.addEventListener('responsebeforerefresh', kolab_files_token_refresh);
|
|
rcmail.addEventListener('responsebeforekeep-alive', kolab_files_token_refresh);
|
|
});
|
|
|
|
|
|
/**********************************************************/
|
|
/********* Shared functionality **********/
|
|
/**********************************************************/
|
|
|
|
// Initializes API object
|
|
function kolab_files_init()
|
|
{
|
|
if (window.file_api)
|
|
return;
|
|
|
|
var editor_config = {};
|
|
|
|
// Initialize application object (don't change var name!)
|
|
file_api = $.extend(new files_api(), new kolab_files_ui());
|
|
|
|
file_api.set_env({
|
|
token: kolab_files_token(),
|
|
url: rcmail.env.files_url,
|
|
sort_col: 'name',
|
|
sort_reverse: false,
|
|
search_threads: rcmail.env.search_threads,
|
|
resources_dir: rcmail.env.files_url.replace(/\/api\/?$/, '/resources'),
|
|
caps: rcmail.env.files_caps,
|
|
supported_mimetypes: rcmail.env.file_mimetypes
|
|
});
|
|
|
|
file_api.translations = rcmail.labels;
|
|
|
|
if (rcmail.task == 'files') {
|
|
if (rcmail.env.action == 'edit' && rcmail.env.editor_type) {
|
|
// Extract the domain here, it can't be done by Chwala
|
|
// when using WOPI, which does not set iframe src attribute
|
|
var domain, href = rcmail.env.file_data.viewer.href;
|
|
if (href && /^(https?:\/\/[^/]+)/i.test(href))
|
|
domain = RegExp.$1;
|
|
|
|
editor_config = {
|
|
// UI elements
|
|
iframe: $('#fileframe').get(0),
|
|
domain: domain,
|
|
export_menu: rcmail.gui_objects.exportmenu ? $('ul', rcmail.gui_objects.exportmenu).get(0) : null,
|
|
title_input: $('#document-title').get(0),
|
|
members_list: $('#members').get(0),
|
|
photo_url: '?_task=addressbook&_action=photo&_error=1&_email=%email',
|
|
photo_default_url: rcmail.env.photo_placeholder,
|
|
// events
|
|
ready: function(data) { document_editor_init(); },
|
|
sessionClosed: function(data) { return document_editor_close(); }
|
|
};
|
|
|
|
if (rcmail.env.file_data.writable)
|
|
editor_config.documentChanged = function(data) { rcmail.enable_command('document-save', true); };
|
|
}
|
|
else if (rcmail.env.action == 'open') {
|
|
// initialize folders list (for dialogs)
|
|
// file_api.folder_list();
|
|
|
|
// get ongoing sessions
|
|
file_api.request('folder_info', {folder: file_api.file_path(rcmail.env.file), sessions: 1}, 'folder_info_response');
|
|
}
|
|
else if (rcmail.env.action == 'share') {
|
|
kolab_files_share_form_init();
|
|
}
|
|
else {
|
|
file_api.env.init_folder = rcmail.env.folder;
|
|
file_api.env.init_collection = rcmail.env.collection;
|
|
file_api.folder_list();
|
|
file_api.browser_capabilities_check();
|
|
|
|
if (rcmail.env.contextmenu) {
|
|
rcmail.env.folders_cm = rcmail.contextmenu.init({menu_name: 'foldercontextmenu', menu_source: '#folderoptions > ul', list_object: 'folder_list'}, {
|
|
addmenuitem: function(p) {
|
|
// don't add Mount option to the menu
|
|
var str = $(p.el).children('a').first().attr('onclick');
|
|
if (str && str.match(/folder-mount/))
|
|
return {result: false, abort: true};
|
|
},
|
|
activate: function(p) {
|
|
var folder = rcmail.env.context_menu_source_id;
|
|
switch (p.command) {
|
|
case 'files-folder-delete':
|
|
case 'folder-rename':
|
|
return !folder.match(/^folder-collection-(.*)$/);
|
|
case 'folder-share':
|
|
return !folder.match(/^folder-collection-(.*)$/) && file_api.is_shareable(folder);
|
|
case 'folder-create':
|
|
case 'folder-mount':
|
|
return true;
|
|
}
|
|
},
|
|
beforecommand: function(e) {
|
|
rcmail.env.file_api_context = [file_api.env.folder, file_api.env.collection];
|
|
file_api.env.folder = rcmail.env.context_menu_source_id;
|
|
},
|
|
aftercommand: function(e) {
|
|
file_api.env.folder = rcmail.env.file_api_context[0];
|
|
file_api.env.collection = rcmail.env.file_api_context[1];
|
|
}
|
|
});
|
|
}
|
|
}
|
|
}
|
|
|
|
if (rcmail.env.files_caps && !rcmail.env.framed && rcmail.env.files_caps.DOCEDIT)
|
|
$.extend(editor_config, {
|
|
// invitation notifications
|
|
api: file_api,
|
|
owner: rcmail.env.files_user,
|
|
interval: rcmail.env.files_interval || 60,
|
|
invitationMore: true,
|
|
invitationChange: document_editor_invitation_handler
|
|
});
|
|
|
|
$.extend(editor_config, {
|
|
// notifications/alerts
|
|
gettext: function(label) { return rcmail.get_label(label, 'kolab_files'); },
|
|
set_busy: function(state, message) { return rcmail.set_busy(state, message ? 'kolab_files.' + message : ''); },
|
|
hide_message: function(id) { return rcmail.hide_message(id); },
|
|
display_message: function(label, type, is_txt, timeout) {
|
|
if (!is_txt)
|
|
label = 'kolab_files.' + label;
|
|
return rcmail.display_message(label, type, timeout * 1000);
|
|
}
|
|
});
|
|
|
|
if (window.document_editor_api)
|
|
document_editor = new document_editor_api(editor_config);
|
|
else
|
|
document_editor = new manticore_api(editor_config);
|
|
|
|
rcmail.addEventListener('responseafterreset', function(o) {
|
|
// update caps/mountpoints on reset
|
|
file_api.set_env({caps: rcmail.env.files_caps});
|
|
});
|
|
};
|
|
|
|
// returns API authorization token
|
|
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 rcmail.is_framed() && parent.rcmail.env.files_token ? parent.rcmail.env.files_token : rcmail.env.files_token;
|
|
};
|
|
|
|
// Event handler for refresh/keep-alive action that can bring a refreshed access token
|
|
function kolab_files_token_refresh(data)
|
|
{
|
|
var i, win, env = data && data.response ? data.response.env : {};
|
|
|
|
if (!env.files_token || rcmail.env.files_token == env.files_token) {
|
|
return;
|
|
}
|
|
|
|
file_api.set_env({ token: env.files_token });
|
|
|
|
// Propagate the change to all iframes
|
|
for (i = 0; i < window.frames.length; i++) {
|
|
win = window.frames[i];
|
|
try {
|
|
win.file_api.set_env({ token: env.files_token });
|
|
} catch (e) {
|
|
// ignore
|
|
}
|
|
}
|
|
};
|
|
|
|
function kolab_files_from_cloud_widget(elem)
|
|
{
|
|
$('<a class="button btn btn-secondary fromcloud">')
|
|
.attr('tabindex', $('button,input', elem).first().attr('tabindex') || 0)
|
|
.text(rcmail.gettext('kolab_files.fromcloud'))
|
|
.click(function() { kolab_files_selector_dialog(); })
|
|
.appendTo(elem);
|
|
|
|
if (rcmail.gui_objects.fileslist) {
|
|
rcmail.fileslist = new rcube_list_widget(rcmail.gui_objects.fileslist, {
|
|
multiselect: true,
|
|
keyboard: true,
|
|
column_movable: false,
|
|
dblclick_time: rcmail.dblclick_time
|
|
});
|
|
rcmail.fileslist.addEventListener('select', function(o) { kolab_files_list_select(o); });
|
|
|
|
rcmail.enable_command('files-sort', 'files-search', 'files-search-reset', true);
|
|
|
|
rcmail.fileslist.init();
|
|
kolab_files_list_coltypes();
|
|
}
|
|
}
|
|
|
|
// folder selection dialog
|
|
function kolab_directory_selector_dialog(id)
|
|
{
|
|
var dialog = $('#files-dialog'),
|
|
input = $('#file-save-as-input'),
|
|
form = $('#file-save-as'),
|
|
list = $('#folderlistbox'),
|
|
buttons = {}, label = 'saveto',
|
|
win = window, fn;
|
|
|
|
// attachment is specified
|
|
if (id) {
|
|
var attach = $('#attach' + id + '> a').first(),
|
|
filename = attach.attr('title');
|
|
|
|
if (!filename) {
|
|
attach = attach.clone();
|
|
$('.attachment-size', attach).remove();
|
|
filename = $.trim(attach.text());
|
|
}
|
|
|
|
form.show();
|
|
dialog.addClass('saveas');
|
|
input.val(filename);
|
|
}
|
|
// attachment preview page
|
|
else if (rcmail.env.action == 'get') {
|
|
id = rcmail.env.part;
|
|
form.show();
|
|
dialog.addClass('saveas');
|
|
input.val(rcmail.env.filename);
|
|
}
|
|
else {
|
|
form.hide();
|
|
dialog.removeClass('saveas');
|
|
label = 'saveall';
|
|
}
|
|
|
|
$('#foldercreatelink').attr('tabindex', 0);
|
|
|
|
buttons[rcmail.gettext('kolab_files.save')] = function () {
|
|
if (!file_api.env.folder)
|
|
return;
|
|
|
|
var lock = rcmail.set_busy(true, 'saving'),
|
|
request = {
|
|
act: 'save-file',
|
|
source: rcmail.env.mailbox,
|
|
uid: rcmail.env.uid,
|
|
dest: file_api.env.folder
|
|
};
|
|
|
|
if (id) {
|
|
request.id = id;
|
|
request.name = input.val();
|
|
}
|
|
|
|
rcmail.http_post('plugin.kolab_files', request, lock);
|
|
kolab_dialog_close(this);
|
|
};
|
|
|
|
buttons[rcmail.gettext('kolab_files.cancel')] = function () {
|
|
kolab_dialog_close(this);
|
|
};
|
|
|
|
if (!rcmail.env.folders_loaded) {
|
|
fn = function() {
|
|
rcmail.env.folder_list_selector = '#files-dialog #files-folder-list';
|
|
rcmail.env.folder_search_selector = '#files-dialog #foldersearch';
|
|
file_api.folder_list({writable: 1});
|
|
rcmail.env.folders_loaded = true;
|
|
};
|
|
}
|
|
|
|
// show dialog window
|
|
kolab_dialog_show(dialog, {
|
|
title: rcmail.gettext('kolab_files.' + label),
|
|
buttons: buttons,
|
|
button_classes: ['mainaction save', 'cancel'],
|
|
classes: {'ui-dialog': 'selection-dialog files-dialog'},
|
|
minWidth: 250,
|
|
minHeight: 300,
|
|
height: 400,
|
|
width: 300
|
|
}, fn);
|
|
|
|
// add link for "more options" drop-down
|
|
if (!dialog.find('foldercreatelink').length)
|
|
$('<a>')
|
|
.attr({href: '#', 'class': 'btn btn-link options add-folder'})
|
|
.text(rcmail.gettext('kolab_files.addfolder'))
|
|
.click(function(e) { rcmail.command('folder-create', '', this, e); })
|
|
.prependTo(dialog.parent().parent().find('.ui-dialog-buttonset'));
|
|
|
|
// "enable" folder creation when dialog is displayed in parent window
|
|
if (rcmail.is_framed()) {
|
|
parent.rcmail.enable_command('folder-create', true);
|
|
parent.rcmail.folder_create = function() {
|
|
win.kolab_files_folder_create_dialog();
|
|
};
|
|
}
|
|
};
|
|
|
|
// file selection dialog
|
|
function kolab_files_selector_dialog()
|
|
{
|
|
var dialog = $('#files-compose-dialog'), buttons = {};
|
|
|
|
buttons[rcmail.gettext('kolab_files.attachsel')] = function () {
|
|
var list = [];
|
|
$('#filelist tr.selected').each(function() {
|
|
list.push($(this).data('file'));
|
|
});
|
|
|
|
kolab_dialog_close(this);
|
|
|
|
if (list.length) {
|
|
// display upload indicator and cancel button
|
|
var content = '<span>' + rcmail.get_label('kolab_files.attaching') + '</span>',
|
|
id = new Date().getTime();
|
|
|
|
rcmail.add2attachment_list(id, {name:'', html:content, classname:'uploading', complete:false});
|
|
|
|
// send request
|
|
rcmail.http_post('plugin.kolab_files', {
|
|
act: 'attach-file',
|
|
files: list,
|
|
id: rcmail.env.compose_id,
|
|
uploadid: id
|
|
});
|
|
}
|
|
};
|
|
|
|
buttons[rcmail.gettext('kolab_files.cancel')] = function () {
|
|
kolab_dialog_close(this);
|
|
};
|
|
|
|
// show dialog window
|
|
kolab_dialog_show(dialog, {
|
|
title: rcmail.gettext('kolab_files.selectfiles'),
|
|
buttons: buttons,
|
|
button_classes: ['mainaction save', 'cancel'],
|
|
classes: {'ui-dialog': 'selection-dialog files-dialog'},
|
|
minWidth: 500,
|
|
minHeight: 300,
|
|
width: 700,
|
|
height: 500
|
|
}, function() { rcmail.fileslist.resize(); });
|
|
|
|
if (!rcmail.env.files_loaded) {
|
|
rcmail.env.folder_list_selector = '#files-compose-dialog #files-folder-list';
|
|
rcmail.env.folder_search_selector = '#files-compose-dialog #foldersearch';
|
|
file_api.folder_list();
|
|
rcmail.env.files_loaded = true;
|
|
}
|
|
else {
|
|
rcmail.fileslist.clear_selection();
|
|
}
|
|
};
|
|
|
|
function kolab_files_attach_menu_open(p)
|
|
{
|
|
if (!p || !p.props || p.props.menu != 'attachmentmenu')
|
|
return;
|
|
|
|
var id = p.props.id;
|
|
|
|
$('#attachmenusaveas').unbind('click').attr('onclick', '').click(function(e) {
|
|
return kolab_directory_selector_dialog(id);
|
|
});
|
|
};
|
|
|
|
// folder creation dialog
|
|
function kolab_files_folder_create_dialog()
|
|
{
|
|
var dialog = $('#files-folder-create-dialog'),
|
|
buttons = {},
|
|
select = $('select[name="parent"]', dialog).html(''),
|
|
input = $('input[name="name"]', dialog).val('');
|
|
|
|
buttons[rcmail.gettext('kolab_files.create')] = function () {
|
|
var folder = '', name = input.val(), parent = select.val();
|
|
|
|
if (!name)
|
|
return;
|
|
|
|
if (parent)
|
|
folder = parent + file_api.env.directory_separator;
|
|
|
|
folder += name;
|
|
|
|
file_api.folder_create(folder);
|
|
kolab_dialog_close(this);
|
|
};
|
|
|
|
buttons[rcmail.gettext('kolab_files.cancel')] = function () {
|
|
kolab_dialog_close(this);
|
|
};
|
|
|
|
// show dialog window
|
|
kolab_dialog_show(dialog, {
|
|
title: rcmail.gettext('kolab_files.foldercreate'),
|
|
buttons: buttons,
|
|
button_classes: ['mainaction save', 'cancel'],
|
|
height: 200
|
|
});
|
|
|
|
// Fix submitting form with Enter
|
|
$('form', dialog).submit(kolab_dialog_submit_handler);
|
|
|
|
// build parent selector
|
|
file_api.folder_select_element(select, {empty: !rcmail.env.files_caps.NOROOT, writable: true});
|
|
};
|
|
|
|
// folder edit dialog
|
|
function kolab_files_folder_edit_dialog()
|
|
{
|
|
var dialog = $('#files-folder-edit-dialog'),
|
|
buttons = {},
|
|
separator = file_api.env.directory_separator,
|
|
current_folder = file_api.env.folder,
|
|
arr = current_folder.split(separator),
|
|
folder = arr.pop(),
|
|
path = arr.join(separator),
|
|
select = $('select[name="parent"]', dialog).html(''),
|
|
input = $('input[name="name"]', dialog).val(folder);
|
|
|
|
buttons[rcmail.gettext('kolab_files.save')] = function () {
|
|
var folder = '', name = input.val(), parent = select.val();
|
|
|
|
if (!name)
|
|
return;
|
|
|
|
if (parent)
|
|
folder = parent + separator;
|
|
|
|
folder += name;
|
|
|
|
file_api.folder_rename(current_folder, folder);
|
|
kolab_dialog_close(this);
|
|
};
|
|
|
|
buttons[rcmail.gettext('kolab_files.cancel')] = function () {
|
|
kolab_dialog_close(this);
|
|
};
|
|
|
|
// show dialog window
|
|
kolab_dialog_show(dialog, {
|
|
title: rcmail.gettext('kolab_files.folderedit'),
|
|
buttons: buttons,
|
|
button_classes: ['mainaction save', 'cancel'],
|
|
height: 200
|
|
});
|
|
|
|
// Fix submitting form with Enter
|
|
$('form', dialog).submit(kolab_dialog_submit_handler);
|
|
|
|
// build parent selector
|
|
file_api.folder_select_element(select, {selected: path, empty: !rcmail.env.files_caps.NOROOT});
|
|
};
|
|
|
|
// folder sharing dialog
|
|
function kolab_files_folder_share_dialog()
|
|
{
|
|
var dialog = $('<iframe>').attr('src', rcmail.url('share', {_folder: file_api.env.folder, _framed: 1}));
|
|
|
|
rcmail.simple_dialog(dialog, rcmail.gettext('kolab_files.foldershare'), null, {
|
|
cancel_button: 'close',
|
|
width: 600,
|
|
height: 500
|
|
});
|
|
};
|
|
|
|
// folder mounting dialog
|
|
function kolab_files_folder_mount_dialog()
|
|
{
|
|
var args = {buttons: {}, title: rcmail.gettext('kolab_files.foldermount')},
|
|
dialog = $('#files-folder-mount-dialog'),
|
|
input = $('#folder-mount-name').val('');
|
|
|
|
args.buttons[rcmail.gettext('kolab_files.save')] = function () {
|
|
var args = {}, folder = input.val(),
|
|
driver = $('input[name="driver"]:checked', dialog).val();
|
|
|
|
if (!folder || !driver)
|
|
return;
|
|
|
|
args.folder = folder;
|
|
args.driver = driver;
|
|
|
|
$('#source-' + driver + ' input').each(function() {
|
|
if (this.name.startsWith(driver + '[')) {
|
|
args[this.name.substring(driver.length + 1, this.name.length - 1)] = this.value;
|
|
}
|
|
});
|
|
|
|
$('.auth-options input', dialog).each(function() {
|
|
args[this.name] = this.type == 'checkbox' && !this.checked ? '' : this.value;
|
|
});
|
|
|
|
file_api.folder_mount(args);
|
|
kolab_dialog_close(this);
|
|
};
|
|
|
|
args.buttons[rcmail.gettext('kolab_files.cancel')] = function () {
|
|
kolab_dialog_close(this);
|
|
};
|
|
|
|
// initialize drivers list
|
|
if (!rcmail.drivers_list_initialized) {
|
|
rcmail.drivers_list_initialized = true;
|
|
|
|
$('td.source', dialog).each(function() {
|
|
var td = $(this),
|
|
id = td.attr('id').replace('source-', ''),
|
|
meta = rcmail.env.external_sources[id];
|
|
|
|
$.each(meta.form_values || [], function(i, v) {
|
|
td.find('#source-' + id + '-' + i).val(v);
|
|
});
|
|
|
|
td.click(function() {
|
|
$('td.selected', dialog).removeClass('selected');
|
|
dialog.find('.driverform').hide();
|
|
$(this).addClass('selected').find('.driverform').show();
|
|
$('input[type="radio"]', this).prop('checked', true);
|
|
});
|
|
});
|
|
}
|
|
|
|
args.button_classes = ['mainaction save', 'cancel'];
|
|
|
|
// show dialog window
|
|
kolab_dialog_show(dialog, args, function() {
|
|
$('td.source:first', dialog).click();
|
|
input.focus();
|
|
});
|
|
};
|
|
|
|
// file edit dialog
|
|
function kolab_files_file_edit_dialog(file, sessions, readonly)
|
|
{
|
|
var content = [], items = [], height = 300,
|
|
dialog = $('#files-file-edit-dialog'),
|
|
buttons = {}, name = file_api.file_name(file),
|
|
title = rcmail.gettext('kolab_files.editfiledialog'),
|
|
mainaction = rcmail.gettext('kolab_files.select'),
|
|
item_fn = function(id, txt, classes) {
|
|
return $('<label>').attr('class', 'session' + (classes ? ' ' + classes : ''))
|
|
.append($('<input>').attr({name: 'opt', value: id, type: 'radio'})).append($('<span>').text(txt));
|
|
},
|
|
select_fn = function(dlg) {
|
|
var session, input = $('input:checked', dialog), id = input.val();
|
|
|
|
if (dlg)
|
|
kolab_dialog_close(dlg);
|
|
|
|
if (id && input.parent().is('.session.request')) {
|
|
document_editor.invitation_request({session_id: id});
|
|
return;
|
|
}
|
|
|
|
if (readonly && (id == 0 || !input.length))
|
|
return kolab_files_file_create_dialog(file);
|
|
|
|
rcmail.files_edit(id ? id : true);
|
|
};
|
|
|
|
// Create sessions selection
|
|
if (sessions && sessions.length) {
|
|
items.push($('<div>').text(rcmail.gettext('kolab_files.editfilesessions')));
|
|
|
|
// first display owned sessions, then invited, other at the end
|
|
$.each(sessions, function() {
|
|
if (this.is_owner) {
|
|
var txt = rcmail.gettext('kolab_files.ownedsession');
|
|
items.push(item_fn(this.id, txt, 'owner'));
|
|
}
|
|
});
|
|
|
|
if (items.length == 1)
|
|
items.push(item_fn(0, rcmail.gettext('kolab_files.newsession' + (readonly ? 'ro' : ''))));
|
|
|
|
$.each(sessions, function() {
|
|
if (this.is_invited) {
|
|
var txt = rcmail.gettext('kolab_files.invitedsession')
|
|
.replace('$user', this.owner_name ? this.owner_name : this.owner);
|
|
items.push(item_fn(this.id, txt, 'invited'));
|
|
}
|
|
});
|
|
|
|
$.each(sessions, function() {
|
|
if (!this.is_owner && !this.is_invited) {
|
|
var txt = rcmail.gettext('kolab_files.joinsession')
|
|
.replace('$user', this.owner_name ? this.owner_name : this.owner);
|
|
items.push(item_fn(this.id, txt, 'request'));
|
|
}
|
|
});
|
|
|
|
// check the first option
|
|
$('input', items[1]).attr('checked', true);
|
|
|
|
$('div', dialog).html(items);
|
|
|
|
// if there's only one session and it's owned, skip the dialog
|
|
if (!readonly && items.length == 2 && $('input:checked', dialog).parent().is('.owner'))
|
|
return select_fn();
|
|
}
|
|
// no ongoing session, folder is readonly warning
|
|
else {
|
|
title = rcmail.gettext('kolab_files.editfilerotitle');
|
|
height = 150;
|
|
$('div', dialog).text(rcmail.gettext('kolab_files.editfilero'));
|
|
mainaction = rcmail.gettext('kolab_files.create');
|
|
}
|
|
|
|
buttons[mainaction] = function() { select_fn(this); };
|
|
buttons[rcmail.gettext('kolab_files.cancel')] = function () {
|
|
kolab_dialog_close(this);
|
|
};
|
|
|
|
// show dialog window
|
|
kolab_dialog_show(dialog, {
|
|
title: title,
|
|
buttons: buttons,
|
|
button_classes: ['mainaction save', 'cancel'],
|
|
minHeight: height - 100,
|
|
height: height
|
|
});
|
|
};
|
|
|
|
// file rename dialog
|
|
function kolab_files_file_rename_dialog(file)
|
|
{
|
|
var dialog = $('#files-file-rename-dialog'),
|
|
buttons = {}, name = file_api.file_name(file)
|
|
input = $('input[name="name"]', dialog).val(name);
|
|
|
|
buttons[rcmail.gettext('kolab_files.save')] = function() {
|
|
var folder = file_api.file_path(file), name = input.val();
|
|
|
|
if (!name)
|
|
return;
|
|
|
|
name = folder + file_api.env.directory_separator + name;
|
|
|
|
if (name != file)
|
|
file_api.file_rename(file, name);
|
|
|
|
kolab_dialog_close(this);
|
|
};
|
|
buttons[rcmail.gettext('kolab_files.cancel')] = function() {
|
|
kolab_dialog_close(this);
|
|
};
|
|
|
|
// Fix submitting form with Enter
|
|
$('form', dialog).submit(kolab_dialog_submit_handler);
|
|
|
|
// show dialog window
|
|
kolab_dialog_show(dialog, {
|
|
title: rcmail.gettext('kolab_files.renamefile'),
|
|
buttons: buttons,
|
|
button_classes: ['mainaction save', 'cancel'],
|
|
minHeight: 100,
|
|
height: 100
|
|
});
|
|
};
|
|
|
|
// file creation (or cloning) dialog
|
|
function kolab_files_file_create_dialog(file)
|
|
{
|
|
var buttons = {}, action = file ? 'copy' : 'create',
|
|
button_classes = ['mainaction save edit'],
|
|
dialog = $('#files-file-create-dialog'),
|
|
type_select = $('select[name="type"]', dialog),
|
|
select = $('select[name="parent"]', dialog).html(''),
|
|
input = $('input[name="name"]', dialog).val(''),
|
|
create_func = function(dialog, editaction) {
|
|
var sel, folder = select.val(), type = type_select.val(), name = input.val();
|
|
|
|
if (!name || !folder || !file_api.is_writable(folder))
|
|
return;
|
|
|
|
if (!/\.[a-z0-9]{1,5}$/.test(name)) {
|
|
name += '.' + rcmail.env.file_extensions[type];
|
|
}
|
|
|
|
name = folder + file_api.env.directory_separator + name;
|
|
|
|
// get type of cloned file
|
|
if (file) {
|
|
if (rcmail.env.file_data)
|
|
type = rcmail.env.file_data.type;
|
|
else {
|
|
sel = rcmail.fileslist.get_selection();
|
|
type = $('#rcmrow' + sel[0]).data('type');
|
|
}
|
|
}
|
|
|
|
file_api.file_create(name, type, editaction, file);
|
|
kolab_dialog_close(dialog);
|
|
};
|
|
|
|
buttons[rcmail.gettext('kolab_files.' + action + 'andedit')] = function() {
|
|
create_func(this, true);
|
|
};
|
|
|
|
if (action == 'create') {
|
|
button_classes.push('save');
|
|
buttons[rcmail.gettext('kolab_files.create')] = function() {
|
|
create_func(this);
|
|
};
|
|
type_select.parent('tr').show();
|
|
}
|
|
else {
|
|
input.val(file_api.file_name(file));
|
|
type_select.parent('tr').hide();
|
|
}
|
|
|
|
button_classes.push('cancel');
|
|
buttons[rcmail.gettext('kolab_files.cancel')] = function() {
|
|
kolab_dialog_close(this);
|
|
};
|
|
|
|
// Fix submitting form with Enter
|
|
$('form', dialog).submit(kolab_dialog_submit_handler);
|
|
|
|
// show dialog window
|
|
kolab_dialog_show(dialog, {
|
|
title: rcmail.gettext('kolab_files.' + action + 'file'),
|
|
buttons: buttons,
|
|
button_classes: button_classes,
|
|
minHeight: 150,
|
|
height: 250
|
|
});
|
|
|
|
// build folder selector
|
|
file_api.folder_select_element(select, {writable: true});
|
|
};
|
|
|
|
// file session dialog
|
|
function kolab_files_session_dialog(session)
|
|
{
|
|
var buttons = {}, button_classes = [],
|
|
dialog = $('#files-session-dialog'),
|
|
filename = file_api.file_name(session.file),
|
|
owner = session.owner_name || session.owner,
|
|
title = rcmail.gettext('kolab_files.sessiondialog'),
|
|
content = rcmail.gettext('kolab_files.sessiondialogcontent'),
|
|
join_session = function(id) {
|
|
var viewer = file_api.file_type_supported('application/vnd.oasis.opendocument.text', rcmail.env.files_caps);
|
|
params = {action: 'edit', session: id};
|
|
|
|
file_api.file_open('', viewer, params);
|
|
};
|
|
|
|
content = content.replace('$file', filename).replace('$owner', owner);
|
|
$('div', dialog).text(content);
|
|
|
|
if (session.is_owner) {
|
|
buttons[rcmail.gettext('kolab_files.open')] = function() {
|
|
kolab_dialog_close(this);
|
|
join_session(session.id);
|
|
};
|
|
buttons[rcmail.gettext('kolab_files.close')] = function() {
|
|
kolab_dialog_close(this);
|
|
file_api.document_delete(session.id);
|
|
};
|
|
button_classes = ['mainaction edit', 'delete'];
|
|
}
|
|
else if (session.is_invited) {
|
|
button_classes = ['mainaction edit'];
|
|
// @TODO: check if not-accepted and provide "Decline invitation" button
|
|
// @TODO: Add "Accept button", add comment field to the dialog
|
|
buttons[rcmail.gettext('kolab_files.join')] = function() {
|
|
kolab_dialog_close(this);
|
|
join_session(session.id);
|
|
};
|
|
}
|
|
else {
|
|
button_classes = ['mainaction session request'];
|
|
buttons[rcmail.gettext('kolab_files.request')] = function() {
|
|
kolab_dialog_close(this);
|
|
// @TODO: Add comment field to the dialog
|
|
document_editor.invitation_request({session_id: session.id});
|
|
};
|
|
}
|
|
|
|
button_classes.push('cancel');
|
|
buttons[rcmail.gettext('kolab_files.cancel')] = function() {
|
|
kolab_dialog_close(this);
|
|
};
|
|
|
|
// show dialog window
|
|
kolab_dialog_show(dialog, {
|
|
title: title,
|
|
buttons: buttons,
|
|
button_classes: button_classes,
|
|
minHeight: 100,
|
|
height: 150
|
|
});
|
|
};
|
|
|
|
function kolab_dialog_show(content, params, onopen)
|
|
{
|
|
params = $.extend({
|
|
modal: true,
|
|
resizable: true,
|
|
minWidth: 400,
|
|
minHeight: 300,
|
|
width: 500,
|
|
height: 400
|
|
}, params || {});
|
|
|
|
// dialog close handler
|
|
params.close = function(e, ui) {
|
|
var elem, stack = rcmail.dialog_stack;
|
|
|
|
content.appendTo(document.body);
|
|
content.hide(); // for Larry's dialogs
|
|
$(this).parent().remove(); // remove dialog
|
|
|
|
// focus previously focused element (guessed)
|
|
stack.pop();
|
|
if (stack.length) {
|
|
elem = stack[stack.length-1].find('input[type!="hidden"]:not(:hidden):first');
|
|
if (!elem.length)
|
|
elem = stack[stack.length-1].parent().find('a[role="button"], .ui-dialog-buttonpane button').first();
|
|
}
|
|
|
|
(elem && elem.length ? elem : window).focus();
|
|
|
|
rcmail.ksearch_blur();
|
|
};
|
|
|
|
// This is required for Larry's dialogs
|
|
params.create = function() { content.show(); };
|
|
|
|
// display it as popup
|
|
var dialog = rcmail.show_popup_dialog(content, params.title, params.buttons, params);
|
|
|
|
if (onopen) onopen(content);
|
|
|
|
// save dialog reference, to handle focus when closing one of opened dialogs
|
|
if (!rcmail.dialog_stack)
|
|
rcmail.dialog_stack = [];
|
|
|
|
rcmail.dialog_stack.push(dialog);
|
|
};
|
|
|
|
// Handle form submit with Enter key, click first dialog button instead
|
|
function kolab_dialog_submit_handler()
|
|
{
|
|
$(this).parents('.ui-dialog').find('.ui-dialog-buttonpane button').first().click();
|
|
return false;
|
|
};
|
|
|
|
// Hides dialog
|
|
function kolab_dialog_close(dialog, destroy)
|
|
{
|
|
(rcmail.is_framed() ? window.parent : window).$(dialog).dialog(destroy ? 'destroy' : 'close');
|
|
};
|
|
|
|
// smart upload button
|
|
function kolab_files_upload_input(button)
|
|
{
|
|
var link = $(button),
|
|
file = $('<input>'),
|
|
offset = link.offset();
|
|
|
|
function move_file_input(e) {
|
|
file.css({top: (e.pageY - offset.top - 10) + 'px', left: (e.pageX - offset.left - 10) + 'px'});
|
|
}
|
|
|
|
file.attr({name: 'file[]', type: 'file', multiple: 'multiple', size: 5, title: link.attr('title'), tabindex: "-1"})
|
|
.change(function() { rcmail.files_upload('#filesuploadform'); })
|
|
.click(function() { setTimeout(function() { link.mouseleave(); }, 20); })
|
|
// opacity:0 does the trick, display/visibility doesn't work
|
|
.css({opacity: 0, cursor: 'pointer', outline: 'none', position: 'absolute'});
|
|
|
|
// In FF and IE we need to move the browser file-input's button under the cursor
|
|
// Thanks to the size attribute above we know the length of the input field
|
|
if (bw.mz || bw.ie)
|
|
file.css({marginLeft: '-80px'});
|
|
|
|
// Note: now, I observe problem with cursor style on FF < 4 only
|
|
// Need position: relative (Bug #2615)
|
|
link.css({overflow: 'hidden', cursor: 'pointer', position: 'relative'})
|
|
.mouseenter(function() { this.__active = true; })
|
|
// place button under the cursor
|
|
.mousemove(function(e) {
|
|
if (rcmail.commands['files-upload'] && this.__active)
|
|
move_file_input(e);
|
|
// move the input away if button is disabled
|
|
else
|
|
$(this).mouseleave();
|
|
})
|
|
.mouseleave(function() {
|
|
file.css({top: '-10000px', left: '-10000px'});
|
|
this.__active = false;
|
|
})
|
|
.attr('onclick', '') // remove default button action
|
|
.click(function(e) {
|
|
// forward click if mouse-enter event was missed
|
|
if (rcmail.commands['files-upload'] && !this.__active) {
|
|
this.__active = true;
|
|
move_file_input(e);
|
|
file.trigger(e);
|
|
}
|
|
})
|
|
.mouseleave() // initially disable/hide input
|
|
.append(file);
|
|
};
|
|
|
|
|
|
/***********************************************************/
|
|
/********** Main functionality **********/
|
|
/***********************************************************/
|
|
|
|
// for reordering column array (Konqueror workaround)
|
|
// and for setting some files/sessions list global variables
|
|
function kolab_files_list_coltypes(type)
|
|
{
|
|
if (!type) type = 'files';
|
|
|
|
var n, list = rcmail[type + 'list'];
|
|
|
|
rcmail.env.subject_col = null;
|
|
|
|
if ((n = $.inArray('name', rcmail.env[type + '_coltypes'])) >= 0) {
|
|
rcmail.env.subject_col = n;
|
|
list.subject_col = n;
|
|
}
|
|
|
|
list.init_header();
|
|
};
|
|
|
|
function kolab_files_set_list_options(cols, sort_col, sort_order, type)
|
|
{
|
|
var update = 0, i, idx, name, newcols = [], oldcols = rcmail.env[type + '_coltypes'];
|
|
|
|
if (sort_col === undefined)
|
|
sort_col = rcmail.env[type + '_sort_col'];
|
|
if (!sort_order)
|
|
sort_order = rcmail.env[type + '_sort_order'];
|
|
|
|
if (rcmail.env[type + '_sort_col'] != sort_col || rcmail.env[type + '_sort_order'] != sort_order) {
|
|
update = 1;
|
|
// set table header class
|
|
kolab_files_set_list_sorting(sort_col, sort_order, type);
|
|
}
|
|
|
|
if (cols && cols.length) {
|
|
// make sure new columns are added at the end of the list
|
|
for (i=0; i<oldcols.length; i++) {
|
|
name = oldcols[i];
|
|
idx = $.inArray(name, cols);
|
|
if (idx != -1) {
|
|
newcols.push(name);
|
|
delete cols[idx];
|
|
}
|
|
}
|
|
for (i=0; i<cols.length; i++)
|
|
if (cols[i])
|
|
newcols.push(cols[i]);
|
|
|
|
if (newcols.join() != oldcols.join()) {
|
|
update += 2;
|
|
oldcols = newcols;
|
|
}
|
|
}
|
|
|
|
if (update == 1)
|
|
rcmail.command(type + '-list', {sort: sort_col, reverse: sort_order == 'DESC'});
|
|
else if (update) {
|
|
rcmail.http_post('files/prefs', {
|
|
type: type,
|
|
kolab_files_list_cols: oldcols,
|
|
kolab_files_sort_col: sort_col,
|
|
kolab_files_sort_order: sort_order
|
|
}, rcmail.set_busy(true, 'loading'));
|
|
}
|
|
};
|
|
|
|
function kolab_files_set_list_sorting(sort_col, sort_order, type)
|
|
{
|
|
// set table header class
|
|
var old_col = rcmail.env[type + '_sort_col'],
|
|
old_sort = rcmail.env[type + '_sort_order'];
|
|
|
|
$('#rcm' + old_col).removeClass('sortedASC sortedDESC');
|
|
$('#rcm' + sort_col).addClass('sorted' + sort_order);
|
|
|
|
rcmail.env[type + '_sort_col'] = sort_col;
|
|
rcmail.env[type + '_sort_order'] = sort_order;
|
|
};
|
|
|
|
function kolab_files_set_coltypes(list, type)
|
|
{
|
|
var i, found, name, cols = list.list.tHead.rows[0].cells;
|
|
|
|
rcmail.env[type + '_coltypes'] = [];
|
|
|
|
for (i=0; i<cols.length; i++)
|
|
if (cols[i].id && cols[i].id.match(/^rcm/)) {
|
|
name = cols[i].id.replace(/^rcm/, '');
|
|
rcmail.env[type + '_coltypes'].push(name);
|
|
}
|
|
|
|
// if ((found = $.inArray('name', rcmail.env.files_coltypes)) >= 0)
|
|
// rcmail.env.subject_col = found;
|
|
rcmail.env.subject_col = list.subject_col;
|
|
|
|
rcmail.http_post('files/prefs', {kolab_files_list_cols: rcmail.env[type + '_coltypes'], type: type});
|
|
};
|
|
|
|
function kolab_files_sessions_list_dblclick(list)
|
|
{
|
|
rcmail.command('sessions-open');
|
|
};
|
|
|
|
function kolab_files_sessions_list_select(list)
|
|
{
|
|
var selected = list.selection.length;
|
|
|
|
rcmail.enable_command('sessions-open', selected == 1);
|
|
};
|
|
|
|
function kolab_files_sessions_list_keypress(list)
|
|
{
|
|
if (list.modkey == CONTROL_KEY)
|
|
return;
|
|
|
|
if (list.key_pressed == list.ENTER_KEY) {
|
|
// use setTimeout(), otherwise the opened dialog will be immediately closed
|
|
setTimeout(function() { rcmail.command('sessions-open'); }, 50);
|
|
}
|
|
// else if (list.key_pressed == list.DELETE_KEY || list.key_pressed == list.BACKSPACE_KEY)
|
|
// rcmail.command('sessions-delete');
|
|
};
|
|
|
|
function kolab_files_list_dblclick(list)
|
|
{
|
|
rcmail.command('files-open');
|
|
};
|
|
|
|
function kolab_files_list_select(list)
|
|
{
|
|
var selected = list.selection.length;
|
|
|
|
rcmail.enable_command(rcmail.env.file_commands_all, selected);
|
|
rcmail.enable_command(rcmail.env.file_commands, selected == 1);
|
|
|
|
// reset all-pages-selection
|
|
// if (list.selection.length && list.selection.length != list.rowcount)
|
|
// rcmail.select_all_mode = false;
|
|
|
|
if (selected == 1) {
|
|
// get file mimetype
|
|
var elem = $('tr.selected', list.list),
|
|
type = elem.data('type'),
|
|
folder = file_api.file_path(elem.data('file'));
|
|
|
|
rcmail.env.viewer = file_api.file_type_supported(type, rcmail.env.files_caps);
|
|
|
|
if (!file_api.is_writable(folder))
|
|
rcmail.enable_command('files-delete', 'files-rename', false);
|
|
}
|
|
else
|
|
rcmail.env.viewer = 0;
|
|
|
|
rcmail.enable_command('files-edit', (rcmail.env.viewer & 4) == 4);
|
|
rcmail.enable_command('files-open', rcmail.env.viewer);
|
|
};
|
|
|
|
function kolab_files_list_keypress(list)
|
|
{
|
|
if (list.modkey == CONTROL_KEY)
|
|
return;
|
|
|
|
if (list.key_pressed == list.ENTER_KEY)
|
|
rcmail.command('files-open');
|
|
else if (list.key_pressed == list.DELETE_KEY || list.key_pressed == list.BACKSPACE_KEY)
|
|
rcmail.command('files-delete');
|
|
};
|
|
|
|
function kolab_files_drag_start(e)
|
|
{
|
|
rcmail.env.drag_target = null;
|
|
|
|
if (rcmail.folder_list)
|
|
rcmail.folder_list.drag_start();
|
|
};
|
|
|
|
function kolab_files_drag_end(e)
|
|
{
|
|
if (rcmail.folder_list) {
|
|
rcmail.folder_list.drag_end();
|
|
|
|
if (rcmail.env.drag_target) {
|
|
var modkey = rcube_event.get_modifier(e),
|
|
menu = rcmail.gui_objects.file_dragmenu;
|
|
|
|
rcmail.fileslist.draglayer.hide();
|
|
|
|
if (menu && modkey == SHIFT_KEY && rcmail.commands['files-copy']) {
|
|
var pos = rcube_event.get_mouse_pos(e);
|
|
rcmail.show_menu(menu.id, true, e);
|
|
$(menu).css({top: (pos.y-10)+'px', left: (pos.x-10)+'px'});
|
|
return;
|
|
}
|
|
|
|
rcmail.command('files-move', rcmail.env.drag_target);
|
|
rcmail.env.drag_target = null;
|
|
}
|
|
}
|
|
};
|
|
|
|
function kolab_files_drag_move(e)
|
|
{
|
|
if (rcmail.folder_list) {
|
|
var mouse = rcube_event.get_mouse_pos(e);
|
|
|
|
rcmail.env.drag_target = rcmail.folder_list.intersects(mouse, true);
|
|
}
|
|
};
|
|
|
|
function kolab_files_drag_menu_action(command)
|
|
{
|
|
var menu = rcmail.gui_objects.file_dragmenu;
|
|
|
|
if (menu)
|
|
$(menu).hide();
|
|
|
|
rcmail.command(command, rcmail.env.drag_target);
|
|
};
|
|
|
|
function kolab_files_selected()
|
|
{
|
|
var files = [];
|
|
$.each(rcmail.fileslist.get_selection(), function(i, v) {
|
|
var name, row = $('#rcmrow'+v);
|
|
|
|
if (row.length == 1 && (name = row.data('file')))
|
|
files.push(name);
|
|
});
|
|
|
|
return files;
|
|
};
|
|
|
|
function kolab_files_frame_load(frame)
|
|
{
|
|
var win = frame.contentWindow,
|
|
info = rcmail.env.file_data;
|
|
|
|
try {
|
|
rcmail.file_editor = win.file_editor;
|
|
}
|
|
catch (e) {};
|
|
|
|
rcmail.enable_command('files-edit', (rcmail.file_editor && rcmail.file_editor.editable)
|
|
|| rcmail.env.editor_type
|
|
|| (file_api.file_type_supported(rcmail.env.file_data.type, rcmail.env.files_caps) & 4));
|
|
|
|
rcmail.enable_command('files-print', (rcmail.file_editor && rcmail.file_editor.printable)
|
|
|| (info && /^image\//i.test(info.type)));
|
|
|
|
// Enable image tools
|
|
rcmail.enable_command('image-scale', 'image-rotate', info && !!/^image\//.test(info.type));
|
|
rcmail.gui_objects.messagepartframe = frame;
|
|
|
|
// on edit page switch immediately to edit mode
|
|
if (rcmail.file_editor && rcmail.file_editor.editable && rcmail.env.action == 'edit')
|
|
rcmail.files_edit();
|
|
|
|
// detect Print button and check if it can be accessed
|
|
try {
|
|
if ($('#fileframe').contents().find('#print').length)
|
|
rcmail.enable_command('files-print', true);
|
|
}
|
|
catch(e) {};
|
|
};
|
|
|
|
// activate html5 file drop feature (if browser supports it)
|
|
function kolab_files_drag_drop_init(container)
|
|
{
|
|
if (!window.FormData && !(window.XMLHttpRequest && XMLHttpRequest.prototype && XMLHttpRequest.prototype.sendAsBinary)) {
|
|
return;
|
|
}
|
|
|
|
if (!container.length)
|
|
return;
|
|
|
|
$(document.body).bind('dragover dragleave drop', function(e) {
|
|
if (!file_api.is_writable())
|
|
return;
|
|
|
|
e.preventDefault();
|
|
container[e.type == 'dragover' ? 'addClass' : 'removeClass']('active');
|
|
});
|
|
|
|
container.bind('dragover dragleave', function(e) {
|
|
return kolab_files_drag_hover(e);
|
|
})
|
|
container.children('div').bind('dragover dragleave', function(e) {
|
|
return kolab_files_drag_hover(e);
|
|
})
|
|
container.get(0).addEventListener('drop', function(e) {
|
|
// abort event and reset UI
|
|
kolab_files_drag_hover(e);
|
|
return file_api.file_drop(e);
|
|
}, false);
|
|
};
|
|
|
|
// handler for drag/drop on element
|
|
function kolab_files_drag_hover(e)
|
|
{
|
|
if (!file_api.is_writable())
|
|
return;
|
|
|
|
e.preventDefault();
|
|
e.stopPropagation();
|
|
|
|
var elem = $(e.target);
|
|
|
|
if (!elem.hasClass('droptarget'))
|
|
elem = elem.parents('.droptarget');
|
|
|
|
elem[e.type == 'dragover' ? 'addClass' : 'removeClass']('hover');
|
|
};
|
|
|
|
// returns localized file size
|
|
function kolab_files_file_size(size)
|
|
{
|
|
var i, units = ['GB', 'MB', 'KB', 'B'];
|
|
|
|
size = file_api.file_size(size);
|
|
|
|
for (i = 0; i < units.length; i++)
|
|
if (size.toUpperCase().indexOf(units[i]) > 0)
|
|
return size.replace(units[i], rcmail.gettext(units[i]));
|
|
|
|
return size;
|
|
};
|
|
|
|
function kolab_files_progress_str(param)
|
|
{
|
|
var current, total = file_api.file_size(param.total).toUpperCase();
|
|
|
|
if (total.indexOf('GB') > 0)
|
|
current = parseFloat(param.current/1073741824).toFixed(1);
|
|
else if (total.indexOf('MB') > 0)
|
|
current = parseFloat(param.current/1048576).toFixed(1);
|
|
else if (total.indexOf('KB') > 0)
|
|
current = parseInt(param.current/1024);
|
|
else
|
|
current = param.current;
|
|
|
|
total = kolab_files_file_size(param.total);
|
|
|
|
return rcmail.gettext('uploadprogress')
|
|
.replace(/\$percent/, param.percent + '%')
|
|
.replace(/\$current/, current)
|
|
.replace(/\$total/, total);
|
|
};
|
|
|
|
function kolab_files_share_form_init()
|
|
{
|
|
$('fieldset > table', rcmail.gui_objects.shareform).each(function() {
|
|
var cnt = 0,
|
|
mode = $(this).data('mode'),
|
|
single = $(this).data('single');
|
|
|
|
$('tbody > tr', this).each(function(i, row) {
|
|
if (!i) {
|
|
$('button.submit', row).on('click', function() { file_api.sharing_submit(rcmail.env.folder, row, mode); });
|
|
$('input[data-autocomplete]').each(function() {
|
|
var input = $(this), req_name = 'filesac-' + mode;
|
|
kolab_files_autocomplete(input, req_name, function(e) {
|
|
$(row).find('input[type=hidden]').each(function() {
|
|
$(this).val(e.data[this.name] || '');
|
|
});
|
|
});
|
|
});
|
|
}
|
|
else {
|
|
cnt++;
|
|
$('button.delete', row).on('click', function() { file_api.sharing_delete(rcmail.env.folder, row, mode); });
|
|
$('select,input[type=text]', row).on('change', function() { file_api.sharing_update(rcmail.env.folder, row, mode); });
|
|
}
|
|
});
|
|
|
|
if (single && cnt) {
|
|
$('tbody > tr:first', this).find('button.submit, input, select').prop('disabled', true);
|
|
}
|
|
});
|
|
};
|
|
|
|
function kolab_files_autocomplete(input, action, insert_callback)
|
|
{
|
|
rcmail.init_address_input_events(input, {action: action});
|
|
|
|
// "Redirect" autocomplete requests to Chwala API
|
|
if (rcmail.env.files_api_version > 3) {
|
|
rcmail.addEventListener('request' + action, function(post) {
|
|
var params = {search: post._search, mode: input.data('autocomplete') || 'user', folder: rcmail.env.folder},
|
|
callback = function(response) {
|
|
var result = response.result || [];
|
|
$.each(result, function() {
|
|
// add fake email to skip Roundcube's group expanding code
|
|
if (this.type == 'group' && !this.email)
|
|
this.email = 1;
|
|
});
|
|
|
|
rcmail.ksearch_query_results(result, post._search, post._reqid);
|
|
},
|
|
error_callback = function(o, status, err, data) {
|
|
file_api.http_error(o, status, err, data);
|
|
rcmail.ksearch_query_results([], post._search, post._reqid);
|
|
};
|
|
|
|
return file_api.get('autocomplete', params, callback, error_callback);
|
|
});
|
|
}
|
|
|
|
// Update hidden fields on selection
|
|
rcmail.addEventListener('autocomplete_insert', function(e) {
|
|
if (e.field == input[0]) {
|
|
input.val(e.insert.replace(/[, ]+$/, ''));
|
|
}
|
|
if (insert_callback)
|
|
insert_callback(e);
|
|
});
|
|
};
|
|
|
|
|
|
/**********************************************************/
|
|
/********* document editor functionality **********/
|
|
/**********************************************************/
|
|
|
|
// Initialize document toolbar functionality
|
|
function document_editor_init()
|
|
{
|
|
var info = rcmail.env.file_data;
|
|
|
|
rcmail.enable_command('document-export', 'document-print', true);
|
|
|
|
if (info && info.session && info.session.is_owner)
|
|
rcmail.enable_command('document-close', 'document-editors', true);
|
|
};
|
|
|
|
// executed on editing session termination
|
|
function document_editor_close()
|
|
{
|
|
var dialog = $('<div>').addClass('popupdialog').attr('role', 'alertdialog')
|
|
.html($('<span>').text(rcmail.gettext('kolab_files.sessionterminated')));
|
|
|
|
rcmail.alert_dialog(dialog, function() { window.close(); }, {
|
|
title: rcmail.gettext('kolab_files.sessionterminatedtitle')
|
|
});
|
|
|
|
return false; // skip Chwala's error message
|
|
};
|
|
|
|
rcube_webmail.prototype.document_save = function()
|
|
{
|
|
document_editor.save(function(data) {
|
|
rcmail.enable_command('document-save', false);
|
|
});
|
|
};
|
|
|
|
rcube_webmail.prototype.document_export = function(type)
|
|
{
|
|
document_editor.export(type || 'odt');
|
|
};
|
|
|
|
rcube_webmail.prototype.document_print = function()
|
|
{
|
|
document_editor.print();
|
|
};
|
|
|
|
rcube_webmail.prototype.document_editors = function()
|
|
{
|
|
kolab_files_editors_dialog();
|
|
};
|
|
|
|
// close editing session
|
|
rcube_webmail.prototype.document_close = function()
|
|
{
|
|
var delete_fn = function() {
|
|
document_editor.terminate(function() {
|
|
var win = window.opener || window.parent;
|
|
|
|
if (win && win.rcmail && win.file_api)
|
|
win.file_api.document_delete(rcmail.env.file_data.session.id);
|
|
|
|
// For Elastic: hide the parent dialog
|
|
if (rcmail.is_framed()) {
|
|
parent.$('.ui-dialog:visible button.cancel').click();
|
|
}
|
|
|
|
window.close();
|
|
});
|
|
};
|
|
|
|
// check document "unsaved changes" state and display a warning
|
|
// skip the warning for WOPI, Collabora will save the document anyway on session close
|
|
if (this.commands['document-save'] && (!this.env.file_data.viewer || !this.env.file_data.viewer.wopi))
|
|
this.confirm_dialog(this.gettext('kolab_files.unsavedchanges'), 'kolab_files.terminate', delete_fn, {button_class: 'delete'});
|
|
else
|
|
delete_fn();
|
|
};
|
|
|
|
// document editors management dialog
|
|
function kolab_files_editors_dialog(session)
|
|
{
|
|
var items = [], buttons = {},
|
|
info = rcmail.env.file_data,
|
|
dialog = $('#document-editors-dialog'),
|
|
comment = $('#invitation-comment');
|
|
|
|
if (!info || !info.session || !info.session.is_owner)
|
|
return;
|
|
|
|
// always add the session organizer
|
|
items.push(kolab_files_attendee_record(info.session.owner, 'organizer'));
|
|
|
|
$.each(info.session.invitations || [], function(i, u) {
|
|
var record = kolab_files_attendee_record(u.user, u.status, u.user_name);
|
|
items.push(record);
|
|
info.session.invitations[i].record = record;
|
|
});
|
|
|
|
$('table > tbody', dialog).html(items);
|
|
|
|
buttons[rcmail.gettext('kolab_files.close')] = function() {
|
|
kolab_dialog_close(this);
|
|
};
|
|
|
|
// show dialog window
|
|
kolab_dialog_show(dialog, {
|
|
title: rcmail.gettext('kolab_files.manageeditors'),
|
|
buttons: buttons,
|
|
button_classes: ['cancel']
|
|
});
|
|
|
|
if (!rcmail.env.editors_dialog) {
|
|
rcmail.env.editors_dialog = dialog;
|
|
|
|
kolab_files_autocomplete($('#invitation-editor-name'), 'files/autocomplete', function(e) {
|
|
var success = false;
|
|
if (e.field.name == 'participant') {
|
|
// e.data && e.data.type == 'group' ? 'GROUP' : 'INDIVIDUAL'
|
|
success = kolab_files_add_attendees(e.insert, comment.val());
|
|
}
|
|
if (e.field && success) {
|
|
e.field.value = '';
|
|
}
|
|
});
|
|
|
|
$('#invitation-editor-add').click(function() {
|
|
var input = $('#invitation-editor-name');
|
|
rcmail.ksearch_blur();
|
|
if (kolab_files_add_attendees(input.val(), comment.val())) {
|
|
input.val('');
|
|
}
|
|
});
|
|
}
|
|
};
|
|
|
|
// add the given list of participants
|
|
function kolab_files_add_attendees(names, comment)
|
|
{
|
|
var i, item, success, email, name, attendees = {}, counter = 0;
|
|
|
|
names = file_api.explode_quoted_string(names.replace(/,\s*$/, ''), ',');
|
|
|
|
// parse name/email pairs
|
|
for (i = 0; i < names.length; i++) {
|
|
email = name = '';
|
|
item = $.trim(names[i]);
|
|
|
|
if (!item.length) {
|
|
continue;
|
|
} // address in brackets without name (do nothing)
|
|
else if (item.match(/^<[^@]+@[^>]+>$/)) {
|
|
email = item.replace(/[<>]/g, '');
|
|
} // address without brackets and without name (add brackets)
|
|
else if (rcube_check_email(item)) {
|
|
email = item;
|
|
} // address with name
|
|
else if (item.match(/([^\s<@]+@[^>]+)>*$/)) {
|
|
email = RegExp.$1;
|
|
name = item.replace(email, '').replace(/^["\s<>]+/, '').replace(/["\s<>]+$/, '');
|
|
}
|
|
|
|
if (email) {
|
|
attendees[email] = {user: email, name: name};
|
|
counter++;
|
|
}
|
|
else {
|
|
rcmail.alert_dialog(rcmail.gettext('noemailwarning'));
|
|
}
|
|
}
|
|
|
|
success = counter > 0;
|
|
|
|
// remove already existing entries
|
|
if (counter) {
|
|
if (attendees[rcmail.env.file_data.session.owner]) {
|
|
delete attendees[this.user];
|
|
counter--;
|
|
}
|
|
$.each(rcmail.env.file_data.session.invitations || [], function() {
|
|
if (this.user in attendees) {
|
|
delete attendees[this.user];
|
|
counter--;
|
|
}
|
|
});
|
|
}
|
|
|
|
if (counter)
|
|
file_api.document_invite(rcmail.env.file_data.session.id, attendees, comment);
|
|
|
|
return success;
|
|
};
|
|
|
|
function kolab_files_attendee_record(user, status, username)
|
|
{
|
|
var options = [], select,
|
|
type = status ? status.replace(/-.*$/, '') : '',
|
|
name = $('<td class="name">').text(user),
|
|
buttons = $('<td class="options">'),
|
|
state = $('<td class="status">').text(rcmail.gettext('kolab_files.status' + type));
|
|
|
|
// @todo: accept/decline invitation request
|
|
if (type == 'requested' || status == 'accepted-owner' || status == 'declined-owner') {
|
|
select = $('<select>').change(function() {
|
|
var val = $(this).val(), map = {accepted: 'invitation_accept', declined: 'invitation_decline'};
|
|
if (map[val])
|
|
document_editor[map[val]]({user: user, session_id: rcmail.env.file_data.session.id});
|
|
});
|
|
|
|
if (type == 'requested')
|
|
options.push($('<option>').text(rcmail.gettext('kolab_files.statusrequested')).attr('value', 'requested'));
|
|
|
|
options.push($('<option>').text(rcmail.gettext('kolab_files.statusaccepted')).attr('value', 'accepted'));
|
|
options.push($('<option>').text(rcmail.gettext('kolab_files.statusdeclined')).attr('value', 'declined'));
|
|
|
|
state.html(select.html(options).val(type));
|
|
}
|
|
|
|
// delete button
|
|
if (status != 'organizer') {
|
|
$('<a>').attr({'class': 'delete', href: '#', title: rcmail.gettext('kolab_files.removeparticipant')})
|
|
.click(function() {
|
|
file_api.document_cancel(rcmail.env.file_data.session.id, [user]);
|
|
})
|
|
.appendTo(buttons);
|
|
}
|
|
|
|
if (username && status != 'organizer')
|
|
name.html($('<a>').attr({href: 'mailto:' + user, 'class': 'mailtolink'}).text(username))
|
|
.click(function(e) { rcmail.command('compose', user, e.target, e); return false; });
|
|
|
|
return $('<tr>').attr('class', 'invitation' + (type ? ' ' + type : ''))
|
|
.append(name).append(state).append(buttons);
|
|
};
|
|
|
|
function document_editor_invitation_handler(invitation)
|
|
{
|
|
// make the "More" link clickable
|
|
$('#' + invitation.id).parent('div').click(function() { kolab_files_invitation_dialog(invitation); });
|
|
};
|
|
|
|
function kolab_files_invitation_dialog(invitation)
|
|
{
|
|
var text, records = [], content = [], buttons = {}, button_classes = [],
|
|
dialog = $('#document-invitation-dialog'),
|
|
data_map = {status: 'status', 'changed': 'when', filename: 'file', comment: 'comment'},
|
|
record_fn = function(type, label, value) {
|
|
records.push($('<tr>').attr('class', type)
|
|
.append($('<td class="label">').text(rcmail.gettext('kolab_files.'+ label)))
|
|
.append($('<td>').text(value))
|
|
);
|
|
};
|
|
join_session = function() {
|
|
var viewer = file_api.file_type_supported('application/vnd.oasis.opendocument.text', rcmail.env.files_caps);
|
|
params = {action: 'edit', session: invitation.session_id};
|
|
|
|
file_api.file_open('', viewer, params);
|
|
};
|
|
|
|
if (!dialog.length)
|
|
dialog = $('<div>').attr({id: 'document-invitation-dialog', role: 'dialog', 'aria-hidden': 'true'})
|
|
.append($('<div>'))
|
|
.appendTo(document.body);
|
|
|
|
if (!invitation.is_session_owner) {
|
|
if (invitation.status == 'invited') {
|
|
text = document_editor.invitation_msg(invitation);
|
|
button_classes = ['session join', 'session accept', 'session decline delete'];
|
|
|
|
buttons[rcmail.gettext('kolab_files.join')] = function() {
|
|
join_session();
|
|
kolab_dialog_close(this);
|
|
};
|
|
buttons[rcmail.gettext('kolab_files.accept')] = function() {
|
|
document_editor.invitation_accept(invitation);
|
|
kolab_dialog_close(this);
|
|
};
|
|
buttons[rcmail.gettext('kolab_files.decline')] = function() {
|
|
document_editor.invitation_decline(invitation);
|
|
kolab_dialog_close(this);
|
|
};
|
|
}
|
|
else if (invitation.status == 'declined-owner') {
|
|
// @todo: add option to request for an invitation again?
|
|
text = document_editor.invitation_msg(invitation);
|
|
}
|
|
else if (invitation.status == 'accepted-owner') {
|
|
text = document_editor.invitation_msg(invitation);
|
|
|
|
button_classes = ['mainaction session join'];
|
|
buttons[rcmail.gettext('kolab_files.join')] = function() {
|
|
join_session();
|
|
kolab_dialog_close(this);
|
|
};
|
|
}
|
|
}
|
|
else {
|
|
if (invitation.status == 'accepted') {
|
|
text = document_editor.invitation_msg(invitation);
|
|
}
|
|
else if (invitation.status == 'declined') {
|
|
// @todo: add option to invite the user again?
|
|
text = document_editor.invitation_msg(invitation);
|
|
}
|
|
else if (invitation.status == 'requested') {
|
|
text = document_editor.invitation_msg(invitation);
|
|
|
|
button_classes = ['session accept', 'session decline delete'];
|
|
buttons[rcmail.gettext('kolab_files.accept')] = function() {
|
|
document_editor.invitation_accept(invitation);
|
|
kolab_dialog_close(this);
|
|
};
|
|
buttons[rcmail.gettext('kolab_files.decline')] = function() {
|
|
document_editor.invitation_decline(invitation);
|
|
kolab_dialog_close(this);
|
|
};
|
|
}
|
|
}
|
|
|
|
if (text) {
|
|
$.each(data_map, function(i, label) {
|
|
var value = invitation[i];
|
|
if (value) {
|
|
if (i == 'status')
|
|
value = rcmail.gettext('kolab_files.status' + value.replace(/-.*$/, ''));
|
|
|
|
record_fn(i, label, value);
|
|
}
|
|
});
|
|
|
|
content.push($('<div>').text(text));
|
|
content.push($('<table class="propform">').html(records));
|
|
}
|
|
|
|
button_classes.push('cancel');
|
|
buttons[rcmail.gettext('kolab_files.close')] = function() {
|
|
kolab_dialog_close(this);
|
|
};
|
|
|
|
$('div', dialog).html(content);
|
|
|
|
// show dialog window
|
|
kolab_dialog_show(dialog, {
|
|
title: rcmail.gettext('kolab_files.invitationtitle').replace('$file', invitation.filename),
|
|
buttons: buttons,
|
|
button_classes: button_classes
|
|
});
|
|
};
|
|
|
|
/***********************************************************/
|
|
/********** Commands **********/
|
|
/***********************************************************/
|
|
|
|
rcube_webmail.prototype.files_sort = function(props)
|
|
{
|
|
this.files_sort_handler(props, 'files');
|
|
};
|
|
|
|
rcube_webmail.prototype.sessions_sort = function(props)
|
|
{
|
|
this.files_sort_handler(props, 'sessions');
|
|
};
|
|
|
|
rcube_webmail.prototype.files_sort_handler = function(col, type)
|
|
{
|
|
var params = {},
|
|
c = type == 'files' ? '' : ('_' + type),
|
|
sort_order = this.env[type + '_sort_order'],
|
|
sort_col = !this.env['kolab_files' + c + '_disabled_sort_col'] ? col : this.env[type + '_sort_col'];
|
|
|
|
if (!this.env['kolab_files' + c + '_disabled_sort_order'])
|
|
sort_order = this.env[type + '_sort_col'] == sort_col && sort_order == 'ASC' ? 'DESC' : 'ASC';
|
|
|
|
// set table header and update env
|
|
kolab_files_set_list_sorting(sort_col, sort_order, type);
|
|
|
|
this.http_post('files/prefs', {kolab_files_sort_col: sort_col, kolab_files_sort_order: sort_order, type: type});
|
|
|
|
params.sort = sort_col;
|
|
params.reverse = sort_order == 'DESC';
|
|
|
|
this.command(type + '-list', params);
|
|
};
|
|
|
|
rcube_webmail.prototype.files_search = function()
|
|
{
|
|
var value = $(this.gui_objects.filesearchbox).val();
|
|
|
|
if (value)
|
|
file_api.file_search(value, $('#search_all_folders').is(':checked'));
|
|
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(prop, elem, event)
|
|
{
|
|
this.hide_menu('folderoptions', event);
|
|
this.confirm_dialog(this.get_label('kolab_files.folderdeleteconfirm'), 'delete', function() {
|
|
file_api.folder_delete(file_api.env.folder);
|
|
});
|
|
};
|
|
|
|
rcube_webmail.prototype.files_delete = function()
|
|
{
|
|
this.confirm_dialog(this.get_label('kolab_files.filedeleteconfirm'), 'delete', function() {
|
|
var files = rcmail.env.file ? [rcmail.env.file] : kolab_files_selected();
|
|
file_api.file_delete(files);
|
|
});
|
|
};
|
|
|
|
rcube_webmail.prototype.files_move = function(folder, obj, event, files)
|
|
{
|
|
if (!files)
|
|
files = kolab_files_selected();
|
|
|
|
if (!folder) {
|
|
var ref = this;
|
|
return this.files_folder_selector(event, function(folder) {
|
|
ref.files_move(folder, null, event, files);
|
|
});
|
|
}
|
|
|
|
file_api.file_move(files, folder);
|
|
};
|
|
|
|
rcube_webmail.prototype.files_copy = function(folder, obj, event, files)
|
|
{
|
|
if (!files)
|
|
files = kolab_files_selected();
|
|
|
|
if (!folder) {
|
|
var ref = this;
|
|
return this.files_folder_selector(event, function(folder) {
|
|
ref.files_copy(folder, null, event, files);
|
|
});
|
|
}
|
|
|
|
file_api.file_copy(files, folder);
|
|
};
|
|
|
|
// create folder selector popup
|
|
rcube_webmail.prototype.files_folder_selector = function(event, callback)
|
|
{
|
|
if (this.folder_selector_reset)
|
|
this.destroy_entity_selector('folder-selector');
|
|
|
|
// The list is incomplete, reset needed before next use
|
|
this.folder_selector_reset = file_api.list_updates > 0;
|
|
|
|
this.entity_selector('folder-selector', callback, file_api.env.folders, function(folder, a, folder_fullname) {
|
|
var n = folder.depth || 0,
|
|
row = $('<li>');
|
|
|
|
if (folder.virtual || folder.readonly)
|
|
a.addClass('virtual').attr({'aria-disabled': 'true', tabindex: '-1'});
|
|
else
|
|
a.addClass('active').data('id', folder_fullname);
|
|
|
|
a.css('padding-left', n ? (n * 16) + 'px' : 0);
|
|
|
|
// add folder name element
|
|
a.append($('<span>').text(folder.name));
|
|
|
|
return row.append(a);
|
|
}, event);
|
|
};
|
|
|
|
rcube_webmail.prototype.files_upload = function(form)
|
|
{
|
|
if (form)
|
|
file_api.file_upload(form);
|
|
};
|
|
|
|
rcube_webmail.prototype.files_list = function(param)
|
|
{
|
|
// just rcmail wrapper, to handle command busy states
|
|
file_api.file_list(param);
|
|
};
|
|
|
|
rcube_webmail.prototype.files_list_update = function(head)
|
|
{
|
|
var list = this.fileslist;
|
|
|
|
$('thead', list.fixed_header ? list.fixed_header : list.list).html(head);
|
|
kolab_files_list_coltypes();
|
|
file_api.file_list();
|
|
};
|
|
|
|
rcube_webmail.prototype.sessions_list = function(param)
|
|
{
|
|
// just rcmail wrapper, to handle command busy states
|
|
file_api.session_list(param);
|
|
};
|
|
|
|
rcube_webmail.prototype.sessions_list_update = function(head)
|
|
{
|
|
var list = this.sessionslist;
|
|
|
|
$('thead', list.fixed_header ? list.fixed_header : list.list).html(head);
|
|
kolab_files_list_coltypes('sessions');
|
|
file_api.sessions_list();
|
|
};
|
|
|
|
rcube_webmail.prototype.files_get = function()
|
|
{
|
|
var files = this.env.file ? [this.env.file] : kolab_files_selected();
|
|
|
|
if (files.length == 1)
|
|
file_api.file_get(files[0], {'force-download': true});
|
|
};
|
|
|
|
rcube_webmail.prototype.files_open = function()
|
|
{
|
|
var files = kolab_files_selected();
|
|
|
|
if (files.length == 1)
|
|
file_api.file_open(files[0], rcmail.env.viewer);
|
|
};
|
|
|
|
// enable file editor
|
|
rcube_webmail.prototype.files_edit = function(session)
|
|
{
|
|
var files, readonly, sessions, file = this.env.file,
|
|
params = {action: 'edit'};
|
|
|
|
if (!file && !this.env.action) {
|
|
files = kolab_files_selected();
|
|
if (files.length == 1)
|
|
file = files[0];
|
|
readonly = !file_api.is_writable(file_api.file_path(file));
|
|
}
|
|
else {
|
|
readonly = !this.env.file_data.writable;
|
|
}
|
|
|
|
// check if the folder is read-only or there are ongoing sessions
|
|
// in such cases display dialog for the user to decide what to do
|
|
if (!session) {
|
|
sessions = file_api.file_sessions(file);
|
|
if (sessions.length || readonly) {
|
|
kolab_files_file_edit_dialog(file, sessions, readonly);
|
|
return;
|
|
}
|
|
}
|
|
else if (session !== true)
|
|
params.session = session;
|
|
|
|
if (this.file_editor && this.file_editor.editable && !session) {
|
|
this.file_editor.enable();
|
|
this.enable_command('files-save', true);
|
|
}
|
|
else if (this.env.file) {
|
|
var viewer = file_api.file_type_supported(this.env.file_data.type, this.env.files_caps);
|
|
params.local = true;
|
|
file_api.file_open(file, viewer, params);
|
|
}
|
|
else if (file) {
|
|
file_api.file_open(file, this.env.viewer, params);
|
|
}
|
|
};
|
|
|
|
// save changes to the file
|
|
rcube_webmail.prototype.files_save = function()
|
|
{
|
|
if (!this.file_editor)
|
|
return;
|
|
|
|
// binary files like ODF need to be updated using FormData
|
|
if (this.file_editor.getContentCallback) {
|
|
if (!file_api.file_uploader_support())
|
|
return;
|
|
|
|
file_api.req = file_api.set_busy(true, 'saving');
|
|
// this.file_editor.disable();
|
|
this.file_editor.getContentCallback(function(content, filename) {
|
|
file_api.file_uploader([content], {
|
|
action: 'file_update',
|
|
params: {file: rcmail.env.file, info: 1, token: file_api.env.token},
|
|
response_handler: 'file_save_response',
|
|
fieldname: 'content',
|
|
single: true
|
|
});
|
|
});
|
|
|
|
return;
|
|
}
|
|
|
|
var content = this.file_editor.getContent();
|
|
|
|
file_api.file_save(this.env.file, content);
|
|
};
|
|
|
|
rcube_webmail.prototype.files_print = function()
|
|
{
|
|
if (this.file_editor && this.file_editor.printable)
|
|
this.file_editor.print();
|
|
else if (/^image\//i.test(this.env.file_data.type)) {
|
|
var frame = $('#fileframe').get(0),
|
|
win = frame ? frame.contentWindow : null;
|
|
|
|
if (win) {
|
|
win.focus();
|
|
win.print();
|
|
}
|
|
}
|
|
else {
|
|
// e.g. Print button in PDF viewer
|
|
try {
|
|
$('#fileframe').contents().find('#print').click();
|
|
}
|
|
catch(e) {};
|
|
}
|
|
};
|
|
|
|
rcube_webmail.prototype.files_set_quota = function(p)
|
|
{
|
|
if (p.total && window.file_api) {
|
|
p.used *= 1024;
|
|
p.total *= 1024;
|
|
p.title = file_api.file_size(p.used) + ' / ' + file_api.file_size(p.total)
|
|
+ ' (' + p.percent + '%)';
|
|
}
|
|
|
|
p.type = this.env.quota_type;
|
|
|
|
this.set_quota(p);
|
|
};
|
|
|
|
rcube_webmail.prototype.files_create = function()
|
|
{
|
|
kolab_files_file_create_dialog();
|
|
};
|
|
|
|
rcube_webmail.prototype.files_rename = function()
|
|
{
|
|
var files = kolab_files_selected();
|
|
kolab_files_file_rename_dialog(files[0]);
|
|
};
|
|
|
|
rcube_webmail.prototype.folder_create = function()
|
|
{
|
|
kolab_files_folder_create_dialog();
|
|
};
|
|
|
|
rcube_webmail.prototype.folder_rename = function(prop, elem, event)
|
|
{
|
|
this.hide_menu('folderoptions', event);
|
|
kolab_files_folder_edit_dialog();
|
|
};
|
|
|
|
rcube_webmail.prototype.folder_share = function(prop, elem, event)
|
|
{
|
|
this.hide_menu('folderoptions', event);
|
|
kolab_files_folder_share_dialog();
|
|
};
|
|
|
|
rcube_webmail.prototype.folder_mount = function(prop, elem, event)
|
|
{
|
|
this.hide_menu('folderoptions', event);
|
|
kolab_files_folder_mount_dialog();
|
|
};
|
|
|
|
// open a session dialog
|
|
rcube_webmail.prototype.sessions_open = function()
|
|
{
|
|
var id = this.sessionslist.get_selection(),
|
|
session = id ? file_api.env.sessions_list[id] : null;
|
|
|
|
if (session)
|
|
kolab_files_session_dialog(session);
|
|
};
|
|
|
|
|
|
/**********************************************************/
|
|
/********* Files API handler **********/
|
|
/**********************************************************/
|
|
|
|
function kolab_files_ui()
|
|
{
|
|
this.requests = {};
|
|
this.uploads = [];
|
|
this.list_updates = 0;
|
|
|
|
/*
|
|
// Called on "session expired" session
|
|
this.logout = function(response) {};
|
|
|
|
// called when a request timed out
|
|
this.request_timed_out = function() {};
|
|
|
|
// called on start of the request
|
|
this.set_request_time = function() {};
|
|
|
|
// called on request response
|
|
this.update_request_time = function() {};
|
|
*/
|
|
// set state
|
|
this.set_busy = function(a, message)
|
|
{
|
|
if (this.req)
|
|
rcmail.hide_message(this.req);
|
|
|
|
return rcmail.set_busy(a, message);
|
|
};
|
|
|
|
// displays error message
|
|
this.display_message = function(label, type)
|
|
{
|
|
return rcmail.display_message(this.t(label), type);
|
|
};
|
|
|
|
this.http_error = function(request, status, err, data)
|
|
{
|
|
rcmail.http_error(request, status, err, data ? data.req_id : null);
|
|
};
|
|
|
|
// check if specified/current folder/view is writable
|
|
this.is_writable = function(folder)
|
|
{
|
|
if (!folder)
|
|
folder = this.env.folder;
|
|
|
|
if (!folder)
|
|
return false;
|
|
|
|
var all_folders = $.extend({}, this.env.folders, this.search_results);
|
|
|
|
if (!all_folders[folder] || all_folders[folder].readonly || all_folders[folder].virtual)
|
|
return false;
|
|
|
|
return true;
|
|
};
|
|
|
|
// Check if specified folder (hierarchy) supports sharing
|
|
this.is_shareable = function(folder)
|
|
{
|
|
if (!folder)
|
|
folder = this.env.folder;
|
|
|
|
if (!folder)
|
|
return false;
|
|
|
|
var root = folder.split(this.env.directory_separator)[0],
|
|
caps = this.env.caps;
|
|
|
|
if (this.env.caps.MOUNTPOINTS[root])
|
|
caps = root != folder ? this.env.caps.MOUNTPOINTS[root] : {};
|
|
|
|
return !!caps.ACL;
|
|
};
|
|
|
|
// folders list request
|
|
this.folder_list = function(params, update)
|
|
{
|
|
if (!params)
|
|
params = {}
|
|
|
|
params.permissions = 1;
|
|
|
|
if (params.level === undefined)
|
|
params.level = -1;
|
|
|
|
if (update) {
|
|
this.list_updates++;
|
|
params.req = rcmail.display_message('', 'loading');
|
|
}
|
|
else {
|
|
params.req = this.set_busy(true, 'loading');
|
|
this.list_params = params;
|
|
}
|
|
|
|
this.request('folder_list', params, update ? 'folder_list_update_response' : 'folder_list_response');
|
|
};
|
|
|
|
// folder list response handler
|
|
this.folder_list_response = function(response, params)
|
|
{
|
|
rcmail.hide_message(params.req);
|
|
|
|
if (!this.response(response))
|
|
return;
|
|
|
|
var folder, first, body, rows = [],
|
|
list_selector = rcmail.env.folder_list_selector || '#files-folder-list',
|
|
search_selector = rcmail.env.folder_search_selector || '#foldersearch',
|
|
elem = $(list_selector),
|
|
searchbox = $(search_selector),
|
|
list = $('<ul class="treelist listing folderlist"></ul>'),
|
|
collections = ['audio', 'video', 'image', 'document'];
|
|
|
|
// try parent window if the list element does not exist
|
|
// i.e. called from a dialog in parent window
|
|
if (!elem.length && rcmail.is_framed() && (rcmail.env.task != 'files' || (rcmail.env.action != 'open' && rcmail.env.action != 'edit'))) {
|
|
body = window.parent.document.body;
|
|
elem = $(list_selector, body);
|
|
searchbox = $(search_selector, body);
|
|
}
|
|
|
|
this.list_element = list;
|
|
|
|
if (elem.data('no-collections') == true)
|
|
collections = [];
|
|
|
|
this.env.folders = this.folder_list_parse(response.result && response.result.list ? response.result.list : response.result);
|
|
|
|
rcmail.enable_command('files-create', response.result && response.result.list && response.result.list.length > 0);
|
|
|
|
if (!elem.length)
|
|
return;
|
|
|
|
elem.html('');
|
|
|
|
$.each(this.env.folders, function(i, f) {
|
|
var row;
|
|
if (row = file_api.folder_list_row(i, f)) {
|
|
if (!first)
|
|
first = i;
|
|
rows.push(row);
|
|
}
|
|
});
|
|
|
|
// add virtual collections
|
|
$.each(collections, function(i, n) {
|
|
var row = $('<li class="mailbox collection ' + n + '"></li>');
|
|
|
|
row.attr('id', 'rcmli' + rcmail.html_identifier_encode('folder-collection-' + n))
|
|
.append($('<a class="name"></a>').text(rcmail.gettext('kolab_files.collection_' + n)))
|
|
|
|
rows.push(row);
|
|
});
|
|
|
|
// add Sessions entry
|
|
if (rcmail.task == 'files' && !rcmail.env.action && this.env.caps && this.env.caps.DOCEDIT) {
|
|
rows.push($('<li class="mailbox collection sessions"></li>')
|
|
.attr('id', 'rcmli' + rcmail.html_identifier_encode('folder-collection-sessions'))
|
|
.append($('<a class="name"></a>').text(rcmail.gettext('kolab_files.sessions')))
|
|
);
|
|
}
|
|
|
|
list.append(rows).appendTo(elem)
|
|
.on('click', 'a.subscription', function(e) {
|
|
return file_api.folder_list_subscription_button_click(this);
|
|
})
|
|
.on('mouseover', 'a.name', function() {
|
|
rcube_webmail.long_subject_title_ex(this);
|
|
});
|
|
|
|
if (rcmail.task == 'files' && rcmail.env.contextmenu)
|
|
list.on('contextmenu', function(e) {
|
|
var elem = $(e.target).closest('li');
|
|
id = rcmail.html_identifier_decode(elem.attr('id').replace(/^rcmli/, ''));
|
|
rcmail.contextmenu.show_one(e, elem[0], id, rcmail.env.folders_cm);
|
|
});
|
|
|
|
if (rcmail.folder_list) {
|
|
rcmail.folder_list.reset();
|
|
this.search_results_widget = null;
|
|
}
|
|
|
|
// init treelist widget
|
|
rcmail.folder_list = new rcube_treelist_widget(list, {
|
|
selectable: true,
|
|
id_prefix: 'rcmli',
|
|
parent_focus: true,
|
|
searchbox: searchbox,
|
|
id_encode: rcmail.html_identifier_encode,
|
|
id_decode: rcmail.html_identifier_decode,
|
|
check_droptarget: function(node) {
|
|
return !node.virtual
|
|
&& node.id != file_api.env.folder
|
|
&& $.inArray('readonly', node.classes) == -1
|
|
&& $.inArray('collection', node.classes) == -1;
|
|
}
|
|
});
|
|
|
|
rcmail.folder_list
|
|
.addEventListener('collapse', function(node) { file_api.folder_collapsed(node); })
|
|
.addEventListener('expand', function(node) { file_api.folder_collapsed(node); })
|
|
.addEventListener('beforeselect', function(node) { return !rcmail.busy; })
|
|
.addEventListener('search', function(search) { file_api.folder_search(search); })
|
|
.addEventListener('select', function(node) {
|
|
if (file_api.search_results_widget)
|
|
file_api.search_results_widget.select();
|
|
file_api.folder_select(node.id);
|
|
});
|
|
|
|
// select first/current folder
|
|
if (response.result.auth_errors && response.result.auth_errors.length)
|
|
this.env.folder = this.env.collection = null;
|
|
else if (this.env.folder)
|
|
rcmail.folder_list.select(this.env.folder);
|
|
else if (this.env.collection)
|
|
rcmail.folder_list.select('folder-collection-' + this.env.collection);
|
|
else if (folder = this.env.init_folder) {
|
|
if (this.env.folders[folder]) {
|
|
this.env.init_folder = null;
|
|
rcmail.folder_list.select(folder);
|
|
}
|
|
}
|
|
else if (folder = this.env.init_collection) {
|
|
this.env.init_collection = null;
|
|
rcmail.folder_list.select('folder-collection-' + folder);
|
|
}
|
|
else if (first)
|
|
rcmail.folder_list.select(first);
|
|
|
|
// handle authentication errors on external sources
|
|
this.folder_list_auth_errors(response.result);
|
|
|
|
// Fetch 2 levels of folder hierarchy for all mount points that
|
|
// do not support fast folders list
|
|
if (rcmail.env.files_api_version > 4) {
|
|
var ref = this;
|
|
$.each(this.env.caps.MOUNTPOINTS || [], function(k, v) {
|
|
if (!v.FAST_FOLDER_LIST)
|
|
ref.folder_list({level: 2, folder: k}, true);
|
|
});
|
|
}
|
|
|
|
// Elastic: Set notree class on the folder list
|
|
var callback = function() {
|
|
list[list.find('.treetoggle').length > 0 ? 'removeClass' : 'addClass']('notree');
|
|
};
|
|
if (window.MutationObserver)
|
|
(new MutationObserver(callback)).observe(list.get(0), {childList: true, subtree: true});
|
|
callback();
|
|
};
|
|
|
|
// folder list response handler
|
|
this.folder_list_update_response = function(response, params)
|
|
{
|
|
rcmail.hide_message(params.req);
|
|
|
|
this.list_updates--;
|
|
|
|
if (!this.response(response))
|
|
return;
|
|
|
|
// handle authentication errors on external sources
|
|
this.folder_list_auth_errors(response.result);
|
|
|
|
// Update the list
|
|
this.folder_list_merge(params.folder, response.result.list, params.level);
|
|
};
|
|
|
|
this.folder_list_update_wait = function(folder)
|
|
{
|
|
var ref = this;
|
|
|
|
// do maximum 10 parallel requests
|
|
if (this.list_updates > 10)
|
|
return setTimeout(function() { ref.folder_list_update_wait(folder); }, 20);
|
|
|
|
this.folder_list({folder: folder, level: 0}, true);
|
|
};
|
|
|
|
this.folder_select = function(folder)
|
|
{
|
|
if (rcmail.busy || !folder)
|
|
return;
|
|
|
|
rcmail.triggerEvent('files-folder-select', {folder: folder});
|
|
|
|
var is_collection = folder.match(/^folder-collection-(.*)$/),
|
|
collection = RegExp.$1 || null;
|
|
|
|
if (rcmail.task == 'files' && !rcmail.env.action)
|
|
rcmail.update_state(is_collection ? {collection: collection} : {folder: folder});
|
|
|
|
if (collection == 'sessions') {
|
|
rcmail.enable_command('files-list', 'files-folder-delete', 'folder-rename', 'files-upload', 'files-open', 'files-edit', false);
|
|
this.sessions_list();
|
|
return;
|
|
}
|
|
|
|
if (is_collection)
|
|
folder = null;
|
|
|
|
// search-reset can re-select the same folder, skip
|
|
if (this.env.folder == folder && this.env.collection == collection)
|
|
return;
|
|
|
|
this.env.folder = folder;
|
|
this.env.collection = collection;
|
|
|
|
rcmail.enable_command('files-list', true);
|
|
rcmail.enable_command('files-folder-delete', 'folder-rename', !is_collection);
|
|
rcmail.enable_command('files-upload', !is_collection && this.is_writable());
|
|
rcmail.enable_command('folder-share', !is_collection && this.is_shareable());
|
|
rcmail.command('files-list', is_collection ? {collection: collection} : {folder: folder});
|
|
|
|
this.quota();
|
|
};
|
|
|
|
this.folder_unselect = function()
|
|
{
|
|
rcmail.folder_list.select();
|
|
this.env.folder = null;
|
|
this.env.collection = null;
|
|
rcmail.enable_command('files-folder-delete', 'files-upload', false);
|
|
};
|
|
|
|
this.folder_collapsed = function(node)
|
|
{
|
|
var prefname = 'kolab_files_collapsed_folders',
|
|
old = rcmail.env[prefname],
|
|
entry = '&' + urlencode(node.id) + '&';
|
|
|
|
if (node.collapsed) {
|
|
rcmail.env[prefname] = rcmail.env[prefname] + entry;
|
|
|
|
// select the folder if one of its childs is currently selected
|
|
// don't select if it's virtual (#1488346)
|
|
if (!node.virtual && this.env.folder && this.env.folder.startsWith(node.id + '/')) {
|
|
rcmail.folder_list.select(node.id);
|
|
}
|
|
}
|
|
else {
|
|
rcmail.env[prefname] = rcmail.env[prefname].replace(entry, '');
|
|
}
|
|
|
|
if (old !== rcmail.env[prefname] && (!rcmail.fileslist || !rcmail.fileslist.drag_active))
|
|
rcmail.command('save-pref', {name: prefname, value: rcmail.env[prefname]});
|
|
};
|
|
|
|
this.folder_list_row = function(i, folder, parent)
|
|
{
|
|
var toggle, sublist, collapsed, parent, parent_name, classes = ['mailbox'],
|
|
row = $('<li>'),
|
|
id = 'rcmli' + rcmail.html_identifier_encode(i),
|
|
content = $('<div>').append($('<a class="name">').text(folder.name));
|
|
|
|
if (folder.virtual)
|
|
classes.push('virtual');
|
|
else {
|
|
if (folder.subscribed !== undefined)
|
|
content.append(this.folder_list_subscription_button(folder.subscribed));
|
|
|
|
if (folder.readonly)
|
|
classes.push('readonly');
|
|
}
|
|
|
|
folder.ref = row.attr({id: id, 'class': classes.join(' ')}).append(content);
|
|
|
|
if (folder.depth) {
|
|
// find parent folder
|
|
parent_name = i.replace(/\/[^/]+$/, '');
|
|
|
|
if (!parent)
|
|
parent = $(this.env.folders[parent_name].ref);
|
|
|
|
toggle = $('div.treetoggle', parent);
|
|
sublist = $('> ul', parent);
|
|
|
|
if (!toggle.length) {
|
|
collapsed = rcmail.env.kolab_files_collapsed_folders.indexOf('&' + urlencode(parent_name) + '&') > -1;
|
|
|
|
toggle = $('<div>').attr('class', 'treetoggle' + (collapsed ? ' collapsed' : ' expanded'))
|
|
.html(' ').appendTo(parent);
|
|
|
|
sublist = $('<ul>').attr({role: 'group'}).appendTo(parent);
|
|
if (collapsed)
|
|
sublist.hide();
|
|
}
|
|
|
|
sublist.append(row);
|
|
}
|
|
else {
|
|
return row;
|
|
}
|
|
};
|
|
|
|
// create subscription button element
|
|
this.folder_list_subscription_button = function(subscribed)
|
|
{
|
|
return $('<a>').attr({
|
|
title: rcmail.gettext('kolab_files.listpermanent'),
|
|
'class': 'subscription' + (subscribed ? ' subscribed' : ''),
|
|
'aria-checked': subscribed,
|
|
role: 'checkbox'
|
|
});
|
|
};
|
|
|
|
// subscription button handler
|
|
this.folder_list_subscription_button_click = function(elem)
|
|
{
|
|
var folder = $(elem).parents('li:first').prop('id').replace(/^rcmli/, ''),
|
|
selected = $(elem).hasClass('subscribed');
|
|
|
|
folder = folder.replace(/--xsR$/, ''); // this might be a search result
|
|
folder = rcmail.html_identifier_decode(folder);
|
|
file_api['folder_' + (selected ? 'unsubscribe' : 'subscribe')](folder);
|
|
return false;
|
|
};
|
|
|
|
// sets subscription button status
|
|
this.folder_list_subscription_state = function(elem, status)
|
|
{
|
|
$(elem).find('a.subscription:first')
|
|
.prop('aria-checked', status)[status ? 'addClass' : 'removeClass']('subscribed');
|
|
};
|
|
|
|
// Folder searching handler (for unsubscribed folders)
|
|
this.folder_search = function(search)
|
|
{
|
|
// hide search results
|
|
if (this.search_results_widget) {
|
|
this.search_results_container.hide();
|
|
this.search_results_widget.reset();
|
|
}
|
|
this.search_results = {};
|
|
|
|
// send search request to the server
|
|
if (search.query && search.execute) {
|
|
// cancel previous search request
|
|
if (this.listsearch_request) {
|
|
this.listsearch_request.abort();
|
|
this.listsearch_request = null;
|
|
}
|
|
|
|
var params = $.extend({search: search.query, unsubscribed: 1}, this.list_params);
|
|
|
|
this.req = this.set_busy(true, rcmail.gettext('searching'));
|
|
this.listsearch_request = this.request('folder_list', params, 'folder_search_response');
|
|
}
|
|
else if (!search.query) {
|
|
if (this.listsearch_request) {
|
|
this.listsearch_request.abort();
|
|
this.listsearch_request = null;
|
|
}
|
|
|
|
// any subscription changed, make sure the newly added records
|
|
// are listed before collections not after
|
|
if (this.folder_subscribe) {
|
|
var r, last, move = [], rows = $(rcmail.folder_list.container).children('li');
|
|
|
|
if (rows.length && !$(rows[rows.length-1]).hasClass('collection')) {
|
|
// collect all folders to move
|
|
while (rows.length--) {
|
|
r = $(rows[rows.length]);
|
|
if (r.hasClass('collection'))
|
|
last = r;
|
|
else if (last)
|
|
break;
|
|
else
|
|
move.push(r);
|
|
}
|
|
|
|
if (last)
|
|
$.each(move, function() {
|
|
this.remove();
|
|
last.before(this);
|
|
});
|
|
}
|
|
}
|
|
}
|
|
};
|
|
|
|
// folder search response handler
|
|
this.folder_search_response = function(response)
|
|
{
|
|
if (!this.response(response))
|
|
return;
|
|
|
|
var folders = response.result && response.result.list ? response.result.list : response.result;
|
|
|
|
if (!folders.length)
|
|
return;
|
|
|
|
folders = this.folder_list_parse(folders, 10000, false);
|
|
|
|
if (!this.search_results_widget) {
|
|
var list = rcmail.folder_list.container,
|
|
title = rcmail.gettext('kolab_files.additionalfolders'),
|
|
list_id = list.attr('id') || '0';
|
|
|
|
this.search_results_container = $('<div class="searchresults"></div>')
|
|
.append($('<h2 class="boxtitle" id="st:' + list_id + '"></h2>').text(title))
|
|
.insertAfter(list);
|
|
|
|
this.search_results_widget = new rcube_treelist_widget('<ul>', {
|
|
id_prefix: 'rcmli',
|
|
id_encode: rcmail.html_identifier_encode,
|
|
id_decode: rcmail.html_identifier_decode,
|
|
selectable: true
|
|
});
|
|
|
|
this.search_results_widget
|
|
.addEventListener('beforeselect', function(node) { return !rcmail.busy; })
|
|
.addEventListener('select', function(node) {
|
|
rcmail.folder_list.select();
|
|
file_api.folder_select(node.id);
|
|
});
|
|
|
|
this.search_results_widget.container
|
|
// copy classes from main list
|
|
.addClass(list.attr('class')).attr('aria-labelledby', 'st:' + list_id)
|
|
.appendTo(this.search_results_container)
|
|
.on('click', 'a.subscription', function(e) {
|
|
return file_api.folder_list_subscription_button_click(this);
|
|
});
|
|
}
|
|
|
|
// add results to the list
|
|
$.each(folders, function(i, folder) {
|
|
var node, separator = file_api.env.directory_separator,
|
|
path = i.split(separator),
|
|
classes = ['mailbox'],
|
|
html = [$('<a>').text(folder.name)];
|
|
|
|
if (!folder.virtual) {
|
|
// add subscription button
|
|
html.push(file_api.folder_list_subscription_button(false));
|
|
|
|
if (folder.readonly)
|
|
classes.push('readonly');
|
|
}
|
|
|
|
path.pop();
|
|
|
|
file_api.search_results_widget.insert({
|
|
id: i,
|
|
classes: classes,
|
|
text: folder.name,
|
|
html: $('<div>').append(html),
|
|
collapsed: false,
|
|
virtual: folder.virtual
|
|
}, path.length ? path.join(separator) : null);
|
|
});
|
|
|
|
this.search_results = folders;
|
|
this.search_results_container.show();
|
|
};
|
|
|
|
// folder subscribe request
|
|
this.folder_subscribe = function(folder)
|
|
{
|
|
this.env.folder_subscribe = folder;
|
|
this.req = this.set_busy(true, 'foldersubscribing');
|
|
this.request('folder_subscribe', {folder: folder}, 'folder_subscribe_response');
|
|
}
|
|
|
|
// folder subscribe response handler
|
|
this.folder_subscribe_response = function(response)
|
|
{
|
|
if (!this.response(response))
|
|
return;
|
|
|
|
this.display_message('foldersubscribed', 'confirmation');
|
|
|
|
var item, node = rcmail.folder_list.get_item(this.env.folder_subscribe);
|
|
|
|
if (this.search_results && this.search_results[this.env.folder_subscribe]) {
|
|
item = this.search_results_widget.get_item(this.env.folder_subscribe);
|
|
this.folder_list_subscription_state(item, true);
|
|
if (item = $(item).attr('id'))
|
|
this.folder_list_subscription_state($('#' + item.replace(/--xsR$/, '')), true);
|
|
}
|
|
|
|
// search result, move from search to main list widget
|
|
if (!node && this.search_results && this.search_results[this.env.folder_subscribe]) {
|
|
var i, html, dir, folder, separator = this.env.directory_separator,
|
|
path = this.env.folder_subscribe.split(separator);
|
|
|
|
// add all folders in a path to the main list if needed
|
|
// including the subscribed folder
|
|
for (i=0; i<path.length; i++) {
|
|
dir = path.slice(0, i + 1).join(separator);
|
|
node = rcmail.folder_list.get_node(dir);
|
|
|
|
if (!node) {
|
|
node = this.search_results_widget.get_node(dir);
|
|
if (!node) {
|
|
// sanity check
|
|
return;
|
|
}
|
|
|
|
if (i == path.length - 1) {
|
|
item = this.search_results_widget.get_item(dir);
|
|
this.folder_list_subscription_state(item, true);
|
|
}
|
|
|
|
folder = this.search_results[dir];
|
|
html = [$('<a>').text(folder.name)];
|
|
if (!folder.virtual)
|
|
html.push(this.folder_list_subscription_button(true));
|
|
|
|
node.html = $('<div>').append(html);
|
|
delete node.children;
|
|
|
|
rcmail.folder_list.insert(node, i > 0 ? path.slice(0, i).join(separator) : null);
|
|
// we're in search result, so there will be two records,
|
|
// add subscription button to the visible one, it was not cloned
|
|
if (!folder.virtual) {
|
|
node = rcmail.folder_list.get_item(dir);
|
|
$(node).append(file_api.folder_list_subscription_button(true));
|
|
}
|
|
|
|
this.env.folders[dir] = folder;
|
|
}
|
|
}
|
|
|
|
// now remove them from the search widget
|
|
while (path.length) {
|
|
dir = path.join(separator);
|
|
node = this.search_results_widget.get_item(dir);
|
|
|
|
if ($('ul[role="group"] > li', node).length)
|
|
break;
|
|
|
|
this.search_results_widget.remove(dir);
|
|
|
|
path.pop();
|
|
}
|
|
|
|
node = null;
|
|
}
|
|
|
|
if (node)
|
|
this.folder_list_subscription_state(node, true);
|
|
|
|
this.env.folders[this.env.folder_subscribe].subscribed = true;
|
|
};
|
|
|
|
// folder unsubscribe request
|
|
this.folder_unsubscribe = function(folder)
|
|
{
|
|
this.env.folder_subscribe = folder;
|
|
this.req = this.set_busy(true, 'folderunsubscribing');
|
|
this.request('folder_unsubscribe', {folder: folder}, 'folder_unsubscribe_response');
|
|
}
|
|
|
|
// folder unsubscribe response handler
|
|
this.folder_unsubscribe_response = function(response)
|
|
{
|
|
if (!this.response(response))
|
|
return;
|
|
|
|
this.display_message('folderunsubscribed', 'confirmation');
|
|
|
|
var folder = this.env.folders[this.env.folder_subscribe],
|
|
node = rcmail.folder_list.get_item(this.env.folder_subscribe);
|
|
|
|
if (this.search_results && this.search_results[this.env.folder_subscribe]) {
|
|
item = this.search_results_widget.get_item(this.env.folder_subscribe);
|
|
|
|
if (item) {
|
|
this.folder_list_subscription_state(item, false);
|
|
item = $('#' + $(item).attr('id').replace(/--xsR$/, ''));
|
|
}
|
|
else
|
|
item = $('#rcmli' + rcmail.html_identifier_encode(this.env.folder_subscribe), rcmail.folder_list.container);
|
|
|
|
this.folder_list_subscription_state(item, false);
|
|
}
|
|
|
|
this.folder_list_subscription_state(node, false);
|
|
|
|
folder.subscribed = false;
|
|
};
|
|
|
|
// folder create request
|
|
this.folder_create = function(folder)
|
|
{
|
|
this.req = this.set_busy(true, 'kolab_files.foldercreating');
|
|
this.request('folder_create', {folder: folder}, 'folder_create_response');
|
|
};
|
|
|
|
// folder create response handler
|
|
this.folder_create_response = function(response)
|
|
{
|
|
if (!this.response(response))
|
|
return;
|
|
|
|
this.display_message('kolab_files.foldercreatenotice', 'confirmation');
|
|
|
|
// refresh folders list
|
|
// TODO: Don't reload the whole list
|
|
this.folder_list();
|
|
};
|
|
|
|
// folder rename request
|
|
this.folder_rename = function(folder, new_name)
|
|
{
|
|
if (folder == new_name)
|
|
return;
|
|
|
|
this.req = this.set_busy(true, 'kolab_files.folderupdating');
|
|
this.request('folder_move', {folder: folder, 'new': new_name}, 'folder_rename_response');
|
|
};
|
|
|
|
// folder create response handler
|
|
this.folder_rename_response = function(response, params)
|
|
{
|
|
if (!this.response(response))
|
|
return;
|
|
|
|
this.display_message('kolab_files.folderupdatenotice', 'confirmation');
|
|
|
|
// refresh folders and files list
|
|
if (this.env.folder == params.folder)
|
|
this.env.folder = params['new'];
|
|
|
|
// Removed mount point, refresh capabilities stored in session
|
|
if (this.env.caps.MOUNTPOINTS[params.folder]) {
|
|
this.env.caps.MOUNTPOINTS[params['new']] = this.env.caps.MOUNTPOINTS[params.folder];
|
|
delete this.env.caps.MOUNTPOINTS[params.folder];
|
|
rcmail.http_post('files/reset', {});
|
|
}
|
|
|
|
// TODO: Don't reload the whole list
|
|
this.folder_list();
|
|
};
|
|
|
|
// folder mount (external storage) request
|
|
this.folder_mount = function(data)
|
|
{
|
|
this.req = this.set_busy(true, 'kolab_files.foldermounting');
|
|
this.request('folder_create', data, 'folder_mount_response');
|
|
};
|
|
|
|
// folder create response handler
|
|
this.folder_mount_response = function(response, params)
|
|
{
|
|
if (!this.response(response))
|
|
return;
|
|
|
|
this.display_message('kolab_files.foldermountnotice', 'confirmation');
|
|
|
|
if (response.result.capabilities) {
|
|
// we make sure the result is an object not array
|
|
// when the list is empty it is an array, because of how works JSON encoding from PHP
|
|
var add = {};
|
|
add[params.folder] = response.result.capabilities;
|
|
this.env.caps.MOUNTPOINTS = $.extend({}, this.env.caps.MOUNTPOINTS, add);
|
|
}
|
|
|
|
// Refresh capabilities stored in session
|
|
rcmail.http_post('files/reset', {});
|
|
|
|
// refresh folders list
|
|
// TODO: load only folders from the created mount point
|
|
this.folder_list();
|
|
};
|
|
|
|
// folder delete request
|
|
this.folder_delete = function(folder)
|
|
{
|
|
this.req = this.set_busy(true, 'kolab_files.folderdeleting');
|
|
this.request('folder_delete', {folder: folder}, 'folder_delete_response');
|
|
};
|
|
|
|
// folder delete response handler
|
|
this.folder_delete_response = function(response, params)
|
|
{
|
|
if (!this.response(response))
|
|
return;
|
|
|
|
this.display_message('kolab_files.folderdeletenotice', 'confirmation');
|
|
|
|
if (this.env.folder == params.folder) {
|
|
this.env.folder = null;
|
|
rcmail.enable_command('files-folder-delete', 'folder-rename', 'files-list', false);
|
|
}
|
|
|
|
// Removed mount point, refresh capabilities stored in session
|
|
if (this.env.caps.MOUNTPOINTS[params.folder]) {
|
|
delete this.env.caps.MOUNTPOINTS[params.folder];
|
|
rcmail.http_post('files/reset', {});
|
|
}
|
|
|
|
// refresh folders list
|
|
this.folder_list();
|
|
this.quota();
|
|
};
|
|
|
|
this.sharing_submit = function(folder, row, mode)
|
|
{
|
|
var post = this.sharing_data(row, {action: 'submit', folder: folder, mode: mode});
|
|
|
|
if (post === false)
|
|
return;
|
|
|
|
this.sharing_submit_post = post;
|
|
this.sharing_submit_row = row;
|
|
this.req = this.set_busy(true, 'kolab_files.updatingfolder' + mode);
|
|
this.post('sharing', post, 'sharing_submit_response');
|
|
};
|
|
|
|
this.sharing_submit_response = function(response)
|
|
{
|
|
if (!this.response(response))
|
|
return;
|
|
|
|
// reset inputs
|
|
$(this.sharing_submit_row).find('input[type=text]').val('');
|
|
|
|
var hidden = [],
|
|
post = $.extend({}, this.sharing_submit_post, response.result || {}),
|
|
form_info = rcmail.env.form_info[post.mode],
|
|
table = $(this.sharing_submit_row).closest('table'),
|
|
row = $('<tr>'),
|
|
btn = $('<button type="button" class="btn btn-secondary btn-danger delete">')
|
|
.text(rcmail.gettext('delete'))
|
|
.on('click', function() { file_api.sharing_delete(post.folder, $(this).closest('tr'), post.mode); });
|
|
|
|
if (form_info.list_column) {
|
|
row.append($('<td>').append($('<span class="name">')
|
|
.text(response.result.display || post[form_info.list_column])
|
|
.attr('title', response.result.title))
|
|
);
|
|
}
|
|
else {
|
|
$.each(form_info.form || [], function(i, v) {
|
|
var content, opts = [];
|
|
|
|
if (v.type == 'select') {
|
|
content = $('<select>').attr('name', i)
|
|
.on('change', function() { file_api.sharing_update(post.folder, $(this).closest('tr'), post.mode); });
|
|
$.each(v.options, function(i, v) {
|
|
opts.push($('<option>').attr('value', i).text(v));
|
|
});
|
|
|
|
content.append(opts).val(post[i]);
|
|
}
|
|
else {
|
|
content = $('<span class="name">').text(response.result.display || post[i]).attr('title', response.result.title);
|
|
hidden.push($('<input>').attr({type: 'hidden', name: i, value: post[i] || ''}));
|
|
}
|
|
|
|
row.append($('<td>').append(content));
|
|
});
|
|
}
|
|
|
|
$.each(form_info.extra_fields || [], function(i, v) {
|
|
hidden.push($('<input>').attr({type: 'hidden', name: i, value: post[i] || ''}));
|
|
});
|
|
|
|
row.append($('<td>').append(btn).append(hidden));
|
|
|
|
$(this.sharing_submit_row).parent().append(row);
|
|
|
|
if (window.UI && UI.pretty_select)
|
|
row.find('select').each(function() { UI.pretty_select(this); }); // for Elastic
|
|
|
|
if (table.data('single')) {
|
|
$('tbody > tr:first', table).find('button,input,select').prop('disabled', true);
|
|
}
|
|
|
|
$('tbody > tr:first', table).find('input[type=text],input[type=password]').val('');
|
|
};
|
|
|
|
this.sharing_update = function(folder, row, mode)
|
|
{
|
|
var post = this.sharing_data(row, {action: 'update', folder: folder, mode: mode});
|
|
|
|
this.req = this.set_busy(true, 'kolab_files.updatingfolder' + mode);
|
|
this.post('sharing', post, 'sharing_update_response');
|
|
};
|
|
|
|
this.sharing_update_response = function(response)
|
|
{
|
|
if (!this.response(response))
|
|
return;
|
|
|
|
// todo: on error reset fields?
|
|
};
|
|
|
|
this.sharing_delete = function(folder, row, mode)
|
|
{
|
|
var post = this.sharing_data(row, {action: 'delete', folder: folder, mode: mode});
|
|
|
|
this.sharing_delete_row = row;
|
|
this.req = this.set_busy(true, 'kolab_files.updatingfolder' + mode);
|
|
this.post('sharing', post, 'sharing_delete_response');
|
|
};
|
|
|
|
this.sharing_delete_response = function(response)
|
|
{
|
|
if (!this.response(response))
|
|
return;
|
|
|
|
var table = $(this.sharing_delete_row).closest('table');
|
|
|
|
if (table.data('single')) {
|
|
$('tbody > tr:first', table).find('button,input,select').prop('disabled', false);
|
|
}
|
|
|
|
$(this.sharing_delete_row).remove();
|
|
};
|
|
|
|
this.sharing_data = function(row, data)
|
|
{
|
|
var error;
|
|
|
|
$('select,input', row).each(function() {
|
|
if (this.type == 'password' && !this.name.match(/confirm$/) && this.value != $('input[name=' + this.name + 'confirm]', row).val())
|
|
error = rcmail.display_message('kolab_files.passwordconflict', 'error');
|
|
|
|
data[this.name] = $(this).val();
|
|
});
|
|
|
|
return error ? false : data;
|
|
};
|
|
|
|
// quota request
|
|
this.quota = function()
|
|
{
|
|
if (rcmail.env.files_quota && (this.env.folder || !this.env.caps.NOROOT))
|
|
this.request('quota', {folder: this.env.folder}, 'quota_response');
|
|
};
|
|
|
|
// quota response handler
|
|
this.quota_response = function(response)
|
|
{
|
|
if (!this.response(response))
|
|
return;
|
|
|
|
rcmail.files_set_quota(response.result);
|
|
};
|
|
|
|
// List of sessions
|
|
this.sessions_list = function(params)
|
|
{
|
|
if (!rcmail.gui_objects.sessionslist)
|
|
return;
|
|
|
|
this.file_list_abort(true);
|
|
|
|
if (!params)
|
|
params = {};
|
|
|
|
if (rcmail.gui_objects.fileslist) {
|
|
$(rcmail.gui_objects.fileslist).parent().hide();
|
|
$(rcmail.gui_objects.sessionslist).parent().show();
|
|
rcmail.fileslist.clear();
|
|
}
|
|
|
|
this.env.folder = null;
|
|
this.env.collection = null;
|
|
|
|
// empty the list
|
|
this.env.sessions_list = {};
|
|
rcmail.sessionslist.clear(true);
|
|
|
|
rcmail.enable_command(rcmail.env.file_commands, false);
|
|
rcmail.enable_command(rcmail.env.file_commands_all, false);
|
|
|
|
params.req_id = this.set_busy(true, 'loading');
|
|
this.requests[params.req_id] = this.request('sessions', params, 'sessions_list_response');
|
|
};
|
|
|
|
// file list response handler
|
|
this.sessions_list_response = function(response)
|
|
{
|
|
if (response.req_id)
|
|
rcmail.hide_message(response.req_id);
|
|
|
|
if (!this.response(response))
|
|
return;
|
|
|
|
$.each(response.result, function(sess_id, data) {
|
|
var row = file_api.session_list_row(sess_id, data);
|
|
rcmail.sessionslist.insert_row(row);
|
|
response.result[sess_id].row = row;
|
|
});
|
|
|
|
this.env.sessions_list = response.result;
|
|
rcmail.sessionslist.resize();
|
|
};
|
|
|
|
// Files list
|
|
this.file_list = function(params)
|
|
{
|
|
if (!rcmail.gui_objects.fileslist)
|
|
return;
|
|
|
|
this.file_list_abort(true);
|
|
|
|
if (!params)
|
|
params = {};
|
|
|
|
if (params.all_folders) {
|
|
params.collection = null;
|
|
params.folder = null;
|
|
this.folder_unselect();
|
|
}
|
|
|
|
if (params.collection == undefined)
|
|
params.collection = this.env.collection;
|
|
if (params.folder == undefined)
|
|
params.folder = this.env.folder;
|
|
if (params.sort == undefined)
|
|
params.sort = this.env.files_sort_col;
|
|
if (params.reverse == undefined)
|
|
params.reverse = this.env.files_sort_reverse;
|
|
if (params.search == undefined)
|
|
params.search = this.env.search;
|
|
|
|
this.env.folder = params.folder;
|
|
this.env.collection = params.collection;
|
|
this.env.files_sort_col = params.sort;
|
|
this.env.files_sort_reverse = params.reverse;
|
|
|
|
rcmail.enable_command(rcmail.env.file_commands, false);
|
|
rcmail.enable_command(rcmail.env.file_commands_all, false);
|
|
|
|
if (rcmail.gui_objects.sessionslist) {
|
|
$(rcmail.gui_objects.sessionslist).parent().hide();
|
|
$(rcmail.gui_objects.fileslist).parent().show();
|
|
rcmail.sessionslist.clear(true)
|
|
}
|
|
|
|
// empty the list
|
|
this.env.file_list = [];
|
|
rcmail.fileslist.clear(true);
|
|
rcmail.triggerEvent('listupdate', {list: rcmail.fileslist, rowcount: 0});
|
|
|
|
// request
|
|
if (params.collection || params.all_folders)
|
|
this.file_list_loop(params);
|
|
else if (this.env.folder) {
|
|
params.req_id = this.env.file_list_req_id = this.set_busy(true, 'loading');
|
|
this.requests[params.req_id] = this.request('file_list', params, 'file_list_response');
|
|
}
|
|
};
|
|
|
|
// file list response handler
|
|
this.file_list_response = function(response)
|
|
{
|
|
if (response.req_id)
|
|
rcmail.hide_message(response.req_id);
|
|
|
|
if (!this.response(response))
|
|
return;
|
|
|
|
var i = 0, list = [];
|
|
|
|
$.each(response.result, function(key, data) {
|
|
var row = file_api.file_list_row(key, data, ++i);
|
|
rcmail.fileslist.insert_row(row);
|
|
data.row = row;
|
|
data.filename = key;
|
|
list.push(data);
|
|
});
|
|
|
|
this.env.file_list = list;
|
|
rcmail.fileslist.resize();
|
|
rcmail.triggerEvent('listupdate', {list: rcmail.fileslist, rowcount: rcmail.fileslist.rowcount});
|
|
|
|
// update document sessions info of this folder
|
|
if (list && list.length)
|
|
this.request('folder_info', {folder: this.file_path(list[0].filename), sessions: 1}, 'folder_info_response');
|
|
};
|
|
|
|
this.file_list_abort = function(all)
|
|
{
|
|
if (all) {
|
|
clearTimeout(this.file_list_worker);
|
|
this.file_list_worker = null;
|
|
}
|
|
|
|
// reset all pending list requests
|
|
$.each(this.requests, function(i, v) {
|
|
v.abort();
|
|
rcmail.hide_message(i);
|
|
});
|
|
|
|
this.requests = {};
|
|
|
|
rcmail.set_busy(false, null, this.env.file_list_req_id);
|
|
};
|
|
|
|
// call file_list request for every folder (used for search and virt. collections)
|
|
this.file_list_loop = function(params)
|
|
{
|
|
var i, folders = [],
|
|
limit = Math.max(this.env.search_threads || 1, 1),
|
|
msg = rcmail.get_label('searching') + ' <a onclick="file_api.file_list_abort()">' + rcmail.get_label('kolab_files.abort') + '</a>';
|
|
|
|
if (params.collection) {
|
|
if (!params.search)
|
|
params.search = {};
|
|
params.search['class'] = params.collection;
|
|
delete params['collection'];
|
|
}
|
|
|
|
delete params['all_folders'];
|
|
|
|
$.each(this.env.folders, function(i, f) {
|
|
if (!f.virtual)
|
|
folders.push(i);
|
|
});
|
|
|
|
this.env.folders_loop = folders;
|
|
this.env.folders_loop_lock = false;
|
|
this.env.file_list_req_id = rcmail.display_message(msg, 'loading', 5 * 60 * 1000, 'files-file-search');
|
|
rcmail.set_busy(true);
|
|
|
|
for (i=0; i<folders.length && i<limit; i++) {
|
|
params.req_id = new Date().getTime();
|
|
params.folder = folders.shift();
|
|
this.requests[params.req_id] = this.request('file_list', params, 'file_list_loop_response');
|
|
}
|
|
};
|
|
|
|
// file list response handler for loop'ed request
|
|
this.file_list_loop_response = function(response, params)
|
|
{
|
|
var folders = this.env.folders_loop,
|
|
valid = this.response(response);
|
|
|
|
if (folders.length) {
|
|
params.req_id = new Date().getTime();
|
|
params.folder = folders.shift();
|
|
this.requests[params.req_id] = this.request('file_list', params, 'file_list_loop_response');
|
|
}
|
|
else {
|
|
rcmail.set_busy(false, null, this.env.file_list_req_id);
|
|
}
|
|
|
|
// refresh sessions info in time intervals (one request for all folders)
|
|
if (!this.file_list_worker && this.env.caps && this.env.caps.DOCEDIT && (rcmail.fileslist || rcmail.env.file))
|
|
this.file_list_worker = setTimeout(function() {
|
|
var params = {req_id: file_api.set_busy(true, 'loading')};
|
|
file_api.request('sessions', params, 'file_list_sessions_response');
|
|
}, 0);
|
|
|
|
rcmail.fileslist.resize();
|
|
|
|
if (!valid)
|
|
return;
|
|
|
|
this.file_list_loop_result_add(response.result);
|
|
};
|
|
|
|
// Update sessions metadata for files list (in multifolder mode)
|
|
this.file_list_sessions_response = function(response)
|
|
{
|
|
this.file_list_worker = setTimeout(function() {
|
|
var params = {req_id: file_api.set_busy(true, 'loading')};
|
|
file_api.request('sessions', params, 'file_list_sessions_response');
|
|
}, (rcmail.env.files_interval || 60) * 1000);
|
|
|
|
if (response.req_id)
|
|
rcmail.hide_message(response.req_id);
|
|
|
|
if (!this.response(response))
|
|
return;
|
|
|
|
this.sessions = [];
|
|
|
|
$.each(response.result || [], function(sess_id, data) {
|
|
var folder = file_api.file_path(data.file);
|
|
if (!file_api.sessions[folder])
|
|
file_api.sessions[folder] = {};
|
|
file_api.sessions[folder][sess_id] = data;
|
|
});
|
|
|
|
// update files list with document session info
|
|
$.each(file_api.env.file_list || [], function(i, file) {
|
|
var folder = file_api.file_path(file.filename);
|
|
file_api.file_session_data_set(file, file_api.sessions[folder]);
|
|
});
|
|
};
|
|
|
|
// add files from list request to the table (with sorting)
|
|
this.file_list_loop_result_add = function(result)
|
|
{
|
|
// chack if result (hash-array) is empty
|
|
if (!object_is_empty(result))
|
|
return;
|
|
|
|
if (this.env.folders_loop_lock) {
|
|
setTimeout(function() { file_api.file_list_loop_result_add(result); }, 100);
|
|
return;
|
|
}
|
|
|
|
// lock table, other list responses will wait
|
|
this.env.folders_loop_lock = true;
|
|
|
|
var n, i, len, elem, folder, list = [],
|
|
index = this.env.file_list.length,
|
|
table = rcmail.fileslist,
|
|
fn = function(result, key, before) {
|
|
var row = file_api.file_list_row(key, result[key], ++index);
|
|
table.insert_row(row, before);
|
|
result[key].row = row;
|
|
result[key].filename = key;
|
|
list.push(result[key]);
|
|
|
|
if (!folder)
|
|
folder = file_api.file_path(key);
|
|
};
|
|
|
|
for (n=0, len=index; n<len; n++) {
|
|
elem = this.env.file_list[n];
|
|
for (i in result) {
|
|
if (this.sort_compare(elem, result[i]) < 0)
|
|
break;
|
|
|
|
fn(result, i, elem.row);
|
|
delete result[i];
|
|
}
|
|
|
|
list.push(elem);
|
|
}
|
|
|
|
// add the rest of rows
|
|
for (i in result) fn(result, i);
|
|
|
|
this.env.file_list = list;
|
|
|
|
// update files list with document session info
|
|
if (folder && this.sessions[folder])
|
|
$.each(list, function(i, file) {
|
|
if (folder == file_api.file_path(file.filename))
|
|
file_api.file_session_data_set(file, file_api.sessions[folder]);
|
|
});
|
|
|
|
this.env.folders_loop_lock = false;
|
|
};
|
|
|
|
// sort files list (without API request)
|
|
this.file_list_sort = function(col, reverse)
|
|
{
|
|
var n, len, list = this.env.file_list,
|
|
table = $('#filelist'), tbody = $('<tbody>', table);
|
|
|
|
this.env.sort_col = col;
|
|
this.env.sort_reverse = reverse;
|
|
|
|
if (!list || !list.length)
|
|
return;
|
|
|
|
// sort the list
|
|
list.sort(function (a, b) {
|
|
return file_api.sort_compare(a, b);
|
|
});
|
|
|
|
// add rows to the new body
|
|
for (n=0, len=list.length; n<len; n++) {
|
|
tbody.append(list[n].row);
|
|
}
|
|
|
|
// replace table bodies
|
|
$('tbody', table).replaceWith(tbody);
|
|
};
|
|
|
|
// Files list record
|
|
this.file_list_row = function(file, data, index)
|
|
{
|
|
var c, col, row = '';
|
|
|
|
for (c in rcmail.env.files_coltypes) {
|
|
c = rcmail.env.files_coltypes[c];
|
|
if (c == 'name')
|
|
col = '<td class="name filename ' + this.file_type_class(data.type) + '">'
|
|
+ '<span>' + escapeHTML(data.name) + '</span></td>';
|
|
else if (c == 'mtime')
|
|
col = '<td class="mtime">' + data.mtime + '</td>';
|
|
else if (c == 'size')
|
|
col = '<td class="size">' + this.file_size(data.size) + '</td>';
|
|
else if (c == 'options')
|
|
col = '<td class="options"><span></span></td>';
|
|
else
|
|
col = '<td class="' + c + '"></td>';
|
|
|
|
row += col;
|
|
}
|
|
|
|
row = $('<tr>')
|
|
.html(row)
|
|
.attr({id: 'rcmrow' + index, 'data-file': file, 'data-type': data.type});
|
|
|
|
// collection (or search) lists files from all folders
|
|
// display file name with full path as title
|
|
if (!this.env.folder)
|
|
$('td.name span', row).attr('title', file);
|
|
|
|
return row.get(0);
|
|
};
|
|
|
|
// Sessions list record
|
|
this.session_list_row = function(id, data)
|
|
{
|
|
var c, col, row = '', classes = ['session'];
|
|
|
|
for (c in rcmail.env.sessions_coltypes) {
|
|
c = rcmail.env.sessions_coltypes[c];
|
|
if (c == 'name')
|
|
col = '<td class="name filename ' + this.file_type_class(data.type) + '">'
|
|
+ '<span>' + escapeHTML(file_api.file_name(data.file)) + '</span></td>';
|
|
else if (c == 'owner')
|
|
col = '<td class="owner">' + escapeHTML(data.owner_name || data.owner) + '</td>';
|
|
else if (c == 'options')
|
|
col = '<td class="options"><span></span></td>';
|
|
|
|
row += col;
|
|
}
|
|
|
|
if (data.is_owner)
|
|
classes.push('owner');
|
|
else if (data.is_invited)
|
|
classes.push('invited');
|
|
|
|
row = $('<tr>')
|
|
.html(row)
|
|
.attr({id: 'rcmrow' + id, 'class': classes.join(' ')});
|
|
|
|
return row.get(0);
|
|
};
|
|
|
|
this.file_search = function(value, all_folders)
|
|
{
|
|
if (value) {
|
|
this.env.search = {name: value};
|
|
rcmail.command('files-list', {search: this.env.search, all_folders: all_folders});
|
|
}
|
|
else
|
|
this.search_reset();
|
|
};
|
|
|
|
this.file_search_reset = function()
|
|
{
|
|
if (this.env.search) {
|
|
this.env.search = null;
|
|
rcmail.command('files-list');
|
|
}
|
|
};
|
|
|
|
// handler for folder info response
|
|
this.folder_info_response = function(response)
|
|
{
|
|
if (!this.response(response) || !response.result)
|
|
return;
|
|
|
|
var folder = response.result.folder,
|
|
prefix = folder + file_api.env.directory_separator;
|
|
|
|
if (response.result.sessions)
|
|
this.sessions[folder] = response.result.sessions;
|
|
|
|
// update files list with document session info
|
|
$.each(file_api.env.file_list || [], function(i, file) {
|
|
// skip files from a different folder (in multi-folder listing)
|
|
if (file.filename.indexOf(prefix) >= 0)
|
|
file_api.file_session_data_set(file, response.result.sessions)
|
|
});
|
|
|
|
// refresh sessions info in time intervals
|
|
if (this.env.caps && this.env.caps.DOCEDIT && (rcmail.fileslist || rcmail.env.file))
|
|
this.file_list_worker = setTimeout(function() {
|
|
file_api.request('folder_info', {folder: folder, sessions: 1}, 'folder_info_response');
|
|
}, (rcmail.env.files_interval || 60) * 1000);
|
|
};
|
|
|
|
// Set html classes on a file list entry according to defined document sessions
|
|
this.file_session_data_set = function(file, sessions)
|
|
{
|
|
var classes = [], old_class = file.row.className;
|
|
|
|
if ($(file.row).is('.selected'))
|
|
classes.push('selected');
|
|
|
|
$.each(sessions || [], function(session_id, session) {
|
|
if (file.filename == session.file) {
|
|
if ($.inArray('session', classes) < 0)
|
|
classes.push('session');
|
|
|
|
if (session.is_owner && $.inArray('owner', classes) < 0)
|
|
classes.push('owner');
|
|
else if (session.is_invited && $.inArray('invited', classes) < 0)
|
|
classes.push('invited');
|
|
}
|
|
});
|
|
|
|
if (classes.length || old_class.length)
|
|
$(file.row).attr('class', classes.join(' '));
|
|
};
|
|
|
|
this.file_get = function(file, params)
|
|
{
|
|
if (!params)
|
|
params = {};
|
|
|
|
params.token = this.env.token;
|
|
params.file = file;
|
|
|
|
rcmail.redirect(this.env.url + this.url('file_get', params), false);
|
|
};
|
|
|
|
// file(s) delete request
|
|
this.file_delete = function(files)
|
|
{
|
|
this.req = this.set_busy(true, 'kolab_files.filedeleting');
|
|
this.request('file_delete', {file: files}, 'file_delete_response');
|
|
};
|
|
|
|
// file(s) delete response handler
|
|
this.file_delete_response = function(response)
|
|
{
|
|
if (!this.response(response))
|
|
return;
|
|
|
|
var rco, dir, self = this;
|
|
|
|
this.display_message('kolab_files.filedeletenotice', 'confirmation');
|
|
|
|
if (rcmail.env.file) {
|
|
rco = rcmail.opener();
|
|
dir = this.file_path(rcmail.env.file);
|
|
|
|
// check if opener window contains files list, if not we can just close current window
|
|
if (rco && rco.fileslist && (opener.file_api.env.folder == dir || !opener.file_api.env.folder))
|
|
self = opener.file_api;
|
|
// also try parent for framed UI (Elastic)
|
|
else if (rcmail.is_framed() && parent.rcmail.fileslist && (parent.file_api.env.folder == dir || !parent.file_api.env.folder))
|
|
self = parent.file_api;
|
|
}
|
|
|
|
// @TODO: consider list modification "in-place" instead of full reload
|
|
self.file_list();
|
|
self.quota();
|
|
|
|
if (rcmail.env.file) {
|
|
if (rcmail.is_framed()) {
|
|
parent.$('.ui-dialog:visible > .ui-dialog-buttonpane button.cancel').click();
|
|
}
|
|
else
|
|
window.close();
|
|
}
|
|
};
|
|
|
|
// file(s) move request
|
|
this.file_move = function(files, folder)
|
|
{
|
|
if (!files || !files.length || !folder)
|
|
return;
|
|
|
|
var count = 0, list = {};
|
|
|
|
$.each(files, function(i, v) {
|
|
var name = folder + file_api.env.directory_separator + file_api.file_name(v);
|
|
|
|
if (name != v) {
|
|
list[v] = name;
|
|
count++;
|
|
}
|
|
});
|
|
|
|
if (!count)
|
|
return;
|
|
|
|
this.req = this.set_busy(true, 'kolab_files.filemoving');
|
|
this.request('file_move', {file: list}, 'file_move_response');
|
|
};
|
|
|
|
// file(s) move response handler
|
|
this.file_move_response = function(response)
|
|
{
|
|
if (!this.response(response))
|
|
return;
|
|
|
|
if (response.result && response.result.already_exist && response.result.already_exist.length)
|
|
this.file_move_ask_user(response.result.already_exist, true);
|
|
else {
|
|
this.display_message('kolab_files.filemovenotice', 'confirmation');
|
|
this.file_list();
|
|
}
|
|
};
|
|
|
|
// file(s) copy request
|
|
this.file_copy = function(files, folder)
|
|
{
|
|
if (!files || !files.length || !folder)
|
|
return;
|
|
|
|
var count = 0, list = {};
|
|
|
|
$.each(files, function(i, v) {
|
|
var name = folder + file_api.env.directory_separator + file_api.file_name(v);
|
|
|
|
if (name != v) {
|
|
list[v] = name;
|
|
count++;
|
|
}
|
|
});
|
|
|
|
if (!count)
|
|
return;
|
|
|
|
this.req = this.set_busy(true, 'kolab_files.filecopying');
|
|
this.request('file_copy', {file: list}, 'file_copy_response');
|
|
};
|
|
|
|
// file(s) copy response handler
|
|
this.file_copy_response = function(response)
|
|
{
|
|
if (!this.response(response))
|
|
return;
|
|
|
|
if (response.result && response.result.already_exist && response.result.already_exist.length)
|
|
this.file_move_ask_user(response.result.already_exist);
|
|
else {
|
|
this.display_message('kolab_files.filecopynotice', 'confirmation');
|
|
this.quota();
|
|
}
|
|
};
|
|
|
|
// when file move/copy operation returns file-exists error
|
|
// this displays a dialog where user can decide to skip
|
|
// or overwrite destination file(s)
|
|
this.file_move_ask_user = function(list, move)
|
|
{
|
|
var file = list[0], buttons = {}, button_classes = ['mainaction save file overwrite'],
|
|
text = rcmail.gettext('kolab_files.filemoveconfirm').replace('$file', file.dst),
|
|
dialog = $('<div></div>');
|
|
|
|
buttons[rcmail.gettext('kolab_files.fileoverwrite')] = function() {
|
|
var file = list.shift(), f = {},
|
|
action = move ? 'file_move' : 'file_copy';
|
|
|
|
f[file.src] = file.dst;
|
|
file_api.file_move_ask_list = list;
|
|
file_api.file_move_ask_mode = move;
|
|
kolab_dialog_close(this, true);
|
|
|
|
file_api.req = file_api.set_busy(true, move ? 'kolab_files.filemoving' : 'kolab_files.filecopying');
|
|
file_api.request(action, {file: f, overwrite: 1}, 'file_move_ask_user_response');
|
|
};
|
|
|
|
if (list.length > 1) {
|
|
button_classes.push('save file overwrite all');
|
|
buttons[rcmail.gettext('kolab_files.fileoverwriteall')] = function() {
|
|
var f = {}, action = move ? 'file_move' : 'file_copy';
|
|
|
|
$.each(list, function() { f[this.src] = this.dst; });
|
|
kolab_dialog_close(this, true);
|
|
|
|
file_api.req = file_api.set_busy(true, move ? 'kolab_files.filemoving' : 'kolab_files.filecopying');
|
|
file_api.request(action, {file: f, overwrite: 1}, action + '_response');
|
|
};
|
|
}
|
|
|
|
var skip_func = function() {
|
|
list.shift();
|
|
kolab_dialog_close(this, true);
|
|
|
|
if (list.length)
|
|
file_api.file_move_ask_user(list, move);
|
|
else if (move)
|
|
file_api.file_list();
|
|
};
|
|
|
|
button_classes.push('cancel file skip');
|
|
buttons[rcmail.gettext('kolab_files.fileskip')] = skip_func;
|
|
|
|
if (list.length > 1) {
|
|
button_classes.push('cancel file skip all');
|
|
buttons[rcmail.gettext('kolab_files.fileskipall')] = function() {
|
|
kolab_dialog_close(this, true);
|
|
if (move)
|
|
file_api.file_list();
|
|
};
|
|
}
|
|
|
|
// open jquery UI dialog
|
|
kolab_dialog_show(dialog.html(text), {
|
|
title: rcmail.gettext('confirmationtitle'),
|
|
close: skip_func,
|
|
buttons: buttons,
|
|
button_classes: button_classes,
|
|
height: 50,
|
|
minWidth: 400,
|
|
width: 400
|
|
});
|
|
};
|
|
|
|
// file move (with overwrite) response handler
|
|
this.file_move_ask_user_response = function(response)
|
|
{
|
|
var move = this.file_move_ask_mode, list = this.file_move_ask_list;
|
|
|
|
this.response(response);
|
|
|
|
if (list && list.length)
|
|
this.file_move_ask_user(list, mode);
|
|
else {
|
|
this.display_message('kolab_files.file' + (move ? 'move' : 'copy') + 'notice', 'confirmation');
|
|
if (move)
|
|
this.file_list();
|
|
}
|
|
};
|
|
|
|
// file(s) create (or clone) request
|
|
this.file_create = function(file, type, edit, cloneof)
|
|
{
|
|
this.file_create_edit_file = edit ? file : null;
|
|
this.file_create_edit_type = edit ? type : null;
|
|
this.file_create_folder = this.file_path(file);
|
|
|
|
if (cloneof) {
|
|
this.req = this.set_busy(true, 'kolab_files.filecopying');
|
|
this.request('file_copy', {file: cloneof, 'new': file}, 'file_create_response');
|
|
}
|
|
else {
|
|
this.req = this.set_busy(true, 'kolab_files.filecreating');
|
|
this.request('file_create', {file: file, 'content-type': type, content: ''}, 'file_create_response');
|
|
}
|
|
};
|
|
|
|
// file(s) create response handler
|
|
this.file_create_response = function(response)
|
|
{
|
|
if (!this.response(response))
|
|
return;
|
|
|
|
// @TODO: we could update metadata instead
|
|
if (this.file_create_folder == this.env.folder)
|
|
this.file_list();
|
|
|
|
// open the file for editing if editable
|
|
if (this.file_create_edit_file) {
|
|
var viewer = this.file_type_supported(this.file_create_edit_type, this.env.caps);
|
|
this.file_open(this.file_create_edit_file, viewer, {action: 'edit'});
|
|
}
|
|
};
|
|
|
|
// file(s) rename request
|
|
this.file_rename = function(oldfile, newfile)
|
|
{
|
|
this.req = this.set_busy(true, 'kolab_files.fileupdating');
|
|
this.request('file_move', {file: oldfile, 'new': newfile}, 'file_rename_response');
|
|
};
|
|
|
|
// file(s) move response handler
|
|
this.file_rename_response = function(response)
|
|
{
|
|
if (!this.response(response))
|
|
return;
|
|
|
|
// @TODO: we could update metadata instead
|
|
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 || !this.file_upload_size_check(field.files))
|
|
return;
|
|
|
|
// submit form and read server response
|
|
this.file_upload_form(form, 'file_upload', function(event) {
|
|
var doc, response;
|
|
try {
|
|
doc = this.contentDocument ? this.contentDocument : this.contentWindow.document;
|
|
response = doc.body.innerHTML;
|
|
// response may be wrapped in <pre> tag
|
|
if (response.slice(0, 5).toLowerCase() == '<pre>' && response.slice(-6).toLowerCase() == '</pre>') {
|
|
response = doc.body.firstChild.firstChild.nodeValue;
|
|
}
|
|
response = eval('(' + response + ')');
|
|
}
|
|
catch (err) {
|
|
response = {status: 'ERROR'};
|
|
}
|
|
|
|
file_api.file_upload_progress_stop(event.data.ts);
|
|
|
|
// refresh the list on upload success
|
|
file_api.file_upload_response(response);
|
|
});
|
|
};
|
|
|
|
// refresh the list on upload success
|
|
this.file_upload_response = function(response)
|
|
{
|
|
if (this.response_parse(response)) {
|
|
this.file_list();
|
|
this.quota();
|
|
}
|
|
};
|
|
|
|
// check upload max size
|
|
this.file_upload_size_check = function(files)
|
|
{
|
|
var i, size = 0, maxsize = rcmail.env.files_max_upload;
|
|
|
|
if (maxsize && files) {
|
|
for (i=0; i < files.length; i++)
|
|
size += files[i].size || files[i].fileSize;
|
|
|
|
if (size > maxsize) {
|
|
rcmail.alert_dialog(rcmail.get_label('kolab_files.uploadsizeerror').replace('$size', kolab_files_file_size(maxsize)));
|
|
return false;
|
|
}
|
|
}
|
|
|
|
return true;
|
|
};
|
|
|
|
// post the given form to a hidden iframe
|
|
this.file_upload_form = function(form, action, onload)
|
|
{
|
|
var ts = new Date().getTime(),
|
|
frame_name = 'fileupload' + ts;
|
|
|
|
// upload progress support
|
|
if (rcmail.env.files_progress_name) {
|
|
var fname = rcmail.env.files_progress_name,
|
|
field = $('input[name='+fname+']', form);
|
|
|
|
if (!field.length) {
|
|
field = $('<input>').attr({type: 'hidden', name: fname});
|
|
field.prependTo(form);
|
|
}
|
|
|
|
field.val(ts);
|
|
this.file_upload_progress(ts, true);
|
|
}
|
|
|
|
rcmail.display_progress({name: ts});
|
|
|
|
// have to do it this way for IE
|
|
// otherwise the form will be posted to a new window
|
|
if (document.all) {
|
|
var html = '<iframe id="'+frame_name+'" name="'+frame_name+'"'
|
|
+ ' src="' + rcmail.assets_path('program/resources/blank.gif') + '"'
|
|
+ ' style="width:0;height:0;visibility:hidden;"></iframe>';
|
|
document.body.insertAdjacentHTML('BeforeEnd', html);
|
|
}
|
|
// for standards-compliant browsers
|
|
else
|
|
$('<iframe>')
|
|
.attr({name: frame_name, id: frame_name})
|
|
.css({border: 'none', width: 0, height: 0, visibility: 'hidden'})
|
|
.appendTo(document.body);
|
|
|
|
// handle upload errors, parsing iframe content in onload
|
|
$('#'+frame_name).on('load', {ts:ts}, onload);
|
|
|
|
$(form).attr({
|
|
target: frame_name,
|
|
action: this.env.url + this.url(action, {folder: this.env.folder, token: this.env.token}),
|
|
method: 'POST'
|
|
}).attr(form.encoding ? 'encoding' : 'enctype', 'multipart/form-data')
|
|
.submit();
|
|
};
|
|
|
|
// handler when files are dropped to a designated area.
|
|
// compose a multipart form data and submit it to the server
|
|
this.file_drop = function(e)
|
|
{
|
|
var files = e.target.files || e.dataTransfer.files;
|
|
|
|
if (!files || !files.length || !this.file_upload_size_check(files))
|
|
return;
|
|
|
|
// prepare multipart form data composition
|
|
var ts = new Date().getTime(),
|
|
formdata = window.FormData ? new FormData() : null,
|
|
fieldname = 'file[]',
|
|
boundary = '------multipartformboundary' + (new Date).getTime(),
|
|
dashdash = '--', crlf = '\r\n',
|
|
multipart = dashdash + boundary + crlf;
|
|
|
|
// inline function to submit the files to the server
|
|
var submit_data = function() {
|
|
var multiple = files.length > 1;
|
|
|
|
rcmail.display_progress({name: ts});
|
|
if (rcmail.env.files_progress_name)
|
|
file_api.file_upload_progress(ts, true);
|
|
|
|
// complete multipart content and post request
|
|
multipart += dashdash + boundary + dashdash + crlf;
|
|
|
|
$.ajax({
|
|
type: 'POST',
|
|
dataType: 'json',
|
|
url: file_api.env.url + file_api.url('file_upload', {folder: file_api.env.folder}),
|
|
contentType: formdata ? false : 'multipart/form-data; boundary=' + boundary,
|
|
processData: false,
|
|
timeout: 0, // disable default timeout set in ajaxSetup()
|
|
data: formdata || multipart,
|
|
headers: {'X-Session-Token': file_api.env.token},
|
|
success: function(data) {
|
|
file_api.file_upload_progress_stop(ts);
|
|
file_api.file_upload_response(data);
|
|
},
|
|
error: function(o, status, err) {
|
|
file_api.file_upload_progress_stop(ts);
|
|
rcmail.http_error(o, status, err);
|
|
},
|
|
xhr: function() {
|
|
var xhr = jQuery.ajaxSettings.xhr();
|
|
if (!formdata && xhr.sendAsBinary)
|
|
xhr.send = xhr.sendAsBinary;
|
|
return xhr;
|
|
}
|
|
});
|
|
};
|
|
|
|
// upload progress supported (and handler exists)
|
|
// add progress ID to the request - need to be added before files
|
|
if (rcmail.env.files_progress_name) {
|
|
if (formdata)
|
|
formdata.append(rcmail.env.files_progress_name, ts);
|
|
else
|
|
multipart += 'Content-Disposition: form-data; name="' + rcmail.env.files_progress_name + '"'
|
|
+ crlf + crlf + ts + crlf + dashdash + boundary + crlf;
|
|
}
|
|
|
|
// get contents of all dropped files
|
|
var f, j, i = 0, last = files.length - 1;
|
|
for (j = 0; j <= last && (f = files[i]); i++) {
|
|
if (!f.name) f.name = f.fileName;
|
|
if (!f.size) f.size = f.fileSize;
|
|
if (!f.type) f.type = 'application/octet-stream';
|
|
|
|
// file name contains non-ASCII characters, do UTF8-binary string conversion.
|
|
if (!formdata && /[^\x20-\x7E]/.test(f.name))
|
|
f.name_bin = unescape(encodeURIComponent(f.name));
|
|
|
|
// do it the easy way with FormData (FF 4+, Chrome 5+, Safari 5+)
|
|
if (formdata) {
|
|
formdata.append(fieldname, f);
|
|
if (j == last)
|
|
return submit_data();
|
|
}
|
|
// use FileReader supporetd by Firefox 3.6
|
|
else if (window.FileReader) {
|
|
var reader = new FileReader();
|
|
|
|
// closure to pass file properties to async callback function
|
|
reader.onload = (function(file, j) {
|
|
return function(e) {
|
|
multipart += 'Content-Disposition: form-data; name="' + fieldname + '"';
|
|
multipart += '; filename="' + (f.name_bin || file.name) + '"' + crlf;
|
|
multipart += 'Content-Length: ' + file.size + crlf;
|
|
multipart += 'Content-Type: ' + file.type + crlf + crlf;
|
|
multipart += reader.result + crlf;
|
|
multipart += dashdash + boundary + crlf;
|
|
|
|
if (j == last) // we're done, submit the data
|
|
return submit_data();
|
|
}
|
|
})(f,j);
|
|
reader.readAsBinaryString(f);
|
|
}
|
|
|
|
j++;
|
|
}
|
|
};
|
|
|
|
// upload progress requests
|
|
this.file_upload_progress = function(id, init)
|
|
{
|
|
if (init && id)
|
|
this.uploads[id] = this.env.folder;
|
|
|
|
setTimeout(function() {
|
|
if (id && file_api.uploads[id])
|
|
file_api.request('upload_progress', {id: id}, 'file_upload_progress_response');
|
|
}, rcmail.env.files_progress_time * 1000);
|
|
};
|
|
|
|
// upload progress response
|
|
this.file_upload_progress_response = function(response)
|
|
{
|
|
if (!this.response(response))
|
|
return;
|
|
|
|
var param = response.result;
|
|
|
|
if (!param.id || !this.uploads[param.id])
|
|
return;
|
|
|
|
if (param.total) {
|
|
param.name = param.id;
|
|
|
|
if (!param.done)
|
|
param.text = kolab_files_progress_str(param);
|
|
|
|
rcmail.display_progress(param);
|
|
}
|
|
|
|
if (!param.done && param.total)
|
|
this.file_upload_progress(param.id);
|
|
else
|
|
delete this.uploads[param.id];
|
|
};
|
|
|
|
this.file_upload_progress_stop = function(id)
|
|
{
|
|
if (id) {
|
|
delete this.uploads[id];
|
|
rcmail.display_progress({name: id});
|
|
}
|
|
};
|
|
|
|
// open file in new window, using file API viewer
|
|
this.file_open = function(file, viewer, params)
|
|
{
|
|
var args = {
|
|
_task: 'files',
|
|
_action: params && params.action ? params.action : 'open',
|
|
_file: file,
|
|
_viewer: viewer || 0,
|
|
_frame: 1
|
|
};
|
|
|
|
if (rcmail.is_framed())
|
|
args._framed = 1;
|
|
|
|
if (params && params.session)
|
|
args._session = params.session;
|
|
|
|
if (rcmail.env.extwin)
|
|
args._extwin = 1;
|
|
|
|
href = '?' + $.param(args);
|
|
|
|
if (params && params.local)
|
|
location.href = href;
|
|
else
|
|
rcmail.open_window(href, false, true);
|
|
};
|
|
|
|
// save file
|
|
this.file_save = function(file, content)
|
|
{
|
|
rcmail.enable_command('files-save', false);
|
|
// because we currently can edit only text files
|
|
// and we do not expect them to be very big, we save
|
|
// file in a very simple way, no upload progress, etc.
|
|
this.req = this.set_busy(true, 'saving');
|
|
this.request('file_update', {file: file, content: content, info: 1}, 'file_save_response');
|
|
};
|
|
|
|
// file save response handler
|
|
this.file_save_response = function(response)
|
|
{
|
|
rcmail.enable_command('files-save', true);
|
|
|
|
if (!this.response(response))
|
|
return;
|
|
|
|
// update file properties table
|
|
var table = $('#fileinfobox table'), file = response.result;
|
|
|
|
if (file) {
|
|
$('td.filetype', table).text(file.type);
|
|
$('td.filesize', table).text(this.file_size(file.size));
|
|
$('td.filemtime', table).text(file.mtime);
|
|
}
|
|
};
|
|
|
|
// document session delete request
|
|
this.document_delete = function(id)
|
|
{
|
|
this.req = this.set_busy(true, 'kolab_files.sessionterminating');
|
|
this.request('document_delete', {id: id}, 'document_delete_response');
|
|
};
|
|
|
|
// document session delete response handler
|
|
this.document_delete_response = function(response, params)
|
|
{
|
|
if (!this.response(response))
|
|
return;
|
|
|
|
var list = rcmail.sessionslist;
|
|
|
|
// remove session from the list (if sessions list exist)
|
|
if (list)
|
|
list.remove_row(params.id);
|
|
|
|
if (this.env.sessions_list)
|
|
delete this.env.sessions_list[params.id];
|
|
|
|
// @todo: force sessions info update, update files list
|
|
};
|
|
|
|
// Invite document session participants
|
|
this.document_invite = function(id, attendees, comment)
|
|
{
|
|
var list = [];
|
|
|
|
// expect attendees to be email => name hash
|
|
$.each(attendees || {}, function() { list.push(this); });
|
|
|
|
if (list.length) {
|
|
this.req = this.set_busy(true, 'kolab_files.documentinviting');
|
|
this.request('document_invite', {id: id, users: list, comment: comment || ''}, 'document_invite_response');
|
|
}
|
|
};
|
|
|
|
// document invite response handler
|
|
this.document_invite_response = function(response)
|
|
{
|
|
if (!this.response(response) || !response.result)
|
|
return;
|
|
|
|
var info = rcmail.env.file_data,
|
|
table = $('#document-editors-dialog table > tbody');
|
|
|
|
$.each(response.result.list || {}, function() {
|
|
var record = kolab_files_attendee_record(this.user, this.status, this.user_name);
|
|
table.append(record);
|
|
if (info.session && info.session.invitations)
|
|
info.session.invitations.push($.extend({status: 'invited', record: record}, this));
|
|
});
|
|
};
|
|
|
|
// Cancel invitations to an editing session
|
|
this.document_cancel = function(id, attendees)
|
|
{
|
|
if (attendees.length) {
|
|
this.req = this.set_busy(true, 'kolab_files.documentcancelling');
|
|
this.request('document_cancel', {id: id, users: attendees}, 'document_cancel_response');
|
|
}
|
|
};
|
|
|
|
// document_cancel response handler
|
|
this.document_cancel_response = function(response)
|
|
{
|
|
if (!this.response(response) || !response.result)
|
|
return;
|
|
|
|
var info = rcmail.env.file_data;
|
|
|
|
$.each(response.result.list || {}, function(i, user) {
|
|
var invitations = [];
|
|
$.each(info.session.invitations, function(i, u) {
|
|
if (u.user == user && u.record)
|
|
u.record.remove();
|
|
else
|
|
invitations.push(u);
|
|
});
|
|
info.session.invitations = invitations;
|
|
});
|
|
};
|
|
|
|
// handle auth errors on folder list
|
|
this.folder_list_auth_errors = function(result)
|
|
{
|
|
if (result && result.auth_errors) {
|
|
if (!this.auth_errors)
|
|
this.auth_errors = {};
|
|
|
|
$.each(result.auth_errors || {}, function(i, v) {
|
|
// for normal errors we display only an error message, other will display a dialog
|
|
if (v.error) {
|
|
if (v.error == 580) {
|
|
rcmail.display_message(rcmail.gettext('kolab_files.storageautherror').replace('$title', i), 'error');
|
|
}
|
|
delete result.auth_errors[i];
|
|
}
|
|
});
|
|
|
|
$.extend(this.auth_errors, result.auth_errors);
|
|
}
|
|
|
|
// ask for password to the first storage on the list
|
|
var ref = this;
|
|
$.each(this.auth_errors || [], function(i, v) {
|
|
if (file_api.folder_list_auth_dialog(i, v))
|
|
return false;
|
|
});
|
|
};
|
|
|
|
// create dialog for user credentials of external storage
|
|
this.folder_list_auth_dialog = function(label, driver)
|
|
{
|
|
var args = {width: 400, height: 300, buttons: {}},
|
|
dialog = $('#files-folder-auth-dialog'),
|
|
content = this.folder_list_auth_form(driver);
|
|
|
|
if ($('#files-folder-auth-dialog').is(':visible'))
|
|
return false;
|
|
|
|
dialog.find('table.propform').remove();
|
|
$('.auth-options', dialog).before(content);
|
|
|
|
args.buttons[this.t('kolab_files.save')] = function() {
|
|
var data = {folder: label, list: 1, permissions: 1, level: -2};
|
|
|
|
$('input', dialog).each(function() {
|
|
data[this.name] = this.type == 'checkbox' && !this.checked ? '' : this.value;
|
|
});
|
|
|
|
file_api.req = file_api.set_busy(true, 'kolab_files.authenticating');
|
|
file_api.request('folder_auth', data, 'folder_auth_response');
|
|
kolab_dialog_close(this);
|
|
};
|
|
|
|
args.buttons[this.t('kolab_files.cancel')] = function() {
|
|
delete file_api.auth_errors[label];
|
|
kolab_dialog_close(this);
|
|
// go to the next one
|
|
file_api.folder_list_auth_errors();
|
|
};
|
|
|
|
args.title = this.t('kolab_files.folderauthtitle').replace('$title', label);
|
|
args.button_classes = ['mainaction save', 'cancel'];
|
|
|
|
// show dialog window
|
|
kolab_dialog_show(dialog, args, function() {
|
|
// focus first empty input
|
|
$('input', dialog).each(function() {
|
|
if (!this.value) {
|
|
this.focus();
|
|
return false;
|
|
}
|
|
});
|
|
});
|
|
|
|
return true;
|
|
};
|
|
|
|
// folder_auth handler
|
|
this.folder_auth_response = function(response, params)
|
|
{
|
|
if (!this.response(response)) {
|
|
this.folder_list_auth_errors();
|
|
return;
|
|
}
|
|
|
|
delete this.auth_errors[response.result.folder];
|
|
|
|
// go to the next one
|
|
this.folder_list_auth_errors();
|
|
|
|
// update the list
|
|
this.folder_list_merge(response.result.folder, response.result.list, params.level);
|
|
};
|
|
|
|
// Update folders list with additional folders
|
|
this.folder_list_merge = function(folder, list, level)
|
|
{
|
|
if (!list || !list.length)
|
|
return;
|
|
|
|
var i, last, folders, result = {}, index = [], ref = this;
|
|
|
|
if (this.list_merge_lock) {
|
|
return setTimeout(function() { ref.folder_list_merge(folder, list); }, 50);
|
|
}
|
|
|
|
this.list_merge_lock = true;
|
|
|
|
// Parse result
|
|
folders = this.folder_list_parse(list);
|
|
|
|
if (level < 0)
|
|
level *= -1;
|
|
|
|
// Add folders from the external source to the list
|
|
$.each(folders, function(i, f) {
|
|
if (ref.env.folders[i]) {
|
|
last = i;
|
|
return;
|
|
}
|
|
|
|
// We don't use this id
|
|
delete f.id;
|
|
|
|
// Append row to the list
|
|
var row = file_api.folder_list_row(i, f);
|
|
if (row)
|
|
ref.list_element.append(row);
|
|
|
|
// Need env.folders update so all parents are available
|
|
// in successive folder_list_row() calls
|
|
ref.env.folders[i] = f;
|
|
index.push(i);
|
|
|
|
// Load deeper folder hierarchies
|
|
if (level && f.depth == level)
|
|
ref.folder_list_update_wait(i);
|
|
});
|
|
|
|
// Reset folders list widget
|
|
rcmail.folder_list.reset(true, true);
|
|
|
|
// Rebuild folders list with correct order
|
|
for (i in this.env.folders) {
|
|
result[i] = this.env.folders[i];
|
|
if (i === last)
|
|
break;
|
|
}
|
|
for (i in index) {
|
|
result[index[i]] = this.env.folders[index[i]];
|
|
}
|
|
for (i in this.env.folders) {
|
|
if (!result[i]) {
|
|
result[i] = this.env.folders[i];
|
|
}
|
|
}
|
|
|
|
this.env.folders = result;
|
|
|
|
if ((folder = this.env.folder) || (folder = this.env.init_folder)) {
|
|
if (this.env.folders[folder]) {
|
|
this.env.init_folder = null;
|
|
if (folder != rcmail.folder_list.get_selection())
|
|
rcmail.folder_list.select(folder);
|
|
}
|
|
}
|
|
|
|
this.list_merge_lock = false;
|
|
};
|
|
|
|
// returns content of the external storage authentication form
|
|
this.folder_list_auth_form = function(driver)
|
|
{
|
|
var rows = [];
|
|
|
|
$.each(driver.form, function(fi, fv) {
|
|
var id = 'authinput' + fi,
|
|
attrs = {type: fi.match(/pass/) ? 'password' : 'text', size: 25, name: fi, id: id},
|
|
input = $('<input>').attr(attrs);
|
|
|
|
if (driver.form_values && driver.form_values[fi])
|
|
input.attr({value: driver.form_values[fi]});
|
|
|
|
rows.push($('<tr>')
|
|
.append($('<td class="title">').append($('<label>').attr('for', id).text(fv)))
|
|
.append($('<td>').append(input))
|
|
);
|
|
});
|
|
|
|
return $('<table class="propform">').append(rows);
|
|
};
|
|
};
|