diff --git a/devenv.nix b/devenv.nix index a87445a..c127ccd 100644 --- a/devenv.nix +++ b/devenv.nix @@ -4,7 +4,19 @@ config, inputs, ... -}: { +}: let + nsrc = pkgs.fetchFromGitHub { + owner = "elm-tooling"; + repo = "elm-language-server"; + rev = "0dc4076180fe7e758bed267a84911cc202011a13"; + sha256 = "1xys9a468fy1vxlby8pmvnpv0kg5hr4956mdp2kclvs55k4j9y43"; + }; + elm-lsp = + lib.overrideDerivation pkgs.elmPackages.elm-language-server + (drv: { + src = nsrc; + }); +in { # https://devenv.sh/basics/ env.GREET = "devenv"; @@ -13,12 +25,20 @@ sqlite nodePackages.typescript-language-server nodePackages.prettier + elm2nix + elmPackages.elm + elmPackages.elm-format + elmPackages.elm-review + elmPackages.elm-test-rs + elmPackages.elm-land + elm-lsp + # elmPackages.lamdera # lol ]; # https://devenv.sh/languages/ # languages.rust.enable = true; languages = { - elm.enable = true; + # elm.enable = true; javascript = { enable = true; bun.enable = true; diff --git a/ui/elm-stuff/0.19.1/Api.elmi b/ui/elm-stuff/0.19.1/Api.elmi new file mode 100644 index 0000000..c3dabae Binary files /dev/null and b/ui/elm-stuff/0.19.1/Api.elmi differ diff --git a/ui/elm-stuff/0.19.1/Api.elmo b/ui/elm-stuff/0.19.1/Api.elmo new file mode 100644 index 0000000..fe2ff9c Binary files /dev/null and b/ui/elm-stuff/0.19.1/Api.elmo differ diff --git a/ui/elm-stuff/0.19.1/Homepage.elmi b/ui/elm-stuff/0.19.1/Homepage.elmi new file mode 100644 index 0000000..80cb875 Binary files /dev/null and b/ui/elm-stuff/0.19.1/Homepage.elmi differ diff --git a/ui/elm-stuff/0.19.1/Homepage.elmo b/ui/elm-stuff/0.19.1/Homepage.elmo new file mode 100644 index 0000000..8ea0d94 Binary files /dev/null and b/ui/elm-stuff/0.19.1/Homepage.elmo differ diff --git a/ui/elm-stuff/0.19.1/Lessonpage.elmi b/ui/elm-stuff/0.19.1/Lessonpage.elmi new file mode 100644 index 0000000..8337d1e Binary files /dev/null and b/ui/elm-stuff/0.19.1/Lessonpage.elmi differ diff --git a/ui/elm-stuff/0.19.1/Lessonpage.elmo b/ui/elm-stuff/0.19.1/Lessonpage.elmo new file mode 100644 index 0000000..30dfdef Binary files /dev/null and b/ui/elm-stuff/0.19.1/Lessonpage.elmo differ diff --git a/ui/elm-stuff/0.19.1/Main.elmi b/ui/elm-stuff/0.19.1/Main.elmi new file mode 100644 index 0000000..2636c04 Binary files /dev/null and b/ui/elm-stuff/0.19.1/Main.elmi differ diff --git a/ui/elm-stuff/0.19.1/Main.elmo b/ui/elm-stuff/0.19.1/Main.elmo new file mode 100644 index 0000000..55a577b Binary files /dev/null and b/ui/elm-stuff/0.19.1/Main.elmo differ diff --git a/ui/elm-stuff/0.19.1/Model.elmi b/ui/elm-stuff/0.19.1/Model.elmi new file mode 100644 index 0000000..cb5d361 Binary files /dev/null and b/ui/elm-stuff/0.19.1/Model.elmi differ diff --git a/ui/elm-stuff/0.19.1/Model.elmo b/ui/elm-stuff/0.19.1/Model.elmo new file mode 100644 index 0000000..77614fd Binary files /dev/null and b/ui/elm-stuff/0.19.1/Model.elmo differ diff --git a/ui/elm-stuff/0.19.1/Router.elmi b/ui/elm-stuff/0.19.1/Router.elmi new file mode 100644 index 0000000..387ba2e Binary files /dev/null and b/ui/elm-stuff/0.19.1/Router.elmi differ diff --git a/ui/elm-stuff/0.19.1/Router.elmo b/ui/elm-stuff/0.19.1/Router.elmo new file mode 100644 index 0000000..d64ab58 Binary files /dev/null and b/ui/elm-stuff/0.19.1/Router.elmo differ diff --git a/ui/elm-stuff/0.19.1/Types.elmi b/ui/elm-stuff/0.19.1/Types.elmi new file mode 100644 index 0000000..86a0b3e Binary files /dev/null and b/ui/elm-stuff/0.19.1/Types.elmi differ diff --git a/ui/elm-stuff/0.19.1/Types.elmo b/ui/elm-stuff/0.19.1/Types.elmo new file mode 100644 index 0000000..68d8689 Binary files /dev/null and b/ui/elm-stuff/0.19.1/Types.elmo differ diff --git a/ui/elm-stuff/0.19.1/d.dat b/ui/elm-stuff/0.19.1/d.dat new file mode 100644 index 0000000..ae44ad9 Binary files /dev/null and b/ui/elm-stuff/0.19.1/d.dat differ diff --git a/ui/elm-stuff/0.19.1/i.dat b/ui/elm-stuff/0.19.1/i.dat new file mode 100644 index 0000000..5b1f89b Binary files /dev/null and b/ui/elm-stuff/0.19.1/i.dat differ diff --git a/ui/elm-stuff/0.19.1/lock b/ui/elm-stuff/0.19.1/lock new file mode 100644 index 0000000..e69de29 diff --git a/ui/elm-stuff/0.19.1/o.dat b/ui/elm-stuff/0.19.1/o.dat new file mode 100644 index 0000000..0ab2de6 Binary files /dev/null and b/ui/elm-stuff/0.19.1/o.dat differ diff --git a/ui/elm-stuff/generated-code/elm-community/elm-test/0.19.1-revision12/dependencies.c7f74a7d6a16fb23c9519e15f0c488cae13be3e1e6b409e2874b4c61dfc2f2e2.json b/ui/elm-stuff/generated-code/elm-community/elm-test/0.19.1-revision12/dependencies.c7f74a7d6a16fb23c9519e15f0c488cae13be3e1e6b409e2874b4c61dfc2f2e2.json new file mode 100644 index 0000000..6cc3bba --- /dev/null +++ b/ui/elm-stuff/generated-code/elm-community/elm-test/0.19.1-revision12/dependencies.c7f74a7d6a16fb23c9519e15f0c488cae13be3e1e6b409e2874b4c61dfc2f2e2.json @@ -0,0 +1 @@ +{"direct":{"elm/browser":"1.0.2","elm/core":"1.0.5","elm/html":"1.0.0","elm/http":"2.0.0","elm/json":"1.1.3","elm/random":"1.0.0","elm/time":"1.0.0","mdgriffith/elm-ui":"1.1.8"},"indirect":{"elm/bytes":"1.0.8","elm/file":"1.0.5","elm/url":"1.0.0","elm/virtual-dom":"1.0.3"}} \ No newline at end of file diff --git a/ui/elm-stuff/generated-code/elm-community/elm-test/0.19.1-revision12/dependencies.f1cf80581383296af663b98efec295339314ab6035bc8e79dc4f0dbd2346e3c8.json b/ui/elm-stuff/generated-code/elm-community/elm-test/0.19.1-revision12/dependencies.f1cf80581383296af663b98efec295339314ab6035bc8e79dc4f0dbd2346e3c8.json new file mode 100644 index 0000000..e46925f --- /dev/null +++ b/ui/elm-stuff/generated-code/elm-community/elm-test/0.19.1-revision12/dependencies.f1cf80581383296af663b98efec295339314ab6035bc8e79dc4f0dbd2346e3c8.json @@ -0,0 +1 @@ +{"direct":{"elm/browser":"1.0.2","elm/core":"1.0.5","elm/html":"1.0.0","elm/http":"2.0.0","elm/json":"1.1.3","elm/random":"1.0.0","elm/time":"1.0.0","elm/url":"1.0.0","mdgriffith/elm-ui":"1.1.8"},"indirect":{"elm/bytes":"1.0.8","elm/file":"1.0.5","elm/virtual-dom":"1.0.3"}} \ No newline at end of file diff --git a/ui/elm-stuff/generated-code/elm-community/elm-test/0.19.1-revision12/elm-stuff/0.19.1/Api.elmi b/ui/elm-stuff/generated-code/elm-community/elm-test/0.19.1-revision12/elm-stuff/0.19.1/Api.elmi new file mode 100644 index 0000000..2b11aec Binary files /dev/null and b/ui/elm-stuff/generated-code/elm-community/elm-test/0.19.1-revision12/elm-stuff/0.19.1/Api.elmi differ diff --git a/ui/elm-stuff/generated-code/elm-community/elm-test/0.19.1-revision12/elm-stuff/0.19.1/Api.elmo b/ui/elm-stuff/generated-code/elm-community/elm-test/0.19.1-revision12/elm-stuff/0.19.1/Api.elmo new file mode 100644 index 0000000..02eac9b Binary files /dev/null and b/ui/elm-stuff/generated-code/elm-community/elm-test/0.19.1-revision12/elm-stuff/0.19.1/Api.elmo differ diff --git a/ui/elm-stuff/generated-code/elm-community/elm-test/0.19.1-revision12/elm-stuff/0.19.1/Main.elmi b/ui/elm-stuff/generated-code/elm-community/elm-test/0.19.1-revision12/elm-stuff/0.19.1/Main.elmi new file mode 100644 index 0000000..774e286 Binary files /dev/null and b/ui/elm-stuff/generated-code/elm-community/elm-test/0.19.1-revision12/elm-stuff/0.19.1/Main.elmi differ diff --git a/ui/elm-stuff/generated-code/elm-community/elm-test/0.19.1-revision12/elm-stuff/0.19.1/Main.elmo b/ui/elm-stuff/generated-code/elm-community/elm-test/0.19.1-revision12/elm-stuff/0.19.1/Main.elmo new file mode 100644 index 0000000..0fb35dc Binary files /dev/null and b/ui/elm-stuff/generated-code/elm-community/elm-test/0.19.1-revision12/elm-stuff/0.19.1/Main.elmo differ diff --git a/ui/elm-stuff/generated-code/elm-community/elm-test/0.19.1-revision12/elm-stuff/0.19.1/Model.elmi b/ui/elm-stuff/generated-code/elm-community/elm-test/0.19.1-revision12/elm-stuff/0.19.1/Model.elmi new file mode 100644 index 0000000..cb5d361 Binary files /dev/null and b/ui/elm-stuff/generated-code/elm-community/elm-test/0.19.1-revision12/elm-stuff/0.19.1/Model.elmi differ diff --git a/ui/elm-stuff/generated-code/elm-community/elm-test/0.19.1-revision12/elm-stuff/0.19.1/Model.elmo b/ui/elm-stuff/generated-code/elm-community/elm-test/0.19.1-revision12/elm-stuff/0.19.1/Model.elmo new file mode 100644 index 0000000..77614fd Binary files /dev/null and b/ui/elm-stuff/generated-code/elm-community/elm-test/0.19.1-revision12/elm-stuff/0.19.1/Model.elmo differ diff --git a/ui/elm-stuff/generated-code/elm-community/elm-test/0.19.1-revision12/elm-stuff/0.19.1/Router.elmi b/ui/elm-stuff/generated-code/elm-community/elm-test/0.19.1-revision12/elm-stuff/0.19.1/Router.elmi new file mode 100644 index 0000000..f0fc303 Binary files /dev/null and b/ui/elm-stuff/generated-code/elm-community/elm-test/0.19.1-revision12/elm-stuff/0.19.1/Router.elmi differ diff --git a/ui/elm-stuff/generated-code/elm-community/elm-test/0.19.1-revision12/elm-stuff/0.19.1/Router.elmo b/ui/elm-stuff/generated-code/elm-community/elm-test/0.19.1-revision12/elm-stuff/0.19.1/Router.elmo new file mode 100644 index 0000000..a83b29f Binary files /dev/null and b/ui/elm-stuff/generated-code/elm-community/elm-test/0.19.1-revision12/elm-stuff/0.19.1/Router.elmo differ diff --git a/ui/elm-stuff/generated-code/elm-community/elm-test/0.19.1-revision12/elm-stuff/0.19.1/Types.elmi b/ui/elm-stuff/generated-code/elm-community/elm-test/0.19.1-revision12/elm-stuff/0.19.1/Types.elmi new file mode 100644 index 0000000..f30c094 Binary files /dev/null and b/ui/elm-stuff/generated-code/elm-community/elm-test/0.19.1-revision12/elm-stuff/0.19.1/Types.elmi differ diff --git a/ui/elm-stuff/generated-code/elm-community/elm-test/0.19.1-revision12/elm-stuff/0.19.1/Types.elmo b/ui/elm-stuff/generated-code/elm-community/elm-test/0.19.1-revision12/elm-stuff/0.19.1/Types.elmo new file mode 100644 index 0000000..90fb837 Binary files /dev/null and b/ui/elm-stuff/generated-code/elm-community/elm-test/0.19.1-revision12/elm-stuff/0.19.1/Types.elmo differ diff --git a/ui/elm-stuff/generated-code/elm-community/elm-test/0.19.1-revision12/elm-stuff/0.19.1/d.dat b/ui/elm-stuff/generated-code/elm-community/elm-test/0.19.1-revision12/elm-stuff/0.19.1/d.dat new file mode 100644 index 0000000..aaebdff Binary files /dev/null and b/ui/elm-stuff/generated-code/elm-community/elm-test/0.19.1-revision12/elm-stuff/0.19.1/d.dat differ diff --git a/ui/elm-stuff/generated-code/elm-community/elm-test/0.19.1-revision12/elm-stuff/0.19.1/i.dat b/ui/elm-stuff/generated-code/elm-community/elm-test/0.19.1-revision12/elm-stuff/0.19.1/i.dat new file mode 100644 index 0000000..b90d2a1 Binary files /dev/null and b/ui/elm-stuff/generated-code/elm-community/elm-test/0.19.1-revision12/elm-stuff/0.19.1/i.dat differ diff --git a/ui/elm-stuff/generated-code/elm-community/elm-test/0.19.1-revision12/elm-stuff/0.19.1/lock b/ui/elm-stuff/generated-code/elm-community/elm-test/0.19.1-revision12/elm-stuff/0.19.1/lock new file mode 100644 index 0000000..e69de29 diff --git a/ui/elm-stuff/generated-code/elm-community/elm-test/0.19.1-revision12/elm-stuff/0.19.1/o.dat b/ui/elm-stuff/generated-code/elm-community/elm-test/0.19.1-revision12/elm-stuff/0.19.1/o.dat new file mode 100644 index 0000000..cddeb26 Binary files /dev/null and b/ui/elm-stuff/generated-code/elm-community/elm-test/0.19.1-revision12/elm-stuff/0.19.1/o.dat differ diff --git a/ui/elm-stuff/generated-code/elm-community/elm-test/0.19.1-revision12/elm.json b/ui/elm-stuff/generated-code/elm-community/elm-test/0.19.1-revision12/elm.json new file mode 100644 index 0000000..4365be6 --- /dev/null +++ b/ui/elm-stuff/generated-code/elm-community/elm-test/0.19.1-revision12/elm.json @@ -0,0 +1,31 @@ +{ + "type": "application", + "source-directories": [ + "src", + "../../../../../../../../../../../nix/store/dbq8fjgrkwz7lfixlg7lzrdma0a6msv8-elm-test-0.19.1-revision12/lib/node_modules/elm-test/elm/src", + "../../../../../src" + ], + "elm-version": "0.19.1", + "dependencies": { + "direct": { + "elm/browser": "1.0.2", + "elm/core": "1.0.5", + "elm/html": "1.0.0", + "elm/http": "2.0.0", + "elm/json": "1.1.3", + "elm/random": "1.0.0", + "elm/time": "1.0.0", + "elm/url": "1.0.0", + "mdgriffith/elm-ui": "1.1.8" + }, + "indirect": { + "elm/bytes": "1.0.8", + "elm/file": "1.0.5", + "elm/virtual-dom": "1.0.3" + } + }, + "test-dependencies": { + "direct": {}, + "indirect": {} + } +} \ No newline at end of file diff --git a/ui/elm.js b/ui/elm.js index fb50992..ea8ab8e 100644 --- a/ui/elm.js +++ b/ui/elm.js @@ -4582,6 +4582,29 @@ var _Bitwise_shiftRightZfBy = F2(function(offset, a) { return a >>> offset; }); + + +function _Url_percentEncode(string) +{ + return encodeURIComponent(string); +} + +function _Url_percentDecode(string) +{ + try + { + return $elm$core$Maybe$Just(decodeURIComponent(string)); + } + catch (e) + { + return $elm$core$Maybe$Nothing; + } +}var $author$project$Types$LinkClicked = function (a) { + return {$: 'LinkClicked', a: a}; +}; +var $author$project$Types$UrlChanged = function (a) { + return {$: 'UrlChanged', a: a}; +}; var $elm$core$Basics$EQ = {$: 'EQ'}; var $elm$core$Basics$GT = {$: 'GT'}; var $elm$core$Basics$LT = {$: 'LT'}; @@ -5370,9 +5393,9 @@ var $elm$core$Task$perform = F2( $elm$core$Task$Perform( A2($elm$core$Task$map, toMessage, task))); }); -var $elm$browser$Browser$element = _Browser_element; -var $author$project$Main$FetchDataHandler = function (a) { - return {$: 'FetchDataHandler', a: a}; +var $elm$browser$Browser$application = _Browser_application; +var $author$project$Types$FetchLessons = function (a) { + return {$: 'FetchLessons', a: a}; }; var $elm$json$Json$Decode$decodeString = _Json_runOnString; var $elm$http$Http$BadStatus_ = F2( @@ -6161,13 +6184,6 @@ var $elm$http$Http$get = function (r) { return $elm$http$Http$request( {body: $elm$http$Http$emptyBody, expect: r.expect, headers: _List_Nil, method: 'GET', timeout: $elm$core$Maybe$Nothing, tracker: $elm$core$Maybe$Nothing, url: r.url}); }; -var $author$project$Api$ErrorResponse = function (a) { - return {$: 'ErrorResponse', a: a}; -}; -var $author$project$Api$OkResponse = function (a) { - return {$: 'OkResponse', a: a}; -}; -var $elm$json$Json$Decode$field = _Json_decodeField; var $elm$json$Json$Decode$andThen = _Json_andThen; var $author$project$Api$convertKeysToIntDict = function (stringKeyedDict) { return $elm$json$Json$Decode$succeed( @@ -6215,14 +6231,15 @@ var $elm$json$Json$Decode$dict = function (decoder) { $elm$core$Dict$fromList, $elm$json$Json$Decode$keyValuePairs(decoder)); }; -var $author$project$Api$Lesson = F3( +var $author$project$Types$Lesson = F3( function (text, id, cards) { return {cards: cards, id: id, text: text}; }); -var $author$project$Api$Card = F3( +var $author$project$Types$Card = F3( function (text, note, id) { return {id: id, note: note, text: text}; }); +var $elm$json$Json$Decode$field = _Json_decodeField; var $elm$json$Json$Decode$int = _Json_decodeInt; var $elm$json$Json$Decode$map3 = _Json_map3; var $elm$json$Json$Decode$oneOf = _Json_oneOf; @@ -6237,7 +6254,7 @@ var $elm$json$Json$Decode$maybe = function (decoder) { var $elm$json$Json$Decode$string = _Json_decodeString; var $author$project$Api$cardDecoder = A4( $elm$json$Json$Decode$map3, - $author$project$Api$Card, + $author$project$Types$Card, A2($elm$json$Json$Decode$field, 'text', $elm$json$Json$Decode$string), A2( $elm$json$Json$Decode$field, @@ -6247,7 +6264,7 @@ var $author$project$Api$cardDecoder = A4( var $elm$json$Json$Decode$list = _Json_decodeList; var $author$project$Api$lessonDecoder = A4( $elm$json$Json$Decode$map3, - $author$project$Api$Lesson, + $author$project$Types$Lesson, A2($elm$json$Json$Decode$field, 'text', $elm$json$Json$Decode$string), A2($elm$json$Json$Decode$field, 'id', $elm$json$Json$Decode$int), A2( @@ -6258,63 +6275,122 @@ var $author$project$Api$lessonsDecoder = A2( $elm$json$Json$Decode$andThen, $author$project$Api$convertKeysToIntDict, $elm$json$Json$Decode$dict($author$project$Api$lessonDecoder)); -var $author$project$Api$serverResponseDecoder = $elm$json$Json$Decode$oneOf( - _List_fromArray( - [ - A2( - $elm$json$Json$Decode$map, - $author$project$Api$OkResponse, - A2($elm$json$Json$Decode$field, 'ok', $author$project$Api$lessonsDecoder)), - A2( - $elm$json$Json$Decode$map, - $author$project$Api$ErrorResponse, - A2($elm$json$Json$Decode$field, 'error', $elm$json$Json$Decode$string)) - ])); -var $author$project$Api$fetchLessons = function (toMsg) { - return $elm$http$Http$get( - { - expect: A2($elm$http$Http$expectJson, toMsg, $author$project$Api$serverResponseDecoder), - url: 'http://localhost:3000/api/lessons' - }); +var $author$project$Types$ErrorResponse = function (a) { + return {$: 'ErrorResponse', a: a}; }; -var $author$project$Main$Lessons = {$: 'Lessons'}; +var $author$project$Types$OkResponse = function (a) { + return {$: 'OkResponse', a: a}; +}; +var $author$project$Api$serverResponseDecoder = function (okDecoder) { + return $elm$json$Json$Decode$oneOf( + _List_fromArray( + [ + A2( + $elm$json$Json$Decode$map, + $author$project$Types$OkResponse, + A2($elm$json$Json$Decode$field, 'ok', okDecoder)), + A2( + $elm$json$Json$Decode$map, + $author$project$Types$ErrorResponse, + A2($elm$json$Json$Decode$field, 'error', $elm$json$Json$Decode$string)) + ])); +}; +var $author$project$Api$fetchLessons = $elm$http$Http$get( + { + expect: A2( + $elm$http$Http$expectJson, + $author$project$Types$FetchLessons, + $author$project$Api$serverResponseDecoder($author$project$Api$lessonsDecoder)), + url: 'http://localhost:3000/api/lessons' + }); var $author$project$Main$sampleLessons = $elm$core$Dict$fromList(_List_Nil); -var $author$project$Main$initialState = {isLoading: false, lessons: $author$project$Main$sampleLessons, tab: $author$project$Main$Lessons}; +var $author$project$Main$initialState = F2( + function (url, key) { + return {isLoading: false, key: key, lessons: $author$project$Main$sampleLessons, url: url}; + }); var $elm$core$Debug$log = _Debug_log; -var $author$project$Main$init = function (flags) { - return function (_v1) { - return _Utils_Tuple2( - $author$project$Main$initialState, - $author$project$Api$fetchLessons($author$project$Main$FetchDataHandler)); - }( - function (_v0) { - return A2($elm$core$Debug$log, 'Initial State', $author$project$Main$initialState); +var $author$project$Main$init = F3( + function (flags, url, key) { + return function (_v0) { + return _Utils_Tuple2( + A2($author$project$Main$initialState, url, key), + $author$project$Api$fetchLessons); }( - A2($elm$core$Debug$log, 'Init flags', flags))); -}; + A2($elm$core$Debug$log, 'Init flags', flags)); + }); var $elm$core$Platform$Sub$batch = _Platform_batch; var $elm$core$Platform$Sub$none = $elm$core$Platform$Sub$batch(_List_Nil); +var $author$project$Main$subscriptions = function (_v0) { + return $elm$core$Platform$Sub$none; +}; +var $elm$browser$Browser$Navigation$load = _Browser_load; var $elm$core$Platform$Cmd$batch = _Platform_batch; var $elm$core$Platform$Cmd$none = $elm$core$Platform$Cmd$batch(_List_Nil); +var $elm$browser$Browser$Navigation$pushUrl = _Browser_pushUrl; +var $elm$url$Url$addPort = F2( + function (maybePort, starter) { + if (maybePort.$ === 'Nothing') { + return starter; + } else { + var port_ = maybePort.a; + return starter + (':' + $elm$core$String$fromInt(port_)); + } + }); +var $elm$url$Url$addPrefixed = F3( + function (prefix, maybeSegment, starter) { + if (maybeSegment.$ === 'Nothing') { + return starter; + } else { + var segment = maybeSegment.a; + return _Utils_ap( + starter, + _Utils_ap(prefix, segment)); + } + }); +var $elm$url$Url$toString = function (url) { + var http = function () { + var _v0 = url.protocol; + if (_v0.$ === 'Http') { + return 'http://'; + } else { + return 'https://'; + } + }(); + return A3( + $elm$url$Url$addPrefixed, + '#', + url.fragment, + A3( + $elm$url$Url$addPrefixed, + '?', + url.query, + _Utils_ap( + A2( + $elm$url$Url$addPort, + url.port_, + _Utils_ap(http, url.host)), + url.path))); +}; var $author$project$Main$update = F2( function (msg, model) { - if (msg.$ === 'UserSelectedTab') { - var t = msg.a; - return _Utils_Tuple2( - _Utils_update( - model, - {tab: t}), - $elm$core$Platform$Cmd$none); - } else { - if (msg.a.$ === 'Ok') { - var serres = msg.a.a; - if (serres.$ === 'OkResponse') { - var lessons = serres.a; - return _Utils_Tuple2( - _Utils_update( - model, - {isLoading: false, lessons: lessons}), - $elm$core$Platform$Cmd$none); + switch (msg.$) { + case 'FetchLessons': + if (msg.a.$ === 'Ok') { + var serres = msg.a.a; + if (serres.$ === 'OkResponse') { + var lessons = serres.a; + return _Utils_Tuple2( + _Utils_update( + model, + {isLoading: false, lessons: lessons}), + $elm$core$Platform$Cmd$none); + } else { + return _Utils_Tuple2( + _Utils_update( + model, + {isLoading: false}), + $elm$core$Platform$Cmd$none); + } } else { return _Utils_Tuple2( _Utils_update( @@ -6322,17 +6398,53 @@ var $author$project$Main$update = F2( {isLoading: false}), $elm$core$Platform$Cmd$none); } - } else { + case 'FetchLesson': + var res = msg.a; return _Utils_Tuple2( _Utils_update( model, {isLoading: false}), $elm$core$Platform$Cmd$none); - } + case 'LinkClicked': + var urlRequest = msg.a; + var _v2 = A2($elm$core$Debug$log, 'url request', urlRequest); + if (urlRequest.$ === 'Internal') { + var url = urlRequest.a; + return _Utils_Tuple2( + model, + A2( + $elm$browser$Browser$Navigation$pushUrl, + model.key, + $elm$url$Url$toString(url))); + } else { + var href = urlRequest.a; + return _Utils_Tuple2( + model, + $elm$browser$Browser$Navigation$load(href)); + } + default: + var url = msg.a; + return _Utils_Tuple2( + _Utils_update( + model, + {url: url}), + $elm$core$Platform$Cmd$none); } }); -var $author$project$Main$Pronunciation = {$: 'Pronunciation'}; -var $author$project$Main$Words = {$: 'Words'}; +var $author$project$Router$NotFound = {$: 'NotFound'}; +var $author$project$Types$FetchLesson = function (a) { + return {$: 'FetchLesson', a: a}; +}; +var $author$project$Api$fetchLesson = function (num) { + return $elm$http$Http$get( + { + expect: A2( + $elm$http$Http$expectJson, + $author$project$Types$FetchLesson, + $author$project$Api$serverResponseDecoder($author$project$Api$lessonDecoder)), + url: 'http://localhost:3000/api/lesson/' + $elm$core$String$fromInt(num) + }); +}; var $mdgriffith$elm_ui$Internal$Model$AlignX = function (a) { return {$: 'AlignX', a: a}; }; @@ -6341,12 +6453,12 @@ var $mdgriffith$elm_ui$Element$centerX = $mdgriffith$elm_ui$Internal$Model$Align var $mdgriffith$elm_ui$Internal$Model$Unkeyed = function (a) { return {$: 'Unkeyed', a: a}; }; -var $mdgriffith$elm_ui$Internal$Model$AsColumn = {$: 'AsColumn'}; -var $mdgriffith$elm_ui$Internal$Model$asColumn = $mdgriffith$elm_ui$Internal$Model$AsColumn; -var $mdgriffith$elm_ui$Internal$Style$classes = {above: 'a', active: 'atv', alignBottom: 'ab', alignCenterX: 'cx', alignCenterY: 'cy', alignContainerBottom: 'acb', alignContainerCenterX: 'accx', alignContainerCenterY: 'accy', alignContainerRight: 'acr', alignLeft: 'al', alignRight: 'ar', alignTop: 'at', alignedHorizontally: 'ah', alignedVertically: 'av', any: 's', behind: 'bh', below: 'b', bold: 'w7', borderDashed: 'bd', borderDotted: 'bdt', borderNone: 'bn', borderSolid: 'bs', capturePointerEvents: 'cpe', clip: 'cp', clipX: 'cpx', clipY: 'cpy', column: 'c', container: 'ctr', contentBottom: 'cb', contentCenterX: 'ccx', contentCenterY: 'ccy', contentLeft: 'cl', contentRight: 'cr', contentTop: 'ct', cursorPointer: 'cptr', cursorText: 'ctxt', focus: 'fcs', focusedWithin: 'focus-within', fullSize: 'fs', grid: 'g', hasBehind: 'hbh', heightContent: 'hc', heightExact: 'he', heightFill: 'hf', heightFillPortion: 'hfp', hover: 'hv', imageContainer: 'ic', inFront: 'fr', inputLabel: 'lbl', inputMultiline: 'iml', inputMultilineFiller: 'imlf', inputMultilineParent: 'imlp', inputMultilineWrapper: 'implw', inputText: 'it', italic: 'i', link: 'lnk', nearby: 'nb', noTextSelection: 'notxt', onLeft: 'ol', onRight: 'or', opaque: 'oq', overflowHidden: 'oh', page: 'pg', paragraph: 'p', passPointerEvents: 'ppe', root: 'ui', row: 'r', scrollbars: 'sb', scrollbarsX: 'sbx', scrollbarsY: 'sby', seButton: 'sbt', single: 'e', sizeByCapital: 'cap', spaceEvenly: 'sev', strike: 'sk', text: 't', textCenter: 'tc', textExtraBold: 'w8', textExtraLight: 'w2', textHeavy: 'w9', textJustify: 'tj', textJustifyAll: 'tja', textLeft: 'tl', textLight: 'w3', textMedium: 'w5', textNormalWeight: 'w4', textRight: 'tr', textSemiBold: 'w6', textThin: 'w1', textUnitalicized: 'tun', transition: 'ts', transparent: 'clr', underline: 'u', widthContent: 'wc', widthExact: 'we', widthFill: 'wf', widthFillPortion: 'wfp', wrapped: 'wrp'}; +var $mdgriffith$elm_ui$Internal$Model$AsEl = {$: 'AsEl'}; +var $mdgriffith$elm_ui$Internal$Model$asEl = $mdgriffith$elm_ui$Internal$Model$AsEl; var $mdgriffith$elm_ui$Internal$Model$Generic = {$: 'Generic'}; var $mdgriffith$elm_ui$Internal$Model$div = $mdgriffith$elm_ui$Internal$Model$Generic; var $mdgriffith$elm_ui$Internal$Model$NoNearbyChildren = {$: 'NoNearbyChildren'}; +var $mdgriffith$elm_ui$Internal$Style$classes = {above: 'a', active: 'atv', alignBottom: 'ab', alignCenterX: 'cx', alignCenterY: 'cy', alignContainerBottom: 'acb', alignContainerCenterX: 'accx', alignContainerCenterY: 'accy', alignContainerRight: 'acr', alignLeft: 'al', alignRight: 'ar', alignTop: 'at', alignedHorizontally: 'ah', alignedVertically: 'av', any: 's', behind: 'bh', below: 'b', bold: 'w7', borderDashed: 'bd', borderDotted: 'bdt', borderNone: 'bn', borderSolid: 'bs', capturePointerEvents: 'cpe', clip: 'cp', clipX: 'cpx', clipY: 'cpy', column: 'c', container: 'ctr', contentBottom: 'cb', contentCenterX: 'ccx', contentCenterY: 'ccy', contentLeft: 'cl', contentRight: 'cr', contentTop: 'ct', cursorPointer: 'cptr', cursorText: 'ctxt', focus: 'fcs', focusedWithin: 'focus-within', fullSize: 'fs', grid: 'g', hasBehind: 'hbh', heightContent: 'hc', heightExact: 'he', heightFill: 'hf', heightFillPortion: 'hfp', hover: 'hv', imageContainer: 'ic', inFront: 'fr', inputLabel: 'lbl', inputMultiline: 'iml', inputMultilineFiller: 'imlf', inputMultilineParent: 'imlp', inputMultilineWrapper: 'implw', inputText: 'it', italic: 'i', link: 'lnk', nearby: 'nb', noTextSelection: 'notxt', onLeft: 'ol', onRight: 'or', opaque: 'oq', overflowHidden: 'oh', page: 'pg', paragraph: 'p', passPointerEvents: 'ppe', root: 'ui', row: 'r', scrollbars: 'sb', scrollbarsX: 'sbx', scrollbarsY: 'sby', seButton: 'sbt', single: 'e', sizeByCapital: 'cap', spaceEvenly: 'sev', strike: 'sk', text: 't', textCenter: 'tc', textExtraBold: 'w8', textExtraLight: 'w2', textHeavy: 'w9', textJustify: 'tj', textJustifyAll: 'tja', textLeft: 'tl', textLight: 'w3', textMedium: 'w5', textNormalWeight: 'w4', textRight: 'tr', textSemiBold: 'w6', textThin: 'w1', textUnitalicized: 'tun', transition: 'ts', transparent: 'clr', underline: 'u', widthContent: 'wc', widthExact: 'we', widthFill: 'wf', widthFillPortion: 'wfp', wrapped: 'wrp'}; var $mdgriffith$elm_ui$Internal$Model$columnClass = $mdgriffith$elm_ui$Internal$Style$classes.any + (' ' + $mdgriffith$elm_ui$Internal$Style$classes.column); var $mdgriffith$elm_ui$Internal$Model$gridClass = $mdgriffith$elm_ui$Internal$Style$classes.any + (' ' + $mdgriffith$elm_ui$Internal$Style$classes.grid); var $mdgriffith$elm_ui$Internal$Model$pageClass = $mdgriffith$elm_ui$Internal$Style$classes.any + (' ' + $mdgriffith$elm_ui$Internal$Style$classes.page); @@ -6443,8 +6555,6 @@ var $mdgriffith$elm_ui$Internal$Model$addKeyedChildren = F3( inFront))); } }); -var $mdgriffith$elm_ui$Internal$Model$AsEl = {$: 'AsEl'}; -var $mdgriffith$elm_ui$Internal$Model$asEl = $mdgriffith$elm_ui$Internal$Model$AsEl; var $mdgriffith$elm_ui$Internal$Model$AsParagraph = {$: 'AsParagraph'}; var $mdgriffith$elm_ui$Internal$Model$asParagraph = $mdgriffith$elm_ui$Internal$Model$AsParagraph; var $mdgriffith$elm_ui$Internal$Flag$Flag = function (a) { @@ -11794,37 +11904,12 @@ var $mdgriffith$elm_ui$Internal$Model$Height = function (a) { return {$: 'Height', a: a}; }; var $mdgriffith$elm_ui$Element$height = $mdgriffith$elm_ui$Internal$Model$Height; -var $mdgriffith$elm_ui$Internal$Model$Attr = function (a) { - return {$: 'Attr', a: a}; -}; -var $mdgriffith$elm_ui$Internal$Model$htmlClass = function (cls) { - return $mdgriffith$elm_ui$Internal$Model$Attr( - $elm$html$Html$Attributes$class(cls)); -}; var $mdgriffith$elm_ui$Internal$Model$Content = {$: 'Content'}; var $mdgriffith$elm_ui$Element$shrink = $mdgriffith$elm_ui$Internal$Model$Content; var $mdgriffith$elm_ui$Internal$Model$Width = function (a) { return {$: 'Width', a: a}; }; var $mdgriffith$elm_ui$Element$width = $mdgriffith$elm_ui$Internal$Model$Width; -var $mdgriffith$elm_ui$Element$column = F2( - function (attrs, children) { - return A4( - $mdgriffith$elm_ui$Internal$Model$element, - $mdgriffith$elm_ui$Internal$Model$asColumn, - $mdgriffith$elm_ui$Internal$Model$div, - A2( - $elm$core$List$cons, - $mdgriffith$elm_ui$Internal$Model$htmlClass($mdgriffith$elm_ui$Internal$Style$classes.contentTop + (' ' + $mdgriffith$elm_ui$Internal$Style$classes.contentLeft)), - A2( - $elm$core$List$cons, - $mdgriffith$elm_ui$Element$height($mdgriffith$elm_ui$Element$shrink), - A2( - $elm$core$List$cons, - $mdgriffith$elm_ui$Element$width($mdgriffith$elm_ui$Element$shrink), - attrs))), - $mdgriffith$elm_ui$Internal$Model$Unkeyed(children)); - }); var $mdgriffith$elm_ui$Element$el = F2( function (attrs, child) { return A4( @@ -11842,10 +11927,13 @@ var $mdgriffith$elm_ui$Element$el = F2( _List_fromArray( [child]))); }); -var $mdgriffith$elm_ui$Internal$Model$Fill = function (a) { - return {$: 'Fill', a: a}; +var $mdgriffith$elm_ui$Internal$Model$Attr = function (a) { + return {$: 'Attr', a: a}; +}; +var $mdgriffith$elm_ui$Internal$Model$htmlClass = function (cls) { + return $mdgriffith$elm_ui$Internal$Model$Attr( + $elm$html$Html$Attributes$class(cls)); }; -var $mdgriffith$elm_ui$Element$fill = $mdgriffith$elm_ui$Internal$Model$Fill(1); var $mdgriffith$elm_ui$Internal$Model$OnlyDynamic = F2( function (a, b) { return {$: 'OnlyDynamic', a: a, b: b}; @@ -12123,25 +12211,182 @@ var $mdgriffith$elm_ui$Element$layoutWith = F3( }); var $mdgriffith$elm_ui$Element$layout = $mdgriffith$elm_ui$Element$layoutWith( {options: _List_Nil}); +var $mdgriffith$elm_ui$Internal$Model$PaddingStyle = F5( + function (a, b, c, d, e) { + return {$: 'PaddingStyle', a: a, b: b, c: c, d: d, e: e}; + }); +var $mdgriffith$elm_ui$Internal$Flag$padding = $mdgriffith$elm_ui$Internal$Flag$flag(2); +var $mdgriffith$elm_ui$Element$padding = function (x) { + var f = x; + return A2( + $mdgriffith$elm_ui$Internal$Model$StyleClass, + $mdgriffith$elm_ui$Internal$Flag$padding, + A5( + $mdgriffith$elm_ui$Internal$Model$PaddingStyle, + 'p-' + $elm$core$String$fromInt(x), + f, + f, + f, + f)); +}; var $mdgriffith$elm_ui$Internal$Model$Text = function (a) { return {$: 'Text', a: a}; }; var $mdgriffith$elm_ui$Element$text = function (content) { return $mdgriffith$elm_ui$Internal$Model$Text(content); }; -var $author$project$Main$lessonPreview = function (lesson) { - return A2( +var $author$project$Router$loadingPage = A2( + $mdgriffith$elm_ui$Element$layout, + _List_Nil, + A2( $mdgriffith$elm_ui$Element$el, + _List_fromArray( + [ + $mdgriffith$elm_ui$Element$centerX, + $mdgriffith$elm_ui$Element$padding(20) + ]), + $mdgriffith$elm_ui$Element$text('Loading lesson...'))); +var $mdgriffith$elm_ui$Internal$Model$Fill = function (a) { + return {$: 'Fill', a: a}; +}; +var $mdgriffith$elm_ui$Element$fill = $mdgriffith$elm_ui$Internal$Model$Fill(1); +var $mdgriffith$elm_ui$Internal$Model$AsColumn = {$: 'AsColumn'}; +var $mdgriffith$elm_ui$Internal$Model$asColumn = $mdgriffith$elm_ui$Internal$Model$AsColumn; +var $mdgriffith$elm_ui$Element$column = F2( + function (attrs, children) { + return A4( + $mdgriffith$elm_ui$Internal$Model$element, + $mdgriffith$elm_ui$Internal$Model$asColumn, + $mdgriffith$elm_ui$Internal$Model$div, + A2( + $elm$core$List$cons, + $mdgriffith$elm_ui$Internal$Model$htmlClass($mdgriffith$elm_ui$Internal$Style$classes.contentTop + (' ' + $mdgriffith$elm_ui$Internal$Style$classes.contentLeft)), + A2( + $elm$core$List$cons, + $mdgriffith$elm_ui$Element$height($mdgriffith$elm_ui$Element$shrink), + A2( + $elm$core$List$cons, + $mdgriffith$elm_ui$Element$width($mdgriffith$elm_ui$Element$shrink), + attrs))), + $mdgriffith$elm_ui$Internal$Model$Unkeyed(children)); + }); +var $elm$html$Html$Attributes$href = function (url) { + return A2( + $elm$html$Html$Attributes$stringProperty, + 'href', + _VirtualDom_noJavaScriptUri(url)); +}; +var $elm$html$Html$Attributes$rel = _VirtualDom_attribute('rel'); +var $mdgriffith$elm_ui$Element$link = F2( + function (attrs, _v0) { + var label = _v0.label; + var url = _v0.url; + return A4( + $mdgriffith$elm_ui$Internal$Model$element, + $mdgriffith$elm_ui$Internal$Model$asEl, + $mdgriffith$elm_ui$Internal$Model$NodeName('a'), + A2( + $elm$core$List$cons, + $mdgriffith$elm_ui$Internal$Model$Attr( + $elm$html$Html$Attributes$href(url)), + A2( + $elm$core$List$cons, + $mdgriffith$elm_ui$Internal$Model$Attr( + $elm$html$Html$Attributes$rel('noopener noreferrer')), + A2( + $elm$core$List$cons, + $mdgriffith$elm_ui$Element$width($mdgriffith$elm_ui$Element$shrink), + A2( + $elm$core$List$cons, + $mdgriffith$elm_ui$Element$height($mdgriffith$elm_ui$Element$shrink), + A2( + $elm$core$List$cons, + $mdgriffith$elm_ui$Internal$Model$htmlClass($mdgriffith$elm_ui$Internal$Style$classes.contentCenterX + (' ' + ($mdgriffith$elm_ui$Internal$Style$classes.contentCenterY + (' ' + $mdgriffith$elm_ui$Internal$Style$classes.link)))), + attrs))))), + $mdgriffith$elm_ui$Internal$Model$Unkeyed( + _List_fromArray( + [label]))); + }); +var $author$project$Lessonpage$lessonView = function (lesson) { + return A2( + $mdgriffith$elm_ui$Element$link, _List_Nil, + { + label: A2( + $mdgriffith$elm_ui$Element$el, + _List_Nil, + A2( + $mdgriffith$elm_ui$Element$column, + _List_Nil, + _List_fromArray( + [ + $mdgriffith$elm_ui$Element$text( + 'Lesson: ' + $elm$core$String$fromInt(lesson.id)), + $mdgriffith$elm_ui$Element$text(lesson.text) + ]))), + url: '/lesson' + $elm$core$String$fromInt(lesson.id) + }); +}; +var $author$project$Lessonpage$page = function (lesson) { + var _v0 = A2($elm$core$Debug$log, 'lesson', lesson); + return A2( + $mdgriffith$elm_ui$Element$layout, + _List_fromArray( + [ + $mdgriffith$elm_ui$Element$width($mdgriffith$elm_ui$Element$fill), + $mdgriffith$elm_ui$Element$height($mdgriffith$elm_ui$Element$fill) + ]), A2( - $mdgriffith$elm_ui$Element$column, - _List_Nil, + $mdgriffith$elm_ui$Element$el, _List_fromArray( - [ - $mdgriffith$elm_ui$Element$text( - 'Lesson: ' + $elm$core$String$fromInt(lesson.id)), - $mdgriffith$elm_ui$Element$text(lesson.text) - ]))); + [$mdgriffith$elm_ui$Element$centerX]), + $author$project$Lessonpage$lessonView(lesson))); +}; +var $author$project$Router$lessonLoader = F2( + function (num, model) { + var _v0 = A2($elm$core$Dict$get, num, model.lessons); + if (_v0.$ === 'Just') { + var lesson = _v0.a; + return _Utils_Tuple3( + model, + $elm$core$Platform$Cmd$none, + $author$project$Lessonpage$page(lesson)); + } else { + return _Utils_Tuple3( + _Utils_update( + model, + {isLoading: true}), + $author$project$Api$fetchLesson(num), + $author$project$Router$loadingPage); + } + }); +var $author$project$Router$notFound = A2( + $mdgriffith$elm_ui$Element$layout, + _List_Nil, + A2( + $mdgriffith$elm_ui$Element$el, + _List_fromArray( + [$mdgriffith$elm_ui$Element$centerX]), + $mdgriffith$elm_ui$Element$text('404'))); +var $author$project$Homepage$lessonPreview = function (lesson) { + return A2( + $mdgriffith$elm_ui$Element$link, + _List_Nil, + { + label: A2( + $mdgriffith$elm_ui$Element$el, + _List_Nil, + A2( + $mdgriffith$elm_ui$Element$column, + _List_Nil, + _List_fromArray( + [ + $mdgriffith$elm_ui$Element$text( + 'Lesson: ' + $elm$core$String$fromInt(lesson.id)), + $mdgriffith$elm_ui$Element$text(lesson.text) + ]))), + url: '/lesson/' + $elm$core$String$fromInt(lesson.id) + }); }; var $elm$core$Dict$values = function (dict) { return A3( @@ -12153,225 +12398,16 @@ var $elm$core$Dict$values = function (dict) { _List_Nil, dict); }; -var $author$project$Main$lessonsView = function (lessons) { +var $author$project$Homepage$lessonsView = function (lessons) { return A2( $mdgriffith$elm_ui$Element$column, _List_Nil, A2( $elm$core$List$map, - $author$project$Main$lessonPreview, + $author$project$Homepage$lessonPreview, $elm$core$Dict$values(lessons))); }; -var $mdgriffith$elm_ui$Internal$Model$AsRow = {$: 'AsRow'}; -var $mdgriffith$elm_ui$Internal$Model$asRow = $mdgriffith$elm_ui$Internal$Model$AsRow; -var $mdgriffith$elm_ui$Element$row = F2( - function (attrs, children) { - return A4( - $mdgriffith$elm_ui$Internal$Model$element, - $mdgriffith$elm_ui$Internal$Model$asRow, - $mdgriffith$elm_ui$Internal$Model$div, - A2( - $elm$core$List$cons, - $mdgriffith$elm_ui$Internal$Model$htmlClass($mdgriffith$elm_ui$Internal$Style$classes.contentLeft + (' ' + $mdgriffith$elm_ui$Internal$Style$classes.contentCenterY)), - A2( - $elm$core$List$cons, - $mdgriffith$elm_ui$Element$width($mdgriffith$elm_ui$Element$shrink), - A2( - $elm$core$List$cons, - $mdgriffith$elm_ui$Element$height($mdgriffith$elm_ui$Element$shrink), - attrs))), - $mdgriffith$elm_ui$Internal$Model$Unkeyed(children)); - }); -var $author$project$Main$UserSelectedTab = function (a) { - return {$: 'UserSelectedTab', a: a}; -}; -var $mdgriffith$elm_ui$Internal$Model$AlignY = function (a) { - return {$: 'AlignY', a: a}; -}; -var $mdgriffith$elm_ui$Internal$Model$CenterY = {$: 'CenterY'}; -var $mdgriffith$elm_ui$Element$centerY = $mdgriffith$elm_ui$Internal$Model$AlignY($mdgriffith$elm_ui$Internal$Model$CenterY); -var $mdgriffith$elm_ui$Internal$Flag$borderColor = $mdgriffith$elm_ui$Internal$Flag$flag(28); -var $mdgriffith$elm_ui$Element$Border$color = function (clr) { - return A2( - $mdgriffith$elm_ui$Internal$Model$StyleClass, - $mdgriffith$elm_ui$Internal$Flag$borderColor, - A3( - $mdgriffith$elm_ui$Internal$Model$Colored, - 'bc-' + $mdgriffith$elm_ui$Internal$Model$formatColorClass(clr), - 'border-color', - clr)); -}; -var $mdgriffith$elm_ui$Element$rgb255 = F3( - function (red, green, blue) { - return A4($mdgriffith$elm_ui$Internal$Model$Rgba, red / 255, green / 255, blue / 255, 1); - }); -var $author$project$Main$color = { - blue: A3($mdgriffith$elm_ui$Element$rgb255, 114, 159, 207), - darkCharcoal: A3($mdgriffith$elm_ui$Element$rgb255, 46, 52, 54), - lightBlue: A3($mdgriffith$elm_ui$Element$rgb255, 197, 232, 247), - lightGrey: A3($mdgriffith$elm_ui$Element$rgb255, 224, 224, 224), - white: A3($mdgriffith$elm_ui$Element$rgb255, 255, 255, 255) -}; -var $elm$core$Basics$composeL = F3( - function (g, f, x) { - return g( - f(x)); - }); -var $elm$virtual_dom$VirtualDom$Normal = function (a) { - return {$: 'Normal', a: a}; -}; -var $elm$virtual_dom$VirtualDom$on = _VirtualDom_on; -var $elm$html$Html$Events$on = F2( - function (event, decoder) { - return A2( - $elm$virtual_dom$VirtualDom$on, - event, - $elm$virtual_dom$VirtualDom$Normal(decoder)); - }); -var $elm$html$Html$Events$onClick = function (msg) { - return A2( - $elm$html$Html$Events$on, - 'click', - $elm$json$Json$Decode$succeed(msg)); -}; -var $mdgriffith$elm_ui$Element$Events$onClick = A2($elm$core$Basics$composeL, $mdgriffith$elm_ui$Internal$Model$Attr, $elm$html$Html$Events$onClick); -var $mdgriffith$elm_ui$Internal$Model$PaddingStyle = F5( - function (a, b, c, d, e) { - return {$: 'PaddingStyle', a: a, b: b, c: c, d: d, e: e}; - }); -var $mdgriffith$elm_ui$Internal$Flag$padding = $mdgriffith$elm_ui$Internal$Flag$flag(2); -var $mdgriffith$elm_ui$Internal$Model$paddingName = F4( - function (top, right, bottom, left) { - return 'pad-' + ($elm$core$String$fromInt(top) + ('-' + ($elm$core$String$fromInt(right) + ('-' + ($elm$core$String$fromInt(bottom) + ('-' + $elm$core$String$fromInt(left))))))); - }); -var $mdgriffith$elm_ui$Element$paddingEach = function (_v0) { - var left = _v0.left; - var bottom = _v0.bottom; - var right = _v0.right; - var top = _v0.top; - if (_Utils_eq(top, right) && (_Utils_eq(top, bottom) && _Utils_eq(top, left))) { - var topFloat = top; - return A2( - $mdgriffith$elm_ui$Internal$Model$StyleClass, - $mdgriffith$elm_ui$Internal$Flag$padding, - A5( - $mdgriffith$elm_ui$Internal$Model$PaddingStyle, - 'p-' + $elm$core$String$fromInt(top), - topFloat, - topFloat, - topFloat, - topFloat)); - } else { - return A2( - $mdgriffith$elm_ui$Internal$Model$StyleClass, - $mdgriffith$elm_ui$Internal$Flag$padding, - A5( - $mdgriffith$elm_ui$Internal$Model$PaddingStyle, - A4($mdgriffith$elm_ui$Internal$Model$paddingName, top, right, bottom, left), - top, - right, - bottom, - left)); - } -}; -var $mdgriffith$elm_ui$Internal$Flag$borderRound = $mdgriffith$elm_ui$Internal$Flag$flag(17); -var $mdgriffith$elm_ui$Element$Border$roundEach = function (_v0) { - var bottomRight = _v0.bottomRight; - var bottomLeft = _v0.bottomLeft; - var topRight = _v0.topRight; - var topLeft = _v0.topLeft; - return A2( - $mdgriffith$elm_ui$Internal$Model$StyleClass, - $mdgriffith$elm_ui$Internal$Flag$borderRound, - A3( - $mdgriffith$elm_ui$Internal$Model$Single, - 'br-' + ($elm$core$String$fromInt(topLeft) + ('-' + ($elm$core$String$fromInt(topRight) + ($elm$core$String$fromInt(bottomLeft) + ('-' + $elm$core$String$fromInt(bottomRight)))))), - 'border-radius', - $elm$core$String$fromInt(topLeft) + ('px ' + ($elm$core$String$fromInt(topRight) + ('px ' + ($elm$core$String$fromInt(bottomRight) + ('px ' + ($elm$core$String$fromInt(bottomLeft) + 'px')))))))); -}; -var $mdgriffith$elm_ui$Internal$Model$BorderWidth = F5( - function (a, b, c, d, e) { - return {$: 'BorderWidth', a: a, b: b, c: c, d: d, e: e}; - }); -var $mdgriffith$elm_ui$Element$Border$width = function (v) { - return A2( - $mdgriffith$elm_ui$Internal$Model$StyleClass, - $mdgriffith$elm_ui$Internal$Flag$borderWidth, - A5( - $mdgriffith$elm_ui$Internal$Model$BorderWidth, - 'b-' + $elm$core$String$fromInt(v), - v, - v, - v, - v)); -}; -var $mdgriffith$elm_ui$Element$Border$widthXY = F2( - function (x, y) { - return A2( - $mdgriffith$elm_ui$Internal$Model$StyleClass, - $mdgriffith$elm_ui$Internal$Flag$borderWidth, - A5( - $mdgriffith$elm_ui$Internal$Model$BorderWidth, - 'b-' + ($elm$core$String$fromInt(x) + ('-' + $elm$core$String$fromInt(y))), - y, - x, - y, - x)); - }); -var $mdgriffith$elm_ui$Element$Border$widthEach = function (_v0) { - var right = _v0.right; - var left = _v0.left; - var top = _v0.top; - var bottom = _v0.bottom; - return (_Utils_eq(top, bottom) && _Utils_eq(left, right)) ? (_Utils_eq(top, right) ? $mdgriffith$elm_ui$Element$Border$width(top) : A2($mdgriffith$elm_ui$Element$Border$widthXY, left, top)) : A2( - $mdgriffith$elm_ui$Internal$Model$StyleClass, - $mdgriffith$elm_ui$Internal$Flag$borderWidth, - A5( - $mdgriffith$elm_ui$Internal$Model$BorderWidth, - 'b-' + ($elm$core$String$fromInt(top) + ('-' + ($elm$core$String$fromInt(right) + ('-' + ($elm$core$String$fromInt(bottom) + ('-' + $elm$core$String$fromInt(left))))))), - top, - right, - bottom, - left)); -}; -var $author$project$Main$tabEl = F2( - function (tab, selectedTab) { - var isSelected = _Utils_eq(tab, selectedTab); - var padOffset = isSelected ? 0 : 2; - var corners = isSelected ? {bottomLeft: 0, bottomRight: 0, topLeft: 6, topRight: 6} : {bottomLeft: 0, bottomRight: 0, topLeft: 0, topRight: 0}; - var borderWidths = isSelected ? {bottom: 0, left: 2, right: 2, top: 2} : {bottom: 2, left: 0, right: 0, top: 0}; - return A2( - $mdgriffith$elm_ui$Element$el, - _List_fromArray( - [ - $mdgriffith$elm_ui$Element$Border$widthEach(borderWidths), - $mdgriffith$elm_ui$Element$Border$roundEach(corners), - $mdgriffith$elm_ui$Element$Border$color($author$project$Main$color.blue), - $mdgriffith$elm_ui$Element$Events$onClick( - $author$project$Main$UserSelectedTab(tab)) - ]), - A2( - $mdgriffith$elm_ui$Element$el, - _List_fromArray( - [ - $mdgriffith$elm_ui$Element$centerX, - $mdgriffith$elm_ui$Element$centerY, - $mdgriffith$elm_ui$Element$paddingEach( - {bottom: 10 - padOffset, left: 30, right: 30, top: 10 + padOffset}) - ]), - $mdgriffith$elm_ui$Element$text( - function () { - switch (tab.$) { - case 'Lessons': - return 'Lessons'; - case 'Words': - return 'Words'; - default: - return 'Audio'; - } - }()))); - }); -var $author$project$Main$view = function (model) { +var $author$project$Homepage$page = function (model) { return model.isLoading ? A2( $mdgriffith$elm_ui$Element$layout, _List_Nil, @@ -12383,34 +12419,298 @@ var $author$project$Main$view = function (model) { $mdgriffith$elm_ui$Element$height($mdgriffith$elm_ui$Element$fill) ]), A2( - $mdgriffith$elm_ui$Element$column, + $mdgriffith$elm_ui$Element$el, _List_fromArray( [$mdgriffith$elm_ui$Element$centerX]), - _List_fromArray( - [ - A2( - $mdgriffith$elm_ui$Element$row, - _List_Nil, - _List_fromArray( - [ - A2($author$project$Main$tabEl, $author$project$Main$Lessons, model.tab), - A2($author$project$Main$tabEl, $author$project$Main$Words, model.tab), - A2($author$project$Main$tabEl, $author$project$Main$Pronunciation, model.tab) - ])), - _Utils_eq(model.tab, $author$project$Main$Lessons) ? $author$project$Main$lessonsView(model.lessons) : A2( - $mdgriffith$elm_ui$Element$el, - _List_Nil, - $mdgriffith$elm_ui$Element$text('WIP')) - ]))); + $author$project$Homepage$lessonsView(model.lessons))); }; -var $author$project$Main$main = $elm$browser$Browser$element( - { - init: $author$project$Main$init, - subscriptions: function (_v0) { - return $elm$core$Platform$Sub$none; - }, - update: $author$project$Main$update, - view: $author$project$Main$view +var $elm$url$Url$Parser$State = F5( + function (visited, unvisited, params, frag, value) { + return {frag: frag, params: params, unvisited: unvisited, value: value, visited: visited}; }); +var $elm$url$Url$Parser$getFirstMatch = function (states) { + getFirstMatch: + while (true) { + if (!states.b) { + return $elm$core$Maybe$Nothing; + } else { + var state = states.a; + var rest = states.b; + var _v1 = state.unvisited; + if (!_v1.b) { + return $elm$core$Maybe$Just(state.value); + } else { + if ((_v1.a === '') && (!_v1.b.b)) { + return $elm$core$Maybe$Just(state.value); + } else { + var $temp$states = rest; + states = $temp$states; + continue getFirstMatch; + } + } + } + } +}; +var $elm$url$Url$Parser$removeFinalEmpty = function (segments) { + if (!segments.b) { + return _List_Nil; + } else { + if ((segments.a === '') && (!segments.b.b)) { + return _List_Nil; + } else { + var segment = segments.a; + var rest = segments.b; + return A2( + $elm$core$List$cons, + segment, + $elm$url$Url$Parser$removeFinalEmpty(rest)); + } + } +}; +var $elm$url$Url$Parser$preparePath = function (path) { + var _v0 = A2($elm$core$String$split, '/', path); + if (_v0.b && (_v0.a === '')) { + var segments = _v0.b; + return $elm$url$Url$Parser$removeFinalEmpty(segments); + } else { + var segments = _v0; + return $elm$url$Url$Parser$removeFinalEmpty(segments); + } +}; +var $elm$url$Url$Parser$addToParametersHelp = F2( + function (value, maybeList) { + if (maybeList.$ === 'Nothing') { + return $elm$core$Maybe$Just( + _List_fromArray( + [value])); + } else { + var list = maybeList.a; + return $elm$core$Maybe$Just( + A2($elm$core$List$cons, value, list)); + } + }); +var $elm$url$Url$percentDecode = _Url_percentDecode; +var $elm$url$Url$Parser$addParam = F2( + function (segment, dict) { + var _v0 = A2($elm$core$String$split, '=', segment); + if ((_v0.b && _v0.b.b) && (!_v0.b.b.b)) { + var rawKey = _v0.a; + var _v1 = _v0.b; + var rawValue = _v1.a; + var _v2 = $elm$url$Url$percentDecode(rawKey); + if (_v2.$ === 'Nothing') { + return dict; + } else { + var key = _v2.a; + var _v3 = $elm$url$Url$percentDecode(rawValue); + if (_v3.$ === 'Nothing') { + return dict; + } else { + var value = _v3.a; + return A3( + $elm$core$Dict$update, + key, + $elm$url$Url$Parser$addToParametersHelp(value), + dict); + } + } + } else { + return dict; + } + }); +var $elm$url$Url$Parser$prepareQuery = function (maybeQuery) { + if (maybeQuery.$ === 'Nothing') { + return $elm$core$Dict$empty; + } else { + var qry = maybeQuery.a; + return A3( + $elm$core$List$foldr, + $elm$url$Url$Parser$addParam, + $elm$core$Dict$empty, + A2($elm$core$String$split, '&', qry)); + } +}; +var $elm$url$Url$Parser$parse = F2( + function (_v0, url) { + var parser = _v0.a; + return $elm$url$Url$Parser$getFirstMatch( + parser( + A5( + $elm$url$Url$Parser$State, + _List_Nil, + $elm$url$Url$Parser$preparePath(url.path), + $elm$url$Url$Parser$prepareQuery(url.query), + url.fragment, + $elm$core$Basics$identity))); + }); +var $author$project$Router$Lesson = function (a) { + return {$: 'Lesson', a: a}; +}; +var $author$project$Router$Root = {$: 'Root'}; +var $elm$url$Url$Parser$Parser = function (a) { + return {$: 'Parser', a: a}; +}; +var $elm$url$Url$Parser$custom = F2( + function (tipe, stringToSomething) { + return $elm$url$Url$Parser$Parser( + function (_v0) { + var value = _v0.value; + var frag = _v0.frag; + var params = _v0.params; + var unvisited = _v0.unvisited; + var visited = _v0.visited; + if (!unvisited.b) { + return _List_Nil; + } else { + var next = unvisited.a; + var rest = unvisited.b; + var _v2 = stringToSomething(next); + if (_v2.$ === 'Just') { + var nextValue = _v2.a; + return _List_fromArray( + [ + A5( + $elm$url$Url$Parser$State, + A2($elm$core$List$cons, next, visited), + rest, + params, + frag, + value(nextValue)) + ]); + } else { + return _List_Nil; + } + } + }); + }); +var $elm$url$Url$Parser$int = A2($elm$url$Url$Parser$custom, 'NUMBER', $elm$core$String$toInt); +var $elm$url$Url$Parser$mapState = F2( + function (func, _v0) { + var value = _v0.value; + var frag = _v0.frag; + var params = _v0.params; + var unvisited = _v0.unvisited; + var visited = _v0.visited; + return A5( + $elm$url$Url$Parser$State, + visited, + unvisited, + params, + frag, + func(value)); + }); +var $elm$url$Url$Parser$map = F2( + function (subValue, _v0) { + var parseArg = _v0.a; + return $elm$url$Url$Parser$Parser( + function (_v1) { + var value = _v1.value; + var frag = _v1.frag; + var params = _v1.params; + var unvisited = _v1.unvisited; + var visited = _v1.visited; + return A2( + $elm$core$List$map, + $elm$url$Url$Parser$mapState(value), + parseArg( + A5($elm$url$Url$Parser$State, visited, unvisited, params, frag, subValue))); + }); + }); +var $elm$url$Url$Parser$oneOf = function (parsers) { + return $elm$url$Url$Parser$Parser( + function (state) { + return A2( + $elm$core$List$concatMap, + function (_v0) { + var parser = _v0.a; + return parser(state); + }, + parsers); + }); +}; +var $elm$url$Url$Parser$s = function (str) { + return $elm$url$Url$Parser$Parser( + function (_v0) { + var value = _v0.value; + var frag = _v0.frag; + var params = _v0.params; + var unvisited = _v0.unvisited; + var visited = _v0.visited; + if (!unvisited.b) { + return _List_Nil; + } else { + var next = unvisited.a; + var rest = unvisited.b; + return _Utils_eq(next, str) ? _List_fromArray( + [ + A5( + $elm$url$Url$Parser$State, + A2($elm$core$List$cons, next, visited), + rest, + params, + frag, + value) + ]) : _List_Nil; + } + }); +}; +var $elm$url$Url$Parser$slash = F2( + function (_v0, _v1) { + var parseBefore = _v0.a; + var parseAfter = _v1.a; + return $elm$url$Url$Parser$Parser( + function (state) { + return A2( + $elm$core$List$concatMap, + parseAfter, + parseBefore(state)); + }); + }); +var $elm$url$Url$Parser$top = $elm$url$Url$Parser$Parser( + function (state) { + return _List_fromArray( + [state]); + }); +var $author$project$Router$routeParser = $elm$url$Url$Parser$oneOf( + _List_fromArray( + [ + A2($elm$url$Url$Parser$map, $author$project$Router$Root, $elm$url$Url$Parser$top), + A2( + $elm$url$Url$Parser$map, + $author$project$Router$Lesson, + A2( + $elm$url$Url$Parser$slash, + $elm$url$Url$Parser$s('lesson'), + $elm$url$Url$Parser$int)) + ])); +var $author$project$Router$router = function (model) { + var route = A2( + $elm$core$Maybe$withDefault, + $author$project$Router$NotFound, + A2($elm$url$Url$Parser$parse, $author$project$Router$routeParser, model.url)); + switch (route.$) { + case 'Root': + return _Utils_Tuple3( + model, + $elm$core$Platform$Cmd$none, + $author$project$Homepage$page(model)); + case 'Lesson': + var num = route.a; + return A2($author$project$Router$lessonLoader, num, model); + default: + return _Utils_Tuple3(model, $elm$core$Platform$Cmd$none, $author$project$Router$notFound); + } +}; +var $author$project$Main$view = function (model) { + var _v0 = $author$project$Router$router(model); + var html = _v0.c; + return { + body: _List_fromArray( + [html]), + title: 'Prosody' + }; +}; +var $author$project$Main$main = $elm$browser$Browser$application( + {init: $author$project$Main$init, onUrlChange: $author$project$Types$UrlChanged, onUrlRequest: $author$project$Types$LinkClicked, subscriptions: $author$project$Main$subscriptions, update: $author$project$Main$update, view: $author$project$Main$view}); _Platform_export({'Main':{'init':$author$project$Main$main( $elm$json$Json$Decode$succeed(_Utils_Tuple0))(0)}});}(this)); \ No newline at end of file diff --git a/ui/elm.json b/ui/elm.json index 7cd88ec..b64e064 100644 --- a/ui/elm.json +++ b/ui/elm.json @@ -11,13 +11,14 @@ "elm/html": "1.0.0", "elm/http": "2.0.0", "elm/json": "1.1.3", + "elm/url": "1.0.0", + "elm-community/list-extra": "8.7.0", "mdgriffith/elm-ui": "1.1.8" }, "indirect": { "elm/bytes": "1.0.8", "elm/file": "1.0.5", "elm/time": "1.0.0", - "elm/url": "1.0.0", "elm/virtual-dom": "1.0.3" } }, diff --git a/ui/src/Api.elm b/ui/src/Api.elm index bcbec63..a509911 100644 --- a/ui/src/Api.elm +++ b/ui/src/Api.elm @@ -1,46 +1,22 @@ -module Api exposing (Card, Lesson, Lessons, ServerResponse(..), fetchLessons) +module Api exposing (addUser, fetchLesson, fetchLessons) import Dict exposing (Dict) import Http import Json.Decode as Decode +import Json.Encode as Encode +import Types exposing (Card, Lesson, Lessons, Msg(..), ServerResponse(..)) -- data types - - -type alias Card = - { text : String - , note : Maybe String - , id : Int - } - - -type alias Lesson = - { text : String - , id : Int - , cards : List Card - } - - -type alias Lessons = - Dict Int Lesson - - -type ServerResponse - = OkResponse Lessons - | ErrorResponse String - - - -- json decoders -serverResponseDecoder : Decode.Decoder ServerResponse -serverResponseDecoder = +serverResponseDecoder : Decode.Decoder t -> Decode.Decoder (ServerResponse t) +serverResponseDecoder okDecoder = Decode.oneOf [ Decode.map OkResponse - (Decode.field "ok" lessonsDecoder) + (Decode.field "ok" okDecoder) , Decode.map ErrorResponse (Decode.field "error" Decode.string) ] @@ -86,14 +62,43 @@ convertKeysToIntDict stringKeyedDict = +-- json encoders + + +newUserEncoder name creds = + Encode.object [ ( "name", Encode.string name ), ( "creds", Encode.string creds ) ] + + + -- http command -fetchLessons : (Result Http.Error ServerResponse -> msg) -> Cmd msg -fetchLessons toMsg = +fetchLessons : Cmd Msg +fetchLessons = Http.get { url = "http://localhost:3000/api/lessons" - , expect = Http.expectJson toMsg serverResponseDecoder + , expect = Http.expectJson FetchLessons (serverResponseDecoder lessonsDecoder) + } + + +fetchLesson : Int -> Cmd Msg +fetchLesson num = + Http.get + { url = "http://localhost:3000/api/lesson/" ++ String.fromInt num + , expect = Http.expectJson FetchLesson (serverResponseDecoder lessonDecoder) + } + + + +-- post requests + + +addUser : String -> String -> Cmd Msg +addUser name pw = + Http.post + { url = "http://localhost:3000/api/lessons" + , body = Http.jsonBody (newUserEncoder name pw) + , expect = Http.expectJson FetchLessons (serverResponseDecoder lessonsDecoder) } diff --git a/ui/src/Homepage.elm b/ui/src/Homepage.elm new file mode 100644 index 0000000..258d42e --- /dev/null +++ b/ui/src/Homepage.elm @@ -0,0 +1,109 @@ +module Homepage exposing (page) + +import Dict +import Element exposing (..) +import Html exposing (Html) +import Types exposing (Lesson, Lessons, Model, Msg(..)) + + + +-- local state +-- type Tab +-- = Lessons +-- | Words +-- | Pronunciation +-- tabEl : Tab -> Tab -> Element Msg +-- tabEl tab selectedTab = +-- let +-- isSelected = +-- tab == selectedTab +-- padOffset = +-- if isSelected then +-- 0 +-- else +-- 2 +-- borderWidths = +-- if isSelected then +-- { left = 2, top = 2, right = 2, bottom = 0 } +-- else +-- { bottom = 2, top = 0, left = 0, right = 0 } +-- corners = +-- if isSelected then +-- { topLeft = 6, topRight = 6, bottomLeft = 0, bottomRight = 0 } +-- else +-- { topLeft = 0, topRight = 0, bottomLeft = 0, bottomRight = 0 } +-- in +-- el +-- [ Border.widthEach borderWidths +-- , Border.roundEach corners +-- , Border.color color.blue +-- , onClick <| UserSelectedTab tab +-- ] +-- <| +-- el +-- [ centerX +-- , centerY +-- , paddingEach { left = 30, right = 30, top = 10 + padOffset, bottom = 10 - padOffset } +-- ] +-- <| +-- text <| +-- case tab of +-- Lessons -> +-- "Lessons" +-- Words -> +-- "Words" +-- Pronunciation -> +-- "Audio" + + +page : Model -> Html Msg +page model = + if model.isLoading then + layout [] (text "...") + + else + layout [ width fill, height fill ] <| + el + [ centerX ] + (lessonsView model.lessons) + + +lessonsView : Lessons -> Element Msg +lessonsView lessons = + Dict.values lessons + |> List.map lessonPreview + |> column [] + + +lessonPreview : Lesson -> Element Msg +lessonPreview lesson = + link [] + { url = "/lesson/" ++ String.fromInt lesson.id + , label = + el [] <| + column [] + [ text ("Lesson: " ++ String.fromInt lesson.id) + , text lesson.text + ] + } + + + +-- mainpage : Model -> Html Msg +-- mainpage model = +-- if model.isLoading then +-- layout [] (text "...") +-- else +-- layout [ width fill, height fill ] <| +-- column +-- [ centerX ] +-- [ row [] +-- [ tabEl Lessons model.tab +-- , tabEl Words model.tab +-- , tabEl Pronunciation model.tab +-- ] +-- , if model.tab == Lessons then +-- lessonsView model.lessons +-- else +-- el [] (text "WIP") +-- ] diff --git a/ui/src/Lessonpage.elm b/ui/src/Lessonpage.elm new file mode 100644 index 0000000..2d72c8a --- /dev/null +++ b/ui/src/Lessonpage.elm @@ -0,0 +1,85 @@ +module Lessonpage exposing (page) + +import Element exposing (..) +import Element.Border as Border +import Html exposing (Html) +import List.Extra +import Types exposing (Card, Lesson, Msg(..)) + + + +-- local state +-- type Tab +-- = Lessons +-- | Words +-- | Pronunciation + + +page : Lesson -> Int -> Html Msg +page lesson cid = + let + _ = + Debug.log "lesson" lesson + in + layout [ width fill, height fill, inFront navbar ] <| + el + [ centerX ] + (lessonView lesson cid) + + +lessonView : Lesson -> Int -> Element Msg +lessonView lesson cid = + case List.Extra.getAt cid lesson.cards of + Just c -> + cardView c + + Nothing -> + notFound + + +cardView : Card -> Element Msg +cardView card = + column [] + [ el [] (text card.text) + , cardNote card.note + ] + + +cardNote : Maybe String -> Element Msg +cardNote ms = + case ms of + Just txt -> + el [] (text txt) + + Nothing -> + el [] (text "") + + +navbar : Element Msg +navbar = + row + [ width fill + , padding 20 + , spacing 20 + , Border.widthEach { bottom = 2, left = 0, right = 0, top = 0 } + ] + [ el + [ width <| + px 80 + , height <| + px 40 + ] + (text "hi") + , el [ alignRight ] <| text "Settings" + ] + + + +-- TODO get rid of this, really bad form + + +notFound : Element Msg +notFound = + el + [ centerX ] + (text "404") diff --git a/ui/src/Main.elm b/ui/src/Main.elm index da55519..38a8ee9 100644 --- a/ui/src/Main.elm +++ b/ui/src/Main.elm @@ -1,49 +1,38 @@ module Main exposing (..) -import Api exposing (Card, Lesson, Lessons, ServerResponse(..), fetchLessons) +import Api exposing (fetchLessons) import Browser +import Browser.Navigation as Nav import Dict exposing (Dict) import Element exposing (..) import Element.Background as Background import Element.Border as Border import Element.Events exposing (onClick) import Element.Font as Font -import Html exposing (Html) -import Http - - -type Tab - = Lessons - | Words - | Pronunciation - - -type Msg - = UserSelectedTab Tab - | FetchDataHandler (Result Http.Error ServerResponse) +import Router exposing (parseUrl, router) +import Types exposing (Lessons, Model, Msg(..), Route(..), ServerResponse(..)) +import Url -- state -type alias Model = - { lessons : Lessons - , tab : Tab - , isLoading : Bool - } - - sampleLessons : Lessons sampleLessons = Dict.fromList [] -initialState : Model -initialState = +initialState : Url.Url -> Nav.Key -> Model +initialState url key = + let + route = + parseUrl url + in { isLoading = False , lessons = sampleLessons - , tab = Lessons + , route = route + , key = key } @@ -54,10 +43,7 @@ initialState = update : Msg -> Model -> ( Model, Cmd Msg ) update msg model = case msg of - UserSelectedTab t -> - ( { model | tab = t }, Cmd.none ) - - FetchDataHandler (Ok serres) -> + FetchLessons (Ok serres) -> -- let -- _ = -- Debug.log "hi" serres @@ -69,115 +55,73 @@ update msg model = ErrorResponse _ -> ( { model | isLoading = False }, Cmd.none ) - FetchDataHandler (Err _) -> + FetchLessons (Err _) -> ( { model | isLoading = False }, Cmd.none ) + FetchLesson res -> + ( { model | isLoading = False }, Cmd.none ) -view : Model -> Html Msg + LinkClicked urlRequest -> + let + _ = + Debug.log "url request" urlRequest + in + case urlRequest of + Browser.Internal url -> + ( model, Nav.pushUrl model.key (Url.toString url) ) + + Browser.External href -> + ( model, Nav.load href ) + + UrlChanged url -> + let + newRoute = + parseUrl url + in + ( { model | route = newRoute }, Cmd.none ) + + + +-- SUBSCRIPTIONS + + +subscriptions : Model -> Sub Msg +subscriptions _ = + Sub.none + + +view : Model -> Browser.Document Msg view model = - if model.isLoading then - layout [] (text "...") - - else - layout [ width fill, height fill ] <| - column - [ centerX ] - [ row [] - [ tabEl Lessons model.tab - , tabEl Words model.tab - , tabEl Pronunciation model.tab - ] - , if model.tab == Lessons then - lessonsView model.lessons - - else - el [] (text "WIP") - ] - - -tabEl : Tab -> Tab -> Element Msg -tabEl tab selectedTab = let - isSelected = - tab == selectedTab + ( _, _, html ) = + router model - padOffset = - if isSelected then - 0 - - else - 2 - - borderWidths = - if isSelected then - { left = 2, top = 2, right = 2, bottom = 0 } - - else - { bottom = 2, top = 0, left = 0, right = 0 } - - corners = - if isSelected then - { topLeft = 6, topRight = 6, bottomLeft = 0, bottomRight = 0 } - - else - { topLeft = 0, topRight = 0, bottomLeft = 0, bottomRight = 0 } + -- _ = + -- Debug.log "model" model in - el - [ Border.widthEach borderWidths - , Border.roundEach corners - , Border.color color.blue - , onClick <| UserSelectedTab tab - ] - <| - el - [ centerX - , centerY - , paddingEach { left = 30, right = 30, top = 10 + padOffset, bottom = 10 - padOffset } - ] - <| - text <| - case tab of - Lessons -> - "Lessons" - - Words -> - "Words" - - Pronunciation -> - "Audio" + { title = "Prosody" + , body = [ html ] + } -lessonsView : Lessons -> Element Msg -lessonsView lessons = - Dict.values lessons - |> List.map lessonPreview - |> column [] - - -lessonPreview : Lesson -> Element Msg -lessonPreview lesson = - el [] - (column [] - [ text ("Lesson: " ++ String.fromInt lesson.id) - , text lesson.text - ] - ) - - -init : flags -> ( Model, Cmd Msg ) -init flags = +init : flags -> Url.Url -> Nav.Key -> ( Model, Cmd Msg ) +init flags url key = Debug.log "Init flags" flags - |> (\_ -> Debug.log "Initial State" initialState) - |> (\_ -> ( initialState, fetchLessons FetchDataHandler )) + -- |> (\_ -> Debug.log "url" url) + -- |> (\_ -> Debug.log "key" key) + -- |> (\_ -> Debug.log "Initial State" initialState) + |> (\_ -> ( initialState url key, fetchLessons )) main : Program () Model Msg main = - Browser.element + Browser.application { init = init , view = view , update = update - , subscriptions = \_ -> Sub.none + , subscriptions = subscriptions + , onUrlRequest = LinkClicked + , onUrlChange = UrlChanged } diff --git a/ui/src/Router.elm b/ui/src/Router.elm new file mode 100644 index 0000000..00cc1a1 --- /dev/null +++ b/ui/src/Router.elm @@ -0,0 +1,61 @@ +module Router exposing (parseUrl, router) + +import Api exposing (fetchLesson) +import Dict +import Element exposing (..) +import Homepage +import Html exposing (Html) +import Lessonpage +import Types exposing (Model, Msg(..), Route(..)) +import Url +import Url.Parser as Parser exposing ((), Parser) + + +routeParser : Parser (Route -> a) a +routeParser = + Parser.oneOf + [ Parser.map Root Parser.top + , Parser.map LessonR (Parser.s "lesson" Parser.int Parser.int) + ] + + +parseUrl : Url.Url -> Route +parseUrl url = + Parser.parse routeParser url |> Maybe.withDefault NotFound + + +router : Model -> ( Model, Cmd Msg, Html Msg ) +router model = + case model.route of + Root -> + ( model, Cmd.none, Homepage.page model ) + + LessonR lid cid -> + lessonLoader lid cid model + + NotFound -> + ( model, Cmd.none, notFound ) + + +lessonLoader : Int -> Int -> Model -> ( Model, Cmd Msg, Html Msg ) +lessonLoader lid cid model = + case Dict.get lid model.lessons of + Just lesson -> + ( model, Cmd.none, Lessonpage.page lesson cid ) + + Nothing -> + ( { model | isLoading = True }, fetchLesson lid, loadingPage ) + + +notFound : Html Msg +notFound = + layout [] <| + el + [ centerX ] + (text "404") + + +loadingPage : Html Msg +loadingPage = + layout [] <| + el [ centerX, padding 20 ] (text "Loading lesson...") diff --git a/ui/src/Types.elm b/ui/src/Types.elm new file mode 100644 index 0000000..c0d856c --- /dev/null +++ b/ui/src/Types.elm @@ -0,0 +1,53 @@ +module Types exposing (..) + +import Browser +import Browser.Navigation as Nav +import Dict exposing (Dict) +import Http +import Url + + +type Route + = Root + | LessonR Int Int + | NotFound + + +type alias Model = + { lessons : Lessons + + -- , tab : Tab + , isLoading : Bool + , key : Nav.Key + , route : Route + } + + +type ServerResponse t + = OkResponse t + | ErrorResponse String + + +type Msg + = FetchLessons (Result Http.Error (ServerResponse Lessons)) + | FetchLesson (Result Http.Error (ServerResponse Lesson)) + | LinkClicked Browser.UrlRequest + | UrlChanged Url.Url + + +type alias Card = + { text : String + , note : Maybe String + , id : Int + } + + +type alias Lesson = + { text : String + , id : Int + , cards : List Card + } + + +type alias Lessons = + Dict Int Lesson