feat: Set up store for teams (#1689)
This commit is contained in:
parent
cadb246eaa
commit
941d4219f0
26 changed files with 1168 additions and 4 deletions
|
@ -11,5 +11,6 @@ describe('#TeamsAPI', () => {
|
||||||
expect(teams).toHaveProperty('delete');
|
expect(teams).toHaveProperty('delete');
|
||||||
expect(teams).toHaveProperty('getAgents');
|
expect(teams).toHaveProperty('getAgents');
|
||||||
expect(teams).toHaveProperty('addAgents');
|
expect(teams).toHaveProperty('addAgents');
|
||||||
|
expect(teams).toHaveProperty('updateAgents');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -15,6 +15,12 @@ export class TeamsAPI extends ApiClient {
|
||||||
user_ids: agentsList,
|
user_ids: agentsList,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
updateAgents({ teamId, agentsList }) {
|
||||||
|
return axios.patch(`${this.url}/${teamId}/team_members`, {
|
||||||
|
user_ids: agentsList,
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export default new TeamsAPI();
|
export default new TeamsAPI();
|
||||||
|
|
|
@ -178,7 +178,6 @@ export default {
|
||||||
icon: 'ion-ios-people',
|
icon: 'ion-ios-people',
|
||||||
label: 'TEAMS',
|
label: 'TEAMS',
|
||||||
hasSubMenu: true,
|
hasSubMenu: true,
|
||||||
newLink: true,
|
|
||||||
key: 'team',
|
key: 'team',
|
||||||
cssClass: 'menu-title align-justify teams-sidebar-menu',
|
cssClass: 'menu-title align-justify teams-sidebar-menu',
|
||||||
toState: frontendURL(`accounts/${this.accountId}/settings/teams`),
|
toState: frontendURL(`accounts/${this.accountId}/settings/teams`),
|
||||||
|
|
|
@ -74,6 +74,7 @@ export default {
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
border-left: 1px solid var(--color-border);
|
border-left: 1px solid var(--color-border);
|
||||||
|
background: var(--color-background-light);
|
||||||
}
|
}
|
||||||
|
|
||||||
.messages-and-sidebar {
|
.messages-and-sidebar {
|
||||||
|
|
|
@ -75,6 +75,13 @@ export const getSidebarItems = accountId => ({
|
||||||
'settings_integrations_integration',
|
'settings_integrations_integration',
|
||||||
'general_settings',
|
'general_settings',
|
||||||
'general_settings_index',
|
'general_settings_index',
|
||||||
|
'settings_teams_list',
|
||||||
|
'settings_teams_new',
|
||||||
|
'settings_teams_add_agents',
|
||||||
|
'settings_teams_finish',
|
||||||
|
'settings_teams_edit',
|
||||||
|
'settings_teams_edit_members',
|
||||||
|
'settings_teams_edit_finish',
|
||||||
],
|
],
|
||||||
menuItems: {
|
menuItems: {
|
||||||
back: {
|
back: {
|
||||||
|
@ -91,6 +98,13 @@ export const getSidebarItems = accountId => ({
|
||||||
toState: frontendURL(`accounts/${accountId}/settings/agents/list`),
|
toState: frontendURL(`accounts/${accountId}/settings/agents/list`),
|
||||||
toStateName: 'agent_list',
|
toStateName: 'agent_list',
|
||||||
},
|
},
|
||||||
|
teams: {
|
||||||
|
icon: 'ion-ios-people',
|
||||||
|
label: 'TEAMS',
|
||||||
|
hasSubMenu: false,
|
||||||
|
toState: frontendURL(`accounts/${accountId}/settings/teams/list`),
|
||||||
|
toStateName: 'settings_teams_list',
|
||||||
|
},
|
||||||
inboxes: {
|
inboxes: {
|
||||||
icon: 'ion-archive',
|
icon: 'ion-archive',
|
||||||
label: 'INBOXES',
|
label: 'INBOXES',
|
||||||
|
|
|
@ -13,6 +13,7 @@ import { default as _settings } from './settings.json';
|
||||||
import { default as _signup } from './signup.json';
|
import { default as _signup } from './signup.json';
|
||||||
import { default as _integrations } from './integrations.json';
|
import { default as _integrations } from './integrations.json';
|
||||||
import { default as _generalSettings } from './generalSettings.json';
|
import { default as _generalSettings } from './generalSettings.json';
|
||||||
|
import { default as _teamsSettings } from './teamsSettings.json';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
..._agentMgmt,
|
..._agentMgmt,
|
||||||
|
@ -30,4 +31,5 @@ export default {
|
||||||
..._signup,
|
..._signup,
|
||||||
..._integrations,
|
..._integrations,
|
||||||
..._generalSettings,
|
..._generalSettings,
|
||||||
|
..._teamsSettings,
|
||||||
};
|
};
|
||||||
|
|
123
app/javascript/dashboard/i18n/locale/en/teamsSettings.json
Normal file
123
app/javascript/dashboard/i18n/locale/en/teamsSettings.json
Normal file
|
@ -0,0 +1,123 @@
|
||||||
|
{
|
||||||
|
"TEAMS_SETTINGS": {
|
||||||
|
"NEW_TEAM": "Create new team",
|
||||||
|
"HEADER": "Teams",
|
||||||
|
"SIDEBAR_TXT": "<p><b>Teams</b></p> <p>Teams let you organize your agents into groups based on their responsibilities. <br /> A user can be part of multiple teams. You can assign conversations to a team when you are working collaboratively. </p>",
|
||||||
|
"LIST": {
|
||||||
|
"404": "There are no teams created on this account.",
|
||||||
|
"EDIT_TEAM": "Edit team"
|
||||||
|
},
|
||||||
|
"CREATE_FLOW": {
|
||||||
|
"CREATE": {
|
||||||
|
"TITLE": "Create a new team",
|
||||||
|
"DESC": "Add a title and description to your new team."
|
||||||
|
},
|
||||||
|
"AGENTS": {
|
||||||
|
"BUTTON_TEXT": "Add agents to team",
|
||||||
|
"TITLE": "Add agents to team - %{teamName}",
|
||||||
|
"DESC": "Add Agents to your newly created team. This lets you collaborate as a team on conversations, get notified on new events in the same conversation."
|
||||||
|
},
|
||||||
|
"WIZARD": [{
|
||||||
|
"title": "Create",
|
||||||
|
"route": "settings_teams_new",
|
||||||
|
"body": "Create a new team of agents."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "Add Agents",
|
||||||
|
"route": "settings_teams_add_agents",
|
||||||
|
"body": "Add agents to the team."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "Finish",
|
||||||
|
"route": "settings_teams_finish",
|
||||||
|
"body": "You are all set to go!"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"EDIT_FLOW": {
|
||||||
|
"CREATE": {
|
||||||
|
"TITLE": "Edit your team details",
|
||||||
|
"DESC": "Edit title and description to your team.",
|
||||||
|
"BUTTON_TEXT": "Update team"
|
||||||
|
},
|
||||||
|
"AGENTS": {
|
||||||
|
"BUTTON_TEXT": "Update agents in team",
|
||||||
|
"TITLE": "Add agents to team - %{teamName}",
|
||||||
|
"DESC": "Add Agents to your newly created team. All the added agents will be notified when a conversation is assigned to this team."
|
||||||
|
},
|
||||||
|
"WIZARD": [{
|
||||||
|
"title": "Team details",
|
||||||
|
"route": "settings_teams_edit",
|
||||||
|
"body": "Change name, description and other details."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "Edit Agents",
|
||||||
|
"route": "settings_teams_edit_members",
|
||||||
|
"body": "Edit agents in your team."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "Finish",
|
||||||
|
"route": "settings_teams_edit_finish",
|
||||||
|
"body": "You are all set to go!"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"TEAM_FORM": {
|
||||||
|
"ERROR_MESSAGE": "Couldn't save the team details. Try again."
|
||||||
|
},
|
||||||
|
"AGENTS": {
|
||||||
|
"AGENT": "AGENT",
|
||||||
|
"EMAIL": "EMAIL",
|
||||||
|
"BUTTON_TEXT": "Add agents",
|
||||||
|
"ADD_AGENTS": "Adding Agents to your Team...",
|
||||||
|
"SELECT": "select",
|
||||||
|
"SELECT_ALL": "select all agents",
|
||||||
|
"SELECTED_COUNT": "%{selected} out of %{total} agents selected."
|
||||||
|
},
|
||||||
|
"ADD": {
|
||||||
|
"TITLE": "Add agents to team - %{teamName}",
|
||||||
|
"DESC": "Add Agents to your newly created team. This lets you collaborate as a team on conversations, get notified on new events in the same conversation.",
|
||||||
|
"SELECT": "select",
|
||||||
|
"SELECT_ALL": "select all agents",
|
||||||
|
"SELECTED_COUNT": "%{selected} out of %{total} agents selected.",
|
||||||
|
"BUTTON_TEXT": "Add agents",
|
||||||
|
"AGENT_VALIDATION_ERROR": "Select atleaset one agent."
|
||||||
|
},
|
||||||
|
|
||||||
|
"FINISH": {
|
||||||
|
"TITLE": "Your team is ready!",
|
||||||
|
"MESSAGE": "You can now collaborate as a team on conversations. Happy supporting ",
|
||||||
|
"BUTTON_TEXT": "Finish"
|
||||||
|
},
|
||||||
|
"DELETE": {
|
||||||
|
"BUTTON_TEXT": "Delete",
|
||||||
|
"API": {
|
||||||
|
"SUCCESS_MESSAGE": "Team deleted successfully.",
|
||||||
|
"ERROR_MESSAGE": "Couldn't delete the team. Try again."
|
||||||
|
},
|
||||||
|
"CONFIRM": {
|
||||||
|
"TITLE": "Are you sure want to delete - %{teamName}",
|
||||||
|
"MESSAGE": "Deleting the team will remove the team assignment from the conversations assigned to this team.",
|
||||||
|
"YES": "Delete ",
|
||||||
|
"NO": "Cancel"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"SETTINGS": "Settings",
|
||||||
|
"FORM": {
|
||||||
|
"UPDATE": "Update team",
|
||||||
|
"CREATE": "Create team",
|
||||||
|
"NAME": {
|
||||||
|
"LABEL": "Team name",
|
||||||
|
"PLACEHOLDER": "Example: Sales, Customer Support"
|
||||||
|
},
|
||||||
|
"DESCRIPTION": {
|
||||||
|
"LABEL": "Team Description",
|
||||||
|
"PLACEHOLDER": "Short description about this team."
|
||||||
|
},
|
||||||
|
"AUTO_ASSIGN": {
|
||||||
|
"LABEL": "Allow auto assign for this team."
|
||||||
|
},
|
||||||
|
"SUBMIT_CREATE": "Create team"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -404,6 +404,7 @@ export default {
|
||||||
this.selectedTabIndex = 0;
|
this.selectedTabIndex = 0;
|
||||||
this.selectedAgents = [];
|
this.selectedAgents = [];
|
||||||
this.$store.dispatch('agents/get');
|
this.$store.dispatch('agents/get');
|
||||||
|
this.$store.dispatch('teams/get');
|
||||||
this.$store.dispatch('inboxes/get').then(() => {
|
this.$store.dispatch('inboxes/get').then(() => {
|
||||||
this.fetchAttachedAgents();
|
this.fetchAttachedAgents();
|
||||||
this.avatarUrl = this.inbox.avatar_url;
|
this.avatarUrl = this.inbox.avatar_url;
|
||||||
|
|
|
@ -7,6 +7,7 @@ import integrations from './integrations/integrations.routes';
|
||||||
import labels from './labels/labels.routes';
|
import labels from './labels/labels.routes';
|
||||||
import profile from './profile/profile.routes';
|
import profile from './profile/profile.routes';
|
||||||
import reports from './reports/reports.routes';
|
import reports from './reports/reports.routes';
|
||||||
|
import teams from './teams/teams.routes';
|
||||||
import store from '../../../store';
|
import store from '../../../store';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
|
@ -30,5 +31,6 @@ export default {
|
||||||
...labels.routes,
|
...labels.routes,
|
||||||
...profile.routes,
|
...profile.routes,
|
||||||
...reports.routes,
|
...reports.routes,
|
||||||
|
...teams.routes,
|
||||||
],
|
],
|
||||||
};
|
};
|
||||||
|
|
|
@ -0,0 +1,179 @@
|
||||||
|
<template>
|
||||||
|
<div>
|
||||||
|
<div class="add-agents__header"></div>
|
||||||
|
<table class="woot-table">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<div class="checkbox-wrap">
|
||||||
|
<input
|
||||||
|
name="select-all-agents"
|
||||||
|
type="checkbox"
|
||||||
|
:checked="allAgentsSelected ? 'checked' : ''"
|
||||||
|
:title="$t('TEAMS_SETTINGS.AGENTS.SELECT_ALL')"
|
||||||
|
@click.self="selectAllAgents"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
<td>{{ $t('TEAMS_SETTINGS.AGENTS.AGENT') }}</td>
|
||||||
|
<td>{{ $t('TEAMS_SETTINGS.AGENTS.EMAIL') }}</td>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<tr
|
||||||
|
v-for="agent in agentList"
|
||||||
|
:key="agent.id"
|
||||||
|
:class="agentRowClass(agent.id)"
|
||||||
|
>
|
||||||
|
<td class="checkbox-cell">
|
||||||
|
<div class="checkbox-wrap">
|
||||||
|
<input
|
||||||
|
type="checkbox"
|
||||||
|
:checked="isAgentSelected(agent.id)"
|
||||||
|
@click.self="() => handleSelectAgent(agent.id)"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<div class="user-info-wrap">
|
||||||
|
<thumbnail
|
||||||
|
:src="agent.thumbnail"
|
||||||
|
size="24px"
|
||||||
|
:username="agent.name"
|
||||||
|
:status="agent.availability_status"
|
||||||
|
/>
|
||||||
|
<h4 class="sub-block-title user-name">
|
||||||
|
{{ agent.name }}
|
||||||
|
</h4>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
{{ agent.email || '---' }}
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
<div class="add-agents__footer">
|
||||||
|
<p>
|
||||||
|
{{
|
||||||
|
$t('TEAMS_SETTINGS.AGENTS.SELECTED_COUNT', {
|
||||||
|
selected: selectedAgents.length,
|
||||||
|
total: agentList.length,
|
||||||
|
})
|
||||||
|
}}
|
||||||
|
</p>
|
||||||
|
<woot-submit-button
|
||||||
|
:button-text="submitButtonText"
|
||||||
|
:loading="isWorking"
|
||||||
|
:disabled="disableSubmitButton"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import Thumbnail from 'dashboard/components/widgets/Thumbnail.vue';
|
||||||
|
|
||||||
|
export default {
|
||||||
|
components: {
|
||||||
|
Thumbnail,
|
||||||
|
},
|
||||||
|
props: {
|
||||||
|
agentList: {
|
||||||
|
type: Array,
|
||||||
|
default: () => [],
|
||||||
|
},
|
||||||
|
selectedAgents: {
|
||||||
|
type: Array,
|
||||||
|
default: () => [],
|
||||||
|
},
|
||||||
|
updateSelectedAgents: {
|
||||||
|
type: Function,
|
||||||
|
default: () => {},
|
||||||
|
},
|
||||||
|
isWorking: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false,
|
||||||
|
},
|
||||||
|
submitButtonText: {
|
||||||
|
type: String,
|
||||||
|
default: '',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {};
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
selectedAgentCount() {
|
||||||
|
return this.selectedAgents.length;
|
||||||
|
},
|
||||||
|
allAgentsSelected() {
|
||||||
|
return this.selectedAgents.length === this.agentList.length;
|
||||||
|
},
|
||||||
|
disableSubmitButton() {
|
||||||
|
return this.selectedAgentCount === 0;
|
||||||
|
},
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
isAgentSelected(agentId) {
|
||||||
|
return this.selectedAgents.includes(agentId);
|
||||||
|
},
|
||||||
|
handleSelectAgent(agentId) {
|
||||||
|
const shouldRemove = this.isAgentSelected(agentId);
|
||||||
|
|
||||||
|
let result = [];
|
||||||
|
if (shouldRemove) {
|
||||||
|
result = this.selectedAgents.filter(item => item !== agentId);
|
||||||
|
} else {
|
||||||
|
result = [...this.selectedAgents, agentId];
|
||||||
|
}
|
||||||
|
|
||||||
|
this.updateSelectedAgents(result);
|
||||||
|
},
|
||||||
|
selectAllAgents() {
|
||||||
|
const result = this.agentList.map(item => item.id);
|
||||||
|
this.updateSelectedAgents(result);
|
||||||
|
},
|
||||||
|
agentRowClass(agentId) {
|
||||||
|
return { 'is-active': this.isAgentSelected(agentId) };
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped lang="scss">
|
||||||
|
.table__meta {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
padding: var(--space-small);
|
||||||
|
}
|
||||||
|
|
||||||
|
.user-info-wrap {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.user-name {
|
||||||
|
margin-bottom: 0;
|
||||||
|
margin-left: var(--space-small);
|
||||||
|
}
|
||||||
|
|
||||||
|
.add-agents__footer {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
}
|
||||||
|
|
||||||
|
.checkbox-wrap {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
|
||||||
|
input {
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.checkbox-cell {
|
||||||
|
width: var(--space-larger);
|
||||||
|
}
|
||||||
|
</style>
|
|
@ -0,0 +1,117 @@
|
||||||
|
<template>
|
||||||
|
<div class="wizard-body columns content-box small-9">
|
||||||
|
<form class="row" @submit.prevent="addAgents">
|
||||||
|
<div class="medium-12 columns">
|
||||||
|
<page-header
|
||||||
|
:header-title="headerTitle"
|
||||||
|
:header-content="$t('TEAMS_SETTINGS.ADD.DESC')"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="medium-12 columns">
|
||||||
|
<div v-if="$v.selectedAgents.$error">
|
||||||
|
<p class="error-message">
|
||||||
|
{{ $t('TEAMS_SETTINGS.ADD.AGENT_VALIDATION_ERROR') }}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<agent-selector
|
||||||
|
:agent-list="agentList"
|
||||||
|
:selected-agents="selectedAgents"
|
||||||
|
:update-selected-agents="updateSelectedAgents"
|
||||||
|
:is-working="isCreating"
|
||||||
|
:submit-button-text="$t('TEAMS_SETTINGS.ADD.BUTTON_TEXT')"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import { mapGetters } from 'vuex';
|
||||||
|
|
||||||
|
import alertMixin from 'shared/mixins/alertMixin';
|
||||||
|
import router from '../../../../index';
|
||||||
|
import PageHeader from '../../SettingsSubPageHeader';
|
||||||
|
import AgentSelector from '../AgentSelector';
|
||||||
|
|
||||||
|
export default {
|
||||||
|
components: {
|
||||||
|
PageHeader,
|
||||||
|
AgentSelector,
|
||||||
|
},
|
||||||
|
mixins: [alertMixin],
|
||||||
|
props: {
|
||||||
|
team: {
|
||||||
|
type: Object,
|
||||||
|
default: () => {},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
validations: {
|
||||||
|
selectedAgents: {
|
||||||
|
isEmpty() {
|
||||||
|
return !!this.selectedAgents.length;
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
selectedAgents: [],
|
||||||
|
isCreating: false,
|
||||||
|
};
|
||||||
|
},
|
||||||
|
|
||||||
|
computed: {
|
||||||
|
...mapGetters({
|
||||||
|
agentList: 'agents/getAgents',
|
||||||
|
}),
|
||||||
|
|
||||||
|
teamId() {
|
||||||
|
return this.$route.params.teamId;
|
||||||
|
},
|
||||||
|
headerTitle() {
|
||||||
|
return this.$t('TEAMS_SETTINGS.ADD.TITLE', {
|
||||||
|
teamName: this.currentTeam.name,
|
||||||
|
});
|
||||||
|
},
|
||||||
|
currentTeam() {
|
||||||
|
return this.$store.getters['teams/getTeam'](this.teamId);
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
mounted() {
|
||||||
|
this.$store.dispatch('agents/get');
|
||||||
|
},
|
||||||
|
|
||||||
|
methods: {
|
||||||
|
updateSelectedAgents(newAgentList) {
|
||||||
|
this.$v.selectedAgents.$touch();
|
||||||
|
this.selectedAgents = [...newAgentList];
|
||||||
|
},
|
||||||
|
selectAllAgents() {
|
||||||
|
this.selectedAgents = this.agentList.map(agent => agent.id);
|
||||||
|
},
|
||||||
|
async addAgents() {
|
||||||
|
this.isCreating = true;
|
||||||
|
const { teamId, selectedAgents } = this;
|
||||||
|
|
||||||
|
try {
|
||||||
|
await this.$store.dispatch('teamMembers/create', {
|
||||||
|
teamId,
|
||||||
|
agentsList: selectedAgents,
|
||||||
|
});
|
||||||
|
router.replace({
|
||||||
|
name: 'settings_teams_finish',
|
||||||
|
params: {
|
||||||
|
page: 'new',
|
||||||
|
teamId,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
} catch (error) {
|
||||||
|
this.showAlert(error.message);
|
||||||
|
}
|
||||||
|
this.isCreating = false;
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
</script>
|
|
@ -0,0 +1,54 @@
|
||||||
|
<template>
|
||||||
|
<div class="wizard-body small-9 columns">
|
||||||
|
<page-header
|
||||||
|
:header-title="$t('TEAMS_SETTINGS.CREATE_FLOW.CREATE.TITLE')"
|
||||||
|
:header-content="$t('TEAMS_SETTINGS.CREATE_FLOW.CREATE.DESC')"
|
||||||
|
/>
|
||||||
|
<div class="row channels">
|
||||||
|
<team-form
|
||||||
|
:on-submit="createTeam"
|
||||||
|
:submit-in-progress="false"
|
||||||
|
:submit-button-text="$t('TEAMS_SETTINGS.FORM.SUBMIT_CREATE')"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import TeamForm from '../TeamForm';
|
||||||
|
import router from '../../../../index';
|
||||||
|
import PageHeader from '../../SettingsSubPageHeader';
|
||||||
|
import alertMixin from 'shared/mixins/alertMixin';
|
||||||
|
|
||||||
|
export default {
|
||||||
|
components: {
|
||||||
|
TeamForm,
|
||||||
|
PageHeader,
|
||||||
|
},
|
||||||
|
mixins: [alertMixin],
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
enabledFeatures: {},
|
||||||
|
};
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
async createTeam(data) {
|
||||||
|
try {
|
||||||
|
const team = await this.$store.dispatch('teams/create', {
|
||||||
|
...data,
|
||||||
|
});
|
||||||
|
|
||||||
|
router.replace({
|
||||||
|
name: 'settings_teams_add_agents',
|
||||||
|
params: {
|
||||||
|
page: 'new',
|
||||||
|
teamId: team.id,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
} catch (error) {
|
||||||
|
this.showAlert(this.$t('TEAMS_SETTINGS.TEAM_FORM.ERROR_MESSAGE'));
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
</script>
|
|
@ -0,0 +1,17 @@
|
||||||
|
<template>
|
||||||
|
<div class="row content-box full-height">
|
||||||
|
<woot-wizard class="small-3 columns" :items="items" />
|
||||||
|
<router-view></router-view>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
computed: {
|
||||||
|
items() {
|
||||||
|
const data = this.$t('TEAMS_SETTINGS.CREATE_FLOW.WIZARD');
|
||||||
|
return data;
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
</script>
|
|
@ -0,0 +1,139 @@
|
||||||
|
<template>
|
||||||
|
<div class="wizard-body columns content-box small-9">
|
||||||
|
<form class="row" @submit.prevent="addAgents">
|
||||||
|
<div class="medium-12 columns">
|
||||||
|
<page-header
|
||||||
|
:header-title="headerTitle"
|
||||||
|
:header-content="$t('TEAMS_SETTINGS.EDIT_FLOW.AGENTS.DESC')"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="medium-12 columns">
|
||||||
|
<div v-if="$v.selectedAgents.$error">
|
||||||
|
<p class="error-message">
|
||||||
|
{{ $t('TEAMS_SETTINGS.ADD.AGENT_VALIDATION_ERROR') }}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<agent-selector
|
||||||
|
v-if="showAgentsList"
|
||||||
|
:agent-list="agentList"
|
||||||
|
:selected-agents="selectedAgents"
|
||||||
|
:update-selected-agents="updateSelectedAgents"
|
||||||
|
:is-working="isCreating"
|
||||||
|
:submit-button-text="
|
||||||
|
$t('TEAMS_SETTINGS.EDIT_FLOW.AGENTS.BUTTON_TEXT')
|
||||||
|
"
|
||||||
|
/>
|
||||||
|
<spinner v-else />
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import { mapGetters } from 'vuex';
|
||||||
|
import Spinner from 'shared/components/Spinner';
|
||||||
|
import alertMixin from 'shared/mixins/alertMixin';
|
||||||
|
|
||||||
|
import router from '../../../../index';
|
||||||
|
import PageHeader from '../../SettingsSubPageHeader';
|
||||||
|
import AgentSelector from '../AgentSelector';
|
||||||
|
|
||||||
|
export default {
|
||||||
|
components: {
|
||||||
|
Spinner,
|
||||||
|
PageHeader,
|
||||||
|
AgentSelector,
|
||||||
|
},
|
||||||
|
mixins: [alertMixin],
|
||||||
|
|
||||||
|
props: {
|
||||||
|
team: {
|
||||||
|
type: Object,
|
||||||
|
default: () => {},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
validations: {
|
||||||
|
selectedAgents: {
|
||||||
|
isEmpty() {
|
||||||
|
return !!this.selectedAgents.length;
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
selectedAgents: [],
|
||||||
|
isCreating: false,
|
||||||
|
};
|
||||||
|
},
|
||||||
|
|
||||||
|
computed: {
|
||||||
|
...mapGetters({
|
||||||
|
agentList: 'agents/getAgents',
|
||||||
|
uiFlags: 'teamMembers/getUIFlags',
|
||||||
|
}),
|
||||||
|
|
||||||
|
teamId() {
|
||||||
|
return this.$route.params.teamId;
|
||||||
|
},
|
||||||
|
headerTitle() {
|
||||||
|
return this.$t('TEAMS_SETTINGS.EDIT_FLOW.AGENTS.TITLE', {
|
||||||
|
teamName: this.currentTeam.name,
|
||||||
|
});
|
||||||
|
},
|
||||||
|
currentTeam() {
|
||||||
|
return this.$store.getters['teams/getTeam'](this.teamId);
|
||||||
|
},
|
||||||
|
teamMembers() {
|
||||||
|
return this.$store.getters['teamMembers/getTeamMembers'](this.teamId);
|
||||||
|
},
|
||||||
|
showAgentsList() {
|
||||||
|
const { id } = this.currentTeam;
|
||||||
|
return id && !this.uiFlags.isFetching;
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
async mounted() {
|
||||||
|
const { teamId } = this.$route.params;
|
||||||
|
this.$store.dispatch('agents/get');
|
||||||
|
try {
|
||||||
|
await this.$store.dispatch('teamMembers/get', {
|
||||||
|
teamId,
|
||||||
|
});
|
||||||
|
const members = this.teamMembers.map(item => item.id);
|
||||||
|
this.updateSelectedAgents(members);
|
||||||
|
} catch {
|
||||||
|
this.updateSelectedAgents([]);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
methods: {
|
||||||
|
updateSelectedAgents(newAgentList) {
|
||||||
|
this.$v.selectedAgents.$touch();
|
||||||
|
this.selectedAgents = [...newAgentList];
|
||||||
|
},
|
||||||
|
async addAgents() {
|
||||||
|
this.isCreating = true;
|
||||||
|
const { teamId, selectedAgents } = this;
|
||||||
|
|
||||||
|
try {
|
||||||
|
await this.$store.dispatch('teamMembers/update', {
|
||||||
|
teamId,
|
||||||
|
agentsList: selectedAgents,
|
||||||
|
});
|
||||||
|
router.replace({
|
||||||
|
name: 'settings_teams_edit_finish',
|
||||||
|
params: {
|
||||||
|
page: 'edit',
|
||||||
|
teamId,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
} catch (error) {
|
||||||
|
this.showAlert(error.message);
|
||||||
|
}
|
||||||
|
this.isCreating = false;
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
</script>
|
|
@ -0,0 +1,77 @@
|
||||||
|
<template>
|
||||||
|
<div class="wizard-body small-9 columns">
|
||||||
|
<page-header
|
||||||
|
:header-title="$t('TEAMS_SETTINGS.EDIT_FLOW.CREATE.TITLE')"
|
||||||
|
:header-content="$t('TEAMS_SETTINGS.EDIT_FLOW.CREATE.DESC')"
|
||||||
|
/>
|
||||||
|
<div class="row channels">
|
||||||
|
<team-form
|
||||||
|
v-if="showTeamForm"
|
||||||
|
:on-submit="updateTeam"
|
||||||
|
:submit-in-progress="false"
|
||||||
|
:submit-button-text="$t('TEAMS_SETTINGS.EDIT_FLOW.CREATE.BUTTON_TEXT')"
|
||||||
|
:form-data="teamData"
|
||||||
|
/>
|
||||||
|
<spinner v-else />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import TeamForm from '../TeamForm';
|
||||||
|
import router from '../../../../index';
|
||||||
|
import PageHeader from '../../SettingsSubPageHeader';
|
||||||
|
import alertMixin from 'shared/mixins/alertMixin';
|
||||||
|
|
||||||
|
import { mapGetters } from 'vuex';
|
||||||
|
import Spinner from 'shared/components/Spinner';
|
||||||
|
|
||||||
|
export default {
|
||||||
|
components: {
|
||||||
|
TeamForm,
|
||||||
|
PageHeader,
|
||||||
|
Spinner,
|
||||||
|
},
|
||||||
|
mixins: [alertMixin],
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
enabledFeatures: {},
|
||||||
|
};
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
teamData() {
|
||||||
|
const { teamId } = this.$route.params;
|
||||||
|
return this.$store.getters['teams/getTeam'](teamId);
|
||||||
|
},
|
||||||
|
showTeamForm() {
|
||||||
|
const { id } = this.teamData;
|
||||||
|
return id && !this.uiFlags.isFetching;
|
||||||
|
},
|
||||||
|
...mapGetters({
|
||||||
|
uiFlags: 'teams/getUIFlags',
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
async updateTeam(data) {
|
||||||
|
try {
|
||||||
|
const { teamId } = this.$route.params;
|
||||||
|
|
||||||
|
await this.$store.dispatch('teams/update', {
|
||||||
|
id: teamId,
|
||||||
|
...data,
|
||||||
|
});
|
||||||
|
|
||||||
|
router.replace({
|
||||||
|
name: 'settings_teams_edit_members',
|
||||||
|
params: {
|
||||||
|
page: 'edit',
|
||||||
|
teamId,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
} catch (error) {
|
||||||
|
this.showAlert(this.$t('TEAMS_SETTINGS.TEAM_FORM.ERROR_MESSAGE'));
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
</script>
|
|
@ -0,0 +1,17 @@
|
||||||
|
<template>
|
||||||
|
<div class="row content-box full-height">
|
||||||
|
<woot-wizard class="small-3 columns" :items="items" />
|
||||||
|
<router-view></router-view>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
computed: {
|
||||||
|
items() {
|
||||||
|
const data = this.$t('TEAMS_SETTINGS.EDIT_FLOW.WIZARD');
|
||||||
|
return data;
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
</script>
|
|
@ -0,0 +1,38 @@
|
||||||
|
<template>
|
||||||
|
<div class="wizard-body columns content-box small-9">
|
||||||
|
<empty-state
|
||||||
|
:title="$t('TEAMS_SETTINGS.FINISH.TITLE')"
|
||||||
|
:message="$t('TEAMS_SETTINGS.FINISH.MESSAGE')"
|
||||||
|
:button-text="$t('TEAMS_SETTINGS.FINISH.BUTTON_TEXT')"
|
||||||
|
>
|
||||||
|
<div class="medium-12 columns text-center">
|
||||||
|
<router-link
|
||||||
|
class="button success nice"
|
||||||
|
:to="{
|
||||||
|
name: 'settings_teams_list',
|
||||||
|
}"
|
||||||
|
>
|
||||||
|
{{ $t('TEAMS_SETTINGS.FINISH.BUTTON_TEXT') }}
|
||||||
|
</router-link>
|
||||||
|
</div>
|
||||||
|
</empty-state>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import EmptyState from '../../../../components/widgets/EmptyState';
|
||||||
|
|
||||||
|
export default {
|
||||||
|
components: {
|
||||||
|
EmptyState,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
@import '~dashboard/assets/scss/variables';
|
||||||
|
|
||||||
|
.website--code {
|
||||||
|
margin: $space-normal auto;
|
||||||
|
max-width: 70%;
|
||||||
|
}
|
||||||
|
</style>
|
|
@ -0,0 +1,140 @@
|
||||||
|
<template>
|
||||||
|
<div class="column content-box">
|
||||||
|
<div class="row">
|
||||||
|
<div class="small-8 columns">
|
||||||
|
<p v-if="!teamsList.length" class="no-items-error-message">
|
||||||
|
{{ $t('TEAMS_SETTINGS.LIST.404') }}
|
||||||
|
<router-link
|
||||||
|
v-if="isAdmin"
|
||||||
|
:to="addAccountScoping('settings/teams/new')"
|
||||||
|
>
|
||||||
|
{{ $t('TEAMS_SETTINGS.NEW_TEAM') }}
|
||||||
|
</router-link>
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<table v-if="teamsList.length" class="woot-table">
|
||||||
|
<tbody>
|
||||||
|
<tr v-for="item in teamsList" :key="item.id">
|
||||||
|
<td>
|
||||||
|
<span class="agent-name">{{ item.name }}</span>
|
||||||
|
<p>{{ item.description }}</p>
|
||||||
|
</td>
|
||||||
|
|
||||||
|
<td>
|
||||||
|
<div class="button-wrapper">
|
||||||
|
<router-link
|
||||||
|
:to="addAccountScoping(`settings/teams/${item.id}/edit`)"
|
||||||
|
>
|
||||||
|
<woot-submit-button
|
||||||
|
v-if="isAdmin"
|
||||||
|
:button-text="$t('TEAMS_SETTINGS.LIST.EDIT_TEAM')"
|
||||||
|
icon-class="ion-gear-b"
|
||||||
|
button-class="link hollow grey-btn"
|
||||||
|
/>
|
||||||
|
</router-link>
|
||||||
|
|
||||||
|
<woot-submit-button
|
||||||
|
v-if="isAdmin"
|
||||||
|
:button-text="$t('TEAMS_SETTINGS.DELETE.BUTTON_TEXT')"
|
||||||
|
:loading="loading[item.id]"
|
||||||
|
icon-class="ion-close-circled"
|
||||||
|
button-class="link hollow grey-btn"
|
||||||
|
@click="openDelete(item)"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="small-4 columns">
|
||||||
|
<span
|
||||||
|
v-html="
|
||||||
|
$t('TEAMS_SETTINGS.SIDEBAR_TXT', {
|
||||||
|
installationName: globalConfig.installationName,
|
||||||
|
})
|
||||||
|
"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<woot-delete-modal
|
||||||
|
:show.sync="showDeletePopup"
|
||||||
|
:on-close="closeDelete"
|
||||||
|
:on-confirm="confirmDeletion"
|
||||||
|
:title="deleteTitle"
|
||||||
|
:message="$t('TEAMS_SETTINGS.DELETE.CONFIRM.MESSAGE')"
|
||||||
|
:confirm-text="deleteConfirmText"
|
||||||
|
:reject-text="deleteRejectText"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<script>
|
||||||
|
import { mapGetters } from 'vuex';
|
||||||
|
import adminMixin from '../../../../mixins/isAdmin';
|
||||||
|
import accountMixin from '../../../../mixins/account';
|
||||||
|
import alertMixin from 'shared/mixins/alertMixin';
|
||||||
|
|
||||||
|
export default {
|
||||||
|
components: {},
|
||||||
|
mixins: [adminMixin, accountMixin, alertMixin],
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
loading: {},
|
||||||
|
showSettings: false,
|
||||||
|
showDeletePopup: false,
|
||||||
|
selectedTeam: {},
|
||||||
|
};
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
...mapGetters({
|
||||||
|
teamsList: 'teams/getTeams',
|
||||||
|
globalConfig: 'globalConfig/get',
|
||||||
|
}),
|
||||||
|
deleteConfirmText() {
|
||||||
|
return `${this.$t('TEAMS_SETTINGS.DELETE.CONFIRM.YES')} ${
|
||||||
|
this.selectedTeam.name
|
||||||
|
}`;
|
||||||
|
},
|
||||||
|
deleteRejectText() {
|
||||||
|
return this.$t('TEAMS_SETTINGS.DELETE.CONFIRM.NO');
|
||||||
|
},
|
||||||
|
deleteTitle() {
|
||||||
|
return this.$t('TEAMS_SETTINGS.DELETE.CONFIRM.TITLE', {
|
||||||
|
teamName: this.selectedTeam.name,
|
||||||
|
});
|
||||||
|
},
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
async deleteTeam({ id }) {
|
||||||
|
try {
|
||||||
|
await this.$store.dispatch('teams/delete', id);
|
||||||
|
this.showAlert(this.$t('TEAMS_SETTINGS.DELETE.API.SUCCESS_MESSAGE'));
|
||||||
|
} catch (error) {
|
||||||
|
this.showAlert(this.$t('TEAMS_SETTINGS.DELETE.API.ERROR_MESSAGE'));
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
confirmDeletion() {
|
||||||
|
this.deleteTeam(this.selectedTeam);
|
||||||
|
this.closeDelete();
|
||||||
|
},
|
||||||
|
openDelete(team) {
|
||||||
|
this.showDeletePopup = true;
|
||||||
|
this.selectedTeam = team;
|
||||||
|
},
|
||||||
|
closeDelete() {
|
||||||
|
this.showDeletePopup = false;
|
||||||
|
this.selectedTeam = {};
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.button-wrapper {
|
||||||
|
min-width: unset;
|
||||||
|
justify-content: flex-end;
|
||||||
|
padding-right: var(--space-large);
|
||||||
|
}
|
||||||
|
</style>
|
|
@ -0,0 +1,99 @@
|
||||||
|
<template>
|
||||||
|
<div class="row">
|
||||||
|
<div class="small-12 medium-8 columns">
|
||||||
|
<form class="row" @submit.prevent="handleSubmit">
|
||||||
|
<woot-input
|
||||||
|
v-model.trim="title"
|
||||||
|
:class="{ error: $v.title.$error }"
|
||||||
|
class="medium-12 columns"
|
||||||
|
:label="$t('TEAMS_SETTINGS.FORM.NAME.LABEL')"
|
||||||
|
:placeholder="$t('TEAMS_SETTINGS.FORM.NAME.PLACEHOLDER')"
|
||||||
|
@input="$v.title.$touch"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<woot-input
|
||||||
|
v-model.trim="description"
|
||||||
|
:class="{ error: $v.description.$error }"
|
||||||
|
class="medium-12 columns"
|
||||||
|
:label="$t('TEAMS_SETTINGS.FORM.DESCRIPTION.LABEL')"
|
||||||
|
:placeholder="$t('TEAMS_SETTINGS.FORM.DESCRIPTION.PLACEHOLDER')"
|
||||||
|
@input="$v.description.$touch"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<div class="medium-12">
|
||||||
|
<input v-model="allowAutoAssign" type="checkbox" :value="true" />
|
||||||
|
<label for="conversation_creation">
|
||||||
|
{{ $t('TEAMS_SETTINGS.FORM.AUTO_ASSIGN.LABEL') }}
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
<div class="modal-footer">
|
||||||
|
<div class="medium-12 columns">
|
||||||
|
<woot-submit-button
|
||||||
|
:disabled="$v.title.$invalid || submitInProgress"
|
||||||
|
:button-text="submitButtonText"
|
||||||
|
:loading="submitInProgress"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import WootSubmitButton from '../../../../components/buttons/FormSubmitButton';
|
||||||
|
import validations from './helpers/validations';
|
||||||
|
|
||||||
|
export default {
|
||||||
|
components: {
|
||||||
|
WootSubmitButton,
|
||||||
|
},
|
||||||
|
|
||||||
|
props: {
|
||||||
|
onSubmit: {
|
||||||
|
type: Function,
|
||||||
|
default: () => {},
|
||||||
|
},
|
||||||
|
submitInProgress: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false,
|
||||||
|
},
|
||||||
|
formData: {
|
||||||
|
type: Object,
|
||||||
|
default: () => {},
|
||||||
|
},
|
||||||
|
submitButtonText: {
|
||||||
|
type: String,
|
||||||
|
default: '',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
const formData = this.formData || {};
|
||||||
|
const {
|
||||||
|
description = '',
|
||||||
|
name: title = '',
|
||||||
|
allow_auto_assign: allowAutoAssign = true,
|
||||||
|
} = formData;
|
||||||
|
|
||||||
|
return {
|
||||||
|
description,
|
||||||
|
title,
|
||||||
|
allowAutoAssign,
|
||||||
|
};
|
||||||
|
},
|
||||||
|
validations,
|
||||||
|
methods: {
|
||||||
|
handleSubmit() {
|
||||||
|
this.$v.$touch();
|
||||||
|
if (this.$v.$invalid) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.onSubmit({
|
||||||
|
description: this.description,
|
||||||
|
name: this.title,
|
||||||
|
allow_auto_assign: this.allowAutoAssign,
|
||||||
|
});
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
</script>
|
|
@ -0,0 +1,10 @@
|
||||||
|
import { required, minLength } from 'vuelidate/lib/validators';
|
||||||
|
|
||||||
|
export default {
|
||||||
|
title: {
|
||||||
|
required,
|
||||||
|
minLength: minLength(2),
|
||||||
|
},
|
||||||
|
description: {},
|
||||||
|
showOnSidebar: {},
|
||||||
|
};
|
|
@ -0,0 +1,91 @@
|
||||||
|
/* eslint arrow-body-style: 0 */
|
||||||
|
import SettingsContent from '../Wrapper';
|
||||||
|
import TeamsHome from './Index';
|
||||||
|
import CreateStepWrap from './Create/Index';
|
||||||
|
import EditStepWrap from './Edit/Index';
|
||||||
|
import CreateTeam from './Create/CreateTeam';
|
||||||
|
import EditTeam from './Edit/EditTeam';
|
||||||
|
import AddAgents from './Create/AddAgents';
|
||||||
|
import EditAgents from './Edit/EditAgents';
|
||||||
|
import FinishSetup from './FinishSetup';
|
||||||
|
import { frontendURL } from '../../../../helper/URLHelper';
|
||||||
|
|
||||||
|
export default {
|
||||||
|
routes: [
|
||||||
|
{
|
||||||
|
path: frontendURL('accounts/:accountId/settings/teams'),
|
||||||
|
component: SettingsContent,
|
||||||
|
props: params => {
|
||||||
|
const showBackButton = params.name !== 'settings_teams_list';
|
||||||
|
return {
|
||||||
|
headerTitle: 'TEAMS_SETTINGS.HEADER',
|
||||||
|
headerButtonText: 'TEAMS_SETTINGS.NEW_TEAM',
|
||||||
|
icon: 'ion-ios-people',
|
||||||
|
newButtonRoutes: ['settings_teams_new'],
|
||||||
|
showBackButton,
|
||||||
|
};
|
||||||
|
},
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
path: '',
|
||||||
|
name: 'settings_teams',
|
||||||
|
redirect: 'list',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: 'list',
|
||||||
|
name: 'settings_teams_list',
|
||||||
|
component: TeamsHome,
|
||||||
|
roles: ['administrator'],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: 'new',
|
||||||
|
component: CreateStepWrap,
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
path: '',
|
||||||
|
name: 'settings_teams_new',
|
||||||
|
component: CreateTeam,
|
||||||
|
roles: ['administrator'],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: ':teamId/finish',
|
||||||
|
name: 'settings_teams_finish',
|
||||||
|
component: FinishSetup,
|
||||||
|
roles: ['administrator'],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: ':teamId/agents',
|
||||||
|
name: 'settings_teams_add_agents',
|
||||||
|
roles: ['administrator'],
|
||||||
|
component: AddAgents,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: ':teamId/edit',
|
||||||
|
component: EditStepWrap,
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
path: '',
|
||||||
|
name: 'settings_teams_edit',
|
||||||
|
component: EditTeam,
|
||||||
|
roles: ['administrator'],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: 'agents',
|
||||||
|
name: 'settings_teams_edit_members',
|
||||||
|
component: EditAgents,
|
||||||
|
roles: ['administrator'],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: 'finish',
|
||||||
|
name: 'settings_teams_edit_finish',
|
||||||
|
roles: ['administrator'],
|
||||||
|
component: FinishSetup,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
};
|
|
@ -56,4 +56,27 @@ describe('#actions', () => {
|
||||||
]);
|
]);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('#update', () => {
|
||||||
|
it('sends correct actions if API is success', async () => {
|
||||||
|
axios.patch.mockResolvedValue({ data: teamMembers });
|
||||||
|
await actions.update({ commit }, { agentsList: teamMembers, teamId: 1 });
|
||||||
|
|
||||||
|
expect(commit.mock.calls).toEqual([
|
||||||
|
[SET_TEAM_MEMBERS_UI_FLAG, { isUpdating: true }],
|
||||||
|
[ADD_AGENTS_TO_TEAM, { data: teamMembers }],
|
||||||
|
[SET_TEAM_MEMBERS_UI_FLAG, { isUpdating: false }],
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
it('sends correct actions if API is error', async () => {
|
||||||
|
axios.patch.mockRejectedValue({ message: 'Incorrect header' });
|
||||||
|
await expect(
|
||||||
|
actions.update({ commit }, { agentsList: teamMembers, teamId: 1 })
|
||||||
|
).rejects.toThrow(Error);
|
||||||
|
expect(commit.mock.calls).toEqual([
|
||||||
|
[SET_TEAM_MEMBERS_UI_FLAG, { isUpdating: true }],
|
||||||
|
[SET_TEAM_MEMBERS_UI_FLAG, { isUpdating: false }],
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -60,7 +60,7 @@ describe('#actions', () => {
|
||||||
|
|
||||||
describe('#update', () => {
|
describe('#update', () => {
|
||||||
it('sends correct actions if API is success', async () => {
|
it('sends correct actions if API is success', async () => {
|
||||||
axios.patch.mockResolvedValue({ data: { payload: teamsList[1] } });
|
axios.patch.mockResolvedValue({ data: teamsList[1] });
|
||||||
await actions.update({ commit }, teamsList[1]);
|
await actions.update({ commit }, teamsList[1]);
|
||||||
|
|
||||||
expect(commit.mock.calls).toEqual([
|
expect(commit.mock.calls).toEqual([
|
||||||
|
|
|
@ -46,6 +46,20 @@ export const actions = {
|
||||||
commit(SET_TEAM_MEMBERS_UI_FLAG, { isCreating: false });
|
commit(SET_TEAM_MEMBERS_UI_FLAG, { isCreating: false });
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
update: async ({ commit }, { agentsList, teamId }) => {
|
||||||
|
commit(SET_TEAM_MEMBERS_UI_FLAG, { isUpdating: true });
|
||||||
|
try {
|
||||||
|
const response = await TeamsAPI.updateAgents({
|
||||||
|
agentsList,
|
||||||
|
teamId,
|
||||||
|
});
|
||||||
|
commit(ADD_AGENTS_TO_TEAM, response);
|
||||||
|
} catch (error) {
|
||||||
|
throw new Error(error);
|
||||||
|
} finally {
|
||||||
|
commit(SET_TEAM_MEMBERS_UI_FLAG, { isUpdating: false });
|
||||||
|
}
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
export const mutations = {
|
export const mutations = {
|
||||||
|
|
|
@ -56,7 +56,7 @@ export const actions = {
|
||||||
commit(SET_TEAM_UI_FLAG, { isUpdating: true });
|
commit(SET_TEAM_UI_FLAG, { isUpdating: true });
|
||||||
try {
|
try {
|
||||||
const response = await TeamsAPI.update(id, updateObj);
|
const response = await TeamsAPI.update(id, updateObj);
|
||||||
commit(EDIT_TEAM, response.data.payload);
|
commit(EDIT_TEAM, response.data);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
throw new Error(error);
|
throw new Error(error);
|
||||||
} finally {
|
} finally {
|
||||||
|
|
|
@ -11790,4 +11790,4 @@ yauzl@2.10.0, yauzl@^2.10.0:
|
||||||
integrity sha1-x+sXyT4RLLEIb6bY5R+wZnt5pfk=
|
integrity sha1-x+sXyT4RLLEIb6bY5R+wZnt5pfk=
|
||||||
dependencies:
|
dependencies:
|
||||||
buffer-crc32 "~0.2.3"
|
buffer-crc32 "~0.2.3"
|
||||||
fd-slicer "~1.1.0"
|
fd-slicer "~1.1.0"
|
Loading…
Add table
Add a link
Reference in a new issue