From bced4a86cef27a36dc6ed65e17d77c109cef1fa8 Mon Sep 17 00:00:00 2001 From: Jan Hajek Date: Mon, 29 Jun 2026 10:46:05 +0200 Subject: [PATCH] feat: enhance Duration component to support customizable hours per day --- package-lock.json | 278 +++++++++++++++++++++----- src/components/Duration/Duration.tsx | 15 +- src/components/Duration/interfaces.ts | 1 + 3 files changed, 235 insertions(+), 59 deletions(-) diff --git a/package-lock.json b/package-lock.json index e96e0fcd..d587b384 100644 --- a/package-lock.json +++ b/package-lock.json @@ -83,60 +83,6 @@ "react-dom": "^16.8.6 || ^17.0.2" } }, - "../../../../../åUsers/dominikbrych/Desktop/NETWORG/INT0014/src/SDK/ClientLibraries": { - "extraneous": true - }, - "../alpha/INT0014/src/SDK/ClientLibraries": { - "name": "@talxis/client-libraries", - "version": "0.0.1", - "extraneous": true, - "license": "MIT", - "dependencies": { - "@azure/msal-browser": "^2.27.0", - "@microsoft/microsoft-graph-client": "^2.2.1", - "async-retry": "^1.3.3", - "dayjs": "^1.11.13", - "debounce": "^2.2.0", - "deep-eql": "^5.0.2", - "exceljs": "^4.3.0", - "fast-sort": "^3.4.1", - "humanize-duration": "^3.32.1", - "liquidjs": "^9.25.1", - "numeral": "^2.0.6", - "validator": "^13.12.0" - }, - "devDependencies": { - "@microsoft/eslint-plugin-power-apps": "^0.2.6", - "@microsoft/microsoft-graph-types": "^1.13.0", - "@rollup/plugin-commonjs": "^21.0.2", - "@rollup/plugin-json": "^6.1.0", - "@rollup/plugin-node-resolve": "^13.1.3", - "@rollup/plugin-typescript": "^8.3.1", - "@types/async-retry": "^1.4.8", - "@types/deep-eql": "^4.0.2", - "@types/humanize-duration": "^3.27.4", - "@types/node": "^20.11.17", - "@types/numeral": "^2.0.5", - "@types/powerapps-component-framework": "^1.3.15", - "@types/validator": "^13.12.2", - "@types/xrm": "^9.0.81", - "@typescript-eslint/eslint-plugin": "^5.36.1", - "@typescript-eslint/parser": "^5.36.1", - "eslint": "^8.23.0", - "glob": "^11.0.0", - "rollup": "^2.70.0", - "rollup-plugin-delete": "^2.0.0", - "rollup-plugin-dts": "^4.2.0", - "rollup-plugin-multi-input": "^1.3.1", - "rollup-plugin-peer-deps-external": "^2.2.4", - "rollup-plugin-postcss": "^4.0.2", - "rollup-plugin-terser": "^7.0.2", - "rollup-plugin-visualizer": "^5.12.0", - "typedoc": "^0.26.9", - "typedoc-plugin-markdown": "^4.2.9", - "typescript": "^4.6.2" - } - }, "../INT0015/common/temp/node_modules/.pnpm/react-dom@17.0.2_react@17.0.2/node_modules/react-dom": { "version": "17.0.2", "license": "MIT", @@ -4678,6 +4624,34 @@ "esbuild-windows-arm64": "0.13.15" } }, + "node_modules/esbuild-android-arm64": { + "version": "0.13.15", + "resolved": "https://registry.npmjs.org/esbuild-android-arm64/-/esbuild-android-arm64-0.13.15.tgz", + "integrity": "sha512-m602nft/XXeO8YQPUDVoHfjyRVPdPgjyyXOxZ44MK/agewFFkPa8tUo6lAzSWh5Ui5PB4KR9UIFTSBKh/RrCmg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/esbuild-darwin-64": { + "version": "0.13.15", + "resolved": "https://registry.npmjs.org/esbuild-darwin-64/-/esbuild-darwin-64-0.13.15.tgz", + "integrity": "sha512-ihOQRGs2yyp7t5bArCwnvn2Atr6X4axqPpEdCFPVp7iUj4cVSdisgvEKdNR7yH3JDjW6aQDw40iQFoTqejqxvQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, "node_modules/esbuild-darwin-arm64": { "version": "0.13.15", "cpu": [ @@ -4690,6 +4664,202 @@ "darwin" ] }, + "node_modules/esbuild-freebsd-64": { + "version": "0.13.15", + "resolved": "https://registry.npmjs.org/esbuild-freebsd-64/-/esbuild-freebsd-64-0.13.15.tgz", + "integrity": "sha512-G3dLBXUI6lC6Z09/x+WtXBXbOYQZ0E8TDBqvn7aMaOCzryJs8LyVXKY4CPnHFXZAbSwkCbqiPuSQ1+HhrNk7EA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ] + }, + "node_modules/esbuild-freebsd-arm64": { + "version": "0.13.15", + "resolved": "https://registry.npmjs.org/esbuild-freebsd-arm64/-/esbuild-freebsd-arm64-0.13.15.tgz", + "integrity": "sha512-KJx0fzEDf1uhNOZQStV4ujg30WlnwqUASaGSFPhznLM/bbheu9HhqZ6mJJZM32lkyfGJikw0jg7v3S0oAvtvQQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ] + }, + "node_modules/esbuild-linux-32": { + "version": "0.13.15", + "resolved": "https://registry.npmjs.org/esbuild-linux-32/-/esbuild-linux-32-0.13.15.tgz", + "integrity": "sha512-ZvTBPk0YWCLMCXiFmD5EUtB30zIPvC5Itxz0mdTu/xZBbbHJftQgLWY49wEPSn2T/TxahYCRDWun5smRa0Tu+g==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/esbuild-linux-64": { + "version": "0.13.15", + "resolved": "https://registry.npmjs.org/esbuild-linux-64/-/esbuild-linux-64-0.13.15.tgz", + "integrity": "sha512-eCKzkNSLywNeQTRBxJRQ0jxRCl2YWdMB3+PkWFo2BBQYC5mISLIVIjThNtn6HUNqua1pnvgP5xX0nHbZbPj5oA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/esbuild-linux-arm": { + "version": "0.13.15", + "resolved": "https://registry.npmjs.org/esbuild-linux-arm/-/esbuild-linux-arm-0.13.15.tgz", + "integrity": "sha512-wUHttDi/ol0tD8ZgUMDH8Ef7IbDX+/UsWJOXaAyTdkT7Yy9ZBqPg8bgB/Dn3CZ9SBpNieozrPRHm0BGww7W/jA==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/esbuild-linux-arm64": { + "version": "0.13.15", + "resolved": "https://registry.npmjs.org/esbuild-linux-arm64/-/esbuild-linux-arm64-0.13.15.tgz", + "integrity": "sha512-bYpuUlN6qYU9slzr/ltyLTR9YTBS7qUDymO8SV7kjeNext61OdmqFAzuVZom+OLW1HPHseBfJ/JfdSlx8oTUoA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/esbuild-linux-mips64le": { + "version": "0.13.15", + "resolved": "https://registry.npmjs.org/esbuild-linux-mips64le/-/esbuild-linux-mips64le-0.13.15.tgz", + "integrity": "sha512-KlVjIG828uFPyJkO/8gKwy9RbXhCEUeFsCGOJBepUlpa7G8/SeZgncUEz/tOOUJTcWMTmFMtdd3GElGyAtbSWg==", + "cpu": [ + "mips64el" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/esbuild-linux-ppc64le": { + "version": "0.13.15", + "resolved": "https://registry.npmjs.org/esbuild-linux-ppc64le/-/esbuild-linux-ppc64le-0.13.15.tgz", + "integrity": "sha512-h6gYF+OsaqEuBjeesTBtUPw0bmiDu7eAeuc2OEH9S6mV9/jPhPdhOWzdeshb0BskRZxPhxPOjqZ+/OqLcxQwEQ==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/esbuild-netbsd-64": { + "version": "0.13.15", + "resolved": "https://registry.npmjs.org/esbuild-netbsd-64/-/esbuild-netbsd-64-0.13.15.tgz", + "integrity": "sha512-3+yE9emwoevLMyvu+iR3rsa+Xwhie7ZEHMGDQ6dkqP/ndFzRHkobHUKTe+NCApSqG5ce2z4rFu+NX/UHnxlh3w==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ] + }, + "node_modules/esbuild-openbsd-64": { + "version": "0.13.15", + "resolved": "https://registry.npmjs.org/esbuild-openbsd-64/-/esbuild-openbsd-64-0.13.15.tgz", + "integrity": "sha512-wTfvtwYJYAFL1fSs8yHIdf5GEE4NkbtbXtjLWjM3Cw8mmQKqsg8kTiqJ9NJQe5NX/5Qlo7Xd9r1yKMMkHllp5g==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ] + }, + "node_modules/esbuild-sunos-64": { + "version": "0.13.15", + "resolved": "https://registry.npmjs.org/esbuild-sunos-64/-/esbuild-sunos-64-0.13.15.tgz", + "integrity": "sha512-lbivT9Bx3t1iWWrSnGyBP9ODriEvWDRiweAs69vI+miJoeKwHWOComSRukttbuzjZ8r1q0mQJ8Z7yUsDJ3hKdw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "sunos" + ] + }, + "node_modules/esbuild-windows-32": { + "version": "0.13.15", + "resolved": "https://registry.npmjs.org/esbuild-windows-32/-/esbuild-windows-32-0.13.15.tgz", + "integrity": "sha512-fDMEf2g3SsJ599MBr50cY5ve5lP1wyVwTe6aLJsM01KtxyKkB4UT+fc5MXQFn3RLrAIAZOG+tHC+yXObpSn7Nw==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/esbuild-windows-64": { + "version": "0.13.15", + "resolved": "https://registry.npmjs.org/esbuild-windows-64/-/esbuild-windows-64-0.13.15.tgz", + "integrity": "sha512-9aMsPRGDWCd3bGjUIKG/ZOJPKsiztlxl/Q3C1XDswO6eNX/Jtwu4M+jb6YDH9hRSUflQWX0XKAfWzgy5Wk54JQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/esbuild-windows-arm64": { + "version": "0.13.15", + "resolved": "https://registry.npmjs.org/esbuild-windows-arm64/-/esbuild-windows-arm64-0.13.15.tgz", + "integrity": "sha512-zzvyCVVpbwQQATaf3IG8mu1IwGEiDxKkYUdA4FpoCHi1KtPa13jeScYDjlW0Qh+ebWzpKfR2ZwvqAQkSWNcKjA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, "node_modules/escalade": { "version": "3.1.1", "dev": true, diff --git a/src/components/Duration/Duration.tsx b/src/components/Duration/Duration.tsx index a7c1e3dc..873cf398 100644 --- a/src/components/Duration/Duration.tsx +++ b/src/components/Duration/Duration.tsx @@ -6,7 +6,7 @@ import { IComboBox, IComboBoxOption, ThemeProvider } from '@fluentui/react'; import numeral from "numeral"; import { getDefaultDurationTranslations } from './translations'; import { durationOptions } from "./durationOptions"; -import humanizeDuration, { Unit } from "humanize-duration"; +import humanizeDuration, { HumanizerOptions, Unit } from "humanize-duration"; import { Numeral } from "@talxis/client-libraries"; export const Duration = (props: IDuration) => { @@ -19,18 +19,23 @@ export const Duration = (props: IDuration) => { const language = formattingInfo.locale; const numberFormatting = context.userSettings.numberFormattingInfo; const onOverrideComponentProps = props.onOverrideComponentProps ?? ((props) => props); + const hoursPerDay = typeof parameters.HoursPerDay?.raw === 'number' && parameters.HoursPerDay.raw > 0 ? parameters.HoursPerDay.raw : 24; + const minutesPerDay = hoursPerDay * 60; const formatter = (value: number | null) => { //all duration formatting should happen here if (typeof value === 'number') { const durationInMilliseconds = value * 60000; - const units: Unit[] = value < 60 ? ['m'] : value >= 1440 ? ['d'] : ['h']; - const options = { + const units: Unit[] = value < 60 ? ['m'] : value >= minutesPerDay ? ['d'] : ['h']; + const options: HumanizerOptions = { units: units, maxDecimalPoints: 2, language: language.slice(0, language.indexOf("-")), decimal: context.userSettings.numberFormattingInfo.numberDecimalSeparator, - fallbacks: ["en"] + fallbacks: ["en"], + unitMeasures: { + d: minutesPerDay * 60000, + } }; return humanizeDuration(durationInMilliseconds, options); } @@ -85,7 +90,7 @@ export const Duration = (props: IDuration) => { case 'hour': return 60 * value; case 'day': - return 60 * value * 24; + return minutesPerDay * value; case 'minute': default: return value; diff --git a/src/components/Duration/interfaces.ts b/src/components/Duration/interfaces.ts index 4a305144..474ce7b6 100644 --- a/src/components/Duration/interfaces.ts +++ b/src/components/Duration/interfaces.ts @@ -9,6 +9,7 @@ export interface IDuration extends IControl; } export interface IDurationOutputs extends IOutputs {