From 047c21103f49bf07f09006260b79a3f3ea46be17 Mon Sep 17 00:00:00 2001 From: Philippe Pittoli Date: Sun, 21 Jan 2024 02:47:12 +0100 Subject: [PATCH] WIP: Bulma module now has modal capabilities. --- src/App/ZoneInterface.purs | 99 +++++++++++++++++++++++++++++--------- src/Bulma.purs | 53 ++++++++++++-------- 2 files changed, 108 insertions(+), 44 deletions(-) diff --git a/src/App/ZoneInterface.purs b/src/App/ZoneInterface.purs index e7432f3..ae6b932 100644 --- a/src/App/ZoneInterface.purs +++ b/src/App/ZoneInterface.purs @@ -3,11 +3,14 @@ -- | This interface allows to: -- | - display all resource records of a zone -- | - * DONE: SOA, NS, A, AAAA, CNAME, TXT, MX, SRV --- | - add new resource records --- | - TODO: modify resource records --- | - remove resource records --- | - ask for confirmation on deletion +-- | - DONE: add new resource records +-- | - DONE: modify resource records +-- | - DONE: remove resource records +-- | - DONE: ask for confirmation on deletion -- | +-- | WIP: adding a new record should be through a modal presenting a specific form for each RR. +-- | This allows to present relevant information, such as use cases. +-- | Also, errors could be shown and further explained with more available screen space. -- | TODO: do not allow for the modification of read-only resource records. -- | -- | TODO: move all serialization code to a single module. @@ -47,6 +50,17 @@ import App.LogMessage (LogMessage(..)) import App.Messages.DNSManagerDaemon as DNSManager import App.Validation as Validation +-- | `App.ZoneInterface` accepts to add a few new entry types. +-- | Each entry type has a specific form in a modal, with relevant and dedicated information. +data AcceptedRRTypes + = A + | AAAA + | TXT + | CNAME + | NS + | MX + | SRV + -- | `App.ZoneInterface` can send messages through websocket interface -- | connected to dnsmanagerd. See `App.WS`. -- | @@ -118,6 +132,8 @@ data Update_Local_Form data Action = DeleteRRModal RRId | CancelModal + | NewRRModal AcceptedRRTypes + -- | NewAModal | Initialize @@ -145,6 +161,9 @@ type State = , wsUp :: Boolean , active_modal :: Maybe Int + -- A modal to present a form for adding a new RR. + , active_new_rr_modal :: Maybe AcceptedRRTypes + -- current entries , _soa :: Maybe (SOARR ()) , _srr :: Array (SimpleRR ()) @@ -182,6 +201,7 @@ initialState :: Input -> State initialState domain = { wsUp: true , active_modal: Nothing + , active_new_rr_modal: Nothing , _domain: domain @@ -204,10 +224,11 @@ type SortableRecord l = Record (rrtype :: String, rrid :: Int | l) render :: forall m. State -> H.ComponentHTML Action () m render state = Bulma.section_small - [ case state.wsUp, state.active_modal of - false, _ -> Bulma.p "You are disconnected." - true, Just rr_id -> modal_rr_delete rr_id - true, Nothing -> HH.div_ [ Bulma.h1 state._domain + [ case state.wsUp, state.active_modal, state.active_new_rr_modal of + false, _, _ -> Bulma.p "You are disconnected." + true, Just rr_id, _ -> modal_rr_delete rr_id + true, Nothing, Just t -> modal_add_new_rr t + true, Nothing, Nothing -> HH.div_ [ Bulma.h1 state._domain , Bulma.hr , render_soa state._soa , render_records state._errors $ sorted state._srr @@ -223,44 +244,67 @@ render state $ map NonEmpty.toArray $ A.groupAllBy (comparing (_.rrtype)) array + -- TODO: these components can have a broader use. +-- generic_modal_header :: forall w. String -> HH.HTML w Action +-- generic_modal_header t = HH.header [HP.classes C.modal_card_head] +-- [ HH.p [HP.classes C.modal_card_title] [HH.text t] +-- ] +-- generic_modal_body x = HH.section [HP.classes C.modal_card_body] [ x ] + modal_rr_delete :: forall w. Int -> HH.HTML w Action modal_rr_delete rr_id = - modal - [ modal_background - , modal_card [modal_header, modal_body] - , modal_foot [modal_delete_button, modal_cancel_button] + Bulma.modal + [ Bulma.modal_background + , Bulma.modal_card [Bulma.modal_header "Deleting a resource record", modal_body] + , Bulma.modal_foot [modal_delete_button, Bulma.modal_cancel_button CancelModal] ] where - modal = HH.div [HP.classes (C.modal <> C.is_active)] - modal_background = HH.div [HP.classes C.modal_background] [] - modal_card = HH.div [HP.classes C.modal_card] - modal_header = HH.header [HP.classes C.modal_card_head] - [ HH.p [HP.classes C.modal_card_title] [HH.text "Deleting a resource record"] - ] modal_body = HH.section [HP.classes C.modal_card_body] [ warning_message ] - modal_foot = HH.div [HP.classes C.modal_card_foot] modal_delete_button = HH.button [ HP.classes (C.button <> C.is_success) , HE.onClick \_ -> RemoveRR rr_id ] [HH.text "Delete the resource record."] - modal_cancel_button - = HH.button [ HP.classes C.button - , HE.onClick \_ -> CancelModal - ] [HH.text "Cancel"] warning_message = HH.p [] [ HH.text $ "You are about to delete a resource record, this actions is " , HH.strong_ [ HH.text "irreversible" ] , HH.text "." ] + modal_add_new_rr :: forall w. AcceptedRRTypes -> HH.HTML w Action + modal_add_new_rr = case _ of + A -> + Bulma.modal + [ Bulma.modal_background + , Bulma.modal_card [Bulma.modal_header "New A resource record" + , modal_body $ Bulma.p "hello, new A RR!"] + , Bulma.modal_foot [Bulma.modal_cancel_button CancelModal] + ] + _ -> + Bulma.modal + [ Bulma.modal_background + , Bulma.modal_card [Bulma.modal_header "New ?? resource record" + , modal_body $ Bulma.p "hello, new ?? RR!"] + , Bulma.modal_foot [Bulma.modal_cancel_button CancelModal] + ] + where + modal_body x = HH.section [HP.classes C.modal_card_body] [ x ] + -- modal_foot = HH.div [HP.classes C.modal_card_foot] + handleAction :: forall m. MonadAff m => Action -> H.HalogenM State Action () Output m Unit handleAction = case _ of + -- Works for both modals. CancelModal -> do - H.modify_ _ { active_modal = Nothing } + H.modify_ _ { active_modal = Nothing, active_new_rr_modal = Nothing } DeleteRRModal rr_id -> do H.modify_ _ { active_modal = Just rr_id } + NewRRModal t -> do + H.modify_ _ { active_new_rr_modal = Just t } + +-- NewAModal -> do +-- H.modify_ _ { active_modal = Just rr_id } + Initialize -> do { _domain } <- H.get H.raise $ Log $ SimpleLog $ "Asking the server for the zone" <> _domain @@ -739,6 +783,13 @@ render_new_records state = Bulma.hdiv [ Bulma.h1 "Adding new records" , Bulma.hr + , Bulma.columns [] [ + Bulma.column_ [ + Bulma.p "List of buttons:" + , Bulma.btn_add_new_rr (NewRRModal A) "A" + , Bulma.btn_add_new_rr (NewRRModal AAAA) "AAAA" + ] + ] , Bulma.columns [] [ render_new_record_column_simple state._newSRR state._errors , render_new_record_colunm_mx state._newMXRR state._errors diff --git a/src/Bulma.purs b/src/Bulma.purs index 689fdb8..9662a24 100644 --- a/src/Bulma.purs +++ b/src/Bulma.purs @@ -292,26 +292,23 @@ btn_delete action btn_add :: forall w i. i -> i -> Boolean -> HH.HTML w i btn_add action1 action2 validity = HH.button - [ btn_add_action validity + [ if validity then (HE.onClick \_ -> action1) else (HE.onClick \_ -> action2) , HP.classes $ btn_classes validity ] [ HH.text "Add" ] - where - - btn_add_action = case _ of - true -> HE.onClick \_ -> action1 - _ -> HE.onClick \_ -> action2 +btn_add_new_rr :: forall w i. i -> String -> HH.HTML w i +btn_add_new_rr action title + = HH.button + [ HE.onClick \_ -> action + , HP.classes $ C.button <> C.is_small <> C.is_info + ] [ HH.text title ] btn :: forall w action. String -> action -> action -> Boolean -> HH.HTML w action btn title action1 action2 validity = HH.button - [ btn_add_action validity + [ if validity then (HE.onClick \_ -> action1) else (HE.onClick \_ -> action2) , HP.classes $ btn_classes validity ] [ HH.text title ] - where - btn_add_action = case _ of - true -> HE.onClick \_ -> action1 - _ -> HE.onClick \_ -> action2 render_input :: forall w i. Boolean -> String -> String -> (String -> i) -> String -> Boolean -> (HP.IProp DHI.HTMLinput i) -> HH.HTML w i @@ -446,23 +443,39 @@ container = HH.div [HP.classes (C.container <> C.is_info)] data_target :: forall r i. String -> HP.IProp r i data_target = HP.attr (AttrName "data-target") +modal :: forall w i. Array (HH.HTML w i) -> HH.HTML w i +modal = HH.div [HP.classes (C.modal <> C.is_active)] +modal_background :: forall w i. HH.HTML w i +modal_background = HH.div [HP.classes C.modal_background] [] +modal_card :: forall w i. Array (HH.HTML w i) -> HH.HTML w i +modal_card = HH.div [HP.classes C.modal_card] +modal_header :: forall w i. String -> HH.HTML w i +modal_header title = HH.header [HP.classes C.modal_card_head] + [ HH.p [HP.classes C.modal_card_title] [HH.text title] + ] +modal_foot :: forall w i. Array (HH.HTML w i) -> HH.HTML w i +modal_foot = HH.div [HP.classes C.modal_card_foot] + +modal_cancel_button :: forall w i. i -> HH.HTML w i +modal_cancel_button action + = HH.button [ HP.classes C.button + , HE.onClick \_ -> action + ] [HH.text "Cancel"] + modal_domain_delete :: forall w i. String -> HH.HTML w i modal_domain_delete domain = modal [ modal_background - , modal_card [modal_header, modal_body] + , modal_card [modal_header "Deleting a domain", modal_body] , modal_foot [modal_delete_button, modal_cancel_button] ] where - modal = HH.div [HP.classes (C.modal <> C.is_active)] - modal_background = HH.div [HP.classes C.modal_background] [] - modal_card = HH.div [HP.classes C.modal_card] - modal_header = HH.header [HP.classes C.modal_card_head] - [ HH.p [HP.classes C.modal_card_title] [HH.text "Deleting a domain"] - --, HH.button [HP.classes C.delete, ARIA.label "close"] [] - ] + -- modal_header = HH.header [HP.classes C.modal_card_head] + -- [ HH.p [HP.classes C.modal_card_title] [HH.text "Deleting a domain"] + -- --, HH.button [HP.classes C.delete, ARIA.label "close"] [] + -- ] modal_body = HH.section [HP.classes C.modal_card_body] [ warning_message ] - modal_foot = HH.div [HP.classes C.modal_card_foot] + -- modal_foot = HH.div [HP.classes C.modal_card_foot] modal_delete_button = HH.button [HP.classes (C.button <> C.is_success)] [HH.text "Delete the domain."] modal_cancel_button = HH.button [HP.classes C.button] [HH.text "Cancel"] warning_message