Signed-off-by: John Molakvoæ (skjnldsv) <skjnldsv@protonmail.com>tags/v14.0.0beta1
@@ -5,7 +5,7 @@ | |||
<script> | |||
export default { | |||
name: 'App', | |||
beforeMount: function () { | |||
beforeMount: function() { | |||
// importing server data into the store | |||
const serverDataElmt = document.getElementById('serverData'); | |||
if (serverDataElmt !== null) { |
@@ -92,18 +92,18 @@ export default { | |||
} | |||
}, | |||
methods: { | |||
showMenu () { | |||
showMen() { | |||
this.openedMenu = true; | |||
}, | |||
hideMenu () { | |||
hideMenu() { | |||
this.openedMenu = false; | |||
}, | |||
toggleCollapse () { | |||
toggleCollapse() { | |||
// if item.opened isn't set, Vue won't trigger view updates https://vuejs.org/v2/api/#Vue-set | |||
// ternary is here to detect the undefined state of item.opened | |||
Vue.set(this.item, 'opened', this.item.opened ? !this.item.opened : true); | |||
}, | |||
cancelEdit () { | |||
cancelEdit() { | |||
// remove the editing class | |||
if (Array.isArray(this.item.classes)) | |||
this.item.classes = this.item.classes.filter(item => item !== 'editing'); |
@@ -238,11 +238,14 @@ export default { | |||
}, | |||
infiniteHandler($state) { | |||
this.$store.dispatch('getUsers', {offset:this.usersOffset, limit:this.usersLimit, group:this.selectedGroup}) | |||
this.$store.dispatch('getUsers', { | |||
offset: this.usersOffset, | |||
limit: this.usersLimit, | |||
group: this.selectedGroup !== 'disabled' ? this.selectedGroup : ''}) | |||
.then((response) => {response?$state.loaded():$state.complete()}); | |||
}, | |||
resetForm () { | |||
resetForm() { | |||
// revert form to original state | |||
Object.assign(this.newUser, this.$options.data.call(this).newUser); | |||
this.loading = false; |
@@ -413,7 +413,7 @@ export default { | |||
// unify format output | |||
return this.setUserQuota(OC.Util.humanFileSize(OC.Util.computerFileSize(quota))); | |||
} | |||
// if no valid doo not change | |||
// if no valid do not change | |||
return false; | |||
}, | |||
@@ -4,7 +4,7 @@ const requestToken = document.getElementsByTagName('head')[0].getAttribute('data | |||
const tokenHeaders = { headers: { requesttoken: requestToken } }; | |||
const sanitize = function(url) { | |||
return url.replace(/\/$/, ''); // Remove last slash of url | |||
return url.replace(/\/$/, ''); // Remove last url slash | |||
}; | |||
export default { | |||
@@ -95,5 +95,19 @@ export default { | |||
return axios.delete(sanitize(url), { data: data, headers: tokenHeaders.headers }) | |||
.then((response) => Promise.resolve(response)) | |||
.catch((error) => Promise.reject(error)); | |||
}, | |||
// OCS API entry points | |||
/** | |||
* | |||
* @param {string} app Application name | |||
* @param {string} key Config key | |||
* @param {string} [value=''] Value to set | |||
* @returns{Promise} | |||
*/ | |||
setAppConfig(app, key, value = '') { | |||
return this.requireAdmin().then((response) => { | |||
return this.post(OC.linkToOCS(`apps/provisioning_api/api/v1/config/apps/${app}/${key}`, 2), {value: value}); | |||
}); | |||
} | |||
}; |
@@ -12,7 +12,7 @@ const getters = { | |||
getServerData(state) { | |||
return state.serverData; | |||
} | |||
} | |||
const actions = {} | |||
}; | |||
const actions = {}; | |||
export default {state, mutations, getters, actions}; |
@@ -38,11 +38,11 @@ const mutations = { | |||
state.userCount = userCount; | |||
state.groups = orderGroups(state.groups, state.orderBy); | |||
}, | |||
addGroup(state, groupid) { | |||
addGroup(state, gid) { | |||
try { | |||
state.groups.push({ | |||
id: groupid, | |||
name: groupid, | |||
id: gid, | |||
name: gid, | |||
usercount: 0 // user will be added after the creation | |||
}); | |||
state.groups = orderGroups(state.groups, state.orderBy); | |||
@@ -50,6 +50,12 @@ const mutations = { | |||
console.log('Can\'t create group', e); | |||
} | |||
}, | |||
removeGroup(state, gid) { | |||
let groupIndex = state.groups.findIndex(groupSearch => groupSearch.id == gid); | |||
if (groupIndex >= 0) { | |||
state.groups.splice(groupIndex, 1); | |||
} | |||
}, | |||
addUserGroup(state, { userid, gid }) { | |||
// this should not be needed as it would means the user contains a group | |||
// the server database doesn't have. | |||
@@ -144,7 +150,7 @@ const actions = { | |||
* @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 | |||
* @returns {Promise} | |||
*/ | |||
getUsers(context, { offset, limit, search, group }) { | |||
search = typeof search === 'string' ? search : ''; | |||
@@ -179,7 +185,7 @@ const actions = { | |||
* @param {Object} options | |||
* @param {int} options.offset List offset to request | |||
* @param {int} options.limit List number to return from offset | |||
* @returns Promise | |||
* @returns {Promise} | |||
*/ | |||
getUsersFromList(context, { offset, limit, search }) { | |||
search = typeof search === 'string' ? search : ''; | |||
@@ -201,7 +207,7 @@ const actions = { | |||
* @param {Object} options | |||
* @param {int} options.offset List offset to request | |||
* @param {int} options.limit List number to return from offset | |||
* @returns Promise | |||
* @returns {Promise} | |||
*/ | |||
getUsersFromGroup(context, { groupid, offset, limit }) { | |||
return api.get(OC.linkToOCS(`cloud/users/${groupid}/details?offset=${offset}&limit=${limit}`, 2)) | |||
@@ -221,7 +227,7 @@ const actions = { | |||
* | |||
* @param {Object} context | |||
* @param {string} gid Group id | |||
* @returns Promise | |||
* @returns {Promise} | |||
*/ | |||
addGroup(context, gid) { | |||
return api.requireAdmin().then((response) => { | |||
@@ -236,14 +242,14 @@ const actions = { | |||
* | |||
* @param {Object} context | |||
* @param {string} gid Group id | |||
* @returns Promise | |||
* @returns {Promise} | |||
*/ | |||
removeGroup(context, gid) { | |||
return api.requireAdmin().then((response) => { | |||
return api.post(OC.linkToOCS(`cloud/groups`, 2), {groupid: gid}) | |||
return api.delete(OC.linkToOCS(`cloud/groups/${gid}`, 2)) | |||
.then((response) => context.commit('removeGroup', gid)) | |||
.catch((error) => {throw error;}); | |||
}).catch((error) => context.commit('API_FAILURE', { userid, error })); | |||
}).catch((error) => context.commit('API_FAILURE', { gid, error })); | |||
}, | |||
/** | |||
@@ -253,7 +259,7 @@ const actions = { | |||
* @param {Object} options | |||
* @param {string} options.userid User id | |||
* @param {string} options.gid Group id | |||
* @returns Promise | |||
* @returns {Promise} | |||
*/ | |||
addUserGroup(context, { userid, gid }) { | |||
return api.requireAdmin().then((response) => { | |||
@@ -270,7 +276,7 @@ const actions = { | |||
* @param {Object} options | |||
* @param {string} options.userid User id | |||
* @param {string} options.gid Group id | |||
* @returns Promise | |||
* @returns {Promise} | |||
*/ | |||
removeUserGroup(context, { userid, gid }) { | |||
return api.requireAdmin().then((response) => { | |||
@@ -287,7 +293,7 @@ const actions = { | |||
* @param {Object} options | |||
* @param {string} options.userid User id | |||
* @param {string} options.gid Group id | |||
* @returns Promise | |||
* @returns {Promise} | |||
*/ | |||
addUserSubAdmin(context, { userid, gid }) { | |||
return api.requireAdmin().then((response) => { | |||
@@ -304,7 +310,7 @@ const actions = { | |||
* @param {Object} options | |||
* @param {string} options.userid User id | |||
* @param {string} options.gid Group id | |||
* @returns Promise | |||
* @returns {Promise} | |||
*/ | |||
removeUserSubAdmin(context, { userid, gid }) { | |||
return api.requireAdmin().then((response) => { | |||
@@ -319,7 +325,7 @@ const actions = { | |||
* | |||
* @param {Object} context | |||
* @param {string} userid User id | |||
* @returns Promise | |||
* @returns {Promise} | |||
*/ | |||
deleteUser(context, { userid }) { | |||
return api.requireAdmin().then((response) => { | |||
@@ -340,7 +346,7 @@ const actions = { | |||
* @param {string} options.groups User groups | |||
* @param {string} options.subadmin User subadmin groups | |||
* @param {string} options.quota User email | |||
* @returns Promise | |||
* @returns {Promise} | |||
*/ | |||
addUser({context, dispatch}, { userid, password, email, groups, subadmin, quota, language }) { | |||
return api.requireAdmin().then((response) => { | |||
@@ -355,7 +361,7 @@ const actions = { | |||
* | |||
* @param {Object} context | |||
* @param {string} userid User id | |||
* @returns Promise | |||
* @returns {Promise} | |||
*/ | |||
addUserData(context, userid) { | |||
return api.requireAdmin().then((response) => { | |||
@@ -371,7 +377,7 @@ const actions = { | |||
* @param {Object} options | |||
* @param {string} options.userid User id | |||
* @param {boolean} options.enabled User enablement status | |||
* @returns Promise | |||
* @returns {Promise} | |||
*/ | |||
enableDisableUser(context, { userid, enabled = true }) { | |||
let userStatus = enabled ? 'enable' : 'disable'; | |||
@@ -390,7 +396,7 @@ const actions = { | |||
* @param {string} options.userid User id | |||
* @param {string} options.key User field to edit | |||
* @param {string} options.value Value of the change | |||
* @returns Promise | |||
* @returns {Promise} | |||
*/ | |||
setUserData(context, { userid, key, value }) { | |||
let allowedEmpty = ['email', 'displayname']; |
@@ -2,6 +2,16 @@ | |||
<div id="app"> | |||
<app-navigation :menu="menu"> | |||
<template slot="settings-content"> | |||
<div> | |||
<p>{{t('settings', 'Default quota :')}}</p> | |||
<multiselect :value="defaultQuota" :options="quotaOptions" | |||
tag-placeholder="create" :placeholder="t('settings', 'Select default quota')" | |||
label="label" track-by="id" class="multiselect-vue" | |||
:allowEmpty="false" :taggable="true" | |||
@tag="validateQuota" @input="setDefaultQuota"> | |||
</multiselect> | |||
</div> | |||
<div> | |||
<input type="checkbox" id="showLanguages" class="checkbox" | |||
:checked="showLanguages" v-model="showLanguages"> | |||
@@ -33,6 +43,10 @@ import appNavigation from '../components/appNavigation'; | |||
import userList from '../components/userList'; | |||
import Vue from 'vue'; | |||
import VueLocalStorage from 'vue-localstorage' | |||
import Multiselect from 'vue-multiselect'; | |||
import api from '../store/api'; | |||
Vue.use(VueLocalStorage) | |||
Vue.use(VueLocalStorage) | |||
export default { | |||
@@ -40,7 +54,8 @@ export default { | |||
props: ['selectedGroup'], | |||
components: { | |||
appNavigation, | |||
userList | |||
userList, | |||
Multiselect | |||
}, | |||
beforeMount() { | |||
this.$store.commit('initGroups', { | |||
@@ -52,6 +67,8 @@ export default { | |||
}, | |||
data() { | |||
return { | |||
// default quota is unlimited | |||
unlimitedQuota: {id:'default', label:t('settings', 'Unlimited')}, | |||
showConfig: { | |||
showStoragePath: false, | |||
showUserBackend: false, | |||
@@ -71,12 +88,53 @@ export default { | |||
this.showConfig[key] = status; | |||
this.$localStorage.set(key, status); | |||
return status; | |||
} | |||
}, | |||
removeGroup(groupid) { | |||
let self = this; | |||
// TODO migrate to a vue js confirm dialog component | |||
OC.dialogs.confirm( | |||
t('settings', 'You are about to remove the group {group}. The users will NOT be deleted.', {group: groupid}), | |||
t('settings','Please confirm the group removal '), | |||
function (success) { | |||
if (success) { | |||
self.$store.dispatch('removeGroup', groupid); | |||
} | |||
} | |||
); | |||
}, | |||
/** | |||
* Dispatch default quota set request | |||
* | |||
* @param {string|Object} quota Quota in readable format '5 GB' or Object {id: '5 GB', label: '5GB'} | |||
* @returns {string} | |||
*/ | |||
setDefaultQuota(quota = 'none') { | |||
// ensure we only send the preset id | |||
quota = quota.id ? quota.id : quota; | |||
api.setAppConfig('files', 'default_quota', quota); | |||
}, | |||
/** | |||
* Validate quota string to make sure it's a valid human file size | |||
* | |||
* @param {string} quota Quota in readable format '5 GB' | |||
* @returns {Promise|boolean} | |||
*/ | |||
validateQuota(quota) { | |||
// only used for new presets sent through @Tag | |||
let validQuota = OC.Util.computerFileSize(quota); | |||
if (validQuota === 0) { | |||
return this.setDefaultQuota('none'); | |||
} else if (validQuota !== null) { | |||
// unify format output | |||
return this.setDefaultQuota(OC.Util.humanFileSize(OC.Util.computerFileSize(quota))); | |||
} | |||
// if no valid do not change | |||
return false; | |||
}, | |||
}, | |||
computed: { | |||
route() { | |||
return this.$store.getters.getRoute; | |||
}, | |||
users() { | |||
return this.$store.getters.getUsers; | |||
}, | |||
@@ -119,7 +177,28 @@ export default { | |||
userCount() { | |||
return this.$store.getters.getUserCount; | |||
}, | |||
settings() { | |||
return this.$store.getters.getServerData; | |||
}, | |||
// default quota | |||
quotaOptions() { | |||
// convert the preset array into objects | |||
let quotaPreset = this.settings.quotaPreset.reduce((acc, cur) => acc.concat({id:cur, label:cur}), []); | |||
// add default presets | |||
quotaPreset.unshift(this.unlimitedQuota); | |||
return quotaPreset; | |||
}, | |||
// mapping saved values to objects | |||
defaultQuota() { | |||
if (OC.Util.computerFileSize(this.settings.defaultQuota) > 0) { | |||
// if value is valid, let's map the quotaOptions or return custom quota | |||
return {id:this.settings.defaultQuota, label:this.settings.defaultQuota}; | |||
} | |||
return this.unlimitedQuota; // unlimited | |||
}, | |||
// BUILD APP NAVIGATION MENU OBJECT | |||
menu() { | |||
// Data provided php side | |||
let groups = this.$store.getters.getGroups; | |||
@@ -143,7 +222,7 @@ export default { | |||
item.utils.actions = [{ | |||
icon: 'icon-delete', | |||
text: t('settings', 'Remove group'), | |||
action: () => {} | |||
action: function() {self.removeGroup(item.id)} | |||
}]; | |||
}; | |||
return item; | |||
@@ -192,10 +271,6 @@ export default { | |||
items: groups | |||
} | |||
}, | |||
removeGroup(groupid) { | |||
console.trace(this); | |||
return this.$store.dispatch('removeGroup', groupid); | |||
} | |||
} | |||
} | |||
</script> |