chore: Ability to filter conversations with priority (#10967)
- Ability to filter conversation with priority --------- Co-authored-by: Shivam Mishra <scm.mymail@gmail.com> Co-authored-by: Sivin Varghese <64252451+iamsivin@users.noreply.github.com> Co-authored-by: Muhsin Keloth <muhsinkeramam@gmail.com>
This commit is contained in:
@@ -2,7 +2,10 @@ import { computed } from 'vue';
|
||||
import { useI18n } from 'vue-i18n';
|
||||
import { useOperators } from './operators';
|
||||
import { useMapGetter } from 'dashboard/composables/store.js';
|
||||
import { buildAttributesFilterTypes } from './helper/filterHelper.js';
|
||||
import {
|
||||
buildAttributesFilterTypes,
|
||||
CONTACT_ATTRIBUTES,
|
||||
} from './helper/filterHelper.js';
|
||||
import countries from 'shared/constants/countries.js';
|
||||
|
||||
/**
|
||||
@@ -59,7 +62,11 @@ export function useContactFilterContext() {
|
||||
* @type {import('vue').ComputedRef<FilterType[]>}
|
||||
*/
|
||||
const customFilterTypes = computed(() =>
|
||||
buildAttributesFilterTypes(contactAttributes.value, getOperatorTypes)
|
||||
buildAttributesFilterTypes(
|
||||
contactAttributes.value,
|
||||
getOperatorTypes,
|
||||
'contact'
|
||||
)
|
||||
);
|
||||
|
||||
/**
|
||||
@@ -67,8 +74,8 @@ export function useContactFilterContext() {
|
||||
*/
|
||||
const filterTypes = computed(() => [
|
||||
{
|
||||
attributeKey: 'name',
|
||||
value: 'name',
|
||||
attributeKey: CONTACT_ATTRIBUTES.NAME,
|
||||
value: CONTACT_ATTRIBUTES.NAME,
|
||||
attributeName: t('CONTACTS_LAYOUT.FILTER.NAME'),
|
||||
label: t('CONTACTS_LAYOUT.FILTER.NAME'),
|
||||
inputType: 'plainText',
|
||||
@@ -77,8 +84,8 @@ export function useContactFilterContext() {
|
||||
attributeModel: 'standard',
|
||||
},
|
||||
{
|
||||
attributeKey: 'email',
|
||||
value: 'email',
|
||||
attributeKey: CONTACT_ATTRIBUTES.EMAIL,
|
||||
value: CONTACT_ATTRIBUTES.EMAIL,
|
||||
attributeName: t('CONTACTS_LAYOUT.FILTER.EMAIL'),
|
||||
label: t('CONTACTS_LAYOUT.FILTER.EMAIL'),
|
||||
inputType: 'plainText',
|
||||
@@ -87,8 +94,8 @@ export function useContactFilterContext() {
|
||||
attributeModel: 'standard',
|
||||
},
|
||||
{
|
||||
attributeKey: 'phone_number',
|
||||
value: 'phone_number',
|
||||
attributeKey: CONTACT_ATTRIBUTES.PHONE_NUMBER,
|
||||
value: CONTACT_ATTRIBUTES.PHONE_NUMBER,
|
||||
attributeName: t('CONTACTS_LAYOUT.FILTER.PHONE_NUMBER'),
|
||||
label: t('CONTACTS_LAYOUT.FILTER.PHONE_NUMBER'),
|
||||
inputType: 'plainText',
|
||||
@@ -97,8 +104,8 @@ export function useContactFilterContext() {
|
||||
attributeModel: 'standard',
|
||||
},
|
||||
{
|
||||
attributeKey: 'identifier',
|
||||
value: 'identifier',
|
||||
attributeKey: CONTACT_ATTRIBUTES.IDENTIFIER,
|
||||
value: CONTACT_ATTRIBUTES.IDENTIFIER,
|
||||
attributeName: t('CONTACTS_LAYOUT.FILTER.IDENTIFIER'),
|
||||
label: t('CONTACTS_LAYOUT.FILTER.IDENTIFIER'),
|
||||
inputType: 'plainText',
|
||||
@@ -107,8 +114,8 @@ export function useContactFilterContext() {
|
||||
attributeModel: 'standard',
|
||||
},
|
||||
{
|
||||
attributeKey: 'country_code',
|
||||
value: 'country_code',
|
||||
attributeKey: CONTACT_ATTRIBUTES.COUNTRY_CODE,
|
||||
value: CONTACT_ATTRIBUTES.COUNTRY_CODE,
|
||||
attributeName: t('FILTER.ATTRIBUTES.COUNTRY_NAME'),
|
||||
label: t('FILTER.ATTRIBUTES.COUNTRY_NAME'),
|
||||
inputType: 'searchSelect',
|
||||
@@ -118,8 +125,8 @@ export function useContactFilterContext() {
|
||||
attributeModel: 'additional',
|
||||
},
|
||||
{
|
||||
attributeKey: 'city',
|
||||
value: 'city',
|
||||
attributeKey: CONTACT_ATTRIBUTES.CITY,
|
||||
value: CONTACT_ATTRIBUTES.CITY,
|
||||
attributeName: t('CONTACTS_LAYOUT.FILTER.CITY'),
|
||||
label: t('CONTACTS_LAYOUT.FILTER.CITY'),
|
||||
inputType: 'plainText',
|
||||
@@ -128,8 +135,8 @@ export function useContactFilterContext() {
|
||||
attributeModel: 'standard',
|
||||
},
|
||||
{
|
||||
attributeKey: 'created_at',
|
||||
value: 'created_at',
|
||||
attributeKey: CONTACT_ATTRIBUTES.CREATED_AT,
|
||||
value: CONTACT_ATTRIBUTES.CREATED_AT,
|
||||
attributeName: t('CONTACTS_LAYOUT.FILTER.CREATED_AT'),
|
||||
label: t('CONTACTS_LAYOUT.FILTER.CREATED_AT'),
|
||||
inputType: 'date',
|
||||
@@ -138,8 +145,8 @@ export function useContactFilterContext() {
|
||||
attributeModel: 'standard',
|
||||
},
|
||||
{
|
||||
attributeKey: 'last_activity_at',
|
||||
value: 'last_activity_at',
|
||||
attributeKey: CONTACT_ATTRIBUTES.LAST_ACTIVITY_AT,
|
||||
value: CONTACT_ATTRIBUTES.LAST_ACTIVITY_AT,
|
||||
attributeName: t('CONTACTS_LAYOUT.FILTER.LAST_ACTIVITY'),
|
||||
label: t('CONTACTS_LAYOUT.FILTER.LAST_ACTIVITY'),
|
||||
inputType: 'date',
|
||||
@@ -148,8 +155,8 @@ export function useContactFilterContext() {
|
||||
attributeModel: 'standard',
|
||||
},
|
||||
{
|
||||
attributeKey: 'referer',
|
||||
value: 'referer',
|
||||
attributeKey: CONTACT_ATTRIBUTES.REFERER,
|
||||
value: CONTACT_ATTRIBUTES.REFERER,
|
||||
attributeName: t('CONTACTS_LAYOUT.FILTER.REFERER_LINK'),
|
||||
label: t('CONTACTS_LAYOUT.FILTER.REFERER_LINK'),
|
||||
inputType: 'plainText',
|
||||
@@ -158,8 +165,8 @@ export function useContactFilterContext() {
|
||||
attributeModel: 'standard',
|
||||
},
|
||||
{
|
||||
attributeKey: 'blocked',
|
||||
value: 'blocked',
|
||||
attributeKey: CONTACT_ATTRIBUTES.BLOCKED,
|
||||
value: CONTACT_ATTRIBUTES.BLOCKED,
|
||||
attributeName: t('CONTACTS_LAYOUT.FILTER.BLOCKED'),
|
||||
label: t('CONTACTS_LAYOUT.FILTER.BLOCKED'),
|
||||
inputType: 'searchSelect',
|
||||
|
||||
@@ -1,3 +1,35 @@
|
||||
/**
|
||||
* Standard attributes of the conversation model
|
||||
*/
|
||||
export const CONVERSATION_ATTRIBUTES = {
|
||||
STATUS: 'status',
|
||||
PRIORITY: 'priority',
|
||||
ASSIGNEE_ID: 'assignee_id',
|
||||
INBOX_ID: 'inbox_id',
|
||||
TEAM_ID: 'team_id',
|
||||
DISPLAY_ID: 'display_id',
|
||||
CAMPAIGN_ID: 'campaign_id',
|
||||
LABELS: 'labels',
|
||||
BROWSER_LANGUAGE: 'browser_language',
|
||||
COUNTRY_CODE: 'country_code',
|
||||
REFERER: 'referer',
|
||||
CREATED_AT: 'created_at',
|
||||
LAST_ACTIVITY_AT: 'last_activity_at',
|
||||
};
|
||||
|
||||
export const CONTACT_ATTRIBUTES = {
|
||||
NAME: 'name',
|
||||
EMAIL: 'email',
|
||||
PHONE_NUMBER: 'phone_number',
|
||||
IDENTIFIER: 'identifier',
|
||||
COUNTRY_CODE: 'country_code',
|
||||
CITY: 'city',
|
||||
CREATED_AT: 'created_at',
|
||||
LAST_ACTIVITY_AT: 'last_activity_at',
|
||||
REFERER: 'referer',
|
||||
BLOCKED: 'blocked',
|
||||
};
|
||||
|
||||
/**
|
||||
* Determines the input type for a custom attribute based on its key
|
||||
* @param {string} key - The attribute display type key
|
||||
@@ -20,24 +52,37 @@ export const getCustomAttributeInputType = key => {
|
||||
|
||||
/**
|
||||
* Builds filter types for custom attributes
|
||||
* This also removes any conflicting attributes
|
||||
* @param {Array} attributes - The attributes array
|
||||
* @param {Function} getOperatorTypes - Function to get operator types
|
||||
* @returns {Array} Array of filter types
|
||||
*/
|
||||
export const buildAttributesFilterTypes = (attributes, getOperatorTypes) => {
|
||||
return attributes.map(attr => ({
|
||||
attributeKey: attr.attributeKey,
|
||||
value: attr.attributeKey,
|
||||
attributeName: attr.attributeDisplayName,
|
||||
label: attr.attributeDisplayName,
|
||||
inputType: getCustomAttributeInputType(attr.attributeDisplayType),
|
||||
filterOperators: getOperatorTypes(attr.attributeDisplayType),
|
||||
options:
|
||||
attr.attributeDisplayType === 'list'
|
||||
? attr.attributeValues.map(item => ({ id: item, name: item }))
|
||||
: [],
|
||||
attributeModel: 'customAttributes',
|
||||
}));
|
||||
export const buildAttributesFilterTypes = (
|
||||
attributes,
|
||||
getOperatorTypes,
|
||||
filterModel = 'conversation'
|
||||
) => {
|
||||
const standardAttributes = Object.values(
|
||||
filterModel === 'conversation'
|
||||
? CONVERSATION_ATTRIBUTES
|
||||
: CONTACT_ATTRIBUTES
|
||||
);
|
||||
|
||||
return attributes
|
||||
.filter(attr => !standardAttributes.includes(attr.attributeKey))
|
||||
.map(attr => ({
|
||||
attributeKey: attr.attributeKey,
|
||||
value: attr.attributeKey,
|
||||
attributeName: attr.attributeDisplayName,
|
||||
label: attr.attributeDisplayName,
|
||||
inputType: getCustomAttributeInputType(attr.attributeDisplayType),
|
||||
filterOperators: getOperatorTypes(attr.attributeDisplayType),
|
||||
options:
|
||||
attr.attributeDisplayType === 'list'
|
||||
? attr.attributeValues.map(item => ({ id: item, name: item }))
|
||||
: [],
|
||||
attributeModel: 'customAttributes',
|
||||
}));
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
@@ -3,7 +3,10 @@ import { useI18n } from 'vue-i18n';
|
||||
import { useOperators } from './operators';
|
||||
import { useMapGetter } from 'dashboard/composables/store.js';
|
||||
import { useChannelIcon } from 'next/icon/provider';
|
||||
import { buildAttributesFilterTypes } from './helper/filterHelper';
|
||||
import {
|
||||
buildAttributesFilterTypes,
|
||||
CONVERSATION_ATTRIBUTES,
|
||||
} from './helper/filterHelper';
|
||||
import countries from 'shared/constants/countries.js';
|
||||
import languages from 'dashboard/components/widgets/conversation/advancedFilterItems/languages.js';
|
||||
|
||||
@@ -70,7 +73,11 @@ export function useConversationFilterContext() {
|
||||
* @type {import('vue').ComputedRef<FilterType[]>}
|
||||
*/
|
||||
const customFilterTypes = computed(() =>
|
||||
buildAttributesFilterTypes(conversationAttributes.value, getOperatorTypes)
|
||||
buildAttributesFilterTypes(
|
||||
conversationAttributes.value,
|
||||
getOperatorTypes,
|
||||
'conversation'
|
||||
)
|
||||
);
|
||||
|
||||
/**
|
||||
@@ -78,8 +85,8 @@ export function useConversationFilterContext() {
|
||||
*/
|
||||
const filterTypes = computed(() => [
|
||||
{
|
||||
attributeKey: 'status',
|
||||
value: 'status',
|
||||
attributeKey: CONVERSATION_ATTRIBUTES.STATUS,
|
||||
value: CONVERSATION_ATTRIBUTES.STATUS,
|
||||
attributeName: t('FILTER.ATTRIBUTES.STATUS'),
|
||||
label: t('FILTER.ATTRIBUTES.STATUS'),
|
||||
inputType: 'multiSelect',
|
||||
@@ -94,8 +101,24 @@ export function useConversationFilterContext() {
|
||||
attributeModel: 'standard',
|
||||
},
|
||||
{
|
||||
attributeKey: 'assignee_id',
|
||||
value: 'assignee_id',
|
||||
attributeKey: CONVERSATION_ATTRIBUTES.PRIORITY,
|
||||
value: CONVERSATION_ATTRIBUTES.PRIORITY,
|
||||
attributeName: t('FILTER.ATTRIBUTES.PRIORITY'),
|
||||
label: t('FILTER.ATTRIBUTES.PRIORITY'),
|
||||
inputType: 'multiSelect',
|
||||
options: ['low', 'medium', 'high', 'urgent'].map(id => {
|
||||
return {
|
||||
id,
|
||||
name: t(`CONVERSATION.PRIORITY.OPTIONS.${id.toUpperCase()}`),
|
||||
};
|
||||
}),
|
||||
dataType: 'text',
|
||||
filterOperators: equalityOperators.value,
|
||||
attributeModel: 'standard',
|
||||
},
|
||||
{
|
||||
attributeKey: CONVERSATION_ATTRIBUTES.ASSIGNEE_ID,
|
||||
value: CONVERSATION_ATTRIBUTES.ASSIGNEE_ID,
|
||||
attributeName: t('FILTER.ATTRIBUTES.ASSIGNEE_NAME'),
|
||||
label: t('FILTER.ATTRIBUTES.ASSIGNEE_NAME'),
|
||||
inputType: 'searchSelect',
|
||||
@@ -110,8 +133,8 @@ export function useConversationFilterContext() {
|
||||
attributeModel: 'standard',
|
||||
},
|
||||
{
|
||||
attributeKey: 'inbox_id',
|
||||
value: 'inbox_id',
|
||||
attributeKey: CONVERSATION_ATTRIBUTES.INBOX_ID,
|
||||
value: CONVERSATION_ATTRIBUTES.INBOX_ID,
|
||||
attributeName: t('FILTER.ATTRIBUTES.INBOX_NAME'),
|
||||
label: t('FILTER.ATTRIBUTES.INBOX_NAME'),
|
||||
inputType: 'searchSelect',
|
||||
@@ -126,8 +149,8 @@ export function useConversationFilterContext() {
|
||||
attributeModel: 'standard',
|
||||
},
|
||||
{
|
||||
attributeKey: 'team_id',
|
||||
value: 'team_id',
|
||||
attributeKey: CONVERSATION_ATTRIBUTES.TEAM_ID,
|
||||
value: CONVERSATION_ATTRIBUTES.TEAM_ID,
|
||||
attributeName: t('FILTER.ATTRIBUTES.TEAM_NAME'),
|
||||
label: t('FILTER.ATTRIBUTES.TEAM_NAME'),
|
||||
inputType: 'searchSelect',
|
||||
@@ -137,8 +160,8 @@ export function useConversationFilterContext() {
|
||||
attributeModel: 'standard',
|
||||
},
|
||||
{
|
||||
attributeKey: 'display_id',
|
||||
value: 'display_id',
|
||||
attributeKey: CONVERSATION_ATTRIBUTES.DISPLAY_ID,
|
||||
value: CONVERSATION_ATTRIBUTES.DISPLAY_ID,
|
||||
attributeName: t('FILTER.ATTRIBUTES.CONVERSATION_IDENTIFIER'),
|
||||
label: t('FILTER.ATTRIBUTES.CONVERSATION_IDENTIFIER'),
|
||||
inputType: 'plainText',
|
||||
@@ -147,8 +170,8 @@ export function useConversationFilterContext() {
|
||||
attributeModel: 'standard',
|
||||
},
|
||||
{
|
||||
attributeKey: 'campaign_id',
|
||||
value: 'campaign_id',
|
||||
attributeKey: CONVERSATION_ATTRIBUTES.CAMPAIGN_ID,
|
||||
value: CONVERSATION_ATTRIBUTES.CAMPAIGN_ID,
|
||||
attributeName: t('FILTER.ATTRIBUTES.CAMPAIGN_NAME'),
|
||||
label: t('FILTER.ATTRIBUTES.CAMPAIGN_NAME'),
|
||||
inputType: 'searchSelect',
|
||||
@@ -161,8 +184,8 @@ export function useConversationFilterContext() {
|
||||
attributeModel: 'standard',
|
||||
},
|
||||
{
|
||||
attributeKey: 'labels',
|
||||
value: 'labels',
|
||||
attributeKey: CONVERSATION_ATTRIBUTES.LABELS,
|
||||
value: CONVERSATION_ATTRIBUTES.LABELS,
|
||||
attributeName: t('FILTER.ATTRIBUTES.LABELS'),
|
||||
label: t('FILTER.ATTRIBUTES.LABELS'),
|
||||
inputType: 'multiSelect',
|
||||
@@ -185,8 +208,8 @@ export function useConversationFilterContext() {
|
||||
attributeModel: 'standard',
|
||||
},
|
||||
{
|
||||
attributeKey: 'browser_language',
|
||||
value: 'browser_language',
|
||||
attributeKey: CONVERSATION_ATTRIBUTES.BROWSER_LANGUAGE,
|
||||
value: CONVERSATION_ATTRIBUTES.BROWSER_LANGUAGE,
|
||||
attributeName: t('FILTER.ATTRIBUTES.BROWSER_LANGUAGE'),
|
||||
label: t('FILTER.ATTRIBUTES.BROWSER_LANGUAGE'),
|
||||
inputType: 'searchSelect',
|
||||
@@ -196,8 +219,8 @@ export function useConversationFilterContext() {
|
||||
attributeModel: 'additional',
|
||||
},
|
||||
{
|
||||
attributeKey: 'country_code',
|
||||
value: 'country_code',
|
||||
attributeKey: CONVERSATION_ATTRIBUTES.COUNTRY_CODE,
|
||||
value: CONVERSATION_ATTRIBUTES.COUNTRY_CODE,
|
||||
attributeName: t('FILTER.ATTRIBUTES.COUNTRY_NAME'),
|
||||
label: t('FILTER.ATTRIBUTES.COUNTRY_NAME'),
|
||||
inputType: 'searchSelect',
|
||||
@@ -207,8 +230,8 @@ export function useConversationFilterContext() {
|
||||
attributeModel: 'additional',
|
||||
},
|
||||
{
|
||||
attributeKey: 'referer',
|
||||
value: 'referer',
|
||||
attributeKey: CONVERSATION_ATTRIBUTES.REFERER,
|
||||
value: CONVERSATION_ATTRIBUTES.REFERER,
|
||||
attributeName: t('FILTER.ATTRIBUTES.REFERER_LINK'),
|
||||
label: t('FILTER.ATTRIBUTES.REFERER_LINK'),
|
||||
inputType: 'plainText',
|
||||
@@ -217,8 +240,8 @@ export function useConversationFilterContext() {
|
||||
attributeModel: 'additional',
|
||||
},
|
||||
{
|
||||
attributeKey: 'created_at',
|
||||
value: 'created_at',
|
||||
attributeKey: CONVERSATION_ATTRIBUTES.CREATED_AT,
|
||||
value: CONVERSATION_ATTRIBUTES.CREATED_AT,
|
||||
attributeName: t('FILTER.ATTRIBUTES.CREATED_AT'),
|
||||
label: t('FILTER.ATTRIBUTES.CREATED_AT'),
|
||||
inputType: 'date',
|
||||
@@ -227,8 +250,8 @@ export function useConversationFilterContext() {
|
||||
attributeModel: 'standard',
|
||||
},
|
||||
{
|
||||
attributeKey: 'last_activity_at',
|
||||
value: 'last_activity_at',
|
||||
attributeKey: CONVERSATION_ATTRIBUTES.LAST_ACTIVITY_AT,
|
||||
value: CONVERSATION_ATTRIBUTES.LAST_ACTIVITY_AT,
|
||||
attributeName: t('FILTER.ATTRIBUTES.LAST_ACTIVITY'),
|
||||
label: t('FILTER.ATTRIBUTES.LAST_ACTIVITY'),
|
||||
inputType: 'date',
|
||||
|
||||
Reference in New Issue
Block a user