Skip to content

Commit d24f44b

Browse files
committed
Merge branch 'solana-labs-main'
2 parents b6bad99 + cbda107 commit d24f44b

File tree

13 files changed

+227
-171
lines changed

13 files changed

+227
-171
lines changed

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
# misc
1919
.DS_Store
2020
*.pem
21+
.env
2122

2223
# debug
2324
npm-debug.log*
@@ -36,3 +37,5 @@ yarn-error.log*
3637

3738
.npmrc
3839
.env
40+
# TypeScript cache
41+
*.tsbuildinfo

components/Button.tsx

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,11 +14,14 @@ const Button: FunctionComponent<ButtonProps> = ({
1414
className,
1515
disabled,
1616
isLoading,
17+
small,
1718
...props
1819
}) => {
1920
return (
2021
<button
21-
className={`${className} default-transition font-bold px-4 py-2.5 rounded-full text-sm focus:outline-none ${
22+
className={`${className} default-transition font-bold px-4 rounded-full ${
23+
small ? 'py-1' : 'py-2.5'
24+
} text-sm focus:outline-none ${
2225
disabled
2326
? 'bg-bkg-4 cursor-not-allowed text-fgd-2'
2427
: 'bg-primary-light text-bkg-2 hover:bg-primary-dark'

components/CancelProposalModal.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ type CancelProposalModalProps = {
1818
const CancelProposalModal = ({ onClose, isOpen }: CancelProposalModalProps) => {
1919
const wallet = useWalletStore((s) => s.current)
2020
const connection = useWalletStore((s) => s.connection)
21-
const fetchRealm = useWalletStore((s) => s.actions.fetchRealm)
21+
const fetchProposal = useWalletStore((s) => s.actions.fetchProposal)
2222
const { realmInfo } = useRealm()
2323
const { proposal } = useProposal()
2424

@@ -39,7 +39,7 @@ const CancelProposalModal = ({ onClose, isOpen }: CancelProposalModalProps) => {
3939

4040
onClose()
4141

42-
await fetchRealm(realmInfo.programId, realmInfo.realmId)
42+
await fetchProposal(proposal.pubkey)
4343
}
4444
} catch (error) {
4545
notify({

components/FinalizeVotesModal.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ const FinalizeVotesModal = ({
2424
}: FinalizeVotesModalProps) => {
2525
const wallet = useWalletStore((s) => s.current)
2626
const connection = useWalletStore((s) => s.connection)
27-
const fetchRealm = useWalletStore((s) => s.actions.fetchRealm)
27+
const fetchProposal = useWalletStore((s) => s.actions.fetchProposal)
2828
const { realmInfo } = useRealm()
2929

3030
const handleFinalizeVote = async () => {
@@ -42,7 +42,7 @@ const FinalizeVotesModal = ({
4242

4343
onClose()
4444

45-
await fetchRealm(realmInfo!.programId, realmInfo!.realmId)
45+
await fetchProposal(proposal.pubkey)
4646
}
4747
} catch (error) {
4848
notify({

components/ProposalActions.tsx

Lines changed: 137 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,137 @@
1+
/* eslint-disable @typescript-eslint/no-non-null-assertion */
2+
import { useEffect, useState } from 'react'
3+
import { useHasVoteTimeExpired } from '../hooks/useHasVoteTimeExpired'
4+
import useRealm from '../hooks/useRealm'
5+
import { getSignatoryRecordAddress, ProposalState } from '../models/accounts'
6+
import useWalletStore from '../stores/useWalletStore'
7+
import Button, { SecondaryButton } from './Button'
8+
import CancelProposalModal from './CancelProposalModal'
9+
import FinalizeVotesModal from './FinalizeVotesModal'
10+
import SignOffProposalModal from './SignOffProposalModal'
11+
12+
const ProposalActionsPanel = () => {
13+
const { governance, proposal, proposalOwner } = useWalletStore(
14+
(s) => s.selectedProposal
15+
)
16+
const { realmInfo } = useRealm()
17+
const wallet = useWalletStore((s) => s.current)
18+
const connected = useWalletStore((s) => s.connected)
19+
const hasVoteTimeExpired = useHasVoteTimeExpired(governance, proposal!)
20+
const signatories = useWalletStore((s) => s.selectedProposal.signatories)
21+
22+
const [showSignOffModal, setShowSignOffModal] = useState(false)
23+
const [signatoryRecord, setSignatoryRecord] = useState<any>(undefined)
24+
const [showFinalizeVoteModal, setShowFinalizeVoteModal] = useState(false)
25+
const [showCancelModal, setShowCancelModal] = useState(false)
26+
27+
const canFinalizeVote =
28+
hasVoteTimeExpired === true &&
29+
connected &&
30+
proposal?.info.state === ProposalState.Voting
31+
32+
const walletPk = wallet?.publicKey
33+
34+
useEffect(() => {
35+
const setup = async () => {
36+
if (proposal && realmInfo && walletPk) {
37+
const signatoryRecordPk = await getSignatoryRecordAddress(
38+
realmInfo.programId,
39+
proposal.pubkey,
40+
walletPk
41+
)
42+
43+
if (signatoryRecordPk && signatories) {
44+
setSignatoryRecord(signatories[signatoryRecordPk.toBase58()])
45+
}
46+
}
47+
}
48+
49+
setup()
50+
}, [proposal, realmInfo, walletPk])
51+
52+
const canSignOff =
53+
signatoryRecord &&
54+
(proposal?.info.state === ProposalState.Draft ||
55+
proposal?.info.state === ProposalState.SigningOff)
56+
57+
const canCancelProposal =
58+
proposal &&
59+
governance &&
60+
proposalOwner &&
61+
wallet?.publicKey &&
62+
proposal.info.canWalletCancel(
63+
governance.info,
64+
proposalOwner.info,
65+
wallet.publicKey
66+
)
67+
68+
return (
69+
<>
70+
{ProposalState.Cancelled === proposal?.info.state ||
71+
ProposalState.Succeeded === proposal?.info.state ||
72+
ProposalState.Defeated === proposal?.info.state ||
73+
(!canCancelProposal && !canSignOff && canFinalizeVote) ? null : (
74+
<div>
75+
<div className="bg-bkg-2 rounded-lg p-6 space-y-6 flex justify-center items-center text-center flex-col w-full mt-4">
76+
{canSignOff && (
77+
<Button
78+
className="w-1/2"
79+
onClick={() => setShowSignOffModal(true)}
80+
disabled={!connected || !canSignOff}
81+
>
82+
Sign Off
83+
</Button>
84+
)}
85+
86+
{canCancelProposal && (
87+
<SecondaryButton
88+
className="w-1/2"
89+
onClick={() => setShowCancelModal(true)}
90+
disabled={!connected}
91+
>
92+
Cancel
93+
</SecondaryButton>
94+
)}
95+
96+
{canFinalizeVote && (
97+
<Button
98+
className="w-1/2"
99+
onClick={() => setShowFinalizeVoteModal(true)}
100+
disabled={!connected || !canFinalizeVote}
101+
>
102+
Finalize
103+
</Button>
104+
)}
105+
</div>
106+
107+
{showSignOffModal && (
108+
<SignOffProposalModal
109+
isOpen={showSignOffModal && canSignOff}
110+
onClose={() => setShowSignOffModal(false)}
111+
signatoryRecord={signatoryRecord}
112+
/>
113+
)}
114+
115+
{showFinalizeVoteModal && (
116+
<FinalizeVotesModal
117+
isOpen={showFinalizeVoteModal && canFinalizeVote}
118+
onClose={() => setShowFinalizeVoteModal(false)}
119+
proposal={proposal}
120+
governance={governance}
121+
/>
122+
)}
123+
124+
{showCancelModal && (
125+
<CancelProposalModal
126+
// @ts-ignore
127+
isOpen={showCancelModal && canCancelProposal}
128+
onClose={() => setShowCancelModal(false)}
129+
/>
130+
)}
131+
</div>
132+
)}
133+
</>
134+
)
135+
}
136+
137+
export default ProposalActionsPanel

components/SignOffProposalModal.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ const SignOffProposalModal = ({
2323
}: SignOffProposalModalProps) => {
2424
const wallet = useWalletStore((s) => s.current)
2525
const connection = useWalletStore((s) => s.connection)
26-
const fetchRealm = useWalletStore((s) => s.actions.fetchRealm)
26+
const fetchProposal = useWalletStore((s) => s.actions.fetchProposal)
2727
const { realmInfo } = useRealm()
2828
const { proposal } = useProposal()
2929

@@ -42,7 +42,7 @@ const SignOffProposalModal = ({
4242

4343
onClose()
4444

45-
await fetchRealm(realmInfo.programId, realmInfo.realmId)
45+
await fetchProposal(proposal.pubkey)
4646
}
4747
} catch (error) {
4848
notify({

components/VoteCommentModal.tsx

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import useWalletStore from '../stores/useWalletStore'
66
import useRealm from '../hooks/useRealm'
77
import { castVote } from '../actions/castVote'
88
import { Vote } from '../models/instructions'
9-
import Button, { LinkButton } from './Button'
9+
import Button, { SecondaryButton } from './Button'
1010
// import { notify } from '../utils/notifications'
1111
import Loading from './Loading'
1212
import Modal from './Modal'
@@ -88,26 +88,33 @@ const VoteCommentModal: FunctionComponent<VoteCommentModalProps> = ({
8888
return (
8989
<Modal onClose={onClose} isOpen={isOpen}>
9090
<h2>Confirm your vote</h2>
91+
9192
<Tooltip content="This will be stored on-chain and displayed publically in the discussion on this proposal">
92-
<label className="border-b border-dashed border-fgd-3 inline-block leading-4 text-fgd-1 text-sm hover:cursor-help hover:border-b-0">
93+
<label className="border- mt-4 border-dashed border-fgd-3 inline-block leading-4 text-fgd-1 text-sm hover:cursor-help hover:border-b-0">
9394
Leave a comment
9495
</label>
9596
<span className="ml-1 text-xs text-fgd-3">(Optional)</span>
9697
</Tooltip>
98+
9799
<Input
98100
className="mt-1.5"
99101
value={comment}
100102
type="text"
101103
onChange={(e) => setComment(e.target.value)}
102104
// placeholder={`Let the DAO know why you vote '${voteString}'`}
103105
/>
104-
<div className="flex items-center pt-6">
105-
<Button onClick={() => submitVote(vote)}>
106+
107+
<div className="flex items-center justify-center mt-8">
108+
<SecondaryButton className="w-44 mr-4" onClick={onClose}>
109+
Cancel
110+
</SecondaryButton>
111+
112+
<Button
113+
className="w-44 flex items-center justify-center"
114+
onClick={() => submitVote(vote)}
115+
>
106116
{submitting ? <Loading /> : <span>{voteString} Proposal</span>}
107117
</Button>
108-
<LinkButton className="ml-4 text-th-fgd-1" onClick={onClose}>
109-
Cancel
110-
</LinkButton>
111118
</div>
112119
</Modal>
113120
)

0 commit comments

Comments
 (0)