diff options
Diffstat (limited to 'apps/files_external/js/settings.js')
-rw-r--r-- | apps/files_external/js/settings.js | 1513 |
1 files changed, 0 insertions, 1513 deletions
diff --git a/apps/files_external/js/settings.js b/apps/files_external/js/settings.js deleted file mode 100644 index db77fe4dfc1..00000000000 --- a/apps/files_external/js/settings.js +++ /dev/null @@ -1,1513 +0,0 @@ -/* - * Copyright (c) 2014 - * - * This file is licensed under the Affero General Public License version 3 - * or later. - * - * See the COPYING-README file. - * - */ - -(function(){ - -/** - * Returns the selection of applicable users in the given configuration row - * - * @param $row configuration row - * @return array array of user names - */ -function getSelection($row) { - var values = $row.find('.applicableUsers').select2('val'); - if (!values || values.length === 0) { - values = []; - } - return values; -} - -function getSelectedApplicable($row) { - var users = []; - var groups = []; - var multiselect = getSelection($row); - $.each(multiselect, function(index, value) { - // FIXME: don't rely on string parts to detect groups... - var pos = (value.indexOf)?value.indexOf('(group)'): -1; - if (pos !== -1) { - groups.push(value.substr(0, pos)); - } else { - users.push(value); - } - }); - - // FIXME: this should be done in the multiselect change event instead - $row.find('.applicable') - .data('applicable-groups', groups) - .data('applicable-users', users); - - return { users, groups }; -} - -function highlightBorder($element, highlight) { - $element.toggleClass('warning-input', highlight); - return highlight; -} - -function isInputValid($input) { - var optional = $input.hasClass('optional'); - switch ($input.attr('type')) { - case 'text': - case 'password': - if ($input.val() === '' && !optional) { - return false; - } - break; - } - return true; -} - -function highlightInput($input) { - switch ($input.attr('type')) { - case 'text': - case 'password': - return highlightBorder($input, !isInputValid($input)); - } -} - -/** - * Initialize select2 plugin on the given elements - * - * @param {Array<Object>} array of jQuery elements - * @param {number} userListLimit page size for result list - */ -function initApplicableUsersMultiselect($elements, userListLimit) { - var escapeHTML = function (text) { - return text.toString() - .split('&').join('&') - .split('<').join('<') - .split('>').join('>') - .split('"').join('"') - .split('\'').join('''); - }; - if (!$elements.length) { - return; - } - return $elements.select2({ - placeholder: t('files_external', 'Type to select user or group.'), - allowClear: true, - multiple: true, - toggleSelect: true, - dropdownCssClass: 'files-external-select2', - //minimumInputLength: 1, - ajax: { - url: OC.generateUrl('apps/files_external/applicable'), - dataType: 'json', - quietMillis: 100, - data: function (term, page) { // page is the one-based page number tracked by Select2 - return { - pattern: term, //search term - limit: userListLimit, // page size - offset: userListLimit*(page-1) // page number starts with 0 - }; - }, - results: function (data) { - if (data.status === 'success') { - - var results = []; - var userCount = 0; // users is an object - - // add groups - $.each(data.groups, function(gid, group) { - results.push({name:gid+'(group)', displayname:group, type:'group' }); - }); - // add users - $.each(data.users, function(id, user) { - userCount++; - results.push({name:id, displayname:user, type:'user' }); - }); - - - var more = (userCount >= userListLimit) || (data.groups.length >= userListLimit); - return {results: results, more: more}; - } else { - //FIXME add error handling - } - } - }, - initSelection: function(element, callback) { - var users = {}; - users['users'] = []; - var toSplit = element.val().split(","); - for (var i = 0; i < toSplit.length; i++) { - users['users'].push(toSplit[i]); - } - - $.ajax(OC.generateUrl('displaynames'), { - type: 'POST', - contentType: 'application/json', - data: JSON.stringify(users), - dataType: 'json' - }).done(function(data) { - var results = []; - if (data.status === 'success') { - $.each(data.users, function(user, displayname) { - if (displayname !== false) { - results.push({name:user, displayname:displayname, type:'user'}); - } - }); - callback(results); - } else { - //FIXME add error handling - } - }); - }, - id: function(element) { - return element.name; - }, - formatResult: function (element) { - var $result = $('<span><div class="avatardiv"></div><span>'+escapeHTML(element.displayname)+'</span></span>'); - var $div = $result.find('.avatardiv') - .attr('data-type', element.type) - .attr('data-name', element.name) - .attr('data-displayname', element.displayname); - if (element.type === 'group') { - var url = OC.imagePath('core','actions/group'); - $div.html('<img width="32" height="32" src="'+url+'">'); - } - return $result.get(0).outerHTML; - }, - formatSelection: function (element) { - if (element.type === 'group') { - return '<span title="'+escapeHTML(element.name)+'" class="group">'+escapeHTML(element.displayname+' '+t('files_external', '(Group)'))+'</span>'; - } else { - return '<span title="'+escapeHTML(element.name)+'" class="user">'+escapeHTML(element.displayname)+'</span>'; - } - }, - escapeMarkup: function (m) { return m; } // we escape the markup in formatResult and formatSelection - }).on('select2-loaded', function() { - $.each($('.avatardiv'), function(i, div) { - var $div = $(div); - if ($div.data('type') === 'user') { - $div.avatar($div.data('name'),32); - } - }); - }).on('change', function(event) { - highlightBorder($(event.target).closest('.applicableUsersContainer').find('.select2-choices'), !event.val.length); - }); -} - -/** - * @class OCA.Files_External.Settings.StorageConfig - * - * @classdesc External storage config - */ -var StorageConfig = function(id) { - this.id = id; - this.backendOptions = {}; -}; -// Keep this in sync with \OCA\Files_External\MountConfig::STATUS_* -StorageConfig.Status = { - IN_PROGRESS: -1, - SUCCESS: 0, - ERROR: 1, - INDETERMINATE: 2 -}; -StorageConfig.Visibility = { - NONE: 0, - PERSONAL: 1, - ADMIN: 2, - DEFAULT: 3 -}; -/** - * @memberof OCA.Files_External.Settings - */ -StorageConfig.prototype = { - _url: null, - - /** - * Storage id - * - * @type int - */ - id: null, - - /** - * Mount point - * - * @type string - */ - mountPoint: '', - - /** - * Backend - * - * @type string - */ - backend: null, - - /** - * Authentication mechanism - * - * @type string - */ - authMechanism: null, - - /** - * Backend-specific configuration - * - * @type Object.<string,object> - */ - backendOptions: null, - - /** - * Mount-specific options - * - * @type Object.<string,object> - */ - mountOptions: null, - - /** - * Creates or saves the storage. - * - * @param {Function} [options.success] success callback, receives result as argument - * @param {Function} [options.error] error callback - */ - save: function(options) { - var self = this; - var url = OC.generateUrl(this._url); - var method = 'POST'; - if (_.isNumber(this.id)) { - method = 'PUT'; - url = OC.generateUrl(this._url + '/{id}', {id: this.id}); - } - - $.ajax({ - type: method, - url: url, - contentType: 'application/json', - data: JSON.stringify(this.getData()), - success: function(result) { - self.id = result.id; - if (_.isFunction(options.success)) { - options.success(result); - } - }, - error: options.error - }); - }, - - /** - * Returns the data from this object - * - * @return {Array} JSON array of the data - */ - getData: function() { - var data = { - mountPoint: this.mountPoint, - backend: this.backend, - authMechanism: this.authMechanism, - backendOptions: this.backendOptions, - testOnly: true - }; - if (this.id) { - data.id = this.id; - } - if (this.mountOptions) { - data.mountOptions = this.mountOptions; - } - return data; - }, - - /** - * Recheck the storage - * - * @param {Function} [options.success] success callback, receives result as argument - * @param {Function} [options.error] error callback - */ - recheck: function(options) { - if (!_.isNumber(this.id)) { - if (_.isFunction(options.error)) { - options.error(); - } - return; - } - $.ajax({ - type: 'GET', - url: OC.generateUrl(this._url + '/{id}', {id: this.id}), - data: {'testOnly': true}, - success: options.success, - error: options.error - }); - }, - - /** - * Deletes the storage - * - * @param {Function} [options.success] success callback - * @param {Function} [options.error] error callback - */ - destroy: function(options) { - if (!_.isNumber(this.id)) { - // the storage hasn't even been created => success - if (_.isFunction(options.success)) { - options.success(); - } - return; - } - $.ajax({ - type: 'DELETE', - url: OC.generateUrl(this._url + '/{id}', {id: this.id}), - success: options.success, - error: options.error - }); - }, - - /** - * Validate this model - * - * @return {boolean} false if errors exist, true otherwise - */ - validate: function() { - if (this.mountPoint === '') { - return false; - } - if (!this.backend) { - return false; - } - if (this.errors) { - return false; - } - return true; - } -}; - -/** - * @class OCA.Files_External.Settings.GlobalStorageConfig - * @augments OCA.Files_External.Settings.StorageConfig - * - * @classdesc Global external storage config - */ -var GlobalStorageConfig = function(id) { - this.id = id; - this.applicableUsers = []; - this.applicableGroups = []; -}; -/** - * @memberOf OCA.Files_External.Settings - */ -GlobalStorageConfig.prototype = _.extend({}, StorageConfig.prototype, - /** @lends OCA.Files_External.Settings.GlobalStorageConfig.prototype */ { - _url: 'apps/files_external/globalstorages', - - /** - * Applicable users - * - * @type Array.<string> - */ - applicableUsers: null, - - /** - * Applicable groups - * - * @type Array.<string> - */ - applicableGroups: null, - - /** - * Storage priority - * - * @type int - */ - priority: null, - - /** - * Returns the data from this object - * - * @return {Array} JSON array of the data - */ - getData: function() { - var data = StorageConfig.prototype.getData.apply(this, arguments); - return _.extend(data, { - applicableUsers: this.applicableUsers, - applicableGroups: this.applicableGroups, - priority: this.priority, - }); - } -}); - -/** - * @class OCA.Files_External.Settings.UserStorageConfig - * @augments OCA.Files_External.Settings.StorageConfig - * - * @classdesc User external storage config - */ -var UserStorageConfig = function(id) { - this.id = id; -}; -UserStorageConfig.prototype = _.extend({}, StorageConfig.prototype, - /** @lends OCA.Files_External.Settings.UserStorageConfig.prototype */ { - _url: 'apps/files_external/userstorages' -}); - -/** - * @class OCA.Files_External.Settings.UserGlobalStorageConfig - * @augments OCA.Files_External.Settings.StorageConfig - * - * @classdesc User external storage config - */ -var UserGlobalStorageConfig = function (id) { - this.id = id; -}; -UserGlobalStorageConfig.prototype = _.extend({}, StorageConfig.prototype, - /** @lends OCA.Files_External.Settings.UserStorageConfig.prototype */ { - - _url: 'apps/files_external/userglobalstorages' -}); - -/** - * @class OCA.Files_External.Settings.MountOptionsDropdown - * - * @classdesc Dropdown for mount options - * - * @param {Object} $container container DOM object - */ -var MountOptionsDropdown = function() { -}; -/** - * @memberof OCA.Files_External.Settings - */ -MountOptionsDropdown.prototype = { - /** - * Dropdown element - * - * @var Object - */ - $el: null, - - /** - * Show dropdown - * - * @param {Object} $container container - * @param {Object} mountOptions mount options - * @param {Array} visibleOptions enabled mount options - */ - show: function($container, mountOptions, visibleOptions) { - if (MountOptionsDropdown._last) { - MountOptionsDropdown._last.hide(); - } - - var $el = $(OCA.Files_External.Templates.mountOptionsDropDown({ - mountOptionsEncodingLabel: t('files_external', 'Compatibility with Mac NFD encoding (slow)'), - mountOptionsEncryptLabel: t('files_external', 'Enable encryption'), - mountOptionsPreviewsLabel: t('files_external', 'Enable previews'), - mountOptionsSharingLabel: t('files_external', 'Enable sharing'), - mountOptionsFilesystemCheckLabel: t('files_external', 'Check for changes'), - mountOptionsFilesystemCheckOnce: t('files_external', 'Never'), - mountOptionsFilesystemCheckDA: t('files_external', 'Once every direct access'), - mountOptionsReadOnlyLabel: t('files_external', 'Read only'), - deleteLabel: t('files_external', 'Disconnect') - })); - this.$el = $el; - - var storage = $container[0].parentNode.className; - - this.setOptions(mountOptions, visibleOptions, storage); - - this.$el.appendTo($container); - MountOptionsDropdown._last = this; - - this.$el.trigger('show'); - }, - - hide: function() { - if (this.$el) { - this.$el.trigger('hide'); - this.$el.remove(); - this.$el = null; - MountOptionsDropdown._last = null; - } - }, - - /** - * Returns the mount options from the dropdown controls - * - * @return {Object} options mount options - */ - getOptions: function() { - var options = {}; - - this.$el.find('input, select').each(function() { - var $this = $(this); - var key = $this.attr('name'); - var value = null; - if ($this.attr('type') === 'checkbox') { - value = $this.prop('checked'); - } else { - value = $this.val(); - } - if ($this.attr('data-type') === 'int') { - value = parseInt(value, 10); - } - options[key] = value; - }); - return options; - }, - - /** - * Sets the mount options to the dropdown controls - * - * @param {Object} options mount options - * @param {Array} visibleOptions enabled mount options - */ - setOptions: function(options, visibleOptions, storage) { - if (storage === 'owncloud') { - var ind = visibleOptions.indexOf('encrypt'); - if (ind > 0) { - visibleOptions.splice(ind, 1); - } - } - var $el = this.$el; - _.each(options, function(value, key) { - var $optionEl = $el.find('input, select').filterAttr('name', key); - if ($optionEl.attr('type') === 'checkbox') { - if (_.isString(value)) { - value = (value === 'true'); - } - $optionEl.prop('checked', !!value); - } else { - $optionEl.val(value); - } - }); - $el.find('.optionRow').each(function(i, row){ - var $row = $(row); - var optionId = $row.find('input, select').attr('name'); - if (visibleOptions.indexOf(optionId) === -1 && !$row.hasClass('persistent')) { - $row.hide(); - } else { - $row.show(); - } - }); - } -}; - -/** - * @class OCA.Files_External.Settings.MountConfigListView - * - * @classdesc Mount configuration list view - * - * @param {Object} $el DOM object containing the list - * @param {Object} [options] - * @param {number} [options.userListLimit] page size in applicable users dropdown - */ -var MountConfigListView = function($el, options) { - this.initialize($el, options); -}; - -MountConfigListView.ParameterFlags = { - OPTIONAL: 1, - USER_PROVIDED: 2 -}; - -MountConfigListView.ParameterTypes = { - TEXT: 0, - BOOLEAN: 1, - PASSWORD: 2, - HIDDEN: 3 -}; - -/** - * @memberOf OCA.Files_External.Settings - */ -MountConfigListView.prototype = _.extend({ - - /** - * jQuery element containing the config list - * - * @type Object - */ - $el: null, - - /** - * Storage config class - * - * @type Class - */ - _storageConfigClass: null, - - /** - * Flag whether the list is about user storage configs (true) - * or global storage configs (false) - * - * @type bool - */ - _isPersonal: false, - - /** - * Page size in applicable users dropdown - * - * @type int - */ - _userListLimit: 30, - - /** - * List of supported backends - * - * @type Object.<string,Object> - */ - _allBackends: null, - - /** - * List of all supported authentication mechanisms - * - * @type Object.<string,Object> - */ - _allAuthMechanisms: null, - - _encryptionEnabled: false, - - /** - * @param {Object} $el DOM object containing the list - * @param {Object} [options] - * @param {number} [options.userListLimit] page size in applicable users dropdown - */ - initialize: function($el, options) { - var self = this; - this.$el = $el; - this._isPersonal = ($el.data('admin') !== true); - if (this._isPersonal) { - this._storageConfigClass = OCA.Files_External.Settings.UserStorageConfig; - } else { - this._storageConfigClass = OCA.Files_External.Settings.GlobalStorageConfig; - } - - if (options && !_.isUndefined(options.userListLimit)) { - this._userListLimit = options.userListLimit; - } - - this._encryptionEnabled = options.encryptionEnabled; - this._canCreateLocal = options.canCreateLocal; - - // read the backend config that was carefully crammed - // into the data-configurations attribute of the select - this._allBackends = this.$el.find('.selectBackend').data('configurations'); - this._allAuthMechanisms = this.$el.find('#addMountPoint .authentication').data('mechanisms'); - - this._initEvents(); - }, - - /** - * Custom JS event handlers - * Trigger callback for all existing configurations - */ - whenSelectBackend: function(callback) { - this.$el.find('tbody tr:not(#addMountPoint):not(.externalStorageLoading)').each(function(i, tr) { - var backend = $(tr).find('.backend').data('identifier'); - callback($(tr), backend); - }); - this.on('selectBackend', callback); - }, - whenSelectAuthMechanism: function(callback) { - var self = this; - this.$el.find('tbody tr:not(#addMountPoint):not(.externalStorageLoading)').each(function(i, tr) { - var authMechanism = $(tr).find('.selectAuthMechanism').val(); - callback($(tr), authMechanism, self._allAuthMechanisms[authMechanism]['scheme']); - }); - this.on('selectAuthMechanism', callback); - }, - - /** - * Initialize DOM event handlers - */ - _initEvents: function() { - var self = this; - - var onChangeHandler = _.bind(this._onChange, this); - //this.$el.on('input', 'td input', onChangeHandler); - this.$el.on('keyup', 'td input', onChangeHandler); - this.$el.on('paste', 'td input', onChangeHandler); - this.$el.on('change', 'td input:checkbox', onChangeHandler); - this.$el.on('change', '.applicable', onChangeHandler); - - this.$el.on('click', '.status>span', function() { - self.recheckStorageConfig($(this).closest('tr')); - }); - - this.$el.on('click', 'td.mountOptionsToggle .icon-delete', function() { - self.deleteStorageConfig($(this).closest('tr')); - }); - - this.$el.on('click', 'td.save>.icon-checkmark', function () { - self.saveStorageConfig($(this).closest('tr')); - }); - - this.$el.on('click', 'td.mountOptionsToggle>.icon-more', function() { - $(this).attr('aria-expanded', 'true'); - self._showMountOptionsDropdown($(this).closest('tr')); - }); - - this.$el.on('change', '.selectBackend', _.bind(this._onSelectBackend, this)); - this.$el.on('change', '.selectAuthMechanism', _.bind(this._onSelectAuthMechanism, this)); - - this.$el.on('change', '.applicableToAllUsers', _.bind(this._onChangeApplicableToAllUsers, this)); - }, - - _onChange: function(event) { - var self = this; - var $target = $(event.target); - if ($target.closest('.dropdown').length) { - // ignore dropdown events - return; - } - highlightInput($target); - var $tr = $target.closest('tr'); - this.updateStatus($tr, null); - }, - - _onSelectBackend: function(event) { - var $target = $(event.target); - var $tr = $target.closest('tr'); - - var storageConfig = new this._storageConfigClass(); - storageConfig.mountPoint = $tr.find('.mountPoint input').val(); - storageConfig.backend = $target.val(); - $tr.find('.mountPoint input').val(''); - - var onCompletion = jQuery.Deferred(); - $tr = this.newStorage(storageConfig, onCompletion); - $tr.find('.applicableToAllUsers').prop('checked', false).trigger('change'); - onCompletion.resolve(); - - $tr.find('td.configuration').children().not('[type=hidden]').first().focus(); - this.saveStorageConfig($tr); - }, - - _onSelectAuthMechanism: function(event) { - var $target = $(event.target); - var $tr = $target.closest('tr'); - var authMechanism = $target.val(); - - var onCompletion = jQuery.Deferred(); - this.configureAuthMechanism($tr, authMechanism, onCompletion); - onCompletion.resolve(); - - this.saveStorageConfig($tr); - }, - - _onChangeApplicableToAllUsers: function(event) { - var $target = $(event.target); - var $tr = $target.closest('tr'); - var checked = $target.is(':checked'); - - $tr.find('.applicableUsersContainer').toggleClass('hidden', checked); - if (!checked) { - $tr.find('.applicableUsers').select2('val', '', true); - } - - this.saveStorageConfig($tr); - }, - - /** - * Configure the storage config with a new authentication mechanism - * - * @param {jQuery} $tr config row - * @param {string} authMechanism - * @param {jQuery.Deferred} onCompletion - */ - configureAuthMechanism: function($tr, authMechanism, onCompletion) { - var authMechanismConfiguration = this._allAuthMechanisms[authMechanism]; - var $td = $tr.find('td.configuration'); - $td.find('.auth-param').remove(); - - $.each(authMechanismConfiguration['configuration'], _.partial( - this.writeParameterInput, $td, _, _, ['auth-param'] - ).bind(this)); - - this.trigger('selectAuthMechanism', - $tr, authMechanism, authMechanismConfiguration['scheme'], onCompletion - ); - }, - - /** - * Create a config row for a new storage - * - * @param {StorageConfig} storageConfig storage config to pull values from - * @param {jQuery.Deferred} onCompletion - * @param {boolean} deferAppend - * @return {jQuery} created row - */ - newStorage: function(storageConfig, onCompletion, deferAppend) { - var mountPoint = storageConfig.mountPoint; - var backend = this._allBackends[storageConfig.backend]; - - if (!backend) { - backend = { - name: 'Unknown: ' + storageConfig.backend, - invalid: true - }; - } - - // FIXME: Replace with a proper Handlebar template - var $template = this.$el.find('tr#addMountPoint'); - var $tr = $template.clone(); - if (!deferAppend) { - $tr.insertBefore($template); - } - - $tr.data('storageConfig', storageConfig); - $tr.show(); - $tr.find('td.mountOptionsToggle, td.save, td.remove').removeClass('hidden'); - $tr.find('td').last().removeAttr('style'); - $tr.removeAttr('id'); - $tr.find('select#selectBackend'); - if (!deferAppend) { - initApplicableUsersMultiselect($tr.find('.applicableUsers'), this._userListLimit); - } - - if (storageConfig.id) { - $tr.data('id', storageConfig.id); - } - - $tr.find('.backend').text(backend.name); - if (mountPoint === '') { - mountPoint = this._suggestMountPoint(backend.name); - } - $tr.find('.mountPoint input').val(mountPoint); - $tr.addClass(backend.identifier); - $tr.find('.backend').data('identifier', backend.identifier); - - if (backend.invalid || (backend.identifier === 'local' && !this._canCreateLocal)) { - $tr.find('[name=mountPoint]').prop('disabled', true); - $tr.find('.applicable,.mountOptionsToggle').empty(); - $tr.find('.save').empty(); - if (backend.invalid) { - this.updateStatus($tr, false, 'Unknown backend: ' + backend.name); - } - return $tr; - } - - var selectAuthMechanism = $('<select class="selectAuthMechanism"></select>'); - var neededVisibility = (this._isPersonal) ? StorageConfig.Visibility.PERSONAL : StorageConfig.Visibility.ADMIN; - $.each(this._allAuthMechanisms, function(authIdentifier, authMechanism) { - if (backend.authSchemes[authMechanism.scheme] && (authMechanism.visibility & neededVisibility)) { - selectAuthMechanism.append( - $('<option value="'+authMechanism.identifier+'" data-scheme="'+authMechanism.scheme+'">'+authMechanism.name+'</option>') - ); - } - }); - if (storageConfig.authMechanism) { - selectAuthMechanism.val(storageConfig.authMechanism); - } else { - storageConfig.authMechanism = selectAuthMechanism.val(); - } - $tr.find('td.authentication').append(selectAuthMechanism); - - var $td = $tr.find('td.configuration'); - $.each(backend.configuration, _.partial(this.writeParameterInput, $td).bind(this)); - - this.trigger('selectBackend', $tr, backend.identifier, onCompletion); - this.configureAuthMechanism($tr, storageConfig.authMechanism, onCompletion); - - if (storageConfig.backendOptions) { - $td.find('input, select').each(function() { - var input = $(this); - var val = storageConfig.backendOptions[input.data('parameter')]; - if (val !== undefined) { - if(input.is('input:checkbox')) { - input.prop('checked', val); - } - input.val(storageConfig.backendOptions[input.data('parameter')]); - highlightInput(input); - } - }); - } - - var applicable = []; - if (storageConfig.applicableUsers) { - applicable = applicable.concat(storageConfig.applicableUsers); - } - if (storageConfig.applicableGroups) { - applicable = applicable.concat( - _.map(storageConfig.applicableGroups, function(group) { - return group+'(group)'; - }) - ); - } - if (applicable.length) { - $tr.find('.applicableUsers').val(applicable).trigger('change') - $tr.find('.applicableUsersContainer').removeClass('hidden'); - } else { - // applicable to all - $tr.find('.applicableUsersContainer').addClass('hidden'); - } - $tr.find('.applicableToAllUsers').prop('checked', !applicable.length); - - var priorityEl = $('<input type="hidden" class="priority" value="' + backend.priority + '" />'); - $tr.append(priorityEl); - - if (storageConfig.mountOptions) { - $tr.find('input.mountOptions').val(JSON.stringify(storageConfig.mountOptions)); - } else { - // FIXME default backend mount options - $tr.find('input.mountOptions').val(JSON.stringify({ - 'encrypt': true, - 'previews': true, - 'enable_sharing': false, - 'filesystem_check_changes': 1, - 'encoding_compatibility': false, - 'readonly': false, - })); - } - - return $tr; - }, - - /** - * Load storages into config rows - */ - loadStorages: function() { - var self = this; - - var onLoaded1 = $.Deferred(); - var onLoaded2 = $.Deferred(); - - this.$el.find('.externalStorageLoading').removeClass('hidden'); - $.when(onLoaded1, onLoaded2).always(() => { - self.$el.find('.externalStorageLoading').addClass('hidden'); - }) - - if (this._isPersonal) { - // load userglobal storages - $.ajax({ - type: 'GET', - url: OC.generateUrl('apps/files_external/userglobalstorages'), - data: {'testOnly' : true}, - contentType: 'application/json', - success: function(result) { - var onCompletion = jQuery.Deferred(); - var $rows = $(); - Object.values(result).forEach(function(storageParams) { - var storageConfig; - var isUserGlobal = storageParams.type === 'system' && self._isPersonal; - storageParams.mountPoint = storageParams.mountPoint.substr(1); // trim leading slash - if (isUserGlobal) { - storageConfig = new UserGlobalStorageConfig(); - } else { - storageConfig = new self._storageConfigClass(); - } - _.extend(storageConfig, storageParams); - var $tr = self.newStorage(storageConfig, onCompletion,true); - - // userglobal storages must be at the top of the list - $tr.detach(); - self.$el.prepend($tr); - - var $authentication = $tr.find('.authentication'); - $authentication.text($authentication.find('select option:selected').text()); - - // disable any other inputs - $tr.find('.mountOptionsToggle, .remove').empty(); - $tr.find('input:not(.user_provided), select:not(.user_provided)').attr('disabled', 'disabled'); - - if (isUserGlobal) { - $tr.find('.configuration').find(':not(.user_provided)').remove(); - } else { - // userglobal storages do not expose configuration data - $tr.find('.configuration').text(t('files_external', 'Admin defined')); - } - $rows = $rows.add($tr); - }); - initApplicableUsersMultiselect(self.$el.find('.applicableUsers'), this._userListLimit); - self.$el.find('tr#addMountPoint').before($rows); - var mainForm = $('#files_external'); - if (result.length === 0 && mainForm.attr('data-can-create') === 'false') { - mainForm.hide(); - $('a[href="#external-storage"]').parent().hide(); - $('.emptycontent').show(); - } - onCompletion.resolve(); - onLoaded1.resolve(); - } - }); - } else { - onLoaded1.resolve(); - } - - var url = this._storageConfigClass.prototype._url; - - $.ajax({ - type: 'GET', - url: OC.generateUrl(url), - contentType: 'application/json', - success: function(result) { - result = Object.values(result); - var onCompletion = jQuery.Deferred(); - var $rows = $(); - result.forEach(function(storageParams) { - storageParams.mountPoint = (storageParams.mountPoint === '/')? '/' : storageParams.mountPoint.substr(1); // trim leading slash - var storageConfig = new self._storageConfigClass(); - _.extend(storageConfig, storageParams); - var $tr = self.newStorage(storageConfig, onCompletion, true); - - // don't recheck config automatically when there are a large number of storages - if (result.length < 20) { - self.recheckStorageConfig($tr); - } else { - self.updateStatus($tr, StorageConfig.Status.INDETERMINATE, t('files_external', 'Automatic status checking is disabled due to the large number of configured storages, click to check status')); - } - $rows = $rows.add($tr); - }); - initApplicableUsersMultiselect($rows.find('.applicableUsers'), this._userListLimit); - self.$el.find('tr#addMountPoint').before($rows); - onCompletion.resolve(); - onLoaded2.resolve(); - } - }); - }, - - /** - * @param {jQuery} $td - * @param {string} parameter - * @param {string} placeholder - * @param {Array} classes - * @return {jQuery} newly created input - */ - writeParameterInput: function($td, parameter, placeholder, classes) { - var hasFlag = function(flag) { - return (placeholder.flags & flag) === flag; - }; - classes = $.isArray(classes) ? classes : []; - classes.push('added'); - if (hasFlag(MountConfigListView.ParameterFlags.OPTIONAL)) { - classes.push('optional'); - } - - if (hasFlag(MountConfigListView.ParameterFlags.USER_PROVIDED)) { - if (this._isPersonal) { - classes.push('user_provided'); - } else { - return; - } - } - - var newElement; - - var trimmedPlaceholder = placeholder.value; - if (placeholder.type === MountConfigListView.ParameterTypes.PASSWORD) { - newElement = $('<input type="password" class="'+classes.join(' ')+'" data-parameter="'+parameter+'" placeholder="'+ trimmedPlaceholder+'" />'); - } else if (placeholder.type === MountConfigListView.ParameterTypes.BOOLEAN) { - var checkboxId = _.uniqueId('checkbox_'); - newElement = $('<div><label><input type="checkbox" id="'+checkboxId+'" class="'+classes.join(' ')+'" data-parameter="'+parameter+'" />'+ trimmedPlaceholder+'</label></div>'); - } else if (placeholder.type === MountConfigListView.ParameterTypes.HIDDEN) { - newElement = $('<input type="hidden" class="'+classes.join(' ')+'" data-parameter="'+parameter+'" />'); - } else { - newElement = $('<input type="text" class="'+classes.join(' ')+'" data-parameter="'+parameter+'" placeholder="'+ trimmedPlaceholder+'" />'); - } - - if (placeholder.defaultValue) { - if (placeholder.type === MountConfigListView.ParameterTypes.BOOLEAN) { - newElement.find('input').prop('checked', placeholder.defaultValue); - } else { - newElement.val(placeholder.defaultValue); - } - } - - if (placeholder.tooltip) { - newElement.attr('title', placeholder.tooltip); - } - - highlightInput(newElement); - $td.append(newElement); - return newElement; - }, - - /** - * Gets the storage model from the given row - * - * @param $tr row element - * @return {OCA.Files_External.StorageConfig} storage model instance - */ - getStorageConfig: function($tr) { - var storageId = $tr.data('id'); - if (!storageId) { - // new entry - storageId = null; - } - - var storage = $tr.data('storageConfig'); - if (!storage) { - storage = new this._storageConfigClass(storageId); - } - storage.errors = null; - storage.mountPoint = $tr.find('.mountPoint input').val(); - storage.backend = $tr.find('.backend').data('identifier'); - storage.authMechanism = $tr.find('.selectAuthMechanism').val(); - - var classOptions = {}; - var configuration = $tr.find('.configuration input'); - var missingOptions = []; - $.each(configuration, function(index, input) { - var $input = $(input); - var parameter = $input.data('parameter'); - if ($input.attr('type') === 'button') { - return; - } - if (!isInputValid($input) && !$input.hasClass('optional')) { - missingOptions.push(parameter); - return; - } - if ($(input).is(':checkbox')) { - if ($(input).is(':checked')) { - classOptions[parameter] = true; - } else { - classOptions[parameter] = false; - } - } else { - classOptions[parameter] = $(input).val(); - } - }); - - storage.backendOptions = classOptions; - if (missingOptions.length) { - storage.errors = { - backendOptions: missingOptions - }; - } - - // gather selected users and groups - if (!this._isPersonal) { - var multiselect = getSelectedApplicable($tr); - var users = multiselect.users || []; - var groups = multiselect.groups || []; - var isApplicableToAllUsers = $tr.find('.applicableToAllUsers').is(':checked'); - - if (isApplicableToAllUsers) { - storage.applicableUsers = []; - storage.applicableGroups = []; - } else { - storage.applicableUsers = users; - storage.applicableGroups = groups; - - if (!storage.applicableUsers.length && !storage.applicableGroups.length) { - if (!storage.errors) { - storage.errors = {}; - } - storage.errors['requiredApplicable'] = true; - } - } - - storage.priority = parseInt($tr.find('input.priority').val() || '100', 10); - } - - var mountOptions = $tr.find('input.mountOptions').val(); - if (mountOptions) { - storage.mountOptions = JSON.parse(mountOptions); - } - - return storage; - }, - - /** - * Deletes the storage from the given tr - * - * @param $tr storage row - * @param Function callback callback to call after save - */ - deleteStorageConfig: function($tr) { - var self = this; - var configId = $tr.data('id'); - if (!_.isNumber(configId)) { - // deleting unsaved storage - $tr.remove(); - return; - } - var storage = new this._storageConfigClass(configId); - - OC.dialogs.confirm(t('files_external', 'Are you sure you want to disconnect this external storage? It will make the storage unavailable in Nextcloud and will lead to a deletion of these files and folders on any sync client that is currently connected but will not delete any files and folders on the external storage itself.', { - storage: this.mountPoint - }), t('files_external', 'Delete storage?'), function(confirm) { - if (confirm) { - self.updateStatus($tr, StorageConfig.Status.IN_PROGRESS); - - storage.destroy({ - success: function () { - $tr.remove(); - }, - error: function () { - self.updateStatus($tr, StorageConfig.Status.ERROR); - } - }); - } - }); - }, - - /** - * Saves the storage from the given tr - * - * @param $tr storage row - * @param Function callback callback to call after save - * @param concurrentTimer only update if the timer matches this - */ - saveStorageConfig:function($tr, callback, concurrentTimer) { - var self = this; - var storage = this.getStorageConfig($tr); - if (!storage || !storage.validate()) { - return false; - } - - this.updateStatus($tr, StorageConfig.Status.IN_PROGRESS); - storage.save({ - success: function(result) { - if (concurrentTimer === undefined - || $tr.data('save-timer') === concurrentTimer - ) { - self.updateStatus($tr, result.status); - $tr.data('id', result.id); - - if (_.isFunction(callback)) { - callback(storage); - } - } - }, - error: function() { - if (concurrentTimer === undefined - || $tr.data('save-timer') === concurrentTimer - ) { - self.updateStatus($tr, StorageConfig.Status.ERROR); - } - } - }); - }, - - /** - * Recheck storage availability - * - * @param {jQuery} $tr storage row - * @return {boolean} success - */ - recheckStorageConfig: function($tr) { - var self = this; - var storage = this.getStorageConfig($tr); - if (!storage.validate()) { - return false; - } - - this.updateStatus($tr, StorageConfig.Status.IN_PROGRESS); - storage.recheck({ - success: function(result) { - self.updateStatus($tr, result.status, result.statusMessage); - }, - error: function() { - self.updateStatus($tr, StorageConfig.Status.ERROR); - } - }); - }, - - /** - * Update status display - * - * @param {jQuery} $tr - * @param {number} status - * @param {string} message - */ - updateStatus: function($tr, status, message) { - var $statusSpan = $tr.find('.status span'); - switch (status) { - case null: - // remove status - break; - case StorageConfig.Status.IN_PROGRESS: - $statusSpan.attr('class', 'icon-loading-small'); - break; - case StorageConfig.Status.SUCCESS: - $statusSpan.attr('class', 'success icon-checkmark-white'); - break; - case StorageConfig.Status.INDETERMINATE: - $statusSpan.attr('class', 'indeterminate icon-info-white'); - break; - default: - $statusSpan.attr('class', 'error icon-error-white'); - } - if (typeof message === 'string') { - $statusSpan.attr('title', message); - $statusSpan.tooltip(); - } else { - $statusSpan.tooltip('dispose'); - } - }, - - /** - * Suggest mount point name that doesn't conflict with the existing names in the list - * - * @param {string} defaultMountPoint default name - */ - _suggestMountPoint: function(defaultMountPoint) { - var $el = this.$el; - var pos = defaultMountPoint.indexOf('/'); - if (pos !== -1) { - defaultMountPoint = defaultMountPoint.substring(0, pos); - } - defaultMountPoint = defaultMountPoint.replace(/\s+/g, ''); - var i = 1; - var append = ''; - var match = true; - while (match && i < 20) { - match = false; - $el.find('tbody td.mountPoint input').each(function(index, mountPoint) { - if ($(mountPoint).val() === defaultMountPoint+append) { - match = true; - return false; - } - }); - if (match) { - append = i; - i++; - } else { - break; - } - } - return defaultMountPoint + append; - }, - - /** - * Toggles the mount options dropdown - * - * @param {Object} $tr configuration row - */ - _showMountOptionsDropdown: function($tr) { - var self = this; - var storage = this.getStorageConfig($tr); - var $toggle = $tr.find('.mountOptionsToggle'); - var dropDown = new MountOptionsDropdown(); - var visibleOptions = [ - 'previews', - 'filesystem_check_changes', - 'enable_sharing', - 'encoding_compatibility', - 'readonly', - 'delete' - ]; - if (this._encryptionEnabled) { - visibleOptions.push('encrypt'); - } - dropDown.show($toggle, storage.mountOptions || [], visibleOptions); - $('body').on('mouseup.mountOptionsDropdown', function(event) { - var $target = $(event.target); - if ($target.closest('.popovermenu').length) { - return; - } - dropDown.hide(); - }); - - dropDown.$el.on('hide', function() { - var mountOptions = dropDown.getOptions(); - $('body').off('mouseup.mountOptionsDropdown'); - $tr.find('input.mountOptions').val(JSON.stringify(mountOptions)); - $tr.find('td.mountOptionsToggle>.icon-more').attr('aria-expanded', 'false'); - self.saveStorageConfig($tr); - }); - } -}, OC.Backbone.Events); - -window.addEventListener('DOMContentLoaded', function() { - var enabled = $('#files_external').attr('data-encryption-enabled'); - var canCreateLocal = $('#files_external').attr('data-can-create-local'); - var encryptionEnabled = (enabled ==='true')? true: false; - var mountConfigListView = new MountConfigListView($('#externalStorage'), { - encryptionEnabled: encryptionEnabled, - canCreateLocal: (canCreateLocal === 'true') ? true: false, - }); - mountConfigListView.loadStorages(); - - // TODO: move this into its own View class - var $allowUserMounting = $('#allowUserMounting'); - $allowUserMounting.bind('change', function() { - OC.msg.startSaving('#userMountingMsg'); - if (this.checked) { - OCP.AppConfig.setValue('files_external', 'allow_user_mounting', 'yes'); - $('input[name="allowUserMountingBackends\\[\\]"]').prop('checked', true); - $('#userMountingBackends').removeClass('hidden'); - $('input[name="allowUserMountingBackends\\[\\]"]').eq(0).trigger('change'); - } else { - OCP.AppConfig.setValue('files_external', 'allow_user_mounting', 'no'); - $('#userMountingBackends').addClass('hidden'); - } - OC.msg.finishedSaving('#userMountingMsg', {status: 'success', data: {message: t('files_external', 'Saved')}}); - }); - - $('input[name="allowUserMountingBackends\\[\\]"]').bind('change', function() { - OC.msg.startSaving('#userMountingMsg'); - - var userMountingBackends = $('input[name="allowUserMountingBackends\\[\\]"]:checked').map(function(){ - return $(this).val(); - }).get(); - var deprecatedBackends = $('input[name="allowUserMountingBackends\\[\\]"][data-deprecate-to]').map(function(){ - if ($.inArray($(this).data('deprecate-to'), userMountingBackends) !== -1) { - return $(this).val(); - } - return null; - }).get(); - userMountingBackends = userMountingBackends.concat(deprecatedBackends); - - OCP.AppConfig.setValue('files_external', 'user_mounting_backends', userMountingBackends.join()); - OC.msg.finishedSaving('#userMountingMsg', {status: 'success', data: {message: t('files_external', 'Saved')}}); - - // disable allowUserMounting - if(userMountingBackends.length === 0) { - $allowUserMounting.prop('checked', false); - $allowUserMounting.trigger('change'); - - } - }); - - $('#global_credentials').on('submit', function() { - var $form = $(this); - var uid = $form.find('[name=uid]').val(); - var user = $form.find('[name=username]').val(); - var password = $form.find('[name=password]').val(); - var $submit = $form.find('[type=submit]'); - $submit.val(t('files_external', 'Saving …')); - $.ajax({ - type: 'POST', - contentType: 'application/json', - data: JSON.stringify({ - uid: uid, - user: user, - password: password - }), - url: OC.generateUrl('apps/files_external/globalcredentials'), - dataType: 'json', - success: function() { - $submit.val(t('files_external', 'Saved')); - setTimeout(function(){ - $submit.val(t('files_external', 'Save')); - }, 2500); - } - }); - return false; - }); - - // global instance - OCA.Files_External.Settings.mountConfig = mountConfigListView; - - /** - * Legacy - * - * @namespace - * @deprecated use OCA.Files_External.Settings.mountConfig instead - */ - OC.MountConfig = { - saveStorage: _.bind(mountConfigListView.saveStorageConfig, mountConfigListView) - }; -}); - -// export - -OCA.Files_External = OCA.Files_External || {}; -/** - * @namespace - */ -OCA.Files_External.Settings = OCA.Files_External.Settings || {}; - -OCA.Files_External.Settings.GlobalStorageConfig = GlobalStorageConfig; -OCA.Files_External.Settings.UserStorageConfig = UserStorageConfig; -OCA.Files_External.Settings.MountConfigListView = MountConfigListView; - -})(); |