From 811617ad3441cdcf40ec814969c21a1a2daf0b9e Mon Sep 17 00:00:00 2001
From: Emmanuel Raviart <emmanuel@raviart.com>
Date: Mon, 2 Dec 2024 17:33:27 +0100
Subject: [PATCH] =?UTF-8?q?Permet=20=C3=A0=20une=20valeur=20=C3=A9dit?=
 =?UTF-8?q?=C3=A9e=20d'=C3=AAtre=20imm=C3=A9diatement=20prise=20en=20compt?=
 =?UTF-8?q?e=20dans=20les=20simulations=20de=20cas=20types?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 src/lib/components/WaterfallView.svelte       | 16 +------
 .../test_cases/TestCaseCompareView.svelte     |  5 ---
 .../components/test_cases/TestCaseEdit.svelte | 14 +-----
 .../test_cases/TestCaseGraph.svelte           | 18 +++-----
 .../test_cases/TestCaseSummary.svelte         | 27 ++++++------
 .../components/test_cases/TestCaseView.svelte |  2 -
 .../components/variables/VariableInput.svelte | 10 ++---
 .../variables/VariableReferredInputs.svelte   | 11 ++---
 .../VariableReferredInputsPane.svelte         | 13 +-----
 src/lib/situations.ts                         | 43 ++++++-------------
 src/routes/+page.svelte                       | 23 +---------
 src/routes/auth/login/+server.ts              |  6 +--
 src/routes/auth/login_callback/+server.ts     |  9 ++--
 src/routes/auth/logout/+server.ts             |  8 ++--
 src/routes/auth/logout_callback/+server.ts    |  8 ++--
 15 files changed, 63 insertions(+), 150 deletions(-)

diff --git a/src/lib/components/WaterfallView.svelte b/src/lib/components/WaterfallView.svelte
index dddff6387..1f91bf5d5 100644
--- a/src/lib/components/WaterfallView.svelte
+++ b/src/lib/components/WaterfallView.svelte
@@ -1,6 +1,5 @@
 <script lang="ts">
   import type { VariableByName } from "@openfisca/json-model"
-  import { createEventDispatcher } from "svelte"
 
   import { goto } from "$app/navigation"
   import TestCaseGraph from "$lib/components/test_cases/TestCaseGraph.svelte"
@@ -66,7 +65,6 @@
       signDisplay: "never",
       style: "currency",
     }).format(removeNegativeZero(value))
-  const dispatch = createEventDispatcher()
   const firstDeltaFormatter = (value: number): string =>
     new Intl.NumberFormat("fr-FR", {
       currency: "EUR",
@@ -190,8 +188,6 @@
   function removeSituationSlider() {
     situation = { ...situation }
     delete situation.slider
-
-    dispatch("changeSituation", situation)
   }
 
   function requestAxesCalculation() {
@@ -235,7 +231,7 @@
     )
 
     // Update situation
-    let updatedSituation = setSituationVariableValue(
+    setSituationVariableValue(
       entityByKey,
       situation,
       variable,
@@ -243,20 +239,13 @@
       year,
       Math.round(updatedStepValue * vectorIndex),
     )
-    if (updatedSituation === situation) {
-      // This can occur, when slider was deselected, then reselected.
-      updatedSituation = { ...situation }
-    }
-    updatedSituation.slider = {
+    situation.slider = {
       ...slider,
       min: updatedMin,
       max: updatedMax,
       stepValue: updatedStepValue,
       vectorIndex: vectorIndex,
     }
-    situation = updatedSituation
-
-    dispatch("changeSituation", situation)
   }
 
   function zoomIn(index: number) {
@@ -751,7 +740,6 @@
         {displayMode}
         {evaluationByName}
         evaluationByNameArray={shared.evaluationByNameArray}
-        on:changeSituation
         {situation}
         {situationIndex}
         {useRevaluationInsteadOfLaw}
diff --git a/src/lib/components/test_cases/TestCaseCompareView.svelte b/src/lib/components/test_cases/TestCaseCompareView.svelte
index 4027424ad..daa5b5186 100644
--- a/src/lib/components/test_cases/TestCaseCompareView.svelte
+++ b/src/lib/components/test_cases/TestCaseCompareView.svelte
@@ -85,11 +85,6 @@
         <div class="w-1/2 border-t border-gray-300 px-2 pb-2">
           <TestCaseSummary
             on:changeTestCaseToEditIndex
-            on:changeSituation={({ detail }) =>
-              dispatch("changeSituation", {
-                situationIndex,
-                situation: detail,
-              })}
             {displayMode}
             mode="compare"
             {situation}
diff --git a/src/lib/components/test_cases/TestCaseEdit.svelte b/src/lib/components/test_cases/TestCaseEdit.svelte
index 22ce81030..164b5965d 100644
--- a/src/lib/components/test_cases/TestCaseEdit.svelte
+++ b/src/lib/components/test_cases/TestCaseEdit.svelte
@@ -449,14 +449,6 @@
     dispatch("changeInputInstantsByVariableName", inputInstantsByVariableName)
   }
 
-  function updateSituation(situation: Situation): void {
-    if (situation === currentSituation) {
-      return
-    }
-    currentSituation = situation
-    dispatch("changeSituation", situation)
-  }
-
   function updateVariablesName(situation: Situation) {
     const newVariablesName = [
       ...iterSituationVariablesName(entityByKey, situation),
@@ -503,9 +495,6 @@
   run(() => {
     updateInputInstantsByVariableName(inputInstantsByVariableName)
   })
-  run(() => {
-    updateSituation(situation)
-  })
   run(() => {
     updateVariablesName(situation)
   })
@@ -966,7 +955,7 @@
             <VariableInput
               {date}
               bind:inputInstantsByVariableName
-              bind:situation
+              {situation}
               {situationIndex}
               bind:valuesByCalculationNameByVariableName
               variable={variableSummaryByName[variableName]}
@@ -1010,7 +999,6 @@
         {inputInstantsByVariableName}
         name={variableName}
         on:changeInputInstantsByVariableName
-        on:changeSituation
         {situation}
         {situationIndex}
         {valuesByCalculationNameByVariableName}
diff --git a/src/lib/components/test_cases/TestCaseGraph.svelte b/src/lib/components/test_cases/TestCaseGraph.svelte
index 17b5e397c..c28d94c51 100644
--- a/src/lib/components/test_cases/TestCaseGraph.svelte
+++ b/src/lib/components/test_cases/TestCaseGraph.svelte
@@ -9,7 +9,7 @@
     type RateBracketAtInstant,
     scaleByInstantFromBrackets,
   } from "@openfisca/json-model"
-  import { createEventDispatcher, untrack } from "svelte"
+  import { untrack } from "svelte"
   import { fade } from "svelte/transition"
 
   import type { CalculationName } from "$lib/calculations.svelte"
@@ -97,7 +97,6 @@
     year,
   }: Props = $props()
 
-  const dispatch = createEventDispatcher()
   const familyEntity = entityByKey[familyEntityKey]
   const formatCurrency = valueFormatter(0, "currency-EUR", false)
   const formatLongOrdinalSup = (n: number) => {
@@ -406,7 +405,7 @@
     )
 
     // Update situation
-    let updatedSituation = setSituationVariableValue(
+    setSituationVariableValue(
       entityByKey,
       situation,
       variable,
@@ -414,11 +413,7 @@
       year,
       Math.round(updatedStepValue * vectorIndex),
     )
-    if (updatedSituation === situation) {
-      // This can occur, when slider was deselected, then reselected.
-      updatedSituation = { ...situation }
-    }
-    updatedSituation.slider = {
+    situation.slider = {
       ...slider,
       min: updatedMin,
       max: updatedMax,
@@ -426,14 +421,11 @@
       vectorIndex: vectorIndex,
     }
     if (domain.y?.min !== undefined) {
-      updatedSituation.slider.yMin = domain.y?.min
+      situation.slider.yMin = domain.y?.min
     }
     if (domain.y?.max !== undefined) {
-      updatedSituation.slider.yMax = domain.y?.max
+      situation.slider.yMax = domain.y?.max
     }
-    situation = updatedSituation
-
-    dispatch("changeSituation", situation)
   }
 
   function stackValues(...groups: VariableGraph[][]) {
diff --git a/src/lib/components/test_cases/TestCaseSummary.svelte b/src/lib/components/test_cases/TestCaseSummary.svelte
index e82273390..575cedc53 100644
--- a/src/lib/components/test_cases/TestCaseSummary.svelte
+++ b/src/lib/components/test_cases/TestCaseSummary.svelte
@@ -147,7 +147,7 @@
       return
     }
     const variable = variableSummaryByName[slider.name]
-    const updatedSituation = setSituationVariableValue(
+    setSituationVariableValue(
       entityByKey,
       situation,
       variable,
@@ -155,12 +155,10 @@
       year,
       Math.round(slider.stepValue * vectorIndex),
     )
-    updatedSituation.slider = {
+    situation.slider = {
       ...slider,
       vectorIndex,
     }
-    situation = updatedSituation
-    dispatch("changeSituation", situation)
   }
 
   function generateActivityLabel(
@@ -284,8 +282,14 @@
   }
 
   function resetSituation() {
-    situation = structuredClone(testCasesCore[situationIndex])
-    dispatch("changeSituation", situation)
+    // Modify situation in place.
+    for (const key in situation) {
+      delete situation[key]
+    }
+    const originalSituation = testCasesCore[situationIndex]
+    for (const key in originalSituation) {
+      situation[key] = structuredClone(originalSituation[key])
+    }
   }
 
   function toggleSlider(variable: Variable) {
@@ -309,7 +313,7 @@
         0,
         Math.min(100, Math.round(value / stepValue)),
       )
-      let updatedSituation = setSituationVariableValue(
+      setSituationVariableValue(
         entityByKey,
         situation,
         variable,
@@ -317,21 +321,14 @@
         year,
         Math.round(stepValue * vectorIndex),
       )
-      if (updatedSituation === situation) {
-        // This can occur, when slider was deselected, then reselected.
-        updatedSituation = { ...situation }
-      }
-      updatedSituation.slider = {
+      situation.slider = {
         ...slider,
         stepValue,
         vectorIndex,
       }
-      situation = updatedSituation
     } else {
-      situation = { ...situation }
       delete situation.slider
     }
-    dispatch("changeSituation", situation)
   }
 </script>
 
diff --git a/src/lib/components/test_cases/TestCaseView.svelte b/src/lib/components/test_cases/TestCaseView.svelte
index 429e05010..68a1a6fe1 100644
--- a/src/lib/components/test_cases/TestCaseView.svelte
+++ b/src/lib/components/test_cases/TestCaseView.svelte
@@ -65,7 +65,6 @@
         <TestCaseSummary
           on:changeTestCasesIndex
           on:changeTestCaseToEditIndex
-          on:changeSituation
           {displayMode}
           mode="view"
           {situation}
@@ -364,7 +363,6 @@
               {displayMode}
               {evaluationByName}
               {highlightDecomposition}
-              on:changeSituation
               {situation}
               {situationIndex}
               variableSummaryByName={completeVariableSummaryByName}
diff --git a/src/lib/components/variables/VariableInput.svelte b/src/lib/components/variables/VariableInput.svelte
index 7e88820ba..70a32d614 100644
--- a/src/lib/components/variables/VariableInput.svelte
+++ b/src/lib/components/variables/VariableInput.svelte
@@ -2,10 +2,7 @@
   import { auditDateIso8601String, laxAudit } from "@auditors/core"
   import type { Variable } from "@openfisca/json-model"
   import { getVariableLatestFormulaDate } from "@openfisca/json-model"
-  import { getContext } from "svelte"
-  import type { Writable } from "svelte/store"
 
-  import { page } from "$app/stores"
   import { requestAllTestCasesCalculations } from "$lib/calculations.svelte"
   import Autocomplete from "$lib/components/Autocomplete.svelte"
   import Tooltip from "$lib/components/Tooltip.svelte"
@@ -42,7 +39,7 @@
     date,
     highlight = undefined,
     inputInstantsByVariableName = $bindable(),
-    situation = $bindable(),
+    situation,
     situationIndex,
     valuesByCalculationNameByVariableName = $bindable(),
     variable,
@@ -169,7 +166,7 @@
   function changeCommune({ detail }: CustomEvent, populationId: string) {
     const { commune } = detail
     const { COM: value } = commune
-    const updatedSituation = setSituationVariableValue(
+    const situationChanged = setSituationVariableValue(
       entityByKey,
       situation,
       variable,
@@ -189,8 +186,7 @@
       }
     }
 
-    if (updatedSituation !== situation) {
-      situation = updatedSituation
+    if (situationChanged) {
       requestAllTestCasesCalculations(situationIndex)
     }
   }
diff --git a/src/lib/components/variables/VariableReferredInputs.svelte b/src/lib/components/variables/VariableReferredInputs.svelte
index 59e6afabb..17e9855c6 100644
--- a/src/lib/components/variables/VariableReferredInputs.svelte
+++ b/src/lib/components/variables/VariableReferredInputs.svelte
@@ -45,21 +45,22 @@
     inputs.filter((input) => directVariablesName.has(input.name)),
   )
 
-  let openAllInputs
-  run(() => {
-    openAllInputs = directInputs.length === 0
-  })
+  let openAllInputs = $state(false)
 
   let allInputsSearchTerms = $derived(parseSearch(allInputsQuery))
 
   let directInputsSearchTerms = $derived(parseSearch(directInputsQuery))
 
+  $effect(() => {
+    openAllInputs = directInputs.length === 0
+  })
+
   function filter(inputs: Variable[], terms: string[] | undefined) {
     if (terms !== undefined && terms.length > 0) {
       return inputs.filter((input) =>
         terms.every(
           (term) =>
-            new RegExp(term, "gi").test(input.label) ||
+            new RegExp(term, "gi").test(input.label ?? "") ||
             new RegExp(term, "gi").test(input.name),
         ),
       )
diff --git a/src/lib/components/variables/VariableReferredInputsPane.svelte b/src/lib/components/variables/VariableReferredInputsPane.svelte
index 0089edac8..050db874a 100644
--- a/src/lib/components/variables/VariableReferredInputsPane.svelte
+++ b/src/lib/components/variables/VariableReferredInputsPane.svelte
@@ -32,14 +32,13 @@
     date,
     inputInstantsByVariableName = $bindable(),
     name,
-    situation = $bindable(),
+    situation,
     situationIndex,
     valuesByCalculationNameByVariableName = $bindable(),
     year,
   }: Props = $props()
 
   let currentInputInstantsByVariableName = inputInstantsByVariableName
-  let currentSituation = situation
   const dispatch = createEventDispatcher()
 
   function getVariableReferredInputs(name: string, date: string): Variable[] {
@@ -65,13 +64,6 @@
     dispatch("changeInputInstantsByVariableName", inputInstantsByVariableName)
   }
 
-  function updateSituation(situation: Situation): void {
-    if (situation === currentSituation) {
-      return
-    }
-    currentSituation = situation
-    dispatch("changeSituation", situation)
-  }
   let variable = $derived(variableSummaryByName[name])
   $effect(() => {
     if (variable === undefined) {
@@ -82,9 +74,6 @@
   $effect(() => {
     updateInputInstantsByVariableName(inputInstantsByVariableName)
   })
-  $effect(() => {
-    updateSituation(situation)
-  })
 </script>
 
 {#if variable !== undefined}
diff --git a/src/lib/situations.ts b/src/lib/situations.ts
index edba7bb4c..de6fb3218 100644
--- a/src/lib/situations.ts
+++ b/src/lib/situations.ts
@@ -286,42 +286,27 @@ export function setSituationVariableValue(
   populationId: string,
   year: number,
   value: VariableValue,
-): Situation {
+): boolean {
   if (value == null) {
     value = variable.default_value
   }
   const entity = entityByKey[variable.entity]
-  const entitySituation = situation[entity.key_plural]
-  const existingValueByPeriod = entitySituation?.[populationId]?.[variable.name]
+  const entitySituation = (situation[entity.key_plural!] ??= {})
+  const populationSituation = (entitySituation[populationId] ??= {})
+  const valueByPeriod = (populationSituation[variable.name] ??= {}) as {
+    [date: string]: VariableValue | null
+  }
   if (
-    existingValueByPeriod !== undefined &&
-    existingValueByPeriod[year - 2] === value &&
-    existingValueByPeriod[year - 1] === value &&
-    existingValueByPeriod[year] === value
+    valueByPeriod[year - 2] === value &&
+    valueByPeriod[year - 1] === value &&
+    valueByPeriod[year] === value
   ) {
-    return situation
-  }
-  return {
-    ...situation,
-    [entity.key_plural]: {
-      ...(entitySituation ?? {}),
-      [populationId]: {
-        ...(entitySituation?.[populationId] ?? {}),
-        [variable.name]: {
-          ...((
-            entitySituation?.[populationId] as {
-              [key: string]: {
-                [date: string]: VariableValue | null
-              }
-            }
-          )?.[variable.name] ?? {}),
-          [year - 2]: value,
-          [year - 1]: value,
-          [year]: value,
-        },
-      },
-    },
+    return false
   }
+  valueByPeriod[year - 2] = value
+  valueByPeriod[year - 1] = value
+  valueByPeriod[year] = value
+  return true
 }
 
 // export function updateTestCasesVariableValues(
diff --git a/src/routes/+page.svelte b/src/routes/+page.svelte
index 30eaf8c4f..f4a33b809 100644
--- a/src/routes/+page.svelte
+++ b/src/routes/+page.svelte
@@ -439,18 +439,6 @@
   //   )
   // }
 
-  function changeCompareSituation({
-    detail,
-  }: {
-    detail: {
-      situationIndex: number
-      situation: Situation
-    }
-  }): void {
-    const { situationIndex, situation } = detail
-    changeSituation(situationIndex, situation)
-  }
-
   function changeInputInstantsByVariableName(
     situationIndex: number,
     inputInstantsByVariableName: {
@@ -466,10 +454,6 @@
       newInputInstantsByVariableNameArray
   }
 
-  function changeSituation(situationIndex: number, situation: Situation): void {
-    shared.testCases[situationIndex] = situation
-  }
-
   function changeTestCasesIndex(testCasesIndex: number[]): void {
     goto(
       newSimulationUrl({
@@ -1013,7 +997,7 @@
                         <div class="mt-7">
                           {#if displayMode.testCasesIndex.length === 0}
                             <WaterfallPlainView
-                              compact={true}
+                              compact
                               on:click={({ detail }) =>
                                 goto(
                                   newSimulationUrl({
@@ -1461,8 +1445,6 @@
                       <TestCaseView
                         {displayMode}
                         {highlightDecomposition}
-                        on:changeSituation={({ detail }) =>
-                          changeSituation(shared.testCasesIndex[0], detail)}
                         on:changeTestCasesIndex={({ detail }) =>
                           changeTestCasesIndex(detail)}
                         on:changeTestCaseToEditIndex={({ detail }) => {
@@ -1481,7 +1463,6 @@
                     {:else}
                       <TestCaseCompareView
                         {displayMode}
-                        on:changeSituation={changeCompareSituation}
                         on:changeTestCasesIndex={({ detail }) =>
                           changeTestCasesIndex(detail)}
                         on:changeTestCaseToEditIndex={({ detail }) => {
@@ -1913,8 +1894,6 @@
           ] ?? {}}
           on:changeInputInstantsByVariableName={({ detail }) =>
             changeInputInstantsByVariableName(displayMode.edit, detail)}
-          on:changeSituation={({ detail }) =>
-            changeSituation(displayMode.edit, detail)}
           situation={shared.testCases[displayMode.edit] ?? {}}
           situationIndex={displayMode.edit}
           valuesByCalculationNameByVariableName={shared
diff --git a/src/routes/auth/login/+server.ts b/src/routes/auth/login/+server.ts
index 1e70ff5c8..7d3725546 100644
--- a/src/routes/auth/login/+server.ts
+++ b/src/routes/auth/login/+server.ts
@@ -7,12 +7,12 @@ import {
   randomState,
 } from "openid-client"
 
-import type { RequestHandler } from "./$types"
-
 import publicConfig from "$lib/public_config"
 import { validateLoginLogoutQuery } from "$lib/server/auditors/queries"
 import serverConfig from "$lib/server/server_config"
 
+import type { RequestHandler } from "./$types"
+
 const { baseUrl } = publicConfig
 
 export const GET: RequestHandler = async ({ cookies, locals, url }) => {
@@ -80,7 +80,7 @@ export const GET: RequestHandler = async ({ cookies, locals, url }) => {
         secure: true,
       },
     )
-    return new Response(undefined, {
+    return new Response(`Redirecting to ${authorizationUrl}…`, {
       status: 302,
       headers: { location: authorizationUrl.toString() },
     })
diff --git a/src/routes/auth/login_callback/+server.ts b/src/routes/auth/login_callback/+server.ts
index d360b89f5..51815eccd 100644
--- a/src/routes/auth/login_callback/+server.ts
+++ b/src/routes/auth/login_callback/+server.ts
@@ -1,4 +1,4 @@
-import { error, type RequestHandler } from "@sveltejs/kit"
+import { error } from "@sveltejs/kit"
 import jwt from "jsonwebtoken"
 import { authorizationCodeGrant } from "openid-client"
 
@@ -6,6 +6,8 @@ import publicConfig from "$lib/public_config"
 import serverConfig from "$lib/server/server_config"
 import type { SigninPayload } from "$lib/users"
 
+import type { RequestHandler } from "./$types"
+
 export const GET: RequestHandler = async ({
   cookies,
   locals,
@@ -73,10 +75,11 @@ export const GET: RequestHandler = async ({
     },
   )
 
-  return new Response(undefined, {
+  const redirectUrl = new URL(`/auth/restore_state`, publicConfig.baseUrl).toString()
+  return new Response(`Redirecting to ${redirectUrl}…`, {
     status: 302,
     headers: {
-      location: new URL(`/auth/restore_state`, publicConfig.baseUrl).toString(),
+      location: redirectUrl,
     },
   })
 }
diff --git a/src/routes/auth/logout/+server.ts b/src/routes/auth/logout/+server.ts
index 23dea3250..02af94550 100644
--- a/src/routes/auth/logout/+server.ts
+++ b/src/routes/auth/logout/+server.ts
@@ -1,11 +1,11 @@
 import { error } from "@sveltejs/kit"
 import { buildEndSessionUrl } from "openid-client"
 
-import type { RequestHandler } from "./$types"
-
 import { validateLoginLogoutQuery } from "$lib/server/auditors/queries"
 import publicConfig from "$lib/public_config"
 
+import type { RequestHandler } from "./$types"
+
 const { baseUrl } = publicConfig
 
 export const GET: RequestHandler = ({ cookies, locals, url }) => {
@@ -38,7 +38,7 @@ export const GET: RequestHandler = ({ cookies, locals, url }) => {
   delete locals.user
 
   if (idToken === undefined) {
-    return new Response(undefined, {
+    return new Response(`Redirecting to ${baseUrl}…`, {
       status: 302,
       headers: { location: baseUrl },
     })
@@ -53,7 +53,7 @@ export const GET: RequestHandler = ({ cookies, locals, url }) => {
         baseUrl,
       ).toString(),
     })
-    return new Response(undefined, {
+    return new Response(`Redirecting to ${endSessionUrl}…`, {
       status: 302,
       headers: { location: endSessionUrl.toString() },
     })
diff --git a/src/routes/auth/logout_callback/+server.ts b/src/routes/auth/logout_callback/+server.ts
index f8f353532..36ebf779e 100644
--- a/src/routes/auth/logout_callback/+server.ts
+++ b/src/routes/auth/logout_callback/+server.ts
@@ -1,12 +1,14 @@
-import type { RequestHandler } from "@sveltejs/kit"
+import type { RequestHandler } from "./$types"
+
 
 import publicConfig from "$lib/public_config"
 
 export const GET: RequestHandler = async () => {
-  return new Response(undefined, {
+  const redirectUrl = new URL(`/auth/restore_state`, publicConfig.baseUrl).toString()
+  return new Response(`Redirecting to ${redirectUrl}…`, {
     status: 302,
     headers: {
-      location: new URL(`/auth/restore_state`, publicConfig.baseUrl).toString(),
+      location: redirectUrl,
     },
   })
 }
-- 
GitLab