├── RLBServer ├── user ├── package.json └── README.md ├── .gitignore ├── 07RLBStarter ├── README.md ├── package.json ├── dist │ └── index.html ├── elm-package.json ├── gulpfile.js └── src │ ├── Main.elm │ ├── Login.elm │ ├── LeaderBoard.elm │ └── Runner.elm ├── 04Websocket ├── README.md ├── package.json ├── elm-package.json ├── server.js └── Main.elm ├── 06Ports ├── package.json ├── elm-package.json ├── completed │ ├── elm-package.json │ ├── appfb.js │ ├── gulpfile.js │ ├── index.html │ └── Main.elm ├── README.md ├── appfb.js ├── gulpfile.js ├── index.html └── Main.elm ├── 09RLBLogin ├── package.json ├── dist │ └── index.html ├── elm-package.json ├── gulpfile.js └── src │ ├── LeaderBoard.elm │ ├── Login.elm │ └── Runner.elm ├── 11RLBLogout ├── package.json ├── elm-package.json ├── dist │ └── index.html ├── gulpfile.js └── src │ ├── LeaderBoard.elm │ ├── Login.elm │ └── Runner.elm ├── 08RLBNavigation ├── package.json ├── dist │ └── index.html ├── completed │ ├── package.json │ ├── dist │ │ └── index.html │ ├── elm-package.json │ ├── gulpfile.js │ └── src │ │ ├── Login.elm │ │ ├── LeaderBoard.elm │ │ └── Runner.elm ├── elm-package.json ├── gulpfile.js └── src │ ├── Login.elm │ ├── LeaderBoard.elm │ ├── Main.elm │ └── Runner.elm ├── 10RLBLoginToken ├── package.json ├── elm-package.json ├── dist │ └── index.html ├── gulpfile.js └── src │ ├── LeaderBoard.elm │ ├── Login.elm │ └── Runner.elm ├── 13RLBAddRunner ├── package.json ├── completed │ ├── package.json │ ├── elm-package.json │ ├── dist │ │ └── index.html │ ├── gulpfile.js │ └── src │ │ ├── LeaderBoard.elm │ │ └── Login.elm ├── elm-package.json ├── dist │ └── index.html ├── gulpfile.js └── src │ ├── LeaderBoard.elm │ └── Login.elm ├── 14RLBWebsocket ├── package.json ├── completed │ ├── package.json │ ├── elm-package.json │ ├── dist │ │ └── index.html │ ├── gulpfile.js │ └── src │ │ └── Login.elm ├── elm-package.json ├── dist │ └── index.html ├── gulpfile.js └── src │ └── Login.elm ├── 16RLBFilterRunner ├── package.json ├── dist │ └── index.html ├── elm-package.json ├── gulpfile.js └── src │ └── Login.elm ├── 12RLBLockRunnerPage ├── package.json ├── elm-package.json ├── dist │ └── index.html ├── gulpfile.js └── src │ ├── LeaderBoard.elm │ ├── Login.elm │ └── Runner.elm ├── 15RLBEstimatedDistance ├── package.json ├── dist │ └── index.html ├── elm-package.json ├── gulpfile.js └── src │ └── Login.elm ├── 00Review ├── elm-package.json └── Login.elm ├── 01The-Elm-Architecture ├── elm-package.json ├── LeaderBoard.elm ├── Login.elm └── Main.elm ├── 02Effects ├── elm-package.json ├── Main.elm └── Completed.elm ├── 05Navigation ├── elm-package.json └── Main.elm ├── 03JSON ├── elm-package.json ├── SimpleDecoding.elm └── Main.elm └── README.md /RLBServer/user: -------------------------------------------------------------------------------- 1 | APP_USERNAME=james 2 | APP_PASSWORD=1234 3 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | elm-stuff 2 | node_modules 3 | .DS_Store 4 | bundle.js 5 | app.css.map 6 | *.db 7 | -------------------------------------------------------------------------------- /07RLBStarter/README.md: -------------------------------------------------------------------------------- 1 | ### Notes 2 | 3 | This dir contains the starter / build process for the Race Leaderboard App. 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /04Websocket/README.md: -------------------------------------------------------------------------------- 1 | # To Run This Example do the following 2 | 3 | 1. Run `npm install` from within the `04Websocket` directory to install the nodejs dependencies. 4 | 2. Run `node server.js` from within the `04Websocket` directory to start the websocket server. 5 | 3. Run `elm reactor` from within the `04Websocket` 6 | -------------------------------------------------------------------------------- /06Ports/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "client", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "Main.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "keywords": [], 10 | "author": "", 11 | "license": "ISC", 12 | "devDependencies": { 13 | "clear": "0.0.1", 14 | "gulp": "^3.9.1", 15 | "gulp-util": "^3.0.7", 16 | "st": "^1.1.0" 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /04Websocket/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "04Websocket", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "server.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1", 8 | "start": "node server.js" 9 | }, 10 | "keywords": [], 11 | "author": "", 12 | "license": "ISC", 13 | "dependencies": { 14 | "dateformat": "^1.0.12", 15 | "rx": "^4.1.0", 16 | "ws": "^1.1.1" 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /07RLBStarter/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "client", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "Main.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "keywords": [], 10 | "author": "", 11 | "license": "ISC", 12 | "devDependencies": { 13 | "clear": "0.0.1", 14 | "gulp": "^3.9.1", 15 | "gulp-livereload": "^3.8.1", 16 | "gutil": "^1.6.4", 17 | "st": "^1.1.0" 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /09RLBLogin/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "client", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "Main.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "keywords": [], 10 | "author": "", 11 | "license": "ISC", 12 | "devDependencies": { 13 | "clear": "0.0.1", 14 | "gulp": "^3.9.1", 15 | "gulp-livereload": "^3.8.1", 16 | "gutil": "^1.6.4", 17 | "st": "^1.1.0" 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /11RLBLogout/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "client", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "Main.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "keywords": [], 10 | "author": "", 11 | "license": "ISC", 12 | "devDependencies": { 13 | "clear": "0.0.1", 14 | "gulp": "^3.9.1", 15 | "gulp-livereload": "^3.8.1", 16 | "gutil": "^1.6.4", 17 | "st": "^1.1.0" 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /07RLBStarter/dist/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Race Results 8 | 9 | 10 | 11 | 12 |
13 | 14 | 15 | 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /08RLBNavigation/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "client", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "Main.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "keywords": [], 10 | "author": "", 11 | "license": "ISC", 12 | "devDependencies": { 13 | "clear": "0.0.1", 14 | "gulp": "^3.9.1", 15 | "gulp-livereload": "^3.8.1", 16 | "gutil": "^1.6.4", 17 | "st": "^1.1.0" 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /09RLBLogin/dist/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Race Results 8 | 9 | 10 | 11 | 12 |
13 | 14 | 15 | 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /10RLBLoginToken/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "client", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "Main.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "keywords": [], 10 | "author": "", 11 | "license": "ISC", 12 | "devDependencies": { 13 | "clear": "0.0.1", 14 | "gulp": "^3.9.1", 15 | "gulp-livereload": "^3.8.1", 16 | "gutil": "^1.6.4", 17 | "st": "^1.1.0" 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /13RLBAddRunner/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "client", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "Main.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "keywords": [], 10 | "author": "", 11 | "license": "ISC", 12 | "devDependencies": { 13 | "clear": "0.0.1", 14 | "gulp": "^3.9.1", 15 | "gulp-livereload": "^3.8.1", 16 | "gutil": "^1.6.4", 17 | "st": "^1.1.0" 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /14RLBWebsocket/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "client", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "Main.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "keywords": [], 10 | "author": "", 11 | "license": "ISC", 12 | "devDependencies": { 13 | "clear": "0.0.1", 14 | "gulp": "^3.9.1", 15 | "gulp-livereload": "^3.8.1", 16 | "gutil": "^1.6.4", 17 | "st": "^1.1.0" 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /16RLBFilterRunner/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "client", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "Main.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "keywords": [], 10 | "author": "", 11 | "license": "ISC", 12 | "devDependencies": { 13 | "clear": "0.0.1", 14 | "gulp": "^3.9.1", 15 | "gulp-livereload": "^3.8.1", 16 | "gutil": "^1.6.4", 17 | "st": "^1.1.0" 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /08RLBNavigation/dist/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Race Results 8 | 9 | 10 | 11 | 12 |
13 | 14 | 15 | 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /12RLBLockRunnerPage/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "client", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "Main.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "keywords": [], 10 | "author": "", 11 | "license": "ISC", 12 | "devDependencies": { 13 | "clear": "0.0.1", 14 | "gulp": "^3.9.1", 15 | "gulp-livereload": "^3.8.1", 16 | "gutil": "^1.6.4", 17 | "st": "^1.1.0" 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /15RLBEstimatedDistance/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "client", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "Main.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "keywords": [], 10 | "author": "", 11 | "license": "ISC", 12 | "devDependencies": { 13 | "clear": "0.0.1", 14 | "gulp": "^3.9.1", 15 | "gulp-livereload": "^3.8.1", 16 | "gutil": "^1.6.4", 17 | "st": "^1.1.0" 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /08RLBNavigation/completed/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "client", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "Main.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "keywords": [], 10 | "author": "", 11 | "license": "ISC", 12 | "devDependencies": { 13 | "clear": "0.0.1", 14 | "gulp": "^3.9.1", 15 | "gulp-livereload": "^3.8.1", 16 | "gutil": "^1.6.4", 17 | "st": "^1.1.0" 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /13RLBAddRunner/completed/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "client", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "Main.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "keywords": [], 10 | "author": "", 11 | "license": "ISC", 12 | "devDependencies": { 13 | "clear": "0.0.1", 14 | "gulp": "^3.9.1", 15 | "gulp-livereload": "^3.8.1", 16 | "gutil": "^1.6.4", 17 | "st": "^1.1.0" 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /14RLBWebsocket/completed/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "client", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "Main.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "keywords": [], 10 | "author": "", 11 | "license": "ISC", 12 | "devDependencies": { 13 | "clear": "0.0.1", 14 | "gulp": "^3.9.1", 15 | "gulp-livereload": "^3.8.1", 16 | "gutil": "^1.6.4", 17 | "st": "^1.1.0" 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /08RLBNavigation/completed/dist/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Race Results 8 | 9 | 10 | 11 | 12 |
13 | 14 | 15 | 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /00Review/elm-package.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "1.0.0", 3 | "summary": "helpful summary of your project, less than 80 characters", 4 | "repository": "https://github.com/user/project.git", 5 | "license": "BSD3", 6 | "source-directories": [ 7 | "." 8 | ], 9 | "exposed-modules": [], 10 | "dependencies": { 11 | "elm-lang/core": "5.0.0 <= v < 6.0.0", 12 | "elm-lang/html": "2.0.0 <= v < 3.0.0" 13 | }, 14 | "elm-version": "0.18.0 <= v < 0.19.0" 15 | } 16 | -------------------------------------------------------------------------------- /06Ports/elm-package.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "1.0.0", 3 | "summary": "helpful summary of your project, less than 80 characters", 4 | "repository": "https://github.com/user/project.git", 5 | "license": "BSD3", 6 | "source-directories": [ 7 | "." 8 | ], 9 | "exposed-modules": [], 10 | "dependencies": { 11 | "elm-lang/core": "5.0.0 <= v < 6.0.0", 12 | "elm-lang/html": "2.0.0 <= v < 3.0.0" 13 | }, 14 | "elm-version": "0.18.0 <= v < 0.19.0" 15 | } 16 | -------------------------------------------------------------------------------- /06Ports/completed/elm-package.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "1.0.0", 3 | "summary": "helpful summary of your project, less than 80 characters", 4 | "repository": "https://github.com/user/project.git", 5 | "license": "BSD3", 6 | "source-directories": [ 7 | "." 8 | ], 9 | "exposed-modules": [], 10 | "dependencies": { 11 | "elm-lang/core": "5.0.0 <= v < 6.0.0", 12 | "elm-lang/html": "2.0.0 <= v < 3.0.0" 13 | }, 14 | "elm-version": "0.18.0 <= v < 0.19.0" 15 | } 16 | -------------------------------------------------------------------------------- /01The-Elm-Architecture/elm-package.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "1.0.0", 3 | "summary": "helpful summary of your project, less than 80 characters", 4 | "repository": "https://github.com/user/project.git", 5 | "license": "BSD3", 6 | "source-directories": [ 7 | "." 8 | ], 9 | "exposed-modules": [], 10 | "dependencies": { 11 | "elm-lang/core": "5.0.0 <= v < 6.0.0", 12 | "elm-lang/html": "2.0.0 <= v < 3.0.0" 13 | }, 14 | "elm-version": "0.18.0 <= v < 0.19.0" 15 | } 16 | -------------------------------------------------------------------------------- /07RLBStarter/elm-package.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "1.0.0", 3 | "summary": "helpful summary of your project, less than 80 characters", 4 | "repository": "https://github.com/user/project.git", 5 | "license": "BSD3", 6 | "source-directories": [ 7 | ".", 8 | "src" 9 | ], 10 | "exposed-modules": [], 11 | "dependencies": { 12 | "elm-lang/core": "5.0.0 <= v < 6.0.0", 13 | "elm-lang/html": "2.0.0 <= v < 3.0.0" 14 | }, 15 | "elm-version": "0.18.0 <= v < 0.19.0" 16 | } 17 | -------------------------------------------------------------------------------- /02Effects/elm-package.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "1.0.0", 3 | "summary": "helpful summary of your project, less than 80 characters", 4 | "repository": "https://github.com/user/project.git", 5 | "license": "BSD3", 6 | "source-directories": [ 7 | "." 8 | ], 9 | "exposed-modules": [], 10 | "dependencies": { 11 | "elm-lang/core": "5.0.0 <= v < 6.0.0", 12 | "elm-lang/html": "2.0.0 <= v < 3.0.0", 13 | "elm-lang/http": "1.0.0 <= v < 2.0.0" 14 | }, 15 | "elm-version": "0.18.0 <= v < 0.19.0" 16 | } 17 | -------------------------------------------------------------------------------- /04Websocket/elm-package.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "1.0.0", 3 | "summary": "helpful summary of your project, less than 80 characters", 4 | "repository": "https://github.com/user/project.git", 5 | "license": "BSD3", 6 | "source-directories": [ 7 | "." 8 | ], 9 | "exposed-modules": [], 10 | "dependencies": { 11 | "elm-lang/core": "5.0.0 <= v < 6.0.0", 12 | "elm-lang/html": "2.0.0 <= v < 3.0.0", 13 | "elm-lang/websocket": "1.0.2 <= v < 2.0.0" 14 | }, 15 | "elm-version": "0.18.0 <= v < 0.19.0" 16 | } 17 | -------------------------------------------------------------------------------- /05Navigation/elm-package.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "1.0.0", 3 | "summary": "helpful summary of your project, less than 80 characters", 4 | "repository": "https://github.com/user/project.git", 5 | "license": "BSD3", 6 | "source-directories": [ 7 | "." 8 | ], 9 | "exposed-modules": [], 10 | "dependencies": { 11 | "elm-lang/core": "5.0.0 <= v < 6.0.0", 12 | "elm-lang/html": "2.0.0 <= v < 3.0.0", 13 | "elm-lang/navigation": "2.0.0 <= v < 3.0.0" 14 | }, 15 | "elm-version": "0.18.0 <= v < 0.19.0" 16 | } 17 | -------------------------------------------------------------------------------- /08RLBNavigation/elm-package.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "1.0.0", 3 | "summary": "helpful summary of your project, less than 80 characters", 4 | "repository": "https://github.com/user/project.git", 5 | "license": "BSD3", 6 | "source-directories": [ 7 | ".", 8 | "src" 9 | ], 10 | "exposed-modules": [], 11 | "dependencies": { 12 | "elm-lang/core": "5.0.0 <= v < 6.0.0", 13 | "elm-lang/html": "2.0.0 <= v < 3.0.0", 14 | "elm-lang/navigation": "2.0.1 <= v < 3.0.0" 15 | }, 16 | "elm-version": "0.18.0 <= v < 0.19.0" 17 | } 18 | -------------------------------------------------------------------------------- /08RLBNavigation/completed/elm-package.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "1.0.0", 3 | "summary": "helpful summary of your project, less than 80 characters", 4 | "repository": "https://github.com/user/project.git", 5 | "license": "BSD3", 6 | "source-directories": [ 7 | ".", 8 | "src" 9 | ], 10 | "exposed-modules": [], 11 | "dependencies": { 12 | "elm-lang/core": "5.0.0 <= v < 6.0.0", 13 | "elm-lang/html": "2.0.0 <= v < 3.0.0", 14 | "elm-lang/navigation": "2.0.1 <= v < 3.0.0" 15 | }, 16 | "elm-version": "0.18.0 <= v < 0.19.0" 17 | } 18 | -------------------------------------------------------------------------------- /03JSON/elm-package.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "1.0.0", 3 | "summary": "helpful summary of your project, less than 80 characters", 4 | "repository": "https://github.com/user/project.git", 5 | "license": "BSD3", 6 | "source-directories": [ 7 | "." 8 | ], 9 | "exposed-modules": [], 10 | "dependencies": { 11 | "NoRedInk/elm-decode-pipeline": "3.0.0 <= v < 4.0.0", 12 | "elm-lang/core": "5.0.0 <= v < 6.0.0", 13 | "elm-lang/html": "2.0.0 <= v < 3.0.0", 14 | "elm-lang/http": "1.0.0 <= v < 2.0.0" 15 | }, 16 | "elm-version": "0.18.0 <= v < 0.19.0" 17 | } 18 | -------------------------------------------------------------------------------- /09RLBLogin/elm-package.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "1.0.0", 3 | "summary": "helpful summary of your project, less than 80 characters", 4 | "repository": "https://github.com/user/project.git", 5 | "license": "BSD3", 6 | "source-directories": [ 7 | ".", 8 | "src" 9 | ], 10 | "exposed-modules": [], 11 | "dependencies": { 12 | "elm-lang/core": "5.0.0 <= v < 6.0.0", 13 | "elm-lang/html": "2.0.0 <= v < 3.0.0", 14 | "elm-lang/http": "1.0.0 <= v < 2.0.0", 15 | "elm-lang/navigation": "2.0.1 <= v < 3.0.0" 16 | }, 17 | "elm-version": "0.18.0 <= v < 0.19.0" 18 | } 19 | -------------------------------------------------------------------------------- /11RLBLogout/elm-package.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "1.0.0", 3 | "summary": "helpful summary of your project, less than 80 characters", 4 | "repository": "https://github.com/user/project.git", 5 | "license": "BSD3", 6 | "source-directories": [ 7 | ".", 8 | "src" 9 | ], 10 | "exposed-modules": [], 11 | "dependencies": { 12 | "elm-lang/core": "5.0.0 <= v < 6.0.0", 13 | "elm-lang/html": "2.0.0 <= v < 3.0.0", 14 | "elm-lang/http": "1.0.0 <= v < 2.0.0", 15 | "elm-lang/navigation": "2.0.1 <= v < 3.0.0" 16 | }, 17 | "elm-version": "0.18.0 <= v < 0.19.0" 18 | } 19 | -------------------------------------------------------------------------------- /13RLBAddRunner/elm-package.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "1.0.0", 3 | "summary": "helpful summary of your project, less than 80 characters", 4 | "repository": "https://github.com/user/project.git", 5 | "license": "BSD3", 6 | "source-directories": [ 7 | ".", 8 | "src" 9 | ], 10 | "exposed-modules": [], 11 | "dependencies": { 12 | "elm-lang/core": "5.0.0 <= v < 6.0.0", 13 | "elm-lang/html": "2.0.0 <= v < 3.0.0", 14 | "elm-lang/http": "1.0.0 <= v < 2.0.0", 15 | "elm-lang/navigation": "2.0.1 <= v < 3.0.0" 16 | }, 17 | "elm-version": "0.18.0 <= v < 0.19.0" 18 | } 19 | -------------------------------------------------------------------------------- /10RLBLoginToken/elm-package.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "1.0.0", 3 | "summary": "helpful summary of your project, less than 80 characters", 4 | "repository": "https://github.com/user/project.git", 5 | "license": "BSD3", 6 | "source-directories": [ 7 | ".", 8 | "src" 9 | ], 10 | "exposed-modules": [], 11 | "dependencies": { 12 | "elm-lang/core": "5.0.0 <= v < 6.0.0", 13 | "elm-lang/html": "2.0.0 <= v < 3.0.0", 14 | "elm-lang/http": "1.0.0 <= v < 2.0.0", 15 | "elm-lang/navigation": "2.0.1 <= v < 3.0.0" 16 | }, 17 | "elm-version": "0.18.0 <= v < 0.19.0" 18 | } 19 | -------------------------------------------------------------------------------- /12RLBLockRunnerPage/elm-package.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "1.0.0", 3 | "summary": "helpful summary of your project, less than 80 characters", 4 | "repository": "https://github.com/user/project.git", 5 | "license": "BSD3", 6 | "source-directories": [ 7 | ".", 8 | "src" 9 | ], 10 | "exposed-modules": [], 11 | "dependencies": { 12 | "elm-lang/core": "5.0.0 <= v < 6.0.0", 13 | "elm-lang/html": "2.0.0 <= v < 3.0.0", 14 | "elm-lang/http": "1.0.0 <= v < 2.0.0", 15 | "elm-lang/navigation": "2.0.1 <= v < 3.0.0" 16 | }, 17 | "elm-version": "0.18.0 <= v < 0.19.0" 18 | } 19 | -------------------------------------------------------------------------------- /13RLBAddRunner/completed/elm-package.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "1.0.0", 3 | "summary": "helpful summary of your project, less than 80 characters", 4 | "repository": "https://github.com/user/project.git", 5 | "license": "BSD3", 6 | "source-directories": [ 7 | ".", 8 | "src" 9 | ], 10 | "exposed-modules": [], 11 | "dependencies": { 12 | "elm-lang/core": "5.0.0 <= v < 6.0.0", 13 | "elm-lang/html": "2.0.0 <= v < 3.0.0", 14 | "elm-lang/http": "1.0.0 <= v < 2.0.0", 15 | "elm-lang/navigation": "2.0.1 <= v < 3.0.0" 16 | }, 17 | "elm-version": "0.18.0 <= v < 0.19.0" 18 | } 19 | -------------------------------------------------------------------------------- /10RLBLoginToken/dist/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Race Results 8 | 9 | 10 | 11 | 12 |
13 | 14 | 15 | 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /14RLBWebsocket/elm-package.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "1.0.0", 3 | "summary": "helpful summary of your project, less than 80 characters", 4 | "repository": "https://github.com/user/project.git", 5 | "license": "BSD3", 6 | "source-directories": [ 7 | ".", 8 | "src" 9 | ], 10 | "exposed-modules": [], 11 | "dependencies": { 12 | "NoRedInk/elm-decode-pipeline": "3.0.0 <= v < 4.0.0", 13 | "elm-lang/core": "5.0.0 <= v < 6.0.0", 14 | "elm-lang/html": "2.0.0 <= v < 3.0.0", 15 | "elm-lang/http": "1.0.0 <= v < 2.0.0", 16 | "elm-lang/navigation": "2.0.1 <= v < 3.0.0", 17 | "elm-lang/websocket": "1.0.2 <= v < 2.0.0" 18 | }, 19 | "elm-version": "0.18.0 <= v < 0.19.0" 20 | } 21 | -------------------------------------------------------------------------------- /14RLBWebsocket/completed/elm-package.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "1.0.0", 3 | "summary": "helpful summary of your project, less than 80 characters", 4 | "repository": "https://github.com/user/project.git", 5 | "license": "BSD3", 6 | "source-directories": [ 7 | ".", 8 | "src" 9 | ], 10 | "exposed-modules": [], 11 | "dependencies": { 12 | "NoRedInk/elm-decode-pipeline": "3.0.0 <= v < 4.0.0", 13 | "elm-lang/core": "5.0.0 <= v < 6.0.0", 14 | "elm-lang/html": "2.0.0 <= v < 3.0.0", 15 | "elm-lang/http": "1.0.0 <= v < 2.0.0", 16 | "elm-lang/navigation": "2.0.1 <= v < 3.0.0", 17 | "elm-lang/websocket": "1.0.2 <= v < 2.0.0" 18 | }, 19 | "elm-version": "0.18.0 <= v < 0.19.0" 20 | } 21 | -------------------------------------------------------------------------------- /03JSON/SimpleDecoding.elm: -------------------------------------------------------------------------------- 1 | module SimpleDecoding exposing (..) 2 | 3 | import Html exposing (..) 4 | import Json.Decode exposing (..) 5 | 6 | 7 | json : String 8 | json = 9 | """ 10 | { 11 | "type":"success", 12 | "value":{ 13 | "id":496, 14 | "joke":"Chuck Norris doesnt wear a watch, HE decides what time it is.", 15 | "categories":[ 16 | "nerdy" 17 | ] 18 | } 19 | } 20 | """ 21 | 22 | 23 | decoder : Decoder String 24 | decoder = 25 | at [ "value", "joke" ] string 26 | 27 | 28 | jokeResult : Result String String 29 | jokeResult = 30 | decodeString decoder json 31 | 32 | 33 | main : Html msg 34 | main = 35 | case jokeResult of 36 | Ok joke -> 37 | text joke 38 | 39 | Err err -> 40 | text err 41 | -------------------------------------------------------------------------------- /RLBServer/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "server", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "server.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1", 8 | "start": "node server.js" 9 | }, 10 | "keywords": [], 11 | "author": "", 12 | "license": "ISC", 13 | "dependencies": { 14 | "bluebird": "^3.4.1", 15 | "dotenv": "^2.0.0", 16 | "joi": "^8.0.5", 17 | "jsonwebtoken": "^6.2.0", 18 | "koa": "^1.2.0", 19 | "koa-body": "^1.4.0", 20 | "koa-cors": "0.0.16", 21 | "koa-router": "^5.4.0", 22 | "koa-websocket": "^1.1.0", 23 | "lodash": "^4.13.1", 24 | "ms": "^0.7.1", 25 | "nedb": "^1.8.0", 26 | "pubsub-js": "^1.5.3", 27 | "random-js": "^1.0.8", 28 | "yargs": "^4.8.1" 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /11RLBLogout/dist/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Race Results 8 | 9 | 10 | 11 | 12 |
13 | 14 | 15 | 27 | 28 | 29 | 30 | -------------------------------------------------------------------------------- /13RLBAddRunner/dist/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Race Results 8 | 9 | 10 | 11 | 12 |
13 | 14 | 15 | 27 | 28 | 29 | 30 | -------------------------------------------------------------------------------- /14RLBWebsocket/dist/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Race Results 8 | 9 | 10 | 11 | 12 |
13 | 14 | 15 | 27 | 28 | 29 | 30 | -------------------------------------------------------------------------------- /12RLBLockRunnerPage/dist/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Race Results 8 | 9 | 10 | 11 | 12 |
13 | 14 | 15 | 27 | 28 | 29 | 30 | -------------------------------------------------------------------------------- /16RLBFilterRunner/dist/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Race Results 8 | 9 | 10 | 11 | 12 |
13 | 14 | 15 | 27 | 28 | 29 | 30 | -------------------------------------------------------------------------------- /13RLBAddRunner/completed/dist/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Race Results 8 | 9 | 10 | 11 | 12 |
13 | 14 | 15 | 27 | 28 | 29 | 30 | -------------------------------------------------------------------------------- /14RLBWebsocket/completed/dist/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Race Results 8 | 9 | 10 | 11 | 12 |
13 | 14 | 15 | 27 | 28 | 29 | 30 | -------------------------------------------------------------------------------- /15RLBEstimatedDistance/dist/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Race Results 8 | 9 | 10 | 11 | 12 |
13 | 14 | 15 | 27 | 28 | 29 | 30 | -------------------------------------------------------------------------------- /16RLBFilterRunner/elm-package.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "1.0.0", 3 | "summary": "helpful summary of your project, less than 80 characters", 4 | "repository": "https://github.com/user/project.git", 5 | "license": "BSD3", 6 | "source-directories": [ 7 | ".", 8 | "src" 9 | ], 10 | "exposed-modules": [], 11 | "dependencies": { 12 | "NoRedInk/elm-decode-pipeline": "3.0.0 <= v < 4.0.0", 13 | "elm-lang/core": "5.0.0 <= v < 6.0.0", 14 | "elm-lang/html": "2.0.0 <= v < 3.0.0", 15 | "elm-lang/http": "1.0.0 <= v < 2.0.0", 16 | "elm-lang/navigation": "2.0.1 <= v < 3.0.0", 17 | "elm-lang/websocket": "1.0.2 <= v < 2.0.0", 18 | "rluiten/elm-date-extra": "8.1.2 <= v < 9.0.0" 19 | }, 20 | "elm-version": "0.18.0 <= v < 0.19.0" 21 | } 22 | -------------------------------------------------------------------------------- /15RLBEstimatedDistance/elm-package.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "1.0.0", 3 | "summary": "helpful summary of your project, less than 80 characters", 4 | "repository": "https://github.com/user/project.git", 5 | "license": "BSD3", 6 | "source-directories": [ 7 | ".", 8 | "src" 9 | ], 10 | "exposed-modules": [], 11 | "dependencies": { 12 | "NoRedInk/elm-decode-pipeline": "3.0.0 <= v < 4.0.0", 13 | "elm-lang/core": "5.0.0 <= v < 6.0.0", 14 | "elm-lang/html": "2.0.0 <= v < 3.0.0", 15 | "elm-lang/http": "1.0.0 <= v < 2.0.0", 16 | "elm-lang/navigation": "2.0.1 <= v < 3.0.0", 17 | "elm-lang/websocket": "1.0.2 <= v < 2.0.0", 18 | "rluiten/elm-date-extra": "8.1.2 <= v < 9.0.0" 19 | }, 20 | "elm-version": "0.18.0 <= v < 0.19.0" 21 | } 22 | -------------------------------------------------------------------------------- /06Ports/README.md: -------------------------------------------------------------------------------- 1 | # Getting Started with Waitlist App 2 | 3 | ### Setup 4 | 5 | Run the following setup steps 6 | 7 | 1. Run `npm install` to install the build process dependancies 8 | 2. Run `npm install gulp -g` to install the gulp executable globally 9 | 3. Run `elm package install ` to install the elm dependancies 10 | 11 | ### Setup Firebase 12 | 13 | 1. Create an account on firebase and create a new database 14 | 2. Add The following temporary rules to your firebase database 15 | 16 | ```json 17 | { 18 | "rules": { 19 | ".read": true, 20 | ".write": true 21 | } 22 | } 23 | ``` 24 | 25 | 3. Update the `appfb.js` file with your new firebase API keys, found here (replace YOURFIREBASEDBHERE, then click Add Firebase to your web app) https://console.firebase.google.com/project/YOURFIREBASEDBHERE/settings/general/ 26 | 27 | ### Start Build Process 28 | 29 | 1. Run `gulp` to start the build process 30 | -------------------------------------------------------------------------------- /06Ports/completed/appfb.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | // Initialize Firebase 3 | // var config = { 4 | // apiKey: "YOURAPIKEYHERE", 5 | // authDomain: "YOURAUTHDOMAINHERE", 6 | // databaseURL: "YOURURLHERE", 7 | // storageBucket: "", 8 | // }; 9 | 10 | var app = firebase.initializeApp(config); 11 | var database = app.database(); 12 | var CUSTOMERREFPATH = "customers" 13 | 14 | function addCustomer(customer){ 15 | var promise = database 16 | .ref(CUSTOMERREFPATH) 17 | .push(customer); 18 | return promise; 19 | } 20 | 21 | function updateCustomer(customer){ 22 | var id = customer.id; 23 | var promise = database 24 | .ref(CUSTOMERREFPATH + "/" + id) 25 | .set(customer); 26 | return promise; 27 | } 28 | 29 | function deleteCustomer(customer){ 30 | var id = customer.id; 31 | var promise = database 32 | .ref(CUSTOMERREFPATH + "/" + id) 33 | .remove(); 34 | return promise; 35 | } 36 | 37 | function customerListener(){ 38 | return database.ref(CUSTOMERREFPATH); 39 | } 40 | -------------------------------------------------------------------------------- /06Ports/appfb.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | // Initialize Firebase 3 | // var config = { 4 | // apiKey: "YOURAPIKEYHERE", 5 | // authDomain: "YOURAUTHDOMAINHERE", 6 | // databaseURL: "YOURURLHERE", 7 | // storageBucket: "", 8 | // }; 9 | 10 | alert('Add firebase config, see README.md! (then remove this)'); 11 | var app = firebase.initializeApp(config); 12 | var database = app.database(); 13 | var CUSTOMERREFPATH = "customers" 14 | 15 | function addCustomer(customer){ 16 | var promise = database 17 | .ref(CUSTOMERREFPATH) 18 | .push(customer); 19 | return promise; 20 | } 21 | 22 | function updateCustomer(customer){ 23 | var id = customer.id; 24 | var promise = database 25 | .ref(CUSTOMERREFPATH + "/" + id) 26 | .set(customer); 27 | return promise; 28 | } 29 | 30 | function deleteCustomer(customer){ 31 | var id = customer.id; 32 | var promise = database 33 | .ref(CUSTOMERREFPATH + "/" + id) 34 | .remove(); 35 | return promise; 36 | } 37 | 38 | function customerListener(){ 39 | return database.ref(CUSTOMERREFPATH); 40 | } 41 | -------------------------------------------------------------------------------- /RLBServer/README.md: -------------------------------------------------------------------------------- 1 | # Node Server 2 | 3 | ## Setup 4 | 5 | 1. Install Recent Version of **Nodejs** by downloading and running the installer found at https://nodejs.org/en/ or use the Node Version Manager found at https://github.com/creationix/nvm 6 | 2. Install Nodejs dependancies by keying `npm install` from within this directory 7 | 8 | ## Starting Server 9 | 10 | The server can be started by keying `node server.js` 11 | 12 | ## Where's the data stored? 13 | 14 | The runner records are saved into `local.db` file, via [nedb](https://github.com/louischatriot/nedb). You can manually edit/delete this file and restart the server. 15 | 16 | ## Where's the username and password? 17 | 18 | The app isn't doing real auth... The username and password is stored in the `user` file and it's loaded using [dotenv](https://github.com/motdotla/dotenv) 19 | 20 | ## Bugs 21 | 22 | Yes, there are bugs in the app... Covering every edge case scenario wouldn't make for a good training videos.. We'd have to go off on too many tangents (edge cases), which would be distracting from the main content. 23 | -------------------------------------------------------------------------------- /04Websocket/server.js: -------------------------------------------------------------------------------- 1 | const WebSocketServer = require('ws').Server; 2 | const Rx = require('rx'); 3 | const dateFormat = require('dateformat'); 4 | 5 | const server = new WebSocketServer({ port: 5000 }); 6 | 7 | server.on('connection', function connection(ws) { 8 | console.log('client connected!') 9 | const pauser = new Rx.Subject(); 10 | Rx.Observable 11 | .interval( 1000 ) 12 | .timeInterval() 13 | .map( x => new Date) 14 | .map( now => dateFormat(now, "h:MM:ss TT") ) 15 | .pausable( pauser ) 16 | .subscribe( ( time ) => { 17 | if (ws.readyState === ws.OPEN){ 18 | ws.send(JSON.stringify({time})); 19 | } 20 | else if (ws.readyState === ws.CLOSED) { 21 | pauser.onNext(false); 22 | } 23 | } 24 | ); 25 | ws.on('message', ( message ) => { 26 | if ( message === "start" ){ 27 | pauser.onNext(true); 28 | } 29 | else if ( message === "stop" ) { 30 | pauser.onNext(false); 31 | } 32 | }); 33 | ws.on('close', ( ) => { 34 | console.log('client disconnected!'); 35 | }) 36 | 37 | }); -------------------------------------------------------------------------------- /06Ports/gulpfile.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var gulp = require('gulp'), 4 | http = require('http'), 5 | st = require('st'), 6 | exec = require('child_process').exec, 7 | gutil = require('gulp-util'), 8 | clear = require('clear'), 9 | counter = 0; 10 | 11 | var cmd = 'elm make ./Main.elm --output ./bundle.js'; 12 | clear(); 13 | gulp.task('default', ['server', 'watch', 'elm']); 14 | 15 | gulp.task('watch', function(cb) { 16 | gulp.watch('**/*.elm', ['elm']); 17 | }); 18 | 19 | gulp.task('server', function(done) { 20 | gutil.log(gutil.colors.blue('Starting server at http://localhost:4000')); 21 | http.createServer( 22 | st({ 23 | path: __dirname , 24 | index: 'index.html', 25 | cache: false 26 | }) 27 | ).listen(4000, done); 28 | }); 29 | 30 | gulp.task('elm', function(cb) { 31 | if (counter > 0){ 32 | clear(); 33 | } 34 | exec(cmd, function(err, stdout, stderr) { 35 | if (err){ 36 | gutil.log(gutil.colors.red('elm make: '),gutil.colors.red(stderr)); 37 | } else { 38 | gutil.log(gutil.colors.green('elm make: '), gutil.colors.green(stdout)); 39 | } 40 | cb(); 41 | }); 42 | counter++; 43 | }); 44 | -------------------------------------------------------------------------------- /01The-Elm-Architecture/LeaderBoard.elm: -------------------------------------------------------------------------------- 1 | module LeaderBoard exposing (..) 2 | 3 | import Html exposing (..) 4 | import Html.Events exposing (..) 5 | import Html.Attributes exposing (..) 6 | 7 | 8 | -- model 9 | 10 | 11 | type alias Model = 12 | { runners : List Runner 13 | , query : String 14 | } 15 | 16 | 17 | type alias Runner = 18 | { id : Int 19 | , name : String 20 | , location : String 21 | } 22 | 23 | 24 | initModel : Model 25 | initModel = 26 | { runners = [] 27 | , query = "" 28 | } 29 | 30 | 31 | 32 | -- update 33 | 34 | 35 | type Msg 36 | = QueryInput String 37 | 38 | 39 | update : Msg -> Model -> Model 40 | update msg model = 41 | case msg of 42 | QueryInput query -> 43 | { model | query = query } 44 | 45 | 46 | 47 | -- view 48 | 49 | 50 | view : Model -> Html Msg 51 | view model = 52 | div [] 53 | [ h3 [] [ text "Leaderboard page... So far" ] 54 | , input 55 | [ type_ "text" 56 | , onInput QueryInput 57 | , value model.query 58 | , placeholder "Search for a runner..." 59 | ] 60 | [] 61 | ] 62 | -------------------------------------------------------------------------------- /06Ports/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Ports - Customer List 8 | 9 | 10 | 11 | 12 |
13 | 14 | 15 | 16 | 34 | 35 | 36 | 37 | -------------------------------------------------------------------------------- /06Ports/completed/gulpfile.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var gulp = require('gulp'), 4 | http = require('http'), 5 | st = require('st'), 6 | exec = require('child_process').exec, 7 | gutil = require('gulp-util'), 8 | clear = require('clear'), 9 | counter = 0; 10 | 11 | var cmd = 'elm make ./Main.elm --output ./bundle.js'; 12 | clear(); 13 | gulp.task('default', ['server', 'watch', 'elm']); 14 | 15 | gulp.task('watch', function(cb) { 16 | gulp.watch('**/*.elm', ['elm']); 17 | }); 18 | 19 | gulp.task('server', function(done) { 20 | gutil.log(gutil.colors.blue('Starting server at http://localhost:4000')); 21 | http.createServer( 22 | st({ 23 | path: __dirname , 24 | index: 'index.html', 25 | cache: false 26 | }) 27 | ).listen(4000, done); 28 | }); 29 | 30 | gulp.task('elm', function(cb) { 31 | if (counter > 0){ 32 | clear(); 33 | } 34 | exec(cmd, function(err, stdout, stderr) { 35 | if (err){ 36 | gutil.log(gutil.colors.red('elm make: '),gutil.colors.red(stderr)); 37 | } else { 38 | gutil.log(gutil.colors.green('elm make: '), gutil.colors.green(stdout)); 39 | } 40 | cb(); 41 | }); 42 | counter++; 43 | }); 44 | -------------------------------------------------------------------------------- /07RLBStarter/gulpfile.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var gulp = require('gulp'), 4 | http = require('http'), 5 | st = require('st'), 6 | exec = require('child_process').exec, 7 | gutil = require('gulp-util'), 8 | clear = require('clear'), 9 | counter = 0; 10 | 11 | var cmd = 'elm make ./src/Main.elm --output ./dist/bundle.js'; 12 | clear(); 13 | gulp.task('default', ['server', 'watch', 'elm']); 14 | 15 | gulp.task('watch', function(cb) { 16 | gulp.watch('**/*.elm', ['elm']); 17 | }); 18 | 19 | gulp.task('server', function(done) { 20 | gutil.log(gutil.colors.blue('Starting server at http://localhost:4000')); 21 | http.createServer( 22 | st({ 23 | path: __dirname + '/dist/', 24 | index: 'index.html', 25 | cache: false 26 | }) 27 | ).listen(4000, done); 28 | }); 29 | 30 | gulp.task('elm', function(cb) { 31 | if (counter > 0){ 32 | clear(); 33 | } 34 | exec(cmd, function(err, stdout, stderr) { 35 | if (err){ 36 | gutil.log(gutil.colors.red('elm make: '),gutil.colors.red(stderr)); 37 | } else { 38 | gutil.log(gutil.colors.green('elm make: '), gutil.colors.green(stdout)); 39 | } 40 | cb(); 41 | }); 42 | counter++; 43 | }); 44 | -------------------------------------------------------------------------------- /08RLBNavigation/gulpfile.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var gulp = require('gulp'), 4 | http = require('http'), 5 | st = require('st'), 6 | exec = require('child_process').exec, 7 | gutil = require('gulp-util'), 8 | clear = require('clear'), 9 | counter = 0; 10 | 11 | var cmd = 'elm make ./src/Main.elm --output ./dist/bundle.js'; 12 | clear(); 13 | gulp.task('default', ['server', 'watch', 'elm']); 14 | 15 | gulp.task('watch', function(cb) { 16 | gulp.watch('**/*.elm', ['elm']); 17 | }); 18 | 19 | gulp.task('server', function(done) { 20 | gutil.log(gutil.colors.blue('Starting server at http://localhost:4000')); 21 | http.createServer( 22 | st({ 23 | path: __dirname + '/dist/', 24 | index: 'index.html', 25 | cache: false 26 | }) 27 | ).listen(4000, done); 28 | }); 29 | 30 | gulp.task('elm', function(cb) { 31 | if (counter > 0){ 32 | clear(); 33 | } 34 | exec(cmd, function(err, stdout, stderr) { 35 | if (err){ 36 | gutil.log(gutil.colors.red('elm make: '),gutil.colors.red(stderr)); 37 | } else { 38 | gutil.log(gutil.colors.green('elm make: '), gutil.colors.green(stdout)); 39 | } 40 | cb(); 41 | }); 42 | counter++; 43 | }); 44 | -------------------------------------------------------------------------------- /09RLBLogin/gulpfile.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var gulp = require('gulp'), 4 | http = require('http'), 5 | st = require('st'), 6 | exec = require('child_process').exec, 7 | gutil = require('gulp-util'), 8 | clear = require('clear'), 9 | counter = 0; 10 | 11 | var cmd = 'elm make ./src/Main.elm --output ./dist/bundle.js --debug'; 12 | clear(); 13 | gulp.task('default', ['server', 'watch', 'elm']); 14 | 15 | gulp.task('watch', function(cb) { 16 | gulp.watch('**/*.elm', ['elm']); 17 | }); 18 | 19 | gulp.task('server', function(done) { 20 | gutil.log(gutil.colors.blue('Starting server at http://localhost:4000')); 21 | http.createServer( 22 | st({ 23 | path: __dirname + '/dist/', 24 | index: 'index.html', 25 | cache: false 26 | }) 27 | ).listen(4000, done); 28 | }); 29 | 30 | gulp.task('elm', function(cb) { 31 | if (counter > 0){ 32 | clear(); 33 | } 34 | exec(cmd, function(err, stdout, stderr) { 35 | if (err){ 36 | gutil.log(gutil.colors.red('elm make: '),gutil.colors.red(stderr)); 37 | } else { 38 | gutil.log(gutil.colors.green('elm make: '), gutil.colors.green(stdout)); 39 | } 40 | cb(); 41 | }); 42 | counter++; 43 | }); 44 | -------------------------------------------------------------------------------- /11RLBLogout/gulpfile.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var gulp = require('gulp'), 4 | http = require('http'), 5 | st = require('st'), 6 | exec = require('child_process').exec, 7 | gutil = require('gulp-util'), 8 | clear = require('clear'), 9 | counter = 0; 10 | 11 | var cmd = 'elm make ./src/Main.elm --output ./dist/bundle.js --debug'; 12 | clear(); 13 | gulp.task('default', ['server', 'watch', 'elm']); 14 | 15 | gulp.task('watch', function(cb) { 16 | gulp.watch('**/*.elm', ['elm']); 17 | }); 18 | 19 | gulp.task('server', function(done) { 20 | gutil.log(gutil.colors.blue('Starting server at http://localhost:4000')); 21 | http.createServer( 22 | st({ 23 | path: __dirname + '/dist/', 24 | index: 'index.html', 25 | cache: false 26 | }) 27 | ).listen(4000, done); 28 | }); 29 | 30 | gulp.task('elm', function(cb) { 31 | if (counter > 0){ 32 | clear(); 33 | } 34 | exec(cmd, function(err, stdout, stderr) { 35 | if (err){ 36 | gutil.log(gutil.colors.red('elm make: '),gutil.colors.red(stderr)); 37 | } else { 38 | gutil.log(gutil.colors.green('elm make: '), gutil.colors.green(stdout)); 39 | } 40 | cb(); 41 | }); 42 | counter++; 43 | }); 44 | -------------------------------------------------------------------------------- /08RLBNavigation/completed/gulpfile.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var gulp = require('gulp'), 4 | http = require('http'), 5 | st = require('st'), 6 | exec = require('child_process').exec, 7 | gutil = require('gulp-util'), 8 | clear = require('clear'), 9 | counter = 0; 10 | 11 | var cmd = 'elm make ./src/Main.elm --output ./dist/bundle.js'; 12 | clear(); 13 | gulp.task('default', ['server', 'watch', 'elm']); 14 | 15 | gulp.task('watch', function(cb) { 16 | gulp.watch('**/*.elm', ['elm']); 17 | }); 18 | 19 | gulp.task('server', function(done) { 20 | gutil.log(gutil.colors.blue('Starting server at http://localhost:4000')); 21 | http.createServer( 22 | st({ 23 | path: __dirname + '/dist/', 24 | index: 'index.html', 25 | cache: false 26 | }) 27 | ).listen(4000, done); 28 | }); 29 | 30 | gulp.task('elm', function(cb) { 31 | if (counter > 0){ 32 | clear(); 33 | } 34 | exec(cmd, function(err, stdout, stderr) { 35 | if (err){ 36 | gutil.log(gutil.colors.red('elm make: '),gutil.colors.red(stderr)); 37 | } else { 38 | gutil.log(gutil.colors.green('elm make: '), gutil.colors.green(stdout)); 39 | } 40 | cb(); 41 | }); 42 | counter++; 43 | }); 44 | -------------------------------------------------------------------------------- /10RLBLoginToken/gulpfile.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var gulp = require('gulp'), 4 | http = require('http'), 5 | st = require('st'), 6 | exec = require('child_process').exec, 7 | gutil = require('gulp-util'), 8 | clear = require('clear'), 9 | counter = 0; 10 | 11 | var cmd = 'elm make ./src/Main.elm --output ./dist/bundle.js --debug'; 12 | clear(); 13 | gulp.task('default', ['server', 'watch', 'elm']); 14 | 15 | gulp.task('watch', function(cb) { 16 | gulp.watch('**/*.elm', ['elm']); 17 | }); 18 | 19 | gulp.task('server', function(done) { 20 | gutil.log(gutil.colors.blue('Starting server at http://localhost:4000')); 21 | http.createServer( 22 | st({ 23 | path: __dirname + '/dist/', 24 | index: 'index.html', 25 | cache: false 26 | }) 27 | ).listen(4000, done); 28 | }); 29 | 30 | gulp.task('elm', function(cb) { 31 | if (counter > 0){ 32 | clear(); 33 | } 34 | exec(cmd, function(err, stdout, stderr) { 35 | if (err){ 36 | gutil.log(gutil.colors.red('elm make: '),gutil.colors.red(stderr)); 37 | } else { 38 | gutil.log(gutil.colors.green('elm make: '), gutil.colors.green(stdout)); 39 | } 40 | cb(); 41 | }); 42 | counter++; 43 | }); 44 | -------------------------------------------------------------------------------- /13RLBAddRunner/gulpfile.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var gulp = require('gulp'), 4 | http = require('http'), 5 | st = require('st'), 6 | exec = require('child_process').exec, 7 | gutil = require('gulp-util'), 8 | clear = require('clear'), 9 | counter = 0; 10 | 11 | var cmd = 'elm make ./src/Main.elm --output ./dist/bundle.js --debug'; 12 | clear(); 13 | gulp.task('default', ['server', 'watch', 'elm']); 14 | 15 | gulp.task('watch', function(cb) { 16 | gulp.watch('**/*.elm', ['elm']); 17 | }); 18 | 19 | gulp.task('server', function(done) { 20 | gutil.log(gutil.colors.blue('Starting server at http://localhost:4000')); 21 | http.createServer( 22 | st({ 23 | path: __dirname + '/dist/', 24 | index: 'index.html', 25 | cache: false 26 | }) 27 | ).listen(4000, done); 28 | }); 29 | 30 | gulp.task('elm', function(cb) { 31 | if (counter > 0){ 32 | clear(); 33 | } 34 | exec(cmd, function(err, stdout, stderr) { 35 | if (err){ 36 | gutil.log(gutil.colors.red('elm make: '),gutil.colors.red(stderr)); 37 | } else { 38 | gutil.log(gutil.colors.green('elm make: '), gutil.colors.green(stdout)); 39 | } 40 | cb(); 41 | }); 42 | counter++; 43 | }); 44 | -------------------------------------------------------------------------------- /14RLBWebsocket/gulpfile.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var gulp = require('gulp'), 4 | http = require('http'), 5 | st = require('st'), 6 | exec = require('child_process').exec, 7 | gutil = require('gulp-util'), 8 | clear = require('clear'), 9 | counter = 0; 10 | 11 | var cmd = 'elm make ./src/Main.elm --output ./dist/bundle.js --debug'; 12 | clear(); 13 | gulp.task('default', ['server', 'watch', 'elm']); 14 | 15 | gulp.task('watch', function(cb) { 16 | gulp.watch('**/*.elm', ['elm']); 17 | }); 18 | 19 | gulp.task('server', function(done) { 20 | gutil.log(gutil.colors.blue('Starting server at http://localhost:4000')); 21 | http.createServer( 22 | st({ 23 | path: __dirname + '/dist/', 24 | index: 'index.html', 25 | cache: false 26 | }) 27 | ).listen(4000, done); 28 | }); 29 | 30 | gulp.task('elm', function(cb) { 31 | if (counter > 0){ 32 | clear(); 33 | } 34 | exec(cmd, function(err, stdout, stderr) { 35 | if (err){ 36 | gutil.log(gutil.colors.red('elm make: '),gutil.colors.red(stderr)); 37 | } else { 38 | gutil.log(gutil.colors.green('elm make: '), gutil.colors.green(stdout)); 39 | } 40 | cb(); 41 | }); 42 | counter++; 43 | }); 44 | -------------------------------------------------------------------------------- /16RLBFilterRunner/gulpfile.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var gulp = require('gulp'), 4 | http = require('http'), 5 | st = require('st'), 6 | exec = require('child_process').exec, 7 | gutil = require('gulp-util'), 8 | clear = require('clear'), 9 | counter = 0; 10 | 11 | var cmd = 'elm make ./src/Main.elm --output ./dist/bundle.js --debug'; 12 | clear(); 13 | gulp.task('default', ['server', 'watch', 'elm']); 14 | 15 | gulp.task('watch', function(cb) { 16 | gulp.watch('**/*.elm', ['elm']); 17 | }); 18 | 19 | gulp.task('server', function(done) { 20 | gutil.log(gutil.colors.blue('Starting server at http://localhost:4000')); 21 | http.createServer( 22 | st({ 23 | path: __dirname + '/dist/', 24 | index: 'index.html', 25 | cache: false 26 | }) 27 | ).listen(4000, done); 28 | }); 29 | 30 | gulp.task('elm', function(cb) { 31 | if (counter > 0){ 32 | clear(); 33 | } 34 | exec(cmd, function(err, stdout, stderr) { 35 | if (err){ 36 | gutil.log(gutil.colors.red('elm make: '),gutil.colors.red(stderr)); 37 | } else { 38 | gutil.log(gutil.colors.green('elm make: '), gutil.colors.green(stdout)); 39 | } 40 | cb(); 41 | }); 42 | counter++; 43 | }); 44 | -------------------------------------------------------------------------------- /12RLBLockRunnerPage/gulpfile.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var gulp = require('gulp'), 4 | http = require('http'), 5 | st = require('st'), 6 | exec = require('child_process').exec, 7 | gutil = require('gulp-util'), 8 | clear = require('clear'), 9 | counter = 0; 10 | 11 | var cmd = 'elm make ./src/Main.elm --output ./dist/bundle.js --debug'; 12 | clear(); 13 | gulp.task('default', ['server', 'watch', 'elm']); 14 | 15 | gulp.task('watch', function(cb) { 16 | gulp.watch('**/*.elm', ['elm']); 17 | }); 18 | 19 | gulp.task('server', function(done) { 20 | gutil.log(gutil.colors.blue('Starting server at http://localhost:4000')); 21 | http.createServer( 22 | st({ 23 | path: __dirname + '/dist/', 24 | index: 'index.html', 25 | cache: false 26 | }) 27 | ).listen(4000, done); 28 | }); 29 | 30 | gulp.task('elm', function(cb) { 31 | if (counter > 0){ 32 | clear(); 33 | } 34 | exec(cmd, function(err, stdout, stderr) { 35 | if (err){ 36 | gutil.log(gutil.colors.red('elm make: '),gutil.colors.red(stderr)); 37 | } else { 38 | gutil.log(gutil.colors.green('elm make: '), gutil.colors.green(stdout)); 39 | } 40 | cb(); 41 | }); 42 | counter++; 43 | }); 44 | -------------------------------------------------------------------------------- /15RLBEstimatedDistance/gulpfile.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var gulp = require('gulp'), 4 | http = require('http'), 5 | st = require('st'), 6 | exec = require('child_process').exec, 7 | gutil = require('gulp-util'), 8 | clear = require('clear'), 9 | counter = 0; 10 | 11 | var cmd = 'elm make ./src/Main.elm --output ./dist/bundle.js --debug'; 12 | clear(); 13 | gulp.task('default', ['server', 'watch', 'elm']); 14 | 15 | gulp.task('watch', function(cb) { 16 | gulp.watch('**/*.elm', ['elm']); 17 | }); 18 | 19 | gulp.task('server', function(done) { 20 | gutil.log(gutil.colors.blue('Starting server at http://localhost:4000')); 21 | http.createServer( 22 | st({ 23 | path: __dirname + '/dist/', 24 | index: 'index.html', 25 | cache: false 26 | }) 27 | ).listen(4000, done); 28 | }); 29 | 30 | gulp.task('elm', function(cb) { 31 | if (counter > 0){ 32 | clear(); 33 | } 34 | exec(cmd, function(err, stdout, stderr) { 35 | if (err){ 36 | gutil.log(gutil.colors.red('elm make: '),gutil.colors.red(stderr)); 37 | } else { 38 | gutil.log(gutil.colors.green('elm make: '), gutil.colors.green(stdout)); 39 | } 40 | cb(); 41 | }); 42 | counter++; 43 | }); 44 | -------------------------------------------------------------------------------- /13RLBAddRunner/completed/gulpfile.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var gulp = require('gulp'), 4 | http = require('http'), 5 | st = require('st'), 6 | exec = require('child_process').exec, 7 | gutil = require('gulp-util'), 8 | clear = require('clear'), 9 | counter = 0; 10 | 11 | var cmd = 'elm make ./src/Main.elm --output ./dist/bundle.js --debug'; 12 | clear(); 13 | gulp.task('default', ['server', 'watch', 'elm']); 14 | 15 | gulp.task('watch', function(cb) { 16 | gulp.watch('**/*.elm', ['elm']); 17 | }); 18 | 19 | gulp.task('server', function(done) { 20 | gutil.log(gutil.colors.blue('Starting server at http://localhost:4000')); 21 | http.createServer( 22 | st({ 23 | path: __dirname + '/dist/', 24 | index: 'index.html', 25 | cache: false 26 | }) 27 | ).listen(4000, done); 28 | }); 29 | 30 | gulp.task('elm', function(cb) { 31 | if (counter > 0){ 32 | clear(); 33 | } 34 | exec(cmd, function(err, stdout, stderr) { 35 | if (err){ 36 | gutil.log(gutil.colors.red('elm make: '),gutil.colors.red(stderr)); 37 | } else { 38 | gutil.log(gutil.colors.green('elm make: '), gutil.colors.green(stdout)); 39 | } 40 | cb(); 41 | }); 42 | counter++; 43 | }); 44 | -------------------------------------------------------------------------------- /14RLBWebsocket/completed/gulpfile.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var gulp = require('gulp'), 4 | http = require('http'), 5 | st = require('st'), 6 | exec = require('child_process').exec, 7 | gutil = require('gulp-util'), 8 | clear = require('clear'), 9 | counter = 0; 10 | 11 | var cmd = 'elm make ./src/Main.elm --output ./dist/bundle.js --debug'; 12 | clear(); 13 | gulp.task('default', ['server', 'watch', 'elm']); 14 | 15 | gulp.task('watch', function(cb) { 16 | gulp.watch('**/*.elm', ['elm']); 17 | }); 18 | 19 | gulp.task('server', function(done) { 20 | gutil.log(gutil.colors.blue('Starting server at http://localhost:4000')); 21 | http.createServer( 22 | st({ 23 | path: __dirname + '/dist/', 24 | index: 'index.html', 25 | cache: false 26 | }) 27 | ).listen(4000, done); 28 | }); 29 | 30 | gulp.task('elm', function(cb) { 31 | if (counter > 0){ 32 | clear(); 33 | } 34 | exec(cmd, function(err, stdout, stderr) { 35 | if (err){ 36 | gutil.log(gutil.colors.red('elm make: '),gutil.colors.red(stderr)); 37 | } else { 38 | gutil.log(gutil.colors.green('elm make: '), gutil.colors.green(stdout)); 39 | } 40 | cb(); 41 | }); 42 | counter++; 43 | }); 44 | -------------------------------------------------------------------------------- /01The-Elm-Architecture/Login.elm: -------------------------------------------------------------------------------- 1 | module Login exposing (..) 2 | 3 | import Html exposing (..) 4 | import Html.Events exposing (..) 5 | import Html.Attributes exposing (..) 6 | 7 | 8 | -- model 9 | 10 | 11 | type alias Model = 12 | { username : String 13 | , password : String 14 | } 15 | 16 | 17 | initModel : Model 18 | initModel = 19 | { username = "" 20 | , password = "" 21 | } 22 | 23 | 24 | 25 | -- update 26 | 27 | 28 | type Msg 29 | = UsernameInput String 30 | | PasswordInput String 31 | 32 | 33 | update : Msg -> Model -> Model 34 | update msg model = 35 | case msg of 36 | UsernameInput username -> 37 | { model | username = username } 38 | 39 | PasswordInput password -> 40 | { model | password = password } 41 | 42 | 43 | 44 | -- view 45 | 46 | 47 | view : Model -> Html Msg 48 | view model = 49 | div [] 50 | [ h3 [] [ text "Login Page... So far" ] 51 | , Html.form [] 52 | [ input 53 | [ type_ "text" 54 | , onInput UsernameInput 55 | , placeholder "username" 56 | ] 57 | [] 58 | , input 59 | [ type_ "password" 60 | , onInput PasswordInput 61 | , placeholder "password" 62 | ] 63 | [] 64 | ] 65 | ] 66 | -------------------------------------------------------------------------------- /02Effects/Main.elm: -------------------------------------------------------------------------------- 1 | module Main exposing (..) 2 | 3 | import Html exposing (..) 4 | import Http 5 | 6 | 7 | -- model 8 | 9 | 10 | type alias Model = 11 | String 12 | 13 | 14 | initModel : Model 15 | initModel = 16 | "Finding a joke..." 17 | 18 | 19 | init : ( Model, Cmd Msg ) 20 | init = 21 | ( initModel, randomJoke ) 22 | 23 | 24 | randomJoke : Cmd Msg 25 | randomJoke = 26 | let 27 | url = 28 | "http://api.icndb.com/jokes/random" 29 | 30 | request = 31 | Http.getString url 32 | 33 | cmd = 34 | Http.send Joke request 35 | in 36 | cmd 37 | 38 | 39 | 40 | -- update 41 | 42 | 43 | type Msg 44 | = Joke (Result Http.Error String) 45 | 46 | 47 | update : Msg -> Model -> ( Model, Cmd Msg ) 48 | update msg model = 49 | case msg of 50 | Joke (Ok joke) -> 51 | ( joke, Cmd.none ) 52 | 53 | Joke (Err err) -> 54 | ( (toString err), Cmd.none ) 55 | 56 | 57 | 58 | -- view 59 | 60 | 61 | view : Model -> Html Msg 62 | view model = 63 | div [] [ text model ] 64 | 65 | 66 | 67 | -- subscription 68 | 69 | 70 | subscriptions : Model -> Sub Msg 71 | subscriptions model = 72 | Sub.none 73 | 74 | 75 | main : Program Never Model Msg 76 | main = 77 | Html.program 78 | { init = init 79 | , update = update 80 | , view = view 81 | , subscriptions = subscriptions 82 | } 83 | -------------------------------------------------------------------------------- /06Ports/completed/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Ports - Customer List 8 | 9 | 10 | 11 | 12 |
13 | 14 | 15 | 16 | 44 | 45 | 46 | 47 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Elm Beyond The Basics 2 | This repo is the source companion to the following course on Learning Elmlang: 3 | http://courses.knowthen.com/courses/elm-beyond-the-basics 4 | 5 | This course teaches the new [Elmlang](http://elm-lang.org/) developer who knows how to make basic apps that just run in the browser, how to make more apps. 6 | 7 | ## Updated to Elm 0.18 8 | 9 | #### Why you should take this course? 10 | 11 | Elm is an amazing language that offers many benefits like: 12 | 13 | * Zero Runtime Exceptions 14 | * Simplified Debugging 15 | * Easy Refactoring 16 | * An Amazingly helpful type system 17 | * Improved Productivity 18 | * Inherently Testable Code 19 | * Enforced Semantic Versioning 20 | * and much more... 21 | 22 | This course will teach you more advanced concepts like: 23 | 24 | * The Elm Architecture 25 | * Effects (HTTP / Websocket) 26 | * JSON Encoding and Decoding 27 | * Single Page App Navigation (Routing) 28 | * Talking to JavaScript using Ports 29 | * and much more... 30 | 31 | #### Why this course? 32 | 33 | Do you ever feel overwhelmed with new technologies? I think most of us do, there is so much change constantly happening and the pace of change seems to be increasing. 34 | 35 | What can you do to manage the learning challenges facing software developers? 36 | 37 | #### Lean learning 38 | 39 | I don't want to waste your time, so you'll learn just what you need to know as quickly as possible. You'll start this course with the end in mind. What do I mean by that? We're going to be building a web application, and you'll learn just what you need to build the app. 40 | -------------------------------------------------------------------------------- /00Review/Login.elm: -------------------------------------------------------------------------------- 1 | module Login exposing (..) 2 | 3 | import Html exposing (..) 4 | import Html.Events exposing (..) 5 | import Html.Attributes exposing (..) 6 | 7 | 8 | -- model 9 | 10 | 11 | type alias Model = 12 | { username : String 13 | , password : String 14 | } 15 | 16 | 17 | initModel : Model 18 | initModel = 19 | { username = "" 20 | , password = "" 21 | } 22 | 23 | 24 | 25 | -- update 26 | 27 | 28 | type Msg 29 | = UsernameInput String 30 | | PasswordInput String 31 | 32 | 33 | update : Msg -> Model -> Model 34 | update msg model = 35 | case msg of 36 | UsernameInput username -> 37 | { model | username = username } 38 | 39 | PasswordInput password -> 40 | { model | password = password } 41 | 42 | 43 | 44 | -- view 45 | 46 | 47 | view : Model -> Html Msg 48 | view model = 49 | div [] 50 | [ h3 [] [ text "Login Page... So far" ] 51 | , Html.form [] 52 | [ input 53 | [ type_ "text" 54 | , onInput UsernameInput 55 | , placeholder "username" 56 | ] 57 | [] 58 | , input 59 | [ type_ "password" 60 | , onInput PasswordInput 61 | , placeholder "password" 62 | ] 63 | [] 64 | , input [ type_ "submit" ] 65 | [ text "Login" ] 66 | ] 67 | ] 68 | 69 | 70 | main : Program Never Model Msg 71 | main = 72 | Html.beginnerProgram 73 | { model = initModel 74 | , update = update 75 | , view = view 76 | } 77 | -------------------------------------------------------------------------------- /02Effects/Completed.elm: -------------------------------------------------------------------------------- 1 | module Completed exposing (..) 2 | 3 | import Html exposing (..) 4 | import Html.Events exposing (..) 5 | import Http 6 | 7 | 8 | -- model 9 | 10 | 11 | type alias Model = 12 | String 13 | 14 | 15 | initModel : Model 16 | initModel = 17 | "Finding a joke..." 18 | 19 | 20 | init : ( Model, Cmd Msg ) 21 | init = 22 | ( initModel, randomJoke ) 23 | 24 | 25 | randomJoke : Cmd Msg 26 | randomJoke = 27 | let 28 | url = 29 | "http://api.icndb.com/jokes/random" 30 | 31 | request = 32 | Http.getString url 33 | 34 | cmd = 35 | Http.send Joke request 36 | in 37 | cmd 38 | 39 | 40 | 41 | -- update 42 | 43 | 44 | type Msg 45 | = Joke (Result Http.Error String) 46 | | NewJoke 47 | 48 | 49 | update : Msg -> Model -> ( Model, Cmd Msg ) 50 | update msg model = 51 | case msg of 52 | Joke (Ok joke) -> 53 | ( joke, Cmd.none ) 54 | 55 | Joke (Err err) -> 56 | ( (toString err), Cmd.none ) 57 | 58 | NewJoke -> 59 | ( "fetching joke ...", randomJoke ) 60 | 61 | 62 | 63 | -- view 64 | 65 | 66 | view : Model -> Html Msg 67 | view model = 68 | div [] 69 | [ button [ onClick NewJoke ] [ text "Fetch a Joke" ] 70 | , br [] [] 71 | , text model 72 | ] 73 | 74 | 75 | 76 | -- subscription 77 | 78 | 79 | subscriptions : Model -> Sub Msg 80 | subscriptions model = 81 | Sub.none 82 | 83 | 84 | main : Program Never Model Msg 85 | main = 86 | Html.program 87 | { init = init 88 | , update = update 89 | , view = view 90 | , subscriptions = subscriptions 91 | } 92 | -------------------------------------------------------------------------------- /07RLBStarter/src/Main.elm: -------------------------------------------------------------------------------- 1 | port module Main exposing (..) 2 | 3 | import Html exposing (..) 4 | import Html.Attributes exposing (..) 5 | 6 | 7 | -- model 8 | 9 | 10 | type alias Model = 11 | { page : Page 12 | } 13 | 14 | 15 | type Page 16 | = NotFound 17 | 18 | 19 | initModel : Model 20 | initModel = 21 | { page = NotFound } 22 | 23 | 24 | init : ( Model, Cmd Msg ) 25 | init = 26 | ( initModel, Cmd.none ) 27 | 28 | 29 | 30 | -- update 31 | 32 | 33 | type Msg 34 | = Navigate Page 35 | 36 | 37 | update : Msg -> Model -> ( Model, Cmd Msg ) 38 | update msg model = 39 | case msg of 40 | Navigate page -> 41 | ( { model | page = page }, Cmd.none ) 42 | 43 | 44 | 45 | -- view 46 | 47 | 48 | view : Model -> Html Msg 49 | view model = 50 | let 51 | page = 52 | case model.page of 53 | NotFound -> 54 | div [ class "main" ] 55 | [ h1 [] 56 | [ text "Page Not Found!" ] 57 | ] 58 | in 59 | div [] 60 | [ pageHeader model 61 | , page 62 | ] 63 | 64 | 65 | pageHeader : Model -> Html Msg 66 | pageHeader model = 67 | header [] 68 | [ a [ href "#/" ] [ text "Race Results" ] 69 | , ul [] 70 | [ li [] 71 | [ a [ href "#" ] [ text "Link" ] 72 | ] 73 | ] 74 | , ul [] 75 | [ li [] 76 | [ a [ href "#" ] [ text "Login" ] 77 | ] 78 | ] 79 | ] 80 | 81 | 82 | 83 | -- subscriptions 84 | 85 | 86 | subscriptions : Model -> Sub Msg 87 | subscriptions model = 88 | Sub.none 89 | 90 | 91 | main : Program Never Model Msg 92 | main = 93 | Html.program 94 | { init = init 95 | , update = update 96 | , view = view 97 | , subscriptions = subscriptions 98 | } 99 | -------------------------------------------------------------------------------- /04Websocket/Main.elm: -------------------------------------------------------------------------------- 1 | module Main exposing (..) 2 | 3 | import Html exposing (..) 4 | import Html.Events exposing (..) 5 | import WebSocket exposing (..) 6 | import Json.Decode exposing (..) 7 | 8 | 9 | -- model 10 | 11 | 12 | type alias Model = 13 | { streamTime : Bool 14 | , time : String 15 | } 16 | 17 | 18 | initModel : Model 19 | initModel = 20 | { streamTime = False 21 | , time = "" 22 | } 23 | 24 | 25 | init : ( Model, Cmd Msg ) 26 | init = 27 | ( initModel, Cmd.none ) 28 | 29 | 30 | 31 | -- update 32 | 33 | 34 | type Msg 35 | = ToggleStreaming 36 | | Time String 37 | 38 | 39 | update : Msg -> Model -> ( Model, Cmd Msg ) 40 | update msg model = 41 | case msg of 42 | ToggleStreaming -> 43 | let 44 | newModel = 45 | { model | streamTime = not model.streamTime } 46 | 47 | msg = 48 | if newModel.streamTime then 49 | "start" 50 | else 51 | "stop" 52 | 53 | cmd = 54 | send wsUrl msg 55 | in 56 | ( newModel, cmd ) 57 | 58 | Time time -> 59 | ( { model | time = time }, Cmd.none ) 60 | 61 | 62 | 63 | -- view 64 | 65 | 66 | view : Model -> Html Msg 67 | view model = 68 | let 69 | toggleLabel = 70 | if model.streamTime then 71 | "Stop" 72 | else 73 | "Start" 74 | in 75 | div [] 76 | [ button [ onClick ToggleStreaming ] [ text toggleLabel ] 77 | , br [] [] 78 | , text model.time 79 | ] 80 | 81 | 82 | 83 | -- subscription 84 | 85 | 86 | wsUrl : String 87 | wsUrl = 88 | "ws://localhost:5000" 89 | 90 | 91 | decodeTime : String -> Msg 92 | decodeTime message = 93 | decodeString (at [ "time" ] string) message 94 | |> Result.withDefault "Error Decoding Time" 95 | |> Time 96 | 97 | 98 | subscriptions : Model -> Sub Msg 99 | subscriptions model = 100 | -- Sub.none 101 | if model.streamTime then 102 | listen wsUrl decodeTime 103 | else 104 | Sub.none 105 | 106 | 107 | main : Program Never Model Msg 108 | main = 109 | Html.program 110 | { init = init 111 | , update = update 112 | , view = view 113 | , subscriptions = subscriptions 114 | } 115 | -------------------------------------------------------------------------------- /01The-Elm-Architecture/Main.elm: -------------------------------------------------------------------------------- 1 | module Main exposing (..) 2 | 3 | import Html exposing (..) 4 | import Html.Events exposing (..) 5 | import Html.Attributes exposing (..) 6 | import Login 7 | import LeaderBoard 8 | 9 | 10 | -- model 11 | 12 | 13 | type alias Model = 14 | { page : Page 15 | , leaderBoard : LeaderBoard.Model 16 | , login : Login.Model 17 | } 18 | 19 | 20 | initModel : Model 21 | initModel = 22 | { page = LeaderBoardPage 23 | , login = Login.initModel 24 | , leaderBoard = LeaderBoard.initModel 25 | } 26 | 27 | 28 | type Page 29 | = LeaderBoardPage 30 | | LoginPage 31 | 32 | 33 | 34 | -- update 35 | 36 | 37 | type Msg 38 | = ChangePage Page 39 | | LeaderBoardMsg LeaderBoard.Msg 40 | | LoginMsg Login.Msg 41 | 42 | 43 | update : Msg -> Model -> Model 44 | update msg model = 45 | case msg of 46 | ChangePage page -> 47 | { model 48 | | page = page 49 | } 50 | 51 | LeaderBoardMsg lbMsg -> 52 | { model 53 | | leaderBoard = 54 | LeaderBoard.update lbMsg model.leaderBoard 55 | } 56 | 57 | LoginMsg loginMsg -> 58 | { model 59 | | login = 60 | Login.update loginMsg model.login 61 | } 62 | 63 | 64 | 65 | -- view 66 | 67 | 68 | view : Model -> Html Msg 69 | view model = 70 | let 71 | page = 72 | case model.page of 73 | LeaderBoardPage -> 74 | Html.map LeaderBoardMsg 75 | (LeaderBoard.view model.leaderBoard) 76 | 77 | LoginPage -> 78 | Html.map LoginMsg 79 | (Login.view model.login) 80 | in 81 | div [] 82 | [ div [] 83 | [ a 84 | [ href "#" 85 | , onClick (ChangePage LeaderBoardPage) 86 | ] 87 | [ text "LeaderBoard" ] 88 | , span [] [ text " | " ] 89 | , a 90 | [ href "#" 91 | , onClick (ChangePage LoginPage) 92 | ] 93 | [ text "Login" ] 94 | ] 95 | , hr [] [] 96 | , page 97 | ] 98 | 99 | 100 | main : Program Never Model Msg 101 | main = 102 | Html.beginnerProgram 103 | { model = initModel 104 | , update = update 105 | , view = view 106 | } 107 | -------------------------------------------------------------------------------- /03JSON/Main.elm: -------------------------------------------------------------------------------- 1 | module Main exposing (..) 2 | 3 | import Html exposing (..) 4 | import Html.Events exposing (..) 5 | import Http 6 | import Json.Decode exposing (..) 7 | import Json.Decode.Pipeline exposing (decode, required, optional) 8 | 9 | 10 | type alias Response = 11 | { id : Int 12 | , joke : String 13 | , categories : List String 14 | } 15 | 16 | 17 | 18 | -- model 19 | 20 | 21 | type alias Model = 22 | String 23 | 24 | 25 | initModel : Model 26 | initModel = 27 | "Finding a joke..." 28 | 29 | 30 | init : ( Model, Cmd Msg ) 31 | init = 32 | ( initModel, randomJoke ) 33 | 34 | 35 | 36 | -- responseDecoder : Decoder Response 37 | -- responseDecoder = 38 | -- map3 Response 39 | -- (field "id" int) 40 | -- (field "joke" string) 41 | -- (field "categories" (list string)) 42 | -- |> at [ "value" ] 43 | 44 | 45 | responseDecoder : Decoder Response 46 | responseDecoder = 47 | decode Response 48 | |> required "id" int 49 | |> required "joke" string 50 | |> optional "categories" (list string) [] 51 | |> at [ "value" ] 52 | 53 | 54 | randomJoke : Cmd Msg 55 | randomJoke = 56 | let 57 | url = 58 | "http://api.icndb.com/jokes/random" 59 | 60 | request = 61 | -- Http.getString url 62 | Http.get url responseDecoder 63 | 64 | cmd = 65 | Http.send Joke request 66 | in 67 | cmd 68 | 69 | 70 | 71 | -- update 72 | 73 | 74 | type Msg 75 | = Joke (Result Http.Error Response) 76 | | NewJoke 77 | 78 | 79 | update : Msg -> Model -> ( Model, Cmd Msg ) 80 | update msg model = 81 | case msg of 82 | Joke (Ok response) -> 83 | ( toString (response.id) ++ " " ++ response.joke, Cmd.none ) 84 | 85 | Joke (Err err) -> 86 | ( (toString err), Cmd.none ) 87 | 88 | NewJoke -> 89 | ( "fetching joke ...", randomJoke ) 90 | 91 | 92 | 93 | -- view 94 | 95 | 96 | view : Model -> Html Msg 97 | view model = 98 | div [] 99 | [ button [ onClick NewJoke ] [ text "Fetch a Joke" ] 100 | , br [] [] 101 | , text model 102 | ] 103 | 104 | 105 | 106 | -- subscription 107 | 108 | 109 | subscriptions : Model -> Sub Msg 110 | subscriptions model = 111 | Sub.none 112 | 113 | 114 | main : Program Never Model Msg 115 | main = 116 | Html.program 117 | { init = init 118 | , update = update 119 | , view = view 120 | , subscriptions = subscriptions 121 | } 122 | -------------------------------------------------------------------------------- /07RLBStarter/src/Login.elm: -------------------------------------------------------------------------------- 1 | module Login exposing (..) 2 | 3 | import Html exposing (..) 4 | import Html.Events exposing (..) 5 | import Html.Attributes exposing (..) 6 | 7 | 8 | -- model 9 | 10 | 11 | type alias Model = 12 | { username : String 13 | , password : String 14 | , error : Maybe String 15 | } 16 | 17 | 18 | initModel : Model 19 | initModel = 20 | { username = "" 21 | , password = "" 22 | , error = Nothing 23 | } 24 | 25 | 26 | init : ( Model, Cmd Msg ) 27 | init = 28 | ( initModel, Cmd.none ) 29 | 30 | 31 | 32 | -- update 33 | 34 | 35 | type Msg 36 | = UsernameInput String 37 | | PasswordInput String 38 | | Submit 39 | | Error String 40 | 41 | 42 | update : Msg -> Model -> ( Model, Cmd Msg ) 43 | update msg model = 44 | case msg of 45 | UsernameInput username -> 46 | ( { model | username = username }, Cmd.none ) 47 | 48 | PasswordInput password -> 49 | ( { model | password = password }, Cmd.none ) 50 | 51 | Submit -> 52 | ( model, Cmd.none ) 53 | 54 | Error error -> 55 | ( { model | error = Just error }, Cmd.none ) 56 | 57 | 58 | 59 | -- view 60 | 61 | 62 | view : Model -> Html Msg 63 | view model = 64 | div [ class "main" ] 65 | [ errorPanel model.error 66 | , loginForm model 67 | ] 68 | 69 | 70 | loginForm : Model -> Html Msg 71 | loginForm model = 72 | Html.form [ class "add-runner", onSubmit Submit ] 73 | [ fieldset [] 74 | [ legend [] [ text "Login" ] 75 | , div [] 76 | [ label [] [ text "User Name" ] 77 | , input 78 | [ type_ "text" 79 | , value model.username 80 | , onInput UsernameInput 81 | ] 82 | [] 83 | ] 84 | , div [] 85 | [ label [] [ text "Password" ] 86 | , input 87 | [ type_ "password" 88 | , value model.password 89 | , onInput PasswordInput 90 | ] 91 | [] 92 | ] 93 | , div [] 94 | [ label [] [] 95 | , button [ type_ "submit" ] [ text "Login" ] 96 | ] 97 | ] 98 | ] 99 | 100 | 101 | errorPanel : Maybe String -> Html a 102 | errorPanel error = 103 | case error of 104 | Nothing -> 105 | text "" 106 | 107 | Just msg -> 108 | div [ class "error" ] 109 | [ text msg ] 110 | 111 | 112 | subscriptions : Model -> Sub Msg 113 | subscriptions model = 114 | Sub.none 115 | -------------------------------------------------------------------------------- /08RLBNavigation/src/Login.elm: -------------------------------------------------------------------------------- 1 | module Login exposing (..) 2 | 3 | import Html exposing (..) 4 | import Html.Events exposing (..) 5 | import Html.Attributes exposing (..) 6 | 7 | 8 | -- model 9 | 10 | 11 | type alias Model = 12 | { username : String 13 | , password : String 14 | , error : Maybe String 15 | } 16 | 17 | 18 | initModel : Model 19 | initModel = 20 | { username = "" 21 | , password = "" 22 | , error = Nothing 23 | } 24 | 25 | 26 | init : ( Model, Cmd Msg ) 27 | init = 28 | ( initModel, Cmd.none ) 29 | 30 | 31 | 32 | -- update 33 | 34 | 35 | type Msg 36 | = UsernameInput String 37 | | PasswordInput String 38 | | Submit 39 | | Error String 40 | 41 | 42 | update : Msg -> Model -> ( Model, Cmd Msg ) 43 | update msg model = 44 | case msg of 45 | UsernameInput username -> 46 | ( { model | username = username }, Cmd.none ) 47 | 48 | PasswordInput password -> 49 | ( { model | password = password }, Cmd.none ) 50 | 51 | Submit -> 52 | ( model, Cmd.none ) 53 | 54 | Error error -> 55 | ( { model | error = Just error }, Cmd.none ) 56 | 57 | 58 | 59 | -- view 60 | 61 | 62 | view : Model -> Html Msg 63 | view model = 64 | div [ class "main" ] 65 | [ errorPanel model.error 66 | , loginForm model 67 | ] 68 | 69 | 70 | loginForm : Model -> Html Msg 71 | loginForm model = 72 | Html.form [ class "add-runner", onSubmit Submit ] 73 | [ fieldset [] 74 | [ legend [] [ text "Login" ] 75 | , div [] 76 | [ label [] [ text "User Name" ] 77 | , input 78 | [ type_ "text" 79 | , value model.username 80 | , onInput UsernameInput 81 | ] 82 | [] 83 | ] 84 | , div [] 85 | [ label [] [ text "Password" ] 86 | , input 87 | [ type_ "password" 88 | , value model.password 89 | , onInput PasswordInput 90 | ] 91 | [] 92 | ] 93 | , div [] 94 | [ label [] [] 95 | , button [ type_ "submit" ] [ text "Login" ] 96 | ] 97 | ] 98 | ] 99 | 100 | 101 | errorPanel : Maybe String -> Html a 102 | errorPanel error = 103 | case error of 104 | Nothing -> 105 | text "" 106 | 107 | Just msg -> 108 | div [ class "error" ] 109 | [ text msg ] 110 | 111 | 112 | subscriptions : Model -> Sub Msg 113 | subscriptions model = 114 | Sub.none 115 | -------------------------------------------------------------------------------- /08RLBNavigation/completed/src/Login.elm: -------------------------------------------------------------------------------- 1 | module Login exposing (..) 2 | 3 | import Html exposing (..) 4 | import Html.Events exposing (..) 5 | import Html.Attributes exposing (..) 6 | 7 | 8 | -- model 9 | 10 | 11 | type alias Model = 12 | { username : String 13 | , password : String 14 | , error : Maybe String 15 | } 16 | 17 | 18 | initModel : Model 19 | initModel = 20 | { username = "" 21 | , password = "" 22 | , error = Nothing 23 | } 24 | 25 | 26 | init : ( Model, Cmd Msg ) 27 | init = 28 | ( initModel, Cmd.none ) 29 | 30 | 31 | 32 | -- update 33 | 34 | 35 | type Msg 36 | = UsernameInput String 37 | | PasswordInput String 38 | | Submit 39 | | Error String 40 | 41 | 42 | update : Msg -> Model -> ( Model, Cmd Msg ) 43 | update msg model = 44 | case msg of 45 | UsernameInput username -> 46 | ( { model | username = username }, Cmd.none ) 47 | 48 | PasswordInput password -> 49 | ( { model | password = password }, Cmd.none ) 50 | 51 | Submit -> 52 | ( model, Cmd.none ) 53 | 54 | Error error -> 55 | ( { model | error = Just error }, Cmd.none ) 56 | 57 | 58 | 59 | -- view 60 | 61 | 62 | view : Model -> Html Msg 63 | view model = 64 | div [ class "main" ] 65 | [ errorPanel model.error 66 | , loginForm model 67 | ] 68 | 69 | 70 | loginForm : Model -> Html Msg 71 | loginForm model = 72 | Html.form [ class "add-runner", onSubmit Submit ] 73 | [ fieldset [] 74 | [ legend [] [ text "Login" ] 75 | , div [] 76 | [ label [] [ text "User Name" ] 77 | , input 78 | [ type_ "text" 79 | , value model.username 80 | , onInput UsernameInput 81 | ] 82 | [] 83 | ] 84 | , div [] 85 | [ label [] [ text "Password" ] 86 | , input 87 | [ type_ "password" 88 | , value model.password 89 | , onInput PasswordInput 90 | ] 91 | [] 92 | ] 93 | , div [] 94 | [ label [] [] 95 | , button [ type_ "submit" ] [ text "Login" ] 96 | ] 97 | ] 98 | ] 99 | 100 | 101 | errorPanel : Maybe String -> Html a 102 | errorPanel error = 103 | case error of 104 | Nothing -> 105 | text "" 106 | 107 | Just msg -> 108 | div [ class "error" ] 109 | [ text msg ] 110 | 111 | 112 | subscriptions : Model -> Sub Msg 113 | subscriptions model = 114 | Sub.none 115 | -------------------------------------------------------------------------------- /06Ports/Main.elm: -------------------------------------------------------------------------------- 1 | port module Main exposing (..) 2 | 3 | import Html exposing (..) 4 | import Html.Events exposing (..) 5 | import Html.Attributes exposing (..) 6 | 7 | 8 | -- model 9 | 10 | 11 | type alias Customer = 12 | { id : String 13 | , name : String 14 | } 15 | 16 | 17 | type alias Model = 18 | { name : String 19 | , customers : List Customer 20 | , error : Maybe String 21 | , nextId : Int 22 | } 23 | 24 | 25 | initModel : Model 26 | initModel = 27 | { name = "" 28 | , customers = [] 29 | , error = Nothing 30 | , nextId = 1 31 | } 32 | 33 | 34 | init : ( Model, Cmd Msg ) 35 | init = 36 | ( initModel, Cmd.none ) 37 | 38 | 39 | 40 | -- update 41 | 42 | 43 | type Msg 44 | = NameInput String 45 | | SaveCustomer 46 | | CustomerSaved String 47 | | CustomerAdded Customer 48 | 49 | 50 | update : Msg -> Model -> ( Model, Cmd Msg ) 51 | update msg model = 52 | case msg of 53 | NameInput name -> 54 | ( { model | name = name }, Cmd.none ) 55 | 56 | SaveCustomer -> 57 | ( model, addCustomer model.name ) 58 | 59 | CustomerSaved key -> 60 | ( { model | name = "" }, Cmd.none ) 61 | 62 | CustomerAdded customer -> 63 | let 64 | newCustomers = 65 | customer :: model.customers 66 | in 67 | ( { model | customers = newCustomers }, Cmd.none ) 68 | 69 | 70 | 71 | -- view 72 | 73 | 74 | viewCustomer : Customer -> Html Msg 75 | viewCustomer customer = 76 | li [] 77 | [ i [ class "remove" ] [] 78 | , text customer.name 79 | ] 80 | 81 | 82 | viewCustomers : List Customer -> Html Msg 83 | viewCustomers customers = 84 | customers 85 | |> List.sortBy .id 86 | |> List.map viewCustomer 87 | |> ul [] 88 | 89 | 90 | viewCustomerForm : Model -> Html Msg 91 | viewCustomerForm model = 92 | Html.form [ onSubmit SaveCustomer ] 93 | [ input [ type_ "text", onInput NameInput, value model.name ] [] 94 | , text <| Maybe.withDefault "" model.error 95 | , button [ type_ "submit" ] [ text "Save" ] 96 | ] 97 | 98 | 99 | view : Model -> Html Msg 100 | view model = 101 | div [] 102 | [ h1 [] [ text "Customer List" ] 103 | , viewCustomerForm model 104 | , viewCustomers model.customers 105 | ] 106 | 107 | 108 | 109 | -- subscription 110 | 111 | 112 | subscriptions : Model -> Sub Msg 113 | subscriptions model = 114 | -- Sub.none 115 | Sub.batch 116 | [ customerSaved CustomerSaved 117 | , newCustomer CustomerAdded 118 | ] 119 | 120 | 121 | port addCustomer : String -> Cmd msg 122 | 123 | 124 | port customerSaved : (String -> msg) -> Sub msg 125 | 126 | 127 | port newCustomer : (Customer -> msg) -> Sub msg 128 | 129 | 130 | main : Program Never Model Msg 131 | main = 132 | Html.program 133 | { init = init 134 | , update = update 135 | , view = view 136 | , subscriptions = subscriptions 137 | } 138 | -------------------------------------------------------------------------------- /05Navigation/Main.elm: -------------------------------------------------------------------------------- 1 | module Main exposing (..) 2 | 3 | import Html exposing (..) 4 | import Html.Events exposing (..) 5 | import Navigation exposing (..) 6 | 7 | 8 | -- model 9 | 10 | 11 | type Page 12 | = LeaderBoard 13 | | AddRunner 14 | | Login 15 | | NotFound 16 | 17 | 18 | type alias Model = 19 | { page : Page 20 | } 21 | 22 | 23 | initModel : Page -> Model 24 | initModel page = 25 | { page = page 26 | } 27 | 28 | 29 | init : Location -> ( Model, Cmd Msg ) 30 | init location = 31 | let 32 | page = 33 | hashToPage location.hash 34 | in 35 | ( initModel page, Cmd.none ) 36 | 37 | 38 | 39 | -- update 40 | 41 | 42 | type Msg 43 | = Navigate Page 44 | | ChangePage Page 45 | 46 | 47 | update : Msg -> Model -> ( Model, Cmd Msg ) 48 | update msg model = 49 | case msg of 50 | Navigate page -> 51 | ( model, newUrl <| pageToHash page ) 52 | 53 | ChangePage page -> 54 | ( { model | page = page }, Cmd.none ) 55 | 56 | 57 | 58 | -- view 59 | 60 | 61 | menu : Model -> Html Msg 62 | menu model = 63 | header [] 64 | [ a [ onClick (Navigate LeaderBoard) ] 65 | [ text "LeaderBoard" ] 66 | , text " | " 67 | , a [ onClick (Navigate AddRunner) ] 68 | [ text "Add Runner" ] 69 | , text " | " 70 | , a [ onClick (Navigate Login) ] 71 | [ text "Login" ] 72 | ] 73 | 74 | 75 | viewPage : String -> Html Msg 76 | viewPage pageDescription = 77 | div [] 78 | [ h3 [] [ text pageDescription ] 79 | , p [] [ text <| "TODO: make " ++ pageDescription ] 80 | ] 81 | 82 | 83 | view : Model -> Html Msg 84 | view model = 85 | let 86 | page = 87 | case model.page of 88 | LeaderBoard -> 89 | viewPage "LeaderBoard Page" 90 | 91 | AddRunner -> 92 | viewPage "Add Runner Page" 93 | 94 | Login -> 95 | viewPage "Login Page" 96 | 97 | NotFound -> 98 | viewPage "Page Not Found" 99 | in 100 | div [] 101 | [ menu model 102 | , hr [] [] 103 | , page 104 | ] 105 | 106 | 107 | 108 | -- subscription 109 | 110 | 111 | subscriptions : Model -> Sub Msg 112 | subscriptions model = 113 | Sub.none 114 | 115 | 116 | pageToHash : Page -> String 117 | pageToHash page = 118 | case page of 119 | LeaderBoard -> 120 | "#" 121 | 122 | AddRunner -> 123 | "#add" 124 | 125 | Login -> 126 | "#login" 127 | 128 | NotFound -> 129 | "#notfound" 130 | 131 | 132 | hashToPage : String -> Page 133 | hashToPage hash = 134 | case hash of 135 | "" -> 136 | LeaderBoard 137 | 138 | "#add" -> 139 | AddRunner 140 | 141 | "#login" -> 142 | Login 143 | 144 | _ -> 145 | NotFound 146 | 147 | 148 | locationToMsg : Location -> Msg 149 | locationToMsg location = 150 | location.hash 151 | |> hashToPage 152 | |> ChangePage 153 | 154 | 155 | main : Program Never Model Msg 156 | main = 157 | Navigation.program locationToMsg 158 | { init = init 159 | , update = update 160 | , view = view 161 | , subscriptions = subscriptions 162 | } 163 | -------------------------------------------------------------------------------- /07RLBStarter/src/LeaderBoard.elm: -------------------------------------------------------------------------------- 1 | module LeaderBoard exposing (..) 2 | 3 | import Html exposing (..) 4 | import Html.Events exposing (..) 5 | import Html.Attributes exposing (..) 6 | 7 | 8 | -- model 9 | 10 | 11 | type alias Model = 12 | { error : Maybe String 13 | , query : String 14 | , runners : List Runner 15 | , active : Bool 16 | } 17 | 18 | 19 | type alias Runner = 20 | { id : String 21 | , name : String 22 | , location : String 23 | , age : Int 24 | , bib : Int 25 | , estimatedDistance : Float 26 | , lastMarkerDistance : Float 27 | , lastMarkerTime : Float 28 | , pace : Float 29 | } 30 | 31 | 32 | tempRunners : List Runner 33 | tempRunners = 34 | [ Runner "1" "James Moore" "Turlock CA" 42 1234 0 1 1463154945381 0.125 35 | , Runner "2" "Meb Keflezighi" "Turlock CA" 41 1238 0 1 1463154945381 0.09 36 | ] 37 | 38 | 39 | initModel : Model 40 | initModel = 41 | { error = Nothing 42 | , query = "" 43 | , runners = tempRunners 44 | , active = False 45 | } 46 | 47 | 48 | init : ( Model, Cmd Msg ) 49 | init = 50 | ( initModel, Cmd.none ) 51 | 52 | 53 | 54 | -- update 55 | 56 | 57 | type Msg 58 | = SearchInput String 59 | | Search 60 | 61 | 62 | update : Msg -> Model -> ( Model, Cmd Msg ) 63 | update msg model = 64 | case msg of 65 | SearchInput query -> 66 | ( { model | query = query }, Cmd.none ) 67 | 68 | Search -> 69 | ( model, Cmd.none ) 70 | 71 | 72 | 73 | -- view 74 | 75 | 76 | view : Model -> Html Msg 77 | view model = 78 | div [ class "main" ] 79 | [ errorPanel model.error 80 | , searchForm model.query 81 | , runners model 82 | ] 83 | 84 | 85 | errorPanel : Maybe String -> Html a 86 | errorPanel error = 87 | case error of 88 | Nothing -> 89 | text "" 90 | 91 | Just msg -> 92 | div [ class "error" ] 93 | [ text msg 94 | , button [ type_ "button" ] [ text "×" ] 95 | ] 96 | 97 | 98 | searchForm : String -> Html Msg 99 | searchForm query = 100 | Html.form [ onSubmit Search ] 101 | [ input 102 | [ type_ "text" 103 | , placeholder "Search for runner..." 104 | , value query 105 | , onInput SearchInput 106 | ] 107 | [] 108 | , button [ type_ "submit" ] [ text "Search" ] 109 | ] 110 | 111 | 112 | runners : Model -> Html Msg 113 | runners { query, runners } = 114 | runners 115 | |> List.map runner 116 | |> tbody [] 117 | |> (\r -> runnersHeader :: [ r ]) 118 | |> table [] 119 | 120 | 121 | runner : Runner -> Html Msg 122 | runner { name, location, age, bib, estimatedDistance } = 123 | tr [] 124 | [ td [] [ text name ] 125 | , td [] [ text location ] 126 | , td [] [ text (toString age) ] 127 | , td [] [ text (toString bib) ] 128 | , td [] 129 | [ text "1 mi @ 08:30AM (TODO)" 130 | ] 131 | , td [] [ text (toString estimatedDistance) ] 132 | ] 133 | 134 | 135 | runnersHeader : Html Msg 136 | runnersHeader = 137 | thead [] 138 | [ tr [] 139 | [ th [] [ text "Name" ] 140 | , th [] [ text "From" ] 141 | , th [] [ text "Age" ] 142 | , th [] [ text "Bib #" ] 143 | , th [] [ text "Last Marker" ] 144 | , th [] [ text "Est. Miles" ] 145 | ] 146 | ] 147 | 148 | 149 | 150 | -- subscriptions 151 | 152 | 153 | subscriptions : Model -> Sub Msg 154 | subscriptions model = 155 | Sub.none 156 | -------------------------------------------------------------------------------- /09RLBLogin/src/LeaderBoard.elm: -------------------------------------------------------------------------------- 1 | module LeaderBoard exposing (..) 2 | 3 | import Html exposing (..) 4 | import Html.Events exposing (..) 5 | import Html.Attributes exposing (..) 6 | 7 | 8 | -- model 9 | 10 | 11 | type alias Model = 12 | { error : Maybe String 13 | , query : String 14 | , runners : List Runner 15 | , active : Bool 16 | } 17 | 18 | 19 | type alias Runner = 20 | { id : String 21 | , name : String 22 | , location : String 23 | , age : Int 24 | , bib : Int 25 | , estimatedDistance : Float 26 | , lastMarkerDistance : Float 27 | , lastMarkerTime : Float 28 | , pace : Float 29 | } 30 | 31 | 32 | tempRunners : List Runner 33 | tempRunners = 34 | [ Runner "1" "James Moore" "Turlock CA" 42 1234 0 1 1463154945381 0.125 35 | , Runner "2" "Meb Keflezighi" "Turlock CA" 41 1238 0 1 1463154945381 0.09 36 | ] 37 | 38 | 39 | initModel : Model 40 | initModel = 41 | { error = Nothing 42 | , query = "" 43 | , runners = tempRunners 44 | , active = False 45 | } 46 | 47 | 48 | init : ( Model, Cmd Msg ) 49 | init = 50 | ( initModel, Cmd.none ) 51 | 52 | 53 | 54 | -- update 55 | 56 | 57 | type Msg 58 | = SearchInput String 59 | | Search 60 | 61 | 62 | update : Msg -> Model -> ( Model, Cmd Msg ) 63 | update msg model = 64 | case msg of 65 | SearchInput query -> 66 | ( { model | query = query }, Cmd.none ) 67 | 68 | Search -> 69 | ( model, Cmd.none ) 70 | 71 | 72 | 73 | -- view 74 | 75 | 76 | view : Model -> Html Msg 77 | view model = 78 | div [ class "main" ] 79 | [ errorPanel model.error 80 | , searchForm model.query 81 | , runners model 82 | ] 83 | 84 | 85 | errorPanel : Maybe String -> Html a 86 | errorPanel error = 87 | case error of 88 | Nothing -> 89 | text "" 90 | 91 | Just msg -> 92 | div [ class "error" ] 93 | [ text msg 94 | , button [ type_ "button" ] [ text "×" ] 95 | ] 96 | 97 | 98 | searchForm : String -> Html Msg 99 | searchForm query = 100 | Html.form [ onSubmit Search ] 101 | [ input 102 | [ type_ "text" 103 | , placeholder "Search for runner..." 104 | , value query 105 | , onInput SearchInput 106 | ] 107 | [] 108 | , button [ type_ "submit" ] [ text "Search" ] 109 | ] 110 | 111 | 112 | runners : Model -> Html Msg 113 | runners { query, runners } = 114 | runners 115 | |> List.map runner 116 | |> tbody [] 117 | |> (\r -> runnersHeader :: [ r ]) 118 | |> table [] 119 | 120 | 121 | runner : Runner -> Html Msg 122 | runner { name, location, age, bib, estimatedDistance } = 123 | tr [] 124 | [ td [] [ text name ] 125 | , td [] [ text location ] 126 | , td [] [ text (toString age) ] 127 | , td [] [ text (toString bib) ] 128 | , td [] 129 | [ text "1 mi @ 08:30AM (TODO)" 130 | ] 131 | , td [] [ text (toString estimatedDistance) ] 132 | ] 133 | 134 | 135 | runnersHeader : Html Msg 136 | runnersHeader = 137 | thead [] 138 | [ tr [] 139 | [ th [] [ text "Name" ] 140 | , th [] [ text "From" ] 141 | , th [] [ text "Age" ] 142 | , th [] [ text "Bib #" ] 143 | , th [] [ text "Last Marker" ] 144 | , th [] [ text "Est. Miles" ] 145 | ] 146 | ] 147 | 148 | 149 | 150 | -- subscriptions 151 | 152 | 153 | subscriptions : Model -> Sub Msg 154 | subscriptions model = 155 | Sub.none 156 | -------------------------------------------------------------------------------- /11RLBLogout/src/LeaderBoard.elm: -------------------------------------------------------------------------------- 1 | module LeaderBoard exposing (..) 2 | 3 | import Html exposing (..) 4 | import Html.Events exposing (..) 5 | import Html.Attributes exposing (..) 6 | 7 | 8 | -- model 9 | 10 | 11 | type alias Model = 12 | { error : Maybe String 13 | , query : String 14 | , runners : List Runner 15 | , active : Bool 16 | } 17 | 18 | 19 | type alias Runner = 20 | { id : String 21 | , name : String 22 | , location : String 23 | , age : Int 24 | , bib : Int 25 | , estimatedDistance : Float 26 | , lastMarkerDistance : Float 27 | , lastMarkerTime : Float 28 | , pace : Float 29 | } 30 | 31 | 32 | tempRunners : List Runner 33 | tempRunners = 34 | [ Runner "1" "James Moore" "Turlock CA" 42 1234 0 1 1463154945381 0.125 35 | , Runner "2" "Meb Keflezighi" "Turlock CA" 41 1238 0 1 1463154945381 0.09 36 | ] 37 | 38 | 39 | initModel : Model 40 | initModel = 41 | { error = Nothing 42 | , query = "" 43 | , runners = tempRunners 44 | , active = False 45 | } 46 | 47 | 48 | init : ( Model, Cmd Msg ) 49 | init = 50 | ( initModel, Cmd.none ) 51 | 52 | 53 | 54 | -- update 55 | 56 | 57 | type Msg 58 | = SearchInput String 59 | | Search 60 | 61 | 62 | update : Msg -> Model -> ( Model, Cmd Msg ) 63 | update msg model = 64 | case msg of 65 | SearchInput query -> 66 | ( { model | query = query }, Cmd.none ) 67 | 68 | Search -> 69 | ( model, Cmd.none ) 70 | 71 | 72 | 73 | -- view 74 | 75 | 76 | view : Model -> Html Msg 77 | view model = 78 | div [ class "main" ] 79 | [ errorPanel model.error 80 | , searchForm model.query 81 | , runners model 82 | ] 83 | 84 | 85 | errorPanel : Maybe String -> Html a 86 | errorPanel error = 87 | case error of 88 | Nothing -> 89 | text "" 90 | 91 | Just msg -> 92 | div [ class "error" ] 93 | [ text msg 94 | , button [ type_ "button" ] [ text "×" ] 95 | ] 96 | 97 | 98 | searchForm : String -> Html Msg 99 | searchForm query = 100 | Html.form [ onSubmit Search ] 101 | [ input 102 | [ type_ "text" 103 | , placeholder "Search for runner..." 104 | , value query 105 | , onInput SearchInput 106 | ] 107 | [] 108 | , button [ type_ "submit" ] [ text "Search" ] 109 | ] 110 | 111 | 112 | runners : Model -> Html Msg 113 | runners { query, runners } = 114 | runners 115 | |> List.map runner 116 | |> tbody [] 117 | |> (\r -> runnersHeader :: [ r ]) 118 | |> table [] 119 | 120 | 121 | runner : Runner -> Html Msg 122 | runner { name, location, age, bib, estimatedDistance } = 123 | tr [] 124 | [ td [] [ text name ] 125 | , td [] [ text location ] 126 | , td [] [ text (toString age) ] 127 | , td [] [ text (toString bib) ] 128 | , td [] 129 | [ text "1 mi @ 08:30AM (TODO)" 130 | ] 131 | , td [] [ text (toString estimatedDistance) ] 132 | ] 133 | 134 | 135 | runnersHeader : Html Msg 136 | runnersHeader = 137 | thead [] 138 | [ tr [] 139 | [ th [] [ text "Name" ] 140 | , th [] [ text "From" ] 141 | , th [] [ text "Age" ] 142 | , th [] [ text "Bib #" ] 143 | , th [] [ text "Last Marker" ] 144 | , th [] [ text "Est. Miles" ] 145 | ] 146 | ] 147 | 148 | 149 | 150 | -- subscriptions 151 | 152 | 153 | subscriptions : Model -> Sub Msg 154 | subscriptions model = 155 | Sub.none 156 | -------------------------------------------------------------------------------- /13RLBAddRunner/src/LeaderBoard.elm: -------------------------------------------------------------------------------- 1 | module LeaderBoard exposing (..) 2 | 3 | import Html exposing (..) 4 | import Html.Events exposing (..) 5 | import Html.Attributes exposing (..) 6 | 7 | 8 | -- model 9 | 10 | 11 | type alias Model = 12 | { error : Maybe String 13 | , query : String 14 | , runners : List Runner 15 | , active : Bool 16 | } 17 | 18 | 19 | type alias Runner = 20 | { id : String 21 | , name : String 22 | , location : String 23 | , age : Int 24 | , bib : Int 25 | , estimatedDistance : Float 26 | , lastMarkerDistance : Float 27 | , lastMarkerTime : Float 28 | , pace : Float 29 | } 30 | 31 | 32 | tempRunners : List Runner 33 | tempRunners = 34 | [ Runner "1" "James Moore" "Turlock CA" 42 1234 0 1 1463154945381 0.125 35 | , Runner "2" "Meb Keflezighi" "Turlock CA" 41 1238 0 1 1463154945381 0.09 36 | ] 37 | 38 | 39 | initModel : Model 40 | initModel = 41 | { error = Nothing 42 | , query = "" 43 | , runners = tempRunners 44 | , active = False 45 | } 46 | 47 | 48 | init : ( Model, Cmd Msg ) 49 | init = 50 | ( initModel, Cmd.none ) 51 | 52 | 53 | 54 | -- update 55 | 56 | 57 | type Msg 58 | = SearchInput String 59 | | Search 60 | 61 | 62 | update : Msg -> Model -> ( Model, Cmd Msg ) 63 | update msg model = 64 | case msg of 65 | SearchInput query -> 66 | ( { model | query = query }, Cmd.none ) 67 | 68 | Search -> 69 | ( model, Cmd.none ) 70 | 71 | 72 | 73 | -- view 74 | 75 | 76 | view : Model -> Html Msg 77 | view model = 78 | div [ class "main" ] 79 | [ errorPanel model.error 80 | , searchForm model.query 81 | , runners model 82 | ] 83 | 84 | 85 | errorPanel : Maybe String -> Html a 86 | errorPanel error = 87 | case error of 88 | Nothing -> 89 | text "" 90 | 91 | Just msg -> 92 | div [ class "error" ] 93 | [ text msg 94 | , button [ type_ "button" ] [ text "×" ] 95 | ] 96 | 97 | 98 | searchForm : String -> Html Msg 99 | searchForm query = 100 | Html.form [ onSubmit Search ] 101 | [ input 102 | [ type_ "text" 103 | , placeholder "Search for runner..." 104 | , value query 105 | , onInput SearchInput 106 | ] 107 | [] 108 | , button [ type_ "submit" ] [ text "Search" ] 109 | ] 110 | 111 | 112 | runners : Model -> Html Msg 113 | runners { query, runners } = 114 | runners 115 | |> List.map runner 116 | |> tbody [] 117 | |> (\r -> runnersHeader :: [ r ]) 118 | |> table [] 119 | 120 | 121 | runner : Runner -> Html Msg 122 | runner { name, location, age, bib, estimatedDistance } = 123 | tr [] 124 | [ td [] [ text name ] 125 | , td [] [ text location ] 126 | , td [] [ text (toString age) ] 127 | , td [] [ text (toString bib) ] 128 | , td [] 129 | [ text "1 mi @ 08:30AM (TODO)" 130 | ] 131 | , td [] [ text (toString estimatedDistance) ] 132 | ] 133 | 134 | 135 | runnersHeader : Html Msg 136 | runnersHeader = 137 | thead [] 138 | [ tr [] 139 | [ th [] [ text "Name" ] 140 | , th [] [ text "From" ] 141 | , th [] [ text "Age" ] 142 | , th [] [ text "Bib #" ] 143 | , th [] [ text "Last Marker" ] 144 | , th [] [ text "Est. Miles" ] 145 | ] 146 | ] 147 | 148 | 149 | 150 | -- subscriptions 151 | 152 | 153 | subscriptions : Model -> Sub Msg 154 | subscriptions model = 155 | Sub.none 156 | -------------------------------------------------------------------------------- /08RLBNavigation/src/LeaderBoard.elm: -------------------------------------------------------------------------------- 1 | module LeaderBoard exposing (..) 2 | 3 | import Html exposing (..) 4 | import Html.Events exposing (..) 5 | import Html.Attributes exposing (..) 6 | 7 | 8 | -- model 9 | 10 | 11 | type alias Model = 12 | { error : Maybe String 13 | , query : String 14 | , runners : List Runner 15 | , active : Bool 16 | } 17 | 18 | 19 | type alias Runner = 20 | { id : String 21 | , name : String 22 | , location : String 23 | , age : Int 24 | , bib : Int 25 | , estimatedDistance : Float 26 | , lastMarkerDistance : Float 27 | , lastMarkerTime : Float 28 | , pace : Float 29 | } 30 | 31 | 32 | tempRunners : List Runner 33 | tempRunners = 34 | [ Runner "1" "James Moore" "Turlock CA" 42 1234 0 1 1463154945381 0.125 35 | , Runner "2" "Meb Keflezighi" "Turlock CA" 41 1238 0 1 1463154945381 0.09 36 | ] 37 | 38 | 39 | initModel : Model 40 | initModel = 41 | { error = Nothing 42 | , query = "" 43 | , runners = tempRunners 44 | , active = False 45 | } 46 | 47 | 48 | init : ( Model, Cmd Msg ) 49 | init = 50 | ( initModel, Cmd.none ) 51 | 52 | 53 | 54 | -- update 55 | 56 | 57 | type Msg 58 | = SearchInput String 59 | | Search 60 | 61 | 62 | update : Msg -> Model -> ( Model, Cmd Msg ) 63 | update msg model = 64 | case msg of 65 | SearchInput query -> 66 | ( { model | query = query }, Cmd.none ) 67 | 68 | Search -> 69 | ( model, Cmd.none ) 70 | 71 | 72 | 73 | -- view 74 | 75 | 76 | view : Model -> Html Msg 77 | view model = 78 | div [ class "main" ] 79 | [ errorPanel model.error 80 | , searchForm model.query 81 | , runners model 82 | ] 83 | 84 | 85 | errorPanel : Maybe String -> Html a 86 | errorPanel error = 87 | case error of 88 | Nothing -> 89 | text "" 90 | 91 | Just msg -> 92 | div [ class "error" ] 93 | [ text msg 94 | , button [ type_ "button" ] [ text "×" ] 95 | ] 96 | 97 | 98 | searchForm : String -> Html Msg 99 | searchForm query = 100 | Html.form [ onSubmit Search ] 101 | [ input 102 | [ type_ "text" 103 | , placeholder "Search for runner..." 104 | , value query 105 | , onInput SearchInput 106 | ] 107 | [] 108 | , button [ type_ "submit" ] [ text "Search" ] 109 | ] 110 | 111 | 112 | runners : Model -> Html Msg 113 | runners { query, runners } = 114 | runners 115 | |> List.map runner 116 | |> tbody [] 117 | |> (\r -> runnersHeader :: [ r ]) 118 | |> table [] 119 | 120 | 121 | runner : Runner -> Html Msg 122 | runner { name, location, age, bib, estimatedDistance } = 123 | tr [] 124 | [ td [] [ text name ] 125 | , td [] [ text location ] 126 | , td [] [ text (toString age) ] 127 | , td [] [ text (toString bib) ] 128 | , td [] 129 | [ text "1 mi @ 08:30AM (TODO)" 130 | ] 131 | , td [] [ text (toString estimatedDistance) ] 132 | ] 133 | 134 | 135 | runnersHeader : Html Msg 136 | runnersHeader = 137 | thead [] 138 | [ tr [] 139 | [ th [] [ text "Name" ] 140 | , th [] [ text "From" ] 141 | , th [] [ text "Age" ] 142 | , th [] [ text "Bib #" ] 143 | , th [] [ text "Last Marker" ] 144 | , th [] [ text "Est. Miles" ] 145 | ] 146 | ] 147 | 148 | 149 | 150 | -- subscriptions 151 | 152 | 153 | subscriptions : Model -> Sub Msg 154 | subscriptions model = 155 | Sub.none 156 | -------------------------------------------------------------------------------- /10RLBLoginToken/src/LeaderBoard.elm: -------------------------------------------------------------------------------- 1 | module LeaderBoard exposing (..) 2 | 3 | import Html exposing (..) 4 | import Html.Events exposing (..) 5 | import Html.Attributes exposing (..) 6 | 7 | 8 | -- model 9 | 10 | 11 | type alias Model = 12 | { error : Maybe String 13 | , query : String 14 | , runners : List Runner 15 | , active : Bool 16 | } 17 | 18 | 19 | type alias Runner = 20 | { id : String 21 | , name : String 22 | , location : String 23 | , age : Int 24 | , bib : Int 25 | , estimatedDistance : Float 26 | , lastMarkerDistance : Float 27 | , lastMarkerTime : Float 28 | , pace : Float 29 | } 30 | 31 | 32 | tempRunners : List Runner 33 | tempRunners = 34 | [ Runner "1" "James Moore" "Turlock CA" 42 1234 0 1 1463154945381 0.125 35 | , Runner "2" "Meb Keflezighi" "Turlock CA" 41 1238 0 1 1463154945381 0.09 36 | ] 37 | 38 | 39 | initModel : Model 40 | initModel = 41 | { error = Nothing 42 | , query = "" 43 | , runners = tempRunners 44 | , active = False 45 | } 46 | 47 | 48 | init : ( Model, Cmd Msg ) 49 | init = 50 | ( initModel, Cmd.none ) 51 | 52 | 53 | 54 | -- update 55 | 56 | 57 | type Msg 58 | = SearchInput String 59 | | Search 60 | 61 | 62 | update : Msg -> Model -> ( Model, Cmd Msg ) 63 | update msg model = 64 | case msg of 65 | SearchInput query -> 66 | ( { model | query = query }, Cmd.none ) 67 | 68 | Search -> 69 | ( model, Cmd.none ) 70 | 71 | 72 | 73 | -- view 74 | 75 | 76 | view : Model -> Html Msg 77 | view model = 78 | div [ class "main" ] 79 | [ errorPanel model.error 80 | , searchForm model.query 81 | , runners model 82 | ] 83 | 84 | 85 | errorPanel : Maybe String -> Html a 86 | errorPanel error = 87 | case error of 88 | Nothing -> 89 | text "" 90 | 91 | Just msg -> 92 | div [ class "error" ] 93 | [ text msg 94 | , button [ type_ "button" ] [ text "×" ] 95 | ] 96 | 97 | 98 | searchForm : String -> Html Msg 99 | searchForm query = 100 | Html.form [ onSubmit Search ] 101 | [ input 102 | [ type_ "text" 103 | , placeholder "Search for runner..." 104 | , value query 105 | , onInput SearchInput 106 | ] 107 | [] 108 | , button [ type_ "submit" ] [ text "Search" ] 109 | ] 110 | 111 | 112 | runners : Model -> Html Msg 113 | runners { query, runners } = 114 | runners 115 | |> List.map runner 116 | |> tbody [] 117 | |> (\r -> runnersHeader :: [ r ]) 118 | |> table [] 119 | 120 | 121 | runner : Runner -> Html Msg 122 | runner { name, location, age, bib, estimatedDistance } = 123 | tr [] 124 | [ td [] [ text name ] 125 | , td [] [ text location ] 126 | , td [] [ text (toString age) ] 127 | , td [] [ text (toString bib) ] 128 | , td [] 129 | [ text "1 mi @ 08:30AM (TODO)" 130 | ] 131 | , td [] [ text (toString estimatedDistance) ] 132 | ] 133 | 134 | 135 | runnersHeader : Html Msg 136 | runnersHeader = 137 | thead [] 138 | [ tr [] 139 | [ th [] [ text "Name" ] 140 | , th [] [ text "From" ] 141 | , th [] [ text "Age" ] 142 | , th [] [ text "Bib #" ] 143 | , th [] [ text "Last Marker" ] 144 | , th [] [ text "Est. Miles" ] 145 | ] 146 | ] 147 | 148 | 149 | 150 | -- subscriptions 151 | 152 | 153 | subscriptions : Model -> Sub Msg 154 | subscriptions model = 155 | Sub.none 156 | -------------------------------------------------------------------------------- /12RLBLockRunnerPage/src/LeaderBoard.elm: -------------------------------------------------------------------------------- 1 | module LeaderBoard exposing (..) 2 | 3 | import Html exposing (..) 4 | import Html.Events exposing (..) 5 | import Html.Attributes exposing (..) 6 | 7 | 8 | -- model 9 | 10 | 11 | type alias Model = 12 | { error : Maybe String 13 | , query : String 14 | , runners : List Runner 15 | , active : Bool 16 | } 17 | 18 | 19 | type alias Runner = 20 | { id : String 21 | , name : String 22 | , location : String 23 | , age : Int 24 | , bib : Int 25 | , estimatedDistance : Float 26 | , lastMarkerDistance : Float 27 | , lastMarkerTime : Float 28 | , pace : Float 29 | } 30 | 31 | 32 | tempRunners : List Runner 33 | tempRunners = 34 | [ Runner "1" "James Moore" "Turlock CA" 42 1234 0 1 1463154945381 0.125 35 | , Runner "2" "Meb Keflezighi" "Turlock CA" 41 1238 0 1 1463154945381 0.09 36 | ] 37 | 38 | 39 | initModel : Model 40 | initModel = 41 | { error = Nothing 42 | , query = "" 43 | , runners = tempRunners 44 | , active = False 45 | } 46 | 47 | 48 | init : ( Model, Cmd Msg ) 49 | init = 50 | ( initModel, Cmd.none ) 51 | 52 | 53 | 54 | -- update 55 | 56 | 57 | type Msg 58 | = SearchInput String 59 | | Search 60 | 61 | 62 | update : Msg -> Model -> ( Model, Cmd Msg ) 63 | update msg model = 64 | case msg of 65 | SearchInput query -> 66 | ( { model | query = query }, Cmd.none ) 67 | 68 | Search -> 69 | ( model, Cmd.none ) 70 | 71 | 72 | 73 | -- view 74 | 75 | 76 | view : Model -> Html Msg 77 | view model = 78 | div [ class "main" ] 79 | [ errorPanel model.error 80 | , searchForm model.query 81 | , runners model 82 | ] 83 | 84 | 85 | errorPanel : Maybe String -> Html a 86 | errorPanel error = 87 | case error of 88 | Nothing -> 89 | text "" 90 | 91 | Just msg -> 92 | div [ class "error" ] 93 | [ text msg 94 | , button [ type_ "button" ] [ text "×" ] 95 | ] 96 | 97 | 98 | searchForm : String -> Html Msg 99 | searchForm query = 100 | Html.form [ onSubmit Search ] 101 | [ input 102 | [ type_ "text" 103 | , placeholder "Search for runner..." 104 | , value query 105 | , onInput SearchInput 106 | ] 107 | [] 108 | , button [ type_ "submit" ] [ text "Search" ] 109 | ] 110 | 111 | 112 | runners : Model -> Html Msg 113 | runners { query, runners } = 114 | runners 115 | |> List.map runner 116 | |> tbody [] 117 | |> (\r -> runnersHeader :: [ r ]) 118 | |> table [] 119 | 120 | 121 | runner : Runner -> Html Msg 122 | runner { name, location, age, bib, estimatedDistance } = 123 | tr [] 124 | [ td [] [ text name ] 125 | , td [] [ text location ] 126 | , td [] [ text (toString age) ] 127 | , td [] [ text (toString bib) ] 128 | , td [] 129 | [ text "1 mi @ 08:30AM (TODO)" 130 | ] 131 | , td [] [ text (toString estimatedDistance) ] 132 | ] 133 | 134 | 135 | runnersHeader : Html Msg 136 | runnersHeader = 137 | thead [] 138 | [ tr [] 139 | [ th [] [ text "Name" ] 140 | , th [] [ text "From" ] 141 | , th [] [ text "Age" ] 142 | , th [] [ text "Bib #" ] 143 | , th [] [ text "Last Marker" ] 144 | , th [] [ text "Est. Miles" ] 145 | ] 146 | ] 147 | 148 | 149 | 150 | -- subscriptions 151 | 152 | 153 | subscriptions : Model -> Sub Msg 154 | subscriptions model = 155 | Sub.none 156 | -------------------------------------------------------------------------------- /13RLBAddRunner/completed/src/LeaderBoard.elm: -------------------------------------------------------------------------------- 1 | module LeaderBoard exposing (..) 2 | 3 | import Html exposing (..) 4 | import Html.Events exposing (..) 5 | import Html.Attributes exposing (..) 6 | 7 | 8 | -- model 9 | 10 | 11 | type alias Model = 12 | { error : Maybe String 13 | , query : String 14 | , runners : List Runner 15 | , active : Bool 16 | } 17 | 18 | 19 | type alias Runner = 20 | { id : String 21 | , name : String 22 | , location : String 23 | , age : Int 24 | , bib : Int 25 | , estimatedDistance : Float 26 | , lastMarkerDistance : Float 27 | , lastMarkerTime : Float 28 | , pace : Float 29 | } 30 | 31 | 32 | tempRunners : List Runner 33 | tempRunners = 34 | [ Runner "1" "James Moore" "Turlock CA" 42 1234 0 1 1463154945381 0.125 35 | , Runner "2" "Meb Keflezighi" "Turlock CA" 41 1238 0 1 1463154945381 0.09 36 | ] 37 | 38 | 39 | initModel : Model 40 | initModel = 41 | { error = Nothing 42 | , query = "" 43 | , runners = tempRunners 44 | , active = False 45 | } 46 | 47 | 48 | init : ( Model, Cmd Msg ) 49 | init = 50 | ( initModel, Cmd.none ) 51 | 52 | 53 | 54 | -- update 55 | 56 | 57 | type Msg 58 | = SearchInput String 59 | | Search 60 | 61 | 62 | update : Msg -> Model -> ( Model, Cmd Msg ) 63 | update msg model = 64 | case msg of 65 | SearchInput query -> 66 | ( { model | query = query }, Cmd.none ) 67 | 68 | Search -> 69 | ( model, Cmd.none ) 70 | 71 | 72 | 73 | -- view 74 | 75 | 76 | view : Model -> Html Msg 77 | view model = 78 | div [ class "main" ] 79 | [ errorPanel model.error 80 | , searchForm model.query 81 | , runners model 82 | ] 83 | 84 | 85 | errorPanel : Maybe String -> Html a 86 | errorPanel error = 87 | case error of 88 | Nothing -> 89 | text "" 90 | 91 | Just msg -> 92 | div [ class "error" ] 93 | [ text msg 94 | , button [ type_ "button" ] [ text "×" ] 95 | ] 96 | 97 | 98 | searchForm : String -> Html Msg 99 | searchForm query = 100 | Html.form [ onSubmit Search ] 101 | [ input 102 | [ type_ "text" 103 | , placeholder "Search for runner..." 104 | , value query 105 | , onInput SearchInput 106 | ] 107 | [] 108 | , button [ type_ "submit" ] [ text "Search" ] 109 | ] 110 | 111 | 112 | runners : Model -> Html Msg 113 | runners { query, runners } = 114 | runners 115 | |> List.map runner 116 | |> tbody [] 117 | |> (\r -> runnersHeader :: [ r ]) 118 | |> table [] 119 | 120 | 121 | runner : Runner -> Html Msg 122 | runner { name, location, age, bib, estimatedDistance } = 123 | tr [] 124 | [ td [] [ text name ] 125 | , td [] [ text location ] 126 | , td [] [ text (toString age) ] 127 | , td [] [ text (toString bib) ] 128 | , td [] 129 | [ text "1 mi @ 08:30AM (TODO)" 130 | ] 131 | , td [] [ text (toString estimatedDistance) ] 132 | ] 133 | 134 | 135 | runnersHeader : Html Msg 136 | runnersHeader = 137 | thead [] 138 | [ tr [] 139 | [ th [] [ text "Name" ] 140 | , th [] [ text "From" ] 141 | , th [] [ text "Age" ] 142 | , th [] [ text "Bib #" ] 143 | , th [] [ text "Last Marker" ] 144 | , th [] [ text "Est. Miles" ] 145 | ] 146 | ] 147 | 148 | 149 | 150 | -- subscriptions 151 | 152 | 153 | subscriptions : Model -> Sub Msg 154 | subscriptions model = 155 | Sub.none 156 | -------------------------------------------------------------------------------- /08RLBNavigation/completed/src/LeaderBoard.elm: -------------------------------------------------------------------------------- 1 | module LeaderBoard exposing (..) 2 | 3 | import Html exposing (..) 4 | import Html.Events exposing (..) 5 | import Html.Attributes exposing (..) 6 | 7 | 8 | -- model 9 | 10 | 11 | type alias Model = 12 | { error : Maybe String 13 | , query : String 14 | , runners : List Runner 15 | , active : Bool 16 | } 17 | 18 | 19 | type alias Runner = 20 | { id : String 21 | , name : String 22 | , location : String 23 | , age : Int 24 | , bib : Int 25 | , estimatedDistance : Float 26 | , lastMarkerDistance : Float 27 | , lastMarkerTime : Float 28 | , pace : Float 29 | } 30 | 31 | 32 | tempRunners : List Runner 33 | tempRunners = 34 | [ Runner "1" "James Moore" "Turlock CA" 42 1234 0 1 1463154945381 0.125 35 | , Runner "2" "Meb Keflezighi" "Turlock CA" 41 1238 0 1 1463154945381 0.09 36 | ] 37 | 38 | 39 | initModel : Model 40 | initModel = 41 | { error = Nothing 42 | , query = "" 43 | , runners = tempRunners 44 | , active = False 45 | } 46 | 47 | 48 | init : ( Model, Cmd Msg ) 49 | init = 50 | ( initModel, Cmd.none ) 51 | 52 | 53 | 54 | -- update 55 | 56 | 57 | type Msg 58 | = SearchInput String 59 | | Search 60 | 61 | 62 | update : Msg -> Model -> ( Model, Cmd Msg ) 63 | update msg model = 64 | case msg of 65 | SearchInput query -> 66 | ( { model | query = query }, Cmd.none ) 67 | 68 | Search -> 69 | ( model, Cmd.none ) 70 | 71 | 72 | 73 | -- view 74 | 75 | 76 | view : Model -> Html Msg 77 | view model = 78 | div [ class "main" ] 79 | [ errorPanel model.error 80 | , searchForm model.query 81 | , runners model 82 | ] 83 | 84 | 85 | errorPanel : Maybe String -> Html a 86 | errorPanel error = 87 | case error of 88 | Nothing -> 89 | text "" 90 | 91 | Just msg -> 92 | div [ class "error" ] 93 | [ text msg 94 | , button [ type_ "button" ] [ text "×" ] 95 | ] 96 | 97 | 98 | searchForm : String -> Html Msg 99 | searchForm query = 100 | Html.form [ onSubmit Search ] 101 | [ input 102 | [ type_ "text" 103 | , placeholder "Search for runner..." 104 | , value query 105 | , onInput SearchInput 106 | ] 107 | [] 108 | , button [ type_ "submit" ] [ text "Search" ] 109 | ] 110 | 111 | 112 | runners : Model -> Html Msg 113 | runners { query, runners } = 114 | runners 115 | |> List.map runner 116 | |> tbody [] 117 | |> (\r -> runnersHeader :: [ r ]) 118 | |> table [] 119 | 120 | 121 | runner : Runner -> Html Msg 122 | runner { name, location, age, bib, estimatedDistance } = 123 | tr [] 124 | [ td [] [ text name ] 125 | , td [] [ text location ] 126 | , td [] [ text (toString age) ] 127 | , td [] [ text (toString bib) ] 128 | , td [] 129 | [ text "1 mi @ 08:30AM (TODO)" 130 | ] 131 | , td [] [ text (toString estimatedDistance) ] 132 | ] 133 | 134 | 135 | runnersHeader : Html Msg 136 | runnersHeader = 137 | thead [] 138 | [ tr [] 139 | [ th [] [ text "Name" ] 140 | , th [] [ text "From" ] 141 | , th [] [ text "Age" ] 142 | , th [] [ text "Bib #" ] 143 | , th [] [ text "Last Marker" ] 144 | , th [] [ text "Est. Miles" ] 145 | ] 146 | ] 147 | 148 | 149 | 150 | -- subscriptions 151 | 152 | 153 | subscriptions : Model -> Sub Msg 154 | subscriptions model = 155 | Sub.none 156 | -------------------------------------------------------------------------------- /06Ports/completed/Main.elm: -------------------------------------------------------------------------------- 1 | port module Main exposing (..) 2 | 3 | import Html exposing (..) 4 | import Html.Events exposing (..) 5 | import Html.Attributes exposing (..) 6 | 7 | 8 | -- model 9 | 10 | 11 | type alias Customer = 12 | { id : String 13 | , name : String 14 | } 15 | 16 | 17 | type alias Model = 18 | { name : String 19 | , customers : List Customer 20 | , error : Maybe String 21 | , nextId : Int 22 | } 23 | 24 | 25 | initModel : Model 26 | initModel = 27 | { name = "" 28 | , customers = [] 29 | , error = Nothing 30 | , nextId = 1 31 | } 32 | 33 | 34 | init : ( Model, Cmd Msg ) 35 | init = 36 | ( initModel, Cmd.none ) 37 | 38 | 39 | 40 | -- update 41 | 42 | 43 | type Msg 44 | = NameInput String 45 | | SaveCustomer 46 | | CustomerSaved String 47 | | CustomerAdded Customer 48 | | DeleteCustomer Customer 49 | | CustomerDeleted String 50 | 51 | 52 | update : Msg -> Model -> ( Model, Cmd Msg ) 53 | update msg model = 54 | case msg of 55 | NameInput name -> 56 | ( { model | name = name }, Cmd.none ) 57 | 58 | SaveCustomer -> 59 | ( model, addCustomer model.name ) 60 | 61 | CustomerSaved key -> 62 | ( { model | name = "" }, Cmd.none ) 63 | 64 | CustomerAdded customer -> 65 | let 66 | newCustomers = 67 | customer :: model.customers 68 | in 69 | ( { model | customers = newCustomers }, Cmd.none ) 70 | 71 | DeleteCustomer customer -> 72 | ( model, deleteCustomer customer ) 73 | 74 | CustomerDeleted id -> 75 | let 76 | newCustomers = 77 | List.filter (\customer -> customer.id /= id) 78 | model.customers 79 | in 80 | ( { model | customers = newCustomers }, Cmd.none ) 81 | 82 | 83 | 84 | -- view 85 | 86 | 87 | viewCustomer : Customer -> Html Msg 88 | viewCustomer customer = 89 | li [] 90 | [ i [ class "remove", onClick (DeleteCustomer customer) ] [] 91 | , text customer.name 92 | ] 93 | 94 | 95 | viewCustomers : List Customer -> Html Msg 96 | viewCustomers customers = 97 | customers 98 | |> List.sortBy .id 99 | |> List.map viewCustomer 100 | |> ul [] 101 | 102 | 103 | viewCustomerForm : Model -> Html Msg 104 | viewCustomerForm model = 105 | Html.form [ onSubmit SaveCustomer ] 106 | [ input [ type_ "text", onInput NameInput, value model.name ] [] 107 | , text <| Maybe.withDefault "" model.error 108 | , button [ type_ "submit" ] [ text "Save" ] 109 | ] 110 | 111 | 112 | view : Model -> Html Msg 113 | view model = 114 | div [] 115 | [ h1 [] [ text "Customer List" ] 116 | , viewCustomerForm model 117 | , viewCustomers model.customers 118 | ] 119 | 120 | 121 | 122 | -- subscription 123 | 124 | 125 | subscriptions : Model -> Sub Msg 126 | subscriptions model = 127 | -- Sub.none 128 | Sub.batch 129 | [ customerSaved CustomerSaved 130 | , newCustomer CustomerAdded 131 | , customerDeleted CustomerDeleted 132 | ] 133 | 134 | 135 | port addCustomer : String -> Cmd msg 136 | 137 | 138 | port customerSaved : (String -> msg) -> Sub msg 139 | 140 | 141 | port newCustomer : (Customer -> msg) -> Sub msg 142 | 143 | 144 | port deleteCustomer : Customer -> Cmd msg 145 | 146 | 147 | port customerDeleted : (String -> msg) -> Sub msg 148 | 149 | 150 | main : Program Never Model Msg 151 | main = 152 | Html.program 153 | { init = init 154 | , update = update 155 | , view = view 156 | , subscriptions = subscriptions 157 | } 158 | -------------------------------------------------------------------------------- /08RLBNavigation/src/Main.elm: -------------------------------------------------------------------------------- 1 | port module Main exposing (..) 2 | 3 | import Html exposing (..) 4 | import Html.Attributes exposing (..) 5 | import Html.Events exposing (..) 6 | import Navigation 7 | import LeaderBoard 8 | 9 | 10 | -- model 11 | 12 | 13 | type alias Model = 14 | { page : Page 15 | , leaderBoard : LeaderBoard.Model 16 | } 17 | 18 | 19 | type Page 20 | = NotFound 21 | | LeaderBoardPage 22 | 23 | 24 | init : Navigation.Location -> ( Model, Cmd Msg ) 25 | init location = 26 | let 27 | page = 28 | hashToPage location.hash 29 | 30 | ( leaderboardInitModel, leaderboardCmd ) = 31 | LeaderBoard.init 32 | 33 | initModel = 34 | { page = page 35 | , leaderBoard = leaderboardInitModel 36 | } 37 | 38 | cmds = 39 | Cmd.batch 40 | [ Cmd.map LeaderBoardMsg leaderboardCmd 41 | ] 42 | in 43 | ( initModel, cmds ) 44 | 45 | 46 | 47 | -- update 48 | 49 | 50 | type Msg 51 | = Navigate Page 52 | | ChangePage Page 53 | | LeaderBoardMsg LeaderBoard.Msg 54 | 55 | 56 | update : Msg -> Model -> ( Model, Cmd Msg ) 57 | update msg model = 58 | case msg of 59 | Navigate page -> 60 | ( { model | page = page }, Navigation.newUrl <| pageToHash page ) 61 | 62 | ChangePage page -> 63 | ( { model | page = page }, Cmd.none ) 64 | 65 | LeaderBoardMsg msg -> 66 | let 67 | ( leaderBoardModel, cmd ) = 68 | LeaderBoard.update msg model.leaderBoard 69 | in 70 | ( { model | leaderBoard = leaderBoardModel } 71 | , Cmd.map LeaderBoardMsg cmd 72 | ) 73 | 74 | 75 | 76 | -- view 77 | 78 | 79 | view : Model -> Html Msg 80 | view model = 81 | let 82 | page = 83 | case model.page of 84 | LeaderBoardPage -> 85 | Html.map LeaderBoardMsg 86 | (LeaderBoard.view model.leaderBoard) 87 | 88 | NotFound -> 89 | div [ class "main" ] 90 | [ h1 [] 91 | [ text "Page Not Found!" ] 92 | ] 93 | in 94 | div [] 95 | [ pageHeader model 96 | , page 97 | ] 98 | 99 | 100 | pageHeader : Model -> Html Msg 101 | pageHeader model = 102 | header [] 103 | [ a [ onClick (Navigate LeaderBoardPage) ] [ text "Race Results" ] 104 | , ul [] 105 | [ li [] 106 | [ a [ href "#" ] [ text "Link" ] 107 | ] 108 | ] 109 | , ul [] 110 | [ li [] 111 | [ a [ href "#" ] [ text "Login" ] 112 | ] 113 | ] 114 | ] 115 | 116 | 117 | 118 | -- subscriptions 119 | 120 | 121 | subscriptions : Model -> Sub Msg 122 | subscriptions model = 123 | let 124 | leaderBoardSub = 125 | LeaderBoard.subscriptions model.leaderBoard 126 | in 127 | Sub.batch 128 | [ Sub.map LeaderBoardMsg leaderBoardSub 129 | ] 130 | 131 | 132 | hashToPage : String -> Page 133 | hashToPage hash = 134 | case hash of 135 | "#/" -> 136 | LeaderBoardPage 137 | 138 | "" -> 139 | LeaderBoardPage 140 | 141 | _ -> 142 | NotFound 143 | 144 | 145 | pageToHash : Page -> String 146 | pageToHash page = 147 | case page of 148 | LeaderBoardPage -> 149 | "#/" 150 | 151 | NotFound -> 152 | "#notfound" 153 | 154 | 155 | locationToMsg : Navigation.Location -> Msg 156 | locationToMsg location = 157 | location.hash 158 | |> hashToPage 159 | |> ChangePage 160 | 161 | 162 | main : Program Never Model Msg 163 | main = 164 | Navigation.program locationToMsg 165 | { init = init 166 | , update = update 167 | , view = view 168 | , subscriptions = subscriptions 169 | } 170 | -------------------------------------------------------------------------------- /09RLBLogin/src/Login.elm: -------------------------------------------------------------------------------- 1 | module Login exposing (..) 2 | 3 | import Html exposing (..) 4 | import Html.Events exposing (..) 5 | import Html.Attributes exposing (..) 6 | import Http 7 | import Json.Encode as JE 8 | import Json.Decode as JD exposing (field) 9 | import Navigation 10 | 11 | 12 | -- model 13 | 14 | 15 | type alias Model = 16 | { username : String 17 | , password : String 18 | , error : Maybe String 19 | } 20 | 21 | 22 | initModel : Model 23 | initModel = 24 | { username = "" 25 | , password = "" 26 | , error = Nothing 27 | } 28 | 29 | 30 | init : ( Model, Cmd Msg ) 31 | init = 32 | ( initModel, Cmd.none ) 33 | 34 | 35 | 36 | -- update 37 | 38 | 39 | type Msg 40 | = UsernameInput String 41 | | PasswordInput String 42 | | Submit 43 | | Error String 44 | | LoginResponse (Result Http.Error String) 45 | 46 | 47 | url : String 48 | url = 49 | "http://localhost:5000/authenticate" 50 | 51 | 52 | update : Msg -> Model -> ( Model, Cmd Msg, Maybe String ) 53 | update msg model = 54 | case msg of 55 | UsernameInput username -> 56 | ( { model | username = username }, Cmd.none, Nothing ) 57 | 58 | PasswordInput password -> 59 | ( { model | password = password }, Cmd.none, Nothing ) 60 | 61 | Submit -> 62 | let 63 | body = 64 | JE.object 65 | [ ( "username", JE.string model.username ) 66 | , ( "password", JE.string model.password ) 67 | ] 68 | |> JE.encode 4 69 | |> Http.stringBody "application/json" 70 | 71 | decoder = 72 | field "token" JD.string 73 | 74 | request = 75 | Http.post url body decoder 76 | 77 | cmd = 78 | Http.send LoginResponse request 79 | in 80 | ( model, cmd, Nothing ) 81 | 82 | Error error -> 83 | ( { model | error = Just error }, Cmd.none, Nothing ) 84 | 85 | LoginResponse (Ok token) -> 86 | ( initModel, Navigation.newUrl "#/", Just token ) 87 | 88 | LoginResponse (Err err) -> 89 | let 90 | errMsg = 91 | case err of 92 | Http.BadStatus resp -> 93 | case resp.status.code of 94 | 401 -> 95 | resp.body 96 | 97 | _ -> 98 | resp.status.message 99 | 100 | _ -> 101 | "Login Error!" 102 | in 103 | ( { model | error = Just errMsg }, Cmd.none, Nothing ) 104 | 105 | 106 | 107 | -- view 108 | 109 | 110 | view : Model -> Html Msg 111 | view model = 112 | div [ class "main" ] 113 | [ errorPanel model.error 114 | , loginForm model 115 | ] 116 | 117 | 118 | loginForm : Model -> Html Msg 119 | loginForm model = 120 | Html.form [ class "add-runner", onSubmit Submit ] 121 | [ fieldset [] 122 | [ legend [] [ text "Login" ] 123 | , div [] 124 | [ label [] [ text "User Name" ] 125 | , input 126 | [ type_ "text" 127 | , value model.username 128 | , onInput UsernameInput 129 | ] 130 | [] 131 | ] 132 | , div [] 133 | [ label [] [ text "Password" ] 134 | , input 135 | [ type_ "password" 136 | , value model.password 137 | , onInput PasswordInput 138 | ] 139 | [] 140 | ] 141 | , div [] 142 | [ label [] [] 143 | , button [ type_ "submit" ] [ text "Login" ] 144 | ] 145 | ] 146 | ] 147 | 148 | 149 | errorPanel : Maybe String -> Html a 150 | errorPanel error = 151 | case error of 152 | Nothing -> 153 | text "" 154 | 155 | Just msg -> 156 | div [ class "error" ] 157 | [ text msg ] 158 | 159 | 160 | subscriptions : Model -> Sub Msg 161 | subscriptions model = 162 | Sub.none 163 | -------------------------------------------------------------------------------- /11RLBLogout/src/Login.elm: -------------------------------------------------------------------------------- 1 | module Login exposing (..) 2 | 3 | import Html exposing (..) 4 | import Html.Events exposing (..) 5 | import Html.Attributes exposing (..) 6 | import Http 7 | import Json.Encode as JE 8 | import Json.Decode as JD exposing (field) 9 | import Navigation 10 | 11 | 12 | -- model 13 | 14 | 15 | type alias Model = 16 | { username : String 17 | , password : String 18 | , error : Maybe String 19 | } 20 | 21 | 22 | initModel : Model 23 | initModel = 24 | { username = "" 25 | , password = "" 26 | , error = Nothing 27 | } 28 | 29 | 30 | init : ( Model, Cmd Msg ) 31 | init = 32 | ( initModel, Cmd.none ) 33 | 34 | 35 | 36 | -- update 37 | 38 | 39 | type Msg 40 | = UsernameInput String 41 | | PasswordInput String 42 | | Submit 43 | | Error String 44 | | LoginResponse (Result Http.Error String) 45 | 46 | 47 | url : String 48 | url = 49 | "http://localhost:5000/authenticate" 50 | 51 | 52 | update : Msg -> Model -> ( Model, Cmd Msg, Maybe String ) 53 | update msg model = 54 | case msg of 55 | UsernameInput username -> 56 | ( { model | username = username }, Cmd.none, Nothing ) 57 | 58 | PasswordInput password -> 59 | ( { model | password = password }, Cmd.none, Nothing ) 60 | 61 | Submit -> 62 | let 63 | body = 64 | JE.object 65 | [ ( "username", JE.string model.username ) 66 | , ( "password", JE.string model.password ) 67 | ] 68 | |> JE.encode 4 69 | |> Http.stringBody "application/json" 70 | 71 | decoder = 72 | field "token" JD.string 73 | 74 | request = 75 | Http.post url body decoder 76 | 77 | cmd = 78 | Http.send LoginResponse request 79 | in 80 | ( model, cmd, Nothing ) 81 | 82 | Error error -> 83 | ( { model | error = Just error }, Cmd.none, Nothing ) 84 | 85 | LoginResponse (Ok token) -> 86 | ( initModel, Navigation.newUrl "#/", Just token ) 87 | 88 | LoginResponse (Err err) -> 89 | let 90 | errMsg = 91 | case err of 92 | Http.BadStatus resp -> 93 | case resp.status.code of 94 | 401 -> 95 | resp.body 96 | 97 | _ -> 98 | resp.status.message 99 | 100 | _ -> 101 | "Login Error!" 102 | in 103 | ( { model | error = Just errMsg }, Cmd.none, Nothing ) 104 | 105 | 106 | 107 | -- view 108 | 109 | 110 | view : Model -> Html Msg 111 | view model = 112 | div [ class "main" ] 113 | [ errorPanel model.error 114 | , loginForm model 115 | ] 116 | 117 | 118 | loginForm : Model -> Html Msg 119 | loginForm model = 120 | Html.form [ class "add-runner", onSubmit Submit ] 121 | [ fieldset [] 122 | [ legend [] [ text "Login" ] 123 | , div [] 124 | [ label [] [ text "User Name" ] 125 | , input 126 | [ type_ "text" 127 | , value model.username 128 | , onInput UsernameInput 129 | ] 130 | [] 131 | ] 132 | , div [] 133 | [ label [] [ text "Password" ] 134 | , input 135 | [ type_ "password" 136 | , value model.password 137 | , onInput PasswordInput 138 | ] 139 | [] 140 | ] 141 | , div [] 142 | [ label [] [] 143 | , button [ type_ "submit" ] [ text "Login" ] 144 | ] 145 | ] 146 | ] 147 | 148 | 149 | errorPanel : Maybe String -> Html a 150 | errorPanel error = 151 | case error of 152 | Nothing -> 153 | text "" 154 | 155 | Just msg -> 156 | div [ class "error" ] 157 | [ text msg ] 158 | 159 | 160 | subscriptions : Model -> Sub Msg 161 | subscriptions model = 162 | Sub.none 163 | -------------------------------------------------------------------------------- /10RLBLoginToken/src/Login.elm: -------------------------------------------------------------------------------- 1 | module Login exposing (..) 2 | 3 | import Html exposing (..) 4 | import Html.Events exposing (..) 5 | import Html.Attributes exposing (..) 6 | import Http 7 | import Json.Encode as JE 8 | import Json.Decode as JD exposing (field) 9 | import Navigation 10 | 11 | 12 | -- model 13 | 14 | 15 | type alias Model = 16 | { username : String 17 | , password : String 18 | , error : Maybe String 19 | } 20 | 21 | 22 | initModel : Model 23 | initModel = 24 | { username = "" 25 | , password = "" 26 | , error = Nothing 27 | } 28 | 29 | 30 | init : ( Model, Cmd Msg ) 31 | init = 32 | ( initModel, Cmd.none ) 33 | 34 | 35 | 36 | -- update 37 | 38 | 39 | type Msg 40 | = UsernameInput String 41 | | PasswordInput String 42 | | Submit 43 | | Error String 44 | | LoginResponse (Result Http.Error String) 45 | 46 | 47 | url : String 48 | url = 49 | "http://localhost:5000/authenticate" 50 | 51 | 52 | update : Msg -> Model -> ( Model, Cmd Msg, Maybe String ) 53 | update msg model = 54 | case msg of 55 | UsernameInput username -> 56 | ( { model | username = username }, Cmd.none, Nothing ) 57 | 58 | PasswordInput password -> 59 | ( { model | password = password }, Cmd.none, Nothing ) 60 | 61 | Submit -> 62 | let 63 | body = 64 | JE.object 65 | [ ( "username", JE.string model.username ) 66 | , ( "password", JE.string model.password ) 67 | ] 68 | |> JE.encode 4 69 | |> Http.stringBody "application/json" 70 | 71 | decoder = 72 | field "token" JD.string 73 | 74 | request = 75 | Http.post url body decoder 76 | 77 | cmd = 78 | Http.send LoginResponse request 79 | in 80 | ( model, cmd, Nothing ) 81 | 82 | Error error -> 83 | ( { model | error = Just error }, Cmd.none, Nothing ) 84 | 85 | LoginResponse (Ok token) -> 86 | ( initModel, Navigation.newUrl "#/", Just token ) 87 | 88 | LoginResponse (Err err) -> 89 | let 90 | errMsg = 91 | case err of 92 | Http.BadStatus resp -> 93 | case resp.status.code of 94 | 401 -> 95 | resp.body 96 | 97 | _ -> 98 | resp.status.message 99 | 100 | _ -> 101 | "Login Error!" 102 | in 103 | ( { model | error = Just errMsg }, Cmd.none, Nothing ) 104 | 105 | 106 | 107 | -- view 108 | 109 | 110 | view : Model -> Html Msg 111 | view model = 112 | div [ class "main" ] 113 | [ errorPanel model.error 114 | , loginForm model 115 | ] 116 | 117 | 118 | loginForm : Model -> Html Msg 119 | loginForm model = 120 | Html.form [ class "add-runner", onSubmit Submit ] 121 | [ fieldset [] 122 | [ legend [] [ text "Login" ] 123 | , div [] 124 | [ label [] [ text "User Name" ] 125 | , input 126 | [ type_ "text" 127 | , value model.username 128 | , onInput UsernameInput 129 | ] 130 | [] 131 | ] 132 | , div [] 133 | [ label [] [ text "Password" ] 134 | , input 135 | [ type_ "password" 136 | , value model.password 137 | , onInput PasswordInput 138 | ] 139 | [] 140 | ] 141 | , div [] 142 | [ label [] [] 143 | , button [ type_ "submit" ] [ text "Login" ] 144 | ] 145 | ] 146 | ] 147 | 148 | 149 | errorPanel : Maybe String -> Html a 150 | errorPanel error = 151 | case error of 152 | Nothing -> 153 | text "" 154 | 155 | Just msg -> 156 | div [ class "error" ] 157 | [ text msg ] 158 | 159 | 160 | subscriptions : Model -> Sub Msg 161 | subscriptions model = 162 | Sub.none 163 | -------------------------------------------------------------------------------- /13RLBAddRunner/src/Login.elm: -------------------------------------------------------------------------------- 1 | module Login exposing (..) 2 | 3 | import Html exposing (..) 4 | import Html.Events exposing (..) 5 | import Html.Attributes exposing (..) 6 | import Http 7 | import Json.Encode as JE 8 | import Json.Decode as JD exposing (field) 9 | import Navigation 10 | 11 | 12 | -- model 13 | 14 | 15 | type alias Model = 16 | { username : String 17 | , password : String 18 | , error : Maybe String 19 | } 20 | 21 | 22 | initModel : Model 23 | initModel = 24 | { username = "" 25 | , password = "" 26 | , error = Nothing 27 | } 28 | 29 | 30 | init : ( Model, Cmd Msg ) 31 | init = 32 | ( initModel, Cmd.none ) 33 | 34 | 35 | 36 | -- update 37 | 38 | 39 | type Msg 40 | = UsernameInput String 41 | | PasswordInput String 42 | | Submit 43 | | Error String 44 | | LoginResponse (Result Http.Error String) 45 | 46 | 47 | url : String 48 | url = 49 | "http://localhost:5000/authenticate" 50 | 51 | 52 | update : Msg -> Model -> ( Model, Cmd Msg, Maybe String ) 53 | update msg model = 54 | case msg of 55 | UsernameInput username -> 56 | ( { model | username = username }, Cmd.none, Nothing ) 57 | 58 | PasswordInput password -> 59 | ( { model | password = password }, Cmd.none, Nothing ) 60 | 61 | Submit -> 62 | let 63 | body = 64 | JE.object 65 | [ ( "username", JE.string model.username ) 66 | , ( "password", JE.string model.password ) 67 | ] 68 | |> JE.encode 4 69 | |> Http.stringBody "application/json" 70 | 71 | decoder = 72 | field "token" JD.string 73 | 74 | request = 75 | Http.post url body decoder 76 | 77 | cmd = 78 | Http.send LoginResponse request 79 | in 80 | ( model, cmd, Nothing ) 81 | 82 | Error error -> 83 | ( { model | error = Just error }, Cmd.none, Nothing ) 84 | 85 | LoginResponse (Ok token) -> 86 | ( initModel, Navigation.newUrl "#/", Just token ) 87 | 88 | LoginResponse (Err err) -> 89 | let 90 | errMsg = 91 | case err of 92 | Http.BadStatus resp -> 93 | case resp.status.code of 94 | 401 -> 95 | resp.body 96 | 97 | _ -> 98 | resp.status.message 99 | 100 | _ -> 101 | "Login Error!" 102 | in 103 | ( { model | error = Just errMsg }, Cmd.none, Nothing ) 104 | 105 | 106 | 107 | -- view 108 | 109 | 110 | view : Model -> Html Msg 111 | view model = 112 | div [ class "main" ] 113 | [ errorPanel model.error 114 | , loginForm model 115 | ] 116 | 117 | 118 | loginForm : Model -> Html Msg 119 | loginForm model = 120 | Html.form [ class "add-runner", onSubmit Submit ] 121 | [ fieldset [] 122 | [ legend [] [ text "Login" ] 123 | , div [] 124 | [ label [] [ text "User Name" ] 125 | , input 126 | [ type_ "text" 127 | , value model.username 128 | , onInput UsernameInput 129 | ] 130 | [] 131 | ] 132 | , div [] 133 | [ label [] [ text "Password" ] 134 | , input 135 | [ type_ "password" 136 | , value model.password 137 | , onInput PasswordInput 138 | ] 139 | [] 140 | ] 141 | , div [] 142 | [ label [] [] 143 | , button [ type_ "submit" ] [ text "Login" ] 144 | ] 145 | ] 146 | ] 147 | 148 | 149 | errorPanel : Maybe String -> Html a 150 | errorPanel error = 151 | case error of 152 | Nothing -> 153 | text "" 154 | 155 | Just msg -> 156 | div [ class "error" ] 157 | [ text msg ] 158 | 159 | 160 | subscriptions : Model -> Sub Msg 161 | subscriptions model = 162 | Sub.none 163 | -------------------------------------------------------------------------------- /14RLBWebsocket/src/Login.elm: -------------------------------------------------------------------------------- 1 | module Login exposing (..) 2 | 3 | import Html exposing (..) 4 | import Html.Events exposing (..) 5 | import Html.Attributes exposing (..) 6 | import Http 7 | import Json.Encode as JE 8 | import Json.Decode as JD exposing (field) 9 | import Navigation 10 | 11 | 12 | -- model 13 | 14 | 15 | type alias Model = 16 | { username : String 17 | , password : String 18 | , error : Maybe String 19 | } 20 | 21 | 22 | initModel : Model 23 | initModel = 24 | { username = "" 25 | , password = "" 26 | , error = Nothing 27 | } 28 | 29 | 30 | init : ( Model, Cmd Msg ) 31 | init = 32 | ( initModel, Cmd.none ) 33 | 34 | 35 | 36 | -- update 37 | 38 | 39 | type Msg 40 | = UsernameInput String 41 | | PasswordInput String 42 | | Submit 43 | | Error String 44 | | LoginResponse (Result Http.Error String) 45 | 46 | 47 | url : String 48 | url = 49 | "http://localhost:5000/authenticate" 50 | 51 | 52 | update : Msg -> Model -> ( Model, Cmd Msg, Maybe String ) 53 | update msg model = 54 | case msg of 55 | UsernameInput username -> 56 | ( { model | username = username }, Cmd.none, Nothing ) 57 | 58 | PasswordInput password -> 59 | ( { model | password = password }, Cmd.none, Nothing ) 60 | 61 | Submit -> 62 | let 63 | body = 64 | JE.object 65 | [ ( "username", JE.string model.username ) 66 | , ( "password", JE.string model.password ) 67 | ] 68 | |> JE.encode 4 69 | |> Http.stringBody "application/json" 70 | 71 | decoder = 72 | field "token" JD.string 73 | 74 | request = 75 | Http.post url body decoder 76 | 77 | cmd = 78 | Http.send LoginResponse request 79 | in 80 | ( model, cmd, Nothing ) 81 | 82 | Error error -> 83 | ( { model | error = Just error }, Cmd.none, Nothing ) 84 | 85 | LoginResponse (Ok token) -> 86 | ( initModel, Navigation.newUrl "#/", Just token ) 87 | 88 | LoginResponse (Err err) -> 89 | let 90 | errMsg = 91 | case err of 92 | Http.BadStatus resp -> 93 | case resp.status.code of 94 | 401 -> 95 | resp.body 96 | 97 | _ -> 98 | resp.status.message 99 | 100 | _ -> 101 | "Login Error!" 102 | in 103 | ( { model | error = Just errMsg }, Cmd.none, Nothing ) 104 | 105 | 106 | 107 | -- view 108 | 109 | 110 | view : Model -> Html Msg 111 | view model = 112 | div [ class "main" ] 113 | [ errorPanel model.error 114 | , loginForm model 115 | ] 116 | 117 | 118 | loginForm : Model -> Html Msg 119 | loginForm model = 120 | Html.form [ class "add-runner", onSubmit Submit ] 121 | [ fieldset [] 122 | [ legend [] [ text "Login" ] 123 | , div [] 124 | [ label [] [ text "User Name" ] 125 | , input 126 | [ type_ "text" 127 | , value model.username 128 | , onInput UsernameInput 129 | ] 130 | [] 131 | ] 132 | , div [] 133 | [ label [] [ text "Password" ] 134 | , input 135 | [ type_ "password" 136 | , value model.password 137 | , onInput PasswordInput 138 | ] 139 | [] 140 | ] 141 | , div [] 142 | [ label [] [] 143 | , button [ type_ "submit" ] [ text "Login" ] 144 | ] 145 | ] 146 | ] 147 | 148 | 149 | errorPanel : Maybe String -> Html a 150 | errorPanel error = 151 | case error of 152 | Nothing -> 153 | text "" 154 | 155 | Just msg -> 156 | div [ class "error" ] 157 | [ text msg ] 158 | 159 | 160 | subscriptions : Model -> Sub Msg 161 | subscriptions model = 162 | Sub.none 163 | -------------------------------------------------------------------------------- /16RLBFilterRunner/src/Login.elm: -------------------------------------------------------------------------------- 1 | module Login exposing (..) 2 | 3 | import Html exposing (..) 4 | import Html.Events exposing (..) 5 | import Html.Attributes exposing (..) 6 | import Http 7 | import Json.Encode as JE 8 | import Json.Decode as JD exposing (field) 9 | import Navigation 10 | 11 | 12 | -- model 13 | 14 | 15 | type alias Model = 16 | { username : String 17 | , password : String 18 | , error : Maybe String 19 | } 20 | 21 | 22 | initModel : Model 23 | initModel = 24 | { username = "" 25 | , password = "" 26 | , error = Nothing 27 | } 28 | 29 | 30 | init : ( Model, Cmd Msg ) 31 | init = 32 | ( initModel, Cmd.none ) 33 | 34 | 35 | 36 | -- update 37 | 38 | 39 | type Msg 40 | = UsernameInput String 41 | | PasswordInput String 42 | | Submit 43 | | Error String 44 | | LoginResponse (Result Http.Error String) 45 | 46 | 47 | url : String 48 | url = 49 | "http://localhost:5000/authenticate" 50 | 51 | 52 | update : Msg -> Model -> ( Model, Cmd Msg, Maybe String ) 53 | update msg model = 54 | case msg of 55 | UsernameInput username -> 56 | ( { model | username = username }, Cmd.none, Nothing ) 57 | 58 | PasswordInput password -> 59 | ( { model | password = password }, Cmd.none, Nothing ) 60 | 61 | Submit -> 62 | let 63 | body = 64 | JE.object 65 | [ ( "username", JE.string model.username ) 66 | , ( "password", JE.string model.password ) 67 | ] 68 | |> JE.encode 4 69 | |> Http.stringBody "application/json" 70 | 71 | decoder = 72 | field "token" JD.string 73 | 74 | request = 75 | Http.post url body decoder 76 | 77 | cmd = 78 | Http.send LoginResponse request 79 | in 80 | ( model, cmd, Nothing ) 81 | 82 | Error error -> 83 | ( { model | error = Just error }, Cmd.none, Nothing ) 84 | 85 | LoginResponse (Ok token) -> 86 | ( initModel, Navigation.newUrl "#/", Just token ) 87 | 88 | LoginResponse (Err err) -> 89 | let 90 | errMsg = 91 | case err of 92 | Http.BadStatus resp -> 93 | case resp.status.code of 94 | 401 -> 95 | resp.body 96 | 97 | _ -> 98 | resp.status.message 99 | 100 | _ -> 101 | "Login Error!" 102 | in 103 | ( { model | error = Just errMsg }, Cmd.none, Nothing ) 104 | 105 | 106 | 107 | -- view 108 | 109 | 110 | view : Model -> Html Msg 111 | view model = 112 | div [ class "main" ] 113 | [ errorPanel model.error 114 | , loginForm model 115 | ] 116 | 117 | 118 | loginForm : Model -> Html Msg 119 | loginForm model = 120 | Html.form [ class "add-runner", onSubmit Submit ] 121 | [ fieldset [] 122 | [ legend [] [ text "Login" ] 123 | , div [] 124 | [ label [] [ text "User Name" ] 125 | , input 126 | [ type_ "text" 127 | , value model.username 128 | , onInput UsernameInput 129 | ] 130 | [] 131 | ] 132 | , div [] 133 | [ label [] [ text "Password" ] 134 | , input 135 | [ type_ "password" 136 | , value model.password 137 | , onInput PasswordInput 138 | ] 139 | [] 140 | ] 141 | , div [] 142 | [ label [] [] 143 | , button [ type_ "submit" ] [ text "Login" ] 144 | ] 145 | ] 146 | ] 147 | 148 | 149 | errorPanel : Maybe String -> Html a 150 | errorPanel error = 151 | case error of 152 | Nothing -> 153 | text "" 154 | 155 | Just msg -> 156 | div [ class "error" ] 157 | [ text msg ] 158 | 159 | 160 | subscriptions : Model -> Sub Msg 161 | subscriptions model = 162 | Sub.none 163 | -------------------------------------------------------------------------------- /12RLBLockRunnerPage/src/Login.elm: -------------------------------------------------------------------------------- 1 | module Login exposing (..) 2 | 3 | import Html exposing (..) 4 | import Html.Events exposing (..) 5 | import Html.Attributes exposing (..) 6 | import Http 7 | import Json.Encode as JE 8 | import Json.Decode as JD exposing (field) 9 | import Navigation 10 | 11 | 12 | -- model 13 | 14 | 15 | type alias Model = 16 | { username : String 17 | , password : String 18 | , error : Maybe String 19 | } 20 | 21 | 22 | initModel : Model 23 | initModel = 24 | { username = "" 25 | , password = "" 26 | , error = Nothing 27 | } 28 | 29 | 30 | init : ( Model, Cmd Msg ) 31 | init = 32 | ( initModel, Cmd.none ) 33 | 34 | 35 | 36 | -- update 37 | 38 | 39 | type Msg 40 | = UsernameInput String 41 | | PasswordInput String 42 | | Submit 43 | | Error String 44 | | LoginResponse (Result Http.Error String) 45 | 46 | 47 | url : String 48 | url = 49 | "http://localhost:5000/authenticate" 50 | 51 | 52 | update : Msg -> Model -> ( Model, Cmd Msg, Maybe String ) 53 | update msg model = 54 | case msg of 55 | UsernameInput username -> 56 | ( { model | username = username }, Cmd.none, Nothing ) 57 | 58 | PasswordInput password -> 59 | ( { model | password = password }, Cmd.none, Nothing ) 60 | 61 | Submit -> 62 | let 63 | body = 64 | JE.object 65 | [ ( "username", JE.string model.username ) 66 | , ( "password", JE.string model.password ) 67 | ] 68 | |> JE.encode 4 69 | |> Http.stringBody "application/json" 70 | 71 | decoder = 72 | field "token" JD.string 73 | 74 | request = 75 | Http.post url body decoder 76 | 77 | cmd = 78 | Http.send LoginResponse request 79 | in 80 | ( model, cmd, Nothing ) 81 | 82 | Error error -> 83 | ( { model | error = Just error }, Cmd.none, Nothing ) 84 | 85 | LoginResponse (Ok token) -> 86 | ( initModel, Navigation.newUrl "#/", Just token ) 87 | 88 | LoginResponse (Err err) -> 89 | let 90 | errMsg = 91 | case err of 92 | Http.BadStatus resp -> 93 | case resp.status.code of 94 | 401 -> 95 | resp.body 96 | 97 | _ -> 98 | resp.status.message 99 | 100 | _ -> 101 | "Login Error!" 102 | in 103 | ( { model | error = Just errMsg }, Cmd.none, Nothing ) 104 | 105 | 106 | 107 | -- view 108 | 109 | 110 | view : Model -> Html Msg 111 | view model = 112 | div [ class "main" ] 113 | [ errorPanel model.error 114 | , loginForm model 115 | ] 116 | 117 | 118 | loginForm : Model -> Html Msg 119 | loginForm model = 120 | Html.form [ class "add-runner", onSubmit Submit ] 121 | [ fieldset [] 122 | [ legend [] [ text "Login" ] 123 | , div [] 124 | [ label [] [ text "User Name" ] 125 | , input 126 | [ type_ "text" 127 | , value model.username 128 | , onInput UsernameInput 129 | ] 130 | [] 131 | ] 132 | , div [] 133 | [ label [] [ text "Password" ] 134 | , input 135 | [ type_ "password" 136 | , value model.password 137 | , onInput PasswordInput 138 | ] 139 | [] 140 | ] 141 | , div [] 142 | [ label [] [] 143 | , button [ type_ "submit" ] [ text "Login" ] 144 | ] 145 | ] 146 | ] 147 | 148 | 149 | errorPanel : Maybe String -> Html a 150 | errorPanel error = 151 | case error of 152 | Nothing -> 153 | text "" 154 | 155 | Just msg -> 156 | div [ class "error" ] 157 | [ text msg ] 158 | 159 | 160 | subscriptions : Model -> Sub Msg 161 | subscriptions model = 162 | Sub.none 163 | -------------------------------------------------------------------------------- /15RLBEstimatedDistance/src/Login.elm: -------------------------------------------------------------------------------- 1 | module Login exposing (..) 2 | 3 | import Html exposing (..) 4 | import Html.Events exposing (..) 5 | import Html.Attributes exposing (..) 6 | import Http 7 | import Json.Encode as JE 8 | import Json.Decode as JD exposing (field) 9 | import Navigation 10 | 11 | 12 | -- model 13 | 14 | 15 | type alias Model = 16 | { username : String 17 | , password : String 18 | , error : Maybe String 19 | } 20 | 21 | 22 | initModel : Model 23 | initModel = 24 | { username = "" 25 | , password = "" 26 | , error = Nothing 27 | } 28 | 29 | 30 | init : ( Model, Cmd Msg ) 31 | init = 32 | ( initModel, Cmd.none ) 33 | 34 | 35 | 36 | -- update 37 | 38 | 39 | type Msg 40 | = UsernameInput String 41 | | PasswordInput String 42 | | Submit 43 | | Error String 44 | | LoginResponse (Result Http.Error String) 45 | 46 | 47 | url : String 48 | url = 49 | "http://localhost:5000/authenticate" 50 | 51 | 52 | update : Msg -> Model -> ( Model, Cmd Msg, Maybe String ) 53 | update msg model = 54 | case msg of 55 | UsernameInput username -> 56 | ( { model | username = username }, Cmd.none, Nothing ) 57 | 58 | PasswordInput password -> 59 | ( { model | password = password }, Cmd.none, Nothing ) 60 | 61 | Submit -> 62 | let 63 | body = 64 | JE.object 65 | [ ( "username", JE.string model.username ) 66 | , ( "password", JE.string model.password ) 67 | ] 68 | |> JE.encode 4 69 | |> Http.stringBody "application/json" 70 | 71 | decoder = 72 | field "token" JD.string 73 | 74 | request = 75 | Http.post url body decoder 76 | 77 | cmd = 78 | Http.send LoginResponse request 79 | in 80 | ( model, cmd, Nothing ) 81 | 82 | Error error -> 83 | ( { model | error = Just error }, Cmd.none, Nothing ) 84 | 85 | LoginResponse (Ok token) -> 86 | ( initModel, Navigation.newUrl "#/", Just token ) 87 | 88 | LoginResponse (Err err) -> 89 | let 90 | errMsg = 91 | case err of 92 | Http.BadStatus resp -> 93 | case resp.status.code of 94 | 401 -> 95 | resp.body 96 | 97 | _ -> 98 | resp.status.message 99 | 100 | _ -> 101 | "Login Error!" 102 | in 103 | ( { model | error = Just errMsg }, Cmd.none, Nothing ) 104 | 105 | 106 | 107 | -- view 108 | 109 | 110 | view : Model -> Html Msg 111 | view model = 112 | div [ class "main" ] 113 | [ errorPanel model.error 114 | , loginForm model 115 | ] 116 | 117 | 118 | loginForm : Model -> Html Msg 119 | loginForm model = 120 | Html.form [ class "add-runner", onSubmit Submit ] 121 | [ fieldset [] 122 | [ legend [] [ text "Login" ] 123 | , div [] 124 | [ label [] [ text "User Name" ] 125 | , input 126 | [ type_ "text" 127 | , value model.username 128 | , onInput UsernameInput 129 | ] 130 | [] 131 | ] 132 | , div [] 133 | [ label [] [ text "Password" ] 134 | , input 135 | [ type_ "password" 136 | , value model.password 137 | , onInput PasswordInput 138 | ] 139 | [] 140 | ] 141 | , div [] 142 | [ label [] [] 143 | , button [ type_ "submit" ] [ text "Login" ] 144 | ] 145 | ] 146 | ] 147 | 148 | 149 | errorPanel : Maybe String -> Html a 150 | errorPanel error = 151 | case error of 152 | Nothing -> 153 | text "" 154 | 155 | Just msg -> 156 | div [ class "error" ] 157 | [ text msg ] 158 | 159 | 160 | subscriptions : Model -> Sub Msg 161 | subscriptions model = 162 | Sub.none 163 | -------------------------------------------------------------------------------- /13RLBAddRunner/completed/src/Login.elm: -------------------------------------------------------------------------------- 1 | module Login exposing (..) 2 | 3 | import Html exposing (..) 4 | import Html.Events exposing (..) 5 | import Html.Attributes exposing (..) 6 | import Http 7 | import Json.Encode as JE 8 | import Json.Decode as JD exposing (field) 9 | import Navigation 10 | 11 | 12 | -- model 13 | 14 | 15 | type alias Model = 16 | { username : String 17 | , password : String 18 | , error : Maybe String 19 | } 20 | 21 | 22 | initModel : Model 23 | initModel = 24 | { username = "" 25 | , password = "" 26 | , error = Nothing 27 | } 28 | 29 | 30 | init : ( Model, Cmd Msg ) 31 | init = 32 | ( initModel, Cmd.none ) 33 | 34 | 35 | 36 | -- update 37 | 38 | 39 | type Msg 40 | = UsernameInput String 41 | | PasswordInput String 42 | | Submit 43 | | Error String 44 | | LoginResponse (Result Http.Error String) 45 | 46 | 47 | url : String 48 | url = 49 | "http://localhost:5000/authenticate" 50 | 51 | 52 | update : Msg -> Model -> ( Model, Cmd Msg, Maybe String ) 53 | update msg model = 54 | case msg of 55 | UsernameInput username -> 56 | ( { model | username = username }, Cmd.none, Nothing ) 57 | 58 | PasswordInput password -> 59 | ( { model | password = password }, Cmd.none, Nothing ) 60 | 61 | Submit -> 62 | let 63 | body = 64 | JE.object 65 | [ ( "username", JE.string model.username ) 66 | , ( "password", JE.string model.password ) 67 | ] 68 | |> JE.encode 4 69 | |> Http.stringBody "application/json" 70 | 71 | decoder = 72 | field "token" JD.string 73 | 74 | request = 75 | Http.post url body decoder 76 | 77 | cmd = 78 | Http.send LoginResponse request 79 | in 80 | ( model, cmd, Nothing ) 81 | 82 | Error error -> 83 | ( { model | error = Just error }, Cmd.none, Nothing ) 84 | 85 | LoginResponse (Ok token) -> 86 | ( initModel, Navigation.newUrl "#/", Just token ) 87 | 88 | LoginResponse (Err err) -> 89 | let 90 | errMsg = 91 | case err of 92 | Http.BadStatus resp -> 93 | case resp.status.code of 94 | 401 -> 95 | resp.body 96 | 97 | _ -> 98 | resp.status.message 99 | 100 | _ -> 101 | "Login Error!" 102 | in 103 | ( { model | error = Just errMsg }, Cmd.none, Nothing ) 104 | 105 | 106 | 107 | -- view 108 | 109 | 110 | view : Model -> Html Msg 111 | view model = 112 | div [ class "main" ] 113 | [ errorPanel model.error 114 | , loginForm model 115 | ] 116 | 117 | 118 | loginForm : Model -> Html Msg 119 | loginForm model = 120 | Html.form [ class "add-runner", onSubmit Submit ] 121 | [ fieldset [] 122 | [ legend [] [ text "Login" ] 123 | , div [] 124 | [ label [] [ text "User Name" ] 125 | , input 126 | [ type_ "text" 127 | , value model.username 128 | , onInput UsernameInput 129 | ] 130 | [] 131 | ] 132 | , div [] 133 | [ label [] [ text "Password" ] 134 | , input 135 | [ type_ "password" 136 | , value model.password 137 | , onInput PasswordInput 138 | ] 139 | [] 140 | ] 141 | , div [] 142 | [ label [] [] 143 | , button [ type_ "submit" ] [ text "Login" ] 144 | ] 145 | ] 146 | ] 147 | 148 | 149 | errorPanel : Maybe String -> Html a 150 | errorPanel error = 151 | case error of 152 | Nothing -> 153 | text "" 154 | 155 | Just msg -> 156 | div [ class "error" ] 157 | [ text msg ] 158 | 159 | 160 | subscriptions : Model -> Sub Msg 161 | subscriptions model = 162 | Sub.none 163 | -------------------------------------------------------------------------------- /14RLBWebsocket/completed/src/Login.elm: -------------------------------------------------------------------------------- 1 | module Login exposing (..) 2 | 3 | import Html exposing (..) 4 | import Html.Events exposing (..) 5 | import Html.Attributes exposing (..) 6 | import Http 7 | import Json.Encode as JE 8 | import Json.Decode as JD exposing (field) 9 | import Navigation 10 | 11 | 12 | -- model 13 | 14 | 15 | type alias Model = 16 | { username : String 17 | , password : String 18 | , error : Maybe String 19 | } 20 | 21 | 22 | initModel : Model 23 | initModel = 24 | { username = "" 25 | , password = "" 26 | , error = Nothing 27 | } 28 | 29 | 30 | init : ( Model, Cmd Msg ) 31 | init = 32 | ( initModel, Cmd.none ) 33 | 34 | 35 | 36 | -- update 37 | 38 | 39 | type Msg 40 | = UsernameInput String 41 | | PasswordInput String 42 | | Submit 43 | | Error String 44 | | LoginResponse (Result Http.Error String) 45 | 46 | 47 | url : String 48 | url = 49 | "http://localhost:5000/authenticate" 50 | 51 | 52 | update : Msg -> Model -> ( Model, Cmd Msg, Maybe String ) 53 | update msg model = 54 | case msg of 55 | UsernameInput username -> 56 | ( { model | username = username }, Cmd.none, Nothing ) 57 | 58 | PasswordInput password -> 59 | ( { model | password = password }, Cmd.none, Nothing ) 60 | 61 | Submit -> 62 | let 63 | body = 64 | JE.object 65 | [ ( "username", JE.string model.username ) 66 | , ( "password", JE.string model.password ) 67 | ] 68 | |> JE.encode 4 69 | |> Http.stringBody "application/json" 70 | 71 | decoder = 72 | field "token" JD.string 73 | 74 | request = 75 | Http.post url body decoder 76 | 77 | cmd = 78 | Http.send LoginResponse request 79 | in 80 | ( model, cmd, Nothing ) 81 | 82 | Error error -> 83 | ( { model | error = Just error }, Cmd.none, Nothing ) 84 | 85 | LoginResponse (Ok token) -> 86 | ( initModel, Navigation.newUrl "#/", Just token ) 87 | 88 | LoginResponse (Err err) -> 89 | let 90 | errMsg = 91 | case err of 92 | Http.BadStatus resp -> 93 | case resp.status.code of 94 | 401 -> 95 | resp.body 96 | 97 | _ -> 98 | resp.status.message 99 | 100 | _ -> 101 | "Login Error!" 102 | in 103 | ( { model | error = Just errMsg }, Cmd.none, Nothing ) 104 | 105 | 106 | 107 | -- view 108 | 109 | 110 | view : Model -> Html Msg 111 | view model = 112 | div [ class "main" ] 113 | [ errorPanel model.error 114 | , loginForm model 115 | ] 116 | 117 | 118 | loginForm : Model -> Html Msg 119 | loginForm model = 120 | Html.form [ class "add-runner", onSubmit Submit ] 121 | [ fieldset [] 122 | [ legend [] [ text "Login" ] 123 | , div [] 124 | [ label [] [ text "User Name" ] 125 | , input 126 | [ type_ "text" 127 | , value model.username 128 | , onInput UsernameInput 129 | ] 130 | [] 131 | ] 132 | , div [] 133 | [ label [] [ text "Password" ] 134 | , input 135 | [ type_ "password" 136 | , value model.password 137 | , onInput PasswordInput 138 | ] 139 | [] 140 | ] 141 | , div [] 142 | [ label [] [] 143 | , button [ type_ "submit" ] [ text "Login" ] 144 | ] 145 | ] 146 | ] 147 | 148 | 149 | errorPanel : Maybe String -> Html a 150 | errorPanel error = 151 | case error of 152 | Nothing -> 153 | text "" 154 | 155 | Just msg -> 156 | div [ class "error" ] 157 | [ text msg ] 158 | 159 | 160 | subscriptions : Model -> Sub Msg 161 | subscriptions model = 162 | Sub.none 163 | -------------------------------------------------------------------------------- /08RLBNavigation/src/Runner.elm: -------------------------------------------------------------------------------- 1 | module Runner exposing (..) 2 | 3 | import Html exposing (..) 4 | import Html.Events exposing (..) 5 | import Html.Attributes exposing (..) 6 | import String 7 | 8 | 9 | -- model 10 | 11 | 12 | type alias Model = 13 | { id : String 14 | , name : String 15 | , nameError : Maybe String 16 | , location : String 17 | , locationError : Maybe String 18 | , age : String 19 | , ageError : Maybe String 20 | , bib : String 21 | , bibError : Maybe String 22 | , error : Maybe String 23 | } 24 | 25 | 26 | initModel : Model 27 | initModel = 28 | { id = "" 29 | , name = "" 30 | , nameError = Nothing 31 | , location = "" 32 | , locationError = Nothing 33 | , age = "" 34 | , ageError = Nothing 35 | , bib = "" 36 | , bibError = Nothing 37 | , error = Nothing 38 | } 39 | 40 | 41 | init : ( Model, Cmd Msg ) 42 | init = 43 | ( initModel, Cmd.none ) 44 | 45 | 46 | 47 | -- update 48 | 49 | 50 | type Msg 51 | = NameInput String 52 | | LocationInput String 53 | | AgeInput String 54 | | BibInput String 55 | | Save 56 | 57 | 58 | update : Msg -> Model -> ( Model, Cmd Msg ) 59 | update msg model = 60 | case msg of 61 | NameInput name -> 62 | ( { model 63 | | name = name 64 | , nameError = Nothing 65 | } 66 | , Cmd.none 67 | ) 68 | 69 | LocationInput location -> 70 | ( { model 71 | | location = location 72 | , locationError = Nothing 73 | } 74 | , Cmd.none 75 | ) 76 | 77 | AgeInput age -> 78 | ageInput model age 79 | 80 | BibInput bib -> 81 | bibInput model bib 82 | 83 | Save -> 84 | ( model, Cmd.none ) 85 | 86 | 87 | ageInput : Model -> String -> ( Model, Cmd Msg ) 88 | ageInput model age = 89 | let 90 | ageInt = 91 | age 92 | |> String.toInt 93 | |> Result.withDefault 0 94 | 95 | ageError = 96 | if ageInt <= 0 then 97 | Just "Must Enter a Positive Number" 98 | else 99 | Nothing 100 | in 101 | ( { model | age = age, ageError = ageError }, Cmd.none ) 102 | 103 | 104 | bibInput : Model -> String -> ( Model, Cmd Msg ) 105 | bibInput model bib = 106 | let 107 | bibInt = 108 | bib 109 | |> String.toInt 110 | |> Result.withDefault 0 111 | 112 | bibError = 113 | if bibInt <= 0 then 114 | Just "Must Enter a Positive Number" 115 | else 116 | Nothing 117 | in 118 | ( { model | bib = bib, bibError = bibError }, Cmd.none ) 119 | 120 | 121 | 122 | -- view 123 | 124 | 125 | view : Model -> Html Msg 126 | view model = 127 | div [ class "main" ] 128 | [ errorPanel model.error 129 | , viewForm model 130 | ] 131 | 132 | 133 | errorPanel : Maybe String -> Html a 134 | errorPanel error = 135 | case error of 136 | Nothing -> 137 | text "" 138 | 139 | Just msg -> 140 | div [ class "error" ] 141 | [ text msg 142 | ] 143 | 144 | 145 | viewForm : Model -> Html Msg 146 | viewForm model = 147 | Html.form [ class "add-runner", onSubmit Save ] 148 | [ fieldset [] 149 | [ legend [] [ text "Add / Edit Runner" ] 150 | , div [] 151 | [ label [] [ text "Name" ] 152 | , input 153 | [ type_ "text" 154 | , value model.name 155 | , onInput NameInput 156 | ] 157 | [] 158 | , span [] [ text <| Maybe.withDefault "" model.nameError ] 159 | ] 160 | , div [] 161 | [ label [] [ text "Location" ] 162 | , input 163 | [ type_ "text" 164 | , value model.location 165 | , onInput LocationInput 166 | ] 167 | [] 168 | , span [] [ text <| Maybe.withDefault "" model.locationError ] 169 | ] 170 | , div [] 171 | [ label [] [ text "Age" ] 172 | , input 173 | [ type_ "text" 174 | , value model.age 175 | , onInput AgeInput 176 | ] 177 | [] 178 | , span [] [ text <| Maybe.withDefault "" model.ageError ] 179 | ] 180 | , div [] 181 | [ label [] [ text "Bib #" ] 182 | , input 183 | [ type_ "text" 184 | , value model.bib 185 | , onInput BibInput 186 | ] 187 | [] 188 | , span [] [ text <| Maybe.withDefault "" model.bibError ] 189 | ] 190 | , div [] 191 | [ label [] [] 192 | , button [ type_ "submit" ] [ text "Save" ] 193 | ] 194 | ] 195 | ] 196 | -------------------------------------------------------------------------------- /07RLBStarter/src/Runner.elm: -------------------------------------------------------------------------------- 1 | module Runner exposing (..) 2 | 3 | import Html exposing (..) 4 | import Html.Events exposing (..) 5 | import Html.Attributes exposing (..) 6 | import String 7 | 8 | 9 | -- model 10 | 11 | 12 | type alias Model = 13 | { id : String 14 | , name : String 15 | , nameError : Maybe String 16 | , location : String 17 | , locationError : Maybe String 18 | , age : String 19 | , ageError : Maybe String 20 | , bib : String 21 | , bibError : Maybe String 22 | , error : Maybe String 23 | } 24 | 25 | 26 | initModel : Model 27 | initModel = 28 | { id = "" 29 | , name = "" 30 | , nameError = Nothing 31 | , location = "" 32 | , locationError = Nothing 33 | , age = "" 34 | , ageError = Nothing 35 | , bib = "" 36 | , bibError = Nothing 37 | , error = Nothing 38 | } 39 | 40 | 41 | init : ( Model, Cmd Msg ) 42 | init = 43 | ( initModel, Cmd.none ) 44 | 45 | 46 | 47 | -- update 48 | 49 | 50 | type Msg 51 | = NameInput String 52 | | LocationInput String 53 | | AgeInput String 54 | | BibInput String 55 | | Save 56 | 57 | 58 | update : Msg -> Model -> ( Model, Cmd Msg ) 59 | update msg model = 60 | case msg of 61 | NameInput name -> 62 | ( { model 63 | | name = name 64 | , nameError = Nothing 65 | } 66 | , Cmd.none 67 | ) 68 | 69 | LocationInput location -> 70 | ( { model 71 | | location = location 72 | , locationError = Nothing 73 | } 74 | , Cmd.none 75 | ) 76 | 77 | AgeInput age -> 78 | ageInput model age 79 | 80 | BibInput bib -> 81 | bibInput model bib 82 | 83 | Save -> 84 | ( model, Cmd.none ) 85 | 86 | 87 | ageInput : Model -> String -> ( Model, Cmd Msg ) 88 | ageInput model age = 89 | let 90 | ageInt = 91 | age 92 | |> String.toInt 93 | |> Result.withDefault 0 94 | 95 | ageError = 96 | if ageInt <= 0 then 97 | Just "Must Enter a Positive Number" 98 | else 99 | Nothing 100 | in 101 | ( { model | age = age, ageError = ageError }, Cmd.none ) 102 | 103 | 104 | bibInput : Model -> String -> ( Model, Cmd Msg ) 105 | bibInput model bib = 106 | let 107 | bibInt = 108 | bib 109 | |> String.toInt 110 | |> Result.withDefault 0 111 | 112 | bibError = 113 | if bibInt <= 0 then 114 | Just "Must Enter a Positive Number" 115 | else 116 | Nothing 117 | in 118 | ( { model | bib = bib, bibError = bibError }, Cmd.none ) 119 | 120 | 121 | 122 | -- view 123 | 124 | 125 | view : Model -> Html Msg 126 | view model = 127 | div [ class "main" ] 128 | [ errorPanel model.error 129 | , viewForm model 130 | ] 131 | 132 | 133 | errorPanel : Maybe String -> Html a 134 | errorPanel error = 135 | case error of 136 | Nothing -> 137 | text "" 138 | 139 | Just msg -> 140 | div [ class "error" ] 141 | [ text msg 142 | ] 143 | 144 | 145 | viewForm : Model -> Html Msg 146 | viewForm model = 147 | Html.form [ class "add-runner", onSubmit Save ] 148 | [ fieldset [] 149 | [ legend [] [ text "Add / Edit Runner" ] 150 | , div [] 151 | [ label [] [ text "Name" ] 152 | , input 153 | [ type_ "text" 154 | , value model.name 155 | , onInput NameInput 156 | ] 157 | [] 158 | , span [] [ text <| Maybe.withDefault "" model.nameError ] 159 | ] 160 | , div [] 161 | [ label [] [ text "Location" ] 162 | , input 163 | [ type_ "text" 164 | , value model.location 165 | , onInput LocationInput 166 | ] 167 | [] 168 | , span [] [ text <| Maybe.withDefault "" model.locationError ] 169 | ] 170 | , div [] 171 | [ label [] [ text "Age" ] 172 | , input 173 | [ type_ "text" 174 | , value model.age 175 | , onInput AgeInput 176 | ] 177 | [] 178 | , span [] [ text <| Maybe.withDefault "" model.ageError ] 179 | ] 180 | , div [] 181 | [ label [] [ text "Bib #" ] 182 | , input 183 | [ type_ "text" 184 | , value model.bib 185 | , onInput BibInput 186 | ] 187 | [] 188 | , span [] [ text <| Maybe.withDefault "" model.bibError ] 189 | ] 190 | , div [] 191 | [ label [] [] 192 | , button [ type_ "submit" ] [ text "Save" ] 193 | ] 194 | ] 195 | ] 196 | 197 | 198 | 199 | -- subscriptions 200 | 201 | 202 | subscriptions : Model -> Sub Msg 203 | subscriptions model = 204 | Sub.none 205 | -------------------------------------------------------------------------------- /09RLBLogin/src/Runner.elm: -------------------------------------------------------------------------------- 1 | module Runner exposing (..) 2 | 3 | import Html exposing (..) 4 | import Html.Events exposing (..) 5 | import Html.Attributes exposing (..) 6 | import String 7 | 8 | 9 | -- model 10 | 11 | 12 | type alias Model = 13 | { id : String 14 | , name : String 15 | , nameError : Maybe String 16 | , location : String 17 | , locationError : Maybe String 18 | , age : String 19 | , ageError : Maybe String 20 | , bib : String 21 | , bibError : Maybe String 22 | , error : Maybe String 23 | } 24 | 25 | 26 | initModel : Model 27 | initModel = 28 | { id = "" 29 | , name = "" 30 | , nameError = Nothing 31 | , location = "" 32 | , locationError = Nothing 33 | , age = "" 34 | , ageError = Nothing 35 | , bib = "" 36 | , bibError = Nothing 37 | , error = Nothing 38 | } 39 | 40 | 41 | init : ( Model, Cmd Msg ) 42 | init = 43 | ( initModel, Cmd.none ) 44 | 45 | 46 | 47 | -- update 48 | 49 | 50 | type Msg 51 | = NameInput String 52 | | LocationInput String 53 | | AgeInput String 54 | | BibInput String 55 | | Save 56 | 57 | 58 | update : Msg -> Model -> ( Model, Cmd Msg ) 59 | update msg model = 60 | case msg of 61 | NameInput name -> 62 | ( { model 63 | | name = name 64 | , nameError = Nothing 65 | } 66 | , Cmd.none 67 | ) 68 | 69 | LocationInput location -> 70 | ( { model 71 | | location = location 72 | , locationError = Nothing 73 | } 74 | , Cmd.none 75 | ) 76 | 77 | AgeInput age -> 78 | ageInput model age 79 | 80 | BibInput bib -> 81 | bibInput model bib 82 | 83 | Save -> 84 | ( model, Cmd.none ) 85 | 86 | 87 | ageInput : Model -> String -> ( Model, Cmd Msg ) 88 | ageInput model age = 89 | let 90 | ageInt = 91 | age 92 | |> String.toInt 93 | |> Result.withDefault 0 94 | 95 | ageError = 96 | if ageInt <= 0 then 97 | Just "Must Enter a Positive Number" 98 | else 99 | Nothing 100 | in 101 | ( { model | age = age, ageError = ageError }, Cmd.none ) 102 | 103 | 104 | bibInput : Model -> String -> ( Model, Cmd Msg ) 105 | bibInput model bib = 106 | let 107 | bibInt = 108 | bib 109 | |> String.toInt 110 | |> Result.withDefault 0 111 | 112 | bibError = 113 | if bibInt <= 0 then 114 | Just "Must Enter a Positive Number" 115 | else 116 | Nothing 117 | in 118 | ( { model | bib = bib, bibError = bibError }, Cmd.none ) 119 | 120 | 121 | 122 | -- view 123 | 124 | 125 | view : Model -> Html Msg 126 | view model = 127 | div [ class "main" ] 128 | [ errorPanel model.error 129 | , viewForm model 130 | ] 131 | 132 | 133 | errorPanel : Maybe String -> Html a 134 | errorPanel error = 135 | case error of 136 | Nothing -> 137 | text "" 138 | 139 | Just msg -> 140 | div [ class "error" ] 141 | [ text msg 142 | ] 143 | 144 | 145 | viewForm : Model -> Html Msg 146 | viewForm model = 147 | Html.form [ class "add-runner", onSubmit Save ] 148 | [ fieldset [] 149 | [ legend [] [ text "Add / Edit Runner" ] 150 | , div [] 151 | [ label [] [ text "Name" ] 152 | , input 153 | [ type_ "text" 154 | , value model.name 155 | , onInput NameInput 156 | ] 157 | [] 158 | , span [] [ text <| Maybe.withDefault "" model.nameError ] 159 | ] 160 | , div [] 161 | [ label [] [ text "Location" ] 162 | , input 163 | [ type_ "text" 164 | , value model.location 165 | , onInput LocationInput 166 | ] 167 | [] 168 | , span [] [ text <| Maybe.withDefault "" model.locationError ] 169 | ] 170 | , div [] 171 | [ label [] [ text "Age" ] 172 | , input 173 | [ type_ "text" 174 | , value model.age 175 | , onInput AgeInput 176 | ] 177 | [] 178 | , span [] [ text <| Maybe.withDefault "" model.ageError ] 179 | ] 180 | , div [] 181 | [ label [] [ text "Bib #" ] 182 | , input 183 | [ type_ "text" 184 | , value model.bib 185 | , onInput BibInput 186 | ] 187 | [] 188 | , span [] [ text <| Maybe.withDefault "" model.bibError ] 189 | ] 190 | , div [] 191 | [ label [] [] 192 | , button [ type_ "submit" ] [ text "Save" ] 193 | ] 194 | ] 195 | ] 196 | 197 | 198 | 199 | -- subscriptions 200 | 201 | 202 | subscriptions : Model -> Sub Msg 203 | subscriptions model = 204 | Sub.none 205 | -------------------------------------------------------------------------------- /11RLBLogout/src/Runner.elm: -------------------------------------------------------------------------------- 1 | module Runner exposing (..) 2 | 3 | import Html exposing (..) 4 | import Html.Events exposing (..) 5 | import Html.Attributes exposing (..) 6 | import String 7 | 8 | 9 | -- model 10 | 11 | 12 | type alias Model = 13 | { id : String 14 | , name : String 15 | , nameError : Maybe String 16 | , location : String 17 | , locationError : Maybe String 18 | , age : String 19 | , ageError : Maybe String 20 | , bib : String 21 | , bibError : Maybe String 22 | , error : Maybe String 23 | } 24 | 25 | 26 | initModel : Model 27 | initModel = 28 | { id = "" 29 | , name = "" 30 | , nameError = Nothing 31 | , location = "" 32 | , locationError = Nothing 33 | , age = "" 34 | , ageError = Nothing 35 | , bib = "" 36 | , bibError = Nothing 37 | , error = Nothing 38 | } 39 | 40 | 41 | init : ( Model, Cmd Msg ) 42 | init = 43 | ( initModel, Cmd.none ) 44 | 45 | 46 | 47 | -- update 48 | 49 | 50 | type Msg 51 | = NameInput String 52 | | LocationInput String 53 | | AgeInput String 54 | | BibInput String 55 | | Save 56 | 57 | 58 | update : Msg -> Model -> ( Model, Cmd Msg ) 59 | update msg model = 60 | case msg of 61 | NameInput name -> 62 | ( { model 63 | | name = name 64 | , nameError = Nothing 65 | } 66 | , Cmd.none 67 | ) 68 | 69 | LocationInput location -> 70 | ( { model 71 | | location = location 72 | , locationError = Nothing 73 | } 74 | , Cmd.none 75 | ) 76 | 77 | AgeInput age -> 78 | ageInput model age 79 | 80 | BibInput bib -> 81 | bibInput model bib 82 | 83 | Save -> 84 | ( model, Cmd.none ) 85 | 86 | 87 | ageInput : Model -> String -> ( Model, Cmd Msg ) 88 | ageInput model age = 89 | let 90 | ageInt = 91 | age 92 | |> String.toInt 93 | |> Result.withDefault 0 94 | 95 | ageError = 96 | if ageInt <= 0 then 97 | Just "Must Enter a Positive Number" 98 | else 99 | Nothing 100 | in 101 | ( { model | age = age, ageError = ageError }, Cmd.none ) 102 | 103 | 104 | bibInput : Model -> String -> ( Model, Cmd Msg ) 105 | bibInput model bib = 106 | let 107 | bibInt = 108 | bib 109 | |> String.toInt 110 | |> Result.withDefault 0 111 | 112 | bibError = 113 | if bibInt <= 0 then 114 | Just "Must Enter a Positive Number" 115 | else 116 | Nothing 117 | in 118 | ( { model | bib = bib, bibError = bibError }, Cmd.none ) 119 | 120 | 121 | 122 | -- view 123 | 124 | 125 | view : Model -> Html Msg 126 | view model = 127 | div [ class "main" ] 128 | [ errorPanel model.error 129 | , viewForm model 130 | ] 131 | 132 | 133 | errorPanel : Maybe String -> Html a 134 | errorPanel error = 135 | case error of 136 | Nothing -> 137 | text "" 138 | 139 | Just msg -> 140 | div [ class "error" ] 141 | [ text msg 142 | ] 143 | 144 | 145 | viewForm : Model -> Html Msg 146 | viewForm model = 147 | Html.form [ class "add-runner", onSubmit Save ] 148 | [ fieldset [] 149 | [ legend [] [ text "Add / Edit Runner" ] 150 | , div [] 151 | [ label [] [ text "Name" ] 152 | , input 153 | [ type_ "text" 154 | , value model.name 155 | , onInput NameInput 156 | ] 157 | [] 158 | , span [] [ text <| Maybe.withDefault "" model.nameError ] 159 | ] 160 | , div [] 161 | [ label [] [ text "Location" ] 162 | , input 163 | [ type_ "text" 164 | , value model.location 165 | , onInput LocationInput 166 | ] 167 | [] 168 | , span [] [ text <| Maybe.withDefault "" model.locationError ] 169 | ] 170 | , div [] 171 | [ label [] [ text "Age" ] 172 | , input 173 | [ type_ "text" 174 | , value model.age 175 | , onInput AgeInput 176 | ] 177 | [] 178 | , span [] [ text <| Maybe.withDefault "" model.ageError ] 179 | ] 180 | , div [] 181 | [ label [] [ text "Bib #" ] 182 | , input 183 | [ type_ "text" 184 | , value model.bib 185 | , onInput BibInput 186 | ] 187 | [] 188 | , span [] [ text <| Maybe.withDefault "" model.bibError ] 189 | ] 190 | , div [] 191 | [ label [] [] 192 | , button [ type_ "submit" ] [ text "Save" ] 193 | ] 194 | ] 195 | ] 196 | 197 | 198 | 199 | -- subscriptions 200 | 201 | 202 | subscriptions : Model -> Sub Msg 203 | subscriptions model = 204 | Sub.none 205 | -------------------------------------------------------------------------------- /10RLBLoginToken/src/Runner.elm: -------------------------------------------------------------------------------- 1 | module Runner exposing (..) 2 | 3 | import Html exposing (..) 4 | import Html.Events exposing (..) 5 | import Html.Attributes exposing (..) 6 | import String 7 | 8 | 9 | -- model 10 | 11 | 12 | type alias Model = 13 | { id : String 14 | , name : String 15 | , nameError : Maybe String 16 | , location : String 17 | , locationError : Maybe String 18 | , age : String 19 | , ageError : Maybe String 20 | , bib : String 21 | , bibError : Maybe String 22 | , error : Maybe String 23 | } 24 | 25 | 26 | initModel : Model 27 | initModel = 28 | { id = "" 29 | , name = "" 30 | , nameError = Nothing 31 | , location = "" 32 | , locationError = Nothing 33 | , age = "" 34 | , ageError = Nothing 35 | , bib = "" 36 | , bibError = Nothing 37 | , error = Nothing 38 | } 39 | 40 | 41 | init : ( Model, Cmd Msg ) 42 | init = 43 | ( initModel, Cmd.none ) 44 | 45 | 46 | 47 | -- update 48 | 49 | 50 | type Msg 51 | = NameInput String 52 | | LocationInput String 53 | | AgeInput String 54 | | BibInput String 55 | | Save 56 | 57 | 58 | update : Msg -> Model -> ( Model, Cmd Msg ) 59 | update msg model = 60 | case msg of 61 | NameInput name -> 62 | ( { model 63 | | name = name 64 | , nameError = Nothing 65 | } 66 | , Cmd.none 67 | ) 68 | 69 | LocationInput location -> 70 | ( { model 71 | | location = location 72 | , locationError = Nothing 73 | } 74 | , Cmd.none 75 | ) 76 | 77 | AgeInput age -> 78 | ageInput model age 79 | 80 | BibInput bib -> 81 | bibInput model bib 82 | 83 | Save -> 84 | ( model, Cmd.none ) 85 | 86 | 87 | ageInput : Model -> String -> ( Model, Cmd Msg ) 88 | ageInput model age = 89 | let 90 | ageInt = 91 | age 92 | |> String.toInt 93 | |> Result.withDefault 0 94 | 95 | ageError = 96 | if ageInt <= 0 then 97 | Just "Must Enter a Positive Number" 98 | else 99 | Nothing 100 | in 101 | ( { model | age = age, ageError = ageError }, Cmd.none ) 102 | 103 | 104 | bibInput : Model -> String -> ( Model, Cmd Msg ) 105 | bibInput model bib = 106 | let 107 | bibInt = 108 | bib 109 | |> String.toInt 110 | |> Result.withDefault 0 111 | 112 | bibError = 113 | if bibInt <= 0 then 114 | Just "Must Enter a Positive Number" 115 | else 116 | Nothing 117 | in 118 | ( { model | bib = bib, bibError = bibError }, Cmd.none ) 119 | 120 | 121 | 122 | -- view 123 | 124 | 125 | view : Model -> Html Msg 126 | view model = 127 | div [ class "main" ] 128 | [ errorPanel model.error 129 | , viewForm model 130 | ] 131 | 132 | 133 | errorPanel : Maybe String -> Html a 134 | errorPanel error = 135 | case error of 136 | Nothing -> 137 | text "" 138 | 139 | Just msg -> 140 | div [ class "error" ] 141 | [ text msg 142 | ] 143 | 144 | 145 | viewForm : Model -> Html Msg 146 | viewForm model = 147 | Html.form [ class "add-runner", onSubmit Save ] 148 | [ fieldset [] 149 | [ legend [] [ text "Add / Edit Runner" ] 150 | , div [] 151 | [ label [] [ text "Name" ] 152 | , input 153 | [ type_ "text" 154 | , value model.name 155 | , onInput NameInput 156 | ] 157 | [] 158 | , span [] [ text <| Maybe.withDefault "" model.nameError ] 159 | ] 160 | , div [] 161 | [ label [] [ text "Location" ] 162 | , input 163 | [ type_ "text" 164 | , value model.location 165 | , onInput LocationInput 166 | ] 167 | [] 168 | , span [] [ text <| Maybe.withDefault "" model.locationError ] 169 | ] 170 | , div [] 171 | [ label [] [ text "Age" ] 172 | , input 173 | [ type_ "text" 174 | , value model.age 175 | , onInput AgeInput 176 | ] 177 | [] 178 | , span [] [ text <| Maybe.withDefault "" model.ageError ] 179 | ] 180 | , div [] 181 | [ label [] [ text "Bib #" ] 182 | , input 183 | [ type_ "text" 184 | , value model.bib 185 | , onInput BibInput 186 | ] 187 | [] 188 | , span [] [ text <| Maybe.withDefault "" model.bibError ] 189 | ] 190 | , div [] 191 | [ label [] [] 192 | , button [ type_ "submit" ] [ text "Save" ] 193 | ] 194 | ] 195 | ] 196 | 197 | 198 | 199 | -- subscriptions 200 | 201 | 202 | subscriptions : Model -> Sub Msg 203 | subscriptions model = 204 | Sub.none 205 | -------------------------------------------------------------------------------- /12RLBLockRunnerPage/src/Runner.elm: -------------------------------------------------------------------------------- 1 | module Runner exposing (..) 2 | 3 | import Html exposing (..) 4 | import Html.Events exposing (..) 5 | import Html.Attributes exposing (..) 6 | import String 7 | 8 | 9 | -- model 10 | 11 | 12 | type alias Model = 13 | { id : String 14 | , name : String 15 | , nameError : Maybe String 16 | , location : String 17 | , locationError : Maybe String 18 | , age : String 19 | , ageError : Maybe String 20 | , bib : String 21 | , bibError : Maybe String 22 | , error : Maybe String 23 | } 24 | 25 | 26 | initModel : Model 27 | initModel = 28 | { id = "" 29 | , name = "" 30 | , nameError = Nothing 31 | , location = "" 32 | , locationError = Nothing 33 | , age = "" 34 | , ageError = Nothing 35 | , bib = "" 36 | , bibError = Nothing 37 | , error = Nothing 38 | } 39 | 40 | 41 | init : ( Model, Cmd Msg ) 42 | init = 43 | ( initModel, Cmd.none ) 44 | 45 | 46 | 47 | -- update 48 | 49 | 50 | type Msg 51 | = NameInput String 52 | | LocationInput String 53 | | AgeInput String 54 | | BibInput String 55 | | Save 56 | 57 | 58 | update : Msg -> Model -> ( Model, Cmd Msg ) 59 | update msg model = 60 | case msg of 61 | NameInput name -> 62 | ( { model 63 | | name = name 64 | , nameError = Nothing 65 | } 66 | , Cmd.none 67 | ) 68 | 69 | LocationInput location -> 70 | ( { model 71 | | location = location 72 | , locationError = Nothing 73 | } 74 | , Cmd.none 75 | ) 76 | 77 | AgeInput age -> 78 | ageInput model age 79 | 80 | BibInput bib -> 81 | bibInput model bib 82 | 83 | Save -> 84 | ( model, Cmd.none ) 85 | 86 | 87 | ageInput : Model -> String -> ( Model, Cmd Msg ) 88 | ageInput model age = 89 | let 90 | ageInt = 91 | age 92 | |> String.toInt 93 | |> Result.withDefault 0 94 | 95 | ageError = 96 | if ageInt <= 0 then 97 | Just "Must Enter a Positive Number" 98 | else 99 | Nothing 100 | in 101 | ( { model | age = age, ageError = ageError }, Cmd.none ) 102 | 103 | 104 | bibInput : Model -> String -> ( Model, Cmd Msg ) 105 | bibInput model bib = 106 | let 107 | bibInt = 108 | bib 109 | |> String.toInt 110 | |> Result.withDefault 0 111 | 112 | bibError = 113 | if bibInt <= 0 then 114 | Just "Must Enter a Positive Number" 115 | else 116 | Nothing 117 | in 118 | ( { model | bib = bib, bibError = bibError }, Cmd.none ) 119 | 120 | 121 | 122 | -- view 123 | 124 | 125 | view : Model -> Html Msg 126 | view model = 127 | div [ class "main" ] 128 | [ errorPanel model.error 129 | , viewForm model 130 | ] 131 | 132 | 133 | errorPanel : Maybe String -> Html a 134 | errorPanel error = 135 | case error of 136 | Nothing -> 137 | text "" 138 | 139 | Just msg -> 140 | div [ class "error" ] 141 | [ text msg 142 | ] 143 | 144 | 145 | viewForm : Model -> Html Msg 146 | viewForm model = 147 | Html.form [ class "add-runner", onSubmit Save ] 148 | [ fieldset [] 149 | [ legend [] [ text "Add / Edit Runner" ] 150 | , div [] 151 | [ label [] [ text "Name" ] 152 | , input 153 | [ type_ "text" 154 | , value model.name 155 | , onInput NameInput 156 | ] 157 | [] 158 | , span [] [ text <| Maybe.withDefault "" model.nameError ] 159 | ] 160 | , div [] 161 | [ label [] [ text "Location" ] 162 | , input 163 | [ type_ "text" 164 | , value model.location 165 | , onInput LocationInput 166 | ] 167 | [] 168 | , span [] [ text <| Maybe.withDefault "" model.locationError ] 169 | ] 170 | , div [] 171 | [ label [] [ text "Age" ] 172 | , input 173 | [ type_ "text" 174 | , value model.age 175 | , onInput AgeInput 176 | ] 177 | [] 178 | , span [] [ text <| Maybe.withDefault "" model.ageError ] 179 | ] 180 | , div [] 181 | [ label [] [ text "Bib #" ] 182 | , input 183 | [ type_ "text" 184 | , value model.bib 185 | , onInput BibInput 186 | ] 187 | [] 188 | , span [] [ text <| Maybe.withDefault "" model.bibError ] 189 | ] 190 | , div [] 191 | [ label [] [] 192 | , button [ type_ "submit" ] [ text "Save" ] 193 | ] 194 | ] 195 | ] 196 | 197 | 198 | 199 | -- subscriptions 200 | 201 | 202 | subscriptions : Model -> Sub Msg 203 | subscriptions model = 204 | Sub.none 205 | -------------------------------------------------------------------------------- /08RLBNavigation/completed/src/Runner.elm: -------------------------------------------------------------------------------- 1 | module Runner exposing (..) 2 | 3 | import Html exposing (..) 4 | import Html.Events exposing (..) 5 | import Html.Attributes exposing (..) 6 | import String 7 | 8 | 9 | -- model 10 | 11 | 12 | type alias Model = 13 | { id : String 14 | , name : String 15 | , nameError : Maybe String 16 | , location : String 17 | , locationError : Maybe String 18 | , age : String 19 | , ageError : Maybe String 20 | , bib : String 21 | , bibError : Maybe String 22 | , error : Maybe String 23 | } 24 | 25 | 26 | initModel : Model 27 | initModel = 28 | { id = "" 29 | , name = "" 30 | , nameError = Nothing 31 | , location = "" 32 | , locationError = Nothing 33 | , age = "" 34 | , ageError = Nothing 35 | , bib = "" 36 | , bibError = Nothing 37 | , error = Nothing 38 | } 39 | 40 | 41 | init : ( Model, Cmd Msg ) 42 | init = 43 | ( initModel, Cmd.none ) 44 | 45 | 46 | 47 | -- update 48 | 49 | 50 | type Msg 51 | = NameInput String 52 | | LocationInput String 53 | | AgeInput String 54 | | BibInput String 55 | | Save 56 | 57 | 58 | update : Msg -> Model -> ( Model, Cmd Msg ) 59 | update msg model = 60 | case msg of 61 | NameInput name -> 62 | ( { model 63 | | name = name 64 | , nameError = Nothing 65 | } 66 | , Cmd.none 67 | ) 68 | 69 | LocationInput location -> 70 | ( { model 71 | | location = location 72 | , locationError = Nothing 73 | } 74 | , Cmd.none 75 | ) 76 | 77 | AgeInput age -> 78 | ageInput model age 79 | 80 | BibInput bib -> 81 | bibInput model bib 82 | 83 | Save -> 84 | ( model, Cmd.none ) 85 | 86 | 87 | ageInput : Model -> String -> ( Model, Cmd Msg ) 88 | ageInput model age = 89 | let 90 | ageInt = 91 | age 92 | |> String.toInt 93 | |> Result.withDefault 0 94 | 95 | ageError = 96 | if ageInt <= 0 then 97 | Just "Must Enter a Positive Number" 98 | else 99 | Nothing 100 | in 101 | ( { model | age = age, ageError = ageError }, Cmd.none ) 102 | 103 | 104 | bibInput : Model -> String -> ( Model, Cmd Msg ) 105 | bibInput model bib = 106 | let 107 | bibInt = 108 | bib 109 | |> String.toInt 110 | |> Result.withDefault 0 111 | 112 | bibError = 113 | if bibInt <= 0 then 114 | Just "Must Enter a Positive Number" 115 | else 116 | Nothing 117 | in 118 | ( { model | bib = bib, bibError = bibError }, Cmd.none ) 119 | 120 | 121 | 122 | -- view 123 | 124 | 125 | view : Model -> Html Msg 126 | view model = 127 | div [ class "main" ] 128 | [ errorPanel model.error 129 | , viewForm model 130 | ] 131 | 132 | 133 | errorPanel : Maybe String -> Html a 134 | errorPanel error = 135 | case error of 136 | Nothing -> 137 | text "" 138 | 139 | Just msg -> 140 | div [ class "error" ] 141 | [ text msg 142 | ] 143 | 144 | 145 | viewForm : Model -> Html Msg 146 | viewForm model = 147 | Html.form [ class "add-runner", onSubmit Save ] 148 | [ fieldset [] 149 | [ legend [] [ text "Add / Edit Runner" ] 150 | , div [] 151 | [ label [] [ text "Name" ] 152 | , input 153 | [ type_ "text" 154 | , value model.name 155 | , onInput NameInput 156 | ] 157 | [] 158 | , span [] [ text <| Maybe.withDefault "" model.nameError ] 159 | ] 160 | , div [] 161 | [ label [] [ text "Location" ] 162 | , input 163 | [ type_ "text" 164 | , value model.location 165 | , onInput LocationInput 166 | ] 167 | [] 168 | , span [] [ text <| Maybe.withDefault "" model.locationError ] 169 | ] 170 | , div [] 171 | [ label [] [ text "Age" ] 172 | , input 173 | [ type_ "text" 174 | , value model.age 175 | , onInput AgeInput 176 | ] 177 | [] 178 | , span [] [ text <| Maybe.withDefault "" model.ageError ] 179 | ] 180 | , div [] 181 | [ label [] [ text "Bib #" ] 182 | , input 183 | [ type_ "text" 184 | , value model.bib 185 | , onInput BibInput 186 | ] 187 | [] 188 | , span [] [ text <| Maybe.withDefault "" model.bibError ] 189 | ] 190 | , div [] 191 | [ label [] [] 192 | , button [ type_ "submit" ] [ text "Save" ] 193 | ] 194 | ] 195 | ] 196 | 197 | 198 | 199 | -- subscriptions 200 | 201 | 202 | subscriptions : Model -> Sub Msg 203 | subscriptions model = 204 | Sub.none 205 | --------------------------------------------------------------------------------