123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433 |
- <!--
- - @copyright Copyright (c) 2018 John Molakvoæ <skjnldsv@protonmail.com>
- -
- - @author John Molakvoæ <skjnldsv@protonmail.com>
- -
- - @license GNU AGPL version 3 or any later version
- -
- - This program is free software: you can redistribute it and/or modify
- - it under the terms of the GNU Affero General Public License as
- - published by the Free Software Foundation, either version 3 of the
- - License, or (at your option) any later version.
- -
- - This program 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 program. If not, see <http://www.gnu.org/licenses/>.
- -
- -->
-
- <template>
- <AppContent app-name="settings" :navigation-class="{ 'icon-loading': loading }">
- <template #navigation>
- <AppNavigationNew button-id="new-user-button" :text="t('settings','New user')" button-class="icon-add" @click="toggleNewUserMenu" />
- <ul id="usergrouplist">
- <AppNavigationItem v-for="item in menu" :key="item.key" :item="item" />
- </ul>
- <AppNavigationSettings>
- <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" v-model="showLanguages">
- <label for="showLanguages">{{t('settings', 'Show Languages')}}</label>
- </div>
- <div>
- <input type="checkbox" id="showLastLogin" class="checkbox" v-model="showLastLogin">
- <label for="showLastLogin">{{t('settings', 'Show last login')}}</label>
- </div>
- <div>
- <input type="checkbox" id="showUserBackend" class="checkbox" v-model="showUserBackend">
- <label for="showUserBackend">{{t('settings', 'Show user backend')}}</label>
- </div>
- <div>
- <input type="checkbox" id="showStoragePath" class="checkbox" v-model="showStoragePath">
- <label for="showStoragePath">{{t('settings', 'Show storage path')}}</label>
- </div>
- </AppNavigationSettings>
- </template>
- <template #content>
- <user-list :users="users" :showConfig="showConfig" :selectedGroup="selectedGroup" :externalActions="externalActions" />
- </template>
- </AppContent>
- </template>
-
- <script>
- import {
- AppContent,
- AppNavigationItem,
- AppNavigationNew,
- AppNavigationSettings,
- } from 'nextcloud-vue';
- 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)
-
- export default {
- name: 'Users',
- props: ['selectedGroup'],
- components: {
- AppContent,
- AppNavigationItem,
- AppNavigationNew,
- AppNavigationSettings,
- userList,
- Multiselect,
- },
- beforeMount() {
- this.$store.commit('initGroups', {
- groups: this.$store.getters.getServerData.groups,
- orderBy: this.$store.getters.getServerData.sortGroups,
- userCount: this.$store.getters.getServerData.userCount
- });
- this.$store.dispatch('getPasswordPolicyMinLength');
- },
- created() {
- // init the OCA.Settings.UserList object
- // and add the registerAction method
- Object.assign(OCA, {
- Settings: {
- UserList: {
- registerAction: this.registerAction
- }
- }
- });
- },
- data() {
- return {
- // default quota is set to unlimited
- unlimitedQuota: {id: 'none', label: t('settings', 'Unlimited')},
- // temporary value used for multiselect change
- selectedQuota: false,
- externalActions: [],
- showAddGroupEntry: false,
- loadingAddGroup: false,
- showConfig: {
- showStoragePath: false,
- showUserBackend: false,
- showLastLogin: false,
- showNewUserForm: false,
- showLanguages: false
- }
- }
- },
- methods: {
- toggleNewUserMenu() {
- this.showConfig.showNewUserForm = !this.showConfig.showNewUserForm;
- if (this.showConfig.showNewUserForm) {
- Vue.nextTick(() => {
- window.newusername.focus();
- });
- }
- },
- getLocalstorage(key) {
- // force initialization
- let localConfig = this.$localStorage.get(key);
- // if localstorage is null, fallback to original values
- this.showConfig[key] = localConfig !== null ? localConfig === 'true' : this.showConfig[key];
- return this.showConfig[key];
- },
- setLocalStorage(key, status) {
- 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') {
- this.$store.dispatch('setAppConfig', {
- app: 'files',
- key: 'default_quota',
- // ensure we only send the preset id
- value: quota.id ? quota.id : quota
- }).then(() => {
- if (typeof quota !== 'object') {
- quota = {id: quota, label: quota};
- }
- this.defaultQuota = 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;
- },
-
- /**
- * Register a new action for the user menu
- *
- * @param {string} icon the icon class
- * @param {string} text the text to display
- * @param {function} action the function to run
- */
- registerAction(icon, text, action) {
- this.externalActions.push({
- icon: icon,
- text: text,
- action: action
- });
- return this.externalActions;
- },
-
- /**
- * Create a new group
- *
- * @param {Object} event The form submit event
- */
- createGroup(event) {
- let gid = event.target[0].value;
- this.loadingAddGroup = true;
- this.$store.dispatch('addGroup', gid)
- .then(() => {
- this.showAddGroupEntry = false;
- this.loadingAddGroup = false;
- })
- .catch(() => {
- this.loadingAddGroup = false;
- });
- }
- },
- computed: {
- users() {
- return this.$store.getters.getUsers;
- },
- loading() {
- return Object.keys(this.users).length === 0;
- },
- usersOffset() {
- return this.$store.getters.getUsersOffset;
- },
- usersLimit() {
- return this.$store.getters.getUsersLimit;
- },
-
- // Local settings
- showLanguages: {
- get: function() {return this.getLocalstorage('showLanguages')},
- set: function(status) {
- this.setLocalStorage('showLanguages', status);
- }
- },
- showLastLogin: {
- get: function() {return this.getLocalstorage('showLastLogin')},
- set: function(status) {
- this.setLocalStorage('showLastLogin', status);
- }
- },
- showUserBackend: {
- get: function() {return this.getLocalstorage('showUserBackend')},
- set: function(status) {
- this.setLocalStorage('showUserBackend', status);
- }
- },
- showStoragePath: {
- get: function() {return this.getLocalstorage('showStoragePath')},
- set: function(status) {
- this.setLocalStorage('showStoragePath', status);
- }
- },
-
- 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: {
- get: function() {
- if (this.selectedQuota !== false) {
- return this.selectedQuota;
- }
- 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
- },
- set: function(quota) {
- this.selectedQuota = quota;
- }
-
- },
-
- // BUILD APP NAVIGATION MENU OBJECT
- menu() {
- // Data provided php side
- let self = this;
- let groups = this.$store.getters.getGroups;
- groups = Array.isArray(groups) ? groups : [];
-
- // Map groups
- groups = groups.map(group => {
- let item = {};
- item.id = group.id.replace(' ', '_');
- item.key = item.id;
- item.utils = {}
-
- // router link to
- item.router = {
- name: 'group',
- params: {selectedGroup: group.id}
- };
-
- // group name
- item.text = group.name;
- item.title = group.name;
-
- // users count for all groups
- if (group.usercount - group.disabled > 0 || group.usercount === -1) {
- item.utils.counter = group.usercount - group.disabled;
- }
-
- if (item.id !== 'admin' && item.id !== 'disabled' && this.settings.isAdmin) {
- // add delete button on real groups
- item.utils.actions = [{
- icon: 'icon-delete',
- text: t('settings', 'Remove group'),
- action: function() {
- self.removeGroup(group.id)
- }
- }];
- };
- return item;
- });
-
- // Every item is added on top of the array, so we're going backward
- // Groups, separator, disabled, admin, everyone
-
- // Add separator
- let realGroups = groups.find((group) => {return group.id !== 'disabled' && group.id !== 'admin'});
- realGroups = typeof realGroups === 'undefined' ? [] : realGroups;
- realGroups = Array.isArray(realGroups) ? realGroups : [realGroups];
- if (realGroups.length > 0) {
- let separator = {
- caption: true,
- text: t('settings', 'Groups')
- };
- groups.unshift(separator);
- }
-
- // Adjust admin and disabled groups
- let adminGroup = groups.find(group => group.id == 'admin');
- let disabledGroup = groups.find(group => group.id == 'disabled');
-
- // filter out admin and disabled
- groups = groups.filter(group => ['admin', 'disabled'].indexOf(group.id) === -1);
-
- if (adminGroup && adminGroup.text) {
- adminGroup.text = t('settings', 'Admins'); // rename admin group
- adminGroup.icon = 'icon-user-admin'; // set icon
- groups.unshift(adminGroup); // add admin group if present
- }
- if (disabledGroup && disabledGroup.text) {
- disabledGroup.text = t('settings', 'Disabled users'); // rename disabled group
- disabledGroup.icon = 'icon-disabled-users'; // set icon
- if (disabledGroup.utils && (
- disabledGroup.utils.counter > 0 // add disabled if not empty
- || disabledGroup.utils.counter === -1) // add disabled if ldap enabled
- ) {
- groups.unshift(disabledGroup);
- }
- }
-
-
- // Add everyone group
- let everyoneGroup = {
- id: 'everyone',
- key: 'everyone',
- icon: 'icon-contacts-dark',
- router: {name:'users'},
- text: t('settings', 'Everyone'),
- };
- // users count
- if (this.userCount > 0) {
- Vue.set(everyoneGroup, 'utils', {
- counter: this.userCount
- });
- }
- groups.unshift(everyoneGroup);
-
- let addGroup = {
- id: 'addgroup',
- key: 'addgroup',
- icon: 'icon-add',
- text: t('settings', 'Add group'),
- classes: this.loadingAddGroup ? 'icon-loading-small' : ''
- };
- if (this.showAddGroupEntry) {
- Vue.set(addGroup, 'edit', {
- text: t('settings', 'Add group'),
- action: this.createGroup,
- reset: function() {
- self.showAddGroupEntry = false
- }
- });
- addGroup.classes = 'editing';
- } else {
- Vue.set(addGroup, 'action', function() {
- self.showAddGroupEntry = true
- })
- }
- groups.unshift(addGroup);
-
- return groups;
- },
- }
- }
- </script>
|