+
+
+
+
{{ $t('FILTER.CANCEL_BUTTON_LABEL') }}
-
+
+ {{ $t('FILTER.UPDATE_BUTTON_LABEL') }}
+
+
{{ $t('FILTER.SUBMIT_BUTTON_LABEL') }}
@@ -81,6 +100,14 @@ export default {
type: Array,
default: () => [],
},
+ activeFolderName: {
+ type: String,
+ default: '',
+ },
+ isFolderView: {
+ type: Boolean,
+ default: false,
+ },
},
validations: {
appliedFilters: {
@@ -107,6 +134,7 @@ export default {
return {
show: true,
appliedFilters: this.initialAppliedFilters,
+ activeFolderNewName: this.activeFolderName,
filterTypes: this.initialFilterTypes,
filterAttributeGroups,
filterGroups: [],
@@ -119,6 +147,16 @@ export default {
...mapGetters({
getAppliedConversationFilters: 'getAppliedConversationFilters',
}),
+ filterModalHeaderTitle() {
+ return !this.isFolderView
+ ? this.$t('FILTER.TITLE')
+ : this.$t('FILTER.EDIT_CUSTOM_FILTER');
+ },
+ filterModalSubTitle() {
+ return !this.isFolderView
+ ? this.$t('FILTER.SUBTITLE')
+ : this.$t('FILTER.CUSTOM_VIEWS_SUBTITLE');
+ },
},
mounted() {
this.setFilterAttributes();
@@ -126,7 +164,7 @@ export default {
if (this.getAppliedConversationFilters.length) {
this.appliedFilters = [];
this.appliedFilters = [...this.getAppliedConversationFilters];
- } else {
+ } else if (!this.isFolderView) {
this.appliedFilters.push({
attribute_key: 'status',
filter_operator: 'equal_to',
@@ -177,11 +215,11 @@ export default {
if (key === 'created_at' || key === 'last_activity_at')
if (operator === 'days_before') return 'plain_text';
const type = this.filterTypes.find(filter => filter.attributeKey === key);
- return type.inputType;
+ return type?.inputType;
},
getOperators(key) {
const type = this.filterTypes.find(filter => filter.attributeKey === key);
- return type.filterOperators;
+ return type?.filterOperators;
},
getDropdownValues(type) {
const statusFilters = this.$t('CHAT_LIST.CHAT_STATUS_FILTER_ITEMS');
@@ -267,11 +305,30 @@ export default {
}
},
appendNewFilter() {
- this.appliedFilters.push({
- attribute_key: 'status',
- filter_operator: 'equal_to',
- values: '',
+ if (this.isFolderView) {
+ this.setQueryOperatorOnLastQuery();
+ } else {
+ this.appliedFilters.push({
+ attribute_key: 'status',
+ filter_operator: 'equal_to',
+ values: '',
+ query_operator: 'and',
+ });
+ }
+ },
+ setQueryOperatorOnLastQuery() {
+ const lastItemIndex = this.appliedFilters.length - 1;
+ this.appliedFilters[lastItemIndex] = {
+ ...this.appliedFilters[lastItemIndex],
query_operator: 'and',
+ };
+ this.$nextTick(() => {
+ this.appliedFilters.push({
+ attribute_key: 'status',
+ filter_operator: 'equal_to',
+ values: '',
+ query_operator: 'and',
+ });
});
},
removeFilter(index) {
@@ -296,6 +353,9 @@ export default {
})),
});
},
+ updateSavedCustomViews() {
+ this.$emit('updateFolder', this.appliedFilters, this.activeFolderNewName);
+ },
resetFilter(index, currentFilter) {
this.appliedFilters[index].filter_operator = this.filterTypes.find(
filter => filter.attributeKey === currentFilter.attribute_key
@@ -322,4 +382,12 @@ export default {
.filter-actions {
margin-top: var(--space-normal);
}
+
+.input-label {
+ margin-bottom: var(--space-smaller);
+
+ .name-input {
+ width: 50%;
+ }
+}
diff --git a/app/javascript/dashboard/helper/customViewsHelper.js b/app/javascript/dashboard/helper/customViewsHelper.js
new file mode 100644
index 000000000..5e8b550ab
--- /dev/null
+++ b/app/javascript/dashboard/helper/customViewsHelper.js
@@ -0,0 +1,119 @@
+export const getInputType = (key, operator, filterTypes) => {
+ if (key === 'created_at' || key === 'last_activity_at')
+ if (operator === 'days_before') return 'plain_text';
+ const type = filterTypes.find(filter => filter.attributeKey === key);
+ return type?.inputType;
+};
+
+export const generateCustomAttributesInputType = type => {
+ const filterInputTypes = {
+ text: 'string',
+ number: 'string',
+ date: 'string',
+ checkbox: 'multi_select',
+ list: 'multi_select',
+ link: 'string',
+ };
+ return filterInputTypes[type];
+};
+
+export const getAttributeInputType = (key, allCustomAttributes) => {
+ const customAttribute = allCustomAttributes.find(
+ attr => attr.attribute_key === key
+ );
+ const { attribute_display_type } = customAttribute;
+ const filterInputTypes = generateCustomAttributesInputType(
+ attribute_display_type
+ );
+ return filterInputTypes;
+};
+
+export const getValuesName = (values, list, idKey, nameKey) => {
+ const item = list?.find(v => v[idKey] === values[0]);
+ return {
+ id: values[0],
+ name: item ? item[nameKey] : values[0],
+ };
+};
+
+const getValuesForLabels = (values, labels) => {
+ const selectedLabels = labels.filter(label => values.includes(label.title));
+ return selectedLabels.map(({ title }) => ({
+ id: title,
+ name: title,
+ }));
+};
+
+const getValuesForLanguages = (values, languages) => {
+ const selectedLanguages = languages.filter(language =>
+ values.includes(language.id)
+ );
+ return selectedLanguages.map(({ id, name }) => ({
+ id: id.toLowerCase(),
+ name: name,
+ }));
+};
+
+const getValuesForCountries = (values, countries) => {
+ const selectedCountries = countries.filter(country =>
+ values.includes(country.id)
+ );
+ return selectedCountries.map(({ id, name }) => ({
+ id: id,
+ name: name,
+ }));
+};
+
+export const getValuesForFilter = (filter, params) => {
+ const { attribute_key, values } = filter;
+ const {
+ languages,
+ countries,
+ agents,
+ inboxes,
+ teams,
+ campaigns,
+ labels,
+ } = params;
+ switch (attribute_key) {
+ case 'assignee_id':
+ return getValuesName(values, agents, 'id', 'name');
+ case 'inbox_id':
+ return getValuesName(values, inboxes, 'id', 'name');
+ case 'team_id':
+ return getValuesName(values, teams, 'id', 'name');
+ case 'campaign_id':
+ return getValuesName(values, campaigns, 'id', 'title');
+ case 'labels': {
+ return getValuesForLabels(values, labels);
+ }
+ case 'browser_language': {
+ return getValuesForLanguages(values, languages);
+ }
+ case 'country_code': {
+ return getValuesForCountries(values, countries);
+ }
+ default:
+ return { id: values[0], name: values[0] };
+ }
+};
+
+export const generateValuesForEditCustomViews = (filter, params) => {
+ const { attribute_key, filter_operator, values } = filter;
+ const { filterTypes, allCustomAttributes } = params;
+ const inboxType = getInputType(attribute_key, filter_operator, filterTypes);
+
+ if (inboxType === undefined) {
+ const filterInputTypes = getAttributeInputType(
+ attribute_key,
+ allCustomAttributes
+ );
+ return filterInputTypes === 'string'
+ ? values[0].toString()
+ : { id: values[0], name: values[0] };
+ }
+
+ return inboxType === 'multi_select' || inboxType === 'search_select'
+ ? getValuesForFilter(filter, params)
+ : values[0].toString();
+};
diff --git a/app/javascript/dashboard/helper/filterQueryGenerator.js b/app/javascript/dashboard/helper/filterQueryGenerator.js
index d519806bf..d70a30a6b 100644
--- a/app/javascript/dashboard/helper/filterQueryGenerator.js
+++ b/app/javascript/dashboard/helper/filterQueryGenerator.js
@@ -1,9 +1,12 @@
+const setArrayValues = item => {
+ return item.values[0]?.id ? item.values.map(val => val.id) : item.values;
+};
const generatePayload = data => {
// Make a copy of data to avoid vue data reactivity issues
const filters = JSON.parse(JSON.stringify(data));
let payload = filters.map(item => {
if (Array.isArray(item.values)) {
- item.values = item.values.map(val => val.id);
+ item.values = setArrayValues(item);
} else if (typeof item.values === 'object') {
item.values = [item.values.id];
} else if (!item.values) {
diff --git a/app/javascript/dashboard/helper/specs/customViewsHelper.spec.js b/app/javascript/dashboard/helper/specs/customViewsHelper.spec.js
new file mode 100644
index 000000000..473f0bf01
--- /dev/null
+++ b/app/javascript/dashboard/helper/specs/customViewsHelper.spec.js
@@ -0,0 +1,278 @@
+import {
+ getAttributeInputType,
+ getInputType,
+ getValuesName,
+ getValuesForFilter,
+ generateValuesForEditCustomViews,
+ generateCustomAttributesInputType,
+} from '../customViewsHelper';
+import advancedFilterTypes from 'dashboard/components/widgets/conversation/advancedFilterItems/index';
+
+describe('customViewsHelper', () => {
+ describe('#getInputType', () => {
+ it('should return plain_text if key is created_at or last_activity_at and operator is days_before', () => {
+ const filterTypes = [
+ { attributeKey: 'created_at', inputType: 'date' },
+ { attributeKey: 'last_activity_at', inputType: 'date' },
+ ];
+ expect(getInputType('created_at', 'days_before', filterTypes)).toEqual(
+ 'plain_text'
+ );
+ expect(
+ getInputType('last_activity_at', 'days_before', filterTypes)
+ ).toEqual('plain_text');
+ });
+
+ it('should return inputType if key is not created_at or last_activity_at', () => {
+ const filterTypes = [
+ { attributeKey: 'created_at', inputType: 'date' },
+ { attributeKey: 'last_activity_at', inputType: 'date' },
+ { attributeKey: 'test', inputType: 'string' },
+ ];
+ expect(getInputType('test', 'days_before', filterTypes)).toEqual(
+ 'string'
+ );
+ });
+
+ it('should return undefined if key is not created_at or last_activity_at and inputType is not present', () => {
+ const filterTypes = [
+ { attributeKey: 'created_at', inputType: 'date' },
+ { attributeKey: 'last_activity_at', inputType: 'date' },
+ { attributeKey: 'test', inputType: 'string' },
+ ];
+ expect(getInputType('test', 'days_before', filterTypes)).toEqual(
+ 'string'
+ );
+ });
+ });
+
+ describe('#getAttributeInputType', () => {
+ it('should return multi_select if attribute_display_type is checkbox or list', () => {
+ const allCustomAttributes = [
+ { attribute_key: 'test', attribute_display_type: 'checkbox' },
+ { attribute_key: 'test2', attribute_display_type: 'list' },
+ ];
+ expect(getAttributeInputType('test', allCustomAttributes)).toEqual(
+ 'multi_select'
+ );
+ expect(getAttributeInputType('test2', allCustomAttributes)).toEqual(
+ 'multi_select'
+ );
+ });
+
+ it('should return string if attribute_display_type is text, number, date or link', () => {
+ const allCustomAttributes = [
+ { attribute_key: 'test', attribute_display_type: 'text' },
+ { attribute_key: 'test2', attribute_display_type: 'number' },
+ { attribute_key: 'test3', attribute_display_type: 'date' },
+ { attribute_key: 'test4', attribute_display_type: 'link' },
+ ];
+ expect(getAttributeInputType('test', allCustomAttributes)).toEqual(
+ 'string'
+ );
+ expect(getAttributeInputType('test2', allCustomAttributes)).toEqual(
+ 'string'
+ );
+ expect(getAttributeInputType('test3', allCustomAttributes)).toEqual(
+ 'string'
+ );
+ expect(getAttributeInputType('test4', allCustomAttributes)).toEqual(
+ 'string'
+ );
+ });
+ });
+
+ describe('#getValuesName', () => {
+ it('should return id and name if item is present', () => {
+ const list = [{ id: 1, name: 'test' }];
+ const idKey = 'id';
+ const nameKey = 'name';
+ const values = [1];
+ expect(getValuesName(values, list, idKey, nameKey)).toEqual({
+ id: 1,
+ name: 'test',
+ });
+ });
+
+ it('should return id and value if item is not present', () => {
+ const list = [{ id: 1, name: 'test' }];
+ const idKey = 'id';
+ const nameKey = 'name';
+ const values = [2];
+ expect(getValuesName(values, list, idKey, nameKey)).toEqual({
+ id: 2,
+ name: 2,
+ });
+ });
+ });
+
+ describe('#getValuesForFilter', () => {
+ it('should return id and name if attribute_key is assignee_id', () => {
+ const filter = { attribute_key: 'assignee_id', values: [1] };
+ const params = { agents: [{ id: 1, name: 'test' }] };
+ expect(getValuesForFilter(filter, params)).toEqual({
+ id: 1,
+ name: 'test',
+ });
+ });
+
+ it('should return id and name if attribute_key is inbox_id', () => {
+ const filter = { attribute_key: 'inbox_id', values: [1] };
+ const params = { inboxes: [{ id: 1, name: 'test' }] };
+ expect(getValuesForFilter(filter, params)).toEqual({
+ id: 1,
+ name: 'test',
+ });
+ });
+
+ it('should return id and name if attribute_key is team_id', () => {
+ const filter = { attribute_key: 'team_id', values: [1] };
+ const params = { teams: [{ id: 1, name: 'test' }] };
+ expect(getValuesForFilter(filter, params)).toEqual({
+ id: 1,
+ name: 'test',
+ });
+ });
+
+ it('should return id and title if attribute_key is campaign_id', () => {
+ const filter = { attribute_key: 'campaign_id', values: [1] };
+ const params = { campaigns: [{ id: 1, title: 'test' }] };
+ expect(getValuesForFilter(filter, params)).toEqual({
+ id: 1,
+ name: 'test',
+ });
+ });
+
+ it('should return id and title if attribute_key is labels', () => {
+ const filter = { attribute_key: 'labels', values: ['test'] };
+ const params = { labels: [{ title: 'test' }] };
+ expect(getValuesForFilter(filter, params)).toEqual([
+ { id: 'test', name: 'test' },
+ ]);
+ });
+
+ it('should return id and name if attribute_key is browser_language', () => {
+ const filter = { attribute_key: 'browser_language', values: ['en'] };
+ const params = { languages: [{ id: 'en', name: 'English' }] };
+ expect(getValuesForFilter(filter, params)).toEqual([
+ { id: 'en', name: 'English' },
+ ]);
+ });
+
+ it('should return id and name if attribute_key is country_code', () => {
+ const filter = { attribute_key: 'country_code', values: ['IN'] };
+ const params = { countries: [{ id: 'IN', name: 'India' }] };
+ expect(getValuesForFilter(filter, params)).toEqual([
+ { id: 'IN', name: 'India' },
+ ]);
+ });
+
+ it('should return id and name if attribute_key is not present', () => {
+ const filter = { attribute_key: 'test', values: [1] };
+ const params = {};
+ expect(getValuesForFilter(filter, params)).toEqual({
+ id: 1,
+ name: 1,
+ });
+ });
+ });
+
+ describe('#generateValuesForEditCustomViews', () => {
+ it('should return id and name if inboxType is multi_select or search_select', () => {
+ const filter = {
+ attribute_key: 'assignee_id',
+ filter_operator: 'and',
+ values: [1],
+ };
+ const params = {
+ filterTypes: advancedFilterTypes,
+ allCustomAttributes: [],
+ agents: [{ id: 1, name: 'test' }],
+ };
+ expect(generateValuesForEditCustomViews(filter, params)).toEqual({
+ id: 1,
+ name: 'test',
+ });
+ });
+
+ it('should return id and name if inboxType is not multi_select or search_select', () => {
+ const filter = {
+ attribute_key: 'assignee_id',
+ filter_operator: 'and',
+ values: [1],
+ };
+ const params = {
+ filterTypes: advancedFilterTypes,
+ allCustomAttributes: [],
+ agents: [{ id: 1, name: 'test' }],
+ };
+ expect(generateValuesForEditCustomViews(filter, params)).toEqual({
+ id: 1,
+ name: 'test',
+ });
+ });
+
+ it('should return id and name if inboxType is undefined', () => {
+ const filter = {
+ attribute_key: 'test2',
+ filter_operator: 'and',
+ values: [1],
+ };
+ const params = {
+ filterTypes: advancedFilterTypes,
+ allCustomAttributes: [
+ { attribute_key: 'test', attribute_display_type: 'checkbox' },
+ { attribute_key: 'test2', attribute_display_type: 'list' },
+ ],
+ };
+ expect(generateValuesForEditCustomViews(filter, params)).toEqual({
+ id: 1,
+ name: 1,
+ });
+ });
+
+ it('should return value as string if filterInputTypes is string', () => {
+ const filter = {
+ attribute_key: 'test',
+ filter_operator: 'and',
+ values: [1],
+ };
+ const params = {
+ filterTypes: advancedFilterTypes,
+ allCustomAttributes: [
+ { attribute_key: 'test', attribute_display_type: 'date' },
+ { attribute_key: 'test2', attribute_display_type: 'list' },
+ ],
+ };
+ expect(generateValuesForEditCustomViews(filter, params)).toEqual('1');
+ });
+ });
+
+ describe('#generateCustomAttributesInputType', () => {
+ it('should return string if type is text', () => {
+ expect(generateCustomAttributesInputType('text')).toEqual('string');
+ });
+
+ it('should return string if type is number', () => {
+ expect(generateCustomAttributesInputType('number')).toEqual('string');
+ });
+
+ it('should return string if type is date', () => {
+ expect(generateCustomAttributesInputType('date')).toEqual('string');
+ });
+
+ it('should return multi_select if type is checkbox', () => {
+ expect(generateCustomAttributesInputType('checkbox')).toEqual(
+ 'multi_select'
+ );
+ });
+
+ it('should return multi_select if type is list', () => {
+ expect(generateCustomAttributesInputType('list')).toEqual('multi_select');
+ });
+
+ it('should return string if type is link', () => {
+ expect(generateCustomAttributesInputType('link')).toEqual('string');
+ });
+ });
+});
diff --git a/app/javascript/dashboard/i18n/locale/en/advancedFilters.json b/app/javascript/dashboard/i18n/locale/en/advancedFilters.json
index 361c0c8ae..eae814131 100644
--- a/app/javascript/dashboard/i18n/locale/en/advancedFilters.json
+++ b/app/javascript/dashboard/i18n/locale/en/advancedFilters.json
@@ -2,12 +2,17 @@
"FILTER": {
"TITLE": "Filter Conversations",
"SUBTITLE": "Add filters below and hit 'Apply filters' to filter conversations.",
+ "EDIT_CUSTOM_FILTER": "Edit Folder",
+ "CUSTOM_VIEWS_SUBTITLE": "Add or remove filters and update your folder.",
"ADD_NEW_FILTER": "Add Filter",
"FILTER_DELETE_ERROR": "You should have atleast one filter to save",
"SUBMIT_BUTTON_LABEL": "Apply filters",
+ "UPDATE_BUTTON_LABEL": "Update folder",
"CANCEL_BUTTON_LABEL": "Cancel",
"CLEAR_BUTTON_LABEL": "Clear Filters",
"EMPTY_VALUE_ERROR": "Value is required",
+ "FOLDER_LABEL": "Folder Name",
+ "FOLDER_QUERY_LABEL": "Folder Query",
"TOOLTIP_LABEL": "Filter conversations",
"QUERY_DROPDOWN_LABELS": {
"AND": "AND",
@@ -71,6 +76,9 @@
"ERROR_MESSAGE": "Error while creating segment"
}
},
+ "EDIT": {
+ "EDIT_BUTTON": "Edit folder"
+ },
"DELETE": {
"DELETE_BUTTON": "Delete filter",
"MODAL": {
diff --git a/app/javascript/dashboard/i18n/locale/en/contactFilters.json b/app/javascript/dashboard/i18n/locale/en/contactFilters.json
index 3f84a8476..207381e12 100644
--- a/app/javascript/dashboard/i18n/locale/en/contactFilters.json
+++ b/app/javascript/dashboard/i18n/locale/en/contactFilters.json
@@ -1,50 +1,50 @@
{
- "CONTACTS_FILTER": {
- "TITLE": "Filter Contacts",
- "SUBTITLE": "Add filters below and hit 'Submit' to filter contacts.",
- "ADD_NEW_FILTER": "Add Filter",
- "CLEAR_ALL_FILTERS": "Clear All Filters",
- "FILTER_DELETE_ERROR": "You should have atleast one filter to save",
- "SUBMIT_BUTTON_LABEL": "Submit",
- "CANCEL_BUTTON_LABEL": "Cancel",
- "CLEAR_BUTTON_LABEL": "Clear Filters",
- "EMPTY_VALUE_ERROR": "Value is required",
- "TOOLTIP_LABEL": "Filter contacts",
- "QUERY_DROPDOWN_LABELS": {
- "AND": "AND",
- "OR": "OR"
- },
- "OPERATOR_LABELS": {
- "equal_to": "Equal to",
- "not_equal_to": "Not equal to",
- "contains": "Contains",
- "does_not_contain": "Does not contain",
- "is_present": "Is present",
- "is_not_present": "Is not present",
- "is_greater_than": "Is greater than",
- "is_lesser_than": "Is lesser than",
- "days_before": "Is x days before"
- },
- "ATTRIBUTES": {
- "NAME": "Name",
- "EMAIL": "Email",
- "PHONE_NUMBER": "Phone number",
- "IDENTIFIER": "Identifier",
- "CITY": "City",
- "COUNTRY": "Country",
- "CUSTOM_ATTRIBUTE_LIST": "List",
- "CUSTOM_ATTRIBUTE_TEXT": "Text",
- "CUSTOM_ATTRIBUTE_NUMBER": "Number",
- "CUSTOM_ATTRIBUTE_LINK": "Link",
- "CUSTOM_ATTRIBUTE_CHECKBOX": "Checkbox",
- "CREATED_AT": "Created At",
- "LAST_ACTIVITY": "Last Activity",
- "REFERER_LINK": "Referrer link"
- },
- "GROUPS": {
- "STANDARD_FILTERS": "Standard Filters",
- "ADDITIONAL_FILTERS": "Additional Filters",
- "CUSTOM_ATTRIBUTES": "Custom Attributes"
- }
+ "CONTACTS_FILTER": {
+ "TITLE": "Filter Contacts",
+ "SUBTITLE": "Add filters below and hit 'Submit' to filter contacts.",
+ "ADD_NEW_FILTER": "Add Filter",
+ "CLEAR_ALL_FILTERS": "Clear All Filters",
+ "FILTER_DELETE_ERROR": "You should have atleast one filter to save",
+ "SUBMIT_BUTTON_LABEL": "Submit",
+ "CANCEL_BUTTON_LABEL": "Cancel",
+ "CLEAR_BUTTON_LABEL": "Clear Filters",
+ "EMPTY_VALUE_ERROR": "Value is required",
+ "TOOLTIP_LABEL": "Filter contacts",
+ "QUERY_DROPDOWN_LABELS": {
+ "AND": "AND",
+ "OR": "OR"
+ },
+ "OPERATOR_LABELS": {
+ "equal_to": "Equal to",
+ "not_equal_to": "Not equal to",
+ "contains": "Contains",
+ "does_not_contain": "Does not contain",
+ "is_present": "Is present",
+ "is_not_present": "Is not present",
+ "is_greater_than": "Is greater than",
+ "is_lesser_than": "Is lesser than",
+ "days_before": "Is x days before"
+ },
+ "ATTRIBUTES": {
+ "NAME": "Name",
+ "EMAIL": "Email",
+ "PHONE_NUMBER": "Phone number",
+ "IDENTIFIER": "Identifier",
+ "CITY": "City",
+ "COUNTRY": "Country",
+ "CUSTOM_ATTRIBUTE_LIST": "List",
+ "CUSTOM_ATTRIBUTE_TEXT": "Text",
+ "CUSTOM_ATTRIBUTE_NUMBER": "Number",
+ "CUSTOM_ATTRIBUTE_LINK": "Link",
+ "CUSTOM_ATTRIBUTE_CHECKBOX": "Checkbox",
+ "CREATED_AT": "Created At",
+ "LAST_ACTIVITY": "Last Activity",
+ "REFERER_LINK": "Referrer link"
+ },
+ "GROUPS": {
+ "STANDARD_FILTERS": "Standard Filters",
+ "ADDITIONAL_FILTERS": "Additional Filters",
+ "CUSTOM_ATTRIBUTES": "Custom Attributes"
}
+ }
}
diff --git a/app/javascript/dashboard/store/modules/customViews.js b/app/javascript/dashboard/store/modules/customViews.js
index 40b126663..ba31dd815 100644
--- a/app/javascript/dashboard/store/modules/customViews.js
+++ b/app/javascript/dashboard/store/modules/customViews.js
@@ -49,6 +49,18 @@ export const actions = {
commit(types.SET_CUSTOM_VIEW_UI_FLAG, { isCreating: false });
}
},
+ update: async function updateCustomViews({ commit }, obj) {
+ commit(types.SET_CUSTOM_VIEW_UI_FLAG, { isCreating: true });
+ try {
+ const response = await CustomViewsAPI.update(obj.id, obj);
+ commit(types.UPDATE_CUSTOM_VIEW, response.data);
+ } catch (error) {
+ const errorMessage = error?.response?.data?.message;
+ throw new Error(errorMessage);
+ } finally {
+ commit(types.SET_CUSTOM_VIEW_UI_FLAG, { isCreating: false });
+ }
+ },
delete: async ({ commit }, { id, filterType }) => {
commit(types.SET_CUSTOM_VIEW_UI_FLAG, { isDeleting: true });
try {
@@ -72,6 +84,7 @@ export const mutations = {
[types.ADD_CUSTOM_VIEW]: MutationHelpers.create,
[types.SET_CUSTOM_VIEW]: MutationHelpers.set,
+ [types.UPDATE_CUSTOM_VIEW]: MutationHelpers.update,
[types.DELETE_CUSTOM_VIEW]: MutationHelpers.destroy,
};
diff --git a/app/javascript/dashboard/store/modules/specs/customViews/actions.spec.js b/app/javascript/dashboard/store/modules/specs/customViews/actions.spec.js
index 5de9732c6..23dca5f3b 100644
--- a/app/javascript/dashboard/store/modules/specs/customViews/actions.spec.js
+++ b/app/javascript/dashboard/store/modules/specs/customViews/actions.spec.js
@@ -1,7 +1,7 @@
import axios from 'axios';
import { actions } from '../../customViews';
import * as types from '../../../mutation-types';
-import customViewList from './fixtures';
+import { customViewList, updateCustomViewList } from './fixtures';
const commit = jest.fn();
global.axios = axios;
@@ -67,4 +67,28 @@ describe('#actions', () => {
]);
});
});
+
+ describe('#update', () => {
+ it('sends correct actions if API is success', async () => {
+ axios.patch.mockResolvedValue({ data: updateCustomViewList[0] });
+ await actions.update(
+ { commit },
+ updateCustomViewList[0].id,
+ updateCustomViewList[0]
+ );
+ expect(commit.mock.calls).toEqual([
+ [types.default.SET_CUSTOM_VIEW_UI_FLAG, { isCreating: true }],
+ [types.default.UPDATE_CUSTOM_VIEW, updateCustomViewList[0]],
+ [types.default.SET_CUSTOM_VIEW_UI_FLAG, { isCreating: false }],
+ ]);
+ });
+ it('sends correct actions if API is error', async () => {
+ axios.patch.mockRejectedValue({ message: 'Incorrect header' });
+ await expect(actions.update({ commit }, 1)).rejects.toThrow(Error);
+ expect(commit.mock.calls).toEqual([
+ [types.default.SET_CUSTOM_VIEW_UI_FLAG, { isCreating: true }],
+ [types.default.SET_CUSTOM_VIEW_UI_FLAG, { isCreating: false }],
+ ]);
+ });
+ });
});
diff --git a/app/javascript/dashboard/store/modules/specs/customViews/fixtures.js b/app/javascript/dashboard/store/modules/specs/customViews/fixtures.js
index 1a620add9..3cd57478e 100644
--- a/app/javascript/dashboard/store/modules/specs/customViews/fixtures.js
+++ b/app/javascript/dashboard/store/modules/specs/customViews/fixtures.js
@@ -1,4 +1,4 @@
-export default [
+export const customViewList = [
{
name: 'Custom view',
filter_type: 0,
@@ -34,3 +34,31 @@ export default [
},
},
];
+
+export const updateCustomViewList = [
+ {
+ id: 1,
+ name: 'Open',
+ filter_type: 'conversation',
+ query: {
+ payload: [
+ {
+ attribute_key: 'status',
+ attribute_model: 'standard',
+ filter_operator: 'equal_to',
+ values: ['open'],
+ query_operator: 'and',
+ custom_attribute_type: '',
+ },
+ {
+ attribute_key: 'assignee_id',
+ filter_operator: 'equal_to',
+ values: [52],
+ custom_attribute_type: '',
+ },
+ ],
+ },
+ created_at: '2022-02-08T03:17:38.761Z',
+ updated_at: '2023-06-05T13:57:48.478Z',
+ },
+];
diff --git a/app/javascript/dashboard/store/modules/specs/customViews/getters.spec.js b/app/javascript/dashboard/store/modules/specs/customViews/getters.spec.js
index ec50a7d5d..5428e4461 100644
--- a/app/javascript/dashboard/store/modules/specs/customViews/getters.spec.js
+++ b/app/javascript/dashboard/store/modules/specs/customViews/getters.spec.js
@@ -1,5 +1,5 @@
import { getters } from '../../customViews';
-import customViewList from './fixtures';
+import { customViewList } from './fixtures';
describe('#getters', () => {
it('getCustomViews', () => {
diff --git a/app/javascript/dashboard/store/modules/specs/customViews/mutations.spec.js b/app/javascript/dashboard/store/modules/specs/customViews/mutations.spec.js
index 05da48b6d..d5eacb236 100644
--- a/app/javascript/dashboard/store/modules/specs/customViews/mutations.spec.js
+++ b/app/javascript/dashboard/store/modules/specs/customViews/mutations.spec.js
@@ -1,6 +1,6 @@
import types from '../../../mutation-types';
import { mutations } from '../../customViews';
-import customViewList from './fixtures';
+import { customViewList, updateCustomViewList } from './fixtures';
describe('#mutations', () => {
describe('#SET_CUSTOM_VIEW', () => {
@@ -26,4 +26,12 @@ describe('#mutations', () => {
expect(state.records).toEqual([customViewList[0]]);
});
});
+
+ describe('#UPDATE_CUSTOM_VIEW', () => {
+ it('update custom view record', () => {
+ const state = { records: [updateCustomViewList[0]] };
+ mutations[types.UPDATE_CUSTOM_VIEW](state, updateCustomViewList[0]);
+ expect(state.records).toEqual(updateCustomViewList);
+ });
+ });
});
diff --git a/app/javascript/dashboard/store/mutation-types.js b/app/javascript/dashboard/store/mutation-types.js
index 2f73080d3..905b62b2e 100644
--- a/app/javascript/dashboard/store/mutation-types.js
+++ b/app/javascript/dashboard/store/mutation-types.js
@@ -221,6 +221,7 @@ export default {
SET_CUSTOM_VIEW_UI_FLAG: 'SET_CUSTOM_VIEW_UI_FLAG',
SET_CUSTOM_VIEW: 'SET_CUSTOM_VIEW',
ADD_CUSTOM_VIEW: 'ADD_CUSTOM_VIEW',
+ UPDATE_CUSTOM_VIEW: 'UPDATE_CUSTOM_VIEW',
DELETE_CUSTOM_VIEW: 'DELETE_CUSTOM_VIEW',
// Bulk Actions