Add create/delete capabilities and UI

This commit is contained in:
Lukas Hirt
2020-09-09 10:35:28 +02:00
parent 8700b63e2a
commit 1965469ae6
6 changed files with 218 additions and 6 deletions
+36 -3
View File
@@ -2,7 +2,16 @@
<div>
<div class="uk-container uk-padding">
<h1 v-text="$gettext('Accounts')" />
<oc-grid v-if="numberOfSelectedAccounts > 0" key="selected-accounts-info" gutter="small" class="uk-flex-middle">
<oc-button
v-if="numberOfSelectedAccounts < 1"
key="create-accounts-button"
v-text="$gettext('Create new user')"
variation="primary"
:disabled="isAccountCreationInProgress || !isInitialized"
:uk-tooltip="disabledCreateAccountBtnTooltip"
@click="setAccountCreationProgress(true)"
/>
<oc-grid v-else key="selected-accounts-info" gutter="small" class="uk-flex-middle">
<span v-text="selectionInfoText" />
<span>|</span>
<div>
@@ -32,7 +41,11 @@
</div>
</oc-grid>
<template v-if="isInitialized">
<accounts-list :accounts="accounts" />
<accounts-list
:accounts="accounts"
:is-create-new-row-displayed="isAccountCreationInProgress"
@cancelAccountCreation="setAccountCreationProgress(false)"
/>
</template>
<oc-loader v-else />
</div>
@@ -45,6 +58,9 @@ import AccountsList from './accounts/AccountsList.vue'
export default {
name: 'App',
components: { AccountsList },
data: () => ({
isAccountCreationInProgress: false
}),
computed: {
...mapGetters('Accounts', ['isInitialized', 'getAccountsSorted']),
...mapState('Accounts', ['selectedAccounts']),
@@ -86,17 +102,34 @@ export default {
}
return actions
},
disabledCreateAccountBtnTooltip () {
if (!this.isInitialized) {
return this.$gettext('Loading users')
}
if (this.isAccountCreationInProgress) {
return this.$gettext('User creation is already in progress')
}
return null
}
},
methods: {
...mapActions('Accounts', ['initialize', 'toggleAccountStatus']),
...mapMutations('Accounts', ['RESET_ACCOUNTS_SELECTION'])
...mapMutations('Accounts', ['RESET_ACCOUNTS_SELECTION']),
setAccountCreationProgress (isInProgress) {
this.isAccountCreationInProgress = isInProgress
}
},
created () {
this.initialize()
},
beforeDestroy () {
this.RESET_ACCOUNTS_SELECTION()
this.setAccountCreationProgress(false)
}
}
</script>
+14 -2
View File
@@ -22,6 +22,7 @@
</oc-table-row>
</oc-table-group>
<oc-table-group>
<accounts-list-new-account-row v-if="isCreateNewRowDisplayed" @cancel="emitCreationCancel" />
<accounts-list-row
v-for="account in accounts"
:key="`account-list-row-${account.id}`"
@@ -35,23 +36,34 @@
<script>
import { mapActions, mapGetters } from 'vuex'
import AccountsListRow from './AccountsListRow.vue'
import AccountsListNewAccountRow from './AccountsListNewAccountRow.vue'
export default {
name: 'AccountsList',
components: {
AccountsListRow
AccountsListRow,
AccountsListNewAccountRow
},
props: {
accounts: {
type: Array,
required: true
},
isCreateNewRowDisplayed: {
type: Boolean,
required: false,
default: false
}
},
computed: {
...mapGetters('Accounts', ['areAllAccountsSelected'])
},
methods: {
...mapActions('Accounts', ['toggleSelectionAll'])
...mapActions('Accounts', ['toggleSelectionAll']),
emitCreationCancel () {
this.$emit('cancelAccountCreation')
}
}
}
</script>
@@ -0,0 +1,126 @@
<template>
<oc-table-row>
<oc-table-cell colspan="9">
<oc-grid gutter="small">
<label>
<oc-text-input
type="text"
v-model="username"
:error-message="usernameError"
:placeholder="$gettext('Username')"
@input="checkUsername"
/>
</label>
<label>
<oc-text-input
type="email"
v-model="email"
:error-message="emailError"
:placeholder="$gettext('Email')"
@input="checkEmail"
/>
</label>
<label class="uk-flex uk-flex-middle">
<oc-text-input
:type="passwordInputType"
v-model="password"
:error-message="passwordError"
:placeholder="$gettext('Password')"
class="uk-margin-xsmall-right"
@input="checkPassword"
/>
<oc-button variation="raw" :aria-label="$gettext('Display password')" @click="togglePasswordVisibility">
<oc-icon name="remove_red_eye" aria-hidden="true" size="small" />
</oc-button>
</label>
<div>
<oc-button v-text="$gettext('Cancel')" @click="emitCancel" class="uk-margin-xsmall-right" />
<oc-button v-text="$gettext('Create')" variation="primary" @click="createAccount" />
</div>
</oc-grid>
</oc-table-cell>
</oc-table-row>
</template>
<script>
import isEmail from 'validator/es/lib/isEmail'
import isEmpty from 'validator/es/lib/isEmpty'
import debounce from 'debounce'
import { mapActions } from 'vuex'
export default {
name: 'AccountsListNewAccountRow',
data: () => ({
username: '',
usernameError: '',
email: '',
emailError: '',
password: '',
passwordError: '',
passwordInputType: 'password'
}),
methods: {
...mapActions('Accounts', ['createNewAccount']),
emitCancel () {
this.$emit('cancel')
},
createAccount () {
this.checkUsername()
this.checkEmail()
this.checkPassword()
if (this.usernameError !== '' || this.emailError !== '' || this.passwordError !== '') {
return
}
this.createNewAccount({ username: this.username, email: this.email, password: this.password })
},
checkUsername () {
if (isEmpty(this.username)) {
debounce(this.usernameError = this.$gettext('Username cannot be empty'), 500)
return
}
this.usernameError = ''
},
checkEmail () {
if (isEmpty(this.email)) {
debounce(this.emailError = this.$gettext('Email cannot be empty'), 500)
return
}
if (!isEmail(this.email)) {
debounce(this.emailError = this.$gettext('Invalid email address'), 500)
return
}
this.emailError = ''
},
checkPassword () {
// Later on some restrictions might be applied here
if (isEmpty(this.password)) {
debounce(this.passwordError = this.$gettext('Password cannot be empty'), 500)
return
}
this.passwordError = ''
},
togglePasswordVisibility () {
this.passwordInputType === 'password'
? this.passwordInputType = 'text'
: this.passwordInputType = 'password'
}
}
}
</script>
+34 -1
View File
@@ -1,5 +1,5 @@
/* eslint-disable camelcase */
import { AccountsService_ListAccounts, AccountsService_UpdateAccount } from '../client/accounts'
import { AccountsService_ListAccounts, AccountsService_UpdateAccount, AccountsService_CreateAccount } from '../client/accounts'
import { RoleService_ListRoles } from '../client/settings'
/* eslint-enable camelcase */
import { injectAuthToken } from '../helpers/auth'
@@ -56,6 +56,10 @@ const mutations = {
RESET_ACCOUNTS_SELECTION (state) {
state.selectedAccounts = []
},
PUSH_NEW_ACCOUNT (state, account) {
state.accounts.push(account)
}
}
@@ -164,6 +168,35 @@ const actions = {
}
commit('RESET_ACCOUNTS_SELECTION')
},
async createNewAccount ({ rootGetters, commit, dispatch }, account) {
injectAuthToken(rootGetters.user.token)
const response = await AccountsService_CreateAccount({
$domain: rootGetters.configuration.server,
body: {
account: {
on_premises_sam_account_name: account.username,
mail: account.email,
password_profile: {
password: account.password
},
account_enabled: true,
display_name: account.username
}
}
})
if (response.status === 201) {
commit('PUSH_NEW_ACCOUNT', account)
console.log(response)
} else {
dispatch('showMessage', {
title: 'Failed to create account',
desc: response.statusText,
status: 'danger'
}, { root: true })
}
}
}