Skip to content

Instantly share code, notes, and snippets.

@bradphelan
Last active September 29, 2019 15:42
Show Gist options
  • Save bradphelan/77f3fcb8e660783790c5610290cd8d97 to your computer and use it in GitHub Desktop.
Save bradphelan/77f3fcb8e660783790c5610290cd8d97 to your computer and use it in GitHub Desktop.
namespace XoaDotNet
open Avalonia.Controls
open Avalonia.Media
open Avalonia.FuncUI.Types
open Avalonia.FuncUI
open Avalonia.Layout
open FSharpx.Collections
open Bogus
[<AutoOpen>]
module Helpers =
let pvSet = PersistentVector.update
let pvGet = PersistentVector.nth
let pvAdd = PersistentVector.conj
type IndexedMessage<'Msg> = ( int*'Msg )
module PersonModule =
type PersonState = {
name : string
age : int
}
let f = Faker()
let personGen() : PersonState = {
name = f.Name.FirstName()
age = f.Random.Number(10,99)
}
type PersonMsg =
| EditName of string
| EditAge of int
let update (msg:PersonMsg) (state:PersonState) : PersonState =
match msg with
| EditName name -> { state with name = name }
| EditAge age -> {state with age = age}
let updateNth (msg:PersonMsg) id state =
pvSet id (update msg (pvGet id state)) state
let view (state:PersonState) (dispatch) : View =
Views.uniformGrid [
Attrs.columns 2
Attrs.children [
Views.textBox [
Attrs.text state.name
Attrs.onKeyUp(fun sender args ->
dispatch (EditName (sender :?> TextBox).Text)
)
]
Views.textBox [
Attrs.text (sprintf "%d" state.age)
Attrs.onKeyUp(fun sender args ->
dispatch (EditAge ((sender :?> TextBox).Text |> int))
)
]
]
]
module PersonsModule =
type PersonsMsg =
| Update of IndexedMessage<PersonModule.PersonMsg>
| Delete of int
let update (personsMsg:PersonsMsg) state =
match personsMsg with
| Update (id, msg) -> pvSet id (PersonModule.update msg (pvGet id state)) state
| Delete id ->
state
|> Seq.indexed
|> Seq.where ( fun (_id,_)->id<>_id)
|> Seq.map (fun (_,p)->p)
|> PersistentVector.ofSeq
let view (state:PersonModule.PersonState PersistentVector) (dispatch) : View =
// Set up a dispatcher for a person at a specific id
let dispatchPerson id = (fun msg -> dispatch(Update(id,msg)))
Views.scrollViewer [
Attrs.content (
Views.stackPanel [
Attrs.children [
for (id,person) in state |> Seq.indexed do
yield Views.dockpanel [
Attrs.children [
Views.button [
Attrs.content "X"
Attrs.onClick ( fun sender args -> dispatch (PersonsMsg.Delete id) )
]
PersonModule.view person (dispatchPerson id)
]
]
]
]
)
]
module ParentView =
open Bogus
// The model holds data that you want to keep track of while the application is running
type ParentState = {
people : PersonModule.PersonState PersistentVector
}
let barConjGen state =
state |> PersistentVector.conj (PersonModule.personGen())
//The initial state of of the application
let initialState = {
people = PersistentVector.empty
|> barConjGen
|> barConjGen
|> barConjGen
|> barConjGen
|> barConjGen
|> barConjGen
|> barConjGen
|> barConjGen
}
type ParentViewMsg =
| PersonsMsg of PersonsModule.PersonsMsg
| NewPerson
let update (msg: ParentViewMsg) (state: ParentState) : ParentState =
match msg with
| PersonsMsg msg -> { state with people = PersonsModule.update msg state.people }
| NewPerson -> { state with people = state.people |> barConjGen }
let view (state: ParentState) (dispatch): View =
Views.dockpanel[
Attrs.children [
Views.button [
Attrs.dockPanel_dock Dock.Bottom
Attrs.content "new"
Attrs.onClick (fun sender args -> dispatch ParentViewMsg.NewPerson)
]
PersonsModule.view state.people (PersonsMsg >> dispatch)
]
]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment