209 lines
8.3 KiB
Text
209 lines
8.3 KiB
Text
-- | `App.NavigationInterface` is the navbar module.
|
|
-- |
|
|
-- | This module is required since some javascript is needed to toggle display of hidden resources.
|
|
-- | On mobile, a burger menu is displayed and hides the navigation buttons.
|
|
-- | On desktop, there is no need for this, all the navigation buttons are displayed by default.
|
|
module App.Page.Navigation where
|
|
|
|
import Prelude (Unit, (<>), not, ($), discard, pure)
|
|
|
|
-- import Data.Array as A
|
|
import Data.Maybe (Maybe(..))
|
|
-- import Data.Either (Either(..))
|
|
import Effect.Aff.Class (class MonadAff)
|
|
import Halogen as H
|
|
import Halogen.HTML as HH
|
|
import Halogen.HTML.Events as HE
|
|
import Halogen.HTML.Properties as HP
|
|
import Halogen.HTML.Properties.ARIA as ARIA
|
|
|
|
import CSSClasses as C
|
|
import Bulma as Bulma
|
|
|
|
import App.Type.Pages (Page(..))
|
|
import App.Type.LogMessage (LogMessage)
|
|
|
|
data Output
|
|
= Log LogMessage
|
|
-- | Once someone clicks on a routing button, `App.Container` needs to know.
|
|
| Routing Page
|
|
-- | Once someone clicks on a the Disconnection button, `App.Container` needs to know.
|
|
| Disconnection
|
|
|
|
-- | The component needs to know when the user is logged or not.
|
|
data Query a
|
|
= ToggleLogged Boolean a
|
|
| ToggleAdmin Boolean a
|
|
|
|
type Slot = H.Slot Query Output
|
|
|
|
type Input = Unit
|
|
|
|
data Action
|
|
-- | `ToggleMenu`: display or hide the content of the burger menu.
|
|
= ToggleMenu
|
|
-- | The navigation interface must be informed when the client wants to change page.
|
|
-- | The request will be propagated to the parent (`App.Container`).
|
|
-- | (`Navigate` is `App.Container.Routing`)
|
|
| Navigate Page
|
|
-- | The navigation interface must be informed when the client wants to disconnect.
|
|
-- | The request will be propagated to the parent (`App.Container`).
|
|
-- | (`UnLog` is `App.Container.Disconnection`)
|
|
| UnLog
|
|
|
|
-- | State is composed of:
|
|
-- | - `logged`, a boolean to toggle the display of some parts of the menu.
|
|
-- | - `active`, a boolean to toggle the display of the menu.
|
|
-- | - `admin`, a boolean to toggle the display of administration page link.
|
|
type State = { logged :: Boolean, active :: Boolean, admin :: Boolean }
|
|
|
|
component :: forall m. MonadAff m => H.Component Query Input Output m
|
|
component =
|
|
H.mkComponent
|
|
{ initialState
|
|
, render
|
|
, eval: H.mkEval $ H.defaultEval { handleAction = handleAction
|
|
, handleQuery = handleQuery
|
|
}
|
|
}
|
|
|
|
initialState :: Input -> State
|
|
initialState _ = { logged: false, active: false, admin: false }
|
|
|
|
handleAction :: forall m. MonadAff m => Action -> H.HalogenM State Action () Output m Unit
|
|
handleAction = case _ of
|
|
ToggleMenu -> H.modify_ \state -> state { active = not state.active }
|
|
-- | Page change.
|
|
Navigate page -> H.raise $ Routing page
|
|
UnLog -> do
|
|
H.raise $ Disconnection
|
|
H.modify_ _ { logged = false }
|
|
|
|
handleQuery :: forall a m. MonadAff m => Query a -> H.HalogenM State Action () Output m (Maybe a)
|
|
handleQuery = case _ of
|
|
ToggleLogged islogged a -> do
|
|
H.modify_ _ { logged = islogged }
|
|
pure (Just a)
|
|
ToggleAdmin isadmin a -> do
|
|
H.modify_ _ { admin = isadmin }
|
|
pure (Just a)
|
|
|
|
|
|
-- | The navigation bar is a complex component to render.
|
|
-- | The component changes when the user is authenticated.
|
|
-- | A button has to appear for administrators.
|
|
-- |
|
|
-- | On mobile (a device with low resolution), a `burger icon` appears instead of the navigation bar.
|
|
-- | When clicked, a list of options (such as pages or a disconnection button) should appear.
|
|
-- | Also, when clicked again, the list disappears.
|
|
|
|
render :: forall m. State -> H.ComponentHTML Action () m
|
|
render { logged, active, admin } =
|
|
main_nav
|
|
[ nav_brand [ logo, burger_menu ]
|
|
, nav_menu
|
|
[ navbar_start left_bar_div
|
|
, navbar_end right_bar_div
|
|
]
|
|
]
|
|
|
|
where
|
|
left_bar_div =
|
|
case logged, admin of
|
|
false, _ -> [ link_home, code_dropdown ]
|
|
_, false -> [ link_home, link_domains, code_dropdown ]
|
|
_, _ -> [ link_home, link_domains, link_authd_admin, code_dropdown ]
|
|
|
|
right_bar_div =
|
|
case logged of
|
|
false -> [ link_auth, link_register, link_mail_validation ]
|
|
_ -> [ link_setup, link_disconnection ]
|
|
|
|
navbar_color = C.is_success
|
|
|
|
main_nav =
|
|
HH.nav [ HP.classes $ C.navbar <> navbar_color
|
|
, ARIA.label "main navigation"
|
|
, ARIA.role "navigation"
|
|
]
|
|
|
|
logo = HH.strong [HP.classes $ C.navbar_item <> (C.is_size 4)] [HH.text "🔻🍉"]
|
|
-- HH.a [HP.classes C.navbar_item, HP.href "/"]
|
|
-- [HH.img [HP.src "/logo.jpeg", HP.width 112, HP.height 28]]
|
|
|
|
burger_menu =
|
|
HH.a [ HP.classes $ C.navbar_burger <> if active then C.is_active else []
|
|
, ARIA.label "menu"
|
|
, ARIA.expanded "false"
|
|
, Bulma.data_target "navbar-netlibre"
|
|
, HE.onClick (\_ -> ToggleMenu)
|
|
] [ HH.span [ARIA.hidden "true"] []
|
|
, HH.span [ARIA.hidden "true"] []
|
|
, HH.span [ARIA.hidden "true"] []
|
|
]
|
|
|
|
nav_brand = HH.div [HP.classes C.navbar_brand]
|
|
nav_menu = HH.div
|
|
[ HP.id "navbar-netlibre"
|
|
, HP.classes $ C.navbar_menu <> C.is_spaced <> if active then C.is_active else []
|
|
]
|
|
|
|
navbar_start = HH.div [HP.classes C.navbar_start]
|
|
navbar_end = HH.div [HP.classes C.navbar_end]
|
|
|
|
link_home = nav_link "Home" (Navigate Home)
|
|
link_domains = nav_link "Domains" (Navigate DomainList)
|
|
link_authd_admin = nav_link "Admin" (Navigate Administration)
|
|
link_auth = nav_link "Login" (Navigate Authentication)
|
|
link_register = nav_link_strong "Register" (Navigate Registration)
|
|
link_mail_validation = nav_link "Mail verification" (Navigate MailValidation)
|
|
link_setup = nav_link_warn "⚒ Setup" (Navigate Setup)
|
|
link_disconnection =
|
|
nav_link_ (C.has_text_light <> C.has_background_danger) "Disconnection" UnLog
|
|
|
|
dropdown title dropdown_elements
|
|
= HH.div [HP.classes $ C.navbar_item <> C.has_dropdown <> C.is_hoverable]
|
|
[ dropdown_title title, HH.div [HP.classes C.navbar_dropdown] dropdown_elements ]
|
|
dropdown_title str = HH.a [HP.classes C.navbar_link] [HH.text str]
|
|
dropdown_separator = HH.hr [HP.classes C.navbar_divider]
|
|
|
|
--nav_button_strong str action = btn C.is_primary action (HH.strong [] [ HH.text str ])
|
|
--nav_button classes str action = btn classes action (HH.text str)
|
|
|
|
nav_link_strong str action =
|
|
HH.a [ HP.classes (C.navbar_item <> C.is_danger <> C.has_background_success_dark)
|
|
, HE.onClick (\_ -> action)
|
|
] [ (HH.strong [] [ HH.text str ]) ]
|
|
|
|
nav_link str action = nav_link_ navbar_color str action
|
|
nav_link_warn str action = nav_link_ (C.has_background_warning <> C.has_text_dark) str action
|
|
|
|
nav_link_ classes str action =
|
|
HH.a [ HP.classes (C.navbar_item <> classes)
|
|
, HE.onClick (\_ -> action)
|
|
] [ (HH.text str) ]
|
|
|
|
dropdown_element classes link str = HH.a [HP.classes (C.navbar_item <> classes), HP.href link] [HH.text str]
|
|
dropdown_element_primary link str = dropdown_element C.has_background_info_light link str
|
|
dropdown_element_secondary link str = dropdown_element C.has_background_warning_light link str
|
|
|
|
dropdown_section_primary t
|
|
= HH.p [HP.classes $ C.has_background_info <> C.has_text_light <> C.navbar_item] [HH.text t]
|
|
dropdown_section_secondary t
|
|
= HH.p [HP.classes $ C.has_background_warning <> C.navbar_item] [HH.text t]
|
|
code_dropdown =
|
|
dropdown "Source code"
|
|
[ dropdown_section_primary "Main parts of this service"
|
|
, dropdown_element_primary "https://git.baguette.netlib.re/Baguette/authd" "authentication daemon"
|
|
, dropdown_element_primary "https://git.baguette.netlib.re/Baguette/dnsmanager" "dnsmanager daemon"
|
|
, dropdown_element_primary "https://git.baguette.netlib.re/Baguette/dnsmanager-webclient" "dnsmanager web client"
|
|
, dropdown_separator
|
|
, dropdown_section_secondary "A few more links (for nerds)"
|
|
, dropdown_element_secondary "https://git.baguette.netlib.re/Baguette/libipc" "libIPC: communication library"
|
|
, dropdown_element_secondary "https://git.baguette.netlib.re/Baguette/dodb.cr" "DoDB: document-oriented database"
|
|
]
|
|
|
|
--btn c action str
|
|
-- = HH.a [ HP.classes (C.navbar_item <> C.button <> c)
|
|
-- , HE.onClick (\_ -> action)
|
|
-- ] [ str ]
|