Skip to content

Commit

Permalink
feat(web): improved structures, dispute template view, case overview
Browse files Browse the repository at this point in the history
  • Loading branch information
kemuru committed Oct 11, 2023
1 parent 1ce3e09 commit a41397c
Show file tree
Hide file tree
Showing 3 changed files with 108 additions and 64 deletions.
52 changes: 40 additions & 12 deletions web/src/pages/Cases/CaseDetails/Overview.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React from "react";
import React, { useEffect, useState } from "react";
import styled, { css } from "styled-components";
import { landscapeStyle } from "styles/landscapeStyle";
import { useParams } from "react-router-dom";
Expand All @@ -8,6 +8,7 @@ import { useDisputeDetailsQuery } from "queries/useDisputeDetailsQuery";
import { useDisputeTemplate } from "queries/useDisputeTemplate";
import { useCourtPolicy } from "queries/useCourtPolicy";
import { isUndefined } from "utils/index";
import { deepParseTemplateWithData, executeAction } from "utils/dataMappings";
import { Periods } from "consts/periods";
import { IPFS_GATEWAY } from "consts/index";
import PolicyIcon from "svgs/icons/policy.svg";
Expand Down Expand Up @@ -117,38 +118,66 @@ const Overview: React.FC<IOverview> = ({ arbitrable, courtID, currentPeriodIndex
const { data: disputeDetails } = useDisputeDetailsQuery(id);
const { data: courtPolicy } = useCourtPolicy(courtID);
const { data: votingHistory } = useVotingHistory(id);

const [parsedDisputeTemplate, setParsedDisputeTemplate] = useState<any>({});

const localRounds = votingHistory?.dispute?.disputeKitDispute?.localRounds;
const courtName = courtPolicy?.name;
const court = disputeDetails?.dispute?.court;
const rewards = court ? `≥ ${formatEther(court.feeForJuror)} ETH` : undefined;
const category = disputeTemplate ? disputeTemplate.category : undefined;

useEffect(() => {
const fetchData = async () => {
try {
const parsedTemplate = JSON.parse(disputeTemplate?.templateData);
const parsedMapping = JSON.parse(disputeTemplate?.templateDataMappings);

let populatedData = {};

for (const action of parsedMapping) {
const result = await executeAction(action);
populatedData = { ...populatedData, ...result };
}

const finalTemplate = deepParseTemplateWithData(parsedTemplate, populatedData);
setParsedDisputeTemplate(finalTemplate);
} catch (e) {
console.error(e);
}
};

fetchData();
}, [disputeTemplate]);

return (
<>
<Container>
<h1>
{isUndefined(disputeTemplate) ? (
<StyledSkeleton />
) : (
disputeTemplate?.title ?? "The dispute's template is not correct please vote refuse to arbitrate"
parsedDisputeTemplate?.template?.content ??
"The dispute's template is not correct please vote refuse to arbitrate"
)}
</h1>
<QuestionAndDescription>
<ReactMarkdown>{disputeTemplate?.question}</ReactMarkdown>
<ReactMarkdown>{disputeTemplate?.description}</ReactMarkdown>
<ReactMarkdown>{parsedDisputeTemplate?.question}</ReactMarkdown>
<ReactMarkdown>{parsedDisputeTemplate?.description}</ReactMarkdown>
</QuestionAndDescription>
{disputeTemplate?.frontendUrl && (
<a href={disputeTemplate?.frontendUrl} target="_blank" rel="noreferrer">
{parsedDisputeTemplate?.frontendUrl && (
<a href={parsedDisputeTemplate?.frontendUrl} target="_blank" rel="noreferrer">
Go to arbitrable
</a>
)}
<VotingOptions>
{disputeTemplate && <h3>Voting Options</h3>}
{parsedDisputeTemplate && <h3>Voting Options</h3>}
<Answers>
{disputeTemplate?.answers?.map((answer: { title: string; description: string }, i: number) => (
{parsedDisputeTemplate?.options?.titles?.map((title: string, i: number) => (
<span key={i}>
<small>Option {i + 1}:</small>
<label>{answer.title}</label>
<label>{title}. </label>
<label>{parsedDisputeTemplate.options.descriptions[i]}</label>
</span>
))}
</Answers>
Expand All @@ -160,14 +189,13 @@ const Overview: React.FC<IOverview> = ({ arbitrable, courtID, currentPeriodIndex
<Divider />
</>
)}

<DisputeInfo courtId={court?.id} court={courtName} round={localRounds?.length} {...{ rewards, category }} />
</Container>
<ShadeArea>
<p>Make sure you understand the Policies</p>
<LinkContainer>
{disputeTemplate?.policyURI && (
<StyledA href={`${IPFS_GATEWAY}${disputeTemplate.policyURI}`} target="_blank" rel="noreferrer">
{parsedDisputeTemplate?.policyURI && (
<StyledA href={`${IPFS_GATEWAY}${parsedDisputeTemplate.policyURI}`} target="_blank" rel="noreferrer">
<PolicyIcon />
Dispute Policy
</StyledA>
Expand Down
98 changes: 47 additions & 51 deletions web/src/pages/DisputeTemplateView.tsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,10 @@
import React, { useMemo, useState } from "react";
import React, { useEffect, useState } from "react";
import styled from "styled-components";
import { Textarea } from "@kleros/ui-components-library";
import PolicyIcon from "svgs/icons/policy.svg";
import { StyledSkeleton } from "components/StyledSkeleton";
import ReactMarkdown from "components/ReactMarkdown";
import { isUndefined } from "utils/index";
import { IPFS_GATEWAY } from "consts/index";
import { useDisputeTemplate } from "hooks/queries/useDisputeTemplate";
import { executeAction, parseTemplateWithData } from "utils/dataMappings";
import { deepParseTemplateWithData, executeAction } from "utils/dataMappings";

const Container = styled.div`
width: 50%;
Expand Down Expand Up @@ -81,69 +78,67 @@ const StyledTextArea = styled(Textarea)`
`;

const DisputeTemplateView: React.FC = () => {
const [disputeTemplate, setDisputeTemplate] = useState<string>("");
const [errorMsg, setErrorMessage] = useState<string>("");
const { data: template } = useDisputeTemplate("7", "0xE4af4D800Ce12149199FA6f8870cD650cD8f3164");

const parsedDisputeTemplate = useMemo(async () => {
try {
console.log(template);
const parsedTemplate = JSON.parse(template?.templateData);
const parsedMapping = JSON.parse(template?.templateDataMappings);

console.log("parsedTemplate", parsedTemplate);
console.log("parsedMapping", parsedMapping);

let populatedData = {};

for (const action of parsedMapping) {
console.log("action of parsedMapping", action);
const result = await executeAction(action);
console.log("result of executeAction", result);
populatedData = { ...populatedData, ...result };
console.log("populatedData inside loop", populatedData);
const [parsedDisputeTemplate, setParsedDisputeTemplate] = useState<any>({});
const [disputeTemplateInput, setDisputeTemplateInput] = useState<string>("");
const [dataMappingsInput, setDataMappingsInput] = useState<string>("");

useEffect(() => {
if (!disputeTemplateInput || !dataMappingsInput) return;

const fetchData = async () => {
let parsedTemplate, parsedMapping;

try {
parsedTemplate = JSON.parse(disputeTemplateInput);
parsedMapping = JSON.parse(dataMappingsInput);
} catch (e) {
console.error(e);
setParsedDisputeTemplate(undefined);
return;
}

const finalTemplate = parseTemplateWithData(parsedTemplate.template.content, populatedData);
console.log("finalTemplate with everything parsed", finalTemplate);
setDisputeTemplate(finalTemplate);
setErrorMessage("");
return finalTemplate;
} catch (e) {
console.log("error", e);
setErrorMessage((e as SyntaxError).message);
return undefined;
}
}, [template, disputeTemplate]);
try {
let populatedData = {};

const isThereInput = useMemo(() => disputeTemplate !== "", [disputeTemplate]);
for (const action of parsedMapping) {
const result = await executeAction(action);
populatedData = { ...populatedData, ...result };
}

const finalTemplate = deepParseTemplateWithData(parsedTemplate, populatedData);
setParsedDisputeTemplate(finalTemplate);
} catch (e) {
console.error(e);
}
};

fetchData();
}, [disputeTemplateInput, dataMappingsInput]);

return (
<Wrapper>
<StyledTextArea
value={disputeTemplate}
onChange={(e) => setDisputeTemplate(e.target.value)}
value={disputeTemplateInput}
onChange={(e) => setDisputeTemplateInput(e.target.value)}
placeholder="Enter dispute template"
variant={isThereInput && errorMsg !== "" ? "error" : ""}
message={isThereInput ? errorMsg : ""}
/>
<StyledTextArea
value={dataMappingsInput}
onChange={(e) => setDataMappingsInput(e.target.value)}
placeholder="Enter data mappings"
/>
<Overview disputeTemplate={parsedDisputeTemplate} />
</Wrapper>
);
};

const Overview: React.FC<{ disputeTemplate: any }> = ({ disputeTemplate }) => {
console.log("disputeTemplate 133", disputeTemplate);

return (
<>
<Container>
<h1>
{isUndefined(disputeTemplate) ? (
<StyledSkeleton />
) : (
disputeTemplate?.title ?? "The dispute's template is not correct please vote refuse to arbitrate"
)}
{disputeTemplate?.template?.content ??
"The dispute's template is not correct please vote refuse to arbitrate"}
</h1>
<QuestionAndDescription>
<ReactMarkdown>{disputeTemplate?.question}</ReactMarkdown>
Expand All @@ -156,10 +151,11 @@ const Overview: React.FC<{ disputeTemplate: any }> = ({ disputeTemplate }) => {
)}
<VotingOptions>
{disputeTemplate && <h3>Voting Options</h3>}
{disputeTemplate?.answers?.map((answer: { title: string; description: string }, i: number) => (
{disputeTemplate?.options?.titles?.map((title: string, i: number) => (
<span key={i}>
<small>Option {i + 1}:</small>
<label>{answer.title}</label>
<label>{title}. </label>
<label>{disputeTemplate.options.descriptions[i]}</label>
</span>
))}
</VotingOptions>
Expand Down
22 changes: 21 additions & 1 deletion web/src/utils/dataMappings.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { createPublicClient, http, parseAbiItem, webSocket } from "viem";
import { createPublicClient, parseAbiItem, webSocket } from "viem";
import { arbitrumGoerli } from "viem/chains";
import fetch from "node-fetch";

Expand Down Expand Up @@ -155,3 +155,23 @@ export const executeAction = async (action) => {
export const parseTemplateWithData = (template, data) => {
return template.replace(/\{\{(.*?)\}\}/g, (_, key) => data[key.trim()] || "");
};

export const deepParseTemplateWithData = (templateObj: any, data: any): any => {
if (typeof templateObj === "string") {
return templateObj.replace(/\{\{(.*?)\}\}/g, (_, key) => data[key.trim()] || "");
}

if (Array.isArray(templateObj)) {
return templateObj.map((item) => deepParseTemplateWithData(item, data));
}

if (typeof templateObj === "object") {
let newObject: any = {};
for (let key in templateObj) {
newObject[key] = deepParseTemplateWithData(templateObj[key], data);
}
return newObject;
}

return templateObj;
};

0 comments on commit a41397c

Please sign in to comment.