-
Notifications
You must be signed in to change notification settings - Fork 18
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* feat: add reason when voting * fix: update voting power fetching * fix: do not pin reason when empty * chore: lint fix * Update apps/ui/src/views/Proposal.vue Co-authored-by: Wiktor Tkaczyński <[email protected]> * fix(ui): improve disabled button UI * Update apps/ui/src/components/ProposalsListItem.vue Co-authored-by: Wiktor Tkaczyński <[email protected]> * fix: improve typing * refactor: use same VotingPowerItem type * refactor: improve chaining * refactor: use optional chaining * chore: fix formatting * chore: fix missing ; * refactor: improve code readability * fix: fix to match updated name * fix: use web3.account to detect logged in user There's not need to check for authInitiated, as we don't support login and logout while in this page * fix: fix PUBLISH button always stuck on loading state for guest user * fix: always use the full VotingPowerItem type * fix(ux): improve button layout on small screen * refactor: avoid deprecated validateForm usage * fix(ui): decrease margin size * fix(ui): improve error message * fix: fix variable not reactive * chore: update tests to include metadataUri * fix: fix metadataUri being ignored from voteHash * fix: check that voting power is successful, in case threshold is 0 * refactor: save propose and vote potential in vp store * chore: remove console output * fix: remove unecessary template wrapper * Update apps/ui/src/views/Space/Proposals.vue Co-authored-by: Wiktor Tkaczyński <[email protected]> --------- Co-authored-by: Wiktor Tkaczyński <[email protected]>
- Loading branch information
Showing
35 changed files
with
645 additions
and
269 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
--- | ||
"@snapshot-labs/sx": patch | ||
--- | ||
|
||
support submitting a reason when voting |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,45 @@ | ||
<script setup lang="ts"> | ||
import { VotingPowerItem } from '@/stores/votingPowers'; | ||
defineProps<{ | ||
votingPower: VotingPowerItem; | ||
action?: 'vote' | 'propose'; | ||
}>(); | ||
defineEmits<{ | ||
(e: 'fetchVotingPower'); | ||
}>(); | ||
</script> | ||
|
||
<template> | ||
<div | ||
v-if="votingPower.status === 'error'" | ||
class="flex flex-col gap-3 items-start" | ||
v-bind="$attrs" | ||
> | ||
<UiAlert type="error"> | ||
There was an error fetching your voting power. | ||
</UiAlert> | ||
<UiButton | ||
type="button" | ||
class="flex items-center gap-2" | ||
@click="$emit('fetchVotingPower')" | ||
> | ||
<IH-refresh />Retry | ||
</UiButton> | ||
</div> | ||
<UiAlert | ||
v-else-if="action === 'vote' && !votingPower.canVote" | ||
type="error" | ||
v-bind="$attrs" | ||
> | ||
You do not have enough voting power to vote. | ||
</UiAlert> | ||
<UiAlert | ||
v-else-if="action === 'propose' && !votingPower.canPropose" | ||
type="error" | ||
v-bind="$attrs" | ||
> | ||
You do not have enough voting power to create proposal in this space. | ||
</UiAlert> | ||
</template> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,168 @@ | ||
<script setup lang="ts"> | ||
import { getChoiceText, getFormattedVotingPower } from '@/helpers/utils'; | ||
import { getValidator } from '@/helpers/validation'; | ||
import { Choice, Proposal } from '@/types'; | ||
const REASON_DEFINITION = { | ||
title: 'Reason', | ||
type: 'string', | ||
format: 'long', | ||
examples: ['Share you reason (optional)'], | ||
maxLength: 1000 | ||
}; | ||
const props = defineProps<{ | ||
proposal: Proposal; | ||
choice: Choice | null; | ||
open: boolean; | ||
}>(); | ||
const emit = defineEmits<{ | ||
(e: 'close'); | ||
(e: 'voted'); | ||
}>(); | ||
const { vote } = useActions(); | ||
const { web3 } = useWeb3(); | ||
const { | ||
votingPower, | ||
fetch: fetchVotingPower, | ||
reset: resetVotingPower | ||
} = useVotingPower(); | ||
const loading = ref(false); | ||
const form = ref<Record<string, string>>({ reason: '' }); | ||
const formErrors = ref({} as Record<string, any>); | ||
const formValidated = ref(false); | ||
const formValidator = getValidator({ | ||
$async: true, | ||
type: 'object', | ||
title: 'Reason', | ||
additionalProperties: false, | ||
required: [], | ||
properties: { | ||
reason: REASON_DEFINITION | ||
} | ||
}); | ||
const formattedVotingPower = computed(() => | ||
getFormattedVotingPower(votingPower.value) | ||
); | ||
const canSubmit = computed( | ||
() => | ||
formValidated && | ||
!!props.choice && | ||
Object.keys(formErrors.value).length === 0 && | ||
votingPower.value?.canVote | ||
); | ||
async function handleSubmit() { | ||
loading.value = true; | ||
if (!props.choice) return; | ||
try { | ||
await vote(props.proposal, props.choice, form.value.reason); | ||
emit('voted'); | ||
emit('close'); | ||
} finally { | ||
loading.value = false; | ||
} | ||
} | ||
function handleFetchVotingPower() { | ||
fetchVotingPower(props.proposal); | ||
} | ||
watch( | ||
[() => props.open, () => web3.value.account], | ||
([open, toAccount], [, fromAccount]) => { | ||
if (fromAccount && toAccount && fromAccount !== toAccount) { | ||
resetVotingPower(); | ||
} | ||
if (open) handleFetchVotingPower(); | ||
}, | ||
{ immediate: true } | ||
); | ||
watchEffect(async () => { | ||
formValidated.value = false; | ||
formErrors.value = await formValidator.validateAsync(form.value); | ||
formValidated.value = true; | ||
}); | ||
</script> | ||
|
||
<template> | ||
<UiModal :open="open" @close="$emit('close')"> | ||
<template #header> | ||
<h3>Cast your vote</h3> | ||
</template> | ||
<div class="m-4 mb-3 flex flex-col space-y-3"> | ||
<MessageVotingPower | ||
v-if="votingPower" | ||
:voting-power="votingPower" | ||
action="vote" | ||
@fetch-voting-power="handleFetchVotingPower" | ||
/> | ||
<dl> | ||
<dt class="text-sm leading-5">Choice</dt> | ||
<dd class="text-skin-heading text-[20px] leading-6"> | ||
<span | ||
v-if="choice" | ||
class="test-skin-heading font-semibold" | ||
v-text="getChoiceText(proposal.choices, choice)" | ||
/> | ||
<div v-else class="flex gap-1 text-skin-danger items-center"> | ||
<IH-exclamation-circle /> | ||
No choice selected | ||
</div> | ||
</dd> | ||
<dt class="text-sm leading-5 mt-3">Voting power</dt> | ||
<dd v-if="!votingPower || votingPower.status === 'loading'"> | ||
<UiLoading /> | ||
</dd> | ||
<dd | ||
v-else-if="votingPower.status === 'success'" | ||
class="font-semibold text-skin-heading text-[20px] leading-6" | ||
v-text="formattedVotingPower" | ||
/> | ||
<dd | ||
v-else-if="votingPower.status === 'error'" | ||
class="font-semibold text-skin-heading text-[20px] leading-6" | ||
v-text="formattedVotingPower" | ||
/> | ||
</dl> | ||
<div class="s-box"> | ||
<UiForm | ||
v-model="form" | ||
:error="formErrors" | ||
:definition="{ properties: { reason: REASON_DEFINITION } }" | ||
/> | ||
</div> | ||
</div> | ||
|
||
<template #footer> | ||
<div class="flex flex-col xs:flex-row gap-3"> | ||
<UiButton | ||
class="w-full order-last xs:order-none" | ||
@click="$emit('close')" | ||
> | ||
Cancel | ||
</UiButton> | ||
<UiButton | ||
primary | ||
class="w-full" | ||
:disabled="!canSubmit" | ||
:loading="loading" | ||
@click="handleSubmit" | ||
> | ||
Confirm | ||
</UiButton> | ||
</div> | ||
</template> | ||
</UiModal> | ||
</template> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.