feat: Show teams on sidebar (#1754)

Co-authored-by: Pranav Raj S <pranav@chatwoot.com>
Co-authored-by: Sojan <sojan@pepalo.com>
This commit is contained in:
Nithin David Thomas 2021-02-13 14:58:05 +05:30 committed by GitHub
parent 8d45849d0c
commit eaafc45f45
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
12 changed files with 110 additions and 4 deletions

View file

@ -6,10 +6,11 @@ class ConversationApi extends ApiClient {
super('conversations', { accountScoped: true });
}
get({ inboxId, status, assigneeType, page, labels }) {
get({ inboxId, status, assigneeType, page, labels, teamId }) {
return axios.get(this.url, {
params: {
inbox_id: inboxId,
team_id: teamId,
status,
assignee_type: assigneeType,
page,
@ -56,13 +57,14 @@ class ConversationApi extends ApiClient {
return axios.post(`${this.url}/${conversationId}/unmute`);
}
meta({ inboxId, status, assigneeType, labels }) {
meta({ inboxId, status, assigneeType, labels, teamId }) {
return axios.get(`${this.url}/meta`, {
params: {
inbox_id: inboxId,
status,
assignee_type: assigneeType,
labels,
team_id: teamId,
},
});
}

View file

@ -80,6 +80,10 @@ export default {
type: String,
default: '',
},
activeTeam: {
type: Object,
default: () => {},
},
},
data() {
return {
@ -128,12 +132,16 @@ export default {
status: this.activeStatus,
page: this.currentPage + 1,
labels: this.label ? [this.label] : undefined,
teamId: this.activeTeam.name ? this.activeTeam.id : undefined,
};
},
pageTitle() {
if (this.inbox.name) {
return this.inbox.name;
}
if (this.activeTeam.name) {
return this.activeTeam.name;
}
if (this.label) {
return `#${this.label}`;
}
@ -162,6 +170,9 @@ export default {
},
},
watch: {
activeTeam() {
this.resetAndFetchData();
},
conversationInbox() {
this.resetAndFetchData();
},

View file

@ -13,6 +13,11 @@
:key="item.toState"
:menu-item="item"
/>
<sidebar-item
v-if="shouldShowTeams"
:key="teamSection.toState"
:menu-item="teamSection"
/>
<sidebar-item
v-if="shouldShowInboxes"
:key="inboxSection.toState"
@ -97,6 +102,7 @@ export default {
accountId: 'getCurrentAccountId',
currentRole: 'getCurrentRole',
accountLabels: 'labels/getLabelsOnSidebar',
teams: 'teams/getMyTeams',
}),
sidemenuItems() {
@ -125,6 +131,9 @@ export default {
shouldShowInboxes() {
return this.sidemenuItems.common.routes.includes(this.currentRoute);
},
shouldShowTeams() {
return this.shouldShowInboxes && this.teams.length;
},
inboxSection() {
return {
icon: 'ion-folder',
@ -164,6 +173,24 @@ export default {
})),
};
},
teamSection() {
return {
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`),
toStateName: 'teams_list',
children: this.teams.map(team => ({
id: team.id,
label: team.name,
truncateLabel: true,
toState: frontendURL(`accounts/${this.accountId}/team/${team.id}`),
})),
};
},
dashboardPath() {
return frontendURL(`accounts/${this.accountId}/dashboard`);
},
@ -179,6 +206,7 @@ export default {
this.$store.dispatch('labels/get');
this.$store.dispatch('inboxes/get');
this.$store.dispatch('notifications/unReadCount');
this.$store.dispatch('teams/get');
this.setChatwootUser();
},
methods: {
@ -305,4 +333,8 @@ export default {
margin-left: auto;
margin-top: auto;
}
.teams-sidebar-menu + .nested.vertical.menu {
padding-left: calc(var(--space-medium) - var(--space-one));
}
</style>

View file

@ -14,6 +14,8 @@ export const getSidebarItems = accountId => ({
'profile_settings_index',
'label_conversations',
'conversations_through_label',
'team_conversations',
'conversations_through_team',
'notifications_index',
],
menuItems: {

View file

@ -124,7 +124,8 @@
"CANNED_RESPONSES": "Canned Responses",
"INTEGRATIONS": "Integrations",
"ACCOUNT_SETTINGS": "Account Settings",
"LABELS": "Labels"
"LABELS": "Labels",
"TEAMS": "Teams"
},
"CREATE_ACCOUNT": {
"NEW_ACCOUNT": "New Account",

View file

@ -3,6 +3,7 @@
<chat-list
:conversation-inbox="inboxId"
:label="label"
:active-team="activeTeam"
@conversation-load="onConversationLoad"
>
<button class="search--button" @click="onSearch">
@ -61,6 +62,10 @@ export default {
type: String,
default: '',
},
teamId: {
type: String,
default: '',
},
},
data() {
return {
@ -81,6 +86,12 @@ export default {
}
return false;
},
activeTeam() {
if (this.teamId) {
return this.$store.getters['teams/getTeam'](this.teamId);
}
return {};
},
},
mounted() {

View file

@ -64,5 +64,24 @@ export default {
label: route.params.label,
}),
},
{
path: frontendURL('accounts/:accountId/team/:teamId'),
name: 'team_conversations',
roles: ['administrator', 'agent'],
component: ConversationView,
props: route => ({ teamId: route.params.teamId }),
},
{
path: frontendURL(
'accounts/:accountId/team/:teamId/conversations/:conversationId'
),
name: 'conversations_through_team',
roles: ['administrator', 'agent'],
component: ConversationView,
props: route => ({
conversationId: route.params.conversationId,
teamId: route.params.teamId,
}),
},
],
};

View file

@ -4,5 +4,13 @@ export default {
account_id: 1,
name: 'Test',
description: 'Some team',
is_member: true,
},
2: {
id: 2,
account_id: 1,
name: 'Test 1',
description: 'Some team',
is_member: false,
},
};

View file

@ -6,7 +6,18 @@ describe('#getters', () => {
const state = {
records: teamsList,
};
expect(getters.getTeams(state)).toEqual([teamsList[1]]);
expect(getters.getTeams(state)).toEqual([teamsList[1], teamsList[2]]);
});
it('getMyTeams', () => {
const state = {
records: teamsList,
};
expect(
getters.getMyTeams(state, {
getTeams: [teamsList[1], teamsList[2]],
})
).toEqual([teamsList[1]]);
});
it('getTeam', () => {
@ -18,6 +29,7 @@ describe('#getters', () => {
account_id: 1,
name: 'Test',
description: 'Some team',
is_member: true,
});
});

View file

@ -12,6 +12,7 @@ describe('#mutations', () => {
it('set teams records', () => {
const state = { records: {} };
mutations[SET_TEAMS](state, [teams[1]]);
mutations[SET_TEAMS](state, [teams[2]]);
expect(state.records).toEqual(teams);
});
});

View file

@ -2,6 +2,12 @@ export const getters = {
getTeams($state) {
return Object.values($state.records).sort((a, b) => a.id - b.id);
},
getMyTeams($state, $getters) {
return $getters.getTeams.filter(team => {
const { is_member: isMember } = team;
return isMember;
});
},
getUIFlags($state) {
return $state.uiFlags;
},

View file

@ -3,3 +3,4 @@ json.name resource.name
json.description resource.description
json.allow_auto_assign resource.allow_auto_assign
json.account_id resource.account.id
json.is_member Current.user.teams.include?(resource)