feat: Ability to edit saved folders (#7236)
* feat: Ability to edit saved filters Co-authored-by: Shivam Mishra <scm.mymail@gmail.com>
This commit is contained in:
@@ -47,6 +47,14 @@
|
|||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div v-if="hasActiveFolders">
|
<div v-if="hasActiveFolders">
|
||||||
|
<woot-button
|
||||||
|
v-tooltip.top-end="$t('FILTER.CUSTOM_VIEWS.EDIT.EDIT_BUTTON')"
|
||||||
|
size="tiny"
|
||||||
|
variant="smooth"
|
||||||
|
color-scheme="secondary"
|
||||||
|
icon="edit"
|
||||||
|
@click="onToggleAdvanceFiltersModal"
|
||||||
|
/>
|
||||||
<woot-button
|
<woot-button
|
||||||
v-tooltip.top-end="$t('FILTER.CUSTOM_VIEWS.DELETE.DELETE_BUTTON')"
|
v-tooltip.top-end="$t('FILTER.CUSTOM_VIEWS.DELETE.DELETE_BUTTON')"
|
||||||
size="tiny"
|
size="tiny"
|
||||||
@@ -168,8 +176,11 @@
|
|||||||
v-if="showAdvancedFilters"
|
v-if="showAdvancedFilters"
|
||||||
:initial-filter-types="advancedFilterTypes"
|
:initial-filter-types="advancedFilterTypes"
|
||||||
:initial-applied-filters="appliedFilter"
|
:initial-applied-filters="appliedFilter"
|
||||||
|
:active-folder-name="activeFolderName"
|
||||||
:on-close="closeAdvanceFiltersModal"
|
:on-close="closeAdvanceFiltersModal"
|
||||||
|
:is-folder-view="hasActiveFolders"
|
||||||
@applyFilter="onApplyFilter"
|
@applyFilter="onApplyFilter"
|
||||||
|
@updateFolder="onUpdateSavedFilter"
|
||||||
/>
|
/>
|
||||||
</woot-modal>
|
</woot-modal>
|
||||||
</div>
|
</div>
|
||||||
@@ -193,6 +204,9 @@ import DeleteCustomViews from 'dashboard/routes/dashboard/customviews/DeleteCust
|
|||||||
import ConversationBulkActions from './widgets/conversation/conversationBulkActions/Index.vue';
|
import ConversationBulkActions from './widgets/conversation/conversationBulkActions/Index.vue';
|
||||||
import alertMixin from 'shared/mixins/alertMixin';
|
import alertMixin from 'shared/mixins/alertMixin';
|
||||||
import filterMixin from 'shared/mixins/filterMixin';
|
import filterMixin from 'shared/mixins/filterMixin';
|
||||||
|
import languages from 'dashboard/components/widgets/conversation/advancedFilterItems/languages';
|
||||||
|
import countries from 'shared/constants/countries';
|
||||||
|
import { generateValuesForEditCustomViews } from 'dashboard/helper/customViewsHelper';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
hasPressedAltAndJKey,
|
hasPressedAltAndJKey,
|
||||||
@@ -289,6 +303,11 @@ export default {
|
|||||||
appliedFilters: 'getAppliedConversationFilters',
|
appliedFilters: 'getAppliedConversationFilters',
|
||||||
folders: 'customViews/getCustomViews',
|
folders: 'customViews/getCustomViews',
|
||||||
inboxes: 'inboxes/getInboxes',
|
inboxes: 'inboxes/getInboxes',
|
||||||
|
agentList: 'agents/getAgents',
|
||||||
|
teamsList: 'teams/getTeams',
|
||||||
|
inboxesList: 'inboxes/getInboxes',
|
||||||
|
campaigns: 'campaigns/getAllCampaigns',
|
||||||
|
labels: 'labels/getLabels',
|
||||||
}),
|
}),
|
||||||
hasAppliedFilters() {
|
hasAppliedFilters() {
|
||||||
return this.appliedFilters.length !== 0;
|
return this.appliedFilters.length !== 0;
|
||||||
@@ -451,6 +470,9 @@ export default {
|
|||||||
}
|
}
|
||||||
return undefined;
|
return undefined;
|
||||||
},
|
},
|
||||||
|
activeFolderName() {
|
||||||
|
return this.activeFolder?.name;
|
||||||
|
},
|
||||||
activeTeam() {
|
activeTeam() {
|
||||||
if (this.teamId) {
|
if (this.teamId) {
|
||||||
return this.$store.getters['teams/getTeam'](this.teamId);
|
return this.$store.getters['teams/getTeam'](this.teamId);
|
||||||
@@ -483,9 +505,7 @@ export default {
|
|||||||
this.resetAndFetchData();
|
this.resetAndFetchData();
|
||||||
},
|
},
|
||||||
activeFolder() {
|
activeFolder() {
|
||||||
if (!this.hasAppliedFilters) {
|
|
||||||
this.resetAndFetchData();
|
this.resetAndFetchData();
|
||||||
}
|
|
||||||
},
|
},
|
||||||
chatLists() {
|
chatLists() {
|
||||||
this.chatsOnView = this.conversationList;
|
this.chatsOnView = this.conversationList;
|
||||||
@@ -496,6 +516,10 @@ export default {
|
|||||||
this.$store.dispatch('setChatSortFilter', this.activeSortBy);
|
this.$store.dispatch('setChatSortFilter', this.activeSortBy);
|
||||||
this.resetAndFetchData();
|
this.resetAndFetchData();
|
||||||
|
|
||||||
|
if (this.hasActiveFolders) {
|
||||||
|
this.$store.dispatch('campaigns/get');
|
||||||
|
}
|
||||||
|
|
||||||
bus.$on('fetch_conversation_stats', () => {
|
bus.$on('fetch_conversation_stats', () => {
|
||||||
this.$store.dispatch('conversationStats/get', this.conversationFilters);
|
this.$store.dispatch('conversationStats/get', this.conversationFilters);
|
||||||
});
|
});
|
||||||
@@ -508,6 +532,15 @@ export default {
|
|||||||
this.$store.dispatch('emptyAllConversations');
|
this.$store.dispatch('emptyAllConversations');
|
||||||
this.fetchFilteredConversations(payload);
|
this.fetchFilteredConversations(payload);
|
||||||
},
|
},
|
||||||
|
onUpdateSavedFilter(payload, folderName) {
|
||||||
|
const payloadData = {
|
||||||
|
...this.activeFolder,
|
||||||
|
name: folderName,
|
||||||
|
query: filterQueryGenerator(payload),
|
||||||
|
};
|
||||||
|
this.$store.dispatch('customViews/update', payloadData);
|
||||||
|
this.closeAdvanceFiltersModal();
|
||||||
|
},
|
||||||
onClickOpenAddFoldersModal() {
|
onClickOpenAddFoldersModal() {
|
||||||
this.showAddFoldersModal = true;
|
this.showAddFoldersModal = true;
|
||||||
},
|
},
|
||||||
@@ -521,15 +554,70 @@ export default {
|
|||||||
this.showDeleteFoldersModal = false;
|
this.showDeleteFoldersModal = false;
|
||||||
},
|
},
|
||||||
onToggleAdvanceFiltersModal() {
|
onToggleAdvanceFiltersModal() {
|
||||||
if (!this.hasAppliedFilters) {
|
if (!this.hasAppliedFilters && !this.hasActiveFolders) {
|
||||||
this.initializeExistingFilterToModal();
|
this.initializeExistingFilterToModal();
|
||||||
}
|
}
|
||||||
|
if (this.hasActiveFolders) {
|
||||||
|
this.initializeFolderToFilterModal(this.activeFolder);
|
||||||
|
}
|
||||||
this.showAdvancedFilters = true;
|
this.showAdvancedFilters = true;
|
||||||
},
|
},
|
||||||
closeAdvanceFiltersModal() {
|
closeAdvanceFiltersModal() {
|
||||||
this.showAdvancedFilters = false;
|
this.showAdvancedFilters = false;
|
||||||
this.appliedFilter = [];
|
this.appliedFilter = [];
|
||||||
},
|
},
|
||||||
|
setParamsForEditFolderModal() {
|
||||||
|
// Here we are setting the params for edit folder modal to show the existing values.
|
||||||
|
|
||||||
|
// For agent, team, inboxes,and campaigns we get only the id's from the query.
|
||||||
|
// So we are mapping the id's to the actual values.
|
||||||
|
|
||||||
|
// For labels we get the name of the label from the query.
|
||||||
|
// If we delete the label from the label list then we will not be able to show the label name.
|
||||||
|
|
||||||
|
// For custom attributes we get only attribute key.
|
||||||
|
// So we are mapping it to find the input type of the attribute to show in the edit folder modal.
|
||||||
|
const params = {
|
||||||
|
agents: this.agentList,
|
||||||
|
teams: this.teamsList,
|
||||||
|
inboxes: this.inboxesList,
|
||||||
|
labels: this.labels,
|
||||||
|
campaigns: this.campaigns,
|
||||||
|
languages: languages,
|
||||||
|
countries: countries,
|
||||||
|
filterTypes: advancedFilterTypes,
|
||||||
|
allCustomAttributes: this.$store.getters[
|
||||||
|
'attributes/getAttributesByModel'
|
||||||
|
]('conversation_attribute'),
|
||||||
|
};
|
||||||
|
return params;
|
||||||
|
},
|
||||||
|
initializeFolderToFilterModal(activeFolder) {
|
||||||
|
// Here we are setting the params for edit folder modal.
|
||||||
|
// To show the existing values. when we click on edit folder button.
|
||||||
|
|
||||||
|
// Here we get the query from the active folder.
|
||||||
|
// And we are mapping the query to the actual values.
|
||||||
|
// To show in the edit folder modal by the help of generateValuesForEditCustomViews helper.
|
||||||
|
const query = activeFolder?.query?.payload;
|
||||||
|
if (!Array.isArray(query)) return;
|
||||||
|
|
||||||
|
this.appliedFilter.push(
|
||||||
|
...query.map(filter => ({
|
||||||
|
attribute_key: filter.attribute_key,
|
||||||
|
attribute_model: filter.attribute_model,
|
||||||
|
filter_operator: filter.filter_operator,
|
||||||
|
values: Array.isArray(filter.values)
|
||||||
|
? generateValuesForEditCustomViews(
|
||||||
|
filter,
|
||||||
|
this.setParamsForEditFolderModal()
|
||||||
|
)
|
||||||
|
: [],
|
||||||
|
query_operator: filter.query_operator,
|
||||||
|
custom_attribute_type: filter.custom_attribute_type,
|
||||||
|
}))
|
||||||
|
);
|
||||||
|
},
|
||||||
getKeyboardListenerParams() {
|
getKeyboardListenerParams() {
|
||||||
const allConversations = this.$refs.activeConversation.querySelectorAll(
|
const allConversations = this.$refs.activeConversation.querySelectorAll(
|
||||||
'div.conversations-list div.conversation'
|
'div.conversations-list div.conversation'
|
||||||
@@ -575,6 +663,7 @@ export default {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
resetAndFetchData() {
|
resetAndFetchData() {
|
||||||
|
this.appliedFilter = [];
|
||||||
this.resetBulkActions();
|
this.resetBulkActions();
|
||||||
this.$store.dispatch('conversationPage/reset');
|
this.$store.dispatch('conversationPage/reset');
|
||||||
this.$store.dispatch('emptyAllConversations');
|
this.$store.dispatch('emptyAllConversations');
|
||||||
@@ -587,7 +676,6 @@ export default {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
this.fetchConversations();
|
this.fetchConversations();
|
||||||
this.appliedFilter = [];
|
|
||||||
},
|
},
|
||||||
fetchConversations() {
|
fetchConversations() {
|
||||||
this.$store
|
this.$store
|
||||||
|
|||||||
@@ -1,9 +1,21 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="column">
|
<div class="column">
|
||||||
<woot-modal-header :header-title="$t('FILTER.TITLE')">
|
<woot-modal-header :header-title="filterModalHeaderTitle">
|
||||||
<p>{{ $t('FILTER.SUBTITLE') }}</p>
|
<p>{{ filterModalSubTitle }}</p>
|
||||||
</woot-modal-header>
|
</woot-modal-header>
|
||||||
<div class="row modal-content">
|
<div class="column modal-content">
|
||||||
|
<div v-if="isFolderView" class="columns">
|
||||||
|
<label class="input-label" :class="{ error: !activeFolderNewName }">
|
||||||
|
{{ $t('FILTER.FOLDER_LABEL') }}
|
||||||
|
<input v-model="activeFolderNewName" type="text" class="name-input" />
|
||||||
|
<span v-if="!activeFolderNewName" class="message">
|
||||||
|
{{ $t('FILTER.EMPTY_VALUE_ERROR') }}
|
||||||
|
</span>
|
||||||
|
</label>
|
||||||
|
<label class="input-label">
|
||||||
|
{{ $t('FILTER.FOLDER_QUERY_LABEL') }}
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
<div class="medium-12 columns filters-wrap">
|
<div class="medium-12 columns filters-wrap">
|
||||||
<filter-input-box
|
<filter-input-box
|
||||||
v-for="(filter, i) in appliedFilters"
|
v-for="(filter, i) in appliedFilters"
|
||||||
@@ -42,7 +54,14 @@
|
|||||||
<woot-button class="button clear" @click.prevent="onClose">
|
<woot-button class="button clear" @click.prevent="onClose">
|
||||||
{{ $t('FILTER.CANCEL_BUTTON_LABEL') }}
|
{{ $t('FILTER.CANCEL_BUTTON_LABEL') }}
|
||||||
</woot-button>
|
</woot-button>
|
||||||
<woot-button @click="submitFilterQuery">
|
<woot-button
|
||||||
|
v-if="isFolderView"
|
||||||
|
:disabled="!activeFolderNewName"
|
||||||
|
@click="updateSavedCustomViews"
|
||||||
|
>
|
||||||
|
{{ $t('FILTER.UPDATE_BUTTON_LABEL') }}
|
||||||
|
</woot-button>
|
||||||
|
<woot-button v-else @click="submitFilterQuery">
|
||||||
{{ $t('FILTER.SUBMIT_BUTTON_LABEL') }}
|
{{ $t('FILTER.SUBMIT_BUTTON_LABEL') }}
|
||||||
</woot-button>
|
</woot-button>
|
||||||
</div>
|
</div>
|
||||||
@@ -81,6 +100,14 @@ export default {
|
|||||||
type: Array,
|
type: Array,
|
||||||
default: () => [],
|
default: () => [],
|
||||||
},
|
},
|
||||||
|
activeFolderName: {
|
||||||
|
type: String,
|
||||||
|
default: '',
|
||||||
|
},
|
||||||
|
isFolderView: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
validations: {
|
validations: {
|
||||||
appliedFilters: {
|
appliedFilters: {
|
||||||
@@ -107,6 +134,7 @@ export default {
|
|||||||
return {
|
return {
|
||||||
show: true,
|
show: true,
|
||||||
appliedFilters: this.initialAppliedFilters,
|
appliedFilters: this.initialAppliedFilters,
|
||||||
|
activeFolderNewName: this.activeFolderName,
|
||||||
filterTypes: this.initialFilterTypes,
|
filterTypes: this.initialFilterTypes,
|
||||||
filterAttributeGroups,
|
filterAttributeGroups,
|
||||||
filterGroups: [],
|
filterGroups: [],
|
||||||
@@ -119,6 +147,16 @@ export default {
|
|||||||
...mapGetters({
|
...mapGetters({
|
||||||
getAppliedConversationFilters: 'getAppliedConversationFilters',
|
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() {
|
mounted() {
|
||||||
this.setFilterAttributes();
|
this.setFilterAttributes();
|
||||||
@@ -126,7 +164,7 @@ export default {
|
|||||||
if (this.getAppliedConversationFilters.length) {
|
if (this.getAppliedConversationFilters.length) {
|
||||||
this.appliedFilters = [];
|
this.appliedFilters = [];
|
||||||
this.appliedFilters = [...this.getAppliedConversationFilters];
|
this.appliedFilters = [...this.getAppliedConversationFilters];
|
||||||
} else {
|
} else if (!this.isFolderView) {
|
||||||
this.appliedFilters.push({
|
this.appliedFilters.push({
|
||||||
attribute_key: 'status',
|
attribute_key: 'status',
|
||||||
filter_operator: 'equal_to',
|
filter_operator: 'equal_to',
|
||||||
@@ -177,11 +215,11 @@ export default {
|
|||||||
if (key === 'created_at' || key === 'last_activity_at')
|
if (key === 'created_at' || key === 'last_activity_at')
|
||||||
if (operator === 'days_before') return 'plain_text';
|
if (operator === 'days_before') return 'plain_text';
|
||||||
const type = this.filterTypes.find(filter => filter.attributeKey === key);
|
const type = this.filterTypes.find(filter => filter.attributeKey === key);
|
||||||
return type.inputType;
|
return type?.inputType;
|
||||||
},
|
},
|
||||||
getOperators(key) {
|
getOperators(key) {
|
||||||
const type = this.filterTypes.find(filter => filter.attributeKey === key);
|
const type = this.filterTypes.find(filter => filter.attributeKey === key);
|
||||||
return type.filterOperators;
|
return type?.filterOperators;
|
||||||
},
|
},
|
||||||
getDropdownValues(type) {
|
getDropdownValues(type) {
|
||||||
const statusFilters = this.$t('CHAT_LIST.CHAT_STATUS_FILTER_ITEMS');
|
const statusFilters = this.$t('CHAT_LIST.CHAT_STATUS_FILTER_ITEMS');
|
||||||
@@ -267,12 +305,31 @@ export default {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
appendNewFilter() {
|
appendNewFilter() {
|
||||||
|
if (this.isFolderView) {
|
||||||
|
this.setQueryOperatorOnLastQuery();
|
||||||
|
} else {
|
||||||
this.appliedFilters.push({
|
this.appliedFilters.push({
|
||||||
attribute_key: 'status',
|
attribute_key: 'status',
|
||||||
filter_operator: 'equal_to',
|
filter_operator: 'equal_to',
|
||||||
values: '',
|
values: '',
|
||||||
query_operator: 'and',
|
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) {
|
removeFilter(index) {
|
||||||
if (this.appliedFilters.length <= 1) {
|
if (this.appliedFilters.length <= 1) {
|
||||||
@@ -296,6 +353,9 @@ export default {
|
|||||||
})),
|
})),
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
updateSavedCustomViews() {
|
||||||
|
this.$emit('updateFolder', this.appliedFilters, this.activeFolderNewName);
|
||||||
|
},
|
||||||
resetFilter(index, currentFilter) {
|
resetFilter(index, currentFilter) {
|
||||||
this.appliedFilters[index].filter_operator = this.filterTypes.find(
|
this.appliedFilters[index].filter_operator = this.filterTypes.find(
|
||||||
filter => filter.attributeKey === currentFilter.attribute_key
|
filter => filter.attributeKey === currentFilter.attribute_key
|
||||||
@@ -322,4 +382,12 @@ export default {
|
|||||||
.filter-actions {
|
.filter-actions {
|
||||||
margin-top: var(--space-normal);
|
margin-top: var(--space-normal);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.input-label {
|
||||||
|
margin-bottom: var(--space-smaller);
|
||||||
|
|
||||||
|
.name-input {
|
||||||
|
width: 50%;
|
||||||
|
}
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
119
app/javascript/dashboard/helper/customViewsHelper.js
Normal file
119
app/javascript/dashboard/helper/customViewsHelper.js
Normal file
@@ -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();
|
||||||
|
};
|
||||||
@@ -1,9 +1,12 @@
|
|||||||
|
const setArrayValues = item => {
|
||||||
|
return item.values[0]?.id ? item.values.map(val => val.id) : item.values;
|
||||||
|
};
|
||||||
const generatePayload = data => {
|
const generatePayload = data => {
|
||||||
// Make a copy of data to avoid vue data reactivity issues
|
// Make a copy of data to avoid vue data reactivity issues
|
||||||
const filters = JSON.parse(JSON.stringify(data));
|
const filters = JSON.parse(JSON.stringify(data));
|
||||||
let payload = filters.map(item => {
|
let payload = filters.map(item => {
|
||||||
if (Array.isArray(item.values)) {
|
if (Array.isArray(item.values)) {
|
||||||
item.values = item.values.map(val => val.id);
|
item.values = setArrayValues(item);
|
||||||
} else if (typeof item.values === 'object') {
|
} else if (typeof item.values === 'object') {
|
||||||
item.values = [item.values.id];
|
item.values = [item.values.id];
|
||||||
} else if (!item.values) {
|
} else if (!item.values) {
|
||||||
|
|||||||
278
app/javascript/dashboard/helper/specs/customViewsHelper.spec.js
Normal file
278
app/javascript/dashboard/helper/specs/customViewsHelper.spec.js
Normal file
@@ -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');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
@@ -2,12 +2,17 @@
|
|||||||
"FILTER": {
|
"FILTER": {
|
||||||
"TITLE": "Filter Conversations",
|
"TITLE": "Filter Conversations",
|
||||||
"SUBTITLE": "Add filters below and hit 'Apply filters' to 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",
|
"ADD_NEW_FILTER": "Add Filter",
|
||||||
"FILTER_DELETE_ERROR": "You should have atleast one filter to save",
|
"FILTER_DELETE_ERROR": "You should have atleast one filter to save",
|
||||||
"SUBMIT_BUTTON_LABEL": "Apply filters",
|
"SUBMIT_BUTTON_LABEL": "Apply filters",
|
||||||
|
"UPDATE_BUTTON_LABEL": "Update folder",
|
||||||
"CANCEL_BUTTON_LABEL": "Cancel",
|
"CANCEL_BUTTON_LABEL": "Cancel",
|
||||||
"CLEAR_BUTTON_LABEL": "Clear Filters",
|
"CLEAR_BUTTON_LABEL": "Clear Filters",
|
||||||
"EMPTY_VALUE_ERROR": "Value is required",
|
"EMPTY_VALUE_ERROR": "Value is required",
|
||||||
|
"FOLDER_LABEL": "Folder Name",
|
||||||
|
"FOLDER_QUERY_LABEL": "Folder Query",
|
||||||
"TOOLTIP_LABEL": "Filter conversations",
|
"TOOLTIP_LABEL": "Filter conversations",
|
||||||
"QUERY_DROPDOWN_LABELS": {
|
"QUERY_DROPDOWN_LABELS": {
|
||||||
"AND": "AND",
|
"AND": "AND",
|
||||||
@@ -71,6 +76,9 @@
|
|||||||
"ERROR_MESSAGE": "Error while creating segment"
|
"ERROR_MESSAGE": "Error while creating segment"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"EDIT": {
|
||||||
|
"EDIT_BUTTON": "Edit folder"
|
||||||
|
},
|
||||||
"DELETE": {
|
"DELETE": {
|
||||||
"DELETE_BUTTON": "Delete filter",
|
"DELETE_BUTTON": "Delete filter",
|
||||||
"MODAL": {
|
"MODAL": {
|
||||||
|
|||||||
@@ -49,6 +49,18 @@ export const actions = {
|
|||||||
commit(types.SET_CUSTOM_VIEW_UI_FLAG, { isCreating: false });
|
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 }) => {
|
delete: async ({ commit }, { id, filterType }) => {
|
||||||
commit(types.SET_CUSTOM_VIEW_UI_FLAG, { isDeleting: true });
|
commit(types.SET_CUSTOM_VIEW_UI_FLAG, { isDeleting: true });
|
||||||
try {
|
try {
|
||||||
@@ -72,6 +84,7 @@ export const mutations = {
|
|||||||
|
|
||||||
[types.ADD_CUSTOM_VIEW]: MutationHelpers.create,
|
[types.ADD_CUSTOM_VIEW]: MutationHelpers.create,
|
||||||
[types.SET_CUSTOM_VIEW]: MutationHelpers.set,
|
[types.SET_CUSTOM_VIEW]: MutationHelpers.set,
|
||||||
|
[types.UPDATE_CUSTOM_VIEW]: MutationHelpers.update,
|
||||||
[types.DELETE_CUSTOM_VIEW]: MutationHelpers.destroy,
|
[types.DELETE_CUSTOM_VIEW]: MutationHelpers.destroy,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import axios from 'axios';
|
import axios from 'axios';
|
||||||
import { actions } from '../../customViews';
|
import { actions } from '../../customViews';
|
||||||
import * as types from '../../../mutation-types';
|
import * as types from '../../../mutation-types';
|
||||||
import customViewList from './fixtures';
|
import { customViewList, updateCustomViewList } from './fixtures';
|
||||||
|
|
||||||
const commit = jest.fn();
|
const commit = jest.fn();
|
||||||
global.axios = axios;
|
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 }],
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
export default [
|
export const customViewList = [
|
||||||
{
|
{
|
||||||
name: 'Custom view',
|
name: 'Custom view',
|
||||||
filter_type: 0,
|
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',
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import { getters } from '../../customViews';
|
import { getters } from '../../customViews';
|
||||||
import customViewList from './fixtures';
|
import { customViewList } from './fixtures';
|
||||||
|
|
||||||
describe('#getters', () => {
|
describe('#getters', () => {
|
||||||
it('getCustomViews', () => {
|
it('getCustomViews', () => {
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import types from '../../../mutation-types';
|
import types from '../../../mutation-types';
|
||||||
import { mutations } from '../../customViews';
|
import { mutations } from '../../customViews';
|
||||||
import customViewList from './fixtures';
|
import { customViewList, updateCustomViewList } from './fixtures';
|
||||||
|
|
||||||
describe('#mutations', () => {
|
describe('#mutations', () => {
|
||||||
describe('#SET_CUSTOM_VIEW', () => {
|
describe('#SET_CUSTOM_VIEW', () => {
|
||||||
@@ -26,4 +26,12 @@ describe('#mutations', () => {
|
|||||||
expect(state.records).toEqual([customViewList[0]]);
|
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);
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -221,6 +221,7 @@ export default {
|
|||||||
SET_CUSTOM_VIEW_UI_FLAG: 'SET_CUSTOM_VIEW_UI_FLAG',
|
SET_CUSTOM_VIEW_UI_FLAG: 'SET_CUSTOM_VIEW_UI_FLAG',
|
||||||
SET_CUSTOM_VIEW: 'SET_CUSTOM_VIEW',
|
SET_CUSTOM_VIEW: 'SET_CUSTOM_VIEW',
|
||||||
ADD_CUSTOM_VIEW: 'ADD_CUSTOM_VIEW',
|
ADD_CUSTOM_VIEW: 'ADD_CUSTOM_VIEW',
|
||||||
|
UPDATE_CUSTOM_VIEW: 'UPDATE_CUSTOM_VIEW',
|
||||||
DELETE_CUSTOM_VIEW: 'DELETE_CUSTOM_VIEW',
|
DELETE_CUSTOM_VIEW: 'DELETE_CUSTOM_VIEW',
|
||||||
|
|
||||||
// Bulk Actions
|
// Bulk Actions
|
||||||
|
|||||||
Reference in New Issue
Block a user