Skip to content

Commit

Permalink
feat(ui): show error message when can't not connect to KERIA (#981)
Browse files Browse the repository at this point in the history
Co-authored-by: Vu Van Duc <[email protected]>
  • Loading branch information
Sotatek-DukeVu and Vu Van Duc authored Mar 5, 2025
1 parent 4cda5f3 commit 011b99f
Show file tree
Hide file tree
Showing 5 changed files with 69 additions and 41 deletions.
7 changes: 4 additions & 3 deletions src/locales/en/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,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 @@ -644,7 +644,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 @@ -838,7 +838,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 @@ -817,7 +817,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 @@ -830,9 +830,9 @@ describe("SSI agent page: show error", () => {
});

await waitFor(() => {
expect(dispatchMock).toBeCalledWith(
setToastMsg(ToastMsgType.UNKNOWN_ERROR)
);
expect(
getByText(EN_TRANSLATIONS.ssiagent.error.unknownissue)
).toBeVisible();
});
});
});
86 changes: 54 additions & 32 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 @@ -80,6 +81,7 @@ const CreateSSIAgent = () => {
const [openInfo, setOpenInfo] = useState(false);
const [loading, setLoading] = useState(false);
const [hasMismatchError, setHasMismatchError] = useState(false);
const [unknownError, setUnknownError] = useState(false);
const [isInvalidBootUrl, setIsInvalidBootUrl] = useState(false);
const [isInvalidConnectUrl, setInvalidConnectUrl] = useState(false);
const [showSwitchModeModal, setSwitchModeModal] = useState(false);
Expand Down Expand Up @@ -139,27 +141,31 @@ const CreateSSIAgent = () => {
setIsInvalidBootUrl(true);
}

if (Agent.KERIA_BOOTED_ALREADY_BUT_CANNOT_CONNECT === errorMessage) {
setInvalidConnectUrl(true);
}

if (Agent.KERIA_NOT_BOOTED === errorMessage) {
setHasMismatchError(true);
}

if (Agent.KERIA_BOOTED_ALREADY_BUT_CANNOT_CONNECT === errorMessage) {
setInvalidConnectUrl(true);
}

if (
[
Agent.KERIA_BOOT_FAILED_BAD_NETWORK,
Agent.KERIA_CONNECT_FAILED_BAD_NETWORK,
].includes(errorMessage)
) {
showError(
"Unable to boot or connect keria",
error,
dispatch,
ToastMsgType.UNKNOWN_ERROR
);
setUnknownError(true);
showError("Bad network", error);
return;
}

showError(
"Unable to boot or connect keria",
error,
dispatch,
ToastMsgType.UNKNOWN_ERROR
);
};

const handleRecoveryWallet = async () => {
Expand Down Expand Up @@ -279,6 +285,7 @@ const CreateSSIAgent = () => {
const handleChangeConnectUrl = (connectionUrl: string) => {
setInvalidConnectUrl(false);
setHasMismatchError(false);
setUnknownError(false);
dispatch(setConnectUrl(connectionUrl));
};

Expand All @@ -301,6 +308,37 @@ const CreateSSIAgent = () => {
? i18n.t("generateseedphrase.onboarding.button.switch")
: i18n.t("verifyrecoveryseedphrase.button.switch");

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

const connectionUrlError = useMemo(() => {
if (unknownError) {
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,
unknownError,
]);

return (
<>
<ScrollablePageLayout
Expand Down Expand Up @@ -348,6 +386,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 +417,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 +434,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 +448,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 011b99f

Please sign in to comment.