Skip to content

Instantly share code, notes, and snippets.

@ianrussellsoftwarepark
Created March 12, 2021 14:52
Show Gist options
  • Save ianrussellsoftwarepark/13569e9a930086d69082481dabebb1f8 to your computer and use it in GitHub Desktop.
Save ianrussellsoftwarepark/13569e9a930086d69082481dabebb1f8 to your computer and use it in GitHub Desktop.
Code for INTRODUCTION TO WEB PROGRAMMING IN F# WITH GIRAFFE - PART 3
open System
open System.IO
open Microsoft.AspNetCore.Builder
open Microsoft.AspNetCore.Hosting
open Microsoft.Extensions.Hosting
open Microsoft.Extensions.DependencyInjection
open Microsoft.AspNetCore.Http
open Giraffe
open Giraffe.ViewEngine
open FSharp.Control.Tasks
open Todos
open System.Collections.Generic
type PingModel = {
Response: string
}
let createPage msg content =
html [] [
head [] [
title [] [ Text msg ]
link [ _rel "stylesheet"; _href "main.css" ]
]
body [] content
]
let todoList = [
{ Id = Guid.NewGuid(); Description = "Hit the gym"; Created = DateTime.UtcNow; IsCompleted = false }
{ Id = Guid.NewGuid(); Description = "Pay bills"; Created = DateTime.UtcNow; IsCompleted = true }
{ Id = Guid.NewGuid(); Description = "Meet George"; Created = DateTime.UtcNow; IsCompleted = false }
{ Id = Guid.NewGuid(); Description = "Buy eggs"; Created = DateTime.UtcNow; IsCompleted = false }
{ Id = Guid.NewGuid(); Description = "Read a book"; Created = DateTime.UtcNow; IsCompleted = false }
{ Id = Guid.NewGuid(); Description = "Organize office"; Created = DateTime.UtcNow; IsCompleted = true }
]
let listItem (todo:Todo) =
let style = if todo.IsCompleted then [ _class "checked" ] else []
li style [ Text todo.Description ]
let todoView =
createPage "My ToDo App" [
div [ _id "myDIV"; _class "header" ] [
h2 [] [ Text "My ToDo List" ]
input [ _type "text"; _id "myInput"; _placeholder "Title..." ]
span [ _class "addBtn"; _onclick "newElement()" ] [ Text "Add" ]
]
ul [ _id "myUL" ] [
for todo in todoList do listItem todo
]
script [ _src "main.js"; _type "text/javascript" ] []
]
module Handlers =
let sayHelloNameHandler (name:string) =
fun (next : HttpFunc) (ctx : HttpContext) ->
task {
let msg = sprintf "Hello, %s" name
return! json { Response = msg } next ctx
}
let viewTasksHandler =
fun (next : HttpFunc) (ctx : HttpContext) ->
task {
let store = ctx.GetService<TodoStore>()
let todos = store.GetAll()
return! json todos next ctx
}
let viewTaskHandler (id:Guid) =
fun (next : HttpFunc) (ctx : HttpContext) ->
task {
let store = ctx.GetService<TodoStore>()
let todo = store.Get(id)
return! json todo next ctx
}
let createTaskHandler =
fun (next : HttpFunc) (ctx : HttpContext) ->
task {
let! newTodo = ctx.BindJsonAsync<NewTodo>()
let store = ctx.GetService<TodoStore>()
let created = store.Create({ Id = Guid.NewGuid(); Description = newTodo.Description; Created = DateTime.UtcNow; IsCompleted = false })
return! json created next ctx
}
let updateTaskHandler =
fun (next : HttpFunc) (ctx : HttpContext) ->
task {
let! todo = ctx.BindJsonAsync<Todo>()
let store = ctx.GetService<TodoStore>()
let created = store.Update(todo)
return! json created next ctx
}
let deleteTaskHandler (id:Guid) =
fun (next : HttpFunc) (ctx : HttpContext) ->
task {
let store = ctx.GetService<TodoStore>()
let existing = store.Get(id)
let deleted = store.Delete(KeyValuePair<TodoId, Todo>(id, existing))
return! json deleted next ctx
}
let apiTodoRoutes : HttpHandler =
subRoute "/todos"
(choose [
GET >=> choose [
routef "/%O" Handlers.viewTaskHandler
route "" >=> Handlers.viewTasksHandler
]
POST >=> route "" >=> Handlers.updateTaskHandler
PUT >=> route "" >=> Handlers.createTaskHandler
DELETE >=> routef "/%O" Handlers.deleteTaskHandler
])
let webApp =
choose [
GET >=> route "/" >=> htmlView todoView
subRoute "/api"
(choose [
apiTodoRoutes
GET >=> route "" >=> json { Response = "ToDo List API" }
GET >=> routef "/%s" Handlers.sayHelloNameHandler
])
setStatusCode 404 >=> text "Not Found"
]
let configureApp (app : IApplicationBuilder) =
app.UseGiraffe webApp
let configureServices (services : IServiceCollection) =
services.AddGiraffe()
.AddSingleton<TodoStore>(TodoStore()) |> ignore
[<EntryPoint>]
let main _ =
let contentRoot = Directory.GetCurrentDirectory()
let webRoot = Path.Combine(contentRoot, "WebRoot")
Host.CreateDefaultBuilder()
.ConfigureWebHostDefaults(fun webHost ->
webHost
.UseWebRoot(webRoot)
.Configure(configureApp)
.ConfigureServices(configureServices)
|> ignore)
.Build()
.Run()
0
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment