From 76f8b85eb9f796d6df861a04f702ef5f48630795 Mon Sep 17 00:00:00 2001 From: Joris Date: Tue, 29 Mar 2016 23:46:47 +0200 Subject: Move logged data to LoggedIn component --- src/client/elm/LoggedData.elm | 40 +++++++ src/client/elm/LoggedIn/Action.elm | 9 ++ src/client/elm/LoggedIn/Home/Account/Action.elm | 3 - src/client/elm/LoggedIn/Home/Account/Model.elm | 20 ++-- src/client/elm/LoggedIn/Home/Account/Update.elm | 50 ++------ src/client/elm/LoggedIn/Home/Account/View.elm | 75 ++++++------ src/client/elm/LoggedIn/Home/Action.elm | 13 +-- src/client/elm/LoggedIn/Home/AddPayment/Action.elm | 3 + src/client/elm/LoggedIn/Home/AddPayment/Update.elm | 3 + src/client/elm/LoggedIn/Home/AddPayment/View.elm | 47 ++++---- src/client/elm/LoggedIn/Home/Model.elm | 18 +-- src/client/elm/LoggedIn/Home/Model/Payer.elm | 5 +- src/client/elm/LoggedIn/Home/Monthly/Action.elm | 10 -- src/client/elm/LoggedIn/Home/Monthly/Model.elm | 17 --- src/client/elm/LoggedIn/Home/Monthly/Update.elm | 21 ---- src/client/elm/LoggedIn/Home/Monthly/View.elm | 91 --------------- src/client/elm/LoggedIn/Home/Update.elm | 129 ++++----------------- src/client/elm/LoggedIn/Home/View.elm | 26 ++--- src/client/elm/LoggedIn/Home/View/Monthly.elm | 90 ++++++++++++++ src/client/elm/LoggedIn/Home/View/Paging.elm | 23 ++-- src/client/elm/LoggedIn/Home/View/Price.elm | 9 +- src/client/elm/LoggedIn/Home/View/Table.elm | 46 ++++---- src/client/elm/LoggedIn/Model.elm | 17 ++- src/client/elm/LoggedIn/Update.elm | 107 +++++++++++++++-- src/client/elm/LoggedIn/View.elm | 15 +-- src/client/elm/Mailbox.elm | 17 +++ src/client/elm/Main.elm | 3 +- src/client/elm/Model.elm | 4 +- src/client/elm/Route.elm | 7 +- src/client/elm/Server.elm | 5 +- src/client/elm/Update.elm | 2 +- src/client/elm/Utils/Tuple.elm | 14 +++ src/client/elm/View.elm | 9 +- src/client/elm/View/Header.elm | 9 +- src/server/Design/Header.hs | 13 +-- 35 files changed, 494 insertions(+), 476 deletions(-) create mode 100644 src/client/elm/LoggedData.elm delete mode 100644 src/client/elm/LoggedIn/Home/Monthly/Action.elm delete mode 100644 src/client/elm/LoggedIn/Home/Monthly/Model.elm delete mode 100644 src/client/elm/LoggedIn/Home/Monthly/Update.elm delete mode 100644 src/client/elm/LoggedIn/Home/Monthly/View.elm create mode 100644 src/client/elm/LoggedIn/Home/View/Monthly.elm create mode 100644 src/client/elm/Mailbox.elm create mode 100644 src/client/elm/Utils/Tuple.elm (limited to 'src') diff --git a/src/client/elm/LoggedData.elm b/src/client/elm/LoggedData.elm new file mode 100644 index 0000000..02e7908 --- /dev/null +++ b/src/client/elm/LoggedData.elm @@ -0,0 +1,40 @@ +module LoggedData + ( LoggedData + , build + ) where + +import Time exposing (Time) + +import Action exposing (Action) + +import Model exposing (Model) +import Model.Translations exposing (..) +import Model.Conf exposing (..) +import Model.Payment exposing (Payments) +import Model.User exposing (Users, UserId) +import Model.Income exposing (Incomes) + +import LoggedIn.Model as LoggedInModel + +type alias LoggedData = + { currentTime : Time + , translations : Translations + , conf : Conf + , users : Users + , me : UserId + , payments : Payments + , monthlyPayments : Payments + , incomes : Incomes + } + +build : Model -> LoggedInModel.Model -> LoggedData +build model loggedIn = + { currentTime = model.currentTime + , translations = model.translations + , conf = model.conf + , users = loggedIn.users + , me = loggedIn.me + , payments = loggedIn.payments + , monthlyPayments = loggedIn.monthlyPayments + , incomes = loggedIn.incomes + } diff --git a/src/client/elm/LoggedIn/Action.elm b/src/client/elm/LoggedIn/Action.elm index 4f9bcc1..ae72dea 100644 --- a/src/client/elm/LoggedIn/Action.elm +++ b/src/client/elm/LoggedIn/Action.elm @@ -2,8 +2,17 @@ module LoggedIn.Action ( Action(..) ) where +import Model.Payment exposing (Payment, PaymentId, PaymentFrequency) +import Model.Income exposing (IncomeId) + import LoggedIn.Home.Action as HomeAction type Action = NoOp | HomeAction HomeAction.Action + | AddPayment String String PaymentFrequency + | ValidateAddPayment PaymentId String Int PaymentFrequency + | DeletePayment Payment PaymentFrequency + | ValidateDeletePayment Payment PaymentFrequency + | UpdateIncome Int + | ValidateUpdateIncome IncomeId Int diff --git a/src/client/elm/LoggedIn/Home/Account/Action.elm b/src/client/elm/LoggedIn/Home/Account/Action.elm index 61dae42..4ce3b20 100644 --- a/src/client/elm/LoggedIn/Home/Account/Action.elm +++ b/src/client/elm/LoggedIn/Home/Account/Action.elm @@ -5,7 +5,6 @@ module LoggedIn.Home.Account.Action import Time exposing (Time) import Model.User exposing (UserId) -import Model.Income exposing (IncomeId) type Action = NoOp @@ -13,5 +12,3 @@ type Action = | ToggleIncomeEdition | UpdateIncomeEdition String | UpdateEditionError String - | UpdateIncome Time Int - | ValidateUpdateIncome IncomeId Time Int diff --git a/src/client/elm/LoggedIn/Home/Account/Model.elm b/src/client/elm/LoggedIn/Home/Account/Model.elm index d8bf748..d04f865 100644 --- a/src/client/elm/LoggedIn/Home/Account/Model.elm +++ b/src/client/elm/LoggedIn/Home/Account/Model.elm @@ -18,24 +18,20 @@ import Model.Income exposing (..) import Model.User exposing (UserId) type alias Model = - { me : UserId - , incomes : Incomes - , visibleDetail : Bool + { visibleDetail : Bool , incomeEdition : Maybe IncomeEdition } -init : UserId -> Incomes -> Model -init me incomes = - { me = me - , incomes = incomes - , visibleDetail = False +init : Model +init = + { visibleDetail = False , incomeEdition = Nothing } -getCurrentIncome : Model -> Maybe Int -getCurrentIncome account = - account.incomes - |> Dict.filter (\_ income -> income.userId == account.me) +getCurrentIncome : Incomes -> UserId -> Model -> Maybe Int +getCurrentIncome incomes me account = + incomes + |> Dict.filter (\_ income -> income.userId == me) |> Dict.values |> List.sortBy .creation |> List.reverse diff --git a/src/client/elm/LoggedIn/Home/Account/Update.elm b/src/client/elm/LoggedIn/Home/Account/Update.elm index 8d002a3..59f1402 100644 --- a/src/client/elm/LoggedIn/Home/Account/Update.elm +++ b/src/client/elm/LoggedIn/Home/Account/Update.elm @@ -3,20 +3,18 @@ module LoggedIn.Home.Account.Update ) where import Maybe -import Dict -import Task import Effects exposing (Effects) -import Server +import LoggedData exposing (LoggedData) import LoggedIn.Home.Account.Action as AccountAction import LoggedIn.Home.Account.Model as AccountModel import Utils.Maybe exposing (isJust) -update : AccountAction.Action -> AccountModel.Model -> (AccountModel.Model, Effects AccountAction.Action) -update action account = +update : LoggedData -> AccountAction.Action -> AccountModel.Model -> (AccountModel.Model, Effects AccountAction.Action) +update loggedData action account = case action of AccountAction.NoOp -> @@ -31,45 +29,21 @@ update action account = ( { account | incomeEdition = if isJust account.incomeEdition then Nothing - else Just (AccountModel.initIncomeEdition (Maybe.withDefault 0 (AccountModel.getCurrentIncome account))) + else Just (AccountModel.initIncomeEdition (Maybe.withDefault 0 (AccountModel.getCurrentIncome loggedData.incomes loggedData.me account))) } , Effects.none ) AccountAction.UpdateIncomeEdition income -> - case account.incomeEdition of - Just incomeEdition -> - ( { account | incomeEdition = Just { incomeEdition | income = income } } - , Effects.none - ) - Nothing -> - ( account - , Effects.none - ) - - AccountAction.UpdateEditionError error -> - case account.incomeEdition of - Just incomeEdition -> - ( { account | incomeEdition = Just { incomeEdition | error = Just error } } - , Effects.none - ) - Nothing -> - ( account - , Effects.none - ) - - AccountAction.UpdateIncome currentTime amount -> - ( account - , Server.setIncome currentTime amount - |> Task.map (\incomeId -> (AccountAction.ValidateUpdateIncome incomeId currentTime amount)) - |> flip Task.onError (always <| Task.succeed AccountAction.NoOp) - |> Effects.task + ( case account.incomeEdition of + Nothing -> account + Just incomeEdition -> { account | incomeEdition = Just { incomeEdition | income = income } } + , Effects.none ) - AccountAction.ValidateUpdateIncome incomeId currentTime amount -> - ( { account - | incomes = Dict.insert incomeId { userId = account.me, creation = currentTime, amount = amount } account.incomes - , incomeEdition = Nothing - } + AccountAction.UpdateEditionError error -> + ( case account.incomeEdition of + Nothing -> account + Just incomeEdition -> { account | incomeEdition = Just { incomeEdition | error = Just error } } , Effects.none ) diff --git a/src/client/elm/LoggedIn/Home/Account/View.elm b/src/client/elm/LoggedIn/Home/Account/View.elm index 252f8cf..a7d3e0c 100644 --- a/src/client/elm/LoggedIn/Home/Account/View.elm +++ b/src/client/elm/LoggedIn/Home/Account/View.elm @@ -3,13 +3,15 @@ module LoggedIn.Home.Account.View ) where import List -import Signal exposing (Address) +import Signal import Html exposing (..) import Html as H exposing (..) import Html.Attributes exposing (..) import Html.Events exposing (..) +import LoggedData exposing (LoggedData) + import LoggedIn.Action as LoggedInAction import LoggedIn.Home.Action as HomeAction @@ -24,14 +26,15 @@ import LoggedIn.Home.Account.Model as AccountModel import Model exposing (Model) import Model.User exposing (getUserName) import Model.Translations exposing (getParamMessage, getMessage) -import Action exposing (..) +import Action +import Mailbox import View.Events exposing (onSubmitPrevDefault) import Utils.Either exposing (toMaybeError) -view : Address Action -> Model -> HomeModel.Model -> Html -view address model homeModel = +view : LoggedData -> HomeModel.Model -> Html +view loggedData homeModel = let account = homeModel.account in div [ classList @@ -39,76 +42,76 @@ view address model homeModel = , ("detail", account.visibleDetail) ] ] - [ exceedingPayers address model homeModel + [ exceedingPayers loggedData homeModel , if account.visibleDetail - then income address model account + then income loggedData account else text "" ] -exceedingPayers : Address Action -> Model -> HomeModel.Model -> Html -exceedingPayers address model homeModel = +exceedingPayers : LoggedData -> HomeModel.Model -> Html +exceedingPayers loggedData homeModel = button [ class "header" - , onClick address (UpdateLoggedIn << LoggedInAction.HomeAction << HomeAction.UpdateAccount <| AccountAction.ToggleDetail) + , onClick Mailbox.address (Action.UpdateLoggedIn << LoggedInAction.HomeAction << HomeAction.UpdateAccount <| AccountAction.ToggleDetail) ] - ( (List.map (exceedingPayer model homeModel) (getOrderedExceedingPayers model.currentTime homeModel.users homeModel.account.incomes homeModel.payments)) + ( (List.map (exceedingPayer loggedData homeModel) (getOrderedExceedingPayers loggedData.currentTime loggedData.users loggedData.incomes loggedData.payments)) ++ [ expand ExpandDown homeModel.account.visibleDetail ] ) -exceedingPayer : Model -> HomeModel.Model -> ExceedingPayer -> Html -exceedingPayer model homeModel payer = +exceedingPayer : LoggedData -> HomeModel.Model -> ExceedingPayer -> Html +exceedingPayer loggedData homeModel payer = div [ class "exceedingPayer" ] [ span [ class "userName" ] [ payer.userId - |> getUserName homeModel.users + |> getUserName loggedData.users |> Maybe.withDefault "−" |> text ] , span [ class "amount" ] - [ text ("+ " ++ (price model payer.amount)) ] + [ text ("+ " ++ (price loggedData.conf payer.amount)) ] ] -income : Address Action -> Model -> AccountModel.Model -> Html -income address model account = +income : LoggedData -> AccountModel.Model -> Html +income loggedData account = case account.incomeEdition of Nothing -> - incomeRead address model account + incomeRead loggedData account Just edition -> - incomeEdition address model account edition + incomeEdition loggedData account edition -incomeRead : Address Action -> Model -> AccountModel.Model -> Html -incomeRead address model account = +incomeRead : LoggedData -> AccountModel.Model -> Html +incomeRead loggedData account = div [ class "income" ] - [ ( case AccountModel.getCurrentIncome account of + [ ( case AccountModel.getCurrentIncome loggedData.incomes loggedData.me account of Nothing -> - text (getMessage "NoIncome" model.translations) + text (getMessage "NoIncome" loggedData.translations) Just income -> - text (getParamMessage [price model income] "Income" model.translations) + text (getParamMessage [price loggedData.conf income] "Income" loggedData.translations) ) - , toggleIncomeEdition address "editIncomeEdition" (getMessage "Edit" model.translations) + , toggleIncomeEdition loggedData "editIncomeEdition" (getMessage "Edit" loggedData.translations) ] -incomeEdition : Address Action -> Model -> AccountModel.Model -> AccountModel.IncomeEdition -> Html -incomeEdition address model account edition = +incomeEdition : LoggedData -> AccountModel.Model -> AccountModel.IncomeEdition -> Html +incomeEdition loggedData account edition = H.form - [ case AccountModel.validateIncome edition.income model.translations of + [ case AccountModel.validateIncome edition.income loggedData.translations of Ok validatedAmount -> - onSubmitPrevDefault address (UpdateLoggedIn << LoggedInAction.HomeAction << HomeAction.UpdateAccount <| AccountAction.UpdateIncome model.currentTime validatedAmount) + onSubmitPrevDefault Mailbox.address (Action.UpdateLoggedIn <| LoggedInAction.UpdateIncome validatedAmount) Err error -> - onSubmitPrevDefault address (UpdateLoggedIn << LoggedInAction.HomeAction << HomeAction.UpdateAccount << AccountAction.UpdateEditionError <| error) + onSubmitPrevDefault Mailbox.address (Action.UpdateLoggedIn << LoggedInAction.HomeAction << HomeAction.UpdateAccount << AccountAction.UpdateEditionError <| error) , class "income" ] [ label [ for "incomeInput" ] - [ text (getMessage "NewIncome" model.translations) ] + [ text (getMessage "NewIncome" loggedData.translations) ] , input [ id "incomeInput" , value edition.income - , on "input" targetValue (Signal.message address << UpdateLoggedIn << LoggedInAction.HomeAction << HomeAction.UpdateAccount << AccountAction.UpdateIncomeEdition) + , on "input" targetValue (Signal.message Mailbox.address << Action.UpdateLoggedIn << LoggedInAction.HomeAction << HomeAction.UpdateAccount << AccountAction.UpdateIncomeEdition) , maxlength 10 ] [] @@ -116,18 +119,18 @@ incomeEdition address model account edition = [ type' "submit" , class "validateIncomeEdition" ] - [ text (getMessage "Validate" model.translations) ] - , toggleIncomeEdition address "undoIncomeEdition" (getMessage "Undo" model.translations) + [ text (getMessage "Validate" loggedData.translations) ] + , toggleIncomeEdition loggedData "undoIncomeEdition" (getMessage "Undo" loggedData.translations) , case edition.error of Just error -> div [ class "error" ] [ text error ] Nothing -> text "" ] -toggleIncomeEdition : Address Action -> String -> String -> Html -toggleIncomeEdition address className name = +toggleIncomeEdition : LoggedData -> String -> String -> Html +toggleIncomeEdition loggedData className name = button [ type' "button" , class className - , onClick address (UpdateLoggedIn << LoggedInAction.HomeAction << HomeAction.UpdateAccount <| AccountAction.ToggleIncomeEdition) + , onClick Mailbox.address (Action.UpdateLoggedIn << LoggedInAction.HomeAction << HomeAction.UpdateAccount <| AccountAction.ToggleIncomeEdition) ] [ text name ] diff --git a/src/client/elm/LoggedIn/Home/Action.elm b/src/client/elm/LoggedIn/Home/Action.elm index d6d82d0..7db705d 100644 --- a/src/client/elm/LoggedIn/Home/Action.elm +++ b/src/client/elm/LoggedIn/Home/Action.elm @@ -2,21 +2,16 @@ module LoggedIn.Home.Action ( Action(..) ) where -import Model.Payment exposing (Payments, Payment, PaymentId, PaymentFrequency) +import Model.Payment exposing (PaymentId) import LoggedIn.Home.Account.Action as AccountAction import LoggedIn.Home.AddPayment.Action as AddPaymentAction -import LoggedIn.Home.Monthly.Action as MonthlyAction type Action = NoOp | UpdateAdd AddPaymentAction.Action - | UpdatePayments Payments - | AddPayment String String PaymentFrequency - | ValidateAddPayment PaymentId String Int PaymentFrequency - | DeletePayment Payment PaymentFrequency - | ValidateDeletePayment Payment PaymentFrequency + | UpdateAccount AccountAction.Action | ToggleEdit PaymentId | UpdatePage Int - | UpdateMonthly MonthlyAction.Action - | UpdateAccount AccountAction.Action + | ShowMonthlyDetail + | ToggleMonthlyDetail diff --git a/src/client/elm/LoggedIn/Home/AddPayment/Action.elm b/src/client/elm/LoggedIn/Home/AddPayment/Action.elm index 095863f..81c32e2 100644 --- a/src/client/elm/LoggedIn/Home/AddPayment/Action.elm +++ b/src/client/elm/LoggedIn/Home/AddPayment/Action.elm @@ -2,8 +2,11 @@ module LoggedIn.Home.AddPayment.Action ( Action(..) ) where +import Model.Payment exposing (PaymentFrequency) + type Action = NoOp + | Init PaymentFrequency | UpdateName String | UpdateCost String | AddError (Maybe String) (Maybe String) diff --git a/src/client/elm/LoggedIn/Home/AddPayment/Update.elm b/src/client/elm/LoggedIn/Home/AddPayment/Update.elm index b8020f1..473e998 100644 --- a/src/client/elm/LoggedIn/Home/AddPayment/Update.elm +++ b/src/client/elm/LoggedIn/Home/AddPayment/Update.elm @@ -19,6 +19,9 @@ update action addPayment = AddPaymentAction.NoOp -> addPayment + AddPaymentAction.Init frequency -> + AddPaymentModel.init frequency + AddPaymentAction.UpdateName name -> { addPayment | name = name } diff --git a/src/client/elm/LoggedIn/Home/AddPayment/View.elm b/src/client/elm/LoggedIn/Home/AddPayment/View.elm index 09d5fbf..47dd6e8 100644 --- a/src/client/elm/LoggedIn/Home/AddPayment/View.elm +++ b/src/client/elm/LoggedIn/Home/AddPayment/View.elm @@ -3,7 +3,6 @@ module LoggedIn.Home.AddPayment.View ) where import Result exposing (..) -import Signal exposing (Address) import Html as H exposing (..) import Html.Attributes exposing (..) @@ -17,10 +16,12 @@ import LoggedIn.Home.Model as HomeModel import LoggedIn.Home.AddPayment.Action as AddPaymentAction import LoggedIn.Home.AddPayment.Model as AddPaymentModel -import Model exposing (Model) import Model.Payment exposing (PaymentFrequency(..)) import Model.Translations exposing (getMessage) -import Action as Action exposing (..) +import LoggedData exposing (LoggedData) + +import Action +import Mailbox import View.Events exposing (onSubmitPrevDefault) import View.Icon exposing (..) @@ -28,21 +29,21 @@ import View.Icon exposing (..) import Utils.Maybe exposing (isJust) import Utils.Either exposing (toMaybeError) -view : Address Action -> Model -> HomeModel.Model -> Html -view address model homeModel = +view : LoggedData -> HomeModel.Model -> Html +view loggedData homeModel = H.form [ let update = if homeModel.add.waitingServer then Action.NoOp else - UpdateLoggedIn << LoggedInAction.HomeAction <| HomeAction.AddPayment homeModel.add.name homeModel.add.cost homeModel.add.frequency - in onSubmitPrevDefault address update + Action.UpdateLoggedIn <| LoggedInAction.AddPayment homeModel.add.name homeModel.add.cost homeModel.add.frequency + in onSubmitPrevDefault Mailbox.address update , class "addPayment" ] - [ addPaymentName address homeModel.add - , addPaymentCost address model homeModel.add - , paymentFrequency address model homeModel.add + [ addPaymentName loggedData homeModel.add + , addPaymentCost loggedData homeModel.add + , paymentFrequency loggedData homeModel.add , button [ type' "submit" , classList @@ -50,13 +51,13 @@ view address model homeModel = , ("waitingServer", homeModel.add.waitingServer) ] ] - [ text (getMessage "Add" model.translations) + [ text (getMessage "Add" loggedData.translations) , if homeModel.add.waitingServer then renderSpinIcon else text "" ] ] -addPaymentName : Address Action -> AddPaymentModel.Model -> Html -addPaymentName address addPayment = +addPaymentName : LoggedData -> AddPaymentModel.Model -> Html +addPaymentName loggedData addPayment = div [ classList [ ("name", True) @@ -66,7 +67,7 @@ addPaymentName address addPayment = [ input [ id "nameInput" , value addPayment.name - , on "input" targetValue (Signal.message address << UpdateLoggedIn << LoggedInAction.HomeAction << HomeAction.UpdateAdd << AddPaymentAction.UpdateName) + , on "input" targetValue (Signal.message Mailbox.address << Action.UpdateLoggedIn << LoggedInAction.HomeAction << HomeAction.UpdateAdd << AddPaymentAction.UpdateName) , maxlength 20 ] [] @@ -80,8 +81,8 @@ addPaymentName address addPayment = text "" ] -addPaymentCost : Address Action -> Model -> AddPaymentModel.Model -> Html -addPaymentCost address model addPayment = +addPaymentCost : LoggedData -> AddPaymentModel.Model -> Html +addPaymentCost loggedData addPayment = div [ classList [ ("cost", True) @@ -91,13 +92,13 @@ addPaymentCost address model addPayment = [ input [ id "costInput" , value addPayment.cost - , on "input" targetValue (Signal.message address << UpdateLoggedIn << LoggedInAction.HomeAction << HomeAction.UpdateAdd << AddPaymentAction.UpdateCost) + , on "input" targetValue (Signal.message Mailbox.address << Action.UpdateLoggedIn << LoggedInAction.HomeAction << HomeAction.UpdateAdd << AddPaymentAction.UpdateCost) , maxlength 7 ] [] , label [ for "costInput" ] - [ text model.conf.currency ] + [ text loggedData.conf.currency ] , case addPayment.costError of Just error -> div [ class "errorMessage" ] [ text error ] @@ -105,12 +106,12 @@ addPaymentCost address model addPayment = text "" ] -paymentFrequency : Address Action -> Model -> AddPaymentModel.Model -> Html -paymentFrequency address model addPayment = +paymentFrequency : LoggedData -> AddPaymentModel.Model -> Html +paymentFrequency loggedData addPayment = button [ type' "button" , class "frequency" - , onClick address (UpdateLoggedIn << LoggedInAction.HomeAction << HomeAction.UpdateAdd <| AddPaymentAction.ToggleFrequency) + , onClick Mailbox.address (Action.UpdateLoggedIn << LoggedInAction.HomeAction << HomeAction.UpdateAdd <| AddPaymentAction.ToggleFrequency) ] [ div [ classList @@ -118,12 +119,12 @@ paymentFrequency address model addPayment = , ("selected", addPayment.frequency == Punctual) ] ] - [ text (getMessage "Punctual" model.translations) ] + [ text (getMessage "Punctual" loggedData.translations) ] , div [ classList [ ("monthly", True) , ("selected", addPayment.frequency == Monthly) ] ] - [ text (getMessage "Monthly" model.translations) ] + [ text (getMessage "Monthly" loggedData.translations) ] ] diff --git a/src/client/elm/LoggedIn/Home/Model.elm b/src/client/elm/LoggedIn/Home/Model.elm index f8d24f5..2bcbe9a 100644 --- a/src/client/elm/LoggedIn/Home/Model.elm +++ b/src/client/elm/LoggedIn/Home/Model.elm @@ -7,29 +7,23 @@ import LoggedIn.Home.Model.Payer exposing (Payers) import Model.User exposing (Users, UserId) import Model.Payment exposing (PaymentId, Payments, PaymentFrequency(..)) -import Model.Init exposing (..) import LoggedIn.Home.Account.Model as AccountModel import LoggedIn.Home.AddPayment.Model as AddPaymentModel -import LoggedIn.Home.Monthly.Model as MonthlyModel type alias Model = { add : AddPaymentModel.Model - , monthly : MonthlyModel.Model , account : AccountModel.Model - , users : Users - , payments : Payments , paymentEdition : Maybe PaymentId , currentPage : Int + , monthlyDetail : Bool } -init : Init -> Model -init initData = - { users = initData.users - , add = AddPaymentModel.init Punctual - , monthly = MonthlyModel.init initData.monthlyPayments - , account = AccountModel.init initData.me initData.incomes - , payments = initData.payments +init : Model +init = + { add = AddPaymentModel.init Punctual + , account = AccountModel.init , paymentEdition = Nothing , currentPage = 1 + , monthlyDetail = False } diff --git a/src/client/elm/LoggedIn/Home/Model/Payer.elm b/src/client/elm/LoggedIn/Home/Model/Payer.elm index 65e3f0e..aabe50a 100644 --- a/src/client/elm/LoggedIn/Home/Model/Payer.elm +++ b/src/client/elm/LoggedIn/Home/Model/Payer.elm @@ -61,8 +61,9 @@ getOrderedExceedingPayers currentTime users incomes payments = getPayers : Time -> Users -> Incomes -> Payments -> Payers getPayers currentTime users incomes payments = - let incomesDefined = incomeDefinedForAll (Dict.keys users) incomes - in Dict.keys users + let userIds = Dict.keys users + incomesDefined = incomeDefinedForAll userIds incomes + in userIds |> List.map (\userId -> ( userId , { preIncomePaymentSum = diff --git a/src/client/elm/LoggedIn/Home/Monthly/Action.elm b/src/client/elm/LoggedIn/Home/Monthly/Action.elm deleted file mode 100644 index 0a1faf4..0000000 --- a/src/client/elm/LoggedIn/Home/Monthly/Action.elm +++ /dev/null @@ -1,10 +0,0 @@ -module LoggedIn.Home.Monthly.Action - ( Action(..) - ) where - -import Model.Payment exposing (Payment) - -type Action = - ToggleDetail - | AddPayment Payment - | DeletePayment Payment diff --git a/src/client/elm/LoggedIn/Home/Monthly/Model.elm b/src/client/elm/LoggedIn/Home/Monthly/Model.elm deleted file mode 100644 index 7f6fd4c..0000000 --- a/src/client/elm/LoggedIn/Home/Monthly/Model.elm +++ /dev/null @@ -1,17 +0,0 @@ -module LoggedIn.Home.Monthly.Model - ( Model - , init - ) where - -import Model.Payment exposing (Payments) - -type alias Model = - { payments : Payments - , visibleDetail : Bool - } - -init : Payments -> Model -init payments = - { payments = payments - , visibleDetail = False - } diff --git a/src/client/elm/LoggedIn/Home/Monthly/Update.elm b/src/client/elm/LoggedIn/Home/Monthly/Update.elm deleted file mode 100644 index 70b2f9c..0000000 --- a/src/client/elm/LoggedIn/Home/Monthly/Update.elm +++ /dev/null @@ -1,21 +0,0 @@ -module LoggedIn.Home.Monthly.Update - ( update - ) where - -import LoggedIn.Home.Monthly.Action as MonthlyAction -import LoggedIn.Home.Monthly.Model as MonthlyModel - -update : MonthlyAction.Action -> MonthlyModel.Model -> MonthlyModel.Model -update action monthly = - case action of - MonthlyAction.ToggleDetail -> - { monthly | visibleDetail = not monthly.visibleDetail } - MonthlyAction.AddPayment payment -> - { monthly - | payments = payment :: monthly.payments - , visibleDetail = True - } - MonthlyAction.DeletePayment payment -> - { monthly - | payments = List.filter (((/=) payment.id) << .id) monthly.payments - } diff --git a/src/client/elm/LoggedIn/Home/Monthly/View.elm b/src/client/elm/LoggedIn/Home/Monthly/View.elm deleted file mode 100644 index f5ab721..0000000 --- a/src/client/elm/LoggedIn/Home/Monthly/View.elm +++ /dev/null @@ -1,91 +0,0 @@ -module LoggedIn.Home.Monthly.View - ( view - ) where - -import String -import Signal exposing (Address) - -import Html exposing (..) -import Html.Attributes exposing (..) -import Html.Events exposing (..) - -import LoggedIn.Action as LoggedInAction - -import LoggedIn.Home.Action as HomeAction -import LoggedIn.Home.Model as HomeModel -import LoggedIn.Home.View.Price exposing (price) -import LoggedIn.Home.View.Expand exposing (..) - -import LoggedIn.Home.Monthly.Action as MonthlyAction -import LoggedIn.Home.Monthly.Model as MonthlyModel - -import Model exposing (Model) -import Model.Payment as Payment exposing (Payments, Payment) -import Model.Translations exposing (getMessage, getParamMessage) -import Action exposing (..) - -import View.Icon exposing (renderIcon) - -view : Address Action -> Model -> HomeModel.Model -> Html -view address model homeModel = - let monthly = homeModel.monthly - in if List.length monthly.payments == 0 - then - text "" - else - div - [ classList - [ ("monthlyPayments", True) - , ("detail", monthly.visibleDetail) - ] - ] - [ monthlyCount address model monthly - , if monthly.visibleDetail then paymentsTable address model homeModel monthly else text "" - ] - -monthlyCount : Address Action -> Model -> MonthlyModel.Model -> Html -monthlyCount address model monthly = - let count = List.length monthly.payments - total = List.sum << List.map .cost <| monthly.payments - key = if count > 1 then "PluralMonthlyCount" else "SingularMonthlyCount" - in button - [ class "header" - , onClick address (UpdateLoggedIn << LoggedInAction.HomeAction << HomeAction.UpdateMonthly <| MonthlyAction.ToggleDetail) - ] - [ text (getParamMessage [toString count, price model total] key model.translations) - , expand ExpandDown monthly.visibleDetail - ] - -paymentsTable : Address Action -> Model -> HomeModel.Model -> MonthlyModel.Model -> Html -paymentsTable address model homeModel monthly = - div - [ class "table" ] - ( monthly.payments - |> List.sortBy (String.toLower << .name) - |> List.map (paymentLine address model homeModel) - ) - -paymentLine : Address Action -> Model -> HomeModel.Model -> Payment -> Html -paymentLine address model homeModel payment = - a - [ classList - [ ("row", True) - , ("edition", homeModel.paymentEdition == Just payment.id) - ] - , onClick address (UpdateLoggedIn << LoggedInAction.HomeAction <| HomeAction.ToggleEdit payment.id) - ] - [ div [ class "cell category" ] [ text (payment.name) ] - , div - [ classList - [ ("cell cost", True) - , ("refund", payment.cost < 0) - ] - ] - [ text (price model payment.cost) ] - , div - [ class "cell delete" - , onClick address (UpdateLoggedIn << LoggedInAction.HomeAction <| HomeAction.DeletePayment payment Payment.Monthly) - ] - [ button [] [ renderIcon "times" ] - ] - ] diff --git a/src/client/elm/LoggedIn/Home/Update.elm b/src/client/elm/LoggedIn/Home/Update.elm index ee0a7c3..b43ebb7 100644 --- a/src/client/elm/LoggedIn/Home/Update.elm +++ b/src/client/elm/LoggedIn/Home/Update.elm @@ -2,136 +2,51 @@ module LoggedIn.Home.Update ( update ) where -import Date -import Dict -import Debug -import Task -import String - import Effects exposing (Effects) -import Http exposing (Error(..)) -import Server +import LoggedData exposing (LoggedData) -import LoggedIn.Home.Action as LoggedInAction -import LoggedIn.Home.Model as LoggedInModel +import LoggedIn.Home.Action as HomeAction +import LoggedIn.Home.Model as HomeModel import LoggedIn.Home.Account.Action as AccountAction import LoggedIn.Home.Account.Update as AccountUpdate -import LoggedIn.Home.AddPayment.Action as AddPaymentAction -import LoggedIn.Home.AddPayment.Model as AddPaymentModel import LoggedIn.Home.AddPayment.Update as AddPaymentUpdate -import LoggedIn.Home.Monthly.Action as MonthlyAction -import LoggedIn.Home.Monthly.Model as MonthlyModel -import LoggedIn.Home.Monthly.Update as MonthlyUpdate - -import Model exposing (Model) -import Model.User exposing (UserId) -import Model.Payment exposing (..) -import Model.Translations exposing (Translations, getMessage) - -update : Model -> LoggedInAction.Action -> LoggedInModel.Model -> (LoggedInModel.Model, Effects LoggedInAction.Action) -update model action loggedInModel = +update : LoggedData -> HomeAction.Action -> HomeModel.Model -> (HomeModel.Model, Effects HomeAction.Action) +update loggedData action homeModel = case action of - LoggedInAction.NoOp -> (loggedInModel, Effects.none) - - LoggedInAction.UpdateAdd addPaymentAction -> - ( { loggedInModel | add = AddPaymentUpdate.update addPaymentAction loggedInModel.add } - , Effects.none - ) + HomeAction.NoOp -> (homeModel, Effects.none) - LoggedInAction.UpdatePayments payments -> - ( { loggedInModel | payments = payments } + HomeAction.UpdateAdd addPaymentAction -> + ( { homeModel | add = AddPaymentUpdate.update addPaymentAction homeModel.add } , Effects.none ) - LoggedInAction.AddPayment name cost frequency -> - ( { loggedInModel | add = AddPaymentUpdate.update AddPaymentAction.WaitingServer loggedInModel.add } - , Server.addPayment name cost frequency - |> Task.map (\paymentId -> - case String.toInt cost of - Err _ -> - LoggedInAction.UpdateAdd (AddPaymentAction.AddError Nothing (Just (getMessage "CostRequired" model.translations))) - Ok costNumber -> - LoggedInAction.ValidateAddPayment paymentId name costNumber frequency - ) - |> flip Task.onError (\err -> - case err of - BadResponse 400 jsonErr -> - case AddPaymentUpdate.addPaymentError model.translations jsonErr of - Just addPaymentAction -> Task.succeed (LoggedInAction.UpdateAdd addPaymentAction) - Nothing -> Task.succeed LoggedInAction.NoOp - _ -> - Task.succeed LoggedInAction.NoOp - ) - |> Effects.task - ) - - LoggedInAction.ValidateAddPayment paymentId name cost frequency -> - let newPayment = Payment paymentId (Date.fromTime model.currentTime) name cost loggedInModel.account.me - newAdd = AddPaymentModel.init frequency - in case frequency of - Punctual -> - ( { loggedInModel - | currentPage = 1 - , add = newAdd - , account = loggedInModel.account - , payments = newPayment :: loggedInModel.payments - } - , Effects.none - ) - Monthly -> - ( { loggedInModel - | add = newAdd - , monthly = MonthlyUpdate.update (MonthlyAction.AddPayment newPayment) loggedInModel.monthly - } - , Effects.none - ) + HomeAction.UpdateAccount accountAction -> + let (newAccount, accountEffects) = AccountUpdate.update loggedData accountAction homeModel.account + in ( { homeModel | account = newAccount } + , Effects.map HomeAction.UpdateAccount accountEffects + ) - LoggedInAction.ToggleEdit id -> - ( { loggedInModel | paymentEdition = if loggedInModel.paymentEdition == Just id then Nothing else Just id } + HomeAction.ToggleEdit id -> + ( { homeModel | paymentEdition = if homeModel.paymentEdition == Just id then Nothing else Just id } , Effects.none ) - LoggedInAction.DeletePayment payment frequency -> - ( loggedInModel - , Server.deletePayment payment frequency - |> Task.map (always (LoggedInAction.ValidateDeletePayment payment frequency)) - |> flip Task.onError (always <| Task.succeed LoggedInAction.NoOp) - |> Effects.task + HomeAction.UpdatePage page -> + ( { homeModel | currentPage = page } + , Effects.none ) - LoggedInAction.ValidateDeletePayment payment frequency -> - case frequency of - Monthly -> - ( { loggedInModel - | monthly = MonthlyUpdate.update (MonthlyAction.DeletePayment payment) loggedInModel.monthly - } - , Effects.none - ) - Punctual -> - ( { loggedInModel - | account = loggedInModel.account - , payments = deletePayment payment.id loggedInModel.payments - } - , Effects.none - ) - - LoggedInAction.UpdatePage page -> - ( { loggedInModel | currentPage = page } + HomeAction.ShowMonthlyDetail -> + ( { homeModel | monthlyDetail = True } , Effects.none ) - LoggedInAction.UpdateMonthly monthlyAction -> - ( { loggedInModel | monthly = MonthlyUpdate.update monthlyAction loggedInModel.monthly } + HomeAction.ToggleMonthlyDetail -> + ( { homeModel | monthlyDetail = not homeModel.monthlyDetail } , Effects.none ) - - LoggedInAction.UpdateAccount accountAction -> - let (newAccount, accountEffects) = AccountUpdate.update accountAction loggedInModel.account - in ( { loggedInModel | account = newAccount } - , Effects.map LoggedInAction.UpdateAccount accountEffects - ) diff --git a/src/client/elm/LoggedIn/Home/View.elm b/src/client/elm/LoggedIn/Home/View.elm index 23da2c5..7e6ba40 100644 --- a/src/client/elm/LoggedIn/Home/View.elm +++ b/src/client/elm/LoggedIn/Home/View.elm @@ -2,33 +2,31 @@ module LoggedIn.Home.View ( view ) where -import Signal exposing (Address) - import Html exposing (..) import Html.Attributes exposing (..) +import LoggedData exposing (LoggedData) + import LoggedIn.Home.Model as LoggedInModel import LoggedIn.Home.Account.View as AccountView import LoggedIn.Home.AddPayment.View as AddPaymentView -import LoggedIn.Home.Monthly.View as MonthlyView - -import Model exposing (Model) -import Model.Payment exposing (Payments) -import Action exposing (Action) +import LoggedIn.Home.View.Monthly as MonthlyView import LoggedIn.Home.View.Table exposing (paymentsTable) import LoggedIn.Home.View.Paging exposing (paymentsPaging) -view : Address Action -> Model -> LoggedInModel.Model -> Html -view address model loggedInModel = +import Mailbox + +view : LoggedData -> LoggedInModel.Model -> Html +view loggedData loggedIn = div [ class "loggedIn" ] - [ AddPaymentView.view address model loggedInModel + [ AddPaymentView.view loggedData loggedIn , div [ class "expandables" ] - [ AccountView.view address model loggedInModel - , MonthlyView.view address model loggedInModel + [ AccountView.view loggedData loggedIn + , MonthlyView.view loggedData loggedIn ] - , paymentsTable address model loggedInModel - , paymentsPaging address loggedInModel + , paymentsTable loggedData loggedIn + , paymentsPaging Mailbox.address loggedData.payments loggedIn ] diff --git a/src/client/elm/LoggedIn/Home/View/Monthly.elm b/src/client/elm/LoggedIn/Home/View/Monthly.elm new file mode 100644 index 0000000..487c05d --- /dev/null +++ b/src/client/elm/LoggedIn/Home/View/Monthly.elm @@ -0,0 +1,90 @@ +module LoggedIn.Home.View.Monthly + ( view + ) where + +import String + +import Html exposing (..) +import Html.Attributes exposing (..) +import Html.Events exposing (..) + +import LoggedIn.Action as LoggedInAction + +import LoggedIn.Home.Action as HomeAction +import LoggedIn.Home.Model as HomeModel +import LoggedIn.Home.View.Price exposing (price) +import LoggedIn.Home.View.Expand exposing (..) + +import Model.Payment as Payment exposing (Payment) +import Model.Translations exposing (getMessage, getParamMessage) +import LoggedData exposing (LoggedData) + +import Action +import Mailbox + +import View.Icon exposing (renderIcon) + +view : LoggedData -> HomeModel.Model -> Html +view loggedData homeModel = + if List.length loggedData.monthlyPayments == 0 + then + text "" + else + div + [ classList + [ ("monthlyPayments", True) + , ("detail", homeModel.monthlyDetail) + ] + ] + [ monthlyCount loggedData homeModel + , if homeModel.monthlyDetail + then paymentsTable loggedData homeModel + else text "" + ] + +monthlyCount : LoggedData -> HomeModel.Model -> Html +monthlyCount loggedData homeModel = + let count = List.length loggedData.monthlyPayments + total = List.sum << List.map .cost <| loggedData.monthlyPayments + key = if count > 1 then "PluralMonthlyCount" else "SingularMonthlyCount" + in button + [ class "header" + , onClick Mailbox.address (Action.UpdateLoggedIn << LoggedInAction.HomeAction <| HomeAction.ToggleMonthlyDetail) + ] + [ text (getParamMessage [toString count, price loggedData.conf total] key loggedData.translations) + , expand ExpandDown homeModel.monthlyDetail + ] + +paymentsTable : LoggedData -> HomeModel.Model -> Html +paymentsTable loggedData homeModel = + div + [ class "table" ] + ( loggedData.monthlyPayments + |> List.sortBy (String.toLower << .name) + |> List.map (paymentLine loggedData homeModel) + ) + +paymentLine : LoggedData -> HomeModel.Model -> Payment -> Html +paymentLine loggedData homeModel payment = + a + [ classList + [ ("row", True) + , ("edition", homeModel.paymentEdition == Just payment.id) + ] + , onClick Mailbox.address (Action.UpdateLoggedIn << LoggedInAction.HomeAction <| HomeAction.ToggleEdit payment.id) + ] + [ div [ class "cell category" ] [ text (payment.name) ] + , div + [ classList + [ ("cell cost", True) + , ("refund", payment.cost < 0) + ] + ] + [ text (price loggedData.conf payment.cost) ] + , div + [ class "cell delete" + , onClick Mailbox.address (Action.UpdateLoggedIn <| LoggedInAction.DeletePayment payment Payment.Monthly) + ] + [ button [] [ renderIcon "times" ] + ] + ] diff --git a/src/client/elm/LoggedIn/Home/View/Paging.elm b/src/client/elm/LoggedIn/Home/View/Paging.elm index 9942aa8..09a5b62 100644 --- a/src/client/elm/LoggedIn/Home/View/Paging.elm +++ b/src/client/elm/LoggedIn/Home/View/Paging.elm @@ -13,17 +13,18 @@ import LoggedIn.Action as LoggedInAction import LoggedIn.Home.Action as HomeAction import LoggedIn.Home.Model as HomeModel -import Action exposing (..) -import Model.Payment exposing (perPage) +import Action exposing (Action) +import LoggedData exposing (LoggedData) +import Model.Payment exposing (Payments, perPage) import View.Icon exposing (renderIcon) showedPages : Int showedPages = 5 -paymentsPaging : Address Action -> HomeModel.Model -> Html -paymentsPaging address homeModel = - let maxPage = ceiling (toFloat (List.length homeModel.payments) / toFloat perPage) +paymentsPaging : Address Action -> Payments -> HomeModel.Model -> Html +paymentsPaging address payments homeModel = + let maxPage = ceiling (toFloat (List.length payments) / toFloat perPage) pages = truncatePages homeModel.currentPage [1..maxPage] in if maxPage == 1 then @@ -60,7 +61,7 @@ firstPage : Address Action -> Html firstPage address = button [ class "page" - , onClick address (UpdateLoggedIn << LoggedInAction.HomeAction << HomeAction.UpdatePage <| 1) + , onClick address (Action.UpdateLoggedIn << LoggedInAction.HomeAction << HomeAction.UpdatePage <| 1) ] [ renderIcon "fast-backward" ] @@ -68,7 +69,7 @@ previousPage : Address Action -> HomeModel.Model -> Html previousPage address homeModel = button [ class "page" - , onClick address (UpdateLoggedIn << LoggedInAction.HomeAction << HomeAction.UpdatePage <| homeModel.currentPage - 1) + , onClick address (Action.UpdateLoggedIn << LoggedInAction.HomeAction << HomeAction.UpdatePage <| homeModel.currentPage - 1) ] [ renderIcon "backward" ] @@ -76,7 +77,7 @@ nextPage : Address Action -> HomeModel.Model -> Html nextPage address homeModel = button [ class "page" - , onClick address (UpdateLoggedIn << LoggedInAction.HomeAction << HomeAction.UpdatePage <| homeModel.currentPage + 1) + , onClick address (Action.UpdateLoggedIn << LoggedInAction.HomeAction << HomeAction.UpdatePage <| homeModel.currentPage + 1) ] [ renderIcon "forward" ] @@ -84,7 +85,7 @@ lastPage : Address Action -> Int -> Html lastPage address maxPage = button [ class "page" - , onClick address (UpdateLoggedIn << LoggedInAction.HomeAction << HomeAction.UpdatePage <| maxPage) + , onClick address (Action.UpdateLoggedIn << LoggedInAction.HomeAction << HomeAction.UpdatePage <| maxPage) ] [ renderIcon "fast-forward" ] @@ -97,6 +98,8 @@ paymentsPage address homeModel page = , ("current", onCurrentPage) ] , onClick address <| - if onCurrentPage then Action.NoOp else UpdateLoggedIn << LoggedInAction.HomeAction << HomeAction.UpdatePage <| page + if onCurrentPage + then Action.NoOp + else Action.UpdateLoggedIn << LoggedInAction.HomeAction << HomeAction.UpdatePage <| page ] [ text (toString page) ] diff --git a/src/client/elm/LoggedIn/Home/View/Price.elm b/src/client/elm/LoggedIn/Home/View/Price.elm index a3229a0..2e208f9 100644 --- a/src/client/elm/LoggedIn/Home/View/Price.elm +++ b/src/client/elm/LoggedIn/Home/View/Price.elm @@ -4,14 +4,13 @@ module LoggedIn.Home.View.Price import String exposing (..) -import Model exposing (Model) -import Model.Translations exposing (getMessage) +import Model.Conf exposing (Conf) -price : Model -> Int -> String -price model amount = +price : Conf -> Int -> String +price conf amount = ( formatInt amount ++ " " - ++ model.conf.currency + ++ conf.currency ) formatInt : Int -> String diff --git a/src/client/elm/LoggedIn/Home/View/Table.elm b/src/client/elm/LoggedIn/Home/View/Table.elm index e49fd05..58f2d0b 100644 --- a/src/client/elm/LoggedIn/Home/View/Table.elm +++ b/src/client/elm/LoggedIn/Home/View/Table.elm @@ -4,13 +4,14 @@ module LoggedIn.Home.View.Table import Dict exposing (..) import Date exposing (Date) -import Signal exposing (Address) import String exposing (append) import Html exposing (..) import Html.Attributes exposing (..) import Html.Events exposing (..) +import LoggedData exposing (LoggedData) + import LoggedIn.Action as LoggedInAction import LoggedIn.Home.Action as HomeAction @@ -18,48 +19,47 @@ import LoggedIn.Home.Model as HomeModel import LoggedIn.Home.View.Date exposing (..) import LoggedIn.Home.View.Price exposing (price) -import Model exposing (Model) import Model.User exposing (getUserName) import Model.Payment exposing (..) -import Model.Translations exposing (getMessage) -import Action exposing (..) +import Action +import Mailbox import View.Icon exposing (renderIcon) -paymentsTable : Address Action -> Model -> HomeModel.Model -> Html -paymentsTable address model homeModel = +paymentsTable : LoggedData -> HomeModel.Model -> Html +paymentsTable loggedData homeModel = div [ class "table" ] - ( headerLine model :: paymentLines address model homeModel) + ( headerLine loggedData :: paymentLines loggedData homeModel) -headerLine : Model -> Html -headerLine model = +headerLine : LoggedData -> Html +headerLine loggedData = div [ class "header" ] [ div [ class "cell category" ] [ renderIcon "shopping-cart" ] - , div [ class "cell cost" ] [ text model.conf.currency ] + , div [ class "cell cost" ] [ text loggedData.conf.currency ] , div [ class "cell user" ] [ renderIcon "user" ] , div [ class "cell date" ] [ renderIcon "calendar" ] , div [ class "cell" ] [] ] -paymentLines : Address Action -> Model -> HomeModel.Model -> List Html -paymentLines address model homeModel = - homeModel.payments +paymentLines : LoggedData -> HomeModel.Model -> List Html +paymentLines loggedData homeModel = + loggedData.payments |> List.sortBy (Date.toTime << .creation) |> List.reverse |> List.drop ((homeModel.currentPage - 1) * perPage) |> List.take perPage - |> List.map (paymentLine address model homeModel) + |> List.map (paymentLine loggedData homeModel) -paymentLine : Address Action -> Model -> HomeModel.Model -> Payment -> Html -paymentLine address model homeModel payment = +paymentLine : LoggedData -> HomeModel.Model -> Payment -> Html +paymentLine loggedData homeModel payment = a [ classList [ ("row", True) , ("edition", homeModel.paymentEdition == Just payment.id) ] - , onClick address (UpdateLoggedIn << LoggedInAction.HomeAction << HomeAction.ToggleEdit <| payment.id) + , onClick Mailbox.address (Action.UpdateLoggedIn << LoggedInAction.HomeAction << HomeAction.ToggleEdit <| payment.id) ] [ div [ class "cell category" ] [ text payment.name ] , div @@ -68,11 +68,11 @@ paymentLine address model homeModel payment = , ("refund", payment.cost < 0) ] ] - [ text (price model payment.cost) ] + [ text (price loggedData.conf payment.cost) ] , div [ class "cell user" ] [ payment.userId - |> getUserName homeModel.users + |> getUserName loggedData.users |> Maybe.withDefault "−" |> text ] @@ -80,17 +80,17 @@ paymentLine address model homeModel payment = [ class "cell date" ] [ span [ class "shortDate" ] - [ text (renderShortDate payment.creation model.translations) ] + [ text (renderShortDate payment.creation loggedData.translations) ] , span [ class "longDate" ] - [ text (renderLongDate payment.creation model.translations) ] + [ text (renderLongDate payment.creation loggedData.translations) ] ] - , if homeModel.account.me == payment.userId + , if loggedData.me == payment.userId then div [ class "cell delete" ] [ button - [ onClick address (UpdateLoggedIn <| LoggedInAction.HomeAction <| HomeAction.DeletePayment payment Punctual)] + [ onClick Mailbox.address (Action.UpdateLoggedIn <| LoggedInAction.DeletePayment payment Punctual)] [ renderIcon "times" ] ] else diff --git a/src/client/elm/LoggedIn/Model.elm b/src/client/elm/LoggedIn/Model.elm index a86b464..90f1b2b 100644 --- a/src/client/elm/LoggedIn/Model.elm +++ b/src/client/elm/LoggedIn/Model.elm @@ -3,15 +3,30 @@ module LoggedIn.Model , init ) where +import Time exposing (Time) + import Model.Init exposing (..) +import Model.Payment exposing (Payments) +import Model.User exposing (Users, UserId) +import Model.Income exposing (Incomes) import LoggedIn.Home.Model as HomeModel type alias Model = { home : HomeModel.Model + , users : Users + , me : UserId + , payments : Payments + , monthlyPayments : Payments + , incomes : Incomes } init : Init -> Model init initData = - { home = HomeModel.init initData + { home = HomeModel.init + , users = initData.users + , me = initData.me + , payments = initData.payments + , monthlyPayments = initData.monthlyPayments + , incomes = initData.incomes } diff --git a/src/client/elm/LoggedIn/Update.elm b/src/client/elm/LoggedIn/Update.elm index 189d901..8fe8d4c 100644 --- a/src/client/elm/LoggedIn/Update.elm +++ b/src/client/elm/LoggedIn/Update.elm @@ -2,9 +2,20 @@ module LoggedIn.Update ( update ) where +import Dict +import String +import Task + import Effects exposing (Effects) +import Http exposing (Error(..)) +import Date import Model exposing (Model) +import Model.Translations exposing (getMessage) +import Model.Payment exposing (Payment, PaymentFrequency(..), deletePayment) + +import Server +import LoggedData import LoggedIn.Action as LoggedInAction import LoggedIn.Model as LoggedInModel @@ -12,18 +23,96 @@ import LoggedIn.Model as LoggedInModel import LoggedIn.Home.Action as HomeAction import LoggedIn.Home.Update as HomeUpdate -type Action = HomeAction HomeAction.Action +import LoggedIn.Home.Account.Action as AccountAction + +import LoggedIn.Home.AddPayment.Action as AddPaymentAction +import LoggedIn.Home.AddPayment.Update as AddPaymentUpdate + +import Utils.Tuple as Tuple +import Utils.Effects as Effects update : Model -> LoggedInAction.Action -> LoggedInModel.Model -> (LoggedInModel.Model, Effects LoggedInAction.Action) update model action loggedIn = - case action of + let loggedData = LoggedData.build model loggedIn + in case action of + + LoggedInAction.NoOp -> + (loggedIn, Effects.none) + + LoggedInAction.HomeAction homeAction -> + case HomeUpdate.update loggedData homeAction loggedIn.home of + (home, effects) -> + ( { loggedIn | home = home } + , Effects.map LoggedInAction.HomeAction effects + ) + + LoggedInAction.AddPayment name cost frequency -> + update model (LoggedInAction.HomeAction <| HomeAction.UpdateAdd <| AddPaymentAction.WaitingServer) loggedIn + |> Tuple.mapSnd (\effect -> + Server.addPayment name cost frequency + |> Task.map (\paymentId -> + case String.toInt cost of + Err _ -> + LoggedInAction.HomeAction <| HomeAction.UpdateAdd (AddPaymentAction.AddError Nothing (Just (getMessage "CostRequired" loggedData.translations))) + Ok costNumber -> + LoggedInAction.ValidateAddPayment paymentId name costNumber frequency + ) + |> flip Task.onError (\err -> + case err of + BadResponse 400 jsonErr -> + case AddPaymentUpdate.addPaymentError model.translations jsonErr of + Just addPaymentAction -> Task.succeed (LoggedInAction.HomeAction <| HomeAction.UpdateAdd addPaymentAction) + Nothing -> Task.succeed LoggedInAction.NoOp + _ -> + Task.succeed LoggedInAction.NoOp + ) + |> Effects.task + |> \effect2 -> [effect, effect2] + |> Effects.batch + ) - LoggedInAction.NoOp -> - (loggedIn, Effects.none) + LoggedInAction.ValidateAddPayment paymentId name cost frequency -> + update model (LoggedInAction.HomeAction <| HomeAction.UpdateAdd <| AddPaymentAction.Init frequency) loggedIn + |> flip Effects.andThen (\loggedIn -> + let newPayment = Payment paymentId (Date.fromTime model.currentTime) name cost loggedIn.me + in case frequency of + Punctual -> + update model (LoggedInAction.HomeAction <| HomeAction.UpdatePage 1) loggedIn + |> Tuple.mapFst (\loggedIn -> { loggedIn | payments = newPayment :: loggedIn.payments }) + Monthly -> + update model (LoggedInAction.HomeAction <| HomeAction.ShowMonthlyDetail) loggedIn + |> Tuple.mapFst (\loggedIn -> { loggedIn | monthlyPayments = newPayment :: loggedIn.monthlyPayments }) + ) - LoggedInAction.HomeAction homeAction -> - case HomeUpdate.update model homeAction loggedIn.home of - (home, effects) -> - ( { loggedIn | home = home } - , Effects.map LoggedInAction.HomeAction effects + LoggedInAction.DeletePayment payment frequency -> + ( loggedIn + , Server.deletePayment payment frequency + |> Task.map (always (LoggedInAction.ValidateDeletePayment payment frequency)) + |> flip Task.onError (always <| Task.succeed LoggedInAction.NoOp) + |> Effects.task ) + + LoggedInAction.ValidateDeletePayment payment frequency -> + ( case frequency of + Monthly -> + { loggedIn | monthlyPayments = deletePayment payment.id loggedIn.monthlyPayments } + Punctual -> + { loggedIn | payments = deletePayment payment.id loggedIn.payments } + , Effects.none + ) + + + LoggedInAction.UpdateIncome amount -> + ( loggedIn + , Server.setIncome amount + |> Task.map (\incomeId -> (LoggedInAction.ValidateUpdateIncome incomeId amount)) + |> flip Task.onError (always <| Task.succeed LoggedInAction.NoOp) + |> Effects.task + ) + + LoggedInAction.ValidateUpdateIncome incomeId amount -> + update model (LoggedInAction.HomeAction <| HomeAction.UpdateAccount <| AccountAction.ToggleIncomeEdition) loggedIn + |> Tuple.mapFst (\loggedIn -> + let newIncome = { userId = loggedIn.me, creation = model.currentTime, amount = amount } + in { loggedIn | incomes = Dict.insert incomeId newIncome loggedIn.incomes } + ) diff --git a/src/client/elm/LoggedIn/View.elm b/src/client/elm/LoggedIn/View.elm index 27bf31a..5f7ae71 100644 --- a/src/client/elm/LoggedIn/View.elm +++ b/src/client/elm/LoggedIn/View.elm @@ -2,8 +2,6 @@ module LoggedIn.View ( view ) where -import Signal exposing (Address) - import Html exposing (..) import TransitRouter @@ -11,13 +9,16 @@ import Route exposing (..) import Action exposing (Action) import Model exposing (Model) +import LoggedData import LoggedIn.Model as LoggedInModel import LoggedIn.Home.View as HomeView -view : Address Action -> Model -> LoggedInModel.Model -> Html -view address model loggedIn = - case TransitRouter.getRoute model of - Home -> HomeView.view address model loggedIn.home - User -> text "" +view : Model -> LoggedInModel.Model -> Html +view model loggedIn = + let loggedData = LoggedData.build model loggedIn + in case TransitRouter.getRoute model of + Empty -> text "" + Home -> HomeView.view loggedData loggedIn.home + User -> text "" diff --git a/src/client/elm/Mailbox.elm b/src/client/elm/Mailbox.elm new file mode 100644 index 0000000..5337f58 --- /dev/null +++ b/src/client/elm/Mailbox.elm @@ -0,0 +1,17 @@ +module Mailbox + ( address + , signal + ) where + +import Signal exposing (Mailbox, Address) + +import Action exposing (Action) + +mailbox : Mailbox Action +mailbox = Signal.mailbox Action.NoOp + +address : Address Action +address = mailbox.address + +signal : Signal Action +signal = mailbox.signal diff --git a/src/client/elm/Main.elm b/src/client/elm/Main.elm index ac70202..561ea91 100644 --- a/src/client/elm/Main.elm +++ b/src/client/elm/Main.elm @@ -14,7 +14,7 @@ import Task exposing (..) import Time exposing (..) import Server - +import Mailbox import Action exposing (..) import Model exposing (Model, initialModel) import Update exposing (update, routerConfig) @@ -34,6 +34,7 @@ app = StartApp.start , inputs = [ Signal.map UpdateTime (Time.every 1000) , Signal.map RouterAction TransitRouter.actions + , Mailbox.signal ] } diff --git a/src/client/elm/Model.elm b/src/client/elm/Model.elm index e006e97..9e3f4a0 100644 --- a/src/client/elm/Model.elm +++ b/src/client/elm/Model.elm @@ -7,7 +7,7 @@ import Time exposing (Time) import Json.Decode as Json import TransitRouter -import Route exposing (..) +import Route exposing (Route) import Model.View exposing (..) import Model.Translations exposing (..) @@ -40,5 +40,5 @@ initialModel initialTime translations conf mbSignInError = case Json.decodeString confDecoder conf of Ok conf -> conf Err _ -> { currency = "" } - , transitRouter = TransitRouter.empty Home + , transitRouter = TransitRouter.empty Route.Empty } diff --git a/src/client/elm/Route.elm b/src/client/elm/Route.elm index dd435a6..8f8518f 100644 --- a/src/client/elm/Route.elm +++ b/src/client/elm/Route.elm @@ -9,17 +9,20 @@ import Effects exposing (Effects) import RouteParser exposing (..) type Route = - Home + Empty + | Home | User matchers : List (Matcher Route) matchers = - [ static Home "/" + [ static Empty "" + , static Home "/" , static User "/user" ] toPath : Route -> String toPath route = case route of + Empty -> "" Home -> "/" User -> "/user" diff --git a/src/client/elm/Server.elm b/src/client/elm/Server.elm index b4afe20..99ce938 100644 --- a/src/client/elm/Server.elm +++ b/src/client/elm/Server.elm @@ -12,7 +12,6 @@ import Task as Task exposing (Task) import Http import Json.Decode as Json exposing ((:=)) import Date -import Time exposing (Time) import Utils.Http exposing (..) @@ -44,8 +43,8 @@ deletePayment payment frequency = post ("/api/payment/delete?id=" ++ (toString payment.id)) |> Task.map (always ()) -setIncome : Time -> Int -> Task Http.Error IncomeId -setIncome currentTime amount = +setIncome : Int -> Task Http.Error IncomeId +setIncome amount = post ("/api/income?amount=" ++ (toString amount)) |> flip Task.andThen (decodeHttpValue <| "id" := incomeIdDecoder) diff --git a/src/client/elm/Update.elm b/src/client/elm/Update.elm index 7d56b36..5c89d0a 100644 --- a/src/client/elm/Update.elm +++ b/src/client/elm/Update.elm @@ -74,7 +74,7 @@ update action model = RouterAction routeAction -> TransitRouter.update routerConfig - (Debug.log "routeAction" routeAction) + routeAction model SignOut -> diff --git a/src/client/elm/Utils/Tuple.elm b/src/client/elm/Utils/Tuple.elm new file mode 100644 index 0000000..d9246f6 --- /dev/null +++ b/src/client/elm/Utils/Tuple.elm @@ -0,0 +1,14 @@ +module Utils.Tuple + ( mapFst + , mapSnd + , mapBoth + ) where + +mapFst : (a -> x) -> (a, b) -> (x, b) +mapFst f (a, b) = (f a, b) + +mapSnd : (b -> x) -> (a, b) -> (a, x) +mapSnd f (a, b) = (a, f b) + +mapBoth : (a -> x) -> (b -> y) -> (a, b) -> (x, y) +mapBoth f g (a, b) = (f a, g b) diff --git a/src/client/elm/View.elm b/src/client/elm/View.elm index 818daf4..6165766 100644 --- a/src/client/elm/View.elm +++ b/src/client/elm/View.elm @@ -8,6 +8,7 @@ import Signal exposing (Address) import Model exposing (Model) import Action exposing (Action) import Model.View exposing (..) +import LoggedData import View.Header exposing (renderHeader) import View.Loading exposing (renderLoading) @@ -28,7 +29,7 @@ renderMain address model = case model.view of LoadingView -> renderLoading address - SignInView signInView -> - SignInView.view address model signInView - LoggedInView loggedInView -> - LoggedInView.view address model loggedInView + SignInView signIn -> + SignInView.view address model signIn + LoggedInView loggedIn -> + LoggedInView.view model loggedIn diff --git a/src/client/elm/View/Header.elm b/src/client/elm/View/Header.elm index 5a37d9b..fb0e880 100644 --- a/src/client/elm/View/Header.elm +++ b/src/client/elm/View/Header.elm @@ -25,17 +25,14 @@ renderHeader address model = [] [ a ( [ class "title" ] ++ clickTo Home) - [ h1 - [] - [ text (getMessage "SharedCost" model.translations) ] - ] + [ text (getMessage "SharedCost" model.translations) ] , case model.view of - LoggedInView { home } -> + LoggedInView { me, users } -> div [ class "signedPanel" ] [ a ( [ class "user" ] ++ clickTo User) - [ Dict.get home.account.me home.users + [ Dict.get me users |> Maybe.map .name |> Maybe.withDefault "" |> text diff --git a/src/server/Design/Header.hs b/src/server/Design/Header.hs index a06a830..e44bce7 100644 --- a/src/server/Design/Header.hs +++ b/src/server/Design/Header.hs @@ -23,21 +23,20 @@ headerDesign = marginBottom blockMarginBottom position relative - ((".title" |> h1) <> ".user" <> ".icon") ? do + (".title" <> ".user" <> ".icon") ? do color C.white backgroundColor C.red hover & backgroundColor darkenedRed focus & backgroundColor darkenedRed ".title" ? do + display block width (pct 100) height (pct 100) - - h1 ? do - fontSize (px 35) - textAlign (alignSide sideLeft) - paddingLeft headerPadding - paddingRight headerPadding + fontSize (px 35) + textAlign (alignSide sideLeft) + paddingLeft headerPadding + paddingRight headerPadding ".signedPanel" ? do float floatRight -- cgit v1.2.3