Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor: more default units #293

Merged
merged 8 commits into from
Feb 14, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 7 additions & 5 deletions src/lib/helpers/sizeConvertion.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import prettyBytes from 'pretty-bytes';

const sizes = ['Bytes', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'];
const sizes = ['Bytes', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'] as const;
export type Size = (typeof sizes)[number];

export function calculateSize(bytes: number, decimals = 1) {
if (bytes === 0) return '0 Bytes';
Expand All @@ -13,25 +14,26 @@ export function calculateSize(bytes: number, decimals = 1) {
return parseFloat((bytes / Math.pow(k, i)).toFixed(dm)) + ' ' + sizes[i];
}

export function sizeToBytes(value: number, unit: string) {
export function sizeToBytes(value: number, unit: Size) {
const index = sizes.indexOf(unit);
return value * Math.pow(1024, index);
}
export function bytesToSize(value: number, unit: string) {

export function bytesToSize(value: number, unit: Size) {
const index = sizes.indexOf(unit);
return value / Math.pow(1024, index);
}

export function humanFileSize(bytes: number): {
value: string;
unit: string;
unit: Size;
} {
const value = prettyBytes(bytes, {
locale: 'en'
}).split(' ');

return {
value: value[0],
unit: value[1]
unit: value[1] as Size
};
}
77 changes: 77 additions & 0 deletions src/lib/helpers/unit.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
import { derived, writable } from 'svelte/store';
import { last } from './array';
import { withPrevious } from './withPrevious';

export type Unit<T = string> = {
name: T;
value: number;
};

/**
* Creates a value-unit pair. When the unit is changed, the value is updated
* to reflect the new unit.
*
* @export
* @template T = string
* @param {number} [initialValue=0]
* @param {Unit<T>[]} units
*/
export function createValueUnitPair<T = string>(initialValue = 0, units: Unit<T>[]) {
if (!units.some((u) => u.value === 1)) {
throw new Error('Units must have a value of 1');
}

if (units.some((u) => u.value < 1)) {
throw new Error('Units must have a value greater than 1');
}

// Highest to lowest
const sortedUnits = units.sort((a, b) => b.value - a.value);

const unit = withPrevious(last(sortedUnits).name);
const value = writable(initialValue);
const baseValue = derived([value, unit], ([$value, $unit]) => {
return $value * units.find((u) => u.name === $unit).value;
});

for (const u of sortedUnits) {
if (initialValue >= u.value && initialValue % u.value === 0) {
unit.set(u.name, { updateAll: true });
value.set(initialValue / u.value);
break;
}
}

unit.subscribe((newValue, prev) => {
value.update((v) => {
const unitInBase = v * units.find((u) => u.name === prev).value;
return unitInBase / units.find((u) => u.name === newValue).value;
});
});

return {
value,
unit,
baseValue
};
}

export function createTimeUnitPair(initialValue = 0) {
const units: Unit[] = [
{ name: 'Days', value: 86400 },
{ name: 'Hours', value: 3600 },
{ name: 'Minutes', value: 60 },
{ name: 'Seconds', value: 1 }
];
return { ...createValueUnitPair(initialValue, units), units };
}

export function createByteUnitPair(initialValue = 0) {
const units: Unit[] = [
{ name: 'Bytes', value: 1 },
{ name: 'Kilobytes', value: 1024 },
{ name: 'Megabytes', value: 1024 ** 2 },
{ name: 'Gigabytes', value: 1024 ** 3 }
];
return { ...createValueUnitPair(initialValue, units), units };
}
38 changes: 38 additions & 0 deletions src/lib/helpers/withPrevious.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
type SetterOptions = {
updateAll?: boolean;
};

type Listener<T> = (value: T, previous: T | null) => void;

export function withPrevious<T>(value: T) {
let current = value;
let previous: T | null = null;

let subscribers: Array<Listener<T>> = [];

const subscribe = (listener: Listener<T>) => {
subscribers.push(listener);
listener(current, previous);

return () => {
subscribers = subscribers.filter((s) => s !== listener);
};
};

const set = (value: T, options?: SetterOptions) => {
previous = options?.updateAll ? value : current;
current = value;

subscribers.forEach((s) => s(current, previous));
};

const getPrevious = () => previous;

const currentStore = {
subscribe,
set,
getPrevious
};

return currentStore;
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,62 +4,18 @@
import { CardGrid, Heading } from '$lib/components';
import { Dependencies } from '$lib/constants';
import { Button, InputNumber, InputSelect } from '$lib/elements/forms';
import { secsToUnit, timeToSeconds } from '$lib/helpers/timeConversion';
import { createTimeUnitPair } from '$lib/helpers/unit';
import { addNotification } from '$lib/stores/notifications';
import { sdkForConsole } from '$lib/stores/sdk';
import { writable } from 'svelte/store';
import { project } from '../../store';

enum Period {
Days = 'd',
Hours = 'h',
Minutes = 'm',
Seconds = 's'
}

const projectId = $project.$id;
const options = [
{ label: 'days', value: Period.Days },
{ label: 'hours', value: Period.Hours },
{ label: 'minutes', value: Period.Minutes },
{ label: 'seconds', value: Period.Seconds }
];

let period = writable(Period.Seconds);

function getInitialTime() {
let t = $project.authDuration;

if (t >= 86400 && t % 86400 === 0) {
$period = Period.Days;
return t / 86400;
}

if (t >= 3600 && t % 3600 === 0) {
$period = Period.Hours;
return t / 3600;
}

if (t >= 60 && t % 60 === 0) {
$period = Period.Minutes;
return t / 60;
}

return t;
}

let time = getInitialTime();
let timeInSecs = timeToSeconds(time, $period);

period.subscribe((p) => {
time = secsToUnit(timeInSecs, p);
});

$: timeInSecs = timeToSeconds(time, $period);
const { value, unit, baseValue, units } = createTimeUnitPair($project.authDuration);
const options = units.map((v) => ({ label: v.name, value: v.name }));

async function updateSessionLength() {
try {
await sdkForConsole.projects.updateAuthDuration(projectId, timeInSecs);
await sdkForConsole.projects.updateAuthDuration(projectId, $baseValue);
invalidate(Dependencies.PROJECT);

addNotification({
Expand Down Expand Up @@ -87,15 +43,15 @@
<svelte:fragment slot="aside">
<form class="form u-grid u-gap-16">
<ul class="form-list is-multiple">
<InputNumber id="length" label="Length" bind:value={time} />
<InputSelect id="period" label="Time Period" bind:value={$period} {options} />
<InputNumber id="length" label="Length" bind:value={$value} min={0} />
<InputSelect id="period" label="Time Period" bind:value={$unit} {options} />
</ul>
</form>
</svelte:fragment>

<svelte:fragment slot="actions">
<Button
disabled={timeToSeconds(time, $period) === $project.authDuration}
disabled={$baseValue === $project.authDuration}
on:click={() => {
updateSessionLength();
}}>
Expand Down
Loading