From 10038dc214793ae766c01bf2eecb7a662ba78722 Mon Sep 17 00:00:00 2001 From: Philippe Pittoli Date: Fri, 15 Mar 2024 02:02:01 +0100 Subject: [PATCH] Add a fancy tabulation system. --- src/App/Page/Zone.purs | 36 +++++++++++++++++++++++++++++++--- src/App/Text/Explanations.purs | 7 +++++++ src/Bulma.purs | 12 ++++++++++++ src/CSSClasses.purs | 21 +++++++++++++++----- 4 files changed, 68 insertions(+), 8 deletions(-) diff --git a/src/App/Page/Zone.purs b/src/App/Page/Zone.purs index a70029a..afeec9b 100644 --- a/src/App/Page/Zone.purs +++ b/src/App/Page/Zone.purs @@ -24,6 +24,7 @@ import Prelude (Unit, unit, void , (+), (&&), ($), (/=), (<<<), (<>), (==), (>), (#)) +import Data.Eq (class Eq) import Data.Array as A import Data.Int (fromString) import Data.Tuple (Tuple(..)) @@ -131,6 +132,9 @@ data Action -- | Create a modal to ask confirmation before deleting a resource record. | DeleteRRModal RRId + -- | Change the current tab. + | ChangeTab Tab + -- | Update new entry form (in the `rr_modal` modal). | UpdateCurrentRR Field @@ -210,6 +214,9 @@ string_to_acceptedtype str = case str of "DKIM" -> Just DKIM _ -> Nothing +data Tab = Zone | TokenExplanation +derive instance eqTab :: Eq Tab + type State = { _domain :: String , wsUp :: Boolean @@ -235,6 +242,8 @@ type State = , dkim :: DKIM.DKIM , _zonefile :: Maybe String + + , current_tab :: Tab } component :: forall m. MonadAff m => H.Component Query Input Output m @@ -284,6 +293,8 @@ initialState domain = , spf_modifier_t: "redirect" , spf_modifier_v: "" , dkim: DKIM.emptyDKIMRR + + , current_tab: Zone } type SortableRecord l = Record (rrtype :: String, rrid :: Int | l) @@ -291,7 +302,23 @@ 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.rr_modal of + [ fancy_tab + , case state.current_tab of + Zone -> render_zone + TokenExplanation -> render_token_explanation + ] + where + fancy_tab = + Bulma.fancy_tabs + [ Bulma.tab_entry (is_tab_active Zone) "Zone" (ChangeTab Zone) + , Bulma.tab_entry (is_tab_active TokenExplanation) "Tokens? 🤨" (ChangeTab TokenExplanation) + ] + is_tab_active tab = state.current_tab == tab + + render_token_explanation = Bulma.explanation Explanations.token_introduction + + render_zone = + case state.wsUp, state.rr_modal of false, _ -> Bulma.p "You are disconnected." true, RemoveRRModal rr_id -> modal_rr_delete rr_id true, NewRRModal _ -> render_current_rr_modal @@ -304,8 +331,7 @@ render state , render_new_records state , render_zonefile state._zonefile ] - ] - where + sorted :: forall l. Array (SortableRecord (l)) -> Array (SortableRecord (l)) sorted array = A.groupAllBy (comparing (_.rrtype)) array -- [x2 z2 x1 y z1 z3] -> [ NE[x2x1] NE[y] NE[z2z1z3] ] @@ -525,6 +551,10 @@ handleAction = case _ of DeleteRRModal rr_id -> do H.modify_ _ { rr_modal = RemoveRRModal rr_id } + -- | Change the current tab. + ChangeTab new_tab -> do + H.modify_ _ { current_tab = new_tab } + -- | Create modal (a form) for a resource record to update. CreateUpdateRRModal rr_id -> do state <- H.get diff --git a/src/App/Text/Explanations.purs b/src/App/Text/Explanations.purs index 6b867d3..820f98e 100644 --- a/src/App/Text/Explanations.purs +++ b/src/App/Text/Explanations.purs @@ -2,6 +2,13 @@ module App.Text.Explanations where import Halogen.HTML as HH import Bulma as Bulma +token_introduction :: forall w i. Array (HH.HTML w i) +token_introduction = + [ Bulma.p """ + Tokens are a way to update a resource record (A or AAAA) in a very simple way. + """ + ] + dkim_introduction :: forall w i. Array (HH.HTML w i) dkim_introduction = [ Bulma.p """ diff --git a/src/Bulma.purs b/src/Bulma.purs index 9eba779..ab3505c 100644 --- a/src/Bulma.purs +++ b/src/Bulma.purs @@ -494,3 +494,15 @@ div_content content = HH.div [HP.classes (C.content)] content explanation :: forall w i. Array (HH.HTML w i) -> HH.HTML w i explanation content = HH.blockquote [HP.classes [HH.ClassName "justified"]] content + + +tabs :: forall w i. Array HH.ClassName -> Array (HH.HTML w i) -> HH.HTML w i +tabs classes tab_list = HH.div [HP.classes $ C.tabs <> classes] [HH.ul_ tab_list] + +fancy_tabs :: forall w i. Array (HH.HTML w i) -> HH.HTML w i +fancy_tabs arr = tabs (C.is_medium <> C.is_boxed <> C.is_centered) arr + +tab_entry :: forall w i. Boolean -> String -> i -> HH.HTML w i +tab_entry active name action = + HH.li (if active then [HP.classes C.is_active] else []) + [ HH.a [HE.onClick \_ -> action] [HH.text name] ] diff --git a/src/CSSClasses.purs b/src/CSSClasses.purs index e408051..0564690 100644 --- a/src/CSSClasses.purs +++ b/src/CSSClasses.purs @@ -4,6 +4,18 @@ import Prelude (show, ($), (<>)) import Halogen.HTML as HH +margin_left :: Int -> Array HH.ClassName +margin_left size = [HH.ClassName $ "ml-" <> show size] + +is :: Int -> Array HH.ClassName +is size = [HH.ClassName $ "is-" <> show size] + +is_size :: Int -> Array HH.ClassName +is_size size = [HH.ClassName $ "is-size-" <> show size] + +padding_left :: Int -> Array HH.ClassName +padding_left size = [HH.ClassName $ "pl-" <> show size] + box = [HH.ClassName "box"] :: Array HH.ClassName breadcrumb = [HH.ClassName "breadcrumb"] :: Array HH.ClassName button = [HH.ClassName "button"] :: Array HH.ClassName @@ -46,6 +58,7 @@ is4 = [HH.ClassName "is-4"] :: is5 = [HH.ClassName "is-5"] :: Array HH.ClassName is_active = [HH.ClassName "is-active"] :: Array HH.ClassName is_ancestor = [HH.ClassName "is-ancestor"] :: Array HH.ClassName +is_boxed = [HH.ClassName "is-boxed"] :: Array HH.ClassName is_centered = [HH.ClassName "is-centered"] :: Array HH.ClassName is_child = [HH.ClassName "is-child"] :: Array HH.ClassName is_danger = [HH.ClassName "is-danger"] :: Array HH.ClassName @@ -55,12 +68,11 @@ is_hoverable = [HH.ClassName "is-hoverable"] :: is_info = [HH.ClassName "is-info"] :: Array HH.ClassName is_large = [HH.ClassName "is-large"] :: Array HH.ClassName is_light = [HH.ClassName "is-light"] :: Array HH.ClassName +is_medium = [HH.ClassName "is-medium"] :: Array HH.ClassName is_normal = [HH.ClassName "is-normal"] :: Array HH.ClassName is_parent = [HH.ClassName "is-parent"] :: Array HH.ClassName is_primary = [HH.ClassName "is-primary"] :: Array HH.ClassName is_selected = [HH.ClassName "is-selected"] :: Array HH.ClassName -is size = [HH.ClassName $ "is-" <> show size] :: Array HH.ClassName -is_size size = [HH.ClassName $ "is-size-" <> show size] :: Array HH.ClassName is_small = [HH.ClassName "is-small"] :: Array HH.ClassName is_spaced = [HH.ClassName "is-spaced"] :: Array HH.ClassName is_static = [HH.ClassName "is-static"] :: Array HH.ClassName @@ -72,7 +84,6 @@ level = [HH.ClassName "level"] :: level_item = [HH.ClassName "level-item"] :: Array HH.ClassName level_left = [HH.ClassName "level-left"] :: Array HH.ClassName level_right = [HH.ClassName "level-right"] :: Array HH.ClassName -margin_left size = [HH.ClassName $ "ml-" <> show size] :: Array HH.ClassName medium = [HH.ClassName "is-medium"] :: Array HH.ClassName message_body = [HH.ClassName "message-body"] :: Array HH.ClassName message_header = [HH.ClassName "message-header"] :: Array HH.ClassName @@ -95,16 +106,16 @@ navbar_link = [HH.ClassName "navbar-link"] :: navbar_menu = [HH.ClassName "navbar-menu"] :: Array HH.ClassName navbar_start = [HH.ClassName "navbar-start"] :: Array HH.ClassName no_margin_bottom = [HH.ClassName "mb-0"] :: Array HH.ClassName -no_padding_left = [HH.ClassName "pl-0"] :: Array HH.ClassName no_padding_bottom = [HH.ClassName "pb-0"] :: Array HH.ClassName +no_padding_left = [HH.ClassName "pl-0"] :: Array HH.ClassName no_padding_top = [HH.ClassName "pt-0"] :: Array HH.ClassName normal = [HH.ClassName "is-normal"] :: Array HH.ClassName notification = [HH.ClassName "notification"] :: Array HH.ClassName -padding_left size = [HH.ClassName $ "pl-" <> show size] :: Array HH.ClassName section = [HH.ClassName "section"] :: Array HH.ClassName select = [HH.ClassName "select"] :: Array HH.ClassName subtitle = [HH.ClassName "subtitle"] :: Array HH.ClassName table = [HH.ClassName "table"] :: Array HH.ClassName +tabs = [HH.ClassName "tabs"] :: Array HH.ClassName tag = [HH.ClassName "tag"] :: Array HH.ClassName tags = [HH.ClassName "tags"] :: Array HH.ClassName textarea = [HH.ClassName "textarea"] :: Array HH.ClassName