From 102635b7b46273977b77230b35214a972d82fd0a Mon Sep 17 00:00:00 2001 From: Gasper Grom Date: Mon, 22 May 2023 12:02:01 +0200 Subject: [PATCH 1/2] Custom attributes mapping --- .../activity/config/filters/date/options.ts | 1 - .../config/filters/platform/config.ts | 1 - .../config/filters/sentiment/options.ts | 1 - .../member/config/filters/activeOn/config.ts | 1 - .../config/filters/avgSentiment/options.ts | 1 - .../config/filters/engagementLevel/options.ts | 1 - .../config/filters/identities/config.ts | 1 - .../modules/member/pages/member-list-page.vue | 6 +- .../src/modules/member/store/pinia/actions.ts | 15 ++ .../src/modules/member/store/pinia/state.ts | 8 +- .../config/filters/activeOn/options.ts | 1 - .../modules/filters/components/Filter.vue | 9 +- .../filters/components/FilterDropdown.vue | 72 ++++++---- .../components/filterTypes/BooleanFilter.vue | 4 +- .../components/filterTypes/DateFilter.vue | 4 +- .../filterTypes/MultiSelectFilter.vue | 2 +- .../components/filterTypes/NumberFilter.vue | 3 +- .../components/filterTypes/SelectFilter.vue | 2 +- .../components/filterTypes/StringFilter.vue | 54 ++++++++ .../string.filter.renderer.ts | 7 + .../filters/config/apiFilterRendererByType.ts | 2 + .../filters/config/filterComponentByType.ts | 2 + .../string.label.renderer.ts | 3 + .../filters/config/itemLabelRendererByType.ts | 2 + .../config/queryUrlParser/boolean.parser.ts | 4 +- .../config/queryUrlParser/date.parser.ts | 4 +- .../queryUrlParser/multiselect.parser.ts | 4 +- .../config/queryUrlParser/number.parser.ts | 4 +- .../config/queryUrlParser/select.parser.ts | 4 +- .../config/queryUrlParser/string.parser.ts | 12 ++ .../filters/config/queryUrlParserByType.ts | 2 + .../services/custom-attributes.service.ts | 130 ++++++++++++++++++ .../filters/services/filter-api.service.ts | 2 +- .../modules/filters/types/FilterConfig.ts | 3 + .../filters/types/FilterCustomAttribute.ts | 24 ++++ .../types/filterTypes/BooleanFilterConfig.ts | 3 +- .../types/filterTypes/DateFilterConfig.ts | 5 +- .../filterTypes/MultiSelectFilterConfig.ts | 4 +- .../types/filterTypes/NumberFilterConfig.ts | 4 +- .../types/filterTypes/SelectFilterConfig.ts | 5 +- .../types/filterTypes/StringFilterConfig.ts | 17 +++ frontend/tsconfig.json | 1 + 42 files changed, 368 insertions(+), 67 deletions(-) create mode 100644 frontend/src/shared/modules/filters/components/filterTypes/StringFilter.vue create mode 100644 frontend/src/shared/modules/filters/config/apiFilterRenderer/string.filter.renderer.ts create mode 100644 frontend/src/shared/modules/filters/config/itemLabelRenderer/string.label.renderer.ts create mode 100644 frontend/src/shared/modules/filters/config/queryUrlParser/string.parser.ts create mode 100644 frontend/src/shared/modules/filters/services/custom-attributes.service.ts create mode 100644 frontend/src/shared/modules/filters/types/FilterCustomAttribute.ts create mode 100644 frontend/src/shared/modules/filters/types/filterTypes/StringFilterConfig.ts diff --git a/frontend/src/modules/activity/config/filters/date/options.ts b/frontend/src/modules/activity/config/filters/date/options.ts index 3c4bc3de1e..763f1e6224 100644 --- a/frontend/src/modules/activity/config/filters/date/options.ts +++ b/frontend/src/modules/activity/config/filters/date/options.ts @@ -3,7 +3,6 @@ import moment from 'moment'; const options: SelectFilterOptionGroup[] = [ { - label: '', options: [ { label: 'Last 24 hours', diff --git a/frontend/src/modules/activity/config/filters/platform/config.ts b/frontend/src/modules/activity/config/filters/platform/config.ts index e2f9a8a9af..b47b6e3dbc 100644 --- a/frontend/src/modules/activity/config/filters/platform/config.ts +++ b/frontend/src/modules/activity/config/filters/platform/config.ts @@ -9,7 +9,6 @@ const platform: MultiSelectFilterConfig = { options: { options: [ { - label: '', options: [ ...(CrowdIntegrations.configs.map((platform) => ({ label: (platform as any).name, diff --git a/frontend/src/modules/activity/config/filters/sentiment/options.ts b/frontend/src/modules/activity/config/filters/sentiment/options.ts index 2d1947d1c9..8961463753 100644 --- a/frontend/src/modules/activity/config/filters/sentiment/options.ts +++ b/frontend/src/modules/activity/config/filters/sentiment/options.ts @@ -2,7 +2,6 @@ import { MultiSelectFilterOptionGroup } from '@/shared/modules/filters/types/fil const options: MultiSelectFilterOptionGroup[] = [ { - label: '', options: [ { label: 'Positive', diff --git a/frontend/src/modules/member/config/filters/activeOn/config.ts b/frontend/src/modules/member/config/filters/activeOn/config.ts index 5759869824..e316f1bef5 100644 --- a/frontend/src/modules/member/config/filters/activeOn/config.ts +++ b/frontend/src/modules/member/config/filters/activeOn/config.ts @@ -11,7 +11,6 @@ const activeOn: MultiSelectFilterConfig = { options: { options: [ { - label: '', options: [ ...(CrowdIntegrations.configs.map((platform) => ({ label: (platform as any).name, diff --git a/frontend/src/modules/member/config/filters/avgSentiment/options.ts b/frontend/src/modules/member/config/filters/avgSentiment/options.ts index 2d1947d1c9..8961463753 100644 --- a/frontend/src/modules/member/config/filters/avgSentiment/options.ts +++ b/frontend/src/modules/member/config/filters/avgSentiment/options.ts @@ -2,7 +2,6 @@ import { MultiSelectFilterOptionGroup } from '@/shared/modules/filters/types/fil const options: MultiSelectFilterOptionGroup[] = [ { - label: '', options: [ { label: 'Positive', diff --git a/frontend/src/modules/member/config/filters/engagementLevel/options.ts b/frontend/src/modules/member/config/filters/engagementLevel/options.ts index 6e664581ae..46034aaee3 100644 --- a/frontend/src/modules/member/config/filters/engagementLevel/options.ts +++ b/frontend/src/modules/member/config/filters/engagementLevel/options.ts @@ -2,7 +2,6 @@ import { MultiSelectFilterOptionGroup } from '@/shared/modules/filters/types/fil const options: MultiSelectFilterOptionGroup[] = [ { - label: '', options: [ { label: 'Silent', diff --git a/frontend/src/modules/member/config/filters/identities/config.ts b/frontend/src/modules/member/config/filters/identities/config.ts index 9390be952d..3619fad950 100644 --- a/frontend/src/modules/member/config/filters/identities/config.ts +++ b/frontend/src/modules/member/config/filters/identities/config.ts @@ -11,7 +11,6 @@ const identities: MultiSelectFilterConfig = { options: { options: [ { - label: '', options: [ ...(CrowdIntegrations.configs.map((platform) => ({ label: (platform as any).name, diff --git a/frontend/src/modules/member/pages/member-list-page.vue b/frontend/src/modules/member/pages/member-list-page.vue index 33124510cf..84dc7a606c 100644 --- a/frontend/src/modules/member/pages/member-list-page.vue +++ b/frontend/src/modules/member/pages/member-list-page.vue @@ -53,10 +53,12 @@ @@ -86,7 +88,8 @@ import { memberSavedViews, memberViews } from '../config/saved-views/main'; // import MemberListTabs from '@/modules/member/components/list/member-list-tabs.vue'; const memberStore = useMemberStore(); -const { filters } = storeToRefs(memberStore); +const { getMemberCustomAttributes } = memberStore; +const { filters, customAttributes } = storeToRefs(memberStore); const membersCount = ref(0); const membersToMergeCount = ref(0); @@ -142,6 +145,7 @@ const fetch = ({ onMounted(() => { fetchMembersToMergeCount(); doGetMembersCount(); + getMemberCustomAttributes(); (window as any).analytics.page('Members'); }); diff --git a/frontend/src/modules/member/store/pinia/actions.ts b/frontend/src/modules/member/store/pinia/actions.ts index 02a61bed5e..69eac2c5b0 100644 --- a/frontend/src/modules/member/store/pinia/actions.ts +++ b/frontend/src/modules/member/store/pinia/actions.ts @@ -1,2 +1,17 @@ +import { MemberService } from '@/modules/member/member-service'; +import { customAttributesService } from '@/shared/modules/filters/services/custom-attributes.service'; +import { FilterCustomAttribute } from '@/shared/modules/filters/types/FilterCustomAttribute'; +import { FilterConfig } from '@/shared/modules/filters/types/FilterConfig'; +import { MemberState } from '@/modules/member/store/pinia/state'; + +const { buildFilterFromAttributes } = customAttributesService(); + export default { + getMemberCustomAttributes(this: MemberState): Promise> { + return MemberService.fetchCustomAttributes() + .then(({ rows }: {rows: FilterCustomAttribute[]}) => { + this.customAttributes = buildFilterFromAttributes(rows); + return Promise.resolve(this.customAttributes); + }); + }, }; diff --git a/frontend/src/modules/member/store/pinia/state.ts b/frontend/src/modules/member/store/pinia/state.ts index 254eb23aeb..49cf94d68b 100644 --- a/frontend/src/modules/member/store/pinia/state.ts +++ b/frontend/src/modules/member/store/pinia/state.ts @@ -1,7 +1,8 @@ -import { Filter } from '@/shared/modules/filters/types/FilterConfig'; +import { Filter, FilterConfig } from '@/shared/modules/filters/types/FilterConfig'; -interface MemberState { - filters: Filter +export interface MemberState { + filters: Filter, + customAttributes: Record } export default () => ({ @@ -17,4 +18,5 @@ export default () => ({ order: 'descending', }, } as Filter, + customAttributes: {}, } as MemberState); diff --git a/frontend/src/modules/organization/config/filters/activeOn/options.ts b/frontend/src/modules/organization/config/filters/activeOn/options.ts index 68f798e9ce..d73bbac708 100644 --- a/frontend/src/modules/organization/config/filters/activeOn/options.ts +++ b/frontend/src/modules/organization/config/filters/activeOn/options.ts @@ -2,7 +2,6 @@ import { MultiSelectFilterOptionGroup } from '@/shared/modules/filters/types/fil const options: MultiSelectFilterOptionGroup[] = [ { - label: '', options: [ { label: 'Github', diff --git a/frontend/src/shared/modules/filters/components/Filter.vue b/frontend/src/shared/modules/filters/components/Filter.vue index 213b81a47d..8540f34302 100644 --- a/frontend/src/shared/modules/filters/components/Filter.vue +++ b/frontend/src/shared/modules/filters/components/Filter.vue @@ -3,7 +3,7 @@
@@ -16,7 +16,7 @@ > {{ filters.relation }} - + @@ -66,6 +66,11 @@ const filters = computed({ }, }); +const configuration = computed(() => ({ + ...props.config, + ...props.customConfig, +})); + const filterList = ref([]); const switchOperator = () => { diff --git a/frontend/src/shared/modules/filters/components/FilterDropdown.vue b/frontend/src/shared/modules/filters/components/FilterDropdown.vue index 9c09164250..4065483ed3 100644 --- a/frontend/src/shared/modules/filters/components/FilterDropdown.vue +++ b/frontend/src/shared/modules/filters/components/FilterDropdown.vue @@ -19,46 +19,51 @@ - + + diff --git a/frontend/src/shared/modules/filters/config/apiFilterRenderer/string.filter.renderer.ts b/frontend/src/shared/modules/filters/config/apiFilterRenderer/string.filter.renderer.ts new file mode 100644 index 0000000000..27505c2fa8 --- /dev/null +++ b/frontend/src/shared/modules/filters/config/apiFilterRenderer/string.filter.renderer.ts @@ -0,0 +1,7 @@ +import { StringFilterValue } from '@/shared/modules/filters/types/filterTypes/StringFilterConfig'; + +export const stringApiFilterRenderer = (property: string, { value }: StringFilterValue): any[] => [ + { + [property]: value, + }, +]; diff --git a/frontend/src/shared/modules/filters/config/apiFilterRendererByType.ts b/frontend/src/shared/modules/filters/config/apiFilterRendererByType.ts index 2ad5e9548d..bde0aa7e06 100644 --- a/frontend/src/shared/modules/filters/config/apiFilterRendererByType.ts +++ b/frontend/src/shared/modules/filters/config/apiFilterRendererByType.ts @@ -1,4 +1,5 @@ import { FilterConfigType } from '@/shared/modules/filters/types/FilterConfig'; +import { stringApiFilterRenderer } from '@/shared/modules/filters/config/apiFilterRenderer/string.filter.renderer'; import { booleanApiFilterRenderer } from './apiFilterRenderer/boolean.filter.renderer'; import { numberApiFilterRenderer } from './apiFilterRenderer/number.filter.renderer'; import { dateApiFilterRenderer } from './apiFilterRenderer/date.filter.renderer'; @@ -13,5 +14,6 @@ export const apiFilterRendererByType: Record [], }; diff --git a/frontend/src/shared/modules/filters/config/filterComponentByType.ts b/frontend/src/shared/modules/filters/config/filterComponentByType.ts index b98b8449d4..a0d7cf59a9 100644 --- a/frontend/src/shared/modules/filters/config/filterComponentByType.ts +++ b/frontend/src/shared/modules/filters/config/filterComponentByType.ts @@ -5,6 +5,7 @@ import MultiSelectFilter from '@/shared/modules/filters/components/filterTypes/M import SelectFilter from '@/shared/modules/filters/components/filterTypes/SelectFilter.vue'; import DateFilter from '@/shared/modules/filters/components/filterTypes/DateFilter.vue'; import NumberFilter from '@/shared/modules/filters/components/filterTypes/NumberFilter.vue'; +import StringFilter from '@/shared/modules/filters/components/filterTypes/StringFilter.vue'; export const filterComponentByType: Record = { [FilterConfigType.BOOLEAN]: BooleanFilter, @@ -12,5 +13,6 @@ export const filterComponentByType: Record = [FilterConfigType.DATE]: DateFilter, [FilterConfigType.SELECT]: SelectFilter, [FilterConfigType.MULTISELECT]: MultiSelectFilter, + [FilterConfigType.STRING]: StringFilter, [FilterConfigType.CUSTOM]: null, }; diff --git a/frontend/src/shared/modules/filters/config/itemLabelRenderer/string.label.renderer.ts b/frontend/src/shared/modules/filters/config/itemLabelRenderer/string.label.renderer.ts new file mode 100644 index 0000000000..a0b33c16a4 --- /dev/null +++ b/frontend/src/shared/modules/filters/config/itemLabelRenderer/string.label.renderer.ts @@ -0,0 +1,3 @@ +import { StringFilterValue } from '@/shared/modules/filters/types/filterTypes/StringFilterConfig'; + +export const stringItemLabelRenderer = (property: string, { value }: StringFilterValue): string => `${property}: ${value}`; diff --git a/frontend/src/shared/modules/filters/config/itemLabelRendererByType.ts b/frontend/src/shared/modules/filters/config/itemLabelRendererByType.ts index f5d279eefd..1172f7263c 100644 --- a/frontend/src/shared/modules/filters/config/itemLabelRendererByType.ts +++ b/frontend/src/shared/modules/filters/config/itemLabelRendererByType.ts @@ -1,4 +1,5 @@ import { FilterConfigType } from '@/shared/modules/filters/types/FilterConfig'; +import { stringItemLabelRenderer } from '@/shared/modules/filters/config/itemLabelRenderer/string.label.renderer'; import { booleanItemLabelRenderer } from './itemLabelRenderer/boolean.label.renderer'; import { numberItemLabelRenderer } from './itemLabelRenderer/number.label.renderer'; import { dateItemLabelRenderer } from './itemLabelRenderer/date.label.renderer'; @@ -13,5 +14,6 @@ export const itemLabelRendererByType: Record '', }; diff --git a/frontend/src/shared/modules/filters/config/queryUrlParser/boolean.parser.ts b/frontend/src/shared/modules/filters/config/queryUrlParser/boolean.parser.ts index d968529ac0..897280b95f 100644 --- a/frontend/src/shared/modules/filters/config/queryUrlParser/boolean.parser.ts +++ b/frontend/src/shared/modules/filters/config/queryUrlParser/boolean.parser.ts @@ -2,10 +2,10 @@ import { BooleanFilterValue } from '@/shared/modules/filters/types/filterTypes/B interface QueryUrlBooleanValue { value: string, - exclude: string, + include: string, } export const booleanQueryUrlParser = (query: QueryUrlBooleanValue): BooleanFilterValue => ({ - exclude: query.exclude === 'true', + include: query.include === 'true', value: query.value === 'true', }); diff --git a/frontend/src/shared/modules/filters/config/queryUrlParser/date.parser.ts b/frontend/src/shared/modules/filters/config/queryUrlParser/date.parser.ts index 64b140a92e..f7690e7261 100644 --- a/frontend/src/shared/modules/filters/config/queryUrlParser/date.parser.ts +++ b/frontend/src/shared/modules/filters/config/queryUrlParser/date.parser.ts @@ -3,10 +3,10 @@ import { DateFilterValue } from '@/shared/modules/filters/types/filterTypes/Date interface QueryUrlDateValue { operator: string, value: string, - exclude: string, + include: string, } export const dateQueryUrlParser = (query: QueryUrlDateValue): DateFilterValue => ({ ...query, - exclude: query.exclude === 'true', + include: query.include === 'true', }); diff --git a/frontend/src/shared/modules/filters/config/queryUrlParser/multiselect.parser.ts b/frontend/src/shared/modules/filters/config/queryUrlParser/multiselect.parser.ts index 16d93f72f0..e323fe0ca5 100644 --- a/frontend/src/shared/modules/filters/config/queryUrlParser/multiselect.parser.ts +++ b/frontend/src/shared/modules/filters/config/queryUrlParser/multiselect.parser.ts @@ -2,11 +2,11 @@ import { MultiSelectFilterValue } from '@/shared/modules/filters/types/filterTyp interface QueryUrlMultiSelectValue { value: string, - exclude: string, + include: string, } export const multiSelectQueryUrlParser = (query: QueryUrlMultiSelectValue): MultiSelectFilterValue => ({ ...query, value: query.value.split(','), - exclude: query.exclude === 'true', + include: query.include === 'true', }); diff --git a/frontend/src/shared/modules/filters/config/queryUrlParser/number.parser.ts b/frontend/src/shared/modules/filters/config/queryUrlParser/number.parser.ts index 319c791b77..1c32649faf 100644 --- a/frontend/src/shared/modules/filters/config/queryUrlParser/number.parser.ts +++ b/frontend/src/shared/modules/filters/config/queryUrlParser/number.parser.ts @@ -3,11 +3,11 @@ import { NumberFilterValue } from '@/shared/modules/filters/types/filterTypes/Nu interface QueryUrlNumberValue { operator: string, value: string, - exclude: string, + include: string, } export const numberQueryUrlParser = (query: QueryUrlNumberValue): NumberFilterValue => ({ ...query, - exclude: query.exclude === 'true', + include: query.include === 'true', value: +query.value, }); diff --git a/frontend/src/shared/modules/filters/config/queryUrlParser/select.parser.ts b/frontend/src/shared/modules/filters/config/queryUrlParser/select.parser.ts index af7f30022f..95e0ad80c5 100644 --- a/frontend/src/shared/modules/filters/config/queryUrlParser/select.parser.ts +++ b/frontend/src/shared/modules/filters/config/queryUrlParser/select.parser.ts @@ -2,10 +2,10 @@ import { SelectFilterValue } from '@/shared/modules/filters/types/filterTypes/Se interface QueryUrlSelectValue { value: string, - exclude: string, + include: string, } export const selectQueryUrlParser = (query: QueryUrlSelectValue): SelectFilterValue => ({ ...query, - exclude: query.exclude === 'true', + include: query.include === 'true', }); diff --git a/frontend/src/shared/modules/filters/config/queryUrlParser/string.parser.ts b/frontend/src/shared/modules/filters/config/queryUrlParser/string.parser.ts new file mode 100644 index 0000000000..2fa99b701f --- /dev/null +++ b/frontend/src/shared/modules/filters/config/queryUrlParser/string.parser.ts @@ -0,0 +1,12 @@ +import { StringFilterValue } from '@/shared/modules/filters/types/filterTypes/StringFilterConfig'; + +interface QueryUrlStringValue { + operator: string, + value: string, + include: string, +} + +export const stringQueryUrlParser = (query: QueryUrlStringValue): StringFilterValue => ({ + ...query, + include: query.include === 'true', +}); diff --git a/frontend/src/shared/modules/filters/config/queryUrlParserByType.ts b/frontend/src/shared/modules/filters/config/queryUrlParserByType.ts index 991ef4dac3..56437900f7 100644 --- a/frontend/src/shared/modules/filters/config/queryUrlParserByType.ts +++ b/frontend/src/shared/modules/filters/config/queryUrlParserByType.ts @@ -4,6 +4,7 @@ import { numberQueryUrlParser } from '@/shared/modules/filters/config/queryUrlPa import { dateQueryUrlParser } from '@/shared/modules/filters/config/queryUrlParser/date.parser'; import { selectQueryUrlParser } from '@/shared/modules/filters/config/queryUrlParser/select.parser'; import { multiSelectQueryUrlParser } from '@/shared/modules/filters/config/queryUrlParser/multiselect.parser'; +import { stringQueryUrlParser } from '@/shared/modules/filters/config/queryUrlParser/string.parser'; export const queryUrlParserByType: Record any> = { [FilterConfigType.BOOLEAN]: booleanQueryUrlParser, @@ -11,5 +12,6 @@ export const queryUrlParserByType: Record any> [FilterConfigType.DATE]: dateQueryUrlParser, [FilterConfigType.SELECT]: selectQueryUrlParser, [FilterConfigType.MULTISELECT]: multiSelectQueryUrlParser, + [FilterConfigType.STRING]: stringQueryUrlParser, [FilterConfigType.CUSTOM]: () => null, }; diff --git a/frontend/src/shared/modules/filters/services/custom-attributes.service.ts b/frontend/src/shared/modules/filters/services/custom-attributes.service.ts new file mode 100644 index 0000000000..72a7bc8e46 --- /dev/null +++ b/frontend/src/shared/modules/filters/services/custom-attributes.service.ts @@ -0,0 +1,130 @@ +import { FilterConfig, FilterConfigType } from '@/shared/modules/filters/types/FilterConfig'; +import { FilterCustomAttribute, FilterCustomAttributeType } from '@/shared/modules/filters/types/FilterCustomAttribute'; +import { NumberFilterConfig, NumberFilterValue } from '@/shared/modules/filters/types/filterTypes/NumberFilterConfig'; +import { apiFilterRendererByType } from '@/shared/modules/filters/config/apiFilterRendererByType'; +import { itemLabelRendererByType } from '@/shared/modules/filters/config/itemLabelRendererByType'; +import { + BooleanFilterConfig, + BooleanFilterValue, +} from '@/shared/modules/filters/types/filterTypes/BooleanFilterConfig'; +import { DateFilterConfig, DateFilterValue } from '@/shared/modules/filters/types/filterTypes/DateFilterConfig'; +import { + MultiSelectFilterConfig, + MultiSelectFilterValue, +} from '@/shared/modules/filters/types/filterTypes/MultiSelectFilterConfig'; +import { StringFilterConfig, StringFilterValue } from '@/shared/modules/filters/types/filterTypes/StringFilterConfig'; + +export const customAttributesService = () => { + function buildFilterFromAttributes( + attributes: FilterCustomAttribute[], + ): Record { + const filters: Record = {}; + attributes + .filter((attribute) => attribute.show) + .forEach((attribute) => { + // Number type + if (attribute.type === FilterCustomAttributeType.NUMBER) { + filters[attribute.name] = { + id: attribute.name, + label: attribute.label, + type: FilterConfigType.NUMBER, + options: { + hideIncludeSwitch: true, + }, + itemLabelRenderer(value: NumberFilterValue): string { + return itemLabelRendererByType[FilterConfigType.NUMBER](attribute.label, value); + }, + apiFilterRenderer(value: NumberFilterValue): any[] { + return apiFilterRendererByType[FilterConfigType.NUMBER](`attributes.${attribute.name}.default`, value); + }, + } as NumberFilterConfig; + return; + } + // Boolean type + if (attribute.type === FilterCustomAttributeType.BOOLEAN) { + filters[attribute.name] = { + id: attribute.name, + label: attribute.label, + type: FilterConfigType.BOOLEAN, + options: { + hideIncludeSwitch: true, + }, + itemLabelRenderer(value: BooleanFilterValue): string { + return itemLabelRendererByType[FilterConfigType.BOOLEAN](attribute.label, value); + }, + apiFilterRenderer(value: BooleanFilterValue): any[] { + return apiFilterRendererByType[FilterConfigType.BOOLEAN](`attributes.${attribute.name}.default`, value); + }, + } as BooleanFilterConfig; + return; + } + // String type + if (attribute.type === FilterCustomAttributeType.STRING || attribute.type === FilterCustomAttributeType.URL) { + filters[attribute.name] = { + id: attribute.name, + label: attribute.label, + type: FilterConfigType.STRING, + options: { + hideIncludeSwitch: true, + }, + itemLabelRenderer(value: StringFilterValue): string { + return itemLabelRendererByType[FilterConfigType.STRING](attribute.label, value); + }, + apiFilterRenderer(value: StringFilterValue): any[] { + return apiFilterRendererByType[FilterConfigType.STRING](`attributes.${attribute.name}.default`, value); + }, + } as StringFilterConfig; + return; + } + // Date type + if (attribute.type === FilterCustomAttributeType.DATE) { + filters[attribute.name] = { + id: attribute.name, + label: attribute.label, + type: FilterConfigType.DATE, + options: { + hideIncludeSwitch: true, + }, + itemLabelRenderer(value: DateFilterValue): string { + return itemLabelRendererByType[FilterConfigType.DATE](attribute.label, value); + }, + apiFilterRenderer(value: DateFilterValue): any[] { + return apiFilterRendererByType[FilterConfigType.DATE](`attributes.${attribute.name}.default`, value); + }, + } as DateFilterConfig; + return; + } + // Multiselect type + if (attribute.type === FilterCustomAttributeType.MULTISELECT + || (attribute.type === FilterCustomAttributeType.SPECIAL && attribute.options.length > 0)) { + filters[attribute.name] = { + id: attribute.name, + label: attribute.label, + type: FilterConfigType.MULTISELECT, + options: { + hideIncludeSwitch: true, + options: [ + { + options: attribute.options.map((option) => ({ + value: option, + label: option, + })), + }, + ], + }, + itemLabelRenderer(value: MultiSelectFilterValue): string { + return itemLabelRendererByType[FilterConfigType.MULTISELECT](attribute.label, value); + }, + apiFilterRenderer(value: MultiSelectFilterValue): any[] { + return apiFilterRendererByType[FilterConfigType.MULTISELECT](`attributes.${attribute.name}.default`, value); + }, + } as MultiSelectFilterConfig; + } + }); + return filters; + } + + return { + buildFilterFromAttributes, + }; +}; diff --git a/frontend/src/shared/modules/filters/services/filter-api.service.ts b/frontend/src/shared/modules/filters/services/filter-api.service.ts index 59d7ea52e0..87854fb84c 100644 --- a/frontend/src/shared/modules/filters/services/filter-api.service.ts +++ b/frontend/src/shared/modules/filters/services/filter-api.service.ts @@ -31,7 +31,7 @@ export const filterApiService = () => { } // Settings - if (savedViewsConfig) { + if (savedViewsConfig && settings) { Object.entries(settings).forEach(([setting, value]) => { const filter = savedViewsConfig.settings[setting]?.apiFilterRenderer(value); if (filter) { diff --git a/frontend/src/shared/modules/filters/types/FilterConfig.ts b/frontend/src/shared/modules/filters/types/FilterConfig.ts index 7d2dec1eab..b54981fd45 100644 --- a/frontend/src/shared/modules/filters/types/FilterConfig.ts +++ b/frontend/src/shared/modules/filters/types/FilterConfig.ts @@ -4,6 +4,7 @@ import { SelectFilterConfig } from '@/shared/modules/filters/types/filterTypes/S import { BooleanFilterConfig } from '@/shared/modules/filters/types/filterTypes/BooleanFilterConfig'; import { DateFilterConfig } from '@/shared/modules/filters/types/filterTypes/DateFilterConfig'; import { CustomFilterConfig } from '@/shared/modules/filters/types/filterTypes/CustomFilterConfig'; +import { StringFilterConfig } from '@/shared/modules/filters/types/filterTypes/StringFilterConfig'; export enum FilterConfigType { NUMBER = 'number', @@ -11,6 +12,7 @@ export enum FilterConfigType { MULTISELECT = 'multiselect', BOOLEAN = 'boolean', DATE = 'date', + STRING = 'string', CUSTOM = 'custom', } @@ -24,6 +26,7 @@ export type FilterConfig = NumberFilterConfig | SelectFilterConfig | BooleanFilterConfig | DateFilterConfig + | StringFilterConfig | CustomFilterConfig export interface FilterStatic { diff --git a/frontend/src/shared/modules/filters/types/FilterCustomAttribute.ts b/frontend/src/shared/modules/filters/types/FilterCustomAttribute.ts new file mode 100644 index 0000000000..5054391cc9 --- /dev/null +++ b/frontend/src/shared/modules/filters/types/FilterCustomAttribute.ts @@ -0,0 +1,24 @@ +export enum FilterCustomAttributeType { + NUMBER = 'number', + BOOLEAN = 'boolean', + MULTISELECT = 'multiSelect', + STRING = 'string', + DATE = 'date', + URL = 'url', + SPECIAL = 'special', +} + +export interface FilterCustomAttribute { + canDelete: boolean; + createdAt: string; + createdById: string; + id: string; + label: string; + name: string; + options: string[] + show: boolean; + tenantId: string; + type: FilterCustomAttributeType; + updatedAt: string + updatedById: string; +} diff --git a/frontend/src/shared/modules/filters/types/filterTypes/BooleanFilterConfig.ts b/frontend/src/shared/modules/filters/types/filterTypes/BooleanFilterConfig.ts index 46d38e377f..dbe4902a00 100644 --- a/frontend/src/shared/modules/filters/types/filterTypes/BooleanFilterConfig.ts +++ b/frontend/src/shared/modules/filters/types/filterTypes/BooleanFilterConfig.ts @@ -2,11 +2,12 @@ import { BaseFilterConfig, FilterConfigType } from '@/shared/modules/filters/types/FilterConfig'; export interface BooleanFilterOptions { + hideIncludeSwitch?: boolean; } export interface BooleanFilterValue { value: boolean, - exclude: boolean, + include: boolean, } export interface BooleanFilterConfig extends BaseFilterConfig { diff --git a/frontend/src/shared/modules/filters/types/filterTypes/DateFilterConfig.ts b/frontend/src/shared/modules/filters/types/filterTypes/DateFilterConfig.ts index 2859680dde..d29d40732b 100644 --- a/frontend/src/shared/modules/filters/types/filterTypes/DateFilterConfig.ts +++ b/frontend/src/shared/modules/filters/types/filterTypes/DateFilterConfig.ts @@ -2,12 +2,13 @@ import { BaseFilterConfig, FilterConfigType } from '@/shared/modules/filters/types/FilterConfig'; export interface DateFilterOptions { - + hideIncludeSwitch?: boolean; } + export interface DateFilterValue { operator: string, value: string, - exclude: boolean, + include: boolean, } export interface DateFilterConfig extends BaseFilterConfig { diff --git a/frontend/src/shared/modules/filters/types/filterTypes/MultiSelectFilterConfig.ts b/frontend/src/shared/modules/filters/types/filterTypes/MultiSelectFilterConfig.ts index 9a73ade59f..82b58c1ccb 100644 --- a/frontend/src/shared/modules/filters/types/filterTypes/MultiSelectFilterConfig.ts +++ b/frontend/src/shared/modules/filters/types/filterTypes/MultiSelectFilterConfig.ts @@ -6,7 +6,7 @@ interface MultiSelectFilterOption { value: string; } export interface MultiSelectFilterOptionGroup { - label: string; + label?: string; options: MultiSelectFilterOption[]; } export interface MultiSelectFilterOptions { @@ -15,7 +15,7 @@ export interface MultiSelectFilterOptions { export interface MultiSelectFilterValue { value: string[], - exclude: boolean, + include: boolean, } export interface MultiSelectFilterConfig extends BaseFilterConfig { diff --git a/frontend/src/shared/modules/filters/types/filterTypes/NumberFilterConfig.ts b/frontend/src/shared/modules/filters/types/filterTypes/NumberFilterConfig.ts index b22085ee95..ddee694259 100644 --- a/frontend/src/shared/modules/filters/types/filterTypes/NumberFilterConfig.ts +++ b/frontend/src/shared/modules/filters/types/filterTypes/NumberFilterConfig.ts @@ -2,12 +2,12 @@ import { BaseFilterConfig, FilterConfigType } from '@/shared/modules/filters/types/FilterConfig'; export interface NumberFilterOptions { - + hideIncludeSwitch?: boolean; } export interface NumberFilterValue { operator: string, value: number | '', - exclude: boolean, + include: boolean, } export interface NumberFilterConfig extends BaseFilterConfig { type: FilterConfigType.NUMBER; diff --git a/frontend/src/shared/modules/filters/types/filterTypes/SelectFilterConfig.ts b/frontend/src/shared/modules/filters/types/filterTypes/SelectFilterConfig.ts index 1a97b7e07d..0ffe51bbf9 100644 --- a/frontend/src/shared/modules/filters/types/filterTypes/SelectFilterConfig.ts +++ b/frontend/src/shared/modules/filters/types/filterTypes/SelectFilterConfig.ts @@ -6,17 +6,18 @@ interface SelectFilterOption { value: string; } export interface SelectFilterOptionGroup { - label: string; + label?: string; options: SelectFilterOption[]; } export interface SelectFilterOptions { + hideIncludeSwitch?: boolean; options: SelectFilterOptionGroup[] } export interface SelectFilterValue { value: string, - exclude: boolean, + include: boolean, } export interface SelectFilterConfig extends BaseFilterConfig { diff --git a/frontend/src/shared/modules/filters/types/filterTypes/StringFilterConfig.ts b/frontend/src/shared/modules/filters/types/filterTypes/StringFilterConfig.ts new file mode 100644 index 0000000000..28018b9451 --- /dev/null +++ b/frontend/src/shared/modules/filters/types/filterTypes/StringFilterConfig.ts @@ -0,0 +1,17 @@ +/* eslint-disable no-unused-vars */ +import { BaseFilterConfig, FilterConfigType } from '@/shared/modules/filters/types/FilterConfig'; + +export interface StringFilterOptions { + +} +export interface StringFilterValue { + operator: string, + value: string, + include: boolean, +} +export interface StringFilterConfig extends BaseFilterConfig { + type: FilterConfigType.STRING; + options: StringFilterOptions; + itemLabelRenderer: (value: StringFilterValue) => string; + apiFilterRenderer: (value: StringFilterValue) => any[]; +} diff --git a/frontend/tsconfig.json b/frontend/tsconfig.json index 65434aef03..dfae97d4a8 100644 --- a/frontend/tsconfig.json +++ b/frontend/tsconfig.json @@ -11,6 +11,7 @@ "esModuleInterop": true, "allowSyntheticDefaultImports": true, "sourceMap": true, + "noImplicitThis": true, "baseUrl": ".", "types": [ "webpack-env" From 135edf622ba6a92b092c4f05756136c855c201cf Mon Sep 17 00:00:00 2001 From: Gasper Grom Date: Mon, 22 May 2023 12:59:22 +0200 Subject: [PATCH 2/2] Change saved views config --- .../modules/member/config/saved-views/views/influential.ts | 2 +- .../modules/member/config/saved-views/views/most-engaged.ts | 2 +- .../modules/member/config/saved-views/views/new-and-active.ts | 4 ++-- .../modules/member/config/saved-views/views/slipping-away.ts | 4 ++-- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/frontend/src/modules/member/config/saved-views/views/influential.ts b/frontend/src/modules/member/config/saved-views/views/influential.ts index 52708baf97..b4eb564988 100644 --- a/frontend/src/modules/member/config/saved-views/views/influential.ts +++ b/frontend/src/modules/member/config/saved-views/views/influential.ts @@ -19,7 +19,7 @@ const influential: SavedView = { reach: { operator: '>=', value: 500, - exclude: false, + include: true, }, }, }; diff --git a/frontend/src/modules/member/config/saved-views/views/most-engaged.ts b/frontend/src/modules/member/config/saved-views/views/most-engaged.ts index 57bf382ba6..af3fd52cf7 100644 --- a/frontend/src/modules/member/config/saved-views/views/most-engaged.ts +++ b/frontend/src/modules/member/config/saved-views/views/most-engaged.ts @@ -18,7 +18,7 @@ const mostEngaged: SavedView = { engagementLevel: { value: ['fan', 'ultra'], - exclude: false, + include: true, }, }, }; diff --git a/frontend/src/modules/member/config/saved-views/views/new-and-active.ts b/frontend/src/modules/member/config/saved-views/views/new-and-active.ts index a4eff4d00f..8f4d3c2175 100644 --- a/frontend/src/modules/member/config/saved-views/views/new-and-active.ts +++ b/frontend/src/modules/member/config/saved-views/views/new-and-active.ts @@ -20,13 +20,13 @@ const newAndActive: SavedView = { joinedDate: { operator: 'after', value: moment().subtract(1, 'month').format('YYYY-MM-DD'), - exclude: false, + include: true, }, lastActivityDate: { operator: 'after', value: moment().subtract(1, 'month').format('YYYY-MM-DD'), - exclude: false, + include: true, }, }, }; diff --git a/frontend/src/modules/member/config/saved-views/views/slipping-away.ts b/frontend/src/modules/member/config/saved-views/views/slipping-away.ts index 3368e152b4..984e35f3ae 100644 --- a/frontend/src/modules/member/config/saved-views/views/slipping-away.ts +++ b/frontend/src/modules/member/config/saved-views/views/slipping-away.ts @@ -19,13 +19,13 @@ const slippingAway: SavedView = { engagementLevel: { value: ['fan', 'ultra'], - exclude: false, + include: true, }, lastActivityDate: { operator: 'after', value: moment().subtract(1, 'month').format('YYYY-MM-DD'), - exclude: false, + include: true, }, }, };