Skip to content

Commit f528cc9

Browse files
authored
Add multi-select organization filter in members, organizations and activities lists (#1560)
1 parent 3cdb7d5 commit f528cc9

File tree

8 files changed

+176
-1
lines changed

8 files changed

+176
-1
lines changed

frontend/src/modules/activity/config/filters/main.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,14 @@ import date from './date/config';
66
import member from './member/config';
77
import platform from './platform/config';
88
import sentiment from './sentiment/config';
9+
import organizations from './organizations/config';
910

1011
export const activityFilters: Record<string, FilterConfig> = {
1112
activityType,
1213
channel,
1314
date,
1415
member,
16+
organizations,
1517
platform,
1618
sentiment,
1719
};
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
import { FilterConfigType } from '@/shared/modules/filters/types/FilterConfig';
2+
import { itemLabelRendererByType } from '@/shared/modules/filters/config/itemLabelRendererByType';
3+
import {
4+
MultiSelectAsyncFilterConfig,
5+
MultiSelectAsyncFilterOptions, MultiSelectAsyncFilterValue,
6+
} from '@/shared/modules/filters/types/filterTypes/MultiSelectAsyncFilterConfig';
7+
import { OrganizationService } from '@/modules/organization/organization-service';
8+
import { DEFAULT_ORGANIZATION_FILTERS } from '@/modules/organization/store/constants';
9+
10+
const organizations: MultiSelectAsyncFilterConfig = {
11+
id: 'organizations',
12+
label: 'Organization',
13+
iconClass: 'ri-community-line',
14+
type: FilterConfigType.MULTISELECT_ASYNC,
15+
options: {
16+
remoteMethod: (query) => OrganizationService.listAutocomplete(query, 10)
17+
.then((data: any[]) => data.map((organization) => ({
18+
label: organization.label,
19+
value: organization.id,
20+
logo: organization.logo,
21+
}))),
22+
remotePopulateItems: (ids: string[]) => OrganizationService.listAutocomplete({
23+
filter: {
24+
and: [
25+
...DEFAULT_ORGANIZATION_FILTERS,
26+
{
27+
id: { in: ids },
28+
},
29+
],
30+
},
31+
orderBy: null,
32+
limit: ids.length,
33+
offset: 0,
34+
})
35+
.then(({ rows }: any) => rows.map((organization: any) => ({
36+
label: organization.displayName,
37+
value: organization.id,
38+
logo: organization.logo,
39+
}))),
40+
},
41+
itemLabelRenderer(value: MultiSelectAsyncFilterValue, options: MultiSelectAsyncFilterOptions, data: any): string {
42+
return itemLabelRendererByType[FilterConfigType.MULTISELECT_ASYNC]('Organization', value, options, data);
43+
},
44+
apiFilterRenderer({ value, include }: MultiSelectAsyncFilterValue): any[] {
45+
const filter = {
46+
organizationId: value,
47+
};
48+
return [
49+
(include ? filter : { not: filter }),
50+
];
51+
},
52+
};
53+
54+
export default organizations;

frontend/src/modules/member/config/filters/main.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,11 @@ import reach from './reach/config';
1414
import tags from './tags/config';
1515
import memberName from './memberName/config';
1616
import jobTitle from './jobTitle/config';
17+
import organizations from './organizations/config';
1718

1819
export const memberFilters: Record<string, FilterConfig> = {
1920
memberName,
21+
organizations,
2022
noOfActivities,
2123
noOfOSSContributions,
2224
jobTitle,
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
import { FilterConfigType } from '@/shared/modules/filters/types/FilterConfig';
2+
import { itemLabelRendererByType } from '@/shared/modules/filters/config/itemLabelRendererByType';
3+
import {
4+
MultiSelectAsyncFilterConfig,
5+
MultiSelectAsyncFilterOptions, MultiSelectAsyncFilterValue,
6+
} from '@/shared/modules/filters/types/filterTypes/MultiSelectAsyncFilterConfig';
7+
import { OrganizationService } from '@/modules/organization/organization-service';
8+
import { DEFAULT_ORGANIZATION_FILTERS } from '@/modules/organization/store/constants';
9+
10+
const organizations: MultiSelectAsyncFilterConfig = {
11+
id: 'organizations',
12+
label: 'Organization',
13+
iconClass: 'ri-community-line',
14+
type: FilterConfigType.MULTISELECT_ASYNC,
15+
options: {
16+
remoteMethod: (query) => OrganizationService.listAutocomplete(query, 10)
17+
.then((data: any[]) => data.map((organization) => ({
18+
label: organization.label,
19+
value: organization.id,
20+
logo: organization.logo,
21+
}))),
22+
remotePopulateItems: (ids: string[]) => OrganizationService.listAutocomplete({
23+
filter: {
24+
and: [
25+
...DEFAULT_ORGANIZATION_FILTERS,
26+
{
27+
id: { in: ids },
28+
},
29+
],
30+
},
31+
orderBy: null,
32+
limit: ids.length,
33+
offset: 0,
34+
})
35+
.then(({ rows }: any) => rows.map((organization: any) => ({
36+
label: organization.displayName,
37+
value: organization.id,
38+
logo: organization.logo,
39+
}))),
40+
},
41+
itemLabelRenderer(value: MultiSelectAsyncFilterValue, options: MultiSelectAsyncFilterOptions, data: any): string {
42+
return itemLabelRendererByType[FilterConfigType.MULTISELECT_ASYNC]('Organization', value, options, data);
43+
},
44+
apiFilterRenderer({ value, include }: MultiSelectAsyncFilterValue): any[] {
45+
const filter = {
46+
or: value.map((id) => ({ organizations: { eq: id } })),
47+
};
48+
return [
49+
(include ? filter : { not: filter }),
50+
];
51+
},
52+
};
53+
54+
export default organizations;

frontend/src/modules/organization/config/filters/main.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,10 @@ import annualEmployeeGrowthRate from './annualEmployeeGrowthRate/config';
1717
import employeeCount from './employeeCount/config';
1818
import tags from './tags/config';
1919
import type from './type/config';
20+
import organizations from './organizations/config';
2021

2122
export const organizationFilters: Record<string, FilterConfig> = {
23+
organizations,
2224
noOfActivities,
2325
noOfMembers,
2426
activeOn,
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
import { FilterConfigType } from '@/shared/modules/filters/types/FilterConfig';
2+
import { itemLabelRendererByType } from '@/shared/modules/filters/config/itemLabelRendererByType';
3+
import {
4+
MultiSelectAsyncFilterConfig,
5+
MultiSelectAsyncFilterOptions, MultiSelectAsyncFilterValue,
6+
} from '@/shared/modules/filters/types/filterTypes/MultiSelectAsyncFilterConfig';
7+
import { OrganizationService } from '@/modules/organization/organization-service';
8+
import { DEFAULT_ORGANIZATION_FILTERS } from '@/modules/organization/store/constants';
9+
10+
const organizations: MultiSelectAsyncFilterConfig = {
11+
id: 'organizations',
12+
label: 'Organization',
13+
iconClass: 'ri-community-line',
14+
type: FilterConfigType.MULTISELECT_ASYNC,
15+
options: {
16+
remoteMethod: (query) => OrganizationService.listAutocomplete(query, 10)
17+
.then((data: any[]) => data.map((organization) => ({
18+
label: organization.label,
19+
value: organization.id,
20+
logo: organization.logo,
21+
}))),
22+
remotePopulateItems: (ids: string[]) => OrganizationService.listAutocomplete({
23+
filter: {
24+
and: [
25+
...DEFAULT_ORGANIZATION_FILTERS,
26+
{
27+
id: { in: ids },
28+
},
29+
],
30+
},
31+
orderBy: null,
32+
limit: ids.length,
33+
offset: 0,
34+
})
35+
.then(({ rows }: any) => rows.map((organization: any) => ({
36+
label: organization.displayName,
37+
value: organization.id,
38+
logo: organization.logo,
39+
}))),
40+
},
41+
itemLabelRenderer(value: MultiSelectAsyncFilterValue, options: MultiSelectAsyncFilterOptions, data: any): string {
42+
return itemLabelRendererByType[FilterConfigType.MULTISELECT_ASYNC]('Organization', value, options, data);
43+
},
44+
apiFilterRenderer({ value, include }: MultiSelectAsyncFilterValue): any[] {
45+
const filter = {
46+
or: value.map((id) => ({ id: { eq: id } })),
47+
};
48+
return [
49+
(include ? filter : { not: filter }),
50+
];
51+
},
52+
};
53+
54+
export default organizations;

frontend/src/shared/modules/filters/components/filterTypes/MultiSelectAsyncFilter.vue

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,13 +26,19 @@
2626
:value="option"
2727
>
2828
<div
29-
class="el-checkbox filter-checkbox h-4"
29+
class="h-4 el-checkbox filter-checkbox"
3030
:class="{ 'is-checked': props.modelValue.value.includes(option.value) }"
3131
>
3232
<span class="el-checkbox__input" :class="{ 'is-checked': form.value.includes(option.value) }">
3333
<span class="el-checkbox__inner" />
3434
</span>
3535
</div>
36+
<template v-if="config.id === 'organizations'">
37+
<span class="flex items-center justify-center w-6 h-6 p-1 mr-3 border rounded-md ">
38+
<img v-if="option.logo" :src="option.logo" class="w-4 h-4 min-w-[16px]" :alt="option.label" />
39+
<i v-else class="flex items-center justify-center w-4 h-4 text-gray-300 ri-community-line" />
40+
</span>
41+
</template>
3642
{{ option.label }}
3743
</el-option>
3844
</el-select>

frontend/src/shared/modules/filters/types/filterTypes/MultiSelectAsyncFilterConfig.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import { BaseFilterConfig, FilterConfigType } from '@/shared/modules/filters/typ
44
export interface MultiSelectAsyncFilterOption {
55
label: string;
66
value: string;
7+
logo?: string;
78
}
89
export interface MultiSelectAsyncFilterOptions {
910
hideIncludeSwitch?: boolean;

0 commit comments

Comments
 (0)