diff --git a/todo-mvc/build.nix b/todo-mvc/build.nix index 0ea8a5d..2854ca5 100644 --- a/todo-mvc/build.nix +++ b/todo-mvc/build.nix @@ -12,7 +12,7 @@ let haskellPackages = pkgs.haskellPackages_ghcjs.override { browserify = pkgs.nodePackages.browserify; client = stdenv.mkDerivation { - name = "chat-client"; + name = "todo-mvc"; version = "1.0"; src = ./.; buildInputs = [ ghc aeson ghcjsBase ghcjsDom ghcjsPrim @@ -35,4 +35,4 @@ in client # oHm ohmChatServer lens pipes pipesConcurrency mvc profunctors; # inherit (pkg.nodePackages) npm browserify; # closurecompiler = pkgs.closurecompiler; - # } \ No newline at end of file + # } diff --git a/todo-mvc/default.nix b/todo-mvc/default.nix index 3e40f9e..1a819b3 100644 --- a/todo-mvc/default.nix +++ b/todo-mvc/default.nix @@ -1,4 +1,4 @@ -{ cabal, aeson, ghcjsBase, ghcjsDom, ghcjsPrim, lens, mvc, oHm +{ cabal, aeson, ghcjsBase, ghcjsDom, ghcjsPrim, lens, mvc, virtualDom, oHm , pipes, pipesConcurrency, profunctors, stm, time }: @@ -9,7 +9,7 @@ cabal.mkDerivation (self: { isLibrary = false; isExecutable = true; buildDepends = [ - aeson ghcjsBase ghcjsDom ghcjsPrim lens mvc oHm pipes + aeson ghcjsBase ghcjsDom ghcjsPrim lens mvc virtualDom oHm pipes pipesConcurrency profunctors stm time ]; doCheck = false; diff --git a/todo-mvc/ohm-todo-mvc.cabal b/todo-mvc/ohm-todo-mvc.cabal index 126f9af..ed4bfbf 100644 --- a/todo-mvc/ohm-todo-mvc.cabal +++ b/todo-mvc/ohm-todo-mvc.cabal @@ -15,8 +15,8 @@ cabal-version: >=1.20 executable todo-mvc main-is: Main.hs -- other-modules: - other-extensions: ForeignFunctionInterface, GeneralizedNewtypeDeriving, OverloadedStrings - build-depends: base >=4.7 && <4.8 + -- other-extensions: ForeignFunctionInterface, GeneralizedNewtypeDeriving, OverloadedStrings + build-depends: base >=4.7 && <5 , containers >=0.5 && <0.6 , lens , profunctors @@ -33,8 +33,8 @@ executable todo-mvc , ghcjs-dom >=0.1.1.1 , ghcjs-prim >= 0.1.0.0 , oHm + , virtual-dom hs-source-dirs: src - js-sources: static/deps.js - ghcjs-options: -O3 -Wall - cpp-options: -DGHCJS_BROWSER -DGHCJS_BUSY_YIELD=30 + -- ghcjs-options: -O3 -Wall + -- cpp-options: -DGHCJS_BROWSER -DGHCJS_BUSY_YIELD=30 default-language: Haskell2010 diff --git a/todo-mvc/shell.nix b/todo-mvc/shell.nix index 2cf5fce..e4d4058 100644 --- a/todo-mvc/shell.nix +++ b/todo-mvc/shell.nix @@ -1,6 +1,7 @@ with import {}; let haskellPackages = pkgs.haskellPackages_ghcjs.override { extension = self: super: { + virtualDom = self.callPackage ./virtual-dom {}; oHm = self.callPackage ./oHm {}; todo = self.callPackage ./. {}; }; @@ -12,7 +13,7 @@ in pkgs.callPackage ./. { buildTools = super.buildTools ++ [ haskellPackages.ghc.ghc.parent.cabalInstall ]; }; }; - inherit (haskellPackages) aeson ghcjsBase ghcjsDom ghcjsPrim oHm lens mvc pipes + inherit (haskellPackages) aeson ghcjsBase ghcjsDom ghcjsPrim virtualDom oHm lens mvc pipes pipesConcurrency profunctors stm; } diff --git a/todo-mvc/src/Main.hs b/todo-mvc/src/Main.hs index 4ce5182..9624d54 100644 --- a/todo-mvc/src/Main.hs +++ b/todo-mvc/src/Main.hs @@ -7,12 +7,19 @@ import Control.Lens hiding (Index, Action) import Pipes --import Prelude hiding ((.)) import Control.Applicative +import Control.Monad.Trans.State.Strict import Data.Foldable (traverse_) import Ohm.Component -import Ohm.HTML -import Prelude hiding (div,id,span,map, filter) +import Ohm.KeyMaster +import Ohm.HTML hiding (classes) +import VirtualDom +import VirtualDom.Prim (HTMLElement, _HTMLElement, HTML, text, properties, attributes) +import Prelude hiding (filter) import qualified Prelude as P +import VirtualDom.HTML.Attributes hiding (form_, span_) +import GHCJS.Foreign + -------------------------------------------------------------------------------- type Index = Int @@ -72,31 +79,32 @@ showFilter Active = "Active" showFilter Completed = "Completed" filterItems :: Filter -> [Item] -> [Item] -filterItems All = P.id +filterItems All = id filterItems Active = P.filter (not . _completed) filterItems Completed = P.filter _completed todoView :: DOMEvent Action -> ToDo -> HTML todoView chan todo@(ToDo itemList _txtEntry currentFilter) = - with div - (classes .= ["body"]) + with div_ (do + onKeyPress $ DOMEvent print + classes .= ["body"]) [ titleRender, itemsRender, renderFilters chan todo] where - titleRender = with h1 (classes .= ["title"]) ["todos"] - itemsRender = with ul (classes .= ["items"]) - (newItem chan todo : (P.map (renderItem chan) $ zip [0..] filteredItems)) + titleRender = with h1_ (classes .= ["title"]) ["todos"] + itemsRender = with ul_ (classes .= ["items"]) + (newItem chan todo : (map (renderItem chan) $ zip [0..] filteredItems)) filteredItems = filterItems currentFilter itemList newItem :: DOMEvent Action -> ToDo -> HTML newItem chan todo = - with li (classes .= ["newItem"]) - [ into form - [ with input (do - attrs . at "placeholder" ?= "Create a new task" - props . at "value" ?= value + with li_ (classes .= ["newItem"]) + [ into form_ + [ with input_ (do + attributes . at "placeholder" ?= "Create a new task" + properties . at "value" ?= value onInput $ contramap SetEditText chan) [] - , with (btn click "Create") (attrs . at "hidden" ?= "true") ["Create"] + , with (btn click "Create") (attributes . at "hidden" ?= "true") ["Create"] ] ] where @@ -105,34 +113,39 @@ newItem chan todo = renderItem :: DOMEvent Action -> (Int, Item) -> HTML renderItem chan (idx, (Item itemTitle complete)) = - into li - [ into form - [ with input (do - props . at "type" ?= "checkbox" - attrs . at "title" ?= "Mark as Completed" - props . at "checked" ?= (if complete then "checked" else "") + into li_ + [ into form_ + [ with input_ (do + properties . at "type" ?= "checkbox" + attributes . at "title" ?= "Mark as Completed" + properties . at "checked" ?= (if complete then "checked" else "") onChange $ contramap (const $ SetCompleted idx (if complete then False else True)) chan classes .= ["completed"]) [] - , with span (classes .= ["description"]) + , with span_ (do + classes .= ["description"] + onKeyPress $ DOMEvent print) [text itemTitle] - , (btn clickCancel "✖") &~ do - classes .= ["complete"] - attrs . at "title" ?= "Remove Item" + , cancelBtn ] ] - where clickCancel = const $ channel chan $ RemoveItem idx + where + clickCancel = const $ channel chan $ RemoveItem idx + cancelBtn = (btn clickCancel "✖") & _HTMLElement %~ + (execState $ do + classes .= ["complete"] + attributes . at "title" ?= "Remove Item") renderFilters :: DOMEvent Action -> ToDo -> HTML renderFilters chan todo = - with ul (classes .= ["filters"]) + with ul_ (classes .= ["filters"]) (renderFilter <$> [All, Active, Completed]) where currentFilter = (todo ^. filter) renderFilter f = - into li - [ with a (do - attrs . at "href" ?= "#" + into li_ + [ with a_ (do + attributes . at "href" ?= "#" classes .= (if f == currentFilter then ["selected"] else []) onClick $ filterClick f) [text $ showFilter f] @@ -140,7 +153,7 @@ renderFilters chan todo = filterClick f = DOMEvent $ const $ (channel chan) $ SetFilter f btn :: (() -> IO ()) -> String -> HTML -btn click txt = with button (onClick $ DOMEvent click) [text txt] +btn click txt = with button_ (onClick $ DOMEvent click) [text txt] -------------------------------------------------------------------------------- @@ -149,4 +162,7 @@ modelComp :: Component () Action ToDo Action modelComp = Component process todoView idProcessor main :: IO () -main = void $ runComponent initialToDo () modelComp +main = do + km <- initKeyMaster + key km "ctrl+a" $ (putStrLn "a called") + void $ initDomDelegator >> runComponent initialToDo () modelComp diff --git a/todo-mvc/src/deps.js b/todo-mvc/src/deps.js deleted file mode 100644 index 66fca22..0000000 --- a/todo-mvc/src/deps.js +++ /dev/null @@ -1,8 +0,0 @@ -global.Delegator = require('dom-delegator'); -global.Delegator(); -global.h = require('virtual-hyperscript'); -global.svg = require('virtual-hyperscript/svg'); -global.hook = require('virtual-hyperscript/hooks/ev-hook'); -global.diff = require('virtual-dom/diff'); -global.patch = require('virtual-dom/patch'); -global.createElement = require('virtual-dom/create-element'); diff --git a/todo-mvc/static/exe b/todo-mvc/static/exe new file mode 120000 index 0000000..b7ddd75 --- /dev/null +++ b/todo-mvc/static/exe @@ -0,0 +1 @@ +../dist/build/todo-mvc/todo-mvc.jsexe/ \ No newline at end of file diff --git a/todo-mvc/static/index.html b/todo-mvc/static/index.html index 425c8a2..136e5dc 100644 --- a/todo-mvc/static/index.html +++ b/todo-mvc/static/index.html @@ -10,7 +10,7 @@ - + Fork me on GitHub diff --git a/todo-mvc/virtual-dom b/todo-mvc/virtual-dom new file mode 120000 index 0000000..299a662 --- /dev/null +++ b/todo-mvc/virtual-dom @@ -0,0 +1 @@ +../../virtual-dom \ No newline at end of file