From 0fc91e798d058c1c98dcfec0c6c5bffbcab3e15e Mon Sep 17 00:00:00 2001 From: Yoshie Muranaka Date: Wed, 5 Feb 2020 11:23:06 -0800 Subject: Add toast component interactions Include boostrap toast component to communicate success and error requests on the local user management page. - Created BVToastMixin to share initialization options - Used async/await pattern to make sure toasts are shown after asynchronous calls are complete - Followed current AngularJS pattern of manual dismiss for error toast and automatic dismiss for success toast Signed-off-by: Yoshie Muranaka Change-Id: I5d5c037b5f41781972106fb5e9a2096cc72c39ab --- src/assets/styles/_obmc-custom.scss | 3 +- src/assets/styles/_toast.scss | 32 ++++++++++++++++++++ src/components/Mixins/BVToastMixin.js | 24 +++++++++++++++ src/main.js | 4 ++- .../AccessControl/LocalUserMangementStore.js | 35 +++++++++++++++------- .../LocalUserManagement/LocalUserManagement.vue | 17 +++++++++-- 6 files changed, 100 insertions(+), 15 deletions(-) create mode 100644 src/assets/styles/_toast.scss create mode 100644 src/components/Mixins/BVToastMixin.js diff --git a/src/assets/styles/_obmc-custom.scss b/src/assets/styles/_obmc-custom.scss index d20e64e4..2e360193 100644 --- a/src/assets/styles/_obmc-custom.scss +++ b/src/assets/styles/_obmc-custom.scss @@ -56,4 +56,5 @@ $colors: map-remove($theme-colors, "light", "dark"); @import "./buttons"; @import "./form-components"; @import "./modal"; -@import "./table"; \ No newline at end of file +@import "./table"; +@import "./toast"; \ No newline at end of file diff --git a/src/assets/styles/_toast.scss b/src/assets/styles/_toast.scss new file mode 100644 index 00000000..3f2f08c0 --- /dev/null +++ b/src/assets/styles/_toast.scss @@ -0,0 +1,32 @@ +.b-toaster { + top: 75px!important; // make sure toasts do not hide top header +} + +.toast { + padding: $spacer/2 $spacer/2 $spacer/2 $spacer; + border-width: 0 0 0 5px; + .close { + font-weight: 300; + opacity: 1; + } +} + +.toast-header { + background-color: inherit!important; //override specificity + border: none; + color: $dark!important; //override specificity + padding-bottom: 0; +} + +.toast-body { + color: $dark; + padding-top: 0; +} + +.b-toast-success .toast { + border-left-color: $success!important; +} + +.b-toast-danger .toast { + border-left-color: $danger!important; +} \ No newline at end of file diff --git a/src/components/Mixins/BVToastMixin.js b/src/components/Mixins/BVToastMixin.js new file mode 100644 index 00000000..489173c9 --- /dev/null +++ b/src/components/Mixins/BVToastMixin.js @@ -0,0 +1,24 @@ +const BVToastMixin = { + methods: { + successToast(message) { + this.$root.$bvToast.toast(message, { + title: 'Success', + variant: 'success', + autoHideDelay: 10000, //auto hide in milliseconds + isStatus: true, + solid: true + }); + }, + errorToast(message) { + this.$root.$bvToast.toast(message, { + title: 'Error', + variant: 'danger', + noAutoHide: true, + isStatus: true, + solid: true + }); + } + } +}; + +export default BVToastMixin; diff --git a/src/main.js b/src/main.js index e32a56be..d80d2019 100644 --- a/src/main.js +++ b/src/main.js @@ -21,7 +21,8 @@ import { ModalPlugin, NavbarPlugin, NavPlugin, - TablePlugin + TablePlugin, + ToastPlugin } from 'bootstrap-vue'; import Vuelidate from 'vuelidate'; @@ -52,6 +53,7 @@ Vue.use(ModalPlugin); Vue.use(NavbarPlugin); Vue.use(NavPlugin); Vue.use(TablePlugin); +Vue.use(ToastPlugin); Vue.use(Vuelidate); new Vue({ diff --git a/src/store/modules/AccessControl/LocalUserMangementStore.js b/src/store/modules/AccessControl/LocalUserMangementStore.js index 815c1661..bc14c734 100644 --- a/src/store/modules/AccessControl/LocalUserMangementStore.js +++ b/src/store/modules/AccessControl/LocalUserMangementStore.js @@ -25,21 +25,28 @@ const LocalUserManagementStore = { const userData = users.map(user => user.data); commit('setUsers', userData); }) - .catch(error => console.log(error)); + .catch(error => { + console.log(error); + throw new Error('Error loading local users.'); + }); }, - createUser({ dispatch }, { username, password, privilege, status }) { + async createUser({ dispatch }, { username, password, privilege, status }) { const data = { UserName: username, Password: password, RoleId: privilege, Enabled: status }; - api + return await api .post('/redfish/v1/AccountService/Accounts', data) .then(() => dispatch('getUsers')) - .catch(error => console.log(error)); + .then(() => `Created user '${username}'.`) + .catch(error => { + console.log(error); + throw new Error(`Error creating user '${username}'.`); + }); }, - updateUser( + async updateUser( { dispatch }, { originalUsername, username, password, privilege, status } ) { @@ -48,16 +55,24 @@ const LocalUserManagementStore = { if (password) data.Password = password; if (privilege) data.RoleId = privilege; if (status !== undefined) data.Enabled = status; - api + return await api .patch(`/redfish/v1/AccountService/Accounts/${originalUsername}`, data) .then(() => dispatch('getUsers')) - .catch(error => console.log(error)); + .then(() => `Updated user '${originalUsername}'.`) + .catch(error => { + console.log(error); + throw new Error(`Error updating user '${originalUsername}'.`); + }); }, - deleteUser({ dispatch }, username) { - api + async deleteUser({ dispatch }, username) { + return await api .delete(`/redfish/v1/AccountService/Accounts/${username}`) .then(() => dispatch('getUsers')) - .catch(error => console.log(error)); + .then(() => `Deleted user '${username}'.`) + .catch(error => { + console.log(error); + throw new Error(`Error deleting user '${username}'.`); + }); } } }; diff --git a/src/views/AccessControl/LocalUserManagement/LocalUserManagement.vue b/src/views/AccessControl/LocalUserManagement/LocalUserManagement.vue index 0ca3428d..e71387da 100644 --- a/src/views/AccessControl/LocalUserManagement/LocalUserManagement.vue +++ b/src/views/AccessControl/LocalUserManagement/LocalUserManagement.vue @@ -67,6 +67,7 @@ import TableRoles from './TableRoles'; import ModalUser from './ModalUser'; import ModalSettings from './ModalSettings'; import PageTitle from '../../../components/Global/PageTitle'; +import BVToastMixin from '../../../components/Mixins/BVToastMixin'; export default { name: 'LocalUsers', @@ -81,6 +82,7 @@ export default { TableRoles, PageTitle }, + mixins: [BVToastMixin], data() { return { activeUser: null, @@ -156,13 +158,22 @@ export default { }, saveUser({ isNewUser, userData }) { if (isNewUser) { - this.$store.dispatch('localUsers/createUser', userData); + this.$store + .dispatch('localUsers/createUser', userData) + .then(success => this.successToast(success)) + .catch(({ message }) => this.errorToast(message)); } else { - this.$store.dispatch('localUsers/updateUser', userData); + this.$store + .dispatch('localUsers/updateUser', userData) + .then(success => this.successToast(success)) + .catch(({ message }) => this.errorToast(message)); } }, deleteUser({ username }) { - this.$store.dispatch('localUsers/deleteUser', username); + this.$store + .dispatch('localUsers/deleteUser', username) + .then(success => this.successToast(success)) + .catch(({ message }) => this.errorToast(message)); } } }; -- cgit v1.2.3