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>
This commit is contained in:
parent
ba9b17c906
commit
c42d977185
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
||||
})();
|
||||
|
|
@ -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;
|
||||
})();
|
|
@ -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;
|
||||
|
|
|
@ -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');
|
||||
|
|
|
@ -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
|
||||
}
|
||||
?>
|
||||
|
|
Loading…
Reference in New Issue