mirror of https://github.com/rancher/dashboard.git
185 lines
4.3 KiB
JavaScript
185 lines
4.3 KiB
JavaScript
export const UNITS = ['', 'K', 'M', 'G', 'T', 'P', 'E', 'Z', 'Y'];
|
|
export const FRACTIONAL = ['', 'm', 'u', 'n', 'p', 'f', 'a', 'z', 'y']; // milli micro nano pico femto
|
|
|
|
export function formatSi(inValue, {
|
|
increment = 1000,
|
|
addSuffix = true,
|
|
addSuffixSpace = true,
|
|
suffix = '',
|
|
firstSuffix = null,
|
|
startingExponent = 0,
|
|
minExponent = 0,
|
|
maxExponent = 99,
|
|
maxPrecision = 2,
|
|
canRoundToZero = true,
|
|
} = {}) {
|
|
let val = inValue;
|
|
let exp = startingExponent;
|
|
const divide = maxExponent >= 0;
|
|
|
|
// TODO More to think about re: min > max
|
|
if (divide) {
|
|
while ( ( val >= increment && exp + 1 < UNITS.length && exp < maxExponent ) || exp < minExponent ) {
|
|
val = val / increment;
|
|
exp++;
|
|
}
|
|
} else {
|
|
while ( ( val < increment && exp + 1 < FRACTIONAL.length && exp < (maxExponent * -1) ) || exp < (minExponent * -1) ) {
|
|
val = val * increment;
|
|
exp++;
|
|
}
|
|
}
|
|
|
|
let out = '';
|
|
|
|
if ( val < 10 && maxPrecision >= 1 ) {
|
|
out = `${ Math.round(val * (10 ** maxPrecision) ) / (10 ** maxPrecision) }`;
|
|
} else {
|
|
out = `${ Math.round(val) }`;
|
|
}
|
|
|
|
if (out === '0' && !canRoundToZero && inValue !== 0) {
|
|
const exponent = exponentNeeded(inValue, increment);
|
|
|
|
return formatSi(inValue, {
|
|
increment,
|
|
addSuffix,
|
|
suffix,
|
|
firstSuffix,
|
|
startingExponent,
|
|
minExponent: exponent,
|
|
maxExponent: exponent,
|
|
maxPrecision,
|
|
canRoundToZero: true,
|
|
});
|
|
}
|
|
|
|
if ( addSuffix ) {
|
|
if (addSuffixSpace) {
|
|
out += ` `;
|
|
}
|
|
|
|
if ( exp === 0 && firstSuffix !== null) {
|
|
out += `${ firstSuffix }`;
|
|
} else {
|
|
out += `${ divide ? UNITS[exp] : FRACTIONAL[exp] }${ suffix }` || '';
|
|
}
|
|
}
|
|
|
|
return out;
|
|
}
|
|
|
|
export function exponentNeeded(val, increment = 1000) {
|
|
let exp = 0;
|
|
|
|
while ( val >= increment ) {
|
|
val = val / increment;
|
|
exp++;
|
|
}
|
|
|
|
return exp;
|
|
}
|
|
|
|
export function parseSi(inValue, opt) {
|
|
opt = opt || {};
|
|
let increment = opt.increment;
|
|
const allowFractional = opt.allowFractional !== false;
|
|
|
|
if ( !inValue || typeof inValue !== 'string' || !inValue.length ) {
|
|
return NaN;
|
|
}
|
|
|
|
inValue = inValue.replace(/,/g, '');
|
|
|
|
// eslint-disable-next-line prefer-const
|
|
let [, valStr, unit, incStr] = inValue.match(/^([0-9.-]+)\s*([^0-9.-]?)([^0-9.-]?)/);
|
|
const val = parseFloat(valStr);
|
|
|
|
if ( !unit ) {
|
|
return val;
|
|
}
|
|
|
|
// micro "mu" symbol -> u
|
|
if ( unit.charCodeAt(0) === 181 ) {
|
|
unit = 'u';
|
|
}
|
|
|
|
const divide = FRACTIONAL.includes(unit);
|
|
const multiply = UNITS.includes(unit.toUpperCase());
|
|
|
|
if ( !increment ) {
|
|
// Automatically handle 1 KB = 1000B, 1 KiB = 1024B if no increment set
|
|
if ( (multiply || divide) && incStr === 'i' ) {
|
|
increment = 1024;
|
|
} else {
|
|
increment = 1000;
|
|
}
|
|
}
|
|
|
|
if ( divide && allowFractional ) {
|
|
const exp = FRACTIONAL.indexOf(unit);
|
|
|
|
return val / (increment ** exp);
|
|
}
|
|
|
|
if ( multiply ) {
|
|
const exp = UNITS.indexOf(unit.toUpperCase());
|
|
|
|
return val * (increment ** exp);
|
|
}
|
|
|
|
// Unrecognized unit character
|
|
return val;
|
|
}
|
|
|
|
export const MEMORY_PARSE_RULES = {
|
|
memory: {
|
|
format: {
|
|
addSuffix: true,
|
|
firstSuffix: 'B',
|
|
increment: 1024,
|
|
maxExponent: 99,
|
|
maxPrecision: 2,
|
|
minExponent: 0,
|
|
startingExponent: 0,
|
|
suffix: 'iB',
|
|
}
|
|
}
|
|
};
|
|
|
|
export function createMemoryFormat(n) {
|
|
const exponent = exponentNeeded(n, MEMORY_PARSE_RULES.memory.format.increment);
|
|
|
|
return {
|
|
...MEMORY_PARSE_RULES.memory.format,
|
|
maxExponent: exponent,
|
|
minExponent: exponent,
|
|
};
|
|
}
|
|
|
|
function createMemoryUnits(n) {
|
|
const exponent = exponentNeeded(n, MEMORY_PARSE_RULES.memory.format.increment);
|
|
|
|
return `${ UNITS[exponent] }${ MEMORY_PARSE_RULES.memory.format.suffix }`;
|
|
}
|
|
|
|
export function createMemoryValues(total, useful) {
|
|
const parsedTotal = parseSi((total || '0').toString());
|
|
const parsedUseful = parseSi((useful || '0').toString());
|
|
const format = createMemoryFormat(parsedTotal);
|
|
const formattedTotal = formatSi(parsedTotal, format);
|
|
const formattedUseful = formatSi(parsedUseful, format);
|
|
|
|
return {
|
|
total: Number.parseFloat(formattedTotal),
|
|
useful: Number.parseFloat(formattedUseful),
|
|
units: createMemoryUnits(parsedTotal)
|
|
};
|
|
}
|
|
|
|
export default {
|
|
exponentNeeded,
|
|
formatSi,
|
|
parseSi,
|
|
};
|