Skip to content

Commit

Permalink
[#710] fix displaying modals to not block signing transactions
Browse files Browse the repository at this point in the history
  • Loading branch information
MSzalowski committed Apr 12, 2024
1 parent f9bbeaa commit 65d228d
Show file tree
Hide file tree
Showing 11 changed files with 392 additions and 254 deletions.
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)

### Added

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 @@ -47,21 +45,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

0 comments on commit 65d228d

Please sign in to comment.