diff --git a/package-lock.json b/package-lock.json index 9f12af07c5303924deb581b2cf12855cc20ee42a..5a2713b26c5e5a1165ba32394037b4d218277c0b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "nghyd", - "version": "1.1.0", + "version": "1.2.0", "lockfileVersion": 1, "requires": true, "dependencies": { @@ -1634,6 +1634,15 @@ "acorn": "^5.0.0" } }, + "adler-32": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/adler-32/-/adler-32-1.2.0.tgz", + "integrity": "sha1-aj5r8KY5ALoVZSgIyxXGgT0aXyU=", + "requires": { + "exit-on-epipe": "~1.0.1", + "printj": "~1.1.0" + } + }, "adm-zip": { "version": "0.4.13", "resolved": "https://registry.npmjs.org/adm-zip/-/adm-zip-0.4.13.tgz", @@ -1693,6 +1702,7 @@ "resolved": "https://registry.npmjs.org/align-text/-/align-text-0.1.4.tgz", "integrity": "sha1-DNkKVhCT810KmSVsIrcGlDP60Rc=", "dev": true, + "optional": true, "requires": { "kind-of": "^3.0.2", "longest": "^1.0.1", @@ -1704,6 +1714,7 @@ "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", "dev": true, + "optional": true, "requires": { "is-buffer": "^1.1.5" } @@ -1840,6 +1851,7 @@ "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.1.5.tgz", "integrity": "sha512-5hYdAkZlcG8tOLujVDTgCT+uPX0VnpAH28gWsLfzpXYm7wP6mp5Q/gYyR7YQ0cKVJcXJnl3j2kpBan13PtQf6w==", "dev": true, + "optional": true, "requires": { "delegates": "^1.0.0", "readable-stream": "^2.0.6" @@ -2757,6 +2769,17 @@ "lazy-cache": "^1.0.3" } }, + "cfb": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/cfb/-/cfb-1.1.0.tgz", + "integrity": "sha512-ZqfxNGWTMKhd0a/n6YKJLq8hWbd5kR3cA4kXwUj9vVEdHlwJ09werR8gN15Z7Y1FTXqdD6dE3GGCxv4uc28raA==", + "requires": { + "adler-32": "~1.2.0", + "commander": "^2.16.0", + "crc-32": "~1.2.0", + "printj": "~1.1.2" + } + }, "chalk": { "version": "2.4.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", @@ -3035,6 +3058,22 @@ } } }, + "codepage": { + "version": "1.14.0", + "resolved": "https://registry.npmjs.org/codepage/-/codepage-1.14.0.tgz", + "integrity": "sha1-jL4lSBMjVZ19MHVxsP/5HnodL5k=", + "requires": { + "commander": "~2.14.1", + "exit-on-epipe": "~1.0.1" + }, + "dependencies": { + "commander": { + "version": "2.14.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.14.1.tgz", + "integrity": "sha512-+YR16o3rK53SmWHU3rEM3tPAh2rwb1yPcQX5irVn7mb0gXbwuCCrnkbV5+PBfETdfg1vui07nM6PCG1zndcjQw==" + } + } + }, "collection-visit": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/collection-visit/-/collection-visit-1.0.0.tgz", @@ -3088,8 +3127,7 @@ "commander": { "version": "2.17.1", "resolved": "https://registry.npmjs.org/commander/-/commander-2.17.1.tgz", - "integrity": "sha512-wPMUt6FnH2yzG95SA6mzjQOEKUU3aLaDEmzs1ti+1E9h+CsrZghRlqEM/EJ4KscsQVG8uNN4uVreUeT8+drlgg==", - "dev": true + "integrity": "sha512-wPMUt6FnH2yzG95SA6mzjQOEKUU3aLaDEmzs1ti+1E9h+CsrZghRlqEM/EJ4KscsQVG8uNN4uVreUeT8+drlgg==" }, "commondir": { "version": "1.0.1", @@ -3217,7 +3255,8 @@ "version": "1.1.0", "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", "integrity": "sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4=", - "dev": true + "dev": true, + "optional": true }, "constants-browserify": { "version": "1.0.0", @@ -3339,6 +3378,15 @@ } } }, + "crc-32": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/crc-32/-/crc-32-1.2.0.tgz", + "integrity": "sha512-1uBwHxF+Y/4yF5G48fwnKq6QsIXheor3ZLPT80yGBV1oEUwpPojlEhQbWKVw1VwcTQyMGHK1/XMmTjmlsmTTGA==", + "requires": { + "exit-on-epipe": "~1.0.1", + "printj": "~1.1.0" + } + }, "create-ecdh": { "version": "4.0.3", "resolved": "https://registry.npmjs.org/create-ecdh/-/create-ecdh-4.0.3.tgz", @@ -3653,7 +3701,8 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", "integrity": "sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o=", - "dev": true + "dev": true, + "optional": true }, "depd": { "version": "1.1.2", @@ -4215,6 +4264,11 @@ "integrity": "sha1-BjJjj42HfMghB9MKD/8aF8uhzQw=", "dev": true }, + "exit-on-epipe": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/exit-on-epipe/-/exit-on-epipe-1.0.1.tgz", + "integrity": "sha512-h2z5mrROTxce56S+pnvAV890uu7ls7f1kEvVGJbw1OlFH3/mlJ5bkXu0KRyW94v37zzHPiUd55iLn3DA7TjWpw==" + }, "expand-braces": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/expand-braces/-/expand-braces-0.1.2.tgz", @@ -4760,6 +4814,11 @@ "integrity": "sha1-mMI9qxF1ZXuMBXPozszZGw/xjIQ=", "dev": true }, + "frac": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/frac/-/frac-1.1.2.tgz", + "integrity": "sha512-w/XBfkibaTl3YDqASwfDUqkna4Z2p9cFSr1aHDt0WoMTECnRfBOv2WArlZILlqgWlmdIlALXGpM2AOhEk5W3IA==" + }, "fragment-cache": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/fragment-cache/-/fragment-cache-0.2.1.tgz", @@ -4858,7 +4917,8 @@ "ansi-regex": { "version": "2.1.1", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "aproba": { "version": "1.2.0", @@ -4879,12 +4939,14 @@ "balanced-match": { "version": "1.0.0", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "brace-expansion": { "version": "1.1.11", "bundled": true, "dev": true, + "optional": true, "requires": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" @@ -4899,17 +4961,20 @@ "code-point-at": { "version": "1.1.0", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "concat-map": { "version": "0.0.1", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "console-control-strings": { "version": "1.1.0", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "core-util-is": { "version": "1.0.2", @@ -5026,7 +5091,8 @@ "inherits": { "version": "2.0.3", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "ini": { "version": "1.3.5", @@ -5038,6 +5104,7 @@ "version": "1.0.0", "bundled": true, "dev": true, + "optional": true, "requires": { "number-is-nan": "^1.0.0" } @@ -5052,6 +5119,7 @@ "version": "3.0.4", "bundled": true, "dev": true, + "optional": true, "requires": { "brace-expansion": "^1.1.7" } @@ -5059,12 +5127,14 @@ "minimist": { "version": "0.0.8", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "minipass": { "version": "2.3.5", "bundled": true, "dev": true, + "optional": true, "requires": { "safe-buffer": "^5.1.2", "yallist": "^3.0.0" @@ -5083,6 +5153,7 @@ "version": "0.5.1", "bundled": true, "dev": true, + "optional": true, "requires": { "minimist": "0.0.8" } @@ -5163,7 +5234,8 @@ "number-is-nan": { "version": "1.0.1", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "object-assign": { "version": "4.1.1", @@ -5175,6 +5247,7 @@ "version": "1.4.0", "bundled": true, "dev": true, + "optional": true, "requires": { "wrappy": "1" } @@ -5260,7 +5333,8 @@ "safe-buffer": { "version": "5.1.2", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "safer-buffer": { "version": "2.1.2", @@ -5296,6 +5370,7 @@ "version": "1.0.2", "bundled": true, "dev": true, + "optional": true, "requires": { "code-point-at": "^1.0.0", "is-fullwidth-code-point": "^1.0.0", @@ -5315,6 +5390,7 @@ "version": "3.0.1", "bundled": true, "dev": true, + "optional": true, "requires": { "ansi-regex": "^2.0.0" } @@ -5358,12 +5434,14 @@ "wrappy": { "version": "1.0.2", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "yallist": { "version": "3.0.3", "bundled": true, - "dev": true + "dev": true, + "optional": true } } }, @@ -5372,6 +5450,7 @@ "resolved": "https://registry.npmjs.org/fstream/-/fstream-1.0.11.tgz", "integrity": "sha1-XB+x8RdHcRTwYyoOtLcbPLD9MXE=", "dev": true, + "optional": true, "requires": { "graceful-fs": "^4.1.2", "inherits": "~2.0.0", @@ -5384,6 +5463,7 @@ "resolved": "https://registry.npmjs.org/gauge/-/gauge-2.7.4.tgz", "integrity": "sha1-LANAXHU4w51+s3sxcCLjJfsBi/c=", "dev": true, + "optional": true, "requires": { "aproba": "^1.0.3", "console-control-strings": "^1.0.0", @@ -5421,7 +5501,8 @@ "version": "4.0.1", "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-4.0.1.tgz", "integrity": "sha1-uWjGsKBDhDJJAui/Gl3zJXmkUP4=", - "dev": true + "dev": true, + "optional": true }, "get-stream": { "version": "3.0.0", @@ -5666,7 +5747,8 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", "integrity": "sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk=", - "dev": true + "dev": true, + "optional": true }, "has-value": { "version": "1.0.0", @@ -6513,7 +6595,8 @@ "version": "0.2.1", "resolved": "https://registry.npmjs.org/is-utf8/-/is-utf8-0.2.1.tgz", "integrity": "sha1-Sw2hRCEE0bM2NA6AeX6GXPOffXI=", - "dev": true + "dev": true, + "optional": true }, "is-windows": { "version": "1.0.2", @@ -7681,6 +7764,7 @@ "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz", "integrity": "sha1-lWkFcI1YtLq0wiYbBPWfMcmTdMA=", "dev": true, + "optional": true, "requires": { "graceful-fs": "^4.1.2", "parse-json": "^2.2.0", @@ -7693,7 +7777,8 @@ "version": "2.3.0", "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", - "dev": true + "dev": true, + "optional": true } } }, @@ -7802,7 +7887,8 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/longest/-/longest-1.0.1.tgz", "integrity": "sha1-MKCy2jj3N3DoKUoNIuZiXtd9AJc=", - "dev": true + "dev": true, + "optional": true }, "loose-envify": { "version": "1.4.0", @@ -7986,7 +8072,8 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-1.0.1.tgz", "integrity": "sha1-2TPOuSBdgr3PSIb2dCvcK03qFG0=", - "dev": true + "dev": true, + "optional": true }, "map-stream": { "version": "0.1.0", @@ -8704,6 +8791,7 @@ "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-4.1.2.tgz", "integrity": "sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==", "dev": true, + "optional": true, "requires": { "are-we-there-yet": "~1.1.2", "console-control-strings": "~1.1.0", @@ -9600,6 +9688,11 @@ "integrity": "sha1-gV7R9uvGWSb4ZbMQwHE7yzMVzks=", "dev": true }, + "printj": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/printj/-/printj-1.1.2.tgz", + "integrity": "sha512-zA2SmoLaxZyArQTOPj5LXecR+RagfPSU5Kw1qP+jkWeNlrq+eJZyY2oS68SU1Z/7/myXM4lo9716laOFAVStCQ==" + }, "prismjs": { "version": "1.15.0", "resolved": "https://registry.npmjs.org/prismjs/-/prismjs-1.15.0.tgz", @@ -9975,6 +10068,7 @@ "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-1.1.0.tgz", "integrity": "sha1-9f+qXs0pyzHAR0vKfXVra7KePyg=", "dev": true, + "optional": true, "requires": { "load-json-file": "^1.0.0", "normalize-package-data": "^2.3.2", @@ -9986,6 +10080,7 @@ "resolved": "https://registry.npmjs.org/path-type/-/path-type-1.1.0.tgz", "integrity": "sha1-WcRPfuSR2nBNpBXaWkBwuk+P5EE=", "dev": true, + "optional": true, "requires": { "graceful-fs": "^4.1.2", "pify": "^2.0.0", @@ -9996,7 +10091,8 @@ "version": "2.3.0", "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", - "dev": true + "dev": true, + "optional": true } } }, @@ -10005,6 +10101,7 @@ "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-1.0.1.tgz", "integrity": "sha1-nWPBMnbAZZGNV/ACpX9AobZD+wI=", "dev": true, + "optional": true, "requires": { "find-up": "^1.0.0", "read-pkg": "^1.0.0" @@ -10015,6 +10112,7 @@ "resolved": "https://registry.npmjs.org/find-up/-/find-up-1.1.2.tgz", "integrity": "sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8=", "dev": true, + "optional": true, "requires": { "path-exists": "^2.0.0", "pinkie-promise": "^2.0.0" @@ -10025,6 +10123,7 @@ "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-2.1.0.tgz", "integrity": "sha1-D+tsZPD8UY2adU3V77YscCJ2H0s=", "dev": true, + "optional": true, "requires": { "pinkie-promise": "^2.0.0" } @@ -11177,6 +11276,14 @@ "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", "dev": true }, + "ssf": { + "version": "0.10.2", + "resolved": "https://registry.npmjs.org/ssf/-/ssf-0.10.2.tgz", + "integrity": "sha512-rDhAPm9WyIsY8eZEKyE8Qsotb3j/wBdvMWBUsOhJdfhKGLfQidRjiBUV0y/MkyCLiXQ38FG6LWW/VYUtqlIDZQ==", + "requires": { + "frac": "~1.1.2" + } + }, "sshpk": { "version": "1.16.1", "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.16.1.tgz", @@ -11360,6 +11467,7 @@ "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz", "integrity": "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=", "dev": true, + "optional": true, "requires": { "is-utf8": "^0.2.0" } @@ -12801,6 +12909,7 @@ "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.3.tgz", "integrity": "sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA==", "dev": true, + "optional": true, "requires": { "string-width": "^1.0.2 || 2" } @@ -12863,6 +12972,20 @@ "ultron": "~1.1.0" } }, + "xlsx": { + "version": "0.14.1", + "resolved": "https://registry.npmjs.org/xlsx/-/xlsx-0.14.1.tgz", + "integrity": "sha512-7hjB5YuyJo1fuuzXQjwuxD8LSUzE4Rxu5ToC3fB5JSunZxGjLcgKg69bEFG9GYoxeVDx5GL0k1dUodlvaQNRQw==", + "requires": { + "adler-32": "~1.2.0", + "cfb": "^1.1.0", + "codepage": "~1.14.0", + "commander": "~2.17.1", + "crc-32": "~1.2.0", + "exit-on-epipe": "~1.0.1", + "ssf": "~0.10.2" + } + }, "xml2js": { "version": "0.4.19", "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.4.19.tgz", diff --git a/package.json b/package.json index 77d7b5888f7620ff738500d9d9894f80ff68abec..bb1875351a7cd2f95737651be8ae0fd92da0f459 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "nghyd", - "version": "1.2.0", + "version": "4.0.0", "license": "MIT", "scripts": { "ng": "ng", @@ -45,6 +45,7 @@ "rxjs": "^6.3.3", "rxjs-compat": "^6.3.3", "tslib": "^1.9.0", + "xlsx": "^0.14.1", "zone.js": "^0.8.28" }, "devDependencies": { @@ -52,7 +53,7 @@ "@angular/cli": "^7.2.2", "@angular/compiler-cli": "^7.2.1", "@angular/language-service": "^7.2.1", - "@compodoc/compodoc": "^1.1.7", + "@compodoc/compodoc": "^1.1.8", "@types/file-saver": "^2.0.0", "@types/jasmine": "^3.3.7", "@types/jasminewd2": "^2.0.6", diff --git a/src/app/app.component.html b/src/app/app.component.html index fbcfa67dbeadfe99ba0a0dc88d45bc44e1eaf537..134007e73fb72733da7467fb444d028cd18d9972 100644 --- a/src/app/app.component.html +++ b/src/app/app.component.html @@ -22,7 +22,7 @@ <span class="calc-name"> {{ currentCalc.title }} </span> - <span class="calc-type" [innerHTML]="'( ' + currentCalc ? currentCalc.type : '' + ' )'"></span> + <span class="calc-type" [innerHTML]="'(' + getCalculatorLabel(currentCalc.type) + ')'"></span> </button> <mat-menu #menu="matMenu" colo="accent"> diff --git a/src/app/app.component.ts b/src/app/app.component.ts index 542a55cdb830a07f55308c501476969b8ba3ed0c..acecbe6d6c16af6261b8478879d8b08402f9371a 100644 --- a/src/app/app.component.ts +++ b/src/app/app.component.ts @@ -1,5 +1,7 @@ import { Component, ApplicationRef, OnInit, OnDestroy, HostListener, ViewChild, ComponentRef } from "@angular/core"; import { Router, Event, NavigationEnd, ActivationEnd } from "@angular/router"; +import { MatSidenav, MatToolbar, MatDialog, MatIconRegistry } from "@angular/material"; +import { DomSanitizer } from "@angular/platform-browser"; import { Observer, jalhydDateRev, CalculatorType } from "jalhyd"; @@ -14,7 +16,6 @@ import { HttpService } from "./services/http/http.service"; import { ApplicationSetupService } from "./services/app-setup/app-setup.service"; import { nghydDateRev } from "../date_revision"; -import { MatSidenav, MatToolbar, MatDialog } from "@angular/material"; import { DialogConfirmEmptySessionComponent } from "./components/dialog-confirm-empty-session/dialog-confirm-empty-session.component"; import { DialogLoadSessionComponent } from "./components/dialog-load-session/dialog-load-session.component"; import { DialogSaveSessionComponent } from "./components/dialog-save-session/dialog-save-session.component"; @@ -69,7 +70,9 @@ export class AppComponent implements OnInit, OnDestroy, Observer { private httpService: HttpService, private confirmEmptySessionDialog: MatDialog, private saveSessionDialog: MatDialog, - private loadSessionDialog: MatDialog + private loadSessionDialog: MatDialog, + private matIconRegistry: MatIconRegistry, + private domSanitizer: DomSanitizer ) { ServiceFactory.instance.httpService = httpService; ServiceFactory.instance.applicationSetupService = appSetupService; @@ -81,6 +84,7 @@ export class AppComponent implements OnInit, OnDestroy, Observer { // close side navigation when clicking a calculator tab if (event instanceof NavigationEnd) { this.sidenav.close(); + window.scrollTo(0, 0); } // [de]activate calc tabs depending on loaded route if (event instanceof ActivationEnd) { @@ -93,6 +97,12 @@ export class AppComponent implements OnInit, OnDestroy, Observer { } } }); + + // icônes personnalisées + this.matIconRegistry.addSvgIcon( + "file_excel", + this.domSanitizer.bypassSecurityTrustResourceUrl("../../assets/icons/file-excel.svg") + ); } ngOnInit() { diff --git a/src/app/components/calculator-results/calculator-results.component.html b/src/app/components/calculator-results/calculator-results.component.html index 1cf1ee86e9e06e53a464453a59f86c8d0ae54081..03c60dfa0215f53ecd21ce647d72338d7715d427 100644 --- a/src/app/components/calculator-results/calculator-results.component.html +++ b/src/app/components/calculator-results/calculator-results.component.html @@ -1,5 +1,5 @@ -<div class="container-fluid"> - <fixedvar-results></fixedvar-results> +<div> <section-results></section-results> <remous-results></remous-results> + <fixedvar-results></fixedvar-results> </div> diff --git a/src/app/components/fixedvar-results/fixed-results.component.html b/src/app/components/fixedvar-results/fixed-results.component.html index b35f932d4c58789bd991bd20f33c13d0dd2ad727..1c2c8f0b4e4937432f1b9cd09e453700432123d2 100644 --- a/src/app/components/fixedvar-results/fixed-results.component.html +++ b/src/app/components/fixedvar-results/fixed-results.component.html @@ -1,17 +1,26 @@ <div class="fixed-results-container" *ngIf="hasFixedParameters"> + + <div class="fixed-results-buttons"> + <button mat-icon-button (click)="exportAsSpreadsheet()"> + <mat-icon color="primary" svgIcon="file_excel" class="scaled09"></mat-icon> + </button> + </div> + <!-- table des résultats fixés --> - <table mat-table [dataSource]="dataSet"> + <div class="fixed-results-inner-container" #tableContainer> + <table mat-table [dataSource]="dataSet"> - <ng-container matColumnDef="parametre"> - <th mat-header-cell *matHeaderCellDef>{{ uitextParamFixes }}</th> - <td mat-cell *matCellDef="let element" [ngClass]="{'highlightedResult': element.isCalcResult}">{{ element.label }}</td> - </ng-container> - <ng-container matColumnDef="valeur"> - <th mat-header-cell *matHeaderCellDef>{{ uitextValeurs }}</th> - <td mat-cell *matCellDef="let element" [ngClass]="{'highlightedResult': element.isCalcResult}">{{ element.value }}</td> - </ng-container> + <ng-container matColumnDef="parametre"> + <th mat-header-cell *matHeaderCellDef>{{ uitextParamFixes }}</th> + <td mat-cell *matCellDef="let element" [ngClass]="{'highlightedResult': element.isCalcResult}">{{ element.label }}</td> + </ng-container> + <ng-container matColumnDef="valeur"> + <th mat-header-cell *matHeaderCellDef>{{ uitextValeurs }}</th> + <td mat-cell *matCellDef="let element" [ngClass]="{'highlightedResult': element.isCalcResult}">{{ element.value }}</td> + </ng-container> - <tr mat-header-row *matHeaderRowDef="tableColumns"></tr> - <tr mat-row *matRowDef="let row; columns: tableColumns;"></tr> - </table> + <tr mat-header-row *matHeaderRowDef="tableColumns"></tr> + <tr mat-row *matRowDef="let row; columns: tableColumns;"></tr> + </table> + </div> </div> diff --git a/src/app/components/fixedvar-results/fixed-results.component.scss b/src/app/components/fixedvar-results/fixed-results.component.scss index 6884f3f370e00c829b993ac10a651536f736868c..5a8e48d7ad5cf2fc3ee75274b1dbd84f2fe3486f 100644 --- a/src/app/components/fixedvar-results/fixed-results.component.scss +++ b/src/app/components/fixedvar-results/fixed-results.component.scss @@ -2,12 +2,29 @@ display: block; } -.fixed-results-container { - margin-top: 1em; +.fixed-results-inner-container { border: solid #ccc 1px; border-radius: 2px; } +.fixed-results-buttons { + padding-right: 4px; + padding-top: 4px; + text-align: right; + background-color: white; + + button { + margin-left: 3px; + width: auto; + + mat-icon { + &.scaled09 { + transform: scale(0.9); + } + } + } +} + table.mat-table { .mat-header-row { @@ -15,7 +32,7 @@ table.mat-table { } .mat-row { - height: 32px; + height: auto; &:nth-child(odd) { background-color: #f4f4f4; @@ -26,6 +43,11 @@ table.mat-table { font-size: 1em; color: black; } + + ::ng-deep .mat-cell { + padding-top: 8px; + padding-bottom: 8px; + } } .highlightedResult { diff --git a/src/app/components/fixedvar-results/fixed-results.component.ts b/src/app/components/fixedvar-results/fixed-results.component.ts index 4e97712b9f79d4c3999c8d76c70c7f77342b5b63..cf23921d8e5e41b06fc6c2346245b324a70e171d 100644 --- a/src/app/components/fixedvar-results/fixed-results.component.ts +++ b/src/app/components/fixedvar-results/fixed-results.component.ts @@ -1,11 +1,11 @@ -import { Component, ViewChild } from "@angular/core"; +import { Component, ViewChild, ElementRef } from "@angular/core"; import { FixedResults } from "../../results/fixed-results"; import { NgParameter } from "../../formulaire/ngparam"; import { CalculatorResults } from "../../results/calculator-results"; import { I18nService } from "../../services/internationalisation/internationalisation.service"; import { ApplicationSetupService } from "../../services/app-setup/app-setup.service"; -import { MatTable } from "@angular/material"; +import * as XLSX from "xlsx"; @Component({ selector: "fixed-results", @@ -18,13 +18,13 @@ export class FixedResultsComponent { /** résultats non mis en forme */ private _fixedResults: FixedResults; - @ViewChild(MatTable) table: MatTable<any>; + @ViewChild("tableContainer") table: ElementRef; public tableColumns = [ "parametre", "valeur" ]; constructor( private intlService: I18nService, - private appSetupService: ApplicationSetupService, + private appSetupService: ApplicationSetupService ) { } public set results(r: FixedResults) { @@ -80,12 +80,14 @@ export class FixedResultsComponent { && res.resultElement && res.extraResults ) { - // 2.1. main result - data.push({ - label: this._fixedResults.calculatedParameterHeader, - value: this.intlService.formatResult(res.name, res.resultElement.vCalc), - isCalcResult: true // for CSS - }); + // 2.1. main result (sometimes empty, for ex. in "Section paramétrée") + if (res.name && res.resultElement.vCalc) { + data.push({ + label: this._fixedResults.calculatedParameterHeader, + value: this.intlService.formatResult(res.name, res.resultElement.vCalc), + isCalcResult: true // for CSS + }); + } // 2.2. extra results const extraResults = res.resultElement.extraResults; @@ -102,4 +104,13 @@ export class FixedResultsComponent { } return data; } + + public exportAsSpreadsheet() { + // automagic <table> extraction + const ws: XLSX.WorkSheet = XLSX.utils.table_to_sheet(this.table.nativeElement); + const wb: XLSX.WorkBook = XLSX.utils.book_new(); + XLSX.utils.book_append_sheet(wb, ws, "default"); + // save and download + XLSX.writeFile(wb, "FixedResults.xlsx"); + } } diff --git a/src/app/components/fixedvar-results/var-results.component.html b/src/app/components/fixedvar-results/var-results.component.html index f89799dfd48f3e55d2f516df358b3ccf908c93a3..30d0afac88a20a45ad13f6c33b08af49de08ffb2 100644 --- a/src/app/components/fixedvar-results/var-results.component.html +++ b/src/app/components/fixedvar-results/var-results.component.html @@ -1,15 +1,31 @@ -<div class="var-results-container"> - <!-- scrollable --> - <div class="var-results-inner-container"> +<div class="var-results-container" #variableResults *ngIf="hasResults" fxLayout="row wrap" fxLayoutAlign="center center"> + <div fxFlex="1 1 100%"> + <div class="var-results-buttons"> + <button mat-icon-button (click)="exportAsSpreadsheet()"> + <mat-icon color="primary" svgIcon="file_excel" class="scaled09"></mat-icon> + </button> + <button mat-icon-button *ngIf="! isFullscreen" (click)="setFullscreen(variableResults)"> + <mat-icon color="primary" class="scaled12">fullscreen</mat-icon> + </button> + <button mat-icon-button *ngIf="isFullscreen" (click)="exitFullscreen()"> + <mat-icon color="primary" class="scaled12">fullscreen_exit</mat-icon> + </button> + </div> - <table mat-table [dataSource]="dataSet"> - <ng-container *ngFor="let h of headers; let i = index" [matColumnDef]="h"> - <th mat-header-cell *matHeaderCellDef>{{ h }}</th> - <td mat-cell *matCellDef="let element">{{ element[i] }}</td> - </ng-container> + <div class="var-results-scrollable-container" [ngClass]="{'full-height': isFullscreen}"> + <!-- scrollable --> + <div class="var-results-inner-container" #tableContainer> - <tr mat-header-row *matHeaderRowDef="headers"></tr> - <tr mat-row *matRowDef="let row; columns: headers;"></tr> - </table> + <table mat-table [dataSource]="dataSet"> + <ng-container *ngFor="let h of headers; let i = index" [matColumnDef]="h"> + <th mat-header-cell *matHeaderCellDef>{{ h }}</th> + <td mat-cell *matCellDef="let element">{{ 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/fixedvar-results/var-results.component.scss b/src/app/components/fixedvar-results/var-results.component.scss index d8b8f970ea6ea458e1f1ccf4acccb0a6839af5f1..aa3f8ec31732183d2e4fdb2e588b2bbf9f19c5b2 100644 --- a/src/app/components/fixedvar-results/var-results.component.scss +++ b/src/app/components/fixedvar-results/var-results.component.scss @@ -3,9 +3,38 @@ } .var-results-container { - overflow-x: scroll; margin-top: 2em; + background-color: white; +} + +.var-results-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) + } + &.scaled09 { + transform: scale(0.9); + } + } + } +} + +.var-results-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 { diff --git a/src/app/components/fixedvar-results/var-results.component.ts b/src/app/components/fixedvar-results/var-results.component.ts index 7b8ca69eb196661c8d0b8619bf10bdad3c314aa2..37657da07f50469513321579049941de533367c0 100644 --- a/src/app/components/fixedvar-results/var-results.component.ts +++ b/src/app/components/fixedvar-results/var-results.component.ts @@ -1,10 +1,9 @@ -import { Component, ViewChild } from "@angular/core"; -import { MatTable } from "@angular/material"; +import { Component, ViewChild, ElementRef } from "@angular/core"; import { VarResults } from "../../results/var-results"; import { ApplicationSetupService } from "../../services/app-setup/app-setup.service"; import { ResultElement } from "jalhyd"; import { I18nService } from "../../services/internationalisation/internationalisation.service"; -import { nbind } from 'q'; +import * as XLSX from "xlsx"; @Component({ selector: "var-results", @@ -24,7 +23,12 @@ export class VarResultsComponent { /** entêtes des colonnes (param à varier, à calculer + extraResults) */ private _headers: string[]; - @ViewChild(MatTable) table: MatTable<any>; + /** tracks the fullscreen state */ + public get isFullscreen() { + return (document["fullscreenElement"] !== null); + } + + @ViewChild("tableContainer") table: ElementRef; constructor( private appSetupService: ApplicationSetupService, @@ -94,4 +98,21 @@ export class VarResultsComponent { } return data; } + + public setFullscreen(element) { + element.requestFullscreen(); + } + + public exitFullscreen() { + document.exitFullscreen(); + } + + public exportAsSpreadsheet() { + // automagic <table> extraction + const ws: XLSX.WorkSheet = XLSX.utils.table_to_sheet(this.table.nativeElement); + const wb: XLSX.WorkBook = XLSX.utils.book_new(); + XLSX.utils.book_append_sheet(wb, ws, "default"); + // save and download + XLSX.writeFile(wb, "VariableResults.xlsx"); + } } diff --git a/src/app/components/generic-calculator/calculator.component.html b/src/app/components/generic-calculator/calculator.component.html index 97446a3a9ce637f766b03da297a2b9882472b0e1..7874908f369790519d73e029d0819a560c0fb714 100644 --- a/src/app/components/generic-calculator/calculator.component.html +++ b/src/app/components/generic-calculator/calculator.component.html @@ -24,7 +24,7 @@ <mat-card-content> <!-- nom du module de calcul --> - <calc-name [title]="uitextCalculatorName"></calc-name> + <calc-name id="calculator-name" [title]="uitextCalculatorName"></calc-name> <div id="calc-cards-container" class="container" fxLayout="row wrap" fxLayoutAlign="space-around start"> <!-- chapitres --> @@ -46,6 +46,7 @@ <!-- résultats --> <mat-card id="calc-card-results" fxFlex.gt-xs="1 0 400px" fxFlex.lt-sm="1 0 300px"> + <div id="fake-results-anchor"></div> <mat-card-header> <mat-card-title> <h1 [innerHTML]="uitextResultsTitle"></h1> diff --git a/src/app/components/generic-calculator/calculator.component.scss b/src/app/components/generic-calculator/calculator.component.scss index b9275137bf8288272c846be0520777d73c5e211f..2346a487428bcb44594db9221dc7e84c2e6fd3ab 100644 --- a/src/app/components/generic-calculator/calculator.component.scss +++ b/src/app/components/generic-calculator/calculator.component.scss @@ -14,6 +14,12 @@ margin-right: -1em; } +// dirty fix for scrollIntoView() positioning +#fake-results-anchor { + float: left; // to avoid following elements being affected by negative margin + margin-top: -54px; +} + 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 ffc2cf9d8fe41c3d9a92fa0beffdbfdd59f30eed..3496192aabb2636a334ae6753ef68c73ea743936 100644 --- a/src/app/components/generic-calculator/calculator.component.ts +++ b/src/app/components/generic-calculator/calculator.component.ts @@ -241,7 +241,7 @@ export class GenericCalculatorComponent extends BaseComponent implements OnInit, } private scrollToResults() { - const element = document.getElementById("resultsComp"); + const element = document.getElementById("fake-results-anchor"); if (element) { element.scrollIntoView(); } diff --git a/src/app/components/log/log.component.scss b/src/app/components/log/log.component.scss index 7dee1f9239623da8254eb25fedcaebd2acff4697..4c37d752b16c35c7d426ce82734044c40d02b32a 100644 --- a/src/app/components/log/log.component.scss +++ b/src/app/components/log/log.component.scss @@ -3,7 +3,7 @@ } .hyd_log { - margin-top: 1em; + margin-top: 2.5em; border: solid #ccc 1px; border-radius: 2px; padding: 1em; diff --git a/src/app/components/remous-results/remous-results.component.html b/src/app/components/remous-results/remous-results.component.html index 24c15f01effb82c4ca45e46839b49138fe3a8f09..4efd8c40dabe2d2ffd9fed7a21755f7e9c400fdb 100644 --- a/src/app/components/remous-results/remous-results.component.html +++ b/src/app/components/remous-results/remous-results.component.html @@ -1,16 +1,46 @@ -<div class="container" *ngIf="hasResults"> - <div> - <chart [type]="graph1_type" [data]="graph1_data" [options]="graph1_options"></chart> - </div> - <div> - <chart *ngIf="extraGraph" [type]="graph2_type" [data]="graph2_data" [options]="graph2_options"></chart> +<div class="remous-results-container" #remousResults *ngIf="hasResults" fxLayout="row wrap" fxLayoutAlign="center center"> + <div fxFlex="1 1 100%"> + <div class="remous-results-buttons"> + <button mat-icon-button (click)="exportAsImage(remousResults)"> + <mat-icon color="primary">image</mat-icon> + </button> + <button mat-icon-button *ngIf="! isFullscreen" (click)="setFullscreen(remousResults)"> + <mat-icon color="primary" class="scaled12">fullscreen</mat-icon> + </button> + <button mat-icon-button *ngIf="isFullscreen" (click)="exitFullscreen()"> + <mat-icon color="primary" class="scaled12">fullscreen_exit</mat-icon> + </button> + </div> + + <chart id="main-chart" ngClass.lt-sm="height300" ngClass.sm="height400" ngClass.md="height400" ngClass.gt-md="height600" + [type]="graph1_type" [data]="graph1_data" [options]="graph1_options"> + </chart> </div> +</div> - <!-- journal --> - <log></log> +<div class="remous-results-extragraph-container" #remousResultsExtra *ngIf="extraGraph" fxLayout="row wrap" fxLayoutAlign="center center"> + <div fxFlex="1 1 100%"> + <div class="remous-results-buttons"> + <button mat-icon-button (click)="exportAsImage(remousResultsExtra)"> + <mat-icon color="primary">image</mat-icon> + </button> + <button mat-icon-button *ngIf="! isFullscreen" (click)="setFullscreen(remousResultsExtra)"> + <mat-icon color="primary" class="scaled12">fullscreen</mat-icon> + </button> + <button mat-icon-button *ngIf="isFullscreen" (click)="exitFullscreen()"> + <mat-icon color="primary" class="scaled12">fullscreen_exit</mat-icon> + </button> + </div> - <div *ngIf="hasData"> - <!-- résultats numériques --> - <var-results></var-results> + <chart [type]="graph2_type" [data]="graph2_data" [options]="graph2_options"></chart> </div> </div> + + +<!-- journal --> +<log></log> + +<div [hidden]="! hasData"><!-- *ngIf breaks @ViewChild availability--> + <!-- résultats numériques --> + <var-results></var-results> +</div> diff --git a/src/app/components/remous-results/remous-results.component.scss b/src/app/components/remous-results/remous-results.component.scss new file mode 100644 index 0000000000000000000000000000000000000000..a9966376574d9609f7e1cd5095fa03d80d0d9fa7 --- /dev/null +++ b/src/app/components/remous-results/remous-results.component.scss @@ -0,0 +1,39 @@ +.remous-results-container{ + display: block; + background-color: white; +} + +#main-chart { + &.height600 { + height:600px; + } + &.height400 { + height: 400px; + } + &.height300 { + height: 300px; + } +} + +.remous-results-extragraph-container{ + display: block; + background-color: white; +} + +.remous-results-buttons { + padding-right: 10px; + padding-top: 4px; + text-align: right; + background-color: white; + + button { + margin-left: 3px; + width: auto; + + mat-icon { + &.scaled12 { + transform: scale(1.2); + } + } + } +} diff --git a/src/app/components/remous-results/remous-results.component.ts b/src/app/components/remous-results/remous-results.component.ts index a64d46ce41d264b9370a6654be5d667281a374fc..d62a814e06bf032b3120d17d9a4058c5cb91096c 100644 --- a/src/app/components/remous-results/remous-results.component.ts +++ b/src/app/components/remous-results/remous-results.component.ts @@ -193,25 +193,8 @@ class GraphData { @Component({ selector: "remous-results", templateUrl: "./remous-results.component.html", - styles: [` - .result_label { - text-align: right; - padding-top:10px; - padding-bottom:10px; - padding-right:10px; - } - .result_value { - text-align: center; - padding-left:30px; - padding-right:30px; - } - .result_id_0 { - background-color: #f0f0f0; - } - .result_id_2 { - font-weight: bold; - } - ` + styleUrls: [ + "./remous-results.component.scss" ] }) export class RemousResultsComponent implements DoCheck { @@ -253,6 +236,11 @@ export class RemousResultsComponent implements DoCheck { @ViewChild(LogComponent) private logComponent: LogComponent; + /** tracks the fullscreen state */ + public get isFullscreen() { + return (document["fullscreenElement"] !== null); + } + constructor( private intlService: I18nService, private appSetup: ApplicationSetupService @@ -270,10 +258,6 @@ export class RemousResultsComponent implements DoCheck { return this.intlService.localizeText("INFO_REMOUSRESULTS_ABSCISSE"); } - private get uitextTirant() { - return this.intlService.localizeText("INFO_REMOUSRESULTS_TIRANT"); - } - private get uitextFond() { return this.intlService.localizeText("INFO_REMOUSRESULTS_FOND"); } @@ -290,7 +274,7 @@ export class RemousResultsComponent implements DoCheck { return this.intlService.localizeText("INFO_REMOUSRESULTS_TIRANTCRITIQUE"); } - private get extraGraph(): boolean { + public get extraGraph(): boolean { return this._remousResults === undefined ? false : this._remousResults.extraGraph; } @@ -299,6 +283,23 @@ export class RemousResultsComponent implements DoCheck { this.intlService.getExtraResLabel(this._remousResults.extraParamSymbol); } + private headers(): string[] { + return this._tableHeaders; + } + + private getResultClass(i: number) { + // tslint:disable-next-line:no-bitwise + return "result_id_" + String(i & 1); + } + + public get hasResults(): boolean { + return this._remousResults !== undefined && this._remousResults.hasResults; + } + + public get hasData(): boolean { + return this._remousResults && this._remousResults.result && this._remousResults.result.ok; + } + public set results(rs: CalculatorResults[]) { this._remousResults = undefined; if (rs !== undefined) { @@ -559,17 +560,12 @@ export class RemousResultsComponent implements DoCheck { const nDigits = this.appSetup.displayDigits; this.graph1_options = { responsive: true, - maintainAspectRatio: true, + maintainAspectRatio: false, animation: { duration: 0 }, legend: { display: true, - position: "right" - }, - title: { - display: true, - text: this.uitextAbscisse, position: "bottom" }, scales: { @@ -582,6 +578,10 @@ export class RemousResultsComponent implements DoCheck { callback: function(value, index, values) { return Number(value).toFixed(nDigits); } + }, + scaleLabel: { + display: true, + labelString: this.uitextAbscisse } }] }, @@ -605,31 +605,45 @@ export class RemousResultsComponent implements DoCheck { }, legend: { display: true, - position: "right" - }, - title: { - display: true, - text: this.uitextAbscisse, position: "bottom" + }, + scales: { + xAxes: [{ + scaleLabel: { + display: true, + labelString: this.uitextAbscisse + }, + ticks: { + precision: nDigits, + callback: function(value, index, values) { + return Number(value).toFixed(nDigits); + } + }, + }] + }, + tooltips: { + callbacks: { + label: function(tooltipItem, data) { + return Number(tooltipItem.yLabel).toFixed(nDigits); + } + } } }; } } - private headers(): string[] { - return this._tableHeaders; - } - - private getResultClass(i: number) { - // tslint:disable-next-line:no-bitwise - return "result_id_" + String(i & 1); + public setFullscreen(element) { + element.requestFullscreen(); } - public get hasResults(): boolean { - return this._remousResults !== undefined && this._remousResults.hasResults; + public exitFullscreen() { + document.exitFullscreen(); } - private get hasData(): boolean { - return this._remousResults && this._remousResults.result && this._remousResults.result.ok; + public exportAsImage(element: HTMLDivElement) { + const canvas: HTMLCanvasElement = element.querySelector("canvas"); + canvas.toBlob((blob) => { + saveAs(blob, "chart.png"); + }); // defaults to image/png } } diff --git a/src/app/components/results-graph/results-graph.component.html b/src/app/components/results-graph/results-graph.component.html index 9f0dc91e235577fd23ee2138e13f465f8b40409c..61ff43cc45dab0e93d125238794f82714cb90910 100644 --- a/src/app/components/results-graph/results-graph.component.html +++ b/src/app/components/results-graph/results-graph.component.html @@ -1,4 +1,20 @@ -<chart [type]="graph_type" [data]="graph_data" [options]="graph_options"> -</chart> +<div class="graph-results-container" #graphResults fxLayout="row wrap" fxLayoutAlign="center center"> + <div fxFlex="1 1 100%"> + <div class="graph-results-buttons"> + <button mat-icon-button (click)="exportAsImage(graphResults)"> + <mat-icon color="primary">image</mat-icon> + </button> + <button mat-icon-button *ngIf="! isFullscreen" (click)="setFullscreen(graphResults)"> + <mat-icon color="primary" class="scaled12">fullscreen</mat-icon> + </button> + <button mat-icon-button *ngIf="isFullscreen" (click)="exitFullscreen()"> + <mat-icon color="primary" class="scaled12">fullscreen_exit</mat-icon> + </button> + </div> + + <chart [type]="graph_type" [data]="graph_data" [options]="graph_options" #graphChart> + </chart> + </div> +</div> <graph-type></graph-type> diff --git a/src/app/components/results-graph/results-graph.component.scss b/src/app/components/results-graph/results-graph.component.scss new file mode 100644 index 0000000000000000000000000000000000000000..7a13a42ec3fbbf6f09d763c9cd79ea58173d65bf --- /dev/null +++ b/src/app/components/results-graph/results-graph.component.scss @@ -0,0 +1,23 @@ +.graph-results-container{ + display: block; + background-color: white; +} + +.graph-results-buttons { + padding-right: 10px; + padding-top: 4px; + margin-bottom: -30px; + text-align: right; + background-color: white; + + button { + margin-left: 3px; + width: auto; + + mat-icon { + &.scaled12 { + transform: scale(1.2); + } + } + } +} diff --git a/src/app/components/results-graph/results-graph.component.ts b/src/app/components/results-graph/results-graph.component.ts index 35dbf11cda534be7b9733acd4538dec58c29c931..0e0fbc26517117fb2b6d0c1fef79fdb4c24ba71b 100644 --- a/src/app/components/results-graph/results-graph.component.ts +++ b/src/app/components/results-graph/results-graph.component.ts @@ -8,7 +8,10 @@ import { ApplicationSetupService } from "../../services/app-setup/app-setup.serv @Component({ selector: "results-graph", - templateUrl: "./results-graph.component.html" + templateUrl: "./results-graph.component.html", + styleUrls: [ + "./results-graph.component.scss" + ] }) export class ResultsGraphComponent implements AfterContentInit, Observer { private _results: VarResults; @@ -36,6 +39,11 @@ export class ResultsGraphComponent implements AfterContentInit, Observer { } }; + /** tracks the fullscreen state */ + public get isFullscreen() { + return (document["fullscreenElement"] !== null); + } + public constructor( private appSetup: ApplicationSetupService ) { @@ -196,6 +204,21 @@ export class ResultsGraphComponent implements AfterContentInit, Observer { }; } + public setFullscreen(element) { + element.requestFullscreen(); + } + + public exitFullscreen() { + document.exitFullscreen(); + } + + public exportAsImage(element: HTMLDivElement) { + const canvas: HTMLCanvasElement = element.querySelector("canvas"); + canvas.toBlob((blob) => { + saveAs(blob, "chart.png"); + }); // defaults to image/png + } + // interface Observer update(sender: any, data: any) { diff --git a/src/app/components/section-results/section-results.component.html b/src/app/components/section-results/section-results.component.html index e9a103d4e780c34cea400353507f9b4762392762..2415b265547f4e7a83cd676108edaefd596f7b03 100644 --- a/src/app/components/section-results/section-results.component.html +++ b/src/app/components/section-results/section-results.component.html @@ -1,18 +1,20 @@ -<div class="container-fluid" *ngIf="hasResults"> - <!-- graphique --> - <div class="row"> - <div class="col" style="text-align: center"> - <section-canvas></section-canvas> +<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)"> + <mat-icon color="primary">image</mat-icon> + </button> + <button mat-icon-button *ngIf="! isFullscreen" (click)="setFullscreen(sectionResults)"> + <mat-icon color="primary" class="scaled12">fullscreen</mat-icon> + </button> + <button mat-icon-button *ngIf="isFullscreen" (click)="exitFullscreen()"> + <mat-icon color="primary" class="scaled12">fullscreen_exit</mat-icon> + </button> </div> - </div> - <!-- tableau de valeurs --> - <div class="row"> - <div class="col mx-auto"> - <table style="width: 100%" cellpadding="15"> - <tr vertical-result-element [result-element]=resultElement> - </tr> - </table> + <!-- graphique --> + <div class="canvas-container"> + <section-canvas></section-canvas> </div> </div> </div> diff --git a/src/app/components/section-results/section-results.component.scss b/src/app/components/section-results/section-results.component.scss new file mode 100644 index 0000000000000000000000000000000000000000..15dd1020226e493cef9354441e3ce9cdbe22b480 --- /dev/null +++ b/src/app/components/section-results/section-results.component.scss @@ -0,0 +1,28 @@ +.section-results-container{ + display: block; + background-color: white; +} + +.section-results-buttons { + padding-right: 10px; + padding-top: 4px; + margin-bottom: -30px; + text-align: right; + background-color: white; + + button { + margin-left: 3px; + width: auto; + + mat-icon { + &.scaled12 { + transform: scale(1.2); + } + } + } +} + +.canvas-container { + // border: dashed red 2px; + text-align: center; +} diff --git a/src/app/components/section-results/section-results.component.ts b/src/app/components/section-results/section-results.component.ts index 83ad69517fa2676d6d94324a98e2b4b52f89042f..34248eae2ec6dd6791f074dfb6a5397add5867df 100644 --- a/src/app/components/section-results/section-results.component.ts +++ b/src/app/components/section-results/section-results.component.ts @@ -6,55 +6,40 @@ import { SectionCanvasComponent } from "../section-canvas/section-canvas.compone import { SectionResults } from "../../results/section-results"; import { ApplicationSetupService } from "../../services/app-setup/app-setup.service"; import { CalculatorResults } from "../../results/calculator-results"; -import { I18nService } from "../../services/internationalisation/internationalisation.service"; +import { FixedResults } from "../../results/fixed-results"; @Component({ selector: "section-results", templateUrl: "./section-results.component.html", - styles: [` - .result_label { - text-align: right; - padding-top:10px; - padding-bottom:10px; - padding-right:10px; - } - .result_value { - text-align: center; - padding-left:30px; - padding-right:30px; - } - .result_id_0 { - background-color: #f0f0f0; - } - .result_id_2 { - font-weight: bold; - } - `] + styleUrls: [ + "./section-results.component.scss" + ] }) export class SectionResultsComponent implements DoCheck { - constructor(private appSetupService: ApplicationSetupService, private intlService: I18nService) { } + constructor( + private appSetupService: ApplicationSetupService + ) { } public set results(rs: CalculatorResults[]) { this._resultElement = undefined; - this._results = undefined; if (rs) { for (const r of rs) { if (r instanceof SectionResults) { this._results = r; - break; } } } 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; } - private get resultElement() { + public get resultElement() { return this._resultElement; } @@ -67,9 +52,8 @@ export class SectionResultsComponent implements DoCheck { "Yc": { r: 255, g: 128, b: 0 }, "Yco": { r: 255, g: 0, b: 255 }, }; - /** - * résultats non mis en forme - */ + + /** résultats non mis en forme */ private _results: SectionResults; /** @@ -82,6 +66,11 @@ export class SectionResultsComponent implements DoCheck { @ViewChild(SectionCanvasComponent) private _sectionCanvas: SectionCanvasComponent; + /** tracks the fullscreen state */ + public get isFullscreen() { + return (document["fullscreenElement"] !== null); + } + public updateView() { if (this._sectionCanvas) { this._sectionCanvas.reset(); @@ -137,4 +126,19 @@ export class SectionResultsComponent implements DoCheck { // tslint:disable-next-line:no-bitwise return "result_id_" + String(i & 1); } + + public setFullscreen(element) { + element.requestFullscreen(); + } + + public exitFullscreen() { + document.exitFullscreen(); + } + + public exportAsImage(element: HTMLDivElement) { + const canvas: HTMLCanvasElement = element.querySelector("canvas"); + canvas.toBlob((blob) => { + saveAs(blob, "chart.png"); + }); // defaults to image/png + } } diff --git a/src/app/formulaire/definition/concrete/form-section-parametree.ts b/src/app/formulaire/definition/concrete/form-section-parametree.ts index e5d22bcf919c95bb75d229c64fe0da09be0dd916..651ec045358362be6e6a3efbd4e21b7a2b5a1c13 100644 --- a/src/app/formulaire/definition/concrete/form-section-parametree.ts +++ b/src/app/formulaire/definition/concrete/form-section-parametree.ts @@ -1,16 +1,12 @@ -import { CalculatorType, acSection, ParamsEquation, ComputeNodeType, IObservable } from "jalhyd"; +import { IObservable } from "jalhyd"; import { FormResultSection } from "../form-result-section"; import { FormDefSection } from "../form-def-section"; -import { NgParameter } from "../../ngparam"; -import { InputField } from "../../input-field"; import { FormComputeSectionParametree } from "../form-compute-section-parametree"; import { FormulaireDefinition } from "../form-definition"; -import { I18nService } from "../../../services/internationalisation/internationalisation.service"; import { CalculatorResults } from "../../../results/calculator-results"; import { FormDefFixedVar } from "../form-def-fixedvar"; import { FieldSet } from "../../fieldset"; -import { SelectField } from "../../select-field"; export class FormulaireSectionParametree extends FormulaireDefinition { private _formFixedVar: FormDefFixedVar; diff --git a/src/app/formulaire/definition/form-compute-section-parametree.ts b/src/app/formulaire/definition/form-compute-section-parametree.ts index 5466762f0bad187cbcb20606afcf09461853ac23..ab2c327b54088ca42c14fb962d9590b6a6886923 100644 --- a/src/app/formulaire/definition/form-compute-section-parametree.ts +++ b/src/app/formulaire/definition/form-compute-section-parametree.ts @@ -1,4 +1,4 @@ -import { SectionParametree, acSection } from "jalhyd"; +import { SectionParametree, acSection, Result } from "jalhyd"; import { FormCompute } from "./form-compute"; import { NgParameter } from "../ngparam"; @@ -80,9 +80,16 @@ export class FormComputeSectionParametree extends FormCompute { this._sectionResults.section = sect; const computePrec: number = this._formBase.getParameterValue("Pr"); // précision de calcul - this._sectionResults.result = sectNub.CalcSerie(computePrec, + const tmpResult: Result = sectNub.CalcSerie(computePrec, undefined, // valeur initiale, non utilisée dans ce cas undefined // variable à calculer, non utilisée ); + + // résultats de section (avec le graphique de section) + this._sectionResults.result = tmpResult; + + // résultats complémentaires des paramètres fixés + this._formSectionResult.addSectionFixedParameters(false); + this._formSectionResult.fixedResults.result = tmpResult; } } diff --git a/src/app/results/section-results.ts b/src/app/results/section-results.ts index ee05b29435cdac3b9d928d6dd58a4770f52a3fa3..c2ab16e7f3650263f18a95015d8327f878adbecc 100644 --- a/src/app/results/section-results.ts +++ b/src/app/results/section-results.ts @@ -1,7 +1,6 @@ -import { acSection, Result, ResultElement } from "jalhyd"; +import { acSection, Result } from "jalhyd"; import { CalculatorResults } from "./calculator-results"; -import { NgParameter } from "../formulaire/ngparam"; export class SectionResults extends CalculatorResults { private _result: Result; diff --git a/src/assets/icons/file-excel-box.svg b/src/assets/icons/file-excel-box.svg new file mode 100644 index 0000000000000000000000000000000000000000..f0be5069bf8d7c2cf0b39456b0c5ee8dccb5c525 --- /dev/null +++ b/src/assets/icons/file-excel-box.svg @@ -0,0 +1 @@ +<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="24" height="24" viewBox="0 0 24 24"><path d="M16.2,17H14.2L12,13.2L9.8,17H7.8L11,12L7.8,7H9.8L12,10.8L14.2,7H16.2L13,12M19,3H5C3.89,3 3,3.89 3,5V19A2,2 0 0,0 5,21H19A2,2 0 0,0 21,19V5C21,3.89 20.1,3 19,3Z" /></svg> \ No newline at end of file diff --git a/src/assets/icons/file-excel.svg b/src/assets/icons/file-excel.svg new file mode 100644 index 0000000000000000000000000000000000000000..77acecd831d1b6a18f1b6c8c8d2f7b473b3a6106 --- /dev/null +++ b/src/assets/icons/file-excel.svg @@ -0,0 +1 @@ +<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="24" height="24" viewBox="0 0 24 24"><path d="M6,2H14L20,8V20A2,2 0 0,1 18,22H6A2,2 0 0,1 4,20V4A2,2 0 0,1 6,2M13,3.5V9H18.5L13,3.5M17,11H13V13H14L12,14.67L10,13H11V11H7V13H8L11,15.5L8,18H7V20H11V18H10L12,16.33L14,18H13V20H17V18H16L13,15.5L16,13H17V11Z" /></svg> \ No newline at end of file