on master help sign in
Got menu working
commit9aeb088300d1c6eb5fcd0bb146244b1beafaa70b authoriko <ilyakooo0@gmail.com> dateFri 29 Jul 2022, 21:37 (4 years ago) parent812de5e
3 files changed+189−149
frontend/Main.elm+32−75 frontend/Pages/Ciphers.elm+88−4 frontend/Pages/Navigation.elm+69−70
frontend/Main.elm+32−75
@@ -34,8 +34,6 @@ type Msg
3434 | ShowCipherPage Bridge.Sub_LoadCipher
3535 | RequestCipher CipherId
3636 | PopView
37− | ToggleMenu
38− | ChangeFilter CipherFilter
3937
4038
4139type alias CipherId =
@@ -45,9 +43,6 @@ type alias CipherId =
4543type alias Model =
4644 { notifications : List Notification.Config
4745 , pageStack : Navigation.PageStack PageModel
48− , menuShown : Bool
49− , email : Maybe String
50− , filter : CipherFilter
5146 }
5247
5348
@@ -64,7 +59,13 @@ type PageModel
6459 | CipherModel Cipher.Model
6560
6661
67−showPage : PageModel -> ( String, List (Html Msg) )
62+showPage :
63+ PageModel
64+ ->
65+ { title : String
66+ , body : List (Html Msg)
67+ , topButton : Maybe (Navigation.TopButton Msg)
68+ }
6869showPage page =
6970 case page of
7071 LoginModel model ->
@@ -72,31 +73,50 @@ showPage page =
7273 p =
7374 Login.page loginCallbacks LoginMsg
7475 in
75− ( p.title model, p.view model )
76+ { title = p.title model
77+ , body = p.view model
78+ , topButton = Nothing
79+ }
7680
7781 CiphersModel model ->
7882 let
7983 p =
8084 Ciphers.page ciphersCallbacks CiphersMsg
8185 in
82− ( p.title model, p.view model )
86+ { title = p.title model
87+ , body = p.view model
88+ , topButton =
89+ Ciphers.menuConfig model
90+ |> Navigation.mapMenuConfig CiphersMsg
91+ |> Navigation.MenuButton
92+ |> Just
93+ }
8394
8495 LoadingPage ->
85− ( "", [ loader ] )
96+ { title = ""
97+ , body = [ loader ]
98+ , topButton = Nothing
99+ }
86100
87101 MasterPasswordModel model ->
88102 let
89103 p =
90104 MasterPassword.page masterPasswordCallbacks MasterPasswordMsg
91105 in
92− ( p.title model, p.view model )
106+ { title = p.title model
107+ , body = p.view model
108+ , topButton = Nothing
109+ }
93110
94111 CipherModel model ->
95112 let
96113 p =
97114 Cipher.page cipherCallbacks CipherMsg
98115 in
99− ( p.title model, p.view model )
116+ { title = p.title model
117+ , body = p.view model
118+ , topButton = Nothing
119+ }
100120
101121
102122main : Program () Model Msg
@@ -137,78 +157,18 @@ subscriptions _ =
137157 )
138158
139159
140−type CipherFilter
141− = AnyCipher
142− | Specific Bridge.Sub_LoadCiphers_cipherType
143−
144−
145−applyCipherFilter : CipherFilter -> Bridge.Sub_LoadCiphers_List -> Bridge.Sub_LoadCiphers_List
146−applyCipherFilter filter list =
147− case filter of
148− AnyCipher ->
149− list
150−
151− Specific t ->
152− list |> List.filter (.cipherType >> (==) t)
153−
154−
155160init : ( Model, Cmd Msg )
156161init =
157162 ( { notifications = []
158163 , pageStack = Nonempty.singleton LoadingPage
159− , menuShown = False
160− , email = Nothing
161− , filter = AnyCipher
162164 }
163165 , FFI.sendBridge Bridge.Init
164166 )
165167
166168
167−pageShouldShowMenu : PageModel -> Bool
168−pageShouldShowMenu page =
169− case page of
170− CiphersModel _ ->
171− True
172−
173− _ ->
174− False
175−
176−
177169view : Model -> Html Msg
178170view model =
179− Navigation.showNavigationView
180− { popStack = PopView
181− , toggleMenu = ToggleMenu
182− }
183− model.pageStack
184− (\page ->
185− let
186− ( title, body ) =
187− case page of
188− CiphersModel m ->
189− CiphersModel { m | ciphers = m.ciphers |> applyCipherFilter model.filter }
190− |> showPage
191−
192− _ ->
193− showPage page
194− in
195− { title = title
196− , body = maybeList (List.head model.notifications) (Notification.notification CloseNotification) ++ body
197− , menuConfig =
198− if pageShouldShowMenu page && model.menuShown then
199− Just
200− { title = Maybe.withDefault "" model.email
201− , items =
202− [ { icons = "", name = "", trigger = ChangeFilter AnyCipher }
203− ]
204− , close = ToggleMenu
205− }
206−
207− else
208− Nothing
209− , menuPossible = pageShouldShowMenu page
210− }
211− )
171+ Navigation.showNavigationView model.pageStack showPage
212172
213173
214174mapHead : (a -> a) -> Nonempty a -> Nonempty a
@@ -357,9 +317,6 @@ update msg model =
357317 , Cmd.none
358318 )
359319
360− ToggleMenu ->
361− ( { model | menuShown = not model.menuShown }, Cmd.none )
362−
363320
364321loginCallbacks : Login.Callbacks Msg
365322loginCallbacks =
frontend/Pages/Ciphers.elm+88−4
@@ -1,10 +1,11 @@
1−module Pages.Ciphers exposing (Callbacks, Model, Msg, page)
1+module Pages.Ciphers exposing (Callbacks, Model, Msg, menuConfig, page)
22
33import Bridge
44import Html exposing (..)
55import Html.Attributes as Attr
66import Html.Events as Ev
77import Page exposing (..)
8+import Pages.Navigation as Navigation
89import Search
910import Utils exposing (..)
1011
@@ -12,12 +13,66 @@ import Utils exposing (..)
1213type alias Model =
1314 { ciphers : Bridge.Sub_LoadCiphers_List
1415 , search : String
16+ , menuVisible : Bool
17+ , ciphersListFilter : CiphersFilter
18+ }
19+
20+
21+type CiphersFilter
22+ = AllCiphers
23+ | SpecificCiphers Bridge.Sub_LoadCiphers_cipherType
24+
25+
26+applyCipherFilter : CiphersFilter -> Bridge.Sub_LoadCiphers_List -> Bridge.Sub_LoadCiphers_List
27+applyCipherFilter filter list =
28+ case filter of
29+ AllCiphers ->
30+ list
31+
32+ SpecificCiphers t ->
33+ list |> List.filter (.cipherType >> (==) t)
34+
35+
36+menuConfig : Model -> Navigation.MenuConfig Msg
37+menuConfig { ciphersListFilter, menuVisible } =
38+ { title = "TODO"
39+ , items =
40+ [ { icon = "units"
41+ , name = "All items"
42+ , trigger = UpdateFilter AllCiphers
43+ , current = ciphersListFilter == AllCiphers
44+ }
45+ , { icon = "security"
46+ , name = "Passwords"
47+ , trigger = UpdateFilter (SpecificCiphers Bridge.LoginType)
48+ , current = ciphersListFilter == SpecificCiphers Bridge.LoginType
49+ }
50+ , { icon = "edit"
51+ , name = "Notes"
52+ , trigger = UpdateFilter (SpecificCiphers Bridge.NoteType)
53+ , current = ciphersListFilter == SpecificCiphers Bridge.NoteType
54+ }
55+ , { icon = "containers"
56+ , name = "Cards"
57+ , trigger = UpdateFilter (SpecificCiphers Bridge.CardType)
58+ , current = ciphersListFilter == SpecificCiphers Bridge.CardType
59+ }
60+ , { icon = "user"
61+ , name = "Identities"
62+ , trigger = UpdateFilter (SpecificCiphers Bridge.IdentityType)
63+ , current = ciphersListFilter == SpecificCiphers Bridge.IdentityType
64+ }
65+ ]
66+ , toggle = ToggleMenu
67+ , visible = menuVisible
1568 }
1669
1770
1871type Msg
1972 = Noop
2073 | UpdateSearch String
74+ | ToggleMenu
75+ | UpdateFilter CiphersFilter
2176
2277
2378type alias Callbacks msg =
@@ -31,13 +86,35 @@ page callbacks liftMsg =
3186 , view = view callbacks liftMsg
3287 , update = \msg model -> update callbacks liftMsg msg model
3388 , subscriptions = \model -> subscriptions model |> Sub.map liftMsg
34− , title = always "Passwords"
89+ , title =
90+ \{ ciphersListFilter } ->
91+ case ciphersListFilter of
92+ AllCiphers ->
93+ "All items"
94+
95+ SpecificCiphers cipherType ->
96+ case cipherType of
97+ Bridge.CardType ->
98+ "Cards"
99+
100+ Bridge.IdentityType ->
101+ "Identities"
102+
103+ Bridge.LoginType ->
104+ "Passwords"
105+
106+ Bridge.NoteType ->
107+ "Notes"
35108 }
36109
37110
38111init : Bridge.Sub_LoadCiphers_List -> ( Model, Cmd Msg )
39112init ciphers =
40− ( { ciphers = ciphers, search = "" }
113+ ( { ciphers = ciphers
114+ , search = ""
115+ , menuVisible = False
116+ , ciphersListFilter = AllCiphers
117+ }
41118 , Cmd.none
42119 )
43120
@@ -51,6 +128,12 @@ update {} liftMsg msg model =
51128 UpdateSearch s ->
52129 ( Ok { model | search = s }, Cmd.none )
53130
131+ ToggleMenu ->
132+ ( Ok { model | menuVisible = not model.menuVisible }, Cmd.none )
133+
134+ UpdateFilter filter ->
135+ ( Ok { model | ciphersListFilter = filter, menuVisible = False }, Cmd.none )
136+
54137
55138subscriptions : Model -> Sub Msg
56139subscriptions model =
@@ -58,7 +141,7 @@ subscriptions model =
58141
59142
60143view : Callbacks emsg -> (Msg -> emsg) -> Model -> List (Html emsg)
61−view { selected } liftMsg { ciphers, search } =
144+view { selected } liftMsg { ciphers, search, ciphersListFilter } =
62145 [ input
63146 [ Attr.type_ "search"
64147 , Attr.value search
@@ -69,6 +152,7 @@ view { selected } liftMsg { ciphers, search } =
69152 []
70153 , ul [ Attr.class "p-list--divided" ]
71154 (ciphers
155+ |> applyCipherFilter ciphersListFilter
72156 |> Search.searchList (cipherSearch search)
73157 |> List.map
74158 (\{ name, date, id } ->
frontend/Pages/Navigation.elm+69−70
@@ -1,7 +1,9 @@
11module Pages.Navigation exposing
22 ( Config
3+ , MenuConfig
34 , PageStack
4− , menu
5+ , TopButton(..)
6+ , mapMenuConfig
57 , popView
68 , pushView
79 , showNavigationView
@@ -14,78 +16,91 @@ import List.Nonempty as Nonempty exposing (Nonempty)
1416import Utils exposing (..)
1517
1618
17−type TopButton
18− = BackButton
19− | MenuButton
19+type TopButton msg
20+ = BackButton msg
21+ | MenuButton (MenuConfig msg)
2022
2123
2224type alias Config msg =
23− { topButton : Maybe TopButton
25+ { topButton : Maybe (TopButton msg)
2426 , title : String
25− , pop : msg
26− , toggleMenu : msg
2727 }
2828
2929
30−navigation : Config msg -> Html msg
31−navigation { topButton, title, pop, toggleMenu } =
32− nav [ Attr.class "p-tabs p-tabs__list" ]
33− [ h3 [ Attr.class "u-no-margin u-no-padding" ]
34− [ button
35− (Attr.class "p-button--base is-inline u-no-margin" :: optional (Nothing == topButton) (Attr.style "visibility" "hidden"))
36− [ i
37− [ Attr.class
38− (case topButton of
39− Just BackButton ->
40− "p-icon--chevron-up ninety-counter"
30+navigation : Config msg -> List (Html msg)
31+navigation { topButton, title } =
32+ (case topButton of
33+ Just (MenuButton cfg) ->
34+ optional cfg.visible (menu cfg)
4135
42− Just MenuButton ->
43− "p-icon--menu"
44−
45− Nothing ->
46− ""
47− )
48− , Ev.onClick
49− (case topButton of
50− Nothing ->
51− pop
52−
53− Just BackButton ->
54− pop
55−
56− Just MenuButton ->
57− toggleMenu
58− )
36+ _ ->
37+ []
38+ )
39+ ++ [ nav [ Attr.class "p-tabs p-tabs__list" ]
40+ [ h3 [ Attr.class "u-no-margin u-no-padding" ]
41+ [ case topButton of
42+ Nothing ->
43+ button
44+ [ Attr.class "p-button--base is-inline u-no-margin", Attr.style "visibility" "hidden" ]
45+ []
46+
47+ Just (BackButton msg) ->
48+ button
49+ [ Attr.class "p-button--base is-inline u-no-margin", Ev.onClick msg ]
50+ [ i [ Attr.class "p-icon--chevron-up ninety-counter" ] [] ]
51+
52+ Just (MenuButton cfg) ->
53+ button
54+ [ Attr.class "p-button--base is-inline u-no-margin", Ev.onClick cfg.toggle ]
55+ [ i [ Attr.class "p-icon--menu" ] [] ]
56+ , text title
5957 ]
60− []
6158 ]
62− , text title
63− ]
64− ]
59+ ]
6560
6661
6762type alias MenuConfig msg =
6863 { title : String
69− , items : List { icon : String, name : String, trigger : msg }
70− , close : msg
64+ , items : List { icon : String, name : String, trigger : msg, current : Bool }
65+ , toggle : msg
66+ , visible : Bool
67+ }
68+
69+
70+mapMenuConfig : (a -> b) -> MenuConfig a -> MenuConfig b
71+mapMenuConfig f { title, items, toggle, visible } =
72+ { items =
73+ List.map
74+ (\{ icon, name, trigger, current } ->
75+ { icon = icon, name = name, trigger = f trigger, current = current }
76+ )
77+ items
78+ , title = title
79+ , toggle = f toggle
80+ , visible = visible
7181 }
7282
7383
7484menu : MenuConfig msg -> Html msg
75−menu { title, items, close } =
85+menu { title, items, toggle } =
7686 div [ Attr.class "p-side-navigation--icons is-drawer-expanded" ]
7787 [ div [ Attr.class "p-side-navigation__overlay" ] []
7888 , nav [ Attr.class "p-side-navigation__drawer" ]
7989 [ div [ Attr.class "p-side-navigation__drawer-header" ]
80− [ a [ Attr.class "p-side-navigation__toggle--in-drawer", Ev.onClick close ] [ text title ]
90+ [ a [ Attr.class "p-side-navigation__toggle--in-drawer", Ev.onClick toggle ] [ text title ]
8191 ]
8292 , ul [ Attr.class "p-side-navigation__list" ]
8393 (items
8494 |> List.map
85− (\{ icon, name, trigger } ->
95+ (\{ icon, name, trigger, current } ->
8696 li [ Attr.class "p-side-navigation__item" ]
8797 [ a [ Attr.class "p-side-navigation__link", Ev.onClick trigger ]
88− [ i [ Attr.class "p-side-navigation__icon", Attr.class ("p-icon--" ++ icon) ] []
98+ [ i
99+ [ Attr.class "p-side-navigation__icon"
100+ , Attr.class ("p-icon--" ++ icon)
101+ , Attr.classList [ ( "is-active", current ) ]
102+ ]
103+ []
89104 , text name
90105 ]
91106 ]
@@ -110,41 +125,25 @@ popView stack =
110125
111126
112127showNavigationView :
113− { popStack : msg
114− , toggleMenu : msg
115− }
116− -> PageStack model
128+ PageStack model
117129 ->
118130 (model
119131 ->
120132 { title : String
121133 , body : List (Html msg)
122− , menuConfig : Maybe (MenuConfig msg)
123− , menuPossible : Bool
134+ , topButton : Maybe (TopButton msg)
124135 }
125136 )
126137 -> Html msg
127−showNavigationView { popStack, toggleMenu } stack render =
138+showNavigationView stack render =
128139 let
129− { title, body, menuConfig, menuPossible } =
140+ { title, body, topButton } =
130141 render (Nonempty.head stack)
131142 in
132143 div []
133− (maybeList menuConfig menu
134− ++ [ navigation
135− { topButton =
136− if menuPossible then
137− Just MenuButton
138−
139− else if Nonempty.length stack > 1 then
140− Just BackButton
141−
142− else
143− Nothing
144− , title = title
145− , pop = popStack
146− , toggleMenu = toggleMenu
147− }
148− , main_ [] body
149− ]
144+ (navigation
145+ { topButton = topButton
146+ , title = title
147+ }
148+ ++ [ main_ [] body ]
150149 )