40228c0c2b
added quit option in notif in app.js added quit option in notif in file-upload.js added quit option in notif in fileinfomodel.js added quit option in notif in filelist.js added quit option in notif in filelist.js added quit option in notif in tagsplugin.js added quit option in notif in statusmanager.js added quit option in notif in external.js added quit option in notif in versionstabview.js added quit option in notif in notification.js changes according to the latest review. timeout removed since there is a button to close it translation capability added typo fixed test files updated small errors fixed Signed-off-by: Morris Jobke <hey@morrisjobke.de>
623 lines
19 KiB
JavaScript
623 lines
19 KiB
JavaScript
/**
|
|
* ownCloud
|
|
*
|
|
* @author Juan Pablo Villafañez Ramos <jvillafanez@owncloud.com>
|
|
* @author Jesus Macias Portela <jesus@owncloud.com>
|
|
* @copyright (C) 2014 ownCloud, Inc.
|
|
*
|
|
* This file is licensed under the Affero General Public License version 3
|
|
* or later.
|
|
*
|
|
* See the COPYING-README file.
|
|
*
|
|
*/
|
|
|
|
/** @global Handlebars */
|
|
|
|
if (!OCA.External) {
|
|
OCA.External = {};
|
|
}
|
|
|
|
if (!OCA.External.StatusManager) {
|
|
OCA.External.StatusManager = {};
|
|
}
|
|
|
|
OCA.External.StatusManager = {
|
|
|
|
mountStatus: null,
|
|
mountPointList: null,
|
|
|
|
/**
|
|
* Function
|
|
* @param {callback} afterCallback
|
|
*/
|
|
|
|
getMountStatus: function (afterCallback) {
|
|
var self = this;
|
|
if (typeof afterCallback !== 'function' || self.isGetMountStatusRunning) {
|
|
return;
|
|
}
|
|
|
|
if (self.mountStatus) {
|
|
afterCallback(self.mountStatus);
|
|
}
|
|
},
|
|
|
|
/**
|
|
* Function Check mount point status from cache
|
|
* @param {string} mount_point
|
|
*/
|
|
|
|
getMountPointListElement: function (mount_point) {
|
|
var element;
|
|
$.each(this.mountPointList, function (key, value) {
|
|
if (value.mount_point === mount_point) {
|
|
element = value;
|
|
return false;
|
|
}
|
|
});
|
|
return element;
|
|
},
|
|
|
|
/**
|
|
* Function Check mount point status from cache
|
|
* @param {string} mount_point
|
|
* @param {string} mount_point
|
|
*/
|
|
|
|
getMountStatusForMount: function (mountData, afterCallback) {
|
|
var self = this;
|
|
if (typeof afterCallback !== 'function' || self.isGetMountStatusRunning) {
|
|
return $.Deferred().resolve();
|
|
}
|
|
|
|
var defObj;
|
|
if (self.mountStatus[mountData.mount_point]) {
|
|
defObj = $.Deferred();
|
|
afterCallback(mountData, self.mountStatus[mountData.mount_point]);
|
|
defObj.resolve(); // not really useful, but it'll keep the same behaviour
|
|
} else {
|
|
defObj = $.ajax({
|
|
type: 'GET',
|
|
url: OC.webroot + '/index.php/apps/files_external/' + ((mountData.type === 'personal') ? 'userstorages' : 'userglobalstorages') + '/' + mountData.id,
|
|
data: {'testOnly' : false},
|
|
success: function (response) {
|
|
if (response && response.status === 0) {
|
|
self.mountStatus[mountData.mount_point] = response;
|
|
} else {
|
|
var statusCode = response.status ? response.status : 1;
|
|
var statusMessage = response.statusMessage ? response.statusMessage : t('files_external', 'Empty response from the server')
|
|
// failure response with error message
|
|
self.mountStatus[mountData.mount_point] = {
|
|
type: mountData.type,
|
|
status: statusCode,
|
|
id: mountData.id,
|
|
error: statusMessage,
|
|
userProvided: response.userProvided
|
|
};
|
|
}
|
|
afterCallback(mountData, self.mountStatus[mountData.mount_point]);
|
|
},
|
|
error: function (jqxhr, state, error) {
|
|
var message;
|
|
if (mountData.location === 3) {
|
|
// In this case the error is because mount point use Login credentials and don't exist in the session
|
|
message = t('files_external', 'Couldn\'t access. Please logout and login to activate this mount point');
|
|
} else {
|
|
message = t('files_external', 'Couldn\'t get the information from the remote server: {code} {type}', {
|
|
code: jqxhr.status,
|
|
type: error
|
|
});
|
|
}
|
|
self.mountStatus[mountData.mount_point] = {
|
|
type: mountData.type,
|
|
status: 1,
|
|
location: mountData.location,
|
|
error: message
|
|
};
|
|
afterCallback(mountData, self.mountStatus[mountData.mount_point]);
|
|
}
|
|
});
|
|
}
|
|
return defObj;
|
|
},
|
|
|
|
/**
|
|
* Function to get external mount point list from the files_external API
|
|
* @param {function} afterCallback function to be executed
|
|
*/
|
|
|
|
getMountPointList: function (afterCallback) {
|
|
var self = this;
|
|
if (typeof afterCallback !== 'function' || self.isGetMountPointListRunning) {
|
|
return;
|
|
}
|
|
|
|
if (self.mountPointList) {
|
|
afterCallback(self.mountPointList);
|
|
} else {
|
|
self.isGetMountPointListRunning = true;
|
|
$.ajax({
|
|
type: 'GET',
|
|
url: OC.linkToOCS('apps/files_external/api/v1') + 'mounts?format=json',
|
|
success: function (response) {
|
|
self.mountPointList = [];
|
|
_.each(response.ocs.data, function (mount) {
|
|
var element = {};
|
|
element.mount_point = mount.name;
|
|
element.type = mount.scope;
|
|
element.location = "";
|
|
element.id = mount.id;
|
|
element.backendText = mount.backend;
|
|
element.backend = mount.class;
|
|
|
|
self.mountPointList.push(element);
|
|
});
|
|
afterCallback(self.mountPointList);
|
|
},
|
|
error: function (jqxhr, state, error) {
|
|
self.mountPointList = [];
|
|
OC.Notification.show(t('files_external', 'Couldn\'t get the list of external mount points: {type}',
|
|
{type: error}), {type: 'error'}
|
|
);
|
|
},
|
|
complete: function () {
|
|
self.isGetMountPointListRunning = false;
|
|
}
|
|
});
|
|
}
|
|
},
|
|
|
|
/**
|
|
* Function to manage action when a mountpoint status = 1 (Errored). Show a dialog to be redirected to settings page.
|
|
* @param {string} name MountPoint Name
|
|
*/
|
|
|
|
manageMountPointError: function (name) {
|
|
this.getMountStatus($.proxy(function (allMountStatus) {
|
|
if (allMountStatus.hasOwnProperty(name) && allMountStatus[name].status > 0 && allMountStatus[name].status < 7) {
|
|
var mountData = allMountStatus[name];
|
|
if (mountData.type === "system") {
|
|
if (mountData.userProvided) {
|
|
// personal mount whit credentials problems
|
|
this.showCredentialsDialog(name, mountData);
|
|
} else {
|
|
OC.dialogs.confirm(t('files_external', 'There was an error with message: ') + mountData.error + '. Do you want to review mount point config in admin settings page?', t('files_external', 'External mount error'), function (e) {
|
|
if (e === true) {
|
|
OC.redirect(OC.generateUrl('/settings/admin/externalstorages'));
|
|
}
|
|
});
|
|
}
|
|
} else {
|
|
OC.dialogs.confirm(t('files_external', 'There was an error with message: ') + mountData.error + '. Do you want to review mount point config in personal settings page?', t('files_external', 'External mount error'), function (e) {
|
|
if (e === true) {
|
|
OC.redirect(OC.generateUrl('/settings/personal#' + t('files_external', 'external-storage')));
|
|
}
|
|
});
|
|
}
|
|
}
|
|
}, this));
|
|
},
|
|
|
|
/**
|
|
* Function to process a mount point in relation with their status, Called from Async Queue.
|
|
* @param {object} mountData
|
|
* @param {object} mountStatus
|
|
*/
|
|
|
|
processMountStatusIndividual: function (mountData, mountStatus) {
|
|
|
|
var mountPoint = mountData.mount_point;
|
|
if (mountStatus.status > 0) {
|
|
var trElement = FileList.findFileEl(OCA.External.StatusManager.Utils.jqSelEscape(mountPoint));
|
|
|
|
var route = OCA.External.StatusManager.Utils.getIconRoute(trElement) + '-error';
|
|
|
|
if (OCA.External.StatusManager.Utils.isCorrectViewAndRootFolder()) {
|
|
OCA.External.StatusManager.Utils.showIconError(mountPoint, $.proxy(OCA.External.StatusManager.manageMountPointError, OCA.External.StatusManager), route);
|
|
}
|
|
return false;
|
|
} else {
|
|
if (OCA.External.StatusManager.Utils.isCorrectViewAndRootFolder()) {
|
|
OCA.External.StatusManager.Utils.restoreFolder(mountPoint);
|
|
OCA.External.StatusManager.Utils.toggleLink(mountPoint, true, true);
|
|
}
|
|
return true;
|
|
}
|
|
},
|
|
|
|
/**
|
|
* Function to process a mount point in relation with their status
|
|
* @param {object} mountData
|
|
* @param {object} mountStatus
|
|
*/
|
|
|
|
processMountList: function (mountList) {
|
|
var elementList = null;
|
|
$.each(mountList, function (name, value) {
|
|
var trElement = $('#fileList tr[data-file=\"' + OCA.External.StatusManager.Utils.jqSelEscape(value.mount_point) + '\"]'); //FileList.findFileEl(OCA.External.StatusManager.Utils.jqSelEscape(value.mount_point));
|
|
trElement.attr('data-external-backend', value.backend);
|
|
if (elementList) {
|
|
elementList = elementList.add(trElement);
|
|
} else {
|
|
elementList = trElement;
|
|
}
|
|
});
|
|
|
|
if (elementList instanceof $) {
|
|
if (OCA.External.StatusManager.Utils.isCorrectViewAndRootFolder()) {
|
|
// Put their custom icon
|
|
OCA.External.StatusManager.Utils.changeFolderIcon(elementList);
|
|
// Save default view
|
|
OCA.External.StatusManager.Utils.storeDefaultFolderIconAndBgcolor(elementList);
|
|
// Disable row until check status
|
|
elementList.addClass('externalDisabledRow');
|
|
OCA.External.StatusManager.Utils.toggleLink(elementList.find('a.name'), false, false);
|
|
}
|
|
}
|
|
},
|
|
|
|
/**
|
|
* Function to process the whole mount point list in relation with their status (Async queue)
|
|
*/
|
|
|
|
launchFullConnectivityCheckOneByOne: function () {
|
|
var self = this;
|
|
this.getMountPointList(function (list) {
|
|
// check if we have a list first
|
|
if (list === undefined && !self.emptyWarningShown) {
|
|
self.emptyWarningShown = true;
|
|
OC.Notification.show(t('files_external', 'Couldn\'t get the list of Windows network drive mount points: empty response from the server'),
|
|
{type: 'error'}
|
|
);
|
|
return;
|
|
}
|
|
if (list && list.length > 0) {
|
|
self.processMountList(list);
|
|
|
|
if (!self.mountStatus) {
|
|
self.mountStatus = {};
|
|
}
|
|
|
|
var ajaxQueue = [];
|
|
$.each(list, function (key, value) {
|
|
var queueElement = {
|
|
funcName: $.proxy(self.getMountStatusForMount, self),
|
|
funcArgs: [value,
|
|
$.proxy(self.processMountStatusIndividual, self)]
|
|
};
|
|
ajaxQueue.push(queueElement);
|
|
});
|
|
|
|
var rolQueue = new OCA.External.StatusManager.RollingQueue(ajaxQueue, 4, function () {
|
|
if (!self.notificationHasShown) {
|
|
var showNotification = false;
|
|
$.each(self.mountStatus, function (key, value) {
|
|
if (value.status === 1) {
|
|
self.notificationHasShown = true;
|
|
showNotification = true;
|
|
}
|
|
});
|
|
if (showNotification) {
|
|
OC.Notification.show(t('files_external', 'Some of the configured external mount points are not connected. Please click on the red row(s) for more information'),
|
|
{type: 'error'}
|
|
);
|
|
}
|
|
}
|
|
});
|
|
rolQueue.runQueue();
|
|
}
|
|
});
|
|
},
|
|
|
|
|
|
/**
|
|
* Function to process a mount point list in relation with their status (Async queue)
|
|
* @param {object} mountListData
|
|
* @param {boolean} recheck delete cached info and force api call to check mount point status
|
|
*/
|
|
|
|
launchPartialConnectivityCheck: function (mountListData, recheck) {
|
|
if (mountListData.length === 0) {
|
|
return;
|
|
}
|
|
|
|
var self = this;
|
|
var ajaxQueue = [];
|
|
$.each(mountListData, function (key, value) {
|
|
if (recheck && value.mount_point in self.mountStatus) {
|
|
delete self.mountStatus[value.mount_point];
|
|
}
|
|
var queueElement = {
|
|
funcName: $.proxy(self.getMountStatusForMount, self),
|
|
funcArgs: [value,
|
|
$.proxy(self.processMountStatusIndividual, self)]
|
|
};
|
|
ajaxQueue.push(queueElement);
|
|
});
|
|
new OCA.External.StatusManager.RollingQueue(ajaxQueue, 4).runQueue();
|
|
},
|
|
|
|
|
|
/**
|
|
* Function to relaunch some mount point status check
|
|
* @param {string} mountListNames
|
|
* @param {boolean} recheck delete cached info and force api call to check mount point status
|
|
*/
|
|
|
|
recheckConnectivityForMount: function (mountListNames, recheck) {
|
|
if (mountListNames.length === 0) {
|
|
return;
|
|
}
|
|
|
|
var self = this;
|
|
var mountListData = [];
|
|
|
|
if (!self.mountStatus) {
|
|
self.mountStatus = {};
|
|
}
|
|
|
|
$.each(mountListNames, function (key, value) {
|
|
var mountData = self.getMountPointListElement(value);
|
|
if (mountData) {
|
|
mountListData.push(mountData);
|
|
}
|
|
});
|
|
|
|
// for all mounts in the list, delete the cached status values
|
|
if (recheck) {
|
|
$.each(mountListData, function (key, value) {
|
|
if (value.mount_point in self.mountStatus) {
|
|
delete self.mountStatus[value.mount_point];
|
|
}
|
|
});
|
|
}
|
|
|
|
self.processMountList(mountListData);
|
|
self.launchPartialConnectivityCheck(mountListData, recheck);
|
|
},
|
|
|
|
credentialsDialogTemplate:
|
|
'<div id="files_external_div_form"><div>' +
|
|
'<div>{{credentials_text}}</div>' +
|
|
'<form>' +
|
|
'<input type="text" name="username" placeholder="{{placeholder_username}}"/>' +
|
|
'<input type="password" name="password" placeholder="{{placeholder_password}}"/>' +
|
|
'</form>' +
|
|
'</div></div>',
|
|
|
|
/**
|
|
* Function to display custom dialog to enter credentials
|
|
* @param mountPoint
|
|
* @param mountData
|
|
*/
|
|
showCredentialsDialog: function (mountPoint, mountData) {
|
|
var template = Handlebars.compile(OCA.External.StatusManager.credentialsDialogTemplate);
|
|
var dialog = $(template({
|
|
credentials_text: t('files_external', 'Please enter the credentials for the {mount} mount', {
|
|
'mount': mountPoint
|
|
}),
|
|
placeholder_username: t('files_external', 'Username'),
|
|
placeholder_password: t('files_external', 'Password')
|
|
}));
|
|
|
|
$('body').append(dialog);
|
|
|
|
var apply = function () {
|
|
var username = dialog.find('[name=username]').val();
|
|
var password = dialog.find('[name=password]').val();
|
|
var endpoint = OC.generateUrl('apps/files_external/userglobalstorages/{id}', {
|
|
id: mountData.id
|
|
});
|
|
$('.oc-dialog-close').hide();
|
|
$.ajax({
|
|
type: 'PUT',
|
|
url: endpoint,
|
|
data: {
|
|
backendOptions: {
|
|
user: username,
|
|
password: password
|
|
}
|
|
},
|
|
success: function (data) {
|
|
OC.Notification.show(t('files_external', 'Credentials saved'), {type: 'error'});
|
|
dialog.ocdialog('close');
|
|
/* Trigger status check again */
|
|
OCA.External.StatusManager.recheckConnectivityForMount([OC.basename(data.mountPoint)], true);
|
|
},
|
|
error: function () {
|
|
$('.oc-dialog-close').show();
|
|
OC.Notification.show(t('files_external', 'Credentials saving failed'), {type: 'error'});
|
|
}
|
|
});
|
|
return false;
|
|
};
|
|
|
|
var ocdialogParams = {
|
|
modal: true,
|
|
title: t('files_external', 'Credentials required'),
|
|
buttons: [{
|
|
text: t('files_external', 'Save'),
|
|
click: apply,
|
|
closeOnEscape: true
|
|
}],
|
|
closeOnExcape: true
|
|
};
|
|
|
|
dialog.ocdialog(ocdialogParams)
|
|
.bind('ocdialogclose', function () {
|
|
dialog.ocdialog('destroy').remove();
|
|
});
|
|
|
|
dialog.find('form').on('submit', apply);
|
|
dialog.find('form input:first').focus();
|
|
dialog.find('form input').keyup(function (e) {
|
|
if ((e.which && e.which === 13) || (e.keyCode && e.keyCode === 13)) {
|
|
$(e.target).closest('form').submit();
|
|
return false;
|
|
} else {
|
|
return true;
|
|
}
|
|
});
|
|
}
|
|
};
|
|
|
|
OCA.External.StatusManager.Utils = {
|
|
|
|
showIconError: function (folder, clickAction, errorImageUrl) {
|
|
var imageUrl = "url(" + errorImageUrl + ")";
|
|
var trFolder = $('#fileList tr[data-file=\"' + OCA.External.StatusManager.Utils.jqSelEscape(folder) + '\"]'); //FileList.findFileEl(OCA.External.StatusManager.Utils.jqSelEscape(folder));
|
|
this.changeFolderIcon(folder, imageUrl);
|
|
this.toggleLink(folder, false, clickAction);
|
|
trFolder.addClass('externalErroredRow');
|
|
},
|
|
|
|
/**
|
|
* @param folder string with the folder or jQuery element pointing to the tr element
|
|
*/
|
|
storeDefaultFolderIconAndBgcolor: function (folder) {
|
|
var trFolder;
|
|
if (folder instanceof $) {
|
|
trFolder = folder;
|
|
} else {
|
|
trFolder = $('#fileList tr[data-file=\"' + OCA.External.StatusManager.Utils.jqSelEscape(folder) + '\"]'); //FileList.findFileEl(OCA.External.StatusManager.Utils.jqSelEscape(folder)); //$('#fileList tr[data-file=\"' + OCA.External.StatusManager.Utils.jqSelEscape(folder) + '\"]');
|
|
}
|
|
trFolder.each(function () {
|
|
var thisElement = $(this);
|
|
if (thisElement.data('oldbgcolor') === undefined) {
|
|
thisElement.data('oldbgcolor', thisElement.css('background-color'));
|
|
}
|
|
});
|
|
|
|
var icon = trFolder.find('td:first-child div.thumbnail');
|
|
icon.each(function () {
|
|
var thisElement = $(this);
|
|
if (thisElement.data('oldImage') === undefined) {
|
|
thisElement.data('oldImage', thisElement.css('background-image'));
|
|
}
|
|
});
|
|
},
|
|
|
|
/**
|
|
* @param folder string with the folder or jQuery element pointing to the tr element
|
|
*/
|
|
restoreFolder: function (folder) {
|
|
var trFolder;
|
|
if (folder instanceof $) {
|
|
trFolder = folder;
|
|
} else {
|
|
// can't use here FileList.findFileEl(OCA.External.StatusManager.Utils.jqSelEscape(folder)); return incorrect instance of filelist
|
|
trFolder = $('#fileList tr[data-file=\"' + OCA.External.StatusManager.Utils.jqSelEscape(folder) + '\"]');
|
|
}
|
|
trFolder.removeClass('externalErroredRow').removeClass('externalDisabledRow');
|
|
var tdChilds = trFolder.find("td:first-child div.thumbnail");
|
|
tdChilds.each(function () {
|
|
var thisElement = $(this);
|
|
thisElement.css('background-image', thisElement.data('oldImage'));
|
|
});
|
|
},
|
|
|
|
/**
|
|
* @param folder string with the folder or jQuery element pointing to the first td element
|
|
* of the tr matching the folder name
|
|
*/
|
|
changeFolderIcon: function (filename) {
|
|
var file;
|
|
var route;
|
|
if (filename instanceof $) {
|
|
//trElementList
|
|
$.each(filename, function (index) {
|
|
route = OCA.External.StatusManager.Utils.getIconRoute($(this));
|
|
$(this).attr("data-icon", route);
|
|
$(this).find('td:first-child div.thumbnail').css('background-image', "url(" + route + ")").css('display', 'none').css('display', 'inline');
|
|
});
|
|
} else {
|
|
file = $("#fileList tr[data-file=\"" + this.jqSelEscape(filename) + "\"] > td:first-child div.thumbnail");
|
|
var parentTr = file.parents('tr:first');
|
|
route = OCA.External.StatusManager.Utils.getIconRoute(parentTr);
|
|
parentTr.attr("data-icon", route);
|
|
file.css('background-image', "url(" + route + ")").css('display', 'none').css('display', 'inline');
|
|
}
|
|
},
|
|
|
|
/**
|
|
* @param backend string with the name of the external storage backend
|
|
* of the tr matching the folder name
|
|
*/
|
|
getIconRoute: function (tr) {
|
|
if (OCA.Theming) {
|
|
var icon = OC.generateUrl('/apps/theming/img/core/filetypes/folder-external.svg?v=' + OCA.Theming.cacheBuster);
|
|
} else {
|
|
var icon = OC.imagePath('core', 'filetypes/folder-external');
|
|
}
|
|
var backend = null;
|
|
|
|
if (tr instanceof $) {
|
|
backend = tr.attr('data-external-backend');
|
|
}
|
|
|
|
switch (backend) {
|
|
case 'windows_network_drive':
|
|
icon = OC.imagePath('windows_network_drive', 'folder-windows');
|
|
break;
|
|
case 'sharepoint':
|
|
icon = OC.imagePath('sharepoint', 'folder-sharepoint');
|
|
break;
|
|
}
|
|
|
|
return icon;
|
|
},
|
|
|
|
toggleLink: function (filename, active, action) {
|
|
var link;
|
|
if (filename instanceof $) {
|
|
link = filename;
|
|
} else {
|
|
link = $("#fileList tr[data-file=\"" + this.jqSelEscape(filename) + "\"] > td:first-child a.name");
|
|
}
|
|
if (active) {
|
|
link.off('click.connectivity');
|
|
OCA.Files.App.fileList.fileActions.display(link.parent(), true, OCA.Files.App.fileList);
|
|
} else {
|
|
link.find('.fileactions, .nametext .action').remove(); // from files/js/fileactions (display)
|
|
link.off('click.connectivity');
|
|
link.on('click.connectivity', function (e) {
|
|
if (action && $.isFunction(action)) {
|
|
action(filename);
|
|
}
|
|
e.preventDefault();
|
|
return false;
|
|
});
|
|
}
|
|
},
|
|
|
|
isCorrectViewAndRootFolder: function () {
|
|
// correct views = files & extstoragemounts
|
|
if (OCA.Files.App.getActiveView() === 'files' || OCA.Files.App.getActiveView() === 'extstoragemounts') {
|
|
return OCA.Files.App.getCurrentAppContainer().find('#dir').val() === '/';
|
|
}
|
|
return false;
|
|
},
|
|
|
|
/* escape a selector expression for jQuery */
|
|
jqSelEscape: function (expression) {
|
|
if (expression) {
|
|
return expression.replace(/[!"#$%&'()*+,.\/:;<=>?@\[\\\]^`{|}~]/g, '\\$&');
|
|
}
|
|
return null;
|
|
},
|
|
|
|
/* Copied from http://stackoverflow.com/questions/2631001/javascript-test-for-existence-of-nested-object-key */
|
|
checkNested: function (cobj /*, level1, level2, ... levelN*/) {
|
|
var args = Array.prototype.slice.call(arguments),
|
|
obj = args.shift();
|
|
|
|
for (var i = 0; i < args.length; i++) {
|
|
if (!obj || !obj.hasOwnProperty(args[i])) {
|
|
return false;
|
|
}
|
|
obj = obj[args[i]];
|
|
}
|
|
return true;
|
|
}
|
|
};
|