aboutsummaryrefslogtreecommitdiffstats
path: root/apps/settings/js/federationsettingsview.js
diff options
context:
space:
mode:
Diffstat (limited to 'apps/settings/js/federationsettingsview.js')
-rw-r--r--apps/settings/js/federationsettingsview.js278
1 files changed, 278 insertions, 0 deletions
diff --git a/apps/settings/js/federationsettingsview.js b/apps/settings/js/federationsettingsview.js
new file mode 100644
index 00000000000..a4587e1bedb
--- /dev/null
+++ b/apps/settings/js/federationsettingsview.js
@@ -0,0 +1,278 @@
+/* global OC, result, _ */
+
+/**
+ * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-or-later
+ */
+
+(function(_, $, OC) {
+ 'use strict';
+
+ /**
+ * Construct a new FederationScopeMenu instance
+ * @constructs FederationScopeMenu
+ * @memberof OC.Settings
+ * @param {object} options
+ * @param {boolean} [options.showFederatedScope=false] whether show the
+ * "v2-federated" scope or not
+ * @param {boolean} [options.showPublishedScope=false] whether show the
+ * "v2-published" scope or not
+ */
+ var FederationSettingsView = OC.Backbone.View.extend({
+ _inputFields: undefined,
+
+ /** @var Backbone.Model */
+ _config: undefined,
+
+ initialize: function(options) {
+ options = options || {};
+
+ if (options.config) {
+ this._config = options.config;
+ } else {
+ this._config = new OC.Settings.UserSettings();
+ }
+ this.showFederatedScope = !!options.showFederatedScope;
+ this.showPublishedScope = !!options.showPublishedScope;
+
+ this._inputFields = [
+ 'displayname',
+ 'phone',
+ 'email',
+ 'website',
+ 'twitter',
+ 'address',
+ 'avatar'
+ ];
+
+ var self = this;
+ _.each(this._inputFields, function(field) {
+ var scopeOnly = field === 'avatar';
+
+ // Initialize config model
+ if (!scopeOnly) {
+ self._config.set(field, $('#' + field).val());
+ }
+ self._config.set(field + 'Scope', $('#' + field + 'scope').val());
+
+ // Set inputs whenever model values change
+ if (!scopeOnly) {
+ self.listenTo(self._config, 'change:' + field, function() {
+ self.$('#' + field).val(self._config.get(field));
+ });
+ }
+ self.listenTo(self._config, 'change:' + field + 'Scope', function() {
+ self._setFieldScopeIcon(field, self._config.get(field + 'Scope'));
+ });
+ });
+
+ this._registerEvents();
+ },
+
+ render: function() {
+ var self = this;
+ var fieldsWithV2Private = [
+ 'avatar',
+ 'phone',
+ 'twitter',
+ 'website',
+ 'address',
+ ];
+
+ _.each(this._inputFields, function(field) {
+ var $icon = self.$('#' + field + 'form .headerbar-label > .federation-menu');
+ var excludedScopes = []
+
+ if (fieldsWithV2Private.indexOf(field) === -1) {
+ excludedScopes.push('v2-private');
+ }
+
+ if (!self.showFederatedScope) {
+ excludedScopes.push('v2-federated');
+ }
+
+ if (!self.showPublishedScope) {
+ excludedScopes.push('v2-published');
+ }
+
+ var scopeMenu = new OC.Settings.FederationScopeMenu({
+ field: field,
+ excludedScopes: excludedScopes,
+ });
+
+ self.listenTo(scopeMenu, 'select:scope', function(scope) {
+ self._onScopeChanged(field, scope);
+ });
+ $icon.append(scopeMenu.$el);
+ $icon.attr('aria-expanded', 'false');
+ $icon.on('click', _.bind(scopeMenu.show, scopeMenu));
+ $icon.on('keydown', function(e) {
+ if (e.keyCode === 32) {
+ // Open the menu when the user presses the space bar
+ e.preventDefault();
+ scopeMenu.show(e);
+ } else if (e.keyCode === 27) {
+ // Close the menu again if opened
+ OC.hideMenus();
+ }
+ }.bind(this));
+
+ // Restore initial state
+ self._setFieldScopeIcon(field, self._config.get(field + 'Scope'));
+ });
+ },
+
+ _registerEvents: function() {
+ var self = this;
+ _.each(this._inputFields, function(field) {
+ if (
+ field === 'avatar' ||
+ field === 'email' ||
+ field === 'displayname' ||
+ field === 'twitter' ||
+ field === 'address' ||
+ field === 'website' ||
+ field === 'phone'
+ ) {
+ return;
+ }
+ self.$('#' + field).keyUpDelayedOrEnter(_.bind(self._onInputChanged, self), true);
+ });
+ },
+
+ _onInputChanged: function(e) {
+ var self = this;
+
+ var $dialog = $('.oc-dialog:visible');
+ if (OC.PasswordConfirmation.requiresPasswordConfirmation()) {
+ if($dialog.length === 0) {
+ OC.PasswordConfirmation.requirePasswordConfirmation(_.bind(this._onInputChanged, this, e));
+ }
+ return;
+ }
+ var $target = $(e.target);
+ var value = $target.val();
+ var field = $target.attr('id');
+ this._config.set(field, value);
+
+ var savingData = this._config.save({
+ error: function(jqXHR) {
+ OC.msg.finishedSaving('#personal-settings-container .msg', jqXHR);
+ }
+ });
+
+ $.when(savingData).done(function(data) {
+ if (data.status === "success") {
+ self._showInputChangeSuccess(field);
+ } else {
+ self._showInputChangeFail(field);
+ }
+ });
+ },
+
+ _onScopeChanged: function(field, scope) {
+ var $dialog = $('.oc-dialog:visible');
+ if (OC.PasswordConfirmation.requiresPasswordConfirmation()) {
+ if($dialog.length === 0) {
+ OC.PasswordConfirmation.requirePasswordConfirmation(_.bind(this._onScopeChanged, this, field, scope));
+ }
+ return;
+ }
+
+ this._config.set(field + 'Scope', scope);
+
+ $('#' + field + 'scope').val(scope);
+
+ // TODO: user loading/success feedback
+ this._config.save();
+ this._setFieldScopeIcon(field, scope);
+ this._updateVerifyButton(field, scope);
+ },
+
+ _updateVerifyButton: function(field, scope) {
+ // show verification button if the value is set and the scope is 'public'
+ if (field === 'twitter' || field === 'website'|| field === 'email') {
+ var verify = this.$('#' + field + 'form > .verify');
+ var scope = this.$('#' + field + 'scope').val();
+ var value = this.$('#' + field).val();
+
+ if (scope === 'public' && value !== '') {
+ verify.removeClass('hidden');
+ return true;
+ } else {
+ verify.addClass('hidden');
+ }
+ }
+
+ return false;
+ },
+
+ _showInputChangeSuccess: function(field) {
+ var $icon = this.$('#' + field + 'form > .icon-checkmark');
+ $icon.fadeIn(200);
+ setTimeout(function() {
+ $icon.fadeOut(300);
+ }, 2000);
+
+ var scope = this.$('#' + field + 'scope').val();
+ var verifyAvailable = this._updateVerifyButton(field, scope);
+
+ // change verification buttons from 'verify' to 'verifying...' on value change
+ if (verifyAvailable) {
+ if (field === 'twitter' || field === 'website') {
+ var verifyStatus = this.$('#' + field + 'form > .verify > #verify-' + field);
+ verifyStatus.attr('data-origin-title', t('settings', 'Verify'));
+ verifyStatus.attr('src', OC.imagePath('core', 'actions/verify.svg'));
+ verifyStatus.data('status', '0');
+ verifyStatus.addClass('verify-action');
+ } else if (field === 'email') {
+ var verifyStatus = this.$('#' + field + 'form > .verify > #verify-' + field);
+ verifyStatus.attr('data-origin-title', t('settings', 'Verifying …'));
+ verifyStatus.data('status', '1');
+ verifyStatus.attr('src', OC.imagePath('core', 'actions/verifying.svg'));
+ }
+ }
+ },
+
+ _showInputChangeFail: function(field) {
+ var $icon = this.$('#' + field + 'form > .icon-error');
+ $icon.fadeIn(200);
+ setTimeout(function() {
+ $icon.fadeOut(300);
+ }, 2000);
+ },
+
+ _setFieldScopeIcon: function(field, scope) {
+ var $icon = this.$('#' + field + 'form > .headerbar-label .icon-federation-menu');
+
+ $icon.removeClass('icon-phone');
+ $icon.removeClass('icon-password');
+ $icon.removeClass('icon-contacts-dark');
+ $icon.removeClass('icon-link');
+ $icon.addClass('hidden');
+
+ switch (scope) {
+ case 'v2-private':
+ $icon.addClass('icon-phone');
+ $icon.removeClass('hidden');
+ break;
+ case 'v2-local':
+ $icon.addClass('icon-password');
+ $icon.removeClass('hidden');
+ break;
+ case 'v2-federated':
+ $icon.addClass('icon-contacts-dark');
+ $icon.removeClass('hidden');
+ break;
+ case 'v2-published':
+ $icon.addClass('icon-link');
+ $icon.removeClass('hidden');
+ break;
+ }
+ }
+ });
+
+ OC.Settings = OC.Settings || {};
+ OC.Settings.FederationSettingsView = FederationSettingsView;
+})(_, $, OC);