feat: New contacts advanced filter (#10514)
This commit is contained in:
@@ -81,21 +81,25 @@ const emit = defineEmits([
|
||||
</Input>
|
||||
</div>
|
||||
<div class="flex items-center gap-2">
|
||||
<Button
|
||||
:icon="
|
||||
isSegmentsView ? 'i-lucide-pen-line' : 'i-lucide-list-filter'
|
||||
"
|
||||
color="slate"
|
||||
size="sm"
|
||||
class="relative"
|
||||
variant="ghost"
|
||||
@click="emit('filter')"
|
||||
>
|
||||
<div
|
||||
v-if="hasActiveFilters && !isSegmentsView"
|
||||
class="absolute top-0 right-0 w-2 h-2 rounded-full bg-n-brand"
|
||||
/>
|
||||
</Button>
|
||||
<div class="relative">
|
||||
<Button
|
||||
id="toggleContactsFilterButton"
|
||||
:icon="
|
||||
isSegmentsView ? 'i-lucide-pen-line' : 'i-lucide-list-filter'
|
||||
"
|
||||
color="slate"
|
||||
size="sm"
|
||||
class="relative"
|
||||
variant="ghost"
|
||||
@click="emit('filter')"
|
||||
>
|
||||
<div
|
||||
v-if="hasActiveFilters && !isSegmentsView"
|
||||
class="absolute top-0 right-0 w-2 h-2 rounded-full bg-n-brand"
|
||||
/>
|
||||
</Button>
|
||||
<slot name="filter" />
|
||||
</div>
|
||||
<Button
|
||||
v-if="hasActiveFilters && !isSegmentsView"
|
||||
icon="i-lucide-save"
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<script setup>
|
||||
import { ref, computed } from 'vue';
|
||||
import { ref, computed, unref } from 'vue';
|
||||
import { useI18n } from 'vue-i18n';
|
||||
import { useStore } from 'dashboard/composables/store';
|
||||
import { useStore, useMapGetter } from 'dashboard/composables/store';
|
||||
import { useRouter } from 'vue-router';
|
||||
import { useAlert, useTrack } from 'dashboard/composables';
|
||||
import { CONTACTS_EVENTS } from 'dashboard/helper/AnalyticsHelper/events';
|
||||
@@ -9,6 +9,10 @@ import filterQueryGenerator from 'dashboard/helper/filterQueryGenerator';
|
||||
import contactFilterItems from 'dashboard/routes/dashboard/contacts/contactFilterItems';
|
||||
import { generateValuesForEditCustomViews } from 'dashboard/helper/customViewsHelper';
|
||||
import countries from 'shared/constants/countries';
|
||||
import {
|
||||
useCamelCase,
|
||||
useSnakeCase,
|
||||
} from 'dashboard/composables/useTransformKeys';
|
||||
|
||||
import ContactsHeader from 'dashboard/components-next/Contacts/ContactsHeader/ContactHeader.vue';
|
||||
import CreateNewContactDialog from 'dashboard/components-next/Contacts/ContactsForm/CreateNewContactDialog.vue';
|
||||
@@ -16,7 +20,7 @@ import ContactExportDialog from 'dashboard/components-next/Contacts/ContactsForm
|
||||
import ContactImportDialog from 'dashboard/components-next/Contacts/ContactsForm/ContactImportDialog.vue';
|
||||
import CreateSegmentDialog from 'dashboard/components-next/Contacts/ContactsForm/CreateSegmentDialog.vue';
|
||||
import DeleteSegmentDialog from 'dashboard/components-next/Contacts/ContactsForm/DeleteSegmentDialog.vue';
|
||||
import ContactsAdvancedFilters from 'dashboard/routes/dashboard/contacts/components/ContactsAdvancedFilters.vue';
|
||||
import ContactsFilter from 'dashboard/components-next/filter/ContactsFilter.vue';
|
||||
|
||||
const props = defineProps({
|
||||
showSearch: {
|
||||
@@ -74,18 +78,13 @@ const showFiltersModal = ref(false);
|
||||
const appliedFilter = ref([]);
|
||||
const segmentsQuery = ref({});
|
||||
|
||||
const appliedFilters = useMapGetter('contacts/getAppliedContactFiltersV4');
|
||||
const contactAttributes = useMapGetter('attributes/getContactAttributes');
|
||||
const hasActiveSegments = computed(
|
||||
() => props.activeSegment && props.segmentsId !== 0
|
||||
);
|
||||
const activeSegmentName = computed(() => props.activeSegment?.name);
|
||||
|
||||
const contactFilterItemsList = computed(() =>
|
||||
contactFilterItems.map(filter => ({
|
||||
...filter,
|
||||
attributeName: t(`CONTACTS_FILTER.ATTRIBUTES.${filter.attributeI18nKey}`),
|
||||
}))
|
||||
);
|
||||
|
||||
const openCreateNewContactDialog = async () => {
|
||||
await createNewContactDialogRef.value?.contactsFormRef.resetValidation();
|
||||
createNewContactDialogRef.value?.dialogRef.open();
|
||||
@@ -182,12 +181,14 @@ const clearFilters = async () => {
|
||||
};
|
||||
|
||||
const onApplyFilter = async payload => {
|
||||
payload = useSnakeCase(payload);
|
||||
segmentsQuery.value = filterQueryGenerator(payload);
|
||||
emit('applyFilter', filterQueryGenerator(payload));
|
||||
showFiltersModal.value = false;
|
||||
};
|
||||
|
||||
const onUpdateSegment = async (payload, segmentName) => {
|
||||
payload = useSnakeCase(payload);
|
||||
const payloadData = {
|
||||
...props.activeSegment,
|
||||
name: segmentName,
|
||||
@@ -201,31 +202,52 @@ const setParamsForEditSegmentModal = () => {
|
||||
return {
|
||||
countries,
|
||||
filterTypes: contactFilterItems,
|
||||
allCustomAttributes:
|
||||
store.getters['attributes/getAttributesByModel']('contact_attribute'),
|
||||
allCustomAttributes: useSnakeCase(contactAttributes.value),
|
||||
};
|
||||
};
|
||||
|
||||
const initializeSegmentToFilterModal = segment => {
|
||||
const query = segment?.query?.payload;
|
||||
const query = unref(segment)?.query?.payload;
|
||||
if (!Array.isArray(query)) return;
|
||||
|
||||
appliedFilter.value = 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, setParamsForEditSegmentModal())
|
||||
: [],
|
||||
query_operator: filter.query_operator,
|
||||
custom_attribute_type: filter.custom_attribute_type,
|
||||
}));
|
||||
const newFilters = query.map(filter => {
|
||||
const transformed = useCamelCase(filter);
|
||||
const values = Array.isArray(transformed.values)
|
||||
? generateValuesForEditCustomViews(
|
||||
useSnakeCase(filter),
|
||||
setParamsForEditSegmentModal()
|
||||
)
|
||||
: [];
|
||||
|
||||
return {
|
||||
attributeKey: transformed.attributeKey,
|
||||
attributeModel: transformed.attributeModel,
|
||||
customAttributeType: transformed.customAttributeType,
|
||||
filterOperator: transformed.filterOperator,
|
||||
queryOperator: transformed.queryOperator ?? 'and',
|
||||
values,
|
||||
};
|
||||
});
|
||||
|
||||
appliedFilter.value = [...appliedFilter.value, ...newFilters];
|
||||
};
|
||||
|
||||
const onToggleFilters = () => {
|
||||
appliedFilter.value = [];
|
||||
if (hasActiveSegments.value) {
|
||||
initializeSegmentToFilterModal(props.activeSegment);
|
||||
} else {
|
||||
appliedFilter.value = props.hasAppliedFilters
|
||||
? [...appliedFilters.value]
|
||||
: [
|
||||
{
|
||||
attributeKey: 'name',
|
||||
filterOperator: 'equal_to',
|
||||
values: '',
|
||||
queryOperator: 'and',
|
||||
attributeModel: 'standard',
|
||||
},
|
||||
];
|
||||
}
|
||||
showFiltersModal.value = true;
|
||||
};
|
||||
@@ -249,28 +271,25 @@ const onToggleFilters = () => {
|
||||
@filter="onToggleFilters"
|
||||
@create-segment="openCreateSegmentDialog"
|
||||
@delete-segment="openDeleteSegmentDialog"
|
||||
/>
|
||||
>
|
||||
<template #filter>
|
||||
<ContactsFilter
|
||||
v-if="showFiltersModal"
|
||||
v-model="appliedFilter"
|
||||
:segment-name="activeSegmentName"
|
||||
:is-segment-view="hasActiveSegments"
|
||||
class="absolute mt-1 ltr:right-0 rtl:left-0 top-full"
|
||||
@apply-filter="onApplyFilter"
|
||||
@update-segment="onUpdateSegment"
|
||||
@close="closeAdvanceFiltersModal"
|
||||
@clear-filters="clearFilters"
|
||||
/>
|
||||
</template>
|
||||
</ContactsHeader>
|
||||
|
||||
<CreateNewContactDialog ref="createNewContactDialogRef" @create="onCreate" />
|
||||
<ContactExportDialog ref="contactExportDialogRef" @export="onExport" />
|
||||
<ContactImportDialog ref="contactImportDialogRef" @import="onImport" />
|
||||
<CreateSegmentDialog ref="createSegmentDialogRef" @create="onCreateSegment" />
|
||||
<DeleteSegmentDialog ref="deleteSegmentDialogRef" @delete="onDeleteSegment" />
|
||||
<woot-modal
|
||||
v-model:show="showFiltersModal"
|
||||
:on-close="closeAdvanceFiltersModal"
|
||||
size="medium"
|
||||
>
|
||||
<ContactsAdvancedFilters
|
||||
v-if="showFiltersModal"
|
||||
:on-close="closeAdvanceFiltersModal"
|
||||
:initial-filter-types="contactFilterItemsList"
|
||||
:initial-applied-filters="appliedFilter"
|
||||
:active-segment-name="activeSegmentName"
|
||||
:is-segments-view="hasActiveSegments"
|
||||
@apply-filter="onApplyFilter"
|
||||
@update-segment="onUpdateSegment"
|
||||
@clear-filters="clearFilters"
|
||||
/>
|
||||
</woot-modal>
|
||||
</template>
|
||||
|
||||
Reference in New Issue
Block a user