Compare commits
12 commits
develop
...
5425/set-u
Author | SHA1 | Date | |
---|---|---|---|
|
2ca92ab90c | ||
|
db6629d5fa | ||
|
a66e883cd1 | ||
|
207a8c5952 | ||
|
988ac11aa8 | ||
|
c13d655f34 | ||
|
9ae52c5124 | ||
|
e8b7efb8af | ||
|
f892781a71 | ||
|
1a887e4895 | ||
|
5ac69a54d1 | ||
|
550df2f661 |
9 changed files with 125 additions and 19 deletions
|
@ -22,6 +22,11 @@ class Api::V1::ProfilesController < Api::BaseController
|
|||
@user.account_users.find_by!(account_id: availability_params[:account_id]).update!(availability: availability_params[:availability])
|
||||
end
|
||||
|
||||
def set_active_account
|
||||
@user.account_users.find_by(account_id: profile_params[:account_id]).update(active_at: Time.now.utc)
|
||||
head :ok
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def set_user
|
||||
|
@ -39,6 +44,7 @@ class Api::V1::ProfilesController < Api::BaseController
|
|||
:display_name,
|
||||
:avatar,
|
||||
:message_signature,
|
||||
:account_id,
|
||||
ui_settings: {}
|
||||
)
|
||||
end
|
||||
|
|
|
@ -147,4 +147,13 @@ export default {
|
|||
deleteAvatar() {
|
||||
return axios.delete(endPoints('deleteAvatar').url);
|
||||
},
|
||||
|
||||
setActiveAccount({ accountId }) {
|
||||
const urlData = endPoints('setActiveAccount');
|
||||
return axios.put(urlData.url, {
|
||||
profile: {
|
||||
account_id: accountId,
|
||||
},
|
||||
});
|
||||
},
|
||||
};
|
||||
|
|
|
@ -40,6 +40,10 @@ const endPoints = {
|
|||
deleteAvatar: {
|
||||
url: '/api/v1/profile/avatar',
|
||||
},
|
||||
|
||||
setActiveAccount: {
|
||||
url: '/api/v1/profile/set_active_account',
|
||||
},
|
||||
};
|
||||
|
||||
export default page => {
|
||||
|
|
|
@ -8,25 +8,33 @@
|
|||
:header-title="$t('SIDEBAR_ITEMS.CHANGE_ACCOUNTS')"
|
||||
:header-content="$t('SIDEBAR_ITEMS.SELECTOR_SUBTITLE')"
|
||||
/>
|
||||
<div
|
||||
v-for="account in currentUser.accounts"
|
||||
:key="account.id"
|
||||
class="account-selector"
|
||||
>
|
||||
<a :href="`/app/accounts/${account.id}/dashboard`">
|
||||
<fluent-icon
|
||||
v-if="account.id === accountId"
|
||||
class="selected--account"
|
||||
icon="checkmark-circle"
|
||||
type="solid"
|
||||
size="24"
|
||||
/>
|
||||
<label :for="account.name" class="account--details">
|
||||
<div class="account--name">{{ account.name }}</div>
|
||||
<div class="account--role">{{ account.role }}</div>
|
||||
</label>
|
||||
</a>
|
||||
<div>
|
||||
<div
|
||||
v-for="account in currentUser.accounts"
|
||||
:key="account.id"
|
||||
class="account-selector"
|
||||
>
|
||||
<button
|
||||
class="button expanded clear link"
|
||||
@click="onChangeAccount(account.id)"
|
||||
>
|
||||
<span class="button__content">
|
||||
<label :for="account.name" class="account--details">
|
||||
<div class="account--name">{{ account.name }}</div>
|
||||
<div class="account--role">{{ account.role }}</div>
|
||||
</label>
|
||||
</span>
|
||||
<fluent-icon
|
||||
v-show="account.id === accountId"
|
||||
class="selected--account"
|
||||
icon="checkmark-circle"
|
||||
type="solid"
|
||||
size="24"
|
||||
/>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div
|
||||
v-if="globalConfig.createNewAccountFromDashboard"
|
||||
class="modal-footer delete-item"
|
||||
|
@ -58,5 +66,37 @@ export default {
|
|||
globalConfig: 'globalConfig/get',
|
||||
}),
|
||||
},
|
||||
methods: {
|
||||
async onChangeAccount(accountId) {
|
||||
const accountUrl = `/app/accounts/${accountId}/dashboard`;
|
||||
window.location.href = accountUrl;
|
||||
await this.$store.dispatch('setActiveAccount', {
|
||||
accountId: accountId,
|
||||
});
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
.account-selector {
|
||||
button {
|
||||
padding: var(--space-one) 0;
|
||||
.account--details {
|
||||
padding-left: var(--space-normal);
|
||||
text-align: left;
|
||||
.account--name {
|
||||
cursor: pointer;
|
||||
font-size: var(--font-size-medium);
|
||||
font-weight: var(--font-weight-medium);
|
||||
line-height: 1;
|
||||
}
|
||||
|
||||
.account--role {
|
||||
cursor: pointer;
|
||||
font-size: var(--font-size-mini);
|
||||
text-transform: capitalize;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
|
@ -143,6 +143,16 @@ export const actions = {
|
|||
}
|
||||
},
|
||||
|
||||
// eslint-disable-next-line no-empty-pattern
|
||||
setActiveAccount: async ({}, { accountId }) => {
|
||||
// eslint-disable-next-line no-useless-catch
|
||||
try {
|
||||
await authAPI.setActiveAccount({ accountId });
|
||||
} catch (error) {
|
||||
throw error;
|
||||
}
|
||||
},
|
||||
|
||||
updateUISettings: async ({ commit }, params) => {
|
||||
try {
|
||||
commit(types.SET_CURRENT_USER_UI_SETTINGS, params);
|
||||
|
|
|
@ -95,6 +95,7 @@ export default {
|
|||
isCreating: 'conversation/getIsCreating',
|
||||
activeCampaign: 'campaign/getActiveCampaign',
|
||||
currentUser: 'contacts/getCurrentUser',
|
||||
setUserTriggerStatus: 'contacts/getSetUserTriggerStatus',
|
||||
}),
|
||||
textColor() {
|
||||
return getContrastingTextColor(this.widgetColor);
|
||||
|
@ -124,6 +125,9 @@ export default {
|
|||
) {
|
||||
return false;
|
||||
}
|
||||
if (this.setUserTriggerStatus && field.name === 'fullName') {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
});
|
||||
},
|
||||
|
|
|
@ -4,9 +4,11 @@ import { SET_USER_ERROR } from '../../constants/errorTypes';
|
|||
import { setHeader } from '../../helpers/axios';
|
||||
const state = {
|
||||
currentUser: {},
|
||||
isSetUserTriggered: false,
|
||||
};
|
||||
|
||||
const SET_CURRENT_USER = 'SET_CURRENT_USER';
|
||||
const TRIGGER_SET_USER = 'TRIGGER_SET_USER';
|
||||
const parseErrorData = error =>
|
||||
error && error.response && error.response.data ? error.response.data : error;
|
||||
export const updateWidgetAuthToken = widgetAuthToken => {
|
||||
|
@ -23,6 +25,9 @@ export const getters = {
|
|||
getCurrentUser(_state) {
|
||||
return _state.currentUser;
|
||||
},
|
||||
getSetUserTriggerStatus(_state) {
|
||||
return _state.isSetUserTriggered;
|
||||
},
|
||||
};
|
||||
|
||||
export const actions = {
|
||||
|
@ -42,7 +47,7 @@ export const actions = {
|
|||
// Ignore error
|
||||
}
|
||||
},
|
||||
setUser: async ({ dispatch }, { identifier, user: userObject }) => {
|
||||
setUser: async ({ dispatch, commit }, { identifier, user: userObject }) => {
|
||||
try {
|
||||
const {
|
||||
email,
|
||||
|
@ -75,6 +80,7 @@ export const actions = {
|
|||
const {
|
||||
data: { widget_auth_token: widgetAuthToken },
|
||||
} = await ContactsAPI.setUser(identifier, user);
|
||||
commit(TRIGGER_SET_USER);
|
||||
updateWidgetAuthToken(widgetAuthToken);
|
||||
dispatch('get');
|
||||
if (identifierHash || widgetAuthToken) {
|
||||
|
@ -108,6 +114,9 @@ export const mutations = {
|
|||
const { currentUser } = $state;
|
||||
$state.currentUser = { ...currentUser, ...user };
|
||||
},
|
||||
[TRIGGER_SET_USER]($state) {
|
||||
$state.isSetUserTriggered = true;
|
||||
},
|
||||
};
|
||||
|
||||
export default {
|
||||
|
|
|
@ -182,6 +182,7 @@ Rails.application.routes.draw do
|
|||
delete :avatar, on: :collection
|
||||
member do
|
||||
post :availability
|
||||
put :set_active_account
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -195,4 +195,27 @@ RSpec.describe 'Profile API', type: :request do
|
|||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe 'PUT /api/v1/profile/set_active_account' do
|
||||
context 'when it is an unauthenticated user' do
|
||||
it 'returns unauthorized' do
|
||||
put '/api/v1/profile/set_active_account'
|
||||
|
||||
expect(response).to have_http_status(:unauthorized)
|
||||
end
|
||||
end
|
||||
|
||||
context 'when it is an authenticated user' do
|
||||
let(:agent) { create(:user, password: 'Test123!', account: account, role: :agent) }
|
||||
|
||||
it 'updates the last active account id' do
|
||||
put '/api/v1/profile/set_active_account',
|
||||
params: { profile: { account_id: account.id } },
|
||||
headers: agent.create_new_auth_token,
|
||||
as: :json
|
||||
|
||||
expect(response).to have_http_status(:success)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
Loading…
Reference in a new issue