refactor(dashboard-v2): replace pretty-bytes with in-house solution
This commit is contained in:
parent
7248147ba7
commit
916a420b72
|
@ -33,7 +33,6 @@
|
||||||
"nanoid": "^3.3.1",
|
"nanoid": "^3.3.1",
|
||||||
"path-browserify": "^1.0.1",
|
"path-browserify": "^1.0.1",
|
||||||
"postcss": "^8.4.6",
|
"postcss": "^8.4.6",
|
||||||
"pretty-bytes": "^6.0.0",
|
|
||||||
"react": "^17.0.1",
|
"react": "^17.0.1",
|
||||||
"react-dom": "^17.0.1",
|
"react-dom": "^17.0.1",
|
||||||
"react-dropzone": "^12.0.4",
|
"react-dropzone": "^12.0.4",
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
import dayjs from "dayjs";
|
import dayjs from "dayjs";
|
||||||
import relativeTime from "dayjs/plugin/relativeTime";
|
import relativeTime from "dayjs/plugin/relativeTime";
|
||||||
import prettyBytes from "pretty-bytes";
|
|
||||||
|
|
||||||
import { useUser } from "../../contexts/user";
|
import { useUser } from "../../contexts/user";
|
||||||
import useActivePlan from "../../hooks/useActivePlan";
|
import useActivePlan from "../../hooks/useActivePlan";
|
||||||
|
import humanBytes from "../../lib/humanBytes";
|
||||||
import { ContainerLoadingIndicator } from "../LoadingIndicator";
|
import { ContainerLoadingIndicator } from "../LoadingIndicator";
|
||||||
|
|
||||||
import LatestPayment from "./LatestPayment";
|
import LatestPayment from "./LatestPayment";
|
||||||
|
@ -33,7 +33,7 @@ const CurrentPlan = () => {
|
||||||
<h4>{activePlan.name}</h4>
|
<h4>{activePlan.name}</h4>
|
||||||
<div className="text-palette-400 justify-between flex flex-col grow">
|
<div className="text-palette-400 justify-between flex flex-col grow">
|
||||||
{activePlan.price === 0 && activePlan.limits && (
|
{activePlan.price === 0 && activePlan.limits && (
|
||||||
<p>{prettyBytes(activePlan.limits.storageLimit, { binary: true })} without paying a dime! 🎉</p>
|
<p>{humanBytes(activePlan.limits.storageLimit)} without paying a dime! 🎉</p>
|
||||||
)}
|
)}
|
||||||
{activePlan.price !== 0 &&
|
{activePlan.price !== 0 &&
|
||||||
(user.subscriptionCancelAtPeriodEnd ? (
|
(user.subscriptionCancelAtPeriodEnd ? (
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
import { useEffect, useMemo, useState } from "react";
|
import { useEffect, useMemo, useState } from "react";
|
||||||
import fileSize from "pretty-bytes";
|
|
||||||
import { Link } from "gatsby";
|
import { Link } from "gatsby";
|
||||||
import cn from "classnames";
|
import cn from "classnames";
|
||||||
import useSWR from "swr";
|
import useSWR from "swr";
|
||||||
|
@ -10,6 +9,7 @@ import { ContainerLoadingIndicator } from "../LoadingIndicator";
|
||||||
|
|
||||||
import { GraphBar } from "./GraphBar";
|
import { GraphBar } from "./GraphBar";
|
||||||
import { UsageGraph } from "./UsageGraph";
|
import { UsageGraph } from "./UsageGraph";
|
||||||
|
import humanBytes from "../../lib/humanBytes";
|
||||||
|
|
||||||
const useUsageData = () => {
|
const useUsageData = () => {
|
||||||
const { user } = useUser();
|
const { user } = useUser();
|
||||||
|
@ -45,7 +45,7 @@ const useUsageData = () => {
|
||||||
};
|
};
|
||||||
|
|
||||||
const size = (bytes) => {
|
const size = (bytes) => {
|
||||||
const text = fileSize(bytes ?? 0, { maximumFractionDigits: 0, binary: true });
|
const text = humanBytes(bytes ?? 0, { precision: 0 });
|
||||||
const [value, unit] = text.split(" ");
|
const [value, unit] = text.split(" ");
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import { useMemo } from "react";
|
import { useMemo } from "react";
|
||||||
import prettyBytes from "pretty-bytes";
|
|
||||||
import dayjs from "dayjs";
|
import dayjs from "dayjs";
|
||||||
import { DATE_FORMAT } from "../../lib/config";
|
import { DATE_FORMAT } from "../../lib/config";
|
||||||
|
import humanBytes from "../../lib/humanBytes";
|
||||||
|
|
||||||
const parseFileName = (fileName) => {
|
const parseFileName = (fileName) => {
|
||||||
const lastDotIndex = Math.max(0, fileName.lastIndexOf(".")) || Infinity;
|
const lastDotIndex = Math.max(0, fileName.lastIndexOf(".")) || Infinity;
|
||||||
|
@ -16,7 +16,7 @@ const formatItem = ({ size, name: rawFileName, uploadedOn, downloadedOn, ...rest
|
||||||
return {
|
return {
|
||||||
...rest,
|
...rest,
|
||||||
date,
|
date,
|
||||||
size: prettyBytes(size),
|
size: humanBytes(size, { precision: 2 }),
|
||||||
type,
|
type,
|
||||||
name,
|
name,
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
import * as React from "react";
|
import * as React from "react";
|
||||||
import cn from "classnames";
|
import cn from "classnames";
|
||||||
import bytes from "pretty-bytes";
|
|
||||||
import { StatusCodes } from "http-status-codes";
|
import { StatusCodes } from "http-status-codes";
|
||||||
import copy from "copy-text-to-clipboard";
|
import copy from "copy-text-to-clipboard";
|
||||||
import path from "path-browserify";
|
import path from "path-browserify";
|
||||||
|
@ -9,6 +8,7 @@ import { ProgressBar } from "./ProgressBar";
|
||||||
import UploaderItemIcon from "./UploaderItemIcon";
|
import UploaderItemIcon from "./UploaderItemIcon";
|
||||||
import buildUploadErrorMessage from "./buildUploadErrorMessage";
|
import buildUploadErrorMessage from "./buildUploadErrorMessage";
|
||||||
import skynetClient from "../../services/skynetClient";
|
import skynetClient from "../../services/skynetClient";
|
||||||
|
import humanBytes from "../../lib/humanBytes";
|
||||||
|
|
||||||
const getFilePath = (file) => file.webkitRelativePath || file.path || file.name;
|
const getFilePath = (file) => file.webkitRelativePath || file.path || file.name;
|
||||||
|
|
||||||
|
@ -88,7 +88,7 @@ export default function UploaderItem({ onUploadStateChange, upload }) {
|
||||||
<div className="font-content truncate">
|
<div className="font-content truncate">
|
||||||
{upload.status === "uploading" && (
|
{upload.status === "uploading" && (
|
||||||
<span className="tabular-nums">
|
<span className="tabular-nums">
|
||||||
Uploading {bytes(upload.file.size * upload.progress)} of {bytes(upload.file.size)}
|
Uploading {humanBytes(upload.file.size * upload.progress)} of {humanBytes(upload.file.size)}
|
||||||
</span>
|
</span>
|
||||||
)}
|
)}
|
||||||
{upload.status === "enqueued" && <span className="text-palette-300">Upload in queue, please wait</span>}
|
{upload.status === "enqueued" && <span className="text-palette-300">Upload in queue, please wait</span>}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import { getReasonPhrase } from "http-status-codes";
|
import { getReasonPhrase } from "http-status-codes";
|
||||||
import bytes from "pretty-bytes";
|
import humanBytes from "../../lib/humanBytes";
|
||||||
|
|
||||||
export default function buildUploadErrorMessage(error) {
|
export default function buildUploadErrorMessage(error) {
|
||||||
// The request was made and the server responded with a status code that falls out of the range of 2xx
|
// The request was made and the server responded with a status code that falls out of the range of 2xx
|
||||||
|
@ -29,7 +29,7 @@ export default function buildUploadErrorMessage(error) {
|
||||||
const matchTusMaxFileSizeError = error.message.match(/upload exceeds maximum size: \d+ > (?<limit>\d+)/);
|
const matchTusMaxFileSizeError = error.message.match(/upload exceeds maximum size: \d+ > (?<limit>\d+)/);
|
||||||
|
|
||||||
if (matchTusMaxFileSizeError) {
|
if (matchTusMaxFileSizeError) {
|
||||||
return `File exceeds size limit of ${bytes(parseInt(matchTusMaxFileSizeError.groups.limit, 10))}`;
|
return `File exceeds size limit of ${humanBytes(matchTusMaxFileSizeError.groups.limit, { precision: 0 })}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: We should add a note "our team has been notified" and have some kind of notification with this error.
|
// TODO: We should add a note "our team has been notified" and have some kind of notification with this error.
|
||||||
|
|
|
@ -0,0 +1,21 @@
|
||||||
|
const UNITS = ["B", "kB", "MB", "GB", "TB", "PB", "EB"];
|
||||||
|
const BASE = 1024;
|
||||||
|
const DEFAULT_OPTIONS = { precision: 1 };
|
||||||
|
|
||||||
|
export default function humanBytes(bytes, { precision } = DEFAULT_OPTIONS) {
|
||||||
|
if (!Number.isFinite(bytes) || bytes < 0) {
|
||||||
|
throw new TypeError(`Expected a finite, positive number. Received: ${typeof bytes}: ${bytes}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
let value = bytes;
|
||||||
|
let unitIndex = 0;
|
||||||
|
|
||||||
|
while (value >= BASE) {
|
||||||
|
value /= BASE;
|
||||||
|
unitIndex += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
const localizedValue = value.toLocaleString(undefined, { maximumFractionDigits: precision });
|
||||||
|
|
||||||
|
return `${localizedValue} ${UNITS[unitIndex]}`;
|
||||||
|
}
|
|
@ -1,5 +1,4 @@
|
||||||
import { useCallback, useState } from "react";
|
import { useCallback, useState } from "react";
|
||||||
import bytes from "pretty-bytes";
|
|
||||||
|
|
||||||
import AuthLayout from "../../layouts/AuthLayout";
|
import AuthLayout from "../../layouts/AuthLayout";
|
||||||
|
|
||||||
|
@ -10,12 +9,13 @@ import { usePortalSettings } from "../../contexts/portal-settings";
|
||||||
import { PlansProvider, usePlans } from "../../contexts/plans";
|
import { PlansProvider, usePlans } from "../../contexts/plans";
|
||||||
import { Metadata } from "../../components/Metadata";
|
import { Metadata } from "../../components/Metadata";
|
||||||
import { useUser } from "../../contexts/user";
|
import { useUser } from "../../contexts/user";
|
||||||
|
import humanBytes from "../../lib/humanBytes";
|
||||||
|
|
||||||
const FreePortalHeader = () => {
|
const FreePortalHeader = () => {
|
||||||
const { plans } = usePlans();
|
const { plans } = usePlans();
|
||||||
|
|
||||||
const freePlan = plans.find(({ price }) => price === 0);
|
const freePlan = plans.find(({ price }) => price === 0);
|
||||||
const freeStorage = freePlan?.limits ? bytes(freePlan.limits?.storageLimit, { binary: true }) : null;
|
const freeStorage = freePlan?.limits ? humanBytes(freePlan.limits?.storageLimit, { binary: true }) : null;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="mt-4 mb-8 font-sans">
|
<div className="mt-4 mb-8 font-sans">
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
import * as React from "react";
|
import * as React from "react";
|
||||||
import bytes from "pretty-bytes";
|
|
||||||
import styled from "styled-components";
|
import styled from "styled-components";
|
||||||
|
|
||||||
import { useUser } from "../contexts/user";
|
import { useUser } from "../contexts/user";
|
||||||
|
@ -14,6 +13,7 @@ import { usePortalSettings } from "../contexts/portal-settings";
|
||||||
import { Alert } from "../components/Alert";
|
import { Alert } from "../components/Alert";
|
||||||
import HighlightedLink from "../components/HighlightedLink";
|
import HighlightedLink from "../components/HighlightedLink";
|
||||||
import { Metadata } from "../components/Metadata";
|
import { Metadata } from "../components/Metadata";
|
||||||
|
import humanBytes from "../lib/humanBytes";
|
||||||
|
|
||||||
const PAID_PORTAL_BREAKPOINTS = [
|
const PAID_PORTAL_BREAKPOINTS = [
|
||||||
{
|
{
|
||||||
|
@ -67,9 +67,9 @@ const Price = ({ price }) => (
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|
||||||
const bandwidth = (value) => `${bytes(value, { bits: true })}/s`;
|
const bandwidth = (value) => `${humanBytes(value, { bits: true })}/s`;
|
||||||
|
|
||||||
const storage = (value) => bytes(value, { binary: true });
|
const storage = (value) => humanBytes(value, { binary: true });
|
||||||
|
|
||||||
const localizedNumber = (value) => value.toLocaleString();
|
const localizedNumber = (value) => value.toLocaleString();
|
||||||
|
|
||||||
|
|
|
@ -12696,11 +12696,6 @@ pretty-bytes@^5.4.1:
|
||||||
resolved "https://registry.yarnpkg.com/pretty-bytes/-/pretty-bytes-5.6.0.tgz#356256f643804773c82f64723fe78c92c62beaeb"
|
resolved "https://registry.yarnpkg.com/pretty-bytes/-/pretty-bytes-5.6.0.tgz#356256f643804773c82f64723fe78c92c62beaeb"
|
||||||
integrity sha512-FFw039TmrBqFK8ma/7OL3sDz/VytdtJr044/QUJtH0wK9lb9jLq9tJyIxUwtQJHwar2BqtiA4iCWSwo9JLkzFg==
|
integrity sha512-FFw039TmrBqFK8ma/7OL3sDz/VytdtJr044/QUJtH0wK9lb9jLq9tJyIxUwtQJHwar2BqtiA4iCWSwo9JLkzFg==
|
||||||
|
|
||||||
pretty-bytes@^6.0.0:
|
|
||||||
version "6.0.0"
|
|
||||||
resolved "https://registry.yarnpkg.com/pretty-bytes/-/pretty-bytes-6.0.0.tgz#928be2ad1f51a2e336add8ba764739f9776a8140"
|
|
||||||
integrity sha512-6UqkYefdogmzqAZWzJ7laYeJnaXDy2/J+ZqiiMtS7t7OfpXWTlaeGMwX8U6EFvPV/YWWEKRkS8hKS4k60WHTOg==
|
|
||||||
|
|
||||||
pretty-error@^2.1.1, pretty-error@^2.1.2:
|
pretty-error@^2.1.1, pretty-error@^2.1.2:
|
||||||
version "2.1.2"
|
version "2.1.2"
|
||||||
resolved "https://registry.yarnpkg.com/pretty-error/-/pretty-error-2.1.2.tgz#be89f82d81b1c86ec8fdfbc385045882727f93b6"
|
resolved "https://registry.yarnpkg.com/pretty-error/-/pretty-error-2.1.2.tgz#be89f82d81b1c86ec8fdfbc385045882727f93b6"
|
||||||
|
|
Reference in New Issue