From 020fec5ce199546a544109f3d88604761c7d695b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Leszczyk?= Date: Fri, 4 Mar 2022 12:01:10 +0100 Subject: [PATCH 01/55] fix(dashboard-v2): fix recent uploads URL --- .../src/components/LatestActivity/LatestActivity.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/dashboard-v2/src/components/LatestActivity/LatestActivity.js b/packages/dashboard-v2/src/components/LatestActivity/LatestActivity.js index 9c53554a..87825661 100644 --- a/packages/dashboard-v2/src/components/LatestActivity/LatestActivity.js +++ b/packages/dashboard-v2/src/components/LatestActivity/LatestActivity.js @@ -23,7 +23,7 @@ export default function LatestActivity() { - + From 8eacf1380689090c4ece29a0dec98712d3330f6b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Leszczyk?= Date: Fri, 4 Mar 2022 12:01:35 +0100 Subject: [PATCH 02/55] feat(dashboard-v2): introduce PlansProvider --- .../src/contexts/plans/PlansContext.js | 7 +++ .../src/contexts/plans/PlansProvider.js | 47 +++++++++++++++++++ .../dashboard-v2/src/contexts/plans/index.js | 2 + .../src/contexts/plans/usePlans.js | 5 ++ 4 files changed, 61 insertions(+) create mode 100644 packages/dashboard-v2/src/contexts/plans/PlansContext.js create mode 100644 packages/dashboard-v2/src/contexts/plans/PlansProvider.js create mode 100644 packages/dashboard-v2/src/contexts/plans/index.js create mode 100644 packages/dashboard-v2/src/contexts/plans/usePlans.js diff --git a/packages/dashboard-v2/src/contexts/plans/PlansContext.js b/packages/dashboard-v2/src/contexts/plans/PlansContext.js new file mode 100644 index 00000000..ff35b45e --- /dev/null +++ b/packages/dashboard-v2/src/contexts/plans/PlansContext.js @@ -0,0 +1,7 @@ +import { createContext } from "react"; + +export const PlansContext = createContext({ + plans: [], + limits: [], + error: null, +}); diff --git a/packages/dashboard-v2/src/contexts/plans/PlansProvider.js b/packages/dashboard-v2/src/contexts/plans/PlansProvider.js new file mode 100644 index 00000000..c481e296 --- /dev/null +++ b/packages/dashboard-v2/src/contexts/plans/PlansProvider.js @@ -0,0 +1,47 @@ +import { useEffect, useState } from "react"; +import useSWR from "swr"; + +import freePlan from "../../lib/tiers"; + +import { PlansContext } from "./PlansContext"; + +/** + * NOTE: this function heavily relies on the fact that each Plan's `tier` + * property corresponds to the plan's index in UserLimits array in + * skynet-accounts code. + * + * @see https://github.com/SkynetLabs/skynet-accounts/blob/7337e740b71b77e6d08016db801e293b8ad81abc/database/user.go#L53-L101 + */ +const aggregatePlansAndLimits = (plans, limits) => { + const sortedPlans = [freePlan, ...plans].sort((planA, planB) => planA.tier - planB.tier); + + // Decorate each plan with its corresponding limits data, if available. + if (limits?.length) { + return sortedPlans.map((plan) => ({ ...plan, limits: limits[plan.tier] || null })); + } + + // If we don't have the limits data yet, set just return the plans. + + return sortedPlans; +}; + +export const PlansProvider = ({ children }) => { + const { data: rawPlans, error: plansError } = useSWR("stripe/prices"); + const { data: limits, error: limitsError } = useSWR("limits"); + + const [plans, setPlans] = useState([freePlan]); + const [loading, setLoading] = useState(true); + const [error, setError] = useState(null); + + useEffect(() => { + if (plansError || limitsError) { + setLoading(false); + setError(plansError || limitsError); + } else if (rawPlans) { + setLoading(false); + setPlans(aggregatePlansAndLimits(rawPlans, limits?.userLimits)); + } + }, [rawPlans, limits, plansError, limitsError]); + + return {children}; +}; diff --git a/packages/dashboard-v2/src/contexts/plans/index.js b/packages/dashboard-v2/src/contexts/plans/index.js new file mode 100644 index 00000000..84dd790f --- /dev/null +++ b/packages/dashboard-v2/src/contexts/plans/index.js @@ -0,0 +1,2 @@ +export * from "./PlansProvider"; +export * from "./usePlans"; diff --git a/packages/dashboard-v2/src/contexts/plans/usePlans.js b/packages/dashboard-v2/src/contexts/plans/usePlans.js new file mode 100644 index 00000000..f36e8595 --- /dev/null +++ b/packages/dashboard-v2/src/contexts/plans/usePlans.js @@ -0,0 +1,5 @@ +import { useContext } from "react"; + +import { PlansContext } from "./PlansContext"; + +export const usePlans = () => useContext(PlansContext); From f1262fb8f7ba1781961bdda0d43753569530c6d4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Leszczyk?= Date: Fri, 4 Mar 2022 12:03:52 +0100 Subject: [PATCH 03/55] refactor(dashboard-v2): make CurrentPlan component use PlansProvider --- .../src/components/CurrentPlan/CurrentPlan.js | 4 +-- .../dashboard-v2/src/hooks/useActivePlan.js | 22 +++++++++++++++ .../src/hooks/useSubscriptionPlans.js | 28 ------------------- packages/dashboard-v2/src/pages/index.js | 5 ++-- 4 files changed, 27 insertions(+), 32 deletions(-) create mode 100644 packages/dashboard-v2/src/hooks/useActivePlan.js delete mode 100644 packages/dashboard-v2/src/hooks/useSubscriptionPlans.js diff --git a/packages/dashboard-v2/src/components/CurrentPlan/CurrentPlan.js b/packages/dashboard-v2/src/components/CurrentPlan/CurrentPlan.js index c5cdee36..86725c93 100644 --- a/packages/dashboard-v2/src/components/CurrentPlan/CurrentPlan.js +++ b/packages/dashboard-v2/src/components/CurrentPlan/CurrentPlan.js @@ -2,7 +2,7 @@ import dayjs from "dayjs"; import relativeTime from "dayjs/plugin/relativeTime"; import { useUser } from "../../contexts/user"; -import useSubscriptionPlans from "../../hooks/useSubscriptionPlans"; +import useActivePlan from "../../hooks/useActivePlan"; import LatestPayment from "./LatestPayment"; import SuggestedPlan from "./SuggestedPlan"; @@ -11,7 +11,7 @@ dayjs.extend(relativeTime); const CurrentPlan = () => { const { user, error: userError } = useUser(); - const { activePlan, plans, error: plansError } = useSubscriptionPlans(user); + const { plans, activePlan, error: plansError } = useActivePlan(user); if (!user || !activePlan) { return ( diff --git a/packages/dashboard-v2/src/hooks/useActivePlan.js b/packages/dashboard-v2/src/hooks/useActivePlan.js new file mode 100644 index 00000000..53e28b63 --- /dev/null +++ b/packages/dashboard-v2/src/hooks/useActivePlan.js @@ -0,0 +1,22 @@ +import { useEffect, useState } from "react"; + +import freeTier from "../lib/tiers"; +import { usePlans } from "../contexts/plans"; + +export default function useActivePlan(user) { + const { plans, error } = usePlans(); + + const [activePlan, setActivePlan] = useState(freeTier); + + useEffect(() => { + if (user) { + setActivePlan(plans.find((plan) => plan.tier === user.tier)); + } + }, [plans, user]); + + return { + error, + plans, + activePlan, + }; +} diff --git a/packages/dashboard-v2/src/hooks/useSubscriptionPlans.js b/packages/dashboard-v2/src/hooks/useSubscriptionPlans.js deleted file mode 100644 index 26658df8..00000000 --- a/packages/dashboard-v2/src/hooks/useSubscriptionPlans.js +++ /dev/null @@ -1,28 +0,0 @@ -import { useEffect, useState } from "react"; -import useSWR from "swr"; -import freeTier from "../lib/tiers"; - -export default function useSubscriptionPlans(user) { - const { data: paidPlans, error, mutate } = useSWR("stripe/prices"); - const [plans, setPlans] = useState([freeTier]); - const [activePlan, setActivePlan] = useState(freeTier); - - useEffect(() => { - if (paidPlans) { - setPlans((plans) => [...plans, ...paidPlans].sort((planA, planB) => planA.tier - planB.tier)); - } - }, [paidPlans]); - - useEffect(() => { - if (user) { - setActivePlan(plans.find((plan) => plan.tier === user.tier)); - } - }, [plans, user]); - - return { - error, - mutate, - plans, - activePlan, - }; -} diff --git a/packages/dashboard-v2/src/pages/index.js b/packages/dashboard-v2/src/pages/index.js index 695e6ac3..4db97e04 100644 --- a/packages/dashboard-v2/src/pages/index.js +++ b/packages/dashboard-v2/src/pages/index.js @@ -2,6 +2,7 @@ import * as React from "react"; import { useMedia } from "react-use"; import theme from "../lib/theme"; +import { PlansProvider } from "../contexts/plans/PlansProvider"; import { ArrowRightIcon } from "../components/Icons"; import { Panel } from "../components/Panel"; import { Tab, TabPanel, Tabs } from "../components/Tabs"; @@ -16,7 +17,7 @@ const IndexPage = () => { const showRecentActivity = useMedia(`(min-width: ${theme.screens.md})`); return ( - <> +
{
)} - +
); }; From b060556d3c4e79cabd7897760bc89890cbd50300 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Leszczyk?= Date: Fri, 4 Mar 2022 13:52:31 +0100 Subject: [PATCH 04/55] feat(dashboard-v2): introduce a loading indicator --- .../ContainerLoadingIndicator.js | 18 ++++++++++++++++++ .../src/components/LoadingIndicator/index.js | 1 + 2 files changed, 19 insertions(+) create mode 100644 packages/dashboard-v2/src/components/LoadingIndicator/ContainerLoadingIndicator.js create mode 100644 packages/dashboard-v2/src/components/LoadingIndicator/index.js diff --git a/packages/dashboard-v2/src/components/LoadingIndicator/ContainerLoadingIndicator.js b/packages/dashboard-v2/src/components/LoadingIndicator/ContainerLoadingIndicator.js new file mode 100644 index 00000000..de86a849 --- /dev/null +++ b/packages/dashboard-v2/src/components/LoadingIndicator/ContainerLoadingIndicator.js @@ -0,0 +1,18 @@ +import styled from "styled-components"; +import { CircledProgressIcon } from "../Icons"; + +/** + * This loading indicator is designed to be replace entire blocks (i.e. components) + * while they are fetching required data. + * + * It will take 50% of the parent's height, but won't get bigger than 150x150 px. + */ +const Wrapper = styled.div.attrs({ + className: "flex w-full h-full justify-center items-center p-8 text-palette-100", +})``; + +export const ContainerLoadingIndicator = (props) => ( + + + +); diff --git a/packages/dashboard-v2/src/components/LoadingIndicator/index.js b/packages/dashboard-v2/src/components/LoadingIndicator/index.js new file mode 100644 index 00000000..df7c2a88 --- /dev/null +++ b/packages/dashboard-v2/src/components/LoadingIndicator/index.js @@ -0,0 +1 @@ +export * from "./ContainerLoadingIndicator"; From 5fec31a3a50a7a0823c57b1d54c610c7b4aabcc8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Leszczyk?= Date: Fri, 4 Mar 2022 13:53:37 +0100 Subject: [PATCH 05/55] feat(dashboard-v2): fetch live data about current usage --- .../components/CurrentUsage/CurrentUsage.js | 80 ++++++++++++++----- 1 file changed, 58 insertions(+), 22 deletions(-) diff --git a/packages/dashboard-v2/src/components/CurrentUsage/CurrentUsage.js b/packages/dashboard-v2/src/components/CurrentUsage/CurrentUsage.js index b467e1ea..f6e6f635 100644 --- a/packages/dashboard-v2/src/components/CurrentUsage/CurrentUsage.js +++ b/packages/dashboard-v2/src/components/CurrentUsage/CurrentUsage.js @@ -1,24 +1,46 @@ -import * as React from "react"; +import { useEffect, useMemo, useState } from "react"; import fileSize from "pretty-bytes"; import { Link } from "gatsby"; +import useSWR from "swr"; + +import { useUser } from "../../contexts/user"; +import useActivePlan from "../../hooks/useActivePlan"; +import { ContainerLoadingIndicator } from "../LoadingIndicator"; import { GraphBar } from "./GraphBar"; import { UsageGraph } from "./UsageGraph"; -// TODO: get real data -const useUsageData = () => ({ - files: { - used: 19_521, - limit: 20_000, - }, - storage: { - used: 23_000_000_000, - limit: 1_000_000_000_000, - }, -}); +const useUsageData = () => { + const { user } = useUser(); + const { activePlan, error } = useActivePlan(user); + const [loading, setLoading] = useState(true); + const { data: stats, error: statsError } = useSWR("user/stats"); + const [usage, setUsage] = useState({}); + + useEffect(() => { + if ((activePlan && stats) || error || statsError) { + setLoading(false); + } + + if (activePlan && stats && !error && !statsError) { + setUsage({ + filesUsed: stats?.numUploads, + filesLimit: activePlan?.limits?.maxNumberUploads, + storageUsed: stats?.totalUploadsSize, + storageLimit: activePlan?.limits?.storageLimit, + }); + } + }, [activePlan, stats, error, statsError]); + + return { + error: error || statsError, + loading, + usage, + }; +}; const size = (bytes) => { - const text = fileSize(bytes, { maximumFractionDigits: 1 }); + const text = fileSize(bytes ?? 0, { maximumFractionDigits: 0 }); const [value, unit] = text.split(" "); return { @@ -28,12 +50,26 @@ const size = (bytes) => { }; }; -export default function CurrentUsage() { - const { files, storage } = useUsageData(); +const ErrorMessage = () => ( +
+

We were not able to fetch the current usage data.

+

We'll try again automatically.

+
+); - const storageUsage = size(storage.used); - const storageLimit = size(storage.limit); - const filesUsedLabel = React.useMemo(() => ({ value: files.used, unit: "files" }), [files.used]); +export default function CurrentUsage() { + const { usage, error, loading } = useUsageData(); + const storageUsage = size(usage.storageUsed); + const storageLimit = size(usage.storageLimit); + const filesUsedLabel = useMemo(() => ({ value: usage.filesUsed, unit: "files" }), [usage.filesUsed]); + + if (loading) { + return ; + } + + if (error) { + return ; + } return ( <> @@ -41,7 +77,7 @@ export default function CurrentUsage() { {storageUsage.text} of {storageLimit.text}

- {files.used} of {files.limit} files + {usage.filesUsed} of {usage.filesLimit} files

@@ -49,8 +85,8 @@ export default function CurrentUsage() { {storageLimit.text}
- - + +
Files @@ -62,7 +98,7 @@ export default function CurrentUsage() { UPGRADE {" "} {/* TODO: proper URL */} - {files.limit} + {usage.filesLimit}
From 623a4b816ba04dc83fde6a62261d9e262dc02df9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Leszczyk?= Date: Fri, 4 Mar 2022 13:53:56 +0100 Subject: [PATCH 06/55] feat(dashboard-v2): setup loading indicators for main screen panels --- .../dashboard-v2/src/components/CurrentPlan/CurrentPlan.js | 6 ++---- .../src/components/LatestActivity/ActivityTable.js | 5 +++-- packages/dashboard-v2/src/layouts/DashboardLayout.js | 3 ++- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/packages/dashboard-v2/src/components/CurrentPlan/CurrentPlan.js b/packages/dashboard-v2/src/components/CurrentPlan/CurrentPlan.js index 86725c93..f8a5cf9e 100644 --- a/packages/dashboard-v2/src/components/CurrentPlan/CurrentPlan.js +++ b/packages/dashboard-v2/src/components/CurrentPlan/CurrentPlan.js @@ -3,6 +3,7 @@ import relativeTime from "dayjs/plugin/relativeTime"; import { useUser } from "../../contexts/user"; import useActivePlan from "../../hooks/useActivePlan"; +import { ContainerLoadingIndicator } from "../LoadingIndicator"; import LatestPayment from "./LatestPayment"; import SuggestedPlan from "./SuggestedPlan"; @@ -14,10 +15,7 @@ const CurrentPlan = () => { const { plans, activePlan, error: plansError } = useActivePlan(user); if (!user || !activePlan) { - return ( - // TODO: a nicer loading indicator -
Loading...
- ); + return ; } if (userError || plansError) { diff --git a/packages/dashboard-v2/src/components/LatestActivity/ActivityTable.js b/packages/dashboard-v2/src/components/LatestActivity/ActivityTable.js index 647f9bf8..e8d86a6c 100644 --- a/packages/dashboard-v2/src/components/LatestActivity/ActivityTable.js +++ b/packages/dashboard-v2/src/components/LatestActivity/ActivityTable.js @@ -2,6 +2,7 @@ import * as React from "react"; import useSWR from "swr"; import { Table, TableBody, TableCell, TableRow } from "../Table"; +import { ContainerLoadingIndicator } from "../LoadingIndicator"; import useFormattedActivityData from "./useFormattedActivityData"; @@ -12,8 +13,8 @@ export default function ActivityTable({ type }) { if (!items.length) { return (
- {/* TODO: proper loading indicator / error message */} - {!data && !error &&

Loading...

} + {/* TODO: proper error message */} + {!data && !error && } {!data && error &&

An error occurred while loading this data.

} {data &&

No files found.

}
diff --git a/packages/dashboard-v2/src/layouts/DashboardLayout.js b/packages/dashboard-v2/src/layouts/DashboardLayout.js index 07f4eabf..b369ece3 100644 --- a/packages/dashboard-v2/src/layouts/DashboardLayout.js +++ b/packages/dashboard-v2/src/layouts/DashboardLayout.js @@ -8,6 +8,7 @@ import { PageContainer } from "../components/PageContainer"; import { NavBar } from "../components/Navbar"; import { Footer } from "../components/Footer"; import { UserProvider, useUser } from "../contexts/user"; +import { ContainerLoadingIndicator } from "../components/LoadingIndicator"; const Wrapper = styled.div.attrs({ className: "min-h-screen overflow-hidden", @@ -25,7 +26,7 @@ const Layout = ({ children }) => { {!user && (
-

Loading...

{/* TODO: Do something nicer here */} +
)} {user && <>{children}} From 431cf6001af974c89386751dfd3d25b415975997 Mon Sep 17 00:00:00 2001 From: Fluffy9 Date: Fri, 4 Mar 2022 11:42:16 -0500 Subject: [PATCH 07/55] Update authorized_keys --- setup-scripts/support/authorized_keys | 1 + 1 file changed, 1 insertion(+) diff --git a/setup-scripts/support/authorized_keys b/setup-scripts/support/authorized_keys index 6ee7b264..43698a94 100644 --- a/setup-scripts/support/authorized_keys +++ b/setup-scripts/support/authorized_keys @@ -8,3 +8,4 @@ ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIPM43lzbKjFLChe5rKETxDpWpNlqXCGTBPiWlDN2vlLD ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIN6Kcx8yetova4/ALUQHigo/PBMJO33ZTKOsg2jxSO2a user@deploy.siasky.dev ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIDcenWnMQ6q/OEC4ZmQgjLDV2obWlR3fENV0zRGFvJF+ marcins@siasky.net ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIB7prtVOTwtcSN9HkXum107RwcW5H8Vggx6Qv7T57ItT daniel@siasky.net +ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAII85HxoIRbPyr+xUjpuFUlQNW7smCNdIcmx2XgpmXnB0 marissa@skynetlabs.com From a5327d00f3631cddcc23b3db7d682385dad7f277 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Leszczyk?= Date: Tue, 8 Mar 2022 09:37:24 +0100 Subject: [PATCH 08/55] style(dashboard-v2): improve code readability --- .../src/components/CurrentUsage/CurrentUsage.js | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/packages/dashboard-v2/src/components/CurrentUsage/CurrentUsage.js b/packages/dashboard-v2/src/components/CurrentUsage/CurrentUsage.js index f6e6f635..44be79ed 100644 --- a/packages/dashboard-v2/src/components/CurrentUsage/CurrentUsage.js +++ b/packages/dashboard-v2/src/components/CurrentUsage/CurrentUsage.js @@ -13,16 +13,20 @@ import { UsageGraph } from "./UsageGraph"; const useUsageData = () => { const { user } = useUser(); const { activePlan, error } = useActivePlan(user); - const [loading, setLoading] = useState(true); const { data: stats, error: statsError } = useSWR("user/stats"); + + const [loading, setLoading] = useState(true); const [usage, setUsage] = useState({}); + const hasError = error || statsError; + const hasData = activePlan && stats; + useEffect(() => { - if ((activePlan && stats) || error || statsError) { + if (hasData || hasError) { setLoading(false); } - if (activePlan && stats && !error && !statsError) { + if (hasData && !hasError) { setUsage({ filesUsed: stats?.numUploads, filesLimit: activePlan?.limits?.maxNumberUploads, @@ -30,7 +34,7 @@ const useUsageData = () => { storageLimit: activePlan?.limits?.storageLimit, }); } - }, [activePlan, stats, error, statsError]); + }, [hasData, hasError, stats, activePlan]); return { error: error || statsError, From 74675f198d2a813a80e9fcc5b4b7cd8945b90bb7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Leszczyk?= Date: Tue, 8 Mar 2022 09:37:46 +0100 Subject: [PATCH 09/55] fix(dashboard-v2): bullet-proof activity table --- .../dashboard-v2/src/components/LatestActivity/ActivityTable.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/dashboard-v2/src/components/LatestActivity/ActivityTable.js b/packages/dashboard-v2/src/components/LatestActivity/ActivityTable.js index e8d86a6c..345a2daa 100644 --- a/packages/dashboard-v2/src/components/LatestActivity/ActivityTable.js +++ b/packages/dashboard-v2/src/components/LatestActivity/ActivityTable.js @@ -16,7 +16,7 @@ export default function ActivityTable({ type }) { {/* TODO: proper error message */} {!data && !error && } {!data && error &&

An error occurred while loading this data.

} - {data &&

No files found.

} + {data && !error &&

No files found.

} ); } From 9302ec8077745299a1c56b03ca6d09319d6fc884 Mon Sep 17 00:00:00 2001 From: Karol Wypchlo Date: Thu, 10 Mar 2022 08:36:54 +0100 Subject: [PATCH 10/55] add missing cors headers --- docker/nginx/conf.d/server/server.api | 2 ++ 1 file changed, 2 insertions(+) diff --git a/docker/nginx/conf.d/server/server.api b/docker/nginx/conf.d/server/server.api index 4f8f2512..ede926f9 100644 --- a/docker/nginx/conf.d/server/server.api +++ b/docker/nginx/conf.d/server/server.api @@ -334,6 +334,8 @@ location /skynet/resolve { } location ~ "^/(([a-zA-Z0-9-_]{46}|[a-z0-9]{55})(/.*)?)$" { + include /etc/nginx/conf.d/include/cors; + set $skylink $2; set $path $3; From fadf7fccb84fb318ba2269c3a3b85d3c5fd05052 Mon Sep 17 00:00:00 2001 From: Karol Wypchlo Date: Thu, 10 Mar 2022 09:54:18 +0100 Subject: [PATCH 11/55] Revert "Merge pull request #1853 from SkynetLabs/add-missing-cors-headers" This reverts commit 85df3958c1e028fc0f7925369bea7dd88f9ac85b, reversing changes made to 8db71f57ec6ffd2db25e2febb59c84ff42c11cd3. --- docker/nginx/conf.d/server/server.api | 2 -- 1 file changed, 2 deletions(-) diff --git a/docker/nginx/conf.d/server/server.api b/docker/nginx/conf.d/server/server.api index ede926f9..4f8f2512 100644 --- a/docker/nginx/conf.d/server/server.api +++ b/docker/nginx/conf.d/server/server.api @@ -334,8 +334,6 @@ location /skynet/resolve { } location ~ "^/(([a-zA-Z0-9-_]{46}|[a-z0-9]{55})(/.*)?)$" { - include /etc/nginx/conf.d/include/cors; - set $skylink $2; set $path $3; From ed3fba1db4d968e90b30ffbe077dce72d8dbf395 Mon Sep 17 00:00:00 2001 From: Karol Wypchlo Date: Thu, 10 Mar 2022 09:54:54 +0100 Subject: [PATCH 12/55] Revert "Merge pull request #1851 from SkynetLabs/adjust-health-checks-to-skylink-redirects" This reverts commit 8db71f57ec6ffd2db25e2febb59c84ff42c11cd3, reversing changes made to 7922f84a237657b3dfb8aae09e5dbed32081f5f8. --- packages/health-check/src/checks/critical.js | 6 +--- packages/health-check/src/checks/extended.js | 32 ++++---------------- 2 files changed, 7 insertions(+), 31 deletions(-) diff --git a/packages/health-check/src/checks/critical.js b/packages/health-check/src/checks/critical.js index 9eec00fb..127ebd8a 100644 --- a/packages/health-check/src/checks/critical.js +++ b/packages/health-check/src/checks/critical.js @@ -201,11 +201,7 @@ async function genericAccessCheck(name, url) { const data = { up: false, url }; try { - const cookie = `nocache=true;${authCookie}`; - const response = await got(url, { - headers: { cookie }, - hooks: { beforeRedirect: [(options) => (options.headers.cookie = cookie)] }, - }); + const response = await got(url, { headers: { cookie: `nocache=true;${authCookie}` } }); data.statusCode = response.statusCode; data.up = true; diff --git a/packages/health-check/src/checks/extended.js b/packages/health-check/src/checks/extended.js index bf8d4b99..aaf74389 100644 --- a/packages/health-check/src/checks/extended.js +++ b/packages/health-check/src/checks/extended.js @@ -1023,27 +1023,13 @@ function fileEndpointCheck(done) { } // check whether hns/note-to-self would properly redirect to note-to-self/ -function skylinkRootDomainEndpointRedirect(done) { +function hnsEndpointDirectoryRedirect(done) { const expected = { - name: "skylink root domain endpoint redirect", - skylink: "AACogzrAimYPG42tDOKhS3lXZD8YvlF8Q8R17afe95iV2Q", - statusCode: 301, - headers: { - location: `https://000ah0pqo256c3orhmmgpol19dslep1v32v52v23ohqur9uuuuc9bm8.${process.env.PORTAL_DOMAIN}`, - }, - }; - - skylinkVerification(done, expected, { followRedirect: false }); -} - -// check whether hns/note-to-self would properly redirect to note-to-self/ -function hnsRootDomainEndpointRedirect(done) { - const expected = { - name: "hns root domain endpoint redirect", + name: "hns endpoint directory redirect", skylink: "hns/note-to-self", - statusCode: 301, + statusCode: 308, headers: { - location: `https://note-to-self.hns.${process.env.PORTAL_DOMAIN}`, + location: "note-to-self/", }, }; @@ -1150,12 +1136,7 @@ async function skylinkVerification(done, expected, { followRedirect = true, meth try { const query = `https://${process.env.PORTAL_DOMAIN}/${expected.skylink}`; - const cookie = `nocache=true;${authCookie}`; - const response = await got[method](query, { - followRedirect, - headers: { cookie }, - hooks: { beforeRedirect: [(options) => (options.headers.cookie = cookie)] }, - }); + const response = await got[method](query, { followRedirect, headers: { cookie: `nocache=true;${authCookie}` } }); const entry = { ...details, up: true, statusCode: response.statusCode, time: calculateElapsedTime(time) }; const info = {}; @@ -1256,8 +1237,7 @@ module.exports = [ // uniswapHNSRedirectCheck, uniswapHNSResolverCheck, uniswapHNSResolverRedirectCheck, - skylinkRootDomainEndpointRedirect, - hnsRootDomainEndpointRedirect, + hnsEndpointDirectoryRedirect, skappSkySend, skappNoteToSelf, skappUniswap, From 6e3f7d76d59e0b13c2a4bf87fe53702e6ab7a7e1 Mon Sep 17 00:00:00 2001 From: Karol Wypchlo Date: Thu, 10 Mar 2022 09:55:09 +0100 Subject: [PATCH 13/55] Revert "Merge pull request #1832 from SkynetLabs/redirect-hns-endpoint-to-hns-subdomain" This reverts commit 1b64969461e93780f0a546c0e8ef338d0b927ac8, reversing changes made to 7da5a24c6e549981ef767f97ca9cc07d02002af9. --- docker/nginx/conf.d/include/location-hns | 13 +++---------- docker/nginx/conf.d/server/server.api | 18 +++++++++--------- 2 files changed, 12 insertions(+), 19 deletions(-) diff --git a/docker/nginx/conf.d/include/location-hns b/docker/nginx/conf.d/include/location-hns index f41ac303..62ff9729 100644 --- a/docker/nginx/conf.d/include/location-hns +++ b/docker/nginx/conf.d/include/location-hns @@ -3,8 +3,7 @@ include /etc/nginx/conf.d/include/proxy-pass-internal; include /etc/nginx/conf.d/include/portal-access-check; # variable definititions - we need to define a variable to be able to access it in lua by ngx.var.something -set $skylink ''; # placeholder for the base64 skylink -set $skylink_base32 ''; # placeholder for the base32 skylink +set $skylink ''; # placeholder for the raw 46 bit skylink # resolve handshake domain by requesting to /hnsres endpoint and assign correct values to $skylink and $rest rewrite_by_lua_block { @@ -75,16 +74,10 @@ rewrite_by_lua_block { if ngx.var.path == "/" and skylink_rest ~= nil and skylink_rest ~= "" and skylink_rest ~= "/" then ngx.var.path = skylink_rest end - - -- assign base32 skylink to be used in proxy_pass - ngx.var.skylink_base32 = require("skynet.skylink").base32(ngx.var.skylink) } -# host header has to be adjusted to properly match server name -proxy_set_header Host $skylink_base32.$skynet_portal_domain; - -# pass the skylink request to subdomain skylink server -proxy_pass $scheme://$server_addr$path$is_args$args; +# we proxy to another nginx location rather than directly to siad because we do not want to deal with caching here +proxy_pass https://127.0.0.1/$skylink$path$is_args$args; # in case siad returns location header, we need to replace the skylink with the domain name header_filter_by_lua_block { diff --git a/docker/nginx/conf.d/server/server.api b/docker/nginx/conf.d/server/server.api index 4f8f2512..6a2b146b 100644 --- a/docker/nginx/conf.d/server/server.api +++ b/docker/nginx/conf.d/server/server.api @@ -123,14 +123,15 @@ location /abuse/report { location /hns { include /etc/nginx/conf.d/include/cors; - rewrite_by_lua_block { - local hns_domain = string.match(ngx.var.uri, "/hns/([^/?]+)") - local path = string.match(ngx.var.uri, "/hns/[^/?]+(.*)") - local args = ngx.var.args and ngx.var.is_args .. ngx.var.args or "" - local hns_subdomain_url = ngx.var.scheme .. "://" .. hns_domain .. ".hns." .. ngx.var.skynet_portal_domain .. path .. args + # match the request_uri and extract the hns domain and anything that is passed in the uri after it + # example: /hns/something/foo/bar matches: + # > hns_domain: something + # > path: /foo/bar/ + set_by_lua_block $hns_domain { return string.match(ngx.var.uri, "/hns/([^/?]+)") } + set_by_lua_block $path { return string.match(ngx.var.uri, "/hns/[^/?]+(.*)") } - return ngx.redirect(hns_subdomain_url, ngx.HTTP_MOVED_PERMANENTLY) - } + proxy_set_header Host $host; + include /etc/nginx/conf.d/include/location-hns; } location /hnsres { @@ -340,8 +341,7 @@ location ~ "^/(([a-zA-Z0-9-_]{46}|[a-z0-9]{55})(/.*)?)$" { rewrite_by_lua_block { local skynet_skylink = require("skynet.skylink") local base32_skylink = skynet_skylink.base32(ngx.var.skylink) - local args = ngx.var.args and ngx.var.is_args .. ngx.var.args or "" - local base32_url = ngx.var.scheme .. "://" .. base32_skylink .. "." .. ngx.var.skynet_portal_domain .. ngx.var.path .. args + local base32_url = ngx.var.scheme .. "://" .. base32_skylink .. "." .. ngx.var.skynet_portal_domain .. ngx.var.path .. ngx.var.is_args .. ngx.var.args return ngx.redirect(base32_url, ngx.HTTP_MOVED_PERMANENTLY) } From a743b625ff5cacf62d1283c6c09276be5f96402e Mon Sep 17 00:00:00 2001 From: Karol Wypchlo Date: Thu, 10 Mar 2022 09:55:24 +0100 Subject: [PATCH 14/55] Revert "Merge pull request #1831 from SkynetLabs/redirect-base64-skylink-to-base32" This reverts commit e998882ca89b04ed25682e538892c4f1217d0109, reversing changes made to 85dd22a72eb77633c1018819fe95c67127291075. --- docker/nginx/conf.d/include/location-skylink | 2 +- docker/nginx/conf.d/server/server.api | 8 +------- docker/nginx/conf.d/server/server.dnslink | 2 +- docker/nginx/libs/skynet/skylink.lua | 20 +++----------------- docker/nginx/libs/skynet/skylink.spec.lua | 19 +++---------------- 5 files changed, 9 insertions(+), 42 deletions(-) diff --git a/docker/nginx/conf.d/include/location-skylink b/docker/nginx/conf.d/include/location-skylink index c613fe29..da4727c7 100644 --- a/docker/nginx/conf.d/include/location-skylink +++ b/docker/nginx/conf.d/include/location-skylink @@ -7,7 +7,7 @@ limit_conn downloads_by_ip 100; # ddos protection: max 100 downloads at a time # ensure that skylink that we pass around is base64 encoded (transform base32 encoded ones) # this is important because we want only one format in cache keys and logs -set_by_lua_block $skylink { return require("skynet.skylink").base64(ngx.var.skylink) } +set_by_lua_block $skylink { return require("skynet.skylink").parse(ngx.var.skylink) } # $skylink_v1 and $skylink_v2 variables default to the same value but in case the requested skylink was: # a) skylink v1 - it would not matter, no additional logic is executed diff --git a/docker/nginx/conf.d/server/server.api b/docker/nginx/conf.d/server/server.api index 6a2b146b..ce93c669 100644 --- a/docker/nginx/conf.d/server/server.api +++ b/docker/nginx/conf.d/server/server.api @@ -338,13 +338,7 @@ location ~ "^/(([a-zA-Z0-9-_]{46}|[a-z0-9]{55})(/.*)?)$" { set $skylink $2; set $path $3; - rewrite_by_lua_block { - local skynet_skylink = require("skynet.skylink") - local base32_skylink = skynet_skylink.base32(ngx.var.skylink) - local base32_url = ngx.var.scheme .. "://" .. base32_skylink .. "." .. ngx.var.skynet_portal_domain .. ngx.var.path .. ngx.var.is_args .. ngx.var.args - - return ngx.redirect(base32_url, ngx.HTTP_MOVED_PERMANENTLY) - } + include /etc/nginx/conf.d/include/location-skylink; } location ~ "^/file/(([a-zA-Z0-9-_]{46}|[a-z0-9]{55})(/.*)?)$" { diff --git a/docker/nginx/conf.d/server/server.dnslink b/docker/nginx/conf.d/server/server.dnslink index 22ce75a3..32e454cc 100644 --- a/docker/nginx/conf.d/server/server.dnslink +++ b/docker/nginx/conf.d/server/server.dnslink @@ -37,7 +37,7 @@ location / { ngx.var.skylink = cache_value end - ngx.var.skylink = require("skynet.skylink").base64(ngx.var.skylink) + ngx.var.skylink = require("skynet.skylink").parse(ngx.var.skylink) ngx.var.skylink_v1 = ngx.var.skylink ngx.var.skylink_v2 = ngx.var.skylink } diff --git a/docker/nginx/libs/skynet/skylink.lua b/docker/nginx/libs/skynet/skylink.lua index c6372a41..adcf0b70 100644 --- a/docker/nginx/libs/skynet/skylink.lua +++ b/docker/nginx/libs/skynet/skylink.lua @@ -3,13 +3,10 @@ local _M = {} local basexx = require("basexx") local hasher = require("hasher") --- use lowercase alphabet since our skylinks are part of urls -local base32_alphabet = "0123456789abcdefghijklmnopqrstuv" - -- parse any skylink and return base64 version -function _M.base64(skylink) +function _M.parse(skylink) if string.len(skylink) == 55 then - local decoded = basexx.from_basexx(string.lower(skylink), base32_alphabet, 5) + local decoded = basexx.from_basexx(string.upper(skylink), "0123456789ABCDEFGHIJKLMNOPQRSTUV", 5) return basexx.to_url64(decoded) end @@ -17,21 +14,10 @@ function _M.base64(skylink) return skylink end --- parse any skylink and return base32 version -function _M.base32(skylink) - if string.len(skylink) == 46 then - local decoded = basexx.from_url64(skylink) - - return basexx.to_basexx(decoded, base32_alphabet, 5) - end - - return skylink -end - -- hash skylink into 32 bytes hash used in blocklist function _M.hash(skylink) -- ensure that the skylink is base64 encoded - local base64Skylink = _M.base64(skylink) + local base64Skylink = _M.parse(skylink) -- decode skylink from base64 encoding local rawSkylink = basexx.from_url64(base64Skylink) diff --git a/docker/nginx/libs/skynet/skylink.spec.lua b/docker/nginx/libs/skynet/skylink.spec.lua index 9949e534..0502a833 100644 --- a/docker/nginx/libs/skynet/skylink.spec.lua +++ b/docker/nginx/libs/skynet/skylink.spec.lua @@ -1,28 +1,15 @@ local skynet_skylink = require("skynet.skylink") -describe("base64", function() +describe("parse", function() local base32 = "0404dsjvti046fsua4ktor9grrpe76erq9jot9cvopbhsvsu76r4r30" local base64 = "AQBG8n_sgEM_nlEp3G0w3vLjmdvSZ46ln8ZXHn-eObZNjA" it("should return unchanged base64 skylink", function() - assert.is.same(skynet_skylink.base64(base64), base64) + assert.is.same(skynet_skylink.parse(base64), base64) end) it("should transform base32 skylink into base64", function() - assert.is.same(skynet_skylink.base64(base32), base64) - end) -end) - -describe("base32", function() - local base32 = "0404dsjvti046fsua4ktor9grrpe76erq9jot9cvopbhsvsu76r4r30" - local base64 = "AQBG8n_sgEM_nlEp3G0w3vLjmdvSZ46ln8ZXHn-eObZNjA" - - it("should return unchanged base32 skylink", function() - assert.is.same(skynet_skylink.base32(base32), base32) - end) - - it("should transform base64 skylink into base32", function() - assert.is.same(skynet_skylink.base32(base64), base32) + assert.is.same(skynet_skylink.parse(base32), base64) end) end) From e40ca0011c23f6e5e43a2716159125e6703b77b4 Mon Sep 17 00:00:00 2001 From: Ivaylo Novakov Date: Thu, 10 Mar 2022 14:52:45 +0100 Subject: [PATCH 15/55] Request /user/limits in bytes. --- docker/nginx/conf.d/server/server.api | 8 ++++---- docker/nginx/libs/skynet/account.lua | 8 ++++---- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/docker/nginx/conf.d/server/server.api b/docker/nginx/conf.d/server/server.api index ce93c669..fec3af90 100644 --- a/docker/nginx/conf.d/server/server.api +++ b/docker/nginx/conf.d/server/server.api @@ -177,13 +177,13 @@ location /skynet/registry/subscription { local httpc = require("resty.http").new() -- fetch account limits and set download bandwidth and registry delays accordingly - local res, err = httpc:request_uri("http://10.10.10.70:3000/user/limits", { + local res, err = httpc:request_uri("http://10.10.10.70:3000/user/limits?unit=byte", { headers = { ["Cookie"] = "skynet-jwt=" .. ngx.var.skynet_jwt } }) -- fail gracefully in case /user/limits failed if err or (res and res.status ~= ngx.HTTP_OK) then - ngx.log(ngx.ERR, "Failed accounts service request /user/limits: ", err or ("[HTTP " .. res.status .. "] " .. res.body)) + ngx.log(ngx.ERR, "Failed accounts service request /user/limits?unit=byte: ", err or ("[HTTP " .. res.status .. "] " .. res.body)) elseif res and res.status == ngx.HTTP_OK then local json = require('cjson') local limits = json.decode(res.body) @@ -267,10 +267,10 @@ location /skynet/tus { if require("skynet.account").is_access_forbidden() then return require("skynet.account").exit_access_forbidden() end - + -- get account limits of currently authenticated user local limits = require("skynet.account").get_account_limits() - + -- apply upload size limits ngx.req.set_header("SkynetMaxUploadSize", limits.maxUploadSize) end diff --git a/docker/nginx/libs/skynet/account.lua b/docker/nginx/libs/skynet/account.lua index 7be6013f..405981d0 100644 --- a/docker/nginx/libs/skynet/account.lua +++ b/docker/nginx/libs/skynet/account.lua @@ -43,15 +43,15 @@ function _M.get_account_limits() if ngx.var.account_limits == "" then local httpc = require("resty.http").new() - + -- 10.10.10.70 points to accounts service (alias not available when using resty-http) - local res, err = httpc:request_uri("http://10.10.10.70:3000/user/limits", { + local res, err = httpc:request_uri("http://10.10.10.70:3000/user/limits?unit=byte", { headers = { ["Cookie"] = "skynet-jwt=" .. ngx.var.skynet_jwt } }) - + -- fail gracefully in case /user/limits failed if err or (res and res.status ~= ngx.HTTP_OK) then - ngx.log(ngx.ERR, "Failed accounts service request /user/limits: ", err or ("[HTTP " .. res.status .. "] " .. res.body)) + ngx.log(ngx.ERR, "Failed accounts service request /user/limits?unit=byte: ", err or ("[HTTP " .. res.status .. "] " .. res.body)) ngx.var.account_limits = cjson.encode(anon_limits) elseif res and res.status == ngx.HTTP_OK then ngx.var.account_limits = res.body From aa6db3d11531a410d8556493b7b09a047ac92450 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Leszczyk?= Date: Mon, 7 Mar 2022 10:55:43 +0100 Subject: [PATCH 16/55] feat(dashboard-v2): implement TextInputIcon component --- .../src/components/Icons/icons/SearchIcon.js | 10 ++++ .../src/components/Icons/index.js | 1 + .../src/components/Icons/withIconProps.js | 2 +- .../components/TextInputIcon/TextInputIcon.js | 59 +++++++++++++------ .../TextInputIcon/TextInputIcon.stories.js | 15 +++-- packages/dashboard-v2/tailwind.config.js | 1 + 6 files changed, 64 insertions(+), 24 deletions(-) create mode 100644 packages/dashboard-v2/src/components/Icons/icons/SearchIcon.js diff --git a/packages/dashboard-v2/src/components/Icons/icons/SearchIcon.js b/packages/dashboard-v2/src/components/Icons/icons/SearchIcon.js new file mode 100644 index 00000000..f551dea6 --- /dev/null +++ b/packages/dashboard-v2/src/components/Icons/icons/SearchIcon.js @@ -0,0 +1,10 @@ +import { withIconProps } from "../withIconProps"; + +export const SearchIcon = withIconProps(({ size, ...props }) => ( + + + +)); diff --git a/packages/dashboard-v2/src/components/Icons/index.js b/packages/dashboard-v2/src/components/Icons/index.js index 41552e34..31b34b56 100644 --- a/packages/dashboard-v2/src/components/Icons/index.js +++ b/packages/dashboard-v2/src/components/Icons/index.js @@ -9,3 +9,4 @@ export * from "./icons/CircledErrorIcon"; export * from "./icons/CircledProgressIcon"; export * from "./icons/CircledArrowUpIcon"; export * from "./icons/PlusIcon"; +export * from "./icons/SearchIcon"; diff --git a/packages/dashboard-v2/src/components/Icons/withIconProps.js b/packages/dashboard-v2/src/components/Icons/withIconProps.js index d4267318..5da47331 100644 --- a/packages/dashboard-v2/src/components/Icons/withIconProps.js +++ b/packages/dashboard-v2/src/components/Icons/withIconProps.js @@ -4,7 +4,7 @@ const propTypes = { /** * Size of the icon's bounding box. */ - size: PropTypes.number, + size: PropTypes.oneOfType([PropTypes.number, PropTypes.string]), }; const defaultProps = { diff --git a/packages/dashboard-v2/src/components/TextInputIcon/TextInputIcon.js b/packages/dashboard-v2/src/components/TextInputIcon/TextInputIcon.js index 892da996..506ee1fc 100644 --- a/packages/dashboard-v2/src/components/TextInputIcon/TextInputIcon.js +++ b/packages/dashboard-v2/src/components/TextInputIcon/TextInputIcon.js @@ -1,20 +1,45 @@ import PropTypes from "prop-types"; +import cn from "classnames"; +import { useEffect, useRef, useState } from "react"; +import { PlusIcon } from "../Icons"; + +export const TextInputIcon = ({ className, icon, placeholder, onChange }) => { + const inputRef = useRef(); + const [focused, setFocused] = useState(false); + const [value, setValue] = useState(""); + + useEffect(() => { + onChange(value); + }, [value, onChange]); -/** - * Primary UI component for user interaction - */ -export const TextInputIcon = ({ icon, position, placeholder }) => { return ( -
- {position === "left" ?
{icon}
: null} - +
{icon}
+ setFocused(true)} + onBlur={() => setFocused(false)} + onChange={(event) => setValue(event.target.value)} + placeholder={placeholder} + className="focus:outline-none bg-transparent placeholder:text-palette-400" /> - {position === "right" ?
{icon}
: null} + {value && ( + setValue("")} + /> + )}
); }; @@ -23,13 +48,13 @@ TextInputIcon.propTypes = { /** * Icon to place in text input */ - icon: PropTypes.element, - /** - * Side to place icon - */ - position: PropTypes.oneOf(["left", "right"]), + icon: PropTypes.element.isRequired, /** * Input placeholder */ placeholder: PropTypes.string, + /** + * Function to be called whenever value changes + */ + onChange: PropTypes.func.isRequired, }; diff --git a/packages/dashboard-v2/src/components/TextInputIcon/TextInputIcon.stories.js b/packages/dashboard-v2/src/components/TextInputIcon/TextInputIcon.stories.js index 676ca9cf..521b90df 100644 --- a/packages/dashboard-v2/src/components/TextInputIcon/TextInputIcon.stories.js +++ b/packages/dashboard-v2/src/components/TextInputIcon/TextInputIcon.stories.js @@ -1,5 +1,6 @@ import { TextInputIcon } from "./TextInputIcon"; -import { CogIcon } from "../Icons"; +import { SearchIcon } from "../Icons"; +import { Panel } from "../Panel"; // More on default export: https://storybook.js.org/docs/react/writing-stories/introduction#default-export export default { @@ -9,19 +10,21 @@ export default { }; // More on component templates: https://storybook.js.org/docs/react/writing-stories/introduction#using-args -const Template = (args) => ; +const Template = (args) => ( + + + +); export const IconLeft = Template.bind({}); // More on args: https://storybook.js.org/docs/react/writing-stories/args IconLeft.args = { - icon: , - position: "left", + icon: , placeholder: "Search", }; export const IconRight = Template.bind({}); IconRight.args = { - icon: , - position: "right", + icon: , placeholder: "Search", }; diff --git a/packages/dashboard-v2/tailwind.config.js b/packages/dashboard-v2/tailwind.config.js index 4afa0cb2..6f4242d9 100644 --- a/packages/dashboard-v2/tailwind.config.js +++ b/packages/dashboard-v2/tailwind.config.js @@ -28,6 +28,7 @@ module.exports = { borderColor: (theme) => ({ ...theme("colors"), ...colors }), textColor: (theme) => ({ ...theme("colors"), ...colors }), placeholderColor: (theme) => ({ ...theme("colors"), ...colors }), + outlineColor: (theme) => ({ ...theme("colors"), ...colors }), extend: { fontFamily: { sans: ["Sora", ...defaultTheme.fontFamily.sans], From badc487018c6842e55d7a937def7d2b2a09f0b88 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Leszczyk?= Date: Mon, 7 Mar 2022 12:09:51 +0100 Subject: [PATCH 17/55] fix(dashboard-v2): fix tabs default tab behavior --- packages/dashboard-v2/src/components/Tabs/Tabs.js | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/packages/dashboard-v2/src/components/Tabs/Tabs.js b/packages/dashboard-v2/src/components/Tabs/Tabs.js index 4bf20ccf..eae51a65 100644 --- a/packages/dashboard-v2/src/components/Tabs/Tabs.js +++ b/packages/dashboard-v2/src/components/Tabs/Tabs.js @@ -34,7 +34,11 @@ const Body = styled.div.attrs({ className: "grow min-h-0" })``; export const Tabs = ({ defaultTab, children, variant }) => { const getTabId = usePrefixedTabIds(); const { tabs, panels, tabsRefs } = useTabsChildren(children, getTabId); - const defaultTabId = useMemo(() => getTabId(defaultTab || tabs[0].props.id), [getTabId, defaultTab, tabs]); + const defaultTabId = useMemo(() => { + const requestedTabIsPresent = tabs.find(({ props }) => props.id === defaultTab); + + return getTabId(requestedTabIsPresent ? defaultTab : tabs[0].props.id); + }, [getTabId, defaultTab, tabs]); const [activeTabId, setActiveTabId] = useState(defaultTabId); const [activeTabRef, setActiveTabRef] = useState(tabsRefs[activeTabId]); const isActive = (id) => id === activeTabId; From a00d4f8db97b4c0587746d1adbc21753e449fe6e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Leszczyk?= Date: Mon, 7 Mar 2022 12:10:32 +0100 Subject: [PATCH 18/55] fix(dashboard-v2): fix table header styles --- packages/dashboard-v2/src/components/Table/TableHeadCell.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/dashboard-v2/src/components/Table/TableHeadCell.js b/packages/dashboard-v2/src/components/Table/TableHeadCell.js index aeb65670..f16530f0 100644 --- a/packages/dashboard-v2/src/components/Table/TableHeadCell.js +++ b/packages/dashboard-v2/src/components/Table/TableHeadCell.js @@ -4,7 +4,8 @@ import styled from "styled-components"; * Accepts all HMTL attributes a `` element does. */ export const TableHeadCell = styled.th.attrs({ - className: `px-6 py-2.5 truncate h-tableRow + className: `first:pl-6 last:pr-6 px-2 py-4 + truncate h-tableRow text-palette-600 font-sans font-light text-xs first:rounded-l-sm last:rounded-r-sm`, })` From cb5a162fe482b121ac4bfe2ba3ccf719eda49fe2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Leszczyk?= Date: Sun, 13 Mar 2022 10:43:39 +0100 Subject: [PATCH 19/55] fix(dashboard-v2): migrate Switch to styled-components --- .../src/components/Switch/Switch.css | 40 -------- .../src/components/Switch/Switch.js | 91 ++++++++++++++----- .../src/components/Switch/Switch.stories.js | 4 +- 3 files changed, 72 insertions(+), 63 deletions(-) delete mode 100644 packages/dashboard-v2/src/components/Switch/Switch.css diff --git a/packages/dashboard-v2/src/components/Switch/Switch.css b/packages/dashboard-v2/src/components/Switch/Switch.css deleted file mode 100644 index 4bd07cf2..00000000 --- a/packages/dashboard-v2/src/components/Switch/Switch.css +++ /dev/null @@ -1,40 +0,0 @@ -.react-switch-checkbox { - height: 0; - width: 0; - visibility: hidden; -} - -.react-switch-label { - display: flex; - align-items: center; - justify-content: space-between; - cursor: pointer; - width: 44px; - height: 22px; - background: white; - border-radius: 11px; - @apply border-palette-200; - border-width: 1px; - position: relative; - transition: background-color 0.2s; -} - -.react-switch-label .react-switch-button { - content: ""; - position: absolute; - top: 2px; - left: 2px; - width: 16px; - height: 16px; - border-radius: 8px; - transition: 0.2s; -} - -.react-switch-checkbox:checked + .react-switch-label .react-switch-button { - left: calc(100% - 2px); - transform: translateX(-100%); -} - -.react-switch-label:active .react-switch-button { - width: 20px; -} diff --git a/packages/dashboard-v2/src/components/Switch/Switch.js b/packages/dashboard-v2/src/components/Switch/Switch.js index 7709412b..ed24bc92 100644 --- a/packages/dashboard-v2/src/components/Switch/Switch.js +++ b/packages/dashboard-v2/src/components/Switch/Switch.js @@ -1,37 +1,86 @@ import PropTypes from "prop-types"; -import "./Switch.css"; +import { useEffect, useMemo, useState } from "react"; +import styled from "styled-components"; +import { nanoid } from "nanoid"; + +const Container = styled.div.attrs({ + className: "inline-flex items-center gap-1 cursor-pointer select-none", +})``; + +const Checkbox = styled.input.attrs({ + type: "checkbox", + className: `h-0 w-0 hidden`, +})``; + +const Label = styled.label.attrs({ + className: "cursor-pointer inline-flex items-center gap-2", +})` + &:active .toggle-pin { + width: 20px; + } +`; + +const Toggle = styled.span.attrs({ + className: `flex flex-row items-center justify-between + w-[44px] h-[22px] bg-white rounded-full + border border-palette-200 relative cursor-pointer`, +})` + &:active .toggle-pin { + width: 20px; + } +`; + +const TogglePin = styled.span.attrs(({ $checked }) => ({ + className: `toggle-pin + absolute top-[2px] w-4 h-4 rounded-full + transition-[width_left] active:w-5 + + ${$checked ? "checked bg-primary" : "bg-palette-200"}`, +}))` + left: 2px; + + &.checked { + left: calc(100% - 2px); + transform: translateX(-100%); + } +`; + +export const Switch = ({ children, defaultChecked, onChange, ...props }) => { + const id = useMemo(nanoid, [onChange]); + const [checked, setChecked] = useState(defaultChecked); + + useEffect(() => { + onChange(checked); + }, [checked, onChange]); -/** - * Primary UI component for user interaction - */ -export const Switch = ({ isOn, handleToggle }) => { return ( - <> - - - + + setChecked(ev.target.checked)} id={id} /> + + ); }; Switch.propTypes = { /** - * Switch's current value + * Should the checkbox be checked by default? */ - isOn: PropTypes.bool, + defaultChecked: PropTypes.bool, + /** + * Element to be rendered as the switch label + */ + children: PropTypes.element, /** * Function to execute on change */ - handleToggle: PropTypes.func, + onChange: PropTypes.func.isRequired, }; Switch.defaultProps = { - isOn: false, + defaultChecked: false, }; diff --git a/packages/dashboard-v2/src/components/Switch/Switch.stories.js b/packages/dashboard-v2/src/components/Switch/Switch.stories.js index 41d64f6b..8e0cba7d 100644 --- a/packages/dashboard-v2/src/components/Switch/Switch.stories.js +++ b/packages/dashboard-v2/src/components/Switch/Switch.stories.js @@ -13,10 +13,10 @@ const Template = (args) => ; export const SwitchTrue = Template.bind({}); // More on args: https://storybook.js.org/docs/react/writing-stories/args SwitchTrue.args = { - isOn: true, + defaultChecked: true, }; export const SwitchFalse = Template.bind({}); // More on args: https://storybook.js.org/docs/react/writing-stories/args SwitchFalse.args = { - isOn: false, + defaultChecked: false, }; From cd425240a0dbfbbe409ec5f9a70c6784da995dcb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Leszczyk?= Date: Sun, 13 Mar 2022 10:44:20 +0100 Subject: [PATCH 20/55] feat(dashboard-v2): implement PopoverMenu --- .../src/components/PopoverMenu/PopoverMenu.js | 90 +++++++++++++++++++ 1 file changed, 90 insertions(+) diff --git a/packages/dashboard-v2/src/components/PopoverMenu/PopoverMenu.js b/packages/dashboard-v2/src/components/PopoverMenu/PopoverMenu.js index e69de29b..1826cd92 100644 --- a/packages/dashboard-v2/src/components/PopoverMenu/PopoverMenu.js +++ b/packages/dashboard-v2/src/components/PopoverMenu/PopoverMenu.js @@ -0,0 +1,90 @@ +import { Children, cloneElement, useRef, useState } from "react"; +import PropTypes from "prop-types"; +import { useClickAway } from "react-use"; +import styled, { css, keyframes } from "styled-components"; + +const dropDown = keyframes` + 0% { + transform: scaleY(0); + } + 80% { + transform: scaleY(1.1); + } + 100% { + transform: scaleY(1); + } +`; + +const Container = styled.div.attrs({ className: "relative inline-flex" })``; + +const Flyout = styled.ul.attrs({ + className: `absolute right-0 z-10 py-2 + border rounded bg-white + overflow-hidden pointer-events-none + shadow-md shadow-palette-200/50 + pointer-events-auto h-auto overflow-visible border-primary`, +})` + top: calc(100% + 2px); + animation: ${css` + ${dropDown} 0.1s ease-in-out + `}; +`; + +const Option = styled.li.attrs({ + className: `font-sans text-xs uppercase + relative pl-3 pr-5 py-1 + text-palette-600 cursor-pointer + hover:text-primary hover:font-normal + active:text-primary active:font-normal + + before:content-[initial] before:absolute before:left-0 before:h-3 before:w-0.5 before:bg-primary before:top-1.5 + hover:before:content-['']`, +})``; + +export const PopoverMenu = ({ options, children, openClassName, ...props }) => { + const containerRef = useRef(); + const [open, setOpen] = useState(false); + + useClickAway(containerRef, () => setOpen(false)); + + const handleChoice = (callback) => () => { + setOpen(false); + callback(); + }; + + return ( + + {Children.only( + cloneElement(children, { + onClick: () => setOpen((open) => !open), + className: `${children.props.className ?? ""} ${open ? openClassName : ""}`, + }) + )} + {open && ( + + {options.map(({ label, callback }) => ( + + ))} + + )} + + ); +}; + +PopoverMenu.propTypes = { + /** + * Accepts a single child node that will become a menu toggle. + */ + children: PropTypes.element.isRequired, + /** + * Positions in the menu + */ + options: PropTypes.arrayOf( + PropTypes.shape({ + label: PropTypes.string.isRequired, + callback: PropTypes.func.isRequired, + }) + ).isRequired, +}; From e4dec7fabdb0e74e27528534dcaf6a5773ae70f0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Leszczyk?= Date: Sun, 13 Mar 2022 10:52:46 +0100 Subject: [PATCH 21/55] feat(dashboard-v2): add CopyIcon and ShareIcon --- .../src/components/Icons/icons/CopyIcon.js | 10 ++++++++++ .../src/components/Icons/icons/ShareIcon.js | 18 ++++++++++++++++++ .../dashboard-v2/src/components/Icons/index.js | 2 ++ 3 files changed, 30 insertions(+) create mode 100644 packages/dashboard-v2/src/components/Icons/icons/CopyIcon.js create mode 100644 packages/dashboard-v2/src/components/Icons/icons/ShareIcon.js diff --git a/packages/dashboard-v2/src/components/Icons/icons/CopyIcon.js b/packages/dashboard-v2/src/components/Icons/icons/CopyIcon.js new file mode 100644 index 00000000..c3ceb9ac --- /dev/null +++ b/packages/dashboard-v2/src/components/Icons/icons/CopyIcon.js @@ -0,0 +1,10 @@ +import { withIconProps } from "../withIconProps"; + +export const CopyIcon = withIconProps(({ size, ...props }) => ( + + + +)); diff --git a/packages/dashboard-v2/src/components/Icons/icons/ShareIcon.js b/packages/dashboard-v2/src/components/Icons/icons/ShareIcon.js new file mode 100644 index 00000000..f25afeaf --- /dev/null +++ b/packages/dashboard-v2/src/components/Icons/icons/ShareIcon.js @@ -0,0 +1,18 @@ +import { withIconProps } from "../withIconProps"; + +export const ShareIcon = withIconProps(({ size, ...props }) => ( + + + +)); diff --git a/packages/dashboard-v2/src/components/Icons/index.js b/packages/dashboard-v2/src/components/Icons/index.js index 31b34b56..05d9b832 100644 --- a/packages/dashboard-v2/src/components/Icons/index.js +++ b/packages/dashboard-v2/src/components/Icons/index.js @@ -10,3 +10,5 @@ export * from "./icons/CircledProgressIcon"; export * from "./icons/CircledArrowUpIcon"; export * from "./icons/PlusIcon"; export * from "./icons/SearchIcon"; +export * from "./icons/CopyIcon"; +export * from "./icons/ShareIcon"; From ef13a84185720836bdb0f20764545b9fd465553c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Leszczyk?= Date: Sun, 13 Mar 2022 10:53:07 +0100 Subject: [PATCH 22/55] feat(dashboard-v2): implement CopyButton --- .../dashboard-v2/src/components/CopyButton.js | 50 +++++++++++++++++++ 1 file changed, 50 insertions(+) create mode 100644 packages/dashboard-v2/src/components/CopyButton.js diff --git a/packages/dashboard-v2/src/components/CopyButton.js b/packages/dashboard-v2/src/components/CopyButton.js new file mode 100644 index 00000000..db5e9c21 --- /dev/null +++ b/packages/dashboard-v2/src/components/CopyButton.js @@ -0,0 +1,50 @@ +import { useCallback, useRef, useState } from "react"; +import copy from "copy-text-to-clipboard"; +import styled from "styled-components"; +import { useClickAway } from "react-use"; + +import { CopyIcon } from "./Icons"; + +const Button = styled.button.attrs({ + className: "relative inline-flex items-center hover:text-primary", +})``; + +const TooltipContainer = styled.div.attrs(({ $visible }) => ({ + className: `absolute left-full top-1/2 z-10 + bg-white rounded border border-primary/30 shadow-md + pointer-events-none transition-opacity duration-150 ease-in-out + ${$visible ? "opacity-100" : "opacity-0"}`, +}))` + transform: translateY(-50%); +`; + +const TooltipContent = styled.div.attrs({ + className: "bg-primary-light/10 text-palette-600 py-2 px-4 ", +})``; + +export const CopyButton = ({ value }) => { + const containerRef = useRef(); + const [copied, setCopied] = useState(false); + const [timer, setTimer] = useState(null); + + const handleCopy = useCallback(() => { + clearTimeout(timer); + copy(value); + setCopied(true); + + setTimer(setTimeout(() => setCopied(false), 150000)); + }, [value, timer]); + + useClickAway(containerRef, () => setCopied(false)); + + return ( +
+ + + Copied to clipboard + +
+ ); +}; From 46a2ff44d51b41ca275953df5d4c434589b95104 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Leszczyk?= Date: Sun, 13 Mar 2022 10:54:26 +0100 Subject: [PATCH 23/55] fix(dashboard-v2): styling fixes for Select and Table components --- .../src/components/Select/Select.js | 19 +++++++++++-------- .../src/components/Table/Table.js | 2 +- 2 files changed, 12 insertions(+), 9 deletions(-) diff --git a/packages/dashboard-v2/src/components/Select/Select.js b/packages/dashboard-v2/src/components/Select/Select.js index 97d3d73b..0a59a581 100644 --- a/packages/dashboard-v2/src/components/Select/Select.js +++ b/packages/dashboard-v2/src/components/Select/Select.js @@ -21,9 +21,11 @@ const dropDown = keyframes` const Container = styled.div.attrs({ className: "relative inline-flex" })``; -const Trigger = styled.button.attrs(({ placeholder }) => ({ - className: `flex items-center cursor-pointer ${placeholder ? "text-palette-300" : ""}`, -}))``; +const Trigger = styled.button.attrs(({ $placeholder }) => ({ + className: `flex items-center cursor-pointer font-bold ${$placeholder ? "text-palette-300" : ""}`, +}))` + text-transform: inherit; +`; const TriggerIcon = styled(ChevronDownIcon).attrs({ className: "transition-transform text-primary", @@ -32,13 +34,14 @@ const TriggerIcon = styled(ChevronDownIcon).attrs({ `; const Flyout = styled.ul.attrs(({ open }) => ({ - className: `absolute top-[20px] right-0 - p-0 h-0 border rounded bg-white + className: `absolute right-0 z-10 + p-0 border rounded bg-white overflow-hidden pointer-events-none shadow-md shadow-palette-200/50 ${open ? "pointer-events-auto h-auto overflow-visible border-primary" : ""} ${open ? "visible" : "invisible"}`, }))` + top: calc(100% + 2px); animation: ${({ open }) => open ? css` @@ -47,7 +50,7 @@ const Flyout = styled.ul.attrs(({ open }) => ({ : "none"}; `; -export const Select = ({ defaultValue, children, onChange, placeholder }) => { +export const Select = ({ defaultValue, children, onChange, placeholder, ...props }) => { const selectRef = useRef(); const options = useMemo(() => Children.toArray(children).filter(({ type }) => type === SelectOption), [children]); const [state, dispatch] = useSelectReducer({ defaultValue, placeholder, options }); @@ -65,8 +68,8 @@ export const Select = ({ defaultValue, children, onChange, placeholder }) => { const activeLabel = activeOption?.props?.label ?? null; return ( - - + + {activeLabel ?? placeholder} diff --git a/packages/dashboard-v2/src/components/Table/Table.js b/packages/dashboard-v2/src/components/Table/Table.js index 8d55e119..e741da20 100644 --- a/packages/dashboard-v2/src/components/Table/Table.js +++ b/packages/dashboard-v2/src/components/Table/Table.js @@ -1,7 +1,7 @@ import styled from "styled-components"; const Container = styled.div.attrs({ - className: "p-1 max-w-full overflow-x-auto", + className: "p-1 max-w-full", })``; const StyledTable = styled.table.attrs({ From fab732c6cc2161b3bec505e2035432e22c21be10 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Leszczyk?= Date: Sun, 13 Mar 2022 10:57:20 +0100 Subject: [PATCH 24/55] feat(dashboard-v2): add Files page --- .../src/components/FileList/FileList.js | 74 ++++++++++++ .../src/components/FileList/FileTable.js | 111 ++++++++++++++++++ .../src/components/FileList/index.js | 1 + .../FileList/useFormattedFilesData.js | 26 ++++ packages/dashboard-v2/src/pages/files.js | 22 +++- 5 files changed, 233 insertions(+), 1 deletion(-) create mode 100644 packages/dashboard-v2/src/components/FileList/FileList.js create mode 100644 packages/dashboard-v2/src/components/FileList/FileTable.js create mode 100644 packages/dashboard-v2/src/components/FileList/index.js create mode 100644 packages/dashboard-v2/src/components/FileList/useFormattedFilesData.js diff --git a/packages/dashboard-v2/src/components/FileList/FileList.js b/packages/dashboard-v2/src/components/FileList/FileList.js new file mode 100644 index 00000000..6342b970 --- /dev/null +++ b/packages/dashboard-v2/src/components/FileList/FileList.js @@ -0,0 +1,74 @@ +import * as React from "react"; +import useSWR from "swr"; +import { useMedia } from "react-use"; + +import theme from "../../lib/theme"; + +import { ContainerLoadingIndicator } from "../LoadingIndicator"; +import { Select, SelectOption } from "../Select"; +import { Switch } from "../Switch"; +import { TextInputIcon } from "../TextInputIcon/TextInputIcon"; +import { SearchIcon } from "../Icons"; + +import FileTable from "./FileTable"; +import useFormattedFilesData from "./useFormattedFilesData"; + +const FileList = ({ type }) => { + const isMediumScreenOrLarger = useMedia(`(min-width: ${theme.screens.md})`); + const { data, error } = useSWR(`user/${type}?pageSize=10`); + const items = useFormattedFilesData(data?.items || []); + + const setFilter = (name, value) => console.log("filter", name, "set to", value); + + if (!items.length) { + return ( +
+ {/* TODO: proper error message */} + {!data && !error && } + {!data && error &&

An error occurred while loading this data.

} + {data &&

No {type} found.

} +
+ ); + } + + return ( +
+
+ } + onChange={console.log.bind(console)} + /> +
+ setFilter("showSmallFiles", value)} className="mr-8"> + + Show small files + + +
+ File type: + +
+
+ Sort: + +
+
+
+ {/* TODO: mobile view (it's not tabular) */} + {isMediumScreenOrLarger ? : "Mobile view"} +
+ ); +}; + +export default FileList; diff --git a/packages/dashboard-v2/src/components/FileList/FileTable.js b/packages/dashboard-v2/src/components/FileList/FileTable.js new file mode 100644 index 00000000..90c9600f --- /dev/null +++ b/packages/dashboard-v2/src/components/FileList/FileTable.js @@ -0,0 +1,111 @@ +import { CogIcon, ShareIcon } from "../Icons"; +import { PopoverMenu } from "../PopoverMenu/PopoverMenu"; +import { Table, TableBody, TableCell, TableHead, TableHeadCell, TableRow } from "../Table"; +import { CopyButton } from "../CopyButton"; + +const buildShareMenu = (item) => { + return [ + { + label: "Facebook", + callback: () => { + console.info("share to Facebook", item); + }, + }, + { + label: "Twitter", + callback: () => { + console.info("share to Twitter", item); + }, + }, + { + label: "Discord", + callback: () => { + console.info("share to Discord", item); + }, + }, + ]; +}; + +const buildOptionsMenu = (item) => { + return [ + { + label: "Preview", + callback: () => { + console.info("preview", item); + }, + }, + { + label: "Download", + callback: () => { + console.info("download", item); + }, + }, + { + label: "Unpin", + callback: () => { + console.info("unpin", item); + }, + }, + { + label: "Report", + callback: () => { + console.info("report", item); + }, + }, + ]; +}; + +export default function FileTable({ items }) { + return ( + + + + Name + Type + + Size + + Uploaded + Skylink + Activity + + + + {items.map((item) => { + const { id, name, type, size, date, skylink } = item; + + return ( + + {name} + {type} + + {size} + + {date} + +
+ + {skylink} +
+
+ +
+ + + + + + +
+
+
+ ); + })} +
+
+ ); +} diff --git a/packages/dashboard-v2/src/components/FileList/index.js b/packages/dashboard-v2/src/components/FileList/index.js new file mode 100644 index 00000000..93296508 --- /dev/null +++ b/packages/dashboard-v2/src/components/FileList/index.js @@ -0,0 +1 @@ +export * from "./FileList"; diff --git a/packages/dashboard-v2/src/components/FileList/useFormattedFilesData.js b/packages/dashboard-v2/src/components/FileList/useFormattedFilesData.js new file mode 100644 index 00000000..82d95090 --- /dev/null +++ b/packages/dashboard-v2/src/components/FileList/useFormattedFilesData.js @@ -0,0 +1,26 @@ +import { useMemo } from "react"; +import prettyBytes from "pretty-bytes"; +import dayjs from "dayjs"; + +const parseFileName = (fileName) => { + const lastDotIndex = Math.max(0, fileName.lastIndexOf(".")) || Infinity; + + return [fileName.substr(0, lastDotIndex), fileName.substr(lastDotIndex)]; +}; + +const formatItem = ({ size, name: rawFileName, uploadedOn, downloadedOn, ...rest }) => { + const [name, type] = parseFileName(rawFileName); + const date = dayjs(uploadedOn || downloadedOn).format("MM/DD/YYYY; HH:MM"); + + return { + ...rest, + date, + size: prettyBytes(size), + type, + name, + }; +}; + +const useFormattedFilesData = (items) => useMemo(() => items.map(formatItem), [items]); + +export default useFormattedFilesData; diff --git a/packages/dashboard-v2/src/pages/files.js b/packages/dashboard-v2/src/pages/files.js index 348a95b3..197cc031 100644 --- a/packages/dashboard-v2/src/pages/files.js +++ b/packages/dashboard-v2/src/pages/files.js @@ -2,8 +2,28 @@ import * as React from "react"; import DashboardLayout from "../layouts/DashboardLayout"; +import { Panel } from "../components/Panel"; +import { Tab, TabPanel, Tabs } from "../components/Tabs"; +import FileList from "../components/FileList/FileList"; +import { useSearchParam } from "react-use"; + const FilesPage = () => { - return <>FILES; + const defaultTab = useSearchParam("tab"); + + return ( + + + + + + + + + + + + + ); }; FilesPage.Layout = DashboardLayout; From 2d9d45fd691425572190d0658609ca1ee5cba205 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 14 Mar 2022 12:09:21 +0000 Subject: [PATCH 25/55] build(deps): bump gatsby-plugin-manifest in /packages/website Bumps [gatsby-plugin-manifest](https://github.com/gatsbyjs/gatsby/tree/HEAD/packages/gatsby-plugin-manifest) from 4.9.0 to 4.9.1. - [Release notes](https://github.com/gatsbyjs/gatsby/releases) - [Changelog](https://github.com/gatsbyjs/gatsby/blob/master/packages/gatsby-plugin-manifest/CHANGELOG.md) - [Commits](https://github.com/gatsbyjs/gatsby/commits/gatsby-plugin-manifest@4.9.1/packages/gatsby-plugin-manifest) --- updated-dependencies: - dependency-name: gatsby-plugin-manifest dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- packages/website/package.json | 2 +- packages/website/yarn.lock | 18 +++++++++--------- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/packages/website/package.json b/packages/website/package.json index 38de206a..c2eb88bf 100644 --- a/packages/website/package.json +++ b/packages/website/package.json @@ -16,7 +16,7 @@ "gatsby": "4.9.2", "gatsby-background-image": "1.6.0", "gatsby-plugin-image": "2.9.0", - "gatsby-plugin-manifest": "4.9.0", + "gatsby-plugin-manifest": "4.9.1", "gatsby-plugin-postcss": "5.9.0", "gatsby-plugin-react-helmet": "5.9.0", "gatsby-plugin-robots-txt": "1.7.0", diff --git a/packages/website/yarn.lock b/packages/website/yarn.lock index 7ef765a0..d26c47ea 100644 --- a/packages/website/yarn.lock +++ b/packages/website/yarn.lock @@ -6197,10 +6197,10 @@ gatsby-cli@^4.9.0: yoga-layout-prebuilt "^1.10.0" yurnalist "^2.1.0" -gatsby-core-utils@^3.8.2, gatsby-core-utils@^3.9.0: - version "3.9.0" - resolved "https://registry.yarnpkg.com/gatsby-core-utils/-/gatsby-core-utils-3.9.0.tgz#7be5969622e44c4475cb14f1ac64b49a4072ab6c" - integrity sha512-SvPnr86oXTY3ldbQ4QAkEew3BQE9vlzUXcXVJqTOhMUeGEz2kibBFUmVp8ia9Y1eOD+K/0xXQ54jUqaResj69w== +gatsby-core-utils@^3.8.2, gatsby-core-utils@^3.9.0, gatsby-core-utils@^3.9.1: + version "3.9.1" + resolved "https://registry.yarnpkg.com/gatsby-core-utils/-/gatsby-core-utils-3.9.1.tgz#a4c1bb2021a7e7c06b4aad8d71c9c76ca9cdc21f" + integrity sha512-DNf7NhhH0WrFuoBvyURjsw4w+eKbp1GlRA0cchYHJwVTaDPvLvX1o7zxN76xIBx+m0kttpnO3KuJ9LDOSli3ag== dependencies: "@babel/runtime" "^7.15.4" ci-info "2.0.0" @@ -6299,13 +6299,13 @@ gatsby-plugin-image@2.9.0: objectFitPolyfill "^2.3.5" prop-types "^15.7.2" -gatsby-plugin-manifest@4.9.0: - version "4.9.0" - resolved "https://registry.yarnpkg.com/gatsby-plugin-manifest/-/gatsby-plugin-manifest-4.9.0.tgz#ddfd6e8d8597df7bdef07d527b08430508837ecb" - integrity sha512-aRoY9pan+7rR1SGoGcm1039A9tWy0w2oS+s7GmNJqqBHJqN2JZUlvJrqjU4ZdyoZ1/DXx9zuzUQDzgiEBFJ2xw== +gatsby-plugin-manifest@4.9.1: + version "4.9.1" + resolved "https://registry.yarnpkg.com/gatsby-plugin-manifest/-/gatsby-plugin-manifest-4.9.1.tgz#20513c7d942b424795b802506893c0f909c69b7a" + integrity sha512-Fye2vr7ioc7ETVKdCfpbc5ByU28+EB7ocqSORbazPgAT8OiPazpaBAYm98BONceuK3WaxGoEXMsmwmNBIIPjRA== dependencies: "@babel/runtime" "^7.15.4" - gatsby-core-utils "^3.9.0" + gatsby-core-utils "^3.9.1" gatsby-plugin-utils "^3.3.0" semver "^7.3.5" sharp "^0.30.1" From 568692452b185be76a8eee7b249733ba97e318e6 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 14 Mar 2022 12:09:30 +0000 Subject: [PATCH 26/55] build(deps): bump stripe from 8.207.0 to 8.209.0 in /packages/dashboard Bumps [stripe](https://github.com/stripe/stripe-node) from 8.207.0 to 8.209.0. - [Release notes](https://github.com/stripe/stripe-node/releases) - [Changelog](https://github.com/stripe/stripe-node/blob/master/CHANGELOG.md) - [Commits](https://github.com/stripe/stripe-node/compare/v8.207.0...v8.209.0) --- updated-dependencies: - dependency-name: stripe dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- packages/dashboard/package.json | 2 +- packages/dashboard/yarn.lock | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/packages/dashboard/package.json b/packages/dashboard/package.json index 23f9f77e..bccac067 100644 --- a/packages/dashboard/package.json +++ b/packages/dashboard/package.json @@ -27,7 +27,7 @@ "react-dom": "17.0.2", "react-toastify": "8.2.0", "skynet-js": "3.0.2", - "stripe": "8.207.0", + "stripe": "8.209.0", "swr": "1.2.2", "yup": "0.32.11" }, diff --git a/packages/dashboard/yarn.lock b/packages/dashboard/yarn.lock index 231968e3..dc18de50 100644 --- a/packages/dashboard/yarn.lock +++ b/packages/dashboard/yarn.lock @@ -2255,10 +2255,10 @@ strip-json-comments@^3.1.0, strip-json-comments@^3.1.1: resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-3.1.1.tgz#31f1281b3832630434831c310c01cccda8cbe006" integrity sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig== -stripe@8.207.0: - version "8.207.0" - resolved "https://registry.yarnpkg.com/stripe/-/stripe-8.207.0.tgz#4b7002f19cecefbc3c48f09f6658c39e359f99c1" - integrity sha512-ZCjdqN2adGfrC5uAAo0v7IquzaiQ3+pDzB324/iV3Q3Deiot9VO7KMVSNVx/0i6E6ywhgV33ko3FMT7iUgxKYA== +stripe@8.209.0: + version "8.209.0" + resolved "https://registry.yarnpkg.com/stripe/-/stripe-8.209.0.tgz#a8f34132fb4140bdf9152943b15c641ad99cd3b1" + integrity sha512-ozfs8t0fxA/uvCK1DNvitSdEublOHK5CTRsrd2AWWk9LogjXcfkxmtz3KGSSQd+jyA2+rbee9TMzhJ6aabQ5WQ== dependencies: "@types/node" ">=8.1.0" qs "^6.6.0" From 710e24e7b974f36d2562f3679f3047cfd2c4fe97 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 14 Mar 2022 12:09:44 +0000 Subject: [PATCH 27/55] build(deps): bump @fontsource/source-sans-pro in /packages/dashboard Bumps [@fontsource/source-sans-pro](https://github.com/fontsource/fontsource/tree/HEAD/packages/source-sans-pro) from 4.5.3 to 4.5.4. - [Release notes](https://github.com/fontsource/fontsource/releases) - [Changelog](https://github.com/fontsource/fontsource/blob/main/CHANGELOG.md) - [Commits](https://github.com/fontsource/fontsource/commits/HEAD/packages/source-sans-pro) --- updated-dependencies: - dependency-name: "@fontsource/source-sans-pro" dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- packages/dashboard/package.json | 2 +- packages/dashboard/yarn.lock | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/packages/dashboard/package.json b/packages/dashboard/package.json index 23f9f77e..b81a41fd 100644 --- a/packages/dashboard/package.json +++ b/packages/dashboard/package.json @@ -9,7 +9,7 @@ }, "dependencies": { "@fontsource/sora": "4.5.3", - "@fontsource/source-sans-pro": "4.5.3", + "@fontsource/source-sans-pro": "4.5.4", "@stripe/react-stripe-js": "1.7.0", "@stripe/stripe-js": "1.24.0", "classnames": "2.3.1", diff --git a/packages/dashboard/yarn.lock b/packages/dashboard/yarn.lock index 231968e3..04b1a33d 100644 --- a/packages/dashboard/yarn.lock +++ b/packages/dashboard/yarn.lock @@ -58,10 +58,10 @@ resolved "https://registry.yarnpkg.com/@fontsource/sora/-/sora-4.5.3.tgz#987c9b43acb00c9e3fa5377ebcedfd4ec9b760a7" integrity sha512-0ipYkroLonvChAyLajgIt6mImXMhvjrHwD5g7iX2ZR1eJ4hLDnwq6haW5pSeehe79lPjgp0BX6ZHivFIP0xR2g== -"@fontsource/source-sans-pro@4.5.3": - version "4.5.3" - resolved "https://registry.yarnpkg.com/@fontsource/source-sans-pro/-/source-sans-pro-4.5.3.tgz#bdb1eeed5db70bcd1f68cd1e8c859834f0e6bc67" - integrity sha512-9xWGu3ArKsjf6+WVrNoCUywybTB3rIidpvOI2tByQpzYVOupFUv6qohyrjDrVvPb6XHJQTD0NIzisR7RKhiP7A== +"@fontsource/source-sans-pro@4.5.4": + version "4.5.4" + resolved "https://registry.yarnpkg.com/@fontsource/source-sans-pro/-/source-sans-pro-4.5.4.tgz#51510723ff40f446c7800f133e9ae604ae2f38d7" + integrity sha512-+YYw6HRvH9wYE+U2Hvxyossg+MHPApAj7VIjEqaXenNeNQa4U3uPD0e7pc+1Gic3srCQATN15O3S9WSFLXTmwQ== "@humanwhocodes/config-array@^0.9.2": version "0.9.2" From 6783cb3d397d4cbab776cca2777904317643cc43 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 14 Mar 2022 12:09:54 +0000 Subject: [PATCH 28/55] build(deps-dev): bump eslint in /packages/dashboard Bumps [eslint](https://github.com/eslint/eslint) from 8.10.0 to 8.11.0. - [Release notes](https://github.com/eslint/eslint/releases) - [Changelog](https://github.com/eslint/eslint/blob/main/CHANGELOG.md) - [Commits](https://github.com/eslint/eslint/compare/v8.10.0...v8.11.0) --- updated-dependencies: - dependency-name: eslint dependency-type: direct:development update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- packages/dashboard/package.json | 2 +- packages/dashboard/yarn.lock | 25 ++++++++++--------------- 2 files changed, 11 insertions(+), 16 deletions(-) diff --git a/packages/dashboard/package.json b/packages/dashboard/package.json index 23f9f77e..242825b8 100644 --- a/packages/dashboard/package.json +++ b/packages/dashboard/package.json @@ -35,7 +35,7 @@ "@tailwindcss/forms": "0.5.0", "@tailwindcss/typography": "0.5.2", "autoprefixer": "10.4.2", - "eslint": "8.10.0", + "eslint": "8.11.0", "eslint-config-next": "12.1.0", "postcss": "8.4.8", "prettier": "2.5.1", diff --git a/packages/dashboard/yarn.lock b/packages/dashboard/yarn.lock index 231968e3..cdd5c031 100644 --- a/packages/dashboard/yarn.lock +++ b/packages/dashboard/yarn.lock @@ -38,16 +38,16 @@ dependencies: regenerator-runtime "^0.13.4" -"@eslint/eslintrc@^1.2.0": - version "1.2.0" - resolved "https://registry.yarnpkg.com/@eslint/eslintrc/-/eslintrc-1.2.0.tgz#7ce1547a5c46dfe56e1e45c3c9ed18038c721c6a" - integrity sha512-igm9SjJHNEJRiUnecP/1R5T3wKLEJ7pL6e2P+GUSfCd0dGjPYYZve08uzw8L2J8foVHFz+NGu12JxRcU2gGo6w== +"@eslint/eslintrc@^1.2.1": + version "1.2.1" + resolved "https://registry.yarnpkg.com/@eslint/eslintrc/-/eslintrc-1.2.1.tgz#8b5e1c49f4077235516bc9ec7d41378c0f69b8c6" + integrity sha512-bxvbYnBPN1Gibwyp6NrpnFzA3YtRL3BBAyEAFVIpNTm2Rn4Vy87GA5M4aSn3InRrlsbX5N0GW7XIx+U4SAEKdQ== dependencies: ajv "^6.12.4" debug "^4.3.2" espree "^9.3.1" globals "^13.9.0" - ignore "^4.0.6" + ignore "^5.2.0" import-fresh "^3.2.1" js-yaml "^4.1.0" minimatch "^3.0.4" @@ -911,12 +911,12 @@ eslint-visitor-keys@^3.0.0, eslint-visitor-keys@^3.3.0: resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-3.3.0.tgz#f6480fa6b1f30efe2d1968aa8ac745b862469826" integrity sha512-mQ+suqKJVyeuwGYHAdjMFqjCyfl8+Ldnxuyp3ldiMBFKkvytrXUZWaiPCEav8qDHKty44bD+qV1IP4T+w+xXRA== -eslint@8.10.0: - version "8.10.0" - resolved "https://registry.yarnpkg.com/eslint/-/eslint-8.10.0.tgz#931be395eb60f900c01658b278e05b6dae47199d" - integrity sha512-tcI1D9lfVec+R4LE1mNDnzoJ/f71Kl/9Cv4nG47jOueCMBrCCKYXr4AUVS7go6mWYGFD4+EoN6+eXSrEbRzXVw== +eslint@8.11.0: + version "8.11.0" + resolved "https://registry.yarnpkg.com/eslint/-/eslint-8.11.0.tgz#88b91cfba1356fc10bb9eb592958457dfe09fb37" + integrity sha512-/KRpd9mIRg2raGxHRGwW9ZywYNAClZrHjdueHcrVDuO3a6bj83eoTirCCk0M0yPwOjWYKHwRVRid+xK4F/GHgA== dependencies: - "@eslint/eslintrc" "^1.2.0" + "@eslint/eslintrc" "^1.2.1" "@humanwhocodes/config-array" "^0.9.2" ajv "^6.10.0" chalk "^4.0.0" @@ -1247,11 +1247,6 @@ ieee754@^1.2.1: resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.2.1.tgz#8eb7a10a63fff25d15a57b001586d177d1b0d352" integrity sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA== -ignore@^4.0.6: - version "4.0.6" - resolved "https://registry.yarnpkg.com/ignore/-/ignore-4.0.6.tgz#750e3db5862087b4737ebac8207ffd1ef27b25fc" - integrity sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg== - ignore@^5.1.4, ignore@^5.2.0: version "5.2.0" resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.2.0.tgz#6d3bac8fa7fe0d45d9f9be7bac2fc279577e345a" From 7670bdaebd83332a84ff2090faf4f444d9ddc668 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 14 Mar 2022 12:09:54 +0000 Subject: [PATCH 29/55] build(deps): bump gatsby-source-filesystem in /packages/website Bumps [gatsby-source-filesystem](https://github.com/gatsbyjs/gatsby/tree/HEAD/packages/gatsby-source-filesystem) from 4.9.0 to 4.9.1. - [Release notes](https://github.com/gatsbyjs/gatsby/releases) - [Changelog](https://github.com/gatsbyjs/gatsby/blob/master/packages/gatsby-source-filesystem/CHANGELOG.md) - [Commits](https://github.com/gatsbyjs/gatsby/commits/gatsby-source-filesystem@4.9.1/packages/gatsby-source-filesystem) --- updated-dependencies: - dependency-name: gatsby-source-filesystem dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- packages/website/package.json | 2 +- packages/website/yarn.lock | 18 +++++++++--------- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/packages/website/package.json b/packages/website/package.json index 38de206a..93136a9b 100644 --- a/packages/website/package.json +++ b/packages/website/package.json @@ -23,7 +23,7 @@ "gatsby-plugin-sharp": "4.9.0", "gatsby-plugin-sitemap": "5.9.0", "gatsby-plugin-svgr": "3.0.0-beta.0", - "gatsby-source-filesystem": "4.9.0", + "gatsby-source-filesystem": "4.9.1", "gatsby-transformer-sharp": "4.9.0", "gatsby-transformer-yaml": "4.9.0", "gbimage-bridge": "0.2.1", diff --git a/packages/website/yarn.lock b/packages/website/yarn.lock index 7ef765a0..09cb527f 100644 --- a/packages/website/yarn.lock +++ b/packages/website/yarn.lock @@ -6197,10 +6197,10 @@ gatsby-cli@^4.9.0: yoga-layout-prebuilt "^1.10.0" yurnalist "^2.1.0" -gatsby-core-utils@^3.8.2, gatsby-core-utils@^3.9.0: - version "3.9.0" - resolved "https://registry.yarnpkg.com/gatsby-core-utils/-/gatsby-core-utils-3.9.0.tgz#7be5969622e44c4475cb14f1ac64b49a4072ab6c" - integrity sha512-SvPnr86oXTY3ldbQ4QAkEew3BQE9vlzUXcXVJqTOhMUeGEz2kibBFUmVp8ia9Y1eOD+K/0xXQ54jUqaResj69w== +gatsby-core-utils@^3.8.2, gatsby-core-utils@^3.9.0, gatsby-core-utils@^3.9.1: + version "3.9.1" + resolved "https://registry.yarnpkg.com/gatsby-core-utils/-/gatsby-core-utils-3.9.1.tgz#a4c1bb2021a7e7c06b4aad8d71c9c76ca9cdc21f" + integrity sha512-DNf7NhhH0WrFuoBvyURjsw4w+eKbp1GlRA0cchYHJwVTaDPvLvX1o7zxN76xIBx+m0kttpnO3KuJ9LDOSli3ag== dependencies: "@babel/runtime" "^7.15.4" ci-info "2.0.0" @@ -6427,16 +6427,16 @@ gatsby-sharp@^0.3.0: "@types/sharp" "^0.29.5" sharp "^0.30.1" -gatsby-source-filesystem@4.9.0: - version "4.9.0" - resolved "https://registry.yarnpkg.com/gatsby-source-filesystem/-/gatsby-source-filesystem-4.9.0.tgz#8cf6f3f67cc97f8a75e284814f444a0eea3263e6" - integrity sha512-woSxEgYeZSVZSpxm+FwB+RjRIyhcix1AR9766W4yk5RwYH2wciF2OfxRC73WW/o/v1ztzeW6RoqIIY+GBXaA1A== +gatsby-source-filesystem@4.9.1: + version "4.9.1" + resolved "https://registry.yarnpkg.com/gatsby-source-filesystem/-/gatsby-source-filesystem-4.9.1.tgz#e619d8a482b0477c28225ffce9c28cbb0606ce67" + integrity sha512-2HS9+5i+F7tRgxBiv8Op9xK/jvd5DGUfedFsJ6/6sfoXUBddowvW4rVEj4XO42TsIQJe7eVj7FfzfqzSqQN8ow== dependencies: "@babel/runtime" "^7.15.4" chokidar "^3.5.2" file-type "^16.5.3" fs-extra "^10.0.0" - gatsby-core-utils "^3.9.0" + gatsby-core-utils "^3.9.1" got "^9.6.0" md5-file "^5.0.0" mime "^2.5.2" From 4f6b5fb0a8ef8e2c6e3daa814fde66d73b99e34d Mon Sep 17 00:00:00 2001 From: Karol Wypchlo Date: Tue, 15 Mar 2022 09:40:25 +0100 Subject: [PATCH 30/55] clean up nginx skylink cache related code --- docker-compose.yml | 2 - docker/nginx/conf.d/include/location-skylink | 81 +------------------ .../conf.d/include/proxy-cache-downloads | 21 ----- docker/nginx/conf.d/server/server.dnslink | 2 - docker/nginx/conf.d/server/server.local | 37 ++------- docker/nginx/libs/skynet/blocklist.lua | 66 --------------- docker/nginx/nginx.conf | 11 --- 7 files changed, 7 insertions(+), 213 deletions(-) delete mode 100644 docker/nginx/conf.d/include/proxy-cache-downloads delete mode 100644 docker/nginx/libs/skynet/blocklist.lua diff --git a/docker-compose.yml b/docker-compose.yml index 9c0d59d5..af9b53a2 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -64,8 +64,6 @@ services: logging: *default-logging env_file: - .env - environment: - - SKYD_DISK_CACHE_ENABLED=${SKYD_DISK_CACHE_ENABLED:-true} volumes: - ./docker/data/nginx/cache:/data/nginx/cache - ./docker/data/nginx/blocker:/data/nginx/blocker diff --git a/docker/nginx/conf.d/include/location-skylink b/docker/nginx/conf.d/include/location-skylink index da4727c7..cfacf5c1 100644 --- a/docker/nginx/conf.d/include/location-skylink +++ b/docker/nginx/conf.d/include/location-skylink @@ -1,6 +1,5 @@ include /etc/nginx/conf.d/include/cors; include /etc/nginx/conf.d/include/proxy-buffer; -include /etc/nginx/conf.d/include/proxy-cache-downloads; include /etc/nginx/conf.d/include/track-download; limit_conn downloads_by_ip 100; # ddos protection: max 100 downloads at a time @@ -9,62 +8,10 @@ limit_conn downloads_by_ip 100; # ddos protection: max 100 downloads at a time # this is important because we want only one format in cache keys and logs set_by_lua_block $skylink { return require("skynet.skylink").parse(ngx.var.skylink) } -# $skylink_v1 and $skylink_v2 variables default to the same value but in case the requested skylink was: -# a) skylink v1 - it would not matter, no additional logic is executed -# b) skylink v2 - in a lua block below we will resolve the skylink v2 into skylink v1 and update -# $skylink_v1 variable so then the proxy request to skyd can be cached in nginx (proxy_cache_key -# in proxy-cache-downloads includes $skylink_v1 as a part of the cache key) -set $skylink_v1 $skylink; -set $skylink_v2 $skylink; - -# variable for Skynet-Proof header that we need to inject -# into a response if the request was for skylink v2 -set $skynet_proof ''; - # default download rate to unlimited set $limit_rate 0; access_by_lua_block { - -- the block below only makes sense if we are using nginx cache - if not ngx.var.skyd_disk_cache_enabled then - local httpc = require("resty.http").new() - - -- detect whether requested skylink is v2 - local isBase32v2 = string.len(ngx.var.skylink) == 55 and string.sub(ngx.var.skylink, 0, 2) == "04" - local isBase64v2 = string.len(ngx.var.skylink) == 46 and string.sub(ngx.var.skylink, 0, 2) == "AQ" - - if isBase32v2 or isBase64v2 then - -- 10.10.10.10 points to sia service (alias not available when using resty-http) - local res, err = httpc:request_uri("http://10.10.10.10:9980/skynet/resolve/" .. ngx.var.skylink_v2, { - headers = { ["User-Agent"] = "Sia-Agent" } - }) - - -- print error and exit with 500 or exit with response if status is not 200 - if err or (res and res.status ~= ngx.HTTP_OK) then - ngx.status = (err and ngx.HTTP_INTERNAL_SERVER_ERROR) or res.status - ngx.header["content-type"] = "text/plain" - ngx.say(err or res.body) - return ngx.exit(ngx.status) - end - - local json = require('cjson') - local resolve = json.decode(res.body) - ngx.var.skylink_v1 = resolve.skylink - ngx.var.skynet_proof = res.headers["Skynet-Proof"] - end - - -- check if skylink v1 is present on blocklist (compare hashes) - if require("skynet.blocklist").is_blocked(ngx.var.skylink_v1) then - return require("skynet.blocklist").exit_illegal() - end - - -- if skylink is found on nocache list then set internal nocache variable - -- to tell nginx that it should not try and cache this file (too large) - if ngx.shared.nocache:get(ngx.var.skylink_v1) then - ngx.var.nocache = "1" - end - end - if require("skynet.account").accounts_enabled() then -- check if portal is in authenticated only mode if require("skynet.account").is_access_unauthorized() then @@ -84,36 +31,10 @@ access_by_lua_block { end } -header_filter_by_lua_block { - ngx.header["Skynet-Portal-Api"] = ngx.var.scheme .. "://" .. ngx.var.skynet_portal_domain - ngx.header["Skynet-Server-Api"] = ngx.var.scheme .. "://" .. ngx.var.skynet_server_domain - - -- the block below only makes sense if we are using nginx cache - if not ngx.var.skyd_disk_cache_enabled then - -- not empty skynet_proof means this is a skylink v2 request - -- so we should replace the Skynet-Proof header with the one - -- we got from /skynet/resolve/ endpoint, otherwise we would - -- be serving cached empty v1 skylink Skynet-Proof header - if ngx.var.skynet_proof and ngx.var.skynet_proof ~= "" then - ngx.header["Skynet-Proof"] = ngx.var.skynet_proof - end - - -- add skylink to nocache list if it exceeds 1GB (1e+9 bytes) threshold - -- (content length can be nil for already cached files - we can ignore them) - if ngx.header["Content-Length"] and tonumber(ngx.header["Content-Length"]) > 1e+9 then - ngx.shared.nocache:set(ngx.var.skylink_v1, ngx.header["Content-Length"]) - end - end -} - limit_rate_after 512k; limit_rate $limit_rate; proxy_read_timeout 600; proxy_set_header User-Agent: Sia-Agent; -# in case the requested skylink was v2 and we already resolved it to skylink v1, we are going to pass resolved -# skylink v1 to skyd to save that extra skylink v2 lookup in skyd but in turn, in case skyd returns a redirect -# we need to rewrite the skylink v1 to skylink v2 in the location header with proxy_redirect -proxy_redirect $skylink_v1 $skylink_v2; -proxy_pass http://sia:9980/skynet/skylink/$skylink_v1$path$is_args$args; +proxy_pass http://sia:9980/skynet/skylink/$skylink$path$is_args$args; diff --git a/docker/nginx/conf.d/include/proxy-cache-downloads b/docker/nginx/conf.d/include/proxy-cache-downloads deleted file mode 100644 index 85aeeb9e..00000000 --- a/docker/nginx/conf.d/include/proxy-cache-downloads +++ /dev/null @@ -1,21 +0,0 @@ -proxy_cache skynet; # cache name -proxy_cache_key $skylink_v1$path$arg_format$arg_attachment$arg_start$arg_end$http_range; # unique cache key -proxy_cache_min_uses 3; # cache after 3 uses -proxy_cache_valid 200 206 307 308 48h; # keep 200, 206, 307 and 308 responses valid for up to 2 days -add_header X-Proxy-Cache $upstream_cache_status; # add response header to indicate cache hits and misses - -# map skyd env variable value to "1" for true and "0" for false (expected by proxy_no_cache) -set_by_lua_block $skyd_disk_cache_enabled { - return os.getenv("SKYD_DISK_CACHE_ENABLED") == "true" and "1" or "0" -} - -# bypass - this will bypass cache hit on request (status BYPASS) -# but still stores file in cache if cache conditions are met -proxy_cache_bypass $cookie_nocache $arg_nocache $skyd_disk_cache_enabled; - -# no cache - this will ignore cache on request (status MISS) -# and does not store file in cache under no condition -set_if_empty $nocache "0"; - -# disable cache when nocache is set or skyd cache is enabled -proxy_no_cache $nocache $skyd_disk_cache_enabled; diff --git a/docker/nginx/conf.d/server/server.dnslink b/docker/nginx/conf.d/server/server.dnslink index 32e454cc..cf385a1d 100644 --- a/docker/nginx/conf.d/server/server.dnslink +++ b/docker/nginx/conf.d/server/server.dnslink @@ -38,8 +38,6 @@ location / { end ngx.var.skylink = require("skynet.skylink").parse(ngx.var.skylink) - ngx.var.skylink_v1 = ngx.var.skylink - ngx.var.skylink_v2 = ngx.var.skylink } include /etc/nginx/conf.d/include/location-skylink; diff --git a/docker/nginx/conf.d/server/server.local b/docker/nginx/conf.d/server/server.local index 3a8ac118..87c02d1f 100644 --- a/docker/nginx/conf.d/server/server.local +++ b/docker/nginx/conf.d/server/server.local @@ -1,37 +1,12 @@ include /etc/nginx/conf.d/include/init-optional-variables; +# TODO: this endpoint could be removed and calls be made directly to skyd +# since we're not using any nginx specific code here any more location /skynet/blocklist { + include /etc/nginx/conf.d/include/sia-auth; + client_max_body_size 10m; # increase max body size to account for large lists - client_body_buffer_size 10m; # force whole body to memory so we can read it - content_by_lua_block { - local httpc = require("resty.http").new() - - ngx.req.read_body() -- ensure the post body data is read before using get_body_data - - -- proxy blocklist update request - -- 10.10.10.10 points to sia service (alias not available when using resty-http) - local res, err = httpc:request_uri("http://10.10.10.10:9980/skynet/blocklist", { - method = "POST", - body = ngx.req.get_body_data(), - headers = { - ["Content-Type"] = "application/x-www-form-urlencoded", - ["Authorization"] = require("skynet.utils").authorization_header(), - ["User-Agent"] = "Sia-Agent", - } - }) - - -- print error and exit with 500 or exit with response if status is not 204 - if err or (res and res.status ~= ngx.HTTP_NO_CONTENT) then - ngx.status = (err and ngx.HTTP_INTERNAL_SERVER_ERROR) or res.status - ngx.header["content-type"] = "text/plain" - ngx.say(err or res.body) - return ngx.exit(ngx.status) - end - - require("skynet.blocklist").reload() - - ngx.status = ngx.HTTP_NO_CONTENT - return ngx.exit(ngx.status) - } + proxy_set_header User-Agent: Sia-Agent; + proxy_pass http://sia:9980/skynet/blocklist; } diff --git a/docker/nginx/libs/skynet/blocklist.lua b/docker/nginx/libs/skynet/blocklist.lua deleted file mode 100644 index 29f53032..00000000 --- a/docker/nginx/libs/skynet/blocklist.lua +++ /dev/null @@ -1,66 +0,0 @@ -local _M = {} - -function _M.reload() - local httpc = require("resty.http").new() - - -- fetch blocklist records (all blocked skylink hashes) - -- 10.10.10.10 points to sia service (alias not available when using resty-http) - local res, err = httpc:request_uri("http://10.10.10.10:9980/skynet/blocklist", { - headers = { - ["User-Agent"] = "Sia-Agent", - } - }) - - -- fail whole request in case this request failed, we want to make sure - -- the blocklist is pre cached before serving first skylink - if err or (res and res.status ~= ngx.HTTP_OK) then - ngx.log(ngx.ERR, "Failed skyd service request /skynet/blocklist: ", err or ("[HTTP " .. res.status .. "] " .. res.body)) - ngx.status = (err and ngx.HTTP_INTERNAL_SERVER_ERROR) or res.status - ngx.header["content-type"] = "text/plain" - ngx.say(err or res.body) - return ngx.exit(ngx.status) - elseif res and res.status == ngx.HTTP_OK then - local json = require('cjson') - local data = json.decode(res.body) - - -- mark all existing entries as expired - ngx.shared.blocklist:flush_all() - - -- check if blocklist is table (it is null when empty) - if type(data.blocklist) == "table" then - -- set all cache entries one by one (resets expiration) - for i, hash in ipairs(data.blocklist) do - ngx.shared.blocklist:set(hash, true) - end - end - - -- ensure that init flag is persisted - ngx.shared.blocklist:set("__init", true) - - -- remove all leftover expired entries - ngx.shared.blocklist:flush_expired() - end -end - -function _M.is_blocked(skylink) - -- make sure that blocklist has been preloaded - if not ngx.shared.blocklist:get("__init") then _M.reload() end - - -- hash skylink before comparing it with blocklist - local hash = require("skynet.skylink").hash(skylink) - - -- we need to use get_stale because we are expiring previous - -- entries when the blocklist is reloading and we still want - -- to block them until the reloading is finished - return ngx.shared.blocklist:get_stale(hash) == true -end - --- exit with 416 illegal content status code -function _M.exit_illegal() - ngx.status = ngx.HTTP_ILLEGAL - ngx.header["content-type"] = "text/plain" - ngx.say("Unavailable For Legal Reasons") - return ngx.exit(ngx.status) -end - -return _M diff --git a/docker/nginx/nginx.conf b/docker/nginx/nginx.conf index 7f43d192..95bb61ac 100644 --- a/docker/nginx/nginx.conf +++ b/docker/nginx/nginx.conf @@ -31,7 +31,6 @@ env SERVER_DOMAIN; env PORTAL_MODULES; env ACCOUNTS_LIMIT_ACCESS; env SIA_API_PASSWORD; -env SKYD_DISK_CACHE_ENABLED; events { worker_connections 8192; @@ -75,20 +74,10 @@ http { # proxy cache definition proxy_cache_path /data/nginx/cache levels=1:2 keys_zone=skynet:10m max_size=50g min_free=100g inactive=48h use_temp_path=off; - # create a shared blocklist dictionary with size of 30 megabytes - # estimated capacity of 1 megabyte dictionary is 3500 blocklist entries - # that gives us capacity of around 100k entries in 30 megabyte dictionary - lua_shared_dict blocklist 30m; - - # create a shared dictionary to fill with skylinks that should not - # be cached due to the large size or some other reasons - lua_shared_dict nocache 10m; - # this runs before forking out nginx worker processes init_by_lua_block { require "cjson" require "resty.http" - require "skynet.blocklist" require "skynet.skylink" require "skynet.utils" } From e2beee6faca1c9a232a20b902d25909ca1fe7aff Mon Sep 17 00:00:00 2001 From: Karol Wypchlo Date: Tue, 15 Mar 2022 10:32:46 +0100 Subject: [PATCH 31/55] drop nginx blocklist proxy endpoint --- docker/nginx/conf.d/server.local.conf | 9 --------- docker/nginx/conf.d/server/server.local | 12 ------------ scripts/blocklist-skylink.sh | 18 ++++++++---------- setup-scripts/blocklist-airtable.py | 18 +++++++++++------- 4 files changed, 19 insertions(+), 38 deletions(-) delete mode 100644 docker/nginx/conf.d/server.local.conf delete mode 100644 docker/nginx/conf.d/server/server.local diff --git a/docker/nginx/conf.d/server.local.conf b/docker/nginx/conf.d/server.local.conf deleted file mode 100644 index 8a487a53..00000000 --- a/docker/nginx/conf.d/server.local.conf +++ /dev/null @@ -1,9 +0,0 @@ -server { - # local server - do not expose this port externally - listen 8000; - - # secure traffic by limiting to only local networks - include /etc/nginx/conf.d/include/local-network-only; - - include /etc/nginx/conf.d/server/server.local; -} diff --git a/docker/nginx/conf.d/server/server.local b/docker/nginx/conf.d/server/server.local deleted file mode 100644 index 87c02d1f..00000000 --- a/docker/nginx/conf.d/server/server.local +++ /dev/null @@ -1,12 +0,0 @@ -include /etc/nginx/conf.d/include/init-optional-variables; - -# TODO: this endpoint could be removed and calls be made directly to skyd -# since we're not using any nginx specific code here any more -location /skynet/blocklist { - include /etc/nginx/conf.d/include/sia-auth; - - client_max_body_size 10m; # increase max body size to account for large lists - - proxy_set_header User-Agent: Sia-Agent; - proxy_pass http://sia:9980/skynet/blocklist; -} diff --git a/scripts/blocklist-skylink.sh b/scripts/blocklist-skylink.sh index ee19c9c2..cb60bbdb 100755 --- a/scripts/blocklist-skylink.sh +++ b/scripts/blocklist-skylink.sh @@ -34,18 +34,16 @@ else skylinks=("$1") # just single skylink passed as input argument fi -# get local nginx ip adress -nginx_ip=$(docker inspect -f '{{range.NetworkSettings.Networks}}{{.IPAddress}}{{end}}' nginx) +# get local skyd ip adress +ipaddress=$(docker inspect -f '{{range.NetworkSettings.Networks}}{{.IPAddress}}{{end}}' sia) + +# get sia api password either from env variable if exists or from apipassword file in sia-data directory +apipassword=$(docker exec sia sh -c '[ ! -z "${SIA_API_PASSWORD}" ] && echo ${SIA_API_PASSWORD} || $(cat /sia-data/apipassword | tr -d '\n')') # iterate over provided skylinks and block them one by one for skylink in "${skylinks[@]}"; do - printf "Blocking ${skylink} ... " - status_code=$(curl --write-out '%{http_code}' --silent --output /dev/null --data "{\"add\":[\"$skylink\"]}" "http://${nginx_ip}:8000/skynet/blocklist") + echo "> Blocking ${skylink} ... " - # print blocklist response status code - if [ $status_code = "204" ]; then - echo "done" - else - echo "error $status_code" - fi + # POST /skynet/blocklist always returns 200 and in case of failure print error message + curl -A Sia-Agent -u "":${apipassword} --data "{\"add\":[\"$skylink\"]}" "http://${ipaddress}:9980/skynet/blocklist" done diff --git a/setup-scripts/blocklist-airtable.py b/setup-scripts/blocklist-airtable.py index 09711605..8bd9d2dc 100755 --- a/setup-scripts/blocklist-airtable.py +++ b/setup-scripts/blocklist-airtable.py @@ -1,6 +1,6 @@ #!/usr/bin/env python3 -from bot_utils import setup, send_msg +from bot_utils import get_api_password, setup, send_msg from random import randint from time import sleep @@ -11,6 +11,8 @@ import asyncio import requests import json +from requests.auth import HTTPBasicAuth + setup() @@ -38,14 +40,14 @@ def exec(command): async def block_skylinks_from_airtable(): - # Get nginx's IP before doing anything else. If this step fails we don't + # Get sia IP before doing anything else. If this step fails we don't # need to continue with the execution of the script. ipaddress = exec( - "docker inspect -f '{{range.NetworkSettings.Networks}}{{.IPAddress}}{{end}}' nginx" + "docker inspect -f '{{range.NetworkSettings.Networks}}{{.IPAddress}}{{end}}' sia" ) if ipaddress == "": - print("Nginx's IP could not be detected. Exiting.") + print("Skyd IP could not be detected. Exiting.") return print("Pulling blocked skylinks from Airtable via api integration") @@ -117,11 +119,13 @@ async def block_skylinks_from_airtable(): print( "Sending /skynet/blocklist request with " + str(len(skylinks)) - + " skylinks to siad through nginx" + + " skylinks to siad" ) response = requests.post( - "http://" + ipaddress + ":8000/skynet/blocklist", + "http://" + ipaddress + ":9980/skynet/blocklist", data=json.dumps({"add": skylinks}), + headers={"User-Agent": "Sia-Agent"}, + auth=HTTPBasicAuth("", get_api_password()), ) if response.status_code != 200: @@ -153,5 +157,5 @@ loop.run_until_complete(run_checks()) # --- BASH EQUIVALENT # skylinks=$(curl "https://api.airtable.com/v0/${AIRTABLE_BASE}/${AIRTABLE_TABLE}?fields%5B%5D=${AIRTABLE_FIELD}" -H "Authorization: Bearer ${AIRTABLE_KEY}" | python3 -c "import sys, json; print('[\"' + '\",\"'.join([entry['fields']['Link'] for entry in json.load(sys.stdin)['records']]) + '\"]')") -# ipaddress=$(docker inspect -f '{{range.NetworkSettings.Networks}}{{.IPAddress}}{{end}}' nginx) +# ipaddress=$(docker inspect -f '{{range.NetworkSettings.Networks}}{{.IPAddress}}{{end}}' sia) # curl --data "{\"add\" : ${skylinks}}" "${ipaddress}:8000/skynet/blocklist" From b4d111871d70c6f02e536d1e85a0dfa28404cbf1 Mon Sep 17 00:00:00 2001 From: Karol Wypchlo Date: Tue, 15 Mar 2022 23:20:55 +0100 Subject: [PATCH 32/55] remove nginx prune script --- scripts/README.md | 6 ----- scripts/lib/nginx-prune-cache-subscript.sh | 30 ---------------------- scripts/nginx-prune.sh | 9 ------- setup-scripts/support/crontab | 1 - 4 files changed, 46 deletions(-) delete mode 100755 scripts/lib/nginx-prune-cache-subscript.sh delete mode 100755 scripts/nginx-prune.sh diff --git a/scripts/README.md b/scripts/README.md index 2085eff7..e7b909b4 100644 --- a/scripts/README.md +++ b/scripts/README.md @@ -29,12 +29,6 @@ the health check. The `portal-upgrade.sh` script upgrades the docker images for a portal and clears and leftover images. -**nginx-prune.sh**\ -The `nginx-prune.sh` script deletes all entries from nginx cache larger than -the given size and smaller entries until nginx cache disk size is smaller than -the given cache size limit. Both values are configured in -`lib/nginx-prune-cache-subscript.sh`. The script doesn't require `sudo`. - ## Webportal Upgrade Procedures TODO... diff --git a/scripts/lib/nginx-prune-cache-subscript.sh b/scripts/lib/nginx-prune-cache-subscript.sh deleted file mode 100755 index 99edb899..00000000 --- a/scripts/lib/nginx-prune-cache-subscript.sh +++ /dev/null @@ -1,30 +0,0 @@ -#!/usr/local/bin/bash - -# This subscript is expected to be run inside docker container using 'bash' -# image. The image is based on Alpine Linux. It's tools (find, stat, awk, sort) -# are non-standard versions from BusyBox. - -MAX_CACHE_DIR_SIZE=20000000000 -MAX_KEEP_FILE_SIZE=1000000000 - -total=0 - -# We sort files by time, newest files are first. Format is: -# time (last modification as seconds since Epoch), filepath, size (bytes) -find /home/user/skynet-webportal/docker/data/nginx/cache -type f -exec stat -c "%Y %n %s" {} + | sort -rgk1 | while read line -do - size=$(echo $line | awk '{print $3}') - new_total=$(($total + $size)) - - # We always delete all files larger than MAX_KEEP_FILE_SIZE. - # We keep all files smaller than MAX_KEEP_FILE_SIZE when cache size is - # below MAX_CACHE_DIR_SIZE, then we delete also smaller files. - if (("$size" <= "$MAX_KEEP_FILE_SIZE" && "$new_total" < "$MAX_CACHE_DIR_SIZE")) - then - total=$new_total - continue - fi - - filename=$(echo $line | awk '{print $2}') - rm $filename -done diff --git a/scripts/nginx-prune.sh b/scripts/nginx-prune.sh deleted file mode 100755 index ea5a1384..00000000 --- a/scripts/nginx-prune.sh +++ /dev/null @@ -1,9 +0,0 @@ -#!/bin/bash - -# We execute the nginx cache pruning subscript from docker container so that we -# can run the pruning script in user crontab without sudo. -docker run --rm -v /home/user:/home/user bash /home/user/skynet-webportal/scripts/lib/nginx-prune-cache-subscript.sh - -# Some cache files are deleted, but are kept open, we hot reload nginx to get -# them closed and removed from filesystem. -docker exec nginx nginx -s reload diff --git a/setup-scripts/support/crontab b/setup-scripts/support/crontab index 2181d09c..7fffdfb9 100644 --- a/setup-scripts/support/crontab +++ b/setup-scripts/support/crontab @@ -5,4 +5,3 @@ 44 5 * * * /home/user/skynet-webportal/scripts/backup-aws-s3.sh 1>>/home/user/skynet-webportal/logs/backup-aws-s3.log 2>>/home/user/skynet-webportal/logs/backup-aws-s3.log 6 13 * * * /home/user/skynet-webportal/scripts/db_backup.sh 1>>/home/user/skynet-webportal/logs/db_backup.log 2>>/home/user/skynet-webportal/logs/db_backup.log 0 5 * * * /home/user/skynet-webportal/scripts/es_cleaner.py 1 http://localhost:9200 -15 * * * * /home/user/skynet-webportal/scripts/nginx-prune.sh From e78aa1dfb36550a94044a5f5806088ffb49a3a00 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 16 Mar 2022 08:58:37 +0000 Subject: [PATCH 33/55] build(deps): bump @fontsource/source-sans-pro in /packages/website Bumps [@fontsource/source-sans-pro](https://github.com/fontsource/fontsource/tree/HEAD/packages/source-sans-pro) from 4.5.3 to 4.5.4. - [Release notes](https://github.com/fontsource/fontsource/releases) - [Changelog](https://github.com/fontsource/fontsource/blob/main/CHANGELOG.md) - [Commits](https://github.com/fontsource/fontsource/commits/HEAD/packages/source-sans-pro) --- updated-dependencies: - dependency-name: "@fontsource/source-sans-pro" dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- packages/website/package.json | 2 +- packages/website/yarn.lock | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/packages/website/package.json b/packages/website/package.json index 38de206a..1d284124 100644 --- a/packages/website/package.json +++ b/packages/website/package.json @@ -6,7 +6,7 @@ "author": "Skynet Labs.", "dependencies": { "@fontsource/sora": "4.5.3", - "@fontsource/source-sans-pro": "4.5.3", + "@fontsource/source-sans-pro": "4.5.4", "@svgr/webpack": "6.2.1", "bytes": "3.1.2", "classnames": "2.3.1", diff --git a/packages/website/yarn.lock b/packages/website/yarn.lock index 7ef765a0..22f37115 100644 --- a/packages/website/yarn.lock +++ b/packages/website/yarn.lock @@ -1103,10 +1103,10 @@ resolved "https://registry.yarnpkg.com/@fontsource/sora/-/sora-4.5.3.tgz#987c9b43acb00c9e3fa5377ebcedfd4ec9b760a7" integrity sha512-0ipYkroLonvChAyLajgIt6mImXMhvjrHwD5g7iX2ZR1eJ4hLDnwq6haW5pSeehe79lPjgp0BX6ZHivFIP0xR2g== -"@fontsource/source-sans-pro@4.5.3": - version "4.5.3" - resolved "https://registry.yarnpkg.com/@fontsource/source-sans-pro/-/source-sans-pro-4.5.3.tgz#bdb1eeed5db70bcd1f68cd1e8c859834f0e6bc67" - integrity sha512-9xWGu3ArKsjf6+WVrNoCUywybTB3rIidpvOI2tByQpzYVOupFUv6qohyrjDrVvPb6XHJQTD0NIzisR7RKhiP7A== +"@fontsource/source-sans-pro@4.5.4": + version "4.5.4" + resolved "https://registry.yarnpkg.com/@fontsource/source-sans-pro/-/source-sans-pro-4.5.4.tgz#51510723ff40f446c7800f133e9ae604ae2f38d7" + integrity sha512-+YYw6HRvH9wYE+U2Hvxyossg+MHPApAj7VIjEqaXenNeNQa4U3uPD0e7pc+1Gic3srCQATN15O3S9WSFLXTmwQ== "@gatsbyjs/parcel-namer-relative-to-cwd@0.0.2": version "0.0.2" From 0ec9b396aa46b40af19e1c42f67a9cef68fea31c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Leszczyk?= Date: Mon, 14 Mar 2022 16:58:45 +0100 Subject: [PATCH 34/55] fix(dashboard-v2): styling fixes for active link in navbar dropdown --- .../src/components/DropdownMenu/DropdownMenuLink.js | 12 +++++------- .../dashboard-v2/src/components/NavBar/NavBar.js | 10 ++++++++-- 2 files changed, 13 insertions(+), 9 deletions(-) diff --git a/packages/dashboard-v2/src/components/DropdownMenu/DropdownMenuLink.js b/packages/dashboard-v2/src/components/DropdownMenu/DropdownMenuLink.js index 45a86483..426501c4 100644 --- a/packages/dashboard-v2/src/components/DropdownMenu/DropdownMenuLink.js +++ b/packages/dashboard-v2/src/components/DropdownMenu/DropdownMenuLink.js @@ -3,18 +3,16 @@ import PropTypes from "prop-types"; const DropdownLink = styled.a.attrs({ className: `m-0 border-t border-palette-200/50 h-[60px] - whitespace-nowrap transition-colors text-current + whitespace-nowrap transition-colors hover:bg-palette-100/50 flex items-center pr-8 pl-6 py-4 gap-4 first:border-0`, })``; export const DropdownMenuLink = ({ active, icon: Icon, label, ...props }) => ( - <> - - {Icon ? : null} - {label} - - + + {Icon ? : null} + {label} + ); DropdownMenuLink.propTypes = { diff --git a/packages/dashboard-v2/src/components/NavBar/NavBar.js b/packages/dashboard-v2/src/components/NavBar/NavBar.js index 2b53f2be..7fa52109 100644 --- a/packages/dashboard-v2/src/components/NavBar/NavBar.js +++ b/packages/dashboard-v2/src/components/NavBar/NavBar.js @@ -68,8 +68,14 @@ export const NavBar = () => ( - - + + From 60b6fd2a48502782f424474a3fdf9274c54b34d0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Leszczyk?= Date: Tue, 15 Mar 2022 15:53:02 +0100 Subject: [PATCH 35/55] fix(dashboard-v2): fix navbar dropdown hiding behind positioned content --- .../src/components/DropdownMenu/DropdownMenu.js | 2 +- packages/dashboard-v2/src/components/NavBar/NavBar.js | 11 +++++++++-- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/packages/dashboard-v2/src/components/DropdownMenu/DropdownMenu.js b/packages/dashboard-v2/src/components/DropdownMenu/DropdownMenu.js index 461a9b7e..86cbad5f 100644 --- a/packages/dashboard-v2/src/components/DropdownMenu/DropdownMenu.js +++ b/packages/dashboard-v2/src/components/DropdownMenu/DropdownMenu.js @@ -30,7 +30,7 @@ const TriggerIcon = styled(ChevronDownIcon).attrs({ `; const Flyout = styled.div.attrs(({ open }) => ({ - className: `absolute top-full right-0 p-0 + className: `absolute top-full right-0 p-0 z-10 border rounded border-palette-100 bg-white shadow-md shadow-palette-200/50 ${open ? "visible" : "invisible"}`, diff --git a/packages/dashboard-v2/src/components/NavBar/NavBar.js b/packages/dashboard-v2/src/components/NavBar/NavBar.js index 7fa52109..6cef6df5 100644 --- a/packages/dashboard-v2/src/components/NavBar/NavBar.js +++ b/packages/dashboard-v2/src/components/NavBar/NavBar.js @@ -9,7 +9,7 @@ import { PageContainer } from "../PageContainer"; import { NavBarLink, NavBarSection } from "."; const NavBarContainer = styled.div.attrs({ - className: `grid sticky top-0 bg-white`, + className: `grid sticky top-0 bg-white z-10`, })``; const NavBarBody = styled.nav.attrs({ @@ -68,7 +68,14 @@ export const NavBar = () => ( - + Date: Tue, 15 Mar 2022 15:54:10 +0100 Subject: [PATCH 36/55] feat(dashboard-v2): add global typography styles --- packages/dashboard-v2/src/styles/global.css | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/packages/dashboard-v2/src/styles/global.css b/packages/dashboard-v2/src/styles/global.css index ae86596a..e0238aad 100644 --- a/packages/dashboard-v2/src/styles/global.css +++ b/packages/dashboard-v2/src/styles/global.css @@ -39,7 +39,14 @@ font-size: 1rem; } h6 { - @apply uppercase; - font-size: 0.875rem; + @apply uppercase text-xs; + } + + p { + @apply mt-2; + } + + hr { + @apply border-t-palette-200; } } From 4a5be18dae646acbc387b57ab207eb9ef12109b5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Leszczyk?= Date: Tue, 15 Mar 2022 15:54:34 +0100 Subject: [PATCH 37/55] fix(dashboard-v2): fix Switch toggle shrinking in narrow spaces --- packages/dashboard-v2/src/components/Switch/Switch.js | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/packages/dashboard-v2/src/components/Switch/Switch.js b/packages/dashboard-v2/src/components/Switch/Switch.js index ed24bc92..02b361c0 100644 --- a/packages/dashboard-v2/src/components/Switch/Switch.js +++ b/packages/dashboard-v2/src/components/Switch/Switch.js @@ -21,7 +21,7 @@ const Label = styled.label.attrs({ `; const Toggle = styled.span.attrs({ - className: `flex flex-row items-center justify-between + className: `flex flex-row items-center justify-between shrink-0 w-[44px] h-[22px] bg-white rounded-full border border-palette-200 relative cursor-pointer`, })` @@ -45,7 +45,7 @@ const TogglePin = styled.span.attrs(({ $checked }) => ({ } `; -export const Switch = ({ children, defaultChecked, onChange, ...props }) => { +export const Switch = ({ children, defaultChecked, labelClassName, onChange, ...props }) => { const id = useMemo(nanoid, [onChange]); const [checked, setChecked] = useState(defaultChecked); @@ -56,7 +56,7 @@ export const Switch = ({ children, defaultChecked, onChange, ...props }) => { return ( setChecked(ev.target.checked)} id={id} /> -