tornado-classic-ui/components/governance/CreateProposal.vue

196 lines
5.0 KiB
Vue

<template>
<div class="proposal">
<h1 class="title">{{ $t('createProposal') }}</h1>
<div class="columns is-multiline">
<div class="column is-6">
<b-field
:label="$t('proposalTitle')"
:message="isValidTitle ? '' : $t('proposal.error.title')"
:type="{ 'is-warning': !isValidTitle }"
>
<b-input v-model="validTitle" :placeholder="$t('title')"></b-input>
</b-field>
</div>
<div class="column is-6">
<b-field
:label="$t('proposalAddress')"
:type="{ 'is-warning': !hasValidAddress }"
:message="hasValidAddress ? '' : addressErrorMessage"
>
<b-input
v-model="address"
:placeholder="$t('proposalAddress')"
:size="!address ? '' : hasValidAddress ? '' : 'is-warning'"
></b-input>
</b-field>
</div>
<div class="column is-12">
<b-field
:message="isValidDescription ? '' : $t('proposal.error.description')"
:type="{ 'is-warning': !isValidDescription }"
:label="$t('proposalDescription')"
>
<b-input v-model="validDescription" maxlength="2000" type="textarea"></b-input>
</b-field>
</div>
</div>
<b-tooltip :label="`${$t('onlyOneProposalErr')}`" position="is-top" :active="cannotCreate" multilined>
<b-button
:disabled="cannotCreate"
type="is-primary"
:icon-left="isFetchingBalances ? '' : 'plus'"
outlined
:loading="isFetchingBalances"
@click="onCreateProposal"
>
{{ $t('createProposal') }}
</b-button>
</b-tooltip>
</div>
</template>
<script>
import { mapActions, mapState, mapGetters } from 'vuex'
import { debounce } from '@/utils'
const { isAddress } = require('web3-utils')
export default {
data() {
return {
proposalAddress: '',
description: '',
title: '',
isValidAddress: true,
isValidContract: true,
isValidTitle: true,
isValidDescription: true
}
},
computed: {
...mapState('governance/gov', ['latestProposalId']),
...mapGetters('governance/gov', ['isFetchingBalances']),
address: {
get() {
return this.proposalAddress
},
set(address) {
this.setInitialState()
this.proposalAddress = address
debounce(this.validateAddress, address)
}
},
validTitle: {
get() {
return this.title
},
set(title) {
this.isValidTitle = true
this.title = title
}
},
addressErrorMessage() {
if (!this.isValidAddress) {
return this.$t('proposal.error.address')
}
if (!this.isValidContract) {
return this.$t('proposal.error.contract')
}
return this.$t('proposal.error.address')
},
validDescription: {
get() {
return this.description
},
set(description) {
this.isValidDescription = true
this.description = description
}
},
hasValidAddress() {
return this.isValidAddress && this.isValidContract
},
cannotCreate() {
return (
this.latestProposalId.value !== 0 &&
(this.latestProposalId.status === 'active' || this.latestProposalId.status === 'pending')
)
}
},
methods: {
...mapActions('governance/gov', ['createProposal']),
async addressIsContract(address) {
if (!address) {
return false
}
const code = await this.$provider.web3.eth.getCode(address)
return code !== '0x'
},
isAddress(address) {
const isCorrect = isAddress(address)
if (!isCorrect && address) {
this.isValidAddress = isCorrect
}
return isCorrect
},
async isContract(address) {
const isContract = await this.addressIsContract(address)
if (!isContract && address) {
this.isValidContract = isContract
}
return isContract
},
setInitialState() {
this.isValidAddress = true
this.isValidContract = true
},
async validateAddress(address) {
const isCorrect = this.isAddress(address)
if (!isCorrect) {
return false
}
const isContract = await this.isContract(address)
return isContract
},
async validationForms() {
this.isValidTitle = this.title
this.isValidDescription = this.description
this.isValidAddress = this.proposalAddress
const isCorrect = await this.validateAddress(this.proposalAddress)
return isCorrect && this.isValidAddress && this.isValidTitle && this.isValidDescription
},
async onCreateProposal() {
const isValidForms = await this.validationForms()
if (!isValidForms) {
return
}
this.$store.dispatch('loading/enable', { message: this.$t('preparingTransactionData') })
await this.createProposal({
proposalAddress: this.proposalAddress,
title: this.title,
description: this.description
})
this.$store.dispatch('loading/disable')
// this.$parent.close()
}
}
}
</script>