Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Elm Frontend #7

Merged
merged 2 commits into from
Jul 24, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,4 @@
*/bundled/*
node_modules
compiled_main.js
elm-stuff/
2 changes: 1 addition & 1 deletion build.sh
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
pushd rps && node_modules/jasmine/bin/jasmine.js && popd

FRONTENDS="web angularWeb refluxWeb reduxWeb vueWeb"
FRONTENDS="web angularWeb refluxWeb reduxWeb vueWeb elmWeb"

for frontend in $FRONTENDS; do
pushd $frontend
Expand Down
15 changes: 15 additions & 0 deletions elmWeb/elm-package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
{
"version": "1.0.0",
"summary": "elmWeb",
"repository": "https://github.com/moonmaster9000/rpsapp.git",
"license": "BSD3",
"source-directories": [
"src"
],
"exposed-modules": [],
"dependencies": {
"elm-lang/core": "5.1.1 <= v < 6.0.0",
"elm-lang/html": "2.0.0 <= v < 3.0.0"
},
"elm-version": "0.18.0 <= v < 0.19.0"
}
10 changes: 10 additions & 0 deletions elmWeb/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<html>
<head>
<script type="application/javascript" src="node_modules/babel-polyfill/dist/polyfill.min.js"></script>
</head>

<body>
<div id="app"></div>
<script src="bundled/main.js" type="application/javascript"></script>
</body>
</html>
7 changes: 7 additions & 0 deletions elmWeb/main.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
const {UseCaseFactory, FakeRepoFactory} = require("rps")
const RPSApp = require("./src/RPSApp")
const useCases = new UseCaseFactory(new FakeRepoFactory())

const element = document.getElementById('app')

RPSApp.render(element, useCases)
27 changes: 27 additions & 0 deletions elmWeb/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
{
"name": "elmWeb",
"version": "0.0.0",
"dependencies": {
"babel-polyfill": "^6.23.0"
},
"devDependencies": {
"babel-plugin-transform-async-to-generator": "^6.24.1",
"babel-plugin-transform-runtime": "latest",
"babel-preset-es2015": "^6.24.1",
"babelify": "^7.3.0",
"browserify": "latest",
"elm": "^0.18.0",
"karma": "^1.7.0",
"karma-chrome-launcher": "^2.2.0",
"karma-jasmine": "^1.1.0",
"rps": "file:../rps",
"rpsPresentationI18n": "file:../rpsPresentationI18n",
"webSpecs": "file:../webSpecs"
},
"scripts": {
"precompile": "elm make src/Main.elm --output bundled/ElmWeb.js",
"compile": "browserify main.js -o bundled/main.js -t [ babelify --presets [ es2015 ] --plugins [ transform-async-to-generator ] ]",
"precompile-test": "elm make src/Main.elm --output bundled/ElmWeb.js",
"compile-test": "browserify spec/webSpec.js -o bundled/compiledSpec.js -t [ babelify --presets [ es2015 ] --plugins [ transform-async-to-generator ] ]"
}
}
15 changes: 15 additions & 0 deletions elmWeb/spec/webSpec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
const webSpecs = require("webSpecs")
const RPSApp = require("../src/RPSApp")

webSpecs(
function createFixture() {
const div = document.createElement("div")
div.id = "elmApp"
return div
},

function mountApp(useCases) {
const div = document.getElementById("elmApp")
RPSApp.render(div, useCases)
},
)
111 changes: 111 additions & 0 deletions elmWeb/src/Main.elm
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
module Main exposing (..)

import Html exposing (..)
import Html.Attributes exposing (type_, id, name, value)
import Html.Events exposing (onInput, onSubmit)
import Observer exposing (Round)
import UseCases


type alias Model =
{ message : String
, p1 : String
, p2 : String
, history : List Round
}


type Msg
= HandleP1Change String
| HandleP2Change String
| Play
| ReceiveResult String
| ReceiveMessage String
| ReceiveRounds (List Round)


initialModel : Model
initialModel =
{ message = ""
, p1 = ""
, p2 = ""
, history = []
}


initialCmd : Cmd Msg
initialCmd =
UseCases.history ()


update : Msg -> Model -> ( Model, Cmd Msg )
update msg model =
case msg of
HandleP1Change p1 ->
( { model | p1 = p1 }, Cmd.none )

HandleP2Change p2 ->
( { model | p2 = p2 }, Cmd.none )

Play ->
( model, UseCases.play ( model.p1, model.p2 ) )

ReceiveResult result ->
( model, Cmd.batch [ UseCases.translate result, UseCases.history () ] )

ReceiveMessage message ->
( { model | message = message }, Cmd.none )

ReceiveRounds rounds ->
( { model | history = rounds }, Cmd.none )


subscriptions : Model -> Sub Msg
subscriptions model =
Sub.batch
[ Observer.invalid (receiveResult "invalid")
, Observer.tie (receiveResult "tie")
, Observer.p1Wins (receiveResult "p1_wins")
, Observer.p2Wins (receiveResult "p2_wins")
, Observer.rounds ReceiveRounds
, Observer.norounds receiveNoRounds
, Observer.message ReceiveMessage
]


receiveResult : String -> a -> Msg
receiveResult result _ =
ReceiveResult result


receiveNoRounds : a -> Msg
receiveNoRounds _ =
ReceiveRounds []


view : Model -> Html Msg
view model =
div []
[ h1 [] [ text model.message ]
, form [ onSubmit Play ]
[ input [ name "p1", id "p1ThrowInput", value model.p1, onInput HandleP1Change ] []
, input [ name "p2", id "p2ThrowInput", value model.p2, onInput HandleP2Change ] []
, button [ id "playButton", type_ "submit" ] [ text "Play" ]
]
, ul [] (List.map roundRow model.history)
]


roundRow : Round -> Html Msg
roundRow round =
li [] [ text (round.p1Throw ++ " " ++ round.p2Throw ++ " " ++ round.winner) ]


main : Program Never Model Msg
main =
Html.program
{ init = ( initialModel, initialCmd )
, view = view
, update = update
, subscriptions = subscriptions
}
31 changes: 31 additions & 0 deletions elmWeb/src/Observer.elm
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
port module Observer exposing (..)

import Json.Encode exposing (Value)


port invalid : (Value -> msg) -> Sub msg


port tie : (Value -> msg) -> Sub msg


port p1Wins : (Value -> msg) -> Sub msg


port p2Wins : (Value -> msg) -> Sub msg


port norounds : (Value -> msg) -> Sub msg


port rounds : (List Round -> msg) -> Sub msg


port message : (String -> msg) -> Sub msg


type alias Round =
{ p1Throw : String
, p2Throw : String
, winner : String
}
32 changes: 32 additions & 0 deletions elmWeb/src/RPSApp.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
const ElmWeb = require("../bundled/ElmWeb")
const Locale = require("rpsPresentationI18n")

const RPSApp = {
render(element, useCases) {
const app = ElmWeb.Main.embed(element)
const locale = new Locale()

const ui = {
invalid: app.ports.invalid.send,
tie: app.ports.tie.send,
p1Wins: app.ports.p1Wins.send,
p2Wins: app.ports.p2Wins.send,
norounds: app.ports.norounds.send,
rounds: app.ports.rounds.send,
}

app.ports.play.subscribe(([p1, p2]) => {
useCases.play(p1, p2, ui)
})

app.ports.translate.subscribe((result) => {
app.ports.message.send(locale.t(result))
})

app.ports.history.subscribe(() => {
useCases.history(ui)
})
}
}

module.exports = RPSApp
10 changes: 10 additions & 0 deletions elmWeb/src/UseCases.elm
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
port module UseCases exposing (..)


port play : ( String, String ) -> Cmd msg


port translate : String -> Cmd msg


port history : () -> Cmd msg
12 changes: 12 additions & 0 deletions elmWeb/test.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<html>
<head>
<link rel="stylesheet" type="text/css" href="node_modules/jasmine-core/lib/jasmine-core/jasmine.css">

<script type="text/javascript" src="node_modules/jasmine-core/lib/jasmine-core/jasmine.js"></script>
<script type="text/javascript" src="node_modules/jasmine-core/lib/jasmine-core/jasmine-html.js"></script>
<script type="text/javascript" src="node_modules/jasmine-core/lib/jasmine-core/boot.js"></script>
<script type="text/javascript" src="bundled/compiledSpec.js"></script>
</head>
<body>
</body>
</html>
64 changes: 64 additions & 0 deletions elmWeb/web.karma.conf.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
module.exports = function(config) {
config.set({

// base path that will be used to resolve all patterns (eg. files, exclude)
basePath: '',


// frameworks to use
// available frameworks: https://npmjs.org/browse/keyword/karma-adapter
frameworks: ['jasmine'],


// list of files / patterns to load in the browser
files: [
'node_modules/babel-polyfill/dist/polyfill.min.js',
'bundled/compiledSpec.js',
],


// list of files to exclude
exclude: [
],


// preprocess matching files before serving them to the browser
// available preprocessors: https://npmjs.org/browse/keyword/karma-preprocessor
preprocessors: {
},


// test results reporter to use
// possible values: 'dots', 'progress'
// available reporters: https://npmjs.org/browse/keyword/karma-reporter
reporters: ['dots'],


// web server port
port: 9876,


// enable / disable colors in the output (reporters and logs)
colors: true,


// level of logging
// possible values: config.LOG_DISABLE || config.LOG_ERROR || config.LOG_WARN || config.LOG_INFO || config.LOG_DEBUG
logLevel: config.LOG_DISABLE,

// enable / disable watching file and executing tests whenever any file changes
autoWatch: true,

// start these browsers
// available browser launchers: https://npmjs.org/browse/keyword/karma-launcher
browsers: ['Chrome'],

// Continuous Integration mode
// if true, Karma captures browsers, runs the tests and exits
singleRun: true,

// Concurrency level
// how many browser should be started simultaneous
concurrency: Infinity
})
}