X-Git-Url: https://git.arvados.org/arvados-workbench2.git/blobdiff_plain/52cc3b912c703c24bc90e67aaf24e8ad912d3ebf..39c55ead904f943894f1658b9efa4a7c77584382:/src/common/formatters.ts diff --git a/src/common/formatters.ts b/src/common/formatters.ts index fe7df14c..a38609a6 100644 --- a/src/common/formatters.ts +++ b/src/common/formatters.ts @@ -2,42 +2,130 @@ // // SPDX-License-Identifier: AGPL-3.0 -export const formatDate = (isoDate: string) => { - const date = new Date(isoDate); - const text = date.toLocaleString(); - return text === 'Invalid Date' ? "" : text; +import { PropertyValue } from 'models/search-bar'; +import { + Vocabulary, + getTagKeyLabel, + getTagValueLabel, +} from 'models/vocabulary'; + +export const formatDate = (isoDate?: string | null, utc: boolean = false) => { + if (isoDate) { + const date = new Date(isoDate); + let text: string; + if (utc) { + text = date.toUTCString(); + } else { + text = date.toLocaleString(); + } + return text === 'Invalid Date' ? '(none)' : text; + } + return '-'; }; -export const formatFileSize = (size?: number) => { - if (typeof size === "number") { - for (const { base, unit } of fileSizes) { +export const formatFileSize = (size?: number | string) => { + if (typeof size === 'number') { + if (size === 0) { + return '0 B'; + } + + for (const { base, unit } of FILE_SIZES) { if (size >= base) { - return `${(size / base).toFixed()} ${unit}`; + return `${(size / base).toFixed(base === 1 ? 0 : 1)} ${unit}`; } } } - return ""; + if ((typeof size === 'string' && size === '') || size === undefined) { + return '-'; + } + return '0 B'; +}; + +export const formatTime = (time: number, seconds?: boolean) => { + const minutes = Math.floor((time / (1000 * 60)) % 60).toFixed(0); + const hours = Math.floor(time / (1000 * 60 * 60)).toFixed(0); + + if (seconds) { + const seconds = Math.floor((time / 1000) % 60).toFixed(0); + return hours + 'h ' + minutes + 'm ' + seconds + 's'; + } + + return hours + 'h ' + minutes + 'm'; +}; + +export const getTimeDiff = (endTime: string, startTime: string) => { + return new Date(endTime).getTime() - new Date(startTime).getTime(); }; -const fileSizes = [ +export const formatProgress = (loaded: number, total: number) => { + const progress = loaded >= 0 && total > 0 ? (loaded * 100) / total : 0; + return `${progress.toFixed(2)}%`; +}; + +export function formatUploadSpeed( + prevLoaded: number, + loaded: number, + prevTime: number, + currentTime: number +) { + const speed = + loaded > prevLoaded && currentTime > prevTime + ? (loaded - prevLoaded) / (currentTime - prevTime) + : 0; + + return `${(speed / 1000).toFixed(2)} MB/s`; +} + +const FILE_SIZES = [ { - base: 1000000000000, - unit: "TB" + base: 1099511627776, + unit: 'TiB', }, { - base: 1000000000, - unit: "GB" + base: 1073741824, + unit: 'GiB', }, { - base: 1000000, - unit: "MB" + base: 1048576, + unit: 'MiB', }, { - base: 1000, - unit: "KB" + base: 1024, + unit: 'KiB', }, { base: 1, - unit: "B" + unit: 'B', + }, +]; + +export const formatPropertyValue = ( + pv: PropertyValue, + vocabulary?: Vocabulary +) => { + if (vocabulary && pv.keyID && pv.valueID) { + return `${getTagKeyLabel(pv.keyID, vocabulary)}: ${getTagValueLabel( + pv.keyID, + pv.valueID!, + vocabulary + )}`; } -]; \ No newline at end of file + if (pv.key) { + return pv.value ? `${pv.key}: ${pv.value}` : pv.key; + } + return ''; +}; + +export const formatContainerCost = (cost: number): string => { + const decimalPlaces = 3; + + const factor = Math.pow(10, decimalPlaces); + const rounded = Math.round(cost * factor) / factor; + if (cost > 0 && rounded === 0) { + // Display min value of 0.001 + return `$${1 / factor}`; + } else { + // Otherwise use rounded value to proper decimal places + return `$${rounded}`; + } +};