Merge pull request #7151 from owncloud/user-jquery
Continuing the New User management
This commit is contained in:
commit
79b3558c6d
|
@ -309,7 +309,7 @@ input[type="submit"].enabled {
|
|||
position: fixed;
|
||||
top:45px;
|
||||
right: 0;
|
||||
left: 0;
|
||||
left:0;
|
||||
height: 44px;
|
||||
width: 100%;
|
||||
padding: 0;
|
||||
|
|
|
@ -1092,6 +1092,7 @@ function initCore() {
|
|||
$('a.action.delete').tipsy({gravity:'e', fade:true, live:true});
|
||||
$('a.action').tipsy({gravity:'s', fade:true, live:true});
|
||||
$('td .modified').tipsy({gravity:'s', fade:true, live:true});
|
||||
$('td.lastLogin').tipsy({gravity:'s', fade:true, html:true});
|
||||
$('input').tipsy({gravity:'w', fade:true});
|
||||
|
||||
// toggle for menus
|
||||
|
|
|
@ -186,7 +186,7 @@ class Group {
|
|||
* @param string $search
|
||||
* @return int|bool
|
||||
*/
|
||||
public function count($search) {
|
||||
public function count($search = '') {
|
||||
$users = false;
|
||||
foreach ($this->backends as $backend) {
|
||||
if($backend->implementsActions(OC_GROUP_BACKEND_COUNT_USERS)) {
|
||||
|
|
|
@ -0,0 +1,188 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* Copyright (c) 2014 Arthur Schiwon <blizzz@owncloud.com>
|
||||
* This file is licensed under the Affero General Public License version 3 or
|
||||
* later.
|
||||
* See the COPYING-README file.
|
||||
*/
|
||||
|
||||
namespace OC\Group;
|
||||
|
||||
class MetaData {
|
||||
const SORT_NONE = 0;
|
||||
const SORT_USERCOUNT = 1;
|
||||
|
||||
/**
|
||||
* @var string $user
|
||||
*/
|
||||
protected $user;
|
||||
|
||||
/**
|
||||
* @var bool $isAdmin
|
||||
*/
|
||||
protected $isAdmin;
|
||||
|
||||
/**
|
||||
* @var string[] $groups
|
||||
*/
|
||||
protected $groups = array();
|
||||
|
||||
/**
|
||||
* @var \OC\Group\Manager $groupManager
|
||||
*/
|
||||
protected $groupManager;
|
||||
|
||||
/**
|
||||
* @var int $sorting
|
||||
*/
|
||||
protected $sorting = false;
|
||||
|
||||
/**
|
||||
* @var string $lastSearch
|
||||
*/
|
||||
protected $lastSearch;
|
||||
|
||||
/**
|
||||
* @param string the uid of the current user
|
||||
* @param bool whether the current users is an admin
|
||||
* @param \OC\Group\Manager
|
||||
*/
|
||||
public function __construct(
|
||||
$user,
|
||||
$isAdmin,
|
||||
\OC\Group\Manager $groupManager
|
||||
) {
|
||||
$this->user = $user;
|
||||
$this->isAdmin = (bool)$isAdmin;
|
||||
$this->groupManager = $groupManager;
|
||||
}
|
||||
|
||||
/**
|
||||
* returns an array with meta data about all available groups
|
||||
* the array is structured as follows:
|
||||
* [0] array containing meta data about admin groups
|
||||
* [1] array containing meta data about unprivileged groups
|
||||
* @param string only effective when instance was created with isAdmin being
|
||||
* true
|
||||
* @return array
|
||||
*/
|
||||
public function get($search = '') {
|
||||
if($this->lastSearch !== $search) {
|
||||
$this->lastSearch = $search;
|
||||
$this->groups = array();
|
||||
}
|
||||
|
||||
$adminGroups = array();
|
||||
$groups = array();
|
||||
$sortGroupsIndex = 0;
|
||||
$sortGroupsKeys = array();
|
||||
$sortAdminGroupsIndex = 0;
|
||||
$sortAdminGroupsKeys = array();
|
||||
|
||||
foreach($this->getGroups($search) as $group) {
|
||||
$groupMetaData = $this->generateGroupMetaData($group);
|
||||
if (strtolower($group->getGID()) !== 'admin') {
|
||||
$this->addEntry(
|
||||
$groups,
|
||||
$sortGroupsKeys,
|
||||
$sortGroupsIndex,
|
||||
$groupMetaData);
|
||||
} else {
|
||||
//admin group is hard coded to 'admin' for now. In future,
|
||||
//backends may define admin groups too. Then the if statement
|
||||
//has to be adjusted accordingly.
|
||||
$this->addEntry(
|
||||
$adminGroups,
|
||||
$sortAdminGroupsKeys,
|
||||
$sortAdminGroupsIndex,
|
||||
$groupMetaData);
|
||||
}
|
||||
}
|
||||
|
||||
//whether sorting is necessary is will be checked in sort()
|
||||
$this->sort($groups, $sortGroupsKeys);
|
||||
$this->sort($adminGroups, $sortAdminGroupsKeys);
|
||||
|
||||
return array($adminGroups, $groups);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief sets the sort mode, currently 0 (none) and 1 (user entries,
|
||||
* descending) are supported
|
||||
* @param int the sortMode (SORT_NONE, SORT_USERCOUNT)
|
||||
*/
|
||||
public function setSorting($sortMode) {
|
||||
if($sortMode >= 0 && $sortMode <= 1) {
|
||||
$this->sorting = $sortMode;
|
||||
} else {
|
||||
$this->sorting = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief adds an group entry to the resulting array
|
||||
* @param array the resulting array, by reference
|
||||
* @param array the sort key array, by reference
|
||||
* @param array the sort key index, by reference
|
||||
* @param array the group's meta data as returned by generateGroupMetaData()
|
||||
* @return null
|
||||
*/
|
||||
private function addEntry(&$entries, &$sortKeys, &$sortIndex, $data) {
|
||||
$entries[] = $data;
|
||||
if($this->sorting === 1) {
|
||||
$sortKeys[$sortIndex] = $data['usercount'];
|
||||
$sortIndex++;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief creates an array containing the group meta data
|
||||
* @param \OC\Group\Group
|
||||
* @return array with the keys 'id', 'name' and 'usercount'
|
||||
*/
|
||||
private function generateGroupMetaData(\OC\Group\Group $group) {
|
||||
return array(
|
||||
'id' => str_replace(' ','', $group->getGID()),
|
||||
'name' => $group->getGID(),
|
||||
'usercount' => $group->count()
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief sorts the result array, if applicable
|
||||
* @param array the result array, by reference
|
||||
* @param array the array containing the sort keys
|
||||
* @param return null
|
||||
*/
|
||||
private function sort(&$entries, $sortKeys) {
|
||||
if($this->sorting > 0) {
|
||||
array_multisort($sortKeys, SORT_DESC, $entries);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief returns the available groups
|
||||
* @param string a search string
|
||||
* @return \OC\Group\Group[]
|
||||
*/
|
||||
private function getGroups($search = '') {
|
||||
if(count($this->groups) === 0) {
|
||||
$this->fetchGroups($search);
|
||||
}
|
||||
return $this->groups;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief fetches the group using the group manager or the subAdmin API
|
||||
* @param string a search string
|
||||
* @return null
|
||||
*/
|
||||
private function fetchGroups($search = '') {
|
||||
if($this->isAdmin) {
|
||||
$this->groups = $this->groupManager->search($search);
|
||||
} else {
|
||||
$this->groups = \OC_SubAdmin::getSubAdminsGroups($this->user);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -4,6 +4,7 @@ OCP\JSON::callCheck();
|
|||
OC_JSON::checkAdminUser();
|
||||
|
||||
$groupname = $_POST["groupname"];
|
||||
$l = OC_L10N::get('settings');
|
||||
|
||||
// Does the group exist?
|
||||
if( in_array( $groupname, OC_Group::getGroups())) {
|
||||
|
|
|
@ -43,12 +43,15 @@ try {
|
|||
OC_Group::addToGroup( $username, $i );
|
||||
}
|
||||
|
||||
OC_JSON::success(array("data" =>
|
||||
$userManager = \OC_User::getManager();
|
||||
$user = $userManager->get($username);
|
||||
OCP\JSON::success(array("data" =>
|
||||
array(
|
||||
// returns whether the home already existed
|
||||
"homeExists" => $homeExists,
|
||||
"username" => $username,
|
||||
"groups" => OC_Group::getUserGroups( $username ))));
|
||||
"groups" => OC_Group::getUserGroups( $username ),
|
||||
'storageLocation' => $user->getHome())));
|
||||
} catch (Exception $exception) {
|
||||
OC_JSON::error(array("data" => array( "message" => $exception->getMessage())));
|
||||
OCP\JSON::error(array("data" => array( "message" => $exception->getMessage())));
|
||||
}
|
||||
|
|
|
@ -0,0 +1,48 @@
|
|||
<?php
|
||||
/**
|
||||
* ownCloud
|
||||
*
|
||||
* @author Arthur Schiwon
|
||||
* @copyright 2014 Arthur Schiwon <blizzz@owncloud.com>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 3 of the License, or any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU AFFERO GENERAL PUBLIC LICENSE for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public
|
||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
OC_JSON::callCheck();
|
||||
OC_JSON::checkSubAdminUser();
|
||||
if (isset($_GET['pattern']) && !empty($_GET['pattern'])) {
|
||||
$pattern = $_GET['pattern'];
|
||||
} else {
|
||||
$pattern = '';
|
||||
}
|
||||
$groups = array();
|
||||
$adminGroups = array();
|
||||
$groupManager = \OC_Group::getManager();
|
||||
$isAdmin = OC_User::isAdminUser(OC_User::getUser());
|
||||
|
||||
//we pass isAdmin as true, because OC_SubAdmin has no search feature,
|
||||
//groups will be filtered out later
|
||||
$groupsInfo = new \OC\Group\MetaData(OC_User::getUser(), true, $groupManager);
|
||||
$groupsInfo->setSorting($groupsInfo::SORT_USERCOUNT);
|
||||
list($adminGroups, $groups) = $groupsInfo->get($pattern);
|
||||
|
||||
$accessibleGroups = $groupManager->search($pattern);
|
||||
if(!$isAdmin) {
|
||||
$subadminGroups = OC_SubAdmin::getSubAdminsGroups(OC_User::getUser());
|
||||
$accessibleGroups = array_intersect($groups, $subadminGroups);
|
||||
}
|
||||
|
||||
OC_JSON::success(
|
||||
array('data' => array('adminGroups' => $adminGroups, 'groups' => $groups)));
|
|
@ -32,26 +32,55 @@ if (isset($_GET['limit'])) {
|
|||
} else {
|
||||
$limit = 10;
|
||||
}
|
||||
if (isset($_GET['gid']) && !empty($_GET['gid'])) {
|
||||
$gid = $_GET['gid'];
|
||||
} else {
|
||||
$gid = false;
|
||||
}
|
||||
if (isset($_GET['pattern']) && !empty($_GET['pattern'])) {
|
||||
$pattern = $_GET['pattern'];
|
||||
} else {
|
||||
$pattern = '';
|
||||
}
|
||||
$users = array();
|
||||
$userManager = \OC_User::getManager();
|
||||
if (OC_User::isAdminUser(OC_User::getUser())) {
|
||||
$batch = OC_User::getDisplayNames('', $limit, $offset);
|
||||
foreach ($batch as $user => $displayname) {
|
||||
if($gid !== false) {
|
||||
$batch = OC_Group::displayNamesInGroup($gid, $pattern, $limit, $offset);
|
||||
} else {
|
||||
$batch = OC_User::getDisplayNames($pattern, $limit, $offset);
|
||||
}
|
||||
foreach ($batch as $uid => $displayname) {
|
||||
$user = $userManager->get($uid);
|
||||
$users[] = array(
|
||||
'name' => $user,
|
||||
'name' => $uid,
|
||||
'displayname' => $displayname,
|
||||
'groups' => join(', ', OC_Group::getUserGroups($user)),
|
||||
'subadmin' => join(', ', OC_SubAdmin::getSubAdminsGroups($user)),
|
||||
'quota' => OC_Preferences::getValue($user, 'files', 'quota', 'default'));
|
||||
'groups' => join(', ', OC_Group::getUserGroups($uid)),
|
||||
'subadmin' => join(', ', OC_SubAdmin::getSubAdminsGroups($uid)),
|
||||
'quota' => OC_Preferences::getValue($uid, 'files', 'quota', 'default'),
|
||||
'storageLocation' => $user->getHome(),
|
||||
'lastLogin' => $user->getLastLogin(),
|
||||
);
|
||||
}
|
||||
} else {
|
||||
$groups = OC_SubAdmin::getSubAdminsGroups(OC_User::getUser());
|
||||
$batch = OC_Group::usersInGroups($groups, '', $limit, $offset);
|
||||
foreach ($batch as $user) {
|
||||
if($gid !== false && in_array($gid, $groups)) {
|
||||
$groups = array($gid);
|
||||
} elseif($gid !== false) {
|
||||
//don't you try to investigate loops you must not know about
|
||||
$groups = array();
|
||||
}
|
||||
$batch = OC_Group::usersInGroups($groups, $pattern, $limit, $offset);
|
||||
foreach ($batch as $uid) {
|
||||
$user = $userManager->get($uid);
|
||||
$users[] = array(
|
||||
'name' => $user,
|
||||
'displayname' => OC_User::getDisplayName($user),
|
||||
'groups' => join(', ', OC_Group::getUserGroups($user)),
|
||||
'quota' => OC_Preferences::getValue($user, 'files', 'quota', 'default'));
|
||||
'displayname' => $user->getDisplayName(),
|
||||
'groups' => join(', ', OC_Group::getUserGroups($uid)),
|
||||
'quota' => OC_Preferences::getValue($uid, 'files', 'quota', 'default'),
|
||||
'storageLocation' => $user->getHome(),
|
||||
'lastLogin' => $user->getLastLogin(),
|
||||
);
|
||||
}
|
||||
}
|
||||
OC_JSON::success(array('data' => $users));
|
||||
|
|
|
@ -5,6 +5,13 @@
|
|||
select#languageinput, select#timezone { width:15em; }
|
||||
input#openid, input#webdav { width:20em; }
|
||||
|
||||
#user-controls {
|
||||
-moz-box-sizing: border-box; -webkit-box-sizing: border-box; box-sizing: border-box;
|
||||
position: fixed; right: 0; left:380px; height: 44px;
|
||||
padding: 0; margin: 0;
|
||||
background: #eee; border-bottom: 1px solid #e7e7e7;
|
||||
z-index: 50;
|
||||
}
|
||||
|
||||
/* PERSONAL */
|
||||
#rootcert_import {
|
||||
|
@ -44,7 +51,37 @@ table.nostyle label { margin-right: 2em; }
|
|||
table.nostyle td { padding: 0.2em 0; }
|
||||
|
||||
/* USERS */
|
||||
#newgroup-init a span { margin-left: 20px; }
|
||||
#newgroup-init a span:before {
|
||||
position: absolute; left: 12px; top:-2px;
|
||||
content: '+'; font-weight: bold; font-size: 150%;
|
||||
}
|
||||
.usercount { float: left; margin: 5px; }
|
||||
li.active span.utils .delete {
|
||||
float: left; position: relative; opacity: 0.5;
|
||||
top: -7px; left: 7px; width: 44px; height: 44px;
|
||||
}
|
||||
li.active .rename {
|
||||
padding: 8px 14px 20px 14px;
|
||||
top: 0px; position: absolute; width: 16px; height: 16px;
|
||||
opacity: 0.5;
|
||||
display: inline-block !important;
|
||||
}
|
||||
li.active span.utils .delete img { margin: 14px; }
|
||||
li.active .rename { opacity: 0.5; }
|
||||
li.active span.utils .delete:hover, li.active .rename:hover { opacity: 1; }
|
||||
span.utils .delete, .rename { display: none; }
|
||||
#app-navigation ul li.active > span.utils .delete,
|
||||
#app-navigation ul li.active > span.utils .rename { display: block; }
|
||||
#usersearchform { position: absolute; top: 4px; right: 10px; }
|
||||
#usersearchform label { font-weight: 700; }
|
||||
form { display:inline; }
|
||||
|
||||
/* display table at full width */
|
||||
table.grid {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
table.grid th { height:2em; color:#999; }
|
||||
table.grid th, table.grid td { border-bottom:1px solid #ddd; padding:0 .5em; padding-left:.8em; text-align:left; font-weight:normal; }
|
||||
td.name, td.password { padding-left:.8em; }
|
||||
|
@ -57,9 +94,8 @@ tr:hover>td.password>span, tr:hover>td.displayName>span { margin:0; cursor:point
|
|||
tr:hover>td.remove>a, tr:hover>td.password>img,tr:hover>td.displayName>img, tr:hover>td.quota>img { visibility:visible; cursor:pointer; }
|
||||
tr:hover>td.remove>a { float:right; }
|
||||
|
||||
table.grid { width:100%; }
|
||||
div.quota {
|
||||
float: right;
|
||||
margin: 10px;
|
||||
display: block;
|
||||
}
|
||||
div.quota-select-wrapper { position: relative; }
|
||||
|
@ -78,6 +114,8 @@ div.quota>span {
|
|||
}
|
||||
select.quota.active { background: #fff; }
|
||||
|
||||
input.userFilter {width: 200px;}
|
||||
|
||||
/* positioning fixes */
|
||||
#newuser .multiselect {
|
||||
min-width: 150px !important;
|
||||
|
|
|
@ -1,546 +0,0 @@
|
|||
/**
|
||||
* Copyright (c) 2011, Robin Appelman <icewind1991@gmail.com>
|
||||
* This file is licensed under the Affero General Public License version 3 or later.
|
||||
* See the COPYING-README file.
|
||||
*/
|
||||
|
||||
function setQuota (uid, quota, ready) {
|
||||
$.post(
|
||||
OC.filePath('settings', 'ajax', 'setquota.php'),
|
||||
{username: uid, quota: quota},
|
||||
function (result) {
|
||||
if (ready) {
|
||||
ready(result.data.quota);
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
var UserList = {
|
||||
useUndo: true,
|
||||
availableGroups: [],
|
||||
offset: 30, //The first 30 users are there. No prob, if less in total.
|
||||
//hardcoded in settings/users.php
|
||||
|
||||
usersToLoad: 10, //So many users will be loaded when user scrolls down
|
||||
|
||||
/**
|
||||
* @brief Initiate user deletion process in UI
|
||||
* @param string uid the user ID to be deleted
|
||||
*
|
||||
* Does not actually delete the user; it sets them for
|
||||
* deletion when the current page is unloaded, at which point
|
||||
* finishDelete() completes the process. This allows for 'undo'.
|
||||
*/
|
||||
do_delete: function (uid) {
|
||||
if (typeof UserList.deleteUid !== 'undefined') {
|
||||
//Already a user in the undo queue
|
||||
UserList.finishDelete(null);
|
||||
}
|
||||
UserList.deleteUid = uid;
|
||||
|
||||
// Set undo flag
|
||||
UserList.deleteCanceled = false;
|
||||
|
||||
// Provide user with option to undo
|
||||
$('#notification').data('deleteuser', true);
|
||||
OC.Notification.showHtml(t('settings', 'deleted') + ' ' + escapeHTML(uid) + '<span class="undo">' + t('settings', 'undo') + '</span>');
|
||||
},
|
||||
|
||||
/**
|
||||
* @brief Delete a user via ajax
|
||||
* @param bool ready whether to use ready() upon completion
|
||||
*
|
||||
* Executes deletion via ajax of user identified by property deleteUid
|
||||
* if 'undo' has not been used. Completes the user deletion procedure
|
||||
* and reflects success in UI.
|
||||
*/
|
||||
finishDelete: function (ready) {
|
||||
|
||||
// Check deletion has not been undone
|
||||
if (!UserList.deleteCanceled && UserList.deleteUid) {
|
||||
|
||||
// Delete user via ajax
|
||||
$.ajax({
|
||||
type: 'POST',
|
||||
url: OC.filePath('settings', 'ajax', 'removeuser.php'),
|
||||
async: false,
|
||||
data: { username: UserList.deleteUid },
|
||||
success: function (result) {
|
||||
if (result.status === 'success') {
|
||||
// Remove undo option, & remove user from table
|
||||
OC.Notification.hide();
|
||||
$('tr').filterAttr('data-uid', UserList.deleteUid).remove();
|
||||
UserList.deleteCanceled = true;
|
||||
if (ready) {
|
||||
ready();
|
||||
}
|
||||
} else {
|
||||
OC.dialogs.alert(result.data.message, t('settings', 'Unable to remove user'));
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
add: function (username, displayname, groups, subadmin, quota, sort) {
|
||||
var tr = $('tbody tr').first().clone();
|
||||
var subadminsEl;
|
||||
var subadminSelect;
|
||||
var groupsSelect;
|
||||
if (tr.find('div.avatardiv').length){
|
||||
$('div.avatardiv', tr).avatar(username, 32);
|
||||
}
|
||||
tr.attr('data-uid', username);
|
||||
tr.attr('data-displayName', displayname);
|
||||
tr.find('td.name').text(username);
|
||||
tr.find('td.displayName > span').text(displayname);
|
||||
|
||||
// make them look like the multiselect buttons
|
||||
// until they get time to really get initialized
|
||||
groupsSelect = $('<select multiple="multiple" class="groupsselect multiselect button" data-placehoder="Groups" title="' + t('settings', 'Groups') + '"></select>')
|
||||
.attr('data-username', username)
|
||||
.data('user-groups', groups);
|
||||
if (tr.find('td.subadmins').length > 0) {
|
||||
subadminSelect = $('<select multiple="multiple" class="subadminsselect multiselect button" data-placehoder="subadmins" title="' + t('settings', 'Group Admin') + '">')
|
||||
.attr('data-username', username)
|
||||
.data('user-groups', groups)
|
||||
.data('subadmin', subadmin);
|
||||
tr.find('td.subadmins').empty();
|
||||
}
|
||||
$.each(this.availableGroups, function (i, group) {
|
||||
groupsSelect.append($('<option value="' + escapeHTML(group) + '">' + escapeHTML(group) + '</option>'));
|
||||
if (typeof subadminSelect !== 'undefined' && group !== 'admin') {
|
||||
subadminSelect.append($('<option value="' + escapeHTML(group) + '">' + escapeHTML(group) + '</option>'));
|
||||
}
|
||||
});
|
||||
tr.find('td.groups').empty().append(groupsSelect);
|
||||
subadminsEl = tr.find('td.subadmins');
|
||||
if (subadminsEl.length > 0) {
|
||||
subadminsEl.append(subadminSelect);
|
||||
}
|
||||
if (tr.find('td.remove img').length === 0 && OC.currentUser !== username) {
|
||||
var rm_img = $('<img class="svg action">').attr({
|
||||
src: OC.imagePath('core', 'actions/delete')
|
||||
});
|
||||
var rm_link = $('<a class="action delete">')
|
||||
.attr({ href: '#', 'original-title': t('settings', 'Delete')})
|
||||
.append(rm_img);
|
||||
tr.find('td.remove').append(rm_link);
|
||||
} else if (OC.currentUser === username) {
|
||||
tr.find('td.remove a').remove();
|
||||
}
|
||||
var quotaSelect = tr.find('select.quota-user');
|
||||
if (quota === 'default') {
|
||||
quotaSelect.find('option').attr('selected', null);
|
||||
quotaSelect.find('option').first().attr('selected', 'selected');
|
||||
quotaSelect.data('previous', 'default');
|
||||
} else {
|
||||
if (quotaSelect.find('option[value="' + quota + '"]').length > 0) {
|
||||
quotaSelect.find('option[value="' + quota + '"]').attr('selected', 'selected');
|
||||
} else {
|
||||
quotaSelect.append('<option value="' + escapeHTML(quota) + '" selected="selected">' + escapeHTML(quota) + '</option>');
|
||||
}
|
||||
}
|
||||
$(tr).appendTo('tbody');
|
||||
|
||||
if (sort) {
|
||||
UserList.doSort();
|
||||
}
|
||||
|
||||
quotaSelect.on('change', function () {
|
||||
var uid = $(this).parent().parent().attr('data-uid');
|
||||
var quota = $(this).val();
|
||||
setQuota(uid, quota, function(returnedQuota){
|
||||
if (quota !== returnedQuota) {
|
||||
$(quotaSelect).find(':selected').text(returnedQuota);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
// defer init so the user first sees the list appear more quickly
|
||||
window.setTimeout(function(){
|
||||
quotaSelect.singleSelect();
|
||||
UserList.applyMultiplySelect(groupsSelect);
|
||||
if (subadminSelect) {
|
||||
UserList.applyMultiplySelect(subadminSelect);
|
||||
}
|
||||
}, 0);
|
||||
return tr;
|
||||
},
|
||||
// From http://my.opera.com/GreyWyvern/blog/show.dml/1671288
|
||||
alphanum: function(a, b) {
|
||||
function chunkify(t) {
|
||||
var tz = [], x = 0, y = -1, n = 0, i, j;
|
||||
|
||||
while (i = (j = t.charAt(x++)).charCodeAt(0)) {
|
||||
var m = (i === 46 || (i >=48 && i <= 57));
|
||||
if (m !== n) {
|
||||
tz[++y] = "";
|
||||
n = m;
|
||||
}
|
||||
tz[y] += j;
|
||||
}
|
||||
return tz;
|
||||
}
|
||||
|
||||
var aa = chunkify(a.toLowerCase());
|
||||
var bb = chunkify(b.toLowerCase());
|
||||
|
||||
for (x = 0; aa[x] && bb[x]; x++) {
|
||||
if (aa[x] !== bb[x]) {
|
||||
var c = Number(aa[x]), d = Number(bb[x]);
|
||||
if (c === aa[x] && d === bb[x]) {
|
||||
return c - d;
|
||||
} else {
|
||||
return (aa[x] > bb[x]) ? 1 : -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
return aa.length - bb.length;
|
||||
},
|
||||
doSort: function() {
|
||||
var self = this;
|
||||
var rows = $('tbody tr').get();
|
||||
|
||||
rows.sort(function(a, b) {
|
||||
return UserList.alphanum($(a).find('td.name').text(), $(b).find('td.name').text());
|
||||
});
|
||||
|
||||
var items = [];
|
||||
$.each(rows, function(index, row) {
|
||||
items.push(row);
|
||||
if(items.length === 100) {
|
||||
$('tbody').append(items);
|
||||
items = [];
|
||||
}
|
||||
});
|
||||
if(items.length > 0) {
|
||||
$('tbody').append(items);
|
||||
}
|
||||
},
|
||||
update: function () {
|
||||
if (UserList.updating) {
|
||||
return;
|
||||
}
|
||||
$('table+.loading').css('visibility', 'visible');
|
||||
UserList.updating = true;
|
||||
var query = $.param({ offset: UserList.offset, limit: UserList.usersToLoad });
|
||||
$.get(OC.generateUrl('/settings/ajax/userlist') + '?' + query, function (result) {
|
||||
var loadedUsers = 0;
|
||||
var trs = [];
|
||||
if (result.status === 'success') {
|
||||
//The offset does not mirror the amount of users available,
|
||||
//because it is backend-dependent. For correct retrieval,
|
||||
//always the limit(requested amount of users) needs to be added.
|
||||
$.each(result.data, function (index, user) {
|
||||
if($('tr[data-uid="' + user.name + '"]').length > 0) {
|
||||
return true;
|
||||
}
|
||||
var tr = UserList.add(user.name, user.displayname, user.groups, user.subadmin, user.quota, false);
|
||||
tr.addClass('appear transparent');
|
||||
trs.push(tr);
|
||||
loadedUsers++;
|
||||
});
|
||||
if (result.data.length > 0) {
|
||||
UserList.doSort();
|
||||
$('table+.loading').css('visibility', 'hidden');
|
||||
}
|
||||
else {
|
||||
UserList.noMoreEntries = true;
|
||||
$('table+.loading').remove();
|
||||
}
|
||||
UserList.offset += loadedUsers;
|
||||
// animate
|
||||
setTimeout(function() {
|
||||
for (var i = 0; i < trs.length; i++) {
|
||||
trs[i].removeClass('transparent');
|
||||
}
|
||||
}, 0);
|
||||
}
|
||||
UserList.updating = false;
|
||||
});
|
||||
},
|
||||
|
||||
applyMultiplySelect: function (element) {
|
||||
var checked = [];
|
||||
var user = element.attr('data-username');
|
||||
if ($(element).hasClass('groupsselect')) {
|
||||
if (element.data('userGroups')) {
|
||||
checked = element.data('userGroups');
|
||||
}
|
||||
if (user) {
|
||||
var checkHandeler = function (group) {
|
||||
if (user === OC.currentUser && group === 'admin') {
|
||||
return false;
|
||||
}
|
||||
if (!oc_isadmin && checked.length === 1 && checked[0] === group) {
|
||||
return false;
|
||||
}
|
||||
$.post(
|
||||
OC.filePath('settings', 'ajax', 'togglegroups.php'),
|
||||
{
|
||||
username: user,
|
||||
group: group
|
||||
},
|
||||
function (response) {
|
||||
if(response.status === 'success'
|
||||
&& UserList.availableGroups.indexOf(response.data.groupname) === -1
|
||||
&& response.data.action === 'add') {
|
||||
UserList.availableGroups.push(response.data.groupname);
|
||||
}
|
||||
if(response.data.message) {
|
||||
OC.Notification.show(response.data.message);
|
||||
}
|
||||
}
|
||||
);
|
||||
};
|
||||
} else {
|
||||
checkHandeler = false;
|
||||
}
|
||||
var addGroup = function (select, group) {
|
||||
$('select[multiple]').each(function (index, element) {
|
||||
if ($(element).find('option[value="' + group + '"]').length === 0 && select.data('msid') !== $(element).data('msid')) {
|
||||
$(element).append('<option value="' + escapeHTML(group) + '">' + escapeHTML(group) + '</option>');
|
||||
}
|
||||
});
|
||||
};
|
||||
var label;
|
||||
if (oc_isadmin) {
|
||||
label = t('settings', 'add group');
|
||||
} else {
|
||||
label = null;
|
||||
}
|
||||
element.multiSelect({
|
||||
createCallback: addGroup,
|
||||
createText: label,
|
||||
selectedFirst: true,
|
||||
checked: checked,
|
||||
oncheck: checkHandeler,
|
||||
onuncheck: checkHandeler,
|
||||
minWidth: 100
|
||||
});
|
||||
}
|
||||
if ($(element).hasClass('subadminsselect')) {
|
||||
if (element.data('subadmin')) {
|
||||
checked = element.data('subadmin');
|
||||
}
|
||||
var checkHandeler = function (group) {
|
||||
if (group === 'admin') {
|
||||
return false;
|
||||
}
|
||||
$.post(
|
||||
OC.filePath('settings', 'ajax', 'togglesubadmins.php'),
|
||||
{
|
||||
username: user,
|
||||
group: group
|
||||
},
|
||||
function () {
|
||||
}
|
||||
);
|
||||
};
|
||||
|
||||
var addSubAdmin = function (group) {
|
||||
$('select[multiple]').each(function (index, element) {
|
||||
if ($(element).find('option[value="' + group + '"]').length === 0) {
|
||||
$(element).append('<option value="' + escapeHTML(group) + '">' + escapeHTML(group) + '</option>');
|
||||
}
|
||||
});
|
||||
};
|
||||
element.multiSelect({
|
||||
createCallback: addSubAdmin,
|
||||
createText: null,
|
||||
checked: checked,
|
||||
oncheck: checkHandeler,
|
||||
onuncheck: checkHandeler,
|
||||
minWidth: 100
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
_onScroll: function(e) {
|
||||
if (!!UserList.noMoreEntries) {
|
||||
return;
|
||||
}
|
||||
if ($(window).scrollTop() + $(window).height() > $(document).height() - 500) {
|
||||
UserList.update(true);
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
$(document).ready(function () {
|
||||
|
||||
UserList.doSort();
|
||||
UserList.availableGroups = $('#content table').data('groups');
|
||||
$(window).scroll(function(e) {UserList._onScroll(e);});
|
||||
$('table').after($('<div class="loading" style="height: 200px; visibility: hidden;"></div>'));
|
||||
|
||||
$('select[multiple]').each(function (index, element) {
|
||||
UserList.applyMultiplySelect($(element));
|
||||
});
|
||||
|
||||
$('table').on('click', 'td.remove>a', function (event) {
|
||||
var row = $(this).parent().parent();
|
||||
var uid = $(row).attr('data-uid');
|
||||
$(row).hide();
|
||||
// Call function for handling delete/undo
|
||||
UserList.do_delete(uid);
|
||||
});
|
||||
|
||||
$('table').on('click', 'td.password>img', function (event) {
|
||||
event.stopPropagation();
|
||||
var img = $(this);
|
||||
var uid = img.parent().parent().attr('data-uid');
|
||||
var input = $('<input type="password">');
|
||||
img.css('display', 'none');
|
||||
img.parent().children('span').replaceWith(input);
|
||||
input.focus();
|
||||
input.keypress(function (event) {
|
||||
if (event.keyCode === 13) {
|
||||
if ($(this).val().length > 0) {
|
||||
var recoveryPasswordVal = $('input:password[id="recoveryPassword"]').val();
|
||||
$.post(
|
||||
OC.generateUrl('/settings/users/changepassword'),
|
||||
{username: uid, password: $(this).val(), recoveryPassword: recoveryPasswordVal},
|
||||
function (result) {
|
||||
if (result.status != 'success') {
|
||||
OC.Notification.show(t('admin', result.data.message));
|
||||
}
|
||||
}
|
||||
);
|
||||
input.blur();
|
||||
} else {
|
||||
input.blur();
|
||||
}
|
||||
}
|
||||
});
|
||||
input.blur(function () {
|
||||
$(this).replaceWith($('<span>●●●●●●●</span>'));
|
||||
img.css('display', '');
|
||||
});
|
||||
});
|
||||
$('input:password[id="recoveryPassword"]').keyup(function(event) {
|
||||
OC.Notification.hide();
|
||||
});
|
||||
|
||||
$('table').on('click', 'td.password', function (event) {
|
||||
$(this).children('img').click();
|
||||
});
|
||||
|
||||
$('table').on('click', 'td.displayName>img', function (event) {
|
||||
event.stopPropagation();
|
||||
var img = $(this);
|
||||
var uid = img.parent().parent().attr('data-uid');
|
||||
var displayName = escapeHTML(img.parent().parent().attr('data-displayName'));
|
||||
var input = $('<input type="text" value="' + displayName + '">');
|
||||
img.css('display', 'none');
|
||||
img.parent().children('span').replaceWith(input);
|
||||
input.focus();
|
||||
input.keypress(function (event) {
|
||||
if (event.keyCode === 13) {
|
||||
if ($(this).val().length > 0) {
|
||||
$.post(
|
||||
OC.filePath('settings', 'ajax', 'changedisplayname.php'),
|
||||
{username: uid, displayName: $(this).val()},
|
||||
function (result) {
|
||||
if (result && result.status==='success'){
|
||||
img.parent().parent().find('div.avatardiv').avatar(result.data.username, 32);
|
||||
}
|
||||
}
|
||||
);
|
||||
input.blur();
|
||||
} else {
|
||||
input.blur();
|
||||
}
|
||||
}
|
||||
});
|
||||
input.blur(function () {
|
||||
var input = $(this),
|
||||
displayName = input.val();
|
||||
input.closest('tr').attr('data-displayName', displayName);
|
||||
input.replaceWith('<span>' + escapeHTML(displayName) + '</span>');
|
||||
img.css('display', '');
|
||||
});
|
||||
});
|
||||
$('table').on('click', 'td.displayName', function (event) {
|
||||
$(this).children('img').click();
|
||||
});
|
||||
|
||||
$('select.quota, select.quota-user').singleSelect().on('change', function () {
|
||||
var select = $(this);
|
||||
var uid = $(this).parent().parent().attr('data-uid');
|
||||
var quota = $(this).val();
|
||||
setQuota(uid, quota, function(returnedQuota){
|
||||
if (quota !== returnedQuota) {
|
||||
select.find(':selected').text(returnedQuota);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
$('#newuser').submit(function (event) {
|
||||
event.preventDefault();
|
||||
var username = $('#newusername').val();
|
||||
var password = $('#newuserpassword').val();
|
||||
if ($.trim(username) === '') {
|
||||
OC.dialogs.alert(
|
||||
t('settings', 'A valid username must be provided'),
|
||||
t('settings', 'Error creating user'));
|
||||
return false;
|
||||
}
|
||||
if ($.trim(password) === '') {
|
||||
OC.dialogs.alert(
|
||||
t('settings', 'A valid password must be provided'),
|
||||
t('settings', 'Error creating user'));
|
||||
return false;
|
||||
}
|
||||
var groups = $('#newusergroups').prev().children('div').data('settings').checked;
|
||||
$('#newuser').get(0).reset();
|
||||
$.post(
|
||||
OC.filePath('settings', 'ajax', 'createuser.php'),
|
||||
{
|
||||
username: username,
|
||||
password: password,
|
||||
groups: groups
|
||||
},
|
||||
function (result) {
|
||||
if (result.status !== 'success') {
|
||||
OC.dialogs.alert(result.data.message,
|
||||
t('settings', 'Error creating user'));
|
||||
} else {
|
||||
if (result.data.groups) {
|
||||
var addedGroups = result.data.groups;
|
||||
UserList.availableGroups = $.unique($.merge(UserList.availableGroups, addedGroups));
|
||||
}
|
||||
if (result.data.homeExists){
|
||||
OC.Notification.hide();
|
||||
OC.Notification.show(t('settings', 'Warning: Home directory for user "{user}" already exists', {user: result.data.username}));
|
||||
if (UserList.notificationTimeout){
|
||||
window.clearTimeout(UserList.notificationTimeout);
|
||||
}
|
||||
UserList.notificationTimeout = window.setTimeout(
|
||||
function(){
|
||||
OC.Notification.hide();
|
||||
UserList.notificationTimeout = null;
|
||||
}, 10000);
|
||||
}
|
||||
if($('tr[data-uid="' + username + '"]').length === 0) {
|
||||
UserList.add(username, username, result.data.groups, null, 'default', true);
|
||||
}
|
||||
}
|
||||
}
|
||||
);
|
||||
});
|
||||
// Handle undo notifications
|
||||
OC.Notification.hide();
|
||||
$('#notification').on('click', '.undo', function () {
|
||||
if ($('#notification').data('deleteuser')) {
|
||||
$('tbody tr').filterAttr('data-uid', UserList.deleteUid).show();
|
||||
UserList.deleteCanceled = true;
|
||||
}
|
||||
OC.Notification.hide();
|
||||
});
|
||||
UserList.useUndo = ('onbeforeunload' in window);
|
||||
$(window).bind('beforeunload', function () {
|
||||
UserList.finishDelete(null);
|
||||
});
|
||||
});
|
|
@ -0,0 +1,171 @@
|
|||
/**
|
||||
* Copyright (c) 2014, Arthur Schiwon <blizzz@owncloud.com>
|
||||
* This file is licensed under the Affero General Public License version 3 or later.
|
||||
* See the COPYING-README file.
|
||||
*/
|
||||
|
||||
/**
|
||||
* takes care of deleting things represented by an ID
|
||||
*
|
||||
* @class
|
||||
* @param {string} endpoint the corresponding ajax PHP script. Currently limited
|
||||
* to settings - ajax path.
|
||||
* @param {string} paramID the by the script expected parameter name holding the
|
||||
* ID of the object to delete
|
||||
* @param {markCallback} markCallback function to be called after successfully
|
||||
* marking the object for deletion.
|
||||
* @param {removeCallback} removeCallback the function to be called after
|
||||
* successful delete.
|
||||
*/
|
||||
function DeleteHandler(endpoint, paramID, markCallback, removeCallback) {
|
||||
this.oidToDelete = false;
|
||||
this.canceled = false;
|
||||
|
||||
this.ajaxEndpoint = endpoint;
|
||||
this.ajaxParamID = paramID;
|
||||
|
||||
this.markCallback = markCallback;
|
||||
this.removeCallback = removeCallback;
|
||||
this.undoCallback = false;
|
||||
|
||||
this.notifier = false;
|
||||
this.notificationDataID = false;
|
||||
this.notificationMessage = false;
|
||||
this.notificationPlaceholder = '%oid';
|
||||
}
|
||||
|
||||
/**
|
||||
* The function to be called after successfully marking the object for deletion
|
||||
* @callback markCallback
|
||||
* @param {string} oid the ID of the specific user or group
|
||||
*/
|
||||
|
||||
/**
|
||||
* The function to be called after successful delete. The id of the object will
|
||||
* be passed as argument. Unsuccessful operations will display an error using
|
||||
* OC.dialogs, no callback is fired.
|
||||
* @callback removeCallback
|
||||
* @param {string} oid the ID of the specific user or group
|
||||
*/
|
||||
|
||||
/**
|
||||
* This callback is fired after "undo" was clicked so the consumer can update
|
||||
* the web interface
|
||||
* @callback undoCallback
|
||||
* @param {string} oid the ID of the specific user or group
|
||||
*/
|
||||
|
||||
/**
|
||||
* enabled the notification system. Required for undo UI.
|
||||
*
|
||||
* @param {object} notifier Usually OC.Notification
|
||||
* @param {string} dataID an identifier for the notifier, e.g. 'deleteuser'
|
||||
* @param {string} message the message that should be shown upon delete. %oid
|
||||
* will be replaced with the affected id of the item to be deleted
|
||||
* @param {undoCallback} undoCallback called after "undo" was clicked
|
||||
*/
|
||||
DeleteHandler.prototype.setNotification = function(notifier, dataID, message, undoCallback) {
|
||||
this.notifier = notifier;
|
||||
this.notificationDataID = dataID;
|
||||
this.notificationMessage = message;
|
||||
this.undoCallback = undoCallback;
|
||||
|
||||
var dh = this;
|
||||
|
||||
$('#notification').on('click', '.undo', function () {
|
||||
if ($('#notification').data(dh.notificationDataID)) {
|
||||
var oid = dh.oidToDelete;
|
||||
dh.cancel();
|
||||
if(typeof dh.undoCallback !== 'undefined') {
|
||||
dh.undoCallback(oid);
|
||||
}
|
||||
}
|
||||
dh.notifier.hide();
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* shows the Undo Notification (if configured)
|
||||
*/
|
||||
DeleteHandler.prototype.showNotification = function() {
|
||||
if(this.notifier !== false) {
|
||||
if(!this.notifier.isHidden()) {
|
||||
this.hideNotification();
|
||||
}
|
||||
$('#notification').data(this.notificationDataID, true);
|
||||
var msg = this.notificationMessage.replace(this.notificationPlaceholder,
|
||||
this.oidToDelete);
|
||||
this.notifier.showHtml(msg);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* hides the Undo Notification
|
||||
*/
|
||||
DeleteHandler.prototype.hideNotification = function() {
|
||||
if(this.notifier !== false) {
|
||||
$('#notification').removeData(this.notificationDataID);
|
||||
this.notifier.hide();
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* initializes the delete operation for a given object id
|
||||
*
|
||||
* @param {string} oid the object id
|
||||
*/
|
||||
DeleteHandler.prototype.mark = function(oid) {
|
||||
if(this.oidToDelete !== false) {
|
||||
this.delete();
|
||||
}
|
||||
this.oidToDelete = oid;
|
||||
this.canceled = false;
|
||||
this.markCallback(oid);
|
||||
this.showNotification();
|
||||
};
|
||||
|
||||
/**
|
||||
* cancels a delete operation
|
||||
*/
|
||||
DeleteHandler.prototype.cancel = function() {
|
||||
this.canceled = true;
|
||||
this.oidToDelete = false;
|
||||
};
|
||||
|
||||
/**
|
||||
* executes a delete operation. Requires that the operation has been
|
||||
* initialized by mark(). On error, it will show a message via
|
||||
* OC.dialogs.alert. On success, a callback is fired so that the client can
|
||||
* update the web interface accordingly.
|
||||
*/
|
||||
DeleteHandler.prototype.delete = function() {
|
||||
if(this.canceled || this.oidToDelete === false) {
|
||||
return false;
|
||||
}
|
||||
|
||||
var dh = this;
|
||||
if($('#notification').data(this.notificationDataID) === true) {
|
||||
dh.hideNotification();
|
||||
}
|
||||
|
||||
var payload = {};
|
||||
payload[dh.ajaxParamID] = dh.oidToDelete;
|
||||
$.ajax({
|
||||
type: 'POST',
|
||||
url: OC.filePath('settings', 'ajax', dh.ajaxEndpoint),
|
||||
async: false,
|
||||
data: payload,
|
||||
success: function (result) {
|
||||
if (result.status === 'success') {
|
||||
// Remove undo option, & remove user from table
|
||||
|
||||
//TODO: following line
|
||||
dh.removeCallback(dh.oidToDelete);
|
||||
dh.canceled = true;
|
||||
} else {
|
||||
OC.dialogs.alert(result.data.message, t('settings', 'Unable to delete ' + escapeHTML(dh.oidToDelete)));
|
||||
dh.undoCallback(dh.oidToDelete);
|
||||
}
|
||||
}
|
||||
});
|
||||
};
|
|
@ -0,0 +1,82 @@
|
|||
/**
|
||||
* Copyright (c) 2014, Arthur Schiwon <blizzz@owncloud.com>
|
||||
* This file is licensed under the Affero General Public License version 3 or later.
|
||||
* See the COPYING-README file.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief this object takes care of the filter functionality on the user
|
||||
* management page
|
||||
* @param jQuery input element that works as the user text input field
|
||||
* @param object the UserList object
|
||||
*/
|
||||
function UserManagementFilter(filterInput, userList, groupList) {
|
||||
this.filterInput = filterInput;
|
||||
this.userList = userList;
|
||||
this.groupList = groupList;
|
||||
this.thread = undefined;
|
||||
this.oldval = this.filterInput.val();
|
||||
|
||||
this.init();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief sets up when the filter action shall be triggered
|
||||
*/
|
||||
UserManagementFilter.prototype.init = function() {
|
||||
var umf = this;
|
||||
this.filterInput.keyup(function(e) {
|
||||
//we want to react on any printable letter, plus on modifying stuff like
|
||||
//Backspace and Delete. extended https://stackoverflow.com/a/12467610
|
||||
var valid =
|
||||
e.keyCode === 0 || e.keyCode === 8 || // like ö or ж; backspace
|
||||
e.keyCode === 9 || e.keyCode === 46 || // tab; delete
|
||||
e.keyCode === 32 || // space
|
||||
(e.keyCode > 47 && e.keyCode < 58) || // number keys
|
||||
(e.keyCode > 64 && e.keyCode < 91) || // letter keys
|
||||
(e.keyCode > 95 && e.keyCode < 112) || // numpad keys
|
||||
(e.keyCode > 185 && e.keyCode < 193) || // ;=,-./` (in order)
|
||||
(e.keyCode > 218 && e.keyCode < 223); // [\]' (in order)
|
||||
|
||||
//besides the keys, the value must have been changed compared to last
|
||||
//time
|
||||
if(valid && umf.oldVal !== umf.getPattern()) {
|
||||
umf.run();
|
||||
}
|
||||
|
||||
umf.oldVal = umf.getPattern();
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief the filter action needs to be done, here the accurate steps are being
|
||||
* taken care of
|
||||
*/
|
||||
UserManagementFilter.prototype.run = _.debounce(function() {
|
||||
this.userList.empty();
|
||||
this.userList.update(GroupList.getCurrentGID());
|
||||
this.groupList.empty();
|
||||
this.groupList.update();
|
||||
},
|
||||
300
|
||||
);
|
||||
|
||||
/**
|
||||
* @brief returns the filter String
|
||||
* @returns string
|
||||
*/
|
||||
UserManagementFilter.prototype.getPattern = function() {
|
||||
return this.filterInput.val();
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief adds reset functionality to an HTML element
|
||||
* @param jQuery the jQuery representation of that element
|
||||
*/
|
||||
UserManagementFilter.prototype.addResetButton = function(button) {
|
||||
var umf = this;
|
||||
button.click(function(){
|
||||
umf.filterInput.val('');
|
||||
umf.run();
|
||||
});
|
||||
};
|
|
@ -0,0 +1,292 @@
|
|||
/**
|
||||
* Copyright (c) 2014, Raghu Nayyar <beingminimal@gmail.com>
|
||||
* Copyright (c) 2014, Arthur Schiwon <blizzz@owncloud.com>
|
||||
* This file is licensed under the Affero General Public License version 3 or later.
|
||||
* See the COPYING-README file.
|
||||
*/
|
||||
|
||||
var $userGroupList;
|
||||
|
||||
var GroupList;
|
||||
GroupList = {
|
||||
activeGID: '',
|
||||
|
||||
addGroup: function (gid, usercount) {
|
||||
var $li = $userGroupList.find('.isgroup:last-child').clone();
|
||||
$li
|
||||
.data('gid', gid)
|
||||
.find('.groupname').text(gid);
|
||||
GroupList.setUserCount($li, usercount);
|
||||
|
||||
$li.appendTo($userGroupList);
|
||||
|
||||
GroupList.sortGroups();
|
||||
|
||||
return $li;
|
||||
},
|
||||
|
||||
setUserCount: function (groupLiElement, usercount) {
|
||||
var $groupLiElement = $(groupLiElement);
|
||||
if (usercount === undefined || usercount === 0) {
|
||||
usercount = '';
|
||||
}
|
||||
$groupLiElement.data('usercount', usercount);
|
||||
$groupLiElement.find('.usercount').text(usercount);
|
||||
},
|
||||
|
||||
getCurrentGID: function () {
|
||||
return GroupList.activeGID;
|
||||
},
|
||||
|
||||
sortGroups: function () {
|
||||
var lis = $('.isgroup').get();
|
||||
|
||||
lis.sort(function (a, b) {
|
||||
return UserList.alphanum(
|
||||
$(a).find('a span').text(),
|
||||
$(b).find('a span').text()
|
||||
);
|
||||
});
|
||||
|
||||
var items = [];
|
||||
$.each(lis, function (index, li) {
|
||||
items.push(li);
|
||||
if (items.length === 100) {
|
||||
$userGroupList.append(items);
|
||||
items = [];
|
||||
}
|
||||
});
|
||||
if (items.length > 0) {
|
||||
$userGroupList.append(items);
|
||||
}
|
||||
},
|
||||
|
||||
createGroup: function (groupname) {
|
||||
$.post(
|
||||
OC.filePath('settings', 'ajax', 'creategroup.php'),
|
||||
{
|
||||
groupname: groupname
|
||||
},
|
||||
function (result) {
|
||||
if (result.status !== 'success') {
|
||||
OC.dialogs.alert(result.data.message,
|
||||
t('settings', 'Error creating group'));
|
||||
}
|
||||
else {
|
||||
if (result.data.groupname) {
|
||||
var addedGroup = result.data.groupname;
|
||||
UserList.availableGroups = $.unique($.merge(UserList.availableGroups, [addedGroup]));
|
||||
GroupList.addGroup(result.data.groupname);
|
||||
|
||||
$('.groupsselect, .subadminsselect')
|
||||
.append($('<option>', { value: result.data.groupname })
|
||||
.text(result.data.groupname));
|
||||
}
|
||||
GroupList.toggleAddGroup();
|
||||
}
|
||||
}
|
||||
);
|
||||
},
|
||||
|
||||
update: function () {
|
||||
if (GroupList.updating) {
|
||||
return;
|
||||
}
|
||||
GroupList.updating = true;
|
||||
$.get(
|
||||
OC.generateUrl('/settings/ajax/grouplist'),
|
||||
{pattern: filter.getPattern()},
|
||||
function (result) {
|
||||
|
||||
var lis = [];
|
||||
if (result.status === 'success') {
|
||||
$.each(result.data, function (i, subset) {
|
||||
$.each(subset, function (index, group) {
|
||||
if (GroupList.getGroupLI(group.name).length > 0) {
|
||||
GroupList.setUserCount(GroupList.getGroupLI(group.name).first(), group.usercount);
|
||||
}
|
||||
else {
|
||||
var $li = GroupList.addGroup(group.name, group.usercount);
|
||||
|
||||
$li.addClass('appear transparent');
|
||||
lis.push($li);
|
||||
}
|
||||
});
|
||||
});
|
||||
if (result.data.length > 0) {
|
||||
GroupList.doSort();
|
||||
}
|
||||
else {
|
||||
GroupList.noMoreEntries = true;
|
||||
}
|
||||
_.defer(function () {
|
||||
$(lis).each(function () {
|
||||
this.removeClass('transparent')
|
||||
});
|
||||
});
|
||||
}
|
||||
GroupList.updating = false;
|
||||
|
||||
}
|
||||
);
|
||||
},
|
||||
|
||||
elementBelongsToAddGroup: function (el) {
|
||||
return !(el !== $('#newgroup-form').get(0) &&
|
||||
$('#newgroup-form').find($(el)).length === 0);
|
||||
},
|
||||
|
||||
hasAddGroupNameText: function () {
|
||||
var name = $('#newgroupname').val();
|
||||
return $.trim(name) !== '';
|
||||
|
||||
},
|
||||
|
||||
showGroup: function (gid) {
|
||||
GroupList.activeGID = gid;
|
||||
UserList.empty();
|
||||
UserList.update(gid);
|
||||
$userGroupList.find('li').removeClass('active');
|
||||
if (gid !== undefined) {
|
||||
//TODO: treat Everyone properly
|
||||
GroupList.getGroupLI(gid).addClass('active');
|
||||
}
|
||||
},
|
||||
|
||||
isAddGroupButtonVisible: function () {
|
||||
return $('#newgroup-init').is(":visible");
|
||||
},
|
||||
|
||||
toggleAddGroup: function (event) {
|
||||
if (GroupList.isAddGroupButtonVisible()) {
|
||||
event.stopPropagation();
|
||||
$('#newgroup-form').show();
|
||||
$('#newgroup-init').hide();
|
||||
$('#newgroupname').focus();
|
||||
}
|
||||
else {
|
||||
$('#newgroup-form').hide();
|
||||
$('#newgroup-init').show();
|
||||
$('#newgroupname').val('');
|
||||
}
|
||||
},
|
||||
|
||||
isGroupNameValid: function (groupname) {
|
||||
if ($.trim(groupname) === '') {
|
||||
OC.dialogs.alert(
|
||||
t('settings', 'A valid group name must be provided'),
|
||||
t('settings', 'Error creating group'));
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
},
|
||||
|
||||
hide: function (gid) {
|
||||
GroupList.getGroupLI(gid).hide();
|
||||
},
|
||||
show: function (gid) {
|
||||
GroupList.getGroupLI(gid).show();
|
||||
},
|
||||
remove: function (gid) {
|
||||
GroupList.getGroupLI(gid).remove();
|
||||
},
|
||||
empty: function () {
|
||||
$userGroupList.find('.isgroup').filter(function(index, item){
|
||||
return $(item).data('gid') !== '';
|
||||
}).remove();
|
||||
},
|
||||
initDeleteHandling: function () {
|
||||
//set up handler
|
||||
GroupDeleteHandler = new DeleteHandler('removegroup.php', 'groupname',
|
||||
GroupList.hide, GroupList.remove);
|
||||
|
||||
//configure undo
|
||||
OC.Notification.hide();
|
||||
var msg = t('settings', 'deleted') + ' %oid <span class="undo">' +
|
||||
t('settings', 'undo') + '</span>';
|
||||
GroupDeleteHandler.setNotification(OC.Notification, 'deletegroup', msg,
|
||||
GroupList.show);
|
||||
|
||||
//when to mark user for delete
|
||||
$userGroupList.on('click', '.delete', function () {
|
||||
// Call function for handling delete/undo
|
||||
GroupDeleteHandler.mark(GroupList.getElementGID(this));
|
||||
});
|
||||
|
||||
//delete a marked user when leaving the page
|
||||
$(window).on('beforeunload', function () {
|
||||
GroupDeleteHandler.delete();
|
||||
});
|
||||
},
|
||||
|
||||
getGroupLI: function (gid) {
|
||||
return $userGroupList.find('li.isgroup').filter(function () {
|
||||
return GroupList.getElementGID(this) === gid;
|
||||
});
|
||||
},
|
||||
|
||||
getElementGID: function (element) {
|
||||
return ($(element).closest('li').data('gid') || '').toString();
|
||||
}
|
||||
};
|
||||
|
||||
$(document).ready( function () {
|
||||
$userGroupList = $('#usergrouplist');
|
||||
GroupList.initDeleteHandling();
|
||||
|
||||
// Display or hide of Create Group List Element
|
||||
$('#newgroup-form').hide();
|
||||
$('#newgroup-init').on('click', function (e) {
|
||||
GroupList.toggleAddGroup(e);
|
||||
});
|
||||
|
||||
$(document).on('click keydown keyup', function(event) {
|
||||
if(!GroupList.isAddGroupButtonVisible() &&
|
||||
!GroupList.elementBelongsToAddGroup(event.target) &&
|
||||
!GroupList.hasAddGroupNameText()) {
|
||||
GroupList.toggleAddGroup();
|
||||
}
|
||||
// Escape
|
||||
if(!GroupList.isAddGroupButtonVisible() && event.keyCode && event.keyCode === 27) {
|
||||
GroupList.toggleAddGroup();
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
// Responsible for Creating Groups.
|
||||
$('#newgroup-form form').submit(function (event) {
|
||||
event.preventDefault();
|
||||
if(GroupList.isGroupNameValid($('#newgroupname').val())) {
|
||||
GroupList.createGroup($('#newgroupname').val());
|
||||
}
|
||||
});
|
||||
|
||||
// click on group name
|
||||
$userGroupList.on('click', '.isgroup', function () {
|
||||
GroupList.showGroup(GroupList.getElementGID(this));
|
||||
});
|
||||
|
||||
// Implements Quota Settings Toggle.
|
||||
var $appSettings = $('#app-settings');
|
||||
$('#app-settings-header').on('click keydown',function(event) {
|
||||
if(wrongKey(event)) {
|
||||
return;
|
||||
}
|
||||
if($appSettings.hasClass('open')) {
|
||||
$appSettings.switchClass('open', '');
|
||||
} else {
|
||||
$appSettings.switchClass('', 'open');
|
||||
}
|
||||
});
|
||||
$('body').on('click', function(event){
|
||||
if($appSettings.find(event.target).length === 0) {
|
||||
$appSettings.switchClass('open', '');
|
||||
}
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
var wrongKey = function(event) {
|
||||
return ((event.type === 'keydown' || event.type === 'keypress') &&
|
||||
(event.keyCode !== 32 && event.keyCode !== 13));
|
||||
};
|
|
@ -0,0 +1,616 @@
|
|||
/**
|
||||
* Copyright (c) 2014, Arthur Schiwon <blizzz@owncloud.com>
|
||||
* Copyright (c) 2014, Raghu Nayyar <beingminimal@gmail.com>
|
||||
* Copyright (c) 2011, Robin Appelman <icewind1991@gmail.com>
|
||||
* This file is licensed under the Affero General Public License version 3 or later.
|
||||
* See the COPYING-README file.
|
||||
*/
|
||||
|
||||
var $userList;
|
||||
var $userListBody;
|
||||
var filter;
|
||||
|
||||
var UserList = {
|
||||
availableGroups: [],
|
||||
offset: 30, //The first 30 users are there. No prob, if less in total.
|
||||
//hardcoded in settings/users.php
|
||||
|
||||
usersToLoad: 10, //So many users will be loaded when user scrolls down
|
||||
currentGid: '',
|
||||
|
||||
add: function (username, displayname, groups, subadmin, quota, storageLocation, lastLogin, sort) {
|
||||
var $tr = $userListBody.find('tr:first-child').clone();
|
||||
var subadminsEl;
|
||||
var subadminSelect;
|
||||
var groupsSelect;
|
||||
if ($tr.find('div.avatardiv').length){
|
||||
$tr.find('.avatardiv').imageplaceholder(username, displayname);
|
||||
$('div.avatardiv', $tr).avatar(username, 32);
|
||||
}
|
||||
$tr.data('uid', username);
|
||||
$tr.data('displayname', displayname);
|
||||
$tr.find('td.name').text(username);
|
||||
$tr.find('td.displayName > span').text(displayname);
|
||||
|
||||
// make them look like the multiselect buttons
|
||||
// until they get time to really get initialized
|
||||
groupsSelect = $('<select multiple="multiple" class="groupsselect multiselect button" data-placehoder="Groups" title="' + t('settings', 'Groups') + '"></select>')
|
||||
.data('username', username)
|
||||
.data('user-groups', groups);
|
||||
if ($tr.find('td.subadmins').length > 0) {
|
||||
subadminSelect = $('<select multiple="multiple" class="subadminsselect multiselect button" data-placehoder="subadmins" title="' + t('settings', 'Group Admin') + '">')
|
||||
.data('username', username)
|
||||
.data('user-groups', groups)
|
||||
.data('subadmin', subadmin);
|
||||
$tr.find('td.subadmins').empty();
|
||||
}
|
||||
$.each(this.availableGroups, function (i, group) {
|
||||
groupsSelect.append($('<option value="' + escapeHTML(group) + '">' + escapeHTML(group) + '</option>'));
|
||||
if (typeof subadminSelect !== 'undefined' && group !== 'admin') {
|
||||
subadminSelect.append($('<option value="' + escapeHTML(group) + '">' + escapeHTML(group) + '</option>'));
|
||||
}
|
||||
});
|
||||
$tr.find('td.groups').empty().append(groupsSelect);
|
||||
subadminsEl = $tr.find('td.subadmins');
|
||||
if (subadminsEl.length > 0) {
|
||||
subadminsEl.append(subadminSelect);
|
||||
}
|
||||
if ($tr.find('td.remove img').length === 0 && OC.currentUser !== username) {
|
||||
var deleteImage = $('<img class="svg action">').attr({
|
||||
src: OC.imagePath('core', 'actions/delete')
|
||||
});
|
||||
var deleteLink = $('<a class="action delete">')
|
||||
.attr({ href: '#', 'original-title': t('settings', 'Delete')})
|
||||
.append(deleteImage);
|
||||
$tr.find('td.remove').append(deleteLink);
|
||||
} else if (OC.currentUser === username) {
|
||||
$tr.find('td.remove a').remove();
|
||||
}
|
||||
var $quotaSelect = $tr.find('.quota-user');
|
||||
if (quota === 'default') {
|
||||
$quotaSelect
|
||||
.data('previous', 'default')
|
||||
.find('option').attr('selected', null)
|
||||
.first().attr('selected', 'selected');
|
||||
} else {
|
||||
if ($quotaSelect.find('option[value="' + quota + '"]').length > 0) {
|
||||
$quotaSelect.find('option[value="' + quota + '"]').attr('selected', 'selected');
|
||||
} else {
|
||||
$quotaSelect.append('<option value="' + escapeHTML(quota) + '" selected="selected">' + escapeHTML(quota) + '</option>');
|
||||
}
|
||||
}
|
||||
$tr.find('td.storageLocation').text(storageLocation);
|
||||
if(lastLogin === 0) {
|
||||
lastLogin = t('settings', 'never');
|
||||
} else {
|
||||
lastLogin = new Date(lastLogin * 1000);
|
||||
lastLogin = relative_modified_date(lastLogin.getTime() / 1000);
|
||||
}
|
||||
$tr.find('td.lastLogin').text(lastLogin);
|
||||
$tr.appendTo($userList);
|
||||
if(UserList.isEmpty === true) {
|
||||
//when the list was emptied, one row was left, necessary to keep
|
||||
//add working and the layout unbroken. We need to remove this item
|
||||
$tr.show();
|
||||
$userListBody.find('tr:first').remove();
|
||||
UserList.isEmpty = false;
|
||||
UserList.checkUsersToLoad();
|
||||
}
|
||||
if (sort) {
|
||||
UserList.doSort();
|
||||
}
|
||||
|
||||
$quotaSelect.on('change', function () {
|
||||
var uid = UserList.getUID(this);
|
||||
var quota = $(this).val();
|
||||
setQuota(uid, quota, function(returnedQuota){
|
||||
if (quota !== returnedQuota) {
|
||||
$($quotaSelect).find(':selected').text(returnedQuota);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
// defer init so the user first sees the list appear more quickly
|
||||
window.setTimeout(function(){
|
||||
$quotaSelect.singleSelect();
|
||||
UserList.applyGroupSelect(groupsSelect);
|
||||
if (subadminSelect) {
|
||||
UserList.applySubadminSelect(subadminSelect);
|
||||
}
|
||||
}, 0);
|
||||
return $tr;
|
||||
},
|
||||
// From http://my.opera.com/GreyWyvern/blog/show.dml/1671288
|
||||
alphanum: function(a, b) {
|
||||
function chunkify(t) {
|
||||
var tz = [], x = 0, y = -1, n = 0, i, j;
|
||||
|
||||
while (i = (j = t.charAt(x++)).charCodeAt(0)) {
|
||||
var m = (i === 46 || (i >=48 && i <= 57));
|
||||
if (m !== n) {
|
||||
tz[++y] = "";
|
||||
n = m;
|
||||
}
|
||||
tz[y] += j;
|
||||
}
|
||||
return tz;
|
||||
}
|
||||
|
||||
var aa = chunkify(a.toLowerCase());
|
||||
var bb = chunkify(b.toLowerCase());
|
||||
|
||||
for (var x = 0; aa[x] && bb[x]; x++) {
|
||||
if (aa[x] !== bb[x]) {
|
||||
var c = Number(aa[x]), d = Number(bb[x]);
|
||||
if (c === aa[x] && d === bb[x]) {
|
||||
return c - d;
|
||||
} else {
|
||||
return (aa[x] > bb[x]) ? 1 : -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
return aa.length - bb.length;
|
||||
},
|
||||
preSortSearchString: function(a, b) {
|
||||
var pattern = filter.getPattern();
|
||||
if(typeof pattern === 'undefined') {
|
||||
return undefined;
|
||||
}
|
||||
pattern = pattern.toLowerCase();
|
||||
var aMatches = false;
|
||||
var bMatches = false;
|
||||
if(typeof a === 'string' && a.toLowerCase().indexOf(pattern) === 0) {
|
||||
aMatches = true;
|
||||
}
|
||||
if(typeof b === 'string' && b.toLowerCase().indexOf(pattern) === 0) {
|
||||
bMatches = true;
|
||||
}
|
||||
|
||||
if((aMatches && bMatches) || (!aMatches && !bMatches)) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
if(aMatches) {
|
||||
return -1;
|
||||
} else {
|
||||
return 1;
|
||||
}
|
||||
},
|
||||
doSort: function() {
|
||||
var rows = $userListBody.find('tr').get();
|
||||
|
||||
rows.sort(function(a, b) {
|
||||
a = $(a).find('td.name').text();
|
||||
b = $(b).find('td.name').text();
|
||||
var firstSort = UserList.preSortSearchString(a, b);
|
||||
if(typeof firstSort !== 'undefined') {
|
||||
return firstSort;
|
||||
}
|
||||
return UserList.alphanum(a, b);
|
||||
});
|
||||
|
||||
var items = [];
|
||||
$.each(rows, function(index, row) {
|
||||
items.push(row);
|
||||
if(items.length === 100) {
|
||||
$userListBody.append(items);
|
||||
items = [];
|
||||
}
|
||||
});
|
||||
if(items.length > 0) {
|
||||
$userListBody.append(items);
|
||||
}
|
||||
},
|
||||
checkUsersToLoad: function() {
|
||||
//30 shall be loaded initially, from then on always 10 upon scrolling
|
||||
if(UserList.isEmpty === false) {
|
||||
UserList.usersToLoad = 10;
|
||||
} else {
|
||||
UserList.usersToLoad = 30;
|
||||
}
|
||||
},
|
||||
empty: function() {
|
||||
//one row needs to be kept, because it is cloned to add new rows
|
||||
$userListBody.find('tr:not(:first)').remove();
|
||||
var $tr = $userListBody.find('tr:first');
|
||||
$tr.hide();
|
||||
//on an update a user may be missing when the username matches with that
|
||||
//of the hidden row. So change this to a random string.
|
||||
$tr.data('uid', Math.random().toString(36).substring(2));
|
||||
UserList.isEmpty = true;
|
||||
UserList.offset = 0;
|
||||
UserList.checkUsersToLoad();
|
||||
},
|
||||
hide: function(uid) {
|
||||
UserList.getRow(uid).hide();
|
||||
},
|
||||
show: function(uid) {
|
||||
UserList.getRow(uid).show();
|
||||
},
|
||||
remove: function(uid) {
|
||||
UserList.getRow(uid).remove();
|
||||
},
|
||||
has: function(uid) {
|
||||
return UserList.getRow(uid).length > 0;
|
||||
},
|
||||
getRow: function(uid) {
|
||||
return $userListBody.find('tr').filter(function(){
|
||||
return UserList.getUID(this) === uid;
|
||||
});
|
||||
},
|
||||
getUID: function(element) {
|
||||
return ($(element).closest('tr').data('uid') || '').toString();
|
||||
},
|
||||
getDisplayName: function(element) {
|
||||
return ($(element).closest('tr').data('displayname') || '').toString();
|
||||
},
|
||||
initDeleteHandling: function() {
|
||||
//set up handler
|
||||
UserDeleteHandler = new DeleteHandler('removeuser.php', 'username',
|
||||
UserList.hide, UserList.remove);
|
||||
|
||||
//configure undo
|
||||
OC.Notification.hide();
|
||||
var msg = t('settings', 'deleted') + ' %oid <span class="undo">' +
|
||||
t('settings', 'undo') + '</span>';
|
||||
UserDeleteHandler.setNotification(OC.Notification, 'deleteuser', msg,
|
||||
UserList.show);
|
||||
|
||||
//when to mark user for delete
|
||||
$userListBody.on('click', '.delete', function () {
|
||||
// Call function for handling delete/undo
|
||||
var uid = UserList.getUID(this);
|
||||
UserDeleteHandler.mark(uid);
|
||||
});
|
||||
|
||||
//delete a marked user when leaving the page
|
||||
$(window).on('beforeunload', function () {
|
||||
UserDeleteHandler.delete();
|
||||
});
|
||||
},
|
||||
update: function (gid) {
|
||||
if (UserList.updating) {
|
||||
return;
|
||||
}
|
||||
$userList.siblings('.loading').css('visibility', 'visible');
|
||||
UserList.updating = true;
|
||||
if(gid === undefined) {
|
||||
gid = '';
|
||||
}
|
||||
UserList.currentGid = gid;
|
||||
var pattern = filter.getPattern();
|
||||
$.get(
|
||||
OC.generateUrl('/settings/ajax/userlist'),
|
||||
{ offset: UserList.offset, limit: UserList.usersToLoad, gid: gid, pattern: pattern },
|
||||
function (result) {
|
||||
var loadedUsers = 0;
|
||||
var trs = [];
|
||||
if (result.status === 'success') {
|
||||
//The offset does not mirror the amount of users available,
|
||||
//because it is backend-dependent. For correct retrieval,
|
||||
//always the limit(requested amount of users) needs to be added.
|
||||
$.each(result.data, function (index, user) {
|
||||
if(UserList.has(user.name)) {
|
||||
return true;
|
||||
}
|
||||
var $tr = UserList.add(user.name, user.displayname, user.groups, user.subadmin, user.quota, user.storageLocation, user.lastLogin, false);
|
||||
$tr.addClass('appear transparent');
|
||||
trs.push($tr);
|
||||
loadedUsers++;
|
||||
});
|
||||
if (result.data.length > 0) {
|
||||
UserList.doSort();
|
||||
$userList.siblings('.loading').css('visibility', 'hidden');
|
||||
}
|
||||
else {
|
||||
UserList.noMoreEntries = true;
|
||||
$userList.siblings('.loading').remove();
|
||||
}
|
||||
UserList.offset += loadedUsers;
|
||||
// animate
|
||||
setTimeout(function() {
|
||||
for (var i = 0; i < trs.length; i++) {
|
||||
trs[i].removeClass('transparent');
|
||||
}
|
||||
}, 0);
|
||||
}
|
||||
UserList.updating = false;
|
||||
});
|
||||
},
|
||||
|
||||
applyGroupSelect: function (element) {
|
||||
var checked = [];
|
||||
var $element = $(element);
|
||||
var user = UserList.getUID($element);
|
||||
|
||||
if ($element.data('user-groups')) {
|
||||
checked = $element.data('user-groups');
|
||||
}
|
||||
var checkHandler = null;
|
||||
if(user) { // Only if in a user row, and not the #newusergroups select
|
||||
checkHandler = function (group) {
|
||||
if (user === OC.currentUser && group === 'admin') {
|
||||
return false;
|
||||
}
|
||||
if (!oc_isadmin && checked.length === 1 && checked[0] === group) {
|
||||
return false;
|
||||
}
|
||||
$.post(
|
||||
OC.filePath('settings', 'ajax', 'togglegroups.php'),
|
||||
{
|
||||
username: user,
|
||||
group: group
|
||||
},
|
||||
function (response) {
|
||||
if (response.status === 'success') {
|
||||
GroupList.update();
|
||||
if (UserList.availableGroups.indexOf(response.data.groupname) === -1 &&
|
||||
response.data.action === 'add'
|
||||
) {
|
||||
UserList.availableGroups.push(response.data.groupname);
|
||||
}
|
||||
}
|
||||
if (response.data.message) {
|
||||
OC.Notification.show(response.data.message);
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
};
|
||||
var addGroup = function (select, group) {
|
||||
$('select[multiple]').each(function (index, element) {
|
||||
$element = $(element);
|
||||
if ($element.find('option[value="' + group + '"]').length === 0 && select.data('msid') !== $element.data('msid')) {
|
||||
$element.append('<option value="' + escapeHTML(group) + '">' + escapeHTML(group) + '</option>');
|
||||
}
|
||||
});
|
||||
GroupList.addGroup(escapeHTML(group));
|
||||
};
|
||||
var label;
|
||||
if (oc_isadmin) {
|
||||
label = t('settings', 'add group');
|
||||
}
|
||||
else {
|
||||
label = null;
|
||||
}
|
||||
$element.multiSelect({
|
||||
createCallback: addGroup,
|
||||
createText: label,
|
||||
selectedFirst: true,
|
||||
checked: checked,
|
||||
oncheck: checkHandler,
|
||||
onuncheck: checkHandler,
|
||||
minWidth: 100
|
||||
});
|
||||
},
|
||||
|
||||
applySubadminSelect: function (element) {
|
||||
var checked = [];
|
||||
var $element = $(element);
|
||||
var user = UserList.getUID($element);
|
||||
|
||||
if ($element.data('subadmin')) {
|
||||
checked = $element.data('subadmin');
|
||||
}
|
||||
var checkHandler = function (group) {
|
||||
if (group === 'admin') {
|
||||
return false;
|
||||
}
|
||||
$.post(
|
||||
OC.filePath('settings', 'ajax', 'togglesubadmins.php'),
|
||||
{
|
||||
username: user,
|
||||
group: group
|
||||
},
|
||||
function () {
|
||||
}
|
||||
);
|
||||
};
|
||||
|
||||
var addSubAdmin = function (group) {
|
||||
$('select[multiple]').each(function (index, element) {
|
||||
if ($(element).find('option[value="' + group + '"]').length === 0) {
|
||||
$(element).append('<option value="' + escapeHTML(group) + '">' + escapeHTML(group) + '</option>');
|
||||
}
|
||||
});
|
||||
};
|
||||
$element.multiSelect({
|
||||
createCallback: addSubAdmin,
|
||||
createText: null,
|
||||
checked: checked,
|
||||
oncheck: checkHandler,
|
||||
onuncheck: checkHandler,
|
||||
minWidth: 100
|
||||
});
|
||||
},
|
||||
|
||||
_onScroll: function() {
|
||||
if (!!UserList.noMoreEntries) {
|
||||
return;
|
||||
}
|
||||
if (UserList.scrollArea.scrollTop() + UserList.scrollArea.height() > UserList.scrollArea.get(0).scrollHeight - 500) {
|
||||
UserList.update(UserList.currentGid, true);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
function setQuota (uid, quota, ready) {
|
||||
$.post(
|
||||
OC.filePath('settings', 'ajax', 'setquota.php'),
|
||||
{username: uid, quota: quota},
|
||||
function (result) {
|
||||
if (ready) {
|
||||
ready(result.data.quota);
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
$(document).ready(function () {
|
||||
$userList = $('#userlist');
|
||||
$userListBody = $userList.find('tbody');
|
||||
|
||||
UserList.initDeleteHandling();
|
||||
|
||||
// Implements User Search
|
||||
filter = new UserManagementFilter($('#usersearchform input'), UserList, GroupList);
|
||||
|
||||
UserList.doSort();
|
||||
UserList.availableGroups = $userList.data('groups');
|
||||
|
||||
|
||||
UserList.scrollArea = $('#app-content');
|
||||
UserList.scrollArea.scroll(function(e) {UserList._onScroll(e);});
|
||||
|
||||
|
||||
$userList.after($('<div class="loading" style="height: 200px; visibility: hidden;"></div>'));
|
||||
|
||||
$('.groupsselect').each(function (index, element) {
|
||||
UserList.applyGroupSelect(element);
|
||||
});
|
||||
$('.subadminsselect').each(function (index, element) {
|
||||
UserList.applySubadminSelect(element);
|
||||
});
|
||||
|
||||
$userListBody.on('click', '.password', function (event) {
|
||||
event.stopPropagation();
|
||||
|
||||
var $td = $(this).closest('td');
|
||||
var uid = UserList.getUID($td);
|
||||
var $input = $('<input type="password">');
|
||||
$td.find('img').hide();
|
||||
$td.children('span').replaceWith($input);
|
||||
$input
|
||||
.focus()
|
||||
.keypress(function (event) {
|
||||
if (event.keyCode === 13) {
|
||||
if ($(this).val().length > 0) {
|
||||
var recoveryPasswordVal = $('input:password[id="recoveryPassword"]').val();
|
||||
$.post(
|
||||
OC.generateUrl('/settings/users/changepassword'),
|
||||
{username: uid, password: $(this).val(), recoveryPassword: recoveryPasswordVal},
|
||||
function (result) {
|
||||
if (result.status != 'success') {
|
||||
OC.Notification.show(t('admin', result.data.message));
|
||||
}
|
||||
}
|
||||
);
|
||||
$input.blur();
|
||||
} else {
|
||||
$input.blur();
|
||||
}
|
||||
}
|
||||
})
|
||||
.blur(function () {
|
||||
$(this).replaceWith($('<span>●●●●●●●</span>'));
|
||||
$td.find('img').show();
|
||||
});
|
||||
});
|
||||
$('input:password[id="recoveryPassword"]').keyup(function() {
|
||||
OC.Notification.hide();
|
||||
});
|
||||
|
||||
$userListBody.on('click', '.displayName', function (event) {
|
||||
event.stopPropagation();
|
||||
var $td = $(this).closest('td');
|
||||
var $tr = $td.closest('tr');
|
||||
var uid = UserList.getUID($td);
|
||||
var displayName = escapeHTML(UserList.getDisplayName($td));
|
||||
var $input = $('<input type="text" value="' + displayName + '">');
|
||||
$td.find('img').hide();
|
||||
$td.children('span').replaceWith($input);
|
||||
$input
|
||||
.focus()
|
||||
.keypress(function (event) {
|
||||
if (event.keyCode === 13) {
|
||||
if ($(this).val().length > 0) {
|
||||
$tr.find('.avatardiv').imageplaceholder(uid, displayName);
|
||||
$.post(
|
||||
OC.filePath('settings', 'ajax', 'changedisplayname.php'),
|
||||
{username: uid, displayName: $(this).val()},
|
||||
function (result) {
|
||||
if (result && result.status==='success'){
|
||||
$tr.find('.avatardiv').avatar(result.data.username, 32);
|
||||
}
|
||||
}
|
||||
);
|
||||
$input.blur();
|
||||
} else {
|
||||
$input.blur();
|
||||
}
|
||||
}
|
||||
})
|
||||
.blur(function () {
|
||||
var displayName = $input.val();
|
||||
$tr.data('displayname', displayName);
|
||||
$input.replaceWith('<span>' + escapeHTML(displayName) + '</span>');
|
||||
$td.find('img').show();
|
||||
});
|
||||
});
|
||||
|
||||
$('#default_quota, .quota-user').singleSelect().on('change', function () {
|
||||
var $select = $(this);
|
||||
var uid = UserList.getUID($select);
|
||||
var quota = $select.val();
|
||||
setQuota(uid, quota, function(returnedQuota){
|
||||
if (quota !== returnedQuota) {
|
||||
$select.find(':selected').text(returnedQuota);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
$('#newuser').submit(function (event) {
|
||||
event.preventDefault();
|
||||
var username = $('#newusername').val();
|
||||
var password = $('#newuserpassword').val();
|
||||
if ($.trim(username) === '') {
|
||||
OC.dialogs.alert(
|
||||
t('settings', 'A valid username must be provided'),
|
||||
t('settings', 'Error creating user'));
|
||||
return false;
|
||||
}
|
||||
if ($.trim(password) === '') {
|
||||
OC.dialogs.alert(
|
||||
t('settings', 'A valid password must be provided'),
|
||||
t('settings', 'Error creating user'));
|
||||
return false;
|
||||
}
|
||||
var groups = $('#newusergroups').val();
|
||||
$('#newuser').get(0).reset();
|
||||
$.post(
|
||||
OC.filePath('settings', 'ajax', 'createuser.php'),
|
||||
{
|
||||
username: username,
|
||||
password: password,
|
||||
groups: groups
|
||||
},
|
||||
function (result) {
|
||||
if (result.status !== 'success') {
|
||||
OC.dialogs.alert(result.data.message,
|
||||
t('settings', 'Error creating user'));
|
||||
} else {
|
||||
if (result.data.groups) {
|
||||
var addedGroups = result.data.groups;
|
||||
UserList.availableGroups = $.unique($.merge(UserList.availableGroups, addedGroups));
|
||||
}
|
||||
if (result.data.homeExists){
|
||||
OC.Notification.hide();
|
||||
OC.Notification.show(t('settings', 'Warning: Home directory for user "{user}" already exists', {user: result.data.username}));
|
||||
if (UserList.notificationTimeout){
|
||||
window.clearTimeout(UserList.notificationTimeout);
|
||||
}
|
||||
UserList.notificationTimeout = window.setTimeout(
|
||||
function(){
|
||||
OC.Notification.hide();
|
||||
UserList.notificationTimeout = null;
|
||||
}, 10000);
|
||||
}
|
||||
if(!UserList.has(username)) {
|
||||
UserList.add(username, username, result.data.groups, null, 'default', result.data.storageLocation, 0, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
});
|
|
@ -25,6 +25,8 @@ $this->create('settings_admin', '/settings/admin')
|
|||
// users
|
||||
$this->create('settings_ajax_userlist', '/settings/ajax/userlist')
|
||||
->actionInclude('settings/ajax/userlist.php');
|
||||
$this->create('settings_ajax_grouplist', '/settings/ajax/grouplist')
|
||||
->actionInclude('settings/ajax/grouplist.php');
|
||||
$this->create('settings_ajax_createuser', '/settings/ajax/createuser.php')
|
||||
->actionInclude('settings/ajax/createuser.php');
|
||||
$this->create('settings_ajax_removeuser', '/settings/ajax/removeuser.php')
|
||||
|
@ -44,6 +46,8 @@ $this->create('settings_users_changepassword', '/settings/users/changepassword')
|
|||
->action('OC\Settings\ChangePassword\Controller', 'changeUserPassword');
|
||||
$this->create('settings_ajax_changedisplayname', '/settings/ajax/changedisplayname.php')
|
||||
->actionInclude('settings/ajax/changedisplayname.php');
|
||||
$this->create('settings_ajax_changegorupname', '/settings/ajax/changegroupname.php')
|
||||
->actionInclude('settings/ajax/changegroupname.php');
|
||||
// personal
|
||||
$this->create('settings_personal_changepassword', '/settings/personal/changepassword')
|
||||
->post()
|
||||
|
|
|
@ -1,176 +0,0 @@
|
|||
<?php
|
||||
/**
|
||||
* Copyright (c) 2011, Robin Appelman <icewind1991@gmail.com>
|
||||
* This file is licensed under the Affero General Public License version 3 or later.
|
||||
* See the COPYING-README file.
|
||||
*/
|
||||
$allGroups=array();
|
||||
foreach($_["groups"] as $group) {
|
||||
$allGroups[] = $group['name'];
|
||||
}
|
||||
$_['subadmingroups'] = $allGroups;
|
||||
$items = array_flip($_['subadmingroups']);
|
||||
unset($items['admin']);
|
||||
$_['subadmingroups'] = array_flip($items);
|
||||
?>
|
||||
|
||||
<div id="controls">
|
||||
<form id="newuser" autocomplete="off">
|
||||
<input id="newusername" type="text" placeholder="<?php p($l->t('Login Name'))?>" /> <input
|
||||
type="password" id="newuserpassword"
|
||||
placeholder="<?php p($l->t('Password'))?>" /> <select
|
||||
class="groupsselect"
|
||||
id="newusergroups" data-placeholder="groups"
|
||||
title="<?php p($l->t('Groups'))?>" multiple="multiple">
|
||||
<?php foreach($_["groups"] as $group): ?>
|
||||
<option value="<?php p($group['name']);?>"><?php p($group['name']);?></option>
|
||||
<?php endforeach;?>
|
||||
</select> <input type="submit" value="<?php p($l->t('Create'))?>" />
|
||||
</form>
|
||||
<?php if((bool)$_['recoveryAdminEnabled']): ?>
|
||||
<div class="recoveryPassword">
|
||||
<input id="recoveryPassword"
|
||||
type="password"
|
||||
placeholder="<?php p($l->t('Admin Recovery Password'))?>"
|
||||
title="<?php p($l->t('Enter the recovery password in order to recover the users files during password change'))?>"
|
||||
alt="<?php p($l->t('Enter the recovery password in order to recover the users files during password change'))?>"/>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
<div class="quota">
|
||||
<span><?php p($l->t('Default Storage'));?></span>
|
||||
<?php if((bool) $_['isadmin']): ?>
|
||||
<select class='quota' data-inputtitle="<?php p($l->t('Please enter storage quota (ex: "512 MB" or "12 GB")')) ?>">
|
||||
<option
|
||||
<?php if($_['default_quota'] === 'none') print_unescaped('selected="selected"');?>
|
||||
value='none'>
|
||||
<?php p($l->t('Unlimited'));?>
|
||||
</option>
|
||||
<?php foreach($_['quota_preset'] as $preset):?>
|
||||
<?php if($preset !== 'default'):?>
|
||||
<option
|
||||
<?php if($_['default_quota']==$preset) print_unescaped('selected="selected"');?>
|
||||
value='<?php p($preset);?>'>
|
||||
<?php p($preset);?>
|
||||
</option>
|
||||
<?php endif;?>
|
||||
<?php endforeach;?>
|
||||
<?php if($_['defaultQuotaIsUserDefined']):?>
|
||||
<option selected="selected"
|
||||
value='<?php p($_['default_quota']);?>'>
|
||||
<?php p($_['default_quota']);?>
|
||||
</option>
|
||||
<?php endif;?>
|
||||
<option data-new value='other'>
|
||||
<?php p($l->t('Other'));?>
|
||||
...
|
||||
</option>
|
||||
</select>
|
||||
<?php endif; ?>
|
||||
<?php if((bool) !$_['isadmin']): ?>
|
||||
<select class='quota' disabled="disabled">
|
||||
<option selected="selected">
|
||||
<?php p($_['default_quota']);?>
|
||||
</option>
|
||||
</select>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<table class="hascontrols grid" data-groups="<?php p(json_encode($allGroups));?>">
|
||||
<thead>
|
||||
<tr>
|
||||
<?php if ($_['enableAvatars']): ?>
|
||||
<th id='headerAvatar'></th>
|
||||
<?php endif; ?>
|
||||
<th id='headerName'><?php p($l->t('Username'))?></th>
|
||||
<th id="headerDisplayName"><?php p($l->t( 'Full Name' )); ?></th>
|
||||
<th id="headerPassword"><?php p($l->t( 'Password' )); ?></th>
|
||||
<th id="headerGroups"><?php p($l->t( 'Groups' )); ?></th>
|
||||
<?php if(is_array($_['subadmins']) || $_['subadmins']): ?>
|
||||
<th id="headerSubAdmins"><?php p($l->t('Group Admin')); ?></th>
|
||||
<?php endif;?>
|
||||
<th id="headerQuota"><?php p($l->t('Storage')); ?></th>
|
||||
<th id="headerRemove"> </th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<?php foreach($_["users"] as $user): ?>
|
||||
<tr data-uid="<?php p($user["name"]) ?>"
|
||||
data-displayName="<?php p($user["displayName"]) ?>">
|
||||
<?php if ($_['enableAvatars']): ?>
|
||||
<td class="avatar"><div class="avatardiv"></div></td>
|
||||
<?php endif; ?>
|
||||
<td class="name"><?php p($user["name"]); ?></td>
|
||||
<td class="displayName"><span><?php p($user["displayName"]); ?></span> <img class="svg action"
|
||||
src="<?php p(image_path('core', 'actions/rename.svg'))?>"
|
||||
alt="<?php p($l->t("change full name"))?>" title="<?php p($l->t("change full name"))?>"/>
|
||||
</td>
|
||||
<td class="password"><span>●●●●●●●</span> <img class="svg action"
|
||||
src="<?php print_unescaped(image_path('core', 'actions/rename.svg'))?>"
|
||||
alt="<?php p($l->t("set new password"))?>" title="<?php p($l->t("set new password"))?>"/>
|
||||
</td>
|
||||
<td class="groups"><select
|
||||
class="groupsselect"
|
||||
data-username="<?php p($user['name']) ;?>"
|
||||
data-user-groups="<?php p(json_encode($user['groups'])) ;?>"
|
||||
data-placeholder="groups" title="<?php p($l->t('Groups'))?>"
|
||||
multiple="multiple">
|
||||
<?php foreach($_["groups"] as $group): ?>
|
||||
<option value="<?php p($group['name']);?>"><?php p($group['name']);?></option>
|
||||
<?php endforeach;?>
|
||||
</select>
|
||||
</td>
|
||||
<?php if(is_array($_['subadmins']) || $_['subadmins']): ?>
|
||||
<td class="subadmins"><select
|
||||
class="subadminsselect"
|
||||
data-username="<?php p($user['name']) ;?>"
|
||||
data-subadmin="<?php p(json_encode($user['subadmin']));?>"
|
||||
data-placeholder="subadmins" title="<?php p($l->t('Group Admin'))?>"
|
||||
multiple="multiple">
|
||||
<?php foreach($_["subadmingroups"] as $group): ?>
|
||||
<option value="<?php p($group);?>"><?php p($group);?></option>
|
||||
<?php endforeach;?>
|
||||
</select>
|
||||
</td>
|
||||
<?php endif;?>
|
||||
<td class="quota">
|
||||
<select class='quota-user' data-inputtitle="<?php p($l->t('Please enter storage quota (ex: "512 MB" or "12 GB")')) ?>">
|
||||
<option
|
||||
<?php if($user['quota'] === 'default') print_unescaped('selected="selected"');?>
|
||||
value='default'>
|
||||
<?php p($l->t('Default'));?>
|
||||
</option>
|
||||
<option
|
||||
<?php if($user['quota'] === 'none') print_unescaped('selected="selected"');?>
|
||||
value='none'>
|
||||
<?php p($l->t('Unlimited'));?>
|
||||
</option>
|
||||
<?php foreach($_['quota_preset'] as $preset):?>
|
||||
<option
|
||||
<?php if($user['quota']==$preset) print_unescaped('selected="selected"');?>
|
||||
value='<?php p($preset);?>'>
|
||||
<?php p($preset);?>
|
||||
</option>
|
||||
<?php endforeach;?>
|
||||
<?php if($user['isQuotaUserDefined']):?>
|
||||
<option selected="selected" value='<?php p($user['quota']);?>'>
|
||||
<?php p($user['quota']);?>
|
||||
</option>
|
||||
<?php endif;?>
|
||||
<option value='other' data-new>
|
||||
<?php p($l->t('Other'));?>
|
||||
...
|
||||
</option>
|
||||
</select>
|
||||
</td>
|
||||
<td class="remove">
|
||||
<?php if($user['name']!=OC_User::getUser()):?>
|
||||
<a href="#" class="action delete" original-title="<?php p($l->t('Delete'))?>">
|
||||
<img src="<?php print_unescaped(image_path('core', 'actions/delete.svg')) ?>" class="svg" />
|
||||
</a>
|
||||
<?php endif;?>
|
||||
</td>
|
||||
</tr>
|
||||
<?php endforeach; ?>
|
||||
</tbody>
|
||||
</table>
|
|
@ -0,0 +1,32 @@
|
|||
<?php
|
||||
/**
|
||||
* Copyright (c) 2011, Robin Appelman <icewind1991@gmail.com>
|
||||
* This file is licensed under the Affero General Public License version 3 or later.
|
||||
* See the COPYING-README file.
|
||||
*/
|
||||
$userlistParams = array();
|
||||
$allGroups=array();
|
||||
foreach($_["groups"] as $group) {
|
||||
$allGroups[] = $group['name'];
|
||||
}
|
||||
foreach($_["adminGroup"] as $group) {
|
||||
$allGroups[] = $group['name'];
|
||||
}
|
||||
$userlistParams['subadmingroups'] = $allGroups;
|
||||
$userlistParams['allGroups'] = json_encode($allGroups);
|
||||
$items = array_flip($userlistParams['subadmingroups']);
|
||||
unset($items['admin']);
|
||||
$userlistParams['subadmingroups'] = array_flip($items);
|
||||
?>
|
||||
|
||||
<div id="app-navigation">
|
||||
<?php print_unescaped($this->inc('users/part.grouplist')); ?>
|
||||
<div id="app-settings">
|
||||
<?php print_unescaped($this->inc('users/part.setquota')); ?>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="app-content">
|
||||
<?php print_unescaped($this->inc('users/part.createuser')); ?>
|
||||
<?php print_unescaped($this->inc('users/part.userlist', $userlistParams)); ?>
|
||||
</div>
|
|
@ -0,0 +1,34 @@
|
|||
<div id="user-controls">
|
||||
<form id="newuser" autocomplete="off">
|
||||
<input id="newusername" type="text"
|
||||
placeholder="<?php p($l->t('Login Name'))?>"
|
||||
autocomplete="off" autocapitalize="off" autocorrect="off" />
|
||||
<input
|
||||
type="password" id="newuserpassword"
|
||||
placeholder="<?php p($l->t('Password'))?>"
|
||||
autocomplete="off" autocapitalize="off" autocorrect="off" />
|
||||
<select
|
||||
class="groupsselect" id="newusergroups" data-placeholder="groups"
|
||||
title="<?php p($l->t('Groups'))?>" multiple="multiple">
|
||||
<?php foreach($_["adminGroup"] as $adminGroup): ?>
|
||||
<option value="<?php p($adminGroup['name']);?>"><?php p($adminGroup['name']); ?></option>
|
||||
<?php endforeach; ?>
|
||||
<?php foreach($_["groups"] as $group): ?>
|
||||
<option value="<?php p($group['name']);?>"><?php p($group['name']);?></option>
|
||||
<?php endforeach;?>
|
||||
</select>
|
||||
<input type="submit" class="button" value="<?php p($l->t('Create'))?>" />
|
||||
</form>
|
||||
<?php if((bool)$_['recoveryAdminEnabled']): ?>
|
||||
<div class="recoveryPassword">
|
||||
<input id="recoveryPassword"
|
||||
type="password"
|
||||
placeholder="<?php p($l->t('Admin Recovery Password'))?>"
|
||||
title="<?php p($l->t('Enter the recovery password in order to recover the users files during password change'))?>"
|
||||
alt="<?php p($l->t('Enter the recovery password in order to recover the users files during password change'))?>"/>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
<form autocomplete="off" id="usersearchform">
|
||||
<input type="text" class="input userFilter" placeholder="<?php p($l->t('Search Users and Groups')); ?>" />
|
||||
</form>
|
||||
</div>
|
|
@ -0,0 +1,50 @@
|
|||
<ul id="usergrouplist">
|
||||
<!-- Add new group -->
|
||||
<li id="newgroup-init">
|
||||
<a href="#">
|
||||
<span><?php p($l->t('Add Group'))?></span>
|
||||
</a>
|
||||
</li>
|
||||
<li id="newgroup-form">
|
||||
<form>
|
||||
<input type="text" id="newgroupname" placeholder="<?php p($l->t('Group')); ?>..." />
|
||||
<input type="submit" class="button" value="<?php p($l->t('Add Group'))?>" />
|
||||
</form>
|
||||
</li>
|
||||
<!-- Everyone -->
|
||||
<li data-gid="" class="isgroup">
|
||||
<a href="#">
|
||||
<span class="groupname">
|
||||
<?php p($l->t('Everyone')); ?>
|
||||
</span>
|
||||
</a>
|
||||
<span class="utils">
|
||||
<span class="usercount"></span>
|
||||
</span>
|
||||
</li>
|
||||
|
||||
<!-- The Admin Group -->
|
||||
<?php foreach($_["adminGroup"] as $adminGroup): ?>
|
||||
<li data-gid="admin" class="isgroup">
|
||||
<a href="#"><span class="groupname"><?php p($l->t('Admins')); ?></span></a>
|
||||
<span class="utils">
|
||||
<span class="usercount"><?php if($adminGroup['usercount'] > 0) { p($adminGroup['usercount']); } ?></span>
|
||||
</span>
|
||||
</li>
|
||||
<?php endforeach; ?>
|
||||
|
||||
<!--List of Groups-->
|
||||
<?php foreach($_["groups"] as $group): ?>
|
||||
<li data-gid="<?php p($group['name']) ?>" data-usercount="<?php p($group['usercount']) ?>" class="isgroup">
|
||||
<a href="#" class="dorename">
|
||||
<span class="groupname"><?php p($group['name']); ?></span>
|
||||
</a>
|
||||
<span class="utils">
|
||||
<span class="usercount"><?php if($group['usercount'] > 0) { p($group['usercount']); } ?></span>
|
||||
<a href="#" class="action delete" original-title="<?php p($l->t('Delete'))?>">
|
||||
<img src="<?php print_unescaped(image_path('core', 'actions/delete.svg')) ?>" class="svg" />
|
||||
</a>
|
||||
</span>
|
||||
</li>
|
||||
<?php endforeach; ?>
|
||||
</ul>
|
|
@ -0,0 +1,39 @@
|
|||
<div id="app-settings-header">
|
||||
<button class="settings-button" tabindex="0"></button>
|
||||
</div>
|
||||
<div id="app-settings-content">
|
||||
<div class="quota">
|
||||
<!-- Default storage -->
|
||||
<span><?php p($l->t('Default Quota'));?></span>
|
||||
<?php if((bool) $_['isAdmin']): ?>
|
||||
<select id='default_quota' data-inputtitle="<?php p($l->t('Please enter storage quota (ex: "512 MB" or "12 GB")')) ?>">
|
||||
<option <?php if($_['default_quota'] === 'none') print_unescaped('selected="selected"');?> value='none'>
|
||||
<?php p($l->t('Unlimited'));?>
|
||||
</option>
|
||||
<?php foreach($_['quota_preset'] as $preset):?>
|
||||
<?php if($preset !== 'default'):?>
|
||||
<option <?php if($_['default_quota']==$preset) print_unescaped('selected="selected"');?> value='<?php p($preset);?>'>
|
||||
<?php p($preset);?>
|
||||
</option>
|
||||
<?php endif;?>
|
||||
<?php endforeach;?>
|
||||
<?php if($_['defaultQuotaIsUserDefined']):?>
|
||||
<option selected="selected" value='<?php p($_['default_quota']);?>'>
|
||||
<?php p($_['default_quota']);?>
|
||||
</option>
|
||||
<?php endif;?>
|
||||
<option data-new value='other'>
|
||||
<?php p($l->t('Other'));?>
|
||||
...
|
||||
</option>
|
||||
</select>
|
||||
<?php endif; ?>
|
||||
<?php if((bool) !$_['isAdmin']): ?>
|
||||
<select class='quota' disabled="disabled">
|
||||
<option selected="selected">
|
||||
<?php p($_['default_quota']);?>
|
||||
</option>
|
||||
</select>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
</div>
|
|
@ -0,0 +1,116 @@
|
|||
<table id="userlist" class="hascontrols grid" data-groups="<?php p($_['allGroups']);?>">
|
||||
<thead>
|
||||
<tr>
|
||||
<?php if ($_['enableAvatars']): ?>
|
||||
<th id='headerAvatar'></th>
|
||||
<?php endif; ?>
|
||||
<th id='headerName'><?php p($l->t('Username'))?></th>
|
||||
<th id="headerDisplayName"><?php p($l->t( 'Full Name' )); ?></th>
|
||||
<th id="headerPassword"><?php p($l->t( 'Password' )); ?></th>
|
||||
<th id="headerGroups"><?php p($l->t( 'Groups' )); ?></th>
|
||||
<?php if(is_array($_['subadmins']) || $_['subadmins']): ?>
|
||||
<th id="headerSubAdmins"><?php p($l->t('Group Admin')); ?></th>
|
||||
<?php endif;?>
|
||||
<th id="headerQuota"><?php p($l->t('Quota')); ?></th>
|
||||
<th id="headerStorageLocation"><?php p($l->t('Storage Location')); ?></th>
|
||||
<th id="headerLastLogin"><?php p($l->t('Last Login')); ?></th>
|
||||
<th id="headerRemove"> </th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<?php foreach($_["users"] as $user): ?>
|
||||
<tr data-uid="<?php p($user["name"]) ?>"
|
||||
data-displayname="<?php p($user["displayName"]) ?>">
|
||||
<?php if ($_['enableAvatars']): ?>
|
||||
<td class="avatar"><div class="avatardiv"></div></td>
|
||||
<?php endif; ?>
|
||||
<td class="name"><?php p($user["name"]); ?></td>
|
||||
<td class="displayName"><span><?php p($user["displayName"]); ?></span> <img class="svg action"
|
||||
src="<?php p(image_path('core', 'actions/rename.svg'))?>"
|
||||
alt="<?php p($l->t("change full name"))?>" title="<?php p($l->t("change full name"))?>"/>
|
||||
</td>
|
||||
<td class="password"><span>●●●●●●●</span> <img class="svg action"
|
||||
src="<?php print_unescaped(image_path('core', 'actions/rename.svg'))?>"
|
||||
alt="<?php p($l->t("set new password"))?>" title="<?php p($l->t("set new password"))?>"/>
|
||||
</td>
|
||||
<td class="groups">
|
||||
<select
|
||||
class="groupsselect"
|
||||
data-username="<?php p($user['name']) ;?>"
|
||||
data-user-groups="<?php p(json_encode($user['groups'])) ;?>"
|
||||
data-placeholder="groups" title="<?php p($l->t('Groups'))?>"
|
||||
multiple="multiple">
|
||||
<?php foreach($_["adminGroup"] as $adminGroup): ?>
|
||||
<option value="<?php p($adminGroup['name']);?>"><?php p($adminGroup['name']); ?></option>
|
||||
<?php endforeach; ?>
|
||||
<?php foreach($_["groups"] as $group): ?>
|
||||
<option value="<?php p($group['name']);?>"><?php p($group['name']);?></option>
|
||||
<?php endforeach;?>
|
||||
</select>
|
||||
</td>
|
||||
<?php if(is_array($_['subadmins']) || $_['subadmins']): ?>
|
||||
<td class="subadmins">
|
||||
<select
|
||||
class="subadminsselect"
|
||||
data-username="<?php p($user['name']) ;?>"
|
||||
data-subadmin="<?php p(json_encode($user['subadmin']));?>"
|
||||
data-placeholder="subadmins" title="<?php p($l->t('Group Admin'))?>"
|
||||
multiple="multiple">
|
||||
<?php foreach($_["subadmingroups"] as $group): ?>
|
||||
<option value="<?php p($group);?>"><?php p($group);?></option>
|
||||
<?php endforeach;?>
|
||||
</select>
|
||||
</td>
|
||||
<?php endif;?>
|
||||
<td class="quota">
|
||||
<select class='quota-user' data-inputtitle="<?php p($l->t('Please enter storage quota (ex: "512 MB" or "12 GB")')) ?>">
|
||||
<option
|
||||
<?php if($user['quota'] === 'default') print_unescaped('selected="selected"');?>
|
||||
value='default'>
|
||||
<?php p($l->t('Default'));?>
|
||||
</option>
|
||||
<option
|
||||
<?php if($user['quota'] === 'none') print_unescaped('selected="selected"');?>
|
||||
value='none'>
|
||||
<?php p($l->t('Unlimited'));?>
|
||||
</option>
|
||||
<?php foreach($_['quota_preset'] as $preset):?>
|
||||
<option
|
||||
<?php if($user['quota']==$preset) print_unescaped('selected="selected"');?>
|
||||
value='<?php p($preset);?>'>
|
||||
<?php p($preset);?>
|
||||
</option>
|
||||
<?php endforeach;?>
|
||||
<?php if($user['isQuotaUserDefined']):?>
|
||||
<option selected="selected" value='<?php p($user['quota']);?>'>
|
||||
<?php p($user['quota']);?>
|
||||
</option>
|
||||
<?php endif;?>
|
||||
<option value='other' data-new>
|
||||
<?php p($l->t('Other'));?>
|
||||
...
|
||||
</option>
|
||||
</select>
|
||||
</td>
|
||||
<td class="storageLocation"><?php p($user["storageLocation"]); ?></td>
|
||||
<?php
|
||||
if($user["lastLogin"] === 0) {
|
||||
$lastLogin = $l->t('never');
|
||||
$lastLoginDate = '';
|
||||
} else {
|
||||
$lastLogin = relative_modified_date($user["lastLogin"]);
|
||||
$lastLoginDate = \OC_Util::formatDate($user["lastLogin"]);
|
||||
}
|
||||
?>
|
||||
<td class="lastLogin" title="<?php p('<span style="white-space: nowrap;">'.$lastLoginDate.'</span>'); ?>"><?php p($lastLogin); ?></td>
|
||||
<td class="remove">
|
||||
<?php if($user['name']!=OC_User::getUser()):?>
|
||||
<a href="#" class="action delete" original-title="<?php p($l->t('Delete'))?>">
|
||||
<img src="<?php print_unescaped(image_path('core', 'actions/delete.svg')) ?>" class="svg" />
|
||||
</a>
|
||||
<?php endif;?>
|
||||
</td>
|
||||
</tr>
|
||||
<?php endforeach; ?>
|
||||
</tbody>
|
||||
</table>
|
|
@ -8,7 +8,10 @@
|
|||
OC_Util::checkSubAdminUser();
|
||||
|
||||
// We have some javascript foo!
|
||||
OC_Util::addScript( 'settings', 'users' );
|
||||
OC_Util::addScript('settings', 'users/deleteHandler');
|
||||
OC_Util::addScript('settings', 'users/filter');
|
||||
OC_Util::addScript( 'settings', 'users/users' );
|
||||
OC_Util::addScript( 'settings', 'users/groups' );
|
||||
OC_Util::addScript( 'core', 'multiselect' );
|
||||
OC_Util::addScript( 'core', 'singleselect' );
|
||||
OC_Util::addScript('core', 'jquery.inview');
|
||||
|
@ -16,19 +19,23 @@ OC_Util::addStyle( 'settings', 'settings' );
|
|||
OC_App::setActiveNavigationEntry( 'core_users' );
|
||||
|
||||
$users = array();
|
||||
$groups = array();
|
||||
$userManager = \OC_User::getManager();
|
||||
$groupManager = \OC_Group::getManager();
|
||||
|
||||
$isAdmin = OC_User::isAdminUser(OC_User::getUser());
|
||||
|
||||
$groupsInfo = new \OC\Group\MetaData(OC_User::getUser(), $isAdmin, $groupManager);
|
||||
$groupsInfo->setSorting($groupsInfo::SORT_USERCOUNT);
|
||||
list($adminGroup, $groups) = $groupsInfo->get();
|
||||
|
||||
$isadmin = OC_User::isAdminUser(OC_User::getUser());
|
||||
$recoveryAdminEnabled = OC_App::isEnabled('files_encryption') &&
|
||||
OC_Appconfig::getValue( 'files_encryption', 'recoveryAdminEnabled' );
|
||||
|
||||
if($isadmin) {
|
||||
$accessiblegroups = OC_Group::getGroups();
|
||||
$accessibleusers = OC_User::getDisplayNames('', 30);
|
||||
if($isAdmin) {
|
||||
$accessibleUsers = OC_User::getDisplayNames('', 30);
|
||||
$subadmins = OC_SubAdmin::getAllSubAdmins();
|
||||
}else{
|
||||
$accessiblegroups = OC_SubAdmin::getSubAdminsGroups(OC_User::getUser());
|
||||
$accessibleusers = OC_Group::displayNamesInGroups($accessiblegroups, '', 30);
|
||||
$accessibleUsers = OC_Group::displayNamesInGroups($groups, '', 30);
|
||||
$subadmins = false;
|
||||
}
|
||||
|
||||
|
@ -45,7 +52,7 @@ $defaultQuotaIsUserDefined=array_search($defaultQuota, $quotaPreset)===false
|
|||
&& array_search($defaultQuota, array('none', 'default'))===false;
|
||||
|
||||
// load users and quota
|
||||
foreach($accessibleusers as $uid => $displayName) {
|
||||
foreach($accessibleUsers as $uid => $displayName) {
|
||||
$quota=OC_Preferences::getValue($uid, 'files', 'quota', 'default');
|
||||
$isQuotaUserDefined=array_search($quota, $quotaPreset)===false
|
||||
&& array_search($quota, array('none', 'default'))===false;
|
||||
|
@ -55,6 +62,7 @@ foreach($accessibleusers as $uid => $displayName) {
|
|||
$name = $name . ' ('.$uid.')';
|
||||
}
|
||||
|
||||
$user = $userManager->get($uid);
|
||||
$users[] = array(
|
||||
"name" => $uid,
|
||||
"displayName" => $displayName,
|
||||
|
@ -62,23 +70,21 @@ foreach($accessibleusers as $uid => $displayName) {
|
|||
'quota' => $quota,
|
||||
'isQuotaUserDefined' => $isQuotaUserDefined,
|
||||
'subadmin' => OC_SubAdmin::getSubAdminsGroups($uid),
|
||||
'storageLocation' => $user->getHome(),
|
||||
'lastLogin' => $user->getLastLogin(),
|
||||
);
|
||||
}
|
||||
|
||||
foreach( $accessiblegroups as $i ) {
|
||||
// Do some more work here soon
|
||||
$groups[] = array( "name" => $i );
|
||||
}
|
||||
|
||||
$tmpl = new OC_Template( "settings", "users", "user" );
|
||||
$tmpl = new OC_Template( "settings", "users/main", "user" );
|
||||
$tmpl->assign( 'users', $users );
|
||||
$tmpl->assign( 'groups', $groups );
|
||||
$tmpl->assign( 'isadmin', (int) $isadmin);
|
||||
$tmpl->assign( 'adminGroup', $adminGroup );
|
||||
$tmpl->assign( 'isAdmin', (int) $isAdmin);
|
||||
$tmpl->assign( 'subadmins', $subadmins);
|
||||
$tmpl->assign( 'numofgroups', count($accessiblegroups));
|
||||
$tmpl->assign( 'numofgroups', count($groups) + count($adminGroup));
|
||||
$tmpl->assign( 'quota_preset', $quotaPreset);
|
||||
$tmpl->assign( 'default_quota', $defaultQuota);
|
||||
$tmpl->assign( 'defaultQuotaIsUserDefined', $defaultQuotaIsUserDefined);
|
||||
$tmpl->assign( 'recoveryAdminEnabled', $recoveryAdminEnabled);
|
||||
$tmpl->assign('enableAvatars', \OC_Config::getValue('enable_avatars', true));
|
||||
$tmpl->assign( 'enableAvatars', \OC_Config::getValue('enable_avatars', true));
|
||||
$tmpl->printPage();
|
||||
|
|
Loading…
Reference in New Issue