From cf18931f24dc418fd54aeff1f97e267da62c17d5 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Fran=C3=A7ois=20Grand?= <francois.grand@inrae.fr>
Date: Mon, 3 Apr 2023 14:37:23 +0200
Subject: [PATCH 1/3] refactor: PAB table: rename first column

refs #615
---
 src/locale/messages.en.json | 2 +-
 src/locale/messages.fr.json | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/src/locale/messages.en.json b/src/locale/messages.en.json
index b7b836bd0..b31fc6330 100755
--- a/src/locale/messages.en.json
+++ b/src/locale/messages.en.json
@@ -470,7 +470,7 @@
     "INFO_PAB_OUVRAGES": "Devices",
     "INFO_PAB_EDIT_VALUES": "Modify values",
     "INFO_CALCULATE_FIRST": "Calculate this module first",
-    "INFO_PAB_NUM_BASSIN": "Basin #",
+    "INFO_PAB_NUM_BASSIN": "Basin/wall #",
     "INFO_PAB_HEADER_TYPE": "Type",
     "INFO_PAB_HEADER_PARAMETERS": "Parameters",
     "INFO_PAB_HEADER_VALUES": "Values",
diff --git a/src/locale/messages.fr.json b/src/locale/messages.fr.json
index 1b2892173..21aca059b 100755
--- a/src/locale/messages.fr.json
+++ b/src/locale/messages.fr.json
@@ -471,7 +471,7 @@
     "INFO_PAB_OUVRAGES": "Ouvrages",
     "INFO_PAB_EDIT_VALUES": "Modifier les valeurs",
     "INFO_CALCULATE_FIRST": "Calculer ce module d'abord",
-    "INFO_PAB_NUM_BASSIN": "N° de bassin",
+    "INFO_PAB_NUM_BASSIN": "N° de bassin/cloison",
     "INFO_PAB_HEADER_TYPE": "Type",
     "INFO_PAB_HEADER_PARAMETERS": "Paramètres",
     "INFO_PAB_HEADER_VALUES": "Valeurs",
-- 
GitLab


From 0be34bb23fc3fca1ea14bc22e033522be87f9d8e Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Fran=C3=A7ois=20Grand?= <francois.grand@inrae.fr>
Date: Tue, 4 Apr 2023 10:53:44 +0200
Subject: [PATCH 2/3] refactor: PAB table: reshape cells, move ZRAM parameter
 out of basin columns

refs #615
---
 .../pab-table/pab-table.component.ts          | 142 ++++++++++--------
 1 file changed, 82 insertions(+), 60 deletions(-)

diff --git a/src/app/components/pab-table/pab-table.component.ts b/src/app/components/pab-table/pab-table.component.ts
index a3919284b..c835b87b4 100644
--- a/src/app/components/pab-table/pab-table.component.ts
+++ b/src/app/components/pab-table/pab-table.component.ts
@@ -464,14 +464,24 @@ export class PabTableComponent implements AfterViewInit, AfterViewChecked, OnIni
 
         // 0. build spanned headers over real columns
         this.headers = [];
-        // 1 header for basin
+        // 1 column for basin number
         let bs: any[] = this.model.children;
         bs = bs.concat(this.model.downWall);
+        this.headers.push({
+            title: this.i18nService.localizeText("INFO_PAB_NUM_BASSIN"),
+            selectable: bs,
+            rowspan: 2
+        });
+        // 3 columns for basin information
         this.headers.push({
             title: this.i18nService.localizeText("INFO_PAB_BASSIN"),
-            colspan: 5,
+            colspan: 3,
             selectable: bs
         });
+        // 1 col for wall
+        this.headers.push({
+            title: this.i18nService.localizeText("INFO_PB_CLOISON"),
+        });
         // 1 header for each device of the wall having the most devices (including downwall)
         for (let i = 0; i < maxNbDevices; i++) {
             this.headers.push({
@@ -489,48 +499,35 @@ export class PabTableComponent implements AfterViewInit, AfterViewChecked, OnIni
         this.cols.push(headerRow1);
         this.cols.push(headerRow2);
 
-        // 5 cols for basin
-        headerRow1.cells.push({
-            title: this.i18nService.localizeText("INFO_PAB_NUM_BASSIN"),
-            selectable: bs,
-            rowspan: 2
-        });
+        // 3 cols for basin information
         headerRow1.cells.push({
             title: this.formService.expandVariableNameAndUnit(CalculatorType.Pab, "LB"),
-            selectable: bs,
-            rowspan: 2
+            selectable: bs
         });
         headerRow1.cells.push({
             title: this.formService.expandVariableNameAndUnit(CalculatorType.Pab, "BB"),
-            selectable: bs,
-            rowspan: 2
+            selectable: bs
         });
         headerRow1.cells.push({
             title: this.formService.expandVariableNameAndUnit(CalculatorType.Pab, "ZRMB"),
-            selectable: bs,
-            rowspan: 2
-        });
-        headerRow1.cells.push({
-            title: this.formService.expandVariableNameAndUnit(CalculatorType.Pab, "ZRAM"),
-            selectable: bs,
-            rowspan: 2
+            selectable: bs
         });
-        // no col for wall type (defined by rowspan-2 header above)
-        // 3 cols for each device of the wall having the most devices (including downwall)
+
+        // 2 cols for each device of the wall having the most devices (including downwall)
         for (let i = 0; i < maxNbDevices; i++) {
             const sel = this.model.children.map(c => c.getChildren()[i]).concat(this.model.downWall.getChildren()[i]);
+            if (i == 0) {
+                headerRow1.cells.push({
+                    title: this.formService.expandVariableNameAndUnit(CalculatorType.Pab, "ZRAM"),
+                    selectable: bs,
+                });
+            }
             headerRow1.cells.push({
-                title: this.i18nService.localizeText("INFO_PAB_HEADER_TYPE"),
-                selectable: sel,
-                selectableColumn: i,
-                colspan: 2
-            });
-            headerRow2.cells.push({
                 title: this.i18nService.localizeText("INFO_PAB_HEADER_PARAMETERS"),
                 selectable: sel,
                 selectableColumn: i
             });
-            headerRow2.cells.push({
+            headerRow1.cells.push({
                 title: this.i18nService.localizeText("INFO_PAB_HEADER_VALUES"),
                 selectable: sel,
                 selectableColumn: i
@@ -546,23 +543,50 @@ export class PabTableComponent implements AfterViewInit, AfterViewChecked, OnIni
                 value: l
             };
         });
+
+        // NOTE : EB = empty cell (3 columns wide) for LB,BB,ZRMB
+        //        EZRAM = empty cell below ZRAM value (QA editor height + 1)
+
+        const minQAEditorRowCount: number = 1;
+
         // B.1 many rows for each wall
         let childIndex = 0;
         for (const cloison of this.model.children) {
-            // as much rows as the greatest number of parameters among its devices
-            const maxNbParams = this.findMaxNumberOfDeviceParameters(cloison);
-            for (let r = 0; r <= maxNbParams; r++) {
-                // build device params row
+            // maximum device parameter count for all devices in this wall
+            const maxDeviceParamCount = this.findMaxNumberOfDeviceParameters(cloison);
+
+            // total row count for this wall = max device parameter row count + 1 line for device type
+            // minimum = 1 row (EB) + 1 row (LB,BB,ZRMB cells) + QA editor
+            const totalRowCount = Math.max(maxDeviceParamCount + 1, 1 + 1 + minQAEditorRowCount);
+
+            // QA editor row count : total row count - 1 (LB,BB,ZRMB cells) - 1 (EB, see note)
+            const QAEditorRowCount = Math.max(totalRowCount - 2, minQAEditorRowCount);
+
+            // total parameter rows (all parameters without device type) = total row count - 1
+            const paramRowCount = totalRowCount - 1;
+
+            for (let r = 0; r < totalRowCount; r++) {
                 const deviceParamRow = { selectable: cloison, cells: [] };
-                // basin number, LB, BB, ZRMB and ZRAM
                 if (r === 0) {
                     // basin number
                     deviceParamRow.cells.push({
                         value: childIndex + 1,
-                        rowspan: maxNbParams + 1,
+                        rowspan: totalRowCount,
                         class: "basin_number",
                         selectable: cloison
                     });
+                    // empty line (EB cell, see note)
+                    deviceParamRow.cells.push({
+                        colspan: 3
+                    });
+                    // ZRAM
+                    deviceParamRow.cells.push({
+                        model: cloison.prms.ZRAM,
+                        title: this.formService.expandVariableNameAndUnit(CalculatorType.Pab, "ZRAM")
+                    });
+                }
+                // LB, BB, ZRMB, EZRAM cell (see note)
+                else if (r === 1) {
                     // Longueur bassin
                     deviceParamRow.cells.push({
                         model: cloison.prms.LB,
@@ -578,27 +602,26 @@ export class PabTableComponent implements AfterViewInit, AfterViewChecked, OnIni
                         model: cloison.prms.ZRMB,
                         title: this.formService.expandVariableNameAndUnit(CalculatorType.Pab, "ZRMB")
                     });
-                    // ZRAM
+                    // empty cell (EZRAM cell, see note)
                     deviceParamRow.cells.push({
-                        model: cloison.prms.ZRAM,
-                        title: this.formService.expandVariableNameAndUnit(CalculatorType.Pab, "ZRAM")
+                        rowspan: paramRowCount
                     });
                 }
-                else if (r === 1) {
-                    // 1 row for QA editor
+                else if (r === 2) {
+                    // rows for QA editor
                     const qaParam = new NgParameter(cloison.prms.QA, this.pabTable.form);
                     qaParam.radioConfig = ParamRadioConfig.VAR;
                     deviceParamRow.cells.push({
                         model: qaParam,
-                        colspan: 4,
-                        rowspan: maxNbParams,
+                        colspan: 3,
+                        rowspan: QAEditorRowCount,
                         qa: true,
                         title: this.formService.expandVariableNameAndUnit(CalculatorType.Pab, "QA")
                     });
                 }
 
                 // devices
-                this.fillParallelStructureCells(deviceParamRow, r, maxNbParams, loisCloisons);
+                this.fillParallelStructureCells(deviceParamRow, r, paramRowCount, loisCloisons);
             }
             childIndex++;
         }
@@ -612,22 +635,23 @@ export class PabTableComponent implements AfterViewInit, AfterViewChecked, OnIni
             };
         });
         // as much rows as the greatest number of parameters among its devices
-        const maxNbParamsDW = this.findMaxNumberOfDeviceParameters(this.model.downWall);
-        for (let r = 0; r <= maxNbParamsDW; r++) {
+        const dwParamCount = this.findMaxNumberOfDeviceParameters(this.model.downWall); // device parameter count
+        const paramRowCount = dwParamCount + 1; // max line number for parameters (without device type)
+        for (let r = 0; r < paramRowCount; r++) {
             // build device params row
             const deviceParamRowDW = { selectable: this.model.downWall, cells: [] };
             if (r === 0) {
                 // "downstream"
                 deviceParamRowDW.cells.push({
                     value: "Aval",
-                    rowspan: maxNbParamsDW + 1,
+                    rowspan: paramRowCount,
                     class: "basin_number",
                     selectable: this.model.downWall
                 });
                 // 3 empty cells
                 deviceParamRowDW.cells.push({
                     colspan: 3,
-                    rowspan: maxNbParamsDW + 1,
+                    rowspan: paramRowCount,
                     selectable: this.model.downWall
                 });
                 // ZRAM
@@ -639,27 +663,24 @@ export class PabTableComponent implements AfterViewInit, AfterViewChecked, OnIni
             if (r === 1) {
                 // 1 empty cell (in place of the QA editor)
                 deviceParamRowDW.cells.push({
-                    rowspan: maxNbParamsDW,
+                    rowspan: dwParamCount,
                     selectable: this.model.downWall
                 });
             }
 
             // devices
-            this.fillParallelStructureCells(deviceParamRowDW, r, maxNbParamsDW, loisAval);
+            this.fillParallelStructureCells(deviceParamRowDW, r, paramRowCount, loisAval);
         }
 
         this.updateValidity();
     }
 
-    private fillParallelStructureCells(tableRow: any, rowIndex: number, maxParamCount: number, loisAdmissibles: any[]) {
-        // device param cells : 3 cells for each device
-
+    private fillParallelStructureCells(tableRow: any, rowIndex: number, maxStructParamRowCount: number, loisAdmissibles: any[]) {
         const ps: ParallelStructure = tableRow.selectable;
-
-        for (const struct of ps.structures) {
-            const childStructParamCount = this.nubVisibleParameterCount(struct);
-            // cell 1 : device type
-            if (rowIndex === 0) { // 1st row
+        for (const struct of ps.structures) { // for each device
+            const structParamCount = this.nubVisibleParameterCount(struct);
+            if (rowIndex === 0) {
+                // 1st row : device type
                 tableRow.cells.push({
                     model: struct,
                     modelValue: struct.getPropValue("loiDebit"),
@@ -668,9 +689,9 @@ export class PabTableComponent implements AfterViewInit, AfterViewChecked, OnIni
                     colspan: 2
                 });
             }
-            else if (rowIndex === childStructParamCount + 1) {
+            else if (rowIndex === structParamCount + 1) {
                 // fill remaining space
-                const remaining = maxParamCount - childStructParamCount;
+                const remaining = maxStructParamRowCount - structParamCount;
                 if (remaining > 0) {
                     tableRow.cells.push({
                         colspan: 2,
@@ -680,16 +701,17 @@ export class PabTableComponent implements AfterViewInit, AfterViewChecked, OnIni
                 }
             }
             else {
+                // parameter row
                 const nvParam = struct.getNthVisibleParam(rowIndex - 1);
                 if (nvParam) {
                     const nvParamTitle = this.formService.expandVariableNameAndUnit(CalculatorType.Pab, nvParam.symbol);
-                    // cell 2 : param name
+                    // parameter name
                     tableRow.cells.push({
                         value: nvParam.symbol,
                         title: nvParamTitle,
                         selectable: struct
                     });
-                    // cell 3 : param value
+                    // parameter value
                     tableRow.cells.push({
                         model: nvParam,
                         title: nvParamTitle,
-- 
GitLab


From f70b4d5bea623b80d2bb62b4e2a1d6da93550494 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Fran=C3=A7ois=20Grand?= <francois.grand@inrae.fr>
Date: Tue, 4 Apr 2023 11:37:31 +0200
Subject: [PATCH 3/3] fix: PAB table: selected areas when clicking on various
 cells

refs #615
---
 src/app/components/pab-table/pab-table.component.ts | 9 ++++++---
 1 file changed, 6 insertions(+), 3 deletions(-)

diff --git a/src/app/components/pab-table/pab-table.component.ts b/src/app/components/pab-table/pab-table.component.ts
index c835b87b4..8d48ab20a 100644
--- a/src/app/components/pab-table/pab-table.component.ts
+++ b/src/app/components/pab-table/pab-table.component.ts
@@ -481,6 +481,7 @@ export class PabTableComponent implements AfterViewInit, AfterViewChecked, OnIni
         // 1 col for wall
         this.headers.push({
             title: this.i18nService.localizeText("INFO_PB_CLOISON"),
+            selectable: bs
         });
         // 1 header for each device of the wall having the most devices (including downwall)
         for (let i = 0; i < maxNbDevices; i++) {
@@ -577,7 +578,8 @@ export class PabTableComponent implements AfterViewInit, AfterViewChecked, OnIni
                     });
                     // empty line (EB cell, see note)
                     deviceParamRow.cells.push({
-                        colspan: 3
+                        colspan: 3,
+                        selectable: cloison
                     });
                     // ZRAM
                     deviceParamRow.cells.push({
@@ -604,7 +606,8 @@ export class PabTableComponent implements AfterViewInit, AfterViewChecked, OnIni
                     });
                     // empty cell (EZRAM cell, see note)
                     deviceParamRow.cells.push({
-                        rowspan: paramRowCount
+                        rowspan: paramRowCount,
+                        selectable: cloison
                     });
                 }
                 else if (r === 2) {
@@ -696,7 +699,7 @@ export class PabTableComponent implements AfterViewInit, AfterViewChecked, OnIni
                     tableRow.cells.push({
                         colspan: 2,
                         rowspan: remaining,
-                        selectable: ps
+                        selectable: struct
                     });
                 }
             }
-- 
GitLab