[Refactor] Cleanup agent store and actions (#373)

* Cleanup agent store and actions

* Move set/create/update/destroy to helpers

* Update mutation specs

* Add specs for API helper

* Fix edit/delete action visibility

* Add actions specs

* Remove unused API helpers

* Remove duplicates

* Remove duplicates

* Fix duplicate
This commit is contained in:
Pranav Raj S
2019-12-21 22:54:35 +05:30
committed by Sojan Jose
parent a92e3817f8
commit 2ce7438c79
26 changed files with 613 additions and 576 deletions

View File

@@ -1,6 +1,5 @@
<template>
<woot-modal :show.sync="show" :on-close="onClose">
<div class="column content-box">
<woot-modal-header
:header-image="headerImage"
@@ -8,15 +7,20 @@
:header-content="$t('AGENT_MGMT.ADD.DESC')"
/>
<form class="row" v-on:submit.prevent="addAgent()">
<form class="row" @submit.prevent="addAgent()">
<div class="medium-12 columns">
<label :class="{ 'error': $v.agentName.$error }">
<label :class="{ error: $v.agentName.$error }">
{{ $t('AGENT_MGMT.ADD.FORM.NAME.LABEL') }}
<input type="text" v-model.trim="agentName" @input="$v.agentName.$touch" :placeholder="$t('AGENT_MGMT.ADD.FORM.NAME.PLACEHOLDER')">
<input
v-model.trim="agentName"
type="text"
:placeholder="$t('AGENT_MGMT.ADD.FORM.NAME.PLACEHOLDER')"
@input="$v.agentName.$touch"
/>
</label>
</div>
<div class="medium-12 columns">
<label :class="{ 'error': $v.agentType.$error }">
<label :class="{ error: $v.agentType.$error }">
{{ $t('AGENT_MGMT.ADD.FORM.AGENT_TYPE.LABEL') }}
<multiselect
v-model="agentType"
@@ -24,27 +28,36 @@
:searchable="false"
label="label"
:placeholder="$t('AGENT_MGMT.ADD.FORM.AGENT_TYPE.PLACEHOLDER')"
@select="setPageName"
:allow-empty="true"
:close-on-select="true"
@select="setPageName"
/>
<span class="message" v-if="$v.agentType.$error">
<span v-if="$v.agentType.$error" class="message">
{{ $t('AGENT_MGMT.ADD.FORM.AGENT_TYPE.ERROR') }}
</span>
</label>
</div>
<div class="medium-12 columns">
<label :class="{ 'error': $v.agentEmail.$error }">
<label :class="{ error: $v.agentEmail.$error }">
{{ $t('AGENT_MGMT.ADD.FORM.EMAIL.LABEL') }}
<input type="text" v-model.trim="agentEmail" @input="$v.agentEmail.$touch" :placeholder="$t('AGENT_MGMT.ADD.FORM.EMAIL.PLACEHOLDER')">
<input
v-model.trim="agentEmail"
type="text"
:placeholder="$t('AGENT_MGMT.ADD.FORM.EMAIL.PLACEHOLDER')"
@input="$v.agentEmail.$touch"
/>
</label>
</div>
<div class="modal-footer">
<div class="medium-12 columns">
<woot-submit-button
:disabled="$v.agentEmail.$invalid || $v.agentName.$invalid || addAgentsApi.showLoading"
:disabled="
$v.agentEmail.$invalid ||
$v.agentName.$invalid ||
uiFlags.isCreating
"
:button-text="$t('AGENT_MGMT.ADD.FORM.SUBMIT')"
:loading="addAgentsApi.showLoading"
:loading="uiFlags.isCreating"
/>
<a @click="onClose">Cancel</a>
</div>
@@ -58,18 +71,12 @@
/* global bus */
/* eslint no-console: 0 */
import { required, minLength, email } from 'vuelidate/lib/validators';
import PageHeader from '../SettingsSubPageHeader';
import { mapGetters } from 'vuex';
const agentImg = require('assets/images/agent.svg');
export default {
props: [
'onClose',
],
components: {
PageHeader,
},
props: ['onClose'],
data() {
return {
agentName: '',
@@ -77,11 +84,6 @@ export default {
agentType: this.$t('AGENT_MGMT.AGENT_TYPES')[1],
vertical: 'bottom',
horizontal: 'center',
addAgentsApi: {
showAlert: false,
showLoading: false,
message: '',
},
agentTypeList: this.$t('AGENT_MGMT.AGENT_TYPES'),
show: true,
};
@@ -90,6 +92,9 @@ export default {
headerImage() {
return agentImg;
},
...mapGetters({
uiFlags: 'agents/getUIFlags',
}),
},
validations: {
agentName: {
@@ -110,36 +115,21 @@ export default {
this.$v.agentType.$touch();
this.agentType = name;
},
showAlert() {
bus.$emit('newToastMessage', this.addAgentsApi.message);
showAlert(message) {
bus.$emit('newToastMessage', message);
},
resetForm() {
this.agentName = this.agentEmail = '';
this.$v.agentName.$reset();
this.$v.agentEmail.$reset();
},
addAgent() {
// Show loading on button
this.addAgentsApi.showLoading = true;
// Make API Calls
this.$store.dispatch('addAgent', {
name: this.agentName,
email: this.agentEmail,
role: this.agentType.name.toLowerCase(),
})
.then(() => {
// Reset Form, Show success message
this.addAgentsApi.showLoading = false;
this.addAgentsApi.message = this.$t('AGENT_MGMT.ADD.API.SUCCESS_MESSAGE');
this.showAlert();
this.resetForm();
async addAgent() {
try {
await this.$store.dispatch('agents/create', {
name: this.agentName,
email: this.agentEmail,
role: this.agentType.name.toLowerCase(),
});
this.showAlert(this.$t('AGENT_MGMT.ADD.API.SUCCESS_MESSAGE'));
this.onClose();
})
.catch(() => {
this.addAgentsApi.showLoading = false;
this.addAgentsApi.message = this.$t('AGENT_MGMT.ADD.API.ERROR_MESSAGE');
this.showAlert();
});
} catch (error) {
this.showAlert(this.$t('AGENT_MGMT.ADD.API.ERROR_MESSAGE'));
}
},
},
};

View File

@@ -1,12 +1,6 @@
<template>
<modal
:show.sync="show"
:on-close="onClose"
>
<woot-modal-header
:header-title="title"
:header-content="message"
/>
<modal :show.sync="show" :on-close="onClose">
<woot-modal-header :header-title="title" :header-content="message" />
<div class="modal-footer delete-item">
<button class="button" @click="onClose">
{{ rejectText }}
@@ -19,13 +13,11 @@
</template>
<script>
import PageHeader from '../SettingsSubPageHeader';
import Modal from '../../../../components/Modal';
export default {
components: {
Modal,
PageHeader,
},
props: {
show: Boolean,

View File

@@ -21,9 +21,9 @@
<multiselect
v-model.trim="agentType"
:options="agentTypeList"
label="label"
:placeholder="$t('AGENT_MGMT.EDIT.FORM.AGENT_TYPE.PLACEHOLDER')"
:searchable="false"
label="label"
@select="setPageName"
/>
<span v-if="$v.agentType.$error" class="message">
@@ -37,10 +37,10 @@
:disabled="
$v.agentType.$invalid ||
$v.agentName.$invalid ||
editAgentsApi.showLoading
uiFlags.isUpdating
"
:button-text="$t('AGENT_MGMT.EDIT.FORM.SUBMIT')"
:loading="editAgentsApi.showLoading"
:loading="uiFlags.isUpdating"
/>
<a @click="onClose">
{{ $t('AGENT_MGMT.EDIT.CANCEL_BUTTON_TEXT') }}
@@ -62,7 +62,7 @@
/* global bus */
/* eslint no-console: 0 */
import { required, minLength } from 'vuelidate/lib/validators';
import { mapGetters } from 'vuex';
import WootSubmitButton from '../../../../components/buttons/FormSubmitButton';
import Modal from '../../../../components/Modal';
import Auth from '../../../../api/auth';
@@ -81,11 +81,6 @@ export default {
},
data() {
return {
editAgentsApi: {
showAlert: false,
showLoading: false,
message: '',
},
agentTypeList: this.$t('AGENT_MGMT.AGENT_TYPES'),
agentName: this.name,
agentType: {
@@ -111,66 +106,41 @@ export default {
pageTitle() {
return `${this.$t('AGENT_MGMT.EDIT.TITLE')} - ${this.name}`;
},
...mapGetters({
uiFlags: 'agents/getUIFlags',
}),
},
methods: {
setPageName({ name }) {
this.$v.agentType.$touch();
this.agentType = name;
},
showAlert() {
bus.$emit('newToastMessage', this.editAgentsApi.message);
showAlert(message) {
bus.$emit('newToastMessage', message);
},
resetForm() {
this.agentName = '';
this.agentType = '';
this.$v.agentName.$reset();
this.$v.agentType.$reset();
},
editAgent() {
// Show loading on button
this.editAgentsApi.showLoading = true;
// Make API Calls
this.$store
.dispatch('editAgent', {
async editAgent() {
try {
await this.$store.dispatch('agents/update', {
id: this.id,
name: this.agentName,
role: this.agentType.name.toLowerCase(),
})
.then(() => {
// Reset Form, Show success message
this.editAgentsApi.showLoading = false;
this.editAgentsApi.message = this.$t(
'AGENT_MGMT.EDIT.API.SUCCESS_MESSAGE'
);
this.showAlert();
this.resetForm();
setTimeout(() => {
this.onClose();
}, 10);
})
.catch(() => {
this.editAgentsApi.showLoading = false;
this.editAgentsApi.message = this.$t(
'AGENT_MGMT.EDIT.API.ERROR_MESSAGE'
);
this.showAlert();
});
this.showAlert(this.$t('AGENT_MGMT.EDIT.API.SUCCESS_MESSAGE'));
this.onClose();
} catch (error) {
console.log(error);
this.showAlert(this.$t('AGENT_MGMT.EDIT.API.ERROR_MESSAGE'));
}
},
resetPassword() {
// Call resetPassword from Auth Service
Auth.resetPassword(this.agentCredentials)
.then(() => {
this.editAgentsApi.message = this.$t(
'AGENT_MGMT.EDIT.PASSWORD_RESET.ADMIN_SUCCESS_MESSAGE'
);
this.showAlert();
})
.catch(() => {
this.editAgentsApi.message = this.$t(
'AGENT_MGMT.EDIT.PASSWORD_RESET.ERROR_MESSAGE'
);
this.showAlert();
});
async resetPassword() {
try {
await Auth.resetPassword(this.agentCredentials);
this.showAlert(
this.$t('AGENT_MGMT.EDIT.PASSWORD_RESET.ADMIN_SUCCESS_MESSAGE')
);
} catch (error) {
this.showAlert(this.$t('AGENT_MGMT.EDIT.PASSWORD_RESET.ERROR_MESSAGE'));
}
},
},
};

View File

@@ -13,63 +13,64 @@
<div class="row">
<div class="small-8 columns">
<woot-loading-state
v-if="fetchStatus"
v-if="uiFlags.isFetching"
:message="$t('AGENT_MGMT.LOADING')"
/>
<p v-if="!fetchStatus && !agentList.length">
{{ $t('AGENT_MGMT.LIST.404') }}
</p>
<table v-if="!fetchStatus && agentList.length" class="woot-table">
<tbody>
<tr v-for="(agent, index) in agentList" :key="agent.email">
<!-- Gravtar Image -->
<td>
<thumbnail
:src="gravatarUrl(agent.email)"
class="columns"
:username="agent.name"
size="40px"
/>
</td>
<!-- Agent Name + Email -->
<td>
<span class="agent-name">{{ agent.name }}</span>
<span>{{ agent.email }}</span>
</td>
<!-- Agent Role + Verification Status -->
<td>
<span class="agent-name">{{ agent.role }}</span>
<span v-if="agent.confirmed">
{{ $t('AGENT_MGMT.LIST.VERIFIED') }}
</span>
<span v-if="!agent.confirmed">
{{ $t('AGENT_MGMT.LIST.VERIFICATION_PENDING') }}
</span>
</td>
<!-- Actions -->
<td>
<div v-if="showActions(agent)" class="button-wrapper">
<div @click="openEditPopup(agent)">
<div v-else>
<p v-if="!agentList.length">
{{ $t('AGENT_MGMT.LIST.404') }}
</p>
<table v-else class="woot-table">
<tbody>
<tr v-for="(agent, index) in agentList" :key="agent.email">
<!-- Gravtar Image -->
<td>
<thumbnail
:src="gravatarUrl(agent.email)"
class="columns"
:username="agent.name"
size="40px"
/>
</td>
<!-- Agent Name + Email -->
<td>
<span class="agent-name">{{ agent.name }}</span>
<span>{{ agent.email }}</span>
</td>
<!-- Agent Role + Verification Status -->
<td>
<span class="agent-name">{{ agent.role }}</span>
<span v-if="agent.confirmed">
{{ $t('AGENT_MGMT.LIST.VERIFIED') }}
</span>
<span v-if="!agent.confirmed">
{{ $t('AGENT_MGMT.LIST.VERIFICATION_PENDING') }}
</span>
</td>
<!-- Actions -->
<td>
<div class="button-wrapper">
<woot-submit-button
v-if="showEditAction(agent)"
:button-text="$t('AGENT_MGMT.EDIT.BUTTON_TEXT')"
icon-class="ion-edit"
button-class="link hollow grey-btn"
@click="openEditPopup(agent)"
/>
</div>
<div @click="openDeletePopup(agent, index)">
<woot-submit-button
v-if="showDeleteAction(agent)"
:button-text="$t('AGENT_MGMT.DELETE.BUTTON_TEXT')"
:loading="loading[agent.id]"
icon-class="ion-close-circled"
button-class="link hollow grey-btn"
@click="openDeletePopup(agent, index)"
/>
</div>
</div>
</td>
</tr>
</tbody>
</table>
</td>
</tr>
</tbody>
</table>
</div>
</div>
<div class="small-4 columns">
<span v-html="$t('AGENT_MGMT.SIDEBAR_TXT')"></span>
@@ -79,7 +80,6 @@
<woot-modal :show.sync="showAddPopup" :on-close="hideAddPopup">
<add-agent :on-close="hideAddPopup" />
</woot-modal>
<!-- Edit Agent -->
<woot-modal :show.sync="showEditPopup" :on-close="hideEditPopup">
<edit-agent
@@ -91,7 +91,6 @@
:on-close="hideEditPopup"
/>
</woot-modal>
<!-- Delete Agent -->
<delete-agent
:show.sync="showDeletePopup"
@@ -102,8 +101,6 @@
:confirm-text="deleteConfirmText"
:reject-text="deleteRejectText"
/>
<!-- Loader Status -->
</div>
</template>
<script>
@@ -138,8 +135,9 @@ export default {
},
computed: {
...mapGetters({
agentList: 'getAgents',
fetchStatus: 'getAgentFetchStatus',
agentList: 'agents/getAgents',
uiFlags: 'agents/getUIFlags',
currentUserId: 'getCurrentUserID',
}),
deleteConfirmText() {
return `${this.$t('AGENT_MGMT.DELETE.CONFIRM.YES')} ${
@@ -158,20 +156,31 @@ export default {
},
},
mounted() {
this.$store.dispatch('fetchAgents');
this.$store.dispatch('agents/get');
},
methods: {
showActions(agent) {
showEditAction(agent) {
return this.currentUserId !== agent.id;
},
showDeleteAction(agent) {
if (this.currentUserId === agent.id) {
return false;
}
if (!agent.confirmed) {
return true;
}
if (agent.role === 'administrator') {
const adminList = this.agentList.filter(
item => item.role === 'administrator'
);
return adminList.length !== 1;
return this.verifiedAdministrators().length !== 1;
}
return true;
},
// List Functions
// Gravatar URL
verifiedAdministrators() {
return this.agentList.filter(
agent => agent.role === 'administrator' && agent.confirmed
);
},
gravatarUrl(email) {
const hash = md5(email);
return `${window.WootConstants.GRAVATAR_URL}${hash}?default=404`;
@@ -206,17 +215,13 @@ export default {
this.closeDeletePopup();
this.deleteAgent(this.currentAgent.id);
},
deleteAgent(id) {
this.$store
.dispatch('deleteAgent', {
id,
})
.then(() => {
this.showAlert(this.$t('AGENT_MGMT.DELETE.API.SUCCESS_MESSAGE'));
})
.catch(() => {
this.showAlert(this.$t('AGENT_MGMT.DELETE.API.ERROR_MESSAGE'));
});
async deleteAgent(id) {
try {
await this.$store.dispatch('agents/delete', id);
this.showAlert(this.$t('AGENT_MGMT.DELETE.API.SUCCESS_MESSAGE'));
} catch (error) {
this.showAlert(this.$t('AGENT_MGMT.DELETE.API.ERROR_MESSAGE'));
}
},
// Show SnackBar
showAlert(message) {

View File

@@ -73,12 +73,12 @@ export default {
computed: {
...mapGetters({
agentList: 'getAgents',
agentList: 'agents/getAgents',
}),
},
mounted() {
this.$store.dispatch('fetchAgents');
this.$store.dispatch('agents/get');
},
methods: {

View File

@@ -88,7 +88,7 @@ export default {
},
computed: {
...mapGetters({
agentList: 'getAgents',
agentList: 'agents/getAgents',
}),
webWidgetScript() {
return createWebsiteWidgetScript(this.inbox.websiteToken);
@@ -98,7 +98,7 @@ export default {
},
},
mounted() {
this.$store.dispatch('fetchAgents').then(() => {
this.$store.dispatch('agents/get').then(() => {
this.fetchAttachedAgents();
});
},