Update according to UI values, id-name pairs

This commit is contained in:
Tejaswini 2021-10-25 17:56:48 +05:30
parent 01f1d5216f
commit 810ebd7866
7 changed files with 580 additions and 7 deletions

View file

@ -51,7 +51,7 @@ class Api::V1::Accounts::ContactsController < Api::V1::Accounts::BaseController
def show; end
def filter
@contacts = ::Contacts::FilterService.new(params[:body], current_user).perform
@contacts = ::Contacts::FilterService.new(params[:payload], current_user).perform
end
def contactable_inboxes

View file

@ -32,15 +32,16 @@ class Api::V1::Accounts::ConversationsController < Api::V1::Accounts::BaseContro
def show; end
def filter
@conversations = ::Conversations::FilterService.new(JSON.parse(params[:body]), current_user).perform
@conversations_count = @conversations.count
result = ::Conversations::FilterService.new(params.permit![:payload], current_user).perform
@conversations = result[:conversations]
@conversations_count = result[:count]
end
def mute
@conversation.mute!
head :ok
end
F
def unmute
@conversation.unmute!
head :ok

View file

@ -0,0 +1,265 @@
<template>
<div class="column">
<woot-modal-header header-title="Filter Conversations">
<p>
{{ $t('FILTER.SUBTITLE') }}
</p>
</woot-modal-header>
<div class="row modal-content">
<div class="medium-12 columns filter-modal-content">
<filter-input-box
v-for="(filter, i) in appliedFilters"
:key="i"
v-model="appliedFilters[i]"
:filter-data="filter"
:filter-attributes="filterAttributes"
:input-type="getInputType(appliedFilters[i].attribute_key)"
:operators="getOperators(appliedFilters[i].attribute_key)"
:dropdown-values="getDropdownValues(appliedFilters[i].attribute_key)"
:show-query-operator="i !== appliedFilters.length - 1"
:v="$v.appliedFilters.$each[i]"
@clearPreviousValues="clearPreviousValues(i)"
@removeFilter="removeFilter(i)"
/>
<div class="filter-actions">
<button class="append-filter-btn" @click="appendNewFilter">
<i class="icon ion-plus-circled margin-right-small" />
<span>{{ $t('FILTER.ADD_NEW_FILTER') }}</span>
</button>
</div>
<div class="modal-footer justify-content-end">
<woot-button class="button clear" @click.prevent="onClose">
{{ $t('FILTER.CANCEL_BUTTON_LABEL') }}
</woot-button>
<woot-button @click="submitFilterQuery">
{{ $t('FILTER.SUBMIT_BUTTON_LABEL') }}
</woot-button>
</div>
</div>
</div>
</div>
</template>
<script>
import Modal from '../../../components/Modal';
import alertMixin from 'shared/mixins/alertMixin';
import { required } from 'vuelidate/lib/validators';
import filterInputBox from './components/FilterInput.vue';
import languages from './advancedFilterItems/languages';
import countries from './advancedFilterItems/countries';
export default {
components: {
Modal,
filterInputBox,
},
mixins: [alertMixin],
props: {
onClose: {
type: Function,
default: () => {},
},
filterTypes: {
type: Array,
default: () => [],
},
},
validations: {
appliedFilters: {
required,
$each: {
values: {
required,
},
},
},
},
data() {
return {
show: true,
appliedFilters: [
{
attribute_key: 'status',
filter_operator: 'equal_to',
values: '',
query_operator: 'and',
},
],
};
},
computed: {
filterAttributes() {
return this.filterTypes.map(type => {
return {
key: type.attributeKey,
name: type.attributeName,
};
});
},
},
mounted() {
this.$store.dispatch('campaigns/get');
},
methods: {
getInputType(key) {
const type = this.filterTypes.find(filter => filter.attributeKey === key);
return type.inputType;
},
getOperators(key) {
const type = this.filterTypes.find(filter => filter.attributeKey === key);
return type.filterOperators;
},
// eslint-disable-next-line consistent-return
getDropdownValues(type) {
switch (type) {
case 'status':
return [
{
id: 'open',
name: 'Open',
},
{
id: 'resolved',
name: 'Resolved',
},
{
id: 'pending',
name: 'Pending',
},
{
id: 'snoozed',
name: 'Snoozed',
},
{
id: 'all',
name: 'All',
},
];
case 'assignee_id':
return this.$store.getters['agents/getAgents'];
case 'contact':
return this.$store.getters['contacts/getContacts'];
case 'inbox':
return this.$store.getters['inboxes/getInboxes'];
case 'team_id':
return this.$store.getters['teams/getTeams'];
case 'campaign_id':
return this.$store.getters['campaigns/getAllCampaigns'].map(i => {
return {
id: i.id,
name: i.title,
};
});
case 'labels':
return this.$store.getters['labels/getLabels'];
case 'browser_language':
return languages;
case 'country_code':
return countries;
default:
break;
}
},
appendNewFilter() {
this.appliedFilters.push({
attribute_key: 'status',
filter_operator: 'equal_to',
values: '',
query_operator: 'and',
});
},
removeFilter(index) {
if (this.appliedFilters.length <= 1) {
this.showAlert(this.$t('FILTER.FILTER_DELETE_ERROR'));
} else {
this.appliedFilters.splice(index, 1);
}
},
submitFilterQuery() {
this.$v.$touch();
if (this.$v.$invalid) return;
this.appliedFilters[this.appliedFilters.length - 1].query_operator = null;
this.$emit('applyFilter', this.appliedFilters);
},
clearPreviousValues(index) {
this.appliedFilters[index].values = '';
},
},
};
</script>
<style lang="scss">
@import '~widget/assets/scss/variables.scss';
.filter-modal-content {
border: 1px solid $color-border;
border-radius: $space-small;
padding: $space-normal;
}
.filter--attributes {
display: flex;
align-items: center;
margin-bottom: $space-normal;
}
.filter--attribute_clearbtn {
font-size: $font-size-bigger;
margin-left: $space-normal;
cursor: pointer;
}
.filter--attributes_select {
margin-bottom: $zero !important;
}
.filter--values_select {
margin-bottom: $zero !important;
}
.padding-right-small {
padding-right: $space-normal;
}
.margin-right-small {
margin-right: $space-slab;
}
.append-filter-btn {
width: 100%;
border: 1px solid $color-border;
border-radius: $space-small;
display: flex;
align-items: center;
justify-content: center;
color: $color-woot;
font-size: $font-size-big;
padding: $space-normal;
height: 38px;
cursor: pointer;
}
.filter-actions {
margin: $space-large $zero $space-normal $zero;
}
.filter--attributes_input {
margin-bottom: $zero !important;
}
.filter--query_operator {
display: flex;
align-items: center;
justify-content: center;
position: relative;
margin: $space-normal $zero;
}
.filter--query_operator_line {
position: absolute;
z-index: 10;
width: 100%;
border-bottom: 1px solid $color-border;
}
.filter--query_operator_container {
position: relative;
z-index: 20;
margin: $zero;
}
.filter--query_operator_select {
width: 100%;
margin-bottom: $zero !important;
border: none;
padding: $zero $space-larger $zero $space-two;
}
</style>

View file

@ -0,0 +1,303 @@
const filterTypes = [
{
attributeKey: 'status',
attributeName: 'Status',
inputType: 'multi_select',
dataType: 'text',
filterOperators: [
{
value: 'equal_to',
label: 'Equal to',
},
{
value: 'not_equal_to',
label: 'Not equal to',
},
],
attribute_type: 'standard',
},
{
attributeKey: 'assignee_id',
attributeName: 'Assignee Name',
inputType: 'search_select',
dataType: 'text',
filterOperators: [
{
value: 'equal_to',
label: 'Equal to',
},
{
value: 'not_equal_to',
label: 'Not equal to',
},
{
value: 'contains',
label: 'Contains',
},
{
value: 'does_not_contain',
label: 'Does not contain',
},
{
value: 'is_present',
label: 'Is present',
},
{
value: 'is_not_present',
label: 'Is not present',
},
],
attribute_type: 'standard',
},
{
attributeKey: 'contact',
attributeName: 'Contact Name',
inputType: 'search_select',
dataType: 'text',
filterOperators: [
{
value: 'equal_to',
label: 'Equal to',
},
{
value: 'not_equal_to',
label: 'Not equal to',
},
{
value: 'contains',
label: 'Contains',
},
{
value: 'does_not_contain',
label: 'Does not contain',
},
{
value: 'is_present',
label: 'Is present',
},
{
value: 'is_not_present',
label: 'Is not present',
},
],
attribute_type: 'standard',
},
{
attributeKey: 'inbox',
attributeName: 'Inbox Name',
inputType: 'search_select',
dataType: 'text',
filterOperators: [
{
value: 'equal_to',
label: 'Equal to',
},
{
value: 'not_equal_to',
label: 'Not equal to',
},
{
value: 'contains',
label: 'Contains',
},
{
value: 'does_not_contain',
label: 'Does not contain',
},
{
value: 'is_present',
label: 'Is present',
},
{
value: 'is_not_present',
label: 'Is not present',
},
],
attribute_type: 'standard',
},
{
attributeKey: 'team_id',
attributeName: 'Team Name',
inputType: 'search_select',
dataType: 'number',
filterOperators: [
{
value: 'equal_to',
label: 'Equal to',
},
{
value: 'not_equal_to',
label: 'Not equal to',
},
{
value: 'contains',
label: 'Contains',
},
{
value: 'does_not_contain',
label: 'Does not contain',
},
{
value: 'is_present',
label: 'Is present',
},
{
value: 'is_not_present',
label: 'Is not present',
},
],
attribute_type: 'standard',
},
{
attributeKey: 'id',
attributeName: 'Conversation Identifier',
inputType: 'plain_text',
dataType: 'Number',
filterOperators: [
{
value: 'equal_to',
label: 'Equal to',
},
{
value: 'not_equal_to',
label: 'Not equal to',
},
{
value: 'contains',
label: 'Contains',
},
{
value: 'does_not_contain',
label: 'Does not contain',
},
],
attribute_type: 'standard',
},
{
attributeKey: 'campaign_id',
attributeName: 'Campaign Name',
inputType: 'search_select',
dataType: 'Number',
filterOperators: [
{
value: 'equal_to',
label: 'Equal to',
},
{
value: 'not_equal_to',
label: 'Not equal to',
},
{
value: 'contains',
label: 'Contains',
},
{
value: 'does_not_contain',
label: 'Does not contain',
},
{
value: 'is_present',
label: 'Is present',
},
{
value: 'is_not_present',
label: 'Is not present',
},
],
attribute_type: 'standard',
},
{
attributeKey: 'labels',
attributeName: 'Labels',
inputType: 'multi_select',
dataType: 'text',
filterOperators: [
{
value: 'equal_to',
label: 'Equal to',
},
{
value: 'not_equal_to',
label: 'Not equal to',
},
{
value: 'contains',
label: 'Contains',
},
{
value: 'does_not_contain',
label: 'Does not contain',
},
{
value: 'is_present',
label: 'Is present',
},
{
value: 'is_not_present',
label: 'Is not present',
},
],
attribute_type: 'standard',
},
{
attributeKey: 'browser_language',
attributeName: 'Browser Language',
inputType: 'search_select',
dataType: 'text',
filterOperators: [
{
value: 'equal_to',
label: 'Equal to',
},
{
value: 'not_equal_to',
label: 'Not equal to',
},
],
attribute_type: 'additional_attributes',
},
{
attributeKey: 'country_code',
attributeName: 'Country Name',
inputType: 'search_select',
dataType: 'text',
filterOperators: [
{
value: 'equal_to',
label: 'Equal to',
},
{
value: 'not_equal_to',
label: 'Not equal to',
},
],
attribute_type: 'additional_attributes',
},
{
attributeKey: 'referer',
attributeName: 'Referer link',
inputType: 'plain_text',
dataType: 'text',
filterOperators: [
{
value: 'equal_to',
label: 'Equal to',
},
{
value: 'not_equal_to',
label: 'Not equal to',
},
{
value: 'contains',
label: 'Contains',
},
{
value: 'does_not_contain',
label: 'Does not contain',
},
],
attribute_type: 'additional_attributes',
},
];
export default filterTypes;

View file

@ -18,7 +18,8 @@ class Conversations::FilterService < FilterService
def conversation_query_builder
conversation_filters = @filters['conversations']
@params.each_with_index do |query_hash, current_index|
query_hash = query_hash.with_indifferent_access
# query_hash = query_hash.with_indifferent_access
current_filter = conversation_filters[query_hash['attribute_key']]
@query_string += conversation_query_string(current_filter, query_hash, current_index)
end

View file

@ -33,8 +33,11 @@ class FilterService
end
def filter_values(query_hash)
# query_hash = query_hash.with_indifferent_access
if query_hash['attribute_key'] == 'labels' || query_hash['attribute_key'] == 'browser_language'
query_hash['values'].map { |x| x['name'] }
elsif query_hash['attribute_key'] == 'status'
query_hash['values'].map { |x| Conversation.statuses[x['id'].to_sym] }
else
query_hash['values'].map { |x| x['id'] }
end

View file

@ -42,11 +42,11 @@ describe ::Conversations::FilterService do
filter_operator: 'equal_to',
values: [
{
id: 0,
id: 'open',
name: 'open'
},
{
id: 2,
id: 'pending',
name: 'pending'
}
],