Skip to content

Commit

Permalink
fix(ui): display error message when KERIA got issue
Browse files Browse the repository at this point in the history
  • Loading branch information
Vu Van Duc authored and Vu Van Duc committed Feb 26, 2025
1 parent ae2bc08 commit 4d36148
Show file tree
Hide file tree
Showing 5 changed files with 63 additions and 48 deletions.
7 changes: 4 additions & 3 deletions src/locales/en/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@
},
"button": {
"continue": "Continue",
"switch": "Switch to recover a wallet",
"switch": "Recover existing wallet",
"recoverydocumentation": "What’s a recovery phrase?"
},
"recoveryseedphrasedocs": {
Expand Down Expand Up @@ -646,7 +646,7 @@
"continue": "Confirm",
"lock": "Try again in 1 minute",
"clear": "Clear all",
"switch": "Switch to create new wallet"
"switch": "Create new wallet"
},
"paragraph": {
"top": "Please verify your recovery phrase to recover your wallet. To start typing click on the first option."
Expand Down Expand Up @@ -839,7 +839,8 @@
"invalidbooturl": "Enter a valid boot URL",
"invalidconnecturl": "Enter a valid connect URL",
"mismatchconnecturl": "This connect URL doesn’t match the boot URL",
"recoverymismatchconnecturl": "Please check this connect URL matches the original boot URL used for onboarding and that your agent is still active"
"recoverymismatchconnecturl": "Please check this connect URL matches the original boot URL used for onboarding and that your agent is still active",
"unknownissue": "We could not reach this server. Either the server is down, you have entered an incorrect URL or you have internet connectivity issues."
}
},
"operationspasswordregex": {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { IonButton, IonIcon } from "@ionic/react";
import { wordlists } from "bip39";
import { closeOutline, refreshOutline } from "ionicons/icons";
import { closeOutline, addOutline } from "ionicons/icons";
import { forwardRef, useImperativeHandle, useRef, useState } from "react";
import { Agent } from "../../../core/agent/agent";
import { i18n } from "../../../i18n";
Expand Down Expand Up @@ -305,7 +305,7 @@ const RecoverySeedPhraseModule = forwardRef<
: undefined
}
tertiaryButtonAction={() => setSwitchModeModal(true)}
tertiaryButtonIcon={refreshOutline}
tertiaryButtonIcon={addOutline}
/>
</div>
<AlertFail
Expand Down
5 changes: 5 additions & 0 deletions src/ui/pages/CreateSSIAgent/CreateSSIAgent.scss
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,11 @@
}
}

.connect-url-input,
.boot-url-input {
margin-bottom: 0.25rem;
}

.page-header {
ion-toolbar {
--background: transparent;
Expand Down
8 changes: 4 additions & 4 deletions src/ui/pages/CreateSSIAgent/CreateSSIAgent.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -811,7 +811,7 @@ describe("SSI agent page: show error", () => {
Promise.reject(new Error(Agent.KERIA_BOOT_FAILED_BAD_NETWORK))
);

const { getByTestId } = render(
const { getByTestId, getByText } = render(
<IonReactMemoryRouter history={history}>
<Provider store={storeMocked}>
<CreateSSIAgent />
Expand All @@ -824,9 +824,9 @@ describe("SSI agent page: show error", () => {
});

await waitFor(() => {
expect(dispatchMock).toBeCalledWith(
setToastMsg(ToastMsgType.UNKNOWN_ERROR)
);
expect(
getByText(EN_TRANSLATIONS.ssiagent.error.unknownissue)
).toBeVisible();
});
});
});
87 changes: 48 additions & 39 deletions src/ui/pages/CreateSSIAgent/CreateSSIAgent.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import {
openOutline,
scanOutline,
refreshOutline,
addOutline,
} from "ionicons/icons";
import {
MouseEvent as ReactMouseEvent,
Expand Down Expand Up @@ -43,7 +44,7 @@ import {
ONBOARDING_DOCUMENTATION_LINK,
RECOVERY_DOCUMENTATION_LINK,
} from "../../globals/constants";
import { OperationType, ToastMsgType } from "../../globals/types";
import { OperationType } from "../../globals/types";
import { useAppIonRouter } from "../../hooks";
import { showError } from "../../utils/error";
import { isValidHttpUrl } from "../../utils/urlChecker";
Expand All @@ -52,6 +53,7 @@ import { OnboardingMode } from "../../components/SwitchOnboardingModeModal/Switc

const SSI_URLS_EMPTY = "SSI url is empty";
const SEED_PHRASE_EMPTY = "Invalid seed phrase";
const SEED_PHRASE_NOT_BOOTED = "agent does not exist for controller";

const InputError = ({
showError,
Expand Down Expand Up @@ -80,6 +82,7 @@ const CreateSSIAgent = () => {
const [openInfo, setOpenInfo] = useState(false);
const [loading, setLoading] = useState(false);
const [hasMismatchError, setHasMismatchError] = useState(false);
const [unknowError, setUnknownError] = useState(false);
const [isInvalidBootUrl, setIsInvalidBootUrl] = useState(false);
const [isInvalidConnectUrl, setInvalidConnectUrl] = useState(false);
const [showSwitchModeModal, setSwitchModeModal] = useState(false);
Expand Down Expand Up @@ -135,6 +138,11 @@ const CreateSSIAgent = () => {
const handleError = (error: Error) => {
const errorMessage = error.message;

if ((error.cause as Error)?.message.includes(SEED_PHRASE_NOT_BOOTED)) {
setUnknownError(true);
return;
}

if (Agent.KERIA_BOOT_FAILED === errorMessage) {
setIsInvalidBootUrl(true);
}
Expand All @@ -153,12 +161,8 @@ const CreateSSIAgent = () => {
Agent.KERIA_CONNECT_FAILED_BAD_NETWORK,
].includes(errorMessage)
) {
showError(
"Unable to boot or connect keria",
error,
dispatch,
ToastMsgType.UNKNOWN_ERROR
);
setUnknownError(true);
showError("Unable to boot or connect keria", error);
}
};

Expand Down Expand Up @@ -198,16 +202,6 @@ const CreateSSIAgent = () => {
ionRouter.push(nextPath.pathname, "forward", "push");
handleClearState();
} catch (e) {
const errorMessage = (e as Error).message;

if (
[SSI_URLS_EMPTY, SEED_PHRASE_EMPTY, Agent.INVALID_MNEMONIC].includes(
errorMessage
)
) {
return;
}

handleError(e as Error);
} finally {
setLoading(false);
Expand Down Expand Up @@ -301,6 +295,37 @@ const CreateSSIAgent = () => {
? i18n.t("generateseedphrase.onboarding.button.switch")
: i18n.t("verifyrecoveryseedphrase.button.switch");

const showConnectionUrlError =
!!displayConnectUrlError ||
hasMismatchError ||
isInvalidConnectUrl ||
unknowError;

const connectionUrlError = useMemo(() => {
if (unknowError) {
return "ssiagent.error.unknownissue";
}

if (hasMismatchError) {
if (isRecoveryMode) {
return "ssiagent.error.recoverymismatchconnecturl";
}
return "ssiagent.error.mismatchconnecturl";
}

if (displayBootUrlError && !isInvalidConnectUrl) {
return "ssiagent.error.invalidurl";
}

return "ssiagent.error.invalidconnecturl";
}, [
displayBootUrlError,
hasMismatchError,
isInvalidConnectUrl,
isRecoveryMode,
unknowError,
]);

return (
<>
<ScrollablePageLayout
Expand Down Expand Up @@ -348,6 +373,7 @@ const CreateSSIAgent = () => {
{!isRecoveryMode && (
<>
<CustomInput
className="boot-url-input"
dataTestId="boot-url-input"
title={`${i18n.t("ssiagent.input.boot.label")}`}
placeholder={`${i18n.t("ssiagent.input.boot.placeholder")}`}
Expand Down Expand Up @@ -378,6 +404,7 @@ const CreateSSIAgent = () => {
</>
)}
<CustomInput
className="connect-url-input"
dataTestId="connect-url-input"
title={`${i18n.t("ssiagent.input.connect.label")}`}
placeholder={`${i18n.t("ssiagent.input.connect.placeholder")}`}
Expand All @@ -394,29 +421,11 @@ const CreateSSIAgent = () => {
}
}}
value={ssiAgent.connectUrl || ""}
error={
!!displayConnectUrlError ||
hasMismatchError ||
isInvalidConnectUrl
}
error={showConnectionUrlError}
/>
<InputError
showError={
!!displayConnectUrlError ||
hasMismatchError ||
isInvalidConnectUrl
}
errorMessage={
hasMismatchError
? `${i18n.t(
isRecoveryMode
? "ssiagent.error.recoverymismatchconnecturl"
: "ssiagent.error.mismatchconnecturl"
)}`
: displayBootUrlError && !isInvalidConnectUrl
? `${i18n.t("ssiagent.error.invalidurl")}`
: `${i18n.t("ssiagent.error.invalidconnecturl")}`
}
showError={showConnectionUrlError}
errorMessage={`${i18n.t(connectionUrlError)}`}
/>
</div>
<PageFooter
Expand All @@ -426,7 +435,7 @@ const CreateSSIAgent = () => {
primaryButtonDisabled={!validated || loading}
tertiaryButtonText={buttonLabel}
tertiaryButtonAction={() => setSwitchModeModal(true)}
tertiaryButtonIcon={refreshOutline}
tertiaryButtonIcon={isRecoveryMode ? addOutline : refreshOutline}
/>
</div>
</ScrollablePageLayout>
Expand Down

0 comments on commit 4d36148

Please # to comment.