An error occurred while loading the file. Please try again.
-
Mathias Chouet authoredb087a84b
import { Component, Input, Output, EventEmitter, OnInit } from "@angular/core";
import { MatDialog } from "@angular/material";
import {
Pab,
Session,
Props,
CalculatorType,
Cloisons,
Nub,
Structure,
ParallelStructure,
LoiDebit
} from "jalhyd";
import { sprintf } from "sprintf-js";
import { I18nService } from "../../services/internationalisation/internationalisation.service";
import { FormulaireService } from "../../services/formulaire/formulaire.service";
import { ApplicationSetupService } from "../../services/app-setup/app-setup.service";
import { NotificationsService } from "../../services/notifications/notifications.service";
import { PabTable } from "../../formulaire/pab-table";
import { DialogEditPabComponent } from "../dialog-edit-pab/dialog-edit-pab.component";
/**
* The big editable data grid for calculator type "Pab" (component)
*/
@Component({
selector: "pab-table",
templateUrl: "./pab-table.component.html",
styleUrls: [
"./pab-table.component.scss"
]
})
export class PabTableComponent implements /* DoCheck, AfterViewInit, */ OnInit {
@Input()
private pabTable: PabTable;
/** flag de validité des FieldSet enfants */
private _isValid = false;
/** événément de changement de validité */
@Output()
private validChange = new EventEmitter();
/** événément de changement de valeur d'un input */
@Output()
private inputChange = new EventEmitter();
/** underlying Pab, binded to the rows */
private model: Pab;
/** general headers above the columns */
public headers: any[];
/** columns headers description */
public cols: any[];
/** data binded to the table */
public rows: any[];
/** number of children to add when clicking "add" or "clone" button */
public childrenToAdd = 1;
/** items currently selected */
private selectedItems: Nub[];
/** used for shift+click implementation */
7172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140
private latestClickedCell: any;
public constructor(
private i18nService: I18nService,
private formService: FormulaireService,
private editPabDialog: MatDialog,
private appSetupService: ApplicationSetupService,
private notifService: NotificationsService
) {
this.selectedItems = [];
}
public get title(): string {
return this.i18nService.localizeText("INFO_PAB_TABLE");
}
public get isValid() {
return this._isValid;
}
/** returns true if the cell has an underlying model (ie. is editable) */
public hasModel(cell: any): boolean {
return (cell !== undefined && cell.model !== undefined);
}
/** returns true if the cell is an editable number */
public isNumberInput(cell: any): boolean {
return this.hasModel(cell) && ! this.isSelect(cell);
}
/** returns true if the cell is a select box @TODO rename */
public isSelect(cell: any): boolean {
return this.hasModel(cell) && (cell.options !== undefined);
}
/** value to display in a cell, if it is not editable */
public cellValue(cell: any) {
if (cell === undefined) {
return "";
} else {
if (this.hasModel(cell)) {
return cell.model;
} else {
return cell.value;
}
}
}
public rowSpan(cell: any) {
if (cell !== undefined && cell.rowspan) {
return cell.rowspan;
}
return undefined;
}
public colSpan(cell: any) {
if (cell !== undefined && cell.colspan) {
return cell.colspan;
}
return undefined;
}
/** returns true if the cell / row has a selectable item */
public isSelectable(cellOrRow: any): boolean {
return (
cellOrRow !== undefined
&& cellOrRow.selectable
);
}
141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210
/** returns true if the cell / row has a selectableColumn item */
public isSelectableByColumn(cellOrRow: any): boolean {
return (
cellOrRow !== undefined
&& cellOrRow.selectableColumn
);
}
/**
* - checks if the cell / row has a selectable item, that is currently
* selected
* - if cell / row has a selectableColumn attribute, also checks if
* this column is selected
*
* returns true if at least one criterion is met
*/
public isSelected(cellOrRow: any): boolean {
let cellSelected = false;
let columnSelected = false;
// cell
if (this.isSelectable(cellOrRow)) {
cellSelected = true;
if (Array.isArray(cellOrRow.selectable)) {
for (const elt of cellOrRow.selectable) {
cellSelected = cellSelected && this.selectedItems.includes(elt);
}
} else {
cellSelected = this.selectedItems.includes(cellOrRow.selectable);
}
}
// column
if (this.isSelectableByColumn(cellOrRow)) {
columnSelected = this.isDeviceColumnSelected(cellOrRow.selectableColumn);
}
// done
return (cellSelected || columnSelected);
}
/**
* returns true if every wall (including downwall) has its nth device
* selected (or has no nth device)
*/
public isDeviceColumnSelected(n: number): boolean {
let ok = true;
for (const c of this.model.children) {
const nthChild = c.getChildren()[n];
if (nthChild) {
ok = ok && this.selectedItems.includes(nthChild);
}
}
const nthChildDW = this.model.downWall.getChildren()[n];
if (nthChildDW) {
ok = ok && this.selectedItems.includes(nthChildDW);
}
return ok;
}
/**
* selects or unselects the clicked cell, depending on its current state
* and the modifier key held if any
*/
public toggleSelection(cell: any, $event: any) {
if (
this.isSelectable(cell)
&& ! this.hasModel(cell) // editable cells listen to the click event for edition only
) {
if ($event.shiftKey && cell !== this.latestClickedCell) { // shift + click
// @TODO interpopolate from this.latestClickedCell to this one
console.log("shift + click");
211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280
} else if (
$event.ctrlKey // ctrl + click
|| ($event.shiftKey && cell === this.latestClickedCell) // shift on same cell => equiv. of ctrl
) {
if (this.isSelected(cell)) {
// unselect this cell / these cells
if (Array.isArray(cell.selectable)) {
this.selectedItems = this.selectedItems.filter(e => ! cell.selectable.includes(e));
} else {
this.selectedItems = this.selectedItems.filter(e => e !== cell.selectable);
}
} else {
// add this cell / these cells to selection
if (Array.isArray(cell.selectable)) {
this.selectedItems = this.selectedItems.concat(cell.selectable);
this.selectedItems = this.selectedItems.filter(
(item, index) => this.selectedItems.indexOf(item) === index // deduplicate
);
} else {
this.selectedItems.push(cell.selectable);
}
}
} else { // just a click
if (this.isSelected(cell)) {
// select nothing
this.selectedItems = [];
} else {
// select this cell / thses cells only
if (Array.isArray(cell.selectable)) {
this.selectedItems = cell.selectable.slice(); // array copy
} else {
this.selectedItems = [ cell.selectable ];
}
}
}
this.latestClickedCell = cell;
// clean list
this.selectedItems = this.selectedItems.filter(e => e !== undefined);
// @TODO useful ?
$event.preventDefault();
$event.stopPropagation();
return false;
}
}
// quick getter for 1st selected item
public get selectedItem() {
if (this.selectedItems.length === 0) {
throw new Error("get selectedItem() : no item selected");
}
return this.selectedItems[0];
}
// prevents Firefox to display weird cell border when ctrl+clicking
public preventCtrlClickBorder($event) {
if ($event.ctrlKey) {
$event.preventDefault();
}
}
public get addManyOptionsList() {
return Array(20).fill(0).map((value, index) => index + 1);
}
// DEBUG
private dumpParams(n: Nub) {
281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350
console.log(`---- PARAMETERS FOR NUB "${n.uid}" (${n.constructor.name}) ----`);
for (const p of n.parameterIterator) {
if (p.visible) {
console.log(`> ${p.symbol} : ${p.singleValue}, ${p.currentValue}, ${p.v}`);
}
}
}
public zpouet() {
console.log("!!!------------ zpoueeeeeeeeet ------------!!!");
for (const c of this.model.children) {
this.dumpParams(c);
}
this.dumpParams(this.model.downWall);
}
// at this time @Input data is supposed to be already populated
public ngOnInit() {
this.model = this.pabTable.pab;
this.refresh();
}
/**
* Builds the editable data grid from the Pab model
*/
private refresh() {
const maxNbDevices = this.findMaxNumberOfDevices();
// 0. build spanned headers over real columns
this.headers = [];
// 1 header for basin
let bs: any[] = this.model.children;
bs = bs.concat(this.model.downWall);
this.headers.push({
title: "Bassin",
colspan: 6,
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: "Cloison : ouvrage n°" + (i + 1),
colspan: 3,
selectable: this.model.children.map(c => c.getChildren()[i]).concat(this.model.downWall.getChildren()[i]),
selectableColumn: i
});
}
// A. build columns set
this.cols = [];
// 6 cols for basin
this.cols.push({
title: "N° de bassin",
selectable: bs
});
this.cols.push({
title: "Longueur",
selectable: bs
});
this.cols.push({
title: "Largeur",
selectable: bs
});
this.cols.push({
title: "Débit d'attrait",
selectable: bs
});
this.cols.push({
title: "Cote radier mi-bassin",
selectable: bs
351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420
});
this.cols.push({
title: "Cote radier amont paroi",
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)
for (let i = 0; i < maxNbDevices; i++) {
this.cols.push({
title: "Type",
selectable: this.model.children.map(c => c.getChildren()[i]).concat(this.model.downWall.getChildren()[i]),
selectableColumn: i
});
this.cols.push({
title: "Paramètres",
selectable: this.model.children.map(c => c.getChildren()[i]).concat(this.model.downWall.getChildren()[i]),
selectableColumn: i
});
this.cols.push({
title: "Valeurs",
selectable: this.model.children.map(c => c.getChildren()[i]).concat(this.model.downWall.getChildren()[i]),
selectableColumn: i
});
}
// B. Build rows set
this.rows = [];
// B.1 many rows for each wall
let childIndex = 0;
for (const cloison of this.model.children) {
// admissible LoiDebit
const loisCloisons = cloison.getLoisAdmissiblesArray().map(l => { // @TODO move up ? (same for all cloisons)
return {
label: LoiDebit[l],
value: l
};
});
// as much rows as the greatest number of parameters among its devices
const maxNbParams = this.findMaxNumberOfDeviceParameters(cloison);
// console.log(">>> max nb params: ", maxNbParams);
for (let i = 0; i < maxNbParams; i++) {
// build device params row
const deviceParamRow = { selectable: cloison, cells: [] };
// basin number
if (i === 0) {
deviceParamRow.cells.push({
value: childIndex + 1,
rowspan: maxNbParams + 1,
class: "basin_number",
selectable: cloison
});
}
// 5 empty cells
if (i === 0) {
deviceParamRow.cells.push({
colspan: 5,
rowspan: maxNbParams,
selectable: cloison
});
}
// device param cells : 3 cells for each device
for (const ouvrage of cloison.structures) {
const nvParam = ouvrage.getNthVisibleParam(i);
// cell 1 : device type
if (i === 0) { // 1st row
deviceParamRow.cells.push({
model: ouvrage,
modelValue: ouvrage.properties.getPropValue("loiDebit"),
options: loisCloisons,
selectable: ouvrage
421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490
});
}
// fill space
if (i === 1) {
deviceParamRow.cells.push({
rowspan: (maxNbParams - 1),
selectable: ouvrage
});
}
// cell 2 : param name
if (nvParam) {
deviceParamRow.cells.push({
value: nvParam.symbol,
selectable: ouvrage
});
} else {
deviceParamRow.cells.push({
selectable: ouvrage
});
}
// cell 3 : param value
if (nvParam) {
deviceParamRow.cells.push({
model: nvParam,
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 the basin after the wall
const basinRow: { selectable: any, cells: any[] } = {
selectable: cloison,
cells: [
// no cell for basin number (defined by rowspan-n cell above)
{
model: cloison.prms.LB
},
{
model: cloison.prms.BB
},
{
model: cloison.prms.QA
},
{
model: cloison.prms.ZRMB
},
{
model: cloison.prms.ZRAM
}
]
};
// fill horizontal space
491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560
for (let i = 0; i < maxNbDevices; i++) {
basinRow.cells.push({
colspan: 3
});
}
// done !
this.rows.push(basinRow);
childIndex ++;
}
// B.2 many rows for downwall
// admissible LoiDebit
const loisAval = this.model.downWall.getLoisAdmissiblesArray().map(l => {
return {
label: LoiDebit[l],
value: l
};
});
// 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++) {
// build device params row
const deviceParamRowDW = { selectable: this.model.downWall, cells: [] };
// basin number
if (i === 0) {
deviceParamRowDW.cells.push({
value: "Aval",
rowspan: maxNbParamsDW,
class: "basin_number",
selectable: this.model.downWall
});
}
// 5 empty cells
if (i === 0) {
deviceParamRowDW.cells.push({
colspan: 5,
rowspan: maxNbParamsDW,
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);
// cell 1 : device type
if (i === 0) { // 1st row
deviceParamRowDW.cells.push({
model: ouvrage,
modelValue: ouvrage.properties.getPropValue("loiDebit"),
options: loisAval
});
}
// fill space
if (i === 1) {
deviceParamRowDW.cells.push({
rowspan: (maxNbParamsDW - 1),
selectable: ouvrage
});
}
// cell 2 : param name
if (nvParam) {
deviceParamRowDW.cells.push({
value: nvParam.symbol,
selectable: ouvrage
});
} else {
deviceParamRowDW.cells.push({
selectable: ouvrage
});
}
// cell 3 : param value
561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630
if (nvParam) {
deviceParamRowDW.cells.push({
model: nvParam,
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
});
}
}
// done !
this.rows.push(deviceParamRowDW);
}
}
private findMaxNumberOfDevices(): number {
let maxNbDevices = 1;
for (const w of this.model.children) {
maxNbDevices = Math.max(maxNbDevices, w.getChildren().length);
}
maxNbDevices = Math.max(maxNbDevices, this.model.downWall.getChildren().length);
return maxNbDevices;
}
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);
}
return maxNbParams;
}
/** returns true if exactly one device is selected, and nothing else */
public get selectionIsOneDevice() {
return (
this.selectedItems.length === 1
&& this.selectedItem instanceof Structure
);
}
/**
* Returns true if there is at least one selected item,
* and all selected items are devices
*/
private onlyDevicesAreSelected() {
let ok = false;
if (this.selectedItems.length > 0) {
ok = true;
for (const s of this.selectedItems) {
631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700
ok = ok && (s instanceof Structure);
}
}
return ok;
}
/**
* Returns true if there is at least one selected item,
* and all selected items are walls
*/
private onlyWallsAreSelected(excludeDownwall: boolean = true) {
let ok = false;
if (this.selectedItems.length > 0) {
ok = true;
for (const s of this.selectedItems) {
if (excludeDownwall) {
ok = ok && (s instanceof Cloisons);
} else {
ok = ok && (s instanceof ParallelStructure);
}
}
}
return ok;
}
public get relatedEntityTitle() {
let title = "";
if (this.onlyDevicesAreSelected()) {
title = "Ouvrages";
} else if (this.onlyWallsAreSelected()) {
title = "Cloisons";
}
if (title !== "") {
title += " :";
}
return title;
}
public get enableAddButton() {
return (
this.selectedItems.length === 1
&& this.selectedItem.parent // exclude downwall
);
}
public get enableCopyButton() {
return (
this.selectedItems.length === 1
&& this.selectedItem.parent // exclude downwall
);
}
public get enableUpButton() {
return (
this.selectedItems.length === 1
&& this.selectedItem.parent
&& this.selectedItem.findPositionInParent() !== 0
);
}
public get enableDownButton() {
return (
this.selectedItems.length === 1
&& this.selectedItem.parent
&& this.selectedItem.findPositionInParent() < (this.selectedItem.parent.getChildren().length - 1)
);
}
public get enableRemoveButton() {
return (
701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770
this.selectedItems.length === 1
&& this.selectedItem.parent
&& this.selectedItem.parent.getChildren().length > 1
);
}
/**
* returns true if at least one object is selected
*/
public get enableEditPabButton() {
return this.selectedItems.length > 0;
}
public onAddClick() {
// add default item
for (let i = 0; i < this.childrenToAdd; i++) {
if (this.selectedItem instanceof Structure) {
// add new default device for wall parent
const newDevice = Session.getInstance().createNub(
new Props({
calcType: CalculatorType.Structure,
loiDebit: (this.selectedItem.parent as ParallelStructure).getDefaultLoiDebit()
})
);
this.selectedItem.parent.addChild(newDevice, this.selectedItem.findPositionInParent());
} else {
// add new default wall for PAB parent
const newWall = Session.getInstance().createNub(
new Props({
calcType: CalculatorType.Cloisons
})
);
// add new default device for new wall
const newDevice = Session.getInstance().createNub(
new Props({
calcType: CalculatorType.Structure,
loiDebit: (newWall as ParallelStructure).getDefaultLoiDebit()
})
);
newWall.addChild(newDevice);
this.model.addChild(newWall, this.selectedItem.findPositionInParent());
}
}
this.refresh();
// notify
const pos = this.selectedItem.findPositionInParent() + 1;
let msg: string;
if (this.childrenToAdd === 1) {
if (this.selectedItem instanceof Structure) {
msg = sprintf(this.i18nService.localizeText("INFO_DEVICE_ADDED"), pos);
} else {
msg = sprintf(this.i18nService.localizeText("INFO_WALL_ADDED"), pos);
}
} else {
if (this.selectedItem instanceof Structure) {
msg = sprintf(this.i18nService.localizeText("INFO_DEVICE_ADDED_N_TIMES"), this.childrenToAdd);
} else {
msg = sprintf(this.i18nService.localizeText("INFO_WALL_ADDED_N_TIMES"), this.childrenToAdd);
}
}
this.notifService.notify(msg);
this.childrenToAdd = 1; // reinit to avoid confusion
}
public onCopyClick() {
// cloned selected item
for (let i = 0; i < this.childrenToAdd; i++) {
771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840
const newChild = Session.getInstance().createNub(
this.selectedItem.properties.clone(),
this.selectedItem.parent
);
// copy parameter values
for (const p of this.selectedItem.prms) {
newChild.getParameter(p.symbol).singleValue = p.singleValue;
}
// copy children
if (this.selectedItem instanceof ParallelStructure) {
for (const c of this.selectedItem.getChildren()) {
const newGrandChild = Session.getInstance().createNub(
c.properties.clone(),
newChild
);
// copy children parameters values
for (const p of c.prms) {
newGrandChild.getParameter(p.symbol).singleValue = p.singleValue;
}
// add to parent
newChild.addChild(
newGrandChild,
c.findPositionInParent()
);
}
}
// add to parent
this.selectedItem.parent.addChild(
newChild,
this.selectedItem.findPositionInParent()
);
}
this.refresh();
// notify
const pos = this.selectedItem.findPositionInParent() + 1;
let msg: string;
if (this.childrenToAdd === 1) {
if (this.selectedItem instanceof Structure) {
msg = sprintf(this.i18nService.localizeText("INFO_DEVICE_COPIED"), pos);
} else {
msg = sprintf(this.i18nService.localizeText("INFO_WALL_COPIED"), pos);
}
} else {
if (this.selectedItem instanceof Structure) {
msg = sprintf(this.i18nService.localizeText("INFO_DEVICE_COPIED_N_TIMES"), pos, this.childrenToAdd);
} else {
msg = sprintf(this.i18nService.localizeText("INFO_WALL_COPIED_N_TIMES"), pos, this.childrenToAdd);
}
}
this.notifService.notify(msg);
this.childrenToAdd = 1; // reinit to avoid confusion
}
public onMoveUpClick() {
const pos = this.selectedItem.findPositionInParent() + 1;
this.selectedItem.parent.moveChildUp(this.selectedItem);
if (this.selectedItem instanceof Structure) {
this.notifService.notify(sprintf(this.i18nService.localizeText("INFO_DEVICE_MOVED"), pos));
} else {
this.notifService.notify(sprintf(this.i18nService.localizeText("INFO_WALL_MOVED"), pos));
}
this.refresh();
}
public onMoveDownClick() {
const pos = this.selectedItem.findPositionInParent() + 1;
this.selectedItem.parent.moveChildDown(this.selectedItem);
if (this.selectedItem instanceof Structure) {
841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910
this.notifService.notify(sprintf(this.i18nService.localizeText("INFO_DEVICE_MOVED"), pos));
} else {
this.notifService.notify(sprintf(this.i18nService.localizeText("INFO_WALL_MOVED"), pos));
}
this.refresh();
}
public onRemoveClick() {
const pos = this.selectedItem.findPositionInParent() + 1;
this.selectedItem.parent.deleteChild(this.selectedItem.findPositionInParent());
if (this.selectedItem instanceof Structure) {
this.notifService.notify(sprintf(this.i18nService.localizeText("INFO_DEVICE_REMOVED"), pos));
} else {
this.notifService.notify(sprintf(this.i18nService.localizeText("INFO_WALL_REMOVED"), pos));
}
this.refresh();
}
/** Replace device Nub when LoiDebit is changed */
public loiDebitSelected($event: any, cell: any) {
const device = cell.model as Nub;
const pos = device.findPositionInParent();
// create new child device
const newDevice = Session.getInstance().createNub(
new Props({
calcType: CalculatorType.Structure,
loiDebit: $event.value
})
);
// replace the current one
device.parent.replaceChildInplace(device, newDevice);
this.refresh();
}
// show modal dialog for values edition
public showEditPab() {
if (this.selectedItems.length > 0) {
// list variables eligible to modification
const availableVariables: { label: string, value: string, occurrences: number, first: number, last: number }[] = [];
for (const c of this.selectedItems) {
for (const p of c.parameterIterator) { // deep one
if (
p.visible &&
! availableVariables.map(av => av.value).includes(p.symbol)
) {
availableVariables.push({
label: this.formService.expandVariableNameAndUnit(CalculatorType.Pab, p.symbol),
value: p.symbol,
occurrences: 0,
first: undefined,
last: undefined
});
}
}
}
// find their min/max values (2nd pass)
for (const av of availableVariables) {
for (const c of this.selectedItems) {
for (const p of c.parameterIterator) {
if (p.visible && p.symbol === av.value) {
av.occurrences ++;
if (av.first === undefined) {
av.first = p.singleValue;
}
av.last = p.singleValue;
}
}
}
}
911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980
// sum up selected items
const walls: ParallelStructure[] = [];
const wallsDevices: Structure[] = [];
const devices: Structure[] = [];
let vertical = true; // @TODO vertical AND consecutive !
let firstDevicePosition: number;
// 1st pass
for (const s of this.selectedItems) {
if (s instanceof ParallelStructure) {
walls.push(s);
for (const c of s.structures) {
if (firstDevicePosition === undefined) {
firstDevicePosition = c.findPositionInParent();
} else {
vertical = (vertical && (c.findPositionInParent() === firstDevicePosition));
}
wallsDevices.push(c);
}
}
}
// 2nd pass
for (const c of this.selectedItems) {
if (c instanceof Structure) {
if (! wallsDevices.includes(c)) {
if (firstDevicePosition === undefined) {
firstDevicePosition = c.findPositionInParent();
} else {
vertical = (vertical && (c.findPositionInParent() === firstDevicePosition));
}
devices.push(c);
}
}
}
// open dialog
const dialogRef = this.editPabDialog.open(
DialogEditPabComponent,
{
data: {
availableVariables: availableVariables,
selectedItemsAbstract: {
walls: walls.length,
wallsDevices: wallsDevices.length,
devices: devices.length
},
vertical: vertical // used to enable interpolation
},
disableClose: true
}
);
// apply modifications
dialogRef.afterClosed().subscribe(result => {
if (result) {
/* console.log("Apply values in parent !!", result.action, result.variable, result.value,
result.delta, result.variableDetails); */
switch (result.action) {
case "set-value":
for (const s of this.selectedItems) {
for (const p of s.parameterIterator) { // deep
if (p.symbol === result.variable) {
p.singleValue = result.value;
}
}
}
break;
case "delta":
for (const s of this.selectedItems) {
981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050
for (const p of s.parameterIterator) { // deep
if (p.symbol === result.variable) {
p.singleValue += result.delta;
}
}
}
break;
case "interpolate":
if (result.variableDetails.occurrences > 1) {
const nDigits = this.appSetupService.displayDigits;
// build values list
const interpolatedValues: number[] = [];
const step = (
(result.variableDetails.last - result.variableDetails.first)
/ (result.variableDetails.occurrences - 1)
);
interpolatedValues.push(result.variableDetails.first);
let currentValue: number = result.variableDetails.first;
for (let i = 0; i < result.variableDetails.occurrences - 2; i++) {
currentValue += step;
interpolatedValues.push(Number(currentValue.toFixed(nDigits)));
}
interpolatedValues.push(result.variableDetails.last);
// apply
let idx = 0;
for (const s of this.selectedItems) {
for (const p of s.parameterIterator) { // deep
if (p.symbol === result.variable) {
p.singleValue = interpolatedValues[idx];
idx ++;
}
}
}
} else {
throw new Error(
`showEditPab() : cannot interpolate, too few occurrences (${result.variableDetails.occurrences})`
);
}
break;
}
}
});
}
}
/* public ngAfterViewInit() {
this.onFieldsetListChange();
this._fieldsetComponents.changes.subscribe(_ => this.onFieldsetListChange());
}
public ngDoCheck() {
this.updateValidity();
} */
/**
* @TODO Calcul de la validité de la Pab
*/
private updateValidity() {
this._isValid = false;
/* if (this._fieldsetComponents !== undefined) {
this._isValid = this._fieldsetComponents.reduce(
// callback
(
// accumulator (valeur précédente du résultat)
acc,
// currentValue (élément courant dans le tableau)
fieldset,
// currentIndex (indice courant dans le tableau)
10511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082
currIndex,
// array (tableau parcouru)
array
) => {
return acc && fieldset.isValid;
}
// valeur initiale
, this._fieldsetComponents.length > 0);
} */
this.validChange.emit();
}
/**
* réception d'un événement de changement de valeur d'un input
*/
private onInputChange($event) {
this.inputChange.emit($event);
}
/**
* Renvoie l'événement au composant du dessus
*/
public onTabPressed(event) {
console.log("tab pressed dans le tablo !");
}
public get uitextEditPabTable() {
return "Modifier les valeurs";
}
}