Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[#710] fix displaying modals to not block signing transactions #711

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ changes.

- Integrate frontend with metadata validation service [Issue 617](https://github.com/IntersectMBO/govtool/issues/617)
- Implement a loading modal for the validation of the metadata [Issue 646](https://github.com/IntersectMBO/govtool/issues/646)
- Fix displaying modals to not block signing transactions [Issue 710](https://github.com/IntersectMBO/govtool/issues/710)
- Change style of url button to trim the file name [Issue 655](https://github.com/IntersectMBO/govtool/issues/655)
- Change regex for parsing urls to match urls without protocol [Issue 655](https://github.com/IntersectMBO/govtool/issues/655)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,8 @@ import {
useScreenDimension,
} from "@hooks";
import { Step } from "@molecules";
import { BgCard, ControlledField, LoadingModalState } from "@organisms";
import { BgCard, ControlledField } from "@organisms";
import { URL_REGEX, openInNewTab } from "@utils";
import { useModal } from "@context";

type StorageInformationProps = {
setStep: Dispatch<SetStateAction<number>>;
Expand All @@ -30,7 +29,6 @@ export const StorageInformation = ({ setStep }: StorageInformationProps) => {
onClickDownloadJson,
isLoading,
} = useCreateGovernanceActionForm(setStep);
const { openModal, closeModal } = useModal<LoadingModalState>();
const { screenWidth } = useScreenDimension();

const fileName = getValues("governance_action_type");
Expand All @@ -48,21 +46,6 @@ export const StorageInformation = ({ setStep }: StorageInformationProps) => {
generateMetadata();
}, []);

useEffect(() => {
if (isLoading) {
openModal({
type: "loadingModal",
state: {
title: t("createGovernanceAction.modals.loading.title"),
message: t("createGovernanceAction.modals.loading.message"),
dataTestId: "storing-information-loading",
},
});
} else {
closeModal();
}
}, [isLoading]);

return (
<BgCard
actionButtonLabel={t("continue")}
Expand Down
137 changes: 69 additions & 68 deletions govtool/frontend/src/hooks/forms/useCreateGovernanceActionForm.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,18 @@ import { useTranslation } from "react-i18next";
import { NodeObject } from "jsonld";

import {
CIP_100,
CIP_108,
GOVERNANCE_ACTION_CONTEXT,
PATHS,
storageInformationErrorModals,
} from "@consts";
import { useCardano, useModal } from "@context";
import { canonizeJSON, downloadJson, generateJsonld } from "@utils";
import {
canonizeJSON,
downloadJson,
generateJsonld,
generateMetadataBody,
} from "@utils";
import { MetadataValidationStatus } from "@models";
import {
GovernanceActionFieldSchemas,
Expand All @@ -40,18 +44,27 @@ export const defaulCreateGovernanceActionValues: CreateGovernanceActionValues =
export const useCreateGovernanceActionForm = (
setStep?: Dispatch<SetStateAction<number>>,
) => {
// Local state
const [isLoading, setIsLoading] = useState<boolean>(false);
const [hash, setHash] = useState<string | null>(null);
const [json, setJson] = useState<NodeObject | null>(null);

// DApp Connector
const {
buildNewInfoGovernanceAction,
buildTreasuryGovernanceAction,
buildSignSubmitConwayCertTx,
} = useCardano();
const { validateMetadata } = useValidateMutation();

// App Management
const { t } = useTranslation();
const [isLoading, setIsLoading] = useState<boolean>(false);
const [hash, setHash] = useState<string | null>(null);
const [json, setJson] = useState<NodeObject | null>(null);
const navigate = useNavigate();
const { openModal, closeModal } = useModal();

// Queries
const { validateMetadata } = useValidateMutation();

// Form
const {
control,
formState: { errors, isValid },
Expand All @@ -64,6 +77,7 @@ export const useCreateGovernanceActionForm = (
} = useFormContext<CreateGovernanceActionValues>();
const govActionType = watch("governance_action_type");

// Navigation
const backToForm = useCallback(() => {
setStep?.(3);
closeModal();
Expand All @@ -74,31 +88,17 @@ export const useCreateGovernanceActionForm = (
closeModal();
}, []);

// Business Logic
const generateMetadata = useCallback(async () => {
const data = getValues();

if (!govActionType) {
throw new Error("Governance action type is not defined");
}

const acceptedKeys = ["title", "motivation", "abstract", "rationale"];

const filteredData = Object.entries(data)
.filter(([key]) => acceptedKeys.includes(key))
.map(([key, value]) => [CIP_108 + key, value]);

const references = (data as CreateGovernanceActionValues).links
?.filter((link) => link.link)
.map((link) => ({
"@type": "Other",
[`${CIP_100}reference-label`]: "Label",
[`${CIP_100}reference-uri`]: link.link,
}));

const body = {
...Object.fromEntries(filteredData),
[`${CIP_108}references`]: references,
};
const body = generateMetadataBody({
data: getValues(),
acceptedKeys: ["title", "motivation", "abstract", "rationale"],
standardReference: CIP_108,
});

const jsonld = await generateJsonld(body, GOVERNANCE_ACTION_CONTEXT);

Expand All @@ -117,42 +117,6 @@ export const useCreateGovernanceActionForm = (
downloadJson(json, govActionType);
}, [govActionType, json]);

const validateHash = useCallback(
async (url: string, localHash: string | null) => {
try {
if (!localHash) {
throw new Error(MetadataValidationStatus.INVALID_HASH);
}
const result = await validateMetadata({ url, hash: localHash });

if (result.status) {
throw result.status;
}
} catch (error) {
if (
Object.values(MetadataValidationStatus).includes(
error as MetadataValidationStatus,
)
) {
openModal({
type: "statusModal",
state: {
...storageInformationErrorModals[
error as MetadataValidationStatus
],
onSubmit: backToForm,
onCancel: backToDashboard,
// TODO: Open usersnap feedback
onFeedback: backToDashboard,
},
});
}
throw error;
}
},
[backToForm],
);

const buildTransaction = useCallback(
async (data: CreateGovernanceActionValues) => {
if (!hash) return;
Expand Down Expand Up @@ -184,10 +148,8 @@ export const useCreateGovernanceActionForm = (
default:
throw new Error(t("errors.invalidGovernanceActionType"));
}
// eslint-disable-next-line @typescript-eslint/no-explicit-any
} catch (error: any) {
console.error(error);
throw error;
} catch (error) {
captureException(error);
}
},
[hash],
Expand All @@ -211,12 +173,33 @@ export const useCreateGovernanceActionForm = (
});
}, []);

const showLoadingModal = useCallback(() => {
openModal({
type: "loadingModal",
state: {
title: t("modals.pendingValidation.title"),
message: t("modals.pendingValidation.message"),
dataTestId: "storing-information-loading",
},
});
}, []);

const onSubmit = useCallback(
async (data: CreateGovernanceActionValues) => {
try {
setIsLoading(true);
showLoadingModal();
if (!hash) {
throw new Error(MetadataValidationStatus.INVALID_HASH);
}
const { status } = await validateMetadata({
url: data.storingURL,
hash,
});

await validateHash(data.storingURL, hash);
if (status) {
throw status;
}

const govActionBuilder = await buildTransaction(data);
await buildSignSubmitConwayCertTx({
Expand All @@ -227,7 +210,25 @@ export const useCreateGovernanceActionForm = (
showSuccessModal();
// eslint-disable-next-line @typescript-eslint/no-explicit-any
} catch (error: any) {
captureException(error);
if (
Object.values(MetadataValidationStatus).includes(
error as MetadataValidationStatus,
)
) {
openModal({
type: "statusModal",
state: {
...storageInformationErrorModals[
error as MetadataValidationStatus
],
onSubmit: backToForm,
onCancel: backToDashboard,
onFeedback: backToDashboard,
},
});
} else {
captureException(error);
}
} finally {
setIsLoading(false);
}
Expand Down
Loading
Loading