Compare commits

...

12 commits

Author SHA1 Message Date
Muhsin Keloth
2ca92ab90c Add status after setUser 2022-09-20 12:55:20 +05:30
Muhsin Keloth
db6629d5fa
Merge branch 'develop' into chore/change-default-account 2022-09-19 10:42:41 +05:30
Muhsin Keloth
a66e883cd1
Merge branch 'develop' into chore/change-default-account 2022-09-15 15:29:01 +05:30
Muhsin Keloth
207a8c5952 Review fixes 2022-09-15 15:28:09 +05:30
Muhsin Keloth
988ac11aa8
Merge branch 'develop' into chore/change-default-account 2022-09-13 18:50:59 +05:30
Muhsin Keloth
c13d655f34
Merge branch 'develop' into chore/change-default-account 2022-09-12 12:09:51 +05:30
Muhsin Keloth
9ae52c5124
Merge branch 'develop' into chore/change-default-account 2022-09-06 12:50:12 +05:30
Sivin Varghese
e8b7efb8af
Merge branch 'develop' into chore/change-default-account 2022-09-05 17:40:09 +05:30
Muhsin Keloth
f892781a71 Fix the specs 2022-09-05 13:23:44 +05:30
Muhsin Keloth
1a887e4895
Merge branch 'develop' into chore/change-default-account 2022-09-05 13:11:40 +05:30
Muhsin Keloth
5ac69a54d1 Set last account id on account change 2022-09-05 12:45:38 +05:30
Muhsin Keloth
550df2f661 Add route 2022-08-29 10:33:53 +05:30
9 changed files with 125 additions and 19 deletions

View file

@ -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

View file

@ -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,
},
});
},
};

View file

@ -40,6 +40,10 @@ const endPoints = {
deleteAvatar: {
url: '/api/v1/profile/avatar',
},
setActiveAccount: {
url: '/api/v1/profile/set_active_account',
},
};
export default page => {

View file

@ -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>

View file

@ -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);

View file

@ -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;
});
},

View file

@ -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 {

View file

@ -182,6 +182,7 @@ Rails.application.routes.draw do
delete :avatar, on: :collection
member do
post :availability
put :set_active_account
end
end

View file

@ -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