diff options
author | Christoph Wurst <christoph@owncloud.com> | 2016-04-20 12:19:39 +0200 |
---|---|---|
committer | Roeland Jago Douma <roeland@famdouma.nl> | 2016-11-21 11:29:10 +0100 |
commit | c42d977185648fcc34c8e0135973ebc1c4776512 (patch) | |
tree | a35e6884341bab334a1973515987c4df8106297b /settings | |
parent | ba9b17c9069c5d9fe8595ffd306647f33067c927 (diff) | |
download | nextcloud-server-c42d977185648fcc34c8e0135973ebc1c4776512.tar.gz nextcloud-server-c42d977185648fcc34c8e0135973ebc1c4776512.zip |
Add more personal information fields to the settings page for enhanced federated sharing
fix layout
Add generic way of handling input change events
Signed-off-by: Roeland Jago Douma <roeland@famdouma.nl>
Diffstat (limited to 'settings')
-rw-r--r-- | settings/css/settings.css | 46 | ||||
-rw-r--r-- | settings/js/federationscopemenu.js | 114 | ||||
-rw-r--r-- | settings/js/federationsettingsview.js | 116 | ||||
-rw-r--r-- | settings/js/personal.js | 23 | ||||
-rw-r--r-- | settings/personal.php | 4 | ||||
-rw-r--r-- | settings/templates/personal.php | 111 |
6 files changed, 371 insertions, 43 deletions
diff --git a/settings/css/settings.css b/settings/css/settings.css index 9008ba5a985..fe3518ae6a3 100644 --- a/settings/css/settings.css +++ b/settings/css/settings.css @@ -8,8 +8,6 @@ input#openid, input#webdav { width:20em; } /* PERSONAL */ #avatar { - display: inline-block; - float: left; width: 160px; padding-right: 0; } @@ -63,6 +61,46 @@ input#openid, input#webdav { width:20em; } float: right; } +#personal-settings-avatar-container { + float: left; +} +#personal-settings-container { + position: relative; + float: left; + min-width: 280px; + width: calc(100% - 200px); +} +#personal-settings-container:after { + clear: both; +} +#personal-settings-container > div { + float: left; + height: 100px; + min-width: 300px; +} +#personal-settings-container > div h2 span[class^="icon-"] { + display: inline-block; + margin-left: 5px; + background-size: 110%; + opacity: 0.3; + cursor: pointer; +} +.personal-settings-setting-box input[type="text"], +.personal-settings-setting-box input[type="email"], +.personal-settings-setting-box input[type="tel"] { + width: 17em; +} +.federationScopeMenu { + top: 66px; +} +.federationScopeMenu.bubble::after { + left: 45px; +} +.federationScopeMenu.popovermenu { + font-weight: 100; + font-size: medium; +} + #displaynameform, #lostpassword, #groups, @@ -104,10 +142,6 @@ input#openid, input#webdav { width:20em; } input#identity { width: 20em; } -#displayName, -#email { - width: 17em; -} #showWizard { display: inline-block; diff --git a/settings/js/federationscopemenu.js b/settings/js/federationscopemenu.js new file mode 100644 index 00000000000..6eb9afb54e0 --- /dev/null +++ b/settings/js/federationscopemenu.js @@ -0,0 +1,114 @@ +/* + * Copyright (c) 2016 + * + * This file is licensed under the Affero General Public License version 3 + * or later. + * + * See the COPYING-README file. + * + */ + +/* global OC, Handlebars */ + +(function() { + + var TEMPLATE_MENU = + '<ul>' + + '{{#each items}}' + + '<li>' + + '<a href="#" class="menuitem action action-{{name}} permanent" data-action="{{name}}">' + + '{{#if icon}}<img class="icon" src="{{icon}}"/>' + + '{{else}}'+ + '{{#if iconClass}}' + + '<span class="icon {{iconClass}}"></span>' + + '{{else}}' + + '<span class="no-icon"></span>' + + '{{/if}}' + + '{{/if}}' + + '<span>{{displayName}}</span></a>' + + '</li>' + + '{{/each}}' + + '</ul>'; + + /** + * Construct a new FederationScopeMenu instance + * @constructs FederationScopeMenu + * @memberof OC.Settings + */ + var FederationScopeMenu = OC.Backbone.View.extend({ + tagName: 'div', + className: 'federationScopeMenu popovermenu bubble hidden open menu', + _scopes: [ + { + name: 'private', + displayName: t('core', 'Private'), + icon: OC.imagePath('core', 'actions/password') + }, + { + name: 'contacts', + displayName: t('core', 'Contacts'), + icon: OC.imagePath('core', 'places/contacts-dark') + }, + { + name: 'public', + displayName: t('core', 'Public'), + icon: OC.imagePath('core', 'places/link') + } + ], + + /** + * Current context + * + * @type OCA.Files.FileActionContext + */ + _context: null, + + events: { + 'click a.action': '_onClickAction' + }, + + template: Handlebars.compile(TEMPLATE_MENU), + + /** + * Event handler whenever an action has been clicked within the menu + * + * @param {Object} event event object + */ + _onClickAction: function(event) { + var $target = $(event.currentTarget); + if (!$target.hasClass('menuitem')) { + $target = $target.closest('.menuitem'); + } + + this.trigger('select:scope', $target.data('action')); + + OC.hideMenus(); + }, + + /** + * Renders the menu with the currently set items + */ + render: function() { + this.$el.html(this.template({ + items: this._scopes + })); + }, + + /** + * Displays the menu + */ + show: function(context) { + this._context = context; + + this.render(); + this.$el.removeClass('hidden'); + + OC.showMenu(null, this.$el); + } + }); + + OC.Settings = OC.Settings || {}; + OC.Settings.FederationScopeMenu = FederationScopeMenu; + +})(); + diff --git a/settings/js/federationsettingsview.js b/settings/js/federationsettingsview.js new file mode 100644 index 00000000000..cf5158fa785 --- /dev/null +++ b/settings/js/federationsettingsview.js @@ -0,0 +1,116 @@ +/* global OC */ + +/** + * Copyright (c) 2016, Christoph Wurst <christoph@owncloud.com> + * + * This file is licensed under the Affero General Public License version 3 or later. + * See the COPYING-README file. + */ + +(function() { + 'use strict'; + + 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.Backbone.Model() + } + + this._inputFields = [ + 'displayname', + 'phone', + 'email', + 'website', + 'address' + ]; + + this._registerEvents(); + }, + + render: function() { + var self = this; + _.each(this._inputFields, function(field) { + var $heading = self.$('#' + field + 'form > h2'); + var $icon = self.$('#' + field + 'form > h2 > span'); + var scopeMenu = new OC.Settings.FederationScopeMenu(); + + self.listenTo(scopeMenu, 'select:scope', function(scope) { + self._onScopeChanged(field, scope); + }); + $heading.append(scopeMenu.$el); + $icon.on('click', _.bind(scopeMenu.show, scopeMenu)); + + // Fix absolute position according to the heading text length + // TODO: fix position without magic numbers + var pos = ($heading.width() - $heading.find('label').width()) - 68; + scopeMenu.$el.css('right', pos); + }); + }, + + _registerEvents: function() { + var self = this; + _.each(this._inputFields, function(field) { + self.$('#' + field).keyUpDelayedOrEnter(_.bind(self._onInputChanged, self)); + }); + }, + + _onInputChanged: function(e) { + OC.msg.startSaving('#personal-settings-container .msg'); + var $target = $(e.target); + var value = $target.val(); + var field = $target.attr('id'); + console.log(field + ' changed to ' + value); + this._config.set(field, value); + console.log(this._config.toJSON()); + // TODO: this._config.save(); + // TODO: OC.msg.finishedSaving('#personal-settings-container .msg', result); + // TODO: call _updateDisplayName after successful update + }, + + _updateDisplayName: function(displayName) { + // update displayName on the top right expand button + $('#expandDisplayName').text($('#displayName').val()); + // update avatar if avatar is available + if(!$('#removeavatar').hasClass('hidden')) { + updateAvatar(); + } + }, + + _onScopeChanged: function(field, scope) { + // TODO: save changes to the server + console.log(field + ' changed to ' + scope); + + this._setFieldScopeIcon(field, scope); + }, + + _setFieldScopeIcon: function(field, scope) { + var $icon = this.$('#' + field + 'form > h2 > span'); + $icon.removeClass('icon-password'); + $icon.removeClass('icon-contacts-dark'); + $icon.removeClass('icon-link'); + switch (scope) { + case 'private': + $icon.addClass('icon-password'); + break; + case 'contacts': + $icon.addClass('icon-contacts-dark'); + break; + case 'public': + $icon.addClass('icon-link'); + break; + } + } + }); + + OC.Settings = OC.Settings || {}; + OC.Settings.FederationSettingsView = FederationSettingsView; +})();
\ No newline at end of file diff --git a/settings/js/personal.js b/settings/js/personal.js index c2cb437bd13..7a8d43d1475 100644 --- a/settings/js/personal.js +++ b/settings/js/personal.js @@ -1,10 +1,15 @@ +/* global OC */ + /** * Copyright (c) 2011, Robin Appelman <icewind1991@gmail.com> * 2013, Morris Jobke <morris.jobke@gmail.com> + * 2016, Christoph Wurst <christoph@owncloud.com> * This file is licensed under the Affero General Public License version 3 or later. * See the COPYING-README file. */ +OC.Settings = OC.Settings || {}; + /** * The callback will be fired as soon as enter is pressed by the * user or 1 second after the last data entry @@ -21,21 +26,21 @@ jQuery.fn.keyUpDelayedOrEnter = function (callback, allowEmptyValue) { return; } if (allowEmptyValue || that.val() !== '') { - cb(); + cb(event); } }, 1000)); this.keypress(function (event) { if (event.keyCode === 13 && (allowEmptyValue || that.val() !== '')) { event.preventDefault(); - cb(); + cb(event); } }); - this.bind('paste', null, function (e) { - if(!e.keyCode){ + this.bind('paste', null, function (event) { + if(!event.keyCode){ if (allowEmptyValue || that.val() !== '') { - cb(); + cb(event); } } }); @@ -265,8 +270,10 @@ $(document).ready(function () { } }); - $('#displayName').keyUpDelayedOrEnter(changeDisplayName); - $('#email').keyUpDelayedOrEnter(changeEmailAddress, true); + var federationSettingsView = new OC.Settings.FederationSettingsView({ + el: '#personal-settings-container' + }); + federationSettingsView.render(); $("#languageinput").change(function () { // Serialize the data @@ -452,3 +459,5 @@ OC.Encryption.msg = { } } }; + +OC.Settings.updateAvatar = updateAvatar; diff --git a/settings/personal.php b/settings/personal.php index 01c358de3ae..1780dddb556 100644 --- a/settings/personal.php +++ b/settings/personal.php @@ -47,7 +47,9 @@ $urlGenerator = \OC::$server->getURLGenerator(); OC_Util::addScript('settings', 'authtoken'); OC_Util::addScript('settings', 'authtoken_collection'); OC_Util::addScript('settings', 'authtoken_view'); -OC_Util::addScript( 'settings', 'personal' ); +OC_Util::addScript('settings', 'federationsettingsview'); +OC_Util::addScript('settings', 'federationscopemenu'); +OC_Util::addScript('settings', 'personal'); OC_Util::addScript('settings', 'certificates'); OC_Util::addStyle( 'settings', 'settings' ); \OC_Util::addVendorScript('strengthify/jquery.strengthify'); diff --git a/settings/templates/personal.php b/settings/templates/personal.php index 8f34d7b87b8..4fb9cefdeb0 100644 --- a/settings/templates/personal.php +++ b/settings/templates/personal.php @@ -33,44 +33,94 @@ </div> <?php if ($_['enableAvatars']): ?> -<form id="avatar" class="section" method="post" action="<?php p(\OC::$server->getURLGenerator()->linkToRoute('core.avatar.postAvatar')); ?>"> - <h2><?php p($l->t('Profile picture')); ?></h2> - <div id="displayavatar"> - <div class="avatardiv"></div> - <div class="warning hidden"></div> - <?php if ($_['avatarChangeSupported']): ?> - <label for="uploadavatar" class="inlineblock button icon-upload" id="uploadavatarbutton" title="<?php p($l->t('Upload new')); ?>"></label> - <div class="inlineblock button icon-folder" id="selectavatar" title="<?php p($l->t('Select from Files')); ?>"></div> - <div class="hidden button icon-delete" id="removeavatar" title="<?php p($l->t('Remove image')); ?>"></div> - <input type="file" name="files[]" id="uploadavatar" class="hiddenuploadfield"> - <p><em><?php p($l->t('png or jpg, max. 20 MB')); ?></em></p> - <?php else: ?> - <?php p($l->t('Picture provided by original account')); ?> - <?php endif; ?> - </div> +<div id="personal-settings-avatar-container"> + <form id="avatar" class="section" method="post" action="<?php p(\OC::$server->getURLGenerator()->linkToRoute('core.avatar.postAvatar')); ?>"> + <h2><?php p($l->t('Profile picture')); ?></h2> + <div id="displayavatar"> + <div class="avatardiv"></div> + <div class="warning hidden"></div> + <?php if ($_['avatarChangeSupported']): ?> + <label for="uploadavatar" class="inlineblock button icon-upload svg" id="uploadavatarbutton" title="<?php p($l->t('Upload new')); ?>"></label> + <div class="inlineblock button icon-folder svg" id="selectavatar" title="<?php p($l->t('Select from Files')); ?>"></div> + <div class="hidden button icon-delete svg" id="removeavatar" title="<?php p($l->t('Remove image')); ?>"></div> + <input type="file" name="files[]" id="uploadavatar" class="hiddenuploadfield"> + <p><em><?php p($l->t('png or jpg, max. 20 MB')); ?></em></p> + <?php else: ?> + <?php p($l->t('Picture provided by original account')); ?> + <?php endif; ?> + </div> - <div id="cropper" class="hidden"> - <div class="inner-container"> + <div id="cropper" class="hidden"> <div class="inlineblock button" id="abortcropperbutton"><?php p($l->t('Cancel')); ?></div> <div class="inlineblock button primary" id="sendcropperbutton"><?php p($l->t('Choose as profile picture')); ?></div> </div> - </div> -</form> + </form> +</div> <?php endif; ?> <?php if($_['displayNameChangeSupported']) { ?> -<form id="displaynameform" class="section"> - <h2> - <label for="displayName"><?php echo $l->t('Full name');?></label> - </h2> - <input type="text" id="displayName" name="displayName" class="password-confirm-required" - value="<?php p($_['displayName'])?>" - autocomplete="on" autocapitalize="off" autocorrect="off" /> - <span class="msg"></span> - <input type="hidden" id="oldDisplayName" name="oldDisplayName" value="<?php p($_['displayName'])?>" /> -</form> +<div id="personal-settings-container"> + <div class="personal-settings-setting-box"> + <form id="displaynameform" class="section"> + <h2> + <label for="displayname"><?php p($l->t('Full name')); ?></label> + <span class="icon-password"/> + </h2> + <input type="text" id="displayname" name="displayname" + value="<?php p($_['displayName']) ?>" + autocomplete="on" autocapitalize="off" autocorrect="off" /> + </form> + </div> + <div class="personal-settings-setting-box"> + <form id="phoneform" class="section"> + <h2> + <label for="phone"><?php p($l->t('Phone name')); ?></label> + <span class="icon-password"/> + </h2> + <input type="tel" id="phone" name="phone" + value="<?php p($_['phone']) ?>" + autocomplete="on" autocapitalize="off" autocorrect="off" /> + </form> + </div> + <div class="personal-settings-setting-box"> + <form id="emailform" class="section"> + <h2> + <label for="email"><?php p($l->t('Email')); ?></label> + <span class="icon-password"/> + </h2> + <input type="email" name="email" id="email" value="<?php p($_['email']); ?>" + placeholder="<?php p($l->t('Your email address')); ?>" + autocomplete="on" autocapitalize="off" autocorrect="off" /> + <br /> + <em><?php p($l->t('For password recovery and notifications')); ?></em> + </form> + </div> + <div class="personal-settings-setting-box"> + <form id="websiteform" class="section"> + <h2> + <label for="website"><?php p($l->t('Website')); ?></label> + <span class="icon-password"/> + </h2> + <input type="text" name="website" id="website" value="<?php p($_['website']); ?>" + placeholder="<?php p($l->t('Your website')); ?>" + autocomplete="on" autocapitalize="off" autocorrect="off" /> + </form> + </div> + <div class="personal-settings-setting-box"> + <form id="addressform" class="section"> + <h2> + <label for="address"><?php echo $l->t('Address'); ?></label> + <span class="icon-password"/> + </h2> + <input type="text" id="address" name="address" + value="<?php p($_['address']) ?>" + autocomplete="on" autocapitalize="off" autocorrect="off" /> + </form> + </div> + <span class="msg"></span> +</div> <?php } else { ?> @@ -99,10 +149,13 @@ if($_['displayNameChangeSupported']) { <?php } else { ?> +======= +>>>>>>> Add more personal information fields to the settings page for enhanced federated sharing <div id="lostpassword" class="section"> <h2><?php echo $l->t('Email'); ?></h2> <span><?php if(isset($_['email'][0])) { p($_['email']); } else { p($l->t('No email address set')); }?></span> </div> +<!-- TODO: show phone/address --> <?php } ?> |