diff --git a/angular.json b/angular.json
index cb5b49b6a3f35dddcc00bd1a7da7d560179484f7..0f22c724bcd8a99caff923b27efe8a2309e2db4e 100644
--- a/angular.json
+++ b/angular.json
@@ -51,14 +51,35 @@
               "node_modules/marked/lib/marked.js",
               "node_modules/katex/dist/katex.min.js"
             ],
-            "showCircularDependencies": false
+            "showCircularDependencies": false,
+            "allowedCommonJsDependencies": [
+              "chartjs-plugin-zoom",
+              "angular2-chartjs/dist/chart.component",
+              "angular2-chartjs/dist/chart.module",
+              "angular2-hotkeys.js",
+              "base-64",
+              "he",
+              "svg-pan-zoom",
+              "mermaid",
+              "pako",
+              "file-saver",
+              "hammerjs",
+              "chart.js",
+              "mousetrap",
+              "xlsx",
+              "scope-css",
+              "lodash",
+              "graphlibrary",
+              "dagre-layout",
+              "dagre-d3-renderer"
+            ]
           },
           "configurations": {
             "production": {
               "budgets": [
                 {
                   "type": "anyComponentStyle",
-                  "maximumWarning": "6kb"
+                  "maximumWarning": "10kb"
                 }
               ],
               "optimization": true,
diff --git a/e2e/calculate-all-params.e2e-spec.ts b/e2e/calculate-all-params.e2e-spec.ts
index d8fafc252971c87066a93b11695868d897b691c4..a74e4e1381d904d80d1510ab07c8be7096fd2b27 100644
--- a/e2e/calculate-all-params.e2e-spec.ts
+++ b/e2e/calculate-all-params.e2e-spec.ts
@@ -2,7 +2,7 @@ import { ListPage } from "./list.po";
 import { CalculatorPage } from "./calculator.po";
 import { Navbar } from "./navbar.po";
 import { PreferencesPage } from "./preferences.po";
-import { browser } from "protractor";
+import { browser, element, by } from "protractor";
 import { testedCalcTypes } from "./tested_calctypes";
 
 /**
@@ -36,8 +36,13 @@ describe("ngHyd − calculate all parameters of all calculators", async () => {
 
     // for each calculator
     for (const ct of calcTypes) {
-        if (ct === 22) {
-            // omit 22 - Solveur is not calculated here because it is not independent
+        if ([ 22, 31, 32, 33, 34 ].includes(ct)) {
+            // omit 22 - Solveur
+            // omit 31 - PbCloison
+            // omit 32 - PbBassin
+            // omit 33 - Espece
+            // omit 34 - Verificateur
+            // (not calculated here because they are not independent)
             continue;
         }
         describe(" − calculate all parameters of calculator type [" + ct + "]", async () => {
@@ -53,6 +58,14 @@ describe("ngHyd − calculate all parameters of all calculators", async () => {
                 if (inputs.length > 0) {
                     // for each param
                     for (let i = 0; i < inputs.length; i++) {
+                        // for PreBarrage, switch back to "input" after calculating, so
+                        // that the calculable parameters are shown
+                        if (ct === 30 && i > 0) {
+                            // prevents "Element is not clickable at point"
+                            await browser.executeScript("window.scrollTo(0, 0);");
+                            const inputLink = element(by.css("#pb-data-results-selector .drs-item a"));
+                            await inputLink.click();
+                        }
                         // grab input again because calculating the module just refreshed all the fieldsets
                         const input = (await calcPage.getParamInputsHavingCalcMode())[i];
                         // click "calc" mode button for this parameter
diff --git a/e2e/calculate-linked-params.e2e-spec.ts b/e2e/calculate-linked-params.e2e-spec.ts
index 443e7939b4bc4f031c1d7a28e10159183489e3c1..3436c8092544a75f4b2de9dee52311351cc03ee3 100644
--- a/e2e/calculate-linked-params.e2e-spec.ts
+++ b/e2e/calculate-linked-params.e2e-spec.ts
@@ -287,7 +287,7 @@ describe("ngHyd − calculate with linked parameters", () => {
         let frt = calcPage.getFixedResultsTable();
         let volumeRow = calcPage.getNthRow(frt, 3);
         let volumeCol = calcPage.getNthColumn(volumeRow, 2);
-        let volume = await volumeCol.getText();
+        let volume = await volumeCol.getAttribute("textContent");
         expect(Number(volume)).toBeCloseTo(44.565, 3);
 
         // click PAB-Nombre tab
@@ -302,7 +302,7 @@ describe("ngHyd − calculate with linked parameters", () => {
         frt = calcPage.getFixedResultsTable();
         volumeRow = calcPage.getNthRow(frt, 3);
         volumeCol = calcPage.getNthColumn(volumeRow, 2);
-        volume = await volumeCol.getText();
+        volume = await volumeCol.getAttribute("textContent");
         expect(Number(volume)).toBeCloseTo(44.565, 3);
     });
 
diff --git a/e2e/calculator.po.ts b/e2e/calculator.po.ts
index 6053029af65d2e09faa8a505e417fdbdadace995..1194295c9979387c0b51149569b81ca4ca2d04e2 100644
--- a/e2e/calculator.po.ts
+++ b/e2e/calculator.po.ts
@@ -80,11 +80,11 @@ export class CalculatorPage {
     }
 
     getAllVariatedResultsTableHeaders() {
-        return element.all(by.css("var-results table thead th"));
+        return element.all(by.css("fixedvar-results var-results table thead th"));
     }
 
     getAllVariatedResultsRows() {
-        return element.all(by.css("var-results table tbody tr"));
+        return element.all(by.css("fixedvar-results var-results table tbody tr"));
     }
 
     scrollTo(elt: ElementFinder) {
@@ -131,6 +131,8 @@ export class CalculatorPage {
             ||
             await this.presentAndVisible("pab-results pab-results-table")
             ||
+            await this.presentAndVisible("pb-results pb-results-table")
+            ||
             await this.presentAndVisible("macrorugo-compound-results macrorugo-compound-results-table")
             ||
             await this.presentAndVisible("jet-results .fixed-results-container")
@@ -294,7 +296,7 @@ export class CalculatorPage {
                 if (!hasDot && !hasExponent && !isN) {
                     keys = "." + keys;
                 }
-                if (! isOb) {
+                if (! isOb && await i.getAttribute("disabled") === null) {
                     await i.sendKeys(keys);
                 }
             }
diff --git a/e2e/tested_calctypes.ts b/e2e/tested_calctypes.ts
index e4eed0389b84f201dbe97200e8af3dea74eb3832..cdd1fc76623d3d0408d0232848ed10438a92395a 100644
--- a/e2e/tested_calctypes.ts
+++ b/e2e/tested_calctypes.ts
@@ -9,5 +9,7 @@ export const testedCalcTypes = [
     // omit 16 - CloisonAval
     17, 18, 19, 20, 21, 22, 23, 24, 25,
     // omit 26 - YAXN
-    27, 29
+    27, 28, 29, 30,
+    // omit 31 - PbCloison and 32 - PbBassin
+    33, 34
 ];
diff --git a/jalhyd_branch b/jalhyd_branch
index f95555f7a46d0099a962879fa5b1ec791ca252ee..22284ff354bd375daf96c4516cffb189fc611602 100644
--- a/jalhyd_branch
+++ b/jalhyd_branch
@@ -1 +1 @@
-204-ajout-de-la-fonctionnalite-respect-des-criteres-2
+32-ajout-de-l-outil-prebarrage
diff --git a/package-lock.json b/package-lock.json
index e066204be8c5cff3efcb8683825b9fb635a95404..b010761ab221e68f14270bb696705d8bf7a0a78e 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -11,19 +11,19 @@
       "dev": true
     },
     "@angular-devkit/architect": {
-      "version": "0.1000.7",
-      "resolved": "https://registry.npmjs.org/@angular-devkit/architect/-/architect-0.1000.7.tgz",
-      "integrity": "sha512-6pa98C5i+OrBumWobEjjGAeVNbv8m3h3LQQnXtihv9tjxCWceg25jtDhaNzeS6L8D/NsBnVb61MhTaOKUj7kUA==",
+      "version": "0.1001.2",
+      "resolved": "https://registry.npmjs.org/@angular-devkit/architect/-/architect-0.1001.2.tgz",
+      "integrity": "sha512-05o12amjZ8NNIFehKm/lFYf12xvCclC7V5tGl/9+V7g/3pQqakwAjCysgb9T+ETffhmKhMnE8XdAJZqF7YrDcw==",
       "dev": true,
       "requires": {
-        "@angular-devkit/core": "10.0.7",
-        "rxjs": "6.5.5"
+        "@angular-devkit/core": "10.1.2",
+        "rxjs": "6.6.2"
       },
       "dependencies": {
         "rxjs": {
-          "version": "6.5.5",
-          "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.5.5.tgz",
-          "integrity": "sha512-WfQI+1gohdf0Dai/Bbmk5L5ItH5tYqm3ki2c5GdWhKjalzjg93N3avFjVStyZZz+A2Em+ZxKH5bNghw9UeylGQ==",
+          "version": "6.6.2",
+          "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.6.2.tgz",
+          "integrity": "sha512-BHdBMVoWC2sL26w//BCu3YzKT4s2jip/WhwsGEDmeKYBhKDZeYezVUnHatYB7L85v5xs0BAQmg6BEYJEKxBabg==",
           "dev": true,
           "requires": {
             "tslib": "^1.9.0"
@@ -38,111 +38,93 @@
       }
     },
     "@angular-devkit/build-angular": {
-      "version": "0.1000.7",
-      "resolved": "https://registry.npmjs.org/@angular-devkit/build-angular/-/build-angular-0.1000.7.tgz",
-      "integrity": "sha512-EeA+X+pu4w8Io+SpmKBkvVUxuhzgcwaRBi42lKM3D4ot0MtrsSJi6E40t5E/Km6kohibRkDBYY32uT0eG4WHsw==",
-      "dev": true,
-      "requires": {
-        "@angular-devkit/architect": "0.1000.7",
-        "@angular-devkit/build-optimizer": "0.1000.7",
-        "@angular-devkit/build-webpack": "0.1000.7",
-        "@angular-devkit/core": "10.0.7",
-        "@babel/core": "7.9.6",
-        "@babel/generator": "7.9.6",
-        "@babel/plugin-transform-runtime": "7.9.6",
-        "@babel/preset-env": "7.9.6",
-        "@babel/runtime": "7.9.6",
-        "@babel/template": "7.8.6",
-        "@jsdevtools/coverage-istanbul-loader": "3.0.3",
-        "@ngtools/webpack": "10.0.7",
-        "ajv": "6.12.3",
-        "autoprefixer": "9.8.0",
+      "version": "0.1001.2",
+      "resolved": "https://registry.npmjs.org/@angular-devkit/build-angular/-/build-angular-0.1001.2.tgz",
+      "integrity": "sha512-G03ORkh5j0+1rFXcMlwiIbIkrx9LpUeubqCQM+9uHmfTOtS2mLpgiY/ChECyGz6NKhy8GhUmQ9BuVkO8Mh+NAQ==",
+      "dev": true,
+      "requires": {
+        "@angular-devkit/architect": "0.1001.2",
+        "@angular-devkit/build-optimizer": "0.1001.2",
+        "@angular-devkit/build-webpack": "0.1001.2",
+        "@angular-devkit/core": "10.1.2",
+        "@babel/core": "7.11.1",
+        "@babel/generator": "7.11.0",
+        "@babel/plugin-transform-runtime": "7.11.0",
+        "@babel/preset-env": "7.11.0",
+        "@babel/runtime": "7.11.2",
+        "@babel/template": "7.10.4",
+        "@jsdevtools/coverage-istanbul-loader": "3.0.5",
+        "@ngtools/webpack": "10.1.2",
+        "autoprefixer": "9.8.6",
         "babel-loader": "8.1.0",
         "browserslist": "^4.9.1",
-        "cacache": "15.0.3",
+        "cacache": "15.0.5",
         "caniuse-lite": "^1.0.30001032",
         "circular-dependency-plugin": "5.2.0",
         "copy-webpack-plugin": "6.0.3",
         "core-js": "3.6.4",
-        "css-loader": "3.5.3",
+        "css-loader": "4.2.2",
         "cssnano": "4.1.10",
         "file-loader": "6.0.0",
         "find-cache-dir": "3.3.1",
         "glob": "7.1.6",
-        "jest-worker": "26.0.0",
+        "jest-worker": "26.3.0",
         "karma-source-map-support": "1.4.0",
-        "less-loader": "6.1.0",
-        "license-webpack-plugin": "2.2.0",
+        "less-loader": "6.2.0",
+        "license-webpack-plugin": "2.3.0",
         "loader-utils": "2.0.0",
-        "mini-css-extract-plugin": "0.9.0",
+        "mini-css-extract-plugin": "0.10.0",
         "minimatch": "3.0.4",
-        "open": "7.0.4",
-        "parse5": "4.0.0",
+        "open": "7.2.0",
+        "parse5": "6.0.1",
+        "parse5-htmlparser2-tree-adapter": "6.0.1",
         "pnp-webpack-plugin": "1.6.4",
-        "postcss": "7.0.31",
+        "postcss": "7.0.32",
         "postcss-import": "12.0.1",
         "postcss-loader": "3.0.0",
         "raw-loader": "4.0.1",
-        "regenerator-runtime": "0.13.5",
+        "regenerator-runtime": "0.13.7",
         "resolve-url-loader": "3.1.1",
         "rimraf": "3.0.2",
-        "rollup": "2.10.9",
-        "rxjs": "6.5.5",
-        "sass": "1.26.5",
-        "sass-loader": "8.0.2",
+        "rollup": "2.26.5",
+        "rxjs": "6.6.2",
+        "sass": "1.26.10",
+        "sass-loader": "10.0.1",
         "semver": "7.3.2",
         "source-map": "0.7.3",
-        "source-map-loader": "1.0.0",
+        "source-map-loader": "1.0.2",
         "source-map-support": "0.5.19",
         "speed-measure-webpack-plugin": "1.3.3",
         "style-loader": "1.2.1",
-        "stylus": "0.54.7",
+        "stylus": "0.54.8",
         "stylus-loader": "3.0.2",
-        "terser": "4.7.0",
-        "terser-webpack-plugin": "3.0.1",
+        "terser": "5.3.0",
+        "terser-webpack-plugin": "4.1.0",
         "tree-kill": "1.2.2",
-        "webpack": "4.43.0",
+        "webpack": "4.44.1",
         "webpack-dev-middleware": "3.7.2",
         "webpack-dev-server": "3.11.0",
         "webpack-merge": "4.2.2",
         "webpack-sources": "1.4.3",
         "webpack-subresource-integrity": "1.4.1",
-        "worker-plugin": "4.0.3"
+        "worker-plugin": "5.0.0"
       },
       "dependencies": {
         "@babel/runtime": {
-          "version": "7.9.6",
-          "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.9.6.tgz",
-          "integrity": "sha512-64AF1xY3OAkFHqOb9s4jpgk1Mm5vDZ4L3acHvAml+53nO1XbXLuDodsVpO4OIUsmemlUHMxNdYMNJmsvOwLrvQ==",
+          "version": "7.11.2",
+          "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.11.2.tgz",
+          "integrity": "sha512-TeWkU52so0mPtDcaCTxNBI/IHiz0pZgr8VEFqXFtZWpYD08ZB6FaSwVAS8MKRQAP3bYKiVjwysOJgMFY28o6Tw==",
           "dev": true,
           "requires": {
             "regenerator-runtime": "^0.13.4"
           }
         },
-        "ajv": {
-          "version": "6.12.3",
-          "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.3.tgz",
-          "integrity": "sha512-4K0cK3L1hsqk9xIb2z9vs/XU+PGJZ9PNpJRDS9YLzmNdX6jmVPfamLvTJr0aDAusnHyCHO6MjzlkAsgtqp9teA==",
-          "dev": true,
-          "requires": {
-            "fast-deep-equal": "^3.1.1",
-            "fast-json-stable-stringify": "^2.0.0",
-            "json-schema-traverse": "^0.4.1",
-            "uri-js": "^4.2.2"
-          }
-        },
         "core-js": {
           "version": "3.6.4",
           "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.6.4.tgz",
           "integrity": "sha512-4paDGScNgZP2IXXilaffL9X7968RuvwlkK3xWtZRVqgd8SYNiVKRJvkFd1aqqEuPfN7E68ZHEp9hDj6lHj4Hyw==",
           "dev": true
         },
-        "fast-deep-equal": {
-          "version": "3.1.3",
-          "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
-          "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==",
-          "dev": true
-        },
         "glob": {
           "version": "7.1.6",
           "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz",
@@ -157,10 +139,29 @@
             "path-is-absolute": "^1.0.0"
           }
         },
+        "is-wsl": {
+          "version": "2.2.0",
+          "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz",
+          "integrity": "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==",
+          "dev": true,
+          "requires": {
+            "is-docker": "^2.0.0"
+          }
+        },
+        "open": {
+          "version": "7.2.0",
+          "resolved": "https://registry.npmjs.org/open/-/open-7.2.0.tgz",
+          "integrity": "sha512-4HeyhxCvBTI5uBePsAdi55C5fmqnWZ2e2MlmvWi5KW5tdH5rxoiv/aMtbeVxKZc3eWkT1GymMnLG8XC4Rq4TDQ==",
+          "dev": true,
+          "requires": {
+            "is-docker": "^2.0.0",
+            "is-wsl": "^2.1.1"
+          }
+        },
         "regenerator-runtime": {
-          "version": "0.13.5",
-          "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.5.tgz",
-          "integrity": "sha512-ZS5w8CpKFinUzOwW3c83oPeVXoNsrLsaCoLtJvAClH135j/R77RuymhiSErhm2lKcwSCIpmvIWSbDkIfAqKQlA==",
+          "version": "0.13.7",
+          "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.7.tgz",
+          "integrity": "sha512-a54FxoJDIr27pgf7IgeQGxmqUNYrcV338lf/6gH456HZ/PhX+5BcwHXG9ajESmwe6WRO0tAzRUrRmNONWgkrew==",
           "dev": true
         },
         "rimraf": {
@@ -173,9 +174,9 @@
           }
         },
         "rxjs": {
-          "version": "6.5.5",
-          "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.5.5.tgz",
-          "integrity": "sha512-WfQI+1gohdf0Dai/Bbmk5L5ItH5tYqm3ki2c5GdWhKjalzjg93N3avFjVStyZZz+A2Em+ZxKH5bNghw9UeylGQ==",
+          "version": "6.6.2",
+          "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.6.2.tgz",
+          "integrity": "sha512-BHdBMVoWC2sL26w//BCu3YzKT4s2jip/WhwsGEDmeKYBhKDZeYezVUnHatYB7L85v5xs0BAQmg6BEYJEKxBabg==",
           "dev": true,
           "requires": {
             "tslib": "^1.9.0"
@@ -188,9 +189,9 @@
           "dev": true
         },
         "terser": {
-          "version": "4.7.0",
-          "resolved": "https://registry.npmjs.org/terser/-/terser-4.7.0.tgz",
-          "integrity": "sha512-Lfb0RiZcjRDXCC3OSHJpEkxJ9Qeqs6mp2v4jf2MHfy8vGERmVDuvjXdd/EnP5Deme5F2yBRBymKmKHCBg2echw==",
+          "version": "5.3.0",
+          "resolved": "https://registry.npmjs.org/terser/-/terser-5.3.0.tgz",
+          "integrity": "sha512-XTT3D3AwxC54KywJijmY2mxZ8nJiEjBHVYzq8l9OaYuRFWeQNBwvipuzzYEP4e+/AVcd1hqG/CqgsdIRyT45Fg==",
           "dev": true,
           "requires": {
             "commander": "^2.20.0",
@@ -215,40 +216,41 @@
       }
     },
     "@angular-devkit/build-optimizer": {
-      "version": "0.1000.7",
-      "resolved": "https://registry.npmjs.org/@angular-devkit/build-optimizer/-/build-optimizer-0.1000.7.tgz",
-      "integrity": "sha512-7vnj++astDMnsTPEiXgpXCTwo/zbFmJadKTIlHoU9VHxQNwSfPwSCtPuPlxynquJu5zxhs24CNUBLXXH8z9ztQ==",
+      "version": "0.1001.2",
+      "resolved": "https://registry.npmjs.org/@angular-devkit/build-optimizer/-/build-optimizer-0.1001.2.tgz",
+      "integrity": "sha512-aykCI0cP6wEW/6GsV0Rs59doN0n5ztsM2+qFrZMSHyggaNzllVafYbQwVvA7t503QpOsmT5E+kve/S/4dMgmFg==",
       "dev": true,
       "requires": {
         "loader-utils": "2.0.0",
         "source-map": "0.7.3",
-        "tslib": "2.0.0",
+        "tslib": "2.0.1",
+        "typescript": "4.0.2",
         "webpack-sources": "1.4.3"
       },
       "dependencies": {
-        "tslib": {
-          "version": "2.0.0",
-          "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.0.0.tgz",
-          "integrity": "sha512-lTqkx847PI7xEDYJntxZH89L2/aXInsyF2luSafe/+0fHOMjlBNXdH6th7f70qxLDhul7KZK0zC8V5ZIyHl0/g==",
+        "typescript": {
+          "version": "4.0.2",
+          "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.0.2.tgz",
+          "integrity": "sha512-e4ERvRV2wb+rRZ/IQeb3jm2VxBsirQLpQhdxplZ2MEzGvDkkMmPglecnNDfSUBivMjP93vRbngYYDQqQ/78bcQ==",
           "dev": true
         }
       }
     },
     "@angular-devkit/build-webpack": {
-      "version": "0.1000.7",
-      "resolved": "https://registry.npmjs.org/@angular-devkit/build-webpack/-/build-webpack-0.1000.7.tgz",
-      "integrity": "sha512-+QYsEBcpZGVFFwrIlfH/NbChVdfIlnxtoTPjjR7xI5DOgl57sb79hOo4Ev0mPkbbgfn5tjSHvE3rmVQmlYqzcg==",
+      "version": "0.1001.2",
+      "resolved": "https://registry.npmjs.org/@angular-devkit/build-webpack/-/build-webpack-0.1001.2.tgz",
+      "integrity": "sha512-+rdxyZOnTou8yAVU8nU49D0PVuIXGQY+V08KukeZsoszJGlwvqfGq1CMJLFlsq3goszTIDCetgmMYvtbaYVrxw==",
       "dev": true,
       "requires": {
-        "@angular-devkit/architect": "0.1000.7",
-        "@angular-devkit/core": "10.0.7",
-        "rxjs": "6.5.5"
+        "@angular-devkit/architect": "0.1001.2",
+        "@angular-devkit/core": "10.1.2",
+        "rxjs": "6.6.2"
       },
       "dependencies": {
         "rxjs": {
-          "version": "6.5.5",
-          "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.5.5.tgz",
-          "integrity": "sha512-WfQI+1gohdf0Dai/Bbmk5L5ItH5tYqm3ki2c5GdWhKjalzjg93N3avFjVStyZZz+A2Em+ZxKH5bNghw9UeylGQ==",
+          "version": "6.6.2",
+          "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.6.2.tgz",
+          "integrity": "sha512-BHdBMVoWC2sL26w//BCu3YzKT4s2jip/WhwsGEDmeKYBhKDZeYezVUnHatYB7L85v5xs0BAQmg6BEYJEKxBabg==",
           "dev": true,
           "requires": {
             "tslib": "^1.9.0"
@@ -263,22 +265,22 @@
       }
     },
     "@angular-devkit/core": {
-      "version": "10.0.7",
-      "resolved": "https://registry.npmjs.org/@angular-devkit/core/-/core-10.0.7.tgz",
-      "integrity": "sha512-pXaZgsQ8LHpRx4QGAUYDE8GwBQLAtoqPh6oUCwRJwBExm5rl13OGPTBWewHiq0ysV/SnFXvOjxwAaHQvC1AgZw==",
+      "version": "10.1.2",
+      "resolved": "https://registry.npmjs.org/@angular-devkit/core/-/core-10.1.2.tgz",
+      "integrity": "sha512-LMxesiCuXRe3UzPdRouXsC1W73/q6rVtACVoD5GdzmmnZ7cRh7oiwonqT0lEXIKQikMsZUasUOXHD2HoKV6BoA==",
       "dev": true,
       "requires": {
-        "ajv": "6.12.3",
+        "ajv": "6.12.4",
         "fast-json-stable-stringify": "2.1.0",
         "magic-string": "0.25.7",
-        "rxjs": "6.5.5",
+        "rxjs": "6.6.2",
         "source-map": "0.7.3"
       },
       "dependencies": {
         "ajv": {
-          "version": "6.12.3",
-          "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.3.tgz",
-          "integrity": "sha512-4K0cK3L1hsqk9xIb2z9vs/XU+PGJZ9PNpJRDS9YLzmNdX6jmVPfamLvTJr0aDAusnHyCHO6MjzlkAsgtqp9teA==",
+          "version": "6.12.4",
+          "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.4.tgz",
+          "integrity": "sha512-eienB2c9qVQs2KWexhkrdMLVDoIQCz5KSeLxwg9Lzk4DOfBtIK9PQwwufcsn1jjGuf9WZmqPMbGxOzfcuphJCQ==",
           "dev": true,
           "requires": {
             "fast-deep-equal": "^3.1.1",
@@ -300,9 +302,9 @@
           "dev": true
         },
         "rxjs": {
-          "version": "6.5.5",
-          "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.5.5.tgz",
-          "integrity": "sha512-WfQI+1gohdf0Dai/Bbmk5L5ItH5tYqm3ki2c5GdWhKjalzjg93N3avFjVStyZZz+A2Em+ZxKH5bNghw9UeylGQ==",
+          "version": "6.6.2",
+          "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.6.2.tgz",
+          "integrity": "sha512-BHdBMVoWC2sL26w//BCu3YzKT4s2jip/WhwsGEDmeKYBhKDZeYezVUnHatYB7L85v5xs0BAQmg6BEYJEKxBabg==",
           "dev": true,
           "requires": {
             "tslib": "^1.9.0"
@@ -317,20 +319,57 @@
       }
     },
     "@angular-devkit/schematics": {
-      "version": "10.0.7",
-      "resolved": "https://registry.npmjs.org/@angular-devkit/schematics/-/schematics-10.0.7.tgz",
-      "integrity": "sha512-eyyYPgpjtr3h7WbnNbkDubJ/p+8TgKU6abWd+NmBfTvyeHrpVFUYZabNRcdXwUDSVzfTQKdmLynIkESj/KROrg==",
+      "version": "10.1.2",
+      "resolved": "https://registry.npmjs.org/@angular-devkit/schematics/-/schematics-10.1.2.tgz",
+      "integrity": "sha512-gS5yP8ntw3/v9zBK9kBsp5r4gYlp8cLvJ3oWLZmSvdzzbm/QznPnRKqNm72AptKrlxRFX0xyrJ7vjtLWcssqxA==",
       "dev": true,
       "requires": {
-        "@angular-devkit/core": "10.0.7",
-        "ora": "4.0.4",
-        "rxjs": "6.5.5"
+        "@angular-devkit/core": "10.1.2",
+        "ora": "5.0.0",
+        "rxjs": "6.6.2"
       },
       "dependencies": {
+        "@angular-devkit/core": {
+          "version": "10.1.2",
+          "resolved": "https://registry.npmjs.org/@angular-devkit/core/-/core-10.1.2.tgz",
+          "integrity": "sha512-LMxesiCuXRe3UzPdRouXsC1W73/q6rVtACVoD5GdzmmnZ7cRh7oiwonqT0lEXIKQikMsZUasUOXHD2HoKV6BoA==",
+          "dev": true,
+          "requires": {
+            "ajv": "6.12.4",
+            "fast-json-stable-stringify": "2.1.0",
+            "magic-string": "0.25.7",
+            "rxjs": "6.6.2",
+            "source-map": "0.7.3"
+          }
+        },
+        "ajv": {
+          "version": "6.12.4",
+          "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.4.tgz",
+          "integrity": "sha512-eienB2c9qVQs2KWexhkrdMLVDoIQCz5KSeLxwg9Lzk4DOfBtIK9PQwwufcsn1jjGuf9WZmqPMbGxOzfcuphJCQ==",
+          "dev": true,
+          "requires": {
+            "fast-deep-equal": "^3.1.1",
+            "fast-json-stable-stringify": "^2.0.0",
+            "json-schema-traverse": "^0.4.1",
+            "uri-js": "^4.2.2"
+          }
+        },
+        "fast-deep-equal": {
+          "version": "3.1.3",
+          "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
+          "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==",
+          "dev": true
+        },
+        "fast-json-stable-stringify": {
+          "version": "2.1.0",
+          "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz",
+          "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==",
+          "dev": true
+        },
         "rxjs": {
-          "version": "6.5.5",
-          "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.5.5.tgz",
-          "integrity": "sha512-WfQI+1gohdf0Dai/Bbmk5L5ItH5tYqm3ki2c5GdWhKjalzjg93N3avFjVStyZZz+A2Em+ZxKH5bNghw9UeylGQ==",
+          "version": "6.6.2",
+          "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.6.2.tgz",
+          "integrity": "sha512-BHdBMVoWC2sL26w//BCu3YzKT4s2jip/WhwsGEDmeKYBhKDZeYezVUnHatYB7L85v5xs0BAQmg6BEYJEKxBabg==",
           "dev": true,
           "requires": {
             "tslib": "^1.9.0"
@@ -345,24 +384,17 @@
       }
     },
     "@angular/animations": {
-      "version": "10.0.12",
-      "resolved": "https://registry.npmjs.org/@angular/animations/-/animations-10.0.12.tgz",
-      "integrity": "sha512-SnY25jLtAkH0jZAH1vhnGUsIb/qeMvnO379gMdVTtRR2mMqQnyz+d4IwRd7qOb2gYVSKiXQOEiLFV8TGJbx5mQ==",
+      "version": "10.1.2",
+      "resolved": "https://registry.npmjs.org/@angular/animations/-/animations-10.1.2.tgz",
+      "integrity": "sha512-39KSRY61pLaggbuikx4bltJQQ/l54RjPDffZrUJsuCXIpBKHd+ew8CJ3rud+zjhDfA3pETb7WE1jeCNKo6Zo1A==",
       "requires": {
         "tslib": "^2.0.0"
-      },
-      "dependencies": {
-        "tslib": {
-          "version": "2.0.1",
-          "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.0.1.tgz",
-          "integrity": "sha512-SgIkNheinmEBgx1IUNirK0TUD4X9yjjBRTqqjggWCU3pUEqIk3/Uwl3yRixYKT6WjQuGiwDv4NomL3wqRCj+CQ=="
-        }
       }
     },
     "@angular/cdk": {
-      "version": "10.1.3",
-      "resolved": "https://registry.npmjs.org/@angular/cdk/-/cdk-10.1.3.tgz",
-      "integrity": "sha512-xMV1M41mfuaQod4rtAG/duYiWffGIC2C87E1YuyHTh8SEcHopGVRQd2C8PWH+iwinPbes7AjU1uzCEvmOYikrA==",
+      "version": "10.2.1",
+      "resolved": "https://registry.npmjs.org/@angular/cdk/-/cdk-10.2.1.tgz",
+      "integrity": "sha512-67nPfteerlGPlwBeKt+EEOgEo2zm3+U6FzwhXVqwEeBxCZ7PWelMDiartHC7zZnzIKkcNEO0Uptq7Bzl2gdU0w==",
       "requires": {
         "parse5": "^5.0.0",
         "tslib": "^2.0.0"
@@ -377,33 +409,68 @@
       }
     },
     "@angular/cli": {
-      "version": "10.0.7",
-      "resolved": "https://registry.npmjs.org/@angular/cli/-/cli-10.0.7.tgz",
-      "integrity": "sha512-o7aLZ5tIndtWodAGjG58XoKqaQMRyTwxad7s/6LGulH/XPo0v7Nk6f+yopKe2HnZJaIh7sVLaBAUxEvp9F1vaQ==",
+      "version": "10.1.2",
+      "resolved": "https://registry.npmjs.org/@angular/cli/-/cli-10.1.2.tgz",
+      "integrity": "sha512-dBcqFTuT71CCkH4BoV2cN5RP5k8ggzOBijNNtwkQv7N4gNcdcczhoPtEa2v4Oo8mPcTwxf/C3RXZ+NicdROJOw==",
       "dev": true,
       "requires": {
-        "@angular-devkit/architect": "0.1000.7",
-        "@angular-devkit/core": "10.0.7",
-        "@angular-devkit/schematics": "10.0.7",
-        "@schematics/angular": "10.0.7",
-        "@schematics/update": "0.1000.7",
+        "@angular-devkit/architect": "0.1001.2",
+        "@angular-devkit/core": "10.1.2",
+        "@angular-devkit/schematics": "10.1.2",
+        "@schematics/angular": "10.1.2",
+        "@schematics/update": "0.1001.2",
         "@yarnpkg/lockfile": "1.1.0",
         "ansi-colors": "4.1.1",
         "debug": "4.1.1",
         "ini": "1.3.5",
-        "inquirer": "7.1.0",
+        "inquirer": "7.3.3",
         "npm-package-arg": "8.0.1",
         "npm-pick-manifest": "6.1.0",
-        "open": "7.0.4",
+        "open": "7.2.0",
         "pacote": "9.5.12",
         "read-package-tree": "5.3.1",
         "rimraf": "3.0.2",
         "semver": "7.3.2",
         "symbol-observable": "1.2.0",
-        "universal-analytics": "0.4.20",
-        "uuid": "8.1.0"
+        "universal-analytics": "0.4.23",
+        "uuid": "8.3.0"
       },
       "dependencies": {
+        "@angular-devkit/architect": {
+          "version": "0.1001.2",
+          "resolved": "https://registry.npmjs.org/@angular-devkit/architect/-/architect-0.1001.2.tgz",
+          "integrity": "sha512-05o12amjZ8NNIFehKm/lFYf12xvCclC7V5tGl/9+V7g/3pQqakwAjCysgb9T+ETffhmKhMnE8XdAJZqF7YrDcw==",
+          "dev": true,
+          "requires": {
+            "@angular-devkit/core": "10.1.2",
+            "rxjs": "6.6.2"
+          }
+        },
+        "@angular-devkit/core": {
+          "version": "10.1.2",
+          "resolved": "https://registry.npmjs.org/@angular-devkit/core/-/core-10.1.2.tgz",
+          "integrity": "sha512-LMxesiCuXRe3UzPdRouXsC1W73/q6rVtACVoD5GdzmmnZ7cRh7oiwonqT0lEXIKQikMsZUasUOXHD2HoKV6BoA==",
+          "dev": true,
+          "requires": {
+            "ajv": "6.12.4",
+            "fast-json-stable-stringify": "2.1.0",
+            "magic-string": "0.25.7",
+            "rxjs": "6.6.2",
+            "source-map": "0.7.3"
+          }
+        },
+        "ajv": {
+          "version": "6.12.4",
+          "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.4.tgz",
+          "integrity": "sha512-eienB2c9qVQs2KWexhkrdMLVDoIQCz5KSeLxwg9Lzk4DOfBtIK9PQwwufcsn1jjGuf9WZmqPMbGxOzfcuphJCQ==",
+          "dev": true,
+          "requires": {
+            "fast-deep-equal": "^3.1.1",
+            "fast-json-stable-stringify": "^2.0.0",
+            "json-schema-traverse": "^0.4.1",
+            "uri-js": "^4.2.2"
+          }
+        },
         "ansi-colors": {
           "version": "4.1.1",
           "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.1.tgz",
@@ -436,9 +503,9 @@
           }
         },
         "chalk": {
-          "version": "3.0.0",
-          "resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz",
-          "integrity": "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==",
+          "version": "4.1.0",
+          "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.0.tgz",
+          "integrity": "sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A==",
           "dev": true,
           "requires": {
             "ansi-styles": "^4.1.0",
@@ -454,6 +521,12 @@
             "restore-cursor": "^3.1.0"
           }
         },
+        "cli-width": {
+          "version": "3.0.0",
+          "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-3.0.0.tgz",
+          "integrity": "sha512-FxqpkPPwu1HjuN93Omfm4h8uIanXofW0RxVEW3k5RKx+mJJYSthzNhp32Kzxxy3YAEZ/Dc/EWN1vZRY0+kOhbw==",
+          "dev": true
+        },
         "color-convert": {
           "version": "2.0.1",
           "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
@@ -472,6 +545,18 @@
             "ms": "^2.1.1"
           }
         },
+        "fast-deep-equal": {
+          "version": "3.1.3",
+          "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
+          "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==",
+          "dev": true
+        },
+        "fast-json-stable-stringify": {
+          "version": "2.1.0",
+          "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz",
+          "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==",
+          "dev": true
+        },
         "figures": {
           "version": "3.2.0",
           "resolved": "https://registry.npmjs.org/figures/-/figures-3.2.0.tgz",
@@ -497,45 +582,33 @@
           }
         },
         "inquirer": {
-          "version": "7.1.0",
-          "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-7.1.0.tgz",
-          "integrity": "sha512-5fJMWEmikSYu0nv/flMc475MhGbB7TSPd/2IpFV4I4rMklboCH2rQjYY5kKiYGHqUF9gvaambupcJFFG9dvReg==",
+          "version": "7.3.3",
+          "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-7.3.3.tgz",
+          "integrity": "sha512-JG3eIAj5V9CwcGvuOmoo6LB9kbAYT8HXffUl6memuszlwDC/qvFAJw49XJ5NROSFNPxp3iQg1GqkFhaY/CR0IA==",
           "dev": true,
           "requires": {
             "ansi-escapes": "^4.2.1",
-            "chalk": "^3.0.0",
+            "chalk": "^4.1.0",
             "cli-cursor": "^3.1.0",
-            "cli-width": "^2.0.0",
+            "cli-width": "^3.0.0",
             "external-editor": "^3.0.3",
             "figures": "^3.0.0",
-            "lodash": "^4.17.15",
+            "lodash": "^4.17.19",
             "mute-stream": "0.0.8",
             "run-async": "^2.4.0",
-            "rxjs": "^6.5.3",
+            "rxjs": "^6.6.0",
             "string-width": "^4.1.0",
             "strip-ansi": "^6.0.0",
             "through": "^2.3.6"
           }
         },
-        "is-fullwidth-code-point": {
-          "version": "3.0.0",
-          "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz",
-          "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==",
-          "dev": true
-        },
-        "lodash": {
-          "version": "4.17.20",
-          "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.20.tgz",
-          "integrity": "sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA==",
-          "dev": true
-        },
-        "lru-cache": {
-          "version": "6.0.0",
-          "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz",
-          "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==",
+        "is-wsl": {
+          "version": "2.2.0",
+          "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz",
+          "integrity": "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==",
           "dev": true,
           "requires": {
-            "yallist": "^4.0.0"
+            "is-docker": "^2.0.0"
           }
         },
         "ms": {
@@ -544,12 +617,6 @@
           "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
           "dev": true
         },
-        "mute-stream": {
-          "version": "0.0.8",
-          "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.8.tgz",
-          "integrity": "sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==",
-          "dev": true
-        },
         "npm-package-arg": {
           "version": "8.0.1",
           "resolved": "https://registry.npmjs.org/npm-package-arg/-/npm-package-arg-8.0.1.tgz",
@@ -561,13 +628,14 @@
             "validate-npm-package-name": "^3.0.0"
           }
         },
-        "onetime": {
-          "version": "5.1.2",
-          "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz",
-          "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==",
+        "open": {
+          "version": "7.2.0",
+          "resolved": "https://registry.npmjs.org/open/-/open-7.2.0.tgz",
+          "integrity": "sha512-4HeyhxCvBTI5uBePsAdi55C5fmqnWZ2e2MlmvWi5KW5tdH5rxoiv/aMtbeVxKZc3eWkT1GymMnLG8XC4Rq4TDQ==",
           "dev": true,
           "requires": {
-            "mimic-fn": "^2.1.0"
+            "is-docker": "^2.0.0",
+            "is-wsl": "^2.1.1"
           }
         },
         "restore-cursor": {
@@ -595,23 +663,21 @@
           "integrity": "sha512-tvVnVv01b8c1RrA6Ep7JkStj85Guv/YrMcwqYQnwjsAS2cTmmPGBBjAjpCW7RrSodNSoE2/qg9O4bceNvUuDgQ==",
           "dev": true
         },
+        "rxjs": {
+          "version": "6.6.2",
+          "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.6.2.tgz",
+          "integrity": "sha512-BHdBMVoWC2sL26w//BCu3YzKT4s2jip/WhwsGEDmeKYBhKDZeYezVUnHatYB7L85v5xs0BAQmg6BEYJEKxBabg==",
+          "dev": true,
+          "requires": {
+            "tslib": "^1.9.0"
+          }
+        },
         "semver": {
           "version": "7.3.2",
           "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.2.tgz",
           "integrity": "sha512-OrOb32TeeambH6UrhtShmF7CRDqhL6/5XpPNp2DuRH6+9QLw/orhp72j87v8Qa1ScDkvrrBNpZcDejAirJmfXQ==",
           "dev": true
         },
-        "string-width": {
-          "version": "4.2.0",
-          "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.0.tgz",
-          "integrity": "sha512-zUz5JD+tgqtuDjMhwIg5uFVV3dtqZ9yQJlZVfq4I01/K5Paj5UHj7VyrQOJvzawSVlKpObApbfD0Ed6yJc+1eg==",
-          "dev": true,
-          "requires": {
-            "emoji-regex": "^8.0.0",
-            "is-fullwidth-code-point": "^3.0.0",
-            "strip-ansi": "^6.0.0"
-          }
-        },
         "strip-ansi": {
           "version": "6.0.0",
           "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz",
@@ -622,68 +688,48 @@
           }
         },
         "supports-color": {
-          "version": "7.1.0",
-          "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.1.0.tgz",
-          "integrity": "sha512-oRSIpR8pxT1Wr2FquTNnGet79b3BWljqOuoW/h4oBhxJ/HUbX5nX6JSruTkvXDCFMwDPvsaTTbvMLKZWSy0R5g==",
+          "version": "7.2.0",
+          "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
+          "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
           "dev": true,
           "requires": {
             "has-flag": "^4.0.0"
           }
         },
-        "type-fest": {
-          "version": "0.11.0",
-          "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.11.0.tgz",
-          "integrity": "sha512-OdjXJxnCN1AvyLSzeKIgXTXxV+99ZuXl3Hpo9XpJAv9MBcHrrJOQ5kV7ypXOuQie+AmWG25hLbiKdwYTifzcfQ==",
+        "tslib": {
+          "version": "1.13.0",
+          "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.13.0.tgz",
+          "integrity": "sha512-i/6DQjL8Xf3be4K/E6Wgpekn5Qasl1usyw++dAA35Ue5orEn65VIxOA+YvNNl9HV3qv70T7CNwjODHZrLwvd1Q==",
           "dev": true
         },
         "uuid": {
-          "version": "8.1.0",
-          "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.1.0.tgz",
-          "integrity": "sha512-CI18flHDznR0lq54xBycOVmphdCYnQLKn8abKn7PXUiKUGdEd+/l9LWNJmugXel4hXq7S+RMNl34ecyC9TntWg==",
-          "dev": true
-        },
-        "yallist": {
-          "version": "4.0.0",
-          "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
-          "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==",
+          "version": "8.3.0",
+          "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.0.tgz",
+          "integrity": "sha512-fX6Z5o4m6XsXBdli9g7DtWgAx+osMsRRZFKma1mIUsLCz6vRvv+pz5VNbyu9UEDzpMWulZfvpgb/cmDXVulYFQ==",
           "dev": true
         }
       }
     },
     "@angular/common": {
-      "version": "10.0.12",
-      "resolved": "https://registry.npmjs.org/@angular/common/-/common-10.0.12.tgz",
-      "integrity": "sha512-nIWXeLEWU3v4/GprKUtucFoVwNWpoD9DL1RWvOkyXT3tXm/Z8zGwXGKPJ13O2p6E22nChx3GauLKjSUmg1SWww==",
+      "version": "10.1.2",
+      "resolved": "https://registry.npmjs.org/@angular/common/-/common-10.1.2.tgz",
+      "integrity": "sha512-zsWZN30sUJVXcakKK+B7ANzDZNK5fqZRwawCp5IteUNveqxfl70CqSTft0twOnva0NGsiTgix9WH5XqnUJqYzg==",
       "requires": {
         "tslib": "^2.0.0"
-      },
-      "dependencies": {
-        "tslib": {
-          "version": "2.0.1",
-          "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.0.1.tgz",
-          "integrity": "sha512-SgIkNheinmEBgx1IUNirK0TUD4X9yjjBRTqqjggWCU3pUEqIk3/Uwl3yRixYKT6WjQuGiwDv4NomL3wqRCj+CQ=="
-        }
       }
     },
     "@angular/compiler": {
-      "version": "10.0.12",
-      "resolved": "https://registry.npmjs.org/@angular/compiler/-/compiler-10.0.12.tgz",
-      "integrity": "sha512-g7BBC69/LW8Qd98IKL+YAY8vSJyc1WHuMejdMq56hU4h8FzLUKJZeKfsDe9MbiIqoPr9DWcDu4dtcg/g4Rc5/w==",
+      "version": "10.1.2",
+      "resolved": "https://registry.npmjs.org/@angular/compiler/-/compiler-10.1.2.tgz",
+      "integrity": "sha512-P7AMt15HwCXVBZcTqh9HqQcSTRzSy1cUjOjy+POz4C5VRAzpOXMUkh5mlbv9FtnrfmCIili7hBrf06a/q8orPQ==",
       "requires": {
         "tslib": "^2.0.0"
-      },
-      "dependencies": {
-        "tslib": {
-          "version": "2.0.1",
-          "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.0.1.tgz",
-          "integrity": "sha512-SgIkNheinmEBgx1IUNirK0TUD4X9yjjBRTqqjggWCU3pUEqIk3/Uwl3yRixYKT6WjQuGiwDv4NomL3wqRCj+CQ=="
-        }
       }
     },
     "@angular/compiler-cli": {
-      "version": "10.0.12",
-      "resolved": "https://registry.npmjs.org/@angular/compiler-cli/-/compiler-cli-10.0.12.tgz",
-      "integrity": "sha512-biFAxoQKxARpu/PMs8McS5flaPTnAFQ6y/xbBg8ItstzxdTjyuQSuYdvgK48Vd0c8eRv8mEgne3f/Cf7U43nDA==",
+      "version": "10.1.2",
+      "resolved": "https://registry.npmjs.org/@angular/compiler-cli/-/compiler-cli-10.1.2.tgz",
+      "integrity": "sha512-oZ6uSmiJ5JnNpLYhpEpKOXIU90mAidjMY0u/aJcCQnARWa/t72c/txlEkiB0CO41Hi6k3Hqb4XAERmIzQ6H59A==",
       "dev": true,
       "requires": {
         "canonical-path": "1.0.0",
@@ -701,42 +747,6 @@
         "yargs": "15.3.0"
       },
       "dependencies": {
-        "ansi-regex": {
-          "version": "5.0.0",
-          "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz",
-          "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==",
-          "dev": true
-        },
-        "ansi-styles": {
-          "version": "4.2.1",
-          "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.2.1.tgz",
-          "integrity": "sha512-9VGjrMsG1vePxcSweQsN20KY/c4zN0h9fLjqAbwbPfahM3t+NL+M9HC8xeXG2I8pX5NoamTGNuomEUFI7fcUjA==",
-          "dev": true,
-          "requires": {
-            "@types/color-name": "^1.1.1",
-            "color-convert": "^2.0.1"
-          }
-        },
-        "cliui": {
-          "version": "6.0.0",
-          "resolved": "https://registry.npmjs.org/cliui/-/cliui-6.0.0.tgz",
-          "integrity": "sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ==",
-          "dev": true,
-          "requires": {
-            "string-width": "^4.2.0",
-            "strip-ansi": "^6.0.0",
-            "wrap-ansi": "^6.2.0"
-          }
-        },
-        "color-convert": {
-          "version": "2.0.1",
-          "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
-          "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
-          "dev": true,
-          "requires": {
-            "color-name": "~1.1.4"
-          }
-        },
         "find-up": {
           "version": "4.1.0",
           "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz",
@@ -758,18 +768,6 @@
             "universalify": "^0.1.0"
           }
         },
-        "get-caller-file": {
-          "version": "2.0.5",
-          "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz",
-          "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==",
-          "dev": true
-        },
-        "is-fullwidth-code-point": {
-          "version": "3.0.0",
-          "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz",
-          "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==",
-          "dev": true
-        },
         "locate-path": {
           "version": "5.0.0",
           "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz",
@@ -794,12 +792,6 @@
           "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==",
           "dev": true
         },
-        "require-main-filename": {
-          "version": "2.0.0",
-          "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz",
-          "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==",
-          "dev": true
-        },
         "semver": {
           "version": "6.3.0",
           "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
@@ -812,87 +804,33 @@
           "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
           "dev": true
         },
-        "string-width": {
-          "version": "4.2.0",
-          "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.0.tgz",
-          "integrity": "sha512-zUz5JD+tgqtuDjMhwIg5uFVV3dtqZ9yQJlZVfq4I01/K5Paj5UHj7VyrQOJvzawSVlKpObApbfD0Ed6yJc+1eg==",
+        "yargs": {
+          "version": "15.3.0",
+          "resolved": "https://registry.npmjs.org/yargs/-/yargs-15.3.0.tgz",
+          "integrity": "sha512-g/QCnmjgOl1YJjGsnUg2SatC7NUYEiLXJqxNOQU9qSpjzGtGXda9b+OKccr1kLTy8BN9yqEyqfq5lxlwdc13TA==",
           "dev": true,
           "requires": {
-            "emoji-regex": "^8.0.0",
-            "is-fullwidth-code-point": "^3.0.0",
-            "strip-ansi": "^6.0.0"
-          }
-        },
-        "strip-ansi": {
-          "version": "6.0.0",
-          "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz",
-          "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==",
-          "dev": true,
-          "requires": {
-            "ansi-regex": "^5.0.0"
-          }
-        },
-        "tslib": {
-          "version": "2.0.1",
-          "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.0.1.tgz",
-          "integrity": "sha512-SgIkNheinmEBgx1IUNirK0TUD4X9yjjBRTqqjggWCU3pUEqIk3/Uwl3yRixYKT6WjQuGiwDv4NomL3wqRCj+CQ==",
-          "dev": true
-        },
-        "wrap-ansi": {
-          "version": "6.2.0",
-          "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz",
-          "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==",
-          "dev": true,
-          "requires": {
-            "ansi-styles": "^4.0.0",
-            "string-width": "^4.1.0",
-            "strip-ansi": "^6.0.0"
-          }
-        },
-        "yargs": {
-          "version": "15.3.0",
-          "resolved": "https://registry.npmjs.org/yargs/-/yargs-15.3.0.tgz",
-          "integrity": "sha512-g/QCnmjgOl1YJjGsnUg2SatC7NUYEiLXJqxNOQU9qSpjzGtGXda9b+OKccr1kLTy8BN9yqEyqfq5lxlwdc13TA==",
-          "dev": true,
-          "requires": {
-            "cliui": "^6.0.0",
-            "decamelize": "^1.2.0",
-            "find-up": "^4.1.0",
-            "get-caller-file": "^2.0.1",
-            "require-directory": "^2.1.1",
-            "require-main-filename": "^2.0.0",
-            "set-blocking": "^2.0.0",
-            "string-width": "^4.2.0",
-            "which-module": "^2.0.0",
-            "y18n": "^4.0.0",
-            "yargs-parser": "^18.1.0"
-          }
-        },
-        "yargs-parser": {
-          "version": "18.1.3",
-          "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-18.1.3.tgz",
-          "integrity": "sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ==",
-          "dev": true,
-          "requires": {
-            "camelcase": "^5.0.0",
-            "decamelize": "^1.2.0"
+            "cliui": "^6.0.0",
+            "decamelize": "^1.2.0",
+            "find-up": "^4.1.0",
+            "get-caller-file": "^2.0.1",
+            "require-directory": "^2.1.1",
+            "require-main-filename": "^2.0.0",
+            "set-blocking": "^2.0.0",
+            "string-width": "^4.2.0",
+            "which-module": "^2.0.0",
+            "y18n": "^4.0.0",
+            "yargs-parser": "^18.1.0"
           }
         }
       }
     },
     "@angular/core": {
-      "version": "10.0.12",
-      "resolved": "https://registry.npmjs.org/@angular/core/-/core-10.0.12.tgz",
-      "integrity": "sha512-qwnZ95HtWH2PBZs93iTXa9fvYCg203c/CnbzHNfMTZXcwaEBEEA7nuUBmjQt+VA8ib2BjO8CkepLNJI0pgo29w==",
+      "version": "10.1.2",
+      "resolved": "https://registry.npmjs.org/@angular/core/-/core-10.1.2.tgz",
+      "integrity": "sha512-iBVkCgXMp3TofrbZVwpuSbLAiLHF/fbx9xHnFcjBQUXBUIoxiEB4NcrPHibmBVNX0J45hO6iLsG+ZtFZbMifNg==",
       "requires": {
         "tslib": "^2.0.0"
-      },
-      "dependencies": {
-        "tslib": {
-          "version": "2.0.1",
-          "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.0.1.tgz",
-          "integrity": "sha512-SgIkNheinmEBgx1IUNirK0TUD4X9yjjBRTqqjggWCU3pUEqIk3/Uwl3yRixYKT6WjQuGiwDv4NomL3wqRCj+CQ=="
-        }
       }
     },
     "@angular/flex-layout": {
@@ -904,77 +842,49 @@
       }
     },
     "@angular/forms": {
-      "version": "10.0.12",
-      "resolved": "https://registry.npmjs.org/@angular/forms/-/forms-10.0.12.tgz",
-      "integrity": "sha512-otFD0ASqD1RMlpnI1OGHCSSDBRsnnz+/Hp5TV7TzqqIsyN9n0SyRw1/ZHMTNLx9JQf+QWhq2pXOOGBYqSiG54Q==",
+      "version": "10.1.2",
+      "resolved": "https://registry.npmjs.org/@angular/forms/-/forms-10.1.2.tgz",
+      "integrity": "sha512-BzzhKabLdI7JZAGz6oa+7ITEpVGhR+Tu0nhRsgyjZijz02vWAMexr1xXILLgCNMiMG509WDFvIbTwsd6lIFsXA==",
       "requires": {
         "tslib": "^2.0.0"
-      },
-      "dependencies": {
-        "tslib": {
-          "version": "2.0.1",
-          "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.0.1.tgz",
-          "integrity": "sha512-SgIkNheinmEBgx1IUNirK0TUD4X9yjjBRTqqjggWCU3pUEqIk3/Uwl3yRixYKT6WjQuGiwDv4NomL3wqRCj+CQ=="
-        }
       }
     },
     "@angular/language-service": {
-      "version": "10.0.12",
-      "resolved": "https://registry.npmjs.org/@angular/language-service/-/language-service-10.0.12.tgz",
-      "integrity": "sha512-zsEzFu5D1Wm14we625R5IsvYKxuLxCE0VkZVVB402vJFImJNUNrXt/prY5mEnqePnK8fAjJLtJfpn64q8IWXBg==",
+      "version": "10.1.2",
+      "resolved": "https://registry.npmjs.org/@angular/language-service/-/language-service-10.1.2.tgz",
+      "integrity": "sha512-NYAvbiqzj2cxIAFiqZQSEVqbKaRaJKEn/qRlzMbfELbJV3Vwzw6oDwV550LnX4ZXOdsfMvEV4zJLBjUMDbpevg==",
       "dev": true
     },
     "@angular/material": {
-      "version": "10.1.3",
-      "resolved": "https://registry.npmjs.org/@angular/material/-/material-10.1.3.tgz",
-      "integrity": "sha512-6ygbCVcejFydmZUlOcNreiWQTvL4kOrEp/M51DV70hqffTnxajCzaRe2MQhxisENB/bR8mtMvf8YY3Rsys/HCw==",
+      "version": "10.2.1",
+      "resolved": "https://registry.npmjs.org/@angular/material/-/material-10.2.1.tgz",
+      "integrity": "sha512-TSfjW4w3orzDtTstNcNR2zsfNcO/R7NNmDMQ11LO6+EfnbNF2yktsMS3FZl811GX6dXEE+R/GCdDgCnlvqv9Mw==",
       "requires": {
         "tslib": "^2.0.0"
       }
     },
     "@angular/platform-browser": {
-      "version": "10.0.12",
-      "resolved": "https://registry.npmjs.org/@angular/platform-browser/-/platform-browser-10.0.12.tgz",
-      "integrity": "sha512-w6R81GGgYS+l221yvibomkf0gQTaiontBLzafJXHyHWIXd1A3oVAaNfLzVpHy5kAfd1YruExRJOjDZ6T4iIfyA==",
+      "version": "10.1.2",
+      "resolved": "https://registry.npmjs.org/@angular/platform-browser/-/platform-browser-10.1.2.tgz",
+      "integrity": "sha512-zI6YUy2juR8y8jDfdGGYHxZ9kv3wDZzFj49CObx9GU6+ijQ9FsFCWnsB44LmlzC17xCoQ9wn+zYIHtpdf80zvA==",
       "requires": {
         "tslib": "^2.0.0"
-      },
-      "dependencies": {
-        "tslib": {
-          "version": "2.0.1",
-          "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.0.1.tgz",
-          "integrity": "sha512-SgIkNheinmEBgx1IUNirK0TUD4X9yjjBRTqqjggWCU3pUEqIk3/Uwl3yRixYKT6WjQuGiwDv4NomL3wqRCj+CQ=="
-        }
       }
     },
     "@angular/platform-browser-dynamic": {
-      "version": "10.0.12",
-      "resolved": "https://registry.npmjs.org/@angular/platform-browser-dynamic/-/platform-browser-dynamic-10.0.12.tgz",
-      "integrity": "sha512-izNbYVJiJOT90+Up58Y+E6WHP3CdrS94CZpFwkJFFgRfHu7uKvNrFnB3EkDr5+Lw+RZ8RN5O7QRzUPtG//AGEQ==",
+      "version": "10.1.2",
+      "resolved": "https://registry.npmjs.org/@angular/platform-browser-dynamic/-/platform-browser-dynamic-10.1.2.tgz",
+      "integrity": "sha512-ePxQdVSh3pJLq4Zxc+27VW+ekyU5MGrGDT/gpLhzXWu1EEUe786Q9fM4T6yA7mDP/1XF7HngF3hlMqla2ayqeA==",
       "requires": {
         "tslib": "^2.0.0"
-      },
-      "dependencies": {
-        "tslib": {
-          "version": "2.0.1",
-          "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.0.1.tgz",
-          "integrity": "sha512-SgIkNheinmEBgx1IUNirK0TUD4X9yjjBRTqqjggWCU3pUEqIk3/Uwl3yRixYKT6WjQuGiwDv4NomL3wqRCj+CQ=="
-        }
       }
     },
     "@angular/router": {
-      "version": "10.0.12",
-      "resolved": "https://registry.npmjs.org/@angular/router/-/router-10.0.12.tgz",
-      "integrity": "sha512-utBfsIiVsFNydGtJexvEskYYgQXAd4+1KVxr5wVfND+AfV9EjC7YhMNdySq72ZRNrtQDpDpSlTHvoz5iVeEraw==",
+      "version": "10.1.2",
+      "resolved": "https://registry.npmjs.org/@angular/router/-/router-10.1.2.tgz",
+      "integrity": "sha512-JufAdFyTsB9I9aMD/WNBaI4Fi81SuN6cJm9idSwsUHbEOfB96aQL4dfNEOarzfD9KtDi1vADzkrmVRc2tz2qNw==",
       "requires": {
         "tslib": "^2.0.0"
-      },
-      "dependencies": {
-        "tslib": {
-          "version": "2.0.1",
-          "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.0.1.tgz",
-          "integrity": "sha512-SgIkNheinmEBgx1IUNirK0TUD4X9yjjBRTqqjggWCU3pUEqIk3/Uwl3yRixYKT6WjQuGiwDv4NomL3wqRCj+CQ=="
-        }
       }
     },
     "@babel/code-frame": {
@@ -983,6 +893,18 @@
       "integrity": "sha512-vG6SvB6oYEhvgisZNFRmRCUkLz11c7rp+tbNTynGqc6mS1d5ATd/sGyV6W0KZZnXRKMTzZDRgQT3Ou9jhpAfUg==",
       "requires": {
         "@babel/highlight": "^7.10.4"
+      },
+      "dependencies": {
+        "@babel/highlight": {
+          "version": "7.10.4",
+          "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.10.4.tgz",
+          "integrity": "sha512-i6rgnR/YgPEQzZZnbTHHuZdlE8qyoBNalD6F+q4vAFlcMEcqmkoG+mPqJYJCo63qPf74+Y1UZsl3l6f7/RIkmA==",
+          "requires": {
+            "@babel/helper-validator-identifier": "^7.10.4",
+            "chalk": "^2.0.0",
+            "js-tokens": "^4.0.0"
+          }
+        }
       }
     },
     "@babel/compat-data": {
@@ -997,48 +919,34 @@
       }
     },
     "@babel/core": {
-      "version": "7.9.6",
-      "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.9.6.tgz",
-      "integrity": "sha512-nD3deLvbsApbHAHttzIssYqgb883yU/d9roe4RZymBCDaZryMJDbptVpEpeQuRh4BJ+SYI8le9YGxKvFEvl1Wg==",
-      "dev": true,
-      "requires": {
-        "@babel/code-frame": "^7.8.3",
-        "@babel/generator": "^7.9.6",
-        "@babel/helper-module-transforms": "^7.9.0",
-        "@babel/helpers": "^7.9.6",
-        "@babel/parser": "^7.9.6",
-        "@babel/template": "^7.8.6",
-        "@babel/traverse": "^7.9.6",
-        "@babel/types": "^7.9.6",
+      "version": "7.11.1",
+      "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.11.1.tgz",
+      "integrity": "sha512-XqF7F6FWQdKGGWAzGELL+aCO1p+lRY5Tj5/tbT3St1G8NaH70jhhDIKknIZaDans0OQBG5wRAldROLHSt44BgQ==",
+      "dev": true,
+      "requires": {
+        "@babel/code-frame": "^7.10.4",
+        "@babel/generator": "^7.11.0",
+        "@babel/helper-module-transforms": "^7.11.0",
+        "@babel/helpers": "^7.10.4",
+        "@babel/parser": "^7.11.1",
+        "@babel/template": "^7.10.4",
+        "@babel/traverse": "^7.11.0",
+        "@babel/types": "^7.11.0",
         "convert-source-map": "^1.7.0",
         "debug": "^4.1.0",
         "gensync": "^1.0.0-beta.1",
         "json5": "^2.1.2",
-        "lodash": "^4.17.13",
+        "lodash": "^4.17.19",
         "resolve": "^1.3.2",
         "semver": "^5.4.1",
         "source-map": "^0.5.0"
       },
       "dependencies": {
-        "@babel/code-frame": {
-          "version": "7.10.4",
-          "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.10.4.tgz",
-          "integrity": "sha512-vG6SvB6oYEhvgisZNFRmRCUkLz11c7rp+tbNTynGqc6mS1d5ATd/sGyV6W0KZZnXRKMTzZDRgQT3Ou9jhpAfUg==",
-          "dev": true,
-          "requires": {
-            "@babel/highlight": "^7.10.4"
-          }
-        },
-        "@babel/highlight": {
-          "version": "7.10.4",
-          "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.10.4.tgz",
-          "integrity": "sha512-i6rgnR/YgPEQzZZnbTHHuZdlE8qyoBNalD6F+q4vAFlcMEcqmkoG+mPqJYJCo63qPf74+Y1UZsl3l6f7/RIkmA==",
-          "dev": true,
-          "requires": {
-            "@babel/helper-validator-identifier": "^7.10.4",
-            "chalk": "^2.0.0",
-            "js-tokens": "^4.0.0"
-          }
+        "@babel/parser": {
+          "version": "7.11.5",
+          "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.11.5.tgz",
+          "integrity": "sha512-X9rD8qqm695vgmeaQ4fvz/o3+Wk4ZzQvSHkDBgpYKxpD4qTAUm88ZKtHkVqIOsYFFbIQ6wQYhC6q7pjqVK0E0Q==",
+          "dev": true
         },
         "convert-source-map": {
           "version": "1.7.0",
@@ -1073,14 +981,13 @@
       }
     },
     "@babel/generator": {
-      "version": "7.9.6",
-      "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.9.6.tgz",
-      "integrity": "sha512-+htwWKJbH2bL72HRluF8zumBxzuX0ZZUFl3JLNyoUjM/Ho8wnVpPXM6aUz8cfKDqQ/h7zHqKt4xzJteUosckqQ==",
+      "version": "7.11.0",
+      "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.11.0.tgz",
+      "integrity": "sha512-fEm3Uzw7Mc9Xi//qU20cBKatTfs2aOtKqmvy/Vm7RkJEGFQ4xc9myCfbXxqK//ZS8MR/ciOHw6meGASJuKmDfQ==",
       "dev": true,
       "requires": {
-        "@babel/types": "^7.9.6",
+        "@babel/types": "^7.11.0",
         "jsesc": "^2.5.1",
-        "lodash": "^4.17.13",
         "source-map": "^0.5.0"
       },
       "dependencies": {
@@ -1124,6 +1031,20 @@
         "semver": "^5.5.0"
       }
     },
+    "@babel/helper-create-class-features-plugin": {
+      "version": "7.10.5",
+      "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.10.5.tgz",
+      "integrity": "sha512-0nkdeijB7VlZoLT3r/mY3bUkw3T8WG/hNw+FATs/6+pG2039IJWjTYL0VTISqsNHMUTEnwbVnc89WIJX9Qed0A==",
+      "dev": true,
+      "requires": {
+        "@babel/helper-function-name": "^7.10.4",
+        "@babel/helper-member-expression-to-functions": "^7.10.5",
+        "@babel/helper-optimise-call-expression": "^7.10.4",
+        "@babel/helper-plugin-utils": "^7.10.4",
+        "@babel/helper-replace-supers": "^7.10.4",
+        "@babel/helper-split-export-declaration": "^7.10.4"
+      }
+    },
     "@babel/helper-create-regexp-features-plugin": {
       "version": "7.10.4",
       "resolved": "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.10.4.tgz",
@@ -1144,14 +1065,6 @@
         "@babel/helper-function-name": "^7.10.4",
         "@babel/types": "^7.10.5",
         "lodash": "^4.17.19"
-      },
-      "dependencies": {
-        "lodash": {
-          "version": "4.17.20",
-          "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.20.tgz",
-          "integrity": "sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA==",
-          "dev": true
-        }
       }
     },
     "@babel/helper-explode-assignable-expression": {
@@ -1251,45 +1164,6 @@
         "@babel/template": "^7.10.4",
         "@babel/types": "^7.11.0",
         "lodash": "^4.17.19"
-      },
-      "dependencies": {
-        "@babel/code-frame": {
-          "version": "7.10.4",
-          "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.10.4.tgz",
-          "integrity": "sha512-vG6SvB6oYEhvgisZNFRmRCUkLz11c7rp+tbNTynGqc6mS1d5ATd/sGyV6W0KZZnXRKMTzZDRgQT3Ou9jhpAfUg==",
-          "dev": true,
-          "requires": {
-            "@babel/highlight": "^7.10.4"
-          }
-        },
-        "@babel/highlight": {
-          "version": "7.10.4",
-          "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.10.4.tgz",
-          "integrity": "sha512-i6rgnR/YgPEQzZZnbTHHuZdlE8qyoBNalD6F+q4vAFlcMEcqmkoG+mPqJYJCo63qPf74+Y1UZsl3l6f7/RIkmA==",
-          "dev": true,
-          "requires": {
-            "@babel/helper-validator-identifier": "^7.10.4",
-            "chalk": "^2.0.0",
-            "js-tokens": "^4.0.0"
-          }
-        },
-        "@babel/template": {
-          "version": "7.10.4",
-          "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.10.4.tgz",
-          "integrity": "sha512-ZCjD27cGJFUB6nmCB1Enki3r+L5kJveX9pq1SvAUKoICy6CZ9yD8xO086YXdYhvNjBdnekm4ZnaP5yC8Cs/1tA==",
-          "dev": true,
-          "requires": {
-            "@babel/code-frame": "^7.10.4",
-            "@babel/parser": "^7.10.4",
-            "@babel/types": "^7.10.4"
-          }
-        },
-        "lodash": {
-          "version": "4.17.20",
-          "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.20.tgz",
-          "integrity": "sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA==",
-          "dev": true
-        }
       }
     },
     "@babel/helper-optimise-call-expression": {
@@ -1314,14 +1188,6 @@
       "dev": true,
       "requires": {
         "lodash": "^4.17.19"
-      },
-      "dependencies": {
-        "lodash": {
-          "version": "4.17.20",
-          "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.20.tgz",
-          "integrity": "sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA==",
-          "dev": true
-        }
       }
     },
     "@babel/helper-remap-async-to-generator": {
@@ -1334,39 +1200,6 @@
         "@babel/helper-wrap-function": "^7.10.4",
         "@babel/template": "^7.10.4",
         "@babel/types": "^7.10.4"
-      },
-      "dependencies": {
-        "@babel/code-frame": {
-          "version": "7.10.4",
-          "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.10.4.tgz",
-          "integrity": "sha512-vG6SvB6oYEhvgisZNFRmRCUkLz11c7rp+tbNTynGqc6mS1d5ATd/sGyV6W0KZZnXRKMTzZDRgQT3Ou9jhpAfUg==",
-          "dev": true,
-          "requires": {
-            "@babel/highlight": "^7.10.4"
-          }
-        },
-        "@babel/highlight": {
-          "version": "7.10.4",
-          "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.10.4.tgz",
-          "integrity": "sha512-i6rgnR/YgPEQzZZnbTHHuZdlE8qyoBNalD6F+q4vAFlcMEcqmkoG+mPqJYJCo63qPf74+Y1UZsl3l6f7/RIkmA==",
-          "dev": true,
-          "requires": {
-            "@babel/helper-validator-identifier": "^7.10.4",
-            "chalk": "^2.0.0",
-            "js-tokens": "^4.0.0"
-          }
-        },
-        "@babel/template": {
-          "version": "7.10.4",
-          "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.10.4.tgz",
-          "integrity": "sha512-ZCjD27cGJFUB6nmCB1Enki3r+L5kJveX9pq1SvAUKoICy6CZ9yD8xO086YXdYhvNjBdnekm4ZnaP5yC8Cs/1tA==",
-          "dev": true,
-          "requires": {
-            "@babel/code-frame": "^7.10.4",
-            "@babel/parser": "^7.10.4",
-            "@babel/types": "^7.10.4"
-          }
-        }
       }
     },
     "@babel/helper-replace-supers": {
@@ -1389,39 +1222,6 @@
       "requires": {
         "@babel/template": "^7.10.4",
         "@babel/types": "^7.10.4"
-      },
-      "dependencies": {
-        "@babel/code-frame": {
-          "version": "7.10.4",
-          "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.10.4.tgz",
-          "integrity": "sha512-vG6SvB6oYEhvgisZNFRmRCUkLz11c7rp+tbNTynGqc6mS1d5ATd/sGyV6W0KZZnXRKMTzZDRgQT3Ou9jhpAfUg==",
-          "dev": true,
-          "requires": {
-            "@babel/highlight": "^7.10.4"
-          }
-        },
-        "@babel/highlight": {
-          "version": "7.10.4",
-          "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.10.4.tgz",
-          "integrity": "sha512-i6rgnR/YgPEQzZZnbTHHuZdlE8qyoBNalD6F+q4vAFlcMEcqmkoG+mPqJYJCo63qPf74+Y1UZsl3l6f7/RIkmA==",
-          "dev": true,
-          "requires": {
-            "@babel/helper-validator-identifier": "^7.10.4",
-            "chalk": "^2.0.0",
-            "js-tokens": "^4.0.0"
-          }
-        },
-        "@babel/template": {
-          "version": "7.10.4",
-          "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.10.4.tgz",
-          "integrity": "sha512-ZCjD27cGJFUB6nmCB1Enki3r+L5kJveX9pq1SvAUKoICy6CZ9yD8xO086YXdYhvNjBdnekm4ZnaP5yC8Cs/1tA==",
-          "dev": true,
-          "requires": {
-            "@babel/code-frame": "^7.10.4",
-            "@babel/parser": "^7.10.4",
-            "@babel/types": "^7.10.4"
-          }
-        }
       }
     },
     "@babel/helper-skip-transparent-expression-wrappers": {
@@ -1437,118 +1237,43 @@
       "version": "7.11.0",
       "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.11.0.tgz",
       "integrity": "sha512-74Vejvp6mHkGE+m+k5vHY93FX2cAtrw1zXrZXRlG4l410Nm9PxfEiVTn1PjDPV5SnmieiueY4AFg2xqhNFuuZg==",
-      "requires": {
-        "@babel/types": "^7.11.0"
-      }
-    },
-    "@babel/helper-validator-identifier": {
-      "version": "7.10.4",
-      "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.10.4.tgz",
-      "integrity": "sha512-3U9y+43hz7ZM+rzG24Qe2mufW5KhvFg/NhnNph+i9mgCtdTCtMJuI1TMkrIUiK7Ix4PYlRF9I5dhqaLYA/ADXw=="
-    },
-    "@babel/helper-wrap-function": {
-      "version": "7.10.4",
-      "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.10.4.tgz",
-      "integrity": "sha512-6py45WvEF0MhiLrdxtRjKjufwLL1/ob2qDJgg5JgNdojBAZSAKnAjkyOCNug6n+OBl4VW76XjvgSFTdaMcW0Ug==",
       "dev": true,
-      "requires": {
-        "@babel/helper-function-name": "^7.10.4",
-        "@babel/template": "^7.10.4",
-        "@babel/traverse": "^7.10.4",
-        "@babel/types": "^7.10.4"
-      },
-      "dependencies": {
-        "@babel/code-frame": {
-          "version": "7.10.4",
-          "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.10.4.tgz",
-          "integrity": "sha512-vG6SvB6oYEhvgisZNFRmRCUkLz11c7rp+tbNTynGqc6mS1d5ATd/sGyV6W0KZZnXRKMTzZDRgQT3Ou9jhpAfUg==",
-          "dev": true,
-          "requires": {
-            "@babel/highlight": "^7.10.4"
-          }
-        },
-        "@babel/highlight": {
-          "version": "7.10.4",
-          "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.10.4.tgz",
-          "integrity": "sha512-i6rgnR/YgPEQzZZnbTHHuZdlE8qyoBNalD6F+q4vAFlcMEcqmkoG+mPqJYJCo63qPf74+Y1UZsl3l6f7/RIkmA==",
-          "dev": true,
-          "requires": {
-            "@babel/helper-validator-identifier": "^7.10.4",
-            "chalk": "^2.0.0",
-            "js-tokens": "^4.0.0"
-          }
-        },
-        "@babel/template": {
-          "version": "7.10.4",
-          "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.10.4.tgz",
-          "integrity": "sha512-ZCjD27cGJFUB6nmCB1Enki3r+L5kJveX9pq1SvAUKoICy6CZ9yD8xO086YXdYhvNjBdnekm4ZnaP5yC8Cs/1tA==",
-          "dev": true,
-          "requires": {
-            "@babel/code-frame": "^7.10.4",
-            "@babel/parser": "^7.10.4",
-            "@babel/types": "^7.10.4"
-          }
-        }
+      "requires": {
+        "@babel/types": "^7.11.0"
       }
     },
-    "@babel/helpers": {
+    "@babel/helper-validator-identifier": {
       "version": "7.10.4",
-      "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.10.4.tgz",
-      "integrity": "sha512-L2gX/XeUONeEbI78dXSrJzGdz4GQ+ZTA/aazfUsFaWjSe95kiCuOZ5HsXvkiw3iwF+mFHSRUfJU8t6YavocdXA==",
+      "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.10.4.tgz",
+      "integrity": "sha512-3U9y+43hz7ZM+rzG24Qe2mufW5KhvFg/NhnNph+i9mgCtdTCtMJuI1TMkrIUiK7Ix4PYlRF9I5dhqaLYA/ADXw=="
+    },
+    "@babel/helper-wrap-function": {
+      "version": "7.10.4",
+      "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.10.4.tgz",
+      "integrity": "sha512-6py45WvEF0MhiLrdxtRjKjufwLL1/ob2qDJgg5JgNdojBAZSAKnAjkyOCNug6n+OBl4VW76XjvgSFTdaMcW0Ug==",
       "dev": true,
       "requires": {
+        "@babel/helper-function-name": "^7.10.4",
         "@babel/template": "^7.10.4",
         "@babel/traverse": "^7.10.4",
         "@babel/types": "^7.10.4"
-      },
-      "dependencies": {
-        "@babel/code-frame": {
-          "version": "7.10.4",
-          "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.10.4.tgz",
-          "integrity": "sha512-vG6SvB6oYEhvgisZNFRmRCUkLz11c7rp+tbNTynGqc6mS1d5ATd/sGyV6W0KZZnXRKMTzZDRgQT3Ou9jhpAfUg==",
-          "dev": true,
-          "requires": {
-            "@babel/highlight": "^7.10.4"
-          }
-        },
-        "@babel/highlight": {
-          "version": "7.10.4",
-          "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.10.4.tgz",
-          "integrity": "sha512-i6rgnR/YgPEQzZZnbTHHuZdlE8qyoBNalD6F+q4vAFlcMEcqmkoG+mPqJYJCo63qPf74+Y1UZsl3l6f7/RIkmA==",
-          "dev": true,
-          "requires": {
-            "@babel/helper-validator-identifier": "^7.10.4",
-            "chalk": "^2.0.0",
-            "js-tokens": "^4.0.0"
-          }
-        },
-        "@babel/template": {
-          "version": "7.10.4",
-          "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.10.4.tgz",
-          "integrity": "sha512-ZCjD27cGJFUB6nmCB1Enki3r+L5kJveX9pq1SvAUKoICy6CZ9yD8xO086YXdYhvNjBdnekm4ZnaP5yC8Cs/1tA==",
-          "dev": true,
-          "requires": {
-            "@babel/code-frame": "^7.10.4",
-            "@babel/parser": "^7.10.4",
-            "@babel/types": "^7.10.4"
-          }
-        }
       }
     },
-    "@babel/highlight": {
+    "@babel/helpers": {
       "version": "7.10.4",
-      "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.10.4.tgz",
-      "integrity": "sha512-i6rgnR/YgPEQzZZnbTHHuZdlE8qyoBNalD6F+q4vAFlcMEcqmkoG+mPqJYJCo63qPf74+Y1UZsl3l6f7/RIkmA==",
+      "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.10.4.tgz",
+      "integrity": "sha512-L2gX/XeUONeEbI78dXSrJzGdz4GQ+ZTA/aazfUsFaWjSe95kiCuOZ5HsXvkiw3iwF+mFHSRUfJU8t6YavocdXA==",
+      "dev": true,
       "requires": {
-        "@babel/helper-validator-identifier": "^7.10.4",
-        "chalk": "^2.0.0",
-        "js-tokens": "^4.0.0"
+        "@babel/template": "^7.10.4",
+        "@babel/traverse": "^7.10.4",
+        "@babel/types": "^7.10.4"
       }
     },
     "@babel/parser": {
-      "version": "7.11.4",
-      "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.11.4.tgz",
-      "integrity": "sha512-MggwidiH+E9j5Sh8pbrX5sJvMcsqS5o+7iB42M9/k0CD63MjYbdP4nhSh7uB5wnv2/RVzTZFTxzF/kIa5mrCqA=="
+      "version": "7.10.4",
+      "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.10.4.tgz",
+      "integrity": "sha512-8jHII4hf+YVDsskTF6WuMB3X4Eh+PsUkC2ljq22so5rHvH+T8BzyL94VOdyFLNR8tBSVXOTbNHOKpR4TfRxVtA=="
     },
     "@babel/plugin-proposal-async-generator-functions": {
       "version": "7.10.5",
@@ -1561,6 +1286,16 @@
         "@babel/plugin-syntax-async-generators": "^7.8.0"
       }
     },
+    "@babel/plugin-proposal-class-properties": {
+      "version": "7.10.4",
+      "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.10.4.tgz",
+      "integrity": "sha512-vhwkEROxzcHGNu2mzUC0OFFNXdZ4M23ib8aRRcJSsW8BZK9pQMD7QB7csl97NBbgGZO7ZyHUyKDnxzOaP4IrCg==",
+      "dev": true,
+      "requires": {
+        "@babel/helper-create-class-features-plugin": "^7.10.4",
+        "@babel/helper-plugin-utils": "^7.10.4"
+      }
+    },
     "@babel/plugin-proposal-dynamic-import": {
       "version": "7.10.4",
       "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-dynamic-import/-/plugin-proposal-dynamic-import-7.10.4.tgz",
@@ -1571,6 +1306,16 @@
         "@babel/plugin-syntax-dynamic-import": "^7.8.0"
       }
     },
+    "@babel/plugin-proposal-export-namespace-from": {
+      "version": "7.10.4",
+      "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-export-namespace-from/-/plugin-proposal-export-namespace-from-7.10.4.tgz",
+      "integrity": "sha512-aNdf0LY6/3WXkhh0Fdb6Zk9j1NMD8ovj3F6r0+3j837Pn1S1PdNtcwJ5EG9WkVPNHPxyJDaxMaAOVq4eki0qbg==",
+      "dev": true,
+      "requires": {
+        "@babel/helper-plugin-utils": "^7.10.4",
+        "@babel/plugin-syntax-export-namespace-from": "^7.8.3"
+      }
+    },
     "@babel/plugin-proposal-json-strings": {
       "version": "7.10.4",
       "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-json-strings/-/plugin-proposal-json-strings-7.10.4.tgz",
@@ -1581,6 +1326,16 @@
         "@babel/plugin-syntax-json-strings": "^7.8.0"
       }
     },
+    "@babel/plugin-proposal-logical-assignment-operators": {
+      "version": "7.11.0",
+      "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-logical-assignment-operators/-/plugin-proposal-logical-assignment-operators-7.11.0.tgz",
+      "integrity": "sha512-/f8p4z+Auz0Uaf+i8Ekf1iM7wUNLcViFUGiPxKeXvxTSl63B875YPiVdUDdem7hREcI0E0kSpEhS8tF5RphK7Q==",
+      "dev": true,
+      "requires": {
+        "@babel/helper-plugin-utils": "^7.10.4",
+        "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4"
+      }
+    },
     "@babel/plugin-proposal-nullish-coalescing-operator": {
       "version": "7.10.4",
       "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-nullish-coalescing-operator/-/plugin-proposal-nullish-coalescing-operator-7.10.4.tgz",
@@ -1633,6 +1388,16 @@
         "@babel/plugin-syntax-optional-chaining": "^7.8.0"
       }
     },
+    "@babel/plugin-proposal-private-methods": {
+      "version": "7.10.4",
+      "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-methods/-/plugin-proposal-private-methods-7.10.4.tgz",
+      "integrity": "sha512-wh5GJleuI8k3emgTg5KkJK6kHNsGEr0uBTDBuQUBJwckk9xs1ez79ioheEVVxMLyPscB0LfkbVHslQqIzWV6Bw==",
+      "dev": true,
+      "requires": {
+        "@babel/helper-create-class-features-plugin": "^7.10.4",
+        "@babel/helper-plugin-utils": "^7.10.4"
+      }
+    },
     "@babel/plugin-proposal-unicode-property-regex": {
       "version": "7.10.4",
       "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-unicode-property-regex/-/plugin-proposal-unicode-property-regex-7.10.4.tgz",
@@ -1652,6 +1417,15 @@
         "@babel/helper-plugin-utils": "^7.8.0"
       }
     },
+    "@babel/plugin-syntax-class-properties": {
+      "version": "7.10.4",
+      "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.10.4.tgz",
+      "integrity": "sha512-GCSBF7iUle6rNugfURwNmCGG3Z/2+opxAMLs1nND4bhEG5PuxTIggDBoeYYSujAlLtsupzOHYJQgPS3pivwXIA==",
+      "dev": true,
+      "requires": {
+        "@babel/helper-plugin-utils": "^7.10.4"
+      }
+    },
     "@babel/plugin-syntax-dynamic-import": {
       "version": "7.8.3",
       "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-dynamic-import/-/plugin-syntax-dynamic-import-7.8.3.tgz",
@@ -1661,6 +1435,15 @@
         "@babel/helper-plugin-utils": "^7.8.0"
       }
     },
+    "@babel/plugin-syntax-export-namespace-from": {
+      "version": "7.8.3",
+      "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-export-namespace-from/-/plugin-syntax-export-namespace-from-7.8.3.tgz",
+      "integrity": "sha512-MXf5laXo6c1IbEbegDmzGPwGNTsHZmEy6QGznu5Sh2UCWvueywb2ee+CCE4zQiZstxU9BMoQO9i6zUFSY0Kj0Q==",
+      "dev": true,
+      "requires": {
+        "@babel/helper-plugin-utils": "^7.8.3"
+      }
+    },
     "@babel/plugin-syntax-json-strings": {
       "version": "7.8.3",
       "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz",
@@ -1670,6 +1453,15 @@
         "@babel/helper-plugin-utils": "^7.8.0"
       }
     },
+    "@babel/plugin-syntax-logical-assignment-operators": {
+      "version": "7.10.4",
+      "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz",
+      "integrity": "sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==",
+      "dev": true,
+      "requires": {
+        "@babel/helper-plugin-utils": "^7.10.4"
+      }
+    },
     "@babel/plugin-syntax-nullish-coalescing-operator": {
       "version": "7.8.3",
       "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz",
@@ -1973,13 +1765,13 @@
       }
     },
     "@babel/plugin-transform-runtime": {
-      "version": "7.9.6",
-      "resolved": "https://registry.npmjs.org/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.9.6.tgz",
-      "integrity": "sha512-qcmiECD0mYOjOIt8YHNsAP1SxPooC/rDmfmiSK9BNY72EitdSc7l44WTEklaWuFtbOEBjNhWWyph/kOImbNJ4w==",
+      "version": "7.11.0",
+      "resolved": "https://registry.npmjs.org/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.11.0.tgz",
+      "integrity": "sha512-LFEsP+t3wkYBlis8w6/kmnd6Kb1dxTd+wGJ8MlxTGzQo//ehtqlVL4S9DNUa53+dtPSQobN2CXx4d81FqC58cw==",
       "dev": true,
       "requires": {
-        "@babel/helper-module-imports": "^7.8.3",
-        "@babel/helper-plugin-utils": "^7.8.3",
+        "@babel/helper-module-imports": "^7.10.4",
+        "@babel/helper-plugin-utils": "^7.10.4",
         "resolve": "^1.8.1",
         "semver": "^5.5.1"
       }
@@ -2032,6 +1824,15 @@
         "@babel/helper-plugin-utils": "^7.10.4"
       }
     },
+    "@babel/plugin-transform-unicode-escapes": {
+      "version": "7.10.4",
+      "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.10.4.tgz",
+      "integrity": "sha512-y5XJ9waMti2J+e7ij20e+aH+fho7Wb7W8rNuu72aKRwCHFqQdhkdU2lo3uZ9tQuboEJcUFayXdARhcxLQ3+6Fg==",
+      "dev": true,
+      "requires": {
+        "@babel/helper-plugin-utils": "^7.10.4"
+      }
+    },
     "@babel/plugin-transform-unicode-regex": {
       "version": "7.10.4",
       "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.10.4.tgz",
@@ -2043,67 +1844,75 @@
       }
     },
     "@babel/preset-env": {
-      "version": "7.9.6",
-      "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.9.6.tgz",
-      "integrity": "sha512-0gQJ9RTzO0heXOhzftog+a/WyOuqMrAIugVYxMYf83gh1CQaQDjMtsOpqOwXyDL/5JcWsrCm8l4ju8QC97O7EQ==",
-      "dev": true,
-      "requires": {
-        "@babel/compat-data": "^7.9.6",
-        "@babel/helper-compilation-targets": "^7.9.6",
-        "@babel/helper-module-imports": "^7.8.3",
-        "@babel/helper-plugin-utils": "^7.8.3",
-        "@babel/plugin-proposal-async-generator-functions": "^7.8.3",
-        "@babel/plugin-proposal-dynamic-import": "^7.8.3",
-        "@babel/plugin-proposal-json-strings": "^7.8.3",
-        "@babel/plugin-proposal-nullish-coalescing-operator": "^7.8.3",
-        "@babel/plugin-proposal-numeric-separator": "^7.8.3",
-        "@babel/plugin-proposal-object-rest-spread": "^7.9.6",
-        "@babel/plugin-proposal-optional-catch-binding": "^7.8.3",
-        "@babel/plugin-proposal-optional-chaining": "^7.9.0",
-        "@babel/plugin-proposal-unicode-property-regex": "^7.8.3",
+      "version": "7.11.0",
+      "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.11.0.tgz",
+      "integrity": "sha512-2u1/k7rG/gTh02dylX2kL3S0IJNF+J6bfDSp4DI2Ma8QN6Y9x9pmAax59fsCk6QUQG0yqH47yJWA+u1I1LccAg==",
+      "dev": true,
+      "requires": {
+        "@babel/compat-data": "^7.11.0",
+        "@babel/helper-compilation-targets": "^7.10.4",
+        "@babel/helper-module-imports": "^7.10.4",
+        "@babel/helper-plugin-utils": "^7.10.4",
+        "@babel/plugin-proposal-async-generator-functions": "^7.10.4",
+        "@babel/plugin-proposal-class-properties": "^7.10.4",
+        "@babel/plugin-proposal-dynamic-import": "^7.10.4",
+        "@babel/plugin-proposal-export-namespace-from": "^7.10.4",
+        "@babel/plugin-proposal-json-strings": "^7.10.4",
+        "@babel/plugin-proposal-logical-assignment-operators": "^7.11.0",
+        "@babel/plugin-proposal-nullish-coalescing-operator": "^7.10.4",
+        "@babel/plugin-proposal-numeric-separator": "^7.10.4",
+        "@babel/plugin-proposal-object-rest-spread": "^7.11.0",
+        "@babel/plugin-proposal-optional-catch-binding": "^7.10.4",
+        "@babel/plugin-proposal-optional-chaining": "^7.11.0",
+        "@babel/plugin-proposal-private-methods": "^7.10.4",
+        "@babel/plugin-proposal-unicode-property-regex": "^7.10.4",
         "@babel/plugin-syntax-async-generators": "^7.8.0",
+        "@babel/plugin-syntax-class-properties": "^7.10.4",
         "@babel/plugin-syntax-dynamic-import": "^7.8.0",
+        "@babel/plugin-syntax-export-namespace-from": "^7.8.3",
         "@babel/plugin-syntax-json-strings": "^7.8.0",
+        "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4",
         "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.0",
-        "@babel/plugin-syntax-numeric-separator": "^7.8.0",
+        "@babel/plugin-syntax-numeric-separator": "^7.10.4",
         "@babel/plugin-syntax-object-rest-spread": "^7.8.0",
         "@babel/plugin-syntax-optional-catch-binding": "^7.8.0",
         "@babel/plugin-syntax-optional-chaining": "^7.8.0",
-        "@babel/plugin-syntax-top-level-await": "^7.8.3",
-        "@babel/plugin-transform-arrow-functions": "^7.8.3",
-        "@babel/plugin-transform-async-to-generator": "^7.8.3",
-        "@babel/plugin-transform-block-scoped-functions": "^7.8.3",
-        "@babel/plugin-transform-block-scoping": "^7.8.3",
-        "@babel/plugin-transform-classes": "^7.9.5",
-        "@babel/plugin-transform-computed-properties": "^7.8.3",
-        "@babel/plugin-transform-destructuring": "^7.9.5",
-        "@babel/plugin-transform-dotall-regex": "^7.8.3",
-        "@babel/plugin-transform-duplicate-keys": "^7.8.3",
-        "@babel/plugin-transform-exponentiation-operator": "^7.8.3",
-        "@babel/plugin-transform-for-of": "^7.9.0",
-        "@babel/plugin-transform-function-name": "^7.8.3",
-        "@babel/plugin-transform-literals": "^7.8.3",
-        "@babel/plugin-transform-member-expression-literals": "^7.8.3",
-        "@babel/plugin-transform-modules-amd": "^7.9.6",
-        "@babel/plugin-transform-modules-commonjs": "^7.9.6",
-        "@babel/plugin-transform-modules-systemjs": "^7.9.6",
-        "@babel/plugin-transform-modules-umd": "^7.9.0",
-        "@babel/plugin-transform-named-capturing-groups-regex": "^7.8.3",
-        "@babel/plugin-transform-new-target": "^7.8.3",
-        "@babel/plugin-transform-object-super": "^7.8.3",
-        "@babel/plugin-transform-parameters": "^7.9.5",
-        "@babel/plugin-transform-property-literals": "^7.8.3",
-        "@babel/plugin-transform-regenerator": "^7.8.7",
-        "@babel/plugin-transform-reserved-words": "^7.8.3",
-        "@babel/plugin-transform-shorthand-properties": "^7.8.3",
-        "@babel/plugin-transform-spread": "^7.8.3",
-        "@babel/plugin-transform-sticky-regex": "^7.8.3",
-        "@babel/plugin-transform-template-literals": "^7.8.3",
-        "@babel/plugin-transform-typeof-symbol": "^7.8.4",
-        "@babel/plugin-transform-unicode-regex": "^7.8.3",
+        "@babel/plugin-syntax-top-level-await": "^7.10.4",
+        "@babel/plugin-transform-arrow-functions": "^7.10.4",
+        "@babel/plugin-transform-async-to-generator": "^7.10.4",
+        "@babel/plugin-transform-block-scoped-functions": "^7.10.4",
+        "@babel/plugin-transform-block-scoping": "^7.10.4",
+        "@babel/plugin-transform-classes": "^7.10.4",
+        "@babel/plugin-transform-computed-properties": "^7.10.4",
+        "@babel/plugin-transform-destructuring": "^7.10.4",
+        "@babel/plugin-transform-dotall-regex": "^7.10.4",
+        "@babel/plugin-transform-duplicate-keys": "^7.10.4",
+        "@babel/plugin-transform-exponentiation-operator": "^7.10.4",
+        "@babel/plugin-transform-for-of": "^7.10.4",
+        "@babel/plugin-transform-function-name": "^7.10.4",
+        "@babel/plugin-transform-literals": "^7.10.4",
+        "@babel/plugin-transform-member-expression-literals": "^7.10.4",
+        "@babel/plugin-transform-modules-amd": "^7.10.4",
+        "@babel/plugin-transform-modules-commonjs": "^7.10.4",
+        "@babel/plugin-transform-modules-systemjs": "^7.10.4",
+        "@babel/plugin-transform-modules-umd": "^7.10.4",
+        "@babel/plugin-transform-named-capturing-groups-regex": "^7.10.4",
+        "@babel/plugin-transform-new-target": "^7.10.4",
+        "@babel/plugin-transform-object-super": "^7.10.4",
+        "@babel/plugin-transform-parameters": "^7.10.4",
+        "@babel/plugin-transform-property-literals": "^7.10.4",
+        "@babel/plugin-transform-regenerator": "^7.10.4",
+        "@babel/plugin-transform-reserved-words": "^7.10.4",
+        "@babel/plugin-transform-shorthand-properties": "^7.10.4",
+        "@babel/plugin-transform-spread": "^7.11.0",
+        "@babel/plugin-transform-sticky-regex": "^7.10.4",
+        "@babel/plugin-transform-template-literals": "^7.10.4",
+        "@babel/plugin-transform-typeof-symbol": "^7.10.4",
+        "@babel/plugin-transform-unicode-escapes": "^7.10.4",
+        "@babel/plugin-transform-unicode-regex": "^7.10.4",
         "@babel/preset-modules": "^0.1.3",
-        "@babel/types": "^7.9.6",
-        "browserslist": "^4.11.1",
+        "@babel/types": "^7.11.0",
+        "browserslist": "^4.12.0",
         "core-js-compat": "^3.6.2",
         "invariant": "^2.2.2",
         "levenary": "^1.1.1",
@@ -2111,9 +1920,9 @@
       }
     },
     "@babel/preset-modules": {
-      "version": "0.1.3",
-      "resolved": "https://registry.npmjs.org/@babel/preset-modules/-/preset-modules-0.1.3.tgz",
-      "integrity": "sha512-Ra3JXOHBq2xd56xSF7lMKXdjBn3T772Y1Wet3yWnkDly9zHvJki029tAFzvAAK5cf4YV3yoxuP61crYRol6SVg==",
+      "version": "0.1.4",
+      "resolved": "https://registry.npmjs.org/@babel/preset-modules/-/preset-modules-0.1.4.tgz",
+      "integrity": "sha512-J36NhwnfdzpmH41M1DrnkkgAqhZaqr/NBdPfQ677mLzlaXo+oDiv1deyCDtgAhz8p328otdob0Du7+xgHGZbKg==",
       "dev": true,
       "requires": {
         "@babel/helper-plugin-utils": "^7.0.0",
@@ -2141,36 +1950,14 @@
       }
     },
     "@babel/template": {
-      "version": "7.8.6",
-      "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.8.6.tgz",
-      "integrity": "sha512-zbMsPMy/v0PWFZEhQJ66bqjhH+z0JgMoBWuikXybgG3Gkd/3t5oQ1Rw2WQhnSrsOmsKXnZOx15tkC4qON/+JPg==",
+      "version": "7.10.4",
+      "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.10.4.tgz",
+      "integrity": "sha512-ZCjD27cGJFUB6nmCB1Enki3r+L5kJveX9pq1SvAUKoICy6CZ9yD8xO086YXdYhvNjBdnekm4ZnaP5yC8Cs/1tA==",
       "dev": true,
       "requires": {
-        "@babel/code-frame": "^7.8.3",
-        "@babel/parser": "^7.8.6",
-        "@babel/types": "^7.8.6"
-      },
-      "dependencies": {
-        "@babel/code-frame": {
-          "version": "7.10.4",
-          "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.10.4.tgz",
-          "integrity": "sha512-vG6SvB6oYEhvgisZNFRmRCUkLz11c7rp+tbNTynGqc6mS1d5ATd/sGyV6W0KZZnXRKMTzZDRgQT3Ou9jhpAfUg==",
-          "dev": true,
-          "requires": {
-            "@babel/highlight": "^7.10.4"
-          }
-        },
-        "@babel/highlight": {
-          "version": "7.10.4",
-          "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.10.4.tgz",
-          "integrity": "sha512-i6rgnR/YgPEQzZZnbTHHuZdlE8qyoBNalD6F+q4vAFlcMEcqmkoG+mPqJYJCo63qPf74+Y1UZsl3l6f7/RIkmA==",
-          "dev": true,
-          "requires": {
-            "@babel/helper-validator-identifier": "^7.10.4",
-            "chalk": "^2.0.0",
-            "js-tokens": "^4.0.0"
-          }
-        }
+        "@babel/code-frame": "^7.10.4",
+        "@babel/parser": "^7.10.4",
+        "@babel/types": "^7.10.4"
       }
     },
     "@babel/traverse": {
@@ -2207,6 +1994,14 @@
             "source-map": "^0.5.0"
           }
         },
+        "@babel/helper-split-export-declaration": {
+          "version": "7.11.0",
+          "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.11.0.tgz",
+          "integrity": "sha512-74Vejvp6mHkGE+m+k5vHY93FX2cAtrw1zXrZXRlG4l410Nm9PxfEiVTn1PjDPV5SnmieiueY4AFg2xqhNFuuZg==",
+          "requires": {
+            "@babel/types": "^7.11.0"
+          }
+        },
         "@babel/highlight": {
           "version": "7.10.4",
           "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.10.4.tgz",
@@ -2217,6 +2012,11 @@
             "js-tokens": "^4.0.0"
           }
         },
+        "@babel/parser": {
+          "version": "7.11.5",
+          "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.11.5.tgz",
+          "integrity": "sha512-X9rD8qqm695vgmeaQ4fvz/o3+Wk4ZzQvSHkDBgpYKxpD4qTAUm88ZKtHkVqIOsYFFbIQ6wQYhC6q7pjqVK0E0Q=="
+        },
         "debug": {
           "version": "4.1.1",
           "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz",
@@ -2565,9 +2365,9 @@
       },
       "dependencies": {
         "ajv": {
-          "version": "6.12.4",
-          "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.4.tgz",
-          "integrity": "sha512-eienB2c9qVQs2KWexhkrdMLVDoIQCz5KSeLxwg9Lzk4DOfBtIK9PQwwufcsn1jjGuf9WZmqPMbGxOzfcuphJCQ==",
+          "version": "6.12.5",
+          "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.5.tgz",
+          "integrity": "sha512-lRF8RORchjpKG50/WFf8xmg7sgCLFiYNNnqdKflk63whMQcWR5ngGjiSXkL9bjxy6B2npOK2HSMN49jEBMSkag==",
           "dev": true,
           "requires": {
             "fast-deep-equal": "^3.1.1",
@@ -2658,16 +2458,16 @@
       "dev": true
     },
     "@jsdevtools/coverage-istanbul-loader": {
-      "version": "3.0.3",
-      "resolved": "https://registry.npmjs.org/@jsdevtools/coverage-istanbul-loader/-/coverage-istanbul-loader-3.0.3.tgz",
-      "integrity": "sha512-TAdNkeGB5Fe4Og+ZkAr1Kvn9by2sfL44IAHFtxlh1BA1XJ5cLpO9iSNki5opWESv3l3vSHsZ9BNKuqFKbEbFaA==",
+      "version": "3.0.5",
+      "resolved": "https://registry.npmjs.org/@jsdevtools/coverage-istanbul-loader/-/coverage-istanbul-loader-3.0.5.tgz",
+      "integrity": "sha512-EUCPEkaRPvmHjWAAZkWMT7JDzpw7FKB00WTISaiXsbNOd5hCHg77XLA8sLYLFDo1zepYLo2w7GstN8YBqRXZfA==",
       "dev": true,
       "requires": {
         "convert-source-map": "^1.7.0",
-        "istanbul-lib-instrument": "^4.0.1",
-        "loader-utils": "^1.4.0",
+        "istanbul-lib-instrument": "^4.0.3",
+        "loader-utils": "^2.0.0",
         "merge-source-map": "^1.1.0",
-        "schema-utils": "^2.6.4"
+        "schema-utils": "^2.7.0"
       },
       "dependencies": {
         "convert-source-map": {
@@ -2679,26 +2479,6 @@
             "safe-buffer": "~5.1.1"
           }
         },
-        "json5": {
-          "version": "1.0.1",
-          "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.1.tgz",
-          "integrity": "sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow==",
-          "dev": true,
-          "requires": {
-            "minimist": "^1.2.0"
-          }
-        },
-        "loader-utils": {
-          "version": "1.4.0",
-          "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.4.0.tgz",
-          "integrity": "sha512-qH0WSMBtn/oHuwjy/NucEgbx5dbxxnxup9s4PVXJUDHZBQY+s0NWA9rJf53RBnQZxfch7euUui7hpoAPvALZdA==",
-          "dev": true,
-          "requires": {
-            "big.js": "^5.2.2",
-            "emojis-list": "^3.0.0",
-            "json5": "^1.0.1"
-          }
-        },
         "merge-source-map": {
           "version": "1.1.0",
           "resolved": "https://registry.npmjs.org/merge-source-map/-/merge-source-map-1.1.0.tgz",
@@ -2744,32 +2524,14 @@
       }
     },
     "@ngtools/webpack": {
-      "version": "10.0.7",
-      "resolved": "https://registry.npmjs.org/@ngtools/webpack/-/webpack-10.0.7.tgz",
-      "integrity": "sha512-yUjTDOgsuEJEtsyqb78jDm3Keo18x6j1AjmZUEeiCxShX2pBQTfErmxtBqxPUAkLa/gD7Wkf5cZM+3xcYyShRg==",
+      "version": "10.1.2",
+      "resolved": "https://registry.npmjs.org/@ngtools/webpack/-/webpack-10.1.2.tgz",
+      "integrity": "sha512-YBzMSzVHQsDGmdsKnmvAklrwQ5bjedQu40REvYczMNpdBthw2aiOI+YKSvRVfSKxMmnLWVL0aYYrqE5IhaMnRg==",
       "dev": true,
       "requires": {
-        "@angular-devkit/core": "10.0.7",
-        "enhanced-resolve": "4.1.1",
-        "rxjs": "6.5.5",
+        "@angular-devkit/core": "10.1.2",
+        "enhanced-resolve": "4.3.0",
         "webpack-sources": "1.4.3"
-      },
-      "dependencies": {
-        "rxjs": {
-          "version": "6.5.5",
-          "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.5.5.tgz",
-          "integrity": "sha512-WfQI+1gohdf0Dai/Bbmk5L5ItH5tYqm3ki2c5GdWhKjalzjg93N3avFjVStyZZz+A2Em+ZxKH5bNghw9UeylGQ==",
-          "dev": true,
-          "requires": {
-            "tslib": "^1.9.0"
-          }
-        },
-        "tslib": {
-          "version": "1.13.0",
-          "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.13.0.tgz",
-          "integrity": "sha512-i/6DQjL8Xf3be4K/E6Wgpekn5Qasl1usyw++dAA35Ue5orEn65VIxOA+YvNNl9HV3qv70T7CNwjODHZrLwvd1Q==",
-          "dev": true
-        }
       }
     },
     "@nodelib/fs.scandir": {
@@ -2821,32 +2583,123 @@
       }
     },
     "@schematics/angular": {
-      "version": "10.0.7",
-      "resolved": "https://registry.npmjs.org/@schematics/angular/-/angular-10.0.7.tgz",
-      "integrity": "sha512-0SljGZjA68tOsn7OIps79lTy9Y96OZglLnBqO6pSLlmCkGMbjFY2ssKQXJzwR0jJ5+TWBjWjpn2U5mir4yzOuQ==",
+      "version": "10.1.2",
+      "resolved": "https://registry.npmjs.org/@schematics/angular/-/angular-10.1.2.tgz",
+      "integrity": "sha512-7BHgSdP4yC0IuoiPGWBGQrwE5ilBhIOGozjKSHx41Utac45YKyXpmjr1Jw+SvFilgsnPEjZwc7VKqgINmeLkqA==",
       "dev": true,
       "requires": {
-        "@angular-devkit/core": "10.0.7",
-        "@angular-devkit/schematics": "10.0.7"
+        "@angular-devkit/core": "10.1.2",
+        "@angular-devkit/schematics": "10.1.2",
+        "jsonc-parser": "2.3.0"
+      },
+      "dependencies": {
+        "@angular-devkit/core": {
+          "version": "10.1.2",
+          "resolved": "https://registry.npmjs.org/@angular-devkit/core/-/core-10.1.2.tgz",
+          "integrity": "sha512-LMxesiCuXRe3UzPdRouXsC1W73/q6rVtACVoD5GdzmmnZ7cRh7oiwonqT0lEXIKQikMsZUasUOXHD2HoKV6BoA==",
+          "dev": true,
+          "requires": {
+            "ajv": "6.12.4",
+            "fast-json-stable-stringify": "2.1.0",
+            "magic-string": "0.25.7",
+            "rxjs": "6.6.2",
+            "source-map": "0.7.3"
+          }
+        },
+        "ajv": {
+          "version": "6.12.4",
+          "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.4.tgz",
+          "integrity": "sha512-eienB2c9qVQs2KWexhkrdMLVDoIQCz5KSeLxwg9Lzk4DOfBtIK9PQwwufcsn1jjGuf9WZmqPMbGxOzfcuphJCQ==",
+          "dev": true,
+          "requires": {
+            "fast-deep-equal": "^3.1.1",
+            "fast-json-stable-stringify": "^2.0.0",
+            "json-schema-traverse": "^0.4.1",
+            "uri-js": "^4.2.2"
+          }
+        },
+        "fast-deep-equal": {
+          "version": "3.1.3",
+          "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
+          "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==",
+          "dev": true
+        },
+        "fast-json-stable-stringify": {
+          "version": "2.1.0",
+          "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz",
+          "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==",
+          "dev": true
+        },
+        "rxjs": {
+          "version": "6.6.2",
+          "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.6.2.tgz",
+          "integrity": "sha512-BHdBMVoWC2sL26w//BCu3YzKT4s2jip/WhwsGEDmeKYBhKDZeYezVUnHatYB7L85v5xs0BAQmg6BEYJEKxBabg==",
+          "dev": true,
+          "requires": {
+            "tslib": "^1.9.0"
+          }
+        },
+        "tslib": {
+          "version": "1.13.0",
+          "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.13.0.tgz",
+          "integrity": "sha512-i/6DQjL8Xf3be4K/E6Wgpekn5Qasl1usyw++dAA35Ue5orEn65VIxOA+YvNNl9HV3qv70T7CNwjODHZrLwvd1Q==",
+          "dev": true
+        }
       }
     },
     "@schematics/update": {
-      "version": "0.1000.7",
-      "resolved": "https://registry.npmjs.org/@schematics/update/-/update-0.1000.7.tgz",
-      "integrity": "sha512-KEOtKu95np+jVxxs/JCQ8UNQ0v21BSZKe0sb+D/Nk3XVPMHXDS3ZvcavDh5OXGC2GucbZHkD2UNvEPTEHpLxMg==",
+      "version": "0.1001.2",
+      "resolved": "https://registry.npmjs.org/@schematics/update/-/update-0.1001.2.tgz",
+      "integrity": "sha512-Z/P08k4FlbKNmxV5pe34yfKPLI2327CjBg26isO5qpR4nB1FVZkC39YXwFwJod3nU7DE6UMkKcA749k30k2KSg==",
       "dev": true,
       "requires": {
-        "@angular-devkit/core": "10.0.7",
-        "@angular-devkit/schematics": "10.0.7",
+        "@angular-devkit/core": "10.1.2",
+        "@angular-devkit/schematics": "10.1.2",
         "@yarnpkg/lockfile": "1.1.0",
         "ini": "1.3.5",
         "npm-package-arg": "^8.0.0",
         "pacote": "9.5.12",
-        "rxjs": "6.5.5",
         "semver": "7.3.2",
         "semver-intersect": "1.4.0"
       },
       "dependencies": {
+        "@angular-devkit/core": {
+          "version": "10.1.2",
+          "resolved": "https://registry.npmjs.org/@angular-devkit/core/-/core-10.1.2.tgz",
+          "integrity": "sha512-LMxesiCuXRe3UzPdRouXsC1W73/q6rVtACVoD5GdzmmnZ7cRh7oiwonqT0lEXIKQikMsZUasUOXHD2HoKV6BoA==",
+          "dev": true,
+          "requires": {
+            "ajv": "6.12.4",
+            "fast-json-stable-stringify": "2.1.0",
+            "magic-string": "0.25.7",
+            "rxjs": "6.6.2",
+            "source-map": "0.7.3"
+          }
+        },
+        "ajv": {
+          "version": "6.12.4",
+          "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.4.tgz",
+          "integrity": "sha512-eienB2c9qVQs2KWexhkrdMLVDoIQCz5KSeLxwg9Lzk4DOfBtIK9PQwwufcsn1jjGuf9WZmqPMbGxOzfcuphJCQ==",
+          "dev": true,
+          "requires": {
+            "fast-deep-equal": "^3.1.1",
+            "fast-json-stable-stringify": "^2.0.0",
+            "json-schema-traverse": "^0.4.1",
+            "uri-js": "^4.2.2"
+          }
+        },
+        "fast-deep-equal": {
+          "version": "3.1.3",
+          "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
+          "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==",
+          "dev": true
+        },
+        "fast-json-stable-stringify": {
+          "version": "2.1.0",
+          "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz",
+          "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==",
+          "dev": true
+        },
         "hosted-git-info": {
           "version": "3.0.5",
           "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-3.0.5.tgz",
@@ -2856,15 +2709,6 @@
             "lru-cache": "^6.0.0"
           }
         },
-        "lru-cache": {
-          "version": "6.0.0",
-          "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz",
-          "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==",
-          "dev": true,
-          "requires": {
-            "yallist": "^4.0.0"
-          }
-        },
         "npm-package-arg": {
           "version": "8.0.1",
           "resolved": "https://registry.npmjs.org/npm-package-arg/-/npm-package-arg-8.0.1.tgz",
@@ -2877,9 +2721,9 @@
           }
         },
         "rxjs": {
-          "version": "6.5.5",
-          "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.5.5.tgz",
-          "integrity": "sha512-WfQI+1gohdf0Dai/Bbmk5L5ItH5tYqm3ki2c5GdWhKjalzjg93N3avFjVStyZZz+A2Em+ZxKH5bNghw9UeylGQ==",
+          "version": "6.6.2",
+          "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.6.2.tgz",
+          "integrity": "sha512-BHdBMVoWC2sL26w//BCu3YzKT4s2jip/WhwsGEDmeKYBhKDZeYezVUnHatYB7L85v5xs0BAQmg6BEYJEKxBabg==",
           "dev": true,
           "requires": {
             "tslib": "^1.9.0"
@@ -2896,12 +2740,6 @@
           "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.13.0.tgz",
           "integrity": "sha512-i/6DQjL8Xf3be4K/E6Wgpekn5Qasl1usyw++dAA35Ue5orEn65VIxOA+YvNNl9HV3qv70T7CNwjODHZrLwvd1Q==",
           "dev": true
-        },
-        "yallist": {
-          "version": "4.0.0",
-          "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
-          "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==",
-          "dev": true
         }
       }
     },
@@ -2965,9 +2803,9 @@
       }
     },
     "@types/jasmine": {
-      "version": "3.5.13",
-      "resolved": "https://registry.npmjs.org/@types/jasmine/-/jasmine-3.5.13.tgz",
-      "integrity": "sha512-bVSrTEWdCNH2RHN+E0QlEr4pGPMRA6puKOmL/X13ZeZmUS0q12ZR1rkB9PVvJSX0zi/OXrMDNvUai+PC380+rQ==",
+      "version": "3.5.14",
+      "resolved": "https://registry.npmjs.org/@types/jasmine/-/jasmine-3.5.14.tgz",
+      "integrity": "sha512-Fkgk536sHPqcOtd+Ow+WiUNuk0TSo/BntKkF8wSvcd6M2FvPjeXcUE6Oz/bwDZiUZEaXLslAgw00Q94Pnx6T4w==",
       "dev": true
     },
     "@types/jasminewd2": {
@@ -2980,9 +2818,9 @@
       }
     },
     "@types/json-schema": {
-      "version": "7.0.5",
-      "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.5.tgz",
-      "integrity": "sha512-7+2BITlgjgDhH0vvwZU/HZJVyk+2XUlvxXe8dFMedNX/aMkaOq++rMAFXc0tM7ij15QaWlbdQASBR9dihi+bDQ==",
+      "version": "7.0.6",
+      "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.6.tgz",
+      "integrity": "sha512-3c+yGKvVP5Y9TYBEibGNR+kLtijnj7mYrXRg+WpFb2X9xm04g/DXYkfg4hmzJQosc9snFNUPkbYIhu+KAm6jJw==",
       "dev": true
     },
     "@types/marked": {
@@ -3002,9 +2840,9 @@
       "integrity": "sha512-13gmo3M2qVvjQrWNseqM3+cR6S2Ss3grbR2NZltgMq94wOwqJYQdgn8qzwDshzgXqMlSUtyPZjysImmktu22ew=="
     },
     "@types/node": {
-      "version": "14.6.0",
-      "resolved": "https://registry.npmjs.org/@types/node/-/node-14.6.0.tgz",
-      "integrity": "sha512-mikldZQitV94akrc4sCcSjtJfsTKt4p+e/s0AGscVA6XArQ9kFclP+ZiYUMnq987rc6QlYxXv/EivqlfSLxpKA==",
+      "version": "14.10.3",
+      "resolved": "https://registry.npmjs.org/@types/node/-/node-14.10.3.tgz",
+      "integrity": "sha512-zdN0hor7TLkjAdKTnYW+Y22oIhUUpil5ZD1V1OFq0CR0CLKw+NdR6dkziTfkWRLo6sKzisayoj/GNpNbe4LY9Q==",
       "dev": true
     },
     "@types/pako": {
@@ -3273,9 +3111,9 @@
       }
     },
     "abab": {
-      "version": "2.0.4",
-      "resolved": "https://registry.npmjs.org/abab/-/abab-2.0.4.tgz",
-      "integrity": "sha512-Eu9ELJWCz/c1e9gTiCY+FceWxcqzjYEbqMgtndnuSqZSUCOL73TWNK2mHfIj4Cw2E/ongOp+JISVNCmovt2KYQ==",
+      "version": "2.0.5",
+      "resolved": "https://registry.npmjs.org/abab/-/abab-2.0.5.tgz",
+      "integrity": "sha512-9IK9EadsbHo6jLWIpxpR6pL0sazTXV6+SQv25ZB+F7Bj9mJNaOc4nCRabwd5M/JwmUa8idz6Eci6eKfJryPs6Q==",
       "dev": true
     },
     "abbrev": {
@@ -3618,27 +3456,27 @@
       "dev": true
     },
     "app-builder-bin": {
-      "version": "3.5.9",
-      "resolved": "https://registry.npmjs.org/app-builder-bin/-/app-builder-bin-3.5.9.tgz",
-      "integrity": "sha512-NSjtqZ3x2kYiDp3Qezsgukx/AUzKPr3Xgf9by4cYt05ILWGAptepeeu0Uv+7MO+41o6ujhLixTou8979JGg2Kg==",
+      "version": "3.5.10",
+      "resolved": "https://registry.npmjs.org/app-builder-bin/-/app-builder-bin-3.5.10.tgz",
+      "integrity": "sha512-Jd+GW68lR0NeetgZDo47PdWBEPdnD+p0jEa7XaxjRC8u6Oo/wgJsfKUkORRgr2NpkD19IFKN50P6JYy04XHFLQ==",
       "dev": true
     },
     "app-builder-lib": {
-      "version": "22.8.0",
-      "resolved": "https://registry.npmjs.org/app-builder-lib/-/app-builder-lib-22.8.0.tgz",
-      "integrity": "sha512-RGaIRjCUrqkmh6QOGsyekQPEOaVynHfmeh8JZuyUymFYUOFdzBbPamkA2nhBVBTkkgfjRHsxK7LhedFKPzvWEQ==",
+      "version": "22.8.1",
+      "resolved": "https://registry.npmjs.org/app-builder-lib/-/app-builder-lib-22.8.1.tgz",
+      "integrity": "sha512-D/ac1+vuGIAAwEeTtXl8b+qWl7Gz/IQatFyzYl2ocag/7N8LqUjKzZFJJISQPWt6PFDPDH0oCj8/GMh63aV0yw==",
       "dev": true,
       "requires": {
         "7zip-bin": "~5.0.3",
         "@develar/schema-utils": "~2.6.5",
         "async-exit-hook": "^2.0.1",
         "bluebird-lst": "^1.0.9",
-        "builder-util": "22.8.0",
+        "builder-util": "22.8.1",
         "builder-util-runtime": "8.7.2",
         "chromium-pickle-js": "^0.2.0",
-        "debug": "^4.1.1",
+        "debug": "^4.2.0",
         "ejs": "^3.1.3",
-        "electron-publish": "22.8.0",
+        "electron-publish": "22.8.1",
         "fs-extra": "^9.0.1",
         "hosted-git-info": "^3.0.5",
         "is-ci": "^2.0.0",
@@ -3654,12 +3492,12 @@
       },
       "dependencies": {
         "debug": {
-          "version": "4.1.1",
-          "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz",
-          "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==",
+          "version": "4.2.0",
+          "resolved": "https://registry.npmjs.org/debug/-/debug-4.2.0.tgz",
+          "integrity": "sha512-IX2ncY78vDTjZMFUdmsvIRFY2Cf4FnD0wRs+nQwJU8Lu99/tPFdb0VybiiMTPe3I6rQmwsqQqRBvxU+bZ/I8sg==",
           "dev": true,
           "requires": {
-            "ms": "^2.1.1"
+            "ms": "2.1.2"
           }
         },
         "esprima": {
@@ -3984,17 +3822,17 @@
       "dev": true
     },
     "autoprefixer": {
-      "version": "9.8.0",
-      "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-9.8.0.tgz",
-      "integrity": "sha512-D96ZiIHXbDmU02dBaemyAg53ez+6F5yZmapmgKcjm35yEe1uVDYI8hGW3VYoGRaG290ZFf91YxHrR518vC0u/A==",
+      "version": "9.8.6",
+      "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-9.8.6.tgz",
+      "integrity": "sha512-XrvP4VVHdRBCdX1S3WXVD8+RyG9qeb1D5Sn1DeLiG2xfSpzellk5k54xbUERJ3M5DggQxes39UGOTP8CFrEGbg==",
       "dev": true,
       "requires": {
         "browserslist": "^4.12.0",
-        "caniuse-lite": "^1.0.30001061",
-        "chalk": "^2.4.2",
+        "caniuse-lite": "^1.0.30001109",
+        "colorette": "^1.2.1",
         "normalize-range": "^0.1.2",
         "num2fraction": "^1.2.2",
-        "postcss": "^7.0.30",
+        "postcss": "^7.0.32",
         "postcss-value-parser": "^4.1.0"
       }
     },
@@ -4494,6 +4332,12 @@
           "integrity": "sha512-a6sumDlzyHVJWb8+YofY4TW112G6p2FCPEAFk+59gIYHv3XHRhm9ltVQ9kli4hNWeQBwSpe8cRN25x0ROunMOw==",
           "dev": true
         },
+        "type-fest": {
+          "version": "0.8.1",
+          "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz",
+          "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==",
+          "dev": true
+        },
         "widest-line": {
           "version": "3.1.0",
           "resolved": "https://registry.npmjs.org/widest-line/-/widest-line-3.1.0.tgz",
@@ -4713,15 +4557,15 @@
       }
     },
     "browserslist": {
-      "version": "4.14.0",
-      "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.14.0.tgz",
-      "integrity": "sha512-pUsXKAF2lVwhmtpeA3LJrZ76jXuusrNyhduuQs7CDFf9foT4Y38aQOserd2lMe5DSSrjf3fx34oHwryuvxAUgQ==",
+      "version": "4.14.2",
+      "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.14.2.tgz",
+      "integrity": "sha512-HI4lPveGKUR0x2StIz+2FXfDk9SfVMrxn6PLh1JeGUwcuoDkdKZebWiyLRJ68iIPDpMI4JLVDf7S7XzslgWOhw==",
       "dev": true,
       "requires": {
-        "caniuse-lite": "^1.0.30001111",
-        "electron-to-chromium": "^1.3.523",
+        "caniuse-lite": "^1.0.30001125",
+        "electron-to-chromium": "^1.3.564",
         "escalade": "^3.0.2",
-        "node-releases": "^1.1.60"
+        "node-releases": "^1.1.61"
       }
     },
     "browserstack": {
@@ -4774,19 +4618,19 @@
       "dev": true
     },
     "builder-util": {
-      "version": "22.8.0",
-      "resolved": "https://registry.npmjs.org/builder-util/-/builder-util-22.8.0.tgz",
-      "integrity": "sha512-H80P1JzVy3TGpi63x81epQDK24XalL034+jAZlrPb5IhLtYmnNNdxCCAVJvg3VjSISd73Y71O+uhqCxWpqbPHw==",
+      "version": "22.8.1",
+      "resolved": "https://registry.npmjs.org/builder-util/-/builder-util-22.8.1.tgz",
+      "integrity": "sha512-LZG+E1xszMdut5hL5h7RkJQ7yOsQqdhJYgn1wvOP7MmF3MoUPRNDiRodLpYiWlaqZmgYhcfaipR/Mb8F/RqK8w==",
       "dev": true,
       "requires": {
         "7zip-bin": "~5.0.3",
         "@types/debug": "^4.1.5",
         "@types/fs-extra": "^9.0.1",
-        "app-builder-bin": "3.5.9",
+        "app-builder-bin": "3.5.10",
         "bluebird-lst": "^1.0.9",
         "builder-util-runtime": "8.7.2",
         "chalk": "^4.1.0",
-        "debug": "^4.1.1",
+        "debug": "^4.2.0",
         "fs-extra": "^9.0.1",
         "is-ci": "^2.0.0",
         "js-yaml": "^3.14.0",
@@ -4825,12 +4669,12 @@
           }
         },
         "debug": {
-          "version": "4.1.1",
-          "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz",
-          "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==",
+          "version": "4.2.0",
+          "resolved": "https://registry.npmjs.org/debug/-/debug-4.2.0.tgz",
+          "integrity": "sha512-IX2ncY78vDTjZMFUdmsvIRFY2Cf4FnD0wRs+nQwJU8Lu99/tPFdb0VybiiMTPe3I6rQmwsqQqRBvxU+bZ/I8sg==",
           "dev": true,
           "requires": {
-            "ms": "^2.1.1"
+            "ms": "2.1.2"
           }
         },
         "esprima": {
@@ -4862,9 +4706,9 @@
           "dev": true
         },
         "supports-color": {
-          "version": "7.1.0",
-          "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.1.0.tgz",
-          "integrity": "sha512-oRSIpR8pxT1Wr2FquTNnGet79b3BWljqOuoW/h4oBhxJ/HUbX5nX6JSruTkvXDCFMwDPvsaTTbvMLKZWSy0R5g==",
+          "version": "7.2.0",
+          "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
+          "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
           "dev": true,
           "requires": {
             "has-flag": "^4.0.0"
@@ -4924,22 +4768,22 @@
       "dev": true
     },
     "cacache": {
-      "version": "15.0.3",
-      "resolved": "https://registry.npmjs.org/cacache/-/cacache-15.0.3.tgz",
-      "integrity": "sha512-bc3jKYjqv7k4pWh7I/ixIjfcjPul4V4jme/WbjvwGS5LzoPL/GzXr4C5EgPNLO/QEZl9Oi61iGitYEdwcrwLCQ==",
+      "version": "15.0.5",
+      "resolved": "https://registry.npmjs.org/cacache/-/cacache-15.0.5.tgz",
+      "integrity": "sha512-lloiL22n7sOjEEXdL8NAjTgv9a1u43xICE9/203qonkZUCj5X1UEWIdf2/Y0d6QcCtMzbKQyhrcDbdvlZTs/+A==",
       "dev": true,
       "requires": {
+        "@npmcli/move-file": "^1.0.1",
         "chownr": "^2.0.0",
         "fs-minipass": "^2.0.0",
         "glob": "^7.1.4",
         "infer-owner": "^1.0.4",
-        "lru-cache": "^5.1.1",
+        "lru-cache": "^6.0.0",
         "minipass": "^3.1.1",
         "minipass-collect": "^1.0.2",
         "minipass-flush": "^1.0.5",
         "minipass-pipeline": "^1.2.2",
         "mkdirp": "^1.0.3",
-        "move-file": "^2.0.0",
         "p-map": "^4.0.0",
         "promise-inflight": "^1.0.1",
         "rimraf": "^3.0.2",
@@ -4962,15 +4806,6 @@
             "path-is-absolute": "^1.0.0"
           }
         },
-        "lru-cache": {
-          "version": "5.1.1",
-          "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz",
-          "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==",
-          "dev": true,
-          "requires": {
-            "yallist": "^3.0.2"
-          }
-        },
         "mkdirp": {
           "version": "1.0.4",
           "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz",
@@ -4985,12 +4820,6 @@
           "requires": {
             "glob": "^7.1.3"
           }
-        },
-        "yallist": {
-          "version": "3.1.1",
-          "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz",
-          "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==",
-          "dev": true
         }
       }
     },
@@ -5119,9 +4948,9 @@
       }
     },
     "caniuse-lite": {
-      "version": "1.0.30001117",
-      "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001117.tgz",
-      "integrity": "sha512-4tY0Fatzdx59kYjQs+bNxUwZB03ZEBgVmJ1UkFPz/Q8OLiUUbjct2EdpnXj0fvFTPej2EkbPIG0w8BWsjAyk1Q==",
+      "version": "1.0.30001131",
+      "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001131.tgz",
+      "integrity": "sha512-4QYi6Mal4MMfQMSqGIRPGbKIbZygeN83QsWq1ixpUwvtfgAZot5BrCKzGygvZaV+CnELdTwD0S4cqUNozq7/Cw==",
       "dev": true
     },
     "canonical-path": {
@@ -5522,17 +5351,6 @@
       "integrity": "sha1-G39Ln1kfHo+DZwQBYANFoCiHQ18=",
       "dev": true
     },
-    "clone-deep": {
-      "version": "4.0.1",
-      "resolved": "https://registry.npmjs.org/clone-deep/-/clone-deep-4.0.1.tgz",
-      "integrity": "sha512-neHB9xuzh/wk0dIHweyAXv2aPGZIVk3pLMe+/RNzINf17fe0OG96QroktYAUm7SM1PBnzTabaLboqqxDyMU+SQ==",
-      "dev": true,
-      "requires": {
-        "is-plain-object": "^2.0.4",
-        "kind-of": "^6.0.2",
-        "shallow-clone": "^3.0.0"
-      }
-    },
     "clone-response": {
       "version": "1.0.2",
       "resolved": "https://registry.npmjs.org/clone-response/-/clone-response-1.0.2.tgz",
@@ -5698,6 +5516,12 @@
       "integrity": "sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==",
       "dev": true
     },
+    "colorette": {
+      "version": "1.2.1",
+      "resolved": "https://registry.npmjs.org/colorette/-/colorette-1.2.1.tgz",
+      "integrity": "sha512-puCDz0CzydiSYOrnXpz/PKd69zRrribezjtE9yd4zvytoRc8+RY/KJPvtPFKZS3E3wP6neGyMe0vOTlHO5L3Pw==",
+      "dev": true
+    },
     "colors": {
       "version": "1.4.0",
       "resolved": "https://registry.npmjs.org/colors/-/colors-1.4.0.tgz",
@@ -6018,31 +5842,6 @@
             "fill-range": "^7.0.1"
           }
         },
-        "cacache": {
-          "version": "15.0.5",
-          "resolved": "https://registry.npmjs.org/cacache/-/cacache-15.0.5.tgz",
-          "integrity": "sha512-lloiL22n7sOjEEXdL8NAjTgv9a1u43xICE9/203qonkZUCj5X1UEWIdf2/Y0d6QcCtMzbKQyhrcDbdvlZTs/+A==",
-          "dev": true,
-          "requires": {
-            "@npmcli/move-file": "^1.0.1",
-            "chownr": "^2.0.0",
-            "fs-minipass": "^2.0.0",
-            "glob": "^7.1.4",
-            "infer-owner": "^1.0.4",
-            "lru-cache": "^6.0.0",
-            "minipass": "^3.1.1",
-            "minipass-collect": "^1.0.2",
-            "minipass-flush": "^1.0.5",
-            "minipass-pipeline": "^1.2.2",
-            "mkdirp": "^1.0.3",
-            "p-map": "^4.0.0",
-            "promise-inflight": "^1.0.1",
-            "rimraf": "^3.0.2",
-            "ssri": "^8.0.0",
-            "tar": "^6.0.2",
-            "unique-filename": "^1.1.1"
-          }
-        },
         "fast-glob": {
           "version": "3.2.4",
           "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.4.tgz",
@@ -6066,20 +5865,6 @@
             "to-regex-range": "^5.0.1"
           }
         },
-        "glob": {
-          "version": "7.1.6",
-          "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz",
-          "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==",
-          "dev": true,
-          "requires": {
-            "fs.realpath": "^1.0.0",
-            "inflight": "^1.0.4",
-            "inherits": "2",
-            "minimatch": "^3.0.4",
-            "once": "^1.3.0",
-            "path-is-absolute": "^1.0.0"
-          }
-        },
         "glob-parent": {
           "version": "5.1.1",
           "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.1.tgz",
@@ -6104,15 +5889,6 @@
           "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==",
           "dev": true
         },
-        "lru-cache": {
-          "version": "6.0.0",
-          "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz",
-          "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==",
-          "dev": true,
-          "requires": {
-            "yallist": "^4.0.0"
-          }
-        },
         "merge2": {
           "version": "1.4.1",
           "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz",
@@ -6129,12 +5905,6 @@
             "picomatch": "^2.0.5"
           }
         },
-        "mkdirp": {
-          "version": "1.0.4",
-          "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz",
-          "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==",
-          "dev": true
-        },
         "normalize-path": {
           "version": "3.0.0",
           "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz",
@@ -6156,15 +5926,6 @@
           "integrity": "sha512-q0M/9eZHzmr0AulXyPwNfZjtwZ/RBZlbN3K3CErVrk50T2ASYI7Bye0EvekFY3IP1Nt2DHu0re+V2ZHIpMkuWg==",
           "dev": true
         },
-        "rimraf": {
-          "version": "3.0.2",
-          "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz",
-          "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==",
-          "dev": true,
-          "requires": {
-            "glob": "^7.1.3"
-          }
-        },
         "to-regex-range": {
           "version": "5.0.1",
           "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
@@ -6173,12 +5934,6 @@
           "requires": {
             "is-number": "^7.0.0"
           }
-        },
-        "yallist": {
-          "version": "4.0.0",
-          "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
-          "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==",
-          "dev": true
         }
       }
     },
@@ -6919,9 +6674,9 @@
       "integrity": "sha512-m7cughw327CjONN/qjzsTpSesLaeybksQh420/gRuSXJX5Zt9NfgsSbqqKDon6jnQ9Mm7h7imgyO2uJ34XMBtA=="
     },
     "cordova-plugin-file-opener2": {
-      "version": "3.0.4",
-      "resolved": "https://registry.npmjs.org/cordova-plugin-file-opener2/-/cordova-plugin-file-opener2-3.0.4.tgz",
-      "integrity": "sha512-bd1aCx62X2RwpC+KUiuB7quoxL/8RnPMEJU7x38Tvs+cUGLWBvsmR9+/LqGBsSns2CIqgnJ34TW0Vazoqu7Ieg=="
+      "version": "3.0.5",
+      "resolved": "https://registry.npmjs.org/cordova-plugin-file-opener2/-/cordova-plugin-file-opener2-3.0.5.tgz",
+      "integrity": "sha512-tjLHDamH5+y0bJZYVe2967L1S4R8tL4Y0rJUzJGoxsyiw3FUlrJNS199POOpzZZ6Xhlntn9a2o7+84r1dMN21A=="
     },
     "cordova-plugin-local-notification": {
       "version": "0.9.0-beta.2",
@@ -7204,56 +6959,35 @@
       }
     },
     "css-loader": {
-      "version": "3.5.3",
-      "resolved": "https://registry.npmjs.org/css-loader/-/css-loader-3.5.3.tgz",
-      "integrity": "sha512-UEr9NH5Lmi7+dguAm+/JSPovNjYbm2k3TK58EiwQHzOHH5Jfq1Y+XoP2bQO6TMn7PptMd0opxxedAWcaSTRKHw==",
+      "version": "4.2.2",
+      "resolved": "https://registry.npmjs.org/css-loader/-/css-loader-4.2.2.tgz",
+      "integrity": "sha512-omVGsTkZPVwVRpckeUnLshPp12KsmMSLqYxs12+RzM9jRR5Y+Idn/tBffjXRvOE+qW7if24cuceFJqYR5FmGBg==",
       "dev": true,
       "requires": {
-        "camelcase": "^5.3.1",
+        "camelcase": "^6.0.0",
         "cssesc": "^3.0.0",
         "icss-utils": "^4.1.1",
-        "loader-utils": "^1.2.3",
-        "normalize-path": "^3.0.0",
-        "postcss": "^7.0.27",
+        "loader-utils": "^2.0.0",
+        "postcss": "^7.0.32",
         "postcss-modules-extract-imports": "^2.0.0",
-        "postcss-modules-local-by-default": "^3.0.2",
+        "postcss-modules-local-by-default": "^3.0.3",
         "postcss-modules-scope": "^2.2.0",
         "postcss-modules-values": "^3.0.0",
-        "postcss-value-parser": "^4.0.3",
-        "schema-utils": "^2.6.6",
-        "semver": "^6.3.0"
+        "postcss-value-parser": "^4.1.0",
+        "schema-utils": "^2.7.0",
+        "semver": "^7.3.2"
       },
       "dependencies": {
-        "json5": {
-          "version": "1.0.1",
-          "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.1.tgz",
-          "integrity": "sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow==",
-          "dev": true,
-          "requires": {
-            "minimist": "^1.2.0"
-          }
-        },
-        "loader-utils": {
-          "version": "1.4.0",
-          "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.4.0.tgz",
-          "integrity": "sha512-qH0WSMBtn/oHuwjy/NucEgbx5dbxxnxup9s4PVXJUDHZBQY+s0NWA9rJf53RBnQZxfch7euUui7hpoAPvALZdA==",
-          "dev": true,
-          "requires": {
-            "big.js": "^5.2.2",
-            "emojis-list": "^3.0.0",
-            "json5": "^1.0.1"
-          }
-        },
-        "normalize-path": {
-          "version": "3.0.0",
-          "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz",
-          "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==",
+        "camelcase": {
+          "version": "6.0.0",
+          "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.0.0.tgz",
+          "integrity": "sha512-8KMDF1Vz2gzOq54ONPJS65IvTUaB1cHJ2DMM7MbPmLZljDH1qpzzLsWdiN9pHh6qvkRVDTi/07+eNGch/oLU4w==",
           "dev": true
         },
         "semver": {
-          "version": "6.3.0",
-          "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
-          "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==",
+          "version": "7.3.2",
+          "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.2.tgz",
+          "integrity": "sha512-OrOb32TeeambH6UrhtShmF7CRDqhL6/5XpPNp2DuRH6+9QLw/orhp72j87v8Qa1ScDkvrrBNpZcDejAirJmfXQ==",
           "dev": true
         }
       }
@@ -8139,13 +7873,13 @@
       }
     },
     "dmg-builder": {
-      "version": "22.8.0",
-      "resolved": "https://registry.npmjs.org/dmg-builder/-/dmg-builder-22.8.0.tgz",
-      "integrity": "sha512-orePWjcrl97SYLA8F/6UUtbXJSoZCYu5KOP1lVqD4LOomr8bjGDyEVYZmZYcg5WqKmXucdmO6OpqgzH/aRMMuA==",
+      "version": "22.8.1",
+      "resolved": "https://registry.npmjs.org/dmg-builder/-/dmg-builder-22.8.1.tgz",
+      "integrity": "sha512-WeGom1moM00gBII6swljl4DQGrlJuEivoUhOmh8U9p1ALgeJL+EiTHbZFERlj8Ejy62xUUjURV+liOxUKmJFWg==",
       "dev": true,
       "requires": {
-        "app-builder-lib": "22.8.0",
-        "builder-util": "22.8.0",
+        "app-builder-lib": "22.8.1",
+        "builder-util": "22.8.1",
         "fs-extra": "^9.0.1",
         "iconv-lite": "^0.6.2",
         "js-yaml": "^3.14.0",
@@ -8349,9 +8083,9 @@
       }
     },
     "electron": {
-      "version": "10.0.0",
-      "resolved": "https://registry.npmjs.org/electron/-/electron-10.0.0.tgz",
-      "integrity": "sha512-0XX/LqYAHHCSbfLjUk9VRDPOeYjDPEzA9i7F50AqpEpFIWR2bp++0S0beRANUpPdkvtBDp+0R6vHV3iXPvuKyA==",
+      "version": "10.1.2",
+      "resolved": "https://registry.npmjs.org/electron/-/electron-10.1.2.tgz",
+      "integrity": "sha512-SvN8DcKCmPZ0UcQSNAJBfaUu+LGACqtRhUn1rW0UBLHgdbbDM76L0GU5/XGQEllH5pu5bwlCZwax3srzIl+Aeg==",
       "dev": true,
       "requires": {
         "@electron/get": "^1.0.1",
@@ -8360,33 +8094,33 @@
       },
       "dependencies": {
         "@types/node": {
-          "version": "12.12.54",
-          "resolved": "https://registry.npmjs.org/@types/node/-/node-12.12.54.tgz",
-          "integrity": "sha512-ge4xZ3vSBornVYlDnk7yZ0gK6ChHf/CHB7Gl1I0Jhah8DDnEQqBzgohYG4FX4p81TNirSETOiSyn+y1r9/IR6w==",
+          "version": "12.12.61",
+          "resolved": "https://registry.npmjs.org/@types/node/-/node-12.12.61.tgz",
+          "integrity": "sha512-+/KPk6uV9qGfVX0y2uUj3y8O0Z6KZWUy3XTS0uQGYYF+iXGtepm9GPETdcRq+hGmErkLOr5QJDX8vuymkwu4sA==",
           "dev": true
         }
       }
     },
     "electron-builder": {
-      "version": "22.8.0",
-      "resolved": "https://registry.npmjs.org/electron-builder/-/electron-builder-22.8.0.tgz",
-      "integrity": "sha512-dUv4F3srJouqxhWivtKqSoQP4Df6vYgjooGdzms+iYMTFi9f0b4LlEbr7kgsPvte8zAglee7VOGOODkCRJDkUQ==",
+      "version": "22.8.1",
+      "resolved": "https://registry.npmjs.org/electron-builder/-/electron-builder-22.8.1.tgz",
+      "integrity": "sha512-Hs7KTMq1rGSvT0fwGKXrjbLiJkK6sAKDQooUSwklOkktUgWi4ATjlP0fVE3l8SmS7zcLoww2yDZonSDqxEFhaQ==",
       "dev": true,
       "requires": {
         "@types/yargs": "^15.0.5",
-        "app-builder-lib": "22.8.0",
+        "app-builder-lib": "22.8.1",
         "bluebird-lst": "^1.0.9",
-        "builder-util": "22.8.0",
+        "builder-util": "22.8.1",
         "builder-util-runtime": "8.7.2",
         "chalk": "^4.1.0",
-        "dmg-builder": "22.8.0",
+        "dmg-builder": "22.8.1",
         "fs-extra": "^9.0.1",
         "is-ci": "^2.0.0",
         "lazy-val": "^1.0.4",
         "read-config-file": "6.0.0",
         "sanitize-filename": "^1.6.3",
         "update-notifier": "^4.1.0",
-        "yargs": "^15.3.1"
+        "yargs": "^15.4.1"
       },
       "dependencies": {
         "ansi-styles": {
@@ -8425,9 +8159,9 @@
           "dev": true
         },
         "supports-color": {
-          "version": "7.1.0",
-          "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.1.0.tgz",
-          "integrity": "sha512-oRSIpR8pxT1Wr2FquTNnGet79b3BWljqOuoW/h4oBhxJ/HUbX5nX6JSruTkvXDCFMwDPvsaTTbvMLKZWSy0R5g==",
+          "version": "7.2.0",
+          "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
+          "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
           "dev": true,
           "requires": {
             "has-flag": "^4.0.0"
@@ -8436,14 +8170,14 @@
       }
     },
     "electron-publish": {
-      "version": "22.8.0",
-      "resolved": "https://registry.npmjs.org/electron-publish/-/electron-publish-22.8.0.tgz",
-      "integrity": "sha512-uM0Zdi9hUqqGOrPj478v7toTvV1Kgto1w11rIiI168batiXAJvNLD8VZRfehOrZT0ibUyZlw8FtxoGCrjyHUOw==",
+      "version": "22.8.1",
+      "resolved": "https://registry.npmjs.org/electron-publish/-/electron-publish-22.8.1.tgz",
+      "integrity": "sha512-zqI66vl7j1CJZJ60J+1ez1tQNQeuqVspW44JvYDa5kZbM5wSFDAJFMK9RWHOqRF1Ezd4LDeiBa4aeTOwOt9syA==",
       "dev": true,
       "requires": {
         "@types/fs-extra": "^9.0.1",
         "bluebird-lst": "^1.0.9",
-        "builder-util": "22.8.0",
+        "builder-util": "22.8.1",
         "builder-util-runtime": "8.7.2",
         "chalk": "^4.1.0",
         "fs-extra": "^9.0.1",
@@ -8493,9 +8227,9 @@
           "dev": true
         },
         "supports-color": {
-          "version": "7.1.0",
-          "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.1.0.tgz",
-          "integrity": "sha512-oRSIpR8pxT1Wr2FquTNnGet79b3BWljqOuoW/h4oBhxJ/HUbX5nX6JSruTkvXDCFMwDPvsaTTbvMLKZWSy0R5g==",
+          "version": "7.2.0",
+          "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
+          "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
           "dev": true,
           "requires": {
             "has-flag": "^4.0.0"
@@ -8504,9 +8238,9 @@
       }
     },
     "electron-to-chromium": {
-      "version": "1.3.545",
-      "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.545.tgz",
-      "integrity": "sha512-+0R/i17u5E1cwF3g0W8Niq3UUKTUMyyT4kLkutZUHG8mDNvFsAckK3HIanzGVtixe3b6rknD8k7gHiR6nKFkgg==",
+      "version": "1.3.570",
+      "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.570.tgz",
+      "integrity": "sha512-Y6OCoVQgFQBP5py6A/06+yWxUZHDlNr/gNDGatjH8AZqXl8X0tE4LfjLJsXGz/JmWJz8a6K7bR1k+QzZ+k//fg==",
       "dev": true
     },
     "elementtree": {
@@ -8710,9 +8444,9 @@
       }
     },
     "enhanced-resolve": {
-      "version": "4.1.1",
-      "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-4.1.1.tgz",
-      "integrity": "sha512-98p2zE+rL7/g/DzMHMTF4zZlCgeVdJ7yr6xzEpJRYwFYrGi9ANdn5DnJURg6RpBkyk60XYDnWIv51VfIhfNGuA==",
+      "version": "4.3.0",
+      "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-4.3.0.tgz",
+      "integrity": "sha512-3e87LvavsdxyoCfGusJnrZ5G8SLPOFeHSNpZI/ATL9a5leXo2k0w6MKnbqhdBad9qTobSfB20Ld7UmgoNbAZkQ==",
       "dev": true,
       "requires": {
         "graceful-fs": "^4.1.2",
@@ -8770,6 +8504,50 @@
         "is-arrayish": "^0.2.1"
       }
     },
+    "es-abstract": {
+      "version": "1.17.6",
+      "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.17.6.tgz",
+      "integrity": "sha512-Fr89bON3WFyUi5EvAeI48QTWX0AyekGgLA8H+c+7fbfCkJwRWRMLd8CQedNEyJuoYYhmtEqY92pgte1FAhBlhw==",
+      "dev": true,
+      "requires": {
+        "es-to-primitive": "^1.2.1",
+        "function-bind": "^1.1.1",
+        "has": "^1.0.3",
+        "has-symbols": "^1.0.1",
+        "is-callable": "^1.2.0",
+        "is-regex": "^1.1.0",
+        "object-inspect": "^1.7.0",
+        "object-keys": "^1.1.1",
+        "object.assign": "^4.1.0",
+        "string.prototype.trimend": "^1.0.1",
+        "string.prototype.trimstart": "^1.0.1"
+      },
+      "dependencies": {
+        "object-inspect": {
+          "version": "1.8.0",
+          "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.8.0.tgz",
+          "integrity": "sha512-jLdtEOB112fORuypAyl/50VRVIBIdVQOSUUGQHzJ4xBSbit81zRarz7GThkEFZy1RceYrWYcPcBFPQwHyAc1gA==",
+          "dev": true
+        },
+        "object-keys": {
+          "version": "1.1.1",
+          "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz",
+          "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==",
+          "dev": true
+        }
+      }
+    },
+    "es-to-primitive": {
+      "version": "1.2.1",
+      "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz",
+      "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==",
+      "dev": true,
+      "requires": {
+        "is-callable": "^1.1.4",
+        "is-date-object": "^1.0.1",
+        "is-symbol": "^1.0.2"
+      }
+    },
     "es5-ext": {
       "version": "0.10.53",
       "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.53.tgz",
@@ -8814,9 +8592,9 @@
       }
     },
     "es6-promise": {
-      "version": "4.2.8",
-      "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-4.2.8.tgz",
-      "integrity": "sha512-HJDGx5daxeIvxdBxvG2cb9g4tEvwIk3i8+nhX0yGrYmZUzbkdg8QbDevheDB8gd0//uPj4c1EQua8Q+MViT0/w==",
+      "version": "4.2.5",
+      "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-4.2.5.tgz",
+      "integrity": "sha512-n6wvpdE43VFtJq+lUDYDBFUwV8TZbuGXLV4D6wKafg13ldznKsyEvatubnmUe31zcvelSzOHF+XbaT+Bl9ObDg==",
       "dev": true
     },
     "es6-promisify": {
@@ -8864,9 +8642,9 @@
       }
     },
     "escalade": {
-      "version": "3.0.2",
-      "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.0.2.tgz",
-      "integrity": "sha512-gPYAU37hYCUhW5euPeR+Y74F7BL+IBsV93j5cvGriSaD1aG6MGsqsV1yamRdrWrb2j3aiZvb0X+UBOWpx3JWtQ==",
+      "version": "3.1.0",
+      "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.0.tgz",
+      "integrity": "sha512-mAk+hPSO8fLDkhV7V0dXazH5pDc6MrjBTPyD3VeKzxnVFjH1MIxbCdqGZB9O8+EwWakZs3ZCbDS4IpRt79V1ig==",
       "dev": true
     },
     "escape-goat": {
@@ -8930,12 +8708,20 @@
       "dev": true
     },
     "esrecurse": {
-      "version": "4.2.1",
-      "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.2.1.tgz",
-      "integrity": "sha512-64RBB++fIOAXPw3P9cy89qfMlvZEXZkqqJkjqqXIvzP5ezRZjW+lPWjw35UX/3EhUPFYbg5ER4JYgDw4007/DQ==",
+      "version": "4.3.0",
+      "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz",
+      "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==",
       "dev": true,
       "requires": {
-        "estraverse": "^4.1.0"
+        "estraverse": "^5.2.0"
+      },
+      "dependencies": {
+        "estraverse": {
+          "version": "5.2.0",
+          "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.2.0.tgz",
+          "integrity": "sha512-BxbNGGNm0RyRYvUdHpIwv9IWzeM9XClbOxwoATuFdOE7ZE6wHL+HQ5T8hoPM+zHvmKzzsEqhgy0GrQ5X13afiQ==",
+          "dev": true
+        }
       }
     },
     "estraverse": {
@@ -9637,15 +9423,6 @@
             "p-locate": "^4.1.0"
           }
         },
-        "make-dir": {
-          "version": "3.1.0",
-          "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz",
-          "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==",
-          "dev": true,
-          "requires": {
-            "semver": "^6.0.0"
-          }
-        },
         "p-locate": {
           "version": "4.1.0",
           "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz",
@@ -9669,12 +9446,6 @@
           "requires": {
             "find-up": "^4.0.0"
           }
-        },
-        "semver": {
-          "version": "6.3.0",
-          "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
-          "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==",
-          "dev": true
         }
       }
     },
@@ -10921,9 +10692,9 @@
       "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0="
     },
     "has-symbols": {
-      "version": "1.0.0",
-      "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.0.tgz",
-      "integrity": "sha1-uhqPGvKg/DllD1yFA2dwQSIGO0Q=",
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.1.tgz",
+      "integrity": "sha512-PLcsoqu++dmEIZB+6totNFKq/7Do+Z0u4oT0zKOJNl3lYK6vGwwu2hjHs+68OEZbTjiUE9bgOABXbP/GvrS0Kg==",
       "dev": true
     },
     "has-value": {
@@ -11234,6 +11005,15 @@
         "debug": "^3.1.0"
       },
       "dependencies": {
+        "agent-base": {
+          "version": "4.3.0",
+          "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-4.3.0.tgz",
+          "integrity": "sha512-salcGninV0nPrwpGNn4VTXBb1SOuXQBiqbrNXoeizJsHrsL6ERFM2Ne3JUSBWRE6aeNJI2ROP/WEEIDUiDe3cg==",
+          "dev": true,
+          "requires": {
+            "es6-promisify": "^5.0.0"
+          }
+        },
         "debug": {
           "version": "3.2.6",
           "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz",
@@ -11644,6 +11424,12 @@
       "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==",
       "dev": true
     },
+    "is-callable": {
+      "version": "1.2.0",
+      "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.0.tgz",
+      "integrity": "sha512-pyVD9AaGLxtg6srb2Ng6ynWJqkHU9bEM087AKck0w8QwDarTfNcpIYoU8x8Hv2Icm8u6kFJM18Dag8lyqGkviw==",
+      "dev": true
+    },
     "is-ci": {
       "version": "2.0.0",
       "resolved": "https://registry.npmjs.org/is-ci/-/is-ci-2.0.0.tgz",
@@ -11688,9 +11474,9 @@
       }
     },
     "is-date-object": {
-      "version": "1.0.1",
-      "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.1.tgz",
-      "integrity": "sha1-mqIOtq7rv/d/vTPnTKAbM1gdOhY=",
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.2.tgz",
+      "integrity": "sha512-USlDT524woQ08aoZFzh3/Z6ch9Y/EWXEHQ/AaRN0SkKq4t2Jw2R2339tSXmwuVoY7LLlBCbOIlx2myP/L5zk0g==",
       "dev": true
     },
     "is-descriptor": {
@@ -11833,6 +11619,21 @@
         "isobject": "^3.0.1"
       }
     },
+    "is-promise": {
+      "version": "2.1.0",
+      "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-2.1.0.tgz",
+      "integrity": "sha1-eaKp7OfwlugPNtKy87wWwf9L8/o=",
+      "dev": true
+    },
+    "is-regex": {
+      "version": "1.1.1",
+      "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.1.tgz",
+      "integrity": "sha512-1+QkEcxiLlB7VEyFtyBg94e08OAsvq7FUBgApTq/w2ymCLyKJgDPsybBENVtA7XCQEgEXxKPonG+mvYRxh/LIg==",
+      "dev": true,
+      "requires": {
+        "has-symbols": "^1.0.1"
+      }
+    },
     "is-relative": {
       "version": "1.0.0",
       "resolved": "https://registry.npmjs.org/is-relative/-/is-relative-1.0.0.tgz",
@@ -11864,12 +11665,12 @@
       }
     },
     "is-symbol": {
-      "version": "1.0.2",
-      "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.2.tgz",
-      "integrity": "sha512-HS8bZ9ox60yCJLH9snBpIwv9pYUAkcuLhSA1oero1UB5y9aiQpRA8y2ex945AOtCZL1lJDeIk3G5LthswI46Lw==",
+      "version": "1.0.3",
+      "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.3.tgz",
+      "integrity": "sha512-OwijhaRSgqvhm/0ZdAcXNZt9lYdKFpcRDT5ULUuYXPoT794UNOdU+gpT6Rzo7b4V2HUl/op6GqY894AZwv9faQ==",
       "dev": true,
       "requires": {
-        "has-symbols": "^1.0.0"
+        "has-symbols": "^1.0.1"
       }
     },
     "is-typedarray": {
@@ -12142,11 +11943,12 @@
       "dev": true
     },
     "jest-worker": {
-      "version": "26.0.0",
-      "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-26.0.0.tgz",
-      "integrity": "sha512-pPaYa2+JnwmiZjK9x7p9BoZht+47ecFCDFA/CJxspHzeDvQcfVBLWzCiWyo+EGrSiQMWZtCFo9iSvMZnAAo8vw==",
+      "version": "26.3.0",
+      "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-26.3.0.tgz",
+      "integrity": "sha512-Vmpn2F6IASefL+DVBhPzI2J9/GJUsqzomdeN+P+dK8/jKxbh8R3BtFnx3FIta7wYlPU62cpJMJQo4kuOowcMnw==",
       "dev": true,
       "requires": {
+        "@types/node": "*",
         "merge-stream": "^2.0.0",
         "supports-color": "^7.0.0"
       },
@@ -12158,9 +11960,9 @@
           "dev": true
         },
         "supports-color": {
-          "version": "7.1.0",
-          "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.1.0.tgz",
-          "integrity": "sha512-oRSIpR8pxT1Wr2FquTNnGet79b3BWljqOuoW/h4oBhxJ/HUbX5nX6JSruTkvXDCFMwDPvsaTTbvMLKZWSy0R5g==",
+          "version": "7.2.0",
+          "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
+          "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
           "dev": true,
           "requires": {
             "has-flag": "^4.0.0"
@@ -12247,6 +12049,12 @@
         "minimist": "^1.2.5"
       }
     },
+    "jsonc-parser": {
+      "version": "2.3.0",
+      "resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-2.3.0.tgz",
+      "integrity": "sha512-b0EBt8SWFNnixVdvoR2ZtEGa9ZqLhbJnOjezn+WP+8kspFm+PFYDN8Z4Bc7pRlDjvuVcADSUkroIuTWWn/YiIA==",
+      "dev": true
+    },
     "jsonfile": {
       "version": "4.0.0",
       "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz",
@@ -12287,24 +12095,23 @@
       }
     },
     "karma": {
-      "version": "5.1.1",
-      "resolved": "https://registry.npmjs.org/karma/-/karma-5.1.1.tgz",
-      "integrity": "sha512-xAlOr5PMqUbiKXSv5PCniHWV3aiwj6wIZ0gUVcwpTCPVQm/qH2WAMFWxtnpM6KJqhkRWrIpovR4Rb0rn8GtJzQ==",
+      "version": "5.2.2",
+      "resolved": "https://registry.npmjs.org/karma/-/karma-5.2.2.tgz",
+      "integrity": "sha512-rB3Ua5yDxmIupTj67r3Q8itz7TxJzRE6DmVcOfV20D509Uu9AoBKlVwbZhND4kcm6BqLfbHtv4DZC9QJfrUY+w==",
       "dev": true,
       "requires": {
         "body-parser": "^1.19.0",
         "braces": "^3.0.2",
-        "chokidar": "^3.0.0",
+        "chokidar": "^3.4.2",
         "colors": "^1.4.0",
         "connect": "^3.7.0",
         "di": "^0.0.1",
         "dom-serialize": "^2.2.1",
-        "flatted": "^2.0.2",
         "glob": "^7.1.6",
         "graceful-fs": "^4.2.4",
         "http-proxy": "^1.18.1",
         "isbinaryfile": "^4.0.6",
-        "lodash": "^4.17.15",
+        "lodash": "^4.17.19",
         "log4js": "^6.2.1",
         "mime": "^2.4.5",
         "minimatch": "^3.0.4",
@@ -12318,6 +12125,22 @@
         "yargs": "^15.3.1"
       },
       "dependencies": {
+        "anymatch": {
+          "version": "3.1.1",
+          "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.1.tgz",
+          "integrity": "sha512-mM8522psRCqzV+6LhomX5wgp25YVibjh8Wj23I5RPkPppSVSjyKD2A2mBJmWGa+KN7f2D6LNh9jkBCeyLktzjg==",
+          "dev": true,
+          "requires": {
+            "normalize-path": "^3.0.0",
+            "picomatch": "^2.0.4"
+          }
+        },
+        "binary-extensions": {
+          "version": "2.1.0",
+          "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.1.0.tgz",
+          "integrity": "sha512-1Yj8h9Q+QDF5FzhMs/c9+6UntbD5MkRfRwac8DoEm9ZfUBZ7tZ55YcGVAzEe4bXsdQHEk+s9S5wsOKVdZrw0tQ==",
+          "dev": true
+        },
         "braces": {
           "version": "3.0.2",
           "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz",
@@ -12327,6 +12150,22 @@
             "fill-range": "^7.0.1"
           }
         },
+        "chokidar": {
+          "version": "3.4.2",
+          "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.4.2.tgz",
+          "integrity": "sha512-IZHaDeBeI+sZJRX7lGcXsdzgvZqKv6sECqsbErJA4mHWfpRrD8B97kSFN4cQz6nGBGiuFia1MKR4d6c1o8Cv7A==",
+          "dev": true,
+          "requires": {
+            "anymatch": "~3.1.1",
+            "braces": "~3.0.2",
+            "fsevents": "~2.1.2",
+            "glob-parent": "~5.1.0",
+            "is-binary-path": "~2.1.0",
+            "is-glob": "~4.0.1",
+            "normalize-path": "~3.0.0",
+            "readdirp": "~3.4.0"
+          }
+        },
         "connect": {
           "version": "3.7.0",
           "resolved": "https://registry.npmjs.org/connect/-/connect-3.7.0.tgz",
@@ -12348,6 +12187,13 @@
             "to-regex-range": "^5.0.1"
           }
         },
+        "fsevents": {
+          "version": "2.1.3",
+          "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.1.3.tgz",
+          "integrity": "sha512-Auw9a4AxqWpa9GUfj370BMPzzyncfBABW8Mab7BGWBYDj4Isgq+cDKtx0i6u9jcX9pQDnswsaaOTgTmA5pEjuQ==",
+          "dev": true,
+          "optional": true
+        },
         "glob": {
           "version": "7.1.6",
           "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz",
@@ -12362,12 +12208,39 @@
             "path-is-absolute": "^1.0.0"
           }
         },
+        "glob-parent": {
+          "version": "5.1.1",
+          "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.1.tgz",
+          "integrity": "sha512-FnI+VGOpnlGHWZxthPGR+QhR78fuiK0sNLkHQv+bL9fQi57lNNdquIbna/WrfROrolq8GK5Ek6BiMwqL/voRYQ==",
+          "dev": true,
+          "requires": {
+            "is-glob": "^4.0.1"
+          }
+        },
         "graceful-fs": {
           "version": "4.2.4",
           "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.4.tgz",
           "integrity": "sha512-WjKPNJF79dtJAVniUlGGWHYGz2jWxT6VhN/4m1NdkbZ2nOsEF+cI1Edgql5zCRhs/VsQYRvrXctxktVXZUkixw==",
           "dev": true
         },
+        "is-binary-path": {
+          "version": "2.1.0",
+          "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz",
+          "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==",
+          "dev": true,
+          "requires": {
+            "binary-extensions": "^2.0.0"
+          }
+        },
+        "is-glob": {
+          "version": "4.0.1",
+          "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.1.tgz",
+          "integrity": "sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg==",
+          "dev": true,
+          "requires": {
+            "is-extglob": "^2.1.1"
+          }
+        },
         "is-number": {
           "version": "7.0.0",
           "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz",
@@ -12380,12 +12253,35 @@
           "integrity": "sha512-RZKhC3EmpBchfTGBVb8fb+RL2cWyw/32lshnsETttkBAyAUXSGHxbEJWWRXc751DrIxG1q04b8QwMbAwkRPpUA==",
           "dev": true
         },
+        "normalize-path": {
+          "version": "3.0.0",
+          "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz",
+          "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==",
+          "dev": true
+        },
         "parseurl": {
           "version": "1.3.3",
           "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz",
           "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==",
           "dev": true
         },
+        "readdirp": {
+          "version": "3.4.0",
+          "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.4.0.tgz",
+          "integrity": "sha512-0xe001vZBnJEK+uKcj8qOhyAKPzIT+gStxWr3LCB0DwcXR5NZJ3IaC+yGnHCYzB/S7ov3m3EEbZI2zeNvX+hGQ==",
+          "dev": true,
+          "requires": {
+            "picomatch": "^2.2.1"
+          },
+          "dependencies": {
+            "picomatch": {
+              "version": "2.2.2",
+              "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.2.2.tgz",
+              "integrity": "sha512-q0M/9eZHzmr0AulXyPwNfZjtwZ/RBZlbN3K3CErVrk50T2ASYI7Bye0EvekFY3IP1Nt2DHu0re+V2ZHIpMkuWg==",
+              "dev": true
+            }
+          }
+        },
         "rimraf": {
           "version": "3.0.2",
           "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz",
@@ -12521,6 +12417,12 @@
       "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==",
       "dev": true
     },
+    "klona": {
+      "version": "2.0.4",
+      "resolved": "https://registry.npmjs.org/klona/-/klona-2.0.4.tgz",
+      "integrity": "sha512-ZRbnvdg/NxqzC7L9Uyqzf4psi1OM4Cuc+sJAkQPjO6XkQIJTNbfK2Rsmbw8fx1p2mkZdp2FZYo2+LwXYY/uwIA==",
+      "dev": true
+    },
     "latest-version": {
       "version": "5.1.0",
       "resolved": "https://registry.npmjs.org/latest-version/-/latest-version-5.1.0.tgz",
@@ -12593,15 +12495,15 @@
       }
     },
     "less-loader": {
-      "version": "6.1.0",
-      "resolved": "https://registry.npmjs.org/less-loader/-/less-loader-6.1.0.tgz",
-      "integrity": "sha512-/jLzOwLyqJ7Kt3xg5sHHkXtOyShWwFj410K9Si9WO+/h8rmYxxkSR0A3/hFEntWudE20zZnWMtpMYnLzqTVdUA==",
+      "version": "6.2.0",
+      "resolved": "https://registry.npmjs.org/less-loader/-/less-loader-6.2.0.tgz",
+      "integrity": "sha512-Cl5h95/Pz/PWub/tCBgT1oNMFeH1WTD33piG80jn5jr12T4XbxZcjThwNXDQ7AG649WEynuIzO4b0+2Tn9Qolg==",
       "dev": true,
       "requires": {
         "clone": "^2.1.2",
-        "less": "^3.11.1",
+        "less": "^3.11.3",
         "loader-utils": "^2.0.0",
-        "schema-utils": "^2.6.6"
+        "schema-utils": "^2.7.0"
       }
     },
     "leven": {
@@ -12630,9 +12532,9 @@
       }
     },
     "license-webpack-plugin": {
-      "version": "2.2.0",
-      "resolved": "https://registry.npmjs.org/license-webpack-plugin/-/license-webpack-plugin-2.2.0.tgz",
-      "integrity": "sha512-XPsdL/0brSHf+7dXIlRqotnCQ58RX2au6otkOg4U3dm8uH+Ka/fW4iukEs95uXm+qKe/SBs+s1Ll/aQddKG+tg==",
+      "version": "2.3.0",
+      "resolved": "https://registry.npmjs.org/license-webpack-plugin/-/license-webpack-plugin-2.3.0.tgz",
+      "integrity": "sha512-JK/DXrtN6UeYQSgkg5q1+pgJ8aiKPL9tnz9Wzw+Ikkf+8mJxG56x6t8O+OH/tAeF/5NREnelTEMyFtbJNkjH4w==",
       "dev": true,
       "requires": {
         "@types/webpack-sources": "^0.1.5",
@@ -12873,12 +12775,58 @@
       "dev": true
     },
     "log-symbols": {
-      "version": "3.0.0",
-      "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-3.0.0.tgz",
-      "integrity": "sha512-dSkNGuI7iG3mfvDzUuYZyvk5dD9ocYCYzNU6CYDE6+Xqd+gwme6Z00NS3dUh8mq/73HaEtT7m6W+yUPtU6BZnQ==",
+      "version": "4.0.0",
+      "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.0.0.tgz",
+      "integrity": "sha512-FN8JBzLx6CzeMrB0tg6pqlGU1wCrXW+ZXGH481kfsBqer0hToTIiHdjH4Mq8xJUbvATujKCvaREGWpGUionraA==",
       "dev": true,
       "requires": {
-        "chalk": "^2.4.2"
+        "chalk": "^4.0.0"
+      },
+      "dependencies": {
+        "ansi-styles": {
+          "version": "4.2.1",
+          "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.2.1.tgz",
+          "integrity": "sha512-9VGjrMsG1vePxcSweQsN20KY/c4zN0h9fLjqAbwbPfahM3t+NL+M9HC8xeXG2I8pX5NoamTGNuomEUFI7fcUjA==",
+          "dev": true,
+          "requires": {
+            "@types/color-name": "^1.1.1",
+            "color-convert": "^2.0.1"
+          }
+        },
+        "chalk": {
+          "version": "4.1.0",
+          "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.0.tgz",
+          "integrity": "sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A==",
+          "dev": true,
+          "requires": {
+            "ansi-styles": "^4.1.0",
+            "supports-color": "^7.1.0"
+          }
+        },
+        "color-convert": {
+          "version": "2.0.1",
+          "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
+          "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
+          "dev": true,
+          "requires": {
+            "color-name": "~1.1.4"
+          }
+        },
+        "has-flag": {
+          "version": "4.0.0",
+          "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
+          "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
+          "dev": true
+        },
+        "supports-color": {
+          "version": "7.2.0",
+          "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
+          "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
+          "dev": true,
+          "requires": {
+            "has-flag": "^4.0.0"
+          }
+        }
       }
     },
     "log4js": {
@@ -13146,9 +13094,9 @@
       "integrity": "sha1-mnHEh0chjrylHlGmbaaCA4zct78="
     },
     "mathjax": {
-      "version": "3.0.5",
-      "resolved": "https://registry.npmjs.org/mathjax/-/mathjax-3.0.5.tgz",
-      "integrity": "sha512-9M7VulhltkD8sIebWutK/VfAD+m+6BIFqfpjDh9Pz/etoKUtjO6UMnOhUcDmNl6iApE8C9xrUmaMyNZkZAlrMw=="
+      "version": "3.1.2",
+      "resolved": "https://registry.npmjs.org/mathjax/-/mathjax-3.1.2.tgz",
+      "integrity": "sha512-BojKspBv4nNWzO1wC6VEI+g9gHDOhkaGHGgLxXkasdU4pwjdO5AXD5M/wcLPkXYPjZ/N+6sU8rjQTlyvN2cWiQ=="
     },
     "md5-file": {
       "version": "5.0.0",
@@ -13224,9 +13172,9 @@
       "dev": true
     },
     "mermaid": {
-      "version": "8.7.0",
-      "resolved": "https://registry.npmjs.org/mermaid/-/mermaid-8.7.0.tgz",
-      "integrity": "sha512-SkinxAY3sIdML+o5U4U7rQEIa628OEywEw+pfhc3wSVDFqLk2XNdX2j3YmkyCw3Kcbp9BXar533ei+/saYBs5g==",
+      "version": "8.8.0",
+      "resolved": "https://registry.npmjs.org/mermaid/-/mermaid-8.8.0.tgz",
+      "integrity": "sha512-SbMzt5T6+XMkHRUECHUneq26H8bvjF752YZCKCJ4G8UU7qI2OmmxYdj4ZJnda7JIx3EuNeN4xSLuLCBJ5ByzSQ==",
       "requires": {
         "@braintree/sanitize-url": "^3.1.0",
         "babel-eslint": "^10.1.0",
@@ -13320,9 +13268,9 @@
       "dev": true
     },
     "mini-css-extract-plugin": {
-      "version": "0.9.0",
-      "resolved": "https://registry.npmjs.org/mini-css-extract-plugin/-/mini-css-extract-plugin-0.9.0.tgz",
-      "integrity": "sha512-lp3GeY7ygcgAmVIcRPBVhIkf8Us7FZjA+ILpal44qLdSu11wmjKQ3d9k15lfD7pO4esu9eUIAW7qiYIBppv40A==",
+      "version": "0.10.0",
+      "resolved": "https://registry.npmjs.org/mini-css-extract-plugin/-/mini-css-extract-plugin-0.10.0.tgz",
+      "integrity": "sha512-QgKgJBjaJhxVPwrLNqqwNS0AGkuQQ31Hp4xGXEK/P7wehEg6qmNtReHKai3zRXqY60wGVWLYcOMJK2b98aGc3A==",
       "dev": true,
       "requires": {
         "loader-utils": "^1.1.0",
@@ -13438,14 +13386,6 @@
       "dev": true,
       "requires": {
         "yallist": "^4.0.0"
-      },
-      "dependencies": {
-        "yallist": {
-          "version": "4.0.0",
-          "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
-          "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==",
-          "dev": true
-        }
       }
     },
     "minipass-collect": {
@@ -13483,14 +13423,6 @@
       "requires": {
         "minipass": "^3.0.0",
         "yallist": "^4.0.0"
-      },
-      "dependencies": {
-        "yallist": {
-          "version": "4.0.0",
-          "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
-          "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==",
-          "dev": true
-        }
       }
     },
     "mississippi": {
@@ -13591,23 +13523,6 @@
         "run-queue": "^1.0.3"
       }
     },
-    "move-file": {
-      "version": "2.0.0",
-      "resolved": "https://registry.npmjs.org/move-file/-/move-file-2.0.0.tgz",
-      "integrity": "sha512-cdkdhNCgbP5dvS4tlGxZbD+nloio9GIimP57EjqFhwLcMjnU+XJKAZzlmg/TN/AK1LuNAdTSvm3CPPP4Xkv0iQ==",
-      "dev": true,
-      "requires": {
-        "path-exists": "^4.0.0"
-      },
-      "dependencies": {
-        "path-exists": {
-          "version": "4.0.0",
-          "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz",
-          "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==",
-          "dev": true
-        }
-      }
-    },
     "ms": {
       "version": "2.0.0",
       "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
@@ -13649,9 +13564,9 @@
       "dev": true
     },
     "nan": {
-      "version": "2.14.0",
-      "resolved": "https://registry.npmjs.org/nan/-/nan-2.14.0.tgz",
-      "integrity": "sha512-INOFj37C7k3AfaNTtX8RhsTw7qRy7eLET14cROi9+5HAVbbHuIWUHEauBv5qT4Av2tWasiTY1Jw6puUNqRJXQg==",
+      "version": "2.12.1",
+      "resolved": "https://registry.npmjs.org/nan/-/nan-2.12.1.tgz",
+      "integrity": "sha512-JY7V6lRkStKcKTvHO5NVSQRv+RV+FIL5pvDoLiAtSL9pKlC5x9PKQcZDsq7m4FO4d57mkhC6Z+QhAh3Jdk5JFw==",
       "dev": true,
       "optional": true
     },
@@ -13829,9 +13744,9 @@
       }
     },
     "node-releases": {
-      "version": "1.1.60",
-      "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-1.1.60.tgz",
-      "integrity": "sha512-gsO4vjEdQaTusZAEebUWp2a5d7dF5DYoIpDG7WySnk7BuZDW+GPpHXoXXuYawRBr/9t5q54tirPz79kFIWg4dA==",
+      "version": "1.1.61",
+      "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-1.1.61.tgz",
+      "integrity": "sha512-DD5vebQLg8jLCOzwupn954fbIiZht05DAZs0k2u8NStSe6h9XdsuIQL8hSRKYiU8WUQRznmSDrKGbv3ObOmC7g==",
       "dev": true
     },
     "nopt": {
@@ -13962,15 +13877,6 @@
             "lru-cache": "^6.0.0"
           }
         },
-        "lru-cache": {
-          "version": "6.0.0",
-          "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz",
-          "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==",
-          "dev": true,
-          "requires": {
-            "yallist": "^4.0.0"
-          }
-        },
         "npm-package-arg": {
           "version": "8.0.1",
           "resolved": "https://registry.npmjs.org/npm-package-arg/-/npm-package-arg-8.0.1.tgz",
@@ -13987,12 +13893,6 @@
           "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.2.tgz",
           "integrity": "sha512-OrOb32TeeambH6UrhtShmF7CRDqhL6/5XpPNp2DuRH6+9QLw/orhp72j87v8Qa1ScDkvrrBNpZcDejAirJmfXQ==",
           "dev": true
-        },
-        "yallist": {
-          "version": "4.0.0",
-          "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
-          "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==",
-          "dev": true
         }
       }
     },
@@ -14154,71 +14054,6 @@
       "requires": {
         "define-properties": "^1.1.3",
         "es-abstract": "^1.17.0-next.1"
-      },
-      "dependencies": {
-        "es-abstract": {
-          "version": "1.17.6",
-          "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.17.6.tgz",
-          "integrity": "sha512-Fr89bON3WFyUi5EvAeI48QTWX0AyekGgLA8H+c+7fbfCkJwRWRMLd8CQedNEyJuoYYhmtEqY92pgte1FAhBlhw==",
-          "dev": true,
-          "requires": {
-            "es-to-primitive": "^1.2.1",
-            "function-bind": "^1.1.1",
-            "has": "^1.0.3",
-            "has-symbols": "^1.0.1",
-            "is-callable": "^1.2.0",
-            "is-regex": "^1.1.0",
-            "object-inspect": "^1.7.0",
-            "object-keys": "^1.1.1",
-            "object.assign": "^4.1.0",
-            "string.prototype.trimend": "^1.0.1",
-            "string.prototype.trimstart": "^1.0.1"
-          }
-        },
-        "es-to-primitive": {
-          "version": "1.2.1",
-          "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz",
-          "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==",
-          "dev": true,
-          "requires": {
-            "is-callable": "^1.1.4",
-            "is-date-object": "^1.0.1",
-            "is-symbol": "^1.0.2"
-          }
-        },
-        "has-symbols": {
-          "version": "1.0.1",
-          "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.1.tgz",
-          "integrity": "sha512-PLcsoqu++dmEIZB+6totNFKq/7Do+Z0u4oT0zKOJNl3lYK6vGwwu2hjHs+68OEZbTjiUE9bgOABXbP/GvrS0Kg==",
-          "dev": true
-        },
-        "is-callable": {
-          "version": "1.2.0",
-          "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.0.tgz",
-          "integrity": "sha512-pyVD9AaGLxtg6srb2Ng6ynWJqkHU9bEM087AKck0w8QwDarTfNcpIYoU8x8Hv2Icm8u6kFJM18Dag8lyqGkviw==",
-          "dev": true
-        },
-        "is-regex": {
-          "version": "1.1.1",
-          "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.1.tgz",
-          "integrity": "sha512-1+QkEcxiLlB7VEyFtyBg94e08OAsvq7FUBgApTq/w2ymCLyKJgDPsybBENVtA7XCQEgEXxKPonG+mvYRxh/LIg==",
-          "dev": true,
-          "requires": {
-            "has-symbols": "^1.0.1"
-          }
-        },
-        "object-inspect": {
-          "version": "1.8.0",
-          "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.8.0.tgz",
-          "integrity": "sha512-jLdtEOB112fORuypAyl/50VRVIBIdVQOSUUGQHzJ4xBSbit81zRarz7GThkEFZy1RceYrWYcPcBFPQwHyAc1gA==",
-          "dev": true
-        },
-        "object-keys": {
-          "version": "1.1.1",
-          "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz",
-          "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==",
-          "dev": true
-        }
       }
     },
     "object.pick": {
@@ -14240,71 +14075,6 @@
         "es-abstract": "^1.17.0-next.1",
         "function-bind": "^1.1.1",
         "has": "^1.0.3"
-      },
-      "dependencies": {
-        "es-abstract": {
-          "version": "1.17.6",
-          "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.17.6.tgz",
-          "integrity": "sha512-Fr89bON3WFyUi5EvAeI48QTWX0AyekGgLA8H+c+7fbfCkJwRWRMLd8CQedNEyJuoYYhmtEqY92pgte1FAhBlhw==",
-          "dev": true,
-          "requires": {
-            "es-to-primitive": "^1.2.1",
-            "function-bind": "^1.1.1",
-            "has": "^1.0.3",
-            "has-symbols": "^1.0.1",
-            "is-callable": "^1.2.0",
-            "is-regex": "^1.1.0",
-            "object-inspect": "^1.7.0",
-            "object-keys": "^1.1.1",
-            "object.assign": "^4.1.0",
-            "string.prototype.trimend": "^1.0.1",
-            "string.prototype.trimstart": "^1.0.1"
-          }
-        },
-        "es-to-primitive": {
-          "version": "1.2.1",
-          "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz",
-          "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==",
-          "dev": true,
-          "requires": {
-            "is-callable": "^1.1.4",
-            "is-date-object": "^1.0.1",
-            "is-symbol": "^1.0.2"
-          }
-        },
-        "has-symbols": {
-          "version": "1.0.1",
-          "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.1.tgz",
-          "integrity": "sha512-PLcsoqu++dmEIZB+6totNFKq/7Do+Z0u4oT0zKOJNl3lYK6vGwwu2hjHs+68OEZbTjiUE9bgOABXbP/GvrS0Kg==",
-          "dev": true
-        },
-        "is-callable": {
-          "version": "1.2.0",
-          "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.0.tgz",
-          "integrity": "sha512-pyVD9AaGLxtg6srb2Ng6ynWJqkHU9bEM087AKck0w8QwDarTfNcpIYoU8x8Hv2Icm8u6kFJM18Dag8lyqGkviw==",
-          "dev": true
-        },
-        "is-regex": {
-          "version": "1.1.1",
-          "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.1.tgz",
-          "integrity": "sha512-1+QkEcxiLlB7VEyFtyBg94e08OAsvq7FUBgApTq/w2ymCLyKJgDPsybBENVtA7XCQEgEXxKPonG+mvYRxh/LIg==",
-          "dev": true,
-          "requires": {
-            "has-symbols": "^1.0.1"
-          }
-        },
-        "object-inspect": {
-          "version": "1.8.0",
-          "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.8.0.tgz",
-          "integrity": "sha512-jLdtEOB112fORuypAyl/50VRVIBIdVQOSUUGQHzJ4xBSbit81zRarz7GThkEFZy1RceYrWYcPcBFPQwHyAc1gA==",
-          "dev": true
-        },
-        "object-keys": {
-          "version": "1.1.1",
-          "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz",
-          "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==",
-          "dev": true
-        }
       }
     },
     "objectorarray": {
@@ -14400,16 +14170,16 @@
       }
     },
     "ora": {
-      "version": "4.0.4",
-      "resolved": "https://registry.npmjs.org/ora/-/ora-4.0.4.tgz",
-      "integrity": "sha512-77iGeVU1cIdRhgFzCK8aw1fbtT1B/iZAvWjS+l/o1x0RShMgxHUZaD2yDpWsNCPwXg9z1ZA78Kbdvr8kBmG/Ww==",
+      "version": "5.0.0",
+      "resolved": "https://registry.npmjs.org/ora/-/ora-5.0.0.tgz",
+      "integrity": "sha512-s26qdWqke2kjN/wC4dy+IQPBIMWBJlSU/0JZhk30ZDBLelW25rv66yutUWARMigpGPzcXHb+Nac5pNhN/WsARw==",
       "dev": true,
       "requires": {
-        "chalk": "^3.0.0",
+        "chalk": "^4.1.0",
         "cli-cursor": "^3.1.0",
-        "cli-spinners": "^2.2.0",
+        "cli-spinners": "^2.4.0",
         "is-interactive": "^1.0.0",
-        "log-symbols": "^3.0.0",
+        "log-symbols": "^4.0.0",
         "mute-stream": "0.0.8",
         "strip-ansi": "^6.0.0",
         "wcwidth": "^1.0.1"
@@ -14432,9 +14202,9 @@
           }
         },
         "chalk": {
-          "version": "3.0.0",
-          "resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz",
-          "integrity": "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==",
+          "version": "4.1.0",
+          "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.0.tgz",
+          "integrity": "sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A==",
           "dev": true,
           "requires": {
             "ansi-styles": "^4.1.0",
@@ -14463,22 +14233,7 @@
           "version": "4.0.0",
           "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
           "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
-          "dev": true
-        },
-        "mute-stream": {
-          "version": "0.0.8",
-          "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.8.tgz",
-          "integrity": "sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==",
-          "dev": true
-        },
-        "onetime": {
-          "version": "5.1.2",
-          "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz",
-          "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==",
-          "dev": true,
-          "requires": {
-            "mimic-fn": "^2.1.0"
-          }
+          "dev": true
         },
         "restore-cursor": {
           "version": "3.1.0",
@@ -14500,9 +14255,9 @@
           }
         },
         "supports-color": {
-          "version": "7.1.0",
-          "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.1.0.tgz",
-          "integrity": "sha512-oRSIpR8pxT1Wr2FquTNnGet79b3BWljqOuoW/h4oBhxJ/HUbX5nX6JSruTkvXDCFMwDPvsaTTbvMLKZWSy0R5g==",
+          "version": "7.2.0",
+          "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
+          "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
           "dev": true,
           "requires": {
             "has-flag": "^4.0.0"
@@ -14874,11 +14629,20 @@
       "dev": true
     },
     "parse5": {
-      "version": "4.0.0",
-      "resolved": "https://registry.npmjs.org/parse5/-/parse5-4.0.0.tgz",
-      "integrity": "sha512-VrZ7eOd3T1Fk4XWNXMgiGBK/z0MG48BWG2uQNU4I72fkQuKUTZpl+u9k+CxEG0twMVzSmXEEz12z5Fnw1jIQFA==",
+      "version": "6.0.1",
+      "resolved": "https://registry.npmjs.org/parse5/-/parse5-6.0.1.tgz",
+      "integrity": "sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw==",
       "dev": true
     },
+    "parse5-htmlparser2-tree-adapter": {
+      "version": "6.0.1",
+      "resolved": "https://registry.npmjs.org/parse5-htmlparser2-tree-adapter/-/parse5-htmlparser2-tree-adapter-6.0.1.tgz",
+      "integrity": "sha512-qPuWvbLgvDGilKc5BoicRovlT4MtYT6JfJyBOMDsKoiT+GiuP5qyrPCnR9HcPECIJJmZh5jRndyNThnhhb/vlA==",
+      "dev": true,
+      "requires": {
+        "parse5": "^6.0.1"
+      }
+    },
     "parseqs": {
       "version": "0.0.5",
       "resolved": "https://registry.npmjs.org/parseqs/-/parseqs-0.0.5.tgz",
@@ -15183,9 +14947,9 @@
       "dev": true
     },
     "postcss": {
-      "version": "7.0.31",
-      "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.31.tgz",
-      "integrity": "sha512-a937VDHE1ftkjk+8/7nj/mrjtmkn69xxzJgRETXdAUU+IgOYPQNJF17haGWbeDxSyk++HA14UA98FurvPyBJOA==",
+      "version": "7.0.32",
+      "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.32.tgz",
+      "integrity": "sha512-03eXong5NLnNCD05xscnGKGDZ98CyzoqPSMjOe6SuoQY7Z2hIj0Ld1g/O/UQRuOle2aRtiIRDg9tDcTGAkLfKw==",
       "dev": true,
       "requires": {
         "chalk": "^2.4.2",
@@ -15202,9 +14966,9 @@
       }
     },
     "postcss-calc": {
-      "version": "7.0.3",
-      "resolved": "https://registry.npmjs.org/postcss-calc/-/postcss-calc-7.0.3.tgz",
-      "integrity": "sha512-IB/EAEmZhIMEIhG7Ov4x+l47UaXOS1n2f4FBUk/aKllQhtSCxWhTzn0nJgkqN7fo/jcWySvWTSB6Syk9L+31bA==",
+      "version": "7.0.4",
+      "resolved": "https://registry.npmjs.org/postcss-calc/-/postcss-calc-7.0.4.tgz",
+      "integrity": "sha512-0I79VRAd1UTkaHzY9w83P39YGO/M3bG7/tNLrHGEunBolfoGM0hSjrGvjoeaj0JE/zIw5GsI2KZ0UwDJqv5hjw==",
       "dev": true,
       "requires": {
         "postcss": "^7.0.27",
@@ -15396,21 +15160,6 @@
         "vendors": "^1.0.0"
       },
       "dependencies": {
-        "dot-prop": {
-          "version": "5.2.0",
-          "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-5.2.0.tgz",
-          "integrity": "sha512-uEUyaDKoSQ1M4Oq8l45hSE26SnTxL6snNnqvK/VWx5wJhmff5z0FUVJDKDanor/6w3kzE3i7XZOk+7wC0EXr1A==",
-          "dev": true,
-          "requires": {
-            "is-obj": "^2.0.0"
-          }
-        },
-        "is-obj": {
-          "version": "2.0.0",
-          "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-2.0.0.tgz",
-          "integrity": "sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w==",
-          "dev": true
-        },
         "postcss-selector-parser": {
           "version": "3.1.2",
           "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-3.1.2.tgz",
@@ -15496,21 +15245,6 @@
         "postcss-selector-parser": "^3.0.0"
       },
       "dependencies": {
-        "dot-prop": {
-          "version": "5.2.0",
-          "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-5.2.0.tgz",
-          "integrity": "sha512-uEUyaDKoSQ1M4Oq8l45hSE26SnTxL6snNnqvK/VWx5wJhmff5z0FUVJDKDanor/6w3kzE3i7XZOk+7wC0EXr1A==",
-          "dev": true,
-          "requires": {
-            "is-obj": "^2.0.0"
-          }
-        },
-        "is-obj": {
-          "version": "2.0.0",
-          "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-2.0.0.tgz",
-          "integrity": "sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w==",
-          "dev": true
-        },
         "postcss-selector-parser": {
           "version": "3.1.2",
           "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-3.1.2.tgz",
@@ -15543,25 +15277,6 @@
         "postcss": "^7.0.32",
         "postcss-selector-parser": "^6.0.2",
         "postcss-value-parser": "^4.1.0"
-      },
-      "dependencies": {
-        "postcss": {
-          "version": "7.0.32",
-          "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.32.tgz",
-          "integrity": "sha512-03eXong5NLnNCD05xscnGKGDZ98CyzoqPSMjOe6SuoQY7Z2hIj0Ld1g/O/UQRuOle2aRtiIRDg9tDcTGAkLfKw==",
-          "dev": true,
-          "requires": {
-            "chalk": "^2.4.2",
-            "source-map": "^0.6.1",
-            "supports-color": "^6.1.0"
-          }
-        },
-        "source-map": {
-          "version": "0.6.1",
-          "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
-          "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
-          "dev": true
-        }
       }
     },
     "postcss-modules-scope": {
@@ -15980,6 +15695,12 @@
           "integrity": "sha1-vShOV8hPEyXacCur/IKlMoGQwMU=",
           "dev": true
         },
+        "ansi-regex": {
+          "version": "5.0.0",
+          "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz",
+          "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==",
+          "dev": true
+        },
         "ansi-styles": {
           "version": "2.2.1",
           "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz",
@@ -15999,6 +15720,37 @@
             "supports-color": "^2.0.0"
           }
         },
+        "cliui": {
+          "version": "6.0.0",
+          "resolved": "https://registry.npmjs.org/cliui/-/cliui-6.0.0.tgz",
+          "integrity": "sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ==",
+          "dev": true,
+          "requires": {
+            "string-width": "^4.2.0",
+            "strip-ansi": "^6.0.0",
+            "wrap-ansi": "^6.2.0"
+          },
+          "dependencies": {
+            "strip-ansi": {
+              "version": "6.0.0",
+              "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz",
+              "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==",
+              "dev": true,
+              "requires": {
+                "ansi-regex": "^5.0.0"
+              }
+            }
+          }
+        },
+        "color-convert": {
+          "version": "2.0.1",
+          "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
+          "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
+          "dev": true,
+          "requires": {
+            "color-name": "~1.1.4"
+          }
+        },
         "del": {
           "version": "2.2.2",
           "resolved": "https://registry.npmjs.org/del/-/del-2.2.2.tgz",
@@ -16014,6 +15766,22 @@
             "rimraf": "^2.2.8"
           }
         },
+        "find-up": {
+          "version": "4.1.0",
+          "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz",
+          "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==",
+          "dev": true,
+          "requires": {
+            "locate-path": "^5.0.0",
+            "path-exists": "^4.0.0"
+          }
+        },
+        "get-caller-file": {
+          "version": "2.0.5",
+          "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz",
+          "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==",
+          "dev": true
+        },
         "globby": {
           "version": "5.0.0",
           "resolved": "https://registry.npmjs.org/globby/-/globby-5.0.0.tgz",
@@ -16028,12 +15796,48 @@
             "pinkie-promise": "^2.0.0"
           }
         },
+        "is-fullwidth-code-point": {
+          "version": "3.0.0",
+          "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz",
+          "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==",
+          "dev": true
+        },
+        "locate-path": {
+          "version": "5.0.0",
+          "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz",
+          "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==",
+          "dev": true,
+          "requires": {
+            "p-locate": "^4.1.0"
+          }
+        },
+        "p-locate": {
+          "version": "4.1.0",
+          "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz",
+          "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==",
+          "dev": true,
+          "requires": {
+            "p-limit": "^2.2.0"
+          }
+        },
+        "path-exists": {
+          "version": "4.0.0",
+          "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz",
+          "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==",
+          "dev": true
+        },
         "pify": {
           "version": "2.3.0",
           "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz",
           "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=",
           "dev": true
         },
+        "require-main-filename": {
+          "version": "2.0.0",
+          "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz",
+          "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==",
+          "dev": true
+        },
         "source-map": {
           "version": "0.5.7",
           "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz",
@@ -16049,6 +15853,28 @@
             "source-map": "^0.5.6"
           }
         },
+        "string-width": {
+          "version": "4.2.0",
+          "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.0.tgz",
+          "integrity": "sha512-zUz5JD+tgqtuDjMhwIg5uFVV3dtqZ9yQJlZVfq4I01/K5Paj5UHj7VyrQOJvzawSVlKpObApbfD0Ed6yJc+1eg==",
+          "dev": true,
+          "requires": {
+            "emoji-regex": "^8.0.0",
+            "is-fullwidth-code-point": "^3.0.0",
+            "strip-ansi": "^6.0.0"
+          },
+          "dependencies": {
+            "strip-ansi": {
+              "version": "6.0.0",
+              "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz",
+              "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==",
+              "dev": true,
+              "requires": {
+                "ansi-regex": "^5.0.0"
+              }
+            }
+          }
+        },
         "supports-color": {
           "version": "2.0.0",
           "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz",
@@ -16073,6 +15899,67 @@
             "semver": "^5.3.0",
             "xml2js": "^0.4.17"
           }
+        },
+        "wrap-ansi": {
+          "version": "6.2.0",
+          "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz",
+          "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==",
+          "dev": true,
+          "requires": {
+            "ansi-styles": "^4.0.0",
+            "string-width": "^4.1.0",
+            "strip-ansi": "^6.0.0"
+          },
+          "dependencies": {
+            "ansi-styles": {
+              "version": "4.2.1",
+              "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.2.1.tgz",
+              "integrity": "sha512-9VGjrMsG1vePxcSweQsN20KY/c4zN0h9fLjqAbwbPfahM3t+NL+M9HC8xeXG2I8pX5NoamTGNuomEUFI7fcUjA==",
+              "dev": true,
+              "requires": {
+                "@types/color-name": "^1.1.1",
+                "color-convert": "^2.0.1"
+              }
+            },
+            "strip-ansi": {
+              "version": "6.0.0",
+              "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz",
+              "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==",
+              "dev": true,
+              "requires": {
+                "ansi-regex": "^5.0.0"
+              }
+            }
+          }
+        },
+        "yargs": {
+          "version": "15.3.1",
+          "resolved": "https://registry.npmjs.org/yargs/-/yargs-15.3.1.tgz",
+          "integrity": "sha512-92O1HWEjw27sBfgmXiixJWT5hRBp2eobqXicLtPBIDBhYB+1HpwZlXmbW2luivBJHBzki+7VyCLRtAkScbTBQA==",
+          "dev": true,
+          "requires": {
+            "cliui": "^6.0.0",
+            "decamelize": "^1.2.0",
+            "find-up": "^4.1.0",
+            "get-caller-file": "^2.0.1",
+            "require-directory": "^2.1.1",
+            "require-main-filename": "^2.0.0",
+            "set-blocking": "^2.0.0",
+            "string-width": "^4.2.0",
+            "which-module": "^2.0.0",
+            "y18n": "^4.0.0",
+            "yargs-parser": "^18.1.1"
+          }
+        },
+        "yargs-parser": {
+          "version": "18.1.3",
+          "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-18.1.3.tgz",
+          "integrity": "sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ==",
+          "dev": true,
+          "requires": {
+            "camelcase": "^5.0.0",
+            "decamelize": "^1.2.0"
+          }
         }
       }
     },
@@ -16462,9 +16349,9 @@
       "dev": true
     },
     "regenerate": {
-      "version": "1.4.0",
-      "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.0.tgz",
-      "integrity": "sha512-1G6jJVDWrt0rK99kBjvEtziZNCICAuvIPkSiUFIQxVP06RCVpq3dmDo2oi6ABpYaDYaTRr67BEhL8r1wgEZZKg==",
+      "version": "1.4.1",
+      "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.1.tgz",
+      "integrity": "sha512-j2+C8+NtXQgEKWk49MMP5P/u2GhnahTtVkRIHr5R5lVRlbKvmQ+oS+A5aLKWp2ma5VkT8sh6v+v4hbH0YHR66A==",
       "dev": true
     },
     "regenerate-unicode-properties": {
@@ -16531,9 +16418,9 @@
       }
     },
     "regjsgen": {
-      "version": "0.5.1",
-      "resolved": "https://registry.npmjs.org/regjsgen/-/regjsgen-0.5.1.tgz",
-      "integrity": "sha512-5qxzGZjDs9w4tzT3TPhCJqWdCc3RLYwy9J2NB0nm5Lz+S273lvWcpjaTGHsT1dc6Hhfq41uSEOw8wBmxrKOuyg==",
+      "version": "0.5.2",
+      "resolved": "https://registry.npmjs.org/regjsgen/-/regjsgen-0.5.2.tgz",
+      "integrity": "sha512-OFFT3MfrH90xIW8OOSyUrk6QHD5E9JOTeGodiJeBS3J6IwlgzJMNE/1bZklWz5oTg+9dCMyEetclvCVXOPoN3A==",
       "dev": true
     },
     "regjsparser": {
@@ -16848,13 +16735,13 @@
       }
     },
     "roarr": {
-      "version": "2.15.3",
-      "resolved": "https://registry.npmjs.org/roarr/-/roarr-2.15.3.tgz",
-      "integrity": "sha512-AEjYvmAhlyxOeB9OqPUzQCo3kuAkNfuDk/HqWbZdFsqDFpapkTjiw+p4svNEoRLvuqNTxqfL+s+gtD4eDgZ+CA==",
+      "version": "2.15.4",
+      "resolved": "https://registry.npmjs.org/roarr/-/roarr-2.15.4.tgz",
+      "integrity": "sha512-CHhPh+UNHD2GTXNYhPWLnU8ONHdI+5DI+4EYIAOaiD63rHeYlZvyh8P+in5999TTSFgUYuKUAjzRI4mdh/p+2A==",
       "dev": true,
       "optional": true,
       "requires": {
-        "boolean": "^3.0.0",
+        "boolean": "^3.0.1",
         "detect-node": "^2.0.4",
         "globalthis": "^1.0.1",
         "json-stringify-safe": "^5.0.1",
@@ -16877,9 +16764,9 @@
       "integrity": "sha512-OlwfYEgA2RdboZohpldlvJ1xngOins5d7ejqnIBWr9KaMxsnBqotpptRXTyfNRLnFpqzX6sTDt+X+a+6udnU8g=="
     },
     "rollup": {
-      "version": "2.10.9",
-      "resolved": "https://registry.npmjs.org/rollup/-/rollup-2.10.9.tgz",
-      "integrity": "sha512-dY/EbjiWC17ZCUSyk14hkxATAMAShkMsD43XmZGWjLrgFj15M3Dw2kEkA9ns64BiLFm9PKN6vTQw8neHwK74eg==",
+      "version": "2.26.5",
+      "resolved": "https://registry.npmjs.org/rollup/-/rollup-2.26.5.tgz",
+      "integrity": "sha512-rCyFG3ZtQdnn9YwfuAVH0l/Om34BdO5lwCA0W6Hq+bNB21dVEBbCRxhaHOmu1G7OBFDWytbzAC104u7rxHwGjA==",
       "dev": true,
       "requires": {
         "fsevents": "~2.1.2"
@@ -16895,10 +16782,13 @@
       }
     },
     "run-async": {
-      "version": "2.4.1",
-      "resolved": "https://registry.npmjs.org/run-async/-/run-async-2.4.1.tgz",
-      "integrity": "sha512-tvVnVv01b8c1RrA6Ep7JkStj85Guv/YrMcwqYQnwjsAS2cTmmPGBBjAjpCW7RrSodNSoE2/qg9O4bceNvUuDgQ==",
-      "dev": true
+      "version": "2.3.0",
+      "resolved": "https://registry.npmjs.org/run-async/-/run-async-2.3.0.tgz",
+      "integrity": "sha1-A3GrSuC91yDUFm19/aZP96RFpsA=",
+      "dev": true,
+      "requires": {
+        "is-promise": "^2.1.0"
+      }
     },
     "run-parallel": {
       "version": "1.1.9",
@@ -16920,9 +16810,9 @@
       "integrity": "sha1-P4Yt+pGrdmsUiF700BEkv9oHT7Q="
     },
     "rxjs": {
-      "version": "6.6.2",
-      "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.6.2.tgz",
-      "integrity": "sha512-BHdBMVoWC2sL26w//BCu3YzKT4s2jip/WhwsGEDmeKYBhKDZeYezVUnHatYB7L85v5xs0BAQmg6BEYJEKxBabg==",
+      "version": "6.6.3",
+      "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.6.3.tgz",
+      "integrity": "sha512-trsQc+xYYXZ3urjOiJOuCOa5N3jAZ3eiSpQB5hIT8zGlL2QfnHLJ2r7GMkBGuIausdJN1OneaI6gQlsqNHHmZQ==",
       "requires": {
         "tslib": "^1.9.0"
       },
@@ -16960,51 +16850,31 @@
       "integrity": "sha512-y/52Mcy7aw3gRm7IrcGDFx/bCk4AhRh2eI9luHOQM86nZsqwiRkkq2GekHXBBD+SmPidc8i2PqtYZl+pWJ8Oeg==",
       "dev": true,
       "requires": {
-        "truncate-utf8-bytes": "^1.0.0"
-      }
-    },
-    "sass": {
-      "version": "1.26.5",
-      "resolved": "https://registry.npmjs.org/sass/-/sass-1.26.5.tgz",
-      "integrity": "sha512-FG2swzaZUiX53YzZSjSakzvGtlds0lcbF+URuU9mxOv7WBh7NhXEVDa4kPKN4hN6fC2TkOTOKqiqp6d53N9X5Q==",
-      "dev": true,
-      "requires": {
-        "chokidar": ">=2.0.0 <4.0.0"
-      }
-    },
-    "sass-loader": {
-      "version": "8.0.2",
-      "resolved": "https://registry.npmjs.org/sass-loader/-/sass-loader-8.0.2.tgz",
-      "integrity": "sha512-7o4dbSK8/Ol2KflEmSco4jTjQoV988bM82P9CZdmo9hR3RLnvNc0ufMNdMrB0caq38JQ/FgF4/7RcbcfKzxoFQ==",
-      "dev": true,
-      "requires": {
-        "clone-deep": "^4.0.1",
-        "loader-utils": "^1.2.3",
-        "neo-async": "^2.6.1",
-        "schema-utils": "^2.6.1",
-        "semver": "^6.3.0"
-      },
-      "dependencies": {
-        "json5": {
-          "version": "1.0.1",
-          "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.1.tgz",
-          "integrity": "sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow==",
-          "dev": true,
-          "requires": {
-            "minimist": "^1.2.0"
-          }
-        },
-        "loader-utils": {
-          "version": "1.4.0",
-          "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.4.0.tgz",
-          "integrity": "sha512-qH0WSMBtn/oHuwjy/NucEgbx5dbxxnxup9s4PVXJUDHZBQY+s0NWA9rJf53RBnQZxfch7euUui7hpoAPvALZdA==",
-          "dev": true,
-          "requires": {
-            "big.js": "^5.2.2",
-            "emojis-list": "^3.0.0",
-            "json5": "^1.0.1"
-          }
-        },
+        "truncate-utf8-bytes": "^1.0.0"
+      }
+    },
+    "sass": {
+      "version": "1.26.10",
+      "resolved": "https://registry.npmjs.org/sass/-/sass-1.26.10.tgz",
+      "integrity": "sha512-bzN0uvmzfsTvjz0qwccN1sPm2HxxpNI/Xa+7PlUEMS+nQvbyuEK7Y0qFqxlPHhiNHb1Ze8WQJtU31olMObkAMw==",
+      "dev": true,
+      "requires": {
+        "chokidar": ">=2.0.0 <4.0.0"
+      }
+    },
+    "sass-loader": {
+      "version": "10.0.1",
+      "resolved": "https://registry.npmjs.org/sass-loader/-/sass-loader-10.0.1.tgz",
+      "integrity": "sha512-b2PSldKVTS3JcFPHSrEXh3BeAfR7XknGiGCAO5aHruR3Pf3kqLP3Gb2ypXLglRrAzgZkloNxLZ7GXEGDX0hBUQ==",
+      "dev": true,
+      "requires": {
+        "klona": "^2.0.3",
+        "loader-utils": "^2.0.0",
+        "neo-async": "^2.6.2",
+        "schema-utils": "^2.7.0",
+        "semver": "^7.3.2"
+      },
+      "dependencies": {
         "neo-async": {
           "version": "2.6.2",
           "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz",
@@ -17012,9 +16882,9 @@
           "dev": true
         },
         "semver": {
-          "version": "6.3.0",
-          "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
-          "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==",
+          "version": "7.3.2",
+          "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.2.tgz",
+          "integrity": "sha512-OrOb32TeeambH6UrhtShmF7CRDqhL6/5XpPNp2DuRH6+9QLw/orhp72j87v8Qa1ScDkvrrBNpZcDejAirJmfXQ==",
           "dev": true
         }
       }
@@ -17035,20 +16905,20 @@
       "dev": true
     },
     "schema-utils": {
-      "version": "2.7.0",
-      "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-2.7.0.tgz",
-      "integrity": "sha512-0ilKFI6QQF5nxDZLFn2dMjvc4hjg/Wkg7rHd3jK6/A4a1Hl9VFdQWvgB1UMGoU94pad1P/8N7fMcEnLnSiju8A==",
+      "version": "2.7.1",
+      "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-2.7.1.tgz",
+      "integrity": "sha512-SHiNtMOUGWBQJwzISiVYKu82GiV4QYGePp3odlY1tuKO7gPtphAT5R/py0fA6xtbgLL/RvtJZnU9b8s0F1q0Xg==",
       "dev": true,
       "requires": {
-        "@types/json-schema": "^7.0.4",
-        "ajv": "^6.12.2",
-        "ajv-keywords": "^3.4.1"
+        "@types/json-schema": "^7.0.5",
+        "ajv": "^6.12.4",
+        "ajv-keywords": "^3.5.2"
       },
       "dependencies": {
         "ajv": {
-          "version": "6.12.4",
-          "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.4.tgz",
-          "integrity": "sha512-eienB2c9qVQs2KWexhkrdMLVDoIQCz5KSeLxwg9Lzk4DOfBtIK9PQwwufcsn1jjGuf9WZmqPMbGxOzfcuphJCQ==",
+          "version": "6.12.5",
+          "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.5.tgz",
+          "integrity": "sha512-lRF8RORchjpKG50/WFf8xmg7sgCLFiYNNnqdKflk63whMQcWR5ngGjiSXkL9bjxy6B2npOK2HSMN49jEBMSkag==",
           "dev": true,
           "requires": {
             "fast-deep-equal": "^3.1.1",
@@ -17057,6 +16927,12 @@
             "uri-js": "^4.2.2"
           }
         },
+        "ajv-keywords": {
+          "version": "3.5.2",
+          "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz",
+          "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==",
+          "dev": true
+        },
         "fast-deep-equal": {
           "version": "3.1.3",
           "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
@@ -17344,15 +17220,6 @@
         "safe-buffer": "^5.0.1"
       }
     },
-    "shallow-clone": {
-      "version": "3.0.1",
-      "resolved": "https://registry.npmjs.org/shallow-clone/-/shallow-clone-3.0.1.tgz",
-      "integrity": "sha512-/6KqX+GVUdqPuPPd2LxDDxzX6CAbjJehAAOKlNpqqUpAqPM6HeL8f+o3a+JsyGjn2lv0WY8UsTgUJjU9Ok55NA==",
-      "dev": true,
-      "requires": {
-        "kind-of": "^6.0.2"
-      }
-    },
     "shallow-copy": {
       "version": "0.0.1",
       "resolved": "https://registry.npmjs.org/shallow-copy/-/shallow-copy-0.0.1.tgz",
@@ -17758,25 +17625,25 @@
       "dev": true
     },
     "source-map-loader": {
-      "version": "1.0.0",
-      "resolved": "https://registry.npmjs.org/source-map-loader/-/source-map-loader-1.0.0.tgz",
-      "integrity": "sha512-ZayyQCSCrQazN50aCvuS84lJT4xc1ZAcykH5blHaBdVveSwjiFK8UGMPvao0ho54DTb0Jf7m57uRRG/YYUZ2Fg==",
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/source-map-loader/-/source-map-loader-1.0.2.tgz",
+      "integrity": "sha512-oX8d6ndRjN+tVyjj6PlXSyFPhDdVAPsZA30nD3/II8g4uOv8fCz0DMn5sy8KtVbDfKQxOpGwGJnK3xIW3tauDw==",
       "dev": true,
       "requires": {
         "data-urls": "^2.0.0",
-        "iconv-lite": "^0.5.1",
+        "iconv-lite": "^0.6.2",
         "loader-utils": "^2.0.0",
-        "schema-utils": "^2.6.6",
-        "source-map": "^0.6.0"
+        "schema-utils": "^2.7.0",
+        "source-map": "^0.6.1"
       },
       "dependencies": {
         "iconv-lite": {
-          "version": "0.5.2",
-          "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.5.2.tgz",
-          "integrity": "sha512-kERHXvpSaB4aU3eANwidg79K8FlrN77m8G9V+0vOR3HYaRifrlwMEpT7ZBJqLSEIHnEgJTHcWK82wwLwwKwtag==",
+          "version": "0.6.2",
+          "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.2.tgz",
+          "integrity": "sha512-2y91h5OpQlolefMPmUlivelittSWy0rP+oYVpn6A7GwVHNE8AWzoYOBNmlwks3LobaJxgHCYZAnyNo2GgpNRNQ==",
           "dev": true,
           "requires": {
-            "safer-buffer": ">= 2.1.2 < 3"
+            "safer-buffer": ">= 2.1.2 < 3.0.0"
           }
         },
         "source-map": {
@@ -18262,71 +18129,6 @@
       "requires": {
         "define-properties": "^1.1.3",
         "es-abstract": "^1.17.5"
-      },
-      "dependencies": {
-        "es-abstract": {
-          "version": "1.17.6",
-          "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.17.6.tgz",
-          "integrity": "sha512-Fr89bON3WFyUi5EvAeI48QTWX0AyekGgLA8H+c+7fbfCkJwRWRMLd8CQedNEyJuoYYhmtEqY92pgte1FAhBlhw==",
-          "dev": true,
-          "requires": {
-            "es-to-primitive": "^1.2.1",
-            "function-bind": "^1.1.1",
-            "has": "^1.0.3",
-            "has-symbols": "^1.0.1",
-            "is-callable": "^1.2.0",
-            "is-regex": "^1.1.0",
-            "object-inspect": "^1.7.0",
-            "object-keys": "^1.1.1",
-            "object.assign": "^4.1.0",
-            "string.prototype.trimend": "^1.0.1",
-            "string.prototype.trimstart": "^1.0.1"
-          }
-        },
-        "es-to-primitive": {
-          "version": "1.2.1",
-          "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz",
-          "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==",
-          "dev": true,
-          "requires": {
-            "is-callable": "^1.1.4",
-            "is-date-object": "^1.0.1",
-            "is-symbol": "^1.0.2"
-          }
-        },
-        "has-symbols": {
-          "version": "1.0.1",
-          "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.1.tgz",
-          "integrity": "sha512-PLcsoqu++dmEIZB+6totNFKq/7Do+Z0u4oT0zKOJNl3lYK6vGwwu2hjHs+68OEZbTjiUE9bgOABXbP/GvrS0Kg==",
-          "dev": true
-        },
-        "is-callable": {
-          "version": "1.2.0",
-          "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.0.tgz",
-          "integrity": "sha512-pyVD9AaGLxtg6srb2Ng6ynWJqkHU9bEM087AKck0w8QwDarTfNcpIYoU8x8Hv2Icm8u6kFJM18Dag8lyqGkviw==",
-          "dev": true
-        },
-        "is-regex": {
-          "version": "1.1.1",
-          "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.1.tgz",
-          "integrity": "sha512-1+QkEcxiLlB7VEyFtyBg94e08OAsvq7FUBgApTq/w2ymCLyKJgDPsybBENVtA7XCQEgEXxKPonG+mvYRxh/LIg==",
-          "dev": true,
-          "requires": {
-            "has-symbols": "^1.0.1"
-          }
-        },
-        "object-inspect": {
-          "version": "1.8.0",
-          "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.8.0.tgz",
-          "integrity": "sha512-jLdtEOB112fORuypAyl/50VRVIBIdVQOSUUGQHzJ4xBSbit81zRarz7GThkEFZy1RceYrWYcPcBFPQwHyAc1gA==",
-          "dev": true
-        },
-        "object-keys": {
-          "version": "1.1.1",
-          "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz",
-          "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==",
-          "dev": true
-        }
       }
     },
     "string.prototype.trimstart": {
@@ -18337,71 +18139,6 @@
       "requires": {
         "define-properties": "^1.1.3",
         "es-abstract": "^1.17.5"
-      },
-      "dependencies": {
-        "es-abstract": {
-          "version": "1.17.6",
-          "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.17.6.tgz",
-          "integrity": "sha512-Fr89bON3WFyUi5EvAeI48QTWX0AyekGgLA8H+c+7fbfCkJwRWRMLd8CQedNEyJuoYYhmtEqY92pgte1FAhBlhw==",
-          "dev": true,
-          "requires": {
-            "es-to-primitive": "^1.2.1",
-            "function-bind": "^1.1.1",
-            "has": "^1.0.3",
-            "has-symbols": "^1.0.1",
-            "is-callable": "^1.2.0",
-            "is-regex": "^1.1.0",
-            "object-inspect": "^1.7.0",
-            "object-keys": "^1.1.1",
-            "object.assign": "^4.1.0",
-            "string.prototype.trimend": "^1.0.1",
-            "string.prototype.trimstart": "^1.0.1"
-          }
-        },
-        "es-to-primitive": {
-          "version": "1.2.1",
-          "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz",
-          "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==",
-          "dev": true,
-          "requires": {
-            "is-callable": "^1.1.4",
-            "is-date-object": "^1.0.1",
-            "is-symbol": "^1.0.2"
-          }
-        },
-        "has-symbols": {
-          "version": "1.0.1",
-          "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.1.tgz",
-          "integrity": "sha512-PLcsoqu++dmEIZB+6totNFKq/7Do+Z0u4oT0zKOJNl3lYK6vGwwu2hjHs+68OEZbTjiUE9bgOABXbP/GvrS0Kg==",
-          "dev": true
-        },
-        "is-callable": {
-          "version": "1.2.0",
-          "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.0.tgz",
-          "integrity": "sha512-pyVD9AaGLxtg6srb2Ng6ynWJqkHU9bEM087AKck0w8QwDarTfNcpIYoU8x8Hv2Icm8u6kFJM18Dag8lyqGkviw==",
-          "dev": true
-        },
-        "is-regex": {
-          "version": "1.1.1",
-          "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.1.tgz",
-          "integrity": "sha512-1+QkEcxiLlB7VEyFtyBg94e08OAsvq7FUBgApTq/w2ymCLyKJgDPsybBENVtA7XCQEgEXxKPonG+mvYRxh/LIg==",
-          "dev": true,
-          "requires": {
-            "has-symbols": "^1.0.1"
-          }
-        },
-        "object-inspect": {
-          "version": "1.8.0",
-          "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.8.0.tgz",
-          "integrity": "sha512-jLdtEOB112fORuypAyl/50VRVIBIdVQOSUUGQHzJ4xBSbit81zRarz7GThkEFZy1RceYrWYcPcBFPQwHyAc1gA==",
-          "dev": true
-        },
-        "object-keys": {
-          "version": "1.1.1",
-          "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz",
-          "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==",
-          "dev": true
-        }
       }
     },
     "string_decoder": {
@@ -18471,21 +18208,6 @@
         "postcss-selector-parser": "^3.0.0"
       },
       "dependencies": {
-        "dot-prop": {
-          "version": "5.2.0",
-          "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-5.2.0.tgz",
-          "integrity": "sha512-uEUyaDKoSQ1M4Oq8l45hSE26SnTxL6snNnqvK/VWx5wJhmff5z0FUVJDKDanor/6w3kzE3i7XZOk+7wC0EXr1A==",
-          "dev": true,
-          "requires": {
-            "is-obj": "^2.0.0"
-          }
-        },
-        "is-obj": {
-          "version": "2.0.0",
-          "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-2.0.0.tgz",
-          "integrity": "sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w==",
-          "dev": true
-        },
         "postcss-selector-parser": {
           "version": "3.1.2",
           "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-3.1.2.tgz",
@@ -18505,18 +18227,18 @@
       "integrity": "sha512-8/3pSmthWM7lsPBKv7NXkzn2Uc9W7NotcwGNpJaa3k7WMM1XDCA4MgT5k/8BIexd5ydZdboXtU90XH9Ec4Bv/Q=="
     },
     "stylus": {
-      "version": "0.54.7",
-      "resolved": "https://registry.npmjs.org/stylus/-/stylus-0.54.7.tgz",
-      "integrity": "sha512-Yw3WMTzVwevT6ZTrLCYNHAFmanMxdylelL3hkWNgPMeTCpMwpV3nXjpOHuBXtFv7aiO2xRuQS6OoAdgkNcSNug==",
+      "version": "0.54.8",
+      "resolved": "https://registry.npmjs.org/stylus/-/stylus-0.54.8.tgz",
+      "integrity": "sha512-vr54Or4BZ7pJafo2mpf0ZcwA74rpuYCZbxrHBsH8kbcXOwSfvBFwsRfpGO5OD5fhG5HDCFW737PKaawI7OqEAg==",
       "dev": true,
       "requires": {
         "css-parse": "~2.0.0",
         "debug": "~3.1.0",
-        "glob": "^7.1.3",
-        "mkdirp": "~0.5.x",
+        "glob": "^7.1.6",
+        "mkdirp": "~1.0.4",
         "safer-buffer": "^2.1.2",
         "sax": "~1.2.4",
-        "semver": "^6.0.0",
+        "semver": "^6.3.0",
         "source-map": "^0.7.3"
       },
       "dependencies": {
@@ -18529,6 +18251,26 @@
             "ms": "2.0.0"
           }
         },
+        "glob": {
+          "version": "7.1.6",
+          "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz",
+          "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==",
+          "dev": true,
+          "requires": {
+            "fs.realpath": "^1.0.0",
+            "inflight": "^1.0.4",
+            "inherits": "2",
+            "minimatch": "^3.0.4",
+            "once": "^1.3.0",
+            "path-is-absolute": "^1.0.0"
+          }
+        },
+        "mkdirp": {
+          "version": "1.0.4",
+          "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz",
+          "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==",
+          "dev": true
+        },
         "semver": {
           "version": "6.3.0",
           "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
@@ -18707,12 +18449,6 @@
           "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz",
           "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==",
           "dev": true
-        },
-        "yallist": {
-          "version": "4.0.0",
-          "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
-          "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==",
-          "dev": true
         }
       }
     },
@@ -18772,40 +18508,31 @@
       }
     },
     "terser-webpack-plugin": {
-      "version": "3.0.1",
-      "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-3.0.1.tgz",
-      "integrity": "sha512-eFDtq8qPUEa9hXcUzTwKXTnugIVtlqc1Z/ZVhG8LmRT3lgRY13+pQTnFLY2N7ATB6TKCHuW/IGjoAnZz9wOIqw==",
+      "version": "4.1.0",
+      "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-4.1.0.tgz",
+      "integrity": "sha512-0ZWDPIP8BtEDZdChbufcXUigOYk6dOX/P/X0hWxqDDcVAQLb8Yy/0FAaemSfax3PAA67+DJR778oz8qVbmy4hA==",
       "dev": true,
       "requires": {
-        "cacache": "^15.0.3",
+        "cacache": "^15.0.5",
         "find-cache-dir": "^3.3.1",
-        "jest-worker": "^26.0.0",
-        "p-limit": "^2.3.0",
+        "jest-worker": "^26.3.0",
+        "p-limit": "^3.0.2",
         "schema-utils": "^2.6.6",
-        "serialize-javascript": "^3.0.0",
+        "serialize-javascript": "^4.0.0",
         "source-map": "^0.6.1",
-        "terser": "^4.6.13",
+        "terser": "^5.0.0",
         "webpack-sources": "^1.4.3"
       },
       "dependencies": {
         "p-limit": {
-          "version": "2.3.0",
-          "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz",
-          "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==",
+          "version": "3.0.2",
+          "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.0.2.tgz",
+          "integrity": "sha512-iwqZSOoWIW+Ew4kAGUlN16J4M7OB3ysMLSZtnhmqx7njIHFPlxWBX8xo3lVTyFVq6mI/lL9qt2IsN1sHwaxJkg==",
           "dev": true,
           "requires": {
             "p-try": "^2.0.0"
           }
         },
-        "serialize-javascript": {
-          "version": "3.1.0",
-          "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-3.1.0.tgz",
-          "integrity": "sha512-JIJT1DGiWmIKhzRsG91aS6Ze4sFUrYbltlkg2onR5OrnNM02Kl/hnY/T4FN2omvyeBbQmMJv+K4cPOpGzOTFBg==",
-          "dev": true,
-          "requires": {
-            "randombytes": "^2.1.0"
-          }
-        },
         "source-map": {
           "version": "0.6.1",
           "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
@@ -18813,9 +18540,9 @@
           "dev": true
         },
         "terser": {
-          "version": "4.8.0",
-          "resolved": "https://registry.npmjs.org/terser/-/terser-4.8.0.tgz",
-          "integrity": "sha512-EAPipTNeWsb/3wLPeup1tVPaXfIaU68xMnVdPafIL1TV05OhASArYyIfFvnvJCNrR2NIOvDVNNTFRa+Re2MWyw==",
+          "version": "5.3.1",
+          "resolved": "https://registry.npmjs.org/terser/-/terser-5.3.1.tgz",
+          "integrity": "sha512-yD80f4hdwCWTH5mojzxe1q8bN1oJbsK/vfJGLcPZM/fl+/jItIVNKhFIHqqR71OipFWMLgj3Kc+GIp6CeIqfnA==",
           "dev": true,
           "requires": {
             "commander": "^2.20.0",
@@ -19029,6 +18756,24 @@
         "make-error": "^1.1.1",
         "source-map-support": "^0.5.17",
         "yn": "3.1.1"
+      },
+      "dependencies": {
+        "source-map": {
+          "version": "0.6.1",
+          "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
+          "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
+          "dev": true
+        },
+        "source-map-support": {
+          "version": "0.5.19",
+          "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.19.tgz",
+          "integrity": "sha512-Wonm7zOCIJzBGQdB+thsPar0kYuCIzYvxZwlBa87yi/Mdjv7Tip2cyVbLj5o0cFPN4EVkuTwb3GDDyUx2DGnGw==",
+          "dev": true,
+          "requires": {
+            "buffer-from": "^1.0.0",
+            "source-map": "^0.6.0"
+          }
+        }
       }
     },
     "ts-pnp": {
@@ -19200,9 +18945,9 @@
       }
     },
     "type-fest": {
-      "version": "0.8.1",
-      "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz",
-      "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==",
+      "version": "0.11.0",
+      "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.11.0.tgz",
+      "integrity": "sha512-OdjXJxnCN1AvyLSzeKIgXTXxV+99ZuXl3Hpo9XpJAv9MBcHrrJOQ5kV7ypXOuQie+AmWG25hLbiKdwYTifzcfQ==",
       "dev": true
     },
     "type-is": {
@@ -19417,20 +19162,20 @@
       }
     },
     "universal-analytics": {
-      "version": "0.4.20",
-      "resolved": "https://registry.npmjs.org/universal-analytics/-/universal-analytics-0.4.20.tgz",
-      "integrity": "sha512-gE91dtMvNkjO+kWsPstHRtSwHXz0l2axqptGYp5ceg4MsuurloM0PU3pdOfpb5zBXUvyjT4PwhWK2m39uczZuw==",
+      "version": "0.4.23",
+      "resolved": "https://registry.npmjs.org/universal-analytics/-/universal-analytics-0.4.23.tgz",
+      "integrity": "sha512-lgMIH7XBI6OgYn1woDEmxhGdj8yDefMKg7GkWdeATAlQZFrMrNyxSkpDzY57iY0/6fdlzTbBV03OawvvzG+q7A==",
       "dev": true,
       "requires": {
-        "debug": "^3.0.0",
-        "request": "^2.88.0",
+        "debug": "^4.1.1",
+        "request": "^2.88.2",
         "uuid": "^3.0.0"
       },
       "dependencies": {
         "debug": {
-          "version": "3.2.6",
-          "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz",
-          "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==",
+          "version": "4.1.1",
+          "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz",
+          "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==",
           "dev": true,
           "requires": {
             "ms": "^2.1.1"
@@ -19441,6 +19186,44 @@
           "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
           "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
           "dev": true
+        },
+        "request": {
+          "version": "2.88.2",
+          "resolved": "https://registry.npmjs.org/request/-/request-2.88.2.tgz",
+          "integrity": "sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw==",
+          "dev": true,
+          "requires": {
+            "aws-sign2": "~0.7.0",
+            "aws4": "^1.8.0",
+            "caseless": "~0.12.0",
+            "combined-stream": "~1.0.6",
+            "extend": "~3.0.2",
+            "forever-agent": "~0.6.1",
+            "form-data": "~2.3.2",
+            "har-validator": "~5.1.3",
+            "http-signature": "~1.2.0",
+            "is-typedarray": "~1.0.0",
+            "isstream": "~0.1.2",
+            "json-stringify-safe": "~5.0.1",
+            "mime-types": "~2.1.19",
+            "oauth-sign": "~0.9.0",
+            "performance-now": "^2.1.0",
+            "qs": "~6.5.2",
+            "safe-buffer": "^5.1.2",
+            "tough-cookie": "~2.5.0",
+            "tunnel-agent": "^0.6.0",
+            "uuid": "^3.3.2"
+          }
+        },
+        "tough-cookie": {
+          "version": "2.5.0",
+          "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.5.0.tgz",
+          "integrity": "sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g==",
+          "dev": true,
+          "requires": {
+            "psl": "^1.1.28",
+            "punycode": "^2.1.1"
+          }
         }
       }
     },
@@ -19811,71 +19594,6 @@
         "es-abstract": "^1.17.2",
         "has-symbols": "^1.0.1",
         "object.getownpropertydescriptors": "^2.1.0"
-      },
-      "dependencies": {
-        "es-abstract": {
-          "version": "1.17.6",
-          "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.17.6.tgz",
-          "integrity": "sha512-Fr89bON3WFyUi5EvAeI48QTWX0AyekGgLA8H+c+7fbfCkJwRWRMLd8CQedNEyJuoYYhmtEqY92pgte1FAhBlhw==",
-          "dev": true,
-          "requires": {
-            "es-to-primitive": "^1.2.1",
-            "function-bind": "^1.1.1",
-            "has": "^1.0.3",
-            "has-symbols": "^1.0.1",
-            "is-callable": "^1.2.0",
-            "is-regex": "^1.1.0",
-            "object-inspect": "^1.7.0",
-            "object-keys": "^1.1.1",
-            "object.assign": "^4.1.0",
-            "string.prototype.trimend": "^1.0.1",
-            "string.prototype.trimstart": "^1.0.1"
-          }
-        },
-        "es-to-primitive": {
-          "version": "1.2.1",
-          "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz",
-          "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==",
-          "dev": true,
-          "requires": {
-            "is-callable": "^1.1.4",
-            "is-date-object": "^1.0.1",
-            "is-symbol": "^1.0.2"
-          }
-        },
-        "has-symbols": {
-          "version": "1.0.1",
-          "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.1.tgz",
-          "integrity": "sha512-PLcsoqu++dmEIZB+6totNFKq/7Do+Z0u4oT0zKOJNl3lYK6vGwwu2hjHs+68OEZbTjiUE9bgOABXbP/GvrS0Kg==",
-          "dev": true
-        },
-        "is-callable": {
-          "version": "1.2.0",
-          "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.0.tgz",
-          "integrity": "sha512-pyVD9AaGLxtg6srb2Ng6ynWJqkHU9bEM087AKck0w8QwDarTfNcpIYoU8x8Hv2Icm8u6kFJM18Dag8lyqGkviw==",
-          "dev": true
-        },
-        "is-regex": {
-          "version": "1.1.1",
-          "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.1.tgz",
-          "integrity": "sha512-1+QkEcxiLlB7VEyFtyBg94e08OAsvq7FUBgApTq/w2ymCLyKJgDPsybBENVtA7XCQEgEXxKPonG+mvYRxh/LIg==",
-          "dev": true,
-          "requires": {
-            "has-symbols": "^1.0.1"
-          }
-        },
-        "object-inspect": {
-          "version": "1.8.0",
-          "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.8.0.tgz",
-          "integrity": "sha512-jLdtEOB112fORuypAyl/50VRVIBIdVQOSUUGQHzJ4xBSbit81zRarz7GThkEFZy1RceYrWYcPcBFPQwHyAc1gA==",
-          "dev": true
-        },
-        "object-keys": {
-          "version": "1.1.1",
-          "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz",
-          "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==",
-          "dev": true
-        }
       }
     },
     "utils-merge": {
@@ -20186,9 +19904,9 @@
       "dev": true
     },
     "webpack": {
-      "version": "4.43.0",
-      "resolved": "https://registry.npmjs.org/webpack/-/webpack-4.43.0.tgz",
-      "integrity": "sha512-GW1LjnPipFW2Y78OOab8NJlCflB7EFskMih2AHdvjbpKMeDJqEgSx24cXXXiPS65+WSwVyxtDsJH6jGX2czy+g==",
+      "version": "4.44.1",
+      "resolved": "https://registry.npmjs.org/webpack/-/webpack-4.44.1.tgz",
+      "integrity": "sha512-4UOGAohv/VGUNQJstzEywwNxqX417FnjZgZJpJQegddzPmTvph37eBIRbRTfdySXzVtJXLJfbMN3mMYhM6GdmQ==",
       "dev": true,
       "requires": {
         "@webassemblyjs/ast": "1.9.0",
@@ -20199,7 +19917,7 @@
         "ajv": "^6.10.2",
         "ajv-keywords": "^3.4.1",
         "chrome-trace-event": "^1.0.2",
-        "enhanced-resolve": "^4.1.0",
+        "enhanced-resolve": "^4.3.0",
         "eslint-scope": "^4.0.3",
         "json-parse-better-errors": "^1.0.2",
         "loader-runner": "^2.4.0",
@@ -20212,14 +19930,14 @@
         "schema-utils": "^1.0.0",
         "tapable": "^1.1.3",
         "terser-webpack-plugin": "^1.4.3",
-        "watchpack": "^1.6.1",
+        "watchpack": "^1.7.4",
         "webpack-sources": "^1.4.1"
       },
       "dependencies": {
         "ajv": {
-          "version": "6.12.4",
-          "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.4.tgz",
-          "integrity": "sha512-eienB2c9qVQs2KWexhkrdMLVDoIQCz5KSeLxwg9Lzk4DOfBtIK9PQwwufcsn1jjGuf9WZmqPMbGxOzfcuphJCQ==",
+          "version": "6.12.5",
+          "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.5.tgz",
+          "integrity": "sha512-lRF8RORchjpKG50/WFf8xmg7sgCLFiYNNnqdKflk63whMQcWR5ngGjiSXkL9bjxy6B2npOK2HSMN49jEBMSkag==",
           "dev": true,
           "requires": {
             "fast-deep-equal": "^3.1.1",
@@ -20711,14 +20429,6 @@
       "dev": true,
       "requires": {
         "lodash": "^4.17.15"
-      },
-      "dependencies": {
-        "lodash": {
-          "version": "4.17.20",
-          "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.20.tgz",
-          "integrity": "sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA==",
-          "dev": true
-        }
       }
     },
     "webpack-sources": {
@@ -20772,9 +20482,9 @@
       "dev": true
     },
     "whatwg-url": {
-      "version": "8.2.0",
-      "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-8.2.0.tgz",
-      "integrity": "sha512-Sl4svq71j4kzaFD13uxkVl2AIsbj/xwp8NTM1VMhFRyNT1ZMTWaV6+Pva0fQs7y8+cAEPrDGfCAFLvJejhT79g==",
+      "version": "8.2.2",
+      "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-8.2.2.tgz",
+      "integrity": "sha512-PcVnO6NiewhkmzV0qn7A+UZ9Xx4maNTI+O+TShmfE4pqjoCMwUMjkvoNhNHPTvgR7QH9Xt3R13iHuWy2sToFxQ==",
       "dev": true,
       "requires": {
         "lodash.sortby": "^4.7.0",
@@ -20910,9 +20620,9 @@
       }
     },
     "worker-plugin": {
-      "version": "4.0.3",
-      "resolved": "https://registry.npmjs.org/worker-plugin/-/worker-plugin-4.0.3.tgz",
-      "integrity": "sha512-7hFDYWiKcE3yHZvemsoM9lZis/PzurHAEX1ej8PLCu818Rt6QqUAiDdxHPCKZctzmhqzPpcFSgvMCiPbtooqAg==",
+      "version": "5.0.0",
+      "resolved": "https://registry.npmjs.org/worker-plugin/-/worker-plugin-5.0.0.tgz",
+      "integrity": "sha512-AXMUstURCxDD6yGam2r4E34aJg6kW85IiaeX72hi+I1cxyaMUtrvVY6sbfpGKAj5e7f68Acl62BjQF5aOOx2IQ==",
       "dev": true,
       "requires": {
         "loader-utils": "^1.1.0"
@@ -20976,6 +20686,11 @@
             "color-name": "~1.1.4"
           }
         },
+        "minimist": {
+          "version": "1.2.5",
+          "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz",
+          "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw=="
+        },
         "strip-ansi": {
           "version": "6.0.0",
           "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz",
@@ -21020,9 +20735,9 @@
       "dev": true
     },
     "xlsx": {
-      "version": "0.16.6",
-      "resolved": "https://registry.npmjs.org/xlsx/-/xlsx-0.16.6.tgz",
-      "integrity": "sha512-iAPNt15C2umCx7Q6h9owZvNHRYVOImLp7Mc00uA4UhJvzjfM1OV3V7TgBXIHuawGF1G6GLXZr/r75e5jsiBefg==",
+      "version": "0.16.7",
+      "resolved": "https://registry.npmjs.org/xlsx/-/xlsx-0.16.7.tgz",
+      "integrity": "sha512-Xc4NRjci2Grbh9NDk/XoaWycJurxEug1wwn0aJCmB0NvIMyQuHYq2muWLWGidYNZPf94aUbqm6K8Fbjd7gKTZg==",
       "requires": {
         "adler-32": "~1.2.0",
         "cfb": "^1.1.4",
diff --git a/package.json b/package.json
index 8a9be8f40f38c06581c7935f7af44b54048ab663..1463b3630e0503d0cbc7b52be3f818a06dbc19bd 100644
--- a/package.json
+++ b/package.json
@@ -36,17 +36,17 @@
   },
   "private": true,
   "dependencies": {
-    "@angular/animations": "^10.0.12",
-    "@angular/cdk": "^10.1.3",
-    "@angular/common": "^10.0.12",
-    "@angular/compiler": "^10.0.12",
-    "@angular/core": "^10.0.12",
+    "@angular/animations": "^10.1.2",
+    "@angular/cdk": "^10.2.1",
+    "@angular/common": "^10.1.2",
+    "@angular/compiler": "^10.1.2",
+    "@angular/core": "^10.1.2",
     "@angular/flex-layout": "^10.0.0-beta.32",
-    "@angular/forms": "^10.0.12",
-    "@angular/material": "^10.1.3",
-    "@angular/platform-browser": "^10.0.12",
-    "@angular/platform-browser-dynamic": "^10.0.12",
-    "@angular/router": "^10.0.12",
+    "@angular/forms": "^10.1.2",
+    "@angular/material": "^10.2.1",
+    "@angular/platform-browser": "^10.1.2",
+    "@angular/platform-browser-dynamic": "^10.1.2",
+    "@angular/router": "^10.1.2",
     "@types/pako": "^1.0.1",
     "@types/sprintf-js": "^1.1.2",
     "angular2-chartjs": "^0.5.1",
@@ -58,7 +58,7 @@
     "cordova-plugin-badge": "^0.8.8",
     "cordova-plugin-device": "^2.0.3",
     "cordova-plugin-file": "^6.0.2",
-    "cordova-plugin-file-opener2": "^3.0.4",
+    "cordova-plugin-file-opener2": "^3.0.5",
     "cordova-plugin-local-notification": "^0.9.0-beta.2",
     "cordova-plugin-whitelist": "^1.3.4",
     "core-js": "^3.6.5",
@@ -66,8 +66,8 @@
     "he": "^1.2.0",
     "jalhyd": "file:../jalhyd",
     "material-design-icons": "^3.0.1",
-    "mathjax": "^3.0.5",
-    "mermaid": "^8.7.0",
+    "mathjax": "^3.1.2",
+    "mermaid": "^8.8.0",
     "ngx-konami": "^1.7.1",
     "ngx-markdown": "^10.1.1",
     "ngx-material-file-input": "^2.1.1",
@@ -76,31 +76,31 @@
     "pako": "^1.0.11",
     "primeng": "^9.1.3",
     "roboto-fontface": "^0.10.0",
-    "rxjs": "^6.6.2",
+    "rxjs": "^6.6.3",
     "screenfull": "^5.0.2",
     "svg-pan-zoom": "^3.6.1",
     "tslib": "^2.0.0",
-    "xlsx": "^0.16.6",
+    "xlsx": "^0.16.7",
     "zone.js": "^0.11.1"
   },
   "devDependencies": {
-    "@angular-devkit/build-angular": "^0.1000.7",
-    "@angular/cli": "^10.0.7",
-    "@angular/compiler-cli": "^10.0.12",
-    "@angular/language-service": "^10.0.12",
+    "@angular-devkit/build-angular": "^0.1001.2",
+    "@angular/cli": "^10.1.2",
+    "@angular/compiler-cli": "^10.1.2",
+    "@angular/language-service": "^10.1.2",
     "@compodoc/compodoc": "^1.1.11",
     "@types/file-saver": "^2.0.1",
-    "@types/jasmine": "^3.5.13",
+    "@types/jasmine": "^3.5.14",
     "@types/jasminewd2": "^2.0.8",
-    "@types/node": "^14.6.0",
+    "@types/node": "^14.10.3",
     "codelyzer": "^6.0.0",
     "cordova": "^10.0.0",
-    "electron": "^10.0.0",
-    "electron-builder": "^22.8.0",
+    "electron": "^10.1.2",
+    "electron-builder": "^22.8.1",
     "fs-extra": "^9.0.1",
     "jasmine-core": "^3.6.0",
     "jasmine-spec-reporter": "~5.0.0",
-    "karma": "^5.1.1",
+    "karma": "^5.2.2",
     "karma-chrome-launcher": "~3.1.0",
     "karma-cli": "~2.0.0",
     "karma-coverage-istanbul-reporter": "^3.0.3",
diff --git a/protractor.conf.js b/protractor.conf.js
index d474c230b2a8c1592f135dd650a605a8af92ec03..3077d88c4a22b765dc4e56950ea0bc26cf305a45 100644
--- a/protractor.conf.js
+++ b/protractor.conf.js
@@ -61,7 +61,7 @@ exports.config = {
     require('ts-node').register({
       project: 'e2e/tsconfig.e2e.json'
     });
-    jasmine.getEnv().addReporter(new SpecReporter({ spec: { displayStacktrace: true } }));
+    jasmine.getEnv().addReporter(new SpecReporter({ spec: { displayStacktrace: "pretty" } }));
     browser.manage().window().setSize(1600, 1000);
     browser.driver.sendChromiumCommand('Page.setDownloadBehavior', {
       behavior: 'allow',
diff --git a/src/app/app.component.ts b/src/app/app.component.ts
index 7b79d655a874978c0a8cb90a26c8206cd958ac86..6ffb143b0f37dcae7d1e9144932a7182564a6e82 100644
--- a/src/app/app.component.ts
+++ b/src/app/app.component.ts
@@ -7,7 +7,6 @@ import { CdkDragDrop, moveItemInArray } from "@angular/cdk/drag-drop";
 
 import { Observer, jalhydDateRev, jalhydVersion, CalculatorType, Session } from "jalhyd";
 
-import { environment } from "../environments/environment";
 import { I18nService } from "./services/internationalisation.service";
 import { FormulaireService } from "./services/formulaire.service";
 import { FormulaireDefinition } from "./formulaire/definition/form-definition";
@@ -643,39 +642,38 @@ export class AppComponent implements OnInit, OnDestroy, Observer {
         });
     }
 
-    public loadSessionFile(f: File, info?: any) {
+    public async loadSessionFile(f: File, info?: any) {
         // notes merge detection: was there already some notes ?
         const existingNotes = Session.getInstance().documentation;
         // load
-        this.formulaireService.loadSession(f, info)
-            .then((data) => {
-                if (data.hasErrors) {
-                    this.notificationsService.notify(this.intlService.localizeText("ERROR_PROBLEM_LOADING_SESSION"), 3500);
-                } else {
-                    if (data.loaded && data.loaded.length > 0) {
-                        if (!isDevMode()) {
-                            this.matomoTracker.trackEvent("userAction", "loadSession");
-                        }
-                        // notes merge detection: was there already some notes ?
-                        const currentNotes = Session.getInstance().documentation;
-                        if (existingNotes !== "" && currentNotes !== existingNotes) {
-                            this.notificationsService.notify(this.intlService.localizeText("WARNING_SESSION_LOAD_NOTES_MERGED"), 3500);
-                        }
-                        // go to calc or diagram depending on what was loaded
-                        if (data.loaded.length > 1) {
-                            this.toDiagram();
-                        } else {
-                            this.toCalc(data.loaded[0]);
-                        }
+        try {
+            const data = await this.formulaireService.loadSession(f, info);
+            if (data.hasErrors) {
+                this.notificationsService.notify(this.intlService.localizeText("ERROR_PROBLEM_LOADING_SESSION"), 3500);
+            } else {
+                if (data.loaded && data.loaded.length > 0) {
+                    if (!isDevMode()) {
+                        this.matomoTracker.trackEvent("userAction", "loadSession");
+                    }
+                    // notes merge detection: was there already some notes ?
+                    const currentNotes = Session.getInstance().documentation;
+                    if (existingNotes !== "" && currentNotes !== existingNotes) {
+                        this.notificationsService.notify(this.intlService.localizeText("WARNING_SESSION_LOAD_NOTES_MERGED"), 3500);
+                    }
+                    // go to calc or diagram depending on what was loaded
+                    if (data.loaded.length > 1) {
+                        this.toDiagram();
+                    } else {
+                        this.toCalc(data.loaded[0]);
                     }
                 }
-            })
-            .catch((err) => {
-                this.notificationsService.notify(this.intlService.localizeText("ERROR_LOADING_SESSION"), 3500);
-                console.error("error loading session - ", err);
-                // rollback to ensure session is clean
-                this.doEmptySession();
-            });
+            }
+        } catch (err) {
+            this.notificationsService.notify(this.intlService.localizeText("ERROR_LOADING_SESSION"), 3500);
+            console.error("error loading session - ", err);
+            // rollback to ensure session is clean
+            this.doEmptySession();
+        }
     }
 
     /**
@@ -852,20 +850,20 @@ export class AppComponent implements OnInit, OnDestroy, Observer {
     /**
      * détection de la fermeture de la page/navigateur et demande de confirmation
      */
-    @HostListener("window:beforeunload", ["$event"]) confirmExit($event) {
+    @HostListener("window:beforeunload", [ "$event" ]) confirmExit($event) {
         if (
-            this.appSetupService.warnBeforeTabClose
-            && environment.production // otherwise prevents dev server to reload app after recompiling
+        this.appSetupService.warnBeforeTabClose
+        && ! isDevMode() // otherwise prevents dev server to reload app after recompiling
         ) {
-            // affecter une valeur différente de null provoque l'affichage d'un dialogue de confirmation, mais le texte n'est pas affiché
-            $event.returnValue = "Your data will be lost !";
+        // affecter une valeur différente de null provoque l'affichage d'un dialogue de confirmation, mais le texte n'est pas affiché
+        $event.returnValue = "Your data will be lost !";
         }
     }
 
-    @HostListener("keydown", ["$event"]) onKeydown(event: any) {
-        if (event.which === 38 || event.which === 40) { // up / down arrow
-            if (event.srcElement.type === "number") {
-                event.preventDefault();
+    @HostListener("keydown", ["$event"]) onKeyDown($event: any) {
+        if ($event.which === 38 || $event.which === 40) { // up / down arrow
+            if ($event.srcElement.type === "number") {
+                $event.preventDefault();
             }
         }
     }
diff --git a/src/app/app.module.ts b/src/app/app.module.ts
index 8ed21e34314d770e30a89a08863990ea05c1286c..f1d0c02158a2d200aa58511119fd390dd95f0b8a 100644
--- a/src/app/app.module.ts
+++ b/src/app/app.module.ts
@@ -44,7 +44,6 @@ import { HttpClientModule } from "@angular/common/http";
 import { FormsModule, ReactiveFormsModule } from "@angular/forms"; // <-- NgModel lives here
 import { ChartModule } from "angular2-chartjs";
 import { RouterModule, Routes } from "@angular/router";
-import { StorageServiceModule } from "ngx-webstorage-service";
 import { HotkeyModule } from "angular2-hotkeys";
 import { MatomoModule } from "ngx-matomo";
 
@@ -67,13 +66,13 @@ import { FixedVarResultsComponent } from "./components/fixedvar-results/fixedvar
 import { SectionResultsComponent } from "./components/section-results/section-results.component";
 import { GenericCalculatorComponent } from "./components/generic-calculator/calculator.component";
 import { CalculatorNameComponent } from "./components/generic-calculator/calc-name.component";
-import { CalcCanvasComponent } from "./components/canvas/canvas.component";
 import { SectionCanvasComponent } from "./components/section-canvas/section-canvas.component";
 import { RemousResultsComponent } from "./components/remous-results/remous-results.component";
 import { ResultsChartComponent } from "./components/results-chart/results-chart.component";
 import { PabResultsComponent } from "./components/pab-results/pab-results.component";
-import { VerificateurResultsComponent } from "./components/verificateur-results/verificateur-results.component";
 import { PabResultsTableComponent } from "./components/pab-results/pab-results-table.component";
+import { PbResultsComponent } from "./components/pb-results/pb-results.component";
+import { PbResultsTableComponent } from "./components/pb-results/pb-results-table.component";
 import { ChartTypeSelectComponent } from "./components/results-chart/chart-type.component";
 import { CalculatorListComponent } from "./components/calculator-list/calculator-list.component";
 import { ApplicationSetupComponent } from "./components/app-setup/app-setup.component";
@@ -81,11 +80,13 @@ import { BaseParamInputComponent } from "./components/base-param-input/base-para
 import { FixedResultsComponent } from "./components/fixedvar-results/fixed-results.component";
 import { VarResultsComponent } from "./components/fixedvar-results/var-results.component";
 import { LogComponent } from "./components/log/log.component";
-import { LogEntryComponent } from "./components/log-entry/log-entry.component";
 import { LogDrawerComponent } from "./components/log-drawer/log-drawer.component";
+import { LogEntryComponent } from "./components/log-entry/log-entry.component";
 import { ParamLinkComponent } from "./components/param-link/param-link.component";
 import { PabProfileChartComponent } from "./components/pab-profile-chart/pab-profile-chart.component";
 import { PabTableComponent } from "./components/pab-table/pab-table.component";
+import { PbSchemaComponent } from "./components/pb-schema/pb-schema.component";
+import { PbCloisonResultsComponent } from "./components/pb-results/pb-cloison-results.component";
 import { VariableResultsSelectorComponent } from "./components/variable-results-selector/variable-results-selector.component";
 import { QuicknavComponent } from "./components/quicknav/quicknav.component";
 import { ModulesDiagramComponent } from "./components/modules-diagram/modules-diagram.component";
@@ -94,6 +95,7 @@ import { MacrorugoCompoundResultsComponent } from "./components/macrorugo-compou
 import { JetResultsComponent } from "./components/jet-results/jet-results.component";
 import { JetTrajectoryChartComponent } from "./components/jet-trajectory-chart/jet-trajectory-chart.component";
 import { SessionPropertiesComponent } from "./components/session-properties/session-properties.component";
+import { VerificateurResultsComponent } from "./components/verificateur-results/verificateur-results.component";
 
 import { DialogConfirmEmptySessionComponent } from "./components/dialog-confirm-empty-session/dialog-confirm-empty-session.component";
 import { DialogConfirmCloseCalcComponent } from "./components/dialog-confirm-close-calc/dialog-confirm-close-calc.component";
@@ -102,10 +104,11 @@ import { DialogEditParamComputedComponent } from "./components/dialog-edit-param
 import { DialogEditParamValuesComponent } from "./components/dialog-edit-param-values/dialog-edit-param-values.component";
 import { DialogGeneratePABComponent } from "./components/dialog-generate-pab/dialog-generate-pab.component";
 import { DialogGeneratePARSimulationComponent } from "./components/dialog-generate-par-simulation/dialog-generate-par-simulation.component";
-import { DialogLoadPredefinedEspeceComponent } from "./components/dialog-load-predefined-espece/dialog-load-predefined-espece.component";
 import { DialogLoadSessionComponent } from "./components/dialog-load-session/dialog-load-session.component";
 import { DialogLogEntriesDetailsComponent } from "./components/dialog-log-entries-details/dialog-log-entries-details.component";
 import { DialogSaveSessionComponent } from "./components/dialog-save-session/dialog-save-session.component";
+import { DialogNewPbCloisonComponent } from "./components/dialog-new-pb-cloison/dialog-new-pb-cloison.component";
+import { DialogLoadPredefinedEspeceComponent } from "./components/dialog-load-predefined-espece/dialog-load-predefined-espece.component";
 
 import { JalhydAsyncModelValidationDirective } from "./directives/jalhyd-async-model-validation.directive";
 import {
@@ -169,13 +172,12 @@ const appRoutes: Routes = [
         MatTooltipModule,
         MatomoModule,
         RouterModule.forRoot(
-            appRoutes,
-            {
-                useHash: true, // prevents reloading whole app when typing url in browser's navigation bar
-                enableTracing: false // debugging purposes only
-            }
+        appRoutes,
+        {
+            useHash: true, // prevents reloading whole app when typing url in browser's navigation bar
+            enableTracing: false // debugging purposes only
+        }
         ),
-        StorageServiceModule,
         TableModule,
         KonamiModule
     ],
@@ -183,7 +185,6 @@ const appRoutes: Routes = [
         AppComponent,
         ApplicationSetupComponent,
         BaseParamInputComponent,
-        CalcCanvasComponent,
         CalculatorListComponent,
         CalculatorNameComponent,
         CalculatorResultsComponent,
@@ -194,10 +195,11 @@ const appRoutes: Routes = [
         DialogEditParamValuesComponent,
         DialogGeneratePABComponent,
         DialogGeneratePARSimulationComponent,
-        DialogLoadPredefinedEspeceComponent,
         DialogLoadSessionComponent,
         DialogLogEntriesDetailsComponent,
         DialogSaveSessionComponent,
+        DialogNewPbCloisonComponent,
+        DialogLoadPredefinedEspeceComponent,
         FieldSetComponent,
         FieldsetContainerComponent,
         FixedResultsComponent,
@@ -221,9 +223,12 @@ const appRoutes: Routes = [
         NgParamInputComponent,
         PabProfileChartComponent,
         PabResultsComponent,
-        VerificateurResultsComponent,
         PabResultsTableComponent,
         PabTableComponent,
+        PbResultsComponent,
+        PbCloisonResultsComponent,
+        PbResultsTableComponent,
+        PbSchemaComponent,
         VariableResultsSelectorComponent,
         MacrorugoCompoundResultsComponent,
         MacrorugoCompoundResultsTableComponent,
@@ -238,7 +243,8 @@ const appRoutes: Routes = [
         SectionResultsComponent,
         SelectFieldLineComponent,
         SessionPropertiesComponent,
-        VarResultsComponent
+        VarResultsComponent,
+        VerificateurResultsComponent
     ],
     entryComponents: [
         DialogConfirmCloseCalcComponent,
@@ -250,6 +256,7 @@ const appRoutes: Routes = [
         DialogGeneratePARSimulationComponent,
         DialogLoadPredefinedEspeceComponent,
         DialogSaveSessionComponent,
+        DialogNewPbCloisonComponent,
         DialogLoadSessionComponent,
         DialogLogEntriesDetailsComponent
     ],
@@ -261,12 +268,12 @@ const appRoutes: Routes = [
         I18nService,
         NotificationsService,
         {
-            provide: ErrorStateMatcher,
-            useClass: ImmediateErrorStateMatcher
+        provide: ErrorStateMatcher,
+        useClass: ImmediateErrorStateMatcher
         }
     ],
-    schemas: [NO_ERRORS_SCHEMA],
-    bootstrap: [AppComponent]
+    schemas: [ NO_ERRORS_SCHEMA ],
+    bootstrap: [ AppComponent ]
 })
 
 export class AppModule { }
diff --git a/src/app/calculators/pbbassin/en.json b/src/app/calculators/pbbassin/en.json
new file mode 100644
index 0000000000000000000000000000000000000000..6566e3fd828cb3b988499fd1881afb6acdbe7f6b
--- /dev/null
+++ b/src/app/calculators/pbbassin/en.json
@@ -0,0 +1,6 @@
+{
+    "fs_basin_params": "Basin parameters",
+
+    "S": "Surface",
+    "ZF": "Bottom elevation"
+}
diff --git a/src/app/calculators/pbbassin/fr.json b/src/app/calculators/pbbassin/fr.json
new file mode 100644
index 0000000000000000000000000000000000000000..71d54fd771d5d737f4d6e7267777f36fc1876358
--- /dev/null
+++ b/src/app/calculators/pbbassin/fr.json
@@ -0,0 +1,6 @@
+{
+    "fs_basin_params": "Paramètres du bassin",
+
+    "S": "Surface",
+    "ZF": "Cote de fond"
+}
diff --git a/src/app/calculators/pbcloison/en.json b/src/app/calculators/pbcloison/en.json
new file mode 100644
index 0000000000000000000000000000000000000000..e621e15fb27199e75f3246ce6c3e82f6dfb78ebf
--- /dev/null
+++ b/src/app/calculators/pbcloison/en.json
@@ -0,0 +1,7 @@
+{
+    "fs_wall_params": "Wall parameters",
+    "fs_wall_device": "Device",
+
+    "select_upstream_basin": "Upstream basin",
+    "select_downstream_basin": "Downstream basin"
+}
diff --git a/src/app/calculators/pbcloison/fr.json b/src/app/calculators/pbcloison/fr.json
new file mode 100644
index 0000000000000000000000000000000000000000..472d7d8973cead05e13d0793e1b112c9c99e501d
--- /dev/null
+++ b/src/app/calculators/pbcloison/fr.json
@@ -0,0 +1,7 @@
+{
+    "fs_wall_params": "Paramètres de la cloison",
+    "fs_wall_device": "Ouvrage",
+
+    "select_upstream_basin": "Bassin amont",
+    "select_downstream_basin": "Bassin aval"
+}
diff --git a/src/app/calculators/prebarrage/config.json b/src/app/calculators/prebarrage/config.json
new file mode 100644
index 0000000000000000000000000000000000000000..510ae56d186ad4bfd66b48a9dba1abd43a06aa66
--- /dev/null
+++ b/src/app/calculators/prebarrage/config.json
@@ -0,0 +1,195 @@
+[
+    {
+        "id": "schema_interactif_pb",
+        "type": "pb_schema"
+    },
+    {
+        "id": "subform_river",
+        "type": "subform",
+        "config": [
+            {
+                "id": "fs_river_params",
+                "type": "fieldset",
+                "fields": [
+                    "Q",
+                    "Z1",
+                    "Z2"
+                ]
+            },
+            {
+                "type": "options",
+                "selectIds": [ ]
+            }
+        ]
+    },
+    {
+        "id": "subform_basin",
+        "type": "subform",
+        "config": [
+            {
+                "id": "fs_basin_params",
+                "type": "fieldset",
+                "fields": [
+                    "S",
+                    "ZF"
+                ]
+            },
+            {
+                "type": "options",
+                "selectIds": [ ]
+            }
+        ]
+    },
+    {
+        "id": "subform_wall",
+        "type": "subform",
+        "config": [
+            {
+                "id": "fs_ouvrage",
+                "type": "fieldset_template",
+                "calcType": "Structure",
+                "defaultStructType": "SeuilRectangulaire",
+                "defaultLoiDebit": "WeirSubmergedLarinier",
+                "fields": [
+                    {
+                        "id": "select_structure",
+                        "type": "select",
+                        "property": "structureType",
+                        "source": "device_structure_type"
+                    },
+                    {
+                        "id": "select_loidebit",
+                        "type": "select",
+                        "property": "loiDebit",
+                        "source": "device_loi_debit",
+                        "help": {
+                            "SeuilRectangulaire_KIVI": "structures/kivi.html",
+                            "SeuilRectangulaire_WeirVillemonte": "structures/kivi.html",
+                            "SeuilRectangulaire_WeirCem88d": "structures/cem_88_d.html",
+                            "SeuilRectangulaire_WeirCem88v": "structures/cem_88_v.html",
+                            "SeuilRectangulaire_WeirCunge80": "structures/cunge_80.html",
+                            "VanneRectangulaire_GateCem88d": "structures/cem_88_d.html",
+                            "VanneRectangulaire_GateCem88v": "structures/cem_88_v.html",
+                            "VanneRectangulaire_GateCunge80": "structures/cunge_80.html",
+                            "Orifice_OrificeSubmerged": "structures/orifice_noye.html",
+                            "Orifice_OrificeFree": "structures/orifice_denoye.html",
+                            "SeuilRectangulaire_WeirSubmergedLarinier": "structures/fente_noyee.html",
+                            "SeuilRectangulaire_WeirSubmerged": "structures/seuil_noye.html",
+                            "SeuilRectangulaire_WeirFree": "structures/seuil_denoye.html",
+                            "SeuilTriangulaire_TriangularWeirFree": "structures/dever_triang.html",
+                            "SeuilTriangulaire_TriangularWeirBroad": "structures/dever_triang.html",
+                            "SeuilTriangulaireTrunc_TriangularTruncWeirFree": "structures/dever_triang_tronque.html"
+                        }
+                    },
+                    {
+                        "id": "S",
+                        "calculable": false
+                    },
+                    {
+                        "id": "ZDV",
+                        "calculable": false
+                    },
+                    {
+                        "id": "L",
+                        "calculable": false
+                    },
+                    {
+                        "id": "W",
+                        "calculable": false
+                    },
+                    {
+                        "id": "CdWS",
+                        "calculable": false
+                    },
+                    {
+                        "id": "CdWSL",
+                        "calculable": false
+                    },
+                    {
+                        "id": "CdWR",
+                        "calculable": false
+                    },
+                    {
+                        "id": "CdGR",
+                        "calculable": false
+                    },
+                    {
+                        "id": "CdCunge",
+                        "calculable": false
+                    },
+                    {
+                        "id": "CdT",
+                        "calculable": false
+                    },
+                    {
+                        "id": "CdO",
+                        "calculable": false
+                    },
+                    {
+                        "id": "alpha",
+                        "calculable": false
+                    },
+                    {
+                        "id": "beta",
+                        "calculable": false
+                    },
+                    {
+                        "id": "ZRAM",
+                        "calculable": false
+                    },
+                    {
+                        "id": "alpha2",
+                        "calculable": false
+                    },
+                    {
+                        "id": "BT",
+                        "calculable": false
+                    },
+                    {
+                        "id": "ZT",
+                        "calculable": false
+                    },
+                    {
+                        "id": "Zco",
+                        "calculable": false
+                    }
+                ]
+            },
+            {
+                "id": "fs_wall_params",
+                "type": "fieldset",
+                "fields": [
+                    {
+                        "id": "select_upstream_basin",
+                        "type": "select_custom",
+                        "source": "upstream_basin"
+                    },
+                    {
+                        "id": "select_downstream_basin",
+                        "type": "select_custom",
+                        "source": "downstream_basin"
+                    }
+                ]
+            },
+            {
+                "id": "struct_container",
+                "type": "template_container",
+                "templates": [
+                    "fs_ouvrage"
+                ]
+            },
+            {
+                "type": "options",
+                "selectIds": [ "select_structure", "select_loidebit" ],
+                "customSelectIds": [ "select_upstream_basin", "select_downstream_basin" ]
+            }
+        ]
+    },
+    {
+        "type": "options",
+        "selectIds": [ ],
+        "upstreamSelectId": "select_upstream",
+        "downstreamSelectId": "select_downstream",
+        "_help": "prebarrage.html"
+    }
+]
diff --git a/src/app/calculators/prebarrage/en.json b/src/app/calculators/prebarrage/en.json
new file mode 100644
index 0000000000000000000000000000000000000000..8fb6bf3da2587bc5a824aeb2337cecda4dacb55e
--- /dev/null
+++ b/src/app/calculators/prebarrage/en.json
@@ -0,0 +1,20 @@
+{
+    "fs_river_params": "River parameters",
+
+    "Q": "Flow",
+    "Z1": "Upstream water elevation",
+    "Z2": "Downstream water elevation",
+
+    "Z": "Water elevation",
+    "S": "Surface",
+    "ZF": "Bottom elevation",
+    "PV": "Dissipated power",
+    "YMOY": "Mean depth",
+
+    "UNIT_Q": "m³/s",
+    "UNIT_S": "m²",
+    "UNIT_Z": "m",
+    "UNIT_ZF": "m",
+    "UNIT_YMOY": "m",
+    "UNIT_PV": "W/m³"
+}
diff --git a/src/app/calculators/prebarrage/fr.json b/src/app/calculators/prebarrage/fr.json
new file mode 100644
index 0000000000000000000000000000000000000000..7b3f06d22fed9d55444f5741c2338c9896482d8c
--- /dev/null
+++ b/src/app/calculators/prebarrage/fr.json
@@ -0,0 +1,20 @@
+{
+    "fs_river_params": "Paramètres de la rivière",
+
+    "Q": "Débit",
+    "Z1": "Cote de l'eau amont",
+    "Z2": "Cote de l'eau aval",
+
+    "Z": "Cote de l'eau",
+    "S": "Surface",
+    "ZF": "Cote de fond",
+    "PV": "Puissance dissipée",
+    "YMOY": "Profondeur moyenne",
+
+    "UNIT_Q": "m³/s",
+    "UNIT_S": "m²",
+    "UNIT_Z": "m",
+    "UNIT_ZF": "m",
+    "UNIT_YMOY": "m",
+    "UNIT_PV": "W/m³"
+}
diff --git a/src/app/components/app-setup/app-setup.component.ts b/src/app/components/app-setup/app-setup.component.ts
index 66b9df46216df020241301b28f5f222a0584c024..1b3c52d158c498cf992ed9ee31e0fe88dca086c5 100644
--- a/src/app/components/app-setup/app-setup.component.ts
+++ b/src/app/components/app-setup/app-setup.component.ts
@@ -135,12 +135,11 @@ export class ApplicationSetupComponent implements Observer, OnInit {
         });
     }
 
-    public restoreDefaultValues() {
+    public async restoreDefaultValues() {
         const text = this.intlService.localizeText("INFO_SNACKBAR_DEFAULT_SETTINGS_RESTORED");
-        this.appSetupService.restoreDefaultValues().then(() => {
-            this.snackBar.open(text, "OK", {
-                duration: 2500
-            });
+        await this.appSetupService.restoreDefaultValues();
+        this.snackBar.open(text, "OK", {
+            duration: 2500
         });
     }
 
diff --git a/src/app/components/calculator-list/calculator-list.component.ts b/src/app/components/calculator-list/calculator-list.component.ts
index 6dc05bea1420b7043f7f1a8c3b92b26bc5acf58f..fcc96d90f5b96ff89aa806113a1e161274abdacb 100644
--- a/src/app/components/calculator-list/calculator-list.component.ts
+++ b/src/app/components/calculator-list/calculator-list.component.ts
@@ -114,10 +114,14 @@ export class CalculatorListComponent implements OnInit {
 
                 for (const t of unusedCalculators) {
                     if ( // those sub-Nub types cannot be built outside a parent
-                        t !== CalculatorType.Structure
-                        && t !== CalculatorType.Section
-                        && t !== CalculatorType.CloisonAval
-                        && t !== CalculatorType.YAXN
+                        ! [
+                            CalculatorType.Structure,
+                            CalculatorType.Section,
+                            CalculatorType.CloisonAval,
+                            CalculatorType.YAXN,
+                            CalculatorType.PbBassin,
+                            CalculatorType.PbCloison
+                        ].includes(t)
                     ) {
                         unusedTheme.calculators.push({
                             type: t,
@@ -138,53 +142,49 @@ export class CalculatorListComponent implements OnInit {
         this.filterItems();
     }
 
-    public create(t: CalculatorType) {
-        const p: Promise<FormulaireDefinition> = ServiceFactory.formulaireService.createFormulaire(t);
-        p.then(f => {
-            this.router.navigate(["/calculator", f.uid]);
-            return f;
-        }).then(f => {
-            // on ajoute un ouvrage après l'ouverture du module de calcul "ouvrages parallèles"
-            if (f instanceof FormulaireParallelStructure) {
-                for (const e of f.allFormElements) {
-                    if (e instanceof FieldsetContainer) {
-                        e.addFromTemplate(0);
-                        break;
-                    }
+    public async create(t: CalculatorType) {
+        const f: FormulaireDefinition = await ServiceFactory.formulaireService.createFormulaire(t);
+        await this.router.navigate(["/calculator", f.uid]);
+        // on ajoute un ouvrage après l'ouverture du module de calcul "ouvrages parallèles"
+        if (f instanceof FormulaireParallelStructure) {
+            for (const e of f.allFormElements) {
+                if (e instanceof FieldsetContainer) {
+                    e.addFromTemplate(0);
+                    break;
                 }
             }
-            // on ajoute un ouvrage après l'ouverture du module de calcul "passe à bassins"
-            if (f instanceof FormulairePab) {
-                for (const e of f.allFormElements) {
-                    if (e instanceof FieldsetContainer) {
-                        e.addFromTemplate(0);
-                        break;
-                    }
+        }
+        // on ajoute un ouvrage après l'ouverture du module de calcul "passe à bassins"
+        if (f instanceof FormulairePab) {
+            for (const e of f.allFormElements) {
+                if (e instanceof FieldsetContainer) {
+                    e.addFromTemplate(0);
+                    break;
                 }
             }
-            // adding GUI for default apron, in MacroRugoCompound
-            if (f instanceof FormulaireMacrorugoCompound) {
-                for (const e of f.allFormElements) {
-                    if (e instanceof FieldsetContainer) {
-                        e.addFromTemplate(0, 0, f.currentNub.getChildren()[0]);
-                        break;
-                    }
+        }
+        // adding GUI for default apron, in MacroRugoCompound
+        if (f instanceof FormulaireMacrorugoCompound) {
+            for (const e of f.allFormElements) {
+                if (e instanceof FieldsetContainer) {
+                    e.addFromTemplate(0, 0, f.currentNub.getChildren()[0]);
+                    break;
                 }
             }
-            // on ajoute un YAXN après l'ouverture du module de calcul "somme / produit de puissances"
-            if (f instanceof FormulaireSPP) {
-                for (const e of f.allFormElements) {
-                    if (e instanceof FieldsetContainer) {
-                        e.addFromTemplate(0);
-                        break;
-                    }
+        }
+        // on ajoute un YAXN après l'ouverture du module de calcul "somme / produit de puissances"
+        if (f instanceof FormulaireSPP) {
+            for (const e of f.allFormElements) {
+                if (e instanceof FieldsetContainer) {
+                    e.addFromTemplate(0);
+                    break;
                 }
             }
+        }
 
-            if (this.appSetupService.enableEmptyFieldsOnFormInit) {
-                f.emptyFields();
-            }
-        });
+        if (this.appSetupService.enableEmptyFieldsOnFormInit) {
+            f.emptyFields();
+        }
     }
 
     public get nbOpenCalculators() {
@@ -268,18 +268,23 @@ export class CalculatorListComponent implements OnInit {
             {
                 label: this.intlService.localizeText("INFO_EXAMPLE_LABEL_PERR"),
                 path: "perr.json"
+            },
+            {
+                label: this.intlService.localizeText("INFO_EXAMPLE_LABEL_PB"),
+                path: "prebarrage.json"
             }
         ];
     }
 
-    public loadExample(path: string) {
+    public async loadExample(path: string) {
         const realPath = "app/examples/" + path;
-        this.httpService.httpGetBlobRequestPromise(realPath).then((d) => {
+        try {
+            const d = await this.httpService.httpGetBlobRequestPromise(realPath);
             const f: any = new Blob([d], { type: "application/json" });
             this.appComponent.loadSessionFile(f);
-        }).catch((e) => {
+        } catch (e) {
             console.error("could not load session file", e);
-        });
+        }
     }
 
     public get uitextWelcomeTitle() {
diff --git a/src/app/components/calculator-results/calculator-results.component.html b/src/app/components/calculator-results/calculator-results.component.html
index 319b3eab39c1483dc3b8c646ce2e2c7e040d63be..61ddf062b3f7b144d0375276fc83fcd9963bc8ee 100644
--- a/src/app/components/calculator-results/calculator-results.component.html
+++ b/src/app/components/calculator-results/calculator-results.component.html
@@ -1,9 +1,10 @@
 <div>
-    <section-results [hidden]="! isSP"></section-results>
-    <remous-results [hidden]="! isRemous"></remous-results>
-    <pab-results [hidden]="! isPAB"></pab-results>
-    <verificateur-results [hidden]="! isVerificateur"></verificateur-results>
-    <macrorugo-compound-results [hidden]="! isMRC"></macrorugo-compound-results>
-    <jet-results [hidden]="! isJet"></jet-results>
-    <fixedvar-results [hidden]="! showGenericResults"></fixedvar-results>
+    <section-results *ngIf="isSP" [results]=formResultsArray></section-results>
+    <remous-results *ngIf="isRemous" [results]=formResultsArray></remous-results>
+    <pab-results *ngIf="isPAB" [results]=formResultsArray></pab-results>
+    <pb-results *ngIf="isPB" [results]=formResultsArray></pb-results>
+    <verificateur-results *ngIf="isVerificateur" [results]=formResultsArray></verificateur-results>
+    <macrorugo-compound-results *ngIf="isMRC" [results]=formResultsArray></macrorugo-compound-results>
+    <jet-results *ngIf="isJet" [results]=formResultsArray></jet-results>
+    <fixedvar-results *ngIf="! isJet" [results]=formResultsArray></fixedvar-results>
 </div>
diff --git a/src/app/components/calculator-results/calculator-results.component.ts b/src/app/components/calculator-results/calculator-results.component.ts
index 900cf877a848c0e0385faf2cacf504334afc7e6a..796d0e481ca79e3504b8ed9efdb98377b1f3a3cd 100644
--- a/src/app/components/calculator-results/calculator-results.component.ts
+++ b/src/app/components/calculator-results/calculator-results.component.ts
@@ -1,16 +1,8 @@
-import { Component, ViewChild, Output, EventEmitter, AfterViewChecked, Inject, forwardRef } from "@angular/core";
+import { Component, Output, EventEmitter, AfterViewChecked, Inject, forwardRef, Input } from "@angular/core";
 
-import { FixedVarResultsComponent } from "../../components/fixedvar-results/fixedvar-results.component";
-import { SectionResultsComponent } from "../../components/section-results/section-results.component";
-import { RemousResultsComponent } from "../../components/remous-results/remous-results.component";
-import { PabResultsComponent } from "../../components/pab-results/pab-results.component";
-import { MacrorugoCompoundResultsComponent } from "../macrorugo-compound-results/macrorugo-compound-results.component";
 import { FormulaireDefinition } from "../../formulaire/definition/form-definition";
-import { JetResultsComponent } from "../jet-results/jet-results.component";
+import { CalculatorResults } from "../../results/calculator-results";
 import { GenericCalculatorComponent } from "../generic-calculator/calculator.component";
-import { VerificateurResultsComponent } from "../verificateur-results/verificateur-results.component";
-
-import { CalculatorType } from "jalhyd";
 
 @Component({
     selector: "calc-results",
@@ -20,51 +12,7 @@ export class CalculatorResultsComponent implements AfterViewChecked {
 
     private _formulaire: FormulaireDefinition;
 
-    /**
-     * composant d'affichage des résultats de paramètres fixés/variables
-     */
-    @ViewChild(FixedVarResultsComponent, { static: true })
-    private fixedVarResultsComponent: FixedVarResultsComponent;
-
-    /**
-     * composant d'affichage des résultats des sections paramétrées
-     */
-    @ViewChild(SectionResultsComponent, { static: true })
-    private sectionResultsComponent: SectionResultsComponent;
-
-    /**
-     * composant d'affichage des résultats des courbes de remous
-     */
-    @ViewChild(RemousResultsComponent, { static: true })
-    private remousResultsComponent: RemousResultsComponent;
-
-    /**
-     * composant d'affichage des résultats des passes à bassins
-     */
-    @ViewChild(PabResultsComponent, { static: true })
-    private pabResultsComponent: PabResultsComponent;
-
-    /**
-     * composant d'affichage des résultats des vérificateurs de critères de franchissement
-     */
-    @ViewChild(VerificateurResultsComponent, { static: true })
-    private verificateurResultsComponent: VerificateurResultsComponent;
-
-    /**
-     * composant d'affichage des résultats des passes à macrorugosités complexes
-     */
-    @ViewChild(MacrorugoCompoundResultsComponent, { static: true })
-    private mrcResultsComponent: MacrorugoCompoundResultsComponent;
-
-    /**
-     * composant d'affichage des résultats des impacts de jet
-     */
-    @ViewChild(JetResultsComponent, { static: true })
-    private jetResultsComponent: JetResultsComponent;
-
-    /**
-     * événement émis à la fin du dessin de la vue
-     */
+    /** notify CalculatorComponent that it may scroll down to results panel */
     @Output()
     private afterViewChecked = new EventEmitter();
 
@@ -72,75 +20,49 @@ export class CalculatorResultsComponent implements AfterViewChecked {
         @Inject(forwardRef(() => GenericCalculatorComponent)) private calculatorComponent: GenericCalculatorComponent
     ) { }
 
-    // @TODO this system is sh*tty !
+    @Input()
     public set formulaire(f: FormulaireDefinition) {
         this._formulaire = f;
-        if (this._formulaire === undefined) {
-            this.fixedVarResultsComponent.results = undefined;
-            this.jetResultsComponent.results = undefined;
-            this.mrcResultsComponent.results = undefined;
-            this.pabResultsComponent.results = undefined;
-            this.remousResultsComponent.results = undefined;
-            this.sectionResultsComponent.results = undefined;
-            this.verificateurResultsComponent.results = undefined;
-        } else {
-            if (this.showGenericResults) { this.fixedVarResultsComponent.results = f.results; }
-            if (this.isJet) { this.jetResultsComponent.results = f.results; }
-            if (this.isMRC) { this.mrcResultsComponent.results = f.results; }
-            if (this.isPAB) { this.pabResultsComponent.results = f.results; }
-            if (this.isRemous) { this.remousResultsComponent.results = f.results; }
-            if (this.isSP) { this.sectionResultsComponent.results = f.results; }
-            if (this.isVerificateur) { this.verificateurResultsComponent.results = f.results; }
-        }
     }
 
-    public updateView() {
-        if (this.showGenericResults) { this.fixedVarResultsComponent.updateView(); }
-        if (this.isJet) { this.jetResultsComponent.updateView(); }
-        if (this.isMRC) { this.mrcResultsComponent.updateView(); }
-        if (this.isPAB) { this.pabResultsComponent.updateView(); }
-        if (this.isRemous) { this.remousResultsComponent.updateView(); }
-        if (this.isSP) { this.sectionResultsComponent.updateView(); }
-        if (this.isVerificateur) { this.verificateurResultsComponent.updateView(); }
+    public get formResultsArray(): CalculatorResults[] {
+        let r: CalculatorResults[] = [];
+        if (this._formulaire !== undefined) {
+            r = this._formulaire.results;
+        }
+        return r;
     }
 
     public ngAfterViewChecked() {
         this.afterViewChecked.emit();
     }
 
-    /** Should we show the default FixedVarResultsComponent ? */
-    public get showGenericResults(): boolean {
-        return (
-            ! this.isJet
-            && ! this.isMRC
-            && ! this.isPAB
-            && ! this.isRemous
-            && ! this.isSP
-            && ! this.isVerificateur
-        );
+    public get isSP() {
+        return this.calculatorComponent.isSP;
     }
 
-    public get isJet(): boolean {
-        return this.calculatorComponent.isJet;
+    public get isRemous() {
+        return this.calculatorComponent.isRemous;
     }
 
-    public get isMRC(): boolean {
-        return this.calculatorComponent.isMRC;
+    public get isPAB() {
+        return this.calculatorComponent.isPAB;
     }
 
-    public get isPAB(): boolean {
-        return this.calculatorComponent.isPAB;
+    public get isPB() {
+        return this.calculatorComponent.isPB;
     }
 
-    public get isRemous(): boolean {
-        return this.calculatorComponent.is(CalculatorType.CourbeRemous);
+    public get isMRC() {
+        return this.calculatorComponent.isMRC;
     }
 
-    public get isSP(): boolean {
-        return this.calculatorComponent.is(CalculatorType.SectionParametree);
+    public get isJet() {
+        return this.calculatorComponent.isJet;
     }
 
-    public get isVerificateur(): boolean {
-        return this.calculatorComponent.is(CalculatorType.Verificateur);
+    public get isVerificateur() {
+        return this.calculatorComponent.isVerificateur;
     }
+
 }
diff --git a/src/app/components/canvas/canvas.component.ts b/src/app/components/canvas/canvas.component.ts
deleted file mode 100644
index 2035e886e543b1b0846c3e043fd0464a1c902f01..0000000000000000000000000000000000000000
--- a/src/app/components/canvas/canvas.component.ts
+++ /dev/null
@@ -1,109 +0,0 @@
-import { Component, Input, ViewChild, ElementRef, AfterViewInit } from "@angular/core";
-
-@Component({
-    selector: "calc-canvas",
-    template: `<canvas #canvas
-    [attr.width]="width"
-    [attr.height]="height">
-    </canvas>
-    `
-})
-export class CalcCanvasComponent implements AfterViewInit {
-
-    public get width(): number {
-        return this._calcCanvas.nativeElement.width;
-    }
-
-    @Input()
-    public set width(w: number) {
-        this._calcCanvas.nativeElement.width = w;
-    }
-
-    public get height(): number {
-        return this._calcCanvas.nativeElement.height;
-    }
-
-    @Input()
-    public set height(h: number) {
-        this._calcCanvas.nativeElement.height = h;
-    }
-
-    private _context2d: CanvasRenderingContext2D;
-
-    @ViewChild("canvas", { static: true })
-    private _calcCanvas: ElementRef;
-
-    ngAfterViewInit() { // wait for the view to init before using the element
-        this._context2d = this._calcCanvas.nativeElement.getContext("2d");
-    }
-
-    public clear() {
-        if (this._context2d) {
-            this._context2d.clearRect(0, 0, this.width, this.height);
-        }
-    }
-
-    public setStrokeColor(r: number, g: number, b: number) {
-        const col: string = "rgb(" + r + "," + g + "," + b + ")";
-        this._context2d.strokeStyle = col;
-    }
-
-    public setFillColor(r: number, g: number, b: number) {
-        const col: string = "rgb(" + r + "," + g + "," + b + ")";
-        this._context2d.fillStyle = col;
-    }
-
-    public setFont(f: string) {
-        this._context2d.font = f;
-    }
-
-    public fillText(s: string, x: number, y: number, align?: any) {
-        if (align) {
-            this._context2d.textAlign = align;
-        }
-        this._context2d.fillText(s, x, y);
-    }
-
-    public setLineWidth(w: number) {
-        this._context2d.lineWidth = w;
-    }
-
-    public setLineDash(d: number[]) {
-        this._context2d.setLineDash(d);
-    }
-
-    public resetLineDash() {
-        this._context2d.setLineDash([]);
-    }
-
-    public drawRect(x1: number, y1: number, w: number, h: number) {
-        this._context2d.strokeRect(x1, y1, w, h);
-    }
-
-    public drawLine(x1: number, y1: number, x2: number, y2: number) {
-        this._context2d.beginPath();
-        this._context2d.moveTo(x1, y1);
-        this._context2d.lineTo(x2, y2);
-        this._context2d.stroke();
-    }
-
-    /**
-     *
-     * @param x The x axis of the coordinate for the ellipse's center.
-     * @param y The y axis of the coordinate for the ellipse's center.
-     * @param radiusX The ellipse's major-axis radius.
-     * @param radiusY The ellipse's minor-axis radius.
-     * @param rotation The rotation for this ellipse, expressed in radians
-     * @param startAngle The starting point, measured from the x axis, from which it will be drawn, expressed in radians
-     * @param endAngle The end ellipse's angle to which it will be drawn, expressed in radians
-     */
-    public drawEllipse(x: number, y: number, radiusX: number, radiusY: number, rotation: number, startAngle: number, endAngle: number) {
-        this._context2d.beginPath();
-        this._context2d.ellipse(x, y, radiusX, radiusY, rotation, startAngle, endAngle);
-        this._context2d.stroke();
-    }
-
-    public get context2d(): CanvasRenderingContext2D {
-        return this._context2d;
-    }
-}
diff --git a/src/app/components/dialog-generate-par-simulation/dialog-generate-par-simulation.component.ts b/src/app/components/dialog-generate-par-simulation/dialog-generate-par-simulation.component.ts
index ff941247e077a8b17258024d630da1701eafa70c..b7aaf61d72def9cd99d15fec5b95d62666de2614 100644
--- a/src/app/components/dialog-generate-par-simulation/dialog-generate-par-simulation.component.ts
+++ b/src/app/components/dialog-generate-par-simulation/dialog-generate-par-simulation.component.ts
@@ -3,8 +3,7 @@ import { Inject, Component } from "@angular/core";
 
 import { I18nService } from "../../services/internationalisation.service";
 import { MultiDimensionResults } from "../../results/multidimension-results";
-
-import { fv, longestVarNgParam } from "../../util";
+import { fv, longestVarParam } from "../../util";
 
 @Component({
     selector: "dialog-generate-par-simulation",
@@ -36,12 +35,12 @@ export class DialogGeneratePARSimulationComponent {
             // pre-extract variable parameters values
             this.varValues = [];
             // find longest list
-            const lvp = longestVarNgParam(this._results.variatedParameters);
+            const lvp = longestVarParam(this._results.variatedParameters);
             this.size = lvp.size;
             // get extended values lists for each variable parameter
             for (const v of this._results.variatedParameters) {
                 const vv = [];
-                const iter = v.getExtendedValuesIterator(this.size);
+                const iter = v.param.getExtendedValuesIterator(this.size);
                 while (iter.hasNext) {
                     const nv = iter.next();
                     vv.push(fv(nv.value));
@@ -88,13 +87,13 @@ export class DialogGeneratePARSimulationComponent {
         for (let i = 0; i < this.varValues.length; i++) {
             const vv = this.varValues[i];
             const vp = this._results.variatedParameters[i];
-            let symbol = vp.symbol;
+            let symbol = vp.param.symbol;
             // is vp a parameter of a child Nub ?
             if (
-                vp.paramDefinition.parentNub
-                && vp.paramDefinition.parentNub !== vp.paramDefinition.originNub
+                vp.param.parentNub
+                && vp.param.parentNub !== vp.param.originNub
             ) {
-                const pos = vp.paramDefinition.parentNub.findPositionInParent() + 1;
+                const pos = vp.param.parentNub.findPositionInParent() + 1;
                 symbol = this.intlService.localizeText("INFO_LIB_RADIER_N_COURT") + pos + "_" + symbol;
             }
             kv.push(`${symbol} = ${vv[index]}`);
diff --git a/src/app/components/dialog-load-session/dialog-load-session.component.ts b/src/app/components/dialog-load-session/dialog-load-session.component.ts
index 653cf5ff55a9376e8ccdce2a7072cb90fa274801..c9d6f5793e03b11fff576ac3993db7910d2295e5 100644
--- a/src/app/components/dialog-load-session/dialog-load-session.component.ts
+++ b/src/app/components/dialog-load-session/dialog-load-session.component.ts
@@ -138,35 +138,34 @@ export class DialogLoadSessionComponent {
         this.checkLinkedParamsAndModelsDependencies();
     }
 
-    public onFileSelected(event: any) {
-        if (event.target.files && event.target.files.length) {
-            this.file = event.target.files[0];
-            // reinit file infos
-            this.calculators = [];
-            this.fileFormatVersion = "";
-            // reinit flags
-            this.loadingError = false;
-            this.loadingComplete = false;
-
-            const formService = ServiceFactory.formulaireService;
-            formService.calculatorInfosFromSessionFile(this.file).then(
-                calcInfos => {
-                    this.fileFormatVersion = calcInfos.formatVersion;
-                    this.calculators = calcInfos.nubs;
-                    for (const n of this.calculators) {
-                        n.selected = true;
-                        // if no title was given, generate a default one
-                        if (!n.title) {
-                            n.title = decode(formService.getLocalisedShortTitleFromCalculatorType(n.type));
-                        }
-                    }
-                    this.loadingComplete = true;
-                }
-            ).catch((err) => {
-                console.error(err);
-                this.loadingError = true;
-            });
+    public async onFileSelected(event: any) {
+      if (event.target.files && event.target.files.length) {
+        this.file = event.target.files[0];
+        // reinit file infos
+        this.calculators = [];
+        this.fileFormatVersion = "";
+        // reinit flags
+        this.loadingError = false;
+        this.loadingComplete = false;
+
+        const formService = ServiceFactory.formulaireService;
+        try {
+          const calcInfos: any = await formService.calculatorInfosFromSessionFile(this.file);
+          this.fileFormatVersion = calcInfos.formatVersion;
+          this.calculators = calcInfos.nubs;
+          for (const n of this.calculators) {
+            n.selected = true;
+            // if no title was given, generate a default one
+            if (! n.title) {
+              n.title = decode(formService.getLocalisedShortTitleFromCalculatorType(n.type));
+            }
+          }
+          this.loadingComplete = true;
+        } catch (err) {
+          console.error(err);
+          this.loadingError = true;
         }
+      }
     }
 
     public loadSession() {
diff --git a/src/app/components/dialog-new-pb-cloison/dialog-new-pb-cloison.component.html b/src/app/components/dialog-new-pb-cloison/dialog-new-pb-cloison.component.html
new file mode 100644
index 0000000000000000000000000000000000000000..a6587c7730d3cf912b851df5f0e55f237fd3bb87
--- /dev/null
+++ b/src/app/components/dialog-new-pb-cloison/dialog-new-pb-cloison.component.html
@@ -0,0 +1,28 @@
+<h1 mat-dialog-title>{{ uitextSelectBasins }}</h1>
+
+<form>
+    <mat-form-field>
+        <mat-select [placeholder]="uiTextUpstreambasin" [(value)]="upstreamIndex" required>
+            <mat-option *ngFor="let b of availableUpstreamIndexes" [value]="b" [disabled]="! basinIsSelectable(b, false)">
+                {{ basinDescription(b, uitextRiverUpstream) }}
+            </mat-option>
+        </mat-select>
+    </mat-form-field>
+
+    <mat-form-field>
+        <mat-select [placeholder]="uiTextDownstreambasin" [(value)]="downstreamIndex" required>
+            <mat-option *ngFor="let b of availableDownstreamIndexes" [value]="b" [disabled]="! basinIsSelectable(b, true)">
+                {{ basinDescription(b, uitextRiverDownstream) }}
+            </mat-option>
+        </mat-select>
+    </mat-form-field>
+
+    <div mat-dialog-actions [attr.align]="'end'">
+        <button mat-raised-button color="primary" [mat-dialog-close]="true" cdkFocusInitial>
+            {{ uitextCancel }}
+        </button>
+        <button mat-raised-button color="warn" (click)="onValidate()" [disabled]="! enableValidate">
+            {{ uitextValidate }}
+        </button>
+    </div>
+</form>
diff --git a/src/app/components/dialog-new-pb-cloison/dialog-new-pb-cloison.component.scss b/src/app/components/dialog-new-pb-cloison/dialog-new-pb-cloison.component.scss
new file mode 100644
index 0000000000000000000000000000000000000000..fc080522ee974e20200905fc9ed90970fd2c1fee
--- /dev/null
+++ b/src/app/components/dialog-new-pb-cloison/dialog-new-pb-cloison.component.scss
@@ -0,0 +1,4 @@
+mat-form-field {
+    display: block;
+    margin-top: 0.5em;
+}
diff --git a/src/app/components/dialog-new-pb-cloison/dialog-new-pb-cloison.component.ts b/src/app/components/dialog-new-pb-cloison/dialog-new-pb-cloison.component.ts
new file mode 100644
index 0000000000000000000000000000000000000000..9f09621154c6e73707b3fe1792d73a46a6499300
--- /dev/null
+++ b/src/app/components/dialog-new-pb-cloison/dialog-new-pb-cloison.component.ts
@@ -0,0 +1,124 @@
+import { MatDialogRef, MAT_DIALOG_DATA } from "@angular/material/dialog";
+import { Inject, Component, OnInit } from "@angular/core";
+
+import { I18nService } from "../../services/internationalisation.service";
+
+import { PbBassin } from "jalhyd";
+
+@Component({
+    selector: "dialog-new-pb-cloison",
+    templateUrl: "dialog-new-pb-cloison.component.html",
+    styleUrls: ["dialog-new-pb-cloison.component.scss"]
+})
+export class DialogNewPbCloisonComponent implements OnInit {
+
+    /** the selected upstream basin */
+    public upstreamIndex: number;
+
+    /** the selected downstream basin */
+    public downstreamIndex: number;
+
+    /** list of connectable basins, plus river upstream / downstream */
+    protected availableBasins: PbBassin[];
+
+    constructor(
+        public dialogRef: MatDialogRef<DialogNewPbCloisonComponent>,
+        private i18nService: I18nService,
+        @Inject(MAT_DIALOG_DATA) public data: any
+    ) {
+        this.availableBasins = data.basins;
+        this.upstreamIndex = 0;
+        this.downstreamIndex = 0;
+    }
+
+    public get availableUpstreamIndexes(): number[] {
+        // add river upstream as "0"
+        const ab: number[] = [ 0 ];
+        for (let i = 0; i < this.availableBasins.length; i++) {
+            ab.push(i + 1);
+        }
+        return ab;
+    }
+
+    public get availableDownstreamIndexes(): number[] {
+        const ab: number[] = [ ];
+        for (let i = 0; i < this.availableBasins.length; i++) {
+            ab.push(i + 1);
+        }
+        // add river downstream as "0"
+        ab.push(0);
+        return ab;
+    }
+
+    /**
+     * Returns true if a basin is selectable in the possible upstream basins list,
+     * considering which downstream basin is currently selected
+     * @param index index of basin
+     * @param downstream if true, inverts the test
+     */
+    public basinIsSelectable(index: number, downstream: boolean = false): boolean {
+        if (downstream) {
+            return (this.upstreamIndex === 0 || index > this.upstreamIndex);
+        } else {
+            return (this.downstreamIndex === 0 || index < this.downstreamIndex);
+        }
+    }
+
+    public basinDescription(i: number, fallback: string): string {
+        if (i === 0) {
+            return fallback;
+        } else {
+            return this.i18nService.localizeText("INFO_PB_BASSIN_N") + i;
+        }
+    }
+
+    // @TODO redundant with lists filtering, useless
+    public get enableValidate(): boolean {
+        return (
+            this.upstreamIndex !== this.downstreamIndex
+            || this.upstreamIndex === 0 // river upstream to river downstream direct connection is allowed
+        );
+    }
+
+    public onValidate(close = true) {
+        if (close) {
+            this.dialogRef.close({
+                up: this.upstreamIndex,
+                down: this.downstreamIndex,
+            });
+        }
+        return true;
+    }
+
+    public ngOnInit() {
+        // this.initVariableValues();
+    }
+
+    public get uitextSelectBasins(): string {
+        return this.i18nService.localizeText("INFO_PB_NEW_WALL_SELECT_BASINS");
+    }
+
+    public get uiTextUpstreambasin(): string {
+        return this.i18nService.localizeText("INFO_PB_NEW_WALL_UP_BASIN");
+    }
+
+    public get uiTextDownstreambasin(): string {
+        return this.i18nService.localizeText("INFO_PB_NEW_WALL_DOWN_BASIN");
+    }
+
+    public get uitextRiverUpstream(): string {
+        return this.i18nService.localizeText("INFO_LIB_AMONT");
+    }
+
+    public get uitextRiverDownstream(): string {
+        return this.i18nService.localizeText("INFO_LIB_AVAL");
+    }
+
+    public get uitextValidate() {
+      return this.i18nService.localizeText("INFO_OPTION_VALIDATE");
+    }
+
+    public get uitextCancel() {
+      return this.i18nService.localizeText("INFO_OPTION_CANCEL");
+    }
+}
diff --git a/src/app/components/field-set/field-set.component.ts b/src/app/components/field-set/field-set.component.ts
index 2d53d8e4d6fb6bb1903662bdff553322b70ec4ed..2dba32318df44ec4ab7af0328c60f2a12a30f5fb 100644
--- a/src/app/components/field-set/field-set.component.ts
+++ b/src/app/components/field-set/field-set.component.ts
@@ -221,7 +221,7 @@ export class FieldSetComponent implements DoCheck {
 
     /**
      * calcul de la validité de tous les ParamFieldLineComponent et tous les
-     * SelectModelFieldLineComponent de la vue
+     * SelectFieldLineComponent de la vue
      */
     private updateValidity() {
         this._isValid = false;
diff --git a/src/app/components/fieldset-container/fieldset-container.component.ts b/src/app/components/fieldset-container/fieldset-container.component.ts
index 65bdb84ebfe9ffb7d4d42053cfd5f58e5ca3ab67..45b87262e5329b8039177d1b4a22fe2014f720b5 100644
--- a/src/app/components/fieldset-container/fieldset-container.component.ts
+++ b/src/app/components/fieldset-container/fieldset-container.component.ts
@@ -126,7 +126,7 @@ export class FieldsetContainerComponent implements DoCheck, AfterViewInit {
     private updateValidity() {
         this._isValid = false;
 
-        if (this._fieldsetComponents !== undefined && this._fieldsetComponents.length > 0) {
+        if (this._fieldsetComponents?.length > 0) {
             this._isValid = this._fieldsetComponents.reduce(
                 // callback
                 (
diff --git a/src/app/components/fixedvar-results/fixed-results.component.html b/src/app/components/fixedvar-results/fixed-results.component.html
index d9bca96253f0a62db118c20b9cf88b8dd74cd0e9..cfd30782d6f3e4b4ce546895e691c61207d36e35 100644
--- a/src/app/components/fixedvar-results/fixed-results.component.html
+++ b/src/app/components/fixedvar-results/fixed-results.component.html
@@ -1,11 +1,9 @@
 <div class="fixed-results-container" *ngIf="hasFixedParameters">
-
     <div class="fixed-results-buttons">
         <button mat-icon-button (click)="exportAsSpreadsheet()" [title]="uitextExportAsSpreadsheet">
             <mat-icon color="primary">file_download</mat-icon>
         </button>
     </div>
-
     <!-- table des résultats fixés -->
     <div class="fixed-results-inner-container" #tableContainer>
         <table mat-table [dataSource]="dataSet" [trackBy]="tbIndex">
diff --git a/src/app/components/fixedvar-results/fixed-results.component.ts b/src/app/components/fixedvar-results/fixed-results.component.ts
index 32660b36862b5b0c3650fc5b133a0be1535743fd..090c1829dd5427bc02aa85c4551c4de3221844c0 100644
--- a/src/app/components/fixedvar-results/fixed-results.component.ts
+++ b/src/app/components/fixedvar-results/fixed-results.component.ts
@@ -1,14 +1,13 @@
-import { Component, ViewChild, ElementRef } from "@angular/core";
+import { Component, ViewChild, ElementRef, Input } from "@angular/core";
 
 import { FixedResults } from "../../results/fixed-results";
-import { NgParameter } from "../../formulaire/elements/ngparam";
-import { CalculatorResults } from "../../results/calculator-results";
 import { I18nService } from "../../services/internationalisation.service";
 import { FormulaireService } from "../../services/formulaire.service";
 import { ResultsComponentDirective } from "./results.component";
 import { AppComponent } from "../../app.component";
+import { NgParameter } from "../../formulaire/elements/ngparam";
 
-import { capitalize } from "jalhyd";
+import { capitalize, Result, ResultElement } from "jalhyd";
 
 import { sprintf } from "sprintf-js";
 
@@ -20,8 +19,9 @@ import { sprintf } from "sprintf-js";
     ]
 })
 export class FixedResultsComponent extends ResultsComponentDirective {
+
     /** résultats non mis en forme */
-    private _fixedResults: FixedResults;
+    protected _fixedResults: FixedResults;
 
     @ViewChild("tableContainer")
     table: ElementRef;
@@ -35,6 +35,7 @@ export class FixedResultsComponent extends ResultsComponentDirective {
         super();
     }
 
+    @Input()
     public set results(r: FixedResults) {
         this._fixedResults = r;
     }
@@ -63,10 +64,6 @@ export class FixedResultsComponent extends ResultsComponentDirective {
         return this._fixedResults && this._fixedResults.fixedParameters.length > 0;
     }
 
-    public formattedLabel(p: NgParameter): string {
-        return CalculatorResults.paramLabel(p, false);
-    }
-
     /**
      * Returns a set of parameters and results for mat-table
      */
@@ -90,6 +87,30 @@ export class FixedResultsComponent extends ResultsComponentDirective {
     protected buildCustomOrderedDataset() {
         const data = [];
         let resultFound: boolean;
+        for (const symbol of this._fixedResults.variablesOrder) {
+
+            // is it a fixed parameter ?
+            for (const fp of this.fixedParams) {
+                if (fp.symbol === symbol) {
+                    let label = this.formattedLabel(fp);
+                    const nub = fp.paramDefinition.parentNub;
+                    // add child type and position before label
+                    if (nub && nub.parent && nub.parent.childrenType) {
+                        const pos = nub.findPositionInParent();
+                        // label = this.intlService.localizeText("INFO_OUVRAGE") + " n°" + (pos + 1) + ": " + label;
+                        const cn = capitalize(this.intlService.childName(nub.parent));
+                        label = sprintf(this.intlService.localizeText("INFO_STUFF_N"), cn)
+                            + (pos + 1) + ": " + label;
+                    }
+                    label += this._fixedResults.getHelpLink(symbol);
+                    data.push({
+                        label: label,
+                        value: this.getFixedParamValue(fp),
+                        isCalcResult: false // for CSS
+                    });
+                }
+            }
+        }
 
         for (const symbol of this._fixedResults.variablesOrder) {
             resultFound = false;
@@ -98,23 +119,23 @@ export class FixedResultsComponent extends ResultsComponentDirective {
             if (
                 res
                 && res.resultElements.length > 0
-                && res.resultElement
-                && res.resultElement.count() > 0
+                && this.getResultElement(res)
+                && this.getResultElement(res).count() > 0
             ) {
                 const sn = this._fixedResults.result.sourceNub;
                 let found = false;
 
                 // 2.1 all results
-                for (const k of res.resultElement.keys) {
+                for (const k of this.getResultElement(res).keys) {
                     if (k === symbol) {
                         found = true;
-                        const er: number = res.resultElement.getValue(k);
+                        const er: number = this.getResultElement(res).getValue(k);
                         // calculator type for translation
                         let ct = sn.calcType;
                         if (sn.parent) {
                             ct = sn.parent.calcType;
                         }
-                        let unit;
+                        let unit: string;
                         // is k the calculated parameter ? If so, extract its unit
                         try {
                             const p = res.sourceNub.getParameter(k);
@@ -137,10 +158,10 @@ export class FixedResultsComponent extends ResultsComponentDirective {
                 if (! found) {
                     for (const c of sn.getChildren()) {
                         if (c.result) {
-                            for (const k of c.result.resultElement.keys) {
+                            for (const k of this.getResultElement(c.result).keys) {
                                 if (k === symbol) {
                                     resultFound = true;
-                                    const er: number = c.result.resultElement.getValue(k);
+                                    const er: number = this.getResultElement(c.result).getValue(k);
                                     // calculator type for translation
                                     let ct = sn.calcType;
                                     if (sn.parent) {
@@ -210,7 +231,7 @@ export class FixedResultsComponent extends ResultsComponentDirective {
             label += this._fixedResults.getHelpLink(fp.symbol);
             data.push({
                 label: label,
-                value: this.formattedValue(fp),
+                value: this.getFixedParamValue(fp),
                 isCalcResult: false // for CSS
             });
         }
@@ -219,20 +240,20 @@ export class FixedResultsComponent extends ResultsComponentDirective {
         if (
             res
             && res.resultElements.length > 0
-            && res.resultElement
-            && res.resultElement.count() > 0
+            && this.getResultElement(res)
+            && this.getResultElement(res).count() > 0
         ) {
             const sn = this._fixedResults.result.sourceNub;
 
             // 2.1 all results
-            for (const k of res.resultElement.keys) {
-                const er: number = res.resultElement.getValue(k);
+            for (const k of this.getResultElement(res).keys) {
+                const er: number = this.getResultElement(res).getValue(k);
                 // calculator type for translation
                 let ct = sn.calcType;
                 if (sn.parent) {
                     ct = sn.parent.calcType;
                 }
-                let unit;
+                let unit: string;
                 // is k the calculated parameter ? If so, extract its unit
                 try {
                     const p = res.sourceNub.getParameter(k);
@@ -252,8 +273,8 @@ export class FixedResultsComponent extends ResultsComponentDirective {
             // 2.2. children results
             for (const c of sn.getChildren()) {
                 if (c.result) {
-                    for (const k of c.result.resultElement.keys) {
-                        const er: number = c.result.resultElement.getValue(k);
+                    for (const k of this.getResultElement(c.result).keys) {
+                        const er: number = this.getResultElement(c.result).getValue(k);
                         // calculator type for translation
                         let ct = sn.calcType;
                         if (sn.parent) {
@@ -276,6 +297,22 @@ export class FixedResultsComponent extends ResultsComponentDirective {
         return data;
     }
 
+    /**
+     * Retourne la valeur du paramètre fixe; redéfini
+     * dans PbCloisonResultsComponent notamment
+     */
+    protected getFixedParamValue(fp: NgParameter): string {
+        return this.formattedValue(fp);
+    }
+
+    /**
+     * Retourne l'élément de résultat en cours pour le résultat donné;
+     * redéfini dans PbCloisonResultsComponent notamment
+     */
+    protected getResultElement(r: Result): ResultElement {
+        return r.resultElement;
+    }
+
     public exportAsSpreadsheet() {
         AppComponent.exportAsSpreadsheet(this.table.nativeElement, true);
     }
diff --git a/src/app/components/fixedvar-results/fixedvar-results.component.html b/src/app/components/fixedvar-results/fixedvar-results.component.html
index 7676b026859cc72cbef157cf5b94edaa9a57d1d4..271a255087c96d893af18ff4988ba741125d3e68 100644
--- a/src/app/components/fixedvar-results/fixedvar-results.component.html
+++ b/src/app/components/fixedvar-results/fixedvar-results.component.html
@@ -1,8 +1,8 @@
 <div class="container">
     <!-- journal -->
-    <log></log>
+    <log [log]=mergedGlobalLogs></log>
 
-    <results-chart [hidden]="! showVarResultsChart"></results-chart>
+    <results-chart [hidden]="! showVarResultsChart" [results]=varResults [resultData]=varResults?.result></results-chart>
 
     <div>
         <!-- table des résultats fixés -->
diff --git a/src/app/components/fixedvar-results/fixedvar-results.component.ts b/src/app/components/fixedvar-results/fixedvar-results.component.ts
index 84d2cda255813c5d5c3e4a76b7938931af3c525f..d93bcc55c48d40acd98a23d556a7ce1b8a838c69 100644
--- a/src/app/components/fixedvar-results/fixedvar-results.component.ts
+++ b/src/app/components/fixedvar-results/fixedvar-results.component.ts
@@ -1,14 +1,9 @@
-import { Component, ViewChild, DoCheck } from "@angular/core";
+import { Component, Input } from "@angular/core";
 
-import { LogComponent } from "../../components/log/log.component";
 import { FixedResults } from "../../results/fixed-results";
 import { VarResults } from "../../results/var-results";
-import { ResultsChartComponent } from "../results-chart/results-chart.component";
 import { CalculatorResults } from "../../results/calculator-results";
 import { Result, cLog } from "jalhyd";
-import { NgParameter } from "../../formulaire/elements/ngparam";
-import { FixedResultsComponent } from "./fixed-results.component";
-import { VarResultsComponent } from "./var-results.component";
 import { ResultsComponentDirective } from "./results.component";
 
 @Component({
@@ -18,36 +13,14 @@ import { ResultsComponentDirective } from "./results.component";
         "./fixedvar-results.component.scss"
     ]
 })
-export class FixedVarResultsComponent extends ResultsComponentDirective implements DoCheck {
+export class FixedVarResultsComponent extends ResultsComponentDirective {
     /**
      * résultats non mis en forme
      */
     protected _fixedResults: FixedResults;
     protected _varResults: VarResults;
 
-    /**
-     * true si les résultats doiventt être remis à jour
-     */
-    protected _doUpdate = false;
-
-    @ViewChild(FixedResultsComponent)
-    private fixedResultsComponent: FixedResultsComponent;
-
-    @ViewChild(VarResultsComponent)
-    private varResultsComponent: VarResultsComponent;
-
-    /**
-     * composant journal
-     */
-    @ViewChild(LogComponent)
-    private logComponent: LogComponent;
-
-    /**
-     * graphique dans le cas d'un paramètre à varier
-     */
-    @ViewChild(ResultsChartComponent)
-    private resultsChartComponent: ResultsChartComponent;
-
+    @Input()
     public set results(rs: CalculatorResults[]) {
         this._fixedResults = undefined;
         this._varResults = undefined;
@@ -60,40 +33,6 @@ export class FixedVarResultsComponent extends ResultsComponentDirective implemen
                 }
             }
         }
-        this.updateView();
-    }
-
-    public updateView() {
-        if (this.logComponent) {
-            this.logComponent.log = undefined;
-        }
-        if (this.fixedResultsComponent) {
-            this.fixedResultsComponent.results = undefined;
-        }
-        if (this.varResultsComponent) {
-            this.varResultsComponent.results = undefined;
-        }
-        if (this.resultsChartComponent) {
-            this.resultsChartComponent.results = undefined;
-        }
-
-        // set _doUpdate flag so that results are rebuilt on the next Angular display cycle
-        this._doUpdate = false;
-        if (this._fixedResults !== undefined) {
-            this._doUpdate = this._fixedResults.hasResults || this._fixedResults.hasLog;
-        }
-        if (this._varResults !== undefined) {
-            this._doUpdate = this._doUpdate || this._varResults.hasResults || this._varResults.hasLog;
-        }
-    }
-
-    public ngDoCheck() {
-        if (this._doUpdate) {
-            // clodo trick @see nghyd#308
-            setTimeout(() => {
-                this._doUpdate = !this.updateResults();
-            }, 10);
-        }
     }
 
     private mergeLog(result: Result, log: cLog) {
@@ -106,7 +45,7 @@ export class FixedVarResultsComponent extends ResultsComponentDirective implemen
         }
     }
 
-    private get mergedGlobalLogs(): cLog {
+    public get mergedGlobalLogs(): cLog {
         const res = new cLog();
         if (this._fixedResults) {
             this.mergeLog(this._fixedResults.result, res);
@@ -117,42 +56,6 @@ export class FixedVarResultsComponent extends ResultsComponentDirective implemen
         return res;
     }
 
-    /**
-     * met à jour l'affichage des résultats
-     * @returns true si les résultats ont pu être mis à jour
-     */
-    protected updateResults() {
-        const fixedUpdated = this._fixedResults !== undefined && this.fixedResultsComponent !== undefined;
-        if (fixedUpdated) {
-            this.fixedResultsComponent.results = this._fixedResults;
-        }
-
-        let graphUpdated: boolean;
-        let varUpdated: boolean;
-        if (this._varResults && this._varResults.hasResults) {
-            varUpdated = this.varResultsComponent !== undefined;
-            if (varUpdated) {
-                this.varResultsComponent.results = this._varResults;
-            }
-
-            graphUpdated = this.resultsChartComponent !== undefined;
-            if (graphUpdated) {
-                this.resultsChartComponent.results = this._varResults;
-                this.resultsChartComponent.updateView();
-            }
-        } else {
-            varUpdated = true;
-            graphUpdated = true;
-        }
-
-        const logUpdated = this.logComponent !== undefined;
-        if (logUpdated) {
-            this.logComponent.log = this.mergedGlobalLogs;
-        }
-
-        return fixedUpdated && varUpdated && logUpdated && graphUpdated;
-    }
-
     /**
      * affichage de la table des résultats fixés
      */
@@ -171,7 +74,7 @@ export class FixedVarResultsComponent extends ResultsComponentDirective implemen
      * affichage du graphique des résultats variés
      */
     public get showVarResultsChart(): boolean {
-        return this._varResults && this._varResults.hasPlottableResults;
+        return this._varResults && this._varResults.hasPlottableResults();
     }
 
     public getFixedResultClass(i: number) {
@@ -187,15 +90,11 @@ export class FixedVarResultsComponent extends ResultsComponentDirective implemen
         return this._fixedResults;
     }
 
-    public formattedLabel(p: NgParameter): string {
-        return CalculatorResults.paramLabel(p, false);
-    }
-
     public get varResults() {
         return this._varResults;
     }
 
     public get hasResults(): boolean {
-        return this._fixedResults !== undefined && this._fixedResults.hasResults;
+        return this._fixedResults?.hasResults;
     }
 }
diff --git a/src/app/components/fixedvar-results/results.component.ts b/src/app/components/fixedvar-results/results.component.ts
index 8ba53061af029d00787e37c77061108fd1f87830..eda93d7c37dfbb6dd71999e6dc90fbdccb9ff42f 100644
--- a/src/app/components/fixedvar-results/results.component.ts
+++ b/src/app/components/fixedvar-results/results.component.ts
@@ -4,6 +4,8 @@ import { Screenfull } from "screenfull"; // @see https://github.com/sindresorhus
 import { NgParameter } from "../../formulaire/elements/ngparam";
 import { ServiceFactory } from "../../services/service-factory";
 import { fv } from "../../util";
+import { CalculatorResults } from "../../results/calculator-results";
+
 import { Directive } from "@angular/core";
 
 /**
@@ -23,21 +25,19 @@ export class ResultsComponentDirective {
         }
     }
 
-    public setFullscreen(element): Promise<void> {
+    public async setFullscreen(element): Promise<void> {
         const sf = <Screenfull>screenfull;
         if (sf.isEnabled) {
-            return sf.request(element).then(() => {
-                this.fullscreenChange(true);
-            });
+            await sf.request(element);
+            this.fullscreenChange(true);
         }
     }
 
-    public exitFullscreen(): Promise<void> {
+    public async exitFullscreen(): Promise<void> {
         const sf = <Screenfull>screenfull;
         if (sf.isEnabled) {
-            return sf.exit().then(() => {
-                this.fullscreenChange(false);
-            });
+            await sf.exit();
+            this.fullscreenChange(false);
         }
     }
 
@@ -82,6 +82,10 @@ export class ResultsComponentDirective {
         ];
     }
 
+    public formattedLabel(p: NgParameter): string {
+        return CalculatorResults.paramLabel(p, false);
+    }
+
     /**
      * Formats (rounds) the given number (or the value of the given parameter) with the
      * number of decimals specified in app preferences; if given number is too low and
diff --git a/src/app/components/fixedvar-results/var-results.component.ts b/src/app/components/fixedvar-results/var-results.component.ts
index b5a66d7742b80b81043d9c725441be162ccaeed1..7493401d2776c1760fbe9c616232aa62ceefecea 100644
--- a/src/app/components/fixedvar-results/var-results.component.ts
+++ b/src/app/components/fixedvar-results/var-results.component.ts
@@ -1,4 +1,4 @@
-import { Component, ViewChild, ElementRef } from "@angular/core";
+import { Component, ViewChild, ElementRef, Input } from "@angular/core";
 
 import { MatDialog } from "@angular/material/dialog";
 
@@ -8,7 +8,7 @@ import { I18nService } from "../../services/internationalisation.service";
 import { ResultsComponentDirective } from "./results.component";
 import { DialogLogEntriesDetailsComponent } from "../dialog-log-entries-details/dialog-log-entries-details.component";
 import { AppComponent } from "../../app.component";
-import { longestVarNgParam } from "../../../app/util";
+import { longestVarParam } from "../../../app/util";
 
 @Component({
     selector: "var-results",
@@ -45,6 +45,7 @@ export class VarResultsComponent extends ResultsComponentDirective {
     }
 
     /** Refreshes results and builds the dataset */
+    @Input()
     public set results(r: VarResults) {
         this._varResults = r;
         this._results = [];
@@ -68,12 +69,12 @@ export class VarResultsComponent extends ResultsComponentDirective {
             // C. pre-extract variable parameters values
             const varValues = [];
             // find longest list
-            const lvp = longestVarNgParam(this._varResults.variatedParameters);
+            const lvp = longestVarParam(this._varResults.variatedParameters);
             this.size = lvp.size;
             // get extended values lists for each variable parameter
             for (const v of this._varResults.variatedParameters) {
                 const vv = [];
-                const iter = v.getExtendedValuesIterator(this.size);
+                const iter = v.param.getExtendedValuesIterator(this.size);
                 while (iter.hasNext) {
                     const nv = iter.next();
                     vv.push(this.formattedValue(nv.value));
diff --git a/src/app/components/generic-calculator/calc-name.component.ts b/src/app/components/generic-calculator/calc-name.component.ts
index a07f51b0c4732537fd17ff912110d20a839f0baf..c1cc4bb7e40a29744a1726e52cc3cf2fd0dac374 100644
--- a/src/app/components/generic-calculator/calc-name.component.ts
+++ b/src/app/components/generic-calculator/calc-name.component.ts
@@ -1,4 +1,4 @@
-import { Component } from "@angular/core";
+import { Component, Input } from "@angular/core";
 import { GenericInputComponentDirective } from "../generic-input/generic-input.component";
 import { FormulaireDefinition } from "../../formulaire/definition/form-definition";
 import { I18nService } from "../../services/internationalisation.service";
@@ -20,6 +20,11 @@ export class CalculatorNameComponent extends GenericInputComponentDirective {
         super(null, intlService, appSetupService);
     }
 
+    @Input()
+    public set model(v: any) {
+        super.model = v;
+    }
+
     /**
      * formulaire géré
      */
diff --git a/src/app/components/generic-calculator/calculator.component.html b/src/app/components/generic-calculator/calculator.component.html
index f5ccefc0fd6f60664002184281dd7510c3ac9c52..7b085815a6bade8c59f4beff28627c292043d9fa 100644
--- a/src/app/components/generic-calculator/calculator.component.html
+++ b/src/app/components/generic-calculator/calculator.component.html
@@ -39,14 +39,25 @@
 
     </mat-card-header>
 
-    <quicknav [fxHide.gt-sm]="! isWide" [items]="quicknavItems" [currentItem]="'input'" [align]="'left'"></quicknav>
+    <quicknav *ngIf="! isPB" [fxHide.gt-sm]="! isWide" [items]="quicknavItems" [currentItem]="'input'" [align]="'left'"></quicknav>
+
+    <div *ngIf="isPB" class="fake-quicknav" id="pb-data-results-selector">
+        <div class="drs-row">
+            <div class="drs-item" [class.current]="showPBInputData">
+                <a (click)="showPBInputData = true;">{{ uitextInputData }}</a>
+            </div>
+            <div class="drs-item" [class.current]="! showPBInputData">
+                <a (click)="showPBInputData = false;">{{ uitextResults }}</a>
+            </div>
+        </div>
+    </div>
 
     <form>
 
         <mat-card-content>
 
             <!-- nom du module de calcul -->
-            <calc-name id="calculator-name" [title]="uitextCalculatorName"></calc-name>
+            <calc-name id="calculator-name" [model]="formulaire" [title]="uitextCalculatorName"></calc-name>
 
             <button mat-raised-button type="button" color="accent" id="load-predefined-espece" *ngIf="isEspece"
                 (click)="loadPredefinedEspece()" [title]="uitextLoadPredefinedEspece">
@@ -62,22 +73,69 @@
                     [fxFlex.lt-md]="isWide ? '1 0 auto' : '1 0 500px'"
                     [fxFlex.lt-sm]="isWide ? '1 0 auto' : '1 0 300px'">
 
-                    <ng-template ngFor let-fe [ngForOf]="formElements">
-                        <field-set *ngIf="isFieldset(fe)" [style.display]="getElementStyleDisplay(fe.id)" [fieldSet]=fe
-                            (radio)=onRadioClick($event) (validChange)=onElementValid()
-                            (inputChange)=onInputChange($event) (tabPressed)="onTabPressed($event)">
-                        </field-set>
-
-                        <fieldset-container *ngIf="isFieldsetContainer(fe)"
-                            [style.display]="getElementStyleDisplay(fe.id)" [_container]=fe (radio)=onRadioClick($event)
-                            (validChange)=onElementValid() (inputChange)=onInputChange($event)
-                            (tabPressed)="onTabPressed($event)">
-                        </fieldset-container>
-
-                        <pab-table *ngIf="isPabTable(fe)" [pabTable]=fe (radio)=onRadioClick($event)
-                            (validChange)=onElementValid() (inputChange)=onInputChange($event)>
-                        </pab-table>
-                    </ng-template>
+                    <div id="calc-card-field-sets-container" [fxLayout]="isPB ? 'row wrap' : 'column'">
+
+                        <!-- PB specific template -->
+                        <div *ngIf="isPB" id="pb-schema-container"
+                            fxFlex.gt-sm="1 0 400px"
+                            fxFlex.lt-md="1 0 500px"
+                            fxFlex.lt-sm="1 0 300px">
+
+                            <!-- without this loop, injecting formElements[0] in <pb-schema> makes it not 
+                                trigger lifecycle hooks when switching from a PreBarrage module to another… -->
+                            <ng-template ngFor let-fe [ngForOf]="formElements">
+                                <pb-schema *ngIf="isPbSchema(fe)" [pbSchema]="fe" (radio)=onRadioClick($event)
+                                    (validChange)=onElementValid() (nodeSelected)="onPBNodeSelected($event)">
+                                </pb-schema>
+                            </ng-template>
+
+                            <div fxHide.sm fxFlex.gt-sm="0 0 16px"></div>
+                        </div>
+                        <!-- PB specific template (2) -->
+                        <div *ngIf="isPB" id="pb-form-container" [hidden]="! showPBInputData"
+                            fxFlex.gt-sm="1 0 400px"
+                            fxFlex.lt-md="1 0 500px"
+                            fxFlex.lt-sm="1 0 300px">
+
+                            <ng-template ngFor let-fe [ngForOf]="formElements">
+                                <field-set *ngIf="isFieldset(fe)"
+                                    [style.display]="getElementStyleDisplay(fe.id)" [fieldSet]=fe
+                                    (radio)=onRadioClick($event) (validChange)=onElementValid() (inputChange)=onInputChange($event)
+                                    (tabPressed)="onTabPressed($event)">
+                                </field-set>
+
+                                <fieldset-container *ngIf="isFieldsetContainer(fe)"
+                                    [style.display]="getElementStyleDisplay(fe.id)" [_container]=fe
+                                    (radio)=onRadioClick($event) (validChange)=onElementValid() (inputChange)=onInputChange($event)
+                                    (tabPressed)="onTabPressed($event)">
+                                </fieldset-container>
+                            </ng-template>
+                        </div>
+
+                        <!-- generic template -->
+                        <ng-template *ngIf="! isPB" ngFor let-fe [ngForOf]="formElements">
+                            <field-set *ngIf="isFieldset(fe)"
+                                [style.display]="getElementStyleDisplay(fe.id)" [fieldSet]=fe
+                                (radio)=onRadioClick($event) (validChange)=onElementValid() (inputChange)=onInputChange($event)
+                                (tabPressed)="onTabPressed($event)"
+                                fxFlex.gt-sm="1 0 auto"
+                                fxFlex.lt-md="1 0 auto"
+                                fxFlex.lt-sm="1 0 auto">
+                            </field-set>
+
+                            <fieldset-container *ngIf="isFieldsetContainer(fe)"
+                                [style.display]="getElementStyleDisplay(fe.id)" [_container]=fe
+                                (radio)=onRadioClick($event) (validChange)=onElementValid() (inputChange)=onInputChange($event)
+                                (tabPressed)="onTabPressed($event)"
+                                fxFlex="1 0 auto">
+                            </fieldset-container>
+
+                            <pab-table *ngIf="isPabTable(fe)" [pabTable]=fe (radio)=onRadioClick($event)
+                                (validChange)=onElementValid() (inputChange)=onInputChange($event)
+                                fxFlex="1 0 auto">
+                            </pab-table>
+                        </ng-template>
+                    </div>
 
                     <mat-card-actions>
                         <!-- bouton calculer -->
@@ -90,17 +148,17 @@
                 </mat-card>
 
                 <!-- résultats -->
-                <mat-card id="calc-card-results" [hidden]="calculateDisabledPermanently" [class.pab-results]="isWide"
-                    [fxFlex.gt-sm]="isWide ? '1 0 auto' : '1 0 400px'"
-                    [fxFlex.lt-md]="isWide ? '1 0 auto' : '1 0 500px'"
-                    [fxFlex.lt-sm]="isWide ? '1 0 auto' : '1 0 300px'">
+                <mat-card id="calc-card-results"
+                  [class.pab-results]="isWide" [hidden]="isPB && showPBInputData"
+                  [fxFlex.gt-sm]="isWide ? '1 0 auto' : '1 0 400px'"
+                  [fxFlex.lt-md]="isWide ? '1 0 auto' : '1 0 500px'"
+                  [fxFlex.lt-sm]="isWide ? '1 0 auto' : '1 0 300px'">
 
                     <div id="fake-results-anchor"></div>
 
-                    <quicknav [ngClass.lt-xs]="'extraSmall'" [fxHide.gt-sm]="! isWide" [items]="quicknavItems"
-                        [currentItem]="'results'" [align]="'left'"></quicknav>
+                    <quicknav *ngIf="! isPB" [ngClass.lt-xs]="'extraSmall'" [fxHide.gt-sm]="! isWide" [items]="quicknavItems" [currentItem]="'results'" [align]="'left'"></quicknav>
 
-                    <mat-card-header *ngIf="! isWide" [fxHide.lt-md]="! isWide">
+                    <mat-card-header *ngIf="! isWide" [fxHide.lt-md]="! isPB && ! isWide">
                         <mat-card-title>
                             <h1 [innerHTML]="uitextResultsTitle"></h1>
                         </mat-card-title>
@@ -134,7 +192,7 @@
                     </button>
 
                     <mat-card-content>
-                        <calc-results id="resultsComp" (afterViewChecked)="onCalcResultsViewChecked()"></calc-results>
+                        <calc-results id="resultsComp" [formulaire]="formulaire" (afterViewChecked)="onCalcResultsViewChecked()"></calc-results>
                     </mat-card-content>
                 </mat-card>
 
diff --git a/src/app/components/generic-calculator/calculator.component.scss b/src/app/components/generic-calculator/calculator.component.scss
index 1aa9e9e26cef4abd09fc8f0a9594811c82e64d36..635d9782ee63da029e6e9dc4023a9cfbc2ff18b8 100644
--- a/src/app/components/generic-calculator/calculator.component.scss
+++ b/src/app/components/generic-calculator/calculator.component.scss
@@ -26,6 +26,63 @@
     margin-bottom: 1em;
 }
 
+#pb-schema-container {
+    display: block;
+}
+
+#pb-form-container {
+    display: block;
+}
+
+/** copy of quicknav style */
+#pb-data-results-selector {
+
+    @import "../../../theme.scss";
+
+    display: block;
+    margin-bottom: .5em;
+    width: 100%;
+
+    .drs-item {
+        display: inline;
+        padding: 0 .5em 3px .5em;
+        text-transform: uppercase;
+        font-size: 18px;
+        font-weight: normal;
+
+        &.current {
+            @extend .border-accent;
+            border-bottom-width: 2px;
+            border-bottom-style: solid;
+            font-size: 24px;
+
+            a {
+                // font-weight: bold;
+                @extend .color-accent;
+            }
+        }
+
+        a {
+            cursor: pointer;
+            color: #cbcbcb;
+            &:focus {
+                outline: none;
+            }
+            &:hover {
+                color: #707070;
+            }
+        }
+    }
+
+    .drs-item:first-of-type {
+        padding-left: 0;
+    }
+
+    .drs-item:last-of-type {
+        padding-right: 0;
+    }
+}
+
 mat-card {
     margin-bottom: 2em;
 
diff --git a/src/app/components/generic-calculator/calculator.component.ts b/src/app/components/generic-calculator/calculator.component.ts
index b662a5000d25250ee124089a9a93d715453b9ad5..33efee5069f6ab5ecadf16ebb0c12d3fa3954de0 100644
--- a/src/app/components/generic-calculator/calculator.component.ts
+++ b/src/app/components/generic-calculator/calculator.component.ts
@@ -19,7 +19,8 @@ import {
     Par,
     ParSimulationParams,
     ParSimulation,
-    Espece
+    Espece,
+    VariatedDetails
 } from "jalhyd";
 
 import { generateValuesCombination } from "../../util";
@@ -30,10 +31,8 @@ import { ApplicationSetupService } from "../../services/app-setup.service";
 import { I18nService } from "../../services/internationalisation.service";
 import { FieldSet } from "../../formulaire/elements/fieldset";
 import { FormulaireDefinition } from "../../formulaire/definition/form-definition";
-import { CalculatorResultsComponent } from "../../components/calculator-results/calculator-results.component";
 import { Subscription } from "rxjs";
 import { FieldSetComponent } from "../field-set/field-set.component";
-import { CalculatorNameComponent } from "./calc-name.component";
 import { FormulaireElement } from "../../formulaire/elements/formulaire-element";
 import { FieldsetContainer } from "../../formulaire/elements/fieldset-container";
 import { FieldsetContainerComponent } from "../fieldset-container/fieldset-container.component";
@@ -45,8 +44,10 @@ import { DialogGeneratePARSimulationComponent } from "../dialog-generate-par-sim
 import { DialogLoadPredefinedEspeceComponent } from "../dialog-load-predefined-espece/dialog-load-predefined-espece.component";
 import { PabTable } from "../../formulaire/elements/pab-table";
 import { MultiDimensionResults } from "../../results/multidimension-results";
-import { NgParameter } from "../../formulaire/elements/ngparam";
 import { FormulaireFixedVar } from "../../formulaire/definition/form-fixedvar";
+import { PbSchema } from "../../formulaire/elements/pb-schema";
+import { PbSchemaComponent } from "../pb-schema/pb-schema.component";
+import { FormulairePrebarrage } from "../../formulaire/definition/form-prebarrage";
 
 import { HotkeysService, Hotkey } from "angular2-hotkeys";
 
@@ -77,16 +78,10 @@ export class GenericCalculatorComponent implements OnInit, DoCheck, AfterViewChe
     private _pabTableComponent: PabTableComponent;
 
     /**
-     * composant d'affichage des résultats
+     * PbSchemaComponent if any
      */
-    @ViewChild(CalculatorResultsComponent, { static: true })
-    private resultsComponent: CalculatorResultsComponent;
-
-    /**
-     * composant "nom du module de calcul"
-     */
-    @ViewChild(CalculatorNameComponent, { static: true })
-    private _calculatorNameComponent: CalculatorNameComponent;
+    @ViewChild(PbSchemaComponent)
+    private _pbSchemaComponent: PbSchemaComponent;
 
     /**
      * formulaire affiché
@@ -124,6 +119,21 @@ export class GenericCalculatorComponent implements OnInit, DoCheck, AfterViewChe
         }
     }
 
+    /** For PreBarrage only: if true, show input data in the right panel, else show results */
+    public get showPBInputData(): boolean {
+        if (this.isPB) {
+            return (this._formulaire as FormulairePrebarrage).showInputData;
+        } else {
+            return false; // whatever, should never happen
+        }
+    }
+
+    public set showPBInputData(v: boolean) {
+        if (this.isPB) {
+            (this._formulaire as FormulairePrebarrage).showInputData = v;
+        } // else do nothing, should never happen
+    }
+
     constructor(
         @Inject(forwardRef(() => AppComponent)) private appComponent: AppComponent,
         private route: ActivatedRoute,
@@ -154,6 +164,10 @@ export class GenericCalculatorComponent implements OnInit, DoCheck, AfterViewChe
         }, this)));
     }
 
+    public get formulaire(): FormulaireDefinition {
+        return this._formulaire;
+    }
+
     public get formElements(): FormulaireElement[] {
         if (this._formulaire === undefined) {
             return [];
@@ -168,24 +182,26 @@ export class GenericCalculatorComponent implements OnInit, DoCheck, AfterViewChe
     /**
      * détermine si un FormulaireElement est du type FieldSet
      */
+    /** détermine si un FormulaireElement est du type FieldSet */
     public isFieldset(fe: any): boolean {
         return fe instanceof FieldSet;
     }
 
-    /**
-     * détermine si un FormulaireElement est du type FieldsetContainer
-     */
+    /** détermine si un FormulaireElement est du type FieldsetContainer */
     public isFieldsetContainer(fe: any): boolean {
         return fe instanceof FieldsetContainer;
     }
 
-    /**
-     * détermine si un FormulaireElement est du type PabTable
-     */
+    /** détermine si un FormulaireElement est du type PabTable */
     public isPabTable(fe: any): boolean {
         return fe instanceof PabTable;
     }
 
+    /** détermine si un FormulaireElement est du type PbSchema */
+    public isPbSchema(fe: any): boolean {
+        return fe instanceof PbSchema;
+    }
+
     public get hasForm() {
         return this._formulaire !== undefined;
     }
@@ -259,6 +275,14 @@ export class GenericCalculatorComponent implements OnInit, DoCheck, AfterViewChe
         return this.intlService.localizeText("INFO_CALCULATOR_USED_BY");
     }
 
+    public get uitextInputData() {
+        return this.intlService.localizeText("INFO_QUICKNAV_INPUT");
+    }
+
+    public get uitextResults() {
+        return this.intlService.localizeText("INFO_QUICKNAV_RESULTS");
+    }
+
     public get quicknavItems() {
         const elts = [ "input", "results" ];
         if (this.isWide && this.hasResults) {
@@ -352,10 +376,7 @@ export class GenericCalculatorComponent implements OnInit, DoCheck, AfterViewChe
         this._formulaire.resetResults([]);
         this.appComponent.showProgressBar = true;
         this._computeClicked = true;
-        // send resetForm to clear log
-        this._formulaire.notifyObservers({
-            "action": "resetForm",
-        }, this._formulaire);
+        this.showPBInputData = false;
         // calculate module
         setTimeout(() => {
             this._formulaire.doCompute();
@@ -407,22 +428,6 @@ export class GenericCalculatorComponent implements OnInit, DoCheck, AfterViewChe
         }
     }
 
-    private setForm(f: FormulaireDefinition) {
-        if (this._formulaire !== undefined) {
-            this._formulaire.removeObserver(this);
-        }
-        this._formulaire = f;
-        if (this._formulaire !== undefined) {
-            this._formulaire.addObserver(this);
-        }
-    }
-
-    private updateFormulaireResults(uid: string) {
-        if (this._formulaire.uid === uid) {
-            this.resultsComponent.updateView();
-        }
-    }
-
     // interface Observer
 
     update(sender: any, data: any): void {
@@ -430,22 +435,9 @@ export class GenericCalculatorComponent implements OnInit, DoCheck, AfterViewChe
             switch (data["action"]) {
                 case "currentFormChanged":
                     const uid: string = data["formId"];
-                    this.setForm(this.formulaireService.getFormulaireFromId(uid));
-                    this.resultsComponent.formulaire = this._formulaire;
-                    this._calculatorNameComponent.model = this._formulaire;
+                    this._formulaire = (this.formulaireService.getFormulaireFromId(uid));
                     // reload localisation in all cases (it does not eat bread)
                     this.formulaireService.updateFormulaireLocalisation(this._formulaire);
-                    // call Form init hook
-                    this._formulaire.onCalculatorInit();
-                    break;
-            }
-        } else if (sender instanceof FormulaireDefinition) {
-            let f: FormulaireDefinition;
-            switch (data["action"]) {
-                case "resetForm": // réinitialisation du formulaire
-                case "resultsUpdated":
-                    f = sender as FormulaireDefinition;
-                    this.updateFormulaireResults(f.uid);
                     break;
             }
         }
@@ -500,6 +492,10 @@ export class GenericCalculatorComponent implements OnInit, DoCheck, AfterViewChe
                 this._isUIValid = this._isUIValid && this._pabTableComponent.isValid;
             }
         }
+
+        if (this._pbSchemaComponent !== undefined) {
+            this._isUIValid = this._isUIValid && this._pbSchemaComponent.isValid;
+        }
     }
 
     public getElementStyleDisplay(id: string) {
@@ -519,8 +515,6 @@ export class GenericCalculatorComponent implements OnInit, DoCheck, AfterViewChe
      */
     public onInputChange(event: any) {
         this._formulaire.resetResults([], (event ? event.symbol : undefined));
-        // to refresh log components, that are fed manually (!)
-        this.resultsComponent.updateView();
     }
 
     /**
@@ -561,6 +555,13 @@ export class GenericCalculatorComponent implements OnInit, DoCheck, AfterViewChe
         elt.select();
     }
 
+    /** réception d'un événement de clic sur un nœud du schéma de PréBarrage */
+    public onPBNodeSelected(event: any) {
+        // show proper form (actually subform elements) or proper results,
+        // depending on what was clicked
+        (this._formulaire as FormulairePrebarrage).nodeSelected(event.node);
+    }
+
     public openHelp() {
         window.open("assets/docs/" + this.appSetupService.language + "/calculators/" + this._formulaire.helpLink, "_blank");
     }
@@ -583,7 +584,7 @@ export class GenericCalculatorComponent implements OnInit, DoCheck, AfterViewChe
 
     // for "one wide column" layout
     public get isWide() {
-        return (this.isPAB || this.isMRC);
+        return (this.isPAB || this.isMRC || (this.isPB && this.showPBInputData));
     }
 
     // true if current Nub is Solveur
@@ -601,6 +602,11 @@ export class GenericCalculatorComponent implements OnInit, DoCheck, AfterViewChe
         return this.is(CalculatorType.MacroRugoCompound);
     }
 
+    // true if current Nub is PreBarrage
+    public get isPB() {
+        return this.is(CalculatorType.PreBarrage);
+    }
+
     // true if current Nub is Jet
     public get isJet() {
         return this.is(CalculatorType.Jet);
@@ -626,11 +632,26 @@ export class GenericCalculatorComponent implements OnInit, DoCheck, AfterViewChe
         return this.is(CalculatorType.Par);
     }
 
+    // true if current Nub is Verificateur
+    public get isVerificateur() {
+        return this.is(CalculatorType.Verificateur);
+    }
+
     // true if current Nub is Espece
     public get isEspece() {
         return this.is(CalculatorType.Espece);
     }
 
+    // true if current Nub is PAR
+    public get isSP() {
+        return this.is(CalculatorType.SectionParametree);
+    }
+
+    // true if current Nub is PAR
+    public get isRemous() {
+        return this.is(CalculatorType.CourbeRemous);
+    }
+
     /**
      * Returns true if no parameter is varying; ignores parameters having
      * one of the given {except} symbols, if any
@@ -686,10 +707,10 @@ export class GenericCalculatorComponent implements OnInit, DoCheck, AfterViewChe
             disableClose: false
           }
         );
-        dialogRef.afterClosed().subscribe(result => {
+        dialogRef.afterClosed().subscribe(async result => {
           if (result) {
             if (result.generate) {
-              this.formulaireService.createFormulaire(CalculatorType.Pab).then((f: FormulaireDefinition) => {
+                const f: FormulaireDefinition = await this.formulaireService.createFormulaire(CalculatorType.Pab);
                 const pab = (f.currentNub as Pab);
                 const params = pab.prms;
                 // paramètres hydrauliques
@@ -701,7 +722,6 @@ export class GenericCalculatorComponent implements OnInit, DoCheck, AfterViewChe
                 pab.addCloisonsFromModel(this._formulaire.currentNub as Cloisons, result.nbBassins);
                 // go to new PAB
                 this.router.navigate(["/calculator", f.uid]);
-              });
             }
           }
         });
@@ -806,7 +826,7 @@ export class GenericCalculatorComponent implements OnInit, DoCheck, AfterViewChe
      * @param Ys tirant(s) d'eau
      * @param Ifs pente(s)
      */
-    private generateBiefSP(Ys: number | number[], Ifs: number | number[]) {
+    private async generateBiefSP(Ys: number | number[], Ifs: number | number[]) {
         const bief = (this._formulaire.currentNub as Bief);
         const serialisedSection = bief.section.serialise();
         const sectionCopy = Session.getInstance().unserialiseSingleNub(serialisedSection, false).nub;
@@ -829,17 +849,14 @@ export class GenericCalculatorComponent implements OnInit, DoCheck, AfterViewChe
             }
         }
 
-        this.formulaireService.createFormulaire(CalculatorType.SectionParametree, secParam)
-            .then((f: FormulaireDefinition) => {
-                const sp = (f.currentNub as SectionParametree);
-                sp.section.prms.Y.setValues(Ys);
-                sp.section.prms.If.setValues(Ifs);
-                // calculate
-                f.doCompute();
-                // go to new SP
-                this.router.navigate(["/calculator", f.uid]).then();
-            }
-        );
+        const f: FormulaireDefinition = await this.formulaireService.createFormulaire(CalculatorType.SectionParametree, secParam);
+        const sp = (f.currentNub as SectionParametree);
+        sp.section.prms.Y.setValues(Ys);
+        sp.section.prms.If.setValues(Ifs);
+        // calculate
+        f.doCompute();
+        // go to new SP
+        this.router.navigate(["/calculator", f.uid]);
     }
 
     public get generateRuSpEnabled(): boolean {
@@ -857,7 +874,7 @@ export class GenericCalculatorComponent implements OnInit, DoCheck, AfterViewChe
     /**
      * Génère une SectionParametree à partir du module RegimeUniforme en cours
      */
-    public generateRuSp() {
+    public async generateRuSp() {
         const ru = (this._formulaire.currentNub as RegimeUniforme);
         // copy section
         const serialisedSection = ru.section.serialise();
@@ -873,13 +890,10 @@ export class GenericCalculatorComponent implements OnInit, DoCheck, AfterViewChe
         }
         Session.getInstance().registerNub(secParam);
 
-        this.formulaireService.createFormulaire(CalculatorType.SectionParametree, secParam)
-            .then((f: FormulaireDefinition) => {
-                // calculate
-                f.doCompute();
-                // go to new SP
-            }
-        );
+        const f: FormulaireDefinition = await this.formulaireService.createFormulaire(CalculatorType.SectionParametree, secParam);
+        // calculate
+        f.doCompute();
+        // go to new SP
     }
 
     public get generatePARSimulationEnabled(): boolean {
@@ -915,7 +929,7 @@ export class GenericCalculatorComponent implements OnInit, DoCheck, AfterViewChe
         const pcal = parCalage.prms;
         let pres: { [key: string]: number } = parCalage.result.values;
 
-        const varParams: NgParameter[] = this._formulaire.getVariatedParameters();
+        const varParams: VariatedDetails[] = this._formulaire.getVariatedParameters();
         if (varParams.length > 0) {
             // open popup to choose combination of varying parameters
             const mdParResults = new MultiDimensionResults();
@@ -978,7 +992,7 @@ export class GenericCalculatorComponent implements OnInit, DoCheck, AfterViewChe
      * Creates a new Formulaire with a ParSimulation Nub, using given
      * values as parameters
      */
-    protected doGenerateParSimWithValues(v: any) {
+    protected async doGenerateParSimWithValues(v: any) {
         const parCalage = (this._formulaire.currentNub as Par);
         const psim = new ParSimulationParams(
             round(v.Q, 3),      round(v.Z1, 3),     round(v.Z2, 3),
@@ -991,14 +1005,11 @@ export class GenericCalculatorComponent implements OnInit, DoCheck, AfterViewChe
         parSimulation.parType = parCalage.parType;
         Session.getInstance().registerNub(parSimulation);
 
-        this.formulaireService.createFormulaire(CalculatorType.ParSimulation, parSimulation)
-            .then((f: FormulaireDefinition) => {
-                // calculate
-                f.doCompute();
-                // go to new ParSimulation
-                this.router.navigate(["/calculator", f.uid]).then();
-            }
-        );
+        const f: FormulaireDefinition = await this.formulaireService.createFormulaire(CalculatorType.ParSimulation, parSimulation);
+        // calculate
+        f.doCompute();
+        // go to new ParSimulation
+        this.router.navigate(["/calculator", f.uid]);
     }
 
     /**
@@ -1018,7 +1029,6 @@ export class GenericCalculatorComponent implements OnInit, DoCheck, AfterViewChe
                 const form = this._formulaire as FormulaireFixedVar;
                 const nub = (form.currentNub as Espece);
                 nub.loadPredefinedSpecies(result.selected);
-                console.log("================ espèce chargée, refresh tout");
                 form.refreshFieldsets();
             }
         });
@@ -1048,11 +1058,10 @@ export class GenericCalculatorComponent implements OnInit, DoCheck, AfterViewChe
     /**
      * Duplicates the current calculator form
      */
-    public cloneCalculator() {
+    public async cloneCalculator() {
         const serialisedNub: string = this._formulaire.currentNub.serialise({ title: this._formulaire.calculatorName });
         const nubPointer = Session.getInstance().unserialiseSingleNub(serialisedNub);
-        this.formulaireService.createFormulaire(nubPointer.nub.calcType, nubPointer.nub, nubPointer.meta.title).then((f) => {
-            this.router.navigate(["/calculator", f.uid]);
-        });
+        const f = await this.formulaireService.createFormulaire(nubPointer.nub.calcType, nubPointer.nub, nubPointer.meta.title);
+        this.router.navigate(["/calculator", f.uid]);
     }
 }
diff --git a/src/app/components/jet-results/jet-results.component.html b/src/app/components/jet-results/jet-results.component.html
index ee434e04fa718f113acf60554f64e5db8156cb15..f3680821b57ef749b4521e1c6707b0dbd78bbdea 100644
--- a/src/app/components/jet-results/jet-results.component.html
+++ b/src/app/components/jet-results/jet-results.component.html
@@ -2,9 +2,9 @@
     <!-- journal -->
     <log></log>
 
-    <results-chart *ngIf="showVarResults" [hidden]="! showVarResultsChart"></results-chart>
+    <results-chart *ngIf="showVarResults" [hidden]="! showVarResultsChart" [results]=varResults [resultData]=varResults?.result></results-chart>
 
-    <jet-trajectory-chart [hidden]="! hasValidResults"></jet-trajectory-chart>
+    <jet-trajectory-chart [hidden]="! hasValidResults" [results]=trajectoryResults?.result></jet-trajectory-chart>
 
     <div>
         <!-- table des résultats fixés -->
diff --git a/src/app/components/jet-results/jet-results.component.ts b/src/app/components/jet-results/jet-results.component.ts
index 0e5c86aa3810c9756a8d59b42d7636a0ca8e00c0..57258cd1ebe79fdf1e4fb871d07262fa2c8c6d5e 100644
--- a/src/app/components/jet-results/jet-results.component.ts
+++ b/src/app/components/jet-results/jet-results.component.ts
@@ -1,7 +1,8 @@
-import { Component, ViewChild } from "@angular/core";
+import { Component } from "@angular/core";
 
 import { FixedVarResultsComponent } from "../fixedvar-results/fixedvar-results.component";
-import { JetTrajectoryChartComponent } from "../jet-trajectory-chart/jet-trajectory-chart.component";
+import { FixedResults } from "../../results/fixed-results";
+import { VarResults } from "../../results/var-results";
 
 @Component({
     selector: "jet-results",
@@ -12,15 +13,11 @@ import { JetTrajectoryChartComponent } from "../jet-trajectory-chart/jet-traject
 })
 export class JetResultsComponent extends FixedVarResultsComponent {
 
-    /** graphique de trajectoire */
-    @ViewChild(JetTrajectoryChartComponent)
-    private jetTrajectoryChartComponent: JetTrajectoryChartComponent;
-
     public get hasResults(): boolean {
         return (
-            (this._fixedResults !== undefined && this._fixedResults.hasResults)
+            (this._fixedResults?.hasResults)
             ||
-            (this._varResults !== undefined && this._varResults.hasResults)
+            (this._varResults?.hasResults)
         );
     }
 
@@ -32,33 +29,13 @@ export class JetResultsComponent extends FixedVarResultsComponent {
         );
     }
 
-    public updateView() {
-        if (this.jetTrajectoryChartComponent) {
-            this.jetTrajectoryChartComponent.results = undefined;
+    public get trajectoryResults(): FixedResults | VarResults {
+        // draw chart whether params are variating or not,
+        // hence different Results object for each case
+        if (this._varResults && this._varResults.hasResults) {
+            return this._varResults;
+        } else {
+            return this._fixedResults;
         }
-        super.updateView();
-    }
-
-    /**
-     * met à jour l'affichage des résultats
-     * @returns true si les résultats ont pu être mis à jour
-     */
-    protected updateResults() {
-        const superUpdated = super.updateResults();
-
-        const trajectoryChartUpdated = this.jetTrajectoryChartComponent !== undefined;
-
-        if (trajectoryChartUpdated) {
-            // draw chart whether params are variating or not,
-            // hence different Results object for each case
-            if (this._varResults && this._varResults.hasResults) {
-                this.jetTrajectoryChartComponent.results = this._varResults;
-            } else {
-                this.jetTrajectoryChartComponent.results = this._fixedResults;
-            }
-            this.jetTrajectoryChartComponent.updateView();
-        }
-
-        return superUpdated && trajectoryChartUpdated;
     }
 }
diff --git a/src/app/components/jet-trajectory-chart/jet-trajectory-chart.component.html b/src/app/components/jet-trajectory-chart/jet-trajectory-chart.component.html
index 1087a424a449b1eaa643bbbf4fbe0b961f547b0e..cedbcf29399b1b64c0fc89833f8b4cbee6e55830 100644
--- a/src/app/components/jet-trajectory-chart/jet-trajectory-chart.component.html
+++ b/src/app/components/jet-trajectory-chart/jet-trajectory-chart.component.html
@@ -17,7 +17,7 @@
         </div>
 
         <div *ngIf="! displayChart" class="fake-chart"></div><!-- trick to avoid blinking effect due to forceRebuild -->
-        <chart *ngIf="displayChart" type="scatter" [data]="graph_data" [options]="graph_options" #graphChart>
+        <chart *ngIf="displayChart" type="scatter" [data]="graph_data" [options]="graph_options">
         </chart>
     </div>
 </div>
\ No newline at end of file
diff --git a/src/app/components/jet-trajectory-chart/jet-trajectory-chart.component.ts b/src/app/components/jet-trajectory-chart/jet-trajectory-chart.component.ts
index 960cda6bde4a059274a8828a55150feea7b51ad1..2d726e9f975d19f3075bc924800f867df01a1134 100644
--- a/src/app/components/jet-trajectory-chart/jet-trajectory-chart.component.ts
+++ b/src/app/components/jet-trajectory-chart/jet-trajectory-chart.component.ts
@@ -1,16 +1,14 @@
-import { Component, ViewChild, ChangeDetectorRef } from "@angular/core";
+import { Component, ViewChild, ChangeDetectorRef, Input, OnChanges } from "@angular/core";
 
 import { ChartComponent } from "angular2-chartjs";
 
 import { I18nService } from "../../services/internationalisation.service";
 import { ResultsComponentDirective } from "../fixedvar-results/results.component";
 import { IYSeries } from "../../results/y-series";
-import { FixedResults } from "../../results/fixed-results";
-import { VarResults } from "../../results/var-results";
 import { fv } from "../../util";
 import { AppComponent } from "../../app.component";
 
-import { Jet } from "jalhyd";
+import { Jet, Result } from "jalhyd";
 
 @Component({
     selector: "jet-trajectory-chart",
@@ -19,12 +17,12 @@ import { Jet } from "jalhyd";
         "./jet-trajectory-chart.component.scss"
     ]
 })
-export class JetTrajectoryChartComponent extends ResultsComponentDirective {
+export class JetTrajectoryChartComponent extends ResultsComponentDirective implements OnChanges {
 
     @ViewChild(ChartComponent)
     private chartComponent;
 
-    private _results: FixedResults | VarResults;
+    private _results: Result;
 
     private _zoomWasChanged = false;
 
@@ -132,12 +130,16 @@ export class JetTrajectoryChartComponent extends ResultsComponentDirective {
         }, 10);
     }
 
-    public set results(r: FixedResults | VarResults) {
+    @Input()
+    public set results(r: Result) {
         this.forceRebuild(); // used for forcing redefinition of xAxes[0].ticks.min/max in generateScatterChart()
         this._results = r;
+    }
 
-        if (this._results && this._results.result) {
-            const nub = this._results.result.sourceNub as Jet;
+    // redessine le graphique dès qu'une entrée change
+    public ngOnChanges() {
+        if (this._results) {
+            const nub = this._results.sourceNub as Jet;
             const length = nub.variatingLength();
             // extract variable values list for legend
             if (nub.resultHasMultipleValues()) {
@@ -158,6 +160,7 @@ export class JetTrajectoryChartComponent extends ResultsComponentDirective {
                     }
                 }
             }
+            this.generateScatterChart();
         }
     }
 
@@ -170,16 +173,12 @@ export class JetTrajectoryChartComponent extends ResultsComponentDirective {
         return this._zoomWasChanged;
     }
 
-    public updateView() {
-        this.generateScatterChart();
-    }
-
     /**
      * génère les données d'un graphique de type "scatter"
      */
     private generateScatterChart() {
         const ySeries = this.getYSeries();
-        const nub = (this._results.result.sourceNub as Jet);
+        const nub = (this._results.sourceNub as Jet);
 
         this.graph_data = {
             datasets: []
@@ -260,7 +259,7 @@ export class JetTrajectoryChartComponent extends ResultsComponentDirective {
     private getYSeries(): IYSeries[] {
         const ret: IYSeries[] = [];
         const palette = ResultsComponentDirective.distinctColors;
-        const nub = (this._results.result.sourceNub as Jet);
+        const nub = (this._results.sourceNub as Jet);
         const trajectories = nub.generateTrajectories();
 
         for (let i = 0; i < trajectories.length; i++) {
diff --git a/src/app/components/log-drawer/log-drawer.component.html b/src/app/components/log-drawer/log-drawer.component.html
index f2139f7c2cac8da90895a812a9cf9de5c61b3e51..24c2ed3a863ba466f6951fd1be7e2cc2681f365c 100644
--- a/src/app/components/log-drawer/log-drawer.component.html
+++ b/src/app/components/log-drawer/log-drawer.component.html
@@ -3,18 +3,18 @@
         <!-- titre -->
         <div class="titre">{{ uitextTitreJournal }}</div>
         <!-- entrées du journal -->
-        <div class="log-entry" *ngFor="let entry of log">
+        <div class="log-entry" *ngFor="let entry of log; let i = index; trackBy: tbIndex">
             <log-entry [_message]="entry.message"></log-entry>
             <div *ngIf="entry.subLog.messages.length" class="drawer">
                 <div class="open-drawer">
-                    <span *ngIf="! entry.isOpen">
-                        <a (click)="entry.isOpen = true;">{{ uitextShowDetails }}</a>
+                    <span *ngIf="! entryIsOpen(i)">
+                        <a (click)="setEntryOpen(i, true);">{{ uitextShowDetails }}</a>
                     </span>
-                    <span *ngIf="entry.isOpen">
-                        <a (click)="entry.isOpen = false">{{ uitextHideDetails }}</a>
+                    <span *ngIf="entryIsOpen(i)">
+                        <a (click)="setEntryOpen(i, false);">{{ uitextHideDetails }}</a>
                     </span>
                 </div>
-                <div class="drawer-contents" [hidden]="! entry.isOpen">
+                <div class="drawer-contents" [hidden]="! entryIsOpen(i)">
                     <log-entry *ngFor="let m of entry.subLog.messages" [_message]="m"></log-entry>
                 </div>
             </div>
diff --git a/src/app/components/log-drawer/log-drawer.component.ts b/src/app/components/log-drawer/log-drawer.component.ts
index 2394e46b84dffcd3b8f7c3b1439ea967d5b3872f..bb4fcf4f39e1342f79b0dcff8e65ca4cb0734908 100644
--- a/src/app/components/log-drawer/log-drawer.component.ts
+++ b/src/app/components/log-drawer/log-drawer.component.ts
@@ -15,7 +15,9 @@ import { I18nService } from "../../services/internationalisation.service";
 export class LogDrawerComponent {
 
     /** A list of log messages accompanied by a sub-log (multiple messages) */
-    public log: Array<{ message: Message, subLog: cLog }>;
+    private _log: Array<{ message: Message, subLog: cLog }>;
+
+    private entriesStates: boolean[] = [];
 
     // title to display above the log
     @Input()
@@ -24,7 +26,16 @@ export class LogDrawerComponent {
     constructor(
         private intlService: I18nService,
     ) {
-        this.log = [];
+        this._log = [];
+    }
+
+    @Input()
+    public set log(log: Array<{ message: Message, subLog: cLog }>) {
+        this._log = log;
+    }
+
+    public get log(): Array<{ message: Message, subLog: cLog }> {
+        return this._log;
     }
 
     public get uitextTitreJournal(): string {
@@ -36,7 +47,7 @@ export class LogDrawerComponent {
     }
 
     public get hasEntries(): boolean {
-        return this.log !== undefined && this.log.length !== 0;
+        return this._log !== undefined && this._log.length !== 0;
     }
 
     public get uitextShowDetails(): string {
@@ -46,4 +57,20 @@ export class LogDrawerComponent {
     public get uitextHideDetails(): string {
         return this.intlService.localizeText("INFO_LOG_HIDE_DETAILS");
     }
+
+    public entryIsOpen(i: number): boolean {
+        if (this.entriesStates[i] !== undefined) {
+            return this.entriesStates[i];
+        }
+        return false;
+    }
+
+    public setEntryOpen(i: number, open: boolean) {
+        this.entriesStates[i] = open;
+    }
+
+    /** trackBy:index simulator @see nghyd#364 */
+    public tbIndex(index: number, item: any) {
+        return index;
+    }
 }
diff --git a/src/app/components/log/log.component.html b/src/app/components/log/log.component.html
index 4d3d0424a7c33bd9da1816c6f61e0c749bcacfef..5920817ec90af8c9dae78dbca027e29197cd7071 100644
--- a/src/app/components/log/log.component.html
+++ b/src/app/components/log/log.component.html
@@ -3,6 +3,6 @@
         <!-- titre -->
         <div class="titre">{{ uitextTitreJournal }}</div>
         <!-- entrées du journal -->
-        <log-entry *ngFor="let m of messages" [_message]="m"></log-entry>
+        <log-entry *ngFor="let m of _log?.messages" [_message]="m"></log-entry>
     </div>
 </div>
diff --git a/src/app/components/log/log.component.ts b/src/app/components/log/log.component.ts
index 622fdd914984ab8da3955b5b6147be420a9a7f5f..b3d9c2f7188e4227f5ec1559bfd488d24aa30e80 100644
--- a/src/app/components/log/log.component.ts
+++ b/src/app/components/log/log.component.ts
@@ -34,13 +34,10 @@ export class LogComponent {
     }
 
     public get hasEntries(): boolean {
-        return this._log !== undefined && this._log.messages.length !== 0;
-    }
-
-    public get messages(): Message[] {
-        return this._log.messages;
+        return this._log?.messages?.length > 0;
     }
 
+    @Input()
     public set log(log: cLog) {
         this._log = log;
     }
diff --git a/src/app/components/macrorugo-compound-results/macrorugo-compound-results-table.component.ts b/src/app/components/macrorugo-compound-results/macrorugo-compound-results-table.component.ts
index abe858dcc5a426d6f7eb832759192c329a16ce3e..bf70492bf1b76785f94acbc9409326e0fada2b0e 100644
--- a/src/app/components/macrorugo-compound-results/macrorugo-compound-results-table.component.ts
+++ b/src/app/components/macrorugo-compound-results/macrorugo-compound-results-table.component.ts
@@ -1,4 +1,4 @@
-import { Component, ViewChild, ElementRef } from "@angular/core";
+import { Component, ViewChild, ElementRef, Input, OnChanges } from "@angular/core";
 
 import { MacroRugo } from "jalhyd";
 
@@ -15,10 +15,15 @@ import { AppComponent } from "../../app.component";
         "./macrorugo-compound-results-table.component.scss"
     ]
 })
-export class MacrorugoCompoundResultsTableComponent extends ResultsComponentDirective {
+export class MacrorugoCompoundResultsTableComponent extends ResultsComponentDirective implements OnChanges {
 
     /** résultats non mis en forme */
-    private _mrcResults: MacrorugoCompoundResults;
+    @Input()
+    public results: MacrorugoCompoundResults;
+
+    /** index de l'élément de résultat à afficher (modifié par le sélecteur de conditions limites) */
+    @Input()
+    public variableIndex = 0;
 
     /** entêtes des colonnes */
     private _headers: string[];
@@ -36,21 +41,19 @@ export class MacrorugoCompoundResultsTableComponent extends ResultsComponentDire
         super();
     }
 
-    public set results(r: MacrorugoCompoundResults) {
-        this._mrcResults = r;
-
+    public ngOnChanges() {
+        // rebuild dataset every time results or variableIndex change
         this._dataSet = [];
         if (
-            this._mrcResults
-            && this._mrcResults.childrenResults
-            && this._mrcResults.childrenResults.length > 0
-            && ! this._mrcResults.hasOnlyErrors()
+            this.results
+            && this.results.childrenResults
+            && this.results.childrenResults.length > 0
+            && ! this.results.hasOnlyErrors()
         ) {
-            const pr = this._mrcResults;
+            const pr = this.results;
             const nDigits = this.appSetupService.displayPrecision;
             // when a parameter is variating, index of the variating parameter
             // values to build the data from
-            const vi = pr.variableIndex;
 
             // refresh headers here if language changed
             this._headers = pr.headers;
@@ -58,13 +61,13 @@ export class MacrorugoCompoundResultsTableComponent extends ResultsComponentDire
             // lines 1 - n-1 (aprons)
             for (let i = 0; i < pr.childrenResults.length; i++) {
                 // protect loop contents with if(vCalc) ? Will hide erroneous apron results..
-                const res = pr.childrenResults[i].resultElements[vi].values;
+                const res = pr.childrenResults[i].resultElements[this.variableIndex].values;
                 const nub = (pr.childrenResults[i].sourceNub as MacroRugo);
                 // does ZF1 or B vary ?
                 let zf1: number;
                 try {
                     if (nub.prms.ZF1.hasMultipleValues) {
-                        zf1 = nub.prms.ZF1.getInferredValuesList()[vi];
+                        zf1 = nub.prms.ZF1.getInferredValuesList()[this.variableIndex];
                     } else {
                         zf1 = nub.prms.ZF1.singleValue;
                     }
@@ -74,7 +77,7 @@ export class MacrorugoCompoundResultsTableComponent extends ResultsComponentDire
                 let b: number;
                 try {
                     if (nub.prms.B.hasMultipleValues) {
-                        b = nub.prms.B.getInferredValuesList()[vi];
+                        b = nub.prms.B.getInferredValuesList()[this.variableIndex];
                     } else {
                         b = nub.prms.B.singleValue;
                     }
@@ -84,7 +87,7 @@ export class MacrorugoCompoundResultsTableComponent extends ResultsComponentDire
                 let Y: number;
                 try {
                     if (nub.prms.Y.hasMultipleValues) {
-                        Y = nub.prms.Y.getInferredValuesList()[vi];
+                        Y = nub.prms.Y.getInferredValuesList()[this.variableIndex];
                     } else {
                         Y = nub.prms.Y.singleValue;
                     }
@@ -111,7 +114,7 @@ export class MacrorugoCompoundResultsTableComponent extends ResultsComponentDire
             this._dataSet.push([
                 this.intlService.localizeText("INFO_LIB_TOTAL"),
                 "", "", "",
-                pr.result.resultElements[vi].vCalc.toFixed(nDigits),
+                pr.result.resultElements[this.variableIndex].vCalc.toFixed(nDigits),
                 "", "", "", "", "", ""
             ]);
         }
diff --git a/src/app/components/macrorugo-compound-results/macrorugo-compound-results.component.html b/src/app/components/macrorugo-compound-results/macrorugo-compound-results.component.html
index 85b150db8a3bbdc7f23bbd2aa6a88f0f7915fb46..593252b2cd8f4cae825bf03b5dee17eb64545eec 100644
--- a/src/app/components/macrorugo-compound-results/macrorugo-compound-results.component.html
+++ b/src/app/components/macrorugo-compound-results/macrorugo-compound-results.component.html
@@ -1,15 +1,16 @@
 <div class="container">
 
-    <log #generalLog [logTitle]="uitextGeneralLogTitle">log général</log>
+    <log [logTitle]="uitextGeneralLogTitle" [log]=globalLog>log général</log>
 
-    <variable-results-selector [results]="mrcResults" (indexChange)="variableIndexChanged()">
+    <variable-results-selector [results]=mrcResults [variatedParameters]=mrcResults?.variatedParameters>
     </variable-results-selector>
 
-    <log #iterationLog></log>
+    <log [log]=iterationLog></log>
 
     <div>
         <!-- tableau de résultats -->
-        <macrorugo-compound-results-table *ngIf="hasDisplayableResults" [results]="mrcResults">
+        <macrorugo-compound-results-table *ngIf="hasDisplayableResults"
+          [results]=mrcResults [variableIndex]=mrcResults?.variableIndex>
         </macrorugo-compound-results-table>
     </div>
 
@@ -20,11 +21,9 @@
     <quicknav *ngIf="hasDisplayableResults" [items]="[ 'input', 'results', 'charts' ]" [currentItem]="'charts'"
         [align]="'left'"></quicknav>
 
-    <div id="macrorugo-compound-graphs-container" class="container" fxLayout="row wrap"
-        fxLayoutAlign="space-around start">
-        <!-- <pab-profile-chart *ngIf="hasDisplayableResults" fxFlex.gt-xs="1 0 400px" fxFlex.lt-sm="1 0 300px">
-        </pab-profile-chart> -->
-        <results-chart *ngIf="hasDisplayableResults" fxFlex.gt-xs="1 0 400px" fxFlex.lt-sm="1 0 300px">
+    <div id="macrorugo-compound-graphs-container" class="container" fxLayout="row wrap" fxLayoutAlign="space-around start">
+        <results-chart *ngIf="hasDisplayableResults" [results]=mrcResults [resultData]=mrcResults?.result
+          [variableIndex]=mrcResults?.variableIndex fxFlex.gt-xs="1 0 400px" fxFlex.lt-sm="1 0 300px">
         </results-chart>
     </div>
 
diff --git a/src/app/components/macrorugo-compound-results/macrorugo-compound-results.component.ts b/src/app/components/macrorugo-compound-results/macrorugo-compound-results.component.ts
index e15ade96ce9b65c46e9d84486fd714cbb3e7036b..232f0c436caa9e177defbe862dbdb940a4f7fd39 100644
--- a/src/app/components/macrorugo-compound-results/macrorugo-compound-results.component.ts
+++ b/src/app/components/macrorugo-compound-results/macrorugo-compound-results.component.ts
@@ -1,20 +1,15 @@
-import { Component, ViewChild, DoCheck } from "@angular/core";
+import { Component, Input } from "@angular/core";
 
 import { Result, cLog, Message, MessageCode, MessageSeverity, MRCInclination } from "jalhyd";
 
 import { fv } from "../../../app/util";
 
-import { LogComponent } from "../../components/log/log.component";
 import { CalculatorResults } from "../../results/calculator-results";
 import { NgParameter } from "../../formulaire/elements/ngparam";
 import { ApplicationSetupService } from "../../services/app-setup.service";
-import { PlottableData } from "../../results/plottable-data";
-import { ResultsChartComponent } from "../results-chart/results-chart.component";
 import { I18nService } from "../../services/internationalisation.service";
-import { VariableResultsSelectorComponent } from "../variable-results-selector/variable-results-selector.component";
-import { MacrorugoCompoundResultsTableComponent } from "./macrorugo-compound-results-table.component";
 import { MacrorugoCompoundResults } from "../../results/macrorugo-compound-results";
-import { PlottableMacrorugoCompoundResults } from "../../results/plottable-macrorugo-compound-results";
+import { ResultsComponentDirective } from "../fixedvar-results/results.component";
 
 @Component({
     selector: "macrorugo-compound-results",
@@ -23,83 +18,24 @@ import { PlottableMacrorugoCompoundResults } from "../../results/plottable-macro
         "./macrorugo-compound-results.component.scss"
     ]
 })
-export class MacrorugoCompoundResultsComponent implements DoCheck {
+export class MacrorugoCompoundResultsComponent extends ResultsComponentDirective {
 
     /** résultats non mis en forme */
     private _mrcResults: MacrorugoCompoundResults;
 
-    /** résultats mis en forme pour le graphique de données (classique) */
-    private _plottableResults: PlottableMacrorugoCompoundResults;
-
-    /** true si les résultats doiventt être remis à jour */
-    private _doUpdate = false;
-
-    @ViewChild(MacrorugoCompoundResultsTableComponent)
-    private mrcResultsTableComponent: MacrorugoCompoundResultsTableComponent;
-
-    @ViewChild(VariableResultsSelectorComponent)
-    private variableResultsSelectorComponent: VariableResultsSelectorComponent;
-
-    @ViewChild("generalLog")
-    private generalLogComponent: LogComponent;
-
-    @ViewChild("iterationLog")
-    private iterationLogComponent: LogComponent;
-
-    @ViewChild(ResultsChartComponent)
-    private resultsChartComponent: ResultsChartComponent;
-
     constructor(
         private appSetupService: ApplicationSetupService,
         private i18nService: I18nService,
     ) {
-        this._plottableResults = new PlottableMacrorugoCompoundResults();
+        super();
     }
 
+    @Input()
     public set results(rs: CalculatorResults[]) {
         this._mrcResults = undefined;
         if (rs.length > 0 && rs[0] instanceof MacrorugoCompoundResults) {
             this._mrcResults = rs[0] as MacrorugoCompoundResults;
         }
-        this.updateView();
-    }
-
-    /**
-     * update results table and chart when the variable index changed (event sent by
-     * VariableResultsSelectorComponent); variable index is already set in
-     * mrcResults at this time
-     */
-    public variableIndexChanged() {
-        this.updateView();
-    }
-
-    public updateView() {
-        if (this.iterationLogComponent) {
-            this.iterationLogComponent.log = undefined;
-        }
-        if (this.generalLogComponent) {
-            this.generalLogComponent.log = undefined;
-        }
-        if (this.mrcResultsTableComponent) {
-            this.mrcResultsTableComponent.results = undefined;
-        }
-        if (this.variableResultsSelectorComponent) {
-            this.variableResultsSelectorComponent.results = undefined;
-        }
-        if (this.resultsChartComponent) {
-            this.resultsChartComponent.results = undefined;
-        }
-        // set _doUpdate flag so that results are rebuilt on the next Angular display cycle
-        this._doUpdate = false;
-        if (this._mrcResults !== undefined) {
-            this._doUpdate = this._doUpdate || this._mrcResults.hasResults || this._mrcResults.hasLog;
-        }
-    }
-
-    public ngDoCheck() {
-        if (this._doUpdate) {
-            this._doUpdate = !this.updateResults();
-        }
     }
 
     private mergeGlobalLog(result: Result, log: cLog) {
@@ -175,7 +111,7 @@ export class MacrorugoCompoundResultsComponent implements DoCheck {
      * du sélecteur d'itération : messages globaux et / ou résumé des messages
      * spécifiques à chaque ResultElement
      */
-    private get globalLog(): cLog {
+    public get globalLog(): cLog {
         const l = new cLog();
         if (this._mrcResults && this.mrcResults.variatedParameters.length > 0) {
             this.mergeGlobalLog(this._mrcResults.result, l);
@@ -197,11 +133,11 @@ export class MacrorugoCompoundResultsComponent implements DoCheck {
     }
 
     /**
-     * Retourne les logs à afficher dans le composant de log global, au dessus
-     * du sélecteur d'itération : messages globaux et / ou résumé des messages
-     * spécifiques à chaque ResultElement
+     * Retourne les logs à afficher dans le composant de log local, en dessous
+     * du sélecteur d'itération : messages concernant l'itération (le ResultElement)
+     * en cours
      */
-    private get iterationLog(): cLog {
+    public get iterationLog(): cLog {
         const l = new cLog();
         if (this._mrcResults) {
             if (this.mrcResults.variatedParameters.length > 0) {
@@ -236,54 +172,10 @@ export class MacrorugoCompoundResultsComponent implements DoCheck {
         return l;
     }
 
-    /**
-     * met à jour l'affichage des résultats
-     * @returns true si les résultats ont pu être mis à jour
-     */
-    private updateResults() {
-        let mrcUpdated: boolean;
-        let resultsChartUpdated: boolean;
-        let selectorUpdated: boolean;
-
-        // results or not, there might be a log
-        const logUpdated = (this.iterationLogComponent !== undefined || this.generalLogComponent !== undefined); // gne ?
-        if (logUpdated) {
-            // order of logs is important !
-            this.iterationLogComponent.log = this.iterationLog;
-            this.generalLogComponent.log = this.globalLog;
-        }
-
-        if (this.hasResults) {
-            mrcUpdated = this.mrcResultsTableComponent !== undefined;
-            if (mrcUpdated) {
-                this.mrcResultsTableComponent.results = this._mrcResults;
-            }
-            selectorUpdated = this.variableResultsSelectorComponent !== undefined;
-            if (selectorUpdated) {
-                this.variableResultsSelectorComponent.results = this._mrcResults;
-            }
-            resultsChartUpdated = this.resultsChartComponent !== undefined;
-            if (resultsChartUpdated) {
-                this.resultsChartComponent.results = this.plottableResults;
-                this.resultsChartComponent.updateView();
-            }
-        } else {
-            mrcUpdated = true;
-            resultsChartUpdated = true;
-            selectorUpdated = true;
-        }
-
-        return mrcUpdated && logUpdated && resultsChartUpdated && selectorUpdated;
-    }
-
     public get mrcResults() {
         return this._mrcResults;
     }
 
-    public formattedLabel(p: NgParameter): string {
-        return CalculatorResults.paramLabel(p, false);
-    }
-
     public formattedValue(p: NgParameter): string {
         const nDigits = this.appSetupService.displayPrecision;
         return p.getValue().toFixed(nDigits);
@@ -330,10 +222,4 @@ export class MacrorugoCompoundResultsComponent implements DoCheck {
         return fv(lincl);
     }
 
-    /** builds a set of PlottableData from MacrorugoCompoundResults, to feed the chart */
-    protected get plottableResults(): PlottableData {
-        this._plottableResults.setMrcResults(this.mrcResults);
-        return this._plottableResults;
-    }
-
 }
diff --git a/src/app/components/modules-diagram/modules-diagram.component.ts b/src/app/components/modules-diagram/modules-diagram.component.ts
index 80d08b7b75f72abd58d0ce47dc6bac8346528354..79118556f2d7739e1969dfb3ba6e5e1ba5fb02e7 100644
--- a/src/app/components/modules-diagram/modules-diagram.component.ts
+++ b/src/app/components/modules-diagram/modules-diagram.component.ts
@@ -111,41 +111,47 @@ export class ModulesDiagramComponent implements AfterContentInit, AfterViewCheck
     }
 
     public ngAfterViewInit(): void {
-        // add click listener on every calculator node in the graph, that
-        // corresponds to an open module
-        this.nativeElement.querySelectorAll("g.node").forEach(item => {
-            if (item.id && this.formIsOpen(item.id)) {
-                item.style.cursor = "pointer";
-                item.addEventListener("click", () => {
-                    this.openCalc(item.id);
-                });
-            }
-        });
+        setTimeout(() => { // clodo trick
+            // add click listener on every calculator node in the graph, that
+            // corresponds to an open module
+            this.nativeElement.querySelectorAll("g.node").forEach(item => {
+                if (item.id && this.formIsOpen(item.id)) {
+                    item.style.cursor = "pointer";
+                    item.addEventListener("click", () => {
+                        this.openCalc(item.id);
+                    });
+                }
+            });
+        }, 20); // @WARNING keep timeout > the one in ngAfterContentInit() below
     }
 
     public ngAfterContentInit(): void {
         this.error = false;
-        mermaid.initialize({
-            // theme: "forest"
-            flowchart: {
-                curve: "basis"
-            }
-        });
-        this.nativeElement = this.diagram.nativeElement;
-
-        if (this.hasModules) {
-            // generate graph description
-            const graphDefinition = this.graphDefinition();
-            // draw
-            try {
-                mermaid.render("graphDiv", graphDefinition, (svgCode, bindFunctions) => {
-                    this.nativeElement.innerHTML = svgCode;
-                });
-            } catch (e) {
-                console.error(e);
-                this.error = true;
+        // clodo trick or displaying modules diagram coming from a
+        // PreBarrage module results in a blank diagram
+        setTimeout(() => {
+            mermaid.initialize({
+                // theme: "forest"
+                flowchart: {
+                    curve: "basis"
+                }
+            });
+            this.nativeElement = this.diagram.nativeElement;
+
+            if (this.hasModules) {
+                // generate graph description
+                const graphDefinition = this.graphDefinition();
+                // draw
+                try {
+                    mermaid.render("graphDiv", graphDefinition, (svgCode, bindFunctions) => {
+                        this.nativeElement.innerHTML = svgCode;
+                    });
+                } catch (e) {
+                    console.error(e);
+                    this.error = true;
+                }
             }
-        }
+        }, 10);
     }
 
     public resetZoom() {
diff --git a/src/app/components/pab-profile-chart/pab-profile-chart.component.html b/src/app/components/pab-profile-chart/pab-profile-chart.component.html
index 35c9c9aecdd6b751495e275b5a1e916150faeb31..f7c4d9079569cf669e92ffecf1e18d01684b654b 100644
--- a/src/app/components/pab-profile-chart/pab-profile-chart.component.html
+++ b/src/app/components/pab-profile-chart/pab-profile-chart.component.html
@@ -16,7 +16,7 @@
             </button>
         </div>
 
-        <chart type="scatter" [data]="graph_data" [options]="graph_options" #graphChart>
+        <chart type="scatter" [data]="graph_data" [options]="graph_options">
         </chart>
     </div>
 </div>
\ No newline at end of file
diff --git a/src/app/components/pab-profile-chart/pab-profile-chart.component.ts b/src/app/components/pab-profile-chart/pab-profile-chart.component.ts
index 4b47585b713b0e4bd90c355900f5788dd2ec07c7..5d9220b27bded151a062f9bdd91f1a6bfb813e72 100644
--- a/src/app/components/pab-profile-chart/pab-profile-chart.component.ts
+++ b/src/app/components/pab-profile-chart/pab-profile-chart.component.ts
@@ -1,4 +1,4 @@
-import { Component, ViewChild, ChangeDetectorRef } from "@angular/core";
+import { Component, ViewChild, ChangeDetectorRef, Input, OnChanges } from "@angular/core";
 
 import { ChartComponent } from "angular2-chartjs";
 
@@ -6,7 +6,7 @@ import { I18nService } from "../../services/internationalisation.service";
 import { ResultsComponentDirective } from "../fixedvar-results/results.component";
 import { PabResults } from "../../results/pab-results";
 import { IYSeries } from "../../results/y-series";
-import { fv, longestVarNgParam } from "../../util";
+import { fv, longestVarParam } from "../../util";
 import { AppComponent } from "../../app.component";
 
 import { CloisonAval, Cloisons, LoiDebit } from "jalhyd";
@@ -20,7 +20,7 @@ import { sprintf } from "sprintf-js";
         "./pab-profile-chart.component.scss"
     ]
 })
-export class PabProfileChartComponent extends ResultsComponentDirective {
+export class PabProfileChartComponent extends ResultsComponentDirective implements OnChanges {
 
     @ViewChild(ChartComponent)
     private chartComponent;
@@ -125,25 +125,30 @@ export class PabProfileChartComponent extends ResultsComponentDirective {
         };
     }
 
+    @Input()
     public set results(r: PabResults) {
         this._results = r;
+    }
 
+    // redessine le graphique dès qu'une entrée change
+    public ngOnChanges() {
         // pre-extract variable parameters values
         if (this._results) {
             this.varValues = [];
             // find longest list
-            const lvp = longestVarNgParam(this._results.variatedParameters);
+            const lvp = longestVarParam(this._results.variatedParameters);
             this.size = lvp.size;
             // get extended values lists for each variable parameter
             for (const v of this._results.variatedParameters) {
                 const vv = [];
-                const iter = v.getExtendedValuesIterator(this.size);
+                const iter = v.param.getExtendedValuesIterator(this.size);
                 while (iter.hasNext) {
                     const nv = iter.next();
                     vv.push(fv(nv.value));
                 }
                 this.varValues.push(vv);
             }
+            this.generateScatterChart();
         }
     }
 
@@ -156,10 +161,6 @@ export class PabProfileChartComponent extends ResultsComponentDirective {
         return this._zoomWasChanged;
     }
 
-    public updateView() {
-        this.generateScatterChart();
-    }
-
     /**
      * génère les données d'un graphique de type "scatter"
      */
@@ -458,7 +459,7 @@ export class PabProfileChartComponent extends ResultsComponentDirective {
             i++;
             let value = "0";
             value = vv[n];
-            return `${vp.symbol} = ${value}`;
+            return `${vp.param.symbol} = ${value}`;
         }).join(", ");
     }
 }
diff --git a/src/app/components/pab-results/pab-results-table.component.ts b/src/app/components/pab-results/pab-results-table.component.ts
index 45418cf16c9bc1d546e5c2b2f9e17d10efac8fa0..3591658a7cbf742531918f8509acfa69245600cb 100644
--- a/src/app/components/pab-results/pab-results-table.component.ts
+++ b/src/app/components/pab-results/pab-results-table.component.ts
@@ -1,4 +1,4 @@
-import { Component, ViewChild, ElementRef } from "@angular/core";
+import { Component, ViewChild, ElementRef, Input, OnChanges } from "@angular/core";
 
 import { CloisonAval, Result, capitalize } from "jalhyd";
 
@@ -15,10 +15,15 @@ import { fv } from "../../util";
         "./pab-results-table.component.scss"
     ]
 })
-export class PabResultsTableComponent extends ResultsComponentDirective {
+export class PabResultsTableComponent extends ResultsComponentDirective implements OnChanges {
 
     /** résultats non mis en forme */
-    private _pabResults: PabResults;
+    @Input()
+    public results: PabResults;
+
+    /** index de l'élément de résultat à afficher (modifié par le sélecteur de conditions limites) */
+    @Input()
+    public variableIndex = 0;
 
     /** entêtes des colonnes */
     private _headers: string[];
@@ -35,33 +40,15 @@ export class PabResultsTableComponent extends ResultsComponentDirective {
         super();
     }
 
-    private getJetTypes(re: Result, vi: number): string {
-        // jet type for each device
-        const devices = re.sourceNub.getChildren();
-        const jetTypes: string[] = devices.map((device) => {
-            const jt = device.result.resultElements[vi].getValue("ENUM_StructureJetType");
-            let jetType = capitalize(this.intlService.localizeText("INFO_ENUM_STRUCTUREJETTYPE_" + jt));
-            if (devices.length > 1) {
-                // evil HTML injection in table cell (simpler)
-                jetType = this.intlService.localizeText("INFO_LIB_FS_OUVRAGE") + " n°"
-                    + (device.findPositionInParent() + 1) + ": " + jetType;
-            }
-            return jetType;
-        });
-        return `<div class="inner-cell-line">` + jetTypes.join(`, </div><div class="inner-cell-line">`) + `</div>`;
-    }
-
-    public set results(r: PabResults) {
-        this._pabResults = r;
-
+    public ngOnChanges() {
         this._dataSet = [];
         if (
-            this._pabResults
-            && this._pabResults.cloisonsResults
-            && this._pabResults.cloisonsResults.length > 0
-            && ! this._pabResults.hasOnlyErrors()
+            this.results
+            && this.results.cloisonsResults
+            && this.results.cloisonsResults.length > 0
+            && ! this.results.hasOnlyErrors()
         ) {
-            const pr = this._pabResults;
+            const pr = this.results;
             // when a parameter is variating, index of the variating parameter
             // values to build the data from
             const vi = pr.variableIndex;
@@ -134,6 +121,22 @@ export class PabResultsTableComponent extends ResultsComponentDirective {
         }
     }
 
+    private getJetTypes(re: Result, vi: number): string {
+        // jet type for each device
+        const devices = re.sourceNub.getChildren();
+        const jetTypes: string[] = devices.map((device) => {
+            const jt = device.result.resultElements[vi].getValue("ENUM_StructureJetType");
+            let jetType = this.intlService.localizeText("INFO_ENUM_STRUCTUREJETTYPE_" + jt);
+            if (devices.length > 1) {
+                // evil HTML injection in table cell (simpler)
+                jetType = this.intlService.localizeText("INFO_LIB_FS_OUVRAGE") + " n°"
+                    + (device.findPositionInParent() + 1) + ": " + jetType;
+            }
+            return jetType;
+        });
+        return `<div class="inner-cell-line">` + jetTypes.join(`, </div><div class="inner-cell-line">`) + `</div>`;
+    }
+
     public get headers() {
         return this._headers;
     }
diff --git a/src/app/components/pab-results/pab-results.component.html b/src/app/components/pab-results/pab-results.component.html
index 9bb311053cb44654634a6785c8f59407d48e36b8..a85d72bd6eccbb2ebbdc0e907be64613e3f58820 100644
--- a/src/app/components/pab-results/pab-results.component.html
+++ b/src/app/components/pab-results/pab-results.component.html
@@ -1,24 +1,27 @@
 <div class="container">
 
-    <log #generalLog [logTitle]="uitextGeneralLogTitle">log général</log>
+    <log [logTitle]="uitextGeneralLogTitle" [log]=globalLog>log général</log>
 
-    <variable-results-selector [results]="pabResults" (indexChange)="variableIndexChanged()">
+    <variable-results-selector [results]="pabResults" [variatedParameters]=pabResults?.variatedParameters>
     </variable-results-selector>
 
-    <log #iterationLog></log>
+    <log [log]=iterationLog></log>
 
     <div>
         <!-- tableau de résultats -->
-        <pab-results-table *ngIf="hasDisplayableResults" [results]="pabResults"></pab-results-table>
+        <pab-results-table *ngIf="hasDisplayableResults"
+          [results]=pabResults [variableIndex]=pabResults?.variableIndex>
+        </pab-results-table>
     </div>
 
     <quicknav *ngIf="hasDisplayableResults" [items]="[ 'input', 'results', 'charts' ]" [currentItem]="'charts'"
         [align]="'left'"></quicknav>
 
     <div id="pab-graphs-container" class="container" fxLayout="row wrap" fxLayoutAlign="space-around start">
-        <pab-profile-chart *ngIf="hasDisplayableResults" fxFlex.gt-xs="1 0 400px" fxFlex.lt-sm="1 0 300px">
+        <pab-profile-chart *ngIf="hasDisplayableResults" [results]=pabResults fxFlex.gt-xs="1 0 400px" fxFlex.lt-sm="1 0 300px">
         </pab-profile-chart>
-        <results-chart *ngIf="hasDisplayableResults" fxFlex.gt-xs="1 0 400px" fxFlex.lt-sm="1 0 300px">
+        <results-chart *ngIf="hasDisplayableResults" [results]=pabResults [resultData]=pabResults?.result
+          [variableIndex]=pabResults?.variableIndex fxFlex.gt-xs="1 0 400px" fxFlex.lt-sm="1 0 300px">
         </results-chart>
     </div>
 
diff --git a/src/app/components/pab-results/pab-results.component.ts b/src/app/components/pab-results/pab-results.component.ts
index 79551c24dc0ff2267f69f7a762ec763b23038ab1..bb190be6a1e861fcf81ffa3a2079ef2efd85ad72 100644
--- a/src/app/components/pab-results/pab-results.component.ts
+++ b/src/app/components/pab-results/pab-results.component.ts
@@ -1,18 +1,11 @@
-import { Component, ViewChild, DoCheck } from "@angular/core";
+import { Component, Input } from "@angular/core";
 
 import { Result, cLog, Message, MessageCode, MessageSeverity } from "jalhyd";
 
-import { LogComponent } from "../../components/log/log.component";
 import { CalculatorResults } from "../../results/calculator-results";
-import { NgParameter } from "../../formulaire/elements/ngparam";
-import { PabResultsTableComponent } from "./pab-results-table.component";
 import { PabResults } from "../../results/pab-results";
-import { VariableResultsSelectorComponent } from "../variable-results-selector/variable-results-selector.component";
-import { PlottableData } from "../../results/plottable-data";
-import { PlottablePabResults } from "../../results/plottable-pab-results";
-import { ResultsChartComponent } from "../results-chart/results-chart.component";
 import { I18nService } from "../../services/internationalisation.service";
-import { PabProfileChartComponent } from "../pab-profile-chart/pab-profile-chart.component";
+import { ResultsComponentDirective } from "../fixedvar-results/results.component";
 
 @Component({
     selector: "pab-results",
@@ -21,88 +14,23 @@ import { PabProfileChartComponent } from "../pab-profile-chart/pab-profile-chart
         "./pab-results.component.scss"
     ]
 })
-export class PabResultsComponent implements DoCheck {
+export class PabResultsComponent extends ResultsComponentDirective {
 
     /** résultats non mis en forme */
     private _pabResults: PabResults;
 
-    /** résultats mis en forme pour le graphique de données (classique) */
-    private _plottableResults: PlottablePabResults;
-
-    /** true si les résultats doiventt être remis à jour */
-    private _doUpdate = false;
-
-    @ViewChild(PabResultsTableComponent)
-    private pabResultsTableComponent: PabResultsTableComponent;
-
-    @ViewChild(VariableResultsSelectorComponent)
-    private variableResultsSelectorComponent: VariableResultsSelectorComponent;
-
-    @ViewChild("generalLog")
-    private generalLogComponent: LogComponent;
-
-    @ViewChild("iterationLog")
-    private iterationLogComponent: LogComponent;
-
-    @ViewChild(ResultsChartComponent)
-    private resultsChartComponent: ResultsChartComponent;
-
-    @ViewChild(PabProfileChartComponent)
-    private profileChartComponent: PabProfileChartComponent;
-
     constructor(
         private i18nService: I18nService,
     ) {
-        this._plottableResults = new PlottablePabResults();
+        super();
     }
 
+    @Input()
     public set results(rs: CalculatorResults[]) {
         this._pabResults = undefined;
         if (rs.length > 0 && rs[0] instanceof PabResults) {
             this._pabResults = rs[0] as PabResults;
         }
-        this.updateView();
-    }
-
-    /**
-     * update results table and chart when the variable index changed (event sent by
-     * VariableResultsSelectorComponent); variable index is already set in
-     * pabResults at this time
-     */
-    public variableIndexChanged() {
-        this.updateView();
-    }
-
-    public updateView() {
-        if (this.iterationLogComponent) {
-            this.iterationLogComponent.log = undefined;
-        }
-        if (this.generalLogComponent) {
-            this.generalLogComponent.log = undefined;
-        }
-        if (this.pabResultsTableComponent) {
-            this.pabResultsTableComponent.results = undefined;
-        }
-        if (this.variableResultsSelectorComponent) {
-            this.variableResultsSelectorComponent.results = undefined;
-        }
-        if (this.resultsChartComponent) {
-            this.resultsChartComponent.results = undefined;
-        }
-        if (this.profileChartComponent) {
-            this.profileChartComponent.results = undefined;
-        }
-        // set _doUpdate flag so that results are rebuilt on the next Angular display cycle
-        this._doUpdate = false;
-        if (this._pabResults !== undefined) {
-            this._doUpdate = this._doUpdate || this._pabResults.hasResults || this._pabResults.hasLog;
-        }
-    }
-
-    public ngDoCheck() {
-        if (this._doUpdate) {
-            this._doUpdate = !this.updateResults();
-        }
     }
 
     private mergeGlobalLog(result: Result, log: cLog) {
@@ -198,7 +126,7 @@ export class PabResultsComponent implements DoCheck {
      * du sélecteur d'itération : messages globaux et / ou résumé des messages
      * spécifiques à chaque ResultElement
      */
-    private get globalLog(): cLog {
+    public get globalLog(): cLog {
         const l = new cLog();
         if (this._pabResults && this.pabResults.variatedParameters.length > 0) {
             this.mergeGlobalLog(this._pabResults.result, l);
@@ -220,11 +148,11 @@ export class PabResultsComponent implements DoCheck {
     }
 
     /**
-     * Retourne les logs à afficher dans le composant de log global, au dessus
-     * du sélecteur d'itération : messages globaux et / ou résumé des messages
-     * spécifiques à chaque ResultElement
+     * Retourne les logs à afficher dans le composant de log local, en dessous
+     * du sélecteur d'itération : messages concernant l'itération (le ResultElement)
+     * en cours
      */
-    private get iterationLog(): cLog {
+    public get iterationLog(): cLog {
         const l = new cLog();
         if (this._pabResults) {
             if (this.pabResults.variatedParameters.length > 0) {
@@ -265,61 +193,10 @@ export class PabResultsComponent implements DoCheck {
         return l;
     }
 
-    /**
-     * met à jour l'affichage des résultats
-     * @returns true si les résultats ont pu être mis à jour
-     */
-    private updateResults() {
-        let pabUpdated: boolean;
-        let resultsChartUpdated: boolean;
-        let profileChartUpdated: boolean;
-        let selectorUpdated: boolean;
-
-        // results or not, there might be a log
-        const logUpdated = (this.iterationLogComponent !== undefined || this.generalLogComponent !== undefined); // gne ?
-        if (logUpdated) {
-            // order of logs is important !
-            this.iterationLogComponent.log = this.iterationLog;
-            this.generalLogComponent.log = this.globalLog;
-        }
-
-        if (this.hasResults) {
-            pabUpdated = this.pabResultsTableComponent !== undefined;
-            if (pabUpdated) {
-                this.pabResultsTableComponent.results = this._pabResults;
-            }
-            selectorUpdated = this.variableResultsSelectorComponent !== undefined;
-            if (selectorUpdated) {
-                this.variableResultsSelectorComponent.results = this._pabResults;
-            }
-            resultsChartUpdated = this.resultsChartComponent !== undefined;
-            if (resultsChartUpdated) {
-                this.resultsChartComponent.results = this.plottableResults;
-                this.resultsChartComponent.updateView();
-            }
-            profileChartUpdated = this.profileChartComponent !== undefined;
-            if (profileChartUpdated) {
-                this.profileChartComponent.results = this._pabResults;
-                this.profileChartComponent.updateView();
-            }
-        } else {
-            pabUpdated = true;
-            resultsChartUpdated = true;
-            profileChartUpdated = true;
-            selectorUpdated = true;
-        }
-
-        return pabUpdated && logUpdated && resultsChartUpdated && profileChartUpdated && selectorUpdated;
-    }
-
     public get pabResults() {
         return this._pabResults;
     }
 
-    public formattedLabel(p: NgParameter): string {
-        return CalculatorResults.paramLabel(p, false);
-    }
-
     public get hasResults(): boolean {
         return this._pabResults && this._pabResults.hasResults;
     }
@@ -343,10 +220,4 @@ export class PabResultsComponent implements DoCheck {
         return this.i18nService.localizeText("INFO_TITREJOURNAL_GLOBAL");
     }
 
-    /** builds a set of PlottableData from PabResults, to feed the chart */
-    protected get plottableResults(): PlottableData {
-        this._plottableResults.setPabResults(this.pabResults);
-        return this._plottableResults;
-    }
-
 }
diff --git a/src/app/components/pab-table/pab-table.component.ts b/src/app/components/pab-table/pab-table.component.ts
index 012f8773efe740d1c97475789dbeba12459f0a3c..b3c8934ecfc243a544c9a43a4aad2c119288d9b6 100644
--- a/src/app/components/pab-table/pab-table.component.ts
+++ b/src/app/components/pab-table/pab-table.component.ts
@@ -96,7 +96,7 @@ export class PabTableComponent implements AfterViewInit, OnInit {
 
     /** returns true if the cell has an underlying model (ie. is editable) */
     public hasModel(cell: any): boolean {
-        return (cell !== undefined && cell.model !== undefined);
+        return (cell?.model !== undefined);
     }
 
     /** returns true if the cell is an editable number */
@@ -124,7 +124,7 @@ export class PabTableComponent implements AfterViewInit, OnInit {
 
     /** "title" tooltip to display in a cell */
     public cellTitle(cell: any) {
-        if (cell !== undefined && cell.title !== undefined) {
+        if (cell?.title !== undefined) {
             return cell.title;
         } else {
             return "";
@@ -132,14 +132,14 @@ export class PabTableComponent implements AfterViewInit, OnInit {
     }
 
     public rowSpan(cell: any) {
-        if (cell !== undefined && cell.rowspan) {
+        if (cell?.rowspan) {
             return cell.rowspan;
         }
         return undefined;
     }
 
     public colSpan(cell: any) {
-        if (cell !== undefined && cell.colspan) {
+        if (cell?.colspan) {
             return cell.colspan;
         }
         return undefined;
diff --git a/src/app/components/pb-results/pb-cloison-results.component.ts b/src/app/components/pb-results/pb-cloison-results.component.ts
new file mode 100644
index 0000000000000000000000000000000000000000..0a59b6a8b1f0581e7ff07e706f24459e6e7df5ce
--- /dev/null
+++ b/src/app/components/pb-results/pb-cloison-results.component.ts
@@ -0,0 +1,43 @@
+import { Component, Input } from "@angular/core";
+
+import { FixedResultsComponent } from "../fixedvar-results/fixed-results.component";
+import { NgParameter } from "../../formulaire/elements/ngparam";
+import { getIthValue } from "../../util";
+import { PbCloisonResults } from "../../results/pb-cloison-results";
+
+import { Result, ResultElement } from "jalhyd";
+
+@Component({
+    selector: "pb-cloison-results",
+    templateUrl: "../fixedvar-results/fixed-results.component.html",
+    styleUrls: [
+        "../fixedvar-results/fixed-results.component.scss"
+    ]
+})
+export class PbCloisonResultsComponent extends FixedResultsComponent {
+
+    @Input()
+    public set results(r: PbCloisonResults) {
+        this._fixedResults = r;
+    }
+
+    public get results(): PbCloisonResults {
+        return this._fixedResults as PbCloisonResults;
+    }
+
+    /** Retourne la valeur du paramètre fixe… qui n'en est pas forcément un ici ! */
+    protected getFixedParamValue(fp: NgParameter): string {
+        let val: string;
+        if (fp.paramDefinition.hasMultipleValues) {
+            val = getIthValue(fp.paramDefinition, this.results.variableIndex, this.results.size);
+        } else {
+            val = this.formattedValue(fp.getValue());
+        }
+        return val;
+    }
+
+    /** Retourne l'élément de résultat en cours, en fonction de l'index variable */
+    protected getResultElement(r: Result): ResultElement {
+        return r.resultElements[this.results.variableIndex];
+    }
+}
diff --git a/src/app/components/pb-results/pb-results-table.component.html b/src/app/components/pb-results/pb-results-table.component.html
new file mode 100644
index 0000000000000000000000000000000000000000..75f0451ffc692eaf760d382fc2f1f57d05be633a
--- /dev/null
+++ b/src/app/components/pb-results/pb-results-table.component.html
@@ -0,0 +1,30 @@
+<div class="pb-results-table-container" #pbResultsTable fxLayout="row wrap" fxLayoutAlign="center center">
+    <div fxFlex="1 1 100%">
+        <div class="pb-results-table-buttons">
+            <button mat-icon-button (click)="exportAsSpreadsheet()" [title]="uitextExportAsSpreadsheet">
+                <mat-icon color="primary">file_download</mat-icon>
+            </button>
+            <button mat-icon-button *ngIf="! isFullscreen" (click)="setFullscreen(pbResultsTable)" [title]="uitextEnterFSTitle">
+                <mat-icon color="primary" class="scaled12">fullscreen</mat-icon>
+            </button>
+            <button mat-icon-button *ngIf="isFullscreen" (click)="exitFullscreen()" [title]="uitextExitFSTitle">
+                <mat-icon color="primary" class="scaled12">fullscreen_exit</mat-icon>
+            </button>
+        </div>
+
+        <div class="pb-results-table-scrollable-container" [ngClass]="{'full-height': isFullscreen}">
+            <!-- scrollable -->
+            <div class="pb-results-table-inner-container" #tableContainer>
+                <table mat-table [dataSource]="dataSet">
+                    <ng-container *ngFor="let h of headers; let i = index" [matColumnDef]="h">
+                        <th mat-header-cell *matHeaderCellDef [innerHTML]="h"></th>
+                        <td mat-cell *matCellDef="let element" [innerHTML]="element[i]"></td>
+                    </ng-container>
+
+                    <tr mat-header-row *matHeaderRowDef="headers"></tr>
+                    <tr mat-row *matRowDef="let row; columns: headers;"></tr>
+                </table>
+            </div>
+        </div>
+    </div>
+</div>
diff --git a/src/app/components/pb-results/pb-results-table.component.scss b/src/app/components/pb-results/pb-results-table.component.scss
new file mode 100644
index 0000000000000000000000000000000000000000..9e49c5ca0d3a6dc21ed1e49e943311bff2a49307
--- /dev/null
+++ b/src/app/components/pb-results/pb-results-table.component.scss
@@ -0,0 +1,52 @@
+/** @see additional styles in src/styles.css */
+
+:host {
+    display: block;
+    margin-bottom: 1.5em;
+}
+
+.pb-results-table-container {
+    background-color: white;
+}
+
+.pb-results-table-buttons {
+    padding-right: 4px;
+    padding-top: 4px;
+    text-align: right;
+    background-color: white;
+
+    button {
+        margin-left: 3px;
+        width: auto;
+
+        mat-icon {
+            &.scaled12 {
+                transform: scale(1.2)
+            }
+        }
+    }
+}
+
+.pb-results-table-scrollable-container {
+    overflow-x: scroll;
+    border: solid #ccc 1px;
+
+    &.full-height {
+        height: calc(100vh - 40px); // rend le mode plein-écran scrollable verticalement, sinon ça dépasse
+    }
+}
+
+table.mat-table {
+
+    .mat-header-row {
+        height: 40px;
+    }
+
+    .mat-row {
+        height: 32px;
+
+        &:nth-child(odd) {
+            background-color: #f4f4f4;
+        }
+    }
+}
diff --git a/src/app/components/pb-results/pb-results-table.component.ts b/src/app/components/pb-results/pb-results-table.component.ts
new file mode 100644
index 0000000000000000000000000000000000000000..c5d8dff4d32791788ce5c62a4e40b1a6acce13da
--- /dev/null
+++ b/src/app/components/pb-results/pb-results-table.component.ts
@@ -0,0 +1,129 @@
+import { Component, ViewChild, ElementRef, Input } from "@angular/core";
+
+import { PreBarrage, PbBassin } from "jalhyd";
+
+import { I18nService } from "../../services/internationalisation.service";
+import { ResultsComponentDirective } from "../fixedvar-results/results.component";
+import { AppComponent } from "../../app.component";
+import { fv, getIthValue } from "../../util";
+import { PrebarrageResults } from "../../results/prebarrage-results";
+
+@Component({
+    selector: "pb-results-table",
+    templateUrl: "./pb-results-table.component.html",
+    styleUrls: [
+        "./pb-results-table.component.scss"
+    ]
+})
+export class PbResultsTableComponent extends ResultsComponentDirective {
+
+    /** résultats non mis en forme */
+    private _pbResults: PrebarrageResults;
+
+    /** entêtes des colonnes */
+    private _headers: string[];
+
+    /** résultats mis en forme */
+    private _dataSet: any[];
+
+    @ViewChild("tableContainer")
+    table: ElementRef;
+
+    constructor(
+        protected intlService: I18nService
+    ) {
+        super();
+    }
+
+    @Input()
+    public set results(r: PrebarrageResults) {
+        this._pbResults = r;
+
+        this._dataSet = [];
+        if (
+            this._pbResults
+            && this._pbResults.bassinsResults
+            && this._pbResults.bassinsResults.length > 0
+            && ! this._pbResults.hasOnlyErrors()
+        ) {
+            const pr = this._pbResults;
+            const pb = pr.result.sourceNub as PreBarrage;
+            // when a parameter is variating, index of the variating parameter
+            // values to build the data from
+            const vi = pr.variableIndex;
+
+            // @TODO results.size ? To extend values lists…
+
+            // refresh headers here if language changed
+            this._headers = pr.headers;
+
+            // upstream line
+            if (pr.result.resultElements[vi].vCalc) { // le calcul peut avoir échoué
+                this._dataSet.push([
+                    this.intlService.localizeText("INFO_LIB_AMONT"),
+                    "", "",
+                    getIthValue(pb.prms.Z1, vi, this._pbResults.size),
+                    "", "",
+                    getIthValue(pb.prms.Q, vi, this._pbResults.size),
+                ]);
+            }
+
+            // basins 1 - n
+            for (let i = 0; i < pr.bassinsResults.length; i++) {
+                if (
+                    Object.keys(pr.bassinsResults[i].resultElements[vi].values).length > 0 // no vCalc in this case
+                ) {
+                    const rb = pr.bassinsResults[i].resultElements[vi].values;
+                    const basin = pr.bassinsResults[i].sourceNub as PbBassin;
+                    this._dataSet.push([
+                        i + 1, // n° cloison
+                        fv(basin.prms.S.V),
+                        fv(basin.prms.ZF.V),
+                        fv(rb.Z),
+                        fv(rb.PV),
+                        fv(rb.YMOY),
+                        fv(rb.Q)
+                    ]);
+                }
+            }
+
+            // downstream line
+            if (pr.result.resultElements[vi].vCalc) { // le calcul peut avoir échoué
+                this._dataSet.push([
+                    this.intlService.localizeText("INFO_LIB_AVAL"),
+                    "", "",
+                    getIthValue(pb.prms.Z2, vi, this._pbResults.size),
+                    "", "",
+                    getIthValue(pb.prms.Q, vi, this._pbResults.size),
+                ]);
+            }
+        }
+    }
+
+    public get headers() {
+        return this._headers;
+    }
+
+    /**
+     * Returns a combination of parameters and results for mat-table
+     */
+    public get dataSet() {
+        return this._dataSet;
+    }
+
+    public exportAsSpreadsheet() {
+        AppComponent.exportAsSpreadsheet(this.table.nativeElement);
+    }
+
+    public get uitextExportAsSpreadsheet() {
+        return this.intlService.localizeText("INFO_RESULTS_EXPORT_AS_SPREADSHEET");
+    }
+
+    public get uitextEnterFSTitle() {
+        return this.intlService.localizeText("INFO_CHART_BUTTON_TITLE_ENTER_FS");
+    }
+
+    public get uitextExitFSTitle() {
+        return this.intlService.localizeText("INFO_CHART_BUTTON_TITLE_EXIT_FS");
+    }
+}
diff --git a/src/app/components/pb-results/pb-results.component.html b/src/app/components/pb-results/pb-results.component.html
new file mode 100644
index 0000000000000000000000000000000000000000..ae300910591b90d0c0ca1b78533013200d91d379
--- /dev/null
+++ b/src/app/components/pb-results/pb-results.component.html
@@ -0,0 +1,25 @@
+<div class="container">
+    <log [logTitle]="uitextGeneralLogTitle" [log]=globalLog>log général</log>
+
+    <variable-results-selector [results]=pbResults>
+    </variable-results-selector>
+
+    <log [log]=iterationLog></log>
+
+    <!-- tableau de résultats des bassins -->
+    <pb-results-table *ngIf="hasBasinResults" [results]=pbResults></pb-results-table>
+
+    <!-- table des résultats fixés -->
+    <pb-cloison-results *ngIf="hasWallResults" [results]=pbResults.cloisonResults></pb-cloison-results>
+
+    <!-- <quicknav *ngIf="hasDisplayableResults" [items]="[ 'input', 'results', 'charts' ]"
+        [currentItem]="'charts'" [align]="'left'"></quicknav> -->
+
+    <!-- <div id="pb-graphs-container" class="container" fxLayout="row wrap" fxLayoutAlign="space-around start">
+        <pb-profile-chart *ngIf="hasDisplayableResults" fxFlex.gt-xs="1 0 400px" fxFlex.lt-sm="1 0 300px">
+        </pb-profile-chart>
+        <results-chart *ngIf="hasDisplayableResults" fxFlex.gt-xs="1 0 400px" fxFlex.lt-sm="1 0 300px">
+        </results-chart>
+    </div> -->
+
+</div>
diff --git a/src/app/components/pb-results/pb-results.component.scss b/src/app/components/pb-results/pb-results.component.scss
new file mode 100644
index 0000000000000000000000000000000000000000..446313ba6da367fde3da7c3b760e39086f71a804
--- /dev/null
+++ b/src/app/components/pb-results/pb-results.component.scss
@@ -0,0 +1,4 @@
+results-chart {
+    margin-left: 1em;
+    margin-right: 1em;
+}
diff --git a/src/app/components/pb-results/pb-results.component.ts b/src/app/components/pb-results/pb-results.component.ts
new file mode 100644
index 0000000000000000000000000000000000000000..b502c4e40fe2335c1688ddc7028aa7112bc105c6
--- /dev/null
+++ b/src/app/components/pb-results/pb-results.component.ts
@@ -0,0 +1,218 @@
+import { Component, Input } from "@angular/core";
+
+import { CalculatorResults } from "../../results/calculator-results";
+import { PrebarrageResults } from "../../results/prebarrage-results";
+import { I18nService } from "../../services/internationalisation.service";
+
+import { cLog } from "jalhyd";
+
+@Component({
+    selector: "pb-results",
+    templateUrl: "./pb-results.component.html",
+    styleUrls: [
+        "./pb-results.component.scss"
+    ]
+})
+export class PbResultsComponent {
+
+    /** résultats des bassins, non mis en forme */
+    private _pbResults: PrebarrageResults;
+
+    constructor(
+        private i18nService: I18nService,
+    ) { }
+
+    @Input()
+    public set results(rs: CalculatorResults[]) {
+        this._pbResults = undefined;
+        for (const r of rs) {
+            if (r instanceof PrebarrageResults) {
+                this._pbResults = r as PrebarrageResults;
+            }
+        }
+    }
+
+    public get pbResults() {
+        return this._pbResults;
+    }
+
+    // true if any result is present
+    public get hasResults(): boolean {
+        return this._pbResults && this._pbResults.hasResults;
+    }
+
+    // true if basin results are present
+    public get hasBasinResults(): boolean {
+        return this._pbResults && this._pbResults.hasBasinResults;
+    }
+
+    // true if wall results are present
+    public get hasWallResults(): boolean {
+        return this._pbResults && this._pbResults.hasWallResults;
+    }
+
+    /* private mergeGlobalLog(result: Result, log: cLog) {
+        if (result) {
+            if (result.hasGlobalLog()) {
+                log.addLog(result.globalLog);
+            }
+            // if no parameter is varying, 1st element log is considered "global"
+            if (this.pbResults.variatedParameters.length === 0) {
+                if (result.hasResultElements() && result.resultElement.hasLog()) {
+                    log.addLog(result.log);
+                }
+            }
+        }
+    } */
+
+    /**
+     * Returns the number of errors, warnings, infos among children logs
+     */
+    /* private logStats(): any {
+        const ret = {
+            info: 0,
+            warning: 0,
+            error: 0
+        };
+        if (this._pbResults.result && this._pbResults.result.hasLog()) {
+            for (const re of this._pbResults.result.resultElements) {
+                if (re.hasLog()) {
+                    for (const m of re.log.messages) {
+                        const s = m.getSeverity();
+                        switch (s) {
+                            case MessageSeverity.INFO:
+                                ret.info ++;
+                                break;
+                            case MessageSeverity.WARNING:
+                                ret.warning ++;
+                                break;
+                            case MessageSeverity.ERROR:
+                                ret.error ++;
+                                break;
+                        }
+                    }
+                }
+            }
+        }
+        for (const cr of this._pbResults.cloisonsResults) {
+            if (cr && cr.hasLog()) {
+                for (const re of cr.resultElements) {
+                    if (re.hasLog()) {
+                        for (const m of re.log.messages) {
+                            const s = m.getSeverity();
+                            switch (s) {
+                                case MessageSeverity.INFO:
+                                    ret.info ++;
+                                    break;
+                                case MessageSeverity.WARNING:
+                                    ret.warning ++;
+                                    break;
+                                case MessageSeverity.ERROR:
+                                    ret.error ++;
+                                    break;
+                            }
+                        }
+                    }
+                }
+            }
+        }
+        if (this._pbResults.cloisonAvalResults && this._pbResults.cloisonAvalResults.hasLog()) {
+            for (const re of this._pbResults.cloisonAvalResults.resultElements) {
+                if (re.hasLog()) {
+                    for (const m of re.log.messages) {
+                        const s = m.getSeverity();
+                        switch (s) {
+                            case MessageSeverity.INFO:
+                                ret.info ++;
+                                break;
+                            case MessageSeverity.WARNING:
+                                ret.warning ++;
+                                break;
+                            case MessageSeverity.ERROR:
+                                ret.error ++;
+                                break;
+                        }
+                    }
+                }
+            }
+        }
+        return ret;
+    } */
+
+    /*
+     * Retourne les logs à afficher dans le composant de log global, au dessus
+     * du sélecteur d'itération : messages globaux et / ou résumé des messages
+     * spécifiques à chaque ResultElement
+     */
+    public get globalLog(): cLog {
+        const l = new cLog();
+        /* if (this._pbResults && this.pbResults.variatedParameters.length > 0) {
+            this.mergeGlobalLog(this._pbResults.result, l);
+            // un problème avec la PAB en général / les cloisons, à une étape quelconque ?
+            if (
+                (this.pbResults.hasLog)
+                && l.messages.length === 0 // existing global messages make generic message below useless
+            ) {
+                const logStats = this.logStats();
+                const m = new Message(MessageCode.WARNING_PROBLEMS_ENCOUNTERED);
+                m.extraVar.info = "" + logStats.info; // to avoid displaying fixed number of digits
+                m.extraVar.warning = "" + logStats.warning;
+                m.extraVar.error = "" + logStats.error;
+                l.add(m);
+                // l.add(new Message(MessageCode.WARNING_PROBLEMS_ENCOUNTERED));
+            }
+        } // sinon pas de log global (aucun paramètre ne varie) */
+        return l;
+    }
+
+    /**
+     * Retourne les logs à afficher dans le composant de log local, en dessous
+     * du sélecteur d'itération : messages concernant l'itération (le ResultElement)
+     * en cours
+     */
+    public get iterationLog(): cLog {
+        const l = new cLog();
+        /* if (this._pabResults) {
+            if (this.pabResults.variatedParameters.length > 0) {
+                // A. si un paramètre varie
+                const vi = this._pabResults.variableIndex;
+                // log de la PAB pour l'itération en cours
+                if (
+                    this._pabResults.result
+                    && this._pabResults.result.hasResultElements()
+                    && this._pabResults.result.resultElements[vi]
+                    && this._pabResults.result.resultElements[vi].hasLog()
+                ) {
+                    l.addLog(this._pabResults.result.resultElements[vi].log);
+                }
+                // logs des enfants pour l'itération en cours
+                for (const cr of this._pabResults.cloisonsResults) {
+                    if (cr && cr.hasResultElements() && cr.resultElements[vi].hasLog()) {
+                        l.addLog(cr.resultElements[vi].log);
+                    }
+                }
+                if (this._pabResults.cloisonAvalResults && this._pabResults.cloisonAvalResults.resultElements[vi].hasLog()) {
+                    l.addLog(this._pabResults.cloisonAvalResults.resultElements[vi].log);
+                }
+            } else {
+                // B. si aucun paramètre ne varie
+                this.mergeGlobalLog(this._pabResults.result, l); // faut bien mettre le log global quelque part
+                // logs des enfants
+                for (const cr of this._pabResults.cloisonsResults) {
+                    if (cr && cr.hasResultElements() && cr.resultElement.hasLog()) {
+                        l.addLog(cr.resultElement.log);
+                    }
+                }
+                if (this._pabResults.cloisonAvalResults && this._pabResults.cloisonAvalResults.resultElement.hasLog()) {
+                    l.addLog(this._pabResults.cloisonAvalResults.resultElement.log);
+                }
+            }
+        } */
+        return l;
+    }
+
+    public get uitextGeneralLogTitle(): string {
+        return this.i18nService.localizeText("INFO_TITREJOURNAL_GLOBAL");
+    }
+
+}
diff --git a/src/app/components/pb-schema/pb-schema.component.html b/src/app/components/pb-schema/pb-schema.component.html
new file mode 100644
index 0000000000000000000000000000000000000000..b9314c653190799eee8a29ec3d40acae2f9002e2
--- /dev/null
+++ b/src/app/components/pb-schema/pb-schema.component.html
@@ -0,0 +1,51 @@
+<mat-card-header class="mat-card-header-text-margin-0 bg-accent-light" [ngClass]="{'side': ! showInputData}">
+    <mat-card-title>
+        {{ title }}
+    </mat-card-title>
+</mat-card-header>
+
+<mat-card-content>
+
+    <div id="pb-schema-toolbar">
+
+        <button type="button" id="add-basin" mat-raised-button color="accent" (click)="onAddBasinClick()">
+            {{ uitextAddBasin }}
+        </button>
+
+        <button type="button" id="add-wall" mat-raised-button color="accent" (click)="onAddWallClick()" [disabled]="! enableAddWallButton">
+            {{ uitextAddWall }}
+        </button>
+
+        <div class="hyd-window-btns">
+            <span class="related-entity-title">
+                {{ prefixedItemDescription }}
+            </span>
+            <button type="button" mat-icon-button color="primary" [disabled]="! enableCopyButton" (click)="onCopyClick()"
+              [title]="uitextCopy">
+                <mat-icon>content_copy</mat-icon>
+            </button>
+          |
+            <button type="button" mat-icon-button color="primary" [disabled]="! enableRemoveButton" (click)="onRemoveClick()"
+              [title]="uitextRemove">
+                <mat-icon>delete</mat-icon>
+            </button>
+            <button type="button" mat-icon-button [disabled]="! enableUpButton" (click)="onMoveBasinUpClick()" [title]="uitextMoveBasinUp">
+                <mat-icon>arrow_upward</mat-icon>
+            </button>
+            <button type="button" mat-icon-button [disabled]="! enableDownButton" (click)="onMoveBasinDownClick()" [title]="uitextMoveBasinDown">
+                <mat-icon>arrow_downward</mat-icon>
+            </button>
+            <!-- 
+            |
+            <button type="button" mat-icon-button color="primary" (click)="exportAsSpreadsheet()"
+              [title]="uitextExportAsSpreadsheet">
+                <mat-icon color="primary">file_download</mat-icon>
+            </button> -->
+        </div>
+    </div>
+
+    <div id="schema" #schema></div>
+
+    <pre id="debug">{{ graphDef }} </pre>
+
+</mat-card-content>
diff --git a/src/app/components/pb-schema/pb-schema.component.scss b/src/app/components/pb-schema/pb-schema.component.scss
new file mode 100644
index 0000000000000000000000000000000000000000..72baa1eddf75dd87f56fcb64057f22af2bab8d93
--- /dev/null
+++ b/src/app/components/pb-schema/pb-schema.component.scss
@@ -0,0 +1,64 @@
+/** @see additional styles in src/styles.css */
+
+:host {
+    display: block;
+    width: 100%;
+}
+
+mat-card-header {
+    margin-left: -16px;
+    margin-right: -16px;
+    padding-left: 16px;
+    padding-top: 8px;
+    color: white;
+
+    &.side {
+        margin-right: -32px;
+    }
+
+    mat-card-title {
+        font-size: 16px !important;
+        margin-bottom: 8px;
+    }
+}
+
+mat-card-content {
+    margin-top: 1em;
+}
+
+#pb-schema-toolbar {
+    #add-basin {
+        float: left;
+    }
+    #add-wall {
+        float: left;
+        margin-left: .5em;
+    }
+    .related-entity-title {
+        vertical-align: middle;
+        font-weight: bold;
+        display: none; // @TODO show it in a way that doesn't make the buttons fall on the next line ?
+    }
+    .hyd-window-btns {
+        text-align: right;
+
+        #add-many-children {
+            width: 3em;
+            vertical-align: middle;
+        }
+
+        button.mat-icon-button {
+            width: 32px;
+        }
+    }
+}
+
+#schema {
+    margin-top: .5em;
+    margin-bottom: .5em;
+    text-align: center;
+}
+
+#debug {
+    display: none;
+}
diff --git a/src/app/components/pb-schema/pb-schema.component.ts b/src/app/components/pb-schema/pb-schema.component.ts
new file mode 100644
index 0000000000000000000000000000000000000000..bf924160d42a8a0514d317029e9be76189ff11c8
--- /dev/null
+++ b/src/app/components/pb-schema/pb-schema.component.ts
@@ -0,0 +1,532 @@
+import { Component, Input, Output, EventEmitter, OnInit, AfterViewInit, ViewChild, Inject, forwardRef, AfterContentInit } from "@angular/core";
+import { MatDialog } from "@angular/material/dialog";
+
+import {
+    PreBarrage, PbBassin, PbBassinParams, PbCloison, Observer, IObservable
+ } from "jalhyd";
+
+import * as mermaid from "mermaid";
+
+import { HotkeysService, Hotkey } from "angular2-hotkeys";
+
+import { I18nService } from "../../services/internationalisation.service";
+import { PbSchema } from "../../formulaire/elements/pb-schema";
+import { DialogNewPbCloisonComponent } from "../dialog-new-pb-cloison/dialog-new-pb-cloison.component";
+import { GenericCalculatorComponent } from "../generic-calculator/calculator.component";
+import { AppComponent } from "../../app.component";
+
+/**
+ * The interactive schema for calculator type "PreBarrage" (component)
+ */
+@Component({
+    selector: "pb-schema",
+    templateUrl: "./pb-schema.component.html",
+    styleUrls: [
+        "./pb-schema.component.scss"
+    ]
+})
+export class PbSchemaComponent implements AfterViewInit, AfterContentInit, OnInit, Observer {
+
+    @Input()
+    private pbSchema: PbSchema;
+
+    @ViewChild("schema", { static: true })
+    public schema: any;
+
+    /** handle on SVG container */
+    private nativeElement: any;
+
+    /** flag de validité du composant */
+    private _isValid = false;
+
+    private upstreamId = "amont";
+
+    private downstreamId = "aval";
+
+    /** événément de changement de validité */
+    @Output()
+    private validChange = new EventEmitter();
+
+    /** événément de sélection d'un nœud du graphique Mermaid */
+    @Output()
+    private nodeSelected = new EventEmitter();
+
+    /** underlying PB */
+    private model: PreBarrage;
+
+    /** Latest clicked item: a PbCloison, a PbBassin or undefined if river "Upstream" or "Downstream" was clicked */
+    private _selectedItem: PbCloison | PbBassin;
+
+    /** Records existing walls as they are built, to detect if multiple walls connect the same pair of basins */
+    private existingWalls: { [key: string]: number };
+
+    public constructor(
+        @Inject(forwardRef(() => GenericCalculatorComponent)) private calculatorComponent: GenericCalculatorComponent,
+        private i18nService: I18nService,
+        private hotkeysService: HotkeysService,
+        private newPbCloisonDialog: MatDialog
+    ) {
+        this.hotkeysService.add(new Hotkey("del", AppComponent.onHotkey(this.removeOnHotkey, this)));
+    }
+
+    public get selectedItem(): any {
+        return this._selectedItem;
+    }
+
+    public ngAfterContentInit(): void {
+        mermaid.initialize({
+            flowchart: {
+                curve: "basis",
+                useMaxWidth: true
+            }
+        });
+        this.nativeElement = this.schema.nativeElement;
+        this.render();
+        // restore previously selected item
+        this._selectedItem = this.pbSchema.form.selectedItem;
+        if (this._selectedItem !== undefined) {
+            // @WARNING clodo timeout to prevent ExpressionChangedAfterItHasBeenCheckedError
+            // and select schema node after schema is refreshed by ngAfterViewInit()
+            setTimeout(() => {
+                this.selectNodeOnSchema(this._selectedItem);
+            }, 20); // timeout has to be greater than the 10ms of ngAfterViewInit()
+        }
+    }
+
+    private render() {
+        this.nativeElement.innerHTML = ""; // or diagram goes blank when refreshing…
+        // generate graph description
+        const graphDefinition = this.graphDefinition();
+        // draw
+        try {
+            mermaid.render("graphDiv", graphDefinition, (svgCode, bindFunctions) => {
+                this.nativeElement.innerHTML = svgCode;
+            });
+        } catch (e) {
+            console.error(e);
+        }
+    }
+
+    /**
+     * Builds the interactive schema from the PreBarrage model
+     */
+    private refresh() {
+        this.render();
+        this.refreshEventListeners();
+        this.updateValidity();
+    }
+
+    public ngAfterViewInit(): void {
+        // subscribe to "refresh" event passed indirectly by FormulairePbCloison (change upstream/downstream basin)
+        this.pbSchema.addObserver(this);
+        // @WARNING clodo trick to prevent blank diagram when switching from a PreBarrage to another
+        setTimeout(() => {
+            this.refresh();
+        }, 10);
+    }
+
+    /** Add click listener on every node and link in the graph */
+    private refreshEventListeners() {
+        this.nativeElement.querySelectorAll("g.node").forEach(item => {
+            item.style.cursor = "pointer";
+            item.addEventListener("click", () => {
+                this.selectNode(item);
+            });
+        });
+    }
+
+    /**
+     * Builds a Mermaid graph text definition, using Nodes
+     * to represent basins as well as walls; sorts connexions
+     * to prevent lines crossings
+     */
+    private graphDefinition() {
+        this.existingWalls = {};
+        this.pbSchema.wallsSuffixes = {};
+        const def: string[] = [ "graph TB" ];
+
+        // river upstream / downstream
+        def.push(`${this.upstreamId}("${this.i18nService.localizeText("INFO_LIB_AMONT")}")`);
+        def.push(`${this.downstreamId}("${this.i18nService.localizeText("INFO_LIB_AVAL")}")`);
+
+        // styles
+        def.push("classDef wall fill:#e8e8e8,stroke-width:0;");
+        def.push("classDef basin fill:#e0f3fb,stroke:#003A80;"); // irstea-ocean 50 / 500
+        def.push("classDef node-highlighted fill:#4DBBE9;"); // irstea-ocean (material "accent"), 300
+
+        const sortedWalls: PbCloison[] = [];
+        for (const c of this.model.children) {
+            if (c instanceof PbBassin) {
+                def.push(`${c.uid}("${this.itemDescription(c)}")`); // rounded edges
+                def.push(`class ${c.uid} basin;`);
+            } else if (c instanceof PbCloison) {
+                // store, to draw later
+                sortedWalls.push(c);
+            }
+        }
+        // sort then draw walls
+        sortedWalls.sort(this.triCloisonsGaucheDroite);
+        for (const c of sortedWalls) {
+            const upstreamBasinId = c.bassinAmont === undefined ? this.upstreamId : c.bassinAmont.uid;
+            const downstreamBasinId = c.bassinAval === undefined ? this.downstreamId : c.bassinAval.uid;
+            // record this wall
+            const basinsPair = upstreamBasinId + "-" + downstreamBasinId;
+            if (! (basinsPair in this.existingWalls)) {
+                this.existingWalls[basinsPair] = 0;
+            }
+            // affect suffix if needed
+            if (this.existingWalls[basinsPair] > 0) {
+                this.pbSchema.wallsSuffixes[c.uid] = this.existingWalls[basinsPair];
+            }
+            this.existingWalls[basinsPair]++;
+            // draw wall Node
+            def.push(`${c.uid}["${this.itemDescription(c)}"]`); // square edges
+            def.push(`class ${c.uid} wall;`);
+            // draw "arrow" with 2 lines
+            def.push(`${upstreamBasinId}---${c.uid}-->${downstreamBasinId}`);
+        }
+
+        return def.join("\n");
+    }
+
+    /** gauche d'abord, droite ensuite */
+    private triCloisonsGaucheDroite(a: PbCloison, b: PbCloison) {
+        // ultra-gauchistes
+        if (a.bassinAmont === undefined && a.bassinAval === undefined) {
+            return -1;
+        }
+        if (b.bassinAmont === undefined && b.bassinAval === undefined) {
+            return 1;
+        }
+        // si A est un super-gauchiste
+        if (a.bassinAmont === undefined || a.bassinAval === undefined) {
+            // B est-il aussi un super-gauchiste ?
+            if (b.bassinAmont === undefined || b.bassinAval === undefined) {
+                // comparer le bassin restant
+                const bassinA = (a.bassinAmont === undefined ? a.bassinAval : a.bassinAmont);
+                const bassinB = (b.bassinAmont === undefined ? b.bassinAval : b.bassinAmont);
+                return (bassinA.findPositionInParent() <= bassinB.findPositionInParent()) ? -1 : 1;
+            }
+            // sinon A gagne
+            return -1;
+        }
+        // si B est un super-gauchiste
+        if (b.bassinAmont === undefined || b.bassinAval === undefined) {
+            // B gagne (le cas de A super-gauchiste est éliminé avant)
+            return 1;
+        }
+        // sinon, aucun des deux n'est super-gauchiste, comparaison des bassins amont et aval
+        const sommeA = a.bassinAmont.findPositionInParent() + a.bassinAval.findPositionInParent();
+        const sommeB = b.bassinAmont.findPositionInParent() + b.bassinAval.findPositionInParent();
+        return (sommeA <= sommeB ? -1 : 1);
+    }
+
+    private selectNode(item: any) {
+        // highlight clicked element
+        this.clearHighlightedItems();
+        item.classList.add("node-highlighted");
+        // find what was clicked
+        if ([ this.upstreamId, this.downstreamId ].includes(item.id)) {
+            this._selectedItem = undefined;
+        } else {
+            this._selectedItem = this.model.findChild(item.id);
+        }
+        // show proper form and hide results
+        this.nodeSelected.emit({
+            node: this._selectedItem
+        });
+    }
+
+    // for debug only
+    public get graphDef(): string {
+        return this.graphDefinition();
+    }
+
+    public get title(): string {
+        return this.i18nService.localizeText("INFO_PB_SCHEMA");
+    }
+
+    /** Global Pb validity */
+    public get isValid() {
+        return this._isValid;
+    }
+
+    /** used for a cosmetics CSS trick only (mat-card-header right margin) */
+    public get showInputData(): boolean {
+        return this.calculatorComponent.showPBInputData;
+    }
+
+    public get prefixedItemDescription(): string {
+        let desc = this.itemDescription(this._selectedItem);
+        if (this._selectedItem instanceof PbCloison) {
+            desc = this.i18nService.localizeText("INFO_PB_CLOISON") + " " + desc;
+        }
+        if (desc !== "") {
+            desc += " : ";
+        }
+        return desc;
+    }
+
+    /** Returns a short description of the given item: wall or basin */
+    private itemDescription(item: PbCloison | PbBassin): string {
+        let desc = "";
+        if (item !== undefined) {
+            desc = this.i18nService.localizeMessage(item.description);
+            if (item instanceof PbCloison) {
+                // there might be multiple walls between the same pair of basins
+                if (item.uid in this.pbSchema.wallsSuffixes) {
+                    desc += " (" + this.pbSchema.wallsSuffixes[item.uid] + ")";
+                }
+            }
+        }
+        return desc;
+    }
+
+    /**
+     * Selects and highlights on the schema the given wall or basin
+     */
+    private selectNodeOnSchema(element: PbBassin | PbCloison) {
+        this.nativeElement.querySelectorAll("g.node").forEach(item => {
+            if (item.id === element.uid) {
+                this.selectNode(item);
+            }
+        });
+    }
+
+    // at this time @Input data is supposed to be already populated
+    public ngOnInit() {
+        this.model = this.pbSchema.pb;
+    }
+
+    public get enableRemoveButton() {
+        if (this._selectedItem === undefined) {
+            return false;
+        }
+        // if deleting a PbCloison would replace it by a new one at
+        // the same place (@see onRemoveClick), make it not deletable
+        if (this._selectedItem instanceof PbCloison) {
+            if ((
+                this._selectedItem.bassinAmont !== undefined
+                && this._selectedItem.bassinAmont.cloisonsAval.length === 1
+                && this._selectedItem.bassinAval === undefined
+            ) || (
+                this._selectedItem.bassinAval !== undefined
+                && this._selectedItem.bassinAval.cloisonsAmont.length === 1
+                && this._selectedItem.bassinAmont === undefined
+            )) {
+                return false;
+            }
+        }
+        return true;
+    }
+
+    /** Removes a basin or wall, and all related items */
+    public onRemoveClick() {
+        this.model.deleteChild(this._selectedItem.findPositionInParent());
+        // never let an unconnected basin ! (not done in model to prevent unwanted
+        // automatic child addition when clearing children)
+        if (this._selectedItem instanceof PbCloison) {
+            // if no downstream connections remain, connect to river downstream
+            if (this._selectedItem.bassinAmont?.cloisonsAval.length === 0) {
+                this.model.addChild(new PbCloison(this._selectedItem.bassinAmont, undefined));
+            }
+            // if no upstream connections remain, connect to river upstream
+            if (this._selectedItem.bassinAval?.cloisonsAmont.length === 0) {
+                this.model.addChild(new PbCloison(undefined, this._selectedItem.bassinAval));
+            }
+        }
+        this.unselect();
+        this.refresh();
+        this.clearResults();
+        this.calculatorComponent.showPBInputData = true;
+    }
+
+    public get uitextRemove() {
+        return this.i18nService.localizeText("INFO_FIELDSET_REMOVE");
+    }
+
+    // listener for "del" hotkey
+    protected removeOnHotkey() {
+        if (this.enableRemoveButton) {
+            this.onRemoveClick();
+        }
+    }
+
+    public get enableCopyButton() {
+        return (this._selectedItem !== undefined && this._selectedItem instanceof PbCloison);
+    }
+
+    /** Copies a wall */
+    public onCopyClick() {
+        const wall = this._selectedItem as PbCloison;
+        const wallCopy = new PbCloison(wall.bassinAmont, wall.bassinAval);
+        wallCopy.loadObjectRepresentation(wall.objectRepresentation());
+        this.model.addChild(wallCopy);
+        this.unselect();
+        this.refresh();
+        this.selectNodeOnSchema(wallCopy);
+        this.clearResults();
+    }
+
+    public get uitextCopy() {
+        return this.i18nService.localizeText("INFO_FIELDSET_COPY");
+    }
+
+    /** Adds a new lone basin */
+    public onAddBasinClick() {
+        const newBasin = new PbBassin(new PbBassinParams(20, 99));
+        this.model.addChild(newBasin);
+        this.unselect();
+        this.refresh();
+        this.selectNodeOnSchema(newBasin);
+        this.clearResults();
+    }
+
+    public get uitextAddBasin() {
+        return this.i18nService.localizeText("INFO_PB_ADD_BASIN");
+    }
+
+    public get enableAddWallButton(): boolean {
+        return (this.model.bassins.length > 0);
+    }
+
+    /** Adds a new lone wall, opening a modal to choose connected basins */
+    public onAddWallClick() {
+        // open dialog
+        const dialogRef = this.newPbCloisonDialog.open(
+            DialogNewPbCloisonComponent,
+            {
+                data: {
+                    basins: this.model.bassins
+                },
+                disableClose: true
+            }
+        );
+        // apply modifications
+        dialogRef.afterClosed().subscribe(result => {
+            if (result.up !== undefined && result.down !== undefined) {
+                const wall = new PbCloison(
+                    result.up === 0 ? undefined : this.model.bassins[result.up - 1],
+                    result.down === 0 ? undefined : this.model.bassins[result.down - 1]
+                );
+                this.model.addChild(wall);
+                this.unselect();
+                this.refresh();
+                this.selectNodeOnSchema(wall);
+                this.clearResults();
+            }
+        });
+    }
+
+    public get uitextAddWall() {
+        return this.i18nService.localizeText("INFO_PB_ADD_WALL");
+    }
+
+    public get enableUpButton() {
+        return (
+            this._selectedItem instanceof PbBassin
+            && this.model.findBasinPosition(this._selectedItem.uid) !== 0
+            && this.isStandaloneBasin(this._selectedItem)
+        );
+    }
+
+    public onMoveBasinUpClick() {
+        if (this._selectedItem instanceof PbBassin) {
+            this.model.moveBasin(this._selectedItem.uid, this.model.findBasinPosition(this._selectedItem.uid) - 1);
+        }
+        const basin = this._selectedItem;
+        this.unselect();
+        this.refresh();
+        this.selectNodeOnSchema(basin);
+        this.clearResults();
+    }
+
+    public get uitextMoveBasinUp() {
+        return this.i18nService.localizeText("INFO_PB_MOVE_BASIN_UP");
+    }
+
+    public get enableDownButton() {
+        return (
+            this._selectedItem instanceof PbBassin
+            && this.model.findBasinPosition(this._selectedItem.uid) !== this.model.bassins.length - 1
+            && this.isStandaloneBasin(this._selectedItem)
+        );
+    }
+
+    public onMoveBasinDownClick() {
+        if (this._selectedItem instanceof PbBassin) {
+            this.model.moveBasin(this._selectedItem.uid, this.model.findBasinPosition(this._selectedItem.uid) + 1);
+        }
+        const basin = this._selectedItem;
+        this.unselect();
+        this.refresh();
+        this.selectNodeOnSchema(basin);
+        this.clearResults();
+    }
+
+    public get uitextMoveBasinDown() {
+        return this.i18nService.localizeText("INFO_PB_MOVE_BASIN_DOWN");
+    }
+
+    /**
+     * Returns true if given basin is either connected to nothing, or only to
+     * river upstream or downstream
+     */
+    private isStandaloneBasin(basin: PbBassin) {
+        return (
+            (
+                basin.cloisonsAmont.length === 0
+                || basin.cloisonsAmont.map(c => c.bassinAmont).every(e => e === undefined)
+            ) && (
+                basin.cloisonsAval.length === 0
+                || basin.cloisonsAval.map(c => c.bassinAval).every(e => e === undefined)
+            )
+        );
+    }
+
+    /**
+     * Computes the global Pab validity : validity of every cell of every row
+     */
+    private updateValidity() {
+        // check that at least 1 basin is present and a route from river
+        // upstream to river downstream exists (2nd check includes 1st)
+        this._isValid = (
+            this.model.hasUpDownConnection()
+            && ! this.model.hasBasinNotConnected()
+        );
+        this.validChange.emit();
+    }
+
+    private clearHighlightedItems() {
+        this.nativeElement.querySelectorAll("g.node").forEach(item => {
+            item.classList.remove("node-highlighted");
+        });
+    }
+
+    private unselect() {
+        this._selectedItem = undefined;
+        this.clearHighlightedItems();
+        this.nodeSelected.emit({}); // nothing selected
+    }
+
+    /** clear all PB form results whenever the basins / walls layout is changed */
+    private clearResults() {
+        this.pbSchema.form.reset();
+    }
+
+    // interface Observer
+
+    public update(sender: IObservable, data: any) {
+        if (sender instanceof PbSchema) {
+            if (data.action === "refresh") {
+                this.unselect();
+                this.refresh();
+                // select a node on the schema ?
+                if (data.value !== undefined) {
+                    this.selectNodeOnSchema(this.model.findChild(data.value));
+                }
+            }
+        }
+    }
+
+}
diff --git a/src/app/components/remous-results/remous-results.component.html b/src/app/components/remous-results/remous-results.component.html
index ed96cbf12dfdbf619938d462cba2959f7f1b2a83..7f9efd5fd03a4a8827d85473bc660943f101a7c4 100644
--- a/src/app/components/remous-results/remous-results.component.html
+++ b/src/app/components/remous-results/remous-results.component.html
@@ -42,10 +42,9 @@
 
 
 <!-- journal -->
-<log></log>
+<log [log]=log></log>
 
-<div [hidden]="! hasData">
-    <!-- *ngIf breaks @ViewChild availability-->
+<div *ngIf="hasData">
     <!-- résultats numériques -->
-    <var-results></var-results>
-</div>
\ No newline at end of file
+    <var-results [results]=varResults></var-results>
+</div>
diff --git a/src/app/components/remous-results/remous-results.component.ts b/src/app/components/remous-results/remous-results.component.ts
index db14a54ceea12f5b03ac76e54b617cb3c10e8114..b39505299078fd465949b1f8c178625e459fc299 100644
--- a/src/app/components/remous-results/remous-results.component.ts
+++ b/src/app/components/remous-results/remous-results.component.ts
@@ -1,17 +1,16 @@
-import { Component, ViewChild, DoCheck } from "@angular/core";
+import { Component, Input, OnChanges, SimpleChanges } from "@angular/core";
 
-import { INumberIterator, CourbeRemousParams, CourbeRemous, ParamDefinition, ParamDomain, ParamDomainValue } from "jalhyd";
+import { INumberIterator, CourbeRemousParams, CourbeRemous, ParamDefinition, ParamDomainValue, cLog } from "jalhyd";
 
 import { I18nService } from "../../services/internationalisation.service";
-import { LogComponent } from "../../components/log/log.component";
 import { RemousResults } from "../../results/remous-results";
 import { CalculatorResults } from "../../results/calculator-results";
-import { VarResultsComponent } from "../fixedvar-results/var-results.component";
 import { FormulaireService } from "../../services/formulaire.service";
 import { ResultsComponentDirective } from "../fixedvar-results/results.component";
 import { AppComponent } from "../../app.component";
 import { LineData, ChartData } from "./line-and-chart-data";
 import { fv } from "../../util";
+import { VarResults } from "../../results/var-results";
 
 @Component({
     selector: "remous-results",
@@ -20,7 +19,7 @@ import { fv } from "../../util";
         "./remous-results.component.scss"
     ]
 })
-export class RemousResultsComponent extends ResultsComponentDirective implements DoCheck {
+export class RemousResultsComponent extends ResultsComponentDirective implements OnChanges {
 
     private _remousResults: RemousResults;
 
@@ -43,23 +42,6 @@ export class RemousResultsComponent extends ResultsComponentDirective implements
      */
     private _tableHeaders: string[];
 
-    /**
-     * true si les résultats doivent être mis à jour
-     */
-    private _doUpdate = false;
-
-    /**
-     * composant des résultats variables
-     */
-    @ViewChild(VarResultsComponent)
-    private varResultsComponent: VarResultsComponent;
-
-    /**
-     * composant journal
-     */
-    @ViewChild(LogComponent)
-    private logComponent: LogComponent;
-
     constructor(
         private intlService: I18nService,
         private formService: FormulaireService
@@ -67,7 +49,11 @@ export class RemousResultsComponent extends ResultsComponentDirective implements
         super();
     }
 
-    private get uitextLigneFluviale() {
+    public get remousResults() {
+        return this._remousResults;
+    }
+
+    public get uitextLigneFluviale() {
         // calculator type for translation
         const sn = this._remousResults.result.sourceNub;
         let ct = sn.calcType;
@@ -77,7 +63,7 @@ export class RemousResultsComponent extends ResultsComponentDirective implements
         return this.formService.expandVariableNameAndUnit(ct, "FLU");
     }
 
-    private get uitextLigneTorrentielle() {
+    public get uitextLigneTorrentielle() {
         // calculator type for translation
         const sn = this._remousResults.result.sourceNub;
         let ct = sn.calcType;
@@ -87,23 +73,23 @@ export class RemousResultsComponent extends ResultsComponentDirective implements
         return this.formService.expandVariableNameAndUnit(ct, "TOR");
     }
 
-    private get uitextAbscisse() {
+    public get uitextAbscisse() {
         return this.intlService.localizeText("INFO_REMOUSRESULTS_ABSCISSE");
     }
 
-    private get uitextFond() {
+    public get uitextFond() {
         return this.intlService.localizeText("INFO_REMOUSRESULTS_FOND");
     }
 
-    private get uitextBerge() {
+    public get uitextBerge() {
         return this.intlService.localizeText("INFO_REMOUSRESULTS_BERGE");
     }
 
-    private get uitextTirantNormal() {
+    public get uitextTirantNormal() {
         return this.intlService.localizeText("INFO_REMOUSRESULTS_TIRANTNORMAL");
     }
 
-    private get uitextTirantCritique() {
+    public get uitextTirantCritique() {
         return this.intlService.localizeText("INFO_REMOUSRESULTS_TIRANTCRITIQUE");
     }
 
@@ -142,13 +128,14 @@ export class RemousResultsComponent extends ResultsComponentDirective implements
     }
 
     public get hasResults(): boolean {
-        return this._remousResults !== undefined && this._remousResults.hasResults;
+        return this._remousResults?.hasResults;
     }
 
     public get hasData(): boolean {
         return this._remousResults && this._remousResults.result && this._remousResults.result.ok;
     }
 
+    @Input()
     public set results(rs: CalculatorResults[]) {
         this._remousResults = undefined;
         if (rs !== undefined) {
@@ -159,43 +146,25 @@ export class RemousResultsComponent extends ResultsComponentDirective implements
                 }
             }
         }
-        this.updateView();
     }
 
-    public updateView() {
-        this.graph1_data = {};
-        this.graph1_options = {};
-        this.graph2_data = {};
-        this.graph2_options = {};
-        if (this.varResultsComponent !== undefined) {
-            this.varResultsComponent.results = undefined;
-        }
-        if (this.logComponent !== undefined) {
-            this.logComponent.log = undefined;
-        }
-        this._tableHeaders = [];
-
-        if (this._remousResults !== undefined) {
-            this._doUpdate = this._remousResults.hasResults;
+    public ngOnChanges(s: SimpleChanges) {
+        // console.log("_________> RRC onChanges", s);
+        if (this._remousResults && this._remousResults.result) {
+            this.generateChart();
         }
     }
 
-    /**
-     * appelé pour gérer les changements non détectés par Angular
-     */
-    public ngDoCheck() {
-        if (this._doUpdate) {
-            this._doUpdate = !this.updateResults();
+    public get log(): cLog {
+        if (this._remousResults !== undefined) {
+            return this._remousResults.log;
         }
     }
 
-    private updateResults() {
-        if (this.logComponent !== undefined && this._remousResults !== undefined) {
-            this.logComponent.log = this._remousResults.log;
-            this.generateChart();
-            return true;
+    public get varResults(): VarResults {
+        if (this._remousResults !== undefined) {
+            return this._remousResults.varResults;
         }
-        return false;
     }
 
     /**
@@ -268,11 +237,7 @@ export class RemousResultsComponent extends ResultsComponentDirective implements
     private generateChart() {
         // http://www.chartjs.org/docs/latest/charts/line.html
         // le dernier dataset de la liste datasets est dessiné en 1er
-
         this._remousResults.update();
-        if (this.varResultsComponent) {
-            this.varResultsComponent.results = this._remousResults.varResults;
-        }
 
         const nub = this._remousResults.result.sourceNub as CourbeRemous;
         const params = nub.prms as CourbeRemousParams;
@@ -315,7 +280,7 @@ export class RemousResultsComponent extends ResultsComponentDirective implements
         }
 
         // hauteur normale
-        if (this._remousResults.hautNormale !== undefined && this._remousResults.hautNormale.ok) {
+        if (this._remousResults.hautNormale?.ok) {
             const Yn = this._remousResults.hautNormale.vCalc;
             gr1.drawSimpleLine(Yn + ZF1, Yn + ZF2,
                 5, "#A4C537", this.uitextTirantNormal
@@ -323,7 +288,7 @@ export class RemousResultsComponent extends ResultsComponentDirective implements
         }
 
         // hauteur critique
-        if (this._remousResults.hautCritique !== undefined && this._remousResults.hautCritique.ok) {
+        if (this._remousResults.hautCritique?.ok) {
             const Yc = this._remousResults.hautCritique.vCalc;
             gr1.drawSimpleLine(Yc + ZF1, Yc + ZF2,
                 6, "#FF0000", this.uitextTirantCritique
diff --git a/src/app/components/results-chart/results-chart.component.html b/src/app/components/results-chart/results-chart.component.html
index 1cf1336d5b43c0c98f79f967a421166a720e799e..be55ade023ec1c2b38630011af12ef652a515152 100644
--- a/src/app/components/results-chart/results-chart.component.html
+++ b/src/app/components/results-chart/results-chart.component.html
@@ -17,7 +17,7 @@
         </div>
 
         <div *ngIf="! displayChart" class="fake-chart"></div><!-- trick to avoid blinking effect due to forceRebuild -->
-        <chart *ngIf="displayChart" [type]="graph_type" [data]="graph_data" [options]="graph_options" #graphChart>
+        <chart *ngIf="displayChart" [type]="graph_type" [data]="graph_data" [options]="graph_options">
         </chart>
     </div>
 </div>
diff --git a/src/app/components/results-chart/results-chart.component.ts b/src/app/components/results-chart/results-chart.component.ts
index 05247e41c836467b53cd4e53a4d66aa24000f8e0..d41858fe728c13c5f9a40072b9d8ee5f8aa621e3 100644
--- a/src/app/components/results-chart/results-chart.component.ts
+++ b/src/app/components/results-chart/results-chart.component.ts
@@ -1,8 +1,8 @@
-import { Component, ViewChild, AfterContentInit, ChangeDetectorRef } from "@angular/core";
+import { Component, ViewChild, AfterContentInit, ChangeDetectorRef, Input, OnChanges } from "@angular/core";
 
 import { ChartComponent } from "angular2-chartjs";
 
-import { Observer, ParamFamily } from "jalhyd";
+import { Observer, ParamFamily, Result } from "jalhyd";
 
 import { ChartTypeSelectComponent } from "./chart-type.component";
 import { I18nService } from "../../services/internationalisation.service";
@@ -21,7 +21,7 @@ import { AppComponent } from "../../app.component";
         "./results-chart.component.scss"
     ]
 })
-export class ResultsChartComponent extends ResultsComponentDirective implements AfterContentInit, Observer {
+export class ResultsChartComponent extends ResultsComponentDirective implements AfterContentInit, Observer, OnChanges {
 
     @ViewChild(ChartComponent)
     private chartComponent;
@@ -90,23 +90,33 @@ export class ResultsChartComponent extends ResultsComponentDirective implements
         };
     }
 
+    @Input()
     public set results(r: PlottableData) {
-        this.forceRebuild();
         this._results = r;
         if (this._results && this._graphTypeComponent) {
-            this._graphTypeComponent.selectedValue = r.graphType;
+            this._graphTypeComponent.selectedValue = r.chartType;
         }
     }
 
-    public get availableXAxis() {
+    @Input()
+    public set resultData(r: Result) {
+        // trick to trigger onChanges when results data changes
+    }
+
+    @Input()
+    public set variableIndex(v: number) {
+        // trick to trigger onChanges when variable index changes
+    }
+
+    public get availableXAxis(): string[] {
         if (this._results) {
             return this._results.getAvailableXAxis();
         }
     }
 
-    public get availableYAxis() {
+    public get availableYAxis(): string[] {
         if (this._results) {
-            if (this._results.graphType !== ChartType.Scatter) {
+            if (this._results.chartType !== ChartType.Scatter) {
                 // do not use real Y axis (that include families), if chart cannot display multiple series
                 return this._results.getAvailableXAxis();
             } else {
@@ -124,9 +134,8 @@ export class ResultsChartComponent extends ResultsComponentDirective implements
     public set chartX(X) {
         if (X !== this.chartX) {
             this._results.chartX = X;
-            this.forceRebuild();
             // refresh chart
-            this.updateView();
+            this.drawChart();
         }
     }
 
@@ -139,9 +148,8 @@ export class ResultsChartComponent extends ResultsComponentDirective implements
     public set chartY(Y) {
         if (Y !== this.chartY) {
             this._results.chartY = Y;
-            this.forceRebuild();
             // refresh chart
-            this.updateView();
+            this.drawChart();
         }
     }
 
@@ -169,23 +177,29 @@ export class ResultsChartComponent extends ResultsComponentDirective implements
         return this._zoomWasChanged;
     }
 
-    public updateView() {
-        // (re)generate chart
-        switch (this._graphTypeComponent.selectedValue) {
-            case ChartType.Histogram:
-                this.graph_type = "bar";
-                this.generateBarChart();
-                break;
-
-            case ChartType.Dots:
-                this.graph_type = "line";
-                this.generateLineChart();
-                break;
-
-            default:
-                this.graph_type = "scatter";
-                this.generateScatterChart();
-                break;
+    public ngOnChanges() {
+        // redessiner le graphique chaque fois qu'une entrée change
+        this.drawChart();
+    }
+
+    public drawChart() {
+        if (this._results && this._results.hasPlottableResults()) {
+            switch (this._graphTypeComponent.selectedValue) {
+                case ChartType.Histogram:
+                    this.graph_type = "bar";
+                    this.generateBarChart();
+                    break;
+
+                case ChartType.Dots:
+                    this.graph_type = "line";
+                    this.generateLineChart();
+                    break;
+
+                default:
+                    this.graph_type = "scatter";
+                    this.generateScatterChart();
+                    break;
+            }
         }
     }
 
@@ -212,15 +226,6 @@ export class ResultsChartComponent extends ResultsComponentDirective implements
         return l;
     }
 
-    /** forces Angular to rebuild the chart @see bug #137 */
-    private forceRebuild() {
-        this.displayChart = false;
-        const that = this;
-        setTimeout(() => { // trick
-            that.displayChart = true;
-        }, 10);
-    }
-
     /**
      * génère les données d'un graphique de type "bar"
      */
@@ -479,9 +484,9 @@ export class ResultsChartComponent extends ResultsComponentDirective implements
     update(sender: any, data: any) {
         if (sender instanceof ChartTypeSelectComponent) {
             if (data.action === "graphTypeChanged") {
-                this._results.graphType = data.value;
+                this._results.chartType = data.value;
             }
         }
-        this.updateView();
+        this.drawChart();
     }
 }
diff --git a/src/app/components/section-canvas/section-canvas.component.html b/src/app/components/section-canvas/section-canvas.component.html
new file mode 100644
index 0000000000000000000000000000000000000000..da242b966d3d4eb18ed9873ad32e8779fec1ce6b
--- /dev/null
+++ b/src/app/components/section-canvas/section-canvas.component.html
@@ -0,0 +1,2 @@
+<canvas #canvas [attr.width]="width" [attr.height]="height">
+</canvas>
diff --git a/src/app/components/section-canvas/section-canvas.component.scss b/src/app/components/section-canvas/section-canvas.component.scss
new file mode 100644
index 0000000000000000000000000000000000000000..7f26ddcb550343c65fbc953a2c7b73b6440c0eae
--- /dev/null
+++ b/src/app/components/section-canvas/section-canvas.component.scss
@@ -0,0 +1,3 @@
+:host {
+    display: block;
+}
diff --git a/src/app/components/section-canvas/section-canvas.component.ts b/src/app/components/section-canvas/section-canvas.component.ts
index 3475f8842d495cac9f058e195fb93a101d4081f2..81b4c45dde483584e6234ca028bf5cef1ae2d5cf 100644
--- a/src/app/components/section-canvas/section-canvas.component.ts
+++ b/src/app/components/section-canvas/section-canvas.component.ts
@@ -1,27 +1,30 @@
-import { Component, ViewChild } from "@angular/core";
+import { Component, ViewChild, Input, OnChanges, AfterViewInit, ElementRef } from "@angular/core";
 
 import {
     acSection, cSnTrapez, ParamsSectionTrapez, cSnRectang, ParamsSectionRectang, cSnCirc,
     ParamsSectionCirc, cSnPuiss, ParamsSectionPuiss, Result
 } from "jalhyd";
 
-import { CalcCanvasComponent } from "../canvas/canvas.component";
+import { ResultsComponentDirective } from "../fixedvar-results/results.component";
 
 @Component({
     selector: "section-canvas",
-    template: `<calc-canvas #calcCanvas
-    [width]="size"
-    [height]="size">
-    </calc-canvas>
-    `
+    templateUrl: "./section-canvas.component.html",
+    styleUrls: [
+        "./section-canvas.component.scss"
+    ]
 })
-export class SectionCanvasComponent {
-
-    /** default square size, supposed to match device size (computed at contruct time) */
-    public originalSize: number;
-
-    /** taille (pixels) du canvas (c'est un carré) */
-    public size = 400;
+export class SectionCanvasComponent extends ResultsComponentDirective implements AfterViewInit, OnChanges {
+
+    private static labelColors: { [key: string]: any; } = {
+        "Hs": { r: 255, g: 0, b: 0 },
+        "Hsc": { r: 0, g: 0, b: 255 },
+        "Yn": { r: 16, g: 128, b: 16 },
+        "Ycor": { r: 128, g: 128, b: 128 },
+        "Yc": { r: 255, g: 128, b: 0 },
+        "Ycon": { r: 255, g: 0, b: 255 },
+        "Y": { r: 50, g: 50, b: 50 }
+    };
 
     /** marges gauche/droite pour le texte (pixels) */
     private _textMargin = 90;
@@ -35,42 +38,59 @@ export class SectionCanvasComponent {
 
     private _section: acSection;
 
+    private _result: Result;
+
+    private _size: number;
+
     // tirants
     private _levels: Object[] = [];
 
-    @ViewChild("calcCanvas")
-    private _calcCanvas: CalcCanvasComponent;
+    public get width(): number {
+        // return this._calcCanvas.nativeElement.width;
+        return this._size;
+    }
 
+    public get height(): number {
+        // return this._calcCanvas.nativeElement.height;
+        return this._size;
+    }
+
+    private _context2d: CanvasRenderingContext2D;
+
+    @ViewChild("canvas", { static: true })
+    private _calcCanvas: ElementRef;
+
+    @Input()
     public set section(s: acSection) {
         this._section = s;
-        if (this._section) {
-            this.draw();
-        }
     }
 
-    public reset() {
-        this._section = undefined;
-        this._levels = [];
-        this._calcCanvas.clear();
+    @Input()
+    public set result(r: Result) {
+        this._result = r;
     }
 
-    private computeScale(maxWidth: number, maxHeight: number) {
-        this._scaleX = (this.size - 2 * this._textMargin) / maxWidth;
-        this._scaleY = (this.size - this._bottomMargin) / maxHeight;
+    @Input()
+    public set size(s: number) {
+        this._size = s;
+        console.log("(i) size set to", this._size);
     }
 
-    /**
-     * convertit une abscisse en m en pixels
-     */
-    private Xm2pix(x: number) {
-        return this._textMargin + x * this._scaleX;
+    // redessine le canvas chaque fois qu'une entrée change
+    public ngOnChanges() {
+        console.log("XXX section canvas on changes");
+        this.draw();
     }
 
-    /**
-     * convertit une ordonnée en m en pixels
-     */
-    private Ym2pix(y: number) {
-        return this.size - this._bottomMargin - y * this._scaleY;
+    public ngAfterViewInit() { // wait for the view to init before using the element
+        this._context2d = this._calcCanvas.nativeElement.getContext("2d");
+        console.log("<<<< after view init >>>");
+        this.draw();
+    }
+
+    public reset() {
+        this._levels = [];
+        this.clear();
     }
 
     public addLevel(val: number, label: string, rgb: {}) {
@@ -83,6 +103,45 @@ export class SectionCanvasComponent {
         return Math.max(this._section.prms.YB.v, this._levels[this._levels.length - 1]["val"]);
     }
 
+    private isSectionLevel(s: string) {
+        for (const k in SectionCanvasComponent.labelColors) {
+            if (k === s) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    public draw() {
+        console.log(">> redrawing at size", this._size);
+        if (this._context2d && this._section) {
+            this.reset();
+
+            // traduction des symboles des variables calculées
+            const re = this._result.resultElement;
+            for (const k in re.values) {
+                if (k !== re.vCalcSymbol) {
+                    const lbl = k.toUpperCase();
+                    const er = re.getValue(k);
+                    // this._resultElement.addExtraResult(lbl, er);
+
+                    if (this.isSectionLevel(k)) {
+                        this.addLevel(er, k + " = " + this.formattedValue(er), SectionCanvasComponent.labelColors[k]);
+                    }
+                }
+            }
+
+            // ajout du tirant d'eau saisi
+            const valY = this._result.sourceNub.getParameter("Y").singleValue;
+            this.addLevel(valY, "Y = " + this.formattedValue(valY), SectionCanvasComponent.labelColors["Y"]);
+
+            this.sortLevels();
+            this.drawFrame();
+            const maxWidth = this.drawSection();
+            this.drawLevels(maxWidth);
+        }
+    }
+
     /**
      * dessin des pointillés au dessus de la berge
      * xmin,xmax : position gauche/droite
@@ -90,9 +149,9 @@ export class SectionCanvasComponent {
      * maxHeight : valeur maxi des cotes
      */
     private drawTopDashLines(xmin: number, xmax: number, yb: number, maxHeight: number) {
-        this._calcCanvas.setLineWidth(2);
-        this._calcCanvas.setLineDash([5]);
-        this._calcCanvas.setStrokeColor(128, 128, 128);
+        this.setLineWidth(2);
+        this.setLineDash([5]);
+        this.setStrokeColor(128, 128, 128);
         this.drawSectionLine(xmin, yb, xmin, maxHeight);
         this.drawSectionLine(xmax, yb, xmax, maxHeight);
     }
@@ -118,8 +177,8 @@ export class SectionCanvasComponent {
 
         // dessin de la section
 
-        this._calcCanvas.setStrokeColor(0, 0, 0);
-        this._calcCanvas.setLineWidth(5);
+        this.setStrokeColor(0, 0, 0);
+        this.setLineWidth(5);
         this.drawSectionLine(0, yb, lp, 0);
         this.drawSectionLine(lp, 0, lp + prms.LargeurFond.v, 0);
         this.drawSectionLine(lp + prms.LargeurFond.v, 0, maxWidth, yb);
@@ -149,8 +208,8 @@ export class SectionCanvasComponent {
 
         // dessin de la section
 
-        this._calcCanvas.setStrokeColor(0, 0, 0);
-        this._calcCanvas.setLineWidth(5);
+        this.setStrokeColor(0, 0, 0);
+        this.setLineWidth(5);
         this.drawSectionLine(0, yb, 0, 0);
         this.drawSectionLine(0, 0, prms.LargeurBerge.v, 0);
         this.drawSectionLine(prms.LargeurBerge.v, 0, maxWidth, yb);
@@ -191,8 +250,8 @@ export class SectionCanvasComponent {
 
             // dessin de la section
 
-            this._calcCanvas.setStrokeColor(0, 0, 0);
-            this._calcCanvas.setLineWidth(5);
+            this.setStrokeColor(0, 0, 0);
+            this.setLineWidth(5);
 
             const wx: number = maxWidth / 2;
             const alpha: Result = sect.CalcSection("Alpha", yb);
@@ -237,19 +296,19 @@ export class SectionCanvasComponent {
 
         // contour de la section
 
-        this._calcCanvas.setStrokeColor(0, 0, 0);
-        this._calcCanvas.setLineWidth(5);
+        this.setStrokeColor(0, 0, 0);
+        this.setLineWidth(5);
         const k: number = prms.k.v;
         const lambda: number = B / Math.pow(yb, k);
         const inv_k: number = 1 / k;
 
         const n = 20;
-        this.beginPath();
+        this._context2d.beginPath();
         for (let x: number = -B / 2; x <= B / 2; x += B / n) {
             const y: number = Math.pow(Math.abs(x) * 2 / lambda, inv_k);
-            this.lineTo(x + B / 2, y);
+            this._context2d.lineTo(this.Xm2pix(x + B / 2), this.Ym2pix(y));
         }
-        this.closePath();
+        this._context2d.stroke();
 
         // pointillés du haut
         this.drawTopDashLines(0, maxWidth, yb, maxHeight);
@@ -257,28 +316,16 @@ export class SectionCanvasComponent {
         return maxWidth;
     }
 
-    private beginPath() {
-        this._calcCanvas.context2d.beginPath();
-    }
-
-    private lineTo(x: number, y: number) {
-        this._calcCanvas.context2d.lineTo(this.Xm2pix(x), this.Ym2pix(y));
-    }
-
-    private closePath() {
-        this._calcCanvas.context2d.stroke();
-    }
-
     private drawSectionEllipse(x: number, y: number, rX: number, rY: number, rot: number, start: number, end: number) {
-        this._calcCanvas.drawEllipse(this.Xm2pix(x), this.Ym2pix(y), rX * this._scaleX, rY * this._scaleY, rot, start, end);
+        this.drawEllipse(this.Xm2pix(x), this.Ym2pix(y), rX * this._scaleX, rY * this._scaleY, rot, start, end);
     }
 
     private drawText(s: string, x: number, y: number, align?: string) {
-        this._calcCanvas.fillText(s, this.Xm2pix(x), this.Ym2pix(y), align);
+        this.fillText(s, this.Xm2pix(x), this.Ym2pix(y), align);
     }
 
     private drawSectionLine(x1: number, y1: number, x2: number, y2: number) {
-        this._calcCanvas.drawLine(this.Xm2pix(x1), this.Ym2pix(y1), this.Xm2pix(x2), this.Ym2pix(y2));
+        this.drawLine(this.Xm2pix(x1), this.Ym2pix(y1), this.Xm2pix(x2), this.Ym2pix(y2));
     }
 
     /**
@@ -301,6 +348,25 @@ export class SectionCanvasComponent {
         throw new Error("SectionCanvasComponent.drawSection() : type de section non pris en charge");
     }
 
+    private computeScale(maxWidth: number, maxHeight: number) {
+        this._scaleX = (this._size - 2 * this._textMargin) / maxWidth;
+        this._scaleY = (this._size - this._bottomMargin) / maxHeight;
+    }
+
+    /**
+     * convertit une abscisse en m en pixels
+     */
+    private Xm2pix(x: number) {
+        return this._textMargin + x * this._scaleX;
+    }
+
+    /**
+     * convertit une ordonnée en m en pixels
+     */
+    private Ym2pix(y: number) {
+        return this._size - this._bottomMargin - y * this._scaleY;
+    }
+
     private sortLevels() {
         this._levels.sort((a, b) => {
             if (a["val"] < b["val"]) {
@@ -316,16 +382,16 @@ export class SectionCanvasComponent {
     private drawLevels(maxWidth: number) {
         let left = true;
 
-        this._calcCanvas.resetLineDash();
-        this._calcCanvas.setLineWidth(1);
-        this._calcCanvas.setFont("12px sans- serif");
+        this.resetLineDash();
+        this.setLineWidth(1);
+        this.setFont("12px sans- serif");
         for (const l of this._levels) {
             const y = l["val"];
             const col = l["rgb"];
-            this._calcCanvas.setStrokeColor(col["r"], col["g"], col["b"]);
+            this.setStrokeColor(col["r"], col["g"], col["b"]);
             this.drawSectionLine(0, y, maxWidth, y);
 
-            this._calcCanvas.setFillColor(col["r"], col["g"], col["b"]);
+            this.setFillColor(col["r"], col["g"], col["b"]);
             if (left) {
                 this.drawText(l["label"], -0.1, y, "right");
             } else {
@@ -337,17 +403,75 @@ export class SectionCanvasComponent {
 
     // contour du canvas
     private drawFrame() {
-        this._calcCanvas.clear();
-        this._calcCanvas.resetLineDash();
-        this._calcCanvas.setStrokeColor(128, 128, 128);
-        this._calcCanvas.drawRect(0, 0, this._calcCanvas.width, this._calcCanvas.height);
+        this.clear();
+        this.resetLineDash();
+        this.setStrokeColor(128, 128, 128);
+        this.drawRect(0, 0, this.width, this.height);
     }
 
-    public draw() {
-        // console.log(">> redrawing at size", this.size);
-        this.sortLevels();
-        this.drawFrame();
-        const maxWidth = this.drawSection();
-        this.drawLevels(maxWidth);
+    public clear() {
+        if (this._context2d) {
+            this._context2d.clearRect(0, 0, this.width, this.height);
+        }
+    }
+
+    public setStrokeColor(r: number, g: number, b: number) {
+        const col: string = "rgb(" + r + "," + g + "," + b + ")";
+        this._context2d.strokeStyle = col;
+    }
+
+    public setFillColor(r: number, g: number, b: number) {
+        const col: string = "rgb(" + r + "," + g + "," + b + ")";
+        this._context2d.fillStyle = col;
+    }
+
+    public setFont(f: string) {
+        this._context2d.font = f;
+    }
+
+    public fillText(s: string, x: number, y: number, align?: any) {
+        if (align) {
+            this._context2d.textAlign = align;
+        }
+        this._context2d.fillText(s, x, y);
+    }
+
+    public setLineWidth(w: number) {
+        this._context2d.lineWidth = w;
+    }
+
+    public setLineDash(d: number[]) {
+        this._context2d.setLineDash(d);
+    }
+
+    public resetLineDash() {
+        this._context2d.setLineDash([]);
+    }
+
+    public drawRect(x1: number, y1: number, w: number, h: number) {
+        this._context2d.strokeRect(x1, y1, w, h);
+    }
+
+    public drawLine(x1: number, y1: number, x2: number, y2: number) {
+        this._context2d.beginPath();
+        this._context2d.moveTo(x1, y1);
+        this._context2d.lineTo(x2, y2);
+        this._context2d.stroke();
+    }
+
+    /**
+     *
+     * @param x The x axis of the coordinate for the ellipse's center.
+     * @param y The y axis of the coordinate for the ellipse's center.
+     * @param radiusX The ellipse's major-axis radius.
+     * @param radiusY The ellipse's minor-axis radius.
+     * @param rotation The rotation for this ellipse, expressed in radians
+     * @param startAngle The starting point, measured from the x axis, from which it will be drawn, expressed in radians
+     * @param endAngle The end ellipse's angle to which it will be drawn, expressed in radians
+     */
+    public drawEllipse(x: number, y: number, radiusX: number, radiusY: number, rotation: number, startAngle: number, endAngle: number) {
+        this._context2d.beginPath();
+        this._context2d.ellipse(x, y, radiusX, radiusY, rotation, startAngle, endAngle);
+        this._context2d.stroke();
     }
 }
diff --git a/src/app/components/section-results/section-results.component.html b/src/app/components/section-results/section-results.component.html
index ff26a315cad7f386d37b69661a6be7d76becdf7c..ac4e78fa01c00b3a81ff4c428e830416831d0142 100644
--- a/src/app/components/section-results/section-results.component.html
+++ b/src/app/components/section-results/section-results.component.html
@@ -1,6 +1,5 @@
 <div class="section-results-container" #sectionResults *ngIf="hasResults" fxLayout="row wrap"
     fxLayoutAlign="center center">
-
     <div fxFlex="1 1 100%">
         <div class="section-results-buttons">
             <button mat-icon-button (click)="exportAsImage(sectionResults)" [title]="uitextExportImageTitle">
@@ -17,25 +16,7 @@
 
         <!-- graphique -->
         <div class="canvas-container">
-            <section-canvas></section-canvas>
+            <section-canvas [result]=result [section]=section [size]=size></section-canvas>
         </div>
     </div>
 </div>
-
-<div class="container">
-    <!-- journal -->
-    <log></log>
-
-    <results-chart *ngIf="showVarResults"></results-chart>
-    <!--<results-chart [hidden]="! showVarResultsChart"></results-chart>-->
-
-    <div>
-        <!-- table des résultats fixés -->
-        <fixed-results [results]=fixedResults></fixed-results>
-
-        <!-- table des résultats variés -->
-        <div *ngIf="showVarResults">
-            <var-results [results]=varResults></var-results>
-        </div>
-    </div>
-</div>
\ No newline at end of file
diff --git a/src/app/components/section-results/section-results.component.ts b/src/app/components/section-results/section-results.component.ts
index 99df6bb4a1346c5376f452cd64c29d79738aa7d3..0893a387f0132b851ff7d7390a1ed8732a51ba63 100644
--- a/src/app/components/section-results/section-results.component.ts
+++ b/src/app/components/section-results/section-results.component.ts
@@ -1,13 +1,10 @@
-import { Component, ViewChild, DoCheck, ElementRef } from "@angular/core";
+import { Component, ElementRef, Input } from "@angular/core";
 
-import { ResultElement } from "jalhyd";
-
-import { SectionCanvasComponent } from "../section-canvas/section-canvas.component";
 import { SectionResults } from "../../results/section-results";
 import { CalculatorResults } from "../../results/calculator-results";
 import { I18nService } from "../../services/internationalisation.service";
 import { AppComponent } from "../../app.component";
-import { FixedVarResultsComponent } from "../fixedvar-results/fixedvar-results.component";
+import { ResultsComponentDirective } from "../fixedvar-results/results.component";
 
 @Component({
     selector: "section-results",
@@ -16,18 +13,32 @@ import { FixedVarResultsComponent } from "../fixedvar-results/fixedvar-results.c
         "./section-results.component.scss"
     ]
 })
-export class SectionResultsComponent extends FixedVarResultsComponent implements DoCheck {
+export class SectionResultsComponent extends ResultsComponentDirective {
+
+    /** taille (pixels) du canvas (c'est un carré) */
+    public _size: number;
+
+    /** hardcoded bullet-proof default canvas size **/
+    private previousContainerSize: number;
+
+    private defaultSize = 400;
+
+    private minimalSize = 300;
+
+    /**  résultats non mis en forme */
+    private _results: SectionResults;
 
     constructor(
         private intlService: I18nService,
         private element: ElementRef,
     ) {
         super();
+        this.previousContainerSize = this.defaultSize;
+        this._size = this.previousContainerSize;
     }
 
+    @Input()
     public set results(rs: CalculatorResults[]) {
-        super.results = rs;
-        this._resultElement = undefined;
         this._results = undefined;
         if (rs) {
             for (const r of rs) {
@@ -36,105 +47,22 @@ export class SectionResultsComponent extends FixedVarResultsComponent implements
                 }
             }
         }
-        this.updateView();
     }
 
-    /** détermine s'il y a des résultats de section "fixes" (pas de paramètre varié, graphique de la section) */
     public get hasResults(): boolean {
         return this._results && this._results.hasResults;
     }
 
-    public get resultElement() {
-        return this._resultElement;
-    }
-
-    private static labelColors: { [key: string]: any; } = {
-        "Hs": { r: 255, g: 0, b: 0 },
-        "Hsc": { r: 0, g: 0, b: 255 },
-        "Yn": { r: 16, g: 128, b: 16 },
-        "Ycor": { r: 128, g: 128, b: 128 },
-        "Yc": { r: 255, g: 128, b: 0 },
-        "Ycon": { r: 255, g: 0, b: 255 },
-        "Y": { r: 50, g: 50, b: 50 }
-    };
-
-    /** hardcoded bullet-proof default canvas size **/
-    private previousContainerSize = 400;
-
-    /**  résultats non mis en forme */
-    private _results: SectionResults;
-
-    /**
-     * ResultElement mis en forme (symboles des variables traduits)
-     */
-    private _resultElement: ResultElement;
-
-    @ViewChild(SectionCanvasComponent)
-    private _sectionCanvasComponent: SectionCanvasComponent;
-
-    public updateView() {
-        if (this._sectionCanvasComponent) {
-            this._sectionCanvasComponent.reset();
-        }
-        if (this._results) {
-            this._doUpdate = this._results.hasResults;
-        }
-        super.updateView();
+    public get section() {
+        return this._results.section;
     }
 
-    private isSectionLevel(s: string) {
-        for (const k in SectionResultsComponent.labelColors) {
-            if (k === s) {
-                return true;
-            }
-        }
-        return false;
+    public get result() {
+        return this._results.result;
     }
 
-    protected updateResults() {
-        const superUpdated = super.updateResults();
-
-        if (this._results && this._sectionCanvasComponent !== undefined) {
-            this._resultElement = new ResultElement();
-
-            // compute canvas optimal size the first time
-            if (this._sectionCanvasComponent.originalSize === undefined) {
-                const container = this.element.nativeElement.querySelector(".section-results-container");
-                const size = Math.min(container.offsetWidth, container.offsetHeight);
-                this._sectionCanvasComponent.originalSize = size - 17; // 417 - 17 = 400
-                this._sectionCanvasComponent.size = this._sectionCanvasComponent.originalSize;
-            }
-
-            // traduction des symboles des variables calculées
-            const re = this._results.result.resultElement;
-            for (const k in re.values) {
-                if (k !== re.vCalcSymbol) {
-                    const lbl = k.toUpperCase();
-                    const er = re.getValue(k);
-                    this._resultElement.addExtraResult(lbl, er);
-
-                    if (this.isSectionLevel(k)) {
-                        this._sectionCanvasComponent.addLevel(
-                            er, k + " = " + this.formattedValue(er), SectionResultsComponent.labelColors[k]
-                        );
-                    }
-                }
-            }
-
-            // ajout du tirant d'eau saisi
-            const valY = this._results.result.sourceNub.getParameter("Y").singleValue;
-            this._sectionCanvasComponent.addLevel(valY, "Y = " + this.formattedValue(valY), SectionResultsComponent.labelColors["Y"]);
-
-            // wait just a little to draw, in case this._sectionCanvas.size was changed above (1st run)
-            setTimeout(() => {
-                if (this._results && this._results.section) {
-                    this._sectionCanvasComponent.section = this._results.section;
-                }
-            }, 100);
-        }
-
-        const canvasUpdated = (! this.hasResults || this._sectionCanvasComponent !== undefined);
-        return superUpdated && canvasUpdated;
+    public get size() {
+        return this._size;
     }
 
     public exportAsImage(element: HTMLDivElement) {
@@ -143,26 +71,34 @@ export class SectionResultsComponent extends FixedVarResultsComponent implements
 
     /** redraw canvas on fullscreen state change (scale drawing) */
     public fullscreenChange(isFullscreen: boolean) {
-        this._sectionCanvasComponent.size = this.getContainerSize(! isFullscreen);
-        this.previousContainerSize = this._sectionCanvasComponent.size;
-        setTimeout(() => {
-            this._sectionCanvasComponent.draw();
-        }, 100);
+        this._size = this.getContainerSize(! isFullscreen, isFullscreen);
+        this.previousContainerSize = this._size;
     }
 
-    private getContainerSize(useOriginalSize: boolean = false): number {
+    private getContainerSize(useDefaultSize: boolean = false, useMinOfWidthAndHeight: boolean = false): number {
         const container = this.element.nativeElement.querySelector(".section-results-container");
+        console.log("[container size in getContainerSize]", container.offsetWidth, container.offsetHeight);
         let size: number;
         if (container) {
-            size = Math.min(container.offsetWidth, container.offsetHeight);
+            if (useMinOfWidthAndHeight) {
+                // when going to fullscreen mode, ensure the drawing
+                // is not larger or higher than the screen
+                size = Math.min(container.offsetWidth, container.offsetHeight);
+            } else {
+                size = container.offsetWidth;
+            }
         } else {
             size = this.previousContainerSize;
         }
         // when going back from fullscreen mode, container size tends to be
-        // too high for whatever reason; use originalSize on this purpose
-        if (useOriginalSize) {
-            size = Math.min(size, this._sectionCanvasComponent.originalSize);
+        // too high for whatever reason; use defaultSize on this purpose
+        if (useDefaultSize) {
+            console.log("~~ use default ~~", size, this.defaultSize);
+            size = this.defaultSize;
         }
+        // lower boundary
+        size = Math.max(size, this.minimalSize);
+
         return size;
     }
 
diff --git a/src/app/components/variable-results-selector/variable-results-selector.component.ts b/src/app/components/variable-results-selector/variable-results-selector.component.ts
index af8dfe927f46ab29fb9dd9742fd0112c0a5a2f66..68491335a515f172f709427ac6ebcd02762e6218 100644
--- a/src/app/components/variable-results-selector/variable-results-selector.component.ts
+++ b/src/app/components/variable-results-selector/variable-results-selector.component.ts
@@ -1,8 +1,11 @@
-import { Component, Output, EventEmitter } from "@angular/core";
+import { Component, Output, EventEmitter, Input, OnChanges } from "@angular/core";
 
 import { I18nService } from "../../services/internationalisation.service";
-import { fv, longestVarNgParam } from "../../util";
+import { fv, longestVarParam } from "../../util";
 import { MultiDimensionResults } from "../../results/multidimension-results";
+import { PrebarrageResults } from "../../results/prebarrage-results";
+
+import { CalculatorType, PbCloison, Structure, VariatedDetails } from "jalhyd";
 
 @Component({
     selector: "variable-results-selector",
@@ -11,12 +14,18 @@ import { MultiDimensionResults } from "../../results/multidimension-results";
         "./variable-results-selector.component.scss"
     ]
 })
-export class VariableResultsSelectorComponent {
+export class VariableResultsSelectorComponent implements OnChanges {
 
     /** résultats non mis en forme */
-    private _results: MultiDimensionResults;
+    @Input()
+    private results: MultiDimensionResults;
+
+    /** détails des paramètres qui varient dans le Nub associé au formulaire */
+    @Input()
+    private variatedParameters: VariatedDetails[];
 
-    private _selectedValue: number;
+    /** valeur en cours */
+    private _selectedValue = 0;
 
     /** size of the longest variable value */
     private size = 0;
@@ -24,28 +33,24 @@ export class VariableResultsSelectorComponent {
     /** inferred extended values list for each variating parameter */
     private varValues = [];
 
-    @Output()
-    protected indexChange = new EventEmitter();
+    /* @Output()
+    protected indexChange = new EventEmitter(); */
 
     constructor(
         protected intlService: I18nService,
-    ) {
-        this._selectedValue = 0;
-    }
+    ) { }
 
-    public set results(r: MultiDimensionResults) {
-        this._results = r;
-
-        if (this._results) {
-            // pre-extract variable parameters values
+    public ngOnChanges() {
+        // rebuild variable parameters values everytime somthing changes
+        if (this.variatedParameters) {
             this.varValues = [];
             // find longest list
-            const lvp = longestVarNgParam(this._results.variatedParameters);
+            const lvp = longestVarParam(this.variatedParameters);
             this.size = lvp.size;
             // get extended values lists for each variable parameter
-            for (const v of this._results.variatedParameters) {
+            for (const v of this.variatedParameters) {
                 const vv = [];
-                const iter = v.getExtendedValuesIterator(this.size);
+                const iter = v.param.getExtendedValuesIterator(this.size);
                 while (iter.hasNext) {
                     const nv = iter.next();
                     vv.push(fv(nv.value));
@@ -53,13 +58,17 @@ export class VariableResultsSelectorComponent {
                 this.varValues.push(vv);
             }
         }
+        // get current variatedIndex even if component was rebuilt
+        if (this.results) {
+            this._selectedValue = this.results.variableIndex;
+        }
     }
 
     public get hasVariableResults(): boolean {
         return (
-            this._results
-            && this._results.hasResults
-            && this._results.variatedParameters.length > 0
+            this.results
+            && this.results.hasResults
+            && this.results.variatedParameters.length > 0
         );
     }
 
@@ -75,15 +84,34 @@ export class VariableResultsSelectorComponent {
         const kv = [];
         for (let i = 0; i < this.varValues.length; i++) {
             const vv = this.varValues[i];
-            const vp = this._results.variatedParameters[i];
-            let symbol = vp.symbol;
+            const vp = this.results.variatedParameters[i];
+            let symbol = vp.param.symbol;
             // is vp a parameter of a child Nub ?
             if (
-                vp.paramDefinition.parentNub
-                && vp.paramDefinition.parentNub !== vp.paramDefinition.originNub
+                vp.param.parentNub
+                && vp.param.parentNub !== vp.param.originNub
             ) {
-                const pos = vp.paramDefinition.parentNub.findPositionInParent() + 1;
-                symbol = this.intlService.localizeText("INFO_LIB_RADIER_N_COURT") + pos + "_" + symbol;
+                let childPrefix: string;
+                // prefix the label depending on (grand)children type
+                switch (vp.param.originNub.calcType) {
+                    case CalculatorType.PreBarrage:
+                        const struct = vp.param.parentNub as Structure;
+                        const pbRes = this.results as PrebarrageResults;
+                        const wall = struct.parent as PbCloison;
+                        const posS = struct.findPositionInParent() + 1;
+                        childPrefix = this.intlService.localizeMessage(wall.description);
+                        // there might be multiple walls between the same pair of basins
+                        if (wall.uid in pbRes.wallsSuffixes) {
+                            childPrefix += " (" + pbRes.wallsSuffixes[wall.uid] + ")";
+                        }
+                        childPrefix += "_" + this.intlService.localizeText("INFO_LIB_STRUCTURE_N_COURT") + posS;
+                        break;
+                    case CalculatorType.MacroRugoCompound:
+                        const posMR = vp.param.parentNub.findPositionInParent() + 1;
+                        childPrefix = this.intlService.localizeText("INFO_LIB_RADIER_N_COURT") + posMR;
+                        break;
+                }
+                symbol = childPrefix + "_" + symbol;
             }
             kv.push(`${symbol} = ${vv[index]}`);
         }
@@ -95,8 +123,8 @@ export class VariableResultsSelectorComponent {
     }
 
     public set selectedValue(v: number) {
-        this._results.variableIndex = v;
-        this.indexChange.emit();
+        this.results.variableIndex = v;
+        // this.indexChange.emit();
     }
 
     public get label() {
diff --git a/src/app/components/verificateur-results/verificateur-results.component.html b/src/app/components/verificateur-results/verificateur-results.component.html
index 1d0f784795249b95dd9efe67895a5ee24087c843..b343b924ea0c74c9157d7436bc7af35246160d2c 100644
--- a/src/app/components/verificateur-results/verificateur-results.component.html
+++ b/src/app/components/verificateur-results/verificateur-results.component.html
@@ -1,8 +1,8 @@
 <div class="container">
-    <log #generalLog [logTitle]="uitextGeneralLogTitle">log général</log>
+    <log [log]="globalLog" [logTitle]="uitextGeneralLogTitle">log général</log>
 
-    <variable-results-selector [results]="verificateurResults" (indexChange)="variableIndexChanged()">
+    <variable-results-selector [results]="verificateurResults" [variatedParameters]=verificateurResults?.variatedParameters>
     </variable-results-selector>
 
-    <log-drawer #iterationLog></log-drawer>
+    <log-drawer [log]="iterationLog"></log-drawer>
 </div>
diff --git a/src/app/components/verificateur-results/verificateur-results.component.ts b/src/app/components/verificateur-results/verificateur-results.component.ts
index 1d76c0420f3a10d49246900585a910fa85c3240a..6770b31acf910cab7a26cd0aef0f9200f5c74528 100644
--- a/src/app/components/verificateur-results/verificateur-results.component.ts
+++ b/src/app/components/verificateur-results/verificateur-results.component.ts
@@ -1,14 +1,11 @@
-import { Component, ViewChild, DoCheck } from "@angular/core";
+import { Component, Input } from "@angular/core";
 
 import { cLog, Message } from "jalhyd";
 
-import { LogComponent } from "../log/log.component";
 import { CalculatorResults } from "../../results/calculator-results";
-import { VariableResultsSelectorComponent } from "../variable-results-selector/variable-results-selector.component";
 import { I18nService } from "../../services/internationalisation.service";
 import { VerificateurResults } from "../../results/verificateur-results";
 import { ResultsComponentDirective } from "../fixedvar-results/results.component";
-import { LogDrawerComponent } from "../log-drawer/log-drawer.component";
 
 @Component({
     selector: "verificateur-results",
@@ -17,74 +14,30 @@ import { LogDrawerComponent } from "../log-drawer/log-drawer.component";
         "./verificateur-results.component.scss"
     ]
 })
-export class VerificateurResultsComponent extends ResultsComponentDirective implements DoCheck {
+export class VerificateurResultsComponent extends ResultsComponentDirective {
 
     /** résultats non mis en forme */
     private _verificateurResults: VerificateurResults;
 
-    /** true si les résultats doiventt être remis à jour */
-    private _doUpdate = false;
-
-    @ViewChild(VariableResultsSelectorComponent)
-    private variableResultsSelectorComponent: VariableResultsSelectorComponent;
-
-    @ViewChild("generalLog")
-    private generalLogComponent: LogComponent;
-
-    @ViewChild("iterationLog")
-    private iterationLogComponent: LogDrawerComponent;
-
     constructor(
         private i18nService: I18nService,
     ) {
         super();
     }
 
+    @Input()
     public set results(rs: CalculatorResults[]) {
         this._verificateurResults = undefined;
         if (rs.length > 0 && rs[0] instanceof VerificateurResults) {
             this._verificateurResults = rs[0] as VerificateurResults;
         }
-        this.updateView();
-    }
-
-    /**
-     * update iteration log when the variable index changed (event sent by
-     * VariableResultsSelectorComponent); variable index is already set in
-     * verificateurResults at this time
-     */
-    public variableIndexChanged() {
-        this.updateView();
-    }
-
-    public updateView() {
-        if (this.iterationLogComponent) {
-            this.iterationLogComponent.log = undefined;
-        }
-        if (this.generalLogComponent) {
-            this.generalLogComponent.log = undefined;
-        }
-        if (this.variableResultsSelectorComponent) {
-            this.variableResultsSelectorComponent.results = undefined;
-        }
-        // set _doUpdate flag so that results are rebuilt on the next Angular display cycle
-        this._doUpdate = false;
-        if (this._verificateurResults !== undefined) {
-            this._doUpdate = this._doUpdate || this._verificateurResults.hasResults || this._verificateurResults.hasLog;
-        }
-    }
-
-    public ngDoCheck() {
-        if (this._doUpdate) {
-            this._doUpdate = !this.updateResults();
-        }
     }
 
     /*
      * Retourne les messages à afficher dans le composant de log global, au dessus
      * du sélecteur d'itération : messages globaux du Verificateur
      */
-    private get globalLog(): cLog {
+    public get globalLog(): cLog {
         const l = new cLog();
         if (this._verificateurResults && this._verificateurResults.result && this._verificateurResults.result.hasGlobalLog()) {
             l.addLog(this._verificateurResults.result.globalLog);
@@ -96,7 +49,7 @@ export class VerificateurResultsComponent extends ResultsComponentDirective impl
      * Retourne les messages à afficher dans le composant de log "du bas" : logs de l'itération
      * en cours (messages non-globaux du Vérificateur et eds Espèce), que le résultat varie ou non
      */
-    private get iterationLog(): Array<{ message: Message, subLog: cLog }> {
+    public get iterationLog(): Array<{ message: Message, subLog: cLog }> {
         const l: Array<{ message: Message, subLog: cLog }> = [];
         if (this._verificateurResults) {
             // = 0 lorsque rien ne varie
@@ -136,33 +89,6 @@ export class VerificateurResultsComponent extends ResultsComponentDirective impl
         return l;
     }
 
-    /**
-     * met à jour l'affichage des résultats
-     * @returns true si les résultats ont pu être mis à jour
-     */
-    private updateResults() {
-        let selectorUpdated: boolean;
-
-        // results or not, there might be a log
-        const logUpdated = (this.iterationLogComponent !== undefined || this.generalLogComponent !== undefined); // gne ?
-        if (logUpdated) {
-            // order of logs is important !
-            this.iterationLogComponent.log = this.iterationLog;
-            this.generalLogComponent.log = this.globalLog;
-        }
-
-        if (this.hasResults) {
-            selectorUpdated = this.variableResultsSelectorComponent !== undefined;
-            if (selectorUpdated) {
-                this.variableResultsSelectorComponent.results = this._verificateurResults;
-            }
-        } else {
-            selectorUpdated = true;
-        }
-
-        return logUpdated && selectorUpdated;
-    }
-
     public get verificateurResults() {
         return this._verificateurResults;
     }
diff --git a/src/app/config.json b/src/app/config.json
index 35925d7698c2eea9e7e93e31e6f9e324a494d549..97f3c60d6743c80c47231016f0666d26fb40e77d 100644
--- a/src/app/config.json
+++ b/src/app/config.json
@@ -15,7 +15,7 @@
                 "path": "passe-bassin.jpg",
                 "credits": "S. Richard / OFB"
             },
-            "calculators": [ 12, 13, 6, 5, 10, 15 ]
+            "calculators": [ 12, 13, 6, 5, 10, 15, 30 ]
         },
         {
             "name": "PASSE_A_RALENTISSEURS",
@@ -39,7 +39,7 @@
                 "path": "verification.jpg",
                 "credits": "S. Richard / OFB"
             },
-            "calculators": [ 31, 30 ]
+            "calculators": [ 34, 33 ]
         },
         {
             "name": "DEVALAISON",
diff --git a/src/app/examples/prebarrage.json b/src/app/examples/prebarrage.json
new file mode 100644
index 0000000000000000000000000000000000000000..c97e06ca02fcfa0c34d40d3c34f9d9aefee0955d
--- /dev/null
+++ b/src/app/examples/prebarrage.json
@@ -0,0 +1,808 @@
+{
+    "header": {
+        "source": "jalhyd",
+        "format_version": "1.3",
+        "created": "2020-06-29T13:15:21.029Z"
+    },
+    "settings": {
+        "precision": 1e-7,
+        "maxIterations": 100,
+        "displayPrecision": 3
+    },
+    "documentation": "",
+    "session": [
+        {
+            "uid": "b2kxNm",
+            "props": {
+                "calcType": "PreBarrage"
+            },
+            "meta": {
+                "title": "Prébarrages"
+            },
+            "children": [
+                {
+                    "uid": "Zjczdz",
+                    "props": {
+                        "calcType": "PbBassin"
+                    },
+                    "children": [],
+                    "parameters": [
+                        {
+                            "symbol": "S",
+                            "mode": "SINGLE",
+                            "value": 13.8
+                        },
+                        {
+                            "symbol": "ZF",
+                            "mode": "SINGLE",
+                            "value": 95
+                        }
+                    ]
+                },
+                {
+                    "uid": "dWJrZX",
+                    "props": {
+                        "calcType": "PbBassin"
+                    },
+                    "children": [],
+                    "parameters": [
+                        {
+                            "symbol": "S",
+                            "mode": "SINGLE",
+                            "value": 15.4
+                        },
+                        {
+                            "symbol": "ZF",
+                            "mode": "SINGLE",
+                            "value": 94.7
+                        }
+                    ]
+                },
+                {
+                    "uid": "dzMxN2",
+                    "props": {
+                        "calcType": "PbBassin"
+                    },
+                    "children": [],
+                    "parameters": [
+                        {
+                            "symbol": "S",
+                            "mode": "SINGLE",
+                            "value": 16.2
+                        },
+                        {
+                            "symbol": "ZF",
+                            "mode": "SINGLE",
+                            "value": 94.7
+                        }
+                    ]
+                },
+                {
+                    "uid": "ZXZua2",
+                    "props": {
+                        "calcType": "PbBassin"
+                    },
+                    "children": [],
+                    "parameters": [
+                        {
+                            "symbol": "S",
+                            "mode": "SINGLE",
+                            "value": 17.5
+                        },
+                        {
+                            "symbol": "ZF",
+                            "mode": "SINGLE",
+                            "value": 94.4
+                        }
+                    ]
+                },
+                {
+                    "uid": "YmR5aD",
+                    "props": {
+                        "calcType": "PbBassin"
+                    },
+                    "children": [],
+                    "parameters": [
+                        {
+                            "symbol": "S",
+                            "mode": "SINGLE",
+                            "value": 32.1
+                        },
+                        {
+                            "symbol": "ZF",
+                            "mode": "SINGLE",
+                            "value": 94.25
+                        }
+                    ]
+                },
+                {
+                    "uid": "bDN2OW",
+                    "props": {
+                        "calcType": "PbBassin"
+                    },
+                    "children": [],
+                    "parameters": [
+                        {
+                            "symbol": "S",
+                            "mode": "SINGLE",
+                            "value": 35
+                        },
+                        {
+                            "symbol": "ZF",
+                            "mode": "SINGLE",
+                            "value": 94.1
+                        }
+                    ]
+                },
+                {
+                    "uid": "MWxycH",
+                    "props": {
+                        "calcType": "PbCloison",
+                        "upstreamBasin": "",
+                        "downstreamBasin": "Zjczdz"
+                    },
+                    "children": [
+                        {
+                            "uid": "MmZ2aG",
+                            "props": {
+                                "calcType": "Structure",
+                                "loiDebit": "WeirCunge80",
+                                "structureType": "SeuilRectangulaire"
+                            },
+                            "children": [],
+                            "parameters": [
+                                {
+                                    "symbol": "ZDV",
+                                    "mode": "SINGLE",
+                                    "value": 95.3
+                                },
+                                {
+                                    "symbol": "L",
+                                    "mode": "SINGLE",
+                                    "value": 0.4
+                                },
+                                {
+                                    "symbol": "CdCunge",
+                                    "mode": "SINGLE",
+                                    "value": 1
+                                }
+                            ]
+                        },
+                        {
+                            "uid": "eW9jZH",
+                            "props": {
+                                "calcType": "Structure",
+                                "loiDebit": "WeirCunge80",
+                                "structureType": "SeuilRectangulaire"
+                            },
+                            "children": [],
+                            "parameters": [
+                                {
+                                    "symbol": "ZDV",
+                                    "mode": "SINGLE",
+                                    "value": 96.25
+                                },
+                                {
+                                    "symbol": "L",
+                                    "mode": "SINGLE",
+                                    "value": 4.4
+                                },
+                                {
+                                    "symbol": "CdCunge",
+                                    "mode": "SINGLE",
+                                    "value": 1
+                                }
+                            ]
+                        }
+                    ],
+                    "parameters": []
+                },
+                {
+                    "uid": "c3Zpb2",
+                    "props": {
+                        "calcType": "PbCloison",
+                        "upstreamBasin": "",
+                        "downstreamBasin": "dWJrZX"
+                    },
+                    "children": [
+                        {
+                            "uid": "bTQ2cG",
+                            "props": {
+                                "calcType": "Structure",
+                                "loiDebit": "WeirCunge80",
+                                "structureType": "SeuilRectangulaire"
+                            },
+                            "children": [],
+                            "parameters": [
+                                {
+                                    "symbol": "ZDV",
+                                    "mode": "SINGLE",
+                                    "value": 96
+                                },
+                                {
+                                    "symbol": "L",
+                                    "mode": "SINGLE",
+                                    "value": 1
+                                },
+                                {
+                                    "symbol": "CdCunge",
+                                    "mode": "SINGLE",
+                                    "value": 1
+                                }
+                            ]
+                        },
+                        {
+                            "uid": "N24zM2",
+                            "props": {
+                                "calcType": "Structure",
+                                "loiDebit": "WeirCunge80",
+                                "structureType": "SeuilRectangulaire"
+                            },
+                            "children": [],
+                            "parameters": [
+                                {
+                                    "symbol": "ZDV",
+                                    "mode": "SINGLE",
+                                    "value": 96.25
+                                },
+                                {
+                                    "symbol": "L",
+                                    "mode": "SINGLE",
+                                    "value": 5
+                                },
+                                {
+                                    "symbol": "CdCunge",
+                                    "mode": "SINGLE",
+                                    "value": 1
+                                }
+                            ]
+                        }
+                    ],
+                    "parameters": []
+                },
+                {
+                    "uid": "MG4wNG",
+                    "props": {
+                        "calcType": "PbCloison",
+                        "upstreamBasin": "",
+                        "downstreamBasin": "YmR5aD"
+                    },
+                    "children": [
+                        {
+                            "uid": "azV4dj",
+                            "props": {
+                                "calcType": "Structure",
+                                "loiDebit": "WeirCunge80",
+                                "structureType": "SeuilRectangulaire"
+                            },
+                            "children": [],
+                            "parameters": [
+                                {
+                                    "symbol": "ZDV",
+                                    "mode": "SINGLE",
+                                    "value": 96.25
+                                },
+                                {
+                                    "symbol": "L",
+                                    "mode": "SINGLE",
+                                    "value": 3.5
+                                },
+                                {
+                                    "symbol": "CdCunge",
+                                    "mode": "SINGLE",
+                                    "value": 1
+                                }
+                            ]
+                        }
+                    ],
+                    "parameters": []
+                },
+                {
+                    "uid": "YjJra2",
+                    "props": {
+                        "calcType": "PbCloison",
+                        "upstreamBasin": "",
+                        "downstreamBasin": "bDN2OW"
+                    },
+                    "children": [
+                        {
+                            "uid": "aDd4Y3",
+                            "props": {
+                                "calcType": "Structure",
+                                "loiDebit": "WeirCunge80",
+                                "structureType": "SeuilRectangulaire"
+                            },
+                            "children": [],
+                            "parameters": [
+                                {
+                                    "symbol": "ZDV",
+                                    "mode": "SINGLE",
+                                    "value": 96.25
+                                },
+                                {
+                                    "symbol": "L",
+                                    "mode": "SINGLE",
+                                    "value": 3.6
+                                },
+                                {
+                                    "symbol": "CdCunge",
+                                    "mode": "SINGLE",
+                                    "value": 1
+                                }
+                            ]
+                        }
+                    ],
+                    "parameters": []
+                },
+                {
+                    "uid": "enE4cn",
+                    "props": {
+                        "calcType": "PbCloison",
+                        "upstreamBasin": "Zjczdz",
+                        "downstreamBasin": "dzMxN2"
+                    },
+                    "children": [
+                        {
+                            "uid": "ZHczZ2",
+                            "props": {
+                                "calcType": "Structure",
+                                "loiDebit": "WeirCunge80",
+                                "structureType": "SeuilRectangulaire"
+                            },
+                            "children": [],
+                            "parameters": [
+                                {
+                                    "symbol": "ZDV",
+                                    "mode": "SINGLE",
+                                    "value": 95
+                                },
+                                {
+                                    "symbol": "L",
+                                    "mode": "SINGLE",
+                                    "value": 0.4
+                                },
+                                {
+                                    "symbol": "CdCunge",
+                                    "mode": "SINGLE",
+                                    "value": 1
+                                }
+                            ]
+                        },
+                        {
+                            "uid": "aXRjZ3",
+                            "props": {
+                                "calcType": "Structure",
+                                "loiDebit": "WeirCunge80",
+                                "structureType": "SeuilRectangulaire"
+                            },
+                            "children": [],
+                            "parameters": [
+                                {
+                                    "symbol": "ZDV",
+                                    "mode": "SINGLE",
+                                    "value": 96.25
+                                },
+                                {
+                                    "symbol": "L",
+                                    "mode": "SINGLE",
+                                    "value": 5.2
+                                },
+                                {
+                                    "symbol": "CdCunge",
+                                    "mode": "SINGLE",
+                                    "value": 1
+                                }
+                            ]
+                        }
+                    ],
+                    "parameters": []
+                },
+                {
+                    "uid": "NXNoNG",
+                    "props": {
+                        "calcType": "PbCloison",
+                        "upstreamBasin": "dWJrZX",
+                        "downstreamBasin": "dzMxN2"
+                    },
+                    "children": [
+                        {
+                            "uid": "eXFqeH",
+                            "props": {
+                                "calcType": "Structure",
+                                "loiDebit": "WeirCunge80",
+                                "structureType": "SeuilRectangulaire"
+                            },
+                            "children": [],
+                            "parameters": [
+                                {
+                                    "symbol": "ZDV",
+                                    "mode": "SINGLE",
+                                    "value": 95.85
+                                },
+                                {
+                                    "symbol": "L",
+                                    "mode": "SINGLE",
+                                    "value": 4.38
+                                },
+                                {
+                                    "symbol": "CdCunge",
+                                    "mode": "SINGLE",
+                                    "value": 1
+                                }
+                            ]
+                        }
+                    ],
+                    "parameters": []
+                },
+                {
+                    "uid": "bGhodG",
+                    "props": {
+                        "calcType": "PbCloison",
+                        "upstreamBasin": "dWJrZX",
+                        "downstreamBasin": "ZXZua2"
+                    },
+                    "children": [
+                        {
+                            "uid": "b3Z3OD",
+                            "props": {
+                                "calcType": "Structure",
+                                "loiDebit": "WeirCunge80",
+                                "structureType": "SeuilRectangulaire"
+                            },
+                            "children": [],
+                            "parameters": [
+                                {
+                                    "symbol": "ZDV",
+                                    "mode": "SINGLE",
+                                    "value": 95.85
+                                },
+                                {
+                                    "symbol": "L",
+                                    "mode": "SINGLE",
+                                    "value": 3
+                                },
+                                {
+                                    "symbol": "CdCunge",
+                                    "mode": "SINGLE",
+                                    "value": 1
+                                }
+                            ]
+                        }
+                    ],
+                    "parameters": []
+                },
+                {
+                    "uid": "MDZ3aH",
+                    "props": {
+                        "calcType": "PbCloison",
+                        "upstreamBasin": "dWJrZX",
+                        "downstreamBasin": "YmR5aD"
+                    },
+                    "children": [
+                        {
+                            "uid": "NTBzZm",
+                            "props": {
+                                "calcType": "Structure",
+                                "loiDebit": "WeirCunge80",
+                                "structureType": "SeuilRectangulaire"
+                            },
+                            "children": [],
+                            "parameters": [
+                                {
+                                    "symbol": "ZDV",
+                                    "mode": "SINGLE",
+                                    "value": 95.5
+                                },
+                                {
+                                    "symbol": "L",
+                                    "mode": "SINGLE",
+                                    "value": 1
+                                },
+                                {
+                                    "symbol": "CdCunge",
+                                    "mode": "SINGLE",
+                                    "value": 1
+                                }
+                            ]
+                        },
+                        {
+                            "uid": "b3pjZX",
+                            "props": {
+                                "calcType": "Structure",
+                                "loiDebit": "WeirCunge80",
+                                "structureType": "SeuilRectangulaire"
+                            },
+                            "children": [],
+                            "parameters": [
+                                {
+                                    "symbol": "ZDV",
+                                    "mode": "SINGLE",
+                                    "value": 95.75
+                                },
+                                {
+                                    "symbol": "L",
+                                    "mode": "SINGLE",
+                                    "value": 3
+                                },
+                                {
+                                    "symbol": "CdCunge",
+                                    "mode": "SINGLE",
+                                    "value": 1
+                                }
+                            ]
+                        }
+                    ],
+                    "parameters": []
+                },
+                {
+                    "uid": "emZ2bX",
+                    "props": {
+                        "calcType": "PbCloison",
+                        "upstreamBasin": "dzMxN2",
+                        "downstreamBasin": "ZXZua2"
+                    },
+                    "children": [
+                        {
+                            "uid": "cGllNj",
+                            "props": {
+                                "calcType": "Structure",
+                                "loiDebit": "WeirCunge80",
+                                "structureType": "SeuilRectangulaire"
+                            },
+                            "children": [],
+                            "parameters": [
+                                {
+                                    "symbol": "ZDV",
+                                    "mode": "SINGLE",
+                                    "value": 94.7
+                                },
+                                {
+                                    "symbol": "L",
+                                    "mode": "SINGLE",
+                                    "value": 0.4
+                                },
+                                {
+                                    "symbol": "CdCunge",
+                                    "mode": "SINGLE",
+                                    "value": 1
+                                }
+                            ]
+                        },
+                        {
+                            "uid": "aWFseW",
+                            "props": {
+                                "calcType": "Structure",
+                                "loiDebit": "WeirCunge80",
+                                "structureType": "SeuilRectangulaire"
+                            },
+                            "children": [],
+                            "parameters": [
+                                {
+                                    "symbol": "ZDV",
+                                    "mode": "SINGLE",
+                                    "value": 95.65
+                                },
+                                {
+                                    "symbol": "L",
+                                    "mode": "SINGLE",
+                                    "value": 5.74
+                                },
+                                {
+                                    "symbol": "CdCunge",
+                                    "mode": "SINGLE",
+                                    "value": 1
+                                }
+                            ]
+                        }
+                    ],
+                    "parameters": []
+                },
+                {
+                    "uid": "bG1ucj",
+                    "props": {
+                        "calcType": "PbCloison",
+                        "upstreamBasin": "ZXZua2",
+                        "downstreamBasin": "YmR5aD"
+                    },
+                    "children": [
+                        {
+                            "uid": "MDJsaD",
+                            "props": {
+                                "calcType": "Structure",
+                                "loiDebit": "WeirCunge80",
+                                "structureType": "SeuilRectangulaire"
+                            },
+                            "children": [],
+                            "parameters": [
+                                {
+                                    "symbol": "ZDV",
+                                    "mode": "SINGLE",
+                                    "value": 94.4
+                                },
+                                {
+                                    "symbol": "L",
+                                    "mode": "SINGLE",
+                                    "value": 0.4
+                                },
+                                {
+                                    "symbol": "CdCunge",
+                                    "mode": "SINGLE",
+                                    "value": 1
+                                }
+                            ]
+                        },
+                        {
+                            "uid": "ZzY2bT",
+                            "props": {
+                                "calcType": "Structure",
+                                "loiDebit": "WeirCunge80",
+                                "structureType": "SeuilRectangulaire"
+                            },
+                            "children": [],
+                            "parameters": [
+                                {
+                                    "symbol": "ZDV",
+                                    "mode": "SINGLE",
+                                    "value": 95.35
+                                },
+                                {
+                                    "symbol": "L",
+                                    "mode": "SINGLE",
+                                    "value": 6
+                                },
+                                {
+                                    "symbol": "CdCunge",
+                                    "mode": "SINGLE",
+                                    "value": 1
+                                }
+                            ]
+                        }
+                    ],
+                    "parameters": []
+                },
+                {
+                    "uid": "dGNnZz",
+                    "props": {
+                        "calcType": "PbCloison",
+                        "upstreamBasin": "YmR5aD",
+                        "downstreamBasin": "bDN2OW"
+                    },
+                    "children": [
+                        {
+                            "uid": "dnNqeX",
+                            "props": {
+                                "calcType": "Structure",
+                                "loiDebit": "WeirCunge80",
+                                "structureType": "SeuilRectangulaire"
+                            },
+                            "children": [],
+                            "parameters": [
+                                {
+                                    "symbol": "ZDV",
+                                    "mode": "SINGLE",
+                                    "value": 94.25
+                                },
+                                {
+                                    "symbol": "L",
+                                    "mode": "SINGLE",
+                                    "value": 0.7
+                                },
+                                {
+                                    "symbol": "CdCunge",
+                                    "mode": "SINGLE",
+                                    "value": 1
+                                }
+                            ]
+                        },
+                        {
+                            "uid": "ODFkZ2",
+                            "props": {
+                                "calcType": "Structure",
+                                "loiDebit": "WeirCunge80",
+                                "structureType": "SeuilRectangulaire"
+                            },
+                            "children": [],
+                            "parameters": [
+                                {
+                                    "symbol": "ZDV",
+                                    "mode": "SINGLE",
+                                    "value": 95.05
+                                },
+                                {
+                                    "symbol": "L",
+                                    "mode": "SINGLE",
+                                    "value": 9.5
+                                },
+                                {
+                                    "symbol": "CdCunge",
+                                    "mode": "SINGLE",
+                                    "value": 1
+                                }
+                            ]
+                        }
+                    ],
+                    "parameters": []
+                },
+                {
+                    "uid": "amprcm",
+                    "props": {
+                        "calcType": "PbCloison",
+                        "upstreamBasin": "bDN2OW",
+                        "downstreamBasin": ""
+                    },
+                    "children": [
+                        {
+                            "uid": "OG02MT",
+                            "props": {
+                                "calcType": "Structure",
+                                "loiDebit": "WeirCunge80",
+                                "structureType": "SeuilRectangulaire"
+                            },
+                            "children": [],
+                            "parameters": [
+                                {
+                                    "symbol": "ZDV",
+                                    "mode": "SINGLE",
+                                    "value": 94.1
+                                },
+                                {
+                                    "symbol": "L",
+                                    "mode": "SINGLE",
+                                    "value": 0.95
+                                },
+                                {
+                                    "symbol": "CdCunge",
+                                    "mode": "SINGLE",
+                                    "value": 1
+                                }
+                            ]
+                        },
+                        {
+                            "uid": "MHVxZn",
+                            "props": {
+                                "calcType": "Structure",
+                                "loiDebit": "WeirCunge80",
+                                "structureType": "SeuilRectangulaire"
+                            },
+                            "children": [],
+                            "parameters": [
+                                {
+                                    "symbol": "ZDV",
+                                    "mode": "SINGLE",
+                                    "value": 94.75
+                                },
+                                {
+                                    "symbol": "L",
+                                    "mode": "SINGLE",
+                                    "value": 10.2
+                                },
+                                {
+                                    "symbol": "CdCunge",
+                                    "mode": "SINGLE",
+                                    "value": 1
+                                }
+                            ]
+                        }
+                    ],
+                    "parameters": []
+                }
+            ],
+            "parameters": [
+                {
+                    "symbol": "Q",
+                    "mode": "SINGLE",
+                    "value": 0.844
+                },
+                {
+                    "symbol": "Z1",
+                    "mode": "CALCUL"
+                },
+                {
+                    "symbol": "Z2",
+                    "mode": "SINGLE",
+                    "value": 94.45
+                }
+            ]
+        }
+    ]
+}
\ No newline at end of file
diff --git a/src/app/formulaire/definition/form-courbe-remous.ts b/src/app/formulaire/definition/form-courbe-remous.ts
index 844a2c2c84d2c9e200daed40b2bce560972a47dc..304fef0ba260451543d63aea3d0a314bbe2efc6d 100644
--- a/src/app/formulaire/definition/form-courbe-remous.ts
+++ b/src/app/formulaire/definition/form-courbe-remous.ts
@@ -15,7 +15,7 @@ export class FormulaireCourbeRemous extends FormulaireSection {
 
     constructor() {
         super();
-        this._remousResults = new RemousResults();
+        this._remousResults = new RemousResults(this);
         this._props["varCalc"] = ""; // important
     }
 
diff --git a/src/app/formulaire/definition/form-definition.ts b/src/app/formulaire/definition/form-definition.ts
index 2baaff2cf28ad4c9916a9243d5cbb9430a60d04d..9ebc4348b874fd2cee9ba78a8747893747c17c64 100644
--- a/src/app/formulaire/definition/form-definition.ts
+++ b/src/app/formulaire/definition/form-definition.ts
@@ -8,22 +8,23 @@ import {
     SectionNub,
     acSection,
     ParamDefinition,
-    Result
+    Result,
+    VariatedDetails
 } from "jalhyd";
 
 import { FormulaireElement } from "../elements/formulaire-element";
-import { NgParameter, ParamRadioConfig } from "../elements/ngparam";
+import { NgParameter } from "../elements/ngparam";
 import { Field } from "../elements/field";
 import { FormulaireNode } from "../elements/formulaire-node";
 import { FieldSet } from "../elements/fieldset";
 import { FieldsetContainer } from "../elements/fieldset-container";
-import { SelectField } from "../elements/select-field";
 import { DeepFieldsetIterator } from "../form-iterator/deep-fieldset-iterator";
 import { TopFormulaireElementIterator } from "../form-iterator/top-element-iterator";
 import { CalculatorResults } from "../../results/calculator-results";
 import { ServiceFactory } from "../../services/service-factory";
 import { PabTable } from "../elements/pab-table";
 import { SelectEntry } from "../elements/select-entry";
+import { SelectField } from "../elements/select-field";
 
 /**
  * classe de base pour tous les formulaires
@@ -49,13 +50,13 @@ export abstract class FormulaireDefinition extends FormulaireNode implements Obs
     protected _calculateDisabled = false;
 
     /** fichier de configuration */
-    private _jsonConfig: {};
+    protected _jsonConfig: {};
 
     /** copy of options.resultsHelp read by FormDefinition.parseOptions() */
     public helpLinks: { [key: string]: string };
 
-    constructor() {
-        super(undefined);
+    constructor(parent?: FormulaireNode) {
+        super(parent);
     }
 
     // surcharge de FormulaireNode::get:uid()
@@ -199,18 +200,19 @@ export abstract class FormulaireDefinition extends FormulaireNode implements Obs
     public removeFieldset(fs: FieldSet) {
     }
 
-    private parse_fieldset(json: {}, nub?: Nub) {
+    protected parse_fieldset(json: {}, nub?: Nub) {
         const fs = this.createFieldset(this, json, undefined, nub);
         fs.parseConfig(json);
         this.afterParseFieldset(fs);
     }
 
-    private parse_template_container(json: {}, templates: any[]) {
+    protected parse_template_container(json: {}, templates: any[]) {
         const fsc: FieldsetContainer = new FieldsetContainer(this);
         fsc.parseConfig(json, templates);
         this.kids.push(fsc);
     }
 
+    // @TODO move to FormulairePAB by overloading parseConfig()
     private parse_pab_table(json: {}) {
         const tab: PabTable = new PabTable(this);
         tab.parseConfig(json);
@@ -293,6 +295,11 @@ export abstract class FormulaireDefinition extends FormulaireNode implements Obs
         return false;
     }
 
+    /**
+     * Trouve le Ngparameter correspondant au symbole "symbol", parmi tous les
+     * éléments du formulaire
+     * @param symbol string
+     */
     public getParamFromSymbol(symbol: string): NgParameter {
         for (const p of this.allFormElements) {
             if (p instanceof NgParameter) {
@@ -303,26 +310,6 @@ export abstract class FormulaireDefinition extends FormulaireNode implements Obs
         }
     }
 
-    public getDisplayedParamFromState(st: ParamRadioConfig): NgParameter {
-        for (const p of this.allFormElements) {
-            if (p.isDisplayed && p instanceof NgParameter) {
-                if (p.radioState === st) {
-                    return p;
-                }
-            }
-        }
-    }
-
-    public getDisplayedParamListFromState(st: ParamRadioConfig): NgParameter[] {
-        const res = [];
-        for (const p of this.allFormElements) {
-            if (p.isDisplayed && p instanceof NgParameter && p.radioState === st) {
-                res.push(p);
-            }
-        }
-        return res;
-    }
-
     public getFieldById(id: string): Field {
         const res = this.getFormulaireNodeById(id);
         if (res instanceof Field) {
@@ -330,37 +317,6 @@ export abstract class FormulaireDefinition extends FormulaireNode implements Obs
         }
     }
 
-    public getFieldsetById(id: string): FieldSet {
-        const res = this.getFormulaireNodeById(id);
-        if (res instanceof FieldSet) {
-            return res;
-        }
-    }
-
-    public getParameterValue(symbol: string): number {
-        for (const fs of this.allFieldsets) {
-            const p = fs.getNodeParameter(symbol);
-            if (p !== undefined) {
-                switch (p.radioState) {
-                    case ParamRadioConfig.FIX:
-                        return p.getValue();
-
-                    case ParamRadioConfig.VAR:
-                    case ParamRadioConfig.CAL:
-                        return undefined;
-                }
-            }
-        }
-
-        throw new Error(`Formulaire.getNodeParameterValue() : pas de paramètre ${symbol} trouvé`);
-    }
-
-    protected notifyReset() {
-        this.notifyObservers({
-            "action": "resetForm"
-        }, this);
-    }
-
     /**
      * Forwards Nub's progress updated notification.
      * Used by CalculatorComponent to update progress bar
@@ -375,8 +331,6 @@ export abstract class FormulaireDefinition extends FormulaireNode implements Obs
      */
     public reset() {
         this.resetResults([], undefined, true);
-        // prévenir les composants qu'il faut détecter les changements
-        this.notifyReset();
     }
 
     /**
@@ -416,7 +370,8 @@ export abstract class FormulaireDefinition extends FormulaireNode implements Obs
     }
 
     public isDisplayed(id: string) {
-        return (<FormulaireElement>this.getFormulaireNodeById(id)).isDisplayed;
+        const fe = <FormulaireElement>this.getFormulaireNodeById(id);
+        return fe?.isDisplayed;
     }
 
     /**
@@ -443,12 +398,6 @@ export abstract class FormulaireDefinition extends FormulaireNode implements Obs
         return new TopFormulaireElementIterator(this);
     }
 
-    /**
-     * Appelé par CalculatorComponent lorsque le Formulaire est chargé dans la vue,
-     * c'est à dire lorsqu'on affiche un module de calcul à l'écran
-     */
-    public onCalculatorInit() {}
-
     //  interface Observer
 
     public update(sender: any, data: any) {
@@ -520,18 +469,20 @@ export abstract class FormulaireDefinition extends FormulaireNode implements Obs
         return ngparam;
     }
 
-    public getVariatedParameters(): NgParameter[] {
-        let res: NgParameter[] = [];
-        // find variated local parameters
-        res = this.getDisplayedParamListFromState(ParamRadioConfig.VAR);
-        // add variated linked parameters
-        const pms = this.getDisplayedParamListFromState(ParamRadioConfig.LINK);
-        for (const p of pms) {
-            if (p.paramDefinition.hasMultipleValues) {
-                res.push(p);
-            }
+    /** find variated (possibly linked) parameters from model, and get their values at the same time */
+    public getVariatedParameters(): VariatedDetails[] {
+        return this._currentNub.findVariatedParams();
+    }
+
+    /** find fixed (possibly linked) parameters from the given Nub */
+    public getFixedParameters(): NgParameter[] {
+        const fixedParams: ParamDefinition[] = this._currentNub.findFixedParams();
+        let fnp: NgParameter[] = [];
+        for (const fp of fixedParams) {
+            fnp.push(this.getParamFromSymbol(fp.symbol));
         }
-        return res;
+        fnp = fnp.filter((e) => e !== undefined);
+        return fnp;
     }
 
     /**
@@ -540,10 +491,6 @@ export abstract class FormulaireDefinition extends FormulaireNode implements Obs
     public doCompute() {
         // calculate module
         this.compute();
-        // refresh results
-        this.notifyObservers({
-            "action": "resultsUpdated",
-        }, this);
     }
 
     public resetFormResults() {}
diff --git a/src/app/formulaire/definition/form-fixedvar.ts b/src/app/formulaire/definition/form-fixedvar.ts
index 87b008f0cad3c3f773555908e934c894789db049..7509e9bd57934d51b9c51418f1989c80bf3fc489 100644
--- a/src/app/formulaire/definition/form-fixedvar.ts
+++ b/src/app/formulaire/definition/form-fixedvar.ts
@@ -5,9 +5,10 @@ import { ChartType } from "../../results/chart-type";
 import { CalculatorResults } from "../../results/calculator-results";
 import { ParamRadioConfig, NgParameter } from "../elements/ngparam";
 import { FieldSet } from "../elements/fieldset";
+import { FormulaireNode } from "../elements/formulaire-node";
 
-import { Nub, IObservable } from "jalhyd";
 import { SelectFieldCustom } from "../elements/select-field-custom";
+import { Nub, IObservable, VariatedDetails } from "jalhyd";
 
 export class FormulaireFixedVar extends FormulaireDefinition {
 
@@ -20,10 +21,10 @@ export class FormulaireFixedVar extends FormulaireDefinition {
     /** ids of "custom" select fields */
     private _customSelectIds: string[] = [];
 
-    constructor() {
-        super();
+    constructor(parent?: FormulaireNode) {
+        super(parent);
         this._fixedResults = new FixedResults();
-        this._varResults = new VarResults();
+        this._varResults = new VarResults(this);
     }
 
     public get fixedResults() {
@@ -44,19 +45,13 @@ export class FormulaireFixedVar extends FormulaireDefinition {
     }
 
     public addFixedParameters() {
-        for (const p of this.getDisplayedParamListFromState(ParamRadioConfig.FIX)) {
+        for (const p of this.getFixedParameters()) {
             this._fixedResults.addFixedParameter(p);
         }
-
-        for (const p of this.getDisplayedParamListFromState(ParamRadioConfig.LINK)) {
-            if (!p.paramDefinition.hasMultipleValues) {
-                this._fixedResults.addFixedParameter(p);
-            }
-        }
     }
 
-    public set graphType(t: ChartType) {
-        this._varResults.graphType = t;
+    public set chartType(t: ChartType) {
+        this._varResults.chartType = t;
     }
 
     public get hasResults(): boolean {
@@ -121,7 +116,7 @@ export class FormulaireFixedVar extends FormulaireDefinition {
         const computedParam: NgParameter = this.getComputedParameter();
         this.resetFormResults(); // to avoid adding fixed parameters more than once (see below)
         this.addFixedParameters();
-        const varParams: NgParameter[] = this.getVariatedParameters();
+        const varParams: VariatedDetails[] = this.getVariatedParameters();
 
         if (varParams.length === 0) {
             // pas de paramètre à varier
diff --git a/src/app/formulaire/definition/form-macrorugo-compound.ts b/src/app/formulaire/definition/form-macrorugo-compound.ts
index f04e6ccfe47b44d0ad032872a2737a080369c54e..a8cbc7ac605ee477cc3a4bbdfa10e6744b7bdf18 100644
--- a/src/app/formulaire/definition/form-macrorugo-compound.ts
+++ b/src/app/formulaire/definition/form-macrorugo-compound.ts
@@ -1,4 +1,4 @@
-import { IObservable, Nub, MacrorugoCompound, Result, MRCInclination } from "jalhyd";
+import { IObservable, Nub, MacrorugoCompound, Result, MRCInclination, VariatedDetails } from "jalhyd";
 
 import { FieldSet } from "../elements/fieldset";
 import { FieldsetContainer } from "../elements/fieldset-container";
@@ -116,7 +116,7 @@ export class FormulaireMacrorugoCompound extends FormulaireRepeatableFieldset {
     protected reaffectResultComponents() {
         const mrc: MacrorugoCompound = (this.currentNub as MacrorugoCompound);
         const computedParam: NgParameter = this.getComputedParameter();
-        const varParams: NgParameter[] = this.getVariatedParameters();
+        const varParams: VariatedDetails[] = this.getVariatedParameters();
 
         // résultat de calcul de la passe à macrorugo complexe
         const mrcr = this.mrcResults;
diff --git a/src/app/formulaire/definition/form-pab.ts b/src/app/formulaire/definition/form-pab.ts
index 593aa219ab297fbe1bb4a517475a03d8e3737778..d88ae78269c05b9aa8139f04b24d951bc98ecbae 100644
--- a/src/app/formulaire/definition/form-pab.ts
+++ b/src/app/formulaire/definition/form-pab.ts
@@ -1,9 +1,9 @@
-import { Pab, Result } from "jalhyd";
+import { Pab, Result, VariatedDetails } from "jalhyd";
 
 import { FormulaireDefinition } from "./form-definition";
 import { PabResults } from "../../results/pab-results";
 import { NgParameter } from "../elements/ngparam";
-import { longestVarNgParam } from "../../util";
+import { longestVarParam } from "../../util";
 import { CalculatorResults } from "../../results/calculator-results";
 
 /**
@@ -35,7 +35,7 @@ export class FormulairePab extends FormulaireDefinition {
     protected reaffectResultComponents() {
         const pab: Pab = (this.currentNub as Pab);
         const computedParam: NgParameter = this.getComputedParameter();
-        const varParams: NgParameter[] = this.getVariatedParameters();
+        const varParams: VariatedDetails[] = this.getVariatedParameters();
 
         // résultat de calcul de la passe à bassins
         const pabr = this.pabResults;
@@ -55,7 +55,7 @@ export class FormulairePab extends FormulaireDefinition {
         pabr.Z2 = [];
         if (varParams.length > 0) {
             // find longest list
-            const lvp = longestVarNgParam(varParams);
+            const lvp = longestVarParam(varParams);
             const longest = lvp.size;
             // get extended values lists for Z2
             if (pab.prms.Z2.hasMultipleValues) {
diff --git a/src/app/formulaire/definition/form-parallel-structures.ts b/src/app/formulaire/definition/form-parallel-structures.ts
index eaffb9f336341df0784a4d83b56a6c08f43f09e1..5e35710f98d06546543fcd44fabc8ca1d6b604c1 100644
--- a/src/app/formulaire/definition/form-parallel-structures.ts
+++ b/src/app/formulaire/definition/form-parallel-structures.ts
@@ -98,7 +98,7 @@ export class FormulaireParallelStructure extends FormulaireRepeatableFieldset {
     }
 
     protected get fieldsetContainer(): FieldsetContainer {
-        const n = this.getFormulaireNodeById("struct_container");
+        const n = this.getFormulaireNodeById("struct_container"); // @TODO make it generic, do not force ID !
         if (n === undefined || !(n instanceof FieldsetContainer)) {
             throw new Error("l'élément 'struct_container' n'est pas du type FieldsetContainer");
         }
@@ -112,7 +112,7 @@ export class FormulaireParallelStructure extends FormulaireRepeatableFieldset {
      * @param name nom de la propriété qui vient de changer
      * @param val nouvelle valeur de la propriété
      */
-    private adjustProperties(props: Props, name: string, val: any) {
+    protected adjustProperties(props: Props, name: string, val: any) {
         if (name === "structureType") {
             if (! StructureProperties.isCompatibleValues(
                 val, props.getPropValue("loiDebit"), this.currentNub as ParallelStructure
@@ -131,7 +131,7 @@ export class FormulaireParallelStructure extends FormulaireRepeatableFieldset {
     /**
      * abonnement en tant qu'observateur des NgParameter des FieldSet contenus dans le FieldsetContainer
      */
-    private subscribeStructureInputFields(fs: FieldSet) {
+    protected subscribeStructureInputFields(fs: FieldSet) {
         for (const n of fs.allFormElements) {
             if (n instanceof NgParameter) {
                 n.addObserver(this);
@@ -141,7 +141,7 @@ export class FormulaireParallelStructure extends FormulaireRepeatableFieldset {
     /**
      * abonnement en tant qu'observateur du SelectField des FieldSet contenus dans le FieldsetContainer
      */
-    private subscribeStructureSelectFields(fs: FieldSet) {
+    protected subscribeStructureSelectFields(fs: FieldSet) {
         for (const n of fs.allFormElements) {
             if (n instanceof SelectField) {
                 n.addObserver(this);
diff --git a/src/app/formulaire/definition/form-pb-cloison.ts b/src/app/formulaire/definition/form-pb-cloison.ts
new file mode 100644
index 0000000000000000000000000000000000000000..f7680be3a4345933e84410724417722e690584a1
--- /dev/null
+++ b/src/app/formulaire/definition/form-pb-cloison.ts
@@ -0,0 +1,153 @@
+import { FormulaireParallelStructure } from "./form-parallel-structures";
+
+import { IObservable, Nub, PbCloison, PbBassin, Structure } from "jalhyd";
+import { FieldSet } from "../elements/fieldset";
+import { FormulaireNode } from "../elements/formulaire-node";
+import { FieldsetContainer } from "../elements/fieldset-container";
+import { FormulairePrebarrage } from "./form-prebarrage";
+import { SelectFieldCustom } from "../elements/select-field-custom";
+
+export class FormulairePbCloison extends FormulaireParallelStructure {
+
+    // interface Observer
+
+    public update(sender: IObservable, data: any) {
+        // do NOT call super.update() or "newFieldset" action will reset results
+        if (sender instanceof FieldsetContainer) {
+            switch (data.action) {
+                case "newFieldset":
+                    // still reset all results when a fieldset if manually added
+                    if (data.resetResults !== false) {
+                        this.reset();
+                    }
+                    this.subscribeStructureInputFields(data["fieldset"]);
+                    this.subscribeStructureSelectFields(data["fieldset"]);
+            }
+        } else if (sender instanceof FieldSet && data.action === "propertyChange") {
+            switch (sender.id) {
+                case "fs_ouvrage":
+                    const props = sender.properties;
+                    // ensure loiDebit is set
+                    props.setPropValue("loiDebit", data.value);
+                    this.adjustProperties(props, data["name"], data["value"]);
+                    // replace Structure Nub
+                    const newNub = this.replaceNub((sender.nub as Structure), props);
+                    sender.setNub(newNub);
+                    // treat the fieldset as new to re-subscribe to Nub properties change events
+                    this.afterParseFieldset(sender);
+                    this.reset();
+                    break;
+            }
+        }
+
+        if (sender instanceof SelectFieldCustom) {
+            const nub = this._currentNub as PbCloison;
+            const pb = nub.parent;
+            // empty "" data.value.value should return undefined, which is good for amont/aval
+            const newBasin = pb.findChild(data.value?.value) as PbBassin;
+            if (sender.id === "select_upstream_basin") {
+                // update only if upstream basin changed (prevents updating on unwanted events)
+                if (newBasin?.uid !== nub.bassinAmont?.uid) {
+                    // remove and recreate wall (easier for pointers consistency) but preserve UID
+                    const uid = nub.uid;
+                    const oldDownstreamBasin = nub.bassinAval;
+                    pb.deleteChild(pb.findChildPosition(nub.uid));
+                    const newWall = new PbCloison(newBasin, oldDownstreamBasin);
+                    newWall.setUid(uid);
+                    // copy structures
+                    for (const s of nub.structures) {
+                        newWall.addChild(s);
+                    }
+                    pb.addChild(newWall);
+                    this.currentNub = newWall;
+                    this.reset();
+                }
+            } else if (sender.id === "select_downstream_basin") {
+                // update only if downstream basin changed (prevents updating on unwanted events)
+                if (newBasin?.uid !== nub.bassinAval?.uid) {
+                    // remove and recreate wall (easier for pointers consistency) but preserve UID
+                    const uid = nub.uid;
+                    const oldUpstreamBasin = nub.bassinAmont;
+                    pb.deleteChild(pb.findChildPosition(nub.uid));
+                    const newWall = new PbCloison(oldUpstreamBasin, newBasin);
+                    newWall.setUid(uid);
+                    // copy structures
+                    for (const s of nub.structures) {
+                        newWall.addChild(s);
+                    }
+                    pb.addChild(newWall);
+                    this.currentNub = newWall;
+                    this.reset();
+                }
+            }
+            this.notifyObservers({
+                action: "updateBasin",
+                value: this._currentNub.uid // node to select on the schema
+            }, this);
+        }
+    }
+
+    // do not reset results after adding fieldset (when switching results view
+    // from one wall to another, the form is rebuilt) @TODO anyway, we should
+    // reset when a fieldset is manually added from "input" (form) view
+    public createFieldset(parent: FormulaireNode, json: {}, data?: {}, nub?: Nub): FieldSet {
+        if (json["calcType"] === "Structure") {
+            // indice après lequel insérer le nouveau FieldSet
+            const after = data["after"];
+
+            const res: FieldSet = new FieldSet(parent);
+            let sn: Nub;
+            if (nub) { // use existing Nub (build interface based on model)
+                sn = nub;
+            } else {
+                sn = this.createChildNub(data["template"]);
+                this.currentNub.addChild(sn, after);
+            }
+            res.setNub(sn, false);
+
+            if (after !== undefined) {
+                parent.kids.splice(after + 1, 0, res);
+            } else {
+                parent.kids.push(res);
+            }
+
+            // still reset all results when a fieldset if manually added
+            if (data["resetResults"] !== false) {
+                this.reset();
+                (this.parent as FormulairePrebarrage).reset();
+            }
+
+            return res;
+        } else {
+            return super.createFieldset(parent, json, data);
+        }
+    }
+
+    /**
+     * réinitialisation du formulaire suite à un changement d'une valeur, d'une option, ... :
+     * effacement des résultats, application des dépendances, ...
+     */
+    public reset() {
+        // also reset parent results (that will reset all its children results)
+        (this.parent as FormulairePrebarrage).reset();
+    }
+
+    // ensure all PBresults are reset
+    public moveFieldsetUp(fs: FieldSet) {
+        super.moveFieldsetUp(fs);
+        this.reset();
+    }
+
+    // ensure all PBresults are reset
+    public moveFieldsetDown(fs: FieldSet) {
+        super.moveFieldsetDown(fs);
+        this.reset();
+    }
+
+    // ensure all PBresults are reset
+    public removeFieldset(fs: FieldSet) {
+        super.removeFieldset(fs);
+        this.reset();
+    }
+
+}
diff --git a/src/app/formulaire/definition/form-prebarrage.ts b/src/app/formulaire/definition/form-prebarrage.ts
new file mode 100644
index 0000000000000000000000000000000000000000..ef81a7f793ef6315b3e7a26d2ded26f6df56461e
--- /dev/null
+++ b/src/app/formulaire/definition/form-prebarrage.ts
@@ -0,0 +1,303 @@
+import { CalculatorType, PbBassin, PbCloison, IObservable, PreBarrage, VariatedDetails, ParamDefinition } from "jalhyd";
+
+import { FormulaireFixedVar } from "./form-fixedvar";
+import { PbSchema } from "../elements/pb-schema";
+import { FormulaireDefinition } from "./form-definition";
+import { ServiceFactory } from "../../services/service-factory";
+import { FormulairePbCloison } from "./form-pb-cloison";
+import { FieldsetContainer } from "../elements/fieldset-container";
+import { CalculatorResults } from "../../results/calculator-results";
+import { PrebarrageResults } from "../../results/prebarrage-results";
+import { NgParameter } from "../elements/ngparam";
+import { longestVarParam } from "../../util";
+
+/**
+ * Formulaire pour les PréBarrage
+ */
+export class FormulairePrebarrage extends FormulaireFixedVar {
+
+    /** child form for river upstream/downstream elevations and flow */
+    private riverForm: FormulaireFixedVar;
+
+    /** child form for basins dimensions */
+    private basinForm: FormulaireFixedVar;
+
+    /** configuration for re-creating basin form every time needed */
+    private basinFormConfig: string;
+
+    /** child form for walls */
+    private wallForm: FormulairePbCloison;
+
+    /** configuration for re-creating wall form every time needed */
+    private wallFormConfig: string;
+
+    protected _selectedItem: PbBassin | PbCloison;
+
+    protected _pbResults: PrebarrageResults;
+
+    /** if true, show input data in the right panel, else show results */
+    public showInputData = true;
+
+    constructor() {
+        super();
+        this._pbResults = new PrebarrageResults();
+    }
+
+    public get selectedItem(): PbBassin | PbCloison {
+        return this._selectedItem;
+    }
+
+    public get pbResults(): PrebarrageResults {
+        return this._pbResults;
+    }
+
+    public get results(): CalculatorResults[] {
+        // ensure help links are propagated
+        this._pbResults.helpLinks = this.helpLinks;
+        return [ this._pbResults ];
+    }
+
+    public get hasResults(): boolean {
+        return this._pbResults.hasResults;
+    }
+
+    public parseConfig(json?: {}) {
+        if (json !== undefined) {
+            this._jsonConfig = json;
+        }
+        for (const conf_index in this._jsonConfig) {
+            const conf = this._jsonConfig[conf_index];
+            const type: string = conf["type"];
+
+            switch (type) {
+                // options globales
+                case "options":
+                    break;
+
+                case "subform":
+                    this.parse_subform(conf);
+                    break;
+
+                case "pb_schema":
+                    this.parse_pb_schema(conf);
+                    break;
+
+                default:
+                    throw new Error(`type d'objet de module de calcul ${type} non pris en charge`);
+            }
+        }
+        this.completeParse();
+    }
+
+    private parse_subform(json: {}) {
+        switch (json["id"]) {
+            case "subform_river":
+                // parse it and build it once then keep it (it always has the same Nub: PreBarrage)
+                this.riverForm = new FormulaireFixedVar();
+                this.riverForm.defaultProperties["calcType"] = CalculatorType.PreBarrage;
+                this.riverForm.currentNub = this.currentNub;
+                this.riverForm.preparseConfig(json["config"]);
+                this.riverForm.parseConfig(json["config"]);
+                this.kids.push(this.riverForm);
+                // show default form
+                this.showFormElements(this.riverForm);
+                break;
+            case "subform_basin":
+                // only store config to create it multiple times on demand
+                this.basinFormConfig = json["config"];
+                break;
+            case "subform_wall":
+                // same as above
+                this.wallFormConfig = json["config"];
+                break;
+        }
+    }
+
+    private parse_pb_schema(json: {}) {
+        const sch: PbSchema = new PbSchema(this);
+        sch.parseConfig(json);
+        this.kids.push(sch);
+    }
+
+    /**
+     * Déclenché par CalculatorComponent lorsque le schéma de prébarrage
+     * envoie un événement "nodeSelected" (on a cliqué sur un nœud)
+     */
+    public nodeSelected(node: PbBassin | PbCloison) {
+        // store for results formatting
+        this._selectedItem = node;
+
+        // show only the relevant form
+        if (node === undefined) {
+            this.showFormElements(this.riverForm);
+
+        } else if (node instanceof PbBassin) {
+            this.basinForm = new FormulaireFixedVar(this);
+            this.basinForm.defaultProperties["calcType"] = CalculatorType.PbBassin;
+            this.basinForm.currentNub = node;
+            this.basinForm.preparseConfig(this.basinFormConfig);
+            this.basinForm.parseConfig(this.basinFormConfig);
+            ServiceFactory.formulaireService.updateFormulaireLocalisation(this.basinForm);
+            this.showFormElements(this.basinForm);
+
+        } else if (node instanceof PbCloison) {
+            this.wallForm = new FormulairePbCloison(this);
+            this.wallForm.defaultProperties["calcType"] = CalculatorType.PbCloison;
+            this.wallForm.currentNub = node;
+            this.wallForm.preparseConfig(this.wallFormConfig);
+            this.wallForm.parseConfig(this.wallFormConfig);
+            // subscribe to upstream/downstream basin change
+            this.wallForm.addObserver(this); // @TODO why not this.form ? wallForm is just a dummy form to extract elements from…
+            ServiceFactory.formulaireService.updateFormulaireLocalisation(this.wallForm);
+            // add fieldsets for existing Structures
+            if (node.structures.length > 0) {
+                for (const struct of node.structures) {
+                    for (const e of this.wallForm.allFormElements) {
+                        if (e instanceof FieldsetContainer) { // @TODO manage many containers one day ?
+                            e.addFromTemplate(0, undefined, struct, { resetResults: false });
+                        }
+                    }
+                }
+            } else {
+                // if there was no existing structure, add a default one
+                for (const e of this.wallForm.allFormElements) {
+                    if (e instanceof FieldsetContainer) {
+                        e.addFromTemplate(0, undefined, undefined, { resetResults: false });
+                        break;
+                    }
+                }
+            }
+            this.showFormElements(this.wallForm);
+        }
+        this.reaffectResultComponents();
+    }
+
+    /**
+     * Adds all elements of given Formulaire f to the current form, right
+     * after the PbSchema, replacing any other element already present
+     * @param f Formulaire to display
+     */
+    private showFormElements(f: FormulaireDefinition) {
+        // clear all kids except PbSchema
+        this._kids = [ this.kids[0] ];
+        for (const e of f.kids) {
+            this.kids.push(e);
+        }
+    }
+
+    private refreshSchema(nodeUidToSelect: string) {
+        const pbs = this.kids[0] as PbSchema;
+        pbs.refresh(nodeUidToSelect);
+    }
+
+    // interface Observer
+
+    public update(sender: IObservable, data: any) {
+        super.update(sender, data);
+        if (sender instanceof FormulairePbCloison) {
+            if (data.action === "updateBasin") {
+                this.refreshSchema(data.value);
+            }
+        }
+    }
+
+    protected compute() {
+        this.runNubCalc(this.currentNub);
+        this.refreshFieldsets(); // important: before reaffectResultComponents() or it will break results components localization
+        // reset variable index to avoid trying to access an index > 0 when nothing varies
+        const pbr = this.pbResults;
+        pbr.variableIndex = 0;
+
+        this.reaffectResultComponents();
+    }
+
+    protected reaffectResultComponents() {
+        const pb: PreBarrage = (this.currentNub as PreBarrage);
+        const computedParam: NgParameter = this.getComputedParameter();
+
+        // cacher les résultats
+        this.pbResults.reset();
+        this.addFixedParameters();
+
+        // pour le sélecteur d'itérations
+        const varParams: VariatedDetails[] = this.getVariatedParameters();
+        if (varParams) {
+            this.pbResults.variatedParameters = varParams;
+            const lvp = longestVarParam(this._pbResults.variatedParameters);
+            this._pbResults.size = lvp.size;
+            this._pbResults.cloisonResults.size = lvp.size;
+        }
+
+        // résultats selon l'objet sélectionné sur le schéma
+        if (this._selectedItem !== undefined && this._selectedItem instanceof PbCloison) {
+            // afficher les résultats de cloison
+            this.pbResults.cloisonResults.result = this._selectedItem.result;
+            if (computedParam !== undefined) {
+                this.pbResults.cloisonResults.calculatedParameter = computedParam;
+            }
+            // transmission des suffixes de cloisons calculés par l'algo de tri de PbSchemaComponent,
+            // pour le sélecteur de conditions limites
+            const pbs = this.kids[0] as PbSchema;
+            this.pbResults.wallsSuffixes = pbs.wallsSuffixes;
+        } else {
+            // afficher les résultats des bassins
+            // résultat général du Nub (amont, aval, débit)
+            this.pbResults.result = pb.result;
+            this.pbResults.calculatedParameter = computedParam;
+            // résultat de chaque bassin
+            for (const b of pb.bassins) {
+                this.pbResults.bassinsResults.push(b.result);
+            }
+        }
+    }
+
+    /**
+     * Trouve le Ngparameter correspondant au paramètre "p", parmi tous les
+     * éléments du formulaire de PbCloison, qui peut contenir plusieurs
+     * structures ayant des paramètres de même nom
+     * @param param ParamDefinition
+     */
+    public getCloisonParam(param: ParamDefinition): NgParameter {
+        for (const p of this.allFormElements) {
+            if (p instanceof NgParameter) {
+                if (p.paramDefinition === param) {
+                    return p;
+                }
+            }
+        }
+    }
+
+    public addFixedParameters() {
+        if (this._selectedItem !== undefined && this._selectedItem instanceof PbCloison) {
+            for (const s of this._selectedItem.structures) {
+                for (const p of s.parameterIterator) {
+                    // if some parameter is variating, add id too (trick with PbResultsComponent)
+                    if (p.visible) {
+                        const ngp = this.getCloisonParam(p);
+                        if (ngp) {
+                            this._pbResults.cloisonResults.addFixedParameter(ngp);
+                        }
+                    }
+                }
+            }
+        }
+    }
+
+    public resetFormResults() {
+        this._pbResults.reset();
+    }
+
+    public resetResults() {
+        super.resetResults();
+        // reset all children nubs
+        for (const c of this.currentNub.getChildren()) {
+            c.resetResult();
+        }
+        // reset all wall forms
+        for (const k of this.kids) {
+            if (k instanceof FormulaireDefinition) {
+                k.reset();
+            }
+        }
+    }
+}
diff --git a/src/app/formulaire/definition/form-section-parametree.ts b/src/app/formulaire/definition/form-section-parametree.ts
index f4d2319fdbcd62e0ccc8097d6e363361298ad3db..743880b5da19f5ae0542af1402223df2537a29db 100644
--- a/src/app/formulaire/definition/form-section-parametree.ts
+++ b/src/app/formulaire/definition/form-section-parametree.ts
@@ -32,7 +32,7 @@ export class FormulaireSectionParametree extends FormulaireSection {
         const sect: acSection = sectNub.section;
         this._sectionResults.section = sect;
 
-        const varParams = this.getSectionVariatedParameters();
+        const varParams = this.getVariatedParameters();
         if (varParams.length > 0) {
             // résultats variés avec tous les résultats complémentaires
             this._varResults.variatedParameters = varParams;
@@ -55,9 +55,9 @@ export class FormulaireSectionParametree extends FormulaireSection {
     }
 
     public get hasResults(): boolean {
-        return (this._fixedResults !== undefined && this._fixedResults.hasResults)
-            || (this._varResults !== undefined && this._varResults.hasResults)
-            || (this._sectionResults !== undefined && this._sectionResults.hasResults);
+        return (this._fixedResults?.hasResults)
+            || (this._varResults?.hasResults)
+            || (this._sectionResults?.hasResults);
     }
 
     public get results(): CalculatorResults[] {
@@ -71,8 +71,4 @@ export class FormulaireSectionParametree extends FormulaireSection {
         res.push(this._sectionResults);
         return res;
     }
-
-    public getSectionVariatedParameters(): NgParameter[] {
-        return this.getDisplayedParamListFromState(ParamRadioConfig.VAR);
-    }
 }
diff --git a/src/app/formulaire/definition/form-verificateur.ts b/src/app/formulaire/definition/form-verificateur.ts
index 1f712ada6a1b1593f6de789246d5a6cd41327201..b357c4a0de658da92bac30bb62669bdd13caeb67 100644
--- a/src/app/formulaire/definition/form-verificateur.ts
+++ b/src/app/formulaire/definition/form-verificateur.ts
@@ -1,10 +1,9 @@
-import { IObservable, Nub, Verificateur, Result } from "jalhyd";
+import { IObservable, Nub, Verificateur, Result, VariatedDetails } from "jalhyd";
 
 import { SelectFieldCustom } from "../elements/select-field-custom";
 import { FormulaireFixedVar } from "./form-fixedvar";
 import { VerificateurResults } from "../../results/verificateur-results";
 import { CalculatorResults } from "../../results/calculator-results";
-import { NgParameter } from "../elements/ngparam";
 import { ServiceFactory } from "../../services/service-factory";
 
 /**
@@ -36,7 +35,7 @@ export class FormulaireVerificateur extends FormulaireFixedVar {
         this.reaffectResultComponents();
     }
 
-    protected findPassVariatedParameters(): NgParameter[] {
+    protected findPassVariatedParameters(): VariatedDetails[] {
         let pvp = [];
         const passUid = this.verificateurNub.nubToVerify.uid;
         const passForm = ServiceFactory.formulaireService.getFormulaireFromNubId(passUid);
diff --git a/src/app/formulaire/elements/fieldset-container.ts b/src/app/formulaire/elements/fieldset-container.ts
index 96f719fcf0dd192ee0f7af1bf613bb9b69309b48..a8c1ecbe60f98fabcfd8ad96e80465e1f23389c6 100644
--- a/src/app/formulaire/elements/fieldset-container.ts
+++ b/src/app/formulaire/elements/fieldset-container.ts
@@ -71,19 +71,23 @@ export class FieldsetContainer extends FormulaireElement {
      * crée un FieldSet à partir d'un template
      * @param templateIndex indice du template dans la liste
      * @param after insère le nouveau FieldSet après cette position, à la fin sinon
+     * @param nub attaches the given Nub to the new FieldSet
+     * @param extra extra key-value pairs to add to the "newFieldset" event
      */
-    public addFromTemplate(templateIndex: number, after?: number, nub?: Nub): FieldSet {
+    public addFromTemplate(templateIndex: number, after?: number, nub?: Nub, extra?: any): FieldSet {
         const templ: FieldsetTemplate = this._templates[templateIndex];
 
-        const inst: FieldSet = templ.instantiateTemplate(this, after, nub);
+        const inst: FieldSet = templ.instantiateTemplate(this, after, nub, extra);
 
         this.updateLocalisation();
 
         // notification de création d'un FieldSet
-        this.notifyObservers({
+        let info = {
             "action": "newFieldset",
             "fieldset": inst
-        }, this);
+        };
+        info = { ...info, ...extra };
+        this.notifyObservers(info, this);
 
         return inst;
     }
diff --git a/src/app/formulaire/elements/fieldset-template.ts b/src/app/formulaire/elements/fieldset-template.ts
index 3c9071131a974222b80bd5e26762f715de9e1864..b65b48874c37bc13364cb622c05da35bd4f4ebd9 100644
--- a/src/app/formulaire/elements/fieldset-template.ts
+++ b/src/app/formulaire/elements/fieldset-template.ts
@@ -42,10 +42,13 @@ export class FieldsetTemplate {
      * @param cont conteneur
      * @param after position à laquelle on ajoute le nouveau FieldSet
      * @param nub Nub existant à injecter dans le Fieldset
+     * @param extra extra key-value pairs to add to the "newFieldset" event
      */
-    public instantiateTemplate(cont: FieldsetContainer, after: number, nub?: Nub): FieldSet {
+    public instantiateTemplate(cont: FieldsetContainer, after: number, nub?: Nub, extra?: any): FieldSet {
         const parentForm = cont.parent as FormulaireDefinition;
-        const res = parentForm.createFieldset(cont, this._jsonConfig, { "template": this, "after": after }, nub);
+        let info = { "template": this, "after": after };
+        info = { ...info, ... extra };
+        const res = parentForm.createFieldset(cont, this._jsonConfig, info, nub);
         res.parseConfig(this._jsonConfig);
         parentForm.afterParseFieldset(res);
         return res;
diff --git a/src/app/formulaire/elements/formulaire-node.ts b/src/app/formulaire/elements/formulaire-node.ts
index 79982717c2e5176ae14aa3562c6183489ba46ac7..7731dfd43029def02f02d3299a9508ad350c653e 100644
--- a/src/app/formulaire/elements/formulaire-node.ts
+++ b/src/app/formulaire/elements/formulaire-node.ts
@@ -22,7 +22,7 @@ export abstract class FormulaireNode implements IObservable {
     private _parentNode: FormulaireNode;
 
     /** enfants (utilisé entre autres pour FormulaireDefinition, FieldSet et FieldsetContainer) */
-    private _kids: FormulaireNode[];
+    protected _kids: FormulaireNode[];
 
     /** implémentation par délégation de IObservable */
     private _observable: Observable;
diff --git a/src/app/formulaire/elements/ngparam.ts b/src/app/formulaire/elements/ngparam.ts
index 457e689763ece29e593941c39b831d4f07899aa2..7943071edcf11c5c0b865d0b76cfd1548c9dc700 100644
--- a/src/app/formulaire/elements/ngparam.ts
+++ b/src/app/formulaire/elements/ngparam.ts
@@ -319,10 +319,6 @@ export class NgParameter extends InputField implements Observer {
         }
     }
 
-    public getExtendedValuesIterator(size: number): INumberIterator {
-        return this._paramDef.getExtendedValuesIterator(size);
-    }
-
     /**
      * notification envoyée après la modification de la valeur du paramètre
      */
@@ -468,6 +464,9 @@ export class NgParameter extends InputField implements Observer {
         }
         this.unit = this.paramDefinition.unit;
         this.radioConfig = this.getRadioConfig();
+        if (json["calculable"] !== undefined && json["calculable"] === false) {
+            this.radioConfig = Math.min(ParamCalculability.FREE, this.getRadioConfig());
+        }
     }
 
     // interface Observer
diff --git a/src/app/formulaire/elements/pab-table.ts b/src/app/formulaire/elements/pab-table.ts
index 3601cf19b5ee2e7a4e6569ce6f6b2551e9122ed8..e9934bb9c5996e828f4c887d3bdb5de86de16ada 100644
--- a/src/app/formulaire/elements/pab-table.ts
+++ b/src/app/formulaire/elements/pab-table.ts
@@ -1,7 +1,6 @@
 import { Pab } from "jalhyd";
 
 import { FormulaireElement } from "./formulaire-element";
-import { FormulaireNode } from "./formulaire-node";
 import { FormulairePab } from "../definition/form-pab";
 
 /**
diff --git a/src/app/formulaire/elements/pb-schema.ts b/src/app/formulaire/elements/pb-schema.ts
new file mode 100644
index 0000000000000000000000000000000000000000..278b7fe395f18c814bdf3774d4c92df4b8f8309d
--- /dev/null
+++ b/src/app/formulaire/elements/pb-schema.ts
@@ -0,0 +1,46 @@
+import { PreBarrage } from "jalhyd";
+
+import { FormulaireElement } from "./formulaire-element";
+import { FormulairePrebarrage } from "../definition/form-prebarrage";
+
+/**
+ * The interactive schema for calculator type "PreBarrage" (form element).
+ *
+ * This is just a gateway between the model (Prebarrage)
+ * and the user interface (PbSchemaComponent)
+ */
+export class PbSchema extends FormulaireElement {
+
+    /** Stores appropriate number suffix for a given wall uid (related to existingWalls above) */
+    public wallsSuffixes: { [key: string]: number };
+
+    public parseConfig(json: {}) {
+        this._confId = json["id"];
+    }
+
+    /**
+     * Returns the Prebarrage model associated to the parent form
+     */
+    public get form(): FormulairePrebarrage {
+        if (this.parentForm) {
+            return this.parentForm as FormulairePrebarrage;
+        }
+    }
+
+    /**
+     * Returns the Prebarrage model associated to the parent form
+     */
+    public get pb(): PreBarrage {
+        if (this.parentForm) {
+            return this.parentForm.currentNub as PreBarrage;
+        }
+    }
+
+    /** Asks PbSchemaComponent to redraw the schema */
+    public refresh(nodeUidToSelect: string) {
+        this.notifyObservers({
+            action: "refresh",
+            value: nodeUidToSelect
+        }, this);
+    }
+}
diff --git a/src/app/formulaire/elements/select-field-custom.ts b/src/app/formulaire/elements/select-field-custom.ts
index a9f28c9c621e7cf9031ce4d026a73f735d8e3632..1036e25ac1fd24cdef5a7bde122ec68fccb321e3 100644
--- a/src/app/formulaire/elements/select-field-custom.ts
+++ b/src/app/formulaire/elements/select-field-custom.ts
@@ -3,7 +3,7 @@ import { ServiceFactory } from "../../services/service-factory";
 import { SelectField } from "./select-field";
 import { decodeHtml, arraysAreEqual } from "../../util";
 
-import { FishSpecies, Session, Solveur, FishPass, CalculatorType, Verificateur, Nub } from "jalhyd";
+import { FishSpecies, Session, Solveur, FishPass, CalculatorType, Verificateur, Nub, PbCloison, PreBarrage } from "jalhyd";
 
 import { sprintf } from "sprintf-js";
 
@@ -50,6 +50,18 @@ export class SelectFieldCustom extends SelectField {
                     }));
                 }
                 break;
+
+            case "upstream_basin": // PbCloisons, bassin amont
+                const ub = (nub as PbCloison).bassinAmont;
+                // console.log("-- load UB", ub, this._entriesBaseId + ub?.uid);
+                this.setValueFromId(this._entriesBaseId + (ub ? ub.uid : "none"));
+                break;
+
+            case "downstream_basin": // PbCloisons, bassin aval
+                const db = (nub as PbCloison).bassinAval;
+                // console.log("-- load DB", db, this._entriesBaseId + db?.uid);
+                this.setValueFromId(this._entriesBaseId + (db ? db.uid : "none"));
+                break;
         }
     }
 
@@ -152,6 +164,60 @@ export class SelectFieldCustom extends SelectField {
                     );
                 }
                 break;
+
+            case "upstream_basin": // PbCloisons, bassin amont
+                const pbWallU = this.parentForm.currentNub as PbCloison;
+                const preBarrageU = pbWallU.parent as PreBarrage;
+                const posDb = pbWallU.bassinAval?.findPositionInParent();
+                // river upstream
+                this.addEntry(
+                    new SelectEntry(
+                        this._entriesBaseId + "none",
+                        undefined,
+                        ServiceFactory.i18nService.localizeText("INFO_LIB_AMONT")
+                    )
+                );
+                // all available basins, depending on current downstream basin
+                for (const b of preBarrageU.bassins) {
+                    const pos = b.findPositionInParent();
+                    if (posDb === undefined || pos < posDb) {
+                        this.addEntry(
+                            new SelectEntry(
+                                this._entriesBaseId + b.uid,
+                                b.uid,
+                                ServiceFactory.i18nService.localizeMessage(b.description)
+                            )
+                        );
+                    }
+                }
+                break;
+
+            case "downstream_basin": // PbCloisons, bassin aval
+                const pbWallD = this.parentForm.currentNub as PbCloison;
+                const preBarrageD = pbWallD.parent as PreBarrage;
+                const posUb = pbWallD.bassinAmont?.findPositionInParent();
+                // all available basins, depending on current upstream basin
+                for (const b of preBarrageD.bassins) {
+                    const pos = b.findPositionInParent();
+                    if (posUb === undefined || pos > posUb) {
+                        this.addEntry(
+                            new SelectEntry(
+                                this._entriesBaseId + b.uid,
+                                b.uid,
+                                ServiceFactory.i18nService.localizeMessage(b.description)
+                            )
+                        );
+                    }
+                }
+                // river downstream
+                this.addEntry(
+                    new SelectEntry(
+                        this._entriesBaseId + "none",
+                        undefined,
+                        ServiceFactory.i18nService.localizeText("INFO_LIB_AVAL")
+                    )
+                );
+                break;
         }
     }
 
diff --git a/src/app/formulaire/elements/select-field.ts b/src/app/formulaire/elements/select-field.ts
index d003d2a6d36f30d495dd7de200e4c1e0b0a96fae..6a0183d2209e9641d413dcd6d02ec714c32aef9f 100644
--- a/src/app/formulaire/elements/select-field.ts
+++ b/src/app/formulaire/elements/select-field.ts
@@ -5,7 +5,8 @@ import {
     StructureType,
     LoiDebit,
     Session,
-    Solveur
+    Solveur,
+    StructureProperties
  } from "jalhyd";
 
 import { Field } from "./field";
@@ -191,11 +192,11 @@ export class SelectField extends Field {
                 // @WARNING for localisation, @see hack in this.updateLocalisation()
                 // 1. calculated param
                 const ntc = (nub as Solveur).nubToCalculate;
-                if (ntc !== undefined && ntc.calculatedParam !== undefined) { // some nubs have no calculatedParam, for ex. SectionParam
+                if (ntc?.calculatedParam !== undefined) { // some nubs have no calculatedParam, for ex. SectionParam
                     this.addEntry(new SelectEntry(this._entriesBaseId + "none", ""));
                 }
                 // 2. extra results
-                if (ntc !== undefined && ntc.resultsFamilies !== undefined) {
+                if (ntc?.resultsFamilies !== undefined) {
                     for (const er of Object.keys(ntc.resultsFamilies)) {
                         const e: SelectEntry = new SelectEntry(this._entriesBaseId + er, er);
                         this.addEntry(e);
@@ -215,9 +216,10 @@ export class SelectField extends Field {
             case "device_loi_debit":
                 // get current structure type from appropriate Nub child
                 const child = nub.getChildren()[this.parent.indexAsKid()];
-                const cst = child.properties.getPropValue("structureType");
                 const la = (nub as ParallelStructure).getLoisAdmissibles();
-                const stName = StructureType[cst];
+                const loiDebit = child.properties.getPropValue("loiDebit");
+                const stCode = StructureProperties.findCompatibleStructure(loiDebit, nub as ParallelStructure);
+                const stName = StructureType[stCode];
                 for (const ld of la[stName]) {
                     const e: SelectEntry = new SelectEntry(this._entriesBaseId + LoiDebit[ld], ld);
                     this.addEntry(e);
diff --git a/src/app/results/macrorugo-compound-results.ts b/src/app/results/macrorugo-compound-results.ts
index 8aba75366df359fc005419da671cd87be46008d2..74e776f72846483d97857ed9f123cb6714dbb5eb 100644
--- a/src/app/results/macrorugo-compound-results.ts
+++ b/src/app/results/macrorugo-compound-results.ts
@@ -1,9 +1,11 @@
-import { Result } from "jalhyd";
+import { Result, ParamDefinition } from "jalhyd";
 
 import { ServiceFactory } from "../services/service-factory";
 import { MultiDimensionResults } from "./multidimension-results";
+import { PlottableData } from "./plottable-data";
+import { ChartType } from "./chart-type";
 
-export class MacrorugoCompoundResults extends MultiDimensionResults {
+export class MacrorugoCompoundResults extends MultiDimensionResults implements PlottableData {
 
     /** résultats des modules MacroRugo enfants */
     public childrenResults: Result[];
@@ -11,6 +13,10 @@ export class MacrorugoCompoundResults extends MultiDimensionResults {
     /** symboles des colonnes de résultat */
     protected _columns: string[];
 
+    public chartType: ChartType = ChartType.Scatter;
+    public chartX: string;
+    public chartY: string;
+
     public constructor() {
         super();
         this.reset();
@@ -28,6 +34,9 @@ export class MacrorugoCompoundResults extends MultiDimensionResults {
             "ENUM_MacroRugoFlowType",
             "xCenter"
         ];
+        // axes par défaut
+        this.chartX = this.chartX || "xCenter";
+        this.chartY = this.chartY || "Q";
     }
 
     /** headers symbols */
@@ -119,4 +128,99 @@ export class MacrorugoCompoundResults extends MultiDimensionResults {
 
         return err;
     }
+    public hasPlottableResults(): boolean {
+        return this.hasResults;
+    }
+
+    /**
+     * Returns the label to display, for an element of getAvailableChartAxis()
+     * @param symbol parameter / result symbol (ex: "Q")
+     */
+    public getChartAxisLabel(symbol: string): string {
+        return this.headers[this.columns.indexOf(symbol)];
+    }
+
+    public expandLabelFromSymbol(p: ParamDefinition): string {
+        return p.symbol;
+    }
+
+    /**
+     * Returns a list of plottable parameters / result elements, that can be defined
+     * as X or Y chart axis
+     */
+    public getAvailableChartAxis(): string[] {
+        const axis = [];
+        for (const c of this.columns) {
+            if (c.indexOf("ENUM_") === -1) { // ENUM variables are not plottable
+                axis.push(c);
+            }
+        }
+        return axis;
+    }
+
+    public getAvailableXAxis(): string[] {
+        return this.getAvailableChartAxis();
+    }
+
+    public getAvailableYAxis(): string[] {
+        return this.getAvailableChartAxis();
+    }
+
+    // just to implement interface
+    public getVariatingParametersSymbols(): string[] {
+        return [];
+    }
+
+    /**
+     * Returns the series of values for the required symbol
+     * @param symbol parameter / result symbol (ex: "Q")
+     */
+    public getValuesSeries(symbol: string): number[] {
+        const data: number[] = [];
+        const l = this.childrenResults.length;
+        // when a parameter is variating, index of the variating parameter
+        // values to build the data from
+        const vi = this.variableIndex;
+
+        if (this.iterationHasError(vi)) {
+            return [];
+        }
+
+        for (let i = 0; i < l; i++) {
+            switch (symbol) {
+                case "RADIER_N":
+                    data.push(i + 1);
+                    break;
+
+                case "ZF1":
+                case "Y":
+                case "B":
+                    let v: number;
+                    const nub = this.childrenResults[i].sourceNub;
+                    const param = nub.getParameter(symbol);
+                    try {
+                        if (param.hasMultipleValues) {
+                            v = param.getInferredValuesList()[vi];
+                        } else {
+                            v = param.singleValue;
+                        }
+                    } catch (e) {
+                        // silent fail
+                    }
+                    data.push(v);
+                    break;
+
+                case "Q":
+                case "Vdeb":
+                case "Fr":
+                case "Vmax":
+                case "PV":
+                case "xCenter":
+                    data.push(this.childrenResults[i].resultElements[vi].getValue(symbol));
+                    break;
+            }
+        }
+
+        return data;
+    }
 }
diff --git a/src/app/results/multidimension-results.ts b/src/app/results/multidimension-results.ts
index 4b2aee2ed330a5bf7a59c008debf9ce2a034f117..c7af4cc990ab030b530ce740f5147cb22fa436d2 100644
--- a/src/app/results/multidimension-results.ts
+++ b/src/app/results/multidimension-results.ts
@@ -1,12 +1,22 @@
 import { CalculatedParamResults } from "./param-calc-results";
-import { NgParameter } from "../formulaire/elements/ngparam";
+
+import { VariatedDetails } from "jalhyd";
 
 
 export class MultiDimensionResults extends CalculatedParamResults {
 
     /** paramètres variés */
-    public variatedParameters: NgParameter[];
+    public variatedParameters: VariatedDetails[] = [];
 
     /** index de la valeur du paramètre varié à afficher dans les résultats */
-    public variableIndex = 0;
+    protected _variableIndex = 0;
+
+    public get variableIndex(): number {
+        return this._variableIndex;
+    }
+
+    /** redéfini par PrebarrageResults notamment */
+    public set variableIndex(v: number) {
+        this._variableIndex = v;
+    }
 }
diff --git a/src/app/results/pab-results.ts b/src/app/results/pab-results.ts
index d08b381f1137262d70d32b21f8ae4950f08ed423..d282524efac3c6e3f05d8e0936f4d15134f74f58 100644
--- a/src/app/results/pab-results.ts
+++ b/src/app/results/pab-results.ts
@@ -1,9 +1,11 @@
-import { Result } from "jalhyd";
+import { Result, ParamDefinition } from "jalhyd";
 
 import { ServiceFactory } from "../services/service-factory";
 import { MultiDimensionResults } from "./multidimension-results";
+import { PlottableData } from "./plottable-data";
+import { ChartType } from "./chart-type";
 
-export class PabResults extends MultiDimensionResults {
+export class PabResults extends MultiDimensionResults implements PlottableData {
 
     /** résultats des modules Cloisons avant chaque bassin */
     public cloisonsResults: Result[];
@@ -20,6 +22,10 @@ export class PabResults extends MultiDimensionResults {
     /** symboles des colonnes de résultat */
     protected _columns: string[];
 
+    public chartType: ChartType = ChartType.Scatter;
+    public chartX: string;
+    public chartY: string;
+
     public constructor() {
         super();
         this.reset();
@@ -36,6 +42,9 @@ export class PabResults extends MultiDimensionResults {
             "QA",
             "ENUM_StructureJetType"
         ];
+        // axes par défaut
+        this.chartX = this.chartX || "CLOISON";
+        this.chartY = this.chartY || "YMOY";
     }
 
     /** headers symbols */
@@ -130,4 +139,121 @@ export class PabResults extends MultiDimensionResults {
 
         return err;
     }
+
+    public hasPlottableResults(): boolean {
+        return this.hasResults;
+    }
+
+    /**
+     * Returns the label to display, for an element of getAvailableChartAxis()
+     * @param symbol parameter / result symbol (ex: "Q")
+     */
+    public getChartAxisLabel(symbol: string): string {
+        if (symbol === "x") { // specific case for wall abscissa
+            return ServiceFactory.i18nService.localizeText("INFO_LIB_ABSCISSE_CLOISON");
+        } else {
+            return this.headers[this.columns.indexOf(symbol)];
+        }
+    }
+
+    public expandLabelFromSymbol(p: ParamDefinition): string {
+        return p.symbol;
+    }
+
+    /**
+     * Returns a list of plottable parameters / result elements, that can be defined
+     * as X or Y chart axis
+     */
+    public getAvailableChartAxis(): string[] {
+        const axis = [];
+        axis.push("x"); // wall abscissa
+        for (const c of this.columns) {
+            if (c.indexOf("ENUM_") === -1) { // ENUM variables are not plottable
+                axis.push(c);
+            }
+        }
+        return axis;
+    }
+
+    public getAvailableXAxis(): string[] {
+        return this.getAvailableChartAxis();
+    }
+
+    public getAvailableYAxis(): string[] {
+        return this.getAvailableChartAxis();
+    }
+
+    // just to implement interface
+    public getVariatingParametersSymbols(): string[] {
+        return [];
+    }
+
+    /**
+     * Returns the series of values for the required symbol
+     * @param symbol parameter / result symbol (ex: "Q")
+     */
+    public getValuesSeries(symbol: string): number[] {
+        const data: number[] = [];
+        const l = this.cloisonsResults.length;
+        // when a parameter is variating, index of the variating parameter
+        // values to build the data from
+        const vi = this.variableIndex;
+
+        if (this.iterationHasError(vi)) {
+            return [];
+        }
+
+        switch (symbol) {
+            case "CLOISON":
+                data.push(undefined);
+                for (let i = 0; i <= l; i++) { // <= for one extra step (downwall)
+                    data.push(i + 1);
+                }
+                break;
+
+            case "DH":
+            case "ZRAM":
+            case "Q":
+                data.push(undefined);
+                for (let i = 0; i < l; i++) {
+                    const er = this.cloisonsResults[i].resultElements[vi].getValue(symbol);
+                    data.push(er);
+                }
+                const zrAval = this.cloisonAvalResults.resultElements[vi].getValue(symbol);
+                data.push(zrAval);
+                break;
+
+            case "Z":
+                for (let i = 0; i < l; i++) {
+                    data.push(this.cloisonsResults[i].resultElements[vi].vCalc);
+                }
+                data.push(this.cloisonAvalResults.resultElements[vi].vCalc);
+                data.push(this.Z2[vi]);
+                break;
+
+            case "PV":
+            case "YMOY":
+            case "ZRMB":
+            case "QA":
+                data.push(undefined);
+                for (let i = 0; i < l; i++) {
+                    const er = this.cloisonsResults[i].resultElements[vi].getValue(symbol);
+                    data.push(er);
+                }
+                data.push(undefined);
+                break;
+
+            case "x": // wall abscissa
+                data.push(undefined);
+                for (let i = 0; i < l; i++) {
+                    const er = this.cloisonsResults[i].resultElements[vi].getValue(symbol);
+                    data.push(er);
+                }
+                const erXdw = this.cloisonAvalResults.resultElements[vi].getValue(symbol);
+                data.push(erXdw);
+                break;
+        }
+
+        return data;
+    }
 }
diff --git a/src/app/results/param-calc-results.ts b/src/app/results/param-calc-results.ts
index 6a24188484a22305e7e9ba15c2be440f351d13a0..eaca087d32dee78357630328c0c72508f7b00e44 100644
--- a/src/app/results/param-calc-results.ts
+++ b/src/app/results/param-calc-results.ts
@@ -40,15 +40,6 @@ export abstract class CalculatedParamResults extends CalculatorResults {
             return false;
         }
         return true;
-        // return ! this.result.hasOnlyErrors;
-    }
-
-    /** return true if there is something to display on the variable results chart */
-    public get hasPlottableResults(): boolean {
-        if (this.result === undefined) {
-            return false;
-        }
-        return ! this.result.hasOnlyErrors;
     }
 
     public get hasLog(): boolean {
diff --git a/src/app/results/pb-cloison-results.ts b/src/app/results/pb-cloison-results.ts
new file mode 100644
index 0000000000000000000000000000000000000000..44524dfacbb3e97bba79d4462d2d3b2ae1cdf5fc
--- /dev/null
+++ b/src/app/results/pb-cloison-results.ts
@@ -0,0 +1,11 @@
+import { FixedResults } from "./fixed-results";
+
+/** Fixed results, that are not really fixed (trick for PreBarrage) */
+export class PbCloisonResults extends FixedResults {
+
+    /** index de la valeur du paramètre varié à afficher dans les résultats */
+    public variableIndex = 0;
+
+    /** size of the longest variating parameter */
+    public size = 1;
+}
diff --git a/src/app/results/plottable-data.ts b/src/app/results/plottable-data.ts
index 35da1e4d9336e5fcac09c0586d39bef974a56b2e..a2bd574d285f9062b359deedd1f1010cd38994f9 100644
--- a/src/app/results/plottable-data.ts
+++ b/src/app/results/plottable-data.ts
@@ -1,11 +1,13 @@
 import { ChartType } from "./chart-type";
 
+import { ParamDefinition } from "jalhyd";
+
 /**
  * Une interface pour nourrir un ResultsChartComponent
  */
 export interface PlottableData {
 
-    graphType: ChartType;
+    chartType: ChartType;
     chartX: string;
     chartY: string;
 
@@ -20,7 +22,7 @@ export interface PlottableData {
      * Returns the translated name of the given symbol (usually a result or child result)
      * if available, with its unit, but without the symbol itself
      */
-    expandLabelFromSymbol(symbol: string): string;
+    expandLabelFromSymbol(p: ParamDefinition): string;
 
     /**
      * Returns a list of plottable parameters / result elements, that can be defined
@@ -45,4 +47,9 @@ export interface PlottableData {
      * (used by tooltip functions)
      */
     getVariatingParametersSymbols(): string[];
+
+    /**
+     * Returns true if results contain data
+     */
+    hasPlottableResults(): boolean;
 }
diff --git a/src/app/results/plottable-macrorugo-compound-results.ts b/src/app/results/plottable-macrorugo-compound-results.ts
deleted file mode 100644
index 82601908cde58547934846fce2c54862ff684b6b..0000000000000000000000000000000000000000
--- a/src/app/results/plottable-macrorugo-compound-results.ts
+++ /dev/null
@@ -1,118 +0,0 @@
-import { PlottableData } from "./plottable-data";
-import { ChartType } from "./chart-type";
-import { MacrorugoCompoundResults } from "./macrorugo-compound-results";
-
-export class PlottableMacrorugoCompoundResults implements PlottableData {
-
-    public graphType: ChartType = ChartType.Scatter;
-    public chartX: string;
-    public chartY: string;
-
-    protected mrcResults: MacrorugoCompoundResults;
-
-    public constructor(mrcResults?: MacrorugoCompoundResults) {
-        if (mrcResults) {
-            this.setMrcResults(mrcResults);
-        }
-        // axes par défaut
-        this.chartX = this.chartX || "xCenter";
-        this.chartY = this.chartY || "Q";
-    }
-
-    /** reaffect mrcResults, for ex. when objet was contructed with empty mrcResults */
-    public setMrcResults(mrcResults: MacrorugoCompoundResults) {
-        this.mrcResults = mrcResults;
-    }
-
-    /**
-     * Returns the label to display, for an element of getAvailableChartAxis()
-     * @param symbol parameter / result symbol (ex: "Q")
-     */
-    public getChartAxisLabel(symbol: string): string {
-        return this.mrcResults.headers[this.mrcResults.columns.indexOf(symbol)];
-    }
-
-    public expandLabelFromSymbol(symbol: string): string {
-        return symbol;
-    }
-
-    /**
-     * Returns a list of plottable parameters / result elements, that can be defined
-     * as X or Y chart axis
-     */
-    public getAvailableChartAxis(): string[] {
-        const axis = [];
-        for (const c of this.mrcResults.columns) {
-            if (c.indexOf("ENUM_") === -1) { // ENUM variables are not plottable
-                axis.push(c);
-            }
-        }
-        return axis;
-    }
-
-    public getAvailableXAxis(): string[] {
-        return this.getAvailableChartAxis();
-    }
-
-    public getAvailableYAxis(): string[] {
-        return this.getAvailableChartAxis();
-    }
-
-    // just to implement interface
-    public getVariatingParametersSymbols(): string[] {
-        return [];
-    }
-
-    /**
-     * Returns the series of values for the required symbol
-     * @param symbol parameter / result symbol (ex: "Q")
-     */
-    public getValuesSeries(symbol: string): number[] {
-        const data: number[] = [];
-        const l = this.mrcResults.childrenResults.length;
-        // when a parameter is variating, index of the variating parameter
-        // values to build the data from
-        const vi = this.mrcResults.variableIndex;
-
-        if (this.mrcResults.iterationHasError(vi)) {
-            return [];
-        }
-
-        for (let i = 0; i < l; i++) {
-            switch (symbol) {
-                case "RADIER_N":
-                    data.push(i + 1);
-                    break;
-
-                case "ZF1":
-                case "Y":
-                case "B":
-                    let v: number;
-                    const nub = this.mrcResults.childrenResults[i].sourceNub;
-                    const param = nub.getParameter(symbol);
-                    try {
-                        if (param.hasMultipleValues) {
-                            v = param.getInferredValuesList()[vi];
-                        } else {
-                            v = param.singleValue;
-                        }
-                    } catch (e) {
-                        // silent fail
-                    }
-                    data.push(v);
-                    break;
-
-                case "Q":
-                case "Vdeb":
-                case "Fr":
-                case "Vmax":
-                case "PV":
-                case "xCenter":
-                    data.push(this.mrcResults.childrenResults[i].resultElements[vi].getValue(symbol));
-                    break;
-            }
-        }
-
-        return data;
-    }
-}
diff --git a/src/app/results/plottable-pab-results.ts b/src/app/results/plottable-pab-results.ts
deleted file mode 100644
index 0d45afb05dfe1d4199858df4c878bdf60a3f2291..0000000000000000000000000000000000000000
--- a/src/app/results/plottable-pab-results.ts
+++ /dev/null
@@ -1,141 +0,0 @@
-import { PlottableData } from "./plottable-data";
-import { PabResults } from "./pab-results";
-import { ChartType } from "./chart-type";
-import { ServiceFactory } from "../services/service-factory";
-
-export class PlottablePabResults implements PlottableData {
-
-    public graphType: ChartType = ChartType.Scatter;
-    public chartX: string;
-    public chartY: string;
-
-    protected pabResults: PabResults;
-
-    public constructor(pabResults?: PabResults) {
-        if (pabResults) {
-            this.setPabResults(pabResults);
-        }
-        // axes par défaut
-        this.chartX = this.chartX || "CLOISON";
-        this.chartY = this.chartY || "YMOY";
-    }
-
-    /** reaffect pabResults, for ex. when objet was contructed with empty pabResults */
-    public setPabResults(pabResults: PabResults) {
-        this.pabResults = pabResults;
-    }
-
-    /**
-     * Returns the label to display, for an element of getAvailableChartAxis()
-     * @param symbol parameter / result symbol (ex: "Q")
-     */
-    public getChartAxisLabel(symbol: string): string {
-        if (symbol === "x") { // specific case for wall abscissa
-            return ServiceFactory.i18nService.localizeText("INFO_LIB_ABSCISSE_CLOISON");
-        } else {
-            return this.pabResults.headers[this.pabResults.columns.indexOf(symbol)];
-        }
-    }
-
-    public expandLabelFromSymbol(symbol: string): string {
-        return symbol;
-    }
-
-    /**
-     * Returns a list of plottable parameters / result elements, that can be defined
-     * as X or Y chart axis
-     */
-    public getAvailableChartAxis(): string[] {
-        const axis = [];
-        axis.push("x"); // wall abscissa
-        for (const c of this.pabResults.columns) {
-            if (c.indexOf("ENUM_") === -1) { // ENUM variables are not plottable
-                axis.push(c);
-            }
-        }
-        return axis;
-    }
-
-    public getAvailableXAxis(): string[] {
-        return this.getAvailableChartAxis();
-    }
-
-    public getAvailableYAxis(): string[] {
-        return this.getAvailableChartAxis();
-    }
-
-    // just to implement interface
-    public getVariatingParametersSymbols(): string[] {
-        return [];
-    }
-
-    /**
-     * Returns the series of values for the required symbol
-     * @param symbol parameter / result symbol (ex: "Q")
-     */
-    public getValuesSeries(symbol: string): number[] {
-        const data: number[] = [];
-        const pr = this.pabResults;
-        const l = this.pabResults.cloisonsResults.length;
-        // when a parameter is variating, index of the variating parameter
-        // values to build the data from
-        const vi = this.pabResults.variableIndex;
-
-        if (this.pabResults.iterationHasError(vi)) {
-            return [];
-        }
-
-        switch (symbol) {
-            case "CLOISON":
-                data.push(undefined);
-                for (let i = 0; i <= l; i++) { // <= for one extra step (downwall)
-                    data.push(i + 1);
-                }
-                break;
-
-            case "DH":
-            case "ZRAM":
-            case "Q":
-                data.push(undefined);
-                for (let i = 0; i < l; i++) {
-                    const er = pr.cloisonsResults[i].resultElements[vi].getValue(symbol);
-                    data.push(er);
-                }
-                const zrAval = pr.cloisonAvalResults.resultElements[vi].getValue(symbol);
-                data.push(zrAval);
-                break;
-
-            case "Z":
-                for (let i = 0; i < l; i++) {
-                    data.push(pr.cloisonsResults[i].resultElements[vi].vCalc);
-                }
-                data.push(pr.cloisonAvalResults.resultElements[vi].vCalc);
-                data.push(pr.Z2[vi]);
-                break;
-
-            case "PV":
-            case "YMOY":
-            case "ZRMB":
-            case "QA":
-                data.push(undefined);
-                for (let i = 0; i < l; i++) {
-                    const er = pr.cloisonsResults[i].resultElements[vi].getValue(symbol);
-                    data.push(er);
-                }
-                data.push(undefined);
-                break;
-
-            case "x": // wall abscissa
-                data.push(undefined);
-                for (let i = 0; i < l; i++) {
-                    const er = pr.cloisonsResults[i].resultElements[vi].getValue(symbol);
-                    data.push(er);
-                }
-                const erXdw = pr.cloisonAvalResults.resultElements[vi].getValue(symbol);
-                data.push(erXdw);
-                break;
-        }
-
-        return data;
-    }
-}
diff --git a/src/app/results/prebarrage-results.ts b/src/app/results/prebarrage-results.ts
new file mode 100644
index 0000000000000000000000000000000000000000..4fba21da8c30fd2a986df5baca2952f216567967
--- /dev/null
+++ b/src/app/results/prebarrage-results.ts
@@ -0,0 +1,143 @@
+import { Result } from "jalhyd";
+
+import { ServiceFactory } from "../services/service-factory";
+import { MultiDimensionResults } from "./multidimension-results";
+import { PbCloisonResults } from "./pb-cloison-results";
+
+export class PrebarrageResults extends MultiDimensionResults {
+
+    /** résultats des bassins, dans l'ordre */
+    public bassinsResults: Result[];
+
+    /** résultat de la cloison actuellement sélectionnée (nourrit le FixedResultsComponent) */
+    public cloisonResults: PbCloisonResults;
+
+    /** symboles des colonnes de résultat */
+    protected _columns: string[];
+
+    /** size of the longest variating parameter */
+    public size: number;
+
+    /** Stores appropriate number suffix for a given wall uid (copied from PbSchema) */
+    public wallsSuffixes: { [key: string]: number } = {};
+
+    public constructor() {
+        super();
+        this.reset();
+        this.size = 1; // boulette-proufe
+        // standard headers
+        this._columns = [
+            "BASSIN",
+            "S",
+            "ZF",
+            "Z",
+            "PV",
+            "YMOY",
+            "Q"
+        ];
+    }
+
+    /** headers symbols */
+    public get columns() {
+        return this._columns;
+    }
+
+    /** translated headers texts */
+    public get headers() {
+        return this._columns.map((h) => {
+            // calculator type for translation
+            const sn = this.result.sourceNub;
+            let ct = sn.calcType;
+            if (sn.parent) {
+                ct = sn.parent.calcType;
+            }
+            let label = ServiceFactory.formulaireService.expandVariableNameAndUnit(ct , h);
+            label += this.getHelpLink(h);
+            return label;
+        });
+    }
+
+    // redéfinir le set() implique de redéfinir le get(), sinon /i
+    public get variableIndex(): number {
+        return this._variableIndex;
+    }
+
+    public set variableIndex(v: number) {
+        this._variableIndex = v;
+        // set index in pseudo-fixed Cloison results too
+        this.cloisonResults.variableIndex = v;
+    }
+
+    public reset() {
+        super.reset();
+        this.bassinsResults = [];
+        this.cloisonResults = new PbCloisonResults();
+        this.cloisonResults.variableIndex = this._variableIndex;
+        this.cloisonResults.size = this.size;
+        this.result = undefined;
+    }
+
+    /**
+     * Returns true if at least one log message is present in the PAB result or any
+     * of the children results
+     */
+    public get hasLog(): boolean {
+        if (this.bassinsResults) {
+            for (const cr of this.bassinsResults) {
+                if (cr && cr.hasLog()) {
+                    return true;
+                }
+            }
+        }
+        return (this.cloisonResults && this.cloisonResults.result && this.cloisonResults.result.hasLog());
+    }
+
+    public get hasResults(): boolean {
+        return this.hasBasinResults || this.hasWallResults;
+    }
+
+    public get hasBasinResults(): boolean {
+        return this.bassinsResults.length > 0 && this.bassinsResults[0] && ! this.bassinsResults[0].hasOnlyErrors;
+    }
+
+    public get hasWallResults(): boolean {
+        return this.cloisonResults  && this.cloisonResults.result && ! this.cloisonResults.result.hasOnlyErrors;
+    }
+
+    /** retourne true si au moins un calcul a échoué (le log a un code négatif) */
+    public hasError(): boolean {
+        let err = false;
+        // log principal
+        err = (err || (this.cloisonResults && this.cloisonResults && this.cloisonResults.result.hasErrorMessages()));
+        // logs des bassins
+        for (const c of this.bassinsResults) {
+            err = (err || c.hasErrorMessages());
+        }
+
+        return err;
+    }
+
+    /** retourne true si le calcul à l'itération i a échoué */
+    public iterationHasError(i: number): boolean {
+        let err = this.cloisonResults && this.cloisonResults.result && this.cloisonResults.result.resultElements[i].hasErrorMessages();
+        // logs des bassins
+        for (const c of this.bassinsResults) {
+            err = (err || c.resultElements[i].hasErrorMessages());
+        }
+
+        return err;
+    }
+
+    /** retourne true si tous les calculs ont échoué */
+    public hasOnlyErrors(): boolean {
+        let err = true;
+        // log principal
+        err = (err && this.cloisonResults && this.cloisonResults.result && this.cloisonResults.result.hasOnlyErrors);
+        // logs des bassins
+        for (const c of this.bassinsResults) {
+            err = (err && c.hasOnlyErrors);
+        }
+
+        return err;
+    }
+}
diff --git a/src/app/results/remous-results.ts b/src/app/results/remous-results.ts
index c6c9e3b8a1daf1f075d182963a5b83c58806ae38..dedfd9a6f78aabbd22f97f66bb02d748d5d4c9de 100644
--- a/src/app/results/remous-results.ts
+++ b/src/app/results/remous-results.ts
@@ -2,8 +2,8 @@ import { cLog, CourbeRemousParams, Result, ResultElement, ParamDefinition, Param
 
 import { CalculatorResults } from "./calculator-results";
 import { VarResults } from "./var-results";
-import { NgParameter } from "../formulaire/elements/ngparam";
 import { ServiceFactory } from "../services/service-factory";
+import { FormulaireDefinition } from "../formulaire/definition/form-definition";
 
 export class RemousResults extends CalculatorResults {
 
@@ -51,8 +51,12 @@ export class RemousResults extends CalculatorResults {
     /** journal de calcul */
     private _log: cLog;
 
-    constructor() {
+    /** pointer to form that instantiated this object */
+    protected _form: FormulaireDefinition;
+
+    constructor(form?: FormulaireDefinition) {
         super();
+        this._form = form;
         this.reset();
     }
 
@@ -132,8 +136,8 @@ export class RemousResults extends CalculatorResults {
         this._log.clear();
         this._log.addLog(this._result.globalLog);
 
-        this._varResults = new VarResults();
-        this._varResults.variatedParameters = [ new NgParameter(this._xValues, undefined) ];
+        this._varResults = new VarResults(this._form);
+        this._varResults.variatedParameters = [ { param: this._xValues, values: this._xValues.paramValues } ];
         this._varResults.result = this._result;
         const keys = [];
         keys.push("Y"); // ligne d'eau
diff --git a/src/app/results/var-results.ts b/src/app/results/var-results.ts
index 6e73b5d03c0a8649f6b8c173e58bc6e364614e32..7b85bfb0dc7efa90f0444dbb42c8d7c460682b25 100644
--- a/src/app/results/var-results.ts
+++ b/src/app/results/var-results.ts
@@ -1,20 +1,19 @@
-import { CalculatorResults } from "./calculator-results";
 import { CalculatedParamResults } from "./param-calc-results";
-import { NgParameter } from "../formulaire/elements/ngparam";
-import { ResultElement, ParamFamily, capitalize, Nub } from "jalhyd";
 import { ServiceFactory } from "../services/service-factory";
 import { PlottableData } from "./plottable-data";
 import { ChartType } from "./chart-type";
+import { longestVarParam } from "../util";
+import { FormulaireDefinition } from "../formulaire/definition/form-definition";
 
 import { sprintf } from "sprintf-js";
 
-import { longestVarNgParam } from "../util";
+import { ResultElement, ParamFamily, capitalize, Nub, VariatedDetails, ParamDefinition, ParamDomain, ParamDomainValue } from "jalhyd";
 
 export class VarResults extends CalculatedParamResults implements PlottableData {
     /**
      * paramètres variés
      */
-    private _variatedParams: NgParameter[];
+    private _variatedParams: VariatedDetails[] = [];
 
     /**
      * titre des colonnes des résultats variés
@@ -36,6 +35,9 @@ export class VarResults extends CalculatedParamResults implements PlottableData
      */
     protected _graphType: ChartType = ChartType.Scatter;
 
+    /** pointer to form that instantiated this object */
+    protected _form: FormulaireDefinition;
+
     /**
      * variated parameter or result displayed as chart's X-axis
      */
@@ -56,8 +58,9 @@ export class VarResults extends CalculatedParamResults implements PlottableData
      */
     private _yValues: number[] = [];
 
-    constructor() {
+    constructor(form?: FormulaireDefinition) {
         super();
+        this._form = form;
         this.reset();
     }
 
@@ -70,11 +73,11 @@ export class VarResults extends CalculatedParamResults implements PlottableData
         this.longest = 0;
     }
 
-    public get variatedParameters(): NgParameter[] {
+    public get variatedParameters(): VariatedDetails[] {
         return this._variatedParams;
     }
 
-    public set variatedParameters(p: NgParameter[]) {
+    public set variatedParameters(p: VariatedDetails[]) {
         this._variatedParams = p;
     }
 
@@ -94,35 +97,44 @@ export class VarResults extends CalculatedParamResults implements PlottableData
         return this._resultHeaders;
     }
 
-    public get graphType(): ChartType {
+    public get chartType(): ChartType {
         return this._graphType;
     }
 
-    public set graphType(gt: ChartType) {
+    public set chartType(gt: ChartType) {
         this._graphType = gt;
         this.resetDefaultAxisIfNeeded();
     }
 
-    public getChartAxisLabel(symbol: string): string {
-        // 1. calculated param ?
-        if (this.calculatedParameter && this.calculatedParameter.symbol === symbol) {
-            return this.calculatedParameterHeader;
+    public hasPlottableResults(): boolean {
+        if (this.result === undefined) {
+            return false;
         }
-        // 2. variated param ?
-        for (let i = 0; i < this.variatedParameters.length; i++) {
-            if (this._variatedParams[i].symbol === symbol) {
-                return this.variableParamHeaders[i];
+        return ! this.result.hasOnlyErrors;
+    }
+
+    public getChartAxisLabel(symbol: string): string {
+        if (this.result) {
+            // 1. calculated param ?
+            if (this.calculatedParameter && this.calculatedParameter.symbol === symbol) {
+                return this.calculatedParameterHeader;
+            }
+            // 2. variated param ?
+            for (let i = 0; i < this.variatedParameters.length; i++) {
+                if (this._variatedParams[i].param.symbol === symbol) {
+                    return this.variableParamHeaders[i];
+                }
             }
+            // 3. Result element / child result
+            return this.expandLabelFromSymbol(new ParamDefinition(undefined, symbol, ParamDomainValue.ANY));
         }
-        // 3. Result element / child result
-        return this.expandLabelFromSymbol(symbol);
     }
 
     /**
      * Returns the translated name of the given symbol (usually a result or child result) with
      * its unit, but without the symbol itself
      */
-    public expandLabelFromSymbol(symbol: string): string {
+    public expandLabelFromSymbol(p: ParamDefinition): string {
         let ret = "";
         // calculator type for translation
         const sn = this.result.sourceNub;
@@ -131,7 +143,8 @@ export class VarResults extends CalculatedParamResults implements PlottableData
             ct = sn.parent.calcType;
         }
         // detect children results
-        const match = /^([0-9]+)_(.+)$/.exec(symbol);
+        const match = /^([0-9]+)_(.+)$/.exec(p.symbol);
+        let symbol = p.symbol;
         if (match !== null) {
             const pos = +match[1];
             // only parent translation file is loaded; look for children translations in it // ct = sn.getChildren()[pos].calcType;
@@ -160,16 +173,16 @@ export class VarResults extends CalculatedParamResults implements PlottableData
             // are we looking for a child variated param ?
             if (isChildResult !== null) {
                 const children = this.result.sourceNub.getChildren();
-                const parameterNub = vp.paramDefinition.parentNub;
+                const parameterNub = vp.param.parentNub;
                 if (children.includes(parameterNub)) { // current var param is a child param !
                     const pos = parameterNub.findPositionInParent();
-                    isTheGoodChild = (pos === +isChildResult[1] && vp.symbol === isChildResult[2]);
+                    isTheGoodChild = (pos === +isChildResult[1] && vp.param.symbol === isChildResult[2]);
                 }
             }
             // in any case
-            if (isTheGoodChild || vp.symbol === symbol) {
+            if (isTheGoodChild || vp.param.symbol === symbol) {
                 found = true;
-                const iter = vp.getExtendedValuesIterator(this.size);
+                const iter = vp.param.getExtendedValuesIterator(this.size);
                 for (const v of iter) {
                     series.push(v);
                 }
@@ -259,13 +272,13 @@ export class VarResults extends CalculatedParamResults implements PlottableData
         // variating parameters
         for (const v of this._variatedParams) {
             // exclude pseudo-family "ANY"
-            const fam = v.paramDefinition.family;
+            const fam = v.param.family;
             if (fam !== undefined && fam !== ParamFamily.ANY) {
                 const f = ParamFamily[fam];
                 if (! (f in families)) {
                     families[f] = [];
                 }
-                families[f].push(v.symbol);
+                families[f].push(v.param.symbol);
             }
         }
         // results
@@ -309,15 +322,15 @@ export class VarResults extends CalculatedParamResults implements PlottableData
      */
     public getVariatingParametersSymbols(): string[] {
         if (this.result && this.result.sourceNub) {
-            return this._variatedParams.map(vp => this.getVariatingParameterSymbol(vp, this.result.sourceNub));
+            return this._variatedParams.map(vp => this.getVariatingParameterSymbol(vp.param, this.result.sourceNub));
         } else {
             return [];
         }
     }
 
-    public getVariatingParameterSymbol(vp: NgParameter, sourceNub: Nub): string {
+    public getVariatingParameterSymbol(vp: ParamDefinition, sourceNub: Nub): string {
         // detect if variated param is a children param
-        const parameterNub = vp.paramDefinition.parentNub;
+        const parameterNub = vp.parentNub;
         const children = sourceNub.getChildren();
         let symb = vp.symbol;
         if (children.includes(parameterNub)) {
@@ -329,13 +342,13 @@ export class VarResults extends CalculatedParamResults implements PlottableData
     public update() {
         // refresh param headers
         this._variableParamHeaders = this._variatedParams.map((v) => {
-            let h = CalculatorResults.paramLabel(v, true, this.result.sourceNub);
-            h += this.getHelpLink(v.symbol);
+            let h = this.expandLabelFromSymbol(v.param);
+            h += this.getHelpLink(v.param.symbol);
             return h;
         });
 
         // liste la plus longue
-        const lvp = longestVarNgParam(this._variatedParams);
+        const lvp = longestVarParam(this._variatedParams);
         this.size = lvp.size;
         this.longest = lvp.index;
 
@@ -358,7 +371,7 @@ export class VarResults extends CalculatedParamResults implements PlottableData
         }
         this.chartY = defaultY;
         if (this.chartX === undefined || ! this.getAvailableXAxis().includes(this.chartX)) {
-            this.chartX = this.getVariatingParameterSymbol(this.variatedParameters[this.longest], this.result.sourceNub);
+            this.chartX = this.getVariatingParameterSymbol(this.variatedParameters[this.longest].param, this.result.sourceNub);
         }
 
         // calculator type for translation
@@ -404,11 +417,11 @@ export class VarResults extends CalculatedParamResults implements PlottableData
      * When variable parameter or chart type changes, ensure the X / Y current values are still available
      */
     public resetDefaultAxisIfNeeded() {
-        if (! this.getAvailableXAxis().includes(this.chartX)) {
-            this.chartX = this.variatedParameters[0].symbol;
+        if (this.variatedParameters.length > 0 && ! this.getAvailableXAxis().includes(this.chartX)) {
+            this.chartX = this.variatedParameters[0].param.symbol;
         }
-        if (! this.getAvailableYAxis().includes(this.chartY)) {
-            this.chartY = this.variatedParameters[0].symbol;
+        if (this.variatedParameters.length > 0 && ! this.getAvailableYAxis().includes(this.chartY)) {
+            this.chartY = this.variatedParameters[0].param.symbol;
         }
     }
 }
diff --git a/src/app/services/app-setup.service.ts b/src/app/services/app-setup.service.ts
index 22db10b3c856b50d69b21d3cc3fc069a2672af8c..d1f01b2af7fbc411487f2e8045bd337299b842b6 100644
--- a/src/app/services/app-setup.service.ts
+++ b/src/app/services/app-setup.service.ts
@@ -115,13 +115,12 @@ export class ApplicationSetupService extends Observable {
     /**
      * Restore configuration values
      */
-    public restoreDefaultValues(): Promise<any> {
-        return this.readValuesFromConfig().then(() => {
-            // notify I18nService
-            this.notifyObservers({
-                action: "languagePreferenceChanged",
-                languages: [ this.language ]
-            });
+    public async restoreDefaultValues(): Promise<any> {
+        await this.readValuesFromConfig();
+        // notify I18nService
+        this.notifyObservers({
+            action: "languagePreferenceChanged",
+            languages: [ this.language ]
         });
     }
 
@@ -172,18 +171,17 @@ export class ApplicationSetupService extends Observable {
     /**
      * Read configuration values from config (async)
      */
-    private readValuesFromConfig(): Promise<any> {
-        return this.httpService.httpGetRequestPromise(this.CONFIG_FILE_PATH).then((data: any) => {
-            // get all config values (volontarily non-generic to prevent side-effects)
-            this.displayPrecision = data.params.displayPrecision;
-            this.computePrecision = data.params.computePrecision;
-            this.maxIterations = data.params.maxIterations;
-            this.enableNotifications = data.params.enableNotifications;
-            this.enableHotkeys = data.params.enableHotkeys;
-            this.enableEmptyFieldsOnFormInit = data.params.enableEmptyFieldsOnFormInit;
-            this.language = data.params.language;
-            // load themes for calculators list page
-            this.themes = data.themes;
-        });
+    private async readValuesFromConfig(): Promise<any> {
+        const data: any = await this.httpService.httpGetRequestPromise(this.CONFIG_FILE_PATH);
+        // get all config values (volontarily non-generic to prevent side-effects)
+        this.displayPrecision = data.params.displayPrecision;
+        this.computePrecision = data.params.computePrecision;
+        this.maxIterations = data.params.maxIterations;
+        this.enableNotifications = data.params.enableNotifications;
+        this.enableHotkeys = data.params.enableHotkeys;
+        this.enableEmptyFieldsOnFormInit = data.params.enableEmptyFieldsOnFormInit;
+        this.language = data.params.language;
+        // load themes for calculators list page
+        this.themes = data.themes;
     }
 }
diff --git a/src/app/services/formulaire.service.ts b/src/app/services/formulaire.service.ts
index a9a6a716006c62da7d8fcc34ab5d9202c713408f..7b494b9dda2f53cdbd2bb1cfe5aa592d7fff3156 100644
--- a/src/app/services/formulaire.service.ts
+++ b/src/app/services/formulaire.service.ts
@@ -14,7 +14,14 @@ import {
     Props,
     Cloisons,
     CloisonAval,
-    SPP
+    SPP,
+    PreBarrage,
+    PbBassin,
+    PbBassinParams,
+    LoiDebit,
+    PbCloison,
+    CreateStructure,
+    Structure
 } from "jalhyd";
 
 import { ApplicationSetupService } from "./app-setup.service";
@@ -42,6 +49,7 @@ import { FormulaireSection } from "../formulaire/definition/form-section";
 import { FormulairePAR } from "../formulaire/definition/form-par";
 import { FormulaireVerificateur } from "../formulaire/definition/form-verificateur";
 import { FormulaireEspece } from "../formulaire/definition/form-espece";
+import { FormulairePrebarrage } from "../formulaire/definition/form-prebarrage";
 
 @Injectable()
 export class FormulaireService extends Observable {
@@ -195,7 +203,9 @@ export class FormulaireService extends Observable {
         if (idx !== -1) {
             symbolBase = symbolBase.substring(idx + 2);
         }
-        let unit;
+        let unit: string;
+        // unit of a parameter is supposed to be read from JaLHyd ParadDefinition and passed
+        // through "forceUnit"; keys like "UNIT_*" in the config file are for extra results
         if (forceUnit) {
             unit = forceUnit;
         } else {
@@ -317,6 +327,10 @@ export class FormulaireService extends Observable {
                 f = new FormulaireEspece();
                 break;
 
+            case CalculatorType.PreBarrage:
+                f = new FormulairePrebarrage();
+                break;
+
             default:
                 f = new FormulaireFixedVar();
         }
@@ -332,106 +346,127 @@ export class FormulaireService extends Observable {
      * @param nub nub existant à associer au formulaire (chargement de session / duplication de module)
      * @param calculatorName nom du module, à afficher dans l'interface
      */
-    public createFormulaire(ct: CalculatorType, nub?: Nub, calculatorName?: string): Promise<FormulaireDefinition> {
+    public async createFormulaire(ct: CalculatorType, nub?: Nub, calculatorName?: string): Promise<FormulaireDefinition> {
         // Crée un formulaire du bon type
         const f: FormulaireDefinition = this.newFormulaire(ct);
         this._formulaires.push(f);
         // Charge la configuration dépendamment du type
-        return this.loadConfig(ct).then(s => {
-            f.preparseConfig(s);
+        const s: any = await this.loadConfig(ct);
+        f.preparseConfig(s);
 
-            // Associe le Nub fourni (chargement de session / duplication de module), sinon en crée un nouveau
-            if (nub) {
-                f.currentNub = nub;
-            } else {
-                f.initNub();
-            }
+        // Associe le Nub fourni (chargement de session / duplication de module), sinon en crée un nouveau
+        if (nub) {
+            f.currentNub = nub;
+        } else {
+            f.initNub();
+        }
 
-            // Restaure le nom du module, sinon affecte le nom par défaut
-            let tempName: string;
-            if (calculatorName) {
-                tempName = calculatorName;
-            } else {
-                tempName = decode(this.getLocalisedShortTitleFromCalculatorType(ct));
-            }
-            // Suffixe le nom du module si nécessaire
-            f.calculatorName = this.suffixNameIfNeeded(tempName);
-
-            f.parseConfig();
-
-            // add fieldsets for existing Structures if needed
-            // (when loading session only)
-            if (f.currentNub instanceof ParallelStructure) {
-                for (const struct of f.currentNub.structures) {
-                    for (const e of f.allFormElements) {
-                        if (e instanceof FieldsetContainer) { // @TODO manage many containers one day ?
-                            e.addFromTemplate(0, undefined, struct);
-                        }
+        // Restaure le nom du module, sinon affecte le nom par défaut
+        let tempName: string;
+        if (calculatorName) {
+            tempName = calculatorName;
+        } else {
+            tempName = decode(this.getLocalisedShortTitleFromCalculatorType(ct));
+        }
+        // Suffixe le nom du module si nécessaire
+        f.calculatorName = this.suffixNameIfNeeded(tempName);
+
+        f.parseConfig();
+
+        // add fieldsets for existing Structures if needed
+        // (when loading session only)
+        if (f.currentNub instanceof ParallelStructure) {
+            for (const struct of f.currentNub.structures) {
+                for (const e of f.allFormElements) {
+                    if (e instanceof FieldsetContainer) { // @TODO manage many containers one day ?
+                        e.addFromTemplate(0, undefined, struct);
                     }
                 }
             }
+        }
 
-            // add fieldsets for existing YAXN if needed
-            // (when loading session only)
-            if (f.currentNub instanceof SPP) {
-                for (const c of f.currentNub.getChildren()) {
-                    for (const e of f.allFormElements) {
-                        if (e instanceof FieldsetContainer) { // @TODO manage many containers one day ?
-                            e.addFromTemplate(0, undefined, c);
-                        }
+        // add fieldsets for existing YAXN if needed
+        // (when loading session only)
+        if (f.currentNub instanceof SPP) {
+            for (const c of f.currentNub.getChildren()) {
+                for (const e of f.allFormElements) {
+                    if (e instanceof FieldsetContainer) { // @TODO manage many containers one day ?
+                        e.addFromTemplate(0, undefined, c);
                     }
                 }
             }
+        }
 
-            // when creating a new Pab, add one wall with one device, plus the downwall
-            // (when loading session, those items are already present)
-            if (
-                f instanceof FormulairePab
-                && f.currentNub instanceof Pab
-                && f.currentNub.children.length === 0
-                && f.currentNub.downWall === undefined
-            ) {
-                // 1. one wall
-                const newWall = Session.getInstance().createNub(
-                    new Props({
-                        calcType: CalculatorType.Cloisons
-                    })
-                ) as Cloisons;
-                // add new default device for new wall
-                const newDevice = Session.getInstance().createNub(
-                    new Props({
-                        calcType: CalculatorType.Structure,
-                        loiDebit: newWall.getDefaultLoiDebit()
-                    })
-                );
-                newWall.addChild(newDevice);
-                f.pabNub.addChild(newWall);
-                // 2. downwall
-                const newDownWall = Session.getInstance().createNub(
-                    new Props({
-                        calcType: CalculatorType.CloisonAval
-                    })
-                ) as CloisonAval;
-                // add new default device for new downwall
-                const newDownwallDevice = Session.getInstance().createNub(
-                    new Props({
-                        calcType: CalculatorType.Structure,
-                        loiDebit: newDownWall.getDefaultLoiDebit()
-                    })
-                );
-                newDownWall.addChild(newDownwallDevice);
-                f.pabNub.downWall = newDownWall;
-            }
+        // when creating a new Pab, add one wall with one device, plus the downwall
+        // (when loading session, those items are already present)
+        if (
+            f instanceof FormulairePab
+            && f.currentNub instanceof Pab
+            && f.currentNub.children.length === 0
+            && f.currentNub.downWall === undefined
+        ) {
+            // 1. one wall
+            const newWall = Session.getInstance().createNub(
+                new Props({
+                    calcType: CalculatorType.Cloisons
+                })
+            ) as Cloisons;
+            // add new default device for new wall
+            const newDevice = Session.getInstance().createNub(
+                new Props({
+                    calcType: CalculatorType.Structure,
+                    loiDebit: newWall.getDefaultLoiDebit()
+                })
+            );
+            newWall.addChild(newDevice);
+            f.pabNub.addChild(newWall);
+            // 2. downwall
+            const newDownWall = Session.getInstance().createNub(
+                new Props({
+                    calcType: CalculatorType.CloisonAval
+                })
+            ) as CloisonAval;
+            // add new default device for new downwall
+            const newDownwallDevice = Session.getInstance().createNub(
+                new Props({
+                    calcType: CalculatorType.Structure,
+                    loiDebit: newDownWall.getDefaultLoiDebit()
+                })
+            );
+            newDownWall.addChild(newDownwallDevice);
+            f.pabNub.downWall = newDownWall;
+        }
 
-            return f;
+        // when creating a new PreBarrage, add one basin and two walls with one
+        // device each (when loading session, those items are already present)
+        if (
+            f instanceof FormulairePrebarrage
+            && f.currentNub instanceof PreBarrage
+            && f.currentNub.children.length === 0
+        ) {
+            // 1 basin
+            f.currentNub.addChild(new PbBassin(new PbBassinParams(13.80, 95)));
+            // 1st wall
+            f.currentNub.addChild(new PbCloison(undefined, f.currentNub.children[0] as PbBassin));
+            const s1: Structure = CreateStructure(LoiDebit.WeirCunge80);
+            s1.prms.ZDV.singleValue = 95.30;
+            s1.getParameter("L").singleValue = 0.4;
+            s1.getParameter("CdGR").singleValue = 1.04;
+            f.currentNub.children[1].addChild(s1);
+            // 2nd wall
+            f.currentNub.addChild(new PbCloison(f.currentNub.children[0] as PbBassin, undefined));
+            const s2: Structure = CreateStructure(LoiDebit.WeirCunge80);
+            s2.prms.ZDV.singleValue = 95.30;
+            s2.getParameter("L").singleValue = 0.4;
+            s2.getParameter("CdGR").singleValue = 1.04;
+            f.currentNub.children[2].addChild(s2);
+        }
 
-        }).then(fi => {
-            this.notifyObservers({
-                "action": "createForm",
-                "form": fi
-            });
-            return fi;
+        this.notifyObservers({
+            "action": "createForm",
+            "form": f
         });
+        return f;
     }
 
     /**
@@ -642,47 +677,49 @@ export class FormulaireService extends Observable {
      * obtient des infos (nom, uid des modules de calcul, dépendances) d'un fichier session
      * @param f fichier session
      */
-    public calculatorInfosFromSessionFile(f: File): Promise<{ nubs: any[], formatVersion: string }> {
-        return this.readSingleFile(f).then(s => {
-            // return value
-            const res: { nubs: any[], formatVersion: string } = {
-                nubs: [],
-                formatVersion: ""
-            };
-            const data = JSON.parse(s);
-            // liste des noms de modules de calcul
-            if (data.session && Array.isArray(data.session)) {
-                data.session.forEach((e: any) => {
-                    const nubInfo = {
-                        uid: e.uid,
-                        title: e.meta && e.meta.title ? e.meta.title : undefined,
-                        requires: [],
-                        children: [],
-                        type: e.props.calcType
-                    };
-                    // list linked params dependencies for each Nub
-                    if (e.parameters) {
-                        e.parameters.forEach((p) => {
-                            if (p.targetNub && ! nubInfo.requires.includes(p.targetNub)) {
-                                nubInfo.requires.push(p.targetNub);
-                            }
-                        });
-                    }
-                    // list children nubs for each Nub
-                    if (e.children) {
-                        e.children.forEach((p) => {
-                            nubInfo.children.push(p.uid);
-                        });
-                    }
-                    res.nubs.push(nubInfo);
-                });
-            }
-            // version du format de fichier
-            if (data.header && data.header.format_version) {
-                res.formatVersion = data.header.format_version;
-            }
-            return res;
-        });
+    public async calculatorInfosFromSessionFile(f: File): Promise<{ nubs: any[], formatVersion: string }> {
+        const s = await this.readSingleFile(f);
+        // return value
+        const res: {
+            nubs: any[];
+            formatVersion: string;
+        } = {
+            nubs: [],
+            formatVersion: ""
+        };
+        const data = JSON.parse(s);
+        // liste des noms de modules de calcul
+        if (data.session && Array.isArray(data.session)) {
+            data.session.forEach((e: any) => {
+                const nubInfo = {
+                    uid: e.uid,
+                    title: e.meta && e.meta.title ? e.meta.title : undefined,
+                    requires: [],
+                    children: [],
+                    type: e.props.calcType
+                };
+                // list linked params dependencies for each Nub
+                if (e.parameters) {
+                    e.parameters.forEach((p) => {
+                        if (p.targetNub && !nubInfo.requires.includes(p.targetNub)) {
+                            nubInfo.requires.push(p.targetNub);
+                        }
+                    });
+                }
+                // list children nubs for each Nub
+                if (e.children) {
+                    e.children.forEach((p) => {
+                        nubInfo.children.push(p.uid);
+                    });
+                }
+                res.nubs.push(nubInfo);
+            });
+        }
+        // version du format de fichier
+        if (data.header && data.header.format_version) {
+            res.formatVersion = data.header.format_version;
+        }
+        return res;
     }
 
     public saveForm(f: FormulaireDefinition) {
diff --git a/src/app/services/internationalisation.service.ts b/src/app/services/internationalisation.service.ts
index 451931f1b508a6d8104470a5b855a174053676ae..05af49767aea932e60f77c7e730f6ab180fa7926 100644
--- a/src/app/services/internationalisation.service.ts
+++ b/src/app/services/internationalisation.service.ts
@@ -59,7 +59,7 @@ export class I18nService extends Observable implements Observer {
      *
      * @param code ISO 639-1 language code
      */
-    public setLanguage(code: string) {
+    public async setLanguage(code: string) {
         // ensure 2-letter language code
         code = code.substring(0, 2);
         // is language supported ?
@@ -79,44 +79,43 @@ export class I18nService extends Observable implements Observer {
                     promisesList.push(this.loadLocalisation(calcType).catch((err) => { /* silent fail */ }));
                 }
             }
-            Promise.all(promisesList).then(() => {
-                this.httpGetMessages(code).then((res: any) => {
-                    that._Messages = res;
-                    // propagate language change to all application
-                    that.notifyObservers(undefined);
-                });
-            });
+            await Promise.all(promisesList);
+            const res = await this.httpGetMessages(code);
+            that._Messages = res;
+            // propagate language change to all application
+            that.notifyObservers(undefined);
         }
     }
 
     /**
      * Loads the localisation file dedicated to calculator type ct; uses cache if available
      */
-    public loadLocalisation(calc: CalculatorType): Promise<any> {
+    public async loadLocalisation(calc: CalculatorType): Promise<any> {
         const lang = this.currentLanguage;
-        return this.loadLocalisationForLang(calc, lang).then((localisation) => {
-            return localisation as StringMap;
-        }).catch((e) => {
+        try {
+            return await this.loadLocalisationForLang(calc, lang) as StringMap;
+        } catch (e) {
             return "";
-        });
+        };
     }
 
     /**
      * Loads the localisation file dedicated to calculator type ct for language lang;
      * keeps it in cache for subsequent calls ()
      */
-    private loadLocalisationForLang(calc: CalculatorType, lang: string): Promise<any> {
+    private async loadLocalisationForLang(calc: CalculatorType, lang: string): Promise<any> {
         const ct = String(calc);
         // if not already in cache
         if (! Object.keys(this._languageCache).includes(ct) || ! Object.keys(this._languageCache[calc]).includes(lang)) {
             const f: string = FormulaireService.getConfigPathPrefix(calc) + lang + ".json";
-            return this.httpService.httpGetRequestPromise(f).then((localisation) => {
+            try {
+                const localisation = await this.httpService.httpGetRequestPromise(f);
                 this._languageCache[ct] = this._languageCache[ct] || {};
                 this._languageCache[ct][lang] = localisation;
                 return localisation as StringMap;
-            }).catch((e) => {
+            } catch (e) {
                 throw new Error(`LOCALISATION_FILE_NOT_FOUND "${f}"`);
-            });
+            }
         } else {
             return new Promise((resolve, reject) => {
                 resolve(); // does nothing but complies with Promise expectation
@@ -128,12 +127,10 @@ export class I18nService extends Observable implements Observer {
      * Loads localized messages from JSON files for the given language
      * (general messages files, not calculator-specific ones)
      */
-    private httpGetMessages(lang: string): Promise<void> {
+    private async httpGetMessages(lang: string): Promise<any> {
         const fileName = "messages." + lang + ".json";
         const filePath = "locale/" + fileName;
-        return this.httpService.httpGetRequestPromise(filePath).then((res: any) => {
-            return res;
-        });
+        return await this.httpService.httpGetRequestPromise(filePath);
     }
 
     private getMessageFromCode(c: MessageCode): string {
@@ -242,7 +239,7 @@ export class I18nService extends Observable implements Observer {
 
         // replace MSG_* with the translation of * ; allows
         // to inject any text translation in a message
-        m = m.replace(/MSG_([^ ,;\.]+)/g, (match, p1) => {
+        m = m.replace(/MSG_([^ ,;\.-]+)/g, (match, p1) => {
             return this.localizeText(p1);
         });
 
@@ -307,13 +304,17 @@ export class I18nService extends Observable implements Observer {
     }
 
     /**
-     * Returns the localized name for the children type of the current Nub
+     * Returns the localized name for the children type of the current Nub; "short" and "plural"
+     * options are mutually exclusive
      * @param plural if true, will return plural name
+     * @param short if true, will return short name
      */
-    public childName(nub: Nub, plural: boolean = false) {
+    public childName(nub: Nub, plural: boolean = false, short: boolean = false) {
         const type: string = nub.childrenType;
         let k = "INFO_CHILD_TYPE_" + type.toUpperCase();
-        if (plural) {
+        if (short) {
+            k += "_SHORT";
+        } else if (plural) {
             k += "_PLUR";
         }
         return this.localizeText(k);
diff --git a/src/app/util.ts b/src/app/util.ts
index 48b0981cc44d23bee009dbcb77cd517a1f13b798..74d0f3329b70a894dd8c5064622651f989b3b150 100644
--- a/src/app/util.ts
+++ b/src/app/util.ts
@@ -1,7 +1,7 @@
 import { NgParameter } from "./formulaire/elements/ngparam";
 import { ServiceFactory } from "./services/service-factory";
 
-import { formattedValue, Nub, VariatedDetails, ParamDefinition } from "jalhyd";
+import { formattedValue, Nub, VariatedDetails, ParamDefinition, ParamValueMode } from "jalhyd";
 
 export function logObject(obj: {}, m?: string) {
     // évite le message "Value below was evaluated just now" dans le debugger de Chrome
@@ -31,6 +31,26 @@ export function fv(p: NgParameter | number): string {
     return formattedValue(value, nDigits);
 }
 
+/**
+ * Returns value at index i for parameter p, whether it is variating
+ * or not, calculated or not
+ * @param p parameter
+ * @param i index
+ */
+export function getIthValue(p: ParamDefinition, i: number, extendTo: number): string {
+    let value: number;
+    if (p.hasMultipleValues) {
+        if (p.valueMode === ParamValueMode.CALCUL) {
+            value = p.parentNub.result.resultElements[i].vCalc;
+        } else {
+            value = p.getInferredValuesList(extendTo)[i];
+        }
+    } else {
+        value = p.V;
+    }
+    return fv(value);
+}
+
 /**
  * Trick to decode HTML entities in a string
  * https://stackoverflow.com/a/7394787/5986614
@@ -42,27 +62,6 @@ export function decodeHtml(html: string): string {
     return txt.value;
 }
 
-/**
- * Given a list of variated NgParameter, returns the parameter having the most
- * values, its index in the list, and the number of values it contains
- * @param varParams
- */
-export function longestVarNgParam(varParams: NgParameter[]): { param: NgParameter, index: number, size: number } {
-    const variated: VariatedDetails[] = [];
-    for (const vp of varParams) {
-        variated.push({
-            param: vp.paramDefinition,
-            values: vp.paramDefinition.paramValues
-        });
-    }
-    const { param, index, size } = longestVarParam(variated);
-    return {
-        param: varParams[index],
-        index,
-        size
-    };
-}
-
 /**
  * Given a list of variated ParamDefinition, returns the parameter having the most
  * values, its index in the list, and the number of values it contains
diff --git a/src/locale/messages.en.json b/src/locale/messages.en.json
index 8f48e654cd1f0835c9eea076b83006dc174d4745..f3b269f33d44926d41b42f87790cc5a097cd3e01 100644
--- a/src/locale/messages.en.json
+++ b/src/locale/messages.en.json
@@ -52,8 +52,12 @@
     "ERROR_PARAMDEF_VALUE_UNDEFINED": "value of '%symbol%' parameter is undefined",
     "ERROR_PARAMDOMAIN_INTERVAL_BOUNDS": "invalid %minValue%/%maxValue% min/max boundaries for 'interval' parameter definition domain",
     "ERROR_PARAMDOMAIN_INVALID": "parameter '%symbol%: non supported '%domain%' definition domain",
+    "ERROR_PREBARRAGE_NON_CONVERGENCE": "Pre-dam: non-convergence of the calculation",
+    "ERROR_PREBARRAGE_STRUCTURE_ZDV_INF_ZF": "Apron elevation of device #%ns% is lower than bottom elevation of upstream basin of wall #%nc%",
+    "ERROR_PREBARRAGE_Z2_SUP_Z1": "Downstream water elevation is greater than upstream water elevation",
     "ERROR_PROBLEM_LOADING_SESSION": "Session loaded, with errors",
     "ERROR_REMOUS_NO_WATER_LINE": "No water line can be calculated",
+    "ERROR_STRUCTURE_AU_MOINS_UNE": "A structure needs at least one device",
     "WARNING_REMOUS_PAS_CALCUL_DEPUIS_AMONT": "Upstream boundary condition < Critical elevation: no possible calculation from upstream",
     "WARNING_REMOUS_PAS_CALCUL_DEPUIS_AVAL": "Downstream boundary condition < Critical elevation: no possible calculation from downstream",
     "ERROR_REMOUS_PAS_CALCUL": "No possible calculation, neither from upstream nor from downstream",
@@ -207,10 +211,13 @@
     "INFO_CHILD_TYPE_CLOISON_PLUR": "walls",
     "INFO_CHILD_TYPE_OUVRAGE": "device",
     "INFO_CHILD_TYPE_OUVRAGE_PLUR": "devices",
+    "INFO_CHILD_TYPE_OUVRAGE_SHORT": "D",
     "INFO_CHILD_TYPE_MACRORUGO": "apron",
     "INFO_CHILD_TYPE_MACRORUGO_PLUR": "aprons",
+    "INFO_CHILD_TYPE_MACRORUGO_SHORT": "A",
     "INFO_CHILD_TYPE_PUISSANCE": "power",
     "INFO_CHILD_TYPE_PUISSANCE_PLUR": "powers",
+    "INFO_CHILD_TYPE_PUISSANCE_SHORT": "P",
     "INFO_DIALOG_PARSIM_DESC": "Choose a combination of values to generate the simulation",
     "INFO_FIELDSET_ADD": "Add",
     "INFO_FIELDSET_COPY": "Copy",
@@ -258,6 +265,7 @@
     "INFO_LIB_AMONT": "Upstream",
     "INFO_LIB_AVAL": "Downstream",
     "INFO_LIB_B": "Surface width",
+    "INFO_LIB_BASSIN": "Basin",
     "INFO_LIB_BB": "Pool width",
     "INFO_LIB_BETA": "Beta coefficient",
     "INFO_LIB_BT": "Half opening of the triangle",
@@ -340,6 +348,7 @@
     "INFO_LIB_STRUCTURE_SEUILTRIANGULAIRE": "Triangular weir",
     "INFO_LIB_STRUCTURE_SEUILTRIANGULAIRETRUNC": "Truncated triangular weir",
     "INFO_LIB_STRUCTURE_VANNERECTANGULAIRE": "Rectangular gate",
+    "INFO_LIB_STRUCTURE_N_COURT": "D",
     "INFO_LIB_TAU0": "Tractive force",
     "INFO_LIB_TOR": "Supercritical water line",
     "INFO_LIB_TOTAL": "Total",
@@ -516,9 +525,25 @@
     "INFO_PARAMFIELD_VARIATED": "Variated",
     "INFO_PARAMMODE_LIST": "Values list",
     "INFO_PARAMMODE_MINMAX": "Min/max",
+    "INFO_PB_BASSIN_DESCRIPTION": "B%order%",
+    "INFO_PB_CLOISON_DESCRIPTION": "%ub%-%db%",
+    "INFO_PB_ADD_BASIN": "Add new basin",
+    "INFO_PB_ADD_WALL": "Add new wall",
+    "INFO_PB_BASSIN_N": "Basin #",
+    "INFO_PB_CLOISON": "Wall",
+    "INFO_PB_MOVE_BASIN_UP": "Move basin up",
+    "INFO_PB_MOVE_BASIN_DOWN": "Move basin down",
+    "INFO_PB_NEW_WALL_SELECT_BASINS": "Select basins to connect",
+    "INFO_PB_NEW_WALL_UP_BASIN": "upstream basin",
+    "INFO_PB_NEW_WALL_DOWN_BASIN": "Downstream basin",
+    "INFO_PB_SCHEMA": "Basins layout",
+    "INFO_PREBARRAGE_TITRE": "Pre-dams",
+    "INFO_PREBARRAGE_DESCRIPTION": "fishes basins cross-walls barrages",
+    "INFO_PREBARRAGE_TITRE_COURT": "Pre-dams",
     "INFO_QUICKNAV_CHARTS": "charts",
     "INFO_QUICKNAV_INPUT": "input",
     "INFO_QUICKNAV_RESULTS": "results",
+    "WARNING_PREBARRAGE_BASSIN_ZF_SUP_Z1": "Bottom elevation of basin #%n% is greater than upstream water elevation",
     "WARNING_PROBLEMS_ENCOUNTERED": "Problems occurred during calculation (info: %info%, warning: %warning%, error: %error%)",
     "INFO_REGIMEUNIFORME_DESCRIPTION": "open-channel flow normal depth",
     "INFO_REGIMEUNIFORME_TITRE_COURT": "Uniform flow",
@@ -530,7 +555,7 @@
     "INFO_REMOUS_LARGEUR_BERGE": "Width at embankment level = %B% m",
     "INFO_REMOUS_RESSAUT_DEHORS": "Hydraulic jump detected %sens% abscissa %x% m",
     "INFO_REMOUS_RESSAUT_HYDRO": "Hydraulic jump detected between abscissa %xmin% and %xmax% m",
-    "INFO_REMOUSRESULTS_ABSCISSE": "Abscissa (m)",
+    "INFO_REMOUSRESULTS_ABSCISSE": "Abscissa",
     "INFO_REMOUSRESULTS_BERGE": "Embankment",
     "INFO_REMOUSRESULTS_FOND": "Bottom",
     "INFO_REMOUSRESULTS_TIRANT": "Draft (m)",
@@ -598,6 +623,7 @@
     "INFO_EXAMPLE_LABEL_PAB_COMPLETE": "Standard fish ladder",
     "INFO_EXAMPLE_LABEL_PAB_ECH_TRIANG": "Triangular weirs fish ladder",
     "INFO_EXAMPLE_LABEL_PENTE_CRITIQUE_CANAL": "Canal critical slope",
+    "INFO_EXAMPLE_LABEL_PB": "Pre-dam",
     "INFO_EXAMPLE_LABEL_PERR": "Rock-ramp fish pass",
     "INFO_EXAMPLE_LABEL_WEIR_JET_LENGTH": "Weir jet length",
     "INFO_EXAMPLES_TITLE": "Examples",
diff --git a/src/locale/messages.fr.json b/src/locale/messages.fr.json
index 6ce7511418153d363b0434466027aead75ac003b..5f9abffd11744f442c606430bb0c97b84bbc5e76 100644
--- a/src/locale/messages.fr.json
+++ b/src/locale/messages.fr.json
@@ -52,8 +52,12 @@
     "ERROR_PARAMDEF_VALUE_UNDEFINED": "La valeur du paramètre %symbol% n'est pas définie",
     "ERROR_PARAMDOMAIN_INTERVAL_BOUNDS": "Les bornes (%minValue%/%maxValue%) de l'intervalle sont incorrectes",
     "ERROR_PARAMDOMAIN_INVALID": "Paramètre '%symbol%'&nbsp;: le domaine de définition '%domain%' est incorrect",
+    "ERROR_PREBARRAGE_NON_CONVERGENCE": "Pré-barrage&nbsp;: non convergence du calcul",
+    "ERROR_PREBARRAGE_STRUCTURE_ZDV_INF_ZF": "Cote de radier de l'ouvrage n°%ns% inférieure à la cote de fond du bassin amont de la cloison n°%nc%",
+    "ERROR_PREBARRAGE_Z2_SUP_Z1": "Cote de l'eau aval supérieure à la cote de l'eau amont",
     "ERROR_PROBLEM_LOADING_SESSION": "Session chargée, avec des erreurs",
     "ERROR_REMOUS_NO_WATER_LINE": "Aucune ligne d'eau ne peut être calculée",
+    "ERROR_STRUCTURE_AU_MOINS_UNE": "Il faut au moins un ouvrage dans une structure",
     "WARNING_REMOUS_PAS_CALCUL_DEPUIS_AMONT": "Condition limite amont > Hauteur critique&nbsp;: pas de calcul possible depuis l'amont",
     "WARNING_REMOUS_PAS_CALCUL_DEPUIS_AVAL": "Condition limite aval < Hauteur critique&nbsp;: pas de calcul possible depuis l'aval",
     "ERROR_REMOUS_PAS_CALCUL": "Aucun calcul possible ni depuis l'amont ni depuis l'aval",
@@ -207,10 +211,13 @@
     "INFO_CHILD_TYPE_CLOISON_PLUR": "cloisons",
     "INFO_CHILD_TYPE_OUVRAGE": "ouvrage",
     "INFO_CHILD_TYPE_OUVRAGE_PLUR": "ouvrages",
+    "INFO_CHILD_TYPE_OUVRAGE_SHORT": "O",
     "INFO_CHILD_TYPE_MACRORUGO": "radier",
     "INFO_CHILD_TYPE_MACRORUGO_PLUR": "radiers",
+    "INFO_CHILD_TYPE_MACRORUGO_SHORT": "R",
     "INFO_CHILD_TYPE_PUISSANCE": "puissance",
     "INFO_CHILD_TYPE_PUISSANCE_PLUR": "puissances",
+    "INFO_CHILD_TYPE_PUISSANCE_SHORT": "P",
     "INFO_DIALOG_PARSIM_DESC": "Choisir une combinaison de valeurs pour générer la simulation",
     "INFO_FIELDSET_ADD": "Ajouter",
     "INFO_FIELDSET_COPY": "Copier",
@@ -258,6 +265,7 @@
     "INFO_LIB_AMONT": "Amont",
     "INFO_LIB_AVAL": "Aval",
     "INFO_LIB_B": "Largeur au miroir",
+    "INFO_LIB_BASSIN": "Bassin",
     "INFO_LIB_BB": "Largeur du bassin",
     "INFO_LIB_BETA": "Coefficient béta",
     "INFO_LIB_BT": "Demi-ouverture du triangle",
@@ -341,6 +349,7 @@
     "INFO_LIB_STRUCTURE_SEUILTRIANGULAIRE": "Seuil triangulaire",
     "INFO_LIB_STRUCTURE_SEUILTRIANGULAIRETRUNC": "Seuil triangulaire tronqué",
     "INFO_LIB_STRUCTURE_VANNERECTANGULAIRE": "Vanne rectangulaire",
+    "INFO_LIB_STRUCTURE_N_COURT": "O",
     "INFO_LIB_TAU0": "Force tractrice",
     "INFO_LIB_TOR": "Ligne d'eau torrentielle",
     "INFO_LIB_TOTAL": "Total",
@@ -517,9 +526,25 @@
     "INFO_PARAMFIELD_VARIATED": "Varié",
     "INFO_PARAMMODE_LIST": "Liste de valeurs",
     "INFO_PARAMMODE_MINMAX": "Min/max",
+    "INFO_PB_BASSIN_DESCRIPTION": "B%order%",
+    "INFO_PB_CLOISON_DESCRIPTION": "%ub%-%db%",
+    "INFO_PB_ADD_BASIN": "Ajouter un bassin",
+    "INFO_PB_ADD_WALL": "Ajouter une cloison",
+    "INFO_PB_BASSIN_N": "Bassin n°",
+    "INFO_PB_CLOISON": "Cloison",
+    "INFO_PB_MOVE_BASIN_UP": "Déplacer le bassin vers le haut",
+    "INFO_PB_MOVE_BASIN_DOWN": "Déplacer le bassin vers le bas",
+    "INFO_PB_NEW_WALL_SELECT_BASINS": "Choisir les bassins à connecter",
+    "INFO_PB_NEW_WALL_UP_BASIN": "Bassin amont",
+    "INFO_PB_NEW_WALL_DOWN_BASIN": "Bassin aval",
+    "INFO_PB_SCHEMA": "Organisation des bassins",
+    "INFO_PREBARRAGE_TITRE": "Prébarrages",
+    "INFO_PREBARRAGE_DESCRIPTION": "poissons cloisons bassins",
+    "INFO_PREBARRAGE_TITRE_COURT": "Prébarrages",
     "INFO_QUICKNAV_CHARTS": "graphiques",
     "INFO_QUICKNAV_INPUT": "données",
     "INFO_QUICKNAV_RESULTS": "résultats",
+    "WARNING_PREBARRAGE_BASSIN_ZF_SUP_Z1": "Cote de fond du bassin n°%n% supérieure à la cote de l'eau amont",
     "WARNING_PROBLEMS_ENCOUNTERED": "Des problèmes sont survenus durant le calcul (info&nbsp;: %info%, avertissement&nbsp;: %warning%, erreur&nbsp;: %error%)",
     "INFO_REGIMEUNIFORME_DESCRIPTION": "hydraulique à surface libre hauteur normale",
     "INFO_REGIMEUNIFORME_TITRE_COURT": "R. uniforme",
@@ -531,7 +556,7 @@
     "INFO_REMOUS_LARGEUR_BERGE": "Largeur au niveau des berges = %B% m",
     "INFO_REMOUS_RESSAUT_DEHORS": "Ressaut hydraulique détecté à l'%sens% de l'abscisse %x% m",
     "INFO_REMOUS_RESSAUT_HYDRO": "Ressaut hydraulique détecté entre les abscisses %xmin% et %xmax% m",
-    "INFO_REMOUSRESULTS_ABSCISSE": "Abscisse (m)",
+    "INFO_REMOUSRESULTS_ABSCISSE": "Abscisse",
     "INFO_REMOUSRESULTS_BERGE": "Berge",
     "INFO_REMOUSRESULTS_FOND": "Fond",
     "INFO_REMOUSRESULTS_TIRANT": "Tirant d'eau (m)",
@@ -599,6 +624,7 @@
     "INFO_EXAMPLE_LABEL_PAB_COMPLETE": "Passe à bassins type",
     "INFO_EXAMPLE_LABEL_PAB_ECH_TRIANG": "Passe à bassins à échancrures triangulaires",
     "INFO_EXAMPLE_LABEL_PENTE_CRITIQUE_CANAL": "Pente critique d'un canal",
+    "INFO_EXAMPLE_LABEL_PB": "Pré-barrage",
     "INFO_EXAMPLE_LABEL_PERR": "Passe à enrochements régulièrement répartis",
     "INFO_EXAMPLE_LABEL_WEIR_JET_LENGTH": "Longueur de jet d'un déversoir",
     "INFO_EXAMPLES_TITLE": "Exemples",
diff --git a/src/styles.scss b/src/styles.scss
index 11ffd2a86d88c3fb20401c6e27137444c4c54a32..4f086079ecf28da2a005d9c00a31a5a3c3b2f211 100644
--- a/src/styles.scss
+++ b/src/styles.scss
@@ -365,7 +365,7 @@ var-results {
     }
 }
 
-fixed-results {
+fixed-results, pb-cloison-results {
 
     table.mat-table {