Skip to content

Commit

Permalink
feat: handle multiple extra fields filters (#575)
Browse files Browse the repository at this point in the history
  • Loading branch information
Volubyl authored Mar 8, 2023
1 parent f610f7b commit 254a597
Show file tree
Hide file tree
Showing 14 changed files with 296 additions and 67 deletions.
4 changes: 2 additions & 2 deletions client/src/definitions/catalogs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ export type Catalog = {
organization: Organization;
extraFields: ExtraField[];
};
export interface ExtraFieldValue {
export type ExtraFieldValue = {
extraFieldId: string;
value: string;
}
};
4 changes: 2 additions & 2 deletions client/src/definitions/datasetFilters.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,11 +24,11 @@ export type DatasetFiltersValue = {
technicalSource: string | null;
tagId: string | null;
license: string | null;
extraFieldValue: ExtraFieldValue | null;
extraFieldValues: ExtraFieldValue[] | null;
};

export type DatasetFiltersOptions = {
[K in keyof Omit<DatasetFiltersValue, "extraFieldValue">]: SelectOption<
[K in keyof Omit<DatasetFiltersValue, "extraFieldValues">]: SelectOption<
DatasetFiltersValue[K]
>[];
};
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
</script>

<div class="fr-form-group">
<legend class="fr-fieldset__legend fr-text--regular" id="radio-legend">
<legend class="fr-text--regular fr-mb-2w">
{label}
</legend>
<div class="fr-fieldset__content">
Expand Down
4 changes: 2 additions & 2 deletions client/src/lib/transformers/datasetFilters.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ describe("transformers -- Dataset filters", () => {
technicalSource: "Serveur GIS",
tagId: null,
license: "Licence Ouverte",
extraFieldValue: null,
extraFieldValues: null,
};

test("toFiltersParams", () => {
Expand All @@ -61,7 +61,7 @@ describe("transformers -- Dataset filters", () => {
["technical_source", "Serveur GIS"],
["tag_id", null],
["license", "Licence Ouverte"],
["extra_field_value", null],
["extra_field_values", null],
];

expect(toFiltersParams(value)).toEqual(params);
Expand Down
44 changes: 30 additions & 14 deletions client/src/lib/transformers/datasetFilters.ts
Original file line number Diff line number Diff line change
Expand Up @@ -77,12 +77,37 @@ export const toFiltersInfo = (data: any): DatasetFiltersInfo => {
};
};

const getExtraFieldValues = (
extraFieldValuesString: string | null
): ExtraFieldValue[] | null => {
if (!extraFieldValuesString) {
return null;
}

return JSON.parse(extraFieldValuesString).map(
transformAPIQueryParamToExtraFieldValue
);
};

const getExtraFieldValuesString = (
extraFieldValues: ExtraFieldValue[] | null
): string | null => {
if (!extraFieldValues) {
return null;
}

return JSON.stringify(
extraFieldValues.map(transformExtraFieldValueToAPIQueryParam)
);
};

export const toFiltersValue = (
searchParams: URLSearchParams
): DatasetFiltersValue => {
const formatId = searchParams.get("format_id");

const extraFieldValue = searchParams.get("extra_field_value");
const extraFieldValuesString = searchParams.get("extra_field_values");

return {
organizationSiret: searchParams.get("organization_siret"),
geographicalCoverage: searchParams.get("geographical_coverage"),
Expand All @@ -91,9 +116,7 @@ export const toFiltersValue = (
technicalSource: searchParams.get("technical_source"),
tagId: searchParams.get("tag_id"),
license: searchParams.get("license"),
extraFieldValue: extraFieldValue
? transformAPIQueryParamToExtraFieldValue(JSON.parse(extraFieldValue))
: null,
extraFieldValues: getExtraFieldValues(extraFieldValuesString),
};
};

Expand All @@ -108,7 +131,7 @@ export const toFiltersParams = (
technicalSource,
tagId,
license,
extraFieldValue,
extraFieldValues,
} = value;

return [
Expand All @@ -119,14 +142,7 @@ export const toFiltersParams = (
["technical_source", technicalSource],
["tag_id", tagId],
["license", license],
[
"extra_field_value",
extraFieldValue
? JSON.stringify(
transformExtraFieldValueToAPIQueryParam(extraFieldValue)
)
: null,
],
["extra_field_values", getExtraFieldValuesString(extraFieldValues)],
];
};

Expand Down Expand Up @@ -165,7 +181,7 @@ export const toFiltersButtonTexts = (
tagIdToName: Record<string, string>,
formatIdToName: Record<string, string>
): {
[K in keyof Omit<DatasetFiltersValue, "extraFieldValue">]: Maybe<string>;
[K in keyof Omit<DatasetFiltersValue, "extraFieldValues">]: Maybe<string>;
} => {
return {
organizationSiret: Maybe.map(
Expand Down
21 changes: 20 additions & 1 deletion client/src/lib/util/array.spec.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { range } from "./array";
import { chunk, range } from "./array";

describe("range", () => {
const startEndCases: [number, number, number[]][] = [
Expand Down Expand Up @@ -29,3 +29,22 @@ describe("range", () => {
expect(range(end)).toStrictEqual(expected);
});
});

describe("chunck", () => {
const cases: [string[], number, string[][] | string[]][] = [
[
["a", "b", "c", "d", "e", "f", "g"],
1,
[["a"], ["b"], ["c"], ["d"], ["e"], ["f"], ["g"]],
],
[
["a", "b", "c", "d", "e", "f", "g"],
3,
[["a", "b", "c"], ["d", "e", "f"], ["g"]],
],
];

test.each(cases)("chunk this array", (data, chunckSize, expected) => {
expect(chunk(data, chunckSize)).toStrictEqual(expected);
});
});
11 changes: 11 additions & 0 deletions client/src/lib/util/array.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,3 +28,14 @@ export const last = <T>(arr: ArrayWithItems<T>): T => {

export const removeEmptyValues = (items: Array<string | null>): Array<string> =>
items.filter((item) => item) as string[];

export const chunk = <T = string>(
arr: T[],
chunkSize = 1,
cache: T[][] = []
): T[][] => {
const tmp: T[] = [...arr];
if (chunkSize <= 0) return cache;
while (tmp.length) cache.push(tmp.splice(0, chunkSize));
return cache;
};
112 changes: 89 additions & 23 deletions client/src/routes/(app)/fiches/search/_FilterPanel.svelte
Original file line number Diff line number Diff line change
@@ -1,19 +1,23 @@
<script lang="ts">
import type { ExtraFieldValue } from "src/definitions/catalogs";
import type { DataFormat } from "src/definitions/dataformat";
import type {
DatasetFiltersInfo,
DatasetFiltersValue,
} from "src/definitions/datasetFilters";
import type { ExtraField } from "src/definitions/extraField";
import type { SelectOption } from "src/definitions/form";
import type { Organization } from "src/definitions/organization";
import type { Tag } from "src/definitions/tag";
import BooleanSearchFilter from "src/lib/components/SearchFilter/BooleanSearchFilter.svelte";
import TextSearchFilter from "src/lib/components/SearchFilter/TextSearchFilter.svelte";
import {
toFiltersButtonTexts,
toFiltersOptions,
} from "src/lib/transformers/datasetFilters";
import { toSelectOption } from "src/lib/transformers/extraField";
import { chunk } from "src/lib/util/array";
import { createEventDispatcher } from "svelte";
export let info: DatasetFiltersInfo;
Expand All @@ -35,6 +39,8 @@
return map;
};
$: extraFieldChunks = chunk<ExtraField>(info.extraFields, 5);
$: organizationSiretToName = createOrganizationSiretToNameMap(
info.organizationSiret
);
Expand All @@ -56,21 +62,69 @@
e: CustomEvent<SelectOption<any> | null>
) => {
if (key === "organizationSiret" && !e.detail?.value) {
value.extraFieldValue = null;
value.extraFieldValues = null;
}
value[key] = e.detail?.value || null;
dispatch("change", value);
};
const removeExistingExtraFieldValue = (
arr: ExtraFieldValue[],
id: string
) => {
return arr.filter((obj) => obj.extraFieldId !== id);
};
const hasAlreadyTheFilter = (
extraFieldValues: ExtraFieldValue[],
id: string
) => {
return extraFieldValues.some((item) => item.extraFieldId === id);
};
const handleExtraFieldValueChange = (name: string, event: Event) => {
const target = event.target as HTMLInputElement;
let newExtraFieldValues: ExtraFieldValue[] = [];
if (value.extraFieldValues) {
if (hasAlreadyTheFilter(value.extraFieldValues, name)) {
const filteredExtraFields = removeExistingExtraFieldValue(
value.extraFieldValues,
name
);
newExtraFieldValues = [
...filteredExtraFields,
{
extraFieldId: name,
value: target.value,
},
];
} else {
newExtraFieldValues = [
...value.extraFieldValues,
{
extraFieldId: name,
value: target.value,
},
];
}
}
if (!value.extraFieldValues) {
newExtraFieldValues = [
{
extraFieldId: name,
value: target.value,
},
];
}
value = {
...value,
extraFieldValue: {
extraFieldId: name,
value: target.value,
},
extraFieldValues: newExtraFieldValues,
};
dispatch("change", value);
Expand All @@ -79,7 +133,7 @@

<div
data-test-id="filter-panel"
class="fr-grid-row fr-grid-row--gutters fr-py-3w filters"
class="fr-grid-row fr-grid-row--gutters fitler_section fr-mt-3w"
>
<section>
<h6>Informations générales</h6>
Expand Down Expand Up @@ -159,26 +213,38 @@
</section>
</div>
{#if info.extraFields.length > 0 && info.extraFields.some((item) => item.type === "BOOL")}
<div class="fr-grid-row fr-grid-row--gutters fr-py-3w filters">
<section>
<h6>Champs complémentaires</h6>

{#each info.extraFields as extraField}
{#if extraField.type === "BOOL"}
<BooleanSearchFilter
name={extraField.name}
options={toSelectOption(extraField)}
label={extraField.title}
on:change={(e) => handleExtraFieldValueChange(extraField.id, e)}
/>
{/if}
{/each}
</section>
</div>
<section
class="fr-py-3w fr-grid-row fr-grid-row--gutters extra_field_filters_section"
>
<h6>Champs complémentaires</h6>

{#each extraFieldChunks as extraFieldChunk}
<div class="fr-grid-row extra_field_filter_chunck">
{#each extraFieldChunk as extraField}
{#if extraField.type === "BOOL"}
<BooleanSearchFilter
name={extraField.name}
options={toSelectOption(extraField)}
label={extraField.title}
on:change={(e) => handleExtraFieldValueChange(extraField.id, e)}
/>
{/if}
{/each}
</div>
{/each}
</section>
{/if}

<style>
.filters {
.extra_field_filters_section {
flex-direction: column;
}
.fitler_section {
justify-content: space-between;
}
.extra_field_filter_chunck {
gap: 80px;
}
</style>
12 changes: 6 additions & 6 deletions server/api/datasets/routes.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import json
import logging
from typing import Optional
from typing import List, Optional

from fastapi import APIRouter, Depends
from fastapi.exceptions import HTTPException
Expand Down Expand Up @@ -53,11 +53,11 @@ async def list_datasets(

page = Page(number=params.page_number, size=params.page_size)

extra_field_value: Optional[ExtraFieldValue] = None
extra_field_values: Optional[List[ExtraFieldValue]] = None

if params.extra_field_value is not None:
item = json.loads(params.extra_field_value)
extra_field_value = ExtraFieldValue(**item)
if params.extra_field_values is not None:
items = json.loads(params.extra_field_values)
extra_field_values = [ExtraFieldValue(**item) for item in items]

query = GetAllDatasets(
page=page,
Expand All @@ -70,7 +70,7 @@ async def list_datasets(
technical_source__in=params.technical_source,
tag__id__in=params.tag_id,
license=params.license,
extra_field_value=extra_field_value,
extra_field_values=extra_field_values,
),
account=request.user.account,
)
Expand Down
Loading

0 comments on commit 254a597

Please sign in to comment.