Files: Multi-folder searches (collections) improvements (Bifrost#T193529)

- To update file sessions metadata use only ony request for all folders
in the search result, instead of potentially massive number of
requests for each folder.
- Added possibility to abort searching.
This commit is contained in:
Aleksander Machniak 2019-03-22 12:09:06 +00:00
parent a0f73ec2c5
commit 391997b9a8
3 changed files with 125 additions and 75 deletions

View file

@ -2103,7 +2103,6 @@ function kolab_files_ui()
{ {
this.requests = {}; this.requests = {};
this.uploads = []; this.uploads = [];
this.workers = {};
this.list_updates = 0; this.list_updates = 0;
/* /*
@ -3044,6 +3043,8 @@ function kolab_files_ui()
if (!rcmail.gui_objects.sessionslist) if (!rcmail.gui_objects.sessionslist)
return; return;
this.file_list_abort(true);
if (!params) if (!params)
params = {}; params = {};
@ -3092,23 +3093,11 @@ function kolab_files_ui()
if (!rcmail.gui_objects.fileslist) if (!rcmail.gui_objects.fileslist)
return; return;
this.file_list_abort(true);
if (!params) if (!params)
params = {}; params = {};
// reset all pending list requests
$.each(this.requests, function(i, v) {
v.abort();
rcmail.hide_message(i);
});
// reset folder_info workers
$.each(this.workers, function(i, v) {
clearTimeout(v);
});
this.workers = {};
this.requests = {};
if (params.all_folders) { if (params.all_folders) {
params.collection = null; params.collection = null;
params.folder = null; params.folder = null;
@ -3149,7 +3138,7 @@ function kolab_files_ui()
if (params.collection || params.all_folders) if (params.collection || params.all_folders)
this.file_list_loop(params); this.file_list_loop(params);
else if (this.env.folder) { else if (this.env.folder) {
params.req_id = this.set_busy(true, 'loading'); 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'); this.requests[params.req_id] = this.request('file_list', params, 'file_list_response');
} }
}; };
@ -3182,10 +3171,30 @@ function kolab_files_ui()
this.request('folder_info', {folder: this.file_path(list[0].filename), sessions: 1}, 'folder_info_response'); 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) // call file_list request for every folder (used for search and virt. collections)
this.file_list_loop = function(params) this.file_list_loop = function(params)
{ {
var i, folders = [], limit = Math.max(this.env.search_threads || 1, 1); 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.collection) {
if (!params.search) if (!params.search)
@ -3202,32 +3211,38 @@ function kolab_files_ui()
}); });
this.env.folders_loop = folders; this.env.folders_loop = folders;
this.env.folders_loop_params = params;
this.env.folders_loop_lock = false; 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++) { for (i=0; i<folders.length && i<limit; i++) {
params.req_id = this.set_busy(true, 'loading'); params.req_id = new Date().getTime();
params.folder = folders.shift(); params.folder = folders.shift();
this.requests[params.req_id] = this.request('file_list', params, 'file_list_loop_response'); this.requests[params.req_id] = this.request('file_list', params, 'file_list_loop_response');
} }
}; };
// file list response handler for loop'ed request // file list response handler for loop'ed request
this.file_list_loop_response = function(response) this.file_list_loop_response = function(response, params)
{ {
var i, folders = this.env.folders_loop, var folders = this.env.folders_loop,
params = this.env.folders_loop_params,
limit = Math.max(this.env.search_threads || 1, 1),
valid = this.response(response); valid = this.response(response);
if (response.req_id) if (folders.length) {
rcmail.hide_message(response.req_id); params.req_id = new Date().getTime();
for (i=0; i<folders.length && i<limit; i++) {
params.req_id = this.set_busy(true, 'loading');
params.folder = folders.shift(); params.folder = folders.shift();
this.requests[params.req_id] = this.request('file_list', params, 'file_list_loop_response'); 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(); rcmail.fileslist.resize();
@ -3237,6 +3252,36 @@ function kolab_files_ui()
this.file_list_loop_result_add(response.result); 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) // add files from list request to the table (with sorting)
this.file_list_loop_result_add = function(result) this.file_list_loop_result_add = function(result)
{ {
@ -3252,9 +3297,19 @@ function kolab_files_ui()
// lock table, other list responses will wait // lock table, other list responses will wait
this.env.folders_loop_lock = true; this.env.folders_loop_lock = true;
var n, i, len, elem, row, folder, list = [], var n, i, len, elem, folder, list = [],
index = this.env.file_list.length, index = this.env.file_list.length,
table = rcmail.fileslist; 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++) { for (n=0, len=index; n<len; n++) {
elem = this.env.file_list[n]; elem = this.env.file_list[n];
@ -3262,15 +3317,7 @@ function kolab_files_ui()
if (this.sort_compare(elem, result[i]) < 0) if (this.sort_compare(elem, result[i]) < 0)
break; break;
row = this.file_list_row(i, result[i], ++index); fn(result, i, elem.row);
table.insert_row(row, elem.row);
result[i].row = row;
result[i].filename = i;
list.push(result[i]);
if (!folder)
folder = this.file_path(i);
delete result[i]; delete result[i];
} }
@ -3278,23 +3325,18 @@ function kolab_files_ui()
} }
// add the rest of rows // add the rest of rows
$.each(result, function(key, data) { for (i in result) fn(result, i);
var row = file_api.file_list_row(key, data, ++index);
table.insert_row(row);
result[key].row = row;
result[key].filename = key;
list.push(result[key]);
if (!folder)
folder = file_api.file_path(key);
});
this.env.file_list = list; this.env.file_list = list;
this.env.folders_loop_lock = false;
// update document sessions info of this folder // update files list with document session info
if (folder) if (folder && this.sessions[folder])
this.request('folder_info', {folder: folder, sessions: 1}, 'folder_info_response'); $.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) // sort files list (without API request)
@ -3420,36 +3462,41 @@ function kolab_files_ui()
// update files list with document session info // update files list with document session info
$.each(file_api.env.file_list || [], function(i, file) { $.each(file_api.env.file_list || [], function(i, file) {
// skip files from a different folder (in multi-folder listing) // skip files from a different folder (in multi-folder listing)
if (file.filename.indexOf(prefix) !== 0) if (file.filename.indexOf(prefix) >= 0)
return; file_api.file_session_data_set(file, response.result.sessions)
var classes = [];
if ($(file.row).is('.selected'))
classes.push('selected');
$.each(response.result.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');
}
});
$(file.row).attr('class', classes.join(' '));
}); });
// refresh sessions info in time intervals // refresh sessions info in time intervals
if (this.env.caps && this.env.caps.DOCEDIT && (rcmail.fileslist || rcmail.env.file)) if (this.env.caps && this.env.caps.DOCEDIT && (rcmail.fileslist || rcmail.env.file))
this.workers[folder] = setTimeout(function() { this.file_list_worker = setTimeout(function() {
file_api.request('folder_info', {folder: folder, sessions: 1}, 'folder_info_response'); file_api.request('folder_info', {folder: folder, sessions: 1}, 'folder_info_response');
}, (rcmail.env.files_interval || 60) * 1000); }, (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) this.file_get = function(file, params)
{ {
if (!params) if (!params)

View file

@ -702,6 +702,8 @@ class kolab_files_engine
$this->rc->output->include_script('list.js'); $this->rc->output->include_script('list.js');
$this->rc->output->add_label('kolab_files.abort', 'searching');
// attach css rules for mimetype icons // attach css rules for mimetype icons
if (!$this->filetypes_style) { if (!$this->filetypes_style) {
$this->plugin->include_stylesheet($this->url . '/skins/default/images/mimetypes/style.css'); $this->plugin->include_stylesheet($this->url . '/skins/default/images/mimetypes/style.css');

View file

@ -68,6 +68,7 @@ $labels['collection_image'] = 'Images';
$labels['collection_document'] = 'Documents'; $labels['collection_document'] = 'Documents';
$labels['sessions'] = 'Sessions'; $labels['sessions'] = 'Sessions';
$labels['abort'] = 'Abort';
$labels['uploading'] = 'Uploading file(s)...'; $labels['uploading'] = 'Uploading file(s)...';
$labels['attaching'] = 'Attaching file(s)...'; $labels['attaching'] = 'Attaching file(s)...';
$labels['authenticating'] = 'Authenticating...'; $labels['authenticating'] = 'Authenticating...';