From 18059ad3f3c3462ffb99714680d8c681a49971d5 Mon Sep 17 00:00:00 2001 From: Redm4x Date: Wed, 18 Oct 2023 12:55:31 -0400 Subject: [PATCH 1/8] Prevent closing tx modal --- .../components/layout/TransactionModal.tsx | 9 ++++---- deploy-web/src/components/shared/Popup.tsx | 2 +- .../context/WalletProvider/WalletProvider.tsx | 21 +++++++++++++------ 3 files changed, 21 insertions(+), 11 deletions(-) diff --git a/deploy-web/src/components/layout/TransactionModal.tsx b/deploy-web/src/components/layout/TransactionModal.tsx index ce00a737f..9c810df58 100644 --- a/deploy-web/src/components/layout/TransactionModal.tsx +++ b/deploy-web/src/components/layout/TransactionModal.tsx @@ -3,18 +3,19 @@ import { Popup } from "../shared/Popup"; import { Box, CircularProgress, Typography } from "@mui/material"; type Props = { + state: "waitingForApproval" | "broadcasting"; open: boolean; - onClose: () => void; + onClose?: () => void; children?: ReactNode; }; -export const TransactionModal: React.FunctionComponent = ({ open, onClose }) => { +export const TransactionModal: React.FunctionComponent = ({ state, open, onClose }) => { return ( Transaction Pending} + title={state === "waitingForApproval" ? <>Waiting for tx approval : <>Transaction Pending} actions={[]} onClose={onClose} maxWidth="xs" @@ -26,7 +27,7 @@ export const TransactionModal: React.FunctionComponent = ({ open, onClose
- BROADCASTING TRANSACTION... + {state === "waitingForApproval" ? "APPROVE OR REJECT TX TO CONTINUE..." : "BROADCASTING TRANSACTION..."}
diff --git a/deploy-web/src/components/shared/Popup.tsx b/deploy-web/src/components/shared/Popup.tsx index dbae2fcff..e610fbc1a 100644 --- a/deploy-web/src/components/shared/Popup.tsx +++ b/deploy-web/src/components/shared/Popup.tsx @@ -167,7 +167,7 @@ export const Popup: React.FC = props => { if (props.title) { component.push( - onClose(event, "action")}> + onClose(event, "action") : undefined}> {props.title} ); diff --git a/deploy-web/src/context/WalletProvider/WalletProvider.tsx b/deploy-web/src/context/WalletProvider/WalletProvider.tsx index 76ed64449..b44c0bd03 100644 --- a/deploy-web/src/context/WalletProvider/WalletProvider.tsx +++ b/deploy-web/src/context/WalletProvider/WalletProvider.tsx @@ -8,7 +8,7 @@ import { useSnackbar } from "notistack"; import { Snackbar } from "@src/components/shared/Snackbar"; import { customRegistry } from "@src/utils/customRegistry"; import { TransactionModal } from "@src/components/layout/TransactionModal"; -import { OpenInNew, WindowSharp } from "@mui/icons-material"; +import { OpenInNew } from "@mui/icons-material"; import { useTheme } from "@mui/material"; import { event } from "nextjs-google-analytics"; import { AnalyticsEvents } from "@src/utils/analytics"; @@ -69,6 +69,7 @@ export const WalletProvider = ({ children }) => { const [isWindowLoaded, setIsWindowLoaded] = useState(false); const [isWalletLoaded, setIsWalletLoaded] = useState(false); const [isBroadcastingTx, setIsBroadcastingTx] = useState(false); + const [isWaitingForApproval, setIsWaitingForApproval] = useState(false); const { enqueueSnackbar, closeSnackbar } = useSnackbar(); const isMounted = useRef(true); const sigingClient = useRef(null); @@ -264,7 +265,7 @@ export const WalletProvider = ({ children }) => { } async function signAndBroadcastTx(msgs: EncodeObject[]): Promise { - setIsBroadcastingTx(true); + setIsWaitingForApproval(true); let pendingSnackbarKey = null; try { const client = await getStargateClient(); @@ -283,7 +284,8 @@ export const WalletProvider = ({ children }) => { }, "" ); - + setIsWaitingForApproval(false); + setIsBroadcastingTx(true); pendingSnackbarKey = enqueueSnackbar(, { variant: "info", autoHideDuration: null @@ -292,6 +294,8 @@ export const WalletProvider = ({ children }) => { const txRawBytes = Uint8Array.from(TxRaw.encode(txRaw).finish()); const txResult = await client.broadcastTx(txRawBytes); + setIsBroadcastingTx(false); + if (txResult.code !== 0) { throw new Error(txResult.rawLog); } @@ -364,11 +368,17 @@ export const WalletProvider = ({ children }) => { closeSnackbar(pendingSnackbarKey); } + setIsWaitingForApproval(false); setIsBroadcastingTx(false); } } - const showTransactionSnackbar = (snackTitle, snackMessage, transactionHash, snackVariant) => { + const showTransactionSnackbar = ( + snackTitle: string, + snackMessage: string, + transactionHash: string, + snackVariant: React.ComponentProps["iconVariant"] + ) => { enqueueSnackbar( { > {children} - setIsBroadcastingTx(false)} /> + ); }; @@ -455,4 +465,3 @@ const TransactionSnackbarContent = ({ snackMessage, transactionHash }) => { ); }; - From 23528bde542b58f2440f48eaf9e02ea4a881ef82 Mon Sep 17 00:00:00 2001 From: Redm4x Date: Wed, 18 Oct 2023 13:03:18 -0400 Subject: [PATCH 2/8] Add link to FAQ in shell connection lost message --- .../components/deploymentDetail/DeploymentLeaseShell.tsx | 9 ++++++++- .../src/components/get-started/CreateWalletSection.tsx | 5 +---- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/deploy-web/src/components/deploymentDetail/DeploymentLeaseShell.tsx b/deploy-web/src/components/deploymentDetail/DeploymentLeaseShell.tsx index 806ee38d3..c58b782d3 100644 --- a/deploy-web/src/components/deploymentDetail/DeploymentLeaseShell.tsx +++ b/deploy-web/src/components/deploymentDetail/DeploymentLeaseShell.tsx @@ -13,6 +13,8 @@ import { LeaseShellCode } from "@src/types/shell"; import { useCustomWebSocket } from "@src/hooks/useCustomWebSocket"; import { LeaseDto } from "@src/types/deployment"; import { useProviderList } from "@src/queries/useProvidersQuery"; +import Link from "next/link"; +import LaunchIcon from "@mui/icons-material/Launch"; type Props = { leases: LeaseDto[]; @@ -271,7 +273,12 @@ export const DeploymentLeaseShell: React.FunctionComponent = ({ leases }) {isConnectionClosed && ( - The connection to your Cloudmos Shell was lost. + The connection to your Cloudmos Shell was lost. ( + + More Info + + + ) )} diff --git a/deploy-web/src/components/get-started/CreateWalletSection.tsx b/deploy-web/src/components/get-started/CreateWalletSection.tsx index f87bcb67e..5938bfdca 100644 --- a/deploy-web/src/components/get-started/CreateWalletSection.tsx +++ b/deploy-web/src/components/get-started/CreateWalletSection.tsx @@ -1,10 +1,7 @@ import React from "react"; import { makeStyles } from "tss-react/mui"; -import { Alert, Box, Button, useTheme } from "@mui/material"; +import { Alert, Box, useTheme } from "@mui/material"; import { useRouter } from "next/router"; -import Link from "next/link"; -import { UrlService } from "@src/utils/urlUtils"; -import ChevronLeftIcon from "@mui/icons-material/ChevronLeft"; import { ExternalLink } from "../shared/ExternalLink"; const useStyles = makeStyles()(theme => ({ From a1df928106e4859745f210045e278941d5b8a111 Mon Sep 17 00:00:00 2001 From: Redm4x Date: Wed, 18 Oct 2023 13:41:54 -0400 Subject: [PATCH 3/8] Add faq entry for tab completion --- .../components/deploymentDetail/ShellDownloadModal.tsx | 2 +- deploy-web/src/pages/faq/index.tsx | 9 +++++++++ 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/deploy-web/src/components/deploymentDetail/ShellDownloadModal.tsx b/deploy-web/src/components/deploymentDetail/ShellDownloadModal.tsx index 3e2d1d093..992baa169 100644 --- a/deploy-web/src/components/deploymentDetail/ShellDownloadModal.tsx +++ b/deploy-web/src/components/deploymentDetail/ShellDownloadModal.tsx @@ -69,7 +69,7 @@ export const ShellDownloadModal = ({ selectedLease, onCloseClick, selectedServic Download file - Enter the path of a file on the server to be downloaded. Example: public/index.html + Enter the path of a file on the server to be downloaded to your computer. Example: ~/app/logs.txt
diff --git a/deploy-web/src/pages/faq/index.tsx b/deploy-web/src/pages/faq/index.tsx index 6186a2bb3..c62c03671 100644 --- a/deploy-web/src/pages/faq/index.tsx +++ b/deploy-web/src/pages/faq/index.tsx @@ -20,6 +20,9 @@ export default function FaqPage() {
  • Can't access shell: "The connection to your Cloudmos Shell was lost."
  • +
  • + Shell: UP arrow and TAB autocompletion does not work +
  • Error while sending manifest to provider. Error: manifest cross-validation error: group "X": service "X": CPU/Memory resources mismatch for ID 1 @@ -76,6 +79,12 @@ export default function FaqPage() {
  • +

    Shell: UP arrow and TAB autocompletion does not work

    +

    + Some docker images use "sh" as the default shell. This shell does not support up arrow and TAB autocompletion. You may try sending the "bash" command + to switch to a bash shell which support those feature. +

    +

    Error while sending manifest to provider. Error: manifest cross-validation error: group "X": service "X": CPU/Memory resources mismatch for ID 1

    From 30b051532273bdb93ed7b4678c383b1f1ce5a157 Mon Sep 17 00:00:00 2001 From: Redm4x Date: Wed, 18 Oct 2023 16:43:41 -0400 Subject: [PATCH 4/8] Show warning when trying to use up arrow in sh shell --- .../deploymentDetail/DeploymentLeaseShell.tsx | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/deploy-web/src/components/deploymentDetail/DeploymentLeaseShell.tsx b/deploy-web/src/components/deploymentDetail/DeploymentLeaseShell.tsx index c58b782d3..0e244a27c 100644 --- a/deploy-web/src/components/deploymentDetail/DeploymentLeaseShell.tsx +++ b/deploy-web/src/components/deploymentDetail/DeploymentLeaseShell.tsx @@ -30,6 +30,7 @@ export const DeploymentLeaseShell: React.FunctionComponent = ({ leases }) const [selectedLease, setSelectedLease] = useState(null); const [isShowingDownloadModal, setIsShowingDownloadModal] = useState(false); const [isChangingSocket, setIsChangingSocket] = useState(false); + const [showArrowAndTabWarning, setShowArrowAndTabWarning] = useState(false); const { data: providers } = useProviderList(); const { localCert, isLocalCertMatching, createCertificate, isCreatingCert } = useCertificate(); const providerInfo = providers?.find(p => p.owner === selectedLease?.provider); @@ -105,6 +106,12 @@ export const DeploymentLeaseShell: React.FunctionComponent = ({ leases }) if (message?.data) { let parsedData = Buffer.from(message.data).toString("utf-8", 1); + // Check if parsedData is either ^[[A, ^[[B, ^[[C or ^[[D + const arrowKeyPattern = /\^\[\[[A-D]/; + if (arrowKeyPattern.test(parsedData)) { + setShowArrowAndTabWarning(true); + } + let exitCode, errorMessage; try { const jsonData = JSON.parse(parsedData); @@ -270,6 +277,15 @@ export const DeploymentLeaseShell: React.FunctionComponent = ({ leases }) )} + {showArrowAndTabWarning && ( + + + Why is my UP arrow and TAB autocompletion not working? + + + + )} + {isConnectionClosed && ( From 6c71c4a4faeb339ce79222707fed420d1c3ca280 Mon Sep 17 00:00:00 2001 From: Redm4x Date: Thu, 19 Oct 2023 10:17:21 -0400 Subject: [PATCH 5/8] Add warning when trying to download from URL --- .../components/deploymentDetail/ShellDownloadModal.tsx | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/deploy-web/src/components/deploymentDetail/ShellDownloadModal.tsx b/deploy-web/src/components/deploymentDetail/ShellDownloadModal.tsx index 992baa169..016cbd884 100644 --- a/deploy-web/src/components/deploymentDetail/ShellDownloadModal.tsx +++ b/deploy-web/src/components/deploymentDetail/ShellDownloadModal.tsx @@ -89,7 +89,11 @@ export const ShellDownloadModal = ({ selectedLease, onCloseClick, selectedServic control={control} name="filePath" rules={{ - required: true + required: "File path is required.", + pattern: { + value: /^(?!https?:).*/i, + message: "Should be a valid path on the server, not a URL." + } }} render={({ field, fieldState }) => { return ( @@ -97,8 +101,8 @@ export const ShellDownloadModal = ({ selectedLease, onCloseClick, selectedServic {...field} type="text" label="File path" - error={!!fieldState.invalid} - helperText={fieldState.invalid && "File path is required."} + error={!!fieldState.error} + helperText={fieldState.error?.message} variant="outlined" autoFocus placeholder="Type a valid file path" From 974d757b382ea1a86977c0ae6a09407334dfbbc3 Mon Sep 17 00:00:00 2001 From: Redm4x Date: Thu, 19 Oct 2023 11:00:01 -0400 Subject: [PATCH 6/8] Fix download file --- .../src/components/deploymentDetail/ShellDownloadModal.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/deploy-web/src/components/deploymentDetail/ShellDownloadModal.tsx b/deploy-web/src/components/deploymentDetail/ShellDownloadModal.tsx index 016cbd884..99689dc1b 100644 --- a/deploy-web/src/components/deploymentDetail/ShellDownloadModal.tsx +++ b/deploy-web/src/components/deploymentDetail/ShellDownloadModal.tsx @@ -45,7 +45,7 @@ export const ShellDownloadModal = ({ selectedLease, onCloseClick, selectedServic }); const onSubmit = async ({ filePath }) => { - downloadFileFromShell(providerInfo.host_uri, selectedLease.dseq, selectedLease.gseq, selectedLease.oseq, selectedService, filePath); + downloadFileFromShell(providerInfo.hostUri, selectedLease.dseq, selectedLease.gseq, selectedLease.oseq, selectedService, filePath); event(AnalyticsEvents.DOWNLOADED_SHELL_FILE, { category: "deployments", From f01618b2da7ac2a7c3b08e9add15657a074388a1 Mon Sep 17 00:00:00 2001 From: Redm4x Date: Thu, 19 Oct 2023 11:39:30 -0400 Subject: [PATCH 7/8] Improve download file error handling --- .../deploymentDetail/ShellDownloadModal.tsx | 5 +++-- .../BackgroundTaskProvider.tsx | 20 ++++++++++++------- 2 files changed, 16 insertions(+), 9 deletions(-) diff --git a/deploy-web/src/components/deploymentDetail/ShellDownloadModal.tsx b/deploy-web/src/components/deploymentDetail/ShellDownloadModal.tsx index 99689dc1b..00de2fa9b 100644 --- a/deploy-web/src/components/deploymentDetail/ShellDownloadModal.tsx +++ b/deploy-web/src/components/deploymentDetail/ShellDownloadModal.tsx @@ -68,8 +68,9 @@ export const ShellDownloadModal = ({ selectedLease, onCloseClick, selectedServic Download file - - Enter the path of a file on the server to be downloaded to your computer. Example: ~/app/logs.txt + Enter the path of a file on the server to be downloaded to your computer. Example: /app/logs.txt + + This is an experimental feature and may not work reliably. diff --git a/deploy-web/src/context/BackgroundTaskProvider/BackgroundTaskProvider.tsx b/deploy-web/src/context/BackgroundTaskProvider/BackgroundTaskProvider.tsx index eedc21941..c728203b8 100644 --- a/deploy-web/src/context/BackgroundTaskProvider/BackgroundTaskProvider.tsx +++ b/deploy-web/src/context/BackgroundTaskProvider/BackgroundTaskProvider.tsx @@ -158,24 +158,29 @@ export const BackgroundTaskProvider = ({ children }) => { let fileContent: Buffer | null = null; ws.onmessage = event => { - let jsonData, exitCode, errorMessage; + let exitCode, errorMessage; try { const message = JSON.parse(event.data).message; const bufferData = Buffer.from(message.data.slice(1)); const stringData = bufferData.toString("utf-8").replace(/^\n|\n$/g, ""); - jsonData = JSON.parse(stringData); - exitCode = jsonData["exit_code"]; - errorMessage = jsonData["message"]; + try { + const jsonData = JSON.parse(stringData); + exitCode = jsonData["exit_code"]; + errorMessage = jsonData["message"]; + } catch (err) {} if (exitCode !== undefined) { if (errorMessage) { console.error(`An error has occured: ${errorMessage}`); + } else if (fileContent === null) { + console.log("File content null"); + } else { + console.log("Download done: " + fileContent.length); + isFinished = true; } - console.log("Download done: " + fileContent.length); - isFinished = true; ws.close(); } else { if (!fileContent) { @@ -188,6 +193,7 @@ export const BackgroundTaskProvider = ({ children }) => { } } catch (error) { console.log(error); + ws.close(); } }; @@ -202,7 +208,7 @@ export const BackgroundTaskProvider = ({ children }) => { } else { console.log("No file / Failed"); closeSnackbar(snackbarKey); - enqueueSnackbar("Failed to download logs", { variant: "error" }); + enqueueSnackbar("Failed to download file", { variant: "error" }); } }; ws.onopen = () => { From d247d03d79ba395d579abe8a2a236a5f14071620 Mon Sep 17 00:00:00 2001 From: Redm4x Date: Thu, 19 Oct 2023 13:13:51 -0400 Subject: [PATCH 8/8] Use UrlService for faq links --- .../src/components/deploymentDetail/DeploymentLeaseShell.tsx | 5 +++-- deploy-web/src/utils/urlUtils.ts | 2 +- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/deploy-web/src/components/deploymentDetail/DeploymentLeaseShell.tsx b/deploy-web/src/components/deploymentDetail/DeploymentLeaseShell.tsx index 0e244a27c..81160cbdd 100644 --- a/deploy-web/src/components/deploymentDetail/DeploymentLeaseShell.tsx +++ b/deploy-web/src/components/deploymentDetail/DeploymentLeaseShell.tsx @@ -15,6 +15,7 @@ import { LeaseDto } from "@src/types/deployment"; import { useProviderList } from "@src/queries/useProvidersQuery"; import Link from "next/link"; import LaunchIcon from "@mui/icons-material/Launch"; +import { UrlService } from "@src/utils/urlUtils"; type Props = { leases: LeaseDto[]; @@ -279,7 +280,7 @@ export const DeploymentLeaseShell: React.FunctionComponent = ({ leases }) {showArrowAndTabWarning && ( - + Why is my UP arrow and TAB autocompletion not working? @@ -290,7 +291,7 @@ export const DeploymentLeaseShell: React.FunctionComponent = ({ leases }) {isConnectionClosed && ( The connection to your Cloudmos Shell was lost. ( - + More Info diff --git a/deploy-web/src/utils/urlUtils.ts b/deploy-web/src/utils/urlUtils.ts index 211b18a22..d49f9429a 100644 --- a/deploy-web/src/utils/urlUtils.ts +++ b/deploy-web/src/utils/urlUtils.ts @@ -30,7 +30,7 @@ export class UrlService { static priceCompareCustom = (cpu: number, memory: number, storage: number, memoryUnit: string, storageUnit: string) => `/price-compare${appendSearchParams({ cpu, memory, storage, memoryUnit, storageUnit })}`; static contact = () => "/contact"; - static faq = () => "/faq"; + static faq = (q?: string) => `/faq${q ? "#" + q : ""}`; static privacyPolicy = () => "/privacy-policy"; static termsOfService = () => "/terms-of-service"; static blocks = () => `/blocks`;