From 973a039b54327df74396605410ea9abe19c8a4e7 Mon Sep 17 00:00:00 2001
From: Joris
Date: Sun, 4 Sep 2016 21:21:11 +0200
Subject: Upgrade to elm 0.17.1
---
.gitignore | 3 +-
.tmuxinator.yml | 8 +
Makefile | 26 ++
alarm.wav | Bin 661032 -> 0 bytes
design/design.css | 171 -------
design/font-awesome/css/font-awesome.min.css | 4 -
design/font-awesome/fonts/FontAwesome.otf | Bin 85908 -> 0 bytes
design/font-awesome/fonts/fontawesome-webfont.eot | Bin 56006 -> 0 bytes
design/font-awesome/fonts/fontawesome-webfont.svg | 520 ---------------------
design/font-awesome/fonts/fontawesome-webfont.ttf | Bin 112160 -> 0 bytes
design/font-awesome/fonts/fontawesome-webfont.woff | Bin 65452 -> 0 bytes
design/reset.css | 68 ---
elm-package.json | 11 +-
gen | 2 -
images/icon.png | Bin 886 -> 0 bytes
index.html | 47 --
package.json | 6 +
public/alarm.wav | Bin 0 -> 661032 bytes
public/images/icon.png | Bin 0 -> 886 bytes
public/index.html | 40 ++
public/style/font-awesome/css/font-awesome.min.css | 4 +
public/style/font-awesome/fonts/FontAwesome.otf | Bin 0 -> 85908 bytes
.../font-awesome/fonts/fontawesome-webfont.eot | Bin 0 -> 56006 bytes
.../font-awesome/fonts/fontawesome-webfont.svg | 520 +++++++++++++++++++++
.../font-awesome/fonts/fontawesome-webfont.ttf | Bin 0 -> 112160 bytes
.../font-awesome/fonts/fontawesome-webfont.woff | Bin 0 -> 65452 bytes
public/style/main.css | 171 +++++++
public/style/reset.css | 68 +++
shell.nix | 15 +
src/Edition/Model.elm | 45 ++
src/Edition/Model/Name.elm | 19 +
src/Edition/Model/Time.elm | 52 +++
src/Edition/Msg.elm | 9 +
src/Edition/Update.elm | 30 ++
src/Main.elm | 72 +--
src/Model.elm | 40 ++
src/Model/Edition/Edition.elm | 44 --
src/Model/Edition/NameEdition.elm | 18 -
src/Model/Edition/TimeEdition.elm | 52 ---
src/Model/Id.elm | 4 +-
src/Model/IdGenerator.elm | 6 +-
src/Model/Keyboard.elm | 5 +
src/Model/Model.elm | 34 --
src/Model/Position.elm | 4 +-
src/Model/Timer.elm | 27 --
src/Model/TimerState.elm | 8 -
src/Msg.elm | 23 +
src/Ring.elm | 5 +
src/Timer/Model.elm | 27 ++
src/Timer/Model/State.elm | 8 +
src/Timer/Msg.elm | 13 +
src/Timer/Update.elm | 56 +++
src/Timer/View.elm | 175 +++++++
src/Update.elm | 141 ++++++
src/Update/Update.elm | 131 ------
src/Update/UpdateEdition.elm | 33 --
src/Update/UpdateTimer.elm | 57 ---
src/Utils/List.elm | 18 +-
src/Utils/Maybe.elm | 4 +-
src/View.elm | 56 +++
src/View/ActivatedClasses.elm | 15 -
src/View/Timer.elm | 171 -------
src/View/View.elm | 67 ---
63 files changed, 1605 insertions(+), 1548 deletions(-)
create mode 100644 .tmuxinator.yml
create mode 100644 Makefile
delete mode 100644 alarm.wav
delete mode 100644 design/design.css
delete mode 100644 design/font-awesome/css/font-awesome.min.css
delete mode 100644 design/font-awesome/fonts/FontAwesome.otf
delete mode 100644 design/font-awesome/fonts/fontawesome-webfont.eot
delete mode 100644 design/font-awesome/fonts/fontawesome-webfont.svg
delete mode 100644 design/font-awesome/fonts/fontawesome-webfont.ttf
delete mode 100644 design/font-awesome/fonts/fontawesome-webfont.woff
delete mode 100644 design/reset.css
delete mode 100755 gen
delete mode 100644 images/icon.png
delete mode 100644 index.html
create mode 100644 package.json
create mode 100644 public/alarm.wav
create mode 100644 public/images/icon.png
create mode 100644 public/index.html
create mode 100644 public/style/font-awesome/css/font-awesome.min.css
create mode 100644 public/style/font-awesome/fonts/FontAwesome.otf
create mode 100644 public/style/font-awesome/fonts/fontawesome-webfont.eot
create mode 100644 public/style/font-awesome/fonts/fontawesome-webfont.svg
create mode 100644 public/style/font-awesome/fonts/fontawesome-webfont.ttf
create mode 100644 public/style/font-awesome/fonts/fontawesome-webfont.woff
create mode 100644 public/style/main.css
create mode 100644 public/style/reset.css
create mode 100644 shell.nix
create mode 100644 src/Edition/Model.elm
create mode 100644 src/Edition/Model/Name.elm
create mode 100644 src/Edition/Model/Time.elm
create mode 100644 src/Edition/Msg.elm
create mode 100644 src/Edition/Update.elm
create mode 100644 src/Model.elm
delete mode 100644 src/Model/Edition/Edition.elm
delete mode 100644 src/Model/Edition/NameEdition.elm
delete mode 100644 src/Model/Edition/TimeEdition.elm
create mode 100644 src/Model/Keyboard.elm
delete mode 100644 src/Model/Model.elm
delete mode 100644 src/Model/Timer.elm
delete mode 100644 src/Model/TimerState.elm
create mode 100644 src/Msg.elm
create mode 100644 src/Ring.elm
create mode 100644 src/Timer/Model.elm
create mode 100644 src/Timer/Model/State.elm
create mode 100644 src/Timer/Msg.elm
create mode 100644 src/Timer/Update.elm
create mode 100644 src/Timer/View.elm
create mode 100644 src/Update.elm
delete mode 100644 src/Update/Update.elm
delete mode 100644 src/Update/UpdateEdition.elm
delete mode 100644 src/Update/UpdateTimer.elm
create mode 100644 src/View.elm
delete mode 100644 src/View/ActivatedClasses.elm
delete mode 100644 src/View/Timer.elm
delete mode 100644 src/View/View.elm
diff --git a/.gitignore b/.gitignore
index 3bd52a1..4f4679c 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,2 +1,3 @@
+node_modules
elm-stuff
-elm.js
+public/client.js
diff --git a/.tmuxinator.yml b/.tmuxinator.yml
new file mode 100644
index 0000000..2be1fda
--- /dev/null
+++ b/.tmuxinator.yml
@@ -0,0 +1,8 @@
+name: sharedCost
+
+windows:
+ - main:
+ layout: fff4,119x58,0,0{94x58,0,0,0,24x58,95,0,1}
+ panes:
+ - # Empty
+ - make install && make && make watch
diff --git a/Makefile b/Makefile
new file mode 100644
index 0000000..daea513
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,26 @@
+all: build
+
+clean:
+ @rm -r node_modules >/dev/null 2>&1 || true
+ @rm -r elm-stuff >/dev/null 2>&1 || true
+
+install:
+ @npm install
+ @elm package install
+
+watch: kill-server launch-server watch-client
+
+# Build and launch
+# ----------------
+
+kill-server:
+ @fuser -k 8080/tcp || true
+
+launch-server:
+ @./node_modules/http-server/bin/http-server ./public -p 8080 &
+
+build:
+ @elm make src/Main.elm --output public/client.js || true
+
+watch-client:
+ @./node_modules/nodemon/bin/nodemon.js --watch src -e elm --exec 'clear && make build --silent'
diff --git a/alarm.wav b/alarm.wav
deleted file mode 100644
index 41d6709..0000000
Binary files a/alarm.wav and /dev/null differ
diff --git a/design/design.css b/design/design.css
deleted file mode 100644
index 7602c7d..0000000
--- a/design/design.css
+++ /dev/null
@@ -1,171 +0,0 @@
-/**************/
-/* Header bar */
-/**************/
-
-.headerBar {
- background-color: #111111;
- font-size: 70px;
- box-shadow: 0px 2px 2px grey;
- min-width: 1020px;
- margin-bottom: 2px;
-}
-
-.headerBar > button {
- background-color: #111111;
- color: white;
- height: 150px;
- line-height: 150px;
- font-size: 70px;
- border: none;
- font-family: "DejaVu Serif";
- transition: color 0.4s ease;
-}
-
-.headerBar > button:focus {
- background-color: #222222;
-}
-
-.headerBar > button.title {
- letter-spacing: 12px;
- padding: 0 50px;
-}
-
-.headerBar > button.addTimer {
- float: right;
- padding: 0 50px;
-}
-
-.headerBar > button:hover,
-.headerBar > button:hover {
- color: #CCCC88;
- border-color: #CCCC88;
-}
-
-.headerBar > button {
- background-color: #111111;
- color: white;
- height: 150px;
- line-height: 150px;
- font-size: 70px;
- border: none;
- font-family: "DejaVu Serif";
- transition: color 0.4s ease;
-}
-
-.headerBar > button:focus {
- background-color: #222222;
-}
-
-.headerBar > button.title {
- letter-spacing: 12px;
- padding: 0 50px;
-}
-
-.headerBar > button.addTimer {
- float: right;
- padding: 0 50px;
-}
-
-.headerBar > button:hover,
-.headerBar > button:hover {
- color: #CCCC88;
- border-color: #CCCC88;
-}
-
-/**********/
-/* Timers */
-/**********/
-
-.timers {
- text-align: center;
- font-size: 30px;
- display: table;
- table-layout: auto;
- margin-left: auto;
- margin-right: auto;
- width: 1020px;
-}
-
-.timer {
- line-height: 140px;
- height: 140px;
- position: relative;
- display: table-row;
-}
-
-.timer:nth-child(even) {
- background-color: #FAFAFA;
-}
-
-.timer.isRinging:hover {
- background-color: #FED5AE;
-}
-
-.timer .name,
-.timer .time,
-.timer button {
- display: table-cell;
-}
-
-.timer button {
- background-color: rgba(0, 0, 0, 0);
- border: none;
- width: 140px;
- height: 140px;
- font-size: 35px;
- padding: 0px;
- position: relative;
-}
-
-.timer button.remove {
- color: #AA2222;
-}
-
-.timer:only-of-type button.remove {
- color: grey;
-}
-
-.timer .name {
- width: 400px;
- letter-spacing: 2px;
- cursor: text;
-}
-
-.timer .time {
- width: 200px;
- letter-spacing: 2px;
- cursor: text;
- border-radius: 0px;
-}
-
-.timer .progressBar {
- background-color: darkgrey;
- position: absolute;
- left: 0;
- top: 133px;
- height: 10px;
-}
-
-.timer.isRunning .progressBar {
- background-color: #CDE4C2;
-}
-
-.timer.isRinging .progressBar {
- background-color: #FED5AE;
-}
-
-.timer:hover.isRinging .progressBar {
- top: 0px;
- height: 143px;
- z-index: 1;
- opacity: 0;
- cursor: pointer;
-}
-
-.timer .edition.empty {
- color: #DDDDDD;
-}
-
-.timer .edition:not(.empty) {
- color: darkgrey;
-}
diff --git a/design/font-awesome/css/font-awesome.min.css b/design/font-awesome/css/font-awesome.min.css
deleted file mode 100644
index ec53d4d..0000000
--- a/design/font-awesome/css/font-awesome.min.css
+++ /dev/null
@@ -1,4 +0,0 @@
-/*!
- * Font Awesome 4.2.0 by @davegandy - http://fontawesome.io - @fontawesome
- * License - http://fontawesome.io/license (Font: SIL OFL 1.1, CSS: MIT License)
- */@font-face{font-family:'FontAwesome';src:url('../fonts/fontawesome-webfont.eot?v=4.2.0');src:url('../fonts/fontawesome-webfont.eot?#iefix&v=4.2.0') format('embedded-opentype'),url('../fonts/fontawesome-webfont.woff?v=4.2.0') format('woff'),url('../fonts/fontawesome-webfont.ttf?v=4.2.0') format('truetype'),url('../fonts/fontawesome-webfont.svg?v=4.2.0#fontawesomeregular') format('svg');font-weight:normal;font-style:normal}.fa{display:inline-block;font:normal normal normal 14px/1 FontAwesome;font-size:inherit;text-rendering:auto;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.fa-lg{font-size:1.33333333em;line-height:.75em;vertical-align:-15%}.fa-2x{font-size:2em}.fa-3x{font-size:3em}.fa-4x{font-size:4em}.fa-5x{font-size:5em}.fa-fw{width:1.28571429em;text-align:center}.fa-ul{padding-left:0;margin-left:2.14285714em;list-style-type:none}.fa-ul>li{position:relative}.fa-li{position:absolute;left:-2.14285714em;width:2.14285714em;top:.14285714em;text-align:center}.fa-li.fa-lg{left:-1.85714286em}.fa-border{padding:.2em .25em .15em;border:solid .08em #eee;border-radius:.1em}.pull-right{float:right}.pull-left{float:left}.fa.pull-left{margin-right:.3em}.fa.pull-right{margin-left:.3em}.fa-spin{-webkit-animation:fa-spin 2s infinite linear;animation:fa-spin 2s infinite linear}@-webkit-keyframes fa-spin{0%{-webkit-transform:rotate(0deg);transform:rotate(0deg)}100%{-webkit-transform:rotate(359deg);transform:rotate(359deg)}}@keyframes fa-spin{0%{-webkit-transform:rotate(0deg);transform:rotate(0deg)}100%{-webkit-transform:rotate(359deg);transform:rotate(359deg)}}.fa-rotate-90{filter:progid:DXImageTransform.Microsoft.BasicImage(rotation=1);-webkit-transform:rotate(90deg);-ms-transform:rotate(90deg);transform:rotate(90deg)}.fa-rotate-180{filter:progid:DXImageTransform.Microsoft.BasicImage(rotation=2);-webkit-transform:rotate(180deg);-ms-transform:rotate(180deg);transform:rotate(180deg)}.fa-rotate-270{filter:progid:DXImageTransform.Microsoft.BasicImage(rotation=3);-webkit-transform:rotate(270deg);-ms-transform:rotate(270deg);transform:rotate(270deg)}.fa-flip-horizontal{filter:progid:DXImageTransform.Microsoft.BasicImage(rotation=0, mirror=1);-webkit-transform:scale(-1, 1);-ms-transform:scale(-1, 1);transform:scale(-1, 1)}.fa-flip-vertical{filter:progid:DXImageTransform.Microsoft.BasicImage(rotation=2, mirror=1);-webkit-transform:scale(1, -1);-ms-transform:scale(1, -1);transform:scale(1, -1)}:root .fa-rotate-90,:root .fa-rotate-180,:root .fa-rotate-270,:root .fa-flip-horizontal,:root .fa-flip-vertical{filter:none}.fa-stack{position:relative;display:inline-block;width:2em;height:2em;line-height:2em;vertical-align:middle}.fa-stack-1x,.fa-stack-2x{position:absolute;left:0;width:100%;text-align:center}.fa-stack-1x{line-height:inherit}.fa-stack-2x{font-size:2em}.fa-inverse{color:#fff}.fa-glass:before{content:"\f000"}.fa-music:before{content:"\f001"}.fa-search:before{content:"\f002"}.fa-envelope-o:before{content:"\f003"}.fa-heart:before{content:"\f004"}.fa-star:before{content:"\f005"}.fa-star-o:before{content:"\f006"}.fa-user:before{content:"\f007"}.fa-film:before{content:"\f008"}.fa-th-large:before{content:"\f009"}.fa-th:before{content:"\f00a"}.fa-th-list:before{content:"\f00b"}.fa-check:before{content:"\f00c"}.fa-remove:before,.fa-close:before,.fa-times:before{content:"\f00d"}.fa-search-plus:before{content:"\f00e"}.fa-search-minus:before{content:"\f010"}.fa-power-off:before{content:"\f011"}.fa-signal:before{content:"\f012"}.fa-gear:before,.fa-cog:before{content:"\f013"}.fa-trash-o:before{content:"\f014"}.fa-home:before{content:"\f015"}.fa-file-o:before{content:"\f016"}.fa-clock-o:before{content:"\f017"}.fa-road:before{content:"\f018"}.fa-download:before{content:"\f019"}.fa-arrow-circle-o-down:before{content:"\f01a"}.fa-arrow-circle-o-up:before{content:"\f01b"}.fa-inbox:before{content:"\f01c"}.fa-play-circle-o:before{content:"\f01d"}.fa-rotate-right:before,.fa-repeat:before{content:"\f01e"}.fa-refresh:before{content:"\f021"}.fa-list-alt:before{content:"\f022"}.fa-lock:before{content:"\f023"}.fa-flag:before{content:"\f024"}.fa-headphones:before{content:"\f025"}.fa-volume-off:before{content:"\f026"}.fa-volume-down:before{content:"\f027"}.fa-volume-up:before{content:"\f028"}.fa-qrcode:before{content:"\f029"}.fa-barcode:before{content:"\f02a"}.fa-tag:before{content:"\f02b"}.fa-tags:before{content:"\f02c"}.fa-book:before{content:"\f02d"}.fa-bookmark:before{content:"\f02e"}.fa-print:before{content:"\f02f"}.fa-camera:before{content:"\f030"}.fa-font:before{content:"\f031"}.fa-bold:before{content:"\f032"}.fa-italic:before{content:"\f033"}.fa-text-height:before{content:"\f034"}.fa-text-width:before{content:"\f035"}.fa-align-left:before{content:"\f036"}.fa-align-center:before{content:"\f037"}.fa-align-right:before{content:"\f038"}.fa-align-justify:before{content:"\f039"}.fa-list:before{content:"\f03a"}.fa-dedent:before,.fa-outdent:before{content:"\f03b"}.fa-indent:before{content:"\f03c"}.fa-video-camera:before{content:"\f03d"}.fa-photo:before,.fa-image:before,.fa-picture-o:before{content:"\f03e"}.fa-pencil:before{content:"\f040"}.fa-map-marker:before{content:"\f041"}.fa-adjust:before{content:"\f042"}.fa-tint:before{content:"\f043"}.fa-edit:before,.fa-pencil-square-o:before{content:"\f044"}.fa-share-square-o:before{content:"\f045"}.fa-check-square-o:before{content:"\f046"}.fa-arrows:before{content:"\f047"}.fa-step-backward:before{content:"\f048"}.fa-fast-backward:before{content:"\f049"}.fa-backward:before{content:"\f04a"}.fa-play:before{content:"\f04b"}.fa-pause:before{content:"\f04c"}.fa-stop:before{content:"\f04d"}.fa-forward:before{content:"\f04e"}.fa-fast-forward:before{content:"\f050"}.fa-step-forward:before{content:"\f051"}.fa-eject:before{content:"\f052"}.fa-chevron-left:before{content:"\f053"}.fa-chevron-right:before{content:"\f054"}.fa-plus-circle:before{content:"\f055"}.fa-minus-circle:before{content:"\f056"}.fa-times-circle:before{content:"\f057"}.fa-check-circle:before{content:"\f058"}.fa-question-circle:before{content:"\f059"}.fa-info-circle:before{content:"\f05a"}.fa-crosshairs:before{content:"\f05b"}.fa-times-circle-o:before{content:"\f05c"}.fa-check-circle-o:before{content:"\f05d"}.fa-ban:before{content:"\f05e"}.fa-arrow-left:before{content:"\f060"}.fa-arrow-right:before{content:"\f061"}.fa-arrow-up:before{content:"\f062"}.fa-arrow-down:before{content:"\f063"}.fa-mail-forward:before,.fa-share:before{content:"\f064"}.fa-expand:before{content:"\f065"}.fa-compress:before{content:"\f066"}.fa-plus:before{content:"\f067"}.fa-minus:before{content:"\f068"}.fa-asterisk:before{content:"\f069"}.fa-exclamation-circle:before{content:"\f06a"}.fa-gift:before{content:"\f06b"}.fa-leaf:before{content:"\f06c"}.fa-fire:before{content:"\f06d"}.fa-eye:before{content:"\f06e"}.fa-eye-slash:before{content:"\f070"}.fa-warning:before,.fa-exclamation-triangle:before{content:"\f071"}.fa-plane:before{content:"\f072"}.fa-calendar:before{content:"\f073"}.fa-random:before{content:"\f074"}.fa-comment:before{content:"\f075"}.fa-magnet:before{content:"\f076"}.fa-chevron-up:before{content:"\f077"}.fa-chevron-down:before{content:"\f078"}.fa-retweet:before{content:"\f079"}.fa-shopping-cart:before{content:"\f07a"}.fa-folder:before{content:"\f07b"}.fa-folder-open:before{content:"\f07c"}.fa-arrows-v:before{content:"\f07d"}.fa-arrows-h:before{content:"\f07e"}.fa-bar-chart-o:before,.fa-bar-chart:before{content:"\f080"}.fa-twitter-square:before{content:"\f081"}.fa-facebook-square:before{content:"\f082"}.fa-camera-retro:before{content:"\f083"}.fa-key:before{content:"\f084"}.fa-gears:before,.fa-cogs:before{content:"\f085"}.fa-comments:before{content:"\f086"}.fa-thumbs-o-up:before{content:"\f087"}.fa-thumbs-o-down:before{content:"\f088"}.fa-star-half:before{content:"\f089"}.fa-heart-o:before{content:"\f08a"}.fa-sign-out:before{content:"\f08b"}.fa-linkedin-square:before{content:"\f08c"}.fa-thumb-tack:before{content:"\f08d"}.fa-external-link:before{content:"\f08e"}.fa-sign-in:before{content:"\f090"}.fa-trophy:before{content:"\f091"}.fa-github-square:before{content:"\f092"}.fa-upload:before{content:"\f093"}.fa-lemon-o:before{content:"\f094"}.fa-phone:before{content:"\f095"}.fa-square-o:before{content:"\f096"}.fa-bookmark-o:before{content:"\f097"}.fa-phone-square:before{content:"\f098"}.fa-twitter:before{content:"\f099"}.fa-facebook:before{content:"\f09a"}.fa-github:before{content:"\f09b"}.fa-unlock:before{content:"\f09c"}.fa-credit-card:before{content:"\f09d"}.fa-rss:before{content:"\f09e"}.fa-hdd-o:before{content:"\f0a0"}.fa-bullhorn:before{content:"\f0a1"}.fa-bell:before{content:"\f0f3"}.fa-certificate:before{content:"\f0a3"}.fa-hand-o-right:before{content:"\f0a4"}.fa-hand-o-left:before{content:"\f0a5"}.fa-hand-o-up:before{content:"\f0a6"}.fa-hand-o-down:before{content:"\f0a7"}.fa-arrow-circle-left:before{content:"\f0a8"}.fa-arrow-circle-right:before{content:"\f0a9"}.fa-arrow-circle-up:before{content:"\f0aa"}.fa-arrow-circle-down:before{content:"\f0ab"}.fa-globe:before{content:"\f0ac"}.fa-wrench:before{content:"\f0ad"}.fa-tasks:before{content:"\f0ae"}.fa-filter:before{content:"\f0b0"}.fa-briefcase:before{content:"\f0b1"}.fa-arrows-alt:before{content:"\f0b2"}.fa-group:before,.fa-users:before{content:"\f0c0"}.fa-chain:before,.fa-link:before{content:"\f0c1"}.fa-cloud:before{content:"\f0c2"}.fa-flask:before{content:"\f0c3"}.fa-cut:before,.fa-scissors:before{content:"\f0c4"}.fa-copy:before,.fa-files-o:before{content:"\f0c5"}.fa-paperclip:before{content:"\f0c6"}.fa-save:before,.fa-floppy-o:before{content:"\f0c7"}.fa-square:before{content:"\f0c8"}.fa-navicon:before,.fa-reorder:before,.fa-bars:before{content:"\f0c9"}.fa-list-ul:before{content:"\f0ca"}.fa-list-ol:before{content:"\f0cb"}.fa-strikethrough:before{content:"\f0cc"}.fa-underline:before{content:"\f0cd"}.fa-table:before{content:"\f0ce"}.fa-magic:before{content:"\f0d0"}.fa-truck:before{content:"\f0d1"}.fa-pinterest:before{content:"\f0d2"}.fa-pinterest-square:before{content:"\f0d3"}.fa-google-plus-square:before{content:"\f0d4"}.fa-google-plus:before{content:"\f0d5"}.fa-money:before{content:"\f0d6"}.fa-caret-down:before{content:"\f0d7"}.fa-caret-up:before{content:"\f0d8"}.fa-caret-left:before{content:"\f0d9"}.fa-caret-right:before{content:"\f0da"}.fa-columns:before{content:"\f0db"}.fa-unsorted:before,.fa-sort:before{content:"\f0dc"}.fa-sort-down:before,.fa-sort-desc:before{content:"\f0dd"}.fa-sort-up:before,.fa-sort-asc:before{content:"\f0de"}.fa-envelope:before{content:"\f0e0"}.fa-linkedin:before{content:"\f0e1"}.fa-rotate-left:before,.fa-undo:before{content:"\f0e2"}.fa-legal:before,.fa-gavel:before{content:"\f0e3"}.fa-dashboard:before,.fa-tachometer:before{content:"\f0e4"}.fa-comment-o:before{content:"\f0e5"}.fa-comments-o:before{content:"\f0e6"}.fa-flash:before,.fa-bolt:before{content:"\f0e7"}.fa-sitemap:before{content:"\f0e8"}.fa-umbrella:before{content:"\f0e9"}.fa-paste:before,.fa-clipboard:before{content:"\f0ea"}.fa-lightbulb-o:before{content:"\f0eb"}.fa-exchange:before{content:"\f0ec"}.fa-cloud-download:before{content:"\f0ed"}.fa-cloud-upload:before{content:"\f0ee"}.fa-user-md:before{content:"\f0f0"}.fa-stethoscope:before{content:"\f0f1"}.fa-suitcase:before{content:"\f0f2"}.fa-bell-o:before{content:"\f0a2"}.fa-coffee:before{content:"\f0f4"}.fa-cutlery:before{content:"\f0f5"}.fa-file-text-o:before{content:"\f0f6"}.fa-building-o:before{content:"\f0f7"}.fa-hospital-o:before{content:"\f0f8"}.fa-ambulance:before{content:"\f0f9"}.fa-medkit:before{content:"\f0fa"}.fa-fighter-jet:before{content:"\f0fb"}.fa-beer:before{content:"\f0fc"}.fa-h-square:before{content:"\f0fd"}.fa-plus-square:before{content:"\f0fe"}.fa-angle-double-left:before{content:"\f100"}.fa-angle-double-right:before{content:"\f101"}.fa-angle-double-up:before{content:"\f102"}.fa-angle-double-down:before{content:"\f103"}.fa-angle-left:before{content:"\f104"}.fa-angle-right:before{content:"\f105"}.fa-angle-up:before{content:"\f106"}.fa-angle-down:before{content:"\f107"}.fa-desktop:before{content:"\f108"}.fa-laptop:before{content:"\f109"}.fa-tablet:before{content:"\f10a"}.fa-mobile-phone:before,.fa-mobile:before{content:"\f10b"}.fa-circle-o:before{content:"\f10c"}.fa-quote-left:before{content:"\f10d"}.fa-quote-right:before{content:"\f10e"}.fa-spinner:before{content:"\f110"}.fa-circle:before{content:"\f111"}.fa-mail-reply:before,.fa-reply:before{content:"\f112"}.fa-github-alt:before{content:"\f113"}.fa-folder-o:before{content:"\f114"}.fa-folder-open-o:before{content:"\f115"}.fa-smile-o:before{content:"\f118"}.fa-frown-o:before{content:"\f119"}.fa-meh-o:before{content:"\f11a"}.fa-gamepad:before{content:"\f11b"}.fa-keyboard-o:before{content:"\f11c"}.fa-flag-o:before{content:"\f11d"}.fa-flag-checkered:before{content:"\f11e"}.fa-terminal:before{content:"\f120"}.fa-code:before{content:"\f121"}.fa-mail-reply-all:before,.fa-reply-all:before{content:"\f122"}.fa-star-half-empty:before,.fa-star-half-full:before,.fa-star-half-o:before{content:"\f123"}.fa-location-arrow:before{content:"\f124"}.fa-crop:before{content:"\f125"}.fa-code-fork:before{content:"\f126"}.fa-unlink:before,.fa-chain-broken:before{content:"\f127"}.fa-question:before{content:"\f128"}.fa-info:before{content:"\f129"}.fa-exclamation:before{content:"\f12a"}.fa-superscript:before{content:"\f12b"}.fa-subscript:before{content:"\f12c"}.fa-eraser:before{content:"\f12d"}.fa-puzzle-piece:before{content:"\f12e"}.fa-microphone:before{content:"\f130"}.fa-microphone-slash:before{content:"\f131"}.fa-shield:before{content:"\f132"}.fa-calendar-o:before{content:"\f133"}.fa-fire-extinguisher:before{content:"\f134"}.fa-rocket:before{content:"\f135"}.fa-maxcdn:before{content:"\f136"}.fa-chevron-circle-left:before{content:"\f137"}.fa-chevron-circle-right:before{content:"\f138"}.fa-chevron-circle-up:before{content:"\f139"}.fa-chevron-circle-down:before{content:"\f13a"}.fa-html5:before{content:"\f13b"}.fa-css3:before{content:"\f13c"}.fa-anchor:before{content:"\f13d"}.fa-unlock-alt:before{content:"\f13e"}.fa-bullseye:before{content:"\f140"}.fa-ellipsis-h:before{content:"\f141"}.fa-ellipsis-v:before{content:"\f142"}.fa-rss-square:before{content:"\f143"}.fa-play-circle:before{content:"\f144"}.fa-ticket:before{content:"\f145"}.fa-minus-square:before{content:"\f146"}.fa-minus-square-o:before{content:"\f147"}.fa-level-up:before{content:"\f148"}.fa-level-down:before{content:"\f149"}.fa-check-square:before{content:"\f14a"}.fa-pencil-square:before{content:"\f14b"}.fa-external-link-square:before{content:"\f14c"}.fa-share-square:before{content:"\f14d"}.fa-compass:before{content:"\f14e"}.fa-toggle-down:before,.fa-caret-square-o-down:before{content:"\f150"}.fa-toggle-up:before,.fa-caret-square-o-up:before{content:"\f151"}.fa-toggle-right:before,.fa-caret-square-o-right:before{content:"\f152"}.fa-euro:before,.fa-eur:before{content:"\f153"}.fa-gbp:before{content:"\f154"}.fa-dollar:before,.fa-usd:before{content:"\f155"}.fa-rupee:before,.fa-inr:before{content:"\f156"}.fa-cny:before,.fa-rmb:before,.fa-yen:before,.fa-jpy:before{content:"\f157"}.fa-ruble:before,.fa-rouble:before,.fa-rub:before{content:"\f158"}.fa-won:before,.fa-krw:before{content:"\f159"}.fa-bitcoin:before,.fa-btc:before{content:"\f15a"}.fa-file:before{content:"\f15b"}.fa-file-text:before{content:"\f15c"}.fa-sort-alpha-asc:before{content:"\f15d"}.fa-sort-alpha-desc:before{content:"\f15e"}.fa-sort-amount-asc:before{content:"\f160"}.fa-sort-amount-desc:before{content:"\f161"}.fa-sort-numeric-asc:before{content:"\f162"}.fa-sort-numeric-desc:before{content:"\f163"}.fa-thumbs-up:before{content:"\f164"}.fa-thumbs-down:before{content:"\f165"}.fa-youtube-square:before{content:"\f166"}.fa-youtube:before{content:"\f167"}.fa-xing:before{content:"\f168"}.fa-xing-square:before{content:"\f169"}.fa-youtube-play:before{content:"\f16a"}.fa-dropbox:before{content:"\f16b"}.fa-stack-overflow:before{content:"\f16c"}.fa-instagram:before{content:"\f16d"}.fa-flickr:before{content:"\f16e"}.fa-adn:before{content:"\f170"}.fa-bitbucket:before{content:"\f171"}.fa-bitbucket-square:before{content:"\f172"}.fa-tumblr:before{content:"\f173"}.fa-tumblr-square:before{content:"\f174"}.fa-long-arrow-down:before{content:"\f175"}.fa-long-arrow-up:before{content:"\f176"}.fa-long-arrow-left:before{content:"\f177"}.fa-long-arrow-right:before{content:"\f178"}.fa-apple:before{content:"\f179"}.fa-windows:before{content:"\f17a"}.fa-android:before{content:"\f17b"}.fa-linux:before{content:"\f17c"}.fa-dribbble:before{content:"\f17d"}.fa-skype:before{content:"\f17e"}.fa-foursquare:before{content:"\f180"}.fa-trello:before{content:"\f181"}.fa-female:before{content:"\f182"}.fa-male:before{content:"\f183"}.fa-gittip:before{content:"\f184"}.fa-sun-o:before{content:"\f185"}.fa-moon-o:before{content:"\f186"}.fa-archive:before{content:"\f187"}.fa-bug:before{content:"\f188"}.fa-vk:before{content:"\f189"}.fa-weibo:before{content:"\f18a"}.fa-renren:before{content:"\f18b"}.fa-pagelines:before{content:"\f18c"}.fa-stack-exchange:before{content:"\f18d"}.fa-arrow-circle-o-right:before{content:"\f18e"}.fa-arrow-circle-o-left:before{content:"\f190"}.fa-toggle-left:before,.fa-caret-square-o-left:before{content:"\f191"}.fa-dot-circle-o:before{content:"\f192"}.fa-wheelchair:before{content:"\f193"}.fa-vimeo-square:before{content:"\f194"}.fa-turkish-lira:before,.fa-try:before{content:"\f195"}.fa-plus-square-o:before{content:"\f196"}.fa-space-shuttle:before{content:"\f197"}.fa-slack:before{content:"\f198"}.fa-envelope-square:before{content:"\f199"}.fa-wordpress:before{content:"\f19a"}.fa-openid:before{content:"\f19b"}.fa-institution:before,.fa-bank:before,.fa-university:before{content:"\f19c"}.fa-mortar-board:before,.fa-graduation-cap:before{content:"\f19d"}.fa-yahoo:before{content:"\f19e"}.fa-google:before{content:"\f1a0"}.fa-reddit:before{content:"\f1a1"}.fa-reddit-square:before{content:"\f1a2"}.fa-stumbleupon-circle:before{content:"\f1a3"}.fa-stumbleupon:before{content:"\f1a4"}.fa-delicious:before{content:"\f1a5"}.fa-digg:before{content:"\f1a6"}.fa-pied-piper:before{content:"\f1a7"}.fa-pied-piper-alt:before{content:"\f1a8"}.fa-drupal:before{content:"\f1a9"}.fa-joomla:before{content:"\f1aa"}.fa-language:before{content:"\f1ab"}.fa-fax:before{content:"\f1ac"}.fa-building:before{content:"\f1ad"}.fa-child:before{content:"\f1ae"}.fa-paw:before{content:"\f1b0"}.fa-spoon:before{content:"\f1b1"}.fa-cube:before{content:"\f1b2"}.fa-cubes:before{content:"\f1b3"}.fa-behance:before{content:"\f1b4"}.fa-behance-square:before{content:"\f1b5"}.fa-steam:before{content:"\f1b6"}.fa-steam-square:before{content:"\f1b7"}.fa-recycle:before{content:"\f1b8"}.fa-automobile:before,.fa-car:before{content:"\f1b9"}.fa-cab:before,.fa-taxi:before{content:"\f1ba"}.fa-tree:before{content:"\f1bb"}.fa-spotify:before{content:"\f1bc"}.fa-deviantart:before{content:"\f1bd"}.fa-soundcloud:before{content:"\f1be"}.fa-database:before{content:"\f1c0"}.fa-file-pdf-o:before{content:"\f1c1"}.fa-file-word-o:before{content:"\f1c2"}.fa-file-excel-o:before{content:"\f1c3"}.fa-file-powerpoint-o:before{content:"\f1c4"}.fa-file-photo-o:before,.fa-file-picture-o:before,.fa-file-image-o:before{content:"\f1c5"}.fa-file-zip-o:before,.fa-file-archive-o:before{content:"\f1c6"}.fa-file-sound-o:before,.fa-file-audio-o:before{content:"\f1c7"}.fa-file-movie-o:before,.fa-file-video-o:before{content:"\f1c8"}.fa-file-code-o:before{content:"\f1c9"}.fa-vine:before{content:"\f1ca"}.fa-codepen:before{content:"\f1cb"}.fa-jsfiddle:before{content:"\f1cc"}.fa-life-bouy:before,.fa-life-buoy:before,.fa-life-saver:before,.fa-support:before,.fa-life-ring:before{content:"\f1cd"}.fa-circle-o-notch:before{content:"\f1ce"}.fa-ra:before,.fa-rebel:before{content:"\f1d0"}.fa-ge:before,.fa-empire:before{content:"\f1d1"}.fa-git-square:before{content:"\f1d2"}.fa-git:before{content:"\f1d3"}.fa-hacker-news:before{content:"\f1d4"}.fa-tencent-weibo:before{content:"\f1d5"}.fa-qq:before{content:"\f1d6"}.fa-wechat:before,.fa-weixin:before{content:"\f1d7"}.fa-send:before,.fa-paper-plane:before{content:"\f1d8"}.fa-send-o:before,.fa-paper-plane-o:before{content:"\f1d9"}.fa-history:before{content:"\f1da"}.fa-circle-thin:before{content:"\f1db"}.fa-header:before{content:"\f1dc"}.fa-paragraph:before{content:"\f1dd"}.fa-sliders:before{content:"\f1de"}.fa-share-alt:before{content:"\f1e0"}.fa-share-alt-square:before{content:"\f1e1"}.fa-bomb:before{content:"\f1e2"}.fa-soccer-ball-o:before,.fa-futbol-o:before{content:"\f1e3"}.fa-tty:before{content:"\f1e4"}.fa-binoculars:before{content:"\f1e5"}.fa-plug:before{content:"\f1e6"}.fa-slideshare:before{content:"\f1e7"}.fa-twitch:before{content:"\f1e8"}.fa-yelp:before{content:"\f1e9"}.fa-newspaper-o:before{content:"\f1ea"}.fa-wifi:before{content:"\f1eb"}.fa-calculator:before{content:"\f1ec"}.fa-paypal:before{content:"\f1ed"}.fa-google-wallet:before{content:"\f1ee"}.fa-cc-visa:before{content:"\f1f0"}.fa-cc-mastercard:before{content:"\f1f1"}.fa-cc-discover:before{content:"\f1f2"}.fa-cc-amex:before{content:"\f1f3"}.fa-cc-paypal:before{content:"\f1f4"}.fa-cc-stripe:before{content:"\f1f5"}.fa-bell-slash:before{content:"\f1f6"}.fa-bell-slash-o:before{content:"\f1f7"}.fa-trash:before{content:"\f1f8"}.fa-copyright:before{content:"\f1f9"}.fa-at:before{content:"\f1fa"}.fa-eyedropper:before{content:"\f1fb"}.fa-paint-brush:before{content:"\f1fc"}.fa-birthday-cake:before{content:"\f1fd"}.fa-area-chart:before{content:"\f1fe"}.fa-pie-chart:before{content:"\f200"}.fa-line-chart:before{content:"\f201"}.fa-lastfm:before{content:"\f202"}.fa-lastfm-square:before{content:"\f203"}.fa-toggle-off:before{content:"\f204"}.fa-toggle-on:before{content:"\f205"}.fa-bicycle:before{content:"\f206"}.fa-bus:before{content:"\f207"}.fa-ioxhost:before{content:"\f208"}.fa-angellist:before{content:"\f209"}.fa-cc:before{content:"\f20a"}.fa-shekel:before,.fa-sheqel:before,.fa-ils:before{content:"\f20b"}.fa-meanpath:before{content:"\f20c"}
\ No newline at end of file
diff --git a/design/font-awesome/fonts/FontAwesome.otf b/design/font-awesome/fonts/FontAwesome.otf
deleted file mode 100644
index 81c9ad9..0000000
Binary files a/design/font-awesome/fonts/FontAwesome.otf and /dev/null differ
diff --git a/design/font-awesome/fonts/fontawesome-webfont.eot b/design/font-awesome/fonts/fontawesome-webfont.eot
deleted file mode 100644
index 84677bc..0000000
Binary files a/design/font-awesome/fonts/fontawesome-webfont.eot and /dev/null differ
diff --git a/design/font-awesome/fonts/fontawesome-webfont.svg b/design/font-awesome/fonts/fontawesome-webfont.svg
deleted file mode 100644
index d907b25..0000000
--- a/design/font-awesome/fonts/fontawesome-webfont.svg
+++ /dev/null
@@ -1,520 +0,0 @@
-
-
-
\ No newline at end of file
diff --git a/design/font-awesome/fonts/fontawesome-webfont.ttf b/design/font-awesome/fonts/fontawesome-webfont.ttf
deleted file mode 100644
index 96a3639..0000000
Binary files a/design/font-awesome/fonts/fontawesome-webfont.ttf and /dev/null differ
diff --git a/design/font-awesome/fonts/fontawesome-webfont.woff b/design/font-awesome/fonts/fontawesome-webfont.woff
deleted file mode 100644
index 628b6a5..0000000
Binary files a/design/font-awesome/fonts/fontawesome-webfont.woff and /dev/null differ
diff --git a/design/reset.css b/design/reset.css
deleted file mode 100644
index 58fedc2..0000000
--- a/design/reset.css
+++ /dev/null
@@ -1,68 +0,0 @@
-/* http://meyerweb.com/eric/tools/css/reset/
- v2.0 | 20110126
- License: none (public domain)
-*/
-
-html, body, div, span, applet, object, iframe,
-h1, h2, h3, h4, h5, h6, p, blockquote, pre,
-a, abbr, acronym, address, big, cite, code,
-del, dfn, em, img, ins, kbd, q, s, samp,
-small, strike, strong, sub, sup, tt, var,
-b, u, i, center,
-dl, dt, dd, ol, ul, li,
-fieldset, form, label, legend,
-table, caption, tbody, tfoot, thead, tr, th, td,
-article, aside, canvas, details, embed,
-figure, figcaption, footer, header, hgroup,
-menu, nav, output, ruby, section, summary,
-time, mark, audio, video {
- margin: 0;
- padding: 0;
- border: 0;
- font-size: 100%;
- font: inherit;
- vertical-align: baseline;
-}
-/* HTML5 display-role reset for older browsers */
-article, aside, details, figcaption, figure,
-footer, header, hgroup, menu, nav, section {
- display: block;
-}
-body {
- line-height: 1;
-}
-ol, ul {
- list-style: none;
-}
-blockquote, q {
- quotes: none;
-}
-blockquote:before, blockquote:after,
-q:before, q:after {
- content: '';
- content: none;
-}
-table {
- border-collapse: collapse;
- border-spacing: 0;
-}
-
-html {
- box-sizing: border-box;
-}
-*, *:before, *:after {
- box-sizing: inherit;
-}
-
-button {
- cursor: pointer;
- box-sizing: border-box;
-}
-
-button::-moz-focus-inner {
- border: 0;
-}
-
-button:focus {
- outline: 0;
-}
diff --git a/elm-package.json b/elm-package.json
index 995d8e9..4d64f3b 100644
--- a/elm-package.json
+++ b/elm-package.json
@@ -1,14 +1,13 @@
{
- "version": "0.0.1",
- "summary": "",
- "description": "",
+ "version": "1.0.0",
+ "summary": "timer",
"repository": "https://github.com/guyonvarch/timer.git",
"license": "BSD3",
"source-directories": ["src"],
"exposed-modules": [],
- "elm-version": "0.15.0 <= v < 0.16.0",
+ "elm-version": "0.17.1 <= v < 0.18.0",
"dependencies": {
- "elm-lang/core": "2.0.1 <= v < 3.0.0",
- "evancz/elm-html": "3.0.0 <= v < 4.0.0"
+ "elm-lang/core": "4.0.5 <= v < 5.0.0",
+ "elm-lang/html": "1.1.0 <= v < 2.0.0"
}
}
diff --git a/gen b/gen
deleted file mode 100755
index e1d94dc..0000000
--- a/gen
+++ /dev/null
@@ -1,2 +0,0 @@
-#!/bin/bash
-elm-make src/Main.elm --output elm.js
diff --git a/images/icon.png b/images/icon.png
deleted file mode 100644
index a489112..0000000
Binary files a/images/icon.png and /dev/null differ
diff --git a/index.html b/index.html
deleted file mode 100644
index f5f825e..0000000
--- a/index.html
+++ /dev/null
@@ -1,47 +0,0 @@
-
-
-
-
-
- Timer
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/package.json b/package.json
new file mode 100644
index 0000000..ba7eb37
--- /dev/null
+++ b/package.json
@@ -0,0 +1,6 @@
+{
+ "devDependencies": {
+ "nodemon": "1.9.1",
+ "http-server": "0.8.5"
+ }
+}
diff --git a/public/alarm.wav b/public/alarm.wav
new file mode 100644
index 0000000..41d6709
Binary files /dev/null and b/public/alarm.wav differ
diff --git a/public/images/icon.png b/public/images/icon.png
new file mode 100644
index 0000000..a489112
Binary files /dev/null and b/public/images/icon.png differ
diff --git a/public/index.html b/public/index.html
new file mode 100644
index 0000000..44749fc
--- /dev/null
+++ b/public/index.html
@@ -0,0 +1,40 @@
+
+
+
+ Timer
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/public/style/font-awesome/css/font-awesome.min.css b/public/style/font-awesome/css/font-awesome.min.css
new file mode 100644
index 0000000..ec53d4d
--- /dev/null
+++ b/public/style/font-awesome/css/font-awesome.min.css
@@ -0,0 +1,4 @@
+/*!
+ * Font Awesome 4.2.0 by @davegandy - http://fontawesome.io - @fontawesome
+ * License - http://fontawesome.io/license (Font: SIL OFL 1.1, CSS: MIT License)
+ */@font-face{font-family:'FontAwesome';src:url('../fonts/fontawesome-webfont.eot?v=4.2.0');src:url('../fonts/fontawesome-webfont.eot?#iefix&v=4.2.0') format('embedded-opentype'),url('../fonts/fontawesome-webfont.woff?v=4.2.0') format('woff'),url('../fonts/fontawesome-webfont.ttf?v=4.2.0') format('truetype'),url('../fonts/fontawesome-webfont.svg?v=4.2.0#fontawesomeregular') format('svg');font-weight:normal;font-style:normal}.fa{display:inline-block;font:normal normal normal 14px/1 FontAwesome;font-size:inherit;text-rendering:auto;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.fa-lg{font-size:1.33333333em;line-height:.75em;vertical-align:-15%}.fa-2x{font-size:2em}.fa-3x{font-size:3em}.fa-4x{font-size:4em}.fa-5x{font-size:5em}.fa-fw{width:1.28571429em;text-align:center}.fa-ul{padding-left:0;margin-left:2.14285714em;list-style-type:none}.fa-ul>li{position:relative}.fa-li{position:absolute;left:-2.14285714em;width:2.14285714em;top:.14285714em;text-align:center}.fa-li.fa-lg{left:-1.85714286em}.fa-border{padding:.2em .25em .15em;border:solid .08em #eee;border-radius:.1em}.pull-right{float:right}.pull-left{float:left}.fa.pull-left{margin-right:.3em}.fa.pull-right{margin-left:.3em}.fa-spin{-webkit-animation:fa-spin 2s infinite linear;animation:fa-spin 2s infinite linear}@-webkit-keyframes fa-spin{0%{-webkit-transform:rotate(0deg);transform:rotate(0deg)}100%{-webkit-transform:rotate(359deg);transform:rotate(359deg)}}@keyframes fa-spin{0%{-webkit-transform:rotate(0deg);transform:rotate(0deg)}100%{-webkit-transform:rotate(359deg);transform:rotate(359deg)}}.fa-rotate-90{filter:progid:DXImageTransform.Microsoft.BasicImage(rotation=1);-webkit-transform:rotate(90deg);-ms-transform:rotate(90deg);transform:rotate(90deg)}.fa-rotate-180{filter:progid:DXImageTransform.Microsoft.BasicImage(rotation=2);-webkit-transform:rotate(180deg);-ms-transform:rotate(180deg);transform:rotate(180deg)}.fa-rotate-270{filter:progid:DXImageTransform.Microsoft.BasicImage(rotation=3);-webkit-transform:rotate(270deg);-ms-transform:rotate(270deg);transform:rotate(270deg)}.fa-flip-horizontal{filter:progid:DXImageTransform.Microsoft.BasicImage(rotation=0, mirror=1);-webkit-transform:scale(-1, 1);-ms-transform:scale(-1, 1);transform:scale(-1, 1)}.fa-flip-vertical{filter:progid:DXImageTransform.Microsoft.BasicImage(rotation=2, mirror=1);-webkit-transform:scale(1, -1);-ms-transform:scale(1, -1);transform:scale(1, -1)}:root .fa-rotate-90,:root .fa-rotate-180,:root .fa-rotate-270,:root .fa-flip-horizontal,:root .fa-flip-vertical{filter:none}.fa-stack{position:relative;display:inline-block;width:2em;height:2em;line-height:2em;vertical-align:middle}.fa-stack-1x,.fa-stack-2x{position:absolute;left:0;width:100%;text-align:center}.fa-stack-1x{line-height:inherit}.fa-stack-2x{font-size:2em}.fa-inverse{color:#fff}.fa-glass:before{content:"\f000"}.fa-music:before{content:"\f001"}.fa-search:before{content:"\f002"}.fa-envelope-o:before{content:"\f003"}.fa-heart:before{content:"\f004"}.fa-star:before{content:"\f005"}.fa-star-o:before{content:"\f006"}.fa-user:before{content:"\f007"}.fa-film:before{content:"\f008"}.fa-th-large:before{content:"\f009"}.fa-th:before{content:"\f00a"}.fa-th-list:before{content:"\f00b"}.fa-check:before{content:"\f00c"}.fa-remove:before,.fa-close:before,.fa-times:before{content:"\f00d"}.fa-search-plus:before{content:"\f00e"}.fa-search-minus:before{content:"\f010"}.fa-power-off:before{content:"\f011"}.fa-signal:before{content:"\f012"}.fa-gear:before,.fa-cog:before{content:"\f013"}.fa-trash-o:before{content:"\f014"}.fa-home:before{content:"\f015"}.fa-file-o:before{content:"\f016"}.fa-clock-o:before{content:"\f017"}.fa-road:before{content:"\f018"}.fa-download:before{content:"\f019"}.fa-arrow-circle-o-down:before{content:"\f01a"}.fa-arrow-circle-o-up:before{content:"\f01b"}.fa-inbox:before{content:"\f01c"}.fa-play-circle-o:before{content:"\f01d"}.fa-rotate-right:before,.fa-repeat:before{content:"\f01e"}.fa-refresh:before{content:"\f021"}.fa-list-alt:before{content:"\f022"}.fa-lock:before{content:"\f023"}.fa-flag:before{content:"\f024"}.fa-headphones:before{content:"\f025"}.fa-volume-off:before{content:"\f026"}.fa-volume-down:before{content:"\f027"}.fa-volume-up:before{content:"\f028"}.fa-qrcode:before{content:"\f029"}.fa-barcode:before{content:"\f02a"}.fa-tag:before{content:"\f02b"}.fa-tags:before{content:"\f02c"}.fa-book:before{content:"\f02d"}.fa-bookmark:before{content:"\f02e"}.fa-print:before{content:"\f02f"}.fa-camera:before{content:"\f030"}.fa-font:before{content:"\f031"}.fa-bold:before{content:"\f032"}.fa-italic:before{content:"\f033"}.fa-text-height:before{content:"\f034"}.fa-text-width:before{content:"\f035"}.fa-align-left:before{content:"\f036"}.fa-align-center:before{content:"\f037"}.fa-align-right:before{content:"\f038"}.fa-align-justify:before{content:"\f039"}.fa-list:before{content:"\f03a"}.fa-dedent:before,.fa-outdent:before{content:"\f03b"}.fa-indent:before{content:"\f03c"}.fa-video-camera:before{content:"\f03d"}.fa-photo:before,.fa-image:before,.fa-picture-o:before{content:"\f03e"}.fa-pencil:before{content:"\f040"}.fa-map-marker:before{content:"\f041"}.fa-adjust:before{content:"\f042"}.fa-tint:before{content:"\f043"}.fa-edit:before,.fa-pencil-square-o:before{content:"\f044"}.fa-share-square-o:before{content:"\f045"}.fa-check-square-o:before{content:"\f046"}.fa-arrows:before{content:"\f047"}.fa-step-backward:before{content:"\f048"}.fa-fast-backward:before{content:"\f049"}.fa-backward:before{content:"\f04a"}.fa-play:before{content:"\f04b"}.fa-pause:before{content:"\f04c"}.fa-stop:before{content:"\f04d"}.fa-forward:before{content:"\f04e"}.fa-fast-forward:before{content:"\f050"}.fa-step-forward:before{content:"\f051"}.fa-eject:before{content:"\f052"}.fa-chevron-left:before{content:"\f053"}.fa-chevron-right:before{content:"\f054"}.fa-plus-circle:before{content:"\f055"}.fa-minus-circle:before{content:"\f056"}.fa-times-circle:before{content:"\f057"}.fa-check-circle:before{content:"\f058"}.fa-question-circle:before{content:"\f059"}.fa-info-circle:before{content:"\f05a"}.fa-crosshairs:before{content:"\f05b"}.fa-times-circle-o:before{content:"\f05c"}.fa-check-circle-o:before{content:"\f05d"}.fa-ban:before{content:"\f05e"}.fa-arrow-left:before{content:"\f060"}.fa-arrow-right:before{content:"\f061"}.fa-arrow-up:before{content:"\f062"}.fa-arrow-down:before{content:"\f063"}.fa-mail-forward:before,.fa-share:before{content:"\f064"}.fa-expand:before{content:"\f065"}.fa-compress:before{content:"\f066"}.fa-plus:before{content:"\f067"}.fa-minus:before{content:"\f068"}.fa-asterisk:before{content:"\f069"}.fa-exclamation-circle:before{content:"\f06a"}.fa-gift:before{content:"\f06b"}.fa-leaf:before{content:"\f06c"}.fa-fire:before{content:"\f06d"}.fa-eye:before{content:"\f06e"}.fa-eye-slash:before{content:"\f070"}.fa-warning:before,.fa-exclamation-triangle:before{content:"\f071"}.fa-plane:before{content:"\f072"}.fa-calendar:before{content:"\f073"}.fa-random:before{content:"\f074"}.fa-comment:before{content:"\f075"}.fa-magnet:before{content:"\f076"}.fa-chevron-up:before{content:"\f077"}.fa-chevron-down:before{content:"\f078"}.fa-retweet:before{content:"\f079"}.fa-shopping-cart:before{content:"\f07a"}.fa-folder:before{content:"\f07b"}.fa-folder-open:before{content:"\f07c"}.fa-arrows-v:before{content:"\f07d"}.fa-arrows-h:before{content:"\f07e"}.fa-bar-chart-o:before,.fa-bar-chart:before{content:"\f080"}.fa-twitter-square:before{content:"\f081"}.fa-facebook-square:before{content:"\f082"}.fa-camera-retro:before{content:"\f083"}.fa-key:before{content:"\f084"}.fa-gears:before,.fa-cogs:before{content:"\f085"}.fa-comments:before{content:"\f086"}.fa-thumbs-o-up:before{content:"\f087"}.fa-thumbs-o-down:before{content:"\f088"}.fa-star-half:before{content:"\f089"}.fa-heart-o:before{content:"\f08a"}.fa-sign-out:before{content:"\f08b"}.fa-linkedin-square:before{content:"\f08c"}.fa-thumb-tack:before{content:"\f08d"}.fa-external-link:before{content:"\f08e"}.fa-sign-in:before{content:"\f090"}.fa-trophy:before{content:"\f091"}.fa-github-square:before{content:"\f092"}.fa-upload:before{content:"\f093"}.fa-lemon-o:before{content:"\f094"}.fa-phone:before{content:"\f095"}.fa-square-o:before{content:"\f096"}.fa-bookmark-o:before{content:"\f097"}.fa-phone-square:before{content:"\f098"}.fa-twitter:before{content:"\f099"}.fa-facebook:before{content:"\f09a"}.fa-github:before{content:"\f09b"}.fa-unlock:before{content:"\f09c"}.fa-credit-card:before{content:"\f09d"}.fa-rss:before{content:"\f09e"}.fa-hdd-o:before{content:"\f0a0"}.fa-bullhorn:before{content:"\f0a1"}.fa-bell:before{content:"\f0f3"}.fa-certificate:before{content:"\f0a3"}.fa-hand-o-right:before{content:"\f0a4"}.fa-hand-o-left:before{content:"\f0a5"}.fa-hand-o-up:before{content:"\f0a6"}.fa-hand-o-down:before{content:"\f0a7"}.fa-arrow-circle-left:before{content:"\f0a8"}.fa-arrow-circle-right:before{content:"\f0a9"}.fa-arrow-circle-up:before{content:"\f0aa"}.fa-arrow-circle-down:before{content:"\f0ab"}.fa-globe:before{content:"\f0ac"}.fa-wrench:before{content:"\f0ad"}.fa-tasks:before{content:"\f0ae"}.fa-filter:before{content:"\f0b0"}.fa-briefcase:before{content:"\f0b1"}.fa-arrows-alt:before{content:"\f0b2"}.fa-group:before,.fa-users:before{content:"\f0c0"}.fa-chain:before,.fa-link:before{content:"\f0c1"}.fa-cloud:before{content:"\f0c2"}.fa-flask:before{content:"\f0c3"}.fa-cut:before,.fa-scissors:before{content:"\f0c4"}.fa-copy:before,.fa-files-o:before{content:"\f0c5"}.fa-paperclip:before{content:"\f0c6"}.fa-save:before,.fa-floppy-o:before{content:"\f0c7"}.fa-square:before{content:"\f0c8"}.fa-navicon:before,.fa-reorder:before,.fa-bars:before{content:"\f0c9"}.fa-list-ul:before{content:"\f0ca"}.fa-list-ol:before{content:"\f0cb"}.fa-strikethrough:before{content:"\f0cc"}.fa-underline:before{content:"\f0cd"}.fa-table:before{content:"\f0ce"}.fa-magic:before{content:"\f0d0"}.fa-truck:before{content:"\f0d1"}.fa-pinterest:before{content:"\f0d2"}.fa-pinterest-square:before{content:"\f0d3"}.fa-google-plus-square:before{content:"\f0d4"}.fa-google-plus:before{content:"\f0d5"}.fa-money:before{content:"\f0d6"}.fa-caret-down:before{content:"\f0d7"}.fa-caret-up:before{content:"\f0d8"}.fa-caret-left:before{content:"\f0d9"}.fa-caret-right:before{content:"\f0da"}.fa-columns:before{content:"\f0db"}.fa-unsorted:before,.fa-sort:before{content:"\f0dc"}.fa-sort-down:before,.fa-sort-desc:before{content:"\f0dd"}.fa-sort-up:before,.fa-sort-asc:before{content:"\f0de"}.fa-envelope:before{content:"\f0e0"}.fa-linkedin:before{content:"\f0e1"}.fa-rotate-left:before,.fa-undo:before{content:"\f0e2"}.fa-legal:before,.fa-gavel:before{content:"\f0e3"}.fa-dashboard:before,.fa-tachometer:before{content:"\f0e4"}.fa-comment-o:before{content:"\f0e5"}.fa-comments-o:before{content:"\f0e6"}.fa-flash:before,.fa-bolt:before{content:"\f0e7"}.fa-sitemap:before{content:"\f0e8"}.fa-umbrella:before{content:"\f0e9"}.fa-paste:before,.fa-clipboard:before{content:"\f0ea"}.fa-lightbulb-o:before{content:"\f0eb"}.fa-exchange:before{content:"\f0ec"}.fa-cloud-download:before{content:"\f0ed"}.fa-cloud-upload:before{content:"\f0ee"}.fa-user-md:before{content:"\f0f0"}.fa-stethoscope:before{content:"\f0f1"}.fa-suitcase:before{content:"\f0f2"}.fa-bell-o:before{content:"\f0a2"}.fa-coffee:before{content:"\f0f4"}.fa-cutlery:before{content:"\f0f5"}.fa-file-text-o:before{content:"\f0f6"}.fa-building-o:before{content:"\f0f7"}.fa-hospital-o:before{content:"\f0f8"}.fa-ambulance:before{content:"\f0f9"}.fa-medkit:before{content:"\f0fa"}.fa-fighter-jet:before{content:"\f0fb"}.fa-beer:before{content:"\f0fc"}.fa-h-square:before{content:"\f0fd"}.fa-plus-square:before{content:"\f0fe"}.fa-angle-double-left:before{content:"\f100"}.fa-angle-double-right:before{content:"\f101"}.fa-angle-double-up:before{content:"\f102"}.fa-angle-double-down:before{content:"\f103"}.fa-angle-left:before{content:"\f104"}.fa-angle-right:before{content:"\f105"}.fa-angle-up:before{content:"\f106"}.fa-angle-down:before{content:"\f107"}.fa-desktop:before{content:"\f108"}.fa-laptop:before{content:"\f109"}.fa-tablet:before{content:"\f10a"}.fa-mobile-phone:before,.fa-mobile:before{content:"\f10b"}.fa-circle-o:before{content:"\f10c"}.fa-quote-left:before{content:"\f10d"}.fa-quote-right:before{content:"\f10e"}.fa-spinner:before{content:"\f110"}.fa-circle:before{content:"\f111"}.fa-mail-reply:before,.fa-reply:before{content:"\f112"}.fa-github-alt:before{content:"\f113"}.fa-folder-o:before{content:"\f114"}.fa-folder-open-o:before{content:"\f115"}.fa-smile-o:before{content:"\f118"}.fa-frown-o:before{content:"\f119"}.fa-meh-o:before{content:"\f11a"}.fa-gamepad:before{content:"\f11b"}.fa-keyboard-o:before{content:"\f11c"}.fa-flag-o:before{content:"\f11d"}.fa-flag-checkered:before{content:"\f11e"}.fa-terminal:before{content:"\f120"}.fa-code:before{content:"\f121"}.fa-mail-reply-all:before,.fa-reply-all:before{content:"\f122"}.fa-star-half-empty:before,.fa-star-half-full:before,.fa-star-half-o:before{content:"\f123"}.fa-location-arrow:before{content:"\f124"}.fa-crop:before{content:"\f125"}.fa-code-fork:before{content:"\f126"}.fa-unlink:before,.fa-chain-broken:before{content:"\f127"}.fa-question:before{content:"\f128"}.fa-info:before{content:"\f129"}.fa-exclamation:before{content:"\f12a"}.fa-superscript:before{content:"\f12b"}.fa-subscript:before{content:"\f12c"}.fa-eraser:before{content:"\f12d"}.fa-puzzle-piece:before{content:"\f12e"}.fa-microphone:before{content:"\f130"}.fa-microphone-slash:before{content:"\f131"}.fa-shield:before{content:"\f132"}.fa-calendar-o:before{content:"\f133"}.fa-fire-extinguisher:before{content:"\f134"}.fa-rocket:before{content:"\f135"}.fa-maxcdn:before{content:"\f136"}.fa-chevron-circle-left:before{content:"\f137"}.fa-chevron-circle-right:before{content:"\f138"}.fa-chevron-circle-up:before{content:"\f139"}.fa-chevron-circle-down:before{content:"\f13a"}.fa-html5:before{content:"\f13b"}.fa-css3:before{content:"\f13c"}.fa-anchor:before{content:"\f13d"}.fa-unlock-alt:before{content:"\f13e"}.fa-bullseye:before{content:"\f140"}.fa-ellipsis-h:before{content:"\f141"}.fa-ellipsis-v:before{content:"\f142"}.fa-rss-square:before{content:"\f143"}.fa-play-circle:before{content:"\f144"}.fa-ticket:before{content:"\f145"}.fa-minus-square:before{content:"\f146"}.fa-minus-square-o:before{content:"\f147"}.fa-level-up:before{content:"\f148"}.fa-level-down:before{content:"\f149"}.fa-check-square:before{content:"\f14a"}.fa-pencil-square:before{content:"\f14b"}.fa-external-link-square:before{content:"\f14c"}.fa-share-square:before{content:"\f14d"}.fa-compass:before{content:"\f14e"}.fa-toggle-down:before,.fa-caret-square-o-down:before{content:"\f150"}.fa-toggle-up:before,.fa-caret-square-o-up:before{content:"\f151"}.fa-toggle-right:before,.fa-caret-square-o-right:before{content:"\f152"}.fa-euro:before,.fa-eur:before{content:"\f153"}.fa-gbp:before{content:"\f154"}.fa-dollar:before,.fa-usd:before{content:"\f155"}.fa-rupee:before,.fa-inr:before{content:"\f156"}.fa-cny:before,.fa-rmb:before,.fa-yen:before,.fa-jpy:before{content:"\f157"}.fa-ruble:before,.fa-rouble:before,.fa-rub:before{content:"\f158"}.fa-won:before,.fa-krw:before{content:"\f159"}.fa-bitcoin:before,.fa-btc:before{content:"\f15a"}.fa-file:before{content:"\f15b"}.fa-file-text:before{content:"\f15c"}.fa-sort-alpha-asc:before{content:"\f15d"}.fa-sort-alpha-desc:before{content:"\f15e"}.fa-sort-amount-asc:before{content:"\f160"}.fa-sort-amount-desc:before{content:"\f161"}.fa-sort-numeric-asc:before{content:"\f162"}.fa-sort-numeric-desc:before{content:"\f163"}.fa-thumbs-up:before{content:"\f164"}.fa-thumbs-down:before{content:"\f165"}.fa-youtube-square:before{content:"\f166"}.fa-youtube:before{content:"\f167"}.fa-xing:before{content:"\f168"}.fa-xing-square:before{content:"\f169"}.fa-youtube-play:before{content:"\f16a"}.fa-dropbox:before{content:"\f16b"}.fa-stack-overflow:before{content:"\f16c"}.fa-instagram:before{content:"\f16d"}.fa-flickr:before{content:"\f16e"}.fa-adn:before{content:"\f170"}.fa-bitbucket:before{content:"\f171"}.fa-bitbucket-square:before{content:"\f172"}.fa-tumblr:before{content:"\f173"}.fa-tumblr-square:before{content:"\f174"}.fa-long-arrow-down:before{content:"\f175"}.fa-long-arrow-up:before{content:"\f176"}.fa-long-arrow-left:before{content:"\f177"}.fa-long-arrow-right:before{content:"\f178"}.fa-apple:before{content:"\f179"}.fa-windows:before{content:"\f17a"}.fa-android:before{content:"\f17b"}.fa-linux:before{content:"\f17c"}.fa-dribbble:before{content:"\f17d"}.fa-skype:before{content:"\f17e"}.fa-foursquare:before{content:"\f180"}.fa-trello:before{content:"\f181"}.fa-female:before{content:"\f182"}.fa-male:before{content:"\f183"}.fa-gittip:before{content:"\f184"}.fa-sun-o:before{content:"\f185"}.fa-moon-o:before{content:"\f186"}.fa-archive:before{content:"\f187"}.fa-bug:before{content:"\f188"}.fa-vk:before{content:"\f189"}.fa-weibo:before{content:"\f18a"}.fa-renren:before{content:"\f18b"}.fa-pagelines:before{content:"\f18c"}.fa-stack-exchange:before{content:"\f18d"}.fa-arrow-circle-o-right:before{content:"\f18e"}.fa-arrow-circle-o-left:before{content:"\f190"}.fa-toggle-left:before,.fa-caret-square-o-left:before{content:"\f191"}.fa-dot-circle-o:before{content:"\f192"}.fa-wheelchair:before{content:"\f193"}.fa-vimeo-square:before{content:"\f194"}.fa-turkish-lira:before,.fa-try:before{content:"\f195"}.fa-plus-square-o:before{content:"\f196"}.fa-space-shuttle:before{content:"\f197"}.fa-slack:before{content:"\f198"}.fa-envelope-square:before{content:"\f199"}.fa-wordpress:before{content:"\f19a"}.fa-openid:before{content:"\f19b"}.fa-institution:before,.fa-bank:before,.fa-university:before{content:"\f19c"}.fa-mortar-board:before,.fa-graduation-cap:before{content:"\f19d"}.fa-yahoo:before{content:"\f19e"}.fa-google:before{content:"\f1a0"}.fa-reddit:before{content:"\f1a1"}.fa-reddit-square:before{content:"\f1a2"}.fa-stumbleupon-circle:before{content:"\f1a3"}.fa-stumbleupon:before{content:"\f1a4"}.fa-delicious:before{content:"\f1a5"}.fa-digg:before{content:"\f1a6"}.fa-pied-piper:before{content:"\f1a7"}.fa-pied-piper-alt:before{content:"\f1a8"}.fa-drupal:before{content:"\f1a9"}.fa-joomla:before{content:"\f1aa"}.fa-language:before{content:"\f1ab"}.fa-fax:before{content:"\f1ac"}.fa-building:before{content:"\f1ad"}.fa-child:before{content:"\f1ae"}.fa-paw:before{content:"\f1b0"}.fa-spoon:before{content:"\f1b1"}.fa-cube:before{content:"\f1b2"}.fa-cubes:before{content:"\f1b3"}.fa-behance:before{content:"\f1b4"}.fa-behance-square:before{content:"\f1b5"}.fa-steam:before{content:"\f1b6"}.fa-steam-square:before{content:"\f1b7"}.fa-recycle:before{content:"\f1b8"}.fa-automobile:before,.fa-car:before{content:"\f1b9"}.fa-cab:before,.fa-taxi:before{content:"\f1ba"}.fa-tree:before{content:"\f1bb"}.fa-spotify:before{content:"\f1bc"}.fa-deviantart:before{content:"\f1bd"}.fa-soundcloud:before{content:"\f1be"}.fa-database:before{content:"\f1c0"}.fa-file-pdf-o:before{content:"\f1c1"}.fa-file-word-o:before{content:"\f1c2"}.fa-file-excel-o:before{content:"\f1c3"}.fa-file-powerpoint-o:before{content:"\f1c4"}.fa-file-photo-o:before,.fa-file-picture-o:before,.fa-file-image-o:before{content:"\f1c5"}.fa-file-zip-o:before,.fa-file-archive-o:before{content:"\f1c6"}.fa-file-sound-o:before,.fa-file-audio-o:before{content:"\f1c7"}.fa-file-movie-o:before,.fa-file-video-o:before{content:"\f1c8"}.fa-file-code-o:before{content:"\f1c9"}.fa-vine:before{content:"\f1ca"}.fa-codepen:before{content:"\f1cb"}.fa-jsfiddle:before{content:"\f1cc"}.fa-life-bouy:before,.fa-life-buoy:before,.fa-life-saver:before,.fa-support:before,.fa-life-ring:before{content:"\f1cd"}.fa-circle-o-notch:before{content:"\f1ce"}.fa-ra:before,.fa-rebel:before{content:"\f1d0"}.fa-ge:before,.fa-empire:before{content:"\f1d1"}.fa-git-square:before{content:"\f1d2"}.fa-git:before{content:"\f1d3"}.fa-hacker-news:before{content:"\f1d4"}.fa-tencent-weibo:before{content:"\f1d5"}.fa-qq:before{content:"\f1d6"}.fa-wechat:before,.fa-weixin:before{content:"\f1d7"}.fa-send:before,.fa-paper-plane:before{content:"\f1d8"}.fa-send-o:before,.fa-paper-plane-o:before{content:"\f1d9"}.fa-history:before{content:"\f1da"}.fa-circle-thin:before{content:"\f1db"}.fa-header:before{content:"\f1dc"}.fa-paragraph:before{content:"\f1dd"}.fa-sliders:before{content:"\f1de"}.fa-share-alt:before{content:"\f1e0"}.fa-share-alt-square:before{content:"\f1e1"}.fa-bomb:before{content:"\f1e2"}.fa-soccer-ball-o:before,.fa-futbol-o:before{content:"\f1e3"}.fa-tty:before{content:"\f1e4"}.fa-binoculars:before{content:"\f1e5"}.fa-plug:before{content:"\f1e6"}.fa-slideshare:before{content:"\f1e7"}.fa-twitch:before{content:"\f1e8"}.fa-yelp:before{content:"\f1e9"}.fa-newspaper-o:before{content:"\f1ea"}.fa-wifi:before{content:"\f1eb"}.fa-calculator:before{content:"\f1ec"}.fa-paypal:before{content:"\f1ed"}.fa-google-wallet:before{content:"\f1ee"}.fa-cc-visa:before{content:"\f1f0"}.fa-cc-mastercard:before{content:"\f1f1"}.fa-cc-discover:before{content:"\f1f2"}.fa-cc-amex:before{content:"\f1f3"}.fa-cc-paypal:before{content:"\f1f4"}.fa-cc-stripe:before{content:"\f1f5"}.fa-bell-slash:before{content:"\f1f6"}.fa-bell-slash-o:before{content:"\f1f7"}.fa-trash:before{content:"\f1f8"}.fa-copyright:before{content:"\f1f9"}.fa-at:before{content:"\f1fa"}.fa-eyedropper:before{content:"\f1fb"}.fa-paint-brush:before{content:"\f1fc"}.fa-birthday-cake:before{content:"\f1fd"}.fa-area-chart:before{content:"\f1fe"}.fa-pie-chart:before{content:"\f200"}.fa-line-chart:before{content:"\f201"}.fa-lastfm:before{content:"\f202"}.fa-lastfm-square:before{content:"\f203"}.fa-toggle-off:before{content:"\f204"}.fa-toggle-on:before{content:"\f205"}.fa-bicycle:before{content:"\f206"}.fa-bus:before{content:"\f207"}.fa-ioxhost:before{content:"\f208"}.fa-angellist:before{content:"\f209"}.fa-cc:before{content:"\f20a"}.fa-shekel:before,.fa-sheqel:before,.fa-ils:before{content:"\f20b"}.fa-meanpath:before{content:"\f20c"}
\ No newline at end of file
diff --git a/public/style/font-awesome/fonts/FontAwesome.otf b/public/style/font-awesome/fonts/FontAwesome.otf
new file mode 100644
index 0000000..81c9ad9
Binary files /dev/null and b/public/style/font-awesome/fonts/FontAwesome.otf differ
diff --git a/public/style/font-awesome/fonts/fontawesome-webfont.eot b/public/style/font-awesome/fonts/fontawesome-webfont.eot
new file mode 100644
index 0000000..84677bc
Binary files /dev/null and b/public/style/font-awesome/fonts/fontawesome-webfont.eot differ
diff --git a/public/style/font-awesome/fonts/fontawesome-webfont.svg b/public/style/font-awesome/fonts/fontawesome-webfont.svg
new file mode 100644
index 0000000..d907b25
--- /dev/null
+++ b/public/style/font-awesome/fonts/fontawesome-webfont.svg
@@ -0,0 +1,520 @@
+
+
+
\ No newline at end of file
diff --git a/public/style/font-awesome/fonts/fontawesome-webfont.ttf b/public/style/font-awesome/fonts/fontawesome-webfont.ttf
new file mode 100644
index 0000000..96a3639
Binary files /dev/null and b/public/style/font-awesome/fonts/fontawesome-webfont.ttf differ
diff --git a/public/style/font-awesome/fonts/fontawesome-webfont.woff b/public/style/font-awesome/fonts/fontawesome-webfont.woff
new file mode 100644
index 0000000..628b6a5
Binary files /dev/null and b/public/style/font-awesome/fonts/fontawesome-webfont.woff differ
diff --git a/public/style/main.css b/public/style/main.css
new file mode 100644
index 0000000..7602c7d
--- /dev/null
+++ b/public/style/main.css
@@ -0,0 +1,171 @@
+/**************/
+/* Header bar */
+/**************/
+
+.headerBar {
+ background-color: #111111;
+ font-size: 70px;
+ box-shadow: 0px 2px 2px grey;
+ min-width: 1020px;
+ margin-bottom: 2px;
+}
+
+.headerBar > button {
+ background-color: #111111;
+ color: white;
+ height: 150px;
+ line-height: 150px;
+ font-size: 70px;
+ border: none;
+ font-family: "DejaVu Serif";
+ transition: color 0.4s ease;
+}
+
+.headerBar > button:focus {
+ background-color: #222222;
+}
+
+.headerBar > button.title {
+ letter-spacing: 12px;
+ padding: 0 50px;
+}
+
+.headerBar > button.addTimer {
+ float: right;
+ padding: 0 50px;
+}
+
+.headerBar > button:hover,
+.headerBar > button:hover {
+ color: #CCCC88;
+ border-color: #CCCC88;
+}
+
+.headerBar > button {
+ background-color: #111111;
+ color: white;
+ height: 150px;
+ line-height: 150px;
+ font-size: 70px;
+ border: none;
+ font-family: "DejaVu Serif";
+ transition: color 0.4s ease;
+}
+
+.headerBar > button:focus {
+ background-color: #222222;
+}
+
+.headerBar > button.title {
+ letter-spacing: 12px;
+ padding: 0 50px;
+}
+
+.headerBar > button.addTimer {
+ float: right;
+ padding: 0 50px;
+}
+
+.headerBar > button:hover,
+.headerBar > button:hover {
+ color: #CCCC88;
+ border-color: #CCCC88;
+}
+
+/**********/
+/* Timers */
+/**********/
+
+.timers {
+ text-align: center;
+ font-size: 30px;
+ display: table;
+ table-layout: auto;
+ margin-left: auto;
+ margin-right: auto;
+ width: 1020px;
+}
+
+.timer {
+ line-height: 140px;
+ height: 140px;
+ position: relative;
+ display: table-row;
+}
+
+.timer:nth-child(even) {
+ background-color: #FAFAFA;
+}
+
+.timer.isRinging:hover {
+ background-color: #FED5AE;
+}
+
+.timer .name,
+.timer .time,
+.timer button {
+ display: table-cell;
+}
+
+.timer button {
+ background-color: rgba(0, 0, 0, 0);
+ border: none;
+ width: 140px;
+ height: 140px;
+ font-size: 35px;
+ padding: 0px;
+ position: relative;
+}
+
+.timer button.remove {
+ color: #AA2222;
+}
+
+.timer:only-of-type button.remove {
+ color: grey;
+}
+
+.timer .name {
+ width: 400px;
+ letter-spacing: 2px;
+ cursor: text;
+}
+
+.timer .time {
+ width: 200px;
+ letter-spacing: 2px;
+ cursor: text;
+ border-radius: 0px;
+}
+
+.timer .progressBar {
+ background-color: darkgrey;
+ position: absolute;
+ left: 0;
+ top: 133px;
+ height: 10px;
+}
+
+.timer.isRunning .progressBar {
+ background-color: #CDE4C2;
+}
+
+.timer.isRinging .progressBar {
+ background-color: #FED5AE;
+}
+
+.timer:hover.isRinging .progressBar {
+ top: 0px;
+ height: 143px;
+ z-index: 1;
+ opacity: 0;
+ cursor: pointer;
+}
+
+.timer .edition.empty {
+ color: #DDDDDD;
+}
+
+.timer .edition:not(.empty) {
+ color: darkgrey;
+}
diff --git a/public/style/reset.css b/public/style/reset.css
new file mode 100644
index 0000000..58fedc2
--- /dev/null
+++ b/public/style/reset.css
@@ -0,0 +1,68 @@
+/* http://meyerweb.com/eric/tools/css/reset/
+ v2.0 | 20110126
+ License: none (public domain)
+*/
+
+html, body, div, span, applet, object, iframe,
+h1, h2, h3, h4, h5, h6, p, blockquote, pre,
+a, abbr, acronym, address, big, cite, code,
+del, dfn, em, img, ins, kbd, q, s, samp,
+small, strike, strong, sub, sup, tt, var,
+b, u, i, center,
+dl, dt, dd, ol, ul, li,
+fieldset, form, label, legend,
+table, caption, tbody, tfoot, thead, tr, th, td,
+article, aside, canvas, details, embed,
+figure, figcaption, footer, header, hgroup,
+menu, nav, output, ruby, section, summary,
+time, mark, audio, video {
+ margin: 0;
+ padding: 0;
+ border: 0;
+ font-size: 100%;
+ font: inherit;
+ vertical-align: baseline;
+}
+/* HTML5 display-role reset for older browsers */
+article, aside, details, figcaption, figure,
+footer, header, hgroup, menu, nav, section {
+ display: block;
+}
+body {
+ line-height: 1;
+}
+ol, ul {
+ list-style: none;
+}
+blockquote, q {
+ quotes: none;
+}
+blockquote:before, blockquote:after,
+q:before, q:after {
+ content: '';
+ content: none;
+}
+table {
+ border-collapse: collapse;
+ border-spacing: 0;
+}
+
+html {
+ box-sizing: border-box;
+}
+*, *:before, *:after {
+ box-sizing: inherit;
+}
+
+button {
+ cursor: pointer;
+ box-sizing: border-box;
+}
+
+button::-moz-focus-inner {
+ border: 0;
+}
+
+button:focus {
+ outline: 0;
+}
diff --git a/shell.nix b/shell.nix
new file mode 100644
index 0000000..d3365c2
--- /dev/null
+++ b/shell.nix
@@ -0,0 +1,15 @@
+with import {}; {
+ env = stdenv.mkDerivation {
+ name = "env";
+ buildInputs = [
+ elmPackages.elm
+ nodejs
+ tmux
+ tmuxinator
+ ];
+ shellHook = ''
+ tmux kill-session -t timer >/dev/null 2>&1
+ tmuxinator local
+ '';
+ };
+}
diff --git a/src/Edition/Model.elm b/src/Edition/Model.elm
new file mode 100644
index 0000000..5c1b295
--- /dev/null
+++ b/src/Edition/Model.elm
@@ -0,0 +1,45 @@
+module Edition.Model exposing
+ ( Edition
+ , Kind(..)
+ , newEdition
+ , keyCodeToChar
+ , isEmpty
+ )
+
+import String
+
+import Model.Id exposing (..)
+import Model.Keyboard exposing (KeyCode)
+
+import Edition.Model.Name as NameEdition
+import Edition.Model.Time as TimeEdition
+
+type alias Edition =
+ { id : Id
+ , kind : Kind
+ , chars : List Char
+ }
+
+type Kind =
+ Name
+ | Time
+
+newEdition id kind =
+ { id = id
+ , kind = kind
+ , chars = []
+ }
+
+keyCodeToChar : Kind -> KeyCode -> Maybe Char
+keyCodeToChar kind =
+ case kind of
+ Name -> NameEdition.keyCodeToChar
+ Time -> TimeEdition.keyCodeToChar
+
+isEmpty : Edition -> Bool
+isEmpty edition =
+ edition.chars
+ |> String.fromList
+ |> String.trim
+ |> String.length
+ |> (==) 0
diff --git a/src/Edition/Model/Name.elm b/src/Edition/Model/Name.elm
new file mode 100644
index 0000000..19f4c04
--- /dev/null
+++ b/src/Edition/Model/Name.elm
@@ -0,0 +1,19 @@
+module Edition.Model.Name exposing
+ ( keyCodeToChar
+ , renderNameEdition
+ )
+
+import Char
+import String
+import List
+
+import Model.Keyboard exposing (KeyCode)
+
+keyCodeToChar : KeyCode -> Maybe Char
+keyCodeToChar = Just << Char.fromCode
+
+renderNameEdition : List Char -> String
+renderNameEdition chars =
+ chars
+ |> List.reverse
+ |> String.fromList
diff --git a/src/Edition/Model/Time.elm b/src/Edition/Model/Time.elm
new file mode 100644
index 0000000..35971c3
--- /dev/null
+++ b/src/Edition/Model/Time.elm
@@ -0,0 +1,52 @@
+module Edition.Model.Time exposing
+ ( keyCodeToChar
+ , toTime
+ , toMinutesAndSeconds
+ )
+
+import Time exposing (Time)
+import List
+import Array
+import String
+import Char
+
+import Model.Keyboard exposing (KeyCode)
+import Utils.List exposing (..)
+import Utils.Maybe exposing (..)
+
+keyCodeToChar : KeyCode -> Maybe Char
+keyCodeToChar code =
+ let char = Char.fromCode code
+ in if Char.isDigit char
+ then Just char
+ else Nothing
+
+toTime : List Char -> Time
+toTime numbers =
+ numbers
+ |> toMinutesAndSeconds
+ |> \(a, b) -> (stringToInt a, stringToInt b)
+ |> \(minutes, seconds) -> (toFloat minutes) * 60 * 1000 + (toFloat seconds) * 1000
+
+toMinutesAndSeconds : List Char -> (String, String)
+toMinutesAndSeconds numbers =
+ numbers
+ |> List.take 4
+ |> List.reverse
+ |> completeBegin '0' 4
+ |> splitAt 2
+ |> \(a, b) -> (String.fromList a, String.fromList b)
+
+completeBegin : a -> Int -> List a -> List a
+completeBegin x count xs =
+ let length = List.length xs
+ in List.append (repeat (count - length) x) xs
+
+stringToInt : String -> Int
+stringToInt str =
+ str
+ |> String.toInt
+ |> \res ->
+ case res of
+ Ok n -> n
+ Err _ -> 0
diff --git a/src/Edition/Msg.elm b/src/Edition/Msg.elm
new file mode 100644
index 0000000..546e45b
--- /dev/null
+++ b/src/Edition/Msg.elm
@@ -0,0 +1,9 @@
+module Edition.Msg exposing
+ ( Msg(..)
+ )
+
+import Char exposing (KeyCode)
+
+type Msg =
+ DeleteLast
+ | AddChar KeyCode
diff --git a/src/Edition/Update.elm b/src/Edition/Update.elm
new file mode 100644
index 0000000..e219629
--- /dev/null
+++ b/src/Edition/Update.elm
@@ -0,0 +1,30 @@
+module Edition.Update exposing
+ ( updateEdition
+ )
+
+import Char
+import Char exposing (KeyCode)
+import List
+
+import Edition.Model exposing (..)
+import Edition.Msg exposing (..)
+
+updateEdition : Msg -> Edition -> Edition
+updateEdition msg edition =
+ case msg of
+
+ DeleteLast ->
+ case List.tail edition.chars of
+ Just tailChars ->
+ { edition | chars = tailChars }
+ Nothing ->
+ edition
+
+ AddChar keyCode ->
+ case keyCodeToChar edition.kind keyCode of
+ Just char ->
+ if keyCode == 32 && List.head edition.chars == Just (Char.fromCode 32)
+ then edition
+ else { edition | chars = char :: edition.chars }
+ Nothing ->
+ edition
diff --git a/src/Main.elm b/src/Main.elm
index 746df14..743c776 100644
--- a/src/Main.elm
+++ b/src/Main.elm
@@ -1,51 +1,29 @@
-module Main
+port module Main exposing
( main
- ) where
+ )
-import Signal
-import Html exposing (Html)
-import Time exposing (..)
-import Mouse
-import Json.Encode exposing (Value)
-import Keyboard
+import Html.App exposing (programWithFlags)
+import Time
import Char
-import Dict
-import List
-import Keyboard exposing (KeyCode)
-import Model.Model exposing (..)
-import Model.Position exposing (..)
-import Model.TimerState exposing (..)
-import Model.Id exposing (..)
-import Update.Update exposing (..)
-import View.View exposing (view)
-
-main : Signal Html
-main = Signal.map view model
-
-model : Signal Model
-model = Signal.foldp logUpdate (initialModel initialTime) input
-
-input : Signal Action
-input =
- Signal.mergeMany
- [ actions.signal
- , Signal.map DeltaTime (fps 30)
- , Signal.map KeyPressed keyPress
- ]
-
-port ringingTimers : Signal Bool
-port ringingTimers =
- Signal.map
- (\model ->
- model.timers
- |> Dict.toList
- |> List.map snd
- |> List.any (\timer -> timer.state == Ringing)
- )
- model
- |> Signal.dropRepeats
-
-port keyPress : Signal KeyCode
-
-port initialTime : Time
+import Model exposing (init)
+import Model.Keyboard exposing (KeyCode)
+import Msg
+import Update exposing (update)
+import View exposing (view)
+
+main : Program Float
+main =
+ programWithFlags
+ { init = init
+ , update = update
+ , subscriptions = (\model ->
+ Sub.batch
+ [ Time.every 40 Msg.Time
+ , keyPress Msg.KeyPressed
+ ]
+ )
+ , view = view
+ }
+
+port keyPress : (KeyCode -> msg) -> Sub msg
diff --git a/src/Model.elm b/src/Model.elm
new file mode 100644
index 0000000..6e75c39
--- /dev/null
+++ b/src/Model.elm
@@ -0,0 +1,40 @@
+module Model exposing
+ ( Model
+ , init
+ , numberOfTimers
+ )
+
+import Dict exposing (Dict)
+import Dict
+import Time exposing (Time)
+import List
+
+import Msg exposing (Msg)
+
+import Model.Id exposing (..)
+import Model.IdGenerator exposing (..)
+
+import Timer.Model as Timer exposing (Timer)
+
+import Edition.Model exposing (Edition)
+
+type alias Model =
+ { time : Time
+ , timers : Dict Id Timer
+ , timerIdGenerator : IdGenerator
+ , edition : Maybe Edition
+ }
+
+init : Time -> (Model, Cmd Msg)
+init initialTime =
+ let (id, idGenerator) = getId initialIdGenerator
+ model =
+ { time = initialTime
+ , timers = Dict.insert id (Timer.init initialTime) Dict.empty
+ , timerIdGenerator = idGenerator
+ , edition = Nothing
+ }
+ in (model, Cmd.none)
+
+numberOfTimers : Model -> Int
+numberOfTimers = List.length << Dict.toList << .timers
diff --git a/src/Model/Edition/Edition.elm b/src/Model/Edition/Edition.elm
deleted file mode 100644
index 9a28253..0000000
--- a/src/Model/Edition/Edition.elm
+++ /dev/null
@@ -1,44 +0,0 @@
-module Model.Edition.Edition
- ( Edition
- , Kind(..)
- , newEdition
- , keyCodeToChar
- , isEmpty
- ) where
-
-import Keyboard exposing (KeyCode)
-import String
-
-import Model.Id exposing (..)
-import Model.Edition.NameEdition as NameEdition
-import Model.Edition.TimeEdition as TimeEdition
-
-type alias Edition =
- { id : Id
- , kind : Kind
- , chars : List Char
- }
-
-type Kind =
- Name
- | Time
-
-newEdition id kind =
- { id = id
- , kind = kind
- , chars = []
- }
-
-keyCodeToChar : Kind -> KeyCode -> Maybe Char
-keyCodeToChar kind =
- case kind of
- Name -> NameEdition.keyCodeToChar
- Time -> TimeEdition.keyCodeToChar
-
-isEmpty : Edition -> Bool
-isEmpty edition =
- edition.chars
- |> String.fromList
- |> String.trim
- |> String.length
- |> (==) 0
diff --git a/src/Model/Edition/NameEdition.elm b/src/Model/Edition/NameEdition.elm
deleted file mode 100644
index be7c6b3..0000000
--- a/src/Model/Edition/NameEdition.elm
+++ /dev/null
@@ -1,18 +0,0 @@
-module Model.Edition.NameEdition
- ( keyCodeToChar
- , renderNameEdition
- ) where
-
-import Char
-import Keyboard exposing (KeyCode)
-import String
-import List
-
-keyCodeToChar : KeyCode -> Maybe Char
-keyCodeToChar = Just << Char.fromCode
-
-renderNameEdition : List Char -> String
-renderNameEdition chars =
- chars
- |> List.reverse
- |> String.fromList
diff --git a/src/Model/Edition/TimeEdition.elm b/src/Model/Edition/TimeEdition.elm
deleted file mode 100644
index 3b70c3d..0000000
--- a/src/Model/Edition/TimeEdition.elm
+++ /dev/null
@@ -1,52 +0,0 @@
-module Model.Edition.TimeEdition
- ( keyCodeToChar
- , toTime
- , toMinutesAndSeconds
- ) where
-
-import Time exposing (Time)
-import List
-import Array
-import String
-import Keyboard exposing (KeyCode)
-import Char
-
-import Utils.List exposing (..)
-import Utils.Maybe exposing (..)
-
-keyCodeToChar : KeyCode -> Maybe Char
-keyCodeToChar code =
- let char = Char.fromCode code
- in if Char.isDigit char
- then Just char
- else Nothing
-
-toTime : List Char -> Time
-toTime numbers =
- numbers
- |> toMinutesAndSeconds
- |> \(a, b) -> (stringToInt a, stringToInt b)
- |> \(minutes, seconds) -> (toFloat minutes) * 60 * 1000 + (toFloat seconds) * 1000
-
-toMinutesAndSeconds : List Char -> (String, String)
-toMinutesAndSeconds numbers =
- numbers
- |> List.take 4
- |> List.reverse
- |> completeBegin '0' 4
- |> splitAt 2
- |> \(a, b) -> (String.fromList a, String.fromList b)
-
-completeBegin : a -> Int -> List a -> List a
-completeBegin x count xs =
- let length = List.length xs
- in List.append (repeat (count - length) x) xs
-
-stringToInt : String -> Int
-stringToInt str =
- str
- |> String.toInt
- |> \res ->
- case res of
- Ok n -> n
- Err _ -> 0
diff --git a/src/Model/Id.elm b/src/Model/Id.elm
index c416804..f71b71e 100644
--- a/src/Model/Id.elm
+++ b/src/Model/Id.elm
@@ -1,5 +1,5 @@
-module Model.Id
+module Model.Id exposing
( Id
- ) where
+ )
type alias Id = Int
diff --git a/src/Model/IdGenerator.elm b/src/Model/IdGenerator.elm
index 9001191..f3eefad 100644
--- a/src/Model/IdGenerator.elm
+++ b/src/Model/IdGenerator.elm
@@ -1,8 +1,8 @@
-module Model.IdGenerator
+module Model.IdGenerator exposing
( IdGenerator
, initialIdGenerator
, getId
- ) where
+ )
import Model.Id exposing (..)
@@ -17,5 +17,5 @@ initialIdGenerator =
getId : IdGenerator -> (Id, IdGenerator)
getId idGenerator =
( idGenerator.counter
- , { idGenerator | counter <- idGenerator.counter + 1 }
+ , { idGenerator | counter = idGenerator.counter + 1 }
)
diff --git a/src/Model/Keyboard.elm b/src/Model/Keyboard.elm
new file mode 100644
index 0000000..7649a56
--- /dev/null
+++ b/src/Model/Keyboard.elm
@@ -0,0 +1,5 @@
+module Model.Keyboard exposing
+ ( KeyCode
+ )
+
+type alias KeyCode = Int
diff --git a/src/Model/Model.elm b/src/Model/Model.elm
deleted file mode 100644
index a660b16..0000000
--- a/src/Model/Model.elm
+++ /dev/null
@@ -1,34 +0,0 @@
-module Model.Model
- ( Model
- , initialModel
- , numberOfTimers
- ) where
-
-import Dict exposing (Dict)
-import Dict
-import Time exposing (Time)
-import List
-
-import Model.Timer exposing (..)
-import Model.Edition.Edition exposing (..)
-import Model.Id exposing (..)
-import Model.IdGenerator exposing (..)
-
-type alias Model =
- { currentTime : Time
- , timers : Dict Id Timer
- , timerIdGenerator : IdGenerator
- , edition : Maybe Edition
- }
-
-initialModel : Time -> Model
-initialModel initialTime =
- let (id, idGenerator) = getId initialIdGenerator
- in { currentTime = initialTime
- , timers = Dict.insert id (initialTimer initialTime) Dict.empty
- , timerIdGenerator = idGenerator
- , edition = Nothing
- }
-
-numberOfTimers : Model -> Int
-numberOfTimers = List.length << Dict.toList << .timers
diff --git a/src/Model/Position.elm b/src/Model/Position.elm
index d15e853..12d2f9b 100644
--- a/src/Model/Position.elm
+++ b/src/Model/Position.elm
@@ -1,6 +1,6 @@
-module Model.Position
+module Model.Position exposing
( positionEncoder
- ) where
+ )
import Json.Encode exposing (..)
diff --git a/src/Model/Timer.elm b/src/Model/Timer.elm
deleted file mode 100644
index 51d293d..0000000
--- a/src/Model/Timer.elm
+++ /dev/null
@@ -1,27 +0,0 @@
-module Model.Timer
- ( Timer
- , initialTimer
- ) where
-
-import List
-import Time exposing (Time)
-
-import Model.TimerState exposing (..)
-
-type alias Timer =
- { creationTime : Time
- , name : Maybe String
- , initialTime : Time
- , currentTime : Time
- , state : TimerState
- }
-
-initialTimer : Time -> Timer
-initialTimer creationTime =
- let initialTime = 5 * 60 * 1000
- in { creationTime = creationTime
- , name = Nothing
- , initialTime = initialTime
- , currentTime = initialTime
- , state = Idle
- }
diff --git a/src/Model/TimerState.elm b/src/Model/TimerState.elm
deleted file mode 100644
index dbbcb80..0000000
--- a/src/Model/TimerState.elm
+++ /dev/null
@@ -1,8 +0,0 @@
-module Model.TimerState
- ( TimerState(..)
- ) where
-
-type TimerState =
- Idle
- | Running
- | Ringing
diff --git a/src/Msg.elm b/src/Msg.elm
new file mode 100644
index 0000000..b5efe2f
--- /dev/null
+++ b/src/Msg.elm
@@ -0,0 +1,23 @@
+module Msg exposing
+ ( Msg(..)
+ )
+
+import Time exposing (Time)
+
+import Model.Id exposing (Id)
+import Model.Keyboard exposing (KeyCode)
+
+import Timer.Msg as Timer
+
+import Edition.Model exposing (Kind)
+
+type Msg =
+ NoOp
+ | Initialize
+ | AddNewTimer
+ | Time Time
+ | UpdateTimer Id Timer.Msg
+ | RemoveTimer Id
+ | Edit Id Kind
+ | ClickAway
+ | KeyPressed KeyCode
diff --git a/src/Ring.elm b/src/Ring.elm
new file mode 100644
index 0000000..fa29928
--- /dev/null
+++ b/src/Ring.elm
@@ -0,0 +1,5 @@
+port module Ring exposing
+ ( ring
+ )
+
+port ring : Bool -> Cmd msg
diff --git a/src/Timer/Model.elm b/src/Timer/Model.elm
new file mode 100644
index 0000000..89af67e
--- /dev/null
+++ b/src/Timer/Model.elm
@@ -0,0 +1,27 @@
+module Timer.Model exposing
+ ( Timer
+ , init
+ )
+
+import List
+import Time exposing (Time)
+
+import Timer.Model.State exposing (..)
+
+type alias Timer =
+ { creationTime : Time
+ , name : Maybe String
+ , initialTime : Time
+ , time : Time
+ , state : State
+ }
+
+init : Time -> Timer
+init creationTime =
+ let initialTime = 5 * 60 * 1000
+ in { creationTime = creationTime
+ , name = Nothing
+ , initialTime = initialTime
+ , time = initialTime
+ , state = Idle
+ }
diff --git a/src/Timer/Model/State.elm b/src/Timer/Model/State.elm
new file mode 100644
index 0000000..1162e59
--- /dev/null
+++ b/src/Timer/Model/State.elm
@@ -0,0 +1,8 @@
+module Timer.Model.State exposing
+ ( State(..)
+ )
+
+type State =
+ Idle
+ | Running
+ | Ringing
diff --git a/src/Timer/Msg.elm b/src/Timer/Msg.elm
new file mode 100644
index 0000000..150d4fc
--- /dev/null
+++ b/src/Timer/Msg.elm
@@ -0,0 +1,13 @@
+module Timer.Msg exposing
+ ( Msg(..)
+ )
+
+import Time exposing (Time)
+
+type Msg =
+ Rename String
+ | Pause
+ | ToggleRunning
+ | Stop
+ | SetTime Time
+ | SubstractTime Time
diff --git a/src/Timer/Update.elm b/src/Timer/Update.elm
new file mode 100644
index 0000000..31e8a43
--- /dev/null
+++ b/src/Timer/Update.elm
@@ -0,0 +1,56 @@
+module Timer.Update exposing
+ ( updateTimer
+ )
+
+import Time exposing (Time)
+
+import Model.Id exposing (..)
+
+import Timer.Model exposing (..)
+import Timer.Model.State exposing (..)
+import Timer.Msg exposing (..)
+
+updateTimer : Msg -> Timer -> Timer
+updateTimer msg timer =
+ case msg of
+
+ Rename name ->
+ { timer | name = Just name }
+
+ Pause ->
+ { timer | state = Idle }
+
+ ToggleRunning ->
+ { timer
+ | state =
+ if timer.time > 0 && timer.state == Idle
+ then Running
+ else Idle
+ }
+
+ Stop ->
+ { timer
+ | time = timer.initialTime
+ , state = Idle
+ }
+
+ SetTime time ->
+ { timer
+ | initialTime = time
+ , time = time
+ }
+
+ SubstractTime time ->
+ if timer.state == Running
+ then
+ let newTime = timer.time - time
+ in if newTime <= 0.0
+ then
+ { timer
+ | time = 0.0
+ , state = Ringing
+ }
+ else
+ { timer | time = newTime }
+ else
+ timer
diff --git a/src/Timer/View.elm b/src/Timer/View.elm
new file mode 100644
index 0000000..561ae8f
--- /dev/null
+++ b/src/Timer/View.elm
@@ -0,0 +1,175 @@
+module Timer.View exposing
+ ( view
+ )
+
+import Html exposing (..)
+import Html.Attributes exposing (..)
+import Html.Events exposing (..)
+import Time exposing (Time)
+import Maybe
+import List
+import String
+
+import Msg exposing (Msg)
+
+import Model exposing (..)
+import Model.Id exposing (..)
+
+import Timer.Model exposing (..)
+import Timer.Model.State exposing (..)
+import Timer.Update exposing (..)
+import Timer.Msg as Timer
+
+import Edition.Model exposing (..)
+import Edition.Model.Name exposing (..)
+import Edition.Model.Time exposing (..)
+
+import Update exposing (..)
+
+import Utils.Maybe exposing (..)
+
+view : Model -> (Id, Timer) -> Html Msg
+view model (id, timer) =
+ div
+ [ [ ("timer", True)
+ , ("isRinging", timer.state == Ringing)
+ , ("isRunning", timer.state == Running)
+ ]
+ |> classList
+ ]
+ [ renderMaybeEdition model id Name (nameBlockReadOnly id timer) (nameBlockEdition id timer)
+ , renderMaybeEdition model id Time (timeBlockReadOnly (id, timer)) (timeBlockEdition (id, timer))
+ , playPauseTimer (id, timer)
+ , stopTimer (id, timer)
+ , removeTimer (id, timer)
+ ]
+
+nameBlockReadOnly : Id -> Timer -> Html Msg
+nameBlockReadOnly id timer =
+ div
+ [ class "name"
+ , onClick (Msg.Edit id Name)
+ ]
+ [ text (timerName id timer) ]
+
+nameBlockEdition : Id -> Timer -> Edition -> Html Msg
+nameBlockEdition id timer edition =
+ div
+ [ [ ("name", True)
+ , ("edition", True)
+ , ("empty", isEmpty edition)
+ ]
+ |> classList
+ , onClick Msg.NoOp
+ ]
+ [ if isEmpty edition
+ then
+ text (timerName id timer)
+ else
+ edition.chars
+ |> renderNameEdition
+ |> flip String.append "_"
+ |> text
+ ]
+
+timerName : Id -> Timer -> String
+timerName id = Maybe.withDefault ("Timer " ++ toString id) << .name
+
+timeBlockReadOnly : (Id, Timer) -> Html Msg
+timeBlockReadOnly (id, timer) =
+ div
+ [ class "time"
+ , onClick (Msg.Edit id Time)
+ ]
+ [ timeWithProgressBar (id, timer) ]
+
+timeBlockEdition : (Id, Timer) -> Edition -> Html Msg
+timeBlockEdition (id, timer) edition =
+ div
+ [ [ ("time", True)
+ , ("edition", True)
+ , ("empty", isEmpty edition)
+ ]
+ |> classList
+ , onClick Msg.NoOp
+ ]
+ [ if isEmpty edition
+ then
+ timeWithProgressBar (id, timer)
+ else
+ text (editionView edition.chars)
+ ]
+
+editionView : List Char -> String
+editionView numbers =
+ let (minutes, seconds) = toMinutesAndSeconds numbers
+ in minutes ++ " : " ++ seconds
+
+timeView : Time -> String
+timeView time =
+ let totalSeconds = ceiling (time / 1000)
+ totalMinutes = totalSeconds // 60
+ restSeconds = totalSeconds `rem` 60
+ in (String.padLeft 2 '0' (toString totalMinutes)) ++ " : " ++ (String.padLeft 2 '0' (toString restSeconds))
+
+timeWithProgressBar : (Id, Timer) -> Html Msg
+timeWithProgressBar (id, timer) =
+ div
+ []
+ [ span
+ [ class "progressBar"
+ , let width =
+ 1 - timer.time / timer.initialTime
+ |> (*) 1020
+ |> round
+ |> toString
+ |> flip String.append "px"
+ in style [ ("width", width) ]
+ , onClick (Msg.UpdateTimer id Timer.Stop)
+ ]
+ []
+ , span
+ [ class "text" ]
+ [ text (timeView timer.time) ]
+ ]
+
+playPauseTimer : (Id, Timer) -> Html Msg
+playPauseTimer (id, timer) =
+ button
+ [ class <| "playPause"
+ , onClick (Msg.UpdateTimer id Timer.ToggleRunning)
+ ]
+ [ let icon = if timer.state == Running then "fa-pause" else "fa-play"
+ in i
+ [ class <| "fa fa-fw " ++ icon ]
+ []
+ ]
+
+stopTimer : (Id, Timer) -> Html Msg
+stopTimer (id, timer) =
+ button
+ [ class <| "stop"
+ , onClick (Msg.UpdateTimer id Timer.Stop)
+ ]
+ [ i [ class "fa fa-fw fa-stop" ] [] ]
+
+removeTimer : (Id, Timer) -> Html Msg
+removeTimer (id, timer) =
+ button
+ [ class <| "remove"
+ , onClick (Msg.RemoveTimer id)
+ ]
+ [ i [ class "fa fa-fw fa-remove" ] [] ]
+
+renderMaybeEdition : Model -> Id -> Kind -> Html Msg -> (Edition -> Html Msg) -> Html Msg
+renderMaybeEdition model id kind readOnlyView editionView =
+ let maybeEdition = filterMaybe (\edition -> edition.id == id) model.edition
+ in case maybeEdition of
+ Just edition ->
+ if edition.kind == kind
+ then
+ editionView edition
+ else
+ readOnlyView
+ Nothing ->
+ readOnlyView
diff --git a/src/Update.elm b/src/Update.elm
new file mode 100644
index 0000000..42eb682
--- /dev/null
+++ b/src/Update.elm
@@ -0,0 +1,141 @@
+module Update exposing
+ ( update
+ )
+
+import Dict
+
+import Msg exposing (Msg)
+
+import Ring
+
+import Model exposing (Model)
+import Model.Id exposing (..)
+import Model.IdGenerator exposing (..)
+import Model.Keyboard exposing (KeyCode)
+
+import Timer.Model as Timer exposing (..)
+import Timer.Model.State as TimerState
+import Timer.Update exposing (..)
+import Timer.Msg as Timer
+
+import Edition.Model exposing (..)
+import Edition.Model.Name exposing (..)
+import Edition.Model.Time exposing (..)
+import Edition.Update exposing (..)
+import Edition.Msg as Edition
+
+import Utils.Maybe exposing (..)
+
+update : Msg -> Model -> (Model, Cmd Msg)
+update msg model =
+ case msg of
+
+ Msg.NoOp ->
+ (model, Cmd.none)
+
+ Msg.Initialize ->
+ Model.init model.time
+
+ Msg.AddNewTimer ->
+ let (id, newTimerIdGenerator) = getId model.timerIdGenerator
+ in ( { model
+ | timers = Dict.insert id (Timer.init model.time) model.timers
+ , timerIdGenerator = newTimerIdGenerator
+ }
+ , Cmd.none
+ )
+
+ Msg.Time time ->
+ let delta = time - model.time
+ newModel =
+ { model
+ | time = time
+ , timers = Dict.map (\id timer -> updateTimer (Timer.SubstractTime delta) timer) model.timers
+ }
+ ringing =
+ newModel.timers
+ |> Dict.values
+ |> List.map .state
+ |> List.member TimerState.Ringing
+ in ( newModel
+ , Ring.ring ringing
+ )
+
+ Msg.UpdateTimer id timerMsg ->
+ let maybeEdition = filterMaybe (\edition -> edition.id == id) model.edition
+ newModel =
+ case maybeEdition of
+ Just edition ->
+ if edition.kind == Time then validEdition model else model
+ Nothing ->
+ model
+ in ( { newModel | timers = Dict.update id (Maybe.map (updateTimer timerMsg)) newModel.timers }
+ , Cmd.none
+ )
+
+ Msg.RemoveTimer id ->
+ if Model.numberOfTimers model > 1
+ then
+ ( { model | timers = Dict.remove id model.timers }
+ , Cmd.none
+ )
+ else
+ (model, Cmd.none)
+
+ Msg.Edit id kind ->
+ ( { model
+ | edition = Just (newEdition id kind)
+ , timers =
+ if kind == Time
+ then Dict.update id (Maybe.map (updateTimer Timer.Pause)) model.timers
+ else model.timers
+ }
+ , Cmd.none
+ )
+
+ Msg.ClickAway ->
+ ( { model | edition = Nothing }
+ , Cmd.none
+ )
+
+ Msg.KeyPressed keyCode ->
+ if isEnterKeyCode keyCode
+ then
+ (validEdition model, Cmd.none)
+ else
+ let editionAction =
+ if isRemoveKeyCode keyCode
+ then Edition.DeleteLast
+ else Edition.AddChar keyCode
+ in ( { model | edition = Maybe.map (updateEdition editionAction) model.edition }
+ , Cmd.none
+ )
+
+validEdition : Model -> Model
+validEdition model =
+ case model.edition of
+ Just edition ->
+ if isEmpty edition
+ then
+ { model
+ | edition = Nothing
+ }
+ else
+ let timerMsg =
+ case edition.kind of
+ Name ->
+ Timer.Rename (renderNameEdition edition.chars)
+ Time ->
+ Timer.SetTime (toTime edition.chars)
+ in { model
+ | timers = Dict.update edition.id (Maybe.map (updateTimer timerMsg)) model.timers
+ , edition = Nothing
+ }
+ Nothing ->
+ model
+
+isEnterKeyCode : KeyCode -> Bool
+isEnterKeyCode = (==) 13
+
+isRemoveKeyCode : KeyCode -> Bool
+isRemoveKeyCode = (==) 8
diff --git a/src/Update/Update.elm b/src/Update/Update.elm
deleted file mode 100644
index b4cf741..0000000
--- a/src/Update/Update.elm
+++ /dev/null
@@ -1,131 +0,0 @@
-module Update.Update
- ( Action(..)
- , actions
- , logUpdate
- , update
- ) where
-
-import Signal
-import Dict
-import Dict exposing (Dict)
-import Time exposing (Time)
-import Maybe
-import Keyboard exposing (KeyCode)
-import Char
-import List
-import Debug
-
-import Model.Model exposing (..)
-import Model.Timer exposing (..)
-import Model.Edition.Edition exposing (..)
-import Model.Edition.NameEdition exposing (..)
-import Model.Edition.TimeEdition exposing (..)
-import Model.Id exposing (..)
-import Model.IdGenerator exposing (..)
-
-import Update.UpdateTimer exposing (..)
-import Update.UpdateEdition exposing (..)
-
-import Utils.Maybe exposing (..)
-
-type Action =
- NoOp
- | Initialize
- | AddNewTimer
- | DeltaTime Time
- | UpdateTimer Id TimerAction
- | RemoveTimer Id
- | Edit Id Kind
- | ClickAway
- | KeyPressed KeyCode
-
-actions : Signal.Mailbox Action
-actions = Signal.mailbox NoOp
-
-logUpdate : Action -> Model -> Model
-logUpdate action model =
- case action of
- DeltaTime _ -> update action model
- _ -> update (Debug.log "action" action) model
-
-update : Action -> Model -> Model
-update action model =
- case action of
- NoOp -> model
- Initialize ->
- initialModel model.currentTime
- AddNewTimer ->
- let (id, newTimerIdGenerator) = getId model.timerIdGenerator
- in { model
- | timers <- Dict.insert id (initialTimer model.currentTime) model.timers
- , timerIdGenerator <- newTimerIdGenerator
- }
- DeltaTime delta ->
- { model
- | currentTime <- model.currentTime + delta
- , timers <- Dict.map (\id timer -> updateTimer (SubstractTime delta) timer) model.timers
- }
- UpdateTimer id timerAction ->
- let maybeEdition = filterMaybe (\edition -> edition.id == id) model.edition
- newModel =
- case maybeEdition of
- Just edition ->
- if edition.kind == Time then validEdition model else model
- Nothing ->
- model
- in { newModel | timers <- Dict.update id (Maybe.map (updateTimer timerAction)) newModel.timers }
- RemoveTimer id ->
- if numberOfTimers model > 1
- then
- { model | timers <- Dict.remove id model.timers }
- else
- model
- Edit id kind ->
- { model
- | edition <- Just (newEdition id kind)
- , timers <-
- if kind == Time
- then Dict.update id (Maybe.map (updateTimer Pause)) model.timers
- else model.timers
- }
- ClickAway ->
- { model | edition <- Nothing }
- KeyPressed keyCode ->
- if isEnterKeyCode keyCode
- then
- validEdition model
- else
- let editionAction =
- if isRemoveKeyCode keyCode
- then DeleteLast
- else AddChar keyCode
- in { model | edition <- Maybe.map (updateEdition editionAction) model.edition }
-
-validEdition : Model -> Model
-validEdition model =
- case model.edition of
- Just edition ->
- if isEmpty edition
- then
- { model
- | edition <- Nothing
- }
- else
- let timerAction =
- case edition.kind of
- Name ->
- Rename (renderNameEdition edition.chars)
- Time ->
- SetTime (toTime edition.chars)
- in { model
- | timers <- Dict.update edition.id (Maybe.map (updateTimer timerAction)) model.timers
- , edition <- Nothing
- }
- Nothing ->
- model
-
-isEnterKeyCode : KeyCode -> Bool
-isEnterKeyCode = (==) 13
-
-isRemoveKeyCode : KeyCode -> Bool
-isRemoveKeyCode = (==) 8
diff --git a/src/Update/UpdateEdition.elm b/src/Update/UpdateEdition.elm
deleted file mode 100644
index 47b0e22..0000000
--- a/src/Update/UpdateEdition.elm
+++ /dev/null
@@ -1,33 +0,0 @@
-module Update.UpdateEdition
- ( updateEdition
- , EditionAction(..)
- ) where
-
-import Char
-import Char exposing (KeyCode)
-
-import Model.Edition.Edition exposing (..)
-
-import Utils.List exposing (..)
-
-type EditionAction =
- DeleteLast
- | AddChar KeyCode
-
-updateEdition : EditionAction -> Edition -> Edition
-updateEdition action edition =
- case action of
- DeleteLast ->
- case maybeTail edition.chars of
- Just tailChars ->
- { edition | chars <- tailChars }
- Nothing ->
- edition
- AddChar keyCode ->
- case keyCodeToChar edition.kind keyCode of
- Just char ->
- if keyCode == 32 && maybeHead edition.chars == Just (Char.fromCode 32)
- then edition
- else { edition | chars <- char :: edition.chars }
- Nothing ->
- edition
diff --git a/src/Update/UpdateTimer.elm b/src/Update/UpdateTimer.elm
deleted file mode 100644
index 08b9969..0000000
--- a/src/Update/UpdateTimer.elm
+++ /dev/null
@@ -1,57 +0,0 @@
-module Update.UpdateTimer
- ( TimerAction(..)
- , updateTimer
- ) where
-
-import Time exposing (Time)
-
-import Model.Timer exposing (..)
-import Model.TimerState exposing (..)
-import Model.Id exposing (..)
-
-type TimerAction =
- Rename String
- | Pause
- | ToggleRunning
- | Stop
- | SetTime Time
- | SubstractTime Time
-
-updateTimer : TimerAction -> Timer -> Timer
-updateTimer action timer =
- case action of
- Rename name ->
- { timer | name <- Just name }
- Pause ->
- { timer | state <- Idle }
- ToggleRunning ->
- { timer
- | state <-
- if timer.currentTime > 0 && timer.state == Idle
- then Running
- else Idle
- }
- Stop ->
- { timer
- | currentTime <- timer.initialTime
- , state <- Idle
- }
- SetTime time ->
- { timer
- | initialTime <- time
- , currentTime <- time
- }
- SubstractTime time ->
- if timer.state == Running
- then
- let newTime = timer.currentTime - time
- in if newTime <= 0.0
- then
- { timer
- | currentTime <- 0.0
- , state <- Ringing
- }
- else
- { timer | currentTime <- newTime }
- else
- timer
diff --git a/src/Utils/List.elm b/src/Utils/List.elm
index 83b11eb..7f2e928 100644
--- a/src/Utils/List.elm
+++ b/src/Utils/List.elm
@@ -1,9 +1,7 @@
-module Utils.List
+module Utils.List exposing
( repeat
, splitAt
- , maybeHead
- , maybeTail
- ) where
+ )
import List
@@ -17,15 +15,3 @@ repeat count elem =
splitAt : Int -> List a -> (List a, List a)
splitAt n xs = (List.take n xs, List.drop n xs)
-
-maybeHead : List a -> Maybe a
-maybeHead xs =
- case xs of
- x :: _ -> Just x
- _ -> Nothing
-
-maybeTail : List a -> Maybe (List a)
-maybeTail xs =
- case xs of
- _ :: tl -> Just tl
- _ -> Nothing
diff --git a/src/Utils/Maybe.elm b/src/Utils/Maybe.elm
index 355ded9..db25bff 100644
--- a/src/Utils/Maybe.elm
+++ b/src/Utils/Maybe.elm
@@ -1,7 +1,7 @@
-module Utils.Maybe
+module Utils.Maybe exposing
( filterMaybe
, orElse
- ) where
+ )
filterMaybe : (a -> Bool) -> Maybe a -> Maybe a
filterMaybe cond maybe =
diff --git a/src/View.elm b/src/View.elm
new file mode 100644
index 0000000..5b3ad8d
--- /dev/null
+++ b/src/View.elm
@@ -0,0 +1,56 @@
+module View exposing
+ ( view
+ )
+
+import Html exposing (..)
+import Html.Attributes exposing (..)
+import Html.Events exposing (..)
+import List
+import Dict
+import Json.Decode as Json
+
+import Msg exposing (Msg)
+
+import Model exposing (..)
+import Model.Id exposing (..)
+
+import Timer.Model exposing (..)
+import Timer.View as Timer
+
+import Update exposing (..)
+
+view : Model -> Html Msg
+view model =
+ div
+ []
+ [ title
+ , model.timers
+ |> Dict.toList
+ |> List.sortBy (.creationTime << snd)
+ |> timers model
+ ]
+
+title : Html Msg
+title =
+ div
+ [ class "headerBar" ]
+ [ button
+ [ onClick Msg.Initialize
+ , class "title"
+ ]
+ [ text "Timer" ]
+ , button
+ [ onClick Msg.AddNewTimer
+ , class "addTimer"
+ ]
+ [ i
+ [ class "fa fa-fw fa-plus" ]
+ []
+ ]
+ ]
+
+timers : Model -> List (Id, Timer) -> Html Msg
+timers model timers =
+ div
+ [ class "timers" ]
+ (List.map (Timer.view model) timers)
diff --git a/src/View/ActivatedClasses.elm b/src/View/ActivatedClasses.elm
deleted file mode 100644
index 85b0841..0000000
--- a/src/View/ActivatedClasses.elm
+++ /dev/null
@@ -1,15 +0,0 @@
-module View.ActivatedClasses
- ( activatedClasses
- ) where
-
-import Html
-import Html.Attributes exposing (..)
-import List
-import String
-
-activatedClasses : List (Bool, String) -> Html.Attribute
-activatedClasses =
- class
- << String.concat
- << List.intersperse " "
- << List.filterMap (\(activated, str) -> if activated then Just str else Nothing)
diff --git a/src/View/Timer.elm b/src/View/Timer.elm
deleted file mode 100644
index 4672594..0000000
--- a/src/View/Timer.elm
+++ /dev/null
@@ -1,171 +0,0 @@
-module View.Timer
- ( timerView
- ) where
-
-import Html exposing (..)
-import Html.Attributes exposing (..)
-import Html.Events exposing (..)
-import Time exposing (Time)
-import Signal
-import Maybe
-import List
-import String
-
-import Model.Model exposing (..)
-import Model.Timer exposing (..)
-import Model.Edition.Edition exposing (..)
-import Model.Edition.NameEdition exposing (..)
-import Model.Edition.TimeEdition exposing (..)
-import Model.TimerState exposing (..)
-import Model.Id exposing (..)
-
-import Update.Update exposing (..)
-import Update.UpdateTimer exposing (..)
-
-import View.ActivatedClasses exposing (..)
-
-import Utils.Maybe exposing (..)
-
-timerView : Model -> (Id, Timer) -> Html
-timerView model (id, timer) =
- div
- [ [ (True, "timer")
- , (timer.state == Ringing, "isRinging")
- , (timer.state == Running, "isRunning")
- ]
- |> activatedClasses
- ]
- [ renderMaybeEdition model id Name (nameBlockReadOnly id timer) (nameBlockEdition id timer)
- , renderMaybeEdition model id Time (timeBlockReadOnly (id, timer)) (timeBlockEdition (id, timer))
- , playPauseTimer (id, timer)
- , stopTimer (id, timer)
- , removeTimer (id, timer)
- ]
-
-nameBlockReadOnly : Id -> Timer -> Html
-nameBlockReadOnly id timer =
- div
- [ class "name"
- , onClick actions.address (Edit id Name)
- ]
- [ text (timerName id timer) ]
-
-nameBlockEdition : Id -> Timer -> Edition -> Html
-nameBlockEdition id timer edition =
- div
- [ [ (True, "name edition")
- , (isEmpty edition, "empty")
- ]
- |> activatedClasses
- , onClick actions.address NoOp
- ]
- [ if isEmpty edition
- then
- text (timerName id timer)
- else
- edition.chars
- |> renderNameEdition
- |> flip String.append "_"
- |> text
- ]
-
-timerName : Id -> Timer -> String
-timerName id = Maybe.withDefault ("Timer " ++ toString id) << .name
-
-timeBlockReadOnly : (Id, Timer) -> Html
-timeBlockReadOnly (id, timer) =
- div
- [ class "time"
- , onClick actions.address (Edit id Time)
- ]
- [ timeWithProgressBar (id, timer) ]
-
-timeBlockEdition : (Id, Timer) -> Edition -> Html
-timeBlockEdition (id, timer) edition =
- div
- [ [ (True, "time edition")
- , (isEmpty edition, "empty")
- ]
- |> activatedClasses
- , onClick actions.address NoOp
- ]
- [ if isEmpty edition
- then
- timeWithProgressBar (id, timer)
- else
- text (editionView edition.chars)
- ]
-
-editionView : List Char -> String
-editionView numbers =
- let (minutes, seconds) = toMinutesAndSeconds numbers
- in minutes ++ " : " ++ seconds
-
-timeView : Time -> String
-timeView time =
- let totalSeconds = ceiling (time / 1000)
- totalMinutes = totalSeconds // 60
- restSeconds = totalSeconds `rem` 60
- in (String.padLeft 2 '0' (toString totalMinutes)) ++ " : " ++ (String.padLeft 2 '0' (toString restSeconds))
-
-timeWithProgressBar : (Id, Timer) -> Html
-timeWithProgressBar (id, timer) =
- div
- []
- [ span
- [ class "progressBar"
- , let width =
- 1 - timer.currentTime / timer.initialTime
- |> (*) 1020
- |> round
- |> toString
- |> flip String.append "px"
- in style [ ("width", width) ]
- , onClick actions.address (UpdateTimer id Stop)
- ]
- []
- , span
- [ class "text" ]
- [ text (timeView timer.currentTime) ]
- ]
-
-playPauseTimer : (Id, Timer) -> Html
-playPauseTimer (id, timer) =
- button
- [ class <| "playPause"
- , onClick actions.address (UpdateTimer id ToggleRunning)
- ]
- [ let icon = if timer.state == Running then "fa-pause" else "fa-play"
- in i
- [ class <| "fa fa-fw " ++ icon ]
- []
- ]
-
-stopTimer : (Id, Timer) -> Html
-stopTimer (id, timer) =
- button
- [ class <| "stop"
- , onClick actions.address (UpdateTimer id Stop)
- ]
- [ i [ class "fa fa-fw fa-stop" ] [] ]
-
-removeTimer : (Id, Timer) -> Html
-removeTimer (id, timer) =
- button
- [ class <| "remove"
- , onClick actions.address (RemoveTimer id)
- ]
- [ i [ class "fa fa-fw fa-remove" ] [] ]
-
-renderMaybeEdition : Model -> Id -> Kind -> Html -> (Edition -> Html) -> Html
-renderMaybeEdition model id kind readOnlyView editionView =
- let maybeEdition = filterMaybe (\edition -> edition.id == id) model.edition
- in case maybeEdition of
- Just edition ->
- if edition.kind == kind
- then
- editionView edition
- else
- readOnlyView
- Nothing ->
- readOnlyView
diff --git a/src/View/View.elm b/src/View/View.elm
deleted file mode 100644
index a69d662..0000000
--- a/src/View/View.elm
+++ /dev/null
@@ -1,67 +0,0 @@
-module View.View
- ( view
- ) where
-
-import Html exposing (..)
-import Html.Attributes exposing (..)
-import Html.Events exposing (..)
-import Signal
-import List
-import Dict
-import Json.Decode as Json
-
-import Model.Model exposing (..)
-import Model.Timer exposing (..)
-import Model.Id exposing (..)
-
-import Update.Update exposing (..)
-
-import View.Timer exposing (timerView)
-
-view : Model -> Html
-view model =
- div
- []
- [ title
- , model.timers
- |> Dict.toList
- |> List.sortBy (.creationTime << snd)
- |> timers model
- ]
-
-title : Html
-title =
- div
- [ class "headerBar" ]
- [ button
- [ onClick actions.address Initialize
- , class "title"
- ]
- [ text "Timer" ]
- , button
- [ onClick actions.address AddNewTimer
- , class "addTimer"
- ]
- [ i
- [ class "fa fa-fw fa-plus" ]
- []
- ]
- ]
-
-onEnter : Signal.Message -> Attribute
-onEnter message =
- on "keydown"
- (Json.customDecoder keyCode is13)
- (always message)
-
-is13 : Int -> Result String ()
-is13 code =
- if code == 13
- then Ok()
- else Err "Not the right key code"
-
-timers : Model -> List (Id, Timer) -> Html
-timers model timers =
- div
- [ class "timers" ]
- (List.map (timerView model) timers)
--
cgit v1.2.3