Skip to content

Commit

Permalink
replace chosen with select2 to provide ajaxified user and group selec…
Browse files Browse the repository at this point in the history
…tion for files_external, fixes #7499
  • Loading branch information
butonic committed Oct 13, 2014
1 parent 564d28b commit 5af5bd5
Show file tree
Hide file tree
Showing 6 changed files with 222 additions and 35 deletions.
26 changes: 26 additions & 0 deletions apps/files_external/ajax/applicable.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
<?php

OCP\JSON::checkAppEnabled('files_external');
OCP\JSON::callCheck();

OCP\JSON::checkAdminUser();

$pattern = '';
$limit = null;
$offset = null;
if (isset($_GET['pattern'])) {
$pattern = $_GET['pattern'];
}
if (isset($_GET['limit'])) {
$limit = $_GET['limit'];
}
if (isset($_GET['offset'])) {
$offset = $_GET['offset'];
}

$groups = \OC_Group::getGroups($pattern, $limit, $offset);
$users = \OCP\User::getDisplayNames($pattern, $limit, $offset);

$results = array('groups' => $groups, 'users' => $users);

\OCP\JSON::success($results);
29 changes: 29 additions & 0 deletions apps/files_external/appinfo/routes.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
<?php
/**
* ownCloud - External Storage Routes
*
* @author Vincent Petry
* @copyright 2014 Vincent Petry <[email protected]>
*
* 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/>.
*
*/

$this->create('files_external_list_applicable', '/applicable')->actionInclude('files_external/ajax/applicable.php');

OC_API::register('get',
'/apps/files_external/api/v1/mounts',
array('\OCA\Files\External\Api', 'getUserMounts'),
'files_external');

25 changes: 25 additions & 0 deletions apps/files_external/css/settings.css
Original file line number Diff line number Diff line change
Expand Up @@ -27,3 +27,28 @@ tr:hover>td.remove>img { visibility:visible; cursor:pointer; }
position: relative;
top: 3px;
}


#externalStorage td.status .success {
border-radius: 50%;
}

#userMountingBackends {
padding-left: 25px;
}

#body-settings .select2-results .select2-result-label {
height: 32px;
padding: 3px;
}
.select2-results .select2-result-label .avatardiv {
display:inline-block;
}
.select2-results .select2-result-label .avatardiv + span {
margin-left: 10px;
}
.select2-results .select2-result-label .avatardiv[data-type="group"] + span {
vertical-align: top;
top: 6px;
position: relative;
}
147 changes: 138 additions & 9 deletions apps/files_external/js/settings.js
Original file line number Diff line number Diff line change
Expand Up @@ -41,9 +41,11 @@ OC.MountConfig={
}
});
if ($('#externalStorage').data('admin') === true) {
var multiselect = $(tr).find('.chzn-select').val();
var multiselect = $(tr).find('.applicableUsers').select2('val');
if (multiselect == null) {
return false;
} else if (multiselect instanceof Array && multiselect.length === 0) {
multiselect.push('all');
}
}
if (addMountPoint) {
Expand Down Expand Up @@ -161,7 +163,138 @@ OC.MountConfig={
};

$(document).ready(function() {
$('.chzn-select').chosen();
//initialize hidden input field with list of users and groups
$('#externalStorage').find('tr:not(#addMountPoint)').each(function(i,tr) {
var applicable = $(tr).find('.applicable');
if (applicable.length > 0) {
var groups = applicable.data('applicable-groups');
var groupsId = [];
$.each(groups, function () {
groupsId.push(this+"(group)");
});
var users = applicable.data('applicable-users');
if (users.indexOf('all') > -1) {
$(tr).find('.applicableUsers').val('');
} else {
$(tr).find('.applicableUsers').val(groupsId.concat(users).join(','));
}
}
});

var userListLimit = 30;
function addSelect2 ($elements) {
if ($elements.length > 0) {
$elements.select2({
placeholder: t('files_external', 'All users. Type to select user or group.'),
allowClear: true,
multiple: true,
//minimumInputLength: 1,
ajax: {
url: OC.generateUrl('apps/files_external/applicable'),
dataType: 'json',
quietMillis: 100,
data: function (term, page) { // page is the one-based page number tracked by Select2
return {
pattern: term, //search term
limit: userListLimit, // page size
offset: userListLimit*(page-1), // page number starts with 0
};
},
results: function (data, page) {
if (data.status === "success") {

var results = [];
var userCount = 0; // users is an object

// add groups
$.each(data.groups, function(i, group) {
results.push({name:group+'(group)', displayname:group, type:'group' });
});
// add users
$.each(data.users, function(id, user) {
userCount++;
results.push({name:id, displayname:user, type:'user' });
});


var more = (userCount >= userListLimit) || (data.groups.length >= userListLimit);
return {results: results, more: more};
} else {
//FIXME add error handling
}
}
},
initSelection: function(element, callback) {

var promises = [];

var results = [];

$(element.val().split(",")).each(function (i,userId) {
var def = new $.Deferred();
promises.push(def.promise());

var pos = userId.indexOf('(group)');
if (pos !== -1) {
//add as group
results.push({name:userId, displayname:userId.substr(0, pos), type:'group'});
def.resolve();
} else {
$.ajax(OC.generateUrl('apps/files_external/applicable'), {
data: {
pattern: userId
},
dataType: "json"
}).done(function(data) {
if (data.status === "success") {
if (data.users[userId]) {
results.push({name:userId, displayname:data.users[userId], type:'user'});
}
def.resolve();
} else {
//FIXME add error handling
}
});
}
});
$.when.apply(undefined, promises).then(function(){
callback(results);
});
},
id: function(element) {
return element.name;
},
formatResult: function (element) {
var $result = $('<span><div class="avatardiv"/><span>'+escapeHTML(element.displayname)+'</span></span>');
var $div = $result.find('.avatardiv')
.attr('data-type', element.type)
.attr('data-name', element.name)
.attr('data-displayname', element.displayname);
if (element.type === 'group') {
var url = OC.imagePath('core','places/contacts-dark'); // TODO better group icon
$div.html('<img width="32" height="32" src="'+url+'">');
}
return $result.get(0).outerHTML;
},
formatSelection: function (element) {
if (element.type === 'group') {
return '<span title="'+escapeHTML(element.name)+'" class="group">'+escapeHTML(element.displayname+' '+t('files_external', '(group)'))+'</span>';
} else {
return '<span title="'+escapeHTML(element.name)+'" class="user">'+escapeHTML(element.displayname)+'</span>';
}
},
escapeMarkup: function (m) { return m; } // we escape the markup in formatResult and formatSelection
}).on("select2-loaded", function() {
$.each($(".avatardiv"), function(i, div) {
$div = $(div);
if ($div.data('type') === 'user') {
$div.avatar($div.data('name'),32);
}
})
});
}
}
addSelect2($('tr:not(#addMountPoint) .applicableUsers'));

$('#externalStorage').on('change', '#selectBackend', function() {
var tr = $(this).parent().parent();
Expand Down Expand Up @@ -199,15 +332,11 @@ $(document).ready(function() {
return false;
}
});
// Reset chosen
var chosen = $(tr).find('.applicable select');
chosen.parent().find('div').remove();
chosen.removeAttr('id').removeClass('chzn-done').css({display:'inline-block'});
chosen.chosen();
$(tr).find('td').last().attr('class', 'remove');
$(tr).find('td').last().removeAttr('style');
$(tr).removeAttr('id');
$(this).remove();
addSelect2($('tr:not(#addMountPoint) .applicableUsers'));
});

function suggestMountPoint(defaultMountPoint) {
Expand Down Expand Up @@ -260,8 +389,8 @@ $(document).ready(function() {
OC.MountConfig.saveStorage($(this).parent().parent().parent());
});

$('#externalStorage').on('change', '.applicable .chzn-select', function() {
OC.MountConfig.saveStorage($(this).parent().parent());
$('#externalStorage').on('change', '.applicable', function() {
OC.MountConfig.saveStorage($(this).parent());
});

$('#sslCertificate').on('click', 'td.remove>img', function() {
Expand Down
6 changes: 2 additions & 4 deletions apps/files_external/settings.php
Original file line number Diff line number Diff line change
Expand Up @@ -23,15 +23,13 @@
OC_Util::checkAdminUser();

OCP\Util::addScript('files_external', 'settings');
OCP\Util::addscript('3rdparty', 'chosen/chosen.jquery.min');
OCP\Util::addStyle('files_external', 'settings');
OCP\Util::addStyle('3rdparty', 'chosen/chosen');
OCP\Util::addScript('files_external', '../3rdparty/select2/select2');
OCP\Util::addStyle('files_external', '../3rdparty/select2/select2');
$tmpl = new OCP\Template('files_external', 'settings');
$tmpl->assign('isAdminPage', true);
$tmpl->assign('mounts', OC_Mount_Config::getSystemMountPoints());
$tmpl->assign('backends', OC_Mount_Config::getBackends());
$tmpl->assign('groups', OC_Group::getGroups());
$tmpl->assign('users', OCP\User::getUsers());
$tmpl->assign('userDisplayNames', OC_User::getDisplayNames());
$tmpl->assign('dependencies', OC_Mount_Config::checkDependencies());
$tmpl->assign('allowUserMounting', OCP\Config::getAppValue('files_external', 'allow_user_mounting', 'yes'));
Expand Down
24 changes: 2 additions & 22 deletions apps/files_external/templates/settings.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
<tbody width="100%">
<?php $_['mounts'] = array_merge($_['mounts'], array('' => array())); ?>
<?php foreach ($_['mounts'] as $mount): ?>
<tr <?php print_unescaped(($mount['mountpoint'] !== '') ? 'class="'.OC_Util::sanitizeHTML($mount['class']).'"' : 'id="addMountPoint"'); ?>>
<tr <?php print_unescaped((isset($mount['mountpoint'])) ? 'class="'.OC_Util::sanitizeHTML($mount['class']).'"' : 'id="addMountPoint"'); ?>>
<td class="status">
<?php if (isset($mount['status'])): ?>
<span class="<?php p(($mount['status']) ? 'success' : 'error'); ?>"></span>
Expand Down Expand Up @@ -85,27 +85,7 @@ class="optional"
print_unescaped(json_encode($mount['applicable']['groups'])); ?>'
data-applicable-users='<?php if (isset($mount['applicable']['users']))
print_unescaped(json_encode($mount['applicable']['users'])); ?>'>
<select class="chzn-select"
multiple style="width:20em;"
data-placeholder="<?php p($l->t('None set')); ?>">
<option value="all" <?php if (isset($mount['applicable']['users']) && in_array('all', $mount['applicable']['users'])) print_unescaped('selected="selected"');?> ><?php p($l->t('All Users')); ?></option>
<optgroup label="<?php p($l->t('Groups')); ?>">
<?php foreach ($_['groups'] as $group): ?>
<option value="<?php p($group); ?>(group)"
<?php if (isset($mount['applicable']['groups']) && in_array($group, $mount['applicable']['groups'])): ?>
selected="selected"
<?php endif; ?>><?php p($group); ?></option>
<?php endforeach; ?>
</optgroup>
<optgroup label="<?php p($l->t('Users')); ?>">
<?php foreach ($_['users'] as $user): ?>
<option value="<?php p($user); ?>"
<?php if (isset($mount['applicable']['users']) && in_array($user, $mount['applicable']['users'])): ?>
selected="selected"
<?php endif; ?>><?php p($_['userDisplayNames'][$user]); ?></option>
<?php endforeach; ?>
</optgroup>
</select>
<input type="hidden" class="applicableUsers" style="width:20em;" value=""/>
</td>
<?php endif; ?>
<td <?php if ($mount['mountpoint'] != ''): ?>class="remove"
Expand Down

0 comments on commit 5af5bd5

Please sign in to comment.