From 941d4219f02578f6a3351946c92b269e00647e99 Mon Sep 17 00:00:00 2001 From: Nithin David Thomas Date: Mon, 15 Mar 2021 18:35:56 +0530 Subject: [PATCH] feat: Set up store for teams (#1689) --- .../dashboard/api/specs/teams.spec.js | 1 + app/javascript/dashboard/api/teams.js | 6 + .../dashboard/components/layout/Sidebar.vue | 1 - .../widgets/conversation/ConversationBox.vue | 1 + .../dashboard/i18n/default-sidebar.js | 14 ++ .../dashboard/i18n/locale/en/index.js | 2 + .../i18n/locale/en/teamsSettings.json | 123 ++++++++++++ .../dashboard/settings/inbox/Settings.vue | 1 + .../dashboard/settings/settings.routes.js | 2 + .../settings/teams/AgentSelector.vue | 179 ++++++++++++++++++ .../settings/teams/Create/AddAgents.vue | 117 ++++++++++++ .../settings/teams/Create/CreateTeam.vue | 54 ++++++ .../dashboard/settings/teams/Create/Index.vue | 17 ++ .../settings/teams/Edit/EditAgents.vue | 139 ++++++++++++++ .../settings/teams/Edit/EditTeam.vue | 77 ++++++++ .../dashboard/settings/teams/Edit/Index.vue | 17 ++ .../dashboard/settings/teams/FinishSetup.vue | 38 ++++ .../routes/dashboard/settings/teams/Index.vue | 140 ++++++++++++++ .../dashboard/settings/teams/TeamForm.vue | 99 ++++++++++ .../settings/teams/helpers/validations.js | 10 + .../dashboard/settings/teams/teams.routes.js | 91 +++++++++ .../modules/specs/teamMembers/actions.spec.js | 23 +++ .../store/modules/specs/teams/actions.spec.js | 2 +- .../dashboard/store/modules/teamMembers.js | 14 ++ .../dashboard/store/modules/teams/actions.js | 2 +- yarn.lock | 2 +- 26 files changed, 1168 insertions(+), 4 deletions(-) create mode 100644 app/javascript/dashboard/i18n/locale/en/teamsSettings.json create mode 100644 app/javascript/dashboard/routes/dashboard/settings/teams/AgentSelector.vue create mode 100644 app/javascript/dashboard/routes/dashboard/settings/teams/Create/AddAgents.vue create mode 100644 app/javascript/dashboard/routes/dashboard/settings/teams/Create/CreateTeam.vue create mode 100644 app/javascript/dashboard/routes/dashboard/settings/teams/Create/Index.vue create mode 100644 app/javascript/dashboard/routes/dashboard/settings/teams/Edit/EditAgents.vue create mode 100644 app/javascript/dashboard/routes/dashboard/settings/teams/Edit/EditTeam.vue create mode 100644 app/javascript/dashboard/routes/dashboard/settings/teams/Edit/Index.vue create mode 100644 app/javascript/dashboard/routes/dashboard/settings/teams/FinishSetup.vue create mode 100644 app/javascript/dashboard/routes/dashboard/settings/teams/Index.vue create mode 100644 app/javascript/dashboard/routes/dashboard/settings/teams/TeamForm.vue create mode 100644 app/javascript/dashboard/routes/dashboard/settings/teams/helpers/validations.js create mode 100644 app/javascript/dashboard/routes/dashboard/settings/teams/teams.routes.js diff --git a/app/javascript/dashboard/api/specs/teams.spec.js b/app/javascript/dashboard/api/specs/teams.spec.js index 7622a5417..6b01ab359 100644 --- a/app/javascript/dashboard/api/specs/teams.spec.js +++ b/app/javascript/dashboard/api/specs/teams.spec.js @@ -11,5 +11,6 @@ describe('#TeamsAPI', () => { expect(teams).toHaveProperty('delete'); expect(teams).toHaveProperty('getAgents'); expect(teams).toHaveProperty('addAgents'); + expect(teams).toHaveProperty('updateAgents'); }); }); diff --git a/app/javascript/dashboard/api/teams.js b/app/javascript/dashboard/api/teams.js index 9c117c71b..ba202dff2 100644 --- a/app/javascript/dashboard/api/teams.js +++ b/app/javascript/dashboard/api/teams.js @@ -15,6 +15,12 @@ export class TeamsAPI extends ApiClient { user_ids: agentsList, }); } + + updateAgents({ teamId, agentsList }) { + return axios.patch(`${this.url}/${teamId}/team_members`, { + user_ids: agentsList, + }); + } } export default new TeamsAPI(); diff --git a/app/javascript/dashboard/components/layout/Sidebar.vue b/app/javascript/dashboard/components/layout/Sidebar.vue index 19c56c2af..59d0c67cb 100644 --- a/app/javascript/dashboard/components/layout/Sidebar.vue +++ b/app/javascript/dashboard/components/layout/Sidebar.vue @@ -178,7 +178,6 @@ export default { icon: 'ion-ios-people', label: 'TEAMS', hasSubMenu: true, - newLink: true, key: 'team', cssClass: 'menu-title align-justify teams-sidebar-menu', toState: frontendURL(`accounts/${this.accountId}/settings/teams`), diff --git a/app/javascript/dashboard/components/widgets/conversation/ConversationBox.vue b/app/javascript/dashboard/components/widgets/conversation/ConversationBox.vue index 587f78304..d6d5bbd85 100644 --- a/app/javascript/dashboard/components/widgets/conversation/ConversationBox.vue +++ b/app/javascript/dashboard/components/widgets/conversation/ConversationBox.vue @@ -74,6 +74,7 @@ export default { flex-direction: column; width: 100%; border-left: 1px solid var(--color-border); + background: var(--color-background-light); } .messages-and-sidebar { diff --git a/app/javascript/dashboard/i18n/default-sidebar.js b/app/javascript/dashboard/i18n/default-sidebar.js index c4074e433..7faa7d2e8 100644 --- a/app/javascript/dashboard/i18n/default-sidebar.js +++ b/app/javascript/dashboard/i18n/default-sidebar.js @@ -75,6 +75,13 @@ export const getSidebarItems = accountId => ({ 'settings_integrations_integration', 'general_settings', '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: { back: { @@ -91,6 +98,13 @@ export const getSidebarItems = accountId => ({ toState: frontendURL(`accounts/${accountId}/settings/agents/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: { icon: 'ion-archive', label: 'INBOXES', diff --git a/app/javascript/dashboard/i18n/locale/en/index.js b/app/javascript/dashboard/i18n/locale/en/index.js index 5dfc44e4b..53d1438c2 100644 --- a/app/javascript/dashboard/i18n/locale/en/index.js +++ b/app/javascript/dashboard/i18n/locale/en/index.js @@ -13,6 +13,7 @@ import { default as _settings } from './settings.json'; import { default as _signup } from './signup.json'; import { default as _integrations } from './integrations.json'; import { default as _generalSettings } from './generalSettings.json'; +import { default as _teamsSettings } from './teamsSettings.json'; export default { ..._agentMgmt, @@ -30,4 +31,5 @@ export default { ..._signup, ..._integrations, ..._generalSettings, + ..._teamsSettings, }; diff --git a/app/javascript/dashboard/i18n/locale/en/teamsSettings.json b/app/javascript/dashboard/i18n/locale/en/teamsSettings.json new file mode 100644 index 000000000..a836134df --- /dev/null +++ b/app/javascript/dashboard/i18n/locale/en/teamsSettings.json @@ -0,0 +1,123 @@ +{ + "TEAMS_SETTINGS": { + "NEW_TEAM": "Create new team", + "HEADER": "Teams", + "SIDEBAR_TXT": "

Teams

Teams let you organize your agents into groups based on their responsibilities.
A user can be part of multiple teams. You can assign conversations to a team when you are working collaboratively.

", + "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" + } + } +} diff --git a/app/javascript/dashboard/routes/dashboard/settings/inbox/Settings.vue b/app/javascript/dashboard/routes/dashboard/settings/inbox/Settings.vue index 83d6b57f6..93820a9ac 100644 --- a/app/javascript/dashboard/routes/dashboard/settings/inbox/Settings.vue +++ b/app/javascript/dashboard/routes/dashboard/settings/inbox/Settings.vue @@ -404,6 +404,7 @@ export default { this.selectedTabIndex = 0; this.selectedAgents = []; this.$store.dispatch('agents/get'); + this.$store.dispatch('teams/get'); this.$store.dispatch('inboxes/get').then(() => { this.fetchAttachedAgents(); this.avatarUrl = this.inbox.avatar_url; diff --git a/app/javascript/dashboard/routes/dashboard/settings/settings.routes.js b/app/javascript/dashboard/routes/dashboard/settings/settings.routes.js index c82f5dfe4..46617349c 100644 --- a/app/javascript/dashboard/routes/dashboard/settings/settings.routes.js +++ b/app/javascript/dashboard/routes/dashboard/settings/settings.routes.js @@ -7,6 +7,7 @@ import integrations from './integrations/integrations.routes'; import labels from './labels/labels.routes'; import profile from './profile/profile.routes'; import reports from './reports/reports.routes'; +import teams from './teams/teams.routes'; import store from '../../../store'; export default { @@ -30,5 +31,6 @@ export default { ...labels.routes, ...profile.routes, ...reports.routes, + ...teams.routes, ], }; diff --git a/app/javascript/dashboard/routes/dashboard/settings/teams/AgentSelector.vue b/app/javascript/dashboard/routes/dashboard/settings/teams/AgentSelector.vue new file mode 100644 index 000000000..6a0bb7e21 --- /dev/null +++ b/app/javascript/dashboard/routes/dashboard/settings/teams/AgentSelector.vue @@ -0,0 +1,179 @@ + + + + + diff --git a/app/javascript/dashboard/routes/dashboard/settings/teams/Create/AddAgents.vue b/app/javascript/dashboard/routes/dashboard/settings/teams/Create/AddAgents.vue new file mode 100644 index 000000000..ec59c6b94 --- /dev/null +++ b/app/javascript/dashboard/routes/dashboard/settings/teams/Create/AddAgents.vue @@ -0,0 +1,117 @@ + + + diff --git a/app/javascript/dashboard/routes/dashboard/settings/teams/Create/CreateTeam.vue b/app/javascript/dashboard/routes/dashboard/settings/teams/Create/CreateTeam.vue new file mode 100644 index 000000000..ff596a953 --- /dev/null +++ b/app/javascript/dashboard/routes/dashboard/settings/teams/Create/CreateTeam.vue @@ -0,0 +1,54 @@ + + + diff --git a/app/javascript/dashboard/routes/dashboard/settings/teams/Create/Index.vue b/app/javascript/dashboard/routes/dashboard/settings/teams/Create/Index.vue new file mode 100644 index 000000000..33f6b3c3f --- /dev/null +++ b/app/javascript/dashboard/routes/dashboard/settings/teams/Create/Index.vue @@ -0,0 +1,17 @@ + + + diff --git a/app/javascript/dashboard/routes/dashboard/settings/teams/Edit/EditAgents.vue b/app/javascript/dashboard/routes/dashboard/settings/teams/Edit/EditAgents.vue new file mode 100644 index 000000000..e99384dff --- /dev/null +++ b/app/javascript/dashboard/routes/dashboard/settings/teams/Edit/EditAgents.vue @@ -0,0 +1,139 @@ + + + diff --git a/app/javascript/dashboard/routes/dashboard/settings/teams/Edit/EditTeam.vue b/app/javascript/dashboard/routes/dashboard/settings/teams/Edit/EditTeam.vue new file mode 100644 index 000000000..fc795fab6 --- /dev/null +++ b/app/javascript/dashboard/routes/dashboard/settings/teams/Edit/EditTeam.vue @@ -0,0 +1,77 @@ + + + diff --git a/app/javascript/dashboard/routes/dashboard/settings/teams/Edit/Index.vue b/app/javascript/dashboard/routes/dashboard/settings/teams/Edit/Index.vue new file mode 100644 index 000000000..f85042003 --- /dev/null +++ b/app/javascript/dashboard/routes/dashboard/settings/teams/Edit/Index.vue @@ -0,0 +1,17 @@ + + + diff --git a/app/javascript/dashboard/routes/dashboard/settings/teams/FinishSetup.vue b/app/javascript/dashboard/routes/dashboard/settings/teams/FinishSetup.vue new file mode 100644 index 000000000..5290c369e --- /dev/null +++ b/app/javascript/dashboard/routes/dashboard/settings/teams/FinishSetup.vue @@ -0,0 +1,38 @@ + + + + diff --git a/app/javascript/dashboard/routes/dashboard/settings/teams/Index.vue b/app/javascript/dashboard/routes/dashboard/settings/teams/Index.vue new file mode 100644 index 000000000..ac74ed1ae --- /dev/null +++ b/app/javascript/dashboard/routes/dashboard/settings/teams/Index.vue @@ -0,0 +1,140 @@ + + + diff --git a/app/javascript/dashboard/routes/dashboard/settings/teams/TeamForm.vue b/app/javascript/dashboard/routes/dashboard/settings/teams/TeamForm.vue new file mode 100644 index 000000000..7f388c734 --- /dev/null +++ b/app/javascript/dashboard/routes/dashboard/settings/teams/TeamForm.vue @@ -0,0 +1,99 @@ + + + diff --git a/app/javascript/dashboard/routes/dashboard/settings/teams/helpers/validations.js b/app/javascript/dashboard/routes/dashboard/settings/teams/helpers/validations.js new file mode 100644 index 000000000..3f063a0c4 --- /dev/null +++ b/app/javascript/dashboard/routes/dashboard/settings/teams/helpers/validations.js @@ -0,0 +1,10 @@ +import { required, minLength } from 'vuelidate/lib/validators'; + +export default { + title: { + required, + minLength: minLength(2), + }, + description: {}, + showOnSidebar: {}, +}; diff --git a/app/javascript/dashboard/routes/dashboard/settings/teams/teams.routes.js b/app/javascript/dashboard/routes/dashboard/settings/teams/teams.routes.js new file mode 100644 index 000000000..95429bd46 --- /dev/null +++ b/app/javascript/dashboard/routes/dashboard/settings/teams/teams.routes.js @@ -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, + }, + ], + }, + ], + }, + ], +}; diff --git a/app/javascript/dashboard/store/modules/specs/teamMembers/actions.spec.js b/app/javascript/dashboard/store/modules/specs/teamMembers/actions.spec.js index 07cb244a9..d293a19eb 100644 --- a/app/javascript/dashboard/store/modules/specs/teamMembers/actions.spec.js +++ b/app/javascript/dashboard/store/modules/specs/teamMembers/actions.spec.js @@ -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 }], + ]); + }); + }); }); diff --git a/app/javascript/dashboard/store/modules/specs/teams/actions.spec.js b/app/javascript/dashboard/store/modules/specs/teams/actions.spec.js index 855322105..8c11fb3a7 100644 --- a/app/javascript/dashboard/store/modules/specs/teams/actions.spec.js +++ b/app/javascript/dashboard/store/modules/specs/teams/actions.spec.js @@ -60,7 +60,7 @@ describe('#actions', () => { describe('#update', () => { 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]); expect(commit.mock.calls).toEqual([ diff --git a/app/javascript/dashboard/store/modules/teamMembers.js b/app/javascript/dashboard/store/modules/teamMembers.js index 581cac4f8..d93df1793 100644 --- a/app/javascript/dashboard/store/modules/teamMembers.js +++ b/app/javascript/dashboard/store/modules/teamMembers.js @@ -46,6 +46,20 @@ export const actions = { 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 = { diff --git a/app/javascript/dashboard/store/modules/teams/actions.js b/app/javascript/dashboard/store/modules/teams/actions.js index 39bc38df2..be6b842e2 100644 --- a/app/javascript/dashboard/store/modules/teams/actions.js +++ b/app/javascript/dashboard/store/modules/teams/actions.js @@ -56,7 +56,7 @@ export const actions = { commit(SET_TEAM_UI_FLAG, { isUpdating: true }); try { const response = await TeamsAPI.update(id, updateObj); - commit(EDIT_TEAM, response.data.payload); + commit(EDIT_TEAM, response.data); } catch (error) { throw new Error(error); } finally { diff --git a/yarn.lock b/yarn.lock index d6319983a..011be7572 100644 --- a/yarn.lock +++ b/yarn.lock @@ -11790,4 +11790,4 @@ yauzl@2.10.0, yauzl@^2.10.0: integrity sha1-x+sXyT4RLLEIb6bY5R+wZnt5pfk= dependencies: buffer-crc32 "~0.2.3" - fd-slicer "~1.1.0" + fd-slicer "~1.1.0" \ No newline at end of file