diff --git a/app/javascript/dashboard/api/conversations.js b/app/javascript/dashboard/api/conversations.js
new file mode 100644
index 000000000..02d312388
--- /dev/null
+++ b/app/javascript/dashboard/api/conversations.js
@@ -0,0 +1,18 @@
+/* global axios */
+import ApiClient from './ApiClient';
+
+class ConversationApi extends ApiClient {
+ constructor() {
+ super('conversations');
+ }
+
+ getLabels(conversationID) {
+ return axios.get(`${this.url}/${conversationID}/labels`);
+ }
+
+ createLabels(conversationID) {
+ return axios.get(`${this.url}/${conversationID}/labels`);
+ }
+}
+
+export default new ConversationApi();
diff --git a/app/javascript/dashboard/api/specs/conversations.spec.js b/app/javascript/dashboard/api/specs/conversations.spec.js
new file mode 100644
index 000000000..71cebae3a
--- /dev/null
+++ b/app/javascript/dashboard/api/specs/conversations.spec.js
@@ -0,0 +1,15 @@
+import conversations from '../conversations';
+import ApiClient from '../ApiClient';
+
+describe('#ConversationApi', () => {
+ it('creates correct instance', () => {
+ expect(conversations).toBeInstanceOf(ApiClient);
+ expect(conversations).toHaveProperty('get');
+ expect(conversations).toHaveProperty('show');
+ expect(conversations).toHaveProperty('create');
+ expect(conversations).toHaveProperty('update');
+ expect(conversations).toHaveProperty('delete');
+ expect(conversations).toHaveProperty('getLabels');
+ expect(conversations).toHaveProperty('createLabels');
+ });
+});
diff --git a/app/javascript/dashboard/i18n/locale/en/contact.json b/app/javascript/dashboard/i18n/locale/en/contact.json
index 5611c5842..9b17e3ddd 100644
--- a/app/javascript/dashboard/i18n/locale/en/contact.json
+++ b/app/javascript/dashboard/i18n/locale/en/contact.json
@@ -7,6 +7,10 @@
"CONVERSATIONS": {
"NO_RECORDS_FOUND": "There are no previous conversations associated to this contact.",
"TITLE": "Previous Conversations"
+ },
+ "LABELS": {
+ "NO_RECORDS_FOUND": "There are no labels associated to this conversation.",
+ "TITLE": "Labels"
}
}
}
diff --git a/app/javascript/dashboard/routes/dashboard/conversation/ContactPanel.vue b/app/javascript/dashboard/routes/dashboard/conversation/ContactPanel.vue
index 8fc660dfe..1a8179b31 100644
--- a/app/javascript/dashboard/routes/dashboard/conversation/ContactPanel.vue
+++ b/app/javascript/dashboard/routes/dashboard/conversation/ContactPanel.vue
@@ -59,18 +59,22 @@
:contact-id="contact.id"
:conversation-id="conversationId"
/>
+
+
+
+
diff --git a/app/javascript/dashboard/store/index.js b/app/javascript/dashboard/store/index.js
index 41fdbdf78..2c848a798 100755
--- a/app/javascript/dashboard/store/index.js
+++ b/app/javascript/dashboard/store/index.js
@@ -9,6 +9,7 @@ import Channel from './modules/channels';
import contacts from './modules/contacts';
import contactConversations from './modules/contactConversations';
import conversationMetadata from './modules/conversationMetadata';
+import conversationLabels from './modules/conversationLabels';
import conversations from './modules/conversations';
import inboxes from './modules/inboxes';
import inboxMembers from './modules/inboxMembers';
@@ -24,6 +25,7 @@ export default new Vuex.Store({
Channel,
contacts,
contactConversations,
+ conversationLabels,
conversationMetadata,
conversations,
inboxes,
diff --git a/app/javascript/dashboard/store/modules/conversationLabels.js b/app/javascript/dashboard/store/modules/conversationLabels.js
new file mode 100644
index 000000000..059a31566
--- /dev/null
+++ b/app/javascript/dashboard/store/modules/conversationLabels.js
@@ -0,0 +1,61 @@
+import Vue from 'vue';
+import * as types from '../mutation-types';
+import ConversationAPI from '../../api/conversations';
+
+const state = {
+ records: {},
+ uiFlags: {
+ isFetching: false,
+ },
+};
+
+export const getters = {
+ getUIFlags($state) {
+ return $state.uiFlags;
+ },
+ getConversationLabels: $state => id => {
+ return $state.records[Number(id)] || [];
+ },
+};
+
+export const actions = {
+ get: async ({ commit }, conversationId) => {
+ commit(types.default.SET_CONVERSATION_LABELS_UI_FLAG, {
+ isFetching: true,
+ });
+ try {
+ const response = await ConversationAPI.getLabels(conversationId);
+ commit(types.default.SET_CONVERSATION_LABELS, {
+ id: conversationId,
+ data: response.data.payload,
+ });
+ commit(types.default.SET_CONVERSATION_LABELS_UI_FLAG, {
+ isFetching: false,
+ });
+ } catch (error) {
+ commit(types.default.SET_CONVERSATION_LABELS_UI_FLAG, {
+ isFetching: false,
+ });
+ }
+ },
+};
+
+export const mutations = {
+ [types.default.SET_CONVERSATION_LABELS_UI_FLAG]($state, data) {
+ $state.uiFlags = {
+ ...$state.uiFlags,
+ ...data,
+ };
+ },
+ [types.default.SET_CONVERSATION_LABELS]: ($state, { id, data }) => {
+ Vue.set($state.records, id, data);
+ },
+};
+
+export default {
+ namespaced: true,
+ state,
+ getters,
+ actions,
+ mutations,
+};
diff --git a/app/javascript/dashboard/store/modules/specs/conversationLabels/actions.spec.js b/app/javascript/dashboard/store/modules/specs/conversationLabels/actions.spec.js
new file mode 100644
index 000000000..cb6818f27
--- /dev/null
+++ b/app/javascript/dashboard/store/modules/specs/conversationLabels/actions.spec.js
@@ -0,0 +1,35 @@
+import axios from 'axios';
+import { actions } from '../../conversationLabels';
+import * as types from '../../../mutation-types';
+
+const commit = jest.fn();
+global.axios = axios;
+jest.mock('axios');
+
+describe('#actions', () => {
+ describe('#get', () => {
+ it('sends correct actions if API is success', async () => {
+ axios.get.mockResolvedValue({
+ data: { payload: ['customer-success', 'on-hold'] },
+ });
+ await actions.get({ commit }, 1);
+ expect(commit.mock.calls).toEqual([
+ [types.default.SET_CONVERSATION_LABELS_UI_FLAG, { isFetching: true }],
+
+ [
+ types.default.SET_CONVERSATION_LABELS,
+ { id: 1, data: ['customer-success', 'on-hold'] },
+ ],
+ [types.default.SET_CONVERSATION_LABELS_UI_FLAG, { isFetching: false }],
+ ]);
+ });
+ it('sends correct actions if API is error', async () => {
+ axios.get.mockRejectedValue({ message: 'Incorrect header' });
+ await actions.get({ commit });
+ expect(commit.mock.calls).toEqual([
+ [types.default.SET_CONVERSATION_LABELS_UI_FLAG, { isFetching: true }],
+ [types.default.SET_CONVERSATION_LABELS_UI_FLAG, { isFetching: false }],
+ ]);
+ });
+ });
+});
diff --git a/app/javascript/dashboard/store/modules/specs/conversationLabels/getters.spec.js b/app/javascript/dashboard/store/modules/specs/conversationLabels/getters.spec.js
new file mode 100644
index 000000000..281b90794
--- /dev/null
+++ b/app/javascript/dashboard/store/modules/specs/conversationLabels/getters.spec.js
@@ -0,0 +1,24 @@
+import { getters } from '../../conversationLabels';
+
+describe('#getters', () => {
+ it('getConversationLabels', () => {
+ const state = {
+ records: { 1: ['customer-success', 'on-hold'] },
+ };
+ expect(getters.getConversationLabels(state)(1)).toEqual([
+ 'customer-success',
+ 'on-hold',
+ ]);
+ });
+
+ it('getUIFlags', () => {
+ const state = {
+ uiFlags: {
+ isFetching: true,
+ },
+ };
+ expect(getters.getUIFlags(state)).toEqual({
+ isFetching: true,
+ });
+ });
+});
diff --git a/app/javascript/dashboard/store/modules/specs/conversationLabels/mutations.spec.js b/app/javascript/dashboard/store/modules/specs/conversationLabels/mutations.spec.js
new file mode 100644
index 000000000..c22bc40f5
--- /dev/null
+++ b/app/javascript/dashboard/store/modules/specs/conversationLabels/mutations.spec.js
@@ -0,0 +1,29 @@
+import * as types from '../../../mutation-types';
+import { mutations } from '../../conversationLabels';
+
+describe('#mutations', () => {
+ describe('#SET_CONVERSATION_LABELS_UI_FLAG', () => {
+ it('set ui flags', () => {
+ const state = { uiFlags: { isFetching: true } };
+ mutations[types.default.SET_CONVERSATION_LABELS_UI_FLAG](state, {
+ isFetching: false,
+ });
+ expect(state.uiFlags).toEqual({
+ isFetching: false,
+ });
+ });
+ });
+
+ describe('#SET_CONVERSATION_LABELS', () => {
+ it('set contact conversation records', () => {
+ const state = { records: {} };
+ mutations[types.default.SET_CONVERSATION_LABELS](state, {
+ id: 1,
+ data: ['customer-success', 'on-hold'],
+ });
+ expect(state.records).toEqual({
+ 1: ['customer-success', 'on-hold'],
+ });
+ });
+ });
+});
diff --git a/app/javascript/dashboard/store/mutation-types.js b/app/javascript/dashboard/store/mutation-types.js
index 12111a3f6..dcd87673a 100755
--- a/app/javascript/dashboard/store/mutation-types.js
+++ b/app/javascript/dashboard/store/mutation-types.js
@@ -66,6 +66,10 @@ export default {
SET_CONTACT_CONVERSATIONS_UI_FLAG: 'SET_CONTACT_CONVERSATIONS_UI_FLAG',
SET_CONTACT_CONVERSATIONS: 'SET_CONTACT_CONVERSATIONS',
+ // Conversation Label
+ SET_CONVERSATION_LABELS_UI_FLAG: 'SET_CONVERSATION_LABELS_UI_FLAG',
+ SET_CONVERSATION_LABELS: 'SET_CONVERSATION_LABELS',
+
// Reports
SET_ACCOUNT_REPORTS: 'SET_ACCOUNT_REPORTS',
SET_ACCOUNT_SUMMARY: 'SET_ACCOUNT_SUMMARY',
diff --git a/app/views/api/v1/conversations/labels/create.json.jbuilder b/app/views/api/v1/conversations/labels/create.json.jbuilder
index 13f99090d..b47f0870f 100644
--- a/app/views/api/v1/conversations/labels/create.json.jbuilder
+++ b/app/views/api/v1/conversations/labels/create.json.jbuilder
@@ -1,8 +1 @@
-json.data do
- json.meta do
- end
-
- json.payload do
- json.labels @labels
- end
-end
+json.payload @labels
diff --git a/app/views/api/v1/conversations/labels/index.json.jbuilder b/app/views/api/v1/conversations/labels/index.json.jbuilder
index 13f99090d..b47f0870f 100644
--- a/app/views/api/v1/conversations/labels/index.json.jbuilder
+++ b/app/views/api/v1/conversations/labels/index.json.jbuilder
@@ -1,8 +1 @@
-json.data do
- json.meta do
- end
-
- json.payload do
- json.labels @labels
- end
-end
+json.payload @labels