mirror of
https://github.com/logos-storage/logos-storage-marketplace-ui.git
synced 2026-01-02 13:33:06 +00:00
Use the debug info port to check the port forwarding
This commit is contained in:
parent
a102f3835a
commit
21fe557157
@ -1,32 +1,10 @@
|
||||
import { useQuery } from "@tanstack/react-query";
|
||||
import { CodexSdk } from "../../sdk/codex";
|
||||
import { Promises } from "../../utils/promises";
|
||||
import { Spinner } from "@codex-storage/marketplace-ui-components";
|
||||
import { useDebug } from "../../hooks/useDebug";
|
||||
|
||||
const throwOnError = true;
|
||||
|
||||
export function Debug() {
|
||||
const { data, isPending } = useQuery({
|
||||
queryFn: () =>
|
||||
CodexSdk.debug()
|
||||
.info()
|
||||
.then((s) => Promises.rejectOnError(s)),
|
||||
|
||||
queryKey: ["debug"],
|
||||
|
||||
// No need to retry because if the connection to the node
|
||||
// is back again, all the queries will be invalidated.
|
||||
retry: false,
|
||||
|
||||
// The client node should be local, so display the cache value while
|
||||
// making a background request looks good.
|
||||
staleTime: 0,
|
||||
|
||||
// Refreshing when focus returns can be useful if a user comes back
|
||||
// to the UI after performing an operation in the terminal.
|
||||
refetchOnWindowFocus: true,
|
||||
|
||||
// Throw the error to the error boundary
|
||||
throwOnError: true,
|
||||
});
|
||||
const { data, isPending } = useDebug(throwOnError);
|
||||
|
||||
if (isPending) {
|
||||
return (
|
||||
|
||||
@ -38,6 +38,11 @@
|
||||
margin-bottom: 0.5rem;
|
||||
}
|
||||
|
||||
.onboarding-codex {
|
||||
margin-top: 1rem;
|
||||
padding-left: 1rem;
|
||||
}
|
||||
|
||||
@keyframes rotate {
|
||||
from {
|
||||
transform: rotate(0deg); /* Start at 0 degrees */
|
||||
|
||||
@ -4,6 +4,7 @@ import "./OnBoardingStepThree.css";
|
||||
import { usePortForwarding } from "../../hooks/usePortForwarding";
|
||||
import { useCodexConnection } from "../../hooks/useCodexConnection";
|
||||
import {
|
||||
Alert,
|
||||
ButtonIcon,
|
||||
Input,
|
||||
SimpleText,
|
||||
@ -12,28 +13,33 @@ import { useEffect, useState } from "react";
|
||||
import { CodexSdk } from "../../sdk/codex";
|
||||
import { useQueryClient } from "@tanstack/react-query";
|
||||
import { usePersistence } from "../../hooks/usePersistence";
|
||||
import { useDebug } from "../../hooks/useDebug";
|
||||
import { DebugUtils } from "../../utils/debug";
|
||||
|
||||
type Props = {
|
||||
online: boolean;
|
||||
onStepValid: (valid: boolean) => void;
|
||||
};
|
||||
|
||||
const throwOnError = false;
|
||||
const defaultPort = 8070;
|
||||
|
||||
export function OnBoardingStepThree({ online, onStepValid }: Props) {
|
||||
const portForwarding = usePortForwarding(online);
|
||||
const codex = useCodexConnection();
|
||||
const persistence = usePersistence(codex.enabled);
|
||||
const codex = useDebug(throwOnError);
|
||||
const portForwarding = usePortForwarding(codex.data);
|
||||
const persistence = usePersistence(codex.isSuccess);
|
||||
const [url, setUrl] = useState(CodexSdk.url);
|
||||
const queryClient = useQueryClient();
|
||||
|
||||
useEffect(() => {
|
||||
onStepValid(online && portForwarding.enabled && codex.enabled);
|
||||
}, [portForwarding.enabled, codex.enabled, onStepValid, online]);
|
||||
onStepValid(online && portForwarding.enabled && codex.isSuccess);
|
||||
}, [portForwarding.enabled, codex.isSuccess, onStepValid, online]);
|
||||
|
||||
useEffect(() => {
|
||||
if (codex.enabled) {
|
||||
if (codex.isSuccess) {
|
||||
persistence.refetch();
|
||||
}
|
||||
}, [codex.enabled]);
|
||||
}, [codex.isSuccess]);
|
||||
|
||||
const onChange = (e: React.FormEvent<HTMLInputElement>) => {
|
||||
const value = e.currentTarget.value;
|
||||
@ -49,9 +55,22 @@ export function OnBoardingStepThree({ online, onStepValid }: Props) {
|
||||
|
||||
const InternetIcon = online ? CheckIcon : X;
|
||||
const PortForWarningIcon = portForwarding.enabled ? CheckIcon : X;
|
||||
const CodexIcon = codex.enabled ? CheckIcon : X;
|
||||
const CodexIcon = codex.isSuccess ? CheckIcon : X;
|
||||
const PersistenceIcon = persistence.enabled ? CheckIcon : ShieldAlert;
|
||||
|
||||
let hasPortForwarningWarning = false;
|
||||
let portValue = 0;
|
||||
|
||||
if (codex.isSuccess && codex.data) {
|
||||
const port = DebugUtils.getTcpPort(codex.data);
|
||||
if (port.error === false && port.data !== defaultPort) {
|
||||
hasPortForwarningWarning = true;
|
||||
}
|
||||
if (!port.error) {
|
||||
portValue = port.data;
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="index-column-section">
|
||||
<div className="onboarding-group">
|
||||
@ -102,6 +121,14 @@ export function OnBoardingStepThree({ online, onStepValid }: Props) {
|
||||
<SimpleText variant="light">
|
||||
Status indicator for port forwarding activation.
|
||||
</SimpleText>
|
||||
{portValue && (
|
||||
<>
|
||||
<br />
|
||||
<SimpleText variant="light">
|
||||
TCP Port detected: {portValue}.
|
||||
</SimpleText>
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
{!portForwarding.enabled && (
|
||||
<a
|
||||
@ -118,59 +145,72 @@ export function OnBoardingStepThree({ online, onStepValid }: Props) {
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
className={classnames(
|
||||
["onboarding-check"],
|
||||
["onboarding-check--valid", codex.enabled]
|
||||
)}>
|
||||
<CodexIcon
|
||||
<p>Codex</p>
|
||||
<div className="onboarding-codex">
|
||||
<div
|
||||
className={classnames(
|
||||
["onboarding-check-icon--valid", codex.enabled],
|
||||
["onboarding-check-icon--invalid", !codex.enabled]
|
||||
)}
|
||||
/>
|
||||
<div className="onboarding-check-line">
|
||||
<div>
|
||||
<p>Codex connection</p>
|
||||
<SimpleText variant="light">
|
||||
Status indicator for the Codex network.
|
||||
</SimpleText>
|
||||
["onboarding-check"],
|
||||
["onboarding-check--valid", codex.isSuccess]
|
||||
)}>
|
||||
<CodexIcon
|
||||
className={classnames(
|
||||
["onboarding-check-icon--valid", codex.isSuccess],
|
||||
["onboarding-check-icon--invalid", !codex.isSuccess]
|
||||
)}
|
||||
/>
|
||||
<div className="onboarding-check-line">
|
||||
<div>
|
||||
<p>Codex connection</p>
|
||||
<SimpleText variant="light">
|
||||
Status indicator for the Codex network.
|
||||
</SimpleText>
|
||||
</div>
|
||||
{!persistence.enabled && (
|
||||
<a
|
||||
className="onboarding-check-refresh"
|
||||
onClick={() => persistence.refetch()}>
|
||||
<RefreshCcw
|
||||
size={"1.25rem"}
|
||||
className={classnames([
|
||||
"onboarding-check-refresh--fetching",
|
||||
persistence.isFetching,
|
||||
])}
|
||||
/>
|
||||
</a>
|
||||
)}
|
||||
</div>
|
||||
{!persistence.enabled && (
|
||||
<a
|
||||
className="onboarding-check-refresh"
|
||||
onClick={() => persistence.refetch()}>
|
||||
<RefreshCcw
|
||||
size={"1.25rem"}
|
||||
className={classnames([
|
||||
"onboarding-check-refresh--fetching",
|
||||
persistence.isFetching,
|
||||
])}
|
||||
/>
|
||||
</a>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
className={classnames(
|
||||
["onboarding-check"],
|
||||
["onboarding-check--valid", persistence.enabled]
|
||||
)}>
|
||||
<PersistenceIcon
|
||||
<div
|
||||
className={classnames(
|
||||
["onboarding-check-icon--valid", persistence.enabled],
|
||||
["onboarding-check-icon--warning", !persistence.enabled]
|
||||
)}
|
||||
/>
|
||||
<div className="onboarding-check-line">
|
||||
<div>
|
||||
<p>Marketplace</p>
|
||||
<SimpleText variant="light">
|
||||
Status indicator for the marketplace on the Codex node.
|
||||
</SimpleText>
|
||||
["onboarding-check"],
|
||||
["onboarding-check--valid", persistence.enabled]
|
||||
)}>
|
||||
<PersistenceIcon
|
||||
className={classnames(
|
||||
["onboarding-check-icon--valid", persistence.enabled],
|
||||
["onboarding-check-icon--warning", !persistence.enabled]
|
||||
)}
|
||||
/>
|
||||
<div className="onboarding-check-line">
|
||||
<div>
|
||||
<p>Marketplace</p>
|
||||
<SimpleText variant="light">
|
||||
Status indicator for the marketplace on the Codex node.
|
||||
</SimpleText>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{hasPortForwarningWarning && (
|
||||
<Alert variant="warning" title="Warning">
|
||||
<span>
|
||||
It seems like you are using a different port than the default one (
|
||||
{defaultPort}). Be sure the port forwarning is enabled for the port
|
||||
you are running.
|
||||
</span>
|
||||
</Alert>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
31
src/hooks/useDebug.ts
Normal file
31
src/hooks/useDebug.ts
Normal file
@ -0,0 +1,31 @@
|
||||
import { useQuery } from "@tanstack/react-query";
|
||||
import { CodexSdk } from "../sdk/codex";
|
||||
import { Promises } from "../utils/promises";
|
||||
|
||||
export function useDebug(throwOnError: boolean) {
|
||||
const { data, isError, isPending, refetch, isSuccess } = useQuery({
|
||||
queryFn: () =>
|
||||
CodexSdk.debug()
|
||||
.info()
|
||||
.then((s) => Promises.rejectOnError(s)),
|
||||
|
||||
queryKey: ["debug"],
|
||||
|
||||
// No need to retry because if the connection to the node
|
||||
// is back again, all the queries will be invalidated.
|
||||
retry: false,
|
||||
|
||||
// The client node should be local, so display the cache value while
|
||||
// making a background request looks good.
|
||||
staleTime: 0,
|
||||
|
||||
// Refreshing when focus returns can be useful if a user comes back
|
||||
// to the UI after performing an operation in the terminal.
|
||||
refetchOnWindowFocus: true,
|
||||
|
||||
// Throw the error to the error boundary
|
||||
throwOnError,
|
||||
});
|
||||
|
||||
return { data, isPending, isError, isSuccess, refetch };
|
||||
}
|
||||
@ -1,19 +1,28 @@
|
||||
import { useQuery } from "@tanstack/react-query";
|
||||
import { Echo } from "../utils/echo";
|
||||
import { Errors } from "../utils/errors";
|
||||
import { CodexDebugInfo } from "@codex-storage/sdk-js";
|
||||
import { DebugUtils } from "../utils/debug";
|
||||
|
||||
type PortForwardingResponse = { reachable: boolean };
|
||||
|
||||
export function usePortForwarding(online: boolean) {
|
||||
export function usePortForwarding(info: CodexDebugInfo | undefined) {
|
||||
const { data, isFetching, refetch } = useQuery({
|
||||
queryFn: (): Promise<PortForwardingResponse> =>
|
||||
Echo.portForwarding().catch((e) => Errors.report(e)),
|
||||
queryFn: (): Promise<PortForwardingResponse> => {
|
||||
const port = DebugUtils.getTcpPort(info!);
|
||||
if (port.error) {
|
||||
Errors.report(port);
|
||||
return Promise.resolve({ reachable: false });
|
||||
} else {
|
||||
return Echo.portForwarding(port.data).catch((e) => Errors.report(e));
|
||||
}
|
||||
},
|
||||
queryKey: ["port-forwarding"],
|
||||
|
||||
initialData: { reachable: false },
|
||||
|
||||
// Enable only when the use has an internet connection
|
||||
enabled: !!online,
|
||||
enabled: !!info,
|
||||
|
||||
// No need to retry because we provide a retry button
|
||||
retry: false,
|
||||
|
||||
@ -138,6 +138,10 @@
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.index-column-section {
|
||||
max-width: 450px;
|
||||
}
|
||||
|
||||
.index-column-section:not(:first-child) {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
@ -12,6 +12,7 @@ import { OnBoardingStepThree } from "../components/OnBoarding/OnBoardingStepThre
|
||||
import { attributes } from "../utils/attributes";
|
||||
import { CodexLogo } from "../components/CodexLogo/CodexLogo";
|
||||
import { OnBoardingImage } from "../components/OnBoarding/OnBoardingImage";
|
||||
import { OnBoardingUtils } from "../utils/onboarding";
|
||||
|
||||
export const Route = createFileRoute("/")({
|
||||
component: Index,
|
||||
@ -24,7 +25,7 @@ export const Route = createFileRoute("/")({
|
||||
|
||||
function Index() {
|
||||
const [isStepValid, setIsStepValid] = useState(true);
|
||||
const [step, setStep] = useState(0);
|
||||
const [step, setStep] = useState(OnBoardingUtils.getStep());
|
||||
const online = useNetwork();
|
||||
const navigate = useNavigate({ from: "/" });
|
||||
const onStepValid = (valid: boolean) => setIsStepValid(valid);
|
||||
@ -39,6 +40,8 @@ function Index() {
|
||||
return;
|
||||
}
|
||||
|
||||
OnBoardingUtils.setStep(step + 1);
|
||||
|
||||
setStep(step + 1);
|
||||
setIsStepValid(false);
|
||||
};
|
||||
|
||||
23
src/utils/debug.ts
Normal file
23
src/utils/debug.ts
Normal file
@ -0,0 +1,23 @@
|
||||
import { CodexDebugInfo, CodexError, SafeValue } from "@codex-storage/sdk-js";
|
||||
|
||||
export const DebugUtils = {
|
||||
getTcpPort(info: CodexDebugInfo): SafeValue<number> {
|
||||
if (info.addrs.length === 0) {
|
||||
return { error: true, data: new CodexError("Not existing address") }
|
||||
}
|
||||
|
||||
const parts = info.addrs[0].split("/")
|
||||
|
||||
if (parts.length < 2) {
|
||||
return { error: true, data: new CodexError("Address misformated") }
|
||||
}
|
||||
|
||||
const port = parseInt(parts[parts.length - 1], 10)
|
||||
|
||||
if (isNaN(port)) {
|
||||
return { error: true, data: new CodexError("Port misformated") }
|
||||
}
|
||||
|
||||
return { error: false, data: port }
|
||||
}
|
||||
}
|
||||
@ -1,5 +1,5 @@
|
||||
export const Echo = {
|
||||
portForwarding: () => fetch(import.meta.env.VITE_GEO_IP_URL + "/port/8070")
|
||||
portForwarding: (port: number) => fetch(import.meta.env.VITE_GEO_IP_URL + "/port/" + port)
|
||||
.then((res) => res.json())
|
||||
|
||||
}
|
||||
9
src/utils/onboarding.ts
Normal file
9
src/utils/onboarding.ts
Normal file
@ -0,0 +1,9 @@
|
||||
export const OnBoardingUtils = {
|
||||
getStep() {
|
||||
return parseInt(localStorage.getItem("onboarding-step") || "0", 10)
|
||||
},
|
||||
|
||||
setStep(step: number) {
|
||||
localStorage.setItem("onboarding-step", step.toString())
|
||||
}
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user