Skip to content

Commit 7053831

Browse files
committed
fix(organizations): filter takes externalIds
1 parent 80c6809 commit 7053831

File tree

6 files changed

+70
-24
lines changed

6 files changed

+70
-24
lines changed

client/src/api/organizations/autocomplete/index.ts

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,16 @@ import { organizationsIndex, postHeaders } from "../../../config/api";
22
import { LightOrganization } from "../../../types/organization";
33
import { SearchArgs, SearchResponse, ElasticResult } from "../../../types/commons";
44

5-
const SOURCE = ["id", "label", "address.main", "address.city", "publicationsCount", "projectsCount", "patentsCount"]
5+
const SOURCE = [
6+
"id",
7+
"label",
8+
"address.main",
9+
"address.city",
10+
"externalIds",
11+
"publicationsCount",
12+
"projectsCount",
13+
"patentsCount",
14+
]
615

716
export async function autocompleteOrganizations({ query }: SearchArgs): Promise<Pick<SearchResponse<LightOrganization>, "data">> {
817
const body: any = {

client/src/pages/organizations/[id]/components/network/index.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import { useIntl } from "react-intl"
66

77
type OrganizationNetworkProps = {
88
data: Network
9-
affiliationsIds: { value: string; label: string }[]
9+
affiliationsIds: { value: any; label: string }[]
1010
}
1111

1212
export default function OrganizationNetwork({ data: network, affiliationsIds }: OrganizationNetworkProps) {

client/src/pages/organizations/[id]/components/organization.tsx

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -56,8 +56,6 @@ export default function OrganizationPresentation({
5656
NETWORK_BADGES_CODES.includes(b.code.toLowerCase()),
5757
);
5858

59-
console.log("data", data)
60-
6159
const propre = data?.institutionOf
6260
?.filter((element) =>
6361
["établissement tutelle", "primary"].includes(element.relationType),
@@ -319,10 +317,7 @@ export default function OrganizationPresentation({
319317
<OrganizationNetwork
320318
data={network}
321319
affiliationsIds={[
322-
{ value: data.id, label: getLangFieldValue(locale)(data.label) },
323-
...data?.externalIds?.filter((extId) => extId.id !== data.id).map((extId) =>
324-
({ value: extId.id, label: extId.id })
325-
),
320+
{ value: [...new Set([data.id, ...data.externalIds?.map((extId) => extId.id)])], label: getLangFieldValue(locale)(data.label) },
326321
]}
327322
/>
328323
<OrganizationProjects

client/src/pages/search/components/publications/filters/organizations.tsx

Lines changed: 16 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,9 @@ import getLangFieldValue from "../../../../../utils/lang";
1616

1717
export default function PublicationOrganizationsFilter() {
1818
const { locale } = useDSFRConfig();
19-
const { currentFilters, handleFilterChange, setOperator } = useUrl();
19+
const { currentFilters, handleArrayFilterChange, setOperator } = useUrl();
2020

21-
const authorsAutocompletedList = useAutocompleteList<LightOrganization>({
21+
const organizationsAutocompletedList = useAutocompleteList<LightOrganization>({
2222
async load({ filterText }) {
2323
if (!filterText) {
2424
return { items: [] };
@@ -55,39 +55,42 @@ export default function PublicationOrganizationsFilter() {
5555
<TagGroup>
5656
{filter?.values?.map(({ value, label }) => (
5757
<DismissibleTag
58-
key={value}
58+
key={Array.isArray(value) ? value.join("|||") : value}
5959
className="fr-mr-1v"
6060
color="orange-terre-battue"
6161
onClick={(e) => {
6262
e.preventDefault()
63-
handleFilterChange({ field: "affiliations.id", value })
63+
handleArrayFilterChange({ field: "affiliations.id", value: Array.isArray(value) ? value : [value] })
6464
}}
6565
>
66-
{label || value}
66+
{label || (Array.isArray(value) ? value.join(", ") : value)}
6767
</DismissibleTag>
6868
))}
6969
</TagGroup>
7070
<Autocomplete
7171
label="Rechercher des structures"
72-
items={authorsAutocompletedList.items}
73-
inputValue={authorsAutocompletedList.filterText}
74-
onInputChange={authorsAutocompletedList.setFilterText}
75-
loadingState={authorsAutocompletedList.loadingState}
72+
items={organizationsAutocompletedList.items}
73+
inputValue={organizationsAutocompletedList.filterText}
74+
onInputChange={organizationsAutocompletedList.setFilterText}
75+
loadingState={organizationsAutocompletedList.loadingState}
7676
// menuTrigger="focus"
7777
size="md"
7878
onSelectionChange={(item) => {
7979
if (!item) return
80-
const [value, label] = item.toString().split("###")
81-
handleFilterChange({ field: "affiliations.id", value, label })
82-
authorsAutocompletedList.setFilterText('')
80+
const [label, values] = item.toString().split("###")
81+
const value = values.split("|||")
82+
handleArrayFilterChange({ field: "affiliations.id", value, label })
83+
organizationsAutocompletedList.setFilterText("")
8384
}}
8485
>
8586
{(item) => (
8687
<AutocompleteItem
8788
startContent={<span className="fr-mr-3v fr-icon--md fr-icon-user-line" />}
8889
endContent={<span className="fr-text--xs fr-text-mention--grey">{item.publicationsCount} publications</span>}
8990
description={item.address?.find((a) => a.main)?.city}
90-
key={`${item.id}###${getLangFieldValue(locale)(item.label)}`}
91+
key={`${getLangFieldValue(locale)(item.label)}###${[
92+
...new Set([item.id, ...(item.externalIds?.map((id) => id.id) || [])]),
93+
].join("|||")}`}
9194
>
9295
{getLangFieldValue(locale)(item.label)}
9396
</AutocompleteItem>

client/src/pages/search/hooks/useUrl.ts

Lines changed: 41 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import useIntegration from "../../networks/hooks/useIntegration";
55

66
type FilterValues = {
77
label?: string;
8-
value: string | number;
8+
value: string | number | (string | number)[];
99
}[];
1010
export type Filter = {
1111
type: "terms" | "range" | "bool";
@@ -67,13 +67,13 @@ export function filtersToElasticQuery(
6767
if (!filter?.values?.length || !filter?.type) return [];
6868
if (filter.operator === "and") {
6969
return filter?.values?.map(({ value }) =>
70-
fromFilterToElasticQuery(field, [value], filter.type)
70+
fromFilterToElasticQuery(field, Array.isArray(value) ? value : [value], filter.type)
7171
);
7272
}
7373
return [
7474
fromFilterToElasticQuery(
7575
field,
76-
filter.values.map(({ value }) => value),
76+
filter.values.flatMap(({ value }) => (Array.isArray(value) ? value : [value])),
7777
filter.type
7878
),
7979
];
@@ -164,6 +164,42 @@ export default function useUrl() {
164164
[currentFilters, handleDeleteFilter, searchParams, setSearchParams]
165165
);
166166

167+
const handleArrayFilterChange = useCallback(
168+
({ field, value, filterType = "terms", label = null }: { field: string; value: (string | number)[]; filterType?: "terms" | "range" | "bool"; label?: string }) => {
169+
if (!field || !value) return;
170+
const prev = { ...currentFilters };
171+
const filter = prev?.[field];
172+
if (!filter) {
173+
const nextFilters = {
174+
...prev,
175+
[field]: {
176+
values: [{ value, label }],
177+
type: filterType,
178+
operator: "or" as "or" | "and",
179+
},
180+
};
181+
searchParams.set("filters", stringifySearchFiltersForURL(nextFilters));
182+
setSearchParams(searchParams);
183+
return;
184+
}
185+
const arrayExists = filter?.values?.some((el) => JSON.stringify(el.value) === JSON.stringify(value))
186+
const nextFilterValues = arrayExists
187+
? filter?.values?.filter((el) => JSON.stringify(el.value) !== JSON.stringify(value))
188+
: [...filter.values, { value, label }];
189+
if (!nextFilterValues.length && filter?.operator !== "and") {
190+
return handleDeleteFilter({ field });
191+
}
192+
const nextFilters = {
193+
...prev,
194+
[field]: { ...filter, values: nextFilterValues },
195+
};
196+
197+
searchParams.set("filters", stringifySearchFiltersForURL(nextFilters));
198+
setSearchParams(searchParams);
199+
},
200+
[currentFilters, handleDeleteFilter, searchParams, setSearchParams]
201+
);
202+
167203
const handleFilterChange = useCallback(
168204
({ field, value, filterType = "terms", label = null }) => {
169205
if (!field || !value) return;
@@ -239,6 +275,7 @@ export default function useUrl() {
239275
handleDeleteFilter,
240276
handleRangeFilterChange,
241277
handleBoolFilterChange,
278+
handleArrayFilterChange,
242279
};
243280
}, [
244281
api,
@@ -252,6 +289,7 @@ export default function useUrl() {
252289
handleDeleteFilter,
253290
handleRangeFilterChange,
254291
handleBoolFilterChange,
292+
handleArrayFilterChange,
255293
]);
256294

257295
return values;

client/src/types/organization.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -145,6 +145,7 @@ export type LightOrganization = {
145145
level: string;
146146
nature: string;
147147
id: string;
148+
externalIds?: Array<ExternalIdsData>;
148149
creationYear: string;
149150
isFrench: string;
150151
active: string;

0 commit comments

Comments
 (0)