2019-01-31 02:54:47 +00:00
|
|
|
|
module Component.NNote where
|
|
|
|
|
|
|
|
|
|
import Prelude hiding (div)
|
|
|
|
|
|
|
|
|
|
import App (destroyNote, editNote)
|
|
|
|
|
import Component.Markdown as Markdown
|
|
|
|
|
import Data.Array (drop, foldMap)
|
|
|
|
|
import Data.Either (Either(..))
|
|
|
|
|
import Data.Lens (Lens', lens, use, (%=), (.=))
|
|
|
|
|
import Data.Maybe (Maybe(..), maybe)
|
|
|
|
|
import Data.Monoid (guard)
|
|
|
|
|
import Data.String (null, split) as S
|
|
|
|
|
import Data.String.Pattern (Pattern(..))
|
|
|
|
|
import Data.Tuple (fst, snd)
|
|
|
|
|
import Effect.Aff (Aff)
|
|
|
|
|
import Effect.Class (liftEffect)
|
|
|
|
|
import Globals (app', mmoment8601)
|
|
|
|
|
import Halogen as H
|
|
|
|
|
import Halogen.HTML (br_, button, div, form, input, label, p, span, text, textarea)
|
|
|
|
|
import Halogen.HTML as HH
|
|
|
|
|
import Halogen.HTML.Events (onChecked, onClick, onSubmit, onValueChange)
|
|
|
|
|
import Halogen.HTML.Properties (ButtonType(..), InputType(..), checked, for, id_, name, rows, title, type_, value)
|
|
|
|
|
import Model (Note)
|
2019-03-08 03:43:47 +00:00
|
|
|
|
import Util (_loc, class_, fromNullableStr, ifElseH)
|
2019-01-31 02:54:47 +00:00
|
|
|
|
import Web.Event.Event (Event, preventDefault)
|
|
|
|
|
import Web.HTML.Location (setHref)
|
2019-03-01 04:45:34 +00:00
|
|
|
|
import Data.Symbol (SProxy(..))
|
2019-01-31 02:54:47 +00:00
|
|
|
|
|
2019-03-01 04:45:34 +00:00
|
|
|
|
data NAction
|
|
|
|
|
= NNop
|
|
|
|
|
| NEditField EditField
|
|
|
|
|
| NEditSubmit Event
|
|
|
|
|
| NEdit Boolean
|
|
|
|
|
| NDeleteAsk Boolean
|
|
|
|
|
| NDestroy
|
2019-01-31 02:54:47 +00:00
|
|
|
|
|
|
|
|
|
type NState =
|
|
|
|
|
{ note :: Note
|
|
|
|
|
, edit_note :: Note
|
|
|
|
|
, deleteAsk :: Boolean
|
|
|
|
|
, edit :: Boolean
|
|
|
|
|
, destroyed :: Boolean
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
_note :: Lens' NState Note
|
|
|
|
|
_note = lens _.note (_ { note = _ })
|
|
|
|
|
|
|
|
|
|
_edit_note :: Lens' NState Note
|
|
|
|
|
_edit_note = lens _.edit_note (_ { edit_note = _ })
|
|
|
|
|
|
|
|
|
|
_edit :: Lens' NState Boolean
|
|
|
|
|
_edit = lens _.edit (_ { edit = _ })
|
|
|
|
|
|
2019-09-15 13:43:03 +00:00
|
|
|
|
-- | FormField Edits
|
2019-01-31 02:54:47 +00:00
|
|
|
|
data EditField
|
|
|
|
|
= Etitle String
|
|
|
|
|
| Etext String
|
|
|
|
|
| EisMarkdown Boolean
|
2019-09-15 13:43:03 +00:00
|
|
|
|
| Eshared Boolean
|
2019-01-31 02:54:47 +00:00
|
|
|
|
|
2019-03-01 04:45:34 +00:00
|
|
|
|
_markdown = SProxy :: SProxy "markdown"
|
2019-01-31 02:54:47 +00:00
|
|
|
|
|
2019-03-01 04:45:34 +00:00
|
|
|
|
type ChildSlots =
|
2019-03-07 04:03:24 +00:00
|
|
|
|
( markdown :: Markdown.Slot Unit
|
2019-03-01 04:45:34 +00:00
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
nnote :: forall q i o. Note -> H.Component HH.HTML q i o Aff
|
2019-01-31 02:54:47 +00:00
|
|
|
|
nnote st' =
|
2019-03-01 04:45:34 +00:00
|
|
|
|
H.mkComponent
|
2019-01-31 02:54:47 +00:00
|
|
|
|
{ initialState: const (mkState st')
|
|
|
|
|
, render
|
2019-03-01 04:45:34 +00:00
|
|
|
|
, eval: H.mkEval $ H.defaultEval { handleAction = handleAction }
|
2019-01-31 02:54:47 +00:00
|
|
|
|
}
|
|
|
|
|
where
|
|
|
|
|
app = app' unit
|
|
|
|
|
|
|
|
|
|
mkState note' =
|
|
|
|
|
{ note: note'
|
|
|
|
|
, edit_note: note'
|
|
|
|
|
, deleteAsk: false
|
|
|
|
|
, edit: note'.id <= 0
|
|
|
|
|
, destroyed: false
|
|
|
|
|
}
|
|
|
|
|
|
2019-03-01 04:45:34 +00:00
|
|
|
|
render :: NState -> H.ComponentHTML NAction ChildSlots Aff
|
2019-01-31 02:54:47 +00:00
|
|
|
|
render st@{ note, edit_note } =
|
2019-03-08 03:43:47 +00:00
|
|
|
|
ifElseH st.destroyed
|
|
|
|
|
display_destroyed
|
|
|
|
|
(const (ifElseH st.edit
|
|
|
|
|
renderNote_edit
|
|
|
|
|
renderNote))
|
2019-01-31 02:54:47 +00:00
|
|
|
|
where
|
|
|
|
|
|
2019-03-08 03:43:47 +00:00
|
|
|
|
renderNote _ =
|
2019-01-31 02:54:47 +00:00
|
|
|
|
div [ id_ (show note.id) , class_ ("note w-100 mw7 pa1 mb2")] $
|
|
|
|
|
[ div [ class_ "display" ] $
|
|
|
|
|
[ div [ class_ ("link f5 lh-title")]
|
|
|
|
|
[ text $ if S.null note.title then "[no title]" else note.title ]
|
|
|
|
|
, br_
|
|
|
|
|
, if note.isMarkdown
|
2019-03-01 04:45:34 +00:00
|
|
|
|
then div [ class_ "description mt1" ] [ HH.slot _markdown unit Markdown.component note.text absurd ]
|
2019-01-31 02:54:47 +00:00
|
|
|
|
else div [ class_ "description mt1 mid-gray" ] (toTextarea note.text)
|
2019-09-15 13:43:03 +00:00
|
|
|
|
, div [ class_ "link f7 dib gray w4"]
|
|
|
|
|
[ span [title (maybe note.created snd (mmoment note))]
|
|
|
|
|
[text (maybe " " fst (mmoment note))]
|
|
|
|
|
, text " - "
|
|
|
|
|
, span [ class_ ("gray")]
|
|
|
|
|
[ text $ if note.shared then "public" else "private" ]
|
|
|
|
|
]
|
2019-01-31 02:54:47 +00:00
|
|
|
|
]
|
|
|
|
|
]
|
|
|
|
|
<> -- | Render Action Links
|
|
|
|
|
[ div [ class_ "edit_links db mt3" ]
|
2019-03-01 04:45:34 +00:00
|
|
|
|
[ button [ type_ ButtonButton, onClick \_ -> Just (NEdit true), class_ "edit light-silver hover-blue" ] [ text "edit " ]
|
2019-01-31 02:54:47 +00:00
|
|
|
|
, div [ class_ "delete_link di" ]
|
2019-03-01 04:45:34 +00:00
|
|
|
|
[ button [ type_ ButtonButton, onClick \_ -> Just (NDeleteAsk true), class_ ("delete light-silver hover-blue" <> guard st.deleteAsk " dn") ] [ text "delete" ]
|
2019-01-31 02:54:47 +00:00
|
|
|
|
, span ([ class_ ("confirm red" <> guard (not st.deleteAsk) " dn") ] )
|
2019-03-01 04:45:34 +00:00
|
|
|
|
[ button [ type_ ButtonButton, onClick \_ -> Just (NDeleteAsk false)] [ text "cancel / " ]
|
|
|
|
|
, button [ type_ ButtonButton, onClick \_ -> Just NDestroy, class_ "red" ] [ text "destroy" ]
|
2019-09-15 13:43:03 +00:00
|
|
|
|
]
|
2019-01-31 02:54:47 +00:00
|
|
|
|
]
|
|
|
|
|
]
|
|
|
|
|
]
|
|
|
|
|
|
2019-03-08 03:43:47 +00:00
|
|
|
|
renderNote_edit _ =
|
2019-03-01 04:45:34 +00:00
|
|
|
|
form [ onSubmit (Just <<< NEditSubmit) ]
|
2019-01-31 02:54:47 +00:00
|
|
|
|
[ p [ class_ "mt2 mb1"] [ text "title:" ]
|
|
|
|
|
, input [ type_ InputText , class_ "title w-100 mb1 pt1 f7 edit_form_input" , name "title"
|
|
|
|
|
, value (edit_note.title) , onValueChange (editField Etitle)
|
|
|
|
|
]
|
|
|
|
|
, br_
|
|
|
|
|
, p [ class_ "mt2 mb1"] [ text "description:" ]
|
|
|
|
|
, textarea [ class_ "description w-100 mb1 pt1 f7 edit_form_input" , name "text", rows 30
|
|
|
|
|
, value (edit_note.text) , onValueChange (editField Etext)
|
|
|
|
|
]
|
|
|
|
|
, div [ class_ "edit_form_checkboxes mb3"]
|
|
|
|
|
[ input [ type_ InputCheckbox , class_ "is-markdown pointer" , id_ "edit_ismarkdown", name "ismarkdown"
|
|
|
|
|
, checked (edit_note.isMarkdown) , onChecked (editField EisMarkdown) ]
|
|
|
|
|
, text " "
|
|
|
|
|
, label [ for "edit_ismarkdown" , class_ "mr2" ] [ text "use markdown?" ]
|
|
|
|
|
, br_
|
|
|
|
|
]
|
2019-09-15 13:43:03 +00:00
|
|
|
|
, div [ class_ "edit_form_checkboxes mb3"]
|
|
|
|
|
[ input [ type_ InputCheckbox , class_ "is-markdown pointer" , id_ "edit_shared", name "shared"
|
|
|
|
|
, checked (edit_note.shared) , onChecked (editField Eshared) ]
|
|
|
|
|
, text " "
|
|
|
|
|
, label [ for "edit_shared" , class_ "mr2" ] [ text "public?" ]
|
|
|
|
|
, br_
|
|
|
|
|
]
|
|
|
|
|
, input [ type_ InputSubmit
|
|
|
|
|
, class_ "mr1 pv1 ph2 dark-gray ba b--moon-gray bg-near-white pointer rdim"
|
|
|
|
|
, value "save" ]
|
2019-01-31 02:54:47 +00:00
|
|
|
|
, text " "
|
2019-09-15 13:43:03 +00:00
|
|
|
|
, input [ type_ InputReset
|
|
|
|
|
, class_ "pv1 ph2 dark-gray ba b--moon-gray bg-near-white pointer rdim"
|
|
|
|
|
, value "cancel"
|
2019-03-01 04:45:34 +00:00
|
|
|
|
, onClick \_ -> Just (NEdit false)
|
2019-01-31 02:54:47 +00:00
|
|
|
|
]
|
|
|
|
|
]
|
|
|
|
|
|
2019-03-08 03:43:47 +00:00
|
|
|
|
display_destroyed _ = p [ class_ "red"] [text "you killed this note"]
|
2019-01-31 02:54:47 +00:00
|
|
|
|
|
|
|
|
|
mmoment n = mmoment8601 n.created
|
2019-03-01 04:45:34 +00:00
|
|
|
|
editField :: forall a. (a -> EditField) -> a -> Maybe NAction
|
|
|
|
|
editField f = Just <<< NEditField <<< f
|
2019-01-31 02:54:47 +00:00
|
|
|
|
toTextarea input =
|
|
|
|
|
S.split (Pattern "\n") input
|
|
|
|
|
# foldMap (\x -> [br_, text x])
|
|
|
|
|
# drop 1
|
|
|
|
|
|
|
|
|
|
|
2019-03-01 04:45:34 +00:00
|
|
|
|
handleAction :: NAction -> H.HalogenM NState NAction ChildSlots o Aff Unit
|
|
|
|
|
handleAction (NNop) = pure unit
|
2019-01-31 02:54:47 +00:00
|
|
|
|
|
|
|
|
|
-- | EditField
|
2019-03-01 04:45:34 +00:00
|
|
|
|
handleAction (NEditField f) = do
|
2019-01-31 02:54:47 +00:00
|
|
|
|
_edit_note %= case f of
|
|
|
|
|
Etitle e -> _ { title = e }
|
|
|
|
|
Etext e -> _ { text = e }
|
|
|
|
|
EisMarkdown e -> _ { isMarkdown = e }
|
2019-09-15 13:43:03 +00:00
|
|
|
|
Eshared e -> _ { shared = e }
|
2019-01-31 02:54:47 +00:00
|
|
|
|
|
|
|
|
|
-- | Delete
|
2019-03-01 04:45:34 +00:00
|
|
|
|
handleAction (NDeleteAsk e) = do
|
2019-01-31 02:54:47 +00:00
|
|
|
|
H.modify_ (_ { deleteAsk = e })
|
|
|
|
|
|
|
|
|
|
-- | Destroy
|
2019-03-01 04:45:34 +00:00
|
|
|
|
handleAction (NDestroy) = do
|
2019-01-31 02:54:47 +00:00
|
|
|
|
note <- use _note
|
|
|
|
|
void $ H.liftAff (destroyNote note.id)
|
|
|
|
|
H.modify_ (_ { destroyed = true })
|
|
|
|
|
|
|
|
|
|
-- | Start/Stop Editing
|
2019-03-01 04:45:34 +00:00
|
|
|
|
handleAction (NEdit e) = do
|
2019-01-31 02:54:47 +00:00
|
|
|
|
note <- use _note
|
|
|
|
|
_edit_note .= note
|
|
|
|
|
_edit .= e
|
|
|
|
|
|
|
|
|
|
-- | Submit
|
2019-03-01 04:45:34 +00:00
|
|
|
|
handleAction (NEditSubmit e) = do
|
2019-01-31 02:54:47 +00:00
|
|
|
|
H.liftEffect (preventDefault e)
|
|
|
|
|
edit_note <- use _edit_note
|
|
|
|
|
res <- H.liftAff (editNote edit_note)
|
|
|
|
|
case res.body of
|
2019-03-01 04:45:34 +00:00
|
|
|
|
Left err -> pure unit
|
2019-01-31 02:54:47 +00:00
|
|
|
|
Right r -> do
|
|
|
|
|
if (edit_note.id == 0)
|
|
|
|
|
then do
|
|
|
|
|
liftEffect (setHref (fromNullableStr app.noteR) =<< _loc)
|
|
|
|
|
else do
|
|
|
|
|
_note .= edit_note
|
|
|
|
|
_edit .= false
|