diff --git a/src/app/components/pab-table/pab-table.component.html b/src/app/components/pab-table/pab-table.component.html index b68a85d56669609ca12e28023b6c4bd62701baa0..d3b0c017eeb1010229cc3362691195e9eecd3d9d 100644 --- a/src/app/components/pab-table/pab-table.component.html +++ b/src/app/components/pab-table/pab-table.component.html @@ -65,12 +65,13 @@ {{ h.title }} </th> </tr> - <tr> - <th *ngFor="let col of columns" (click)="toggleSelection(col, $event)" - (mousedown)="preventCtrlClickBorder($event)" [class.selectable-cell]="isSelectable(col)" - [class.selected-cell]="isSelected(col)"> + <tr *ngFor="let col of columns"> + <th *ngFor="let cell of col.cells" (click)="toggleSelection(cell, $event)" + (mousedown)="preventCtrlClickBorder($event)" [class.selectable-cell]="isSelectable(cell)" + [class.selected-cell]="isSelected(cell)" [attr.rowspan]="rowSpan(cell)" + [attr.colspan]="colSpan(cell)" [title]="cellTitle(cell)"> - {{ col.title }} + {{ cell.title }} </th> </tr> </ng-template> diff --git a/src/app/components/pab-table/pab-table.component.ts b/src/app/components/pab-table/pab-table.component.ts index dc2470aef9334fdf718ddc095c103a460279dece..8d48ab20a3b7a42edc349e47a265f229f51b342c 100644 --- a/src/app/components/pab-table/pab-table.component.ts +++ b/src/app/components/pab-table/pab-table.component.ts @@ -84,7 +84,6 @@ export class PabTableComponent implements AfterViewInit, AfterViewChecked, OnIni private i18nService: I18nService, private formService: FormulaireService, private editPabDialog: MatDialog, - private appSetupService: ApplicationSetupService, private notifService: NotificationsService ) { this.selectedItems = []; @@ -465,19 +464,30 @@ 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"), selectable: bs }); // 1 header for each device of the wall having the most devices (including downwall) for (let i = 0; i < maxNbDevices; i++) { this.headers.push({ title: sprintf(this.i18nService.localizeText("INFO_PAB_CLOISON_OUVRAGE_N"), (i + 1)), - colspan: 3, + colspan: 2, selectable: this.model.children.map(c => c.getChildren()[i]).concat(this.model.downWall.getChildren()[i]), selectableColumn: i }); @@ -485,43 +495,42 @@ export class PabTableComponent implements AfterViewInit, AfterViewChecked, OnIni // A. build columns set this.cols = []; - // 5 cols for basin - this.cols.push({ - title: this.i18nService.localizeText("INFO_PAB_NUM_BASSIN"), - selectable: bs - }); - this.cols.push({ + const headerRow1 = { cells: [] }; + const headerRow2 = { cells: [] }; + this.cols.push(headerRow1); + this.cols.push(headerRow2); + + // 3 cols for basin information + headerRow1.cells.push({ title: this.formService.expandVariableNameAndUnit(CalculatorType.Pab, "LB"), selectable: bs }); - this.cols.push({ + headerRow1.cells.push({ title: this.formService.expandVariableNameAndUnit(CalculatorType.Pab, "BB"), selectable: bs }); - this.cols.push({ + headerRow1.cells.push({ title: this.formService.expandVariableNameAndUnit(CalculatorType.Pab, "ZRMB"), selectable: bs }); - this.cols.push({ - title: this.formService.expandVariableNameAndUnit(CalculatorType.Pab, "ZRAM"), - 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++) { - this.cols.push({ - title: this.i18nService.localizeText("INFO_PAB_HEADER_TYPE"), - selectable: this.model.children.map(c => c.getChildren()[i]).concat(this.model.downWall.getChildren()[i]), - selectableColumn: i - }); - this.cols.push({ + 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_PARAMETERS"), - selectable: this.model.children.map(c => c.getChildren()[i]).concat(this.model.downWall.getChildren()[i]), + selectable: sel, selectableColumn: i }); - this.cols.push({ + headerRow1.cells.push({ title: this.i18nService.localizeText("INFO_PAB_HEADER_VALUES"), - selectable: this.model.children.map(c => c.getChildren()[i]).concat(this.model.downWall.getChildren()[i]), + selectable: sel, selectableColumn: i }); } @@ -535,27 +544,41 @@ 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 i = 0; i < maxNbParams; i++) { - // 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 and ZRAM - if (i === 0) { + if (r === 0) { // basin number deviceParamRow.cells.push({ value: childIndex + 1, - rowspan: maxNbParams + 1, + rowspan: totalRowCount, class: "basin_number", selectable: cloison }); - // 3 empty cells + // empty line (EB cell, see note) deviceParamRow.cells.push({ colspan: 3, - rowspan: maxNbParams - 1, selectable: cloison }); // ZRAM @@ -564,111 +587,46 @@ export class PabTableComponent implements AfterViewInit, AfterViewChecked, OnIni title: this.formService.expandVariableNameAndUnit(CalculatorType.Pab, "ZRAM") }); } - // basin cells on the last but 1 row - if (i === maxNbParams - 1) { + // LB, BB, ZRMB, EZRAM cell (see note) + else if (r === 1) { + // Longueur bassin deviceParamRow.cells.push({ model: cloison.prms.LB, title: this.formService.expandVariableNameAndUnit(CalculatorType.Pab, "LB") }); + // Largeur bassin deviceParamRow.cells.push({ model: cloison.prms.BB, title: this.formService.expandVariableNameAndUnit(CalculatorType.Pab, "BB") }); + // Cote radier mi bassin deviceParamRow.cells.push({ model: cloison.prms.ZRMB, title: this.formService.expandVariableNameAndUnit(CalculatorType.Pab, "ZRMB") }); - } - // 1 empty cell below ZRAM - if (i === 1) { + // empty cell (EZRAM cell, see note) deviceParamRow.cells.push({ - rowspan: maxNbParams, + rowspan: paramRowCount, selectable: cloison }); } - // device param cells : 3 cells for each device - for (const ouvrage of cloison.structures) { - const nvParam = ouvrage.getNthVisibleParam(i); - const nvParamTitle = nvParam ? this.formService.expandVariableNameAndUnit(CalculatorType.Pab, nvParam.symbol) : ""; - // cell 1 : device type - if (i === 0) { // 1st row - deviceParamRow.cells.push({ - model: ouvrage, - modelValue: ouvrage.getPropValue("loiDebit"), - options: loisCloisons, - selectable: ouvrage - }); - } - // fill space below device type selector - if (i === 1) { - deviceParamRow.cells.push({ - rowspan: (maxNbParams - 1), - selectable: ouvrage - }); - } - // cell 2 : param name - if (nvParam) { - deviceParamRow.cells.push({ - value: nvParam.symbol, - title: nvParamTitle, - selectable: ouvrage - }); - } else { - deviceParamRow.cells.push({ - selectable: ouvrage - }); - } - // cell 3 : param value - if (nvParam) { - deviceParamRow.cells.push({ - model: nvParam, - title: nvParamTitle, - selectable: ouvrage - }); - } else { - deviceParamRow.cells.push({ - selectable: ouvrage - }); - } - } - // fill horizontal space - const devDiff = (maxNbDevices - cloison.structures.length); - if (i === 0) { - for (let j = 0; j < devDiff; j++) { - deviceParamRow.cells.push({ - colspan: 3, - rowspan: maxNbParams, - selectable: cloison, - selectableColumn: cloison.structures.length + j - }); - } - } - // done ! - this.rows.push(deviceParamRow); - } - // 1 row for QA editor - const qaParam = new NgParameter(cloison.prms.QA, this.pabTable.form); - qaParam.radioConfig = ParamRadioConfig.VAR; - const qaRow: { selectable: any, cells: any[] } = { - selectable: undefined, - cells: [ - { + 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: 3, + rowspan: QAEditorRowCount, qa: true, title: this.formService.expandVariableNameAndUnit(CalculatorType.Pab, "QA") - } - ] - }; - // as many pairs of columns as the maximum number of devices - qaRow.cells.push({ - colspan: maxNbDevices * 3, - // selectable: cloison @TODO oui ou non ? - }); - // done ! - this.rows.push(qaRow); + }); + } - childIndex ++; + // devices + this.fillParallelStructureCells(deviceParamRow, r, paramRowCount, loisCloisons); + } + childIndex++; } // B.2 many rows for downwall @@ -680,22 +638,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 i = 0; i < maxNbParamsDW; i++) { + 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: [] }; - // basin number - if (i === 0) { + if (r === 0) { + // "downstream" deviceParamRowDW.cells.push({ value: "Aval", - rowspan: maxNbParamsDW, + rowspan: paramRowCount, class: "basin_number", selectable: this.model.downWall }); // 3 empty cells deviceParamRowDW.cells.push({ colspan: 3, - rowspan: maxNbParamsDW , + rowspan: paramRowCount, selectable: this.model.downWall }); // ZRAM @@ -704,74 +663,68 @@ export class PabTableComponent implements AfterViewInit, AfterViewChecked, OnIni title: this.formService.expandVariableNameAndUnit(CalculatorType.Pab, "ZRAM") }); } - if (i === 1) { - // 1 empty cell + if (r === 1) { + // 1 empty cell (in place of the QA editor) deviceParamRowDW.cells.push({ - rowspan: maxNbParamsDW - 1, + rowspan: dwParamCount, selectable: this.model.downWall }); } - // downwall device param cells : 3 cells for each device - for (const ouvrage of this.model.downWall.structures) { - const nvParam = ouvrage.getNthVisibleParam(i); - const nvParamTitle = nvParam ? this.formService.expandVariableNameAndUnit(CalculatorType.Pab, nvParam.symbol) : ""; - // cell 1 : device type - if (i === 0) { // 1st row - deviceParamRowDW.cells.push({ - model: ouvrage, - modelValue: ouvrage.getPropValue("loiDebit"), - options: loisAval - }); - } - // fill space - if (i === 1) { - deviceParamRowDW.cells.push({ - rowspan: (maxNbParamsDW - 1), - selectable: ouvrage + + // devices + this.fillParallelStructureCells(deviceParamRowDW, r, paramRowCount, loisAval); + } + + this.updateValidity(); + } + + private fillParallelStructureCells(tableRow: any, rowIndex: number, maxStructParamRowCount: number, loisAdmissibles: any[]) { + const ps: ParallelStructure = tableRow.selectable; + 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"), + options: loisAdmissibles, + selectable: struct, + colspan: 2 + }); + } + else if (rowIndex === structParamCount + 1) { + // fill remaining space + const remaining = maxStructParamRowCount - structParamCount; + if (remaining > 0) { + tableRow.cells.push({ + colspan: 2, + rowspan: remaining, + selectable: struct }); } - // cell 2 : param name + } + else { + // parameter row + const nvParam = struct.getNthVisibleParam(rowIndex - 1); if (nvParam) { - deviceParamRowDW.cells.push({ + const nvParamTitle = this.formService.expandVariableNameAndUnit(CalculatorType.Pab, nvParam.symbol); + // parameter name + tableRow.cells.push({ value: nvParam.symbol, title: nvParamTitle, - selectable: ouvrage - }); - } else { - deviceParamRowDW.cells.push({ - selectable: ouvrage + selectable: struct }); - } - // cell 3 : param value - if (nvParam) { - deviceParamRowDW.cells.push({ + // parameter value + tableRow.cells.push({ model: nvParam, title: nvParamTitle, - selectable: ouvrage - }); - } else { - deviceParamRowDW.cells.push({ - selectable: ouvrage - }); - } - } - // fill horizontal space - const devDiff = (maxNbDevices - this.model.downWall.structures.length); - if (i === 0) { - for (let j = 0; j < devDiff; j++) { - deviceParamRowDW.cells.push({ - colspan: 3, - rowspan: maxNbParamsDW, - selectable: this.model.downWall, - selectableColumn: this.model.downWall.structures.length + j + selectable: struct }); } } - // done ! - this.rows.push(deviceParamRowDW); } - - this.updateValidity(); + // done ! + this.rows.push(tableRow); } /** @@ -790,18 +743,20 @@ export class PabTableComponent implements AfterViewInit, AfterViewChecked, OnIni return maxNbDevices; } + private nubVisibleParameterCount(n: Nub) { + let res = 0; + for (const p of n.parameterIterator) { + if (p.visible) { + res++; + } + } + return res; + } + private findMaxNumberOfDeviceParameters(struct: ParallelStructure): number { let maxNbParams = 1; - for (const d of struct.getChildren()) { - let nbParams = 0; - for (const p of d.parameterIterator) { - if (p.visible) { - // console.log("(counting)", p.symbol); - nbParams ++; - } - } - // console.log(">>> child params: ", nbParams); - maxNbParams = Math.max(maxNbParams, nbParams); + for (const child of struct.getChildren()) { + maxNbParams = Math.max(maxNbParams, this.nubVisibleParameterCount(child)); } return maxNbParams; } @@ -1039,7 +994,7 @@ export class PabTableComponent implements AfterViewInit, AfterViewChecked, OnIni for (let i = 0; i < this.childrenToAdd; i++) { for (const si of this.selectedItems) { const newChild = Session.getInstance().createNub( - si.properties.clone(), + si, si.parent ); // copy parameter values @@ -1052,7 +1007,7 @@ export class PabTableComponent implements AfterViewInit, AfterViewChecked, OnIni if (si instanceof ParallelStructure) { for (const c of si.getChildren()) { const newGrandChild = Session.getInstance().createNub( - c.properties.clone(), + c, newChild ); // copy children parameters values diff --git a/src/locale/messages.en.json b/src/locale/messages.en.json index b7b836bd09864cbe81f26ff922b9d154c1a98a70..b31fc6330b5b2de4bd86edeefe7fcff5786c7fa5 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 1b2892173b6f6383f61f07fac4766fbc1288b0b5..21aca059bcbca69d01786097c849cecafa1e842d 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",