From 1e47a7754ca38bd1a6c74765d8378caf68ce4619 Mon Sep 17 00:00:00 2001 From: Joris Date: Sun, 26 Mar 2017 21:10:42 +0200 Subject: Separate client and server watch --- src/client/LoggedIn/Income/Model.elm | 36 +++++++++ src/client/LoggedIn/Income/Msg.elm | 9 +++ src/client/LoggedIn/Income/Update.elm | 24 ++++++ src/client/LoggedIn/Income/View.elm | 108 +++++++++++++++++++++++++ src/client/LoggedIn/Income/View/Table.elm | 129 ++++++++++++++++++++++++++++++ 5 files changed, 306 insertions(+) create mode 100644 src/client/LoggedIn/Income/Model.elm create mode 100644 src/client/LoggedIn/Income/Msg.elm create mode 100644 src/client/LoggedIn/Income/Update.elm create mode 100644 src/client/LoggedIn/Income/View.elm create mode 100644 src/client/LoggedIn/Income/View/Table.elm (limited to 'src/client/LoggedIn/Income') diff --git a/src/client/LoggedIn/Income/Model.elm b/src/client/LoggedIn/Income/Model.elm new file mode 100644 index 0000000..7d852b9 --- /dev/null +++ b/src/client/LoggedIn/Income/Model.elm @@ -0,0 +1,36 @@ +module LoggedIn.Income.Model exposing + ( Model + , AddIncome + , init + , initForm + , validation + ) + +import Date exposing (Date) + +import Form exposing (Form) +import Form.Validate as Validate exposing (Validation) +import Validation + +type alias Model = + { addIncome : Form String AddIncome + } + +type alias AddIncome = + { amount : Int + , date : Date + } + +init : Model +init = + { addIncome = initForm + } + +initForm : Form String AddIncome +initForm = Form.initial [] validation + +validation : Validation String AddIncome +validation = + Validate.map2 AddIncome + (Validate.field "amount" (Validate.int |> Validate.andThen (Validate.minInt 1))) + (Validate.field "date" Validation.date) diff --git a/src/client/LoggedIn/Income/Msg.elm b/src/client/LoggedIn/Income/Msg.elm new file mode 100644 index 0000000..0a09dad --- /dev/null +++ b/src/client/LoggedIn/Income/Msg.elm @@ -0,0 +1,9 @@ +module LoggedIn.Income.Msg exposing + ( Msg(..) + ) + +import Form exposing (Form) + +type Msg = + NoOp + | AddIncomeMsg Form.Msg diff --git a/src/client/LoggedIn/Income/Update.elm b/src/client/LoggedIn/Income/Update.elm new file mode 100644 index 0000000..0023c76 --- /dev/null +++ b/src/client/LoggedIn/Income/Update.elm @@ -0,0 +1,24 @@ +module LoggedIn.Income.Update exposing + ( update + ) + +import Form exposing (Form) + +import LoggedData exposing (LoggedData) + +import LoggedIn.Income.Model as Income +import LoggedIn.Income.Msg as Income + +update : LoggedData -> Income.Msg -> Income.Model -> (Income.Model, Cmd Income.Msg) +update loggedData msg model = + case msg of + + Income.NoOp -> + ( model + , Cmd.none + ) + + Income.AddIncomeMsg formMsg -> + ( { model | addIncome = Form.update Income.validation formMsg model.addIncome } + , Cmd.none + ) diff --git a/src/client/LoggedIn/Income/View.elm b/src/client/LoggedIn/Income/View.elm new file mode 100644 index 0000000..00a1646 --- /dev/null +++ b/src/client/LoggedIn/Income/View.elm @@ -0,0 +1,108 @@ +module LoggedIn.Income.View exposing + ( view + ) + +import Dict +import Date +import Time exposing (Time) +import Task + +import FontAwesome + +import Html exposing (..) +import Html.Events exposing (..) +import Html.Attributes exposing (..) + +import Form exposing (Form) +import View.Form as Form +import View.Events exposing (onSubmitPrevDefault) + +import Dialog +import Dialog.AddIncome.Model as AddIncome +import Dialog.AddIncome.View as AddIncome + +import Msg exposing (Msg) + +import LoggedData exposing (LoggedData) + +import Model.Income exposing (IncomeId, Income, userCumulativeIncomeSince) +import Model.Translations exposing (getMessage, getParamMessage) +import Model.Payer exposing (useIncomesFrom) +import Model.User exposing (UserId, User) +import Model.View as View +import LoggedIn.Income.Model as Income + +import LoggedIn.Msg as LoggedInMsg +import LoggedIn.Income.Msg as IncomeMsg + +import View.Date as Date +import LoggedIn.View.Format as Format +import View.Color as Color +import LoggedIn.Income.View.Table as Table + +view : LoggedData -> Income.Model -> Html Msg +view loggedData incomeModel = + div + [ class "income" ] + [ div + [ class "withMargin" ] + [ case useIncomesFrom loggedData.users loggedData.incomes loggedData.payments of + Just since -> cumulativeIncomesView loggedData since + Nothing -> text "" + , div + [ class "titleButton" ] + [ h1 [] [ text <| getMessage loggedData.translations "MonthlyNetIncomes" ] + , AddIncome.button + loggedData + (AddIncome.initialAdd loggedData.translations (Date.fromTime loggedData.currentTime)) + "AddIncome" + (text (getMessage loggedData.translations "AddIncome")) + Nothing + ] + ] + , Table.view loggedData incomeModel + ] + +cumulativeIncomesView : LoggedData -> Time -> Html Msg +cumulativeIncomesView loggedData since = + let longDate = Date.longView (Date.fromTime since) loggedData.translations + in div + [] + [ h1 [] [ text <| getParamMessage [longDate] loggedData.translations "CumulativeIncomesSince" ] + , ul + [] + ( Dict.toList loggedData.users + |> List.map (\(userId, user) -> + (user.name, userCumulativeIncomeSince loggedData.currentTime since loggedData.incomes userId) + ) + |> List.sortBy Tuple.second + |> List.map (\(userName, cumulativeIncome) -> + li + [] + [ text userName + , text " − " + , text <| Format.price loggedData.conf cumulativeIncome + ] + ) + ) + ] + +incomeView : LoggedData -> (IncomeId, Income) -> Html Msg +incomeView loggedData (incomeId, income) = + li + [] + [ text <| Date.shortView (Date.fromTime income.time) loggedData.translations + , text " − " + , text <| Format.price loggedData.conf income.amount + , let dialogConfig = + { className = "deleteIncomeDialog" + , title = getMessage loggedData.translations "ConfirmIncomeDelete" + , body = always <| text "" + , confirm = getMessage loggedData.translations "Confirm" + , confirmMsg = always <| Msg.Dialog <| Dialog.UpdateAndClose <| Msg.DeleteIncome incomeId + , undo = getMessage loggedData.translations "Undo" + } + in button + [ onClick (Msg.Dialog <| Dialog.Open dialogConfig) ] + [ FontAwesome.trash Color.chestnutRose 14 ] + ] diff --git a/src/client/LoggedIn/Income/View/Table.elm b/src/client/LoggedIn/Income/View/Table.elm new file mode 100644 index 0000000..aa5e392 --- /dev/null +++ b/src/client/LoggedIn/Income/View/Table.elm @@ -0,0 +1,129 @@ +module LoggedIn.Income.View.Table exposing + ( view + ) + +import Dict exposing (..) +import Date exposing (Date) +import String exposing (append) + +import FontAwesome +import View.Color as Color + +import Html exposing (..) +import Html.Attributes exposing (..) +import Html.Events exposing (..) + +import Dialog +import Dialog.AddIncome.Model as AddIncome +import Dialog.AddIncome.View as AddIncome + +import Tooltip + +import Msg exposing (Msg) + +import LoggedData exposing (LoggedData) + +import LoggedIn.Msg as LoggedInMsg + +import LoggedIn.Income.Model as Income +import View.Date as Date +import LoggedIn.View.Format as Format + +import Model.User exposing (getUserName) +import Model.Income as Income exposing (..) +import Model.Translations exposing (getMessage) + +view : LoggedData -> Income.Model -> Html Msg +view loggedData incomeModel = + let incomes = + loggedData.incomes + |> Dict.toList + |> List.sortBy (.time << Tuple.second) + |> List.reverse + in div + [ class "table" ] + [ div + [ class "lines" ] + ( headerLine loggedData :: List.map (paymentLine loggedData incomeModel) incomes) + , if List.isEmpty (Dict.toList loggedData.incomes) + then + div + [ class "emptyTableMsg" ] + [ text <| getMessage loggedData.translations "NoIncome" ] + else + text "" + ] + +headerLine : LoggedData -> Html Msg +headerLine loggedData = + div + [ class "header" ] + [ div [ class "cell name" ] [ text <| getMessage loggedData.translations "Name" ] + , div [ class "cell income" ] [ text <| getMessage loggedData.translations "Income" ] + , div [ class "cell date" ] [ text <| getMessage loggedData.translations "Date" ] + , div [ class "cell" ] [] + , div [ class "cell" ] [] + , div [ class "cell" ] [] + ] + +paymentLine : LoggedData -> Income.Model -> (IncomeId, Income) -> Html Msg +paymentLine loggedData incomeModel (incomeId, income) = + div + [ class "row" ] + [ div + [ class "cell name" ] + [ income.userId + |> getUserName loggedData.users + |> Maybe.withDefault "−" + |> text + ] + , div + [ class "cell income" ] + [ text (Format.price loggedData.conf income.amount) ] + , div + [ class "cell date" ] + [ text (Date.longView (Date.fromTime income.time) loggedData.translations) ] + , div + [ class "cell button" ] + [ let currentDate = Date.fromTime loggedData.currentTime + in AddIncome.button + loggedData + (AddIncome.initialClone loggedData.translations currentDate income) + "CloneIncome" + (FontAwesome.clone Color.chestnutRose 18) + (Just (getMessage loggedData.translations "Clone")) + ] + , div + [ class "cell button" ] + [ if loggedData.me /= income.userId + then + text "" + else + AddIncome.button + loggedData + (AddIncome.initialEdit loggedData.translations incomeId income) + "EditIncome" + (FontAwesome.pencil Color.chestnutRose 18) + (Just (getMessage loggedData.translations "Edit")) + ] + , div + [ class "cell button" ] + [ if loggedData.me /= income.userId + then + text "" + else + let dialogConfig = + { className = "deleteIncomeDialog" + , title = getMessage loggedData.translations "ConfirmIncomeDelete" + , body = always <| text "" + , confirm = getMessage loggedData.translations "Confirm" + , confirmMsg = always <| Msg.Dialog <| Dialog.UpdateAndClose <| Msg.DeleteIncome incomeId + , undo = getMessage loggedData.translations "Undo" + } + in button + ( Tooltip.show Msg.Tooltip (getMessage loggedData.translations "Delete") + ++ [ onClick (Msg.Dialog <| Dialog.Open dialogConfig) ] + ) + [ FontAwesome.trash Color.chestnutRose 18 ] + ] + ] -- cgit v1.2.3