Last active
December 5, 2016 22:04
-
-
Save AdrianoFerrari/2c5c5d46828bf969def1c53c7b30aae3 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
--- TYPES | |
type alias ViewState = | |
{ active : String | |
, activePast : List String | |
, activeFuture : List String | |
, descendants : List String | |
, editing : Maybe String | |
, field : String | |
} | |
-- Trimmed down ViewState for view functions | |
-- so that (in theory), lazy can avoid rebuilding | |
-- DOM if these arguments are the same | |
type alias VisibleViewState = | |
{ active : String | |
, editing : Maybe (String, String) | |
, descendants : List String | |
} | |
type alias Tree = | |
{ id : String | |
, content : String | |
, children : Children -- ~ List Tree (recursive) | |
} | |
type Children = Children (List Tree) | |
type alias Group = List Tree | |
type alias Column = List (List Tree) | |
-- VIEW | |
view : ViewState -> Tree -> Html Msg | |
view vstate tree = | |
let | |
columnsWithDepth = | |
getColumnsWithDepth [([[ tree ]], 0)] | |
getViewArgs cwd = | |
let | |
editing_ = | |
case vstate.editing of | |
Nothing -> | |
Nothing | |
Just editId -> | |
if (first cwd |> List.concat |> List.map .id |> List.member editId ) then | |
Just (editId, vstate.field) -- only send down 'field' if this column actually contains card being edited | |
else | |
Nothing | |
in | |
VisibleViewState | |
vstate.active | |
editing_ | |
vstate.descendants | |
columns = | |
[([[]], -1)] ++ | |
columnsWithDepth ++ | |
[([[]], List.length columnsWithDepth)] | |
|> List.map (\t -> lazy3 viewColumn (getViewArgs t) (second t) (first t)) | |
-- I believe this call would mean that if I'm editing a card in e.g. column 1, | |
-- none of the arguments to lazy3 are changing in e.g. column 3. | |
-- Yet when I open Chrome inspector, divs in all columns are flashing on every edit keystroke. | |
in | |
div [ id "app" | |
, classList [ ("editing", vstate.editing /= Nothing) ] | |
] | |
( columns | |
) | |
viewColumn : VisibleViewState -> Int -> Column -> Html Msg | |
viewColumn vstate depth col = | |
let | |
buffer = | |
[div [ class "buffer" ][]] | |
in | |
div | |
[ class "column" ] | |
( buffer ++ | |
(List.map (lazy3 viewGroup vstate depth) col) ++ | |
buffer | |
) | |
viewGroup : VisibleViewState -> Int -> Group -> Html Msg | |
viewGroup vstate depth xs = | |
let | |
firstChild = | |
xs | |
|> List.head | |
|> Maybe.withDefault defaultTree | |
|> .id | |
isActiveDescendant = | |
vstate.descendants | |
|> List.member firstChild | |
viewFunction t = | |
let | |
isActive = | |
t.id == vstate.active | |
field_ = | |
case vstate.editing of | |
Just (editId, field) -> | |
if editId == t.id then | |
Just field | |
else | |
Nothing | |
Nothing -> | |
Nothing | |
in | |
viewKeyedCard (isActive, field_, depth) t | |
in | |
Keyed.node "div" | |
[ classList [ ("group", True) | |
, ("active-descendant", isActiveDescendant) | |
] | |
] | |
(List.map viewFunction xs) | |
viewKeyedCard : (Bool, Maybe String, Int) -> Tree -> (String, Html Msg) | |
viewKeyedCard tup tree = | |
(tree.id, lazy2 viewCard tup tree) | |
viewCard : (Bool, Maybe String, Int) -> Tree -> Html Msg | |
viewCard (isActive, field_, depth) tree = | |
let | |
isEditing = | |
field_ /= Nothing | |
isRoot = tree.id == "0" | |
options = | |
{ githubFlavored = Just { tables = True, breaks = True } | |
, defaultHighlighting = Nothing | |
, sanitize = False | |
, smartypants = False | |
} | |
hasChildren = | |
case tree.children of | |
Children c -> | |
( c | |
|> List.length | |
) /= 0 | |
tarea content = | |
textarea | |
[ id ( "card-edit-" ++ tree.id ) | |
, classList [ ("edit", True) | |
, ("mousetrap", True) | |
] | |
, value content | |
, onInput UpdateField | |
] | |
[] | |
buttons = | |
case (isEditing, field_, isRoot) of | |
( False, Just field, False ) -> | |
[ div [ class "flex-row card-top-overlay" ] | |
[ span | |
[ class "card-btn ins-above" | |
, title "Insert Above (Ctrl+K)" | |
, onClick (InsertAbove tree.id) | |
] | |
[ text "+" ] | |
] | |
, div [ class "flex-column card-right-overlay"] | |
[ span | |
[ class "card-btn delete" | |
, title "Delete Card (Ctrl+Backspace)" | |
, onClick (DeleteCard tree.id) | |
] | |
[] | |
, span | |
[ class "card-btn ins-right" | |
, title "Add Child (Ctrl+L)" | |
, onClick (InsertChild tree.id) | |
] | |
[ text "+" ] | |
, span | |
[ class "card-btn edit" | |
, title "Edit Card (Enter)" | |
, onClick (OpenCard tree.id tree.content) | |
] | |
[] | |
] | |
, div [ class "flex-row card-bottom-overlay" ] | |
[ span | |
[ class "card-btn ins-below" | |
, title "Insert Below (Ctrl+J)" | |
, onClick (InsertBelow tree.id) | |
] | |
[ text "+" ] | |
] | |
] | |
( False, Just field, True ) -> | |
[ div [ class "flex-column card-right-overlay"] | |
[ span | |
[ class "card-btn ins-right" | |
, title "Add Child (Ctrl+L)" | |
, onClick (InsertChild tree.id) | |
] | |
[ text "+" ] | |
, span | |
[ class "card-btn edit" | |
, title "Edit Card (Enter)" | |
, onClick (OpenCard tree.id tree.content) | |
] | |
[] | |
] | |
] | |
( True, _, _ ) -> | |
[ div [ class "flex-column card-right-overlay"] | |
[ span | |
[ class "card-btn save" | |
, title "Save Changes (Ctrl+Enter)" | |
, onClick SaveCard | |
] | |
[] | |
] | |
] | |
_ -> | |
[] | |
cardAttributes = | |
[ id ("card-" ++ tree.id) | |
, classList [ ("card", True) | |
, ("root", isRoot) | |
, ("active", isActive) | |
, ("editing", isEditing) | |
, ("has-children", hasChildren) | |
] | |
] | |
splitContent = | |
String.split newLine tree.content | |
autoheading = | |
List.repeat (Basics.min 6 (depth+1)) "#" | |
content = | |
case splitContent of | |
[] -> "" | |
head :: tail -> | |
if String.startsWith "#" head then | |
String.join newLine splitContent | |
else | |
String.concat | |
( autoheading ++ [" ", head, newLine, String.join newLine tail] ) | |
in | |
case field_ of | |
Just field -> | |
div cardAttributes | |
( | |
[ tarea field ] | |
++ | |
buttons | |
) | |
Nothing -> | |
div cardAttributes | |
( | |
[ Markdown.toHtmlWith options | |
[ class "view" | |
, onClick (Activate tree.id) | |
, onDoubleClick (OpenCard tree.id tree.content) | |
] content | |
, tarea content | |
] ++ | |
buttons | |
) | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment