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

Dispute creation wizard (basic) integrated to the court v2 #1388

Merged
merged 33 commits into from
Jan 10, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
33 commits
Select commit Hold shift + click to select a range
0fc9bcc
feat(web): basic-dispute-resolver-ui
Harman-singh-waraich Dec 29, 2023
f457622
feat(web): add-dispute-data-collection-and-basic-dispute-creation
Harman-singh-waraich Jan 2, 2024
e0f9f04
feat(web): add-success-popup-on-dispute-creation-and-update-wrapWithT…
Harman-singh-waraich Jan 2, 2024
ddeb92c
fix(web): remove-dispute-data-from-localstorage-on-reset
Harman-singh-waraich Jan 2, 2024
33e3c00
fix(web): fixed-value-not-persisting-in-some-fields-in-resolver
Harman-singh-waraich Jan 3, 2024
52d0037
refactor(web): better-dispute-template-construction
Harman-singh-waraich Jan 3, 2024
2d6c702
fix(web): disable-submitCase-button-while-sending-txn
Harman-singh-waraich Jan 3, 2024
63c87dd
fix(web): fix-policy-uri-not-being-passed-in-props
Harman-singh-waraich Jan 3, 2024
f96dfdb
feat(web): handle-policy-upload
Harman-singh-waraich Jan 3, 2024
6b95e0c
refactor(web): better-enable-condition-for-dispute-submittion-prepare…
Harman-singh-waraich Jan 4, 2024
4014b05
fix(web): fix-courtId-prop-was-hardcoded-in-Preview-policy
Harman-singh-waraich Jan 4, 2024
269d772
feat(web): add-alias-handling-and-UI
Harman-singh-waraich Jan 4, 2024
22c21e6
feat(web): add-multiple-voting-options-support
Harman-singh-waraich Jan 4, 2024
3279eaa
refactor(web): fix-code-smells
Harman-singh-waraich Jan 5, 2024
dbe0c9c
refactor(web): fix-unique-id-as-key-instead-of-array-index
Harman-singh-waraich Jan 5, 2024
43f2887
refactor(web): better-decoding-logic-to-retrieve-dispute-id
Harman-singh-waraich Jan 8, 2024
3c6d76a
refactor(web): add-network-check-and-loading-ui-to-submit-case-button
Harman-singh-waraich Jan 8, 2024
327a6d5
refactor(web): disable-next-button-when-arbitration-cost-loading
Harman-singh-waraich Jan 8, 2024
2ccc6d7
refactor(web): use-uselocalstorage-hook-to-handle-dispute-data-persist
Harman-singh-waraich Jan 8, 2024
8b2cd78
refactor(web): remove-data-mappings-todo-from-submit-dispute-call
Harman-singh-waraich Jan 8, 2024
5ebbcd6
refactor(web): move-resolver-access-to-kleros-solution-list
Harman-singh-waraich Jan 8, 2024
961545c
fix(web): fix-typo
Harman-singh-waraich Jan 8, 2024
71cf0e3
feat(web): add-description-field-in-resolver-forms
Harman-singh-waraich Jan 9, 2024
8e8b6e1
feat(web): option-description-display-in-dispute-context
Harman-singh-waraich Jan 9, 2024
78600b0
feat(web): add-cta-for-dispute-resolver
Harman-singh-waraich Jan 9, 2024
dc7c187
refactor(web): update-voting-options-and-counterparties-layout
Harman-singh-waraich Jan 9, 2024
71f4afa
fix(web): disable-next-button-while-policy-uploading
Harman-singh-waraich Jan 9, 2024
54f64e5
fix(web): remove-default-court-id-let-user-select-explicitly
Harman-singh-waraich Jan 9, 2024
6993b98
feat(web): add-dispute-resolvation-estimate-date
Harman-singh-waraich Jan 9, 2024
7bf1ac9
refactor(web): update-wrap-with-toast-function
Harman-singh-waraich Jan 10, 2024
51806c6
refactor(web): update-policy-upload-placeholder
Harman-singh-waraich Jan 10, 2024
1fb2b05
refactor(web): addressing-sonar-check-issue
Harman-singh-waraich Jan 10, 2024
f0e01ec
fix: linter
jaybuidl Jan 10, 2024
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
25 changes: 15 additions & 10 deletions web/src/app.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ import Cases from "./pages/Cases";
import Dashboard from "./pages/Dashboard";
import Courts from "./pages/Courts";
import DisputeTemplateView from "./pages/DisputeTemplateView";
import DisputeResolver from "./pages/Resolver";
import { NewDisputeProvider } from "./context/NewDisputeContext";

const App: React.FC = () => {
return (
Expand All @@ -22,16 +24,19 @@ const App: React.FC = () => {
<RefetchOnBlock />
<Web3Provider>
<IsListProvider>
<SentryRoutes>
<Route path="/" element={<Layout />}>
<Route index element={<Home />} />
<Route path="cases/*" element={<Cases />} />
<Route path="courts/*" element={<Courts />} />
<Route path="dashboard/:page/:order/:filter" element={<Dashboard />} />
<Route path="disputeTemplate" element={<DisputeTemplateView />} />
<Route path="*" element={<h1>Justice not found here ¯\_( ͡° ͜ʖ ͡°)_/¯</h1>} />
</Route>
</SentryRoutes>
<NewDisputeProvider>
<SentryRoutes>
<Route path="/" element={<Layout />}>
<Route index element={<Home />} />
<Route path="cases/*" element={<Cases />} />
<Route path="courts/*" element={<Courts />} />
<Route path="dashboard/:page/:order/:filter" element={<Dashboard />} />
<Route path="disputeTemplate" element={<DisputeTemplateView />} />
<Route path="resolver/*" element={<DisputeResolver />} />
<Route path="*" element={<h1>Justice not found here ¯\_( ͡° ͜ʖ ͡°)_/¯</h1>} />
</Route>
</SentryRoutes>
</NewDisputeProvider>
</IsListProvider>
</Web3Provider>
</QueryClientProvider>
Expand Down
11 changes: 11 additions & 0 deletions web/src/assets/svgs/icons/dispute.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
3 changes: 3 additions & 0 deletions web/src/assets/svgs/icons/ellipse.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
3 changes: 3 additions & 0 deletions web/src/assets/svgs/icons/minus.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
10 changes: 10 additions & 0 deletions web/src/assets/svgs/icons/plus.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
3 changes: 2 additions & 1 deletion web/src/components/ConnectWallet/AccountDisplay.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { landscapeStyle } from "styles/landscapeStyle";
import { useAccount, useNetwork, useEnsAvatar, useEnsName } from "wagmi";
import Identicon from "react-identicons";
import { shortenAddress } from "utils/shortenAddress";
import { isAddress } from "viem";

const Container = styled.div`
display: flex;
Expand Down Expand Up @@ -134,7 +135,7 @@ export const AddressOrName: React.FC<IAddressOrName> = ({ address: propAddress }
chainId: 1,
});

return <label>{data ?? (address && shortenAddress(address))}</label>;
return <label>{data ?? (isAddress(address) ? shortenAddress(address) : address)}</label>;
};

export const ChainDisplay: React.FC = () => {
Expand Down
50 changes: 50 additions & 0 deletions web/src/components/DisputePreview/Alias.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
import React from "react";
import styled from "styled-components";
import { AddressOrName, IdenticonOrAvatar } from "../ConnectWallet/AccountDisplay";
import { Alias } from "context/NewDisputeContext";
import { isUndefined } from "utils/index";
import { useEnsAddress } from "wagmi";
import { isAddress } from "viem";
import Skeleton from "react-loading-skeleton";

const AliasContainer = styled.div`
min-height: 32px;
display: flex;
gap: 8px;
align-items: center;
`;

const TextContainer = styled.div`
display: flex;
> label {
color: ${({ theme }) => theme.primaryText};
font-size: 14px;
}
`;

interface IAlias {
alias: Alias;
}

const AliasDisplay: React.FC<IAlias> = ({ alias }) => {
const { data: addressFromENS, isLoading } = useEnsAddress({
enabled: !isAddress(alias.address), // if alias.address is not an Address, we treat it as ENS and try to fetch address from there
name: alias.address,
chainId: 1,
});

// try fetching ens name, else go with address
const address = addressFromENS ?? alias.address;

return (
<AliasContainer>
{isLoading ? <Skeleton width={30} height={24} /> : <IdenticonOrAvatar address={address} size="24" />}
<TextContainer>
{isLoading ? <Skeleton width={30} height={24} /> : <AddressOrName address={address} />}&nbsp;
{!isUndefined(alias.name) && alias.name !== "" ? <label>({alias.name})</label> : null}
</TextContainer>
</AliasContainer>
);
};

export default AliasDisplay;
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@ import ReactMarkdown from "components/ReactMarkdown";
import styled from "styled-components";
import { StyledSkeleton } from "components/StyledSkeleton";
import { isUndefined } from "utils/index";
import { Answer as IAnswer, IDisputeTemplate } from "context/NewDisputeContext";
import AliasDisplay from "./Alias";
import { responsiveSize } from "styles/responsiveSize";

const StyledH1 = styled.h1`
margin: 0;
Expand All @@ -11,6 +14,10 @@ const StyledH1 = styled.h1`
const QuestionAndDescription = styled.div`
display: flex;
flex-direction: column;
div:first-child p:first-of-type {
font-size: 16px;
font-weight: 600;
}
`;

const StyledReactMarkDown = styled(ReactMarkdown)`
Expand All @@ -31,32 +38,24 @@ const AnswersContainer = styled.div`
const Answer = styled.div`
margin: 0px;
display: flex;
gap: 8px;
flex-wrap: wrap;
gap: ${responsiveSize(2, 8)};
`;

interface IAnswer {
id?: string;
title: string;
description?: string;
reserved?: boolean;
}

interface IDisputeTemplate {
answers: IAnswer[];
arbitrableAddress: string;
arbitrableChainID: string;
arbitratorAddress: string;
arbitratorChainID: string;
category?: string;
description: string;
frontendUrl?: string;
lang?: string;
policyURI?: string;
question: string;
specification?: string;
title: string;
}
const AliasesContainer = styled.div`
display: flex;
flex-wrap: wrap;
gap: ${responsiveSize(8, 20)};
`;

const Divider = styled.hr`
width: 100%;
display: flex;
border: none;
height: 1px;
background-color: ${({ theme }) => theme.stroke};
margin: 0;
`;
interface IDisputeContext {
disputeTemplate: IDisputeTemplate;
}
Expand Down Expand Up @@ -86,13 +85,27 @@ export const DisputeContext: React.FC<IDisputeContext> = ({ disputeTemplate }) =
{isUndefined(disputeTemplate) ? null : <h3>Voting Options</h3>}
<AnswersContainer>
{disputeTemplate?.answers?.map((answer: IAnswer, i: number) => (
<Answer key={i}>
<Answer key={answer.title}>
<small>Option {i + 1}:</small>
<label>{answer.title}</label>
<label>
{answer.title}
{answer.description ? ` - ${answer.description}` : null}
</label>
</Answer>
))}
</AnswersContainer>
</VotingOptions>

{isUndefined(disputeTemplate?.aliases) ? null : (
<>
<Divider />
<AliasesContainer>
{disputeTemplate.aliases.map((alias) => (
<AliasDisplay alias={alias} key={alias.address} />
))}
</AliasesContainer>
</>
)}
</>
);
};
File renamed without changes.
36 changes: 36 additions & 0 deletions web/src/components/LabeledInput.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import { Field, FieldProps } from "@kleros/ui-components-library";
import React from "react";
import styled from "styled-components";
import { isUndefined } from "utils/index";

const Container = styled.div`
width: 100%;
display: flex;
flex-direction: column;
`;
const StyledField = styled(Field)`
width: 100%;
> small {
margin-top: 16px;
margin-bottom: 16px;
}
`;

const StyledLabel = styled.label`
width: 100%;
margin-bottom: 12px;
`;

interface ILabeledInput extends FieldProps {
label?: string;
}
const LabeledInput: React.FC<ILabeledInput> = (props) => {
return (
<Container>
{!isUndefined(props.label) ? <StyledLabel id={props.label}>{props.label}</StyledLabel> : null}
<StyledField {...props} id={props?.label} />
</Container>
);
};

export default LabeledInput;
63 changes: 63 additions & 0 deletions web/src/components/PlusMinusField.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
import React from "react";
import styled, { css } from "styled-components";
import Ellipse from "assets/svgs/icons/ellipse.svg";
import Plus from "assets/svgs/icons/plus.svg";
import Minus from "assets/svgs/icons/minus.svg";

const Container = styled.div`
display: flex;
gap: 8px;
margin: 32px 0px 48px;
`;

const IconContainer = styled.button`
position: relative;
padding: 0;
border-radius: 50%;
border: none;
background-color: transparent;
cursor: pointer;
`;

const StyledEllipseIcon = styled(Ellipse)<{ isDisabled?: boolean }>`
circle {
${({ isDisabled }) =>
isDisabled &&
css`
fill-opacity: 0.12;
`};
}
`;

const Icon = styled.svg`
fill: ${({ theme }) => theme.white};
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
`;

interface IPlusMinusField {
currentValue: number;
updateValue: (currentValue: number) => void;
minValue?: number;
className?: string;
}
const PlusMinusField: React.FC<IPlusMinusField> = ({ currentValue, updateValue, minValue = 0, className }) => {
const incrementValue = () => updateValue(++currentValue);
const decrementValue = () => currentValue > minValue && updateValue(--currentValue);
return (
<Container className={className}>
<IconContainer onClick={incrementValue}>
<StyledEllipseIcon />
<Icon as={Plus} />
</IconContainer>
<IconContainer onClick={decrementValue}>
<StyledEllipseIcon isDisabled={currentValue === minValue} />
<Icon as={Minus} />
</IconContainer>
</Container>
);
};

export default PlusMinusField;
Loading