Persist personal settings federated sharing scopes Show new settings fields in read-only mode too Insert values on page load Return updated values; show inline success feedback Signed-off-by: Roeland Jago Douma <roeland@famdouma.nl>tags/v11.0RC2
@@ -493,17 +493,62 @@ class UsersController extends Controller { | |||
} | |||
/** | |||
* Set the mail address of a user | |||
* @todo add method description | |||
* | |||
* @NoAdminRequired | |||
* @NoSubadminRequired | |||
* @PasswordConfirmationRequired | |||
* | |||
* @param string $userId | |||
* @param string $displayname | |||
* @param string $displaynameScope | |||
* @param string $phone | |||
* @param string $phoneScope | |||
* @param string $email | |||
* @param string $emailScope | |||
* @param string $website | |||
* @param string $websiteScope | |||
* @param string $address | |||
* @param string $addressScope | |||
* @return DataResponse | |||
*/ | |||
public function saveUserSettings($userId, | |||
$displayname, $displaynameScope, | |||
$phone, $phoneScope, | |||
$email, $emailScope, | |||
$website, $websiteScope, | |||
$address, $addressScope) { | |||
// TODO: implement | |||
return new DataResponse( | |||
array( | |||
'status' => 'success', | |||
'data' => array( | |||
'userId' => $userId, | |||
'displayname' => $displayname, | |||
'displaynameScope' => 'public', // force value for test purposes | |||
'email' => $email, | |||
'emailScope' => $emailScope, | |||
'website' => $website, | |||
'websiteScope' => $websiteScope, | |||
'address' => $address, | |||
'addressScope' => $addressScope, | |||
'message' => (string)$this->l10n->t('Settings saved') | |||
) | |||
), | |||
Http::STATUS_OK | |||
); | |||
} | |||
/** | |||
* Set the mail address of a user | |||
* | |||
* @todo Merge into saveUserSettings | |||
* | |||
* @param string $id | |||
* @param string $mailAddress | |||
* @return DataResponse | |||
*/ | |||
public function setMailAddress($id, $mailAddress) { | |||
private function setMailAddress($id, $mailAddress) { | |||
$userId = $this->userSession->getUser()->getUID(); | |||
$user = $this->userManager->get($id); | |||
@@ -619,12 +664,13 @@ class UsersController extends Controller { | |||
* @NoAdminRequired | |||
* @NoSubadminRequired | |||
* @PasswordConfirmationRequired | |||
* @todo merge into saveUserSettings | |||
* | |||
* @param string $username | |||
* @param string $displayName | |||
* @return DataResponse | |||
*/ | |||
public function setDisplayName($username, $displayName) { | |||
private function setDisplayName($username, $displayName) { | |||
$currentUser = $this->userSession->getUser(); | |||
if ($username === null) { |
@@ -78,6 +78,10 @@ input#openid, input#webdav { width:20em; } | |||
height: 100px; | |||
min-width: 300px; | |||
} | |||
#personal-settings-container.no-edit > div { | |||
height: 20px; | |||
min-width: 200px; | |||
} | |||
#personal-settings-container > div h2 span[class^="icon-"] { | |||
display: inline-block; | |||
margin-left: 5px; | |||
@@ -90,6 +94,12 @@ input#openid, input#webdav { width:20em; } | |||
.personal-settings-setting-box input[type="tel"] { | |||
width: 17em; | |||
} | |||
#personal-settings-container > div > form span[class^="icon-checkmark"] { | |||
position: absolute; | |||
left: 239px; | |||
top: 73px; | |||
pointer-events: none; | |||
} | |||
.federationScopeMenu { | |||
top: 66px; | |||
} | |||
@@ -101,7 +111,6 @@ input#openid, input#webdav { width:20em; } | |||
font-size: medium; | |||
} | |||
#displaynameform, | |||
#lostpassword, | |||
#groups, | |||
#passwordform { |
@@ -1,4 +1,4 @@ | |||
/* global OC */ | |||
/* global OC, result */ | |||
/** | |||
* Copyright (c) 2016, Christoph Wurst <christoph@owncloud.com> | |||
@@ -22,7 +22,7 @@ | |||
if (options.config) { | |||
this._config = options.config; | |||
} else { | |||
this._config = new OC.Backbone.Model() | |||
this._config = new OC.Settings.UserSettings(); | |||
} | |||
this._inputFields = [ | |||
@@ -33,6 +33,21 @@ | |||
'address' | |||
]; | |||
var self = this; | |||
_.each(this._inputFields, function(field) { | |||
// Initialize config model | |||
self._config.set(field, $('#' + field).val()); | |||
self._config.set(field + 'Scope', $('#' + field + 'scope').val()); | |||
// Set inputs whenever model values change | |||
self.listenTo(self._config, 'change:' + field, function () { | |||
self.$('#' + field).val(self._config.get(field)); | |||
}); | |||
self.listenTo(self._config, 'change:' + field + 'Scope', function () { | |||
self._onScopeChanged(field, self._config.get(field + 'Scope')); | |||
}); | |||
}); | |||
this._registerEvents(); | |||
}, | |||
@@ -53,6 +68,8 @@ | |||
// TODO: fix position without magic numbers | |||
var pos = ($heading.width() - $heading.find('label').width()) - 68; | |||
scopeMenu.$el.css('right', pos); | |||
self._onScopeChanged(field, self._config.get(field + 'Scope')); | |||
}); | |||
}, | |||
@@ -64,21 +81,30 @@ | |||
}, | |||
_onInputChanged: function(e) { | |||
OC.msg.startSaving('#personal-settings-container .msg'); | |||
var self = this; | |||
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 | |||
var savingData = this._config.save({ | |||
error: function(jqXHR) { | |||
OC.msg.finishedSaving('#personal-settings-container .msg', jqXHR); | |||
} | |||
}); | |||
$.when(savingData).done(function() { | |||
//OC.msg.finishedSaving('#personal-settings-container .msg', result) | |||
self._showInputChangeSuccess(field); | |||
if (field === 'displayname') { | |||
self._updateDisplayName(value); | |||
} | |||
}); | |||
}, | |||
_updateDisplayName: function(displayName) { | |||
// update displayName on the top right expand button | |||
$('#expandDisplayName').text($('#displayName').val()); | |||
$('#expandDisplayName').text(displayName); | |||
// update avatar if avatar is available | |||
if(!$('#removeavatar').hasClass('hidden')) { | |||
updateAvatar(); | |||
@@ -86,12 +112,20 @@ | |||
}, | |||
_onScopeChanged: function(field, scope) { | |||
// TODO: save changes to the server | |||
console.log(field + ' changed to ' + scope); | |||
this._config.set(field + 'Scope', scope); | |||
// TODO: user loading/success feedback | |||
this._config.save(); | |||
this._setFieldScopeIcon(field, scope); | |||
}, | |||
_showInputChangeSuccess: function(field) { | |||
var $icon = this.$('#' + field + 'form > span'); | |||
$icon.fadeIn(200); | |||
setTimeout(function() { | |||
$icon.fadeOut(300); | |||
}, 2000); | |||
}, | |||
_setFieldScopeIcon: function(field, scope) { | |||
var $icon = this.$('#' + field + 'form > h2 > span'); | |||
$icon.removeClass('icon-password'); |
@@ -0,0 +1,47 @@ | |||
/* 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'; | |||
/** | |||
* Model for storing and saving user settings | |||
* | |||
* @class UserSettings | |||
*/ | |||
var UserSettings = OC.Backbone.Model.extend({ | |||
url: OC.generateUrl('/settings/users/{id}/settings', {id: OC.currentUser}), | |||
parse: function(data) { | |||
if (_.isUndefined(data)) { | |||
return null; | |||
} | |||
if (_.isUndefined(data.data)) { | |||
return null; | |||
} | |||
data = data.data; | |||
var ignored = [ | |||
'userId', | |||
'message' | |||
]; | |||
_.each(ignored, function(ign) { | |||
if (!_.isUndefined(data[ign])) { | |||
delete data[ign]; | |||
} | |||
}); | |||
return data; | |||
} | |||
}); | |||
OC.Settings = OC.Settings || {}; | |||
OC.Settings.UserSettings = UserSettings; | |||
})(); |
@@ -47,6 +47,7 @@ $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', 'usersettings'); | |||
OC_Util::addScript('settings', 'federationsettingsview'); | |||
OC_Util::addScript('settings', 'federationscopemenu'); | |||
OC_Util::addScript('settings', 'personal'); | |||
@@ -164,6 +165,18 @@ $tmpl->assign('activelanguage', $userLang); | |||
$tmpl->assign('passwordChangeSupported', OC_User::canUserChangePassword(OC_User::getUser())); | |||
$tmpl->assign('displayNameChangeSupported', OC_User::canUserChangeDisplayName(OC_User::getUser())); | |||
$tmpl->assign('displayName', OC_User::getDisplayName()); | |||
// TODO: insert real data | |||
$tmpl->assign('phone', '+43 660 56565 5446'); | |||
$tmpl->assign('website', 'owncloud.org'); | |||
$tmpl->assign('address', 'Stuttgart'); | |||
$tmpl->assign('avatarScope', 'contacts'); | |||
$tmpl->assign('displayNameScope', 'public'); | |||
$tmpl->assign('phoneScope', 'contacts'); | |||
$tmpl->assign('emailScope', 'contacts'); | |||
$tmpl->assign('websiteScope', 'public'); | |||
$tmpl->assign('addressScope', 'private'); | |||
// END TODO | |||
$tmpl->assign('enableAvatars', $config->getSystemValue('enable_avatars', true) === true); | |||
$tmpl->assign('avatarChangeSupported', OC_User::canUserChangeAvatar(OC_User::getUser())); | |||
$tmpl->assign('certs', $certificateManager->listCertificates()); |
@@ -50,8 +50,7 @@ $application->registerRoutes($this, [ | |||
['name' => 'AppSettings#viewApps', 'url' => '/settings/apps', 'verb' => 'GET'], | |||
['name' => 'AppSettings#listApps', 'url' => '/settings/apps/list', 'verb' => 'GET'], | |||
['name' => 'SecuritySettings#trustedDomains', 'url' => '/settings/admin/security/trustedDomains', 'verb' => 'POST'], | |||
['name' => 'Users#setDisplayName', 'url' => '/settings/users/{username}/displayName', 'verb' => 'POST'], | |||
['name' => 'Users#setMailAddress', 'url' => '/settings/users/{id}/mailAddress', 'verb' => 'PUT'], | |||
['name' => 'Users#saveUserSettings', 'url' => '/settings/users/{username}/settings', 'verb' => 'POST'], | |||
['name' => 'Users#stats', 'url' => '/settings/users/stats', 'verb' => 'GET'], | |||
['name' => 'LogSettings#setLogLevel', 'url' => '/settings/admin/log/level', 'verb' => 'POST'], | |||
['name' => 'LogSettings#getEntries', 'url' => '/settings/admin/log/entries', 'verb' => 'GET'], |
@@ -71,6 +71,8 @@ if($_['displayNameChangeSupported']) { | |||
<input type="text" id="displayname" name="displayname" | |||
value="<?php p($_['displayName']) ?>" | |||
autocomplete="on" autocapitalize="off" autocorrect="off" /> | |||
<span class="icon-checkmark hidden"/> | |||
<input type="hidden" id="displaynamescope" value="<?php p($_['displayNameScope']) ?>"> | |||
</form> | |||
</div> | |||
<div class="personal-settings-setting-box"> | |||
@@ -82,6 +84,8 @@ if($_['displayNameChangeSupported']) { | |||
<input type="tel" id="phone" name="phone" | |||
value="<?php p($_['phone']) ?>" | |||
autocomplete="on" autocapitalize="off" autocorrect="off" /> | |||
<span class="icon-checkmark hidden"/> | |||
<input type="hidden" id="phonescope" value="<?php p($_['phoneScope']) ?>"> | |||
</form> | |||
</div> | |||
<div class="personal-settings-setting-box"> | |||
@@ -93,8 +97,10 @@ if($_['displayNameChangeSupported']) { | |||
<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" /> | |||
<input type="hidden" id="emailscope" value="<?php p($_['emailScope']) ?>"> | |||
<br /> | |||
<em><?php p($l->t('For password recovery and notifications')); ?></em> | |||
<span class="icon-checkmark hidden"/> | |||
</form> | |||
</div> | |||
<div class="personal-settings-setting-box"> | |||
@@ -106,6 +112,8 @@ if($_['displayNameChangeSupported']) { | |||
<input type="text" name="website" id="website" value="<?php p($_['website']); ?>" | |||
placeholder="<?php p($l->t('Your website')); ?>" | |||
autocomplete="on" autocapitalize="off" autocorrect="off" /> | |||
<span class="icon-checkmark hidden"/> | |||
<input type="hidden" id="websitescope" value="<?php p($_['websiteScope']) ?>"> | |||
</form> | |||
</div> | |||
<div class="personal-settings-setting-box"> | |||
@@ -117,6 +125,8 @@ if($_['displayNameChangeSupported']) { | |||
<input type="text" id="address" name="address" | |||
value="<?php p($_['address']) ?>" | |||
autocomplete="on" autocapitalize="off" autocorrect="off" /> | |||
<span class="icon-checkmark hidden"/> | |||
<input type="hidden" id="addressscope" value="<?php p($_['addressScope']) ?>"> | |||
</form> | |||
</div> | |||
<span class="msg"></span> | |||
@@ -149,13 +159,31 @@ 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 id="personal-settings-container" class="no-edit"> | |||
<div id="displaynameform" class="section"> | |||
<h2><?php p($l->t('Full name'));?></h2> | |||
<span><?php if(isset($_['displayName'][0])) { p($_['displayName']); } else { p($l->t('No display name set')); } ?></span> | |||
</div> | |||
<div id="emailform" class="section"> | |||
<h2><?php p($l->t('Email')); ?></h2> | |||
<span><?php if(isset($_['email'][0])) { p($_['email']); } else { p($l->t('No email address set')); }?></span> | |||
</div> | |||
<div id="phoneform" class="section"> | |||
<h2><?php p($l->t('Phone')); ?></h2> | |||
<span><?php if(isset($_['phone'][0])) { p($_['phone']); } else { p($l->t('No phone number set')); }?></span> | |||
</div> | |||
<div id="websiteform" class="section"> | |||
<h2><?php p($l->t('Website')); ?></h2> | |||
<span><?php if(isset($_['website'][0])) { p($_['website']); } else { p($l->t('No website set')); }?></span> | |||
</div> | |||
<div id="addressform" class="section"> | |||
<h2><?php p($l->t('Address')); ?></h2> | |||
<span><?php if(isset($_['address'][0])) { p($_['address']); } else { p($l->t('No address set')); }?></span> | |||
</div> | |||
</div> | |||
<!-- TODO: show phone/address --> | |||
<?php | |||
} | |||
?> |