Skip to content
This repository was archived by the owner on Feb 16, 2022. It is now read-only.
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
1 change: 1 addition & 0 deletions index.html
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
font-family: 'Noto Serif', serif;
}
</style>
<link rel="stylesheet" href="./src/styles.scss">
</head>

<body>
Expand Down
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
"elm-format": "^0.8.3",
"elm-hot": "^1.1.4",
"node-elm-compiler": "^5.0.4",
"sass": "^1.26.11",
"typescript": "^3.8.3"
},
"dependencies": {
Expand Down
29 changes: 28 additions & 1 deletion src/Decoder.elm
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
module Decoder exposing (decodeAlternative, decodeReceivedIssue, decodeVote, decodeWebSocketMessage)
module Decoder exposing (decodeAlternative, decodeReceivedIssue, decodeVote, decodeWebSocketMessage, encodeIssueState)

import Json.Decode as D
import Model exposing (Alternative, Client, Issue, IssueState(..), Vote(..), WebSocketMessage(..))
Expand Down Expand Up @@ -45,13 +45,32 @@ decodeIssueState s =
"inprogress" ->
D.succeed InProgress

"votingfinished" ->
D.succeed VotingFinished

"finished" ->
D.succeed Finished

_ ->
D.fail ("error decoding '" ++ s ++ "' as IssueState")


encodeIssueState : IssueState -> String
encodeIssueState state =
case state of
NotStarted ->
"notstarted"

InProgress ->
"inprogress"

VotingFinished ->
"votingfinished"

Finished ->
"finished"


decodeReceivedIssue : D.Decoder Issue
decodeReceivedIssue =
D.map8 Issue
Expand All @@ -65,6 +84,11 @@ decodeReceivedIssue =
(D.field "show_distribution" D.bool)


decodeReceivedIssues : D.Decoder (List Issue)
decodeReceivedIssues =
D.field "issues" (D.list decodeReceivedIssue)


decodeWebSocketMessage : D.Decoder WebSocketMessage
decodeWebSocketMessage =
D.field "type" D.string
Expand All @@ -74,6 +98,9 @@ decodeWebSocketMessage =
decodeMessageType : String -> D.Decoder WebSocketMessage
decodeMessageType messageType =
case messageType of
"all_issues" ->
decodeReceivedIssues |> D.map IssuesMessage

"issue" ->
decodeReceivedIssue |> D.map IssueMessage

Expand Down
29 changes: 27 additions & 2 deletions src/Main.elm
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ port module Main exposing (main)

import Browser
import Browser.Navigation as Nav
import Decoder exposing (decodeWebSocketMessage)
import Decoder exposing (decodeWebSocketMessage, encodeIssueState)
import Json.Decode as D
import Json.Encode as E
import Model exposing (ConnectionStatus(..), EventStatus(..), Flags, IssueState(..), Model, Msg(..), Theme(..), WebSocketMessage(..), dummyIssue)
Expand Down Expand Up @@ -42,6 +42,7 @@ init flags url key =
, route = Route.fromUrl url
, key = key
, config = Light
, issues = []
}
, send SendWebsocketConnect
)
Expand Down Expand Up @@ -106,7 +107,14 @@ update msg model =
)

ReceiveIssue issue ->
( { model | activeIssue = issue }, Cmd.none )
let
issues =
List.filter (\i -> i.id /= issue.id) model.issues ++ [ issue ]
in
( { model | activeIssue = issue, issues = issues }, Cmd.none )

ReceiveIssues issues ->
( { model | issues = issues }, Cmd.none )

SelectAlternative clickedAlternative ->
let
Expand Down Expand Up @@ -210,6 +218,20 @@ update msg model =
SetConfig config ->
( { model | config = config }, Cmd.none )

ListAllIssues ->
( model, sendEvent (E.object [ ( "type", E.string "list_all_issues" ) ]) )

SetIssueState issue state ->
( model
, sendEvent
(E.object
[ ( "type", E.string "set_issue_state" )
, ( "issue_id", E.string issue.id )
, ( "state", E.string (encodeIssueState state) )
]
)
)



-- util function which accepts a Msg as argument and converts it to a Cmd Msg.
Expand Down Expand Up @@ -247,6 +269,9 @@ webSocketMessageToMsg value =
ClientMessage client ->
SetClient client

IssuesMessage issues ->
ReceiveIssues issues

Err _ ->
-- TODO Handle error somehow
NoOp
Expand Down
8 changes: 7 additions & 1 deletion src/Model.elm
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,8 @@ type alias Alternative =
type IssueState
= NotStarted
| InProgress
| Finished
| VotingFinished -- Voting finished, but result not published
| Finished -- Issue completely finished, case closed style


type alias Issue =
Expand Down Expand Up @@ -73,6 +74,7 @@ type WebSocketMessage
= IssueMessage Issue
| VoteMessage Vote
| ClientMessage Client
| IssuesMessage (List Issue)


type EventStatus
Expand Down Expand Up @@ -103,6 +105,7 @@ type alias Model =
, route : Maybe Route
, key : Nav.Key
, config : Config
, issues : List Issue
}


Expand All @@ -117,6 +120,7 @@ type IssueField
type Msg
= NoOp
| ReceiveIssue Issue
| ReceiveIssues (List Issue)
| SelectAlternative Alternative
| SendVote Alternative
| SetVoteStatus EventStatus
Expand All @@ -133,6 +137,8 @@ type Msg
| UpdateIssue Issue
| UrlChanged Url
| LinkClicked Browser.UrlRequest
| ListAllIssues
| SetIssueState Issue IssueState


type Theme
Expand Down
81 changes: 79 additions & 2 deletions src/Page/Admin.elm
Original file line number Diff line number Diff line change
@@ -1,13 +1,24 @@
module Page.Admin exposing (view)

import Html exposing (Html, button, div, h2, text)
import Html exposing (Html, button, div, h2, h3, h4, p, text)
import Html.Attributes exposing (class)
import Html.Events exposing (onClick)
import Model exposing (Model, Msg, dummyIssue)
import Model exposing (Issue, IssueState(..), Model, Msg, dummyIssue)
import Page.CreateIssue


view : Model -> Html Msg
view model =
let
activeIssues =
List.filter (\i -> i.state == InProgress || i.state == VotingFinished) model.issues

finishedIssues =
List.filter (\i -> i.state == Finished) model.issues

availableIssues =
List.filter (\i -> i.state == NotStarted) model.issues
in
div []
[ h2 [] [ text "Admin page" ]
, case model.newIssue of
Expand All @@ -16,4 +27,70 @@ view model =

Nothing ->
button [ onClick (Model.UpdateIssue dummyIssue) ] [ text "Create new issue" ]
, div []
[ h3 [] [ text "Issues" ]
, button [ onClick Model.ListAllIssues ] [ text "List all issues" ]
, div [ class "issue-list issue-list--active" ] [ issueList "Active Issue" activeIssues ]
, div [ class "issue-list issue-list--available" ] [ issueList "Available Issues" availableIssues ]
, div [ class "issue-list issue-list--completed" ] [ issueList "Completed Issues" finishedIssues ]
]
]


issueList : String -> List Issue -> Html Msg
issueList title issues =
div []
[ h4 []
[ text
(if List.isEmpty issues then
"No " ++ title

else
title
)
]
, div [] (List.map issueListItem issues)
]


type alias IssueStateTransition =
{ toState : IssueState
, text : String
}


issueListItem : Issue -> Html Msg
issueListItem issue =
let
availableActions =
case issue.state of
NotStarted ->
[ { toState = InProgress, text = "set active" }
, { toState = NotStarted, text = "delete" }
]

InProgress ->
[ { toState = InProgress, text = "reset voting" }
, { toState = VotingFinished, text = "close voting" }
]

VotingFinished ->
[ { toState = InProgress, text = "reset voting" }
, { toState = Finished, text = "publish results" }
]

Finished ->
[]
in
div [ class "issue-list--item" ]
[ div [ class "issue-list--item--header" ]
[ h4 [] [ text issue.title ]
, div [ class "issue-list--actions" ] (List.map (actionButton issue) availableActions)
]
, div [] [ p [] [ text issue.description ] ]
]


actionButton : Issue -> IssueStateTransition -> Html Msg
actionButton issue transition =
div [ onClick (Model.SetIssueState issue transition.toState) ] [ text ("[" ++ transition.text ++ "]") ]
46 changes: 46 additions & 0 deletions src/Page/Admin.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
.issue-list {
margin: 1rem 0;
border: 1px solid #ddd;
border-radius: 6px;

&--item {
margin: 0.5rem 0;

&--header {
display: flex;
justify-content: space-between;

> h4 {
margin: 0;
}
}

p {
margin: 0.5rem;
}
}

h4 {
margin-top: 0;
}

&--actions {
display: flex;
justify-content: space-between;
}

&--active {
background-color: #1abc9c;
border-color: #1abc9c;
}

&--available {
background-color: #2980b9;
border-color: #2980b9;
}

&--completed {
background-color: #8e44ad;
border-color: #8e44ad;
}
}
3 changes: 3 additions & 0 deletions src/Page/Vote.elm
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,9 @@ issueProgress voters issue =
InProgress ->
"In Progress"

VotingFinished ->
"Voting Finished"

Finished ->
"Finished"

Expand Down
2 changes: 2 additions & 0 deletions src/styles.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
/* ToDo: find a nicer way to import (recursively?) */
@import "./Page/Admin.scss";
Loading