From dcf4864eb2f7f69854d457cb3dd21b0aa868482f Mon Sep 17 00:00:00 2001 From: Jose Ignacio Recuerda Cambil Date: Thu, 27 Dec 2018 17:16:14 +0100 Subject: [PATCH] TSK-738 - Add timeZone conversion to Taskana UI and Rest API --- web/package-lock.json | 275 +++++++++++------- web/package.json | 2 +- .../administration/administration.module.ts | 4 +- .../restConnector/rest-connector.service.ts | 9 + .../date-picker/date-picker.component.html | 12 + .../date-picker/date-picker.component.scss | 18 ++ .../date-picker/date-picker.component.spec.ts | 55 ++++ .../date-picker/date-picker.component.ts | 26 ++ .../general-message-modal.component.scss | 2 +- .../master-and-detail.component.ts | 5 +- web/src/app/shared/shared.module.ts | 5 +- web/src/app/shared/util/taskana.date.ts | 10 +- .../app/workplace/services/task.service.ts | 30 +- .../app/workplace/task/task.component.html | 2 +- .../general/general-fields.component.html | 46 +-- .../general/general-fields.component.ts | 8 +- web/src/assets/_bootstrap.scss | 2 + web/src/assets/_date-picker.scss | 15 + web/src/assets/_main.scss | 8 +- web/src/assets/_ngxbootstrap.scss | 1 + web/src/assets/_variables.scss | 4 +- 21 files changed, 395 insertions(+), 144 deletions(-) create mode 100644 web/src/app/shared/date-picker/date-picker.component.html create mode 100644 web/src/app/shared/date-picker/date-picker.component.scss create mode 100644 web/src/app/shared/date-picker/date-picker.component.spec.ts create mode 100644 web/src/app/shared/date-picker/date-picker.component.ts create mode 100644 web/src/assets/_bootstrap.scss create mode 100644 web/src/assets/_date-picker.scss create mode 100644 web/src/assets/_ngxbootstrap.scss diff --git a/web/package-lock.json b/web/package-lock.json index 34d53e35d..e85fb478e 100644 --- a/web/package-lock.json +++ b/web/package-lock.json @@ -640,14 +640,12 @@ "balanced-match": { "version": "1.0.0", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "brace-expansion": { "version": "1.1.11", "bundled": true, "dev": true, - "optional": true, "requires": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" @@ -662,20 +660,17 @@ "code-point-at": { "version": "1.1.0", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "concat-map": { "version": "0.0.1", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "console-control-strings": { "version": "1.1.0", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "core-util-is": { "version": "1.0.2", @@ -792,8 +787,7 @@ "inherits": { "version": "2.0.3", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "ini": { "version": "1.3.5", @@ -805,7 +799,6 @@ "version": "1.0.0", "bundled": true, "dev": true, - "optional": true, "requires": { "number-is-nan": "^1.0.0" } @@ -820,7 +813,6 @@ "version": "3.0.4", "bundled": true, "dev": true, - "optional": true, "requires": { "brace-expansion": "^1.1.7" } @@ -828,14 +820,12 @@ "minimist": { "version": "0.0.8", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "minipass": { "version": "2.2.4", "bundled": true, "dev": true, - "optional": true, "requires": { "safe-buffer": "^5.1.1", "yallist": "^3.0.0" @@ -854,7 +844,6 @@ "version": "0.5.1", "bundled": true, "dev": true, - "optional": true, "requires": { "minimist": "0.0.8" } @@ -935,8 +924,7 @@ "number-is-nan": { "version": "1.0.1", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "object-assign": { "version": "4.1.1", @@ -948,7 +936,6 @@ "version": "1.4.0", "bundled": true, "dev": true, - "optional": true, "requires": { "wrappy": "1" } @@ -1070,7 +1057,6 @@ "version": "1.0.2", "bundled": true, "dev": true, - "optional": true, "requires": { "code-point-at": "^1.0.0", "is-fullwidth-code-point": "^1.0.0", @@ -2112,9 +2098,9 @@ } }, "ajv-errors": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/ajv-errors/-/ajv-errors-1.0.0.tgz", - "integrity": "sha1-7PAh+hCP0X37Xms4Py3SM+Mf/Fk=", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/ajv-errors/-/ajv-errors-1.0.1.tgz", + "integrity": "sha512-DCRfO/4nQ+89p/RK43i8Ezd41EqdGIU4ld7nGF8OQ14oc/we5rEntLCUa7+jrn3nn83BosfwZA0wb4pon2o8iQ==", "dev": true }, "ajv-keywords": { @@ -2165,9 +2151,9 @@ } }, "ansi-colors": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-3.2.1.tgz", - "integrity": "sha512-Xt+zb6nqgvV9SWAVp0EG3lRsHcbq5DDgqjPPz6pwgtj6RKz65zGXMNa82oJfOSBA/to6GmRP7Dr+6o+kbApTzQ==", + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-3.2.3.tgz", + "integrity": "sha512-LEHHyuhlPY3TmuUYMh2oz89lTShfvgbmzaBcxve9t/9Wuy7Dwf4yoAKcND7KFT1HAQfqZ12qtc+DUrBMeKF9nw==", "dev": true }, "ansi-escapes": { @@ -2257,9 +2243,9 @@ "integrity": "sha1-3wEKoSh+Fku9pvlyOwqWoexBh6E=" }, "array-flatten": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-2.1.1.tgz", - "integrity": "sha1-Qmu52oQJDBg42BLIFQryCoMx4pY=", + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-2.1.2.tgz", + "integrity": "sha512-hNfzcOV8W4NdualtqBFPyVO+54DSJuZGY9qT4pRroB6S9e3iiido2ISIC5h9R2sPJ8H3FHCIiEnsv1lPXO3KtQ==", "dev": true }, "array-slice": { @@ -3465,9 +3451,9 @@ } }, "connect-history-api-fallback": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/connect-history-api-fallback/-/connect-history-api-fallback-1.5.0.tgz", - "integrity": "sha1-sGhzk0vF40T+9hGhlqb6rgruAVo=", + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/connect-history-api-fallback/-/connect-history-api-fallback-1.6.0.tgz", + "integrity": "sha512-e54B99q/OUoH64zYYRf3HBP5z24G38h5D3qXu23JGRoigpX5Ss4r9ZnDk3g0Z8uQC2x2lPaJ+UlWBc1ZWBWdLg==", "dev": true }, "console-browserify": { @@ -5035,8 +5021,7 @@ "ansi-regex": { "version": "2.1.1", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "aproba": { "version": "1.2.0", @@ -5057,14 +5042,12 @@ "balanced-match": { "version": "1.0.0", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "brace-expansion": { "version": "1.1.11", "bundled": true, "dev": true, - "optional": true, "requires": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" @@ -5079,20 +5062,17 @@ "code-point-at": { "version": "1.1.0", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "concat-map": { "version": "0.0.1", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "console-control-strings": { "version": "1.1.0", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "core-util-is": { "version": "1.0.2", @@ -5209,8 +5189,7 @@ "inherits": { "version": "2.0.3", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "ini": { "version": "1.3.5", @@ -5222,7 +5201,6 @@ "version": "1.0.0", "bundled": true, "dev": true, - "optional": true, "requires": { "number-is-nan": "^1.0.0" } @@ -5237,7 +5215,6 @@ "version": "3.0.4", "bundled": true, "dev": true, - "optional": true, "requires": { "brace-expansion": "^1.1.7" } @@ -5245,14 +5222,12 @@ "minimist": { "version": "0.0.8", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "minipass": { "version": "2.2.4", "bundled": true, "dev": true, - "optional": true, "requires": { "safe-buffer": "^5.1.1", "yallist": "^3.0.0" @@ -5271,7 +5246,6 @@ "version": "0.5.1", "bundled": true, "dev": true, - "optional": true, "requires": { "minimist": "0.0.8" } @@ -5352,8 +5326,7 @@ "number-is-nan": { "version": "1.0.1", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "object-assign": { "version": "4.1.1", @@ -5365,7 +5338,6 @@ "version": "1.4.0", "bundled": true, "dev": true, - "optional": true, "requires": { "wrappy": "1" } @@ -5487,7 +5459,6 @@ "version": "1.0.2", "bundled": true, "dev": true, - "optional": true, "requires": { "code-point-at": "^1.0.0", "is-fullwidth-code-point": "^1.0.0", @@ -5507,7 +5478,6 @@ "version": "3.0.1", "bundled": true, "dev": true, - "optional": true, "requires": { "ansi-regex": "^2.0.0" } @@ -5713,9 +5683,9 @@ "integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=" }, "handle-thing": { - "version": "1.2.5", - "resolved": "https://registry.npmjs.org/handle-thing/-/handle-thing-1.2.5.tgz", - "integrity": "sha1-/Xqtcmvxpf0W38KbL3pmAdJxOcQ=", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/handle-thing/-/handle-thing-2.0.0.tgz", + "integrity": "sha512-d4sze1JNC454Wdo2fkuyzCr6aHcbL6PGGuFAz0Li/NcOm1tCHGnWDRmJP85dh9IhQErTc2svWFEX5xHIOo//kQ==", "dev": true }, "handlebars": { @@ -6548,9 +6518,9 @@ } }, "p-limit": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.0.0.tgz", - "integrity": "sha512-fl5s52lI5ahKCernzzIyAP0QAZbGIovtVHGwpcu1Jr/EpzLVDI2myISHwGqK7m8uQFugVWSrbxH7XnhGtvEc+A==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.1.0.tgz", + "integrity": "sha512-NhURkNcrVB+8hNfLuysU8enY5xn2KXphsHBaC2YmRNTZRc7RWusw6apSpdEj3jo4CMb6W9nrF6tTnsJsJeyu6g==", "dev": true, "requires": { "p-try": "^2.0.0" @@ -8852,9 +8822,9 @@ "dev": true }, "ngx-bootstrap": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/ngx-bootstrap/-/ngx-bootstrap-3.0.1.tgz", - "integrity": "sha512-ni91yYtn8ldgf/pxrlwl9lkVcLURGzopSpJnEbbgG1v1EZWTobI8y7J3mx4Kxptkn0EeiQwnLel67G7XJSox4A==" + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/ngx-bootstrap/-/ngx-bootstrap-3.2.0.tgz", + "integrity": "sha512-oLSLIWZgRiIfcuxyXLMZUOhX3wZtg6lpuMbdo/0UzMDg2bSOe1XPskcKZ/iuOa3FOlU9rjuYMzswHYYV5f/QCA==" }, "ngx-infinite-scroll": { "version": "6.0.1", @@ -11268,32 +11238,84 @@ "integrity": "sha1-yd96NCRZSt5r0RkA1ZZpbcBrrFc=" }, "spdy": { - "version": "3.4.7", - "resolved": "https://registry.npmjs.org/spdy/-/spdy-3.4.7.tgz", - "integrity": "sha1-Qv9B7OXMD5mjpsKKq7c/XDsDrLw=", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/spdy/-/spdy-4.0.0.tgz", + "integrity": "sha512-ot0oEGT/PGUpzf/6uk4AWLqkq+irlqHXkrdbk51oWONh3bxQmBuljxPNl66zlRRcIJStWq0QkLUCPOPjgjvU0Q==", "dev": true, "requires": { - "debug": "^2.6.8", - "handle-thing": "^1.2.5", + "debug": "^4.1.0", + "handle-thing": "^2.0.0", "http-deceiver": "^1.2.7", - "safe-buffer": "^5.0.1", "select-hose": "^2.0.0", - "spdy-transport": "^2.0.18" + "spdy-transport": "^3.0.0" + }, + "dependencies": { + "debug": { + "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" + } + }, + "ms": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", + "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==", + "dev": true + } } }, "spdy-transport": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/spdy-transport/-/spdy-transport-2.1.1.tgz", - "integrity": "sha512-q7D8c148escoB3Z7ySCASadkegMmUZW8Wb/Q1u0/XBgDKMO880rLQDj8Twiew/tYi7ghemKUi/whSYOwE17f5Q==", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/spdy-transport/-/spdy-transport-3.0.0.tgz", + "integrity": "sha512-hsLVFE5SjA6TCisWeJXFKniGGOpBgMLmerfO2aCyCU5s7nJ/rpAepqmFifv/GCbSbueEeAJJnmSQ2rKC/g8Fcw==", "dev": true, "requires": { - "debug": "^2.6.8", - "detect-node": "^2.0.3", + "debug": "^4.1.0", + "detect-node": "^2.0.4", "hpack.js": "^2.1.6", - "obuf": "^1.1.1", - "readable-stream": "^2.2.9", - "safe-buffer": "^5.0.1", - "wbuf": "^1.7.2" + "obuf": "^1.1.2", + "readable-stream": "^3.0.6", + "wbuf": "^1.7.3" + }, + "dependencies": { + "debug": { + "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" + } + }, + "ms": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", + "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==", + "dev": true + }, + "readable-stream": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.1.1.tgz", + "integrity": "sha512-DkN66hPyqDhnIQ6Jcsvx9bFjhw214O4poMBcIMgPVpQvNy9a0e0Uhg5SqySyDKAmUlwt8LonTBz1ezOnM8pUdA==", + "dev": true, + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + }, + "string_decoder": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.2.0.tgz", + "integrity": "sha512-6YqyX6ZWEYguAxgZzHGL7SsCeGx3V2TtOTqZz1xSTSWnqsbWwbptafNyvf/ACquZUXV3DANr5BDIwNYe1mN42w==", + "dev": true, + "requires": { + "safe-buffer": "~5.1.0" + } + } } }, "split-string": { @@ -12680,8 +12702,7 @@ "balanced-match": { "version": "1.0.0", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "brace-expansion": { "version": "1.1.11", @@ -12706,8 +12727,7 @@ "concat-map": { "version": "0.0.1", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "console-control-strings": { "version": "1.1.0", @@ -13716,9 +13736,9 @@ } }, "webpack-dev-server": { - "version": "3.1.10", - "resolved": "https://registry.npmjs.org/webpack-dev-server/-/webpack-dev-server-3.1.10.tgz", - "integrity": "sha512-RqOAVjfqZJtQcB0LmrzJ5y4Jp78lv9CK0MZ1YJDTaTmedMZ9PU9FLMQNrMCfVu8hHzaVLVOJKBlGEHMN10z+ww==", + "version": "3.1.14", + "resolved": "https://registry.npmjs.org/webpack-dev-server/-/webpack-dev-server-3.1.14.tgz", + "integrity": "sha512-mGXDgz5SlTxcF3hUpfC8hrQ11yhAttuUQWf1Wmb+6zo3x6rb7b9mIfuQvAPLdfDRCGRGvakBWHdHOa0I9p/EVQ==", "dev": true, "requires": { "ansi-html": "0.0.7", @@ -13740,12 +13760,14 @@ "portfinder": "^1.0.9", "schema-utils": "^1.0.0", "selfsigned": "^1.9.1", + "semver": "^5.6.0", "serve-index": "^1.7.2", "sockjs": "0.3.19", "sockjs-client": "1.3.0", - "spdy": "^3.4.1", + "spdy": "^4.0.0", "strip-ansi": "^3.0.0", "supports-color": "^5.1.0", + "url": "^0.11.0", "webpack-dev-middleware": "3.4.0", "webpack-log": "^2.0.0", "yargs": "12.0.2" @@ -13857,6 +13879,19 @@ } } }, + "cross-spawn": { + "version": "6.0.5", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz", + "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==", + "dev": true, + "requires": { + "nice-try": "^1.0.4", + "path-key": "^2.0.1", + "semver": "^5.5.0", + "shebang-command": "^1.2.0", + "which": "^1.2.9" + } + }, "debug": { "version": "3.2.6", "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", @@ -13883,6 +13918,21 @@ "xregexp": "4.0.0" } }, + "execa": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/execa/-/execa-1.0.0.tgz", + "integrity": "sha512-adbxcyWV46qiHyvSp50TKt05tB4tK3HcmF7/nxfAdhnox83seTDbwnaqKO4sXRy7roHAIFqJP/Rw/AuEbX61LA==", + "dev": true, + "requires": { + "cross-spawn": "^6.0.0", + "get-stream": "^4.0.0", + "is-stream": "^1.1.0", + "npm-run-path": "^2.0.0", + "p-finally": "^1.0.0", + "signal-exit": "^3.0.0", + "strip-eof": "^1.0.0" + } + }, "expand-brackets": { "version": "2.1.4", "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz", @@ -14052,6 +14102,15 @@ "locate-path": "^3.0.0" } }, + "get-stream": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz", + "integrity": "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==", + "dev": true, + "requires": { + "pump": "^3.0.0" + } + }, "glob-parent": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz", @@ -14208,26 +14267,26 @@ } }, "mime": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/mime/-/mime-2.3.1.tgz", - "integrity": "sha512-OEUllcVoydBHGN1z84yfQDimn58pZNNNXgZlHXSboxMlFvgI6MXSWpWKpFRra7H1HxpVhHTkrghfRW49k6yjeg==", + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-2.4.0.tgz", + "integrity": "sha512-ikBcWwyqXQSHKtciCcctu9YfPbFYZ4+gbHEmE0Q8jzcTYQg5dHCr3g2wwAZjPoJfQVXZq6KXAjpXOTf5/cjT7w==", "dev": true }, "os-locale": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-3.0.1.tgz", - "integrity": "sha512-7g5e7dmXPtzcP4bgsZ8ixDVqA7oWYuEz4lOSujeWyliPai4gfVDiFIcwBg3aGCPnmSGfzOKTK3ccPn0CKv3DBw==", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-3.1.0.tgz", + "integrity": "sha512-Z8l3R4wYWM40/52Z+S265okfFj8Kt2cC2MKY+xNi3kFs+XGI7WXu/I309QQQYbRW4ijiZ+yxs9pqEhJh0DqW3Q==", "dev": true, "requires": { - "execa": "^0.10.0", + "execa": "^1.0.0", "lcid": "^2.0.0", "mem": "^4.0.0" } }, "p-limit": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.0.0.tgz", - "integrity": "sha512-fl5s52lI5ahKCernzzIyAP0QAZbGIovtVHGwpcu1Jr/EpzLVDI2myISHwGqK7m8uQFugVWSrbxH7XnhGtvEc+A==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.1.0.tgz", + "integrity": "sha512-NhURkNcrVB+8hNfLuysU8enY5xn2KXphsHBaC2YmRNTZRc7RWusw6apSpdEj3jo4CMb6W9nrF6tTnsJsJeyu6g==", "dev": true, "requires": { "p-try": "^2.0.0" @@ -14254,6 +14313,16 @@ "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", "dev": true }, + "pump": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", + "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", + "dev": true, + "requires": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, "schema-utils": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-1.0.0.tgz", @@ -14265,6 +14334,12 @@ "ajv-keywords": "^3.1.0" } }, + "semver": { + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.6.0.tgz", + "integrity": "sha512-RS9R6R35NYgQn++fkDWaOmqGoj4Ek9gGs+DPxNUZKuwE183xjJroKvyo1IzVFeXvUrvmALy6FWD5xrdJT25gMg==", + "dev": true + }, "string-width": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", diff --git a/web/package.json b/web/package.json index c4780f10e..0fa2202ad 100644 --- a/web/package.json +++ b/web/package.json @@ -34,7 +34,7 @@ "magic-string": "0.22.4", "material-design-icons": "3.0.1", "ng2-charts": "1.6.0", - "ngx-bootstrap": "3.0.1", + "ngx-bootstrap": "3.2.0", "ngx-infinite-scroll": "6.0.1", "node-sass": "4.9.2", "popper.js": "1.14.3", diff --git a/web/src/app/administration/administration.module.ts b/web/src/app/administration/administration.module.ts index 4cd2b5ee9..aaec09e75 100644 --- a/web/src/app/administration/administration.module.ts +++ b/web/src/app/administration/administration.module.ts @@ -6,7 +6,7 @@ import {AngularSvgIconModule} from 'angular-svg-icon'; import {AlertModule, TypeaheadModule} from 'ngx-bootstrap'; import {SharedModule} from 'app/shared/shared.module'; import {AdministrationRoutingModule} from './administration-routing.module'; -import { InfiniteScrollModule } from 'ngx-infinite-scroll'; +import {InfiniteScrollModule} from 'ngx-infinite-scroll'; /** * Components */ @@ -30,8 +30,8 @@ import {ClassificationDefinitionService} from './services/classification-definit import {WorkbasketDefinitionService} from './services/workbasket-definition/workbasket-definition.service'; import {ClassificationsService} from '../services/classifications/classifications.service'; import {ClassificationCategoriesService} from 'app/services/classifications/classification-categories.service'; -import { AccessItemsManagementComponent } from 'app/administration/access-items-management/access-items-management.component'; import { ImportExportService } from './services/import-export/import-export.service'; +import {AccessItemsManagementComponent} from 'app/administration/access-items-management/access-items-management.component'; const MODULES = [ CommonModule, diff --git a/web/src/app/monitor/services/restConnector/rest-connector.service.ts b/web/src/app/monitor/services/restConnector/rest-connector.service.ts index 1f70502ed..58b3571d6 100644 --- a/web/src/app/monitor/services/restConnector/rest-connector.service.ts +++ b/web/src/app/monitor/services/restConnector/rest-connector.service.ts @@ -4,6 +4,8 @@ import { environment } from 'environments/environment'; import { Observable } from 'rxjs'; import { ReportData } from '../../models/report-data'; import { ChartData } from 'app/monitor/models/chart-data'; +import { TaskanaDate } from 'app/shared/util/taskana.date'; +import { map } from 'rxjs/internal/operators/map'; @Injectable() export class RestConnectorService { @@ -13,6 +15,13 @@ export class RestConnectorService { getTaskStatusReport(): Observable { return this.httpClient.get(environment.taskanaRestUrl + '/v1/monitor/tasks-status-report?states=READY,CLAIMED,COMPLETED') + .pipe(map( + (response: ReportData) => { + if (response.meta.date) { + response.meta.date = TaskanaDate.applyTimeZone(response.meta.date); + } + return response; + })); } getWorkbasketStatistics(): Observable { diff --git a/web/src/app/shared/date-picker/date-picker.component.html b/web/src/app/shared/date-picker/date-picker.component.html new file mode 100644 index 000000000..f590c263b --- /dev/null +++ b/web/src/app/shared/date-picker/date-picker.component.html @@ -0,0 +1,12 @@ +
+ + date_range +
diff --git a/web/src/app/shared/date-picker/date-picker.component.scss b/web/src/app/shared/date-picker/date-picker.component.scss new file mode 100644 index 000000000..07f7a71ad --- /dev/null +++ b/web/src/app/shared/date-picker/date-picker.component.scss @@ -0,0 +1,18 @@ +.input-icon-wrap { + display: flex; + flex-direction: row; + border: 1px solid #ccc; + border-radius: 4px; + box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); + height: 35px; +} + +.input-with-icon { + border: none; + height: 33px; +} + +.input-icon span { + padding-top: 5px; + padding-right: 6px; +} diff --git a/web/src/app/shared/date-picker/date-picker.component.spec.ts b/web/src/app/shared/date-picker/date-picker.component.spec.ts new file mode 100644 index 000000000..7a1d5d34d --- /dev/null +++ b/web/src/app/shared/date-picker/date-picker.component.spec.ts @@ -0,0 +1,55 @@ +import { async, ComponentFixture, TestBed } from '@angular/core/testing'; + +import { DatePickerComponent } from './date-picker.component'; +import { BsDatepickerModule, BsDatepickerConfig, ComponentLoaderFactory, PositioningService, BsLocaleService } from 'ngx-bootstrap'; + +describe('DatePickerComponent', () => { + let component: DatePickerComponent; + let fixture: ComponentFixture; + + beforeEach(async(() => { + TestBed.configureTestingModule({ + imports: [BsDatepickerModule], + declarations: [DatePickerComponent], + providers: [BsDatepickerConfig, ComponentLoaderFactory, PositioningService, + BsLocaleService] + }) + .compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(DatePickerComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); + + it('should receive the input properties', () => { + component.placeholder = 'placeholder'; + component.value = '01/01/2019'; + component.id = 'id'; + component.name = 'name'; + expect(component.placeholder).toBe('placeholder'); + expect(component.value).toBe('01/01/2019'); + expect(component.id).toBe('id'); + expect(component.name).toBe('name'); + }); + + it('should all properties have a value', () => { + component.placeholder = 'test'; + component.value = '01/01/2019'; + component.id = 'id'; + component.name = 'name'; + expect(component.placeholder).not.toBeNull(''); + expect(component.placeholder).not.toBeNaN(); + expect(component.value).not.toBeNull(''); + expect(component.value).not.toBeNaN(); + expect(component.id).not.toBeNull(''); + expect(component.id).not.toBeNaN(); + expect(component.name).not.toBeNull(''); + expect(component.name).not.toBeNaN(); + }); +}); diff --git a/web/src/app/shared/date-picker/date-picker.component.ts b/web/src/app/shared/date-picker/date-picker.component.ts new file mode 100644 index 000000000..1cfed4d8a --- /dev/null +++ b/web/src/app/shared/date-picker/date-picker.component.ts @@ -0,0 +1,26 @@ +import { Component, Input, Output, EventEmitter, OnInit } from '@angular/core'; + +@Component({ + selector: 'taskana-date-picker', + templateUrl: './date-picker.component.html', + styleUrls: ['./date-picker.component.scss'] +}) +export class DatePickerComponent implements OnInit { + @Input() placeholder: string; + @Input() value: string; + @Input() id: string; + @Input() name: string; + @Output() dateOutput = new EventEmitter(); + + valueDate: Date; + + ngOnInit(): void { + this.valueDate = new Date(this.value); + } + + dateChange(newValue: Date) { + if (newValue) { + this.dateOutput.emit(newValue.toISOString()); + } + } +} diff --git a/web/src/app/shared/general-message-modal/general-message-modal.component.scss b/web/src/app/shared/general-message-modal/general-message-modal.component.scss index 3a296c0d1..48b8b5d34 100644 --- a/web/src/app/shared/general-message-modal/general-message-modal.component.scss +++ b/web/src/app/shared/general-message-modal/general-message-modal.component.scss @@ -1,4 +1,4 @@ .word-break{word-break: break-word; } .modal{ z-index: 1051; -} \ No newline at end of file +} diff --git a/web/src/app/shared/master-and-detail/master-and-detail.component.ts b/web/src/app/shared/master-and-detail/master-and-detail.component.ts index abf511f4f..41fb86a75 100644 --- a/web/src/app/shared/master-and-detail/master-and-detail.component.ts +++ b/web/src/app/shared/master-and-detail/master-and-detail.component.ts @@ -1,5 +1,5 @@ -import { Component, OnInit, OnDestroy } from '@angular/core'; -import { Router, Routes, ActivatedRoute, NavigationStart, RouterEvent } from '@angular/router'; +import { Component, OnInit } from '@angular/core'; +import { Router, ActivatedRoute, NavigationStart, RouterEvent } from '@angular/router'; import { MasterAndDetailService } from 'app/services/masterAndDetail/master-and-detail.service' @Component({ @@ -13,7 +13,6 @@ export class MasterAndDetailComponent implements OnInit { private workbaskets = 'workbaskets'; private tasks = 'tasks'; private detailRoutes: Array = ['/workbaskets/(detail', 'classifications/(detail', 'tasks/(detail']; - private sub: any; showDetail = false; currentRoute = ''; diff --git a/web/src/app/shared/shared.module.ts b/web/src/app/shared/shared.module.ts index bac156a4c..f280a5ca9 100644 --- a/web/src/app/shared/shared.module.ts +++ b/web/src/app/shared/shared.module.ts @@ -5,7 +5,7 @@ import { HttpClientModule, HTTP_INTERCEPTORS } from '@angular/common/http'; import { AngularSvgIconModule } from 'angular-svg-icon'; import { RouterModule } from '@angular/router'; import { TreeModule } from 'angular-tree-component'; -import { AlertModule, TypeaheadModule } from 'ngx-bootstrap'; +import { AlertModule, TypeaheadModule, BsDatepickerModule } from 'ngx-bootstrap'; import { AccordionModule } from 'ngx-bootstrap/accordion'; /** @@ -24,6 +24,7 @@ import { IconTypeComponent } from 'app/administration/components/type-icon/icon- import { FieldErrorDisplayComponent } from 'app/shared/field-error-display/field-error-display.component'; import { PaginationComponent } from './pagination/pagination.component'; import { ProgressBarComponent } from './progress-bar/progress-bar.component'; +import { DatePickerComponent } from './date-picker/date-picker.component'; /** * Pipes @@ -48,6 +49,7 @@ const MODULES = [ AlertModule.forRoot(), TypeaheadModule.forRoot(), AccordionModule.forRoot(), + BsDatepickerModule.forRoot(), AngularSvgIconModule, HttpClientModule, RouterModule, @@ -75,6 +77,7 @@ const DECLARATIONS = [ FieldErrorDisplayComponent, PaginationComponent, ProgressBarComponent, + DatePickerComponent ]; @NgModule({ diff --git a/web/src/app/shared/util/taskana.date.ts b/web/src/app/shared/util/taskana.date.ts index 832f1f057..46b2b1377 100644 --- a/web/src/app/shared/util/taskana.date.ts +++ b/web/src/app/shared/util/taskana.date.ts @@ -17,14 +17,14 @@ export class TaskanaDate { } public static getDateToDisplay(date: string): string { + return this.applyTimeZone(date); + } + + public static applyTimeZone(date: string): string | null { const dateFormat = 'yyyy-MM-dd HH:mm:ss'; const dateLocale = 'en-US'; const datePipe = new DatePipe(dateLocale); - return datePipe.transform(date, dateFormat); - } - - public static convertToBrowserTimeZone(date: Date): string { - return date.toLocaleString('en-US', { timeZone: Intl.DateTimeFormat().resolvedOptions().timeZone }) + return datePipe.transform(date, dateFormat, Intl.DateTimeFormat().resolvedOptions().timeZone); } } diff --git a/web/src/app/workplace/services/task.service.ts b/web/src/app/workplace/services/task.service.ts index a451a0069..b2c015697 100644 --- a/web/src/app/workplace/services/task.service.ts +++ b/web/src/app/workplace/services/task.service.ts @@ -6,6 +6,8 @@ import {environment} from 'environments/environment'; import {TaskResource} from 'app/workplace/models/task-resource'; import {Direction} from 'app/models/sorting'; import { TaskanaQueryParameters } from 'app/shared/util/query-parameters'; +import { TaskanaDate } from 'app/shared/util/taskana.date'; +import { map } from 'rxjs/operators'; @Injectable() export class TaskService { @@ -76,7 +78,12 @@ export class TaskService { } getTask(id: string): Observable { - return this.httpClient.get(`${this.url}/${id}`); + return this.httpClient.get(`${this.url}/${id}`) + .pipe(map( + (response: Task) => { + response = this.applyTaskDatesTimeZone(response); + return response; + })); } completeTask(id: string): Observable { @@ -92,6 +99,7 @@ export class TaskService { } updateTask(task: Task): Observable { + task = this.convertTasksDatesToGMT(task); return this.httpClient.put(`${this.url}/${task.taskId}`, task); } @@ -102,4 +110,24 @@ export class TaskService { createTask(task: Task): Observable { return this.httpClient.post(this.url, task); } + + private applyTaskDatesTimeZone(task: Task): Task { + if (task.due) { task.due = TaskanaDate.applyTimeZone(task.due); } + if (task.modified) { task.modified = TaskanaDate.applyTimeZone(task.modified); } + if (task.completed) { task.completed = TaskanaDate.applyTimeZone(task.completed); } + if (task.planned) { task.planned = TaskanaDate.applyTimeZone(task.planned); } + if (task.claimed) { task.claimed = TaskanaDate.applyTimeZone(task.claimed); } + if (task.created) { task.created = TaskanaDate.applyTimeZone(task.created); } + return task; + } + + private convertTasksDatesToGMT(task: Task): Task { + if (task.created) { task.created = new Date(task.created).toISOString(); } + if (task.claimed) { task.claimed = new Date(task.claimed).toISOString(); } + if (task.completed) { task.completed = new Date(task.completed).toISOString(); } + if (task.modified) { task.modified = new Date(task.modified).toISOString(); } + if (task.planned) { task.planned = new Date(task.planned).toISOString(); } + if (task.due) { task.due = new Date(task.due).toISOString(); } + return task; + } } diff --git a/web/src/app/workplace/task/task.component.html b/web/src/app/workplace/task/task.component.html index 8443a44b3..bbd96f16b 100644 --- a/web/src/app/workplace/task/task.component.html +++ b/web/src/app/workplace/task/task.component.html @@ -53,4 +53,4 @@ - \ No newline at end of file + diff --git a/web/src/app/workplace/taskdetails/general/general-fields.component.html b/web/src/app/workplace/taskdetails/general/general-fields.component.html index 4d1d0148b..f1b3b1c5b 100644 --- a/web/src/app/workplace/taskdetails/general/general-fields.component.html +++ b/web/src/app/workplace/taskdetails/general/general-fields.component.html @@ -73,35 +73,18 @@ -
+
+ + +
+
-
-
-
- - -
-
-
-
- - -
-
- - - - - -
+
+ + + + + +
+
+
+
+ + +
+
+
- \ No newline at end of file + diff --git a/web/src/app/workplace/taskdetails/general/general-fields.component.ts b/web/src/app/workplace/taskdetails/general/general-fields.component.ts index 04e322146..1c127e4b6 100644 --- a/web/src/app/workplace/taskdetails/general/general-fields.component.ts +++ b/web/src/app/workplace/taskdetails/general/general-fields.component.ts @@ -1,4 +1,4 @@ -import { Component, EventEmitter, Input, OnInit, Output, ViewChild, SimpleChanges, OnChanges } from '@angular/core'; +import { Component, EventEmitter, Input, OnInit, Output, ViewChild, SimpleChanges, OnChanges, HostListener } from '@angular/core'; import { Task } from 'app/workplace/models/task'; import { Classification } from '../../../models/classification'; import { ClassificationsService } from '../../../services/classifications/classifications.service'; @@ -76,4 +76,10 @@ export class TaskdetailsGeneralFieldsComponent implements OnInit, OnChanges { return this.formsValidatorService.isFieldValid(this.taskForm, field); } + updateDate($event) { + if (new Date(this.task.due).toISOString() !== $event) { + this.task.due = $event; + } + } + } diff --git a/web/src/assets/_bootstrap.scss b/web/src/assets/_bootstrap.scss new file mode 100644 index 000000000..83d1282c3 --- /dev/null +++ b/web/src/assets/_bootstrap.scss @@ -0,0 +1,2 @@ +$icon-font-path: '../../node_modules/bootstrap-sass/assets/fonts/bootstrap/'; +@import '../../node_modules/bootstrap-sass/assets/stylesheets/_bootstrap'; diff --git a/web/src/assets/_date-picker.scss b/web/src/assets/_date-picker.scss new file mode 100644 index 000000000..53e572bd7 --- /dev/null +++ b/web/src/assets/_date-picker.scss @@ -0,0 +1,15 @@ +.theme-green .bs-datepicker-head { + background-color: #246972; +} + +.theme-green .bs-datepicker-body table td span.selected, .theme-green .bs-datepicker-body table td.selected span, .theme-green .bs-datepicker-body table td span[class*="select-"]:after, .theme-green .bs-datepicker-body table td[class*="select-"] span:after { + background-color: #246972; +} + +.theme-green .bs-datepicker-body table td.week span { + color: #175263; +} + +.bs-datepicker-container { + padding: 0; +} diff --git a/web/src/assets/_main.scss b/web/src/assets/_main.scss index 291e0084e..a754901f0 100644 --- a/web/src/assets/_main.scss +++ b/web/src/assets/_main.scss @@ -1,14 +1,16 @@ +@import 'bootstrap'; +@import 'ngxbootstrap'; +@import 'bootstrap-3-backward-compatibility'; @import 'variables'; -@import '../../node_modules/bootstrap-sass/assets/stylesheets/_bootstrap'; @import '../../node_modules/angular-tree-component/dist/angular-tree-component.css'; +@import '../../node_modules/ngx-bootstrap/datepicker/bs-datepicker.scss'; @import 'material-icons'; @import 'site'; @import 'forms'; @import 'tree'; @import 'type-ahead'; +@import 'date-picker'; @import 'checkboxes'; @import 'buttons'; @import 'tabs'; -@import 'bootstrap-3-backward-compatibility'; -@import 'mixin/colors'; @import 'progress-bar'; diff --git a/web/src/assets/_ngxbootstrap.scss b/web/src/assets/_ngxbootstrap.scss new file mode 100644 index 000000000..55d83122c --- /dev/null +++ b/web/src/assets/_ngxbootstrap.scss @@ -0,0 +1 @@ +@import '../../node_modules/bootstrap-sass/assets/stylesheets/_bootstrap'; diff --git a/web/src/assets/_variables.scss b/web/src/assets/_variables.scss index 7eaf71f6c..41c6a6545 100644 --- a/web/src/assets/_variables.scss +++ b/web/src/assets/_variables.scss @@ -1,5 +1,5 @@ @import '_colors'; -$icon-font-path: '../../node_modules/bootstrap-sass/assets/fonts/bootstrap/'; +@import 'mixin/colors'; @mixin degraded-bar ($direction, $width, $height) { display: block; @@ -7,4 +7,4 @@ $icon-font-path: '../../node_modules/bootstrap-sass/assets/fonts/bootstrap/'; height: $height; background-image: linear-gradient(to $direction, $pallete-blue 30%, $pallete-green 50%); content: ' '; -} \ No newline at end of file +}