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
12 changes: 11 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,16 @@ Copy `.env.example` to `.env` and fill out the info
`DEV_FORCE_IS_EBOARD="true"` will force vote to treat all users as E-Board members
`DEV_FORCE_IS_EVALS="true"` will force vote to treat all users as the Evals director

## Running Locally

This project can be easily run using either `docker` or `podman`

The run command is the same for both, just replace `podman` with `docker` if you perfer to use docker over podman

```sh
podman compose up
```

## Linting
These will be checked by CI

Expand All @@ -40,7 +50,7 @@ go vet *.go

- [ ] Don't let the user fuck it up
- [ ] Show E-Board polls with a higher priority
- [x] Move Hide Vote to create instead of after you vote :skull:
- [X] Move Hide Vote to create instead of after you vote :skull:
- [X] Display the reason why a user is on the results page of a running poll
- [ ] Display minimum time left that a poll is open
- [ ] Move routes to their own functions
Expand Down
7 changes: 7 additions & 0 deletions api.go
Original file line number Diff line number Diff line change
Expand Up @@ -224,6 +224,13 @@ func CreatePoll(c *gin.Context) {
return
}

poll.Id = pollId

broker.Notifier <- sse.NotificationEvent{
EventName: "new-polls",
Payload: poll,
}

c.Redirect(http.StatusFound, "/poll/"+pollId)
}

Expand Down
4 changes: 3 additions & 1 deletion main.go
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,9 @@ func main() {
"MakeLinks": MakeLinks,
})
r.LoadHTMLGlob("templates/*")
broker = sse.NewBroker()
broker = sse.NewBroker(
GetUserData,
)

csh := cshAuth.CSHAuth{}
csh.Init(
Expand Down
25 changes: 22 additions & 3 deletions sse/broker.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,11 @@ package sse
import (
"io"
"log"
"slices"
"time"

cshAuth "github.com/computersciencehouse/csh-auth"
"github.com/computersciencehouse/vote/database"
"github.com/gin-gonic/gin"
)

Expand All @@ -54,22 +57,28 @@ type (

// Client connections registry
clients map[NotifierChan]struct{}

// Callbacks for cross-package access to main package functions
GetUser func(*gin.Context) cshAuth.CSHUserInfo
}
)

func NewBroker() (broker *Broker) {
func NewBroker(getUser func(*gin.Context) cshAuth.CSHUserInfo) (broker *Broker) {
// Instantiate a broker
return &Broker{
Notifier: make(NotifierChan, 1),
newClients: make(chan NotifierChan),
closingClients: make(chan NotifierChan),
clients: make(map[NotifierChan]struct{}),
GetUser: getUser,
}
}

func (broker *Broker) ServeHTTP(c *gin.Context) {
eventName := c.Param("topic")

username := broker.GetUser(c).Username

// Each connection registers its own message channel with the Broker's connections registry
messageChan := make(NotifierChan)

Expand All @@ -86,8 +95,18 @@ func (broker *Broker) ServeHTTP(c *gin.Context) {
// Emit Server Sent Events compatible
event := <-messageChan

switch eventName {
case event.EventName:
switch event.EventName {
case "new-polls":
payload, ok := event.Payload.(*database.Poll)

if !ok {
log.Fatal("Event payload is not of type database.Poll")
}

if !(payload.Gatekeep && payload.HideForIneligible) || slices.Contains(payload.AllowedUsers, username) {
c.SSEvent(event.EventName, event.Payload)
}
case eventName:
c.SSEvent(event.EventName, event.Payload)
}

Expand Down
40 changes: 34 additions & 6 deletions templates/index.tmpl
Original file line number Diff line number Diff line change
Expand Up @@ -18,18 +18,46 @@
class="list-group-item list-group-item-action p-3"
href="/poll/{{ $poll.Id }}"
>
<span><strong>
{{ $poll.Title }}
</strong></span>
<strong>
{{ $poll.Title }}
</strong>

<span
><i>(created by {{ $poll.CreatedBy }})</i></span
>
<i>(created by {{ $poll.CreatedBy }})</i>
</a>
</li>
{{ end }}
</ul>
</div>
</div>
<script>
const handlePollEvent = function (event) {
const data = JSON.parse(event.data);

console.log(data);

const listItem = document.createElement("li");
const link = document.createElement("a");
const title = document.createElement("strong");
const author = document.createElement("i");

link.classList.add("list-group-item", "list-group-item-action", "p-3");
link.href = `/poll/${data.Id}`;

title.innerText = data.Title;

author.innerText = ` (created by ${data.CreatedBy})`;

link.appendChild(title);
link.appendChild(author);
listItem.appendChild(link);
document.querySelector("ul.list-group").prepend(listItem);

console.log(listItem);
}

let eventSource = new EventSource("/stream/new-polls");

eventSource.addEventListener("new-polls", handlePollEvent);
</script>
</body>
</html>
Loading