Skip to content
This repository has been archived by the owner on Oct 22, 2024. It is now read-only.

Recherche de structures par le nom pour les admins et managers #458

Open
wants to merge 12 commits into
base: main
Choose a base branch
from
Open
4 changes: 4 additions & 0 deletions src/lib/components/forms/fields/select-field.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,9 @@

// Spécifique du select
export let choices: Choice[];
export let searchFunction:
| ((searchText: string) => Promise<Choice[]>)
| undefined = undefined;
export let sort = false;
export let onChange = undefined;
export let placeholderMulti = "Choisir";
Expand Down Expand Up @@ -47,6 +50,7 @@
{id}
{choices}
{sort}
{searchFunction}
bind:value
on:blur={onBlur}
{onChange}
Expand Down
9 changes: 6 additions & 3 deletions src/lib/components/inputs/select/select.svelte
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
<script lang="ts">
import AutoComplete from "./simple-autocomplete.svelte";

type Choice = { value: string | number; label: string };

export let id: string;
export let choices: { value: string | number; label: string }[] | undefined =
undefined;
export let choices: Choice[] | undefined = undefined;
export let fixedItemsValues: string[] = [];
export let sort = false;
export let value: string | number | string[] | number[] | undefined =
Expand All @@ -15,7 +16,9 @@
export let placeholderMulti = "";
export let multiple = false;
export let hideArrow = false;
export let searchFunction = undefined;
export let searchFunction:
| ((searchTxt: string) => Promise<Choice[]>)
| undefined = undefined;
export let delay = undefined;
export let localFiltering = undefined;
export let minCharactersToSearch = undefined;
Expand Down
4 changes: 3 additions & 1 deletion src/lib/components/inputs/select/simple-autocomplete.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,9 @@
export let fixedItemsValues: string[] = [];

// function to use to get all items (alternative to providing items)
export let searchFunction = null;
export let searchFunction:
| ((searchText: string) => Promise<any[]>)
| undefined = undefined;

export let textCleanFunction = function (userEnteredText) {
return userEnteredText;
Expand Down
7 changes: 5 additions & 2 deletions src/lib/requests/structures.ts
Original file line number Diff line number Diff line change
Expand Up @@ -60,8 +60,11 @@ export async function siretWasAlreadyClaimed(siret: string) {
return result;
}

export async function getManagedStructures(): Promise<ShortStructure[]> {
const url = `${getApiURL()}/structures/?managed=1`;
export async function getManagedStructures(
searchText?: string
): Promise<ShortStructure[]> {
const searchParam = searchText ? `&search=${searchText}` : "";
const url = `${getApiURL()}/structures/?managed=1${searchParam}`;
return (await fetchData<ShortStructure[]>(url)).data;
}

Expand Down
22 changes: 22 additions & 0 deletions src/lib/utils/misc.ts
Original file line number Diff line number Diff line change
Expand Up @@ -217,3 +217,25 @@ export function clickOutside(node: HTMLElement) {
},
};
}

// Helper type pour aplatir les promesses
type Awaited<T> = T extends PromiseLike<infer U> ? U : T;

export function debounce<T extends (...args: any[]) => any>(
func: T,
delay = 300
): (...args: Parameters<T>) => Promise<Awaited<ReturnType<T>>> {
let timeoutId: ReturnType<typeof setTimeout>;

return (...args: Parameters<T>) => {
return new Promise<Awaited<ReturnType<T>>>((resolve) => {
if (timeoutId) {
clearTimeout(timeoutId);
} // Réinitialiser le timeout s'il existe déjà
timeoutId = setTimeout(() => {
const result = func(...args);
resolve(result); // Résout avec le résultat, qui peut être une promesse ou une valeur simple
}, delay);
});
};
}
25 changes: 23 additions & 2 deletions src/routes/(modeles-services)/_common/fields-structure.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,20 @@
import FieldSet from "$lib/components/display/fieldset.svelte";
import SelectField from "$lib/components/forms/fields/select-field.svelte";
import { getModel, getServicesOptions } from "$lib/requests/services";
import { getStructure } from "$lib/requests/structures";
import { getManagedStructures, getStructure } from "$lib/requests/structures";
import type {
Choice,
Model,
Service,
ServicesOptions,
ShortStructure,
} from "$lib/types";
import { debounce } from "$lib/utils/misc";
import { onMount } from "svelte";

export let servicesOptions: ServicesOptions;
export let service: Service;
export let managedStructureSearchMode = false;
export let structures: ShortStructure[];
export let structure: ShortStructure | undefined;
export let isModel = false;
Expand Down Expand Up @@ -100,8 +103,20 @@
}
}

async function searchFunction(searchText: string): Promise<Choice[]> {
if (searchText.length < 3) {
return [];
}
return (await getManagedStructures(searchText)).map((struct) => ({
value: struct.slug,
label: struct.name,
}));
}

// Il s'agit d'une édition de service existant
const showStructures = service.structure ? false : structures.length > 1;
const showStructures = service.structure
? false
: structures.length > 1 || managedStructureSearchMode;

onMount(() => {
if (structure && service.structure) {
Expand All @@ -120,7 +135,13 @@
}))}
onChange={handleStructureChange}
sort
searchFunction={managedStructureSearchMode
? debounce(searchFunction)
: undefined}
disabled={!showStructures}
placeholder="Sélectionnez la structure…"
description={managedStructureSearchMode
? "Tapez au moins 3 lettres pour lancer la recherche."
: ""}
/>
</FieldSet>
3 changes: 2 additions & 1 deletion src/routes/(modeles-services)/services/creer/+page.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
<CenteredGrid>
<h1>Création d’un service</h1>

{#if !data.structures.length}
{#if !data.managedStructureSearchMode && !data.structures.length}
<Notice title="Impossible de créer un nouveau service" type="error">
<p class="text-f14">Vous n’êtes rattaché à aucune structure.</p>
</Notice>
Expand All @@ -22,6 +22,7 @@
<ServiceEditionForm
service={data.service}
servicesOptions={data.servicesOptions}
managedStructureSearchMode={data.managedStructureSearchMode}
structures={data.structures}
structure={data.structure}
model={data.model}
Expand Down
9 changes: 6 additions & 3 deletions src/routes/(modeles-services)/services/creer/+page.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { getNewService } from "$lib/utils/forms";
import { getModel, getServicesOptions } from "$lib/requests/services";
import { userInfo } from "$lib/utils/auth";
import { get } from "svelte/store";
import { getStructure, getManagedStructures } from "$lib/requests/structures";
import { getStructure } from "$lib/requests/structures";
import type { PageLoad } from "./$types";
import type { Model, Service, ShortStructure } from "$lib/types";
import { error } from "@sveltejs/kit";
Expand All @@ -22,6 +22,8 @@ export const load: PageLoad = async ({ url, parent }) => {
return {};
}

const managedStructureSearchMode = user.isStaff || user.isManager;

let structures: ShortStructure[] = user.structures;
let service: Service;
let model: Model | undefined = undefined;
Expand Down Expand Up @@ -49,8 +51,8 @@ export const load: PageLoad = async ({ url, parent }) => {
error(404, "Page Not Found");
}
} else {
if (user.isStaff || user.isManager) {
structures = await getManagedStructures();
if (managedStructureSearchMode) {
structures = [];
} else {
structures = user.structures;
}
Expand All @@ -67,6 +69,7 @@ export const load: PageLoad = async ({ url, parent }) => {
noIndex: true,
title: "Création d’un service | DORA",
servicesOptions: await getServicesOptions(),
managedStructureSearchMode,
structures,
structure,
service,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@

export let service: Service;
export let servicesOptions: ServicesOptions;
export let managedStructureSearchMode = false;
export let structures: ShortStructure[];
export let structure: ShortStructure | undefined;
export let model: Model | undefined;
Expand Down Expand Up @@ -165,13 +166,14 @@
</div>
{/if}

{#if structures.length}
{#if managedStructureSearchMode || structures.length}
<div class="lg:w-2/3">
<FieldsStructure
bind:structure
bind:service
bind:servicesOptions
bind:model
{managedStructureSearchMode}
{structures}
/>
</div>
Expand Down
Loading