From f2f33e5d39bbfccb39ce799cd229e6e143d68cc9 Mon Sep 17 00:00:00 2001 From: Matthieu Viry Date: Wed, 2 Oct 2024 15:10:55 +0200 Subject: [PATCH] Improve input of manual breaks in classification panel --- src/components/Modals/ClassificationPanel.tsx | 156 ++++++++++++------ src/i18n/en/index.ts | 2 +- src/i18n/fr/index.ts | 2 +- src/i18n/i18n-types.ts | 8 +- 4 files changed, 111 insertions(+), 57 deletions(-) diff --git a/src/components/Modals/ClassificationPanel.tsx b/src/components/Modals/ClassificationPanel.tsx index d0d41f50..891b682f 100644 --- a/src/components/Modals/ClassificationPanel.tsx +++ b/src/components/Modals/ClassificationPanel.tsx @@ -1,7 +1,7 @@ // Imports from solid-js import { - createSignal, JSX, Match, - onCleanup, onMount, + createSignal, JSX, For, + Match, onCleanup, onMount, Show, Switch, } from 'solid-js'; @@ -12,7 +12,6 @@ import { getSequentialColors, PaletteType, } from 'dicopal'; -import toast from 'solid-toast'; // Helpers import { useI18nContext } from '../../i18n/i18n-solid'; @@ -21,7 +20,6 @@ import { classificationMethodHasOption, getClassifier, OptionsClassification, - parseUserDefinedBreaks, prepareStatisticalSummary, } from '../../helpers/classification'; import { isFiniteNumber } from '../../helpers/common'; @@ -47,6 +45,74 @@ import { type CustomPalette, } from '../../global.d'; +// Component for choosing breaks manually +function ManualBreaks( + props: { + currentBreaksInfo: ClassificationParameters, + setCurrentBreaksInfo: (cp: ClassificationParameters) => void, + precision: number, + }, +): JSX.Element { + const { LL } = useI18nContext(); + return
+ + { + (b, i) => = props.currentBreaksInfo.breaks[i() + 1]) + || (i() > 0 + && value <= props.currentBreaksInfo.breaks[i() - 1]) + ) { + // eslint-disable-next-line no-param-reassign + this.value = round(b, props.precision); + return; + } + const newBreaks = [...props.currentBreaksInfo.breaks]; + newBreaks[i()] = value; + props.setCurrentBreaksInfo({ + ...props.currentBreaksInfo, + breaks: newBreaks, + }); + }} + /> + } + +
; +} + +// Component to display current breaks +// based on currentBreaksInfo +function DisplayBreaks( + props: { + breaks: number[], + precision: number, + }, +): JSX.Element { + return
+

{ + props.breaks + .map((d) => round(d, props.precision)) + .join(' - ') + }

+
; +} + +// The main component export default function ClassificationPanel(): JSX.Element { // Function to recompute the classification given the current options. // We scope it here to facilitate the use of the signals that are defined below... @@ -325,7 +391,7 @@ export default function ClassificationPanel(): JSX.Element { { name: LL().ClassificationPanel.classificationMethods.manual(), value: ClassificationMethod.manual, - options: [OptionsClassification.breaks], + options: [OptionsClassification.breaks, OptionsClassification.numberOfClasses], }, ].filter((d) => d !== null); @@ -461,6 +527,15 @@ export default function ClassificationPanel(): JSX.Element { // eslint-disable-next-line no-param-reassign event.target.value = `${v}`; } + if (classificationMethod() === ClassificationMethod.manual) { + setCustomBreaks( + Array.from({ length: v }) + .map((_, i) => ( + statSummary.minimum + ( + i * (statSummary.maximum - statSummary.minimum)) / v)) + .concat([statSummary.maximum]), + ); + } setNumberOfClasses(v); updateClassificationParameters(); }} @@ -530,54 +605,33 @@ export default function ClassificationPanel(): JSX.Element { - -
-

{ LL().ClassificationPanel.breaksInput() }

- - -
-
+ + + + + +
-

{ - currentBreaksInfo().breaks - .map((d) => round(d, statSummary.precision)) - .join(' - ') - }

diff --git a/src/i18n/en/index.ts b/src/i18n/en/index.ts index be853998..99e1f0ba 100644 --- a/src/i18n/en/index.ts +++ b/src/i18n/en/index.ts @@ -1150,7 +1150,7 @@ const en = { validate: 'Validate', missingValues: '{{ One feature without data | ?? features without data }}', count: 'Features per class', - errorCustomBreaks: 'Error - The class limits entered are invalid. Please enter numerical values separated by dashes to form at least 2 classes.', + breaksCantBeChanged: 'This class boundary cannot be changed because it is automatically calculated.', lowerLimit: 'Lower limit', upperLimit: 'Upper limit', size: 'Size (px)', diff --git a/src/i18n/fr/index.ts b/src/i18n/fr/index.ts index 47405b9c..c12428be 100644 --- a/src/i18n/fr/index.ts +++ b/src/i18n/fr/index.ts @@ -1150,7 +1150,7 @@ const fr = { validate: 'Valider', missingValues: '{{ Une entité sans données | ?? entités sans données }}', count: 'Entités par classe', - errorCustomBreaks: 'Erreur - Les limites de classes saisies ne sont pas valides. Veillez à saisir des valeurs numériques séparées par des tirets et permettant de former au minimum 2 classes.', + breaksCantBeChanged: 'Cette limite de classe ne peut pas être modifiée manuellement.', lowerLimit: 'Limite inférieure', upperLimit: 'Limite supérieure', size: 'Size (px)', diff --git a/src/i18n/i18n-types.ts b/src/i18n/i18n-types.ts index 777d312f..d9ce9675 100644 --- a/src/i18n/i18n-types.ts +++ b/src/i18n/i18n-types.ts @@ -4063,9 +4063,9 @@ type RootTranslation = { */ count: string /** - * E​r​r​o​r​ ​-​ ​T​h​e​ ​c​l​a​s​s​ ​l​i​m​i​t​s​ ​e​n​t​e​r​e​d​ ​a​r​e​ ​i​n​v​a​l​i​d​.​ ​P​l​e​a​s​e​ ​e​n​t​e​r​ ​n​u​m​e​r​i​c​a​l​ ​v​a​l​u​e​s​ ​s​e​p​a​r​a​t​e​d​ ​b​y​ ​d​a​s​h​e​s​ ​t​o​ ​f​o​r​m​ ​a​t​ ​l​e​a​s​t​ ​2​ ​c​l​a​s​s​e​s​. + * T​h​i​s​ ​c​l​a​s​s​ ​b​o​u​n​d​a​r​y​ ​c​a​n​n​o​t​ ​b​e​ ​c​h​a​n​g​e​d​ ​b​e​c​a​u​s​e​ ​i​t​ ​i​s​ ​a​u​t​o​m​a​t​i​c​a​l​l​y​ ​c​a​l​c​u​l​a​t​e​d​. */ - errorCustomBreaks: string + breaksCantBeChanged: string /** * L​o​w​e​r​ ​l​i​m​i​t */ @@ -8389,9 +8389,9 @@ export type TranslationFunctions = { */ count: () => LocalizedString /** - * Error - The class limits entered are invalid. Please enter numerical values separated by dashes to form at least 2 classes. + * This class boundary cannot be changed because it is automatically calculated. */ - errorCustomBreaks: () => LocalizedString + breaksCantBeChanged: () => LocalizedString /** * Lower limit */