Advertisement
Guest User

Untitled

a guest
Mar 7th, 2019
79
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
F# 7.41 KB | None | 0 0
  1. module Client
  2.  
  3. open Elmish
  4. open Elmish.React
  5.  
  6. open Fable.Helpers.React
  7. open Fable.Helpers.React.Props
  8. open Fable.PowerPack.Fetch
  9.  
  10. open Thoth.Json
  11.  
  12. open Shared
  13.  
  14.  
  15. open Fulma
  16. open Fable.Helpers
  17.  
  18.  
  19. // The model holds data that you want to keep track of while the application is running
  20. // in this case, we are keeping track of a counter
  21. // we mark it as optional, because initially it will not be available from the client
  22. // the initial value will be requested from server
  23. type Activation =
  24.     | Activate
  25.     | Deactivate
  26.  
  27. type Model = {
  28.                Counter: Counter option
  29.                IsActive: bool
  30.              }
  31.              //member __.Activation = if __.IsActive then Deactivate else Activate
  32.  
  33. // The Msg type defines what events/actions can occur while the application is running
  34. // the state of the application changes *only* in reaction to these events
  35. type Msg =
  36. | Increment
  37. | Decrement
  38. | Activation of Activation
  39. | InitialCountLoaded of Result<Counter, exn>
  40.  
  41. let initialCounter = fetchAs<Counter> "/api/init" (Decode.Auto.generateDecoder())
  42.  
  43. // defines the initial state and initial command (= side-effect) of the application
  44. let init () : Model * Cmd<Msg> =
  45.     let initialModel = { Counter = None; IsActive = false}
  46.     let loadCountCmd =
  47.         Cmd.ofPromise
  48.             initialCounter
  49.             []
  50.             (Ok >> InitialCountLoaded)
  51.             (Error >> InitialCountLoaded)
  52.     initialModel, loadCountCmd
  53.  
  54.  
  55.  
  56. // The update function computes the next state of the application based on the current state and the incoming events/messages
  57. // It can also run side-effects (encoded as commands) like calling the server via Http.
  58. // these commands in turn, can dispatch messages to which the update function will react.
  59. let update (msg : Msg) (currentModel : Model) : Model * Cmd<Msg> =
  60.     match currentModel.Counter, msg with
  61.     | Some counter, Increment ->
  62.         let nextModel = { currentModel with Counter = Some { Value = counter.Value + 1 } }
  63.         nextModel, Cmd.none
  64.     | Some counter, Decrement ->
  65.         let nextModel = { currentModel with Counter = Some { Value = counter.Value - 1 } }
  66.         nextModel, Cmd.none
  67.     | _, Activation act ->
  68.         let nextModel = match act with
  69.                         | Activate ->  {currentModel with IsActive = true }
  70.                         | Deactivate -> {currentModel with IsActive = false}
  71.         nextModel, Cmd.none
  72.     | _, InitialCountLoaded (Ok initialCount)->
  73.         let nextModel = { Counter = Some initialCount; IsActive = false}
  74.         nextModel, Cmd.none
  75.  
  76.     | _ -> currentModel, Cmd.none
  77.  
  78.  
  79. let safeComponents =
  80.     let components =
  81.         span [ ]
  82.            [
  83.              a [ Href "https://saturnframework.github.io" ] [ str "Saturn" ]
  84.              str ", "
  85.              a [ Href "http://fable.io" ] [ str "Fable" ]
  86.              str ", "
  87.              a [ Href "https://elmish.github.io/elmish/" ] [ str "Elmish" ]
  88.              str ", "
  89.              a [ Href "https://fulma.github.io/Fulma" ] [ str "Fulma" ]
  90.            ]
  91.  
  92.     p [ ]
  93.         [ strong [] [ str "SAFE Template" ]
  94.           str " powered by: "
  95.           components ]
  96.  
  97. let show = function
  98. | { Counter = Some counter } -> string counter.Value
  99. | { Counter = None   } -> "Loading..."
  100.  
  101. let button txt onClick =
  102.     Button.button
  103.         [ Button.IsFullWidth
  104.           Button.Color IsPrimary
  105.           Button.OnClick onClick ]
  106.         [ str txt ]
  107.  
  108. let basicModal isActive closeDisplay =
  109.     Modal.modal [ Modal.IsActive isActive ]
  110.         [ Modal.background [ Props [ OnClick closeDisplay ] ] [ ]
  111.           Modal.content [ ]
  112.             [ Box.box' [ ]
  113.                [ str "Test" ] ]
  114.          Modal.close [ Modal.Close.Size IsLarge
  115.                        Modal.Close.OnClick closeDisplay ] [ ] ]
  116.  
  117. //let toggleDisplay (modal : Fable.Import.React.ReactElement) = Modal.IsActive (not modal)
  118.  
  119.  
  120.  
  121. let view (model : Model) (dispatch : Msg -> unit) =
  122.    div []
  123.        [
  124.          Navbar.navbar [ ]
  125.              [ Navbar.Brand.div [ ]
  126.                  [ Navbar.Item.a [ Navbar.Item.Props [ Href "#" ] ]
  127.                      [ img [ Style [ Width "2.5em" ] // Force svg display
  128.                              Src @"C:\Projects\fs\safe\src\Client\public\favicon.png" ] ]
  129.                    Navbar.burger [
  130.                        GenericOption.Props [
  131.                            //HTMLAttr.Custom ("data-target", "myNavbar")
  132.                            //HTMLAttr.Custom ("aria-label", "menu")
  133.                            AriaExpanded model.IsActive
  134.                            OnClick (fun _ -> match model.IsActive with
  135.                                              | true -> dispatch (Activation (Deactivate))
  136.                                              | _ -> dispatch (Activation (Activate)))
  137.                        ]
  138.                        CustomClass "burger"
  139.                        CustomClass (if model.IsActive then "is-active" else "")
  140.                    ] [
  141.                        span [ Hidden true ] []
  142.                        span [ Hidden true ] []
  143.                        span [ Hidden true ] []
  144.                    ]
  145.                  ]
  146.                Navbar.menu [
  147.                    Navbar.Menu.Props [
  148.                        Id "myNavbar"
  149.                    ]
  150.                    Navbar.Menu.Option.CustomClass (if model.IsActive then "is-active" else "")
  151.                ] [
  152.                Navbar.Item.a [ Navbar.Item.HasDropdown
  153.                                Navbar.Item.IsHoverable ]
  154.                  [ Navbar.Link.a [ ]
  155.                      [ str "Docs" ]
  156.                    Navbar.Dropdown.div [ ]
  157.                      [ Navbar.Item.a [ ]
  158.                          [ str "Overwiew" ]
  159.                        Navbar.Item.a [ ]
  160.                          [ str "Elements" ]
  161.                        Navbar.divider [ ] [ ]
  162.                        Navbar.Item.a [ ]
  163.                          [ str "Components" ] ] ]
  164.                Navbar.Item.a [ Navbar.Item.HasDropdown
  165.                                Navbar.Item.IsHoverable ]
  166.                  [ Navbar.Link.a [ Navbar.Link.Option.IsArrowless ]
  167.                      [ str "Link without arrow" ]
  168.                    Navbar.Dropdown.div [ ]
  169.                      [ Navbar.Item.a [ ]
  170.                          [ str "Overwiew" ] ] ]
  171.                ]
  172.                Navbar.End.div [ ]
  173.                  [ Navbar.Item.div [ ]
  174.                      [ Button.button [ Button.Color IsSuccess ]
  175.                          [ str "Demo" ] ] ] ]
  176.          
  177.  
  178.          Container.container []
  179.              [ Content.content [ Content.Modifiers [ Modifier.TextAlignment (Screen.All, TextAlignment.Centered) ] ]
  180.                    [ Heading.h3 [] [ str ("Press buttons to manipulate counter: " + show model) ] ]
  181.                Columns.columns []
  182.                    [ Column.column [] [ button "-" (fun _ -> dispatch Decrement) ]
  183.                      Column.column [] [ button "+" (fun _ -> dispatch Increment) ] ] ]
  184.  
  185.          Footer.footer [ ]
  186.                [ Content.content [ Content.Modifiers [ Modifier.TextAlignment (Screen.All, TextAlignment.Centered) ] ]
  187.                    [ safeComponents ] ] ]
  188.  
  189. #if DEBUG
  190. open Elmish.Debug
  191. open Elmish.HMR
  192. #endif
  193.  
  194. Program.mkProgram init update view
  195. #if DEBUG
  196. |> Program.withConsoleTrace
  197. |> Program.withHMR
  198. #endif
  199. |> Program.withReact "elmish-app"
  200. #if DEBUG
  201. |> Program.withDebugger
  202. #endif
  203. |> Program.run
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement