Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
140 changes: 72 additions & 68 deletions server/src/votings/dto.go
Original file line number Diff line number Diff line change
@@ -1,129 +1,133 @@
package votings

import (
"net/http"
"net/http"

"github.com/google/uuid"
"github.com/google/uuid"
)

type Vote struct {
Voting uuid.UUID `json:"voting"`
Note uuid.UUID `json:"note"`
User uuid.UUID `json:"user"`
Voting uuid.UUID `json:"voting"`
Note uuid.UUID `json:"note"`
User uuid.UUID `json:"user"`
}

func (v *Vote) From(vote DatabaseVote) *Vote {
v.Voting = vote.Voting
v.Note = vote.Note
v.User = vote.User
return v
v.Voting = vote.Voting
v.Note = vote.Note
v.User = vote.User
return v
}

func Votes(votes []DatabaseVote) []*Vote {
if votes == nil {
return nil
}

list := make([]*Vote, len(votes))
for index, vote := range votes {
list[index] = new(Vote).From(vote)
}
return list
if votes == nil {
return nil
}

list := make([]*Vote, len(votes))
for index, vote := range votes {
list[index] = new(Vote).From(vote)
}
return list
}

// VoteRequest represents the request to add or delete a vote.
type VoteRequest struct {
Note uuid.UUID `json:"note"`
Board uuid.UUID `json:"-"`
User uuid.UUID `json:"-"`
Note uuid.UUID `json:"note"`
Board uuid.UUID `json:"-"`
User uuid.UUID `json:"-"`
}

// VotingCreateRequest represents the request to create a new voting session.
type VotingCreateRequest struct {
Board uuid.UUID `json:"-"`
VoteLimit int `json:"voteLimit"`
AllowMultipleVotes bool `json:"allowMultipleVotes"`
ShowVotesOfOthers bool `json:"showVotesOfOthers"`
IsAnonymous bool `json:"isAnonymous"`
Board uuid.UUID `json:"-"`
VoteLimit int `json:"voteLimit"`
AllowMultipleVotes bool `json:"allowMultipleVotes"`
ShowVotesOfOthers bool `json:"showVotesOfOthers"`
IsAnonymous bool `json:"isAnonymous"`
}

// VotingUpdateRequest represents the request to update a voting session.
type VotingUpdateRequest struct {
ID uuid.UUID `json:"-"`
Board uuid.UUID `json:"-"`
Status VotingStatus `json:"status"`
ID uuid.UUID `json:"-"`
Board uuid.UUID `json:"-"`
Status VotingStatus `json:"status"`
}

// Voting is the response for all voting requests.
type Voting struct {
ID uuid.UUID `json:"id"`
VoteLimit int `json:"voteLimit"`
AllowMultipleVotes bool `json:"allowMultipleVotes"`
ShowVotesOfOthers bool `json:"showVotesOfOthers"`
Status VotingStatus `json:"status"`
VotingResults *VotingResults `json:"votes,omitempty"`
IsAnonymous bool `json:"isAnonymous"`
ID uuid.UUID `json:"id"`
VoteLimit int `json:"voteLimit"`
AllowMultipleVotes bool `json:"allowMultipleVotes"`
ShowVotesOfOthers bool `json:"showVotesOfOthers"`
Status VotingStatus `json:"status"`
VotingResults *VotingResults `json:"votes,omitempty"`
IsAnonymous bool `json:"isAnonymous"`
}

func (v *Voting) From(voting DatabaseVoting, votes []DatabaseVote) *Voting {
v.ID = voting.ID
v.VoteLimit = voting.VoteLimit
v.AllowMultipleVotes = voting.AllowMultipleVotes
v.ShowVotesOfOthers = voting.ShowVotesOfOthers
v.Status = voting.Status
v.VotingResults = getVotingWithResults(voting, votes)
v.IsAnonymous = voting.IsAnonymous
return v
v.ID = voting.ID
v.VoteLimit = voting.VoteLimit
v.AllowMultipleVotes = voting.AllowMultipleVotes
v.ShowVotesOfOthers = voting.ShowVotesOfOthers
v.Status = voting.Status
v.VotingResults = getVotingWithResults(voting, votes)
v.IsAnonymous = voting.IsAnonymous
return v
}

func (*Voting) Render(_ http.ResponseWriter, _ *http.Request) error {
return nil
return nil
}

type VotingResults struct {
Total int `json:"total"`
Votes map[uuid.UUID]VotingResultsPerNote `json:"votesPerNote"`
Total int `json:"total"`
Votes map[uuid.UUID]VotingResultsPerNote `json:"votesPerNote"`
}

type VotingResultsPerUser struct {
ID uuid.UUID `json:"id"`
Total int `json:"total"`
ID uuid.UUID `json:"id"`
Total int `json:"total"`
}

type VotingResultsPerNote struct {
Total int `json:"total"`
Users *[]VotingResultsPerUser `json:"userVotes,omitempty"`
Total int `json:"total"`
Users *[]VotingResultsPerUser `json:"userVotes,omitempty"`
}

type VotingUpdated struct {
Notes []Note `json:"notes"`
Voting *Voting `json:"voting"`
Notes []Note `json:"notes"`
Voting *Voting `json:"voting"`
}

type Note struct {
// The id of the note
ID uuid.UUID `json:"id"`
// The id of the note
ID uuid.UUID `json:"id"`

// The author of the note.
Author uuid.UUID `json:"author"`
// The author of the note.
Author uuid.UUID `json:"author"`

// The text of the note.
Text string `json:"text"`
// The text of the note.
Text string `json:"text"`

Edited bool `json:"edited"`
Edited bool `json:"edited"`

// The position of the note.
Position NotePosition `json:"position"`
// The position of the note.
Position NotePosition `json:"position"`
}

type NotePosition struct {

// The column of the note.
Column uuid.UUID `json:"column"`
// The column of the note.
Column uuid.UUID `json:"column"`

// The parent note for this note in a stack.
Stack uuid.NullUUID `json:"stack"`
// The parent note for this note in a stack.
Stack uuid.NullUUID `json:"stack"`

// The note rank.
Rank int `json:"rank"`
// The note rank.
Rank int `json:"rank"`
}
type notesWithVotes struct {
Note Note
Votes int
}
37 changes: 35 additions & 2 deletions server/src/votings/service.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import (
"context"
"database/sql"
"errors"

"github.com/google/uuid"
"go.opentelemetry.io/otel"
"go.opentelemetry.io/otel/attribute"
Expand Down Expand Up @@ -326,13 +325,37 @@ func (s *Service) updatedVoting(ctx context.Context, board uuid.UUID, voting Dat
attribute.Bool("scrumlr.votings.service.update.show_votes", voting.ShowVotesOfOthers),
)

aVoting := new(Voting).From(voting, votes)
var notesSortedByVotes []notesWithVotes
if aVoting.VotingResults != nil {

for k, v := range aVoting.VotingResults.Votes {
note, err := popNote(&affectedNotes, k)
if err != nil {
span.SetStatus(codes.Error, "missing note from voting results")
span.RecordError(err)
log.Errorw("unable to find note from a voting", "note", k, "err", err)
return
}
if len(notesSortedByVotes) == 0 || notesSortedByVotes[0].Votes > v.Total {
notesSortedByVotes = append([]notesWithVotes{{note, v.Total}}, notesSortedByVotes...)
} else {
notesSortedByVotes = append(notesSortedByVotes, notesWithVotes{note, v.Total})
}
}

for _, note := range notesSortedByVotes {
affectedNotes = append([]Note{note.Note}, affectedNotes...)
}
}

err := s.realtime.BroadcastToBoard(ctx, board, realtime.BoardEvent{
Type: realtime.BoardEventVotingUpdated,
Data: struct {
Voting *Voting `json:"voting"`
Notes []Note `json:"notes"`
}{
Voting: new(Voting).From(voting, votes),
Voting: aVoting,
Notes: affectedNotes,
},
})
Expand All @@ -343,3 +366,13 @@ func (s *Service) updatedVoting(ctx context.Context, board uuid.UUID, voting Dat
log.Errorw("unable to send voting update", "err", err)
}
}

func popNote(affectedNotes *[]Note, noteID uuid.UUID) (Note, error) {
for i, n := range *affectedNotes {
if n.ID == noteID {
*affectedNotes = append((*affectedNotes)[:i], (*affectedNotes)[i+1:]...)
return n, nil
}
}
return Note{}, errors.New("note not found")
}
Loading
Loading