diff --git a/client/webserver/site/src/css/proposal.scss b/client/webserver/site/src/css/proposal.scss index d621ed3f57..91f3f65093 100644 --- a/client/webserver/site/src/css/proposal.scss +++ b/client/webserver/site/src/css/proposal.scss @@ -1,8 +1,3 @@ -.vote-icon { - color: #fff; - display: block; -} - .proposal-content { h1, h2, h3 { font-size: 1.3rem; @@ -10,39 +5,9 @@ } .vote-btn { - display: flex; - align-items: center; - width: 100%; - max-width: 420px; - border: none; - font-weight: 600; - cursor: pointer; - color: #fff; -} - -.vote-btn .icon { - width: 20px; - height: 20px; - border-radius: 50%; - display: grid; - place-items: center; - font-size: 20px; - font-weight: 700; -} - -.vote-btn .label { flex: 1; - text-align: center; -} - -.vote-btn.vote-yes { - background: #6dff4f; -} -.vote-btn.vote-no { - background: #d81e14; -} - -.vote-btn.active { - border: 3px solid var(--btn-go-bg); + &.active { + outline: 3px solid var(--text-color); + } } diff --git a/client/webserver/site/src/html/proposal.tmpl b/client/webserver/site/src/html/proposal.tmpl index 2c22d4d95f..d25dc8034a 100644 --- a/client/webserver/site/src/html/proposal.tmpl +++ b/client/webserver/site/src/html/proposal.tmpl @@ -119,36 +119,20 @@
[[[vote]]]
-

+

[[[cast_vote_prompt]]] -

-
[[[voting_power]]]: {{$votingPower}}
-
- - -
- - -
+
+ [[[voting_power]]]: {{$votingPower}} +
+
+ + +
+
+ +
+
diff --git a/client/webserver/site/src/js/proposal.ts b/client/webserver/site/src/js/proposal.ts index 3d3f6764ca..e0ba9123b8 100644 --- a/client/webserver/site/src/js/proposal.ts +++ b/client/webserver/site/src/js/proposal.ts @@ -107,6 +107,7 @@ export default class ProposalPage extends BasePage { Doc.show(page.voteFormError) return } + Doc.hide(page.viewVoteFormBtn) this.closePopups() this.showSuccess(intl.prep(intl.ID_VOTE_CAST_MESSAGE)) } diff --git a/dex/politeia/politeia.go b/dex/politeia/politeia.go index eb67ad4b1e..53a587e52a 100644 --- a/dex/politeia/politeia.go +++ b/dex/politeia/politeia.go @@ -141,32 +141,45 @@ func New(ctx context.Context, politeiaURL string, dbPath string, log dex.Logger) // have voted along with their votes, and the total yes and no votes cast by // the wallet. func (p *Politeia) WalletProposalVoteDetails(wallet VotingWallet, token string) (*WalletProposalVoteDetails, error) { - req := tkv1.Results{ - Token: token, - } - votesResults, err := p.client.TicketVoteResults(req) + // Fetch the vote details to get the full list of eligible tickets + // from the snapshot. + voteDetails, err := p.client.TicketVoteDetails(tkv1.Details{Token: token}) if err != nil { - return nil, err + return nil, fmt.Errorf("TicketVoteDetails error: %w", err) + } + if voteDetails.Vote == nil { + return nil, fmt.Errorf("no vote details for proposal %s", token) } - hashes := make([]*chainhash.Hash, 0, len(votesResults.Votes)) - castVotes := make(map[string]string) - for _, v := range votesResults.Votes { - hash, err := chainhash.NewHashFromStr(v.Ticket) + // Build the list of all eligible ticket hashes from the vote snapshot. + eligibleHashes := make([]*chainhash.Hash, 0, len(voteDetails.Vote.EligibleTickets)) + for _, ticketStr := range voteDetails.Vote.EligibleTickets { + hash, err := chainhash.NewHashFromStr(ticketStr) if err != nil { return nil, err } - hashes = append(hashes, hash) + eligibleHashes = append(eligibleHashes, hash) + } + + // Fetch the votes already cast to know which tickets have voted. + votesResults, err := p.client.TicketVoteResults(tkv1.Results{Token: token}) + if err != nil { + return nil, fmt.Errorf("TicketVoteResults error: %w", err) + } + + castVotes := make(map[string]string, len(votesResults.Votes)) + for _, v := range votesResults.Votes { castVotes[v.Ticket] = v.VoteBit } - walletTicketHashes, addresses, err := wallet.CommittedTickets(hashes) + // Check which eligible tickets belong to this wallet. + walletTicketHashes, addresses, err := wallet.CommittedTickets(eligibleHashes) if err != nil { return nil, err } - eligibleWalletTickets := make([]*Ticket, 0) // eligibleWalletTickets are wallet tickets that have not yet voted. - walletVotedTickets := make([]*Ticket, 0) // walletVotedTickets are wallet tickets that have voted. + eligibleWalletTickets := make([]*Ticket, 0) + walletVotedTickets := make([]*Ticket, 0) for i := 0; i < len(walletTicketHashes); i++ { ticket := &Ticket{ Hash: walletTicketHashes[i].String(), @@ -176,17 +189,18 @@ func (p *Politeia) WalletProposalVoteDetails(wallet VotingWallet, token string) isMine, accountNumber, err := wallet.AddressAccount(ticket.Address) if err != nil { if strings.Contains(err.Error(), "address not found in wallet") { - continue // address not found in wallet, skip this ticket + continue } return nil, err } - // filter out tickets controlled by imported accounts or not owned by this wallet + // Filter out tickets controlled by imported accounts or not + // owned by this wallet. if !isMine || accountNumber == udb.ImportedAddrAccount { continue } - // filter out wallet tickets that have voted. + // Separate into already-voted and eligible. if _, ok := castVotes[ticket.Hash]; ok { walletVotedTickets = append(walletVotedTickets, ticket) continue @@ -262,6 +276,13 @@ func (p *Politeia) CastVotes(wallet VotingWallet, eligibleTickets []*Ticket, bit return fmt.Errorf("errors casting votes: %v", strings.Join(voteErrors, "; ")) } + ticketHashes := make([]string, len(eligibleTickets)) + for i, t := range eligibleTickets { + ticketHashes[i] = t.Hash + } + p.log.Infof("Successfully cast %d %s vote(s) on proposal %s with tickets: %s", + len(eligibleTickets), bit, token, strings.Join(ticketHashes, ", ")) + return nil }