Add batch actions UI

This commit is contained in:
Lukas Hirt
2020-09-06 21:40:15 +02:00
parent 8e665bb126
commit 45c170729e
4 changed files with 115 additions and 5 deletions
+70 -1
View File
@@ -4,6 +4,29 @@
<h1>
Accounts
</h1>
<oc-grid v-if="selectedAccountsAmount > 0" key="selected-accounts-info" gutter="small" class="uk-flex-middle">
<span v-text="selectionInfoText" />
<div>
<oc-action-drop>
<template v-slot:button>
<span class="uk-margin-xsmall-right" v-text="$gettext('Actions')" />
<oc-icon name="expand_more" />
</template>
<template v-slot:actions>
<oc-button
v-for="(action, index) in actions"
:key="action.label"
variation="raw"
role="menuitem"
:class="{ 'uk-margin-small-bottom': index + 1 !== actions.length }"
class="uk-width-1-1 uk-flex-left"
>
{{ action.label }}
</oc-button>
</template>
</oc-action-drop>
</div>
</oc-grid>
<template v-if="isInitialized">
<accounts-list :accounts="accounts" />
</template>
@@ -13,15 +36,47 @@
</template>
<script>
import { mapGetters, mapActions } from 'vuex'
import { mapGetters, mapActions, mapState } from 'vuex'
import AccountsList from './accounts/AccountsList.vue'
export default {
name: 'App',
components: { AccountsList },
computed: {
...mapGetters('Accounts', ['isInitialized', 'getAccountsSorted']),
...mapState('Accounts', ['selectedAccounts']),
accounts () {
return this.getAccountsSorted
},
selectedAccountsAmount () {
return this.selectedAccounts.length
},
selectionInfoText () {
const translated = this.$ngettext('%{ amount } selected user', '%{ amount } selected users', this.selectedAccountsAmount)
return this.$gettextInterpolate(translated, { amount: this.selectedAccountsAmount })
},
actions () {
const actions = []
const isAnyAccountDisabled = this.selectedAccounts.some(account => !account.accountEnabled)
const isAnyAccountEnabled = this.selectedAccounts.some(account => account.accountEnabled)
if (isAnyAccountDisabled) {
actions.push({
label: this.$gettext('Enable')
})
}
if (isAnyAccountEnabled) {
actions.push({
label: this.$gettext('Disable')
})
}
return actions
}
},
methods: {
@@ -32,3 +87,17 @@ export default {
}
}
</script>
<style>
/* TODO: After https://github.com/owncloud/owncloud-design-system/pull/418 gets merged
there won't be an extra span and this won't be needed anymore */
.accounts-selection-actions-btn > span {
display: flex;
align-items: center;
}
/* TODO: Adjust in ODS */
.oc-dropdown-menu {
width: 150px;
}
</style>
+19
View File
@@ -3,6 +3,14 @@
<oc-table middle divider>
<oc-table-group>
<oc-table-row>
<oc-table-cell shrink type="head">
<oc-checkbox
:value="areAllAccountsSelected"
:label="$gettext('Select all users')"
hide-label
@change="toggleAllAccountsSelection"
/>
</oc-table-cell>
<oc-table-cell shrink type="head" />
<oc-table-cell type="head" v-text="$gettext('Username')" />
<oc-table-cell type="head" v-text="$gettext('Display name')" />
@@ -25,6 +33,7 @@
</template>
<script>
import { mapActions, mapGetters } from 'vuex'
import AccountsListRow from './AccountsListRow.vue'
export default {
@@ -37,6 +46,16 @@ export default {
type: Array,
required: true
}
},
computed: {
...mapGetters('Accounts', ['areAllAccountsSelected'])
},
methods: {
...mapActions('Accounts', ['toggleSelectionAll']),
toggleAllAccountsSelection () {
this.toggleSelectionAll()
}
}
}
</script>
+10 -2
View File
@@ -1,5 +1,8 @@
<template>
<oc-table-row>
<oc-table-cell>
<oc-checkbox :value="isAccountSelected" @change="TOGGLE_SELECTION_ACCOUNT(account)" />
</oc-table-cell>
<oc-table-cell>
<avatar :user-name="account.displayName || account.onPremisesSamAccountName" :userid="account.id" :width="35" />
</oc-table-cell>
@@ -46,7 +49,7 @@
</template>
<script>
import { mapGetters, mapState, mapActions } from 'vuex'
import { mapGetters, mapState, mapActions, mapMutations } from 'vuex'
import { isObjectEmpty } from '../../helpers/utils'
import { injectAuthToken } from '../../helpers/auth'
// eslint-disable-next-line camelcase
@@ -73,7 +76,11 @@ export default {
computed: {
...mapGetters(['user', 'configuration']),
...mapState('Accounts', ['roles'])
...mapState('Accounts', ['roles', 'selectedAccounts']),
isAccountSelected () {
return this.selectedAccounts.indexOf(this.account) > -1
}
},
created () {
@@ -82,6 +89,7 @@ export default {
methods: {
...mapActions(['showMessage']),
...mapMutations('Accounts', ['TOGGLE_SELECTION_ACCOUNT']),
async changeRole (roleId) {
injectAuthToken(this.user.token)
+16 -2
View File
@@ -8,7 +8,8 @@ const state = {
config: null,
initialized: false,
accounts: {},
roles: null
roles: null,
selectedAccounts: []
}
const getters = {
@@ -21,7 +22,8 @@ const getters = {
}
return a1.onPremisesSamAccountName.localeCompare(a2.onPremisesSamAccountName)
})
}
},
areAllAccountsSelected: state => state.accounts.length === state.selectedAccounts.length
}
const mutations = {
@@ -36,6 +38,14 @@ const mutations = {
},
SET_ROLES (state, roles) {
state.roles = roles
},
TOGGLE_SELECTION_ACCOUNT (state, account) {
const accountIndex = state.selectedAccounts.indexOf(account)
accountIndex > -1 ? state.selectedAccounts.splice(accountIndex, 1) : state.selectedAccounts.push(account)
},
SET_SELECTED_ACCOUNTS (state, accounts) {
state.selectedAccounts = accounts
}
}
@@ -87,6 +97,10 @@ const actions = {
status: 'danger'
}, { root: true })
}
},
toggleSelectionAll ({ commit, getters, state }) {
getters.areAllAccountsSelected ? commit('SET_SELECTED_ACCOUNTS', []) : commit('SET_SELECTED_ACCOUNTS', [...state.accounts])
}
}