feat: Ability for the logged in user to create a new account (#985)
Co-authored-by: Divyesh <dkothari@box8.in> Co-authored-by: Pranav Raj S <pranav@thoughtwoot.com>
This commit is contained in:
@@ -1,9 +1,14 @@
|
||||
/* global axios */
|
||||
import ApiClient from './ApiClient';
|
||||
|
||||
class AccountAPI extends ApiClient {
|
||||
constructor() {
|
||||
super('', { accountScoped: true });
|
||||
}
|
||||
|
||||
createAccount(data) {
|
||||
return axios.post(`${this.apiVersion}/accounts`, data);
|
||||
}
|
||||
}
|
||||
|
||||
export default new AccountAPI();
|
||||
|
||||
@@ -34,7 +34,7 @@
|
||||
class="dropdown-pane top"
|
||||
>
|
||||
<ul class="vertical dropdown menu">
|
||||
<li v-if="currentUser.accounts.length > 1">
|
||||
<li v-if="showChangeAccountOption">
|
||||
<button
|
||||
class="button clear change-accounts--button"
|
||||
@click="changeAccount"
|
||||
@@ -94,6 +94,58 @@
|
||||
</label>
|
||||
</a>
|
||||
</div>
|
||||
<div
|
||||
v-if="globalConfig.createNewAccountFromDashboard"
|
||||
class="modal-footer delete-item"
|
||||
>
|
||||
<button
|
||||
class="button success large expanded nice"
|
||||
@click="createAccount"
|
||||
>
|
||||
{{ $t('CREATE_ACCOUNT.NEW_ACCOUNT') }}
|
||||
</button>
|
||||
</div>
|
||||
</woot-modal>
|
||||
|
||||
<woot-modal
|
||||
:show="showCreateAccountModal"
|
||||
:on-close="onCloseCreate"
|
||||
class="account-selector--modal"
|
||||
>
|
||||
<div class="column content-box">
|
||||
<woot-modal-header
|
||||
:header-title="$t('CREATE_ACCOUNT.NEW_ACCOUNT')"
|
||||
:header-content="$t('CREATE_ACCOUNT.SELECTOR_SUBTITLE')"
|
||||
/>
|
||||
|
||||
<form class="row" @submit.prevent="addAccount()">
|
||||
<div class="medium-12 columns">
|
||||
<label :class="{ error: $v.accountName.$error }">
|
||||
{{ $t('CREATE_ACCOUNT.FORM.NAME.LABEL') }}
|
||||
<input
|
||||
v-model.trim="accountName"
|
||||
type="text"
|
||||
:placeholder="$t('CREATE_ACCOUNT.FORM.NAME.PLACEHOLDER')"
|
||||
@input="$v.accountName.$touch"
|
||||
/>
|
||||
</label>
|
||||
</div>
|
||||
<div class="modal-footer medium-12 columns">
|
||||
<div class="medium-12 columns">
|
||||
<woot-submit-button
|
||||
:disabled="
|
||||
$v.accountName.$invalid ||
|
||||
$v.accountName.$invalid ||
|
||||
uiFlags.isCreating
|
||||
"
|
||||
:button-text="$t('CREATE_ACCOUNT.FORM.SUBMIT')"
|
||||
:loading="uiFlags.isCreating"
|
||||
button-class="large expanded"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</woot-modal>
|
||||
</aside>
|
||||
</template>
|
||||
@@ -108,13 +160,16 @@ import SidebarItem from './SidebarItem';
|
||||
import { frontendURL } from '../../helper/URLHelper';
|
||||
import Thumbnail from '../widgets/Thumbnail';
|
||||
import { getSidebarItems } from '../../i18n/default-sidebar';
|
||||
import { required, minLength } from 'vuelidate/lib/validators';
|
||||
import alertMixin from 'shared/mixins/alertMixin';
|
||||
// import accountMixin from '../../../../../mixins/account';
|
||||
|
||||
export default {
|
||||
components: {
|
||||
SidebarItem,
|
||||
Thumbnail,
|
||||
},
|
||||
mixins: [clickaway, adminMixin],
|
||||
mixins: [clickaway, adminMixin, alertMixin],
|
||||
props: {
|
||||
route: {
|
||||
type: String,
|
||||
@@ -125,8 +180,18 @@ export default {
|
||||
return {
|
||||
showOptionsMenu: false,
|
||||
showAccountModal: false,
|
||||
showCreateAccountModal: false,
|
||||
accountName: '',
|
||||
vertical: 'bottom',
|
||||
horizontal: 'center',
|
||||
};
|
||||
},
|
||||
validations: {
|
||||
accountName: {
|
||||
required,
|
||||
minLength: minLength(1),
|
||||
},
|
||||
},
|
||||
computed: {
|
||||
...mapGetters({
|
||||
currentUser: 'getCurrentUser',
|
||||
@@ -134,8 +199,15 @@ export default {
|
||||
inboxes: 'inboxes/getInboxes',
|
||||
accountId: 'getCurrentAccountId',
|
||||
currentRole: 'getCurrentRole',
|
||||
uiFlags: 'agents/getUIFlags',
|
||||
accountLabels: 'labels/getLabelsOnSidebar',
|
||||
}),
|
||||
showChangeAccountOption() {
|
||||
if (this.globalConfig.createNewAccountFromDashboard) {
|
||||
return true;
|
||||
}
|
||||
return this.currentUser.accounts.length > 1;
|
||||
},
|
||||
sidemenuItems() {
|
||||
return getSidebarItems(this.accountId);
|
||||
},
|
||||
@@ -230,6 +302,29 @@ export default {
|
||||
onClose() {
|
||||
this.showAccountModal = false;
|
||||
},
|
||||
createAccount() {
|
||||
this.showAccountModal = false;
|
||||
this.showCreateAccountModal = true;
|
||||
},
|
||||
onCloseCreate() {
|
||||
this.showCreateAccountModal = false;
|
||||
},
|
||||
async addAccount() {
|
||||
try {
|
||||
const account_id = await this.$store.dispatch('accounts/create', {
|
||||
account_name: this.accountName,
|
||||
});
|
||||
this.onClose();
|
||||
this.showAlert(this.$t('CREATE_ACCOUNT.API.SUCCESS_MESSAGE'));
|
||||
window.location = `/app/accounts/${account_id}/dashboard`;
|
||||
} catch (error) {
|
||||
if (error.response.status === 422) {
|
||||
this.showAlert(this.$t('CREATE_ACCOUNT.API.EXIST_MESSAGE'));
|
||||
} else {
|
||||
this.showAlert(this.$t('CREATE_ACCOUNT.API.ERROR_MESSAGE'));
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
@@ -122,5 +122,22 @@
|
||||
"INTEGRATIONS": "Integrations",
|
||||
"ACCOUNT_SETTINGS": "Account Settings",
|
||||
"LABELS": "Labels"
|
||||
},
|
||||
"CREATE_ACCOUNT": {
|
||||
"NEW_ACCOUNT": "New Account",
|
||||
"SELECTOR_SUBTITLE": "Create a new account",
|
||||
"API": {
|
||||
"SUCCESS_MESSAGE": "Account created successfully",
|
||||
"EXIST_MESSAGE": "Account already exists",
|
||||
"ERROR_MESSAGE": "Could not connect to Woot Server, Please try again later"
|
||||
},
|
||||
"FORM": {
|
||||
"NAME": {
|
||||
"LABEL": "Account Name",
|
||||
"PLACEHOLDER": "Wayne Enterprises"
|
||||
},
|
||||
"SUBMIT": "Submit"
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -48,6 +48,18 @@ export const actions = {
|
||||
throw new Error(error);
|
||||
}
|
||||
},
|
||||
create: async ({ commit }, accountInfo) => {
|
||||
commit(types.default.SET_ACCOUNT_UI_FLAG, { isCreating: true });
|
||||
try {
|
||||
const response = await AccountAPI.createAccount(accountInfo);
|
||||
const account_id = response.data.data.account_id;
|
||||
commit(types.default.SET_ACCOUNT_UI_FLAG, { isCreating: false });
|
||||
return account_id;
|
||||
} catch (error) {
|
||||
commit(types.default.SET_ACCOUNT_UI_FLAG, { isCreating: false });
|
||||
throw error;
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
export const mutations = {
|
||||
|
||||
@@ -8,6 +8,10 @@ const accountData = {
|
||||
locale: 'en',
|
||||
};
|
||||
|
||||
const newAccountInfo = {
|
||||
accountName: 'Company two',
|
||||
};
|
||||
|
||||
const commit = jest.fn();
|
||||
global.axios = axios;
|
||||
jest.mock('axios');
|
||||
@@ -53,4 +57,27 @@ describe('#actions', () => {
|
||||
]);
|
||||
});
|
||||
});
|
||||
|
||||
describe('#create', () => {
|
||||
it('sends correct actions if API is success', async () => {
|
||||
axios.post.mockResolvedValue({
|
||||
data: { data: { id: 1, name: 'John' } },
|
||||
});
|
||||
await actions.create({ commit, getters }, newAccountInfo);
|
||||
expect(commit.mock.calls).toEqual([
|
||||
[types.default.SET_ACCOUNT_UI_FLAG, { isCreating: true }],
|
||||
[types.default.SET_ACCOUNT_UI_FLAG, { isCreating: false }],
|
||||
]);
|
||||
});
|
||||
it('sends correct actions if API is error', async () => {
|
||||
axios.patch.mockRejectedValue({ message: 'Incorrect header' });
|
||||
await expect(
|
||||
actions.create({ commit, getters }, newAccountInfo)
|
||||
).rejects.toThrow(Error);
|
||||
expect(commit.mock.calls).toEqual([
|
||||
[types.default.SET_ACCOUNT_UI_FLAG, { isCreating: true }],
|
||||
[types.default.SET_ACCOUNT_UI_FLAG, { isCreating: false }],
|
||||
]);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,19 +1,21 @@
|
||||
const {
|
||||
CREATE_NEW_ACCOUNT_FROM_DASHBOARD: createNewAccountFromDashboard,
|
||||
INSTALLATION_NAME: installationName,
|
||||
LOGO_THUMBNAIL: logoThumbnail,
|
||||
LOGO: logo,
|
||||
INSTALLATION_NAME: installationName,
|
||||
WIDGET_BRAND_URL: widgetBrandURL,
|
||||
TERMS_URL: termsURL,
|
||||
PRIVACY_URL: privacyURL,
|
||||
TERMS_URL: termsURL,
|
||||
WIDGET_BRAND_URL: widgetBrandURL,
|
||||
} = window.globalConfig;
|
||||
|
||||
const state = {
|
||||
logoThumbnail,
|
||||
logo,
|
||||
createNewAccountFromDashboard,
|
||||
installationName,
|
||||
widgetBrandURL,
|
||||
termsURL,
|
||||
logo,
|
||||
logoThumbnail,
|
||||
privacyURL,
|
||||
termsURL,
|
||||
widgetBrandURL,
|
||||
};
|
||||
|
||||
export const getters = {
|
||||
|
||||
Reference in New Issue
Block a user