on master help sign in
Got creation working
c9bade6iko
backend/BW.js+6−1
@@ -17,6 +17,7 @@ import { StateService as BaseStateService } from "../../deps/bw/libs/shared/dist
17import { PasswordTokenRequest } from "../../deps/bw/libs/shared/dist/src/models/request/identityToken/passwordTokenRequest";
17import { PasswordTokenRequest } from "../../deps/bw/libs/shared/dist/src/models/request/identityToken/passwordTokenRequest";
18import { TokenRequestTwoFactor } from "../../deps/bw/libs/common/src/models/request/identityToken/tokenRequestTwoFactor";
18import { TokenRequestTwoFactor } from "../../deps/bw/libs/common/src/models/request/identityToken/tokenRequestTwoFactor";
19import { CipherRequest } from "../../deps/bw/libs/common/src/models/request/cipherRequest";
19import { CipherRequest } from "../../deps/bw/libs/common/src/models/request/cipherRequest";
20+import { CipherCreateRequest } from "../../deps/bw/libs/common/src/models/request/cipherCreateRequest";
20import { Cipher } from "../../deps/bw/libs/common/src/models/domain/cipher";
21import { Cipher } from "../../deps/bw/libs/common/src/models/domain/cipher";
21import { CipherData } from "../../deps/bw/libs/common/src/models/data/cipherData";
22import { CipherData } from "../../deps/bw/libs/common/src/models/data/cipherData";
22import { PasswordGenerationService } from "../../deps/bw/libs/common/src/services/passwordGeneration.service";
23import { PasswordGenerationService } from "../../deps/bw/libs/common/src/services/passwordGeneration.service";
@@ -76,7 +77,7 @@ export function getServices() {
76 )
77 )
77 ),
78 ),
78 getSync: () => api.getSync().then(sanitize),
79 getSync: () => api.getSync().then(sanitize),
79− postCipher: (cipher) => api.postCipher(makeCipherRequest(cipher)),
80+ postCipherCreate: (cipher) => api.postCipherCreate(makeCipherCreateRequest(cipher)),
80 putCipher: (cipher) => api.putCipher(cipher.id, makeCipherRequest(cipher)),
81 putCipher: (cipher) => api.putCipher(cipher.id, makeCipherRequest(cipher)),
81 }
82 }
82 },
83 },
@@ -90,6 +91,10 @@ function makeCipherRequest(cipher) {
90 return new CipherRequest(new Cipher(new CipherData(cipher)))
91 return new CipherRequest(new Cipher(new CipherData(cipher)))
91}
92}
92
93
94+function makeCipherCreateRequest(cipher) {
95+ return new CipherCreateRequest(new Cipher(new CipherData(cipher)))
96+}
97+
93class MainBackground {
98class MainBackground {
94 // messagingService; //: MessagingServiceAbstraction;
99 // messagingService; //: MessagingServiceAbstraction;
95 // storageService; //: StorageServiceAbstraction;
100 // storageService; //: StorageServiceAbstraction;
backend/BW.purs+1−1
@@ -32,7 +32,7 @@ type ApiService
32 -- TODO: There can really be more request and response types. Maybe handle this later.
32 -- TODO: There can really be more request and response types. Maybe handle this later.
33 , postIdentityToken :: PasswordTokenRequest -> Promise (IdentityCaptchaResponse |+| IdentityTokenResponse)
33 , postIdentityToken :: PasswordTokenRequest -> Promise (IdentityCaptchaResponse |+| IdentityTokenResponse)
34 , getSync :: Unit -> Promise SyncResponse
34 , getSync :: Unit -> Promise SyncResponse
35− , postCipher :: CipherResponse -> Promise CipherResponse
35+ , postCipherCreate :: CipherResponse -> Promise CipherResponse
36 , putCipher :: CipherResponse -> Promise CipherResponse
36 , putCipher :: CipherResponse -> Promise CipherResponse
37 }
37 }
38
38
backend/Bridge.purs+1
@@ -448,6 +448,7 @@ derive instance ordCmd_Login :: Ord Cmd_Login
448
448
449data Cmd =
449data Cmd =
450 Copy String
450 Copy String
451+ | CreateCipher FullCipher
451 | GeneratePassword PasswordGeneratorConfig
452 | GeneratePassword PasswordGeneratorConfig
452 | Init
453 | Init
453 | Login Cmd_Login
454 | Login Cmd_Login
backend/Data/EncString.js−1
@@ -1,7 +1,6 @@
1import { EncString } from "../../deps/bw/libs/shared/dist/src/models/domain/encString"
1import { EncString } from "../../deps/bw/libs/shared/dist/src/models/domain/encString"
2
2
3export function fromString(str) {
3export function fromString(str) {
4− console.log("fromString " + str)
5 const x = new EncString(str)
4 const x = new EncString(str)
6 return x
5 return x
7}
6}
backend/Main.purs+8
@@ -198,6 +198,14 @@ main = do
198 password <- liftPromise $ services.passwordGeneration.generatePassword cfg
198 password <- liftPromise $ services.passwordGeneration.generatePassword cfg
199 send $ Bridge.GeneratedPassword password
199 send $ Bridge.GeneratedPassword password
200 pure unit
200 pure unit
201+ Bridge.CreateCipher fullCipher ->
202+ runWithDecryptionKey do
203+ api <- getAuthedApi
204+ cipher <- encodeCipher fullCipher
205+ newCipher <- liftPromise (api.postCipherCreate cipher) >>= decodeCipher
206+ send $ Bridge.CipherChanged newCipher
207+ performSync
208+ pure unit
201
209
202processCipher ::
210processCipher ::
203 forall r.
211 forall r.
bridge.yaml+1
@@ -33,6 +33,7 @@ Cmd:
33- Copy: String
33- Copy: String
34- Open: String
34- Open: String
35- UpdateCipher: FullCipher
35- UpdateCipher: FullCipher
36+- CreateCipher: FullCipher
36- GeneratePassword: PasswordGeneratorConfig
37- GeneratePassword: PasswordGeneratorConfig
37
38
38FullCipher:
39FullCipher:
frontend/Bridge.elm+3
@@ -502,6 +502,7 @@ jsonEncCmd_Login val =
502
502
503type Cmd =
503type Cmd =
504 Copy String
504 Copy String
505+ | CreateCipher FullCipher
505 | GeneratePassword PasswordGeneratorConfig
506 | GeneratePassword PasswordGeneratorConfig
506 | Init
507 | Init
507 | Login Cmd_Login
508 | Login Cmd_Login
@@ -517,6 +518,7 @@ jsonDecCmd : Json.Decode.Decoder ( Cmd )
517jsonDecCmd =
518jsonDecCmd =
518 let jsonDecDictCmd = Dict.fromList
519 let jsonDecDictCmd = Dict.fromList
519 [ ("Copy", Json.Decode.lazy (\_ -> Json.Decode.map Copy (Json.Decode.string)))
520 [ ("Copy", Json.Decode.lazy (\_ -> Json.Decode.map Copy (Json.Decode.string)))
521+ , ("CreateCipher", Json.Decode.lazy (\_ -> Json.Decode.map CreateCipher (jsonDecFullCipher)))
520 , ("GeneratePassword", Json.Decode.lazy (\_ -> Json.Decode.map GeneratePassword (jsonDecPasswordGeneratorConfig)))
522 , ("GeneratePassword", Json.Decode.lazy (\_ -> Json.Decode.map GeneratePassword (jsonDecPasswordGeneratorConfig)))
521 , ("Init", Json.Decode.lazy (\_ -> Json.Decode.succeed Init))
523 , ("Init", Json.Decode.lazy (\_ -> Json.Decode.succeed Init))
522 , ("Login", Json.Decode.lazy (\_ -> Json.Decode.map Login (jsonDecCmd_Login)))
524 , ("Login", Json.Decode.lazy (\_ -> Json.Decode.map Login (jsonDecCmd_Login)))
@@ -535,6 +537,7 @@ jsonEncCmd : Cmd -> Value
535jsonEncCmd val =
537jsonEncCmd val =
536 let keyval v = case v of
538 let keyval v = case v of
537 Copy v1 -> ("Copy", encodeValue (Json.Encode.string v1))
539 Copy v1 -> ("Copy", encodeValue (Json.Encode.string v1))
540+ CreateCipher v1 -> ("CreateCipher", encodeValue (jsonEncFullCipher v1))
538 GeneratePassword v1 -> ("GeneratePassword", encodeValue (jsonEncPasswordGeneratorConfig v1))
541 GeneratePassword v1 -> ("GeneratePassword", encodeValue (jsonEncPasswordGeneratorConfig v1))
539 Init -> ("Init", encodeValue (Json.Encode.list identity []))
542 Init -> ("Init", encodeValue (Json.Encode.list identity []))
540 Login v1 -> ("Login", encodeValue (jsonEncCmd_Login v1))
543 Login v1 -> ("Login", encodeValue (jsonEncCmd_Login v1))
frontend/Main.elm+116−8
@@ -16,6 +16,7 @@ import Pages.Loader exposing (loader)
16import Pages.Login as Login
16import Pages.Login as Login
17import Pages.MasterPassword as MasterPassword
17import Pages.MasterPassword as MasterPassword
18import Pages.Navigation as Navigation exposing (TopButton(..))
18import Pages.Navigation as Navigation exposing (TopButton(..))
19+import Pages.SelectCipherType as SelectCipherType
19import Task
20import Task
20import Time
21import Time
21import Types exposing (CipherId)
22import Types exposing (CipherId)
@@ -58,8 +59,12 @@ type Msg
58 | UpdateLastNotificatioTime Time.Posix
59 | UpdateLastNotificatioTime Time.Posix
59 | EditCipher Bridge.FullCipher
60 | EditCipher Bridge.FullCipher
60 | UpdateCipher Bridge.FullCipher
61 | UpdateCipher Bridge.FullCipher
62+ | CreateCipher Bridge.FullCipher
61 | FireGlobalEvent Event
63 | FireGlobalEvent Event
62 | GeneratePassword Bridge.PasswordGeneratorConfig
64 | GeneratePassword Bridge.PasswordGeneratorConfig
65+ | CreateNewCipher
66+ | SelectCipherTypeMsg SelectCipherType.Msg
67+ | OpenNewCipherEditPage Bridge.CipherType
63
68
64
69
65type alias Model =
70type alias Model =
@@ -79,10 +84,11 @@ type PageModel
79 = LoginModel Login.Model
84 = LoginModel Login.Model
80 | LoadingPage
85 | LoadingPage
81 | CiphersModel Ciphers.Model
86 | CiphersModel Ciphers.Model
82− | EditCipherModel EditCipher.Model
87+ | EditCipherModel (EditCipher.Model Msg)
83 | MasterPasswordModel MasterPassword.Model
88 | MasterPasswordModel MasterPassword.Model
84 | CipherModel Cipher.Model
89 | CipherModel Cipher.Model
85 | CaptchaModel Captcha.Model
90 | CaptchaModel Captcha.Model
91+ | SelectCipherTypeModel SelectCipherType.Model
86
92
87
93
88showPage :
94showPage :
@@ -162,13 +168,23 @@ showPage email page =
162 EditCipherModel model ->
168 EditCipherModel model ->
163 let
169 let
164 p =
170 p =
165− EditCipher.page editCipherCallbacks EditCipherMsg
171+ EditCipher.page EditCipherMsg
166 in
172 in
167 { title = p.title model
173 { title = p.title model
168 , body = p.view model
174 , body = p.view model
169 , topButton = Just (BackButton { action = PopView, icon = Just "close" })
175 , topButton = Just (BackButton { action = PopView, icon = Just "close" })
170 }
176 }
171
177
178+ SelectCipherTypeModel model ->
179+ let
180+ p =
181+ SelectCipherType.page selectCipherTypeCallbacks SelectCipherTypeMsg
182+ in
183+ { title = p.title model
184+ , body = p.view model
185+ , topButton = Just simpleBackButton
186+ }
187+
172
188
173main : Program () Model Msg
189main : Program () Model Msg
174main =
190main =
@@ -263,6 +279,9 @@ doNotStoreInHistory page =
263 LoadingPage ->
279 LoadingPage ->
264 True
280 True
265
281
282+ SelectCipherTypeModel _ ->
283+ True
284+
266 _ ->
285 _ ->
267 False
286 False
268
287
@@ -388,8 +407,6 @@ update msg model =
388 , cmd
407 , cmd
389 )
408 )
390
409
391− -- (Ciphers.page ciphersCallbacks CiphersMsg).init ciphers
392− -- |> Tuple.mapFirst (\pageModel -> appendPageStack <| CiphersModel pageModel)
393 OpenCiphersScreen ->
410 OpenCiphersScreen ->
394 ( appendPageStack <| LoadingPage, Cmd.batch [ sendBridge Bridge.NeedCiphersList, sendBridge Bridge.NeedEmail ] )
411 ( appendPageStack <| LoadingPage, Cmd.batch [ sendBridge Bridge.NeedCiphersList, sendBridge Bridge.NeedEmail ] )
395
412
@@ -425,7 +442,7 @@ update msg model =
425 EditCipherMsg imsg ->
442 EditCipherMsg imsg ->
426 case currentPage of
443 case currentPage of
427 EditCipherModel page ->
444 EditCipherModel page ->
428− (EditCipher.page editCipherCallbacks EditCipherMsg).update imsg page |> processPage EditCipherModel
445+ (EditCipher.page EditCipherMsg).update imsg page |> processPage EditCipherModel
429
446
430 _ ->
447 _ ->
431 ( model, Cmd.none )
448 ( model, Cmd.none )
@@ -479,7 +496,7 @@ update msg model =
479 ( model, Cmd.none )
496 ( model, Cmd.none )
480
497
481 EditCipher cipher ->
498 EditCipher cipher ->
482− (EditCipher.page editCipherCallbacks EditCipherMsg).init cipher
499+ (EditCipher.page EditCipherMsg).init { fullCipher = cipher, callbacks = editCipherCallbacks }
483 |> Tuple.mapFirst (\pageModel -> keepStackWith <| EditCipherModel pageModel)
500 |> Tuple.mapFirst (\pageModel -> keepStackWith <| EditCipherModel pageModel)
484
501
485 UpdateCipher cipher ->
502 UpdateCipher cipher ->
@@ -491,6 +508,14 @@ update msg model =
491 ]
508 ]
492 )
509 )
493
510
511+ CreateCipher cipher ->
512+ ( model
513+ , Cmd.batch
514+ [ Bridge.CreateCipher cipher |> sendBridge
515+ , PopView |> pureCmd
516+ ]
517+ )
518+
494 FireGlobalEvent ev ->
519 FireGlobalEvent ev ->
495 ( { model
520 ( { model
496 | pageStack =
521 | pageStack =
@@ -514,10 +539,13 @@ update msg model =
514 (Cipher.page cipherCallbacks CipherMsg).event m ev |> CipherModel
539 (Cipher.page cipherCallbacks CipherMsg).event m ev |> CipherModel
515
540
516 EditCipherModel m ->
541 EditCipherModel m ->
517− (EditCipher.page editCipherCallbacks EditCipherMsg).event m ev |> EditCipherModel
542+ (EditCipher.page EditCipherMsg).event m ev |> EditCipherModel
518
543
519 CaptchaModel m ->
544 CaptchaModel m ->
520 (Captcha.page captchaCallbacks CaptchaMsg).event m ev |> CaptchaModel
545 (Captcha.page captchaCallbacks CaptchaMsg).event m ev |> CaptchaModel
546+
547+ SelectCipherTypeModel m ->
548+ (SelectCipherType.page selectCipherTypeCallbacks SelectCipherTypeMsg).event m ev |> SelectCipherTypeModel
521 )
549 )
522 }
550 }
523 , Cmd.none
551 , Cmd.none
@@ -526,6 +554,73 @@ update msg model =
526 GeneratePassword cfg ->
554 GeneratePassword cfg ->
527 ( model, FFI.sendBridge (Bridge.GeneratePassword cfg) )
555 ( model, FFI.sendBridge (Bridge.GeneratePassword cfg) )
528
556
557+ SelectCipherTypeMsg imsg ->
558+ case currentPage of
559+ SelectCipherTypeModel page ->
560+ (SelectCipherType.page selectCipherTypeCallbacks SelectCipherTypeMsg).update imsg page |> processPage SelectCipherTypeModel
561+
562+ _ ->
563+ ( model, Cmd.none )
564+
565+ CreateNewCipher ->
566+ (SelectCipherType.page selectCipherTypeCallbacks SelectCipherTypeMsg).init ()
567+ |> Tuple.mapFirst (\pageModel -> appendPageStack <| SelectCipherTypeModel pageModel)
568+
569+ OpenNewCipherEditPage t ->
570+ (EditCipher.page EditCipherMsg).init
571+ { callbacks = createCipherCallbacks
572+ , fullCipher =
573+ { reprompt = 0
574+ , favorite = False
575+ , id = ""
576+ , name = ""
577+ , cipher =
578+ case t of
579+ Bridge.LoginType ->
580+ Bridge.LoginCipher
581+ { uris = []
582+ , username = Nothing
583+ , password = Nothing
584+ }
585+
586+ Bridge.NoteType ->
587+ Bridge.NoteCipher ""
588+
589+ Bridge.CardType ->
590+ Bridge.CardCipher
591+ { cardholderName = Nothing
592+ , brand = Nothing
593+ , number = Nothing
594+ , expMonth = Nothing
595+ , expYear = Nothing
596+ , code = Nothing
597+ }
598+
599+ Bridge.IdentityType ->
600+ Bridge.IdentityCipher
601+ { title = Nothing
602+ , firstName = Nothing
603+ , middleName = Nothing
604+ , lastName = Nothing
605+ , address1 = Nothing
606+ , address2 = Nothing
607+ , address3 = Nothing
608+ , city = Nothing
609+ , state = Nothing
610+ , postalCode = Nothing
611+ , country = Nothing
612+ , company = Nothing
613+ , email = Nothing
614+ , phone = Nothing
615+ , ssn = Nothing
616+ , username = Nothing
617+ , passportNumber = Nothing
618+ , licenseNumber = Nothing
619+ }
620+ }
621+ }
622+ |> Tuple.mapFirst (\pageModel -> keepStackWith <| EditCipherModel pageModel)
623+
529
624
530loginCallbacks : Login.Callbacks Msg
625loginCallbacks : Login.Callbacks Msg
531loginCallbacks =
626loginCallbacks =
@@ -534,7 +629,10 @@ loginCallbacks =
534
629
535ciphersCallbacks : Ciphers.Callbacks Msg
630ciphersCallbacks : Ciphers.Callbacks Msg
536ciphersCallbacks =
631ciphersCallbacks =
537− { selected = RequestCipher, logOut = NeedsReset }
632+ { selected = RequestCipher
633+ , logOut = NeedsReset
634+ , createNewCipher = CreateNewCipher
635+ }
538
636
539
637
540cipherCallbacks : Cipher.Callbacks Msg
638cipherCallbacks : Cipher.Callbacks Msg
@@ -547,6 +645,11 @@ editCipherCallbacks =
547 { save = UpdateCipher, generatePassword = GeneratePassword }
645 { save = UpdateCipher, generatePassword = GeneratePassword }
548
646
549
647
648+createCipherCallbacks : EditCipher.Callbacks Msg
649+createCipherCallbacks =
650+ { save = CreateCipher, generatePassword = GeneratePassword }
651+
652+
550captchaCallbacks : Captcha.Callbacks
653captchaCallbacks : Captcha.Callbacks
551captchaCallbacks =
654captchaCallbacks =
552 {}
655 {}
@@ -557,3 +660,8 @@ masterPasswordCallbacks =
557 { submit = SendMasterPassword
660 { submit = SendMasterPassword
558 , reset = NeedsReset
661 , reset = NeedsReset
559 }
662 }
663+
664+
665+selectCipherTypeCallbacks : SelectCipherType.Callbacks Msg
666+selectCipherTypeCallbacks =
667+ { choose = OpenNewCipherEditPage }
frontend/Pages/Ciphers.elm+8−2
@@ -64,7 +64,7 @@ menuConfig email { ciphersListFilter, menuVisible } =
64 , current = ciphersListFilter == SpecificCiphers Bridge.CardType
64 , current = ciphersListFilter == SpecificCiphers Bridge.CardType
65 }
65 }
66 , { icon = "user"
66 , { icon = "user"
67− , name = "Identities"
67+ , name = "Contacts"
68 , trigger = UpdateFilter (SpecificCiphers Bridge.IdentityType)
68 , trigger = UpdateFilter (SpecificCiphers Bridge.IdentityType)
69 , current = ciphersListFilter == SpecificCiphers Bridge.IdentityType
69 , current = ciphersListFilter == SpecificCiphers Bridge.IdentityType
70 }
70 }
@@ -83,11 +83,13 @@ type Msg
83 | LogOut
83 | LogOut
84 | LoadMore InfiniteScroll.Direction
84 | LoadMore InfiniteScroll.Direction
85 | InfiniteScrollMsg InfiniteScroll.Msg
85 | InfiniteScrollMsg InfiniteScroll.Msg
86+ | CreateNewCipher
86
87
87
88
88type alias Callbacks msg =
89type alias Callbacks msg =
89 { selected : String -> msg
90 { selected : String -> msg
90 , logOut : msg
91 , logOut : msg
92+ , createNewCipher : msg
91 }
93 }
92
94
93
95
@@ -118,6 +120,7 @@ page callbacks liftMsg =
118 Bridge.NoteType ->
120 Bridge.NoteType ->
119 "Notes"
121 "Notes"
120 )
122 )
123+ , span [ Attr.class "u-float-right" ] [ iconButton "plus" (liftMsg CreateNewCipher) ]
121 ]
124 ]
122 , event =
125 , event =
123 \model ev ->
126 \model ev ->
@@ -155,7 +158,7 @@ init ciphers =
155
158
156
159
157update : Callbacks emsg -> (Msg -> emsg) -> Msg -> Model -> ( Result String Model, Cmd emsg )
160update : Callbacks emsg -> (Msg -> emsg) -> Msg -> Model -> ( Result String Model, Cmd emsg )
158−update { logOut } liftMsg msg model =
161+update { logOut, createNewCipher } liftMsg msg model =
159 case msg of
162 case msg of
160 Noop ->
163 Noop ->
161 ( Ok model, Cmd.none )
164 ( Ok model, Cmd.none )
@@ -191,6 +194,9 @@ update { logOut } liftMsg msg model =
191 in
194 in
192 ( Ok { model | scroll = scroll }, Cmd.map liftMsg cmd )
195 ( Ok { model | scroll = scroll }, Cmd.map liftMsg cmd )
193
196
197+ CreateNewCipher ->
198+ ( Ok model, pureCmd createNewCipher )
199+
194
200
195subscriptions : Model -> Sub Msg
201subscriptions : Model -> Sub Msg
196subscriptions _ =
202subscriptions _ =
frontend/Pages/EditCipher.elm+16−14
@@ -11,9 +11,10 @@ import Pages.PasswordGenerator as PasswordGenerator
11import Utils exposing (..)
11import Utils exposing (..)
12
12
13
13
14−type alias Model =
14+type alias Model msg =
15 { fullCipher : Bridge.FullCipher
15 { fullCipher : Bridge.FullCipher
16 , passwordGenerator : Maybe PasswordGenerator.Model
16 , passwordGenerator : Maybe PasswordGenerator.Model
17+ , callbacks : Callbacks msg
17 }
18 }
18
19
19
20
@@ -31,14 +32,14 @@ type alias Callbacks msg =
31 }
32 }
32
33
33
34
34−page : Callbacks emsg -> Page Bridge.FullCipher Model Msg emsg
35+page : Page { fullCipher : Bridge.FullCipher, callbacks : Callbacks emsg } (Model emsg) Msg emsg
35−page callbacks liftMsg =
36+page liftMsg =
36− { init = \data -> Tuple.mapSecond (Cmd.map liftMsg) (init data)
37+ { init = init
37 , view = \model -> view model |> List.map (Html.map liftMsg)
38 , view = \model -> view model |> List.map (Html.map liftMsg)
38− , update = \msg model -> update callbacks liftMsg msg model
39+ , update = \msg model -> update liftMsg msg model
39 , subscriptions = \model -> subscriptions model |> Sub.map liftMsg
40 , subscriptions = \model -> subscriptions model |> Sub.map liftMsg
40 , title =
41 , title =
41− \{ fullCipher } ->
42+ \{ fullCipher, callbacks } ->
42 [ text fullCipher.name
43 [ text fullCipher.name
43 , span [ Attr.class "u-float-right" ] [ iconButton "task-outstanding" (callbacks.save fullCipher) ]
44 , span [ Attr.class "u-float-right" ] [ iconButton "task-outstanding" (callbacks.save fullCipher) ]
44 ]
45 ]
@@ -77,17 +78,18 @@ page callbacks liftMsg =
77 }
78 }
78
79
79
80
80−init : Bridge.FullCipher -> ( Model, Cmd Msg )
81+init : { fullCipher : Bridge.FullCipher, callbacks : Callbacks emsg } -> ( Model emsg, Cmd emsg )
81−init cipher =
82+init { fullCipher, callbacks } =
82− ( { fullCipher = cipher
83+ ( { fullCipher = fullCipher
83 , passwordGenerator = Nothing
84 , passwordGenerator = Nothing
85+ , callbacks = callbacks
84 }
86 }
85 , Cmd.none
87 , Cmd.none
86 )
88 )
87
89
88
90
89−update : Callbacks emsg -> (Msg -> emsg) -> Msg -> Model -> ( Result String Model, Cmd emsg )
91+update : (Msg -> emsg) -> Msg -> Model emsg -> ( Result String (Model emsg), Cmd emsg )
90−update { generatePassword } _ msg model =
92+update _ msg model =
91 case msg of
93 case msg of
92 EditCipher fullCipher ->
94 EditCipher fullCipher ->
93 ( Ok { model | fullCipher = fullCipher }, Cmd.none )
95 ( Ok { model | fullCipher = fullCipher }, Cmd.none )
@@ -106,10 +108,10 @@ update { generatePassword } _ msg model =
106 ( Ok { model | passwordGenerator = Nothing }, Cmd.none )
108 ( Ok { model | passwordGenerator = Nothing }, Cmd.none )
107
109
108 GeneratePassword cfg ->
110 GeneratePassword cfg ->
109− ( Ok model, pureCmd (generatePassword cfg) )
111+ ( Ok model, pureCmd (model.callbacks.generatePassword cfg) )
110
112
111
113
112−subscriptions : Model -> Sub Msg
114+subscriptions : Model emsg -> Sub Msg
113subscriptions _ =
115subscriptions _ =
114 Sub.none
116 Sub.none
115
117
@@ -128,7 +130,7 @@ row { name, nameIcon, attrs } =
128 ]
130 ]
129
131
130
132
131−view : Model -> List (Html Msg)
133+view : Model emsg -> List (Html Msg)
132view { fullCipher, passwordGenerator } =
134view { fullCipher, passwordGenerator } =
133 maybeList passwordGenerator
135 maybeList passwordGenerator
134 (\x ->
136 (\x ->
frontend/Pages/SelectCipherType.elmnew file+76
@@ -0,0 +1,76 @@
1+module Pages.SelectCipherType exposing (..)
2+
3+import Bridge
4+import Html exposing (..)
5+import Html.Attributes as Attr
6+import Html.Events as Ev
7+import Page exposing (..)
8+import Utils exposing (..)
9+
10+
11+type alias Model =
12+ {}
13+
14+
15+type Msg
16+ = Choose Bridge.CipherType
17+
18+
19+type alias Callbacks msg =
20+ { choose : Bridge.CipherType -> msg
21+ }
22+
23+
24+page : Callbacks emsg -> Page () Model Msg emsg
25+page callbacks liftMsg =
26+ { init = \() -> Tuple.mapSecond (Cmd.map liftMsg) init
27+ , view = \model -> view model |> List.map (Html.map liftMsg)
28+ , update = \msg model -> update callbacks liftMsg msg model
29+ , subscriptions = \model -> subscriptions model |> Sub.map liftMsg
30+ , title = always [ text "Select entry type" ]
31+ , event = \model _ -> model
32+ }
33+
34+
35+init : ( Model, Cmd Msg )
36+init =
37+ ( {}, Cmd.none )
38+
39+
40+update : Callbacks emsg -> (Msg -> emsg) -> Msg -> Model -> ( Result String Model, Cmd emsg )
41+update { choose } _ msg model =
42+ case msg of
43+ Choose t ->
44+ ( Ok model, pureCmd (choose t) )
45+
46+
47+subscriptions : Model -> Sub Msg
48+subscriptions model =
49+ Sub.none
50+
51+
52+view : Model -> List (Html Msg)
53+view {} =
54+ [ div [ Attr.class "select-cipher-type-container" ]
55+ [ button
56+ [ Attr.class "p-button"
57+ , Ev.onClick (Choose Bridge.LoginType)
58+ ]
59+ [ text "Login" ]
60+ , button
61+ [ Attr.class "p-button"
62+ , Ev.onClick (Choose Bridge.CardType)
63+ ]
64+ [ text "Card" ]
65+ , button
66+ [ Attr.class "p-button"
67+ , Ev.onClick (Choose Bridge.NoteType)
68+ ]
69+ [ text "Note" ]
70+ , button
71+ [ Attr.class "p-button"
72+ , Ev.onClick (Choose Bridge.IdentityType)
73+ ]
74+ [ text "Contact" ]
75+ ]
76+ ]
frontend/Utils.elm+7
@@ -2,6 +2,7 @@ module Utils exposing (..)
2
2
3import Html exposing (..)
3import Html exposing (..)
4import Html.Attributes as Attr
4import Html.Attributes as Attr
5+import Html.Events as Ev
5import Task
6import Task
6
7
7
8
@@ -144,3 +145,9 @@ spanList f aa =
144
145
145 else
146 else
146 ( [], aa )
147 ( [], aa )
148+
149+
150+iconButton : String -> msg -> Html msg
151+iconButton name msg =
152+ button [ Attr.class "p-button is-inline is-dense has-icon", Ev.onClick msg ]
153+ [ i [ Attr.class ("p-icon--" ++ name) ] [] ]
style.css+12
@@ -111,3 +111,15 @@ textarea {
111.p-side-navigation__drawer {
111.p-side-navigation__drawer {
112 max-width: initial;
112 max-width: initial;
113}
113}
114+
115+.select-cipher-type-container {
116+ display: flex;
117+ flex-direction: column;
118+ align-items: center;
119+ justify-content: center;
120+}
121+
122+.select-cipher-type-container > * {
123+ margin: 0px;
124+ margin-bottom: 1.5rem;
125+}