]> source.dussan.org Git - nextcloud-server.git/commitdiff
Add more personal information fields to the settings page for enhanced federated...
authorChristoph Wurst <christoph@owncloud.com>
Wed, 20 Apr 2016 10:19:39 +0000 (12:19 +0200)
committerRoeland Jago Douma <roeland@famdouma.nl>
Mon, 21 Nov 2016 10:29:10 +0000 (11:29 +0100)
fix layout

Add generic way of handling input change events

Signed-off-by: Roeland Jago Douma <roeland@famdouma.nl>
settings/css/settings.css
settings/js/federationscopemenu.js [new file with mode: 0644]
settings/js/federationsettingsview.js [new file with mode: 0644]
settings/js/personal.js
settings/personal.php
settings/templates/personal.php

index 9008ba5a985bab9f18cc4c84f8328f52f1fdae10..fe3518ae6a300202759c1c8b09eaf20a2f1c2389 100644 (file)
@@ -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 (file)
index 0000000..6eb9afb
--- /dev/null
@@ -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 (file)
index 0000000..cf5158f
--- /dev/null
@@ -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
index c2cb437bd13a80776ede39a3fe7f3432b34bbd26..7a8d43d14756462727eb6656370c1b63a83b6310 100644 (file)
@@ -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;
index 01c358de3aefa4cd7a77ea22e3d934506f9d48fc..1780dddb5563c86baabf447db3349c6e2ca9010c 100644 (file)
@@ -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');
index 8f34d7b87b861ca288d29f99dd13b72c86684512..4fb9cefdeb0e537da8e883c91340277166828bfb 100644 (file)
 </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
 }
 ?>