mirror of
https://github.com/nextcloud/server.git
synced 2026-02-20 00:12:30 -05:00
Group filtering, disable state, ocs api final update
Signed-off-by: John Molakvoæ (skjnldsv) <skjnldsv@protonmail.com>
This commit is contained in:
parent
c8f670dd8f
commit
2ae82137cd
11 changed files with 202 additions and 69 deletions
|
|
@ -636,8 +636,9 @@ input {
|
|||
opacity: 1 !important;
|
||||
}
|
||||
}
|
||||
&.multiselect--disabled {
|
||||
background-color: nc-darken($color-main-background, 8%);
|
||||
&.multiselect--disabled,
|
||||
&.multiselect--disabled .multiselect__single {
|
||||
background-color: nc-darken($color-main-background, 8%) !important;
|
||||
}
|
||||
.multiselect__tags {
|
||||
display: flex;
|
||||
|
|
@ -683,7 +684,7 @@ input {
|
|||
.multiselect__single {
|
||||
padding: 8px 10px;
|
||||
flex: 0 0 100%;
|
||||
z-index: 5;
|
||||
z-index: 1; /* above input */
|
||||
background-color: $color-main-background;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1289,6 +1289,9 @@ doesnotexist:-o-prefocus, .strengthify-wrapper {
|
|||
grid-template-columns: 44px;
|
||||
grid-auto-columns: min-content;
|
||||
border-top: $color-border 1px solid;
|
||||
&.disabled {
|
||||
opacity: .5;
|
||||
}
|
||||
.name,
|
||||
.displayName,
|
||||
.password {
|
||||
|
|
@ -1363,6 +1366,7 @@ doesnotexist:-o-prefocus, .strengthify-wrapper {
|
|||
left: 2px;
|
||||
bottom: 2px;
|
||||
height: 3px;
|
||||
z-index: 5; /* above multiselect */
|
||||
}
|
||||
}
|
||||
.icon-confirm {
|
||||
|
|
@ -1381,6 +1385,9 @@ doesnotexist:-o-prefocus, .strengthify-wrapper {
|
|||
img {
|
||||
display: block;
|
||||
}
|
||||
&.icon-loading > img {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
.toggleUserActions {
|
||||
position: relative;
|
||||
|
|
@ -1419,6 +1426,7 @@ doesnotexist:-o-prefocus, .strengthify-wrapper {
|
|||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
grid-row-start: span 4;
|
||||
}
|
||||
.users-list-end {
|
||||
opacity: .5;
|
||||
|
|
|
|||
File diff suppressed because one or more lines are too long
|
|
@ -1,10 +1,10 @@
|
|||
<template>
|
||||
<li>
|
||||
<a @click="dispatchToStore" v-if="item.href" :href="(item.href) ? item.href : '#' ">
|
||||
<a @click="item.action" v-if="item.href" :href="(item.href) ? item.href : '#' ">
|
||||
<span :class="item.icon"></span>
|
||||
<span>{{item.text}}</span>
|
||||
</a>
|
||||
<button @click="dispatchToStore(item.action)" v-else>
|
||||
<button @click="item.action" v-else>
|
||||
<span :class="item.icon"></span>
|
||||
<span>{{item.text}}</span>
|
||||
</button>
|
||||
|
|
@ -13,11 +13,6 @@
|
|||
|
||||
<script>
|
||||
export default {
|
||||
props: ['item'],
|
||||
methods: {
|
||||
dispatchToStore () {
|
||||
this.$store.dispatch(this.item.action, this.item.data);
|
||||
}
|
||||
}
|
||||
props: ['item']
|
||||
}
|
||||
</script>
|
||||
|
|
|
|||
|
|
@ -82,11 +82,17 @@
|
|||
</div>
|
||||
</form>
|
||||
|
||||
<user-row v-for="(user, key) in users" :user="user" :key="key" :settings="settings" :showConfig="showConfig"
|
||||
<user-row v-for="(user, key) in filteredUsers" :user="user" :key="key" :settings="settings" :showConfig="showConfig"
|
||||
:groups="groups" :subAdminsGroups="subAdminsGroups" :quotaOptions="quotaOptions" />
|
||||
<infinite-loading @infinite="infiniteHandler">
|
||||
<span slot="spinner"><div class="users-icon-loading"></div></span>
|
||||
<span slot="no-more"><div class="users-list-end">— {{t('settings', 'no more results')}} —</div></span>
|
||||
<infinite-loading @infinite="infiniteHandler" ref="infiniteLoading">
|
||||
<div slot="spinner"><div class="users-icon-loading icon-loading"></div></div>
|
||||
<div slot="no-more"><div class="users-list-end">— {{t('settings', 'no more results')}} —</div></div>
|
||||
<div slot="no-results">
|
||||
<div id="emptycontent">
|
||||
<div class="icon-contacts-dark"></div>
|
||||
<h2>{{t('settings', 'No users in here')}}</h2>
|
||||
</div>
|
||||
</div>
|
||||
</infinite-loading>
|
||||
</div>
|
||||
</template>
|
||||
|
|
@ -132,6 +138,12 @@ export default {
|
|||
settings() {
|
||||
return this.$store.getters.getServerData;
|
||||
},
|
||||
filteredUsers() {
|
||||
if (this.route.hash === '#group_disabled') {
|
||||
return this.users.filter(user => user.enabled !== true);
|
||||
}
|
||||
return this.users.filter(user => user.enabled === true);
|
||||
},
|
||||
groups() {
|
||||
// data provided php side + remove the disabled group
|
||||
return this.$store.getters.getGroups.filter(group => group.id !== '_disabled');
|
||||
|
|
@ -156,7 +168,30 @@ export default {
|
|||
},
|
||||
usersLimit() {
|
||||
return this.$store.getters.getUsersLimit;
|
||||
},
|
||||
},
|
||||
route() {
|
||||
return this.$store.getters.getRoute;
|
||||
},
|
||||
// get selected hash
|
||||
selectedGroup() {
|
||||
let hash = this.route.hash;
|
||||
if (typeof hash === 'string' && hash.length > 0) {
|
||||
// we have a valid hash: groupXXXX
|
||||
// group_XXXX are reserved groups
|
||||
let split = hash.split('group');
|
||||
if (split.length === 2 && split[1].charAt(0) !== '_') {
|
||||
return hash.split('group')[1];
|
||||
}
|
||||
}
|
||||
return '';
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
// watch url change and group select
|
||||
selectedGroup: function (val, old) {
|
||||
this.$store.commit('resetUsers');
|
||||
this.$refs.infiniteLoading.$emit('$InfiniteLoading:reset');
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
onScroll(event) {
|
||||
|
|
@ -182,7 +217,7 @@ export default {
|
|||
},
|
||||
|
||||
infiniteHandler($state) {
|
||||
this.$store.dispatch('getUsers', {offset:this.usersOffset, limit:this.usersLimit})
|
||||
this.$store.dispatch('getUsers', {offset:this.usersOffset, limit:this.usersLimit, group:this.selectedGroup})
|
||||
.then((response) => {response?$state.loaded():$state.complete()});
|
||||
},
|
||||
|
||||
|
|
@ -197,8 +232,10 @@ export default {
|
|||
userid: this.newUser.id,
|
||||
password: this.newUser.password,
|
||||
email: this.newUser.mailAddress,
|
||||
groups: this.newUser.groups.map(group => group.id)
|
||||
}).then(() =>this.resetForm());
|
||||
groups: this.newUser.groups.map(group => group.id),
|
||||
subadmin: this.newUser.subAdminsGroups.map(group => group.id),
|
||||
quota: this.newUser.quota.id
|
||||
}).then(() => this.resetForm());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
<template>
|
||||
<div class="row">
|
||||
<div class="avatar"><img alt="" width="32" height="32" :src="generateAvatar(user.id, 32)" :srcset="generateAvatar(user.id, 64)+' 2x, '+generateAvatar(user.id, 128)+' 4x'"></div>
|
||||
<div class="row" :class="{'disabled': loading.delete || loading.disable}">
|
||||
<div class="avatar" :class="{'icon-loading': loading.delete || loading.disable}"><img alt="" width="32" height="32" :src="generateAvatar(user.id, 32)" :srcset="generateAvatar(user.id, 64)+' 2x, '+generateAvatar(user.id, 128)+' 4x'"></div>
|
||||
<div class="name">{{user.id}}</div>
|
||||
<form class="displayName" :class="{'icon-loading-small': loading.displayName}" v-on:submit.prevent="updateDisplayName">
|
||||
<input :id="'displayName'+user.id+rand" type="text"
|
||||
|
|
@ -59,7 +59,7 @@
|
|||
{{user.lastLogin>0 ? OC.Util.relativeModifiedDate(user.lastLogin) : t('settings','Never')}}
|
||||
</div>
|
||||
<div class="userActions">
|
||||
<div class="toggleUserActions" v-if="OC.currentUser !== user.id && user.id !== 'admin'">
|
||||
<div class="toggleUserActions" v-if="OC.currentUser !== user.id && user.id !== 'admin' && !loading.all">
|
||||
<div class="icon-more" v-click-outside="hideMenu" @click="showMenu"></div>
|
||||
<div class="popovermenu" :class="{ 'open': openedMenu }">
|
||||
<popover-menu :menu="userActions" />
|
||||
|
|
@ -100,7 +100,9 @@ export default {
|
|||
mailAddress: false,
|
||||
groups: false,
|
||||
subadmins: false,
|
||||
quota: false
|
||||
quota: false,
|
||||
delete: false,
|
||||
disable: false
|
||||
}
|
||||
}
|
||||
},
|
||||
|
|
@ -110,13 +112,11 @@ export default {
|
|||
return [{
|
||||
icon: 'icon-delete',
|
||||
text: t('settings','Delete user'),
|
||||
action: 'deleteUser',
|
||||
data: this.user.id
|
||||
action: this.deleteUser
|
||||
},{
|
||||
'icon': this.user.enabled ? 'icon-close' : 'icon-add',
|
||||
'text': this.user.enabled ? t('settings','Disable user') : t('settings','Enable user'),
|
||||
'action': 'enableDisableUser',
|
||||
data: {userid: this.user.id, enabled: !this.user.enabled}
|
||||
'action': this.enableDisableUser
|
||||
}]
|
||||
},
|
||||
|
||||
|
|
@ -199,6 +199,29 @@ export default {
|
|||
return '+'+count;
|
||||
},
|
||||
|
||||
deleteUser() {
|
||||
this.loading.delete = true;
|
||||
this.loading.all = true;
|
||||
let userid = this.user.id;
|
||||
return this.$store.dispatch('deleteUser', {userid})
|
||||
.then(() => {
|
||||
this.loading.delete = false
|
||||
this.loading.all = false
|
||||
});
|
||||
},
|
||||
|
||||
enableDisableUser() {
|
||||
this.loading.delete = true;
|
||||
this.loading.all = true;
|
||||
let userid = this.user.id;
|
||||
let enabled = !this.user.enabled;
|
||||
return this.$store.dispatch('enableDisableUser', {userid, enabled})
|
||||
.then(() => {
|
||||
this.loading.delete = false
|
||||
this.loading.all = false
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* Set user displayName
|
||||
*
|
||||
|
|
|
|||
|
|
@ -33,7 +33,7 @@ export default {
|
|||
.catch((error) => Promise.reject(error));
|
||||
},
|
||||
patch(url, data) {
|
||||
return axios.patch(sanitize(url), { data: data, headers: tokenHeaders.headers })
|
||||
return axios.patch(sanitize(url), data, tokenHeaders)
|
||||
.then((response) => Promise.resolve(response))
|
||||
.catch((error) => Promise.reject(error));
|
||||
},
|
||||
|
|
|
|||
|
|
@ -1,17 +1,23 @@
|
|||
import Vue from 'vue'
|
||||
import Vuex from 'vuex'
|
||||
import users from './users'
|
||||
import settings from './settings'
|
||||
import Vue from 'vue';
|
||||
import Vuex from 'vuex';
|
||||
import users from './users';
|
||||
import settings from './settings';
|
||||
|
||||
Vue.use(Vuex)
|
||||
|
||||
const debug = process.env.NODE_ENV !== 'production'
|
||||
const debug = process.env.NODE_ENV !== 'production';
|
||||
|
||||
const mutations = {
|
||||
API_FAILURE(state, error) {
|
||||
console.log(state, error);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const getters = {
|
||||
getRoute(state) {
|
||||
return state.route;
|
||||
}
|
||||
};
|
||||
|
||||
export default new Vuex.Store({
|
||||
modules: {
|
||||
|
|
@ -20,5 +26,6 @@ export default new Vuex.Store({
|
|||
},
|
||||
strict: debug,
|
||||
|
||||
mutations
|
||||
})
|
||||
mutations,
|
||||
getters
|
||||
});
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@ const state = {
|
|||
minPasswordLength: 0,
|
||||
usersOffset: 0,
|
||||
usersLimit: 25,
|
||||
userCount: 0
|
||||
};
|
||||
|
||||
const mutations = {
|
||||
|
|
@ -31,9 +32,10 @@ const mutations = {
|
|||
setPasswordPolicyMinLength(state, length) {
|
||||
state.minPasswordLength = length!=='' ? length : 0;
|
||||
},
|
||||
initGroups(state, {groups, orderBy}) {
|
||||
initGroups(state, {groups, orderBy, userCount}) {
|
||||
state.groups = groups;
|
||||
state.orderBy = orderBy;
|
||||
state.userCount = userCount;
|
||||
state.groups = orderGroups(state.groups, state.orderBy);
|
||||
},
|
||||
addGroup(state, groupid) {
|
||||
|
|
@ -87,7 +89,10 @@ const mutations = {
|
|||
},
|
||||
enableDisableUser(state, { userid, enabled }) {
|
||||
state.users.find(user => user.id == userid).enabled = enabled;
|
||||
// increment or not
|
||||
state.groups.find(group => group.id == '_disabled').usercount += enabled ? -1 : 1;
|
||||
state.userCount += enabled ? 1 : -1;
|
||||
console.log(enabled);
|
||||
},
|
||||
setUserData(state, { userid, key, value }) {
|
||||
if (key === 'quota') {
|
||||
|
|
@ -97,6 +102,14 @@ const mutations = {
|
|||
state.users.find(user => user.id == userid)[key] = value;
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Reset users list
|
||||
*/
|
||||
resetUsers(state) {
|
||||
state.users = [];
|
||||
state.usersOffset = 0;
|
||||
}
|
||||
};
|
||||
|
||||
const getters = {
|
||||
|
|
@ -114,10 +127,14 @@ const getters = {
|
|||
},
|
||||
getUsersLimit(state) {
|
||||
return state.usersLimit;
|
||||
},
|
||||
getUserCount(state) {
|
||||
return state.userCount;
|
||||
}
|
||||
};
|
||||
|
||||
const actions = {
|
||||
|
||||
/**
|
||||
* Get all users with full details
|
||||
*
|
||||
|
|
@ -125,10 +142,25 @@ const actions = {
|
|||
* @param {Object} options
|
||||
* @param {int} options.offset List offset to request
|
||||
* @param {int} options.limit List number to return from offset
|
||||
* @param {string} options.search Search amongst users
|
||||
* @param {string} options.group Get users from group
|
||||
* @returns {Promise}
|
||||
*/
|
||||
getUsers(context, { offset, limit, search }) {
|
||||
getUsers(context, { offset, limit, search, group }) {
|
||||
search = typeof search === 'string' ? search : '';
|
||||
group = typeof group === 'string' ? group : '';
|
||||
if (group !== '') {
|
||||
return api.get(OC.linkToOCS(`cloud/groups/${group}/users/details?offset=${offset}&limit=${limit}&search=${search}`, 2))
|
||||
.then((response) => {
|
||||
if (Object.keys(response.data.ocs.data.users).length > 0) {
|
||||
context.commit('appendUsers', response.data.ocs.data.users);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
})
|
||||
.catch((error) => context.commit('API_FAILURE', error));
|
||||
}
|
||||
|
||||
return api.get(OC.linkToOCS(`cloud/users/details?offset=${offset}&limit=${limit}&search=${search}`, 2))
|
||||
.then((response) => {
|
||||
if (Object.keys(response.data.ocs.data.users).length > 0) {
|
||||
|
|
@ -200,7 +232,7 @@ const actions = {
|
|||
},
|
||||
|
||||
/**
|
||||
* Add group
|
||||
* Remove group
|
||||
*
|
||||
* @param {Object} context
|
||||
* @param {string} gid Group id
|
||||
|
|
@ -289,7 +321,7 @@ const actions = {
|
|||
* @param {string} userid User id
|
||||
* @returns {Promise}
|
||||
*/
|
||||
deleteUser(context, userid) {
|
||||
deleteUser(context, { userid }) {
|
||||
return api.requireAdmin().then((response) => {
|
||||
return api.delete(OC.linkToOCS(`cloud/users/${userid}`, 2))
|
||||
.then((response) => context.commit('deleteUser', userid))
|
||||
|
|
@ -305,12 +337,19 @@ const actions = {
|
|||
* @param {string} options.userid User id
|
||||
* @param {string} options.password User password
|
||||
* @param {string} options.email User email
|
||||
* @param {string} options.groups User groups
|
||||
* @param {string} options.subadmin User subadmin groups
|
||||
* @param {string} options.quota User email
|
||||
* @returns {Promise}
|
||||
*/
|
||||
addUser({context, dispatch}, {userid, password, email, groups}) {
|
||||
addUser({context, dispatch}, { userid, password, email, groups, subadmin, quota }) {
|
||||
console.log(subadmin, quota);
|
||||
return api.requireAdmin().then((response) => {
|
||||
return api.post(OC.linkToOCS(`cloud/users`, 2), {userid, password, email, groups})
|
||||
.then((response) => dispatch('addUserData', userid))
|
||||
return api.post(OC.linkToOCS(`cloud/users`, 2), { userid, password, email, groups, subadmin, quota })
|
||||
.then((response) => {
|
||||
//let quotaDis = dispatch('setUserData', { userid, key: 'quota', value:quota });
|
||||
//let subadminDis = dispatch('addUserSubAdmin', userid);
|
||||
})
|
||||
.catch((error) => context.commit('API_FAILURE', { userid, error }));
|
||||
});
|
||||
},
|
||||
|
|
|
|||
|
|
@ -39,7 +39,8 @@ export default {
|
|||
beforeMount() {
|
||||
this.$store.commit('initGroups', {
|
||||
groups: this.$store.getters.getServerData.groups,
|
||||
orderBy: this.$store.getters.getServerData.sortGroups
|
||||
orderBy: this.$store.getters.getServerData.sortGroups,
|
||||
userCount: this.$store.getters.getServerData.userCount
|
||||
});
|
||||
this.$store.dispatch('getPasswordPolicyMinLength');
|
||||
},
|
||||
|
|
@ -66,6 +67,9 @@ export default {
|
|||
}
|
||||
},
|
||||
computed: {
|
||||
route() {
|
||||
return this.$store.getters.getRoute;
|
||||
},
|
||||
users() {
|
||||
return this.$store.getters.getUsers;
|
||||
},
|
||||
|
|
@ -96,6 +100,9 @@ export default {
|
|||
this.setLocalStorage('showStoragePath', status);
|
||||
}
|
||||
},
|
||||
userCount() {
|
||||
return this.$store.getters.getUserCount;
|
||||
},
|
||||
menu() {
|
||||
let self = this;
|
||||
// Data provided php side
|
||||
|
|
@ -114,24 +121,34 @@ export default {
|
|||
});
|
||||
|
||||
// Adjust data
|
||||
if (groups[0].id === 'admin') {
|
||||
groups[0].text = t('settings', 'Admins');} // rename admin group
|
||||
if (groups[1].id === '_disabled') {
|
||||
groups[1].text = t('settings', 'Disabled users'); // rename disabled group
|
||||
if (groups[1].utils.counter === 0) {
|
||||
groups.splice(1, 1); // remove disabled if empty
|
||||
let adminGroup = groups.find(group => group.id == 'admin');
|
||||
let disabledGroup = groups.find(group => group.id == '_disabled');
|
||||
if (adminGroup.text) {
|
||||
adminGroup.text = t('settings', 'Admins');} // rename admin group
|
||||
if (disabledGroup.text) {
|
||||
disabledGroup.text = t('settings', 'Disabled users'); // rename disabled group
|
||||
if (disabledGroup.utils.counter === 0) {
|
||||
groups.splice(groups.findIndex(group => group.id == '_disabled'), 1); // remove disabled if empty
|
||||
}
|
||||
}
|
||||
|
||||
// Add everyone group
|
||||
groups.unshift({
|
||||
id: '_everyone',
|
||||
classes: ['active'],
|
||||
classes: [],
|
||||
href:'#group_everyone',
|
||||
text: t('settings', 'Everyone'),
|
||||
utils: {counter: this.users.length}
|
||||
utils: {counter: this.userCount}
|
||||
});
|
||||
|
||||
// Set current group as active
|
||||
let activeGroup = groups.findIndex(group => group.href === this.route.hash);
|
||||
if (activeGroup >= 0) {
|
||||
groups[activeGroup].classes.push('active');
|
||||
} else {
|
||||
groups[0].classes.push('active');
|
||||
}
|
||||
|
||||
// Return
|
||||
return {
|
||||
id: 'usergrouplist',
|
||||
|
|
|
|||
|
|
@ -113,16 +113,22 @@ $disabledUsersGroup = [
|
|||
$allGroups = array_merge_recursive($adminGroup, $groups);
|
||||
|
||||
/* QUOTAS PRESETS */
|
||||
$quotaPreset=$config->getAppValue('files', 'quota_preset', '1 GB, 5 GB, 10 GB');
|
||||
$quotaPreset=explode(',', $quotaPreset);
|
||||
foreach($quotaPreset as &$preset) {
|
||||
$preset=trim($preset);
|
||||
$quotaPreset = $config->getAppValue('files', 'quota_preset', '1 GB, 5 GB, 10 GB');
|
||||
$quotaPreset = explode(',', $quotaPreset);
|
||||
foreach ($quotaPreset as &$preset) {
|
||||
$preset = trim($preset);
|
||||
}
|
||||
$quotaPreset=array_diff($quotaPreset, array('default', 'none'));
|
||||
$defaultQuota=$config->getAppValue('files', 'default_quota', 'none');
|
||||
$quotaPreset = array_diff($quotaPreset, array('default', 'none'));
|
||||
$defaultQuota = $config->getAppValue('files', 'default_quota', 'none');
|
||||
|
||||
\OC::$server->getEventDispatcher()->dispatch('OC\Settings\Users::loadAdditionalScripts');
|
||||
|
||||
/* TOTAL USERS COUNT */
|
||||
function addition($v, $w) {
|
||||
return $v+$w;
|
||||
}
|
||||
$userCount = array_reduce($userManager->countUsers(), 'addition', 0);
|
||||
|
||||
/* FINAL DATA */
|
||||
$serverData = array();
|
||||
// groups
|
||||
|
|
@ -132,7 +138,7 @@ $serverData['subadmingroups'] = $groups;
|
|||
$serverData['subadmins'] = $subAdmins;
|
||||
$serverData['sortGroups'] = $sortGroupsBy;
|
||||
$serverData['quotaPreset'] = $quotaPreset;
|
||||
$serverData['userCount'] = $userManager->countUsers();
|
||||
$serverData['userCount'] = $userCount-$disabledUsers;
|
||||
// Settings
|
||||
$serverData['defaultQuota'] = $defaultQuota;
|
||||
$serverData['canChangePassword'] = $canChangePassword;
|
||||
|
|
|
|||
Loading…
Reference in a new issue