From 1c9ef0d8c80d825f3139178aed562200fe05ced1 Mon Sep 17 00:00:00 2001 From: Artsiom Shamsutdzinau Date: Wed, 16 Sep 2020 22:04:18 +0000 Subject: [PATCH 01/13] Add simple calculator to price and amount --- .../live/transaction_live/form_component.ex | 96 +++++++++++++++++++ .../transaction_live/form_component.html.leex | 4 +- 2 files changed, 98 insertions(+), 2 deletions(-) diff --git a/lib/simp_web/live/transaction_live/form_component.ex b/lib/simp_web/live/transaction_live/form_component.ex index b14abeb..5b07d79 100644 --- a/lib/simp_web/live/transaction_live/form_component.ex +++ b/lib/simp_web/live/transaction_live/form_component.ex @@ -43,6 +43,8 @@ defmodule SimpWeb.TransactionLive.FormComponent do @impl true def handle_event("validate", %{"transaction" => transaction_params}, socket) do + transaction_params = parse_price_and_amount(transaction_params) + changeset = socket.assigns.transaction |> Transactions.change_transaction(transaction_params) @@ -68,6 +70,8 @@ defmodule SimpWeb.TransactionLive.FormComponent do } } = socket ) do + transaction_params = parse_price_and_amount(transaction_params) + if current_user.id == transaction.user_id do case Transactions.update_transaction(transaction, transaction_params) do {:ok, _transaction} -> @@ -95,6 +99,8 @@ defmodule SimpWeb.TransactionLive.FormComponent do } } = socket ) do + transaction_params = parse_price_and_amount(transaction_params) + case Transactions.create_transaction(transaction_params, current_user) do {:ok, _transaction} -> {:noreply, @@ -114,4 +120,94 @@ defmodule SimpWeb.TransactionLive.FormComponent do "_new" end end + + def parse_price_and_amount(%{"price" => price, "amount" => amount} = transaction_params) do + price_parsed = parse_price_or_amount(price) + transaction_params = Map.put(transaction_params, "price", price_parsed) + + amount_parsed = parse_price_or_amount(amount) + Map.put(transaction_params, "amount", amount_parsed) + end + + def parse_price_or_amount(string) do + parsingError = %{ + hasError: true, + isDotUsed: false, + sign: nil, + num: "", + res: 0 + } + + %{sign: sign, num: num, res: res, isDotUsed: isDotUsed, hasError: hasError} = + Enum.reduce( + String.graphemes(string), + %{sign: "+", num: "", res: 0, isDotUsed: false, hasError: false}, + fn symbol, %{sign: sign, num: num, res: res, isDotUsed: isDotUsed, hasError: hasError} -> + cond do + hasError or + (Enum.member?(["+", "-"], symbol) and num === "") or + ((symbol === "." and isDotUsed) or + (symbol === "." and num === "")) -> + parsingError + + Enum.member?(["0", "1", "2", "3", "4", "5", "6", "7", "8", "9"], symbol) -> + %{ + hasError: false, + sign: sign, + num: num <> symbol, + res: res, + isDotUsed: isDotUsed + } + + symbol === "." -> + %{ + hasError: false, + sign: sign, + num: num <> symbol, + res: res, + isDotUsed: true + } + + Enum.member?(["+", "-"], symbol) -> + %{ + hasError: false, + sign: symbol, + num: "", + isDotUsed: false, + res: + res + + if sign === "+" do + {parsed, _} = Float.parse(num) + parsed + else + {parsed, _} = Float.parse(num) + -parsed + end + } + + true -> + parsingError + end + end + ) + + cond do + hasError -> + "error" + + true -> + if num === "" do + res + else + res + + if sign === "+" do + {parsed, _} = Float.parse(num) + parsed + else + {parsed, _} = Float.parse(num) + -parsed + end + end + end + end end diff --git a/lib/simp_web/live/transaction_live/form_component.html.leex b/lib/simp_web/live/transaction_live/form_component.html.leex index cf13faa..d8ddb53 100644 --- a/lib/simp_web/live/transaction_live/form_component.html.leex +++ b/lib/simp_web/live/transaction_live/form_component.html.leex @@ -53,13 +53,13 @@
<%= label f, :price %> - <%= number_input f, :price, step: "any" %> + <%= text_input f, :price, inputmode: "tel" %> <%= error_tag f, :price %>
<%= label f, :amount %> - <%= number_input f, :amount, step: "any" %> + <%= text_input f, :amount, inputmode: "tel" %> <%= error_tag f, :amount %>
From 8ec0f9cb290653357c4d053086a581bae52e86b4 Mon Sep 17 00:00:00 2001 From: Artsiom Shamsutdzinau Date: Sun, 11 Oct 2020 07:35:21 +0000 Subject: [PATCH 02/13] Fix searchForm top --- assets/css/components/transactions.scss | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/assets/css/components/transactions.scss b/assets/css/components/transactions.scss index 94eb7bf..03e9157 100644 --- a/assets/css/components/transactions.scss +++ b/assets/css/components/transactions.scss @@ -5,7 +5,7 @@ align-items: center; flex-grow: 1; } - + &__item { max-width: var(--max-page-width); width: 100%; @@ -26,13 +26,13 @@ margin-bottom: 80px; } } - + &__itemSection { display: flex; justify-content: space-between; width: 100%; } - + &__itemLink { position: absolute; width: 100%; @@ -44,7 +44,7 @@ &__searchForm { border-bottom: 1px solid var(--c-gray-4); position: sticky; - top: 46px; + top: 45px; left: 0; background-color: var(--c-gray-1); z-index: 1; From acda4c7e4f473e7d71046ad621e9aa958d3a38c0 Mon Sep 17 00:00:00 2001 From: Artsiom Shamsutdzinau Date: Mon, 9 Nov 2020 18:34:53 +0000 Subject: [PATCH 03/13] Fix searchForm top again --- assets/css/components/transactions.scss | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assets/css/components/transactions.scss b/assets/css/components/transactions.scss index 03e9157..59a8d00 100644 --- a/assets/css/components/transactions.scss +++ b/assets/css/components/transactions.scss @@ -44,7 +44,7 @@ &__searchForm { border-bottom: 1px solid var(--c-gray-4); position: sticky; - top: 45px; + top: 46px; left: 0; background-color: var(--c-gray-1); z-index: 1; From 80c6c2feafce0c1337c3ae0f06741e52d53dac3e Mon Sep 17 00:00:00 2001 From: Artsiom Shamsutdzinau Date: Sun, 6 Dec 2020 13:09:47 +0300 Subject: [PATCH 04/13] Change reset css --- assets/css/reset.scss | 159 +++++++++++++++++++++++++++++++++--------- 1 file changed, 126 insertions(+), 33 deletions(-) diff --git a/assets/css/reset.scss b/assets/css/reset.scss index afdfb25..345a2c2 100644 --- a/assets/css/reset.scss +++ b/assets/css/reset.scss @@ -1,3 +1,10 @@ +html, +body, +div, +span, +applet, +object, +iframe, h1, h2, h3, @@ -5,66 +12,156 @@ h4, h5, h6, p, -fieldset, -body, -button, +blockquote, +pre, +a, +abbr, +acronym, +address, +big, +cite, +code, +del, +dfn, +em, +img, +ins, +kbd, +q, +s, +samp, +small, +strike, +strong, +sub, +sup, +tt, +var, +b, +u, +i, +center, +dl, +dt, +dd, +ol, ul, +li, +fieldset, +form, +label, +legend, +table, +caption, +tbody, +tfoot, +thead, +tr, +th, +td, +article, +aside, +canvas, +details, +embed, figure, -ol { +figcaption, +footer, +header, +hgroup, +menu, +nav, +output, +ruby, +section, +summary, +time, +mark, +audio, +video { margin: 0; + padding: 0; + border: 0; + font: inherit; + font-size: inherit; + vertical-align: baseline; } -fieldset, -button, -legend, -ul, -ol { - padding: 0; +article, +aside, +details, +figcaption, +figure, +footer, +header, +hgroup, +menu, +nav, +section, +img { + display: block; } -fieldset { - border: none; +li { + list-style: none; +} + +blockquote, +q { + quotes: none; +} + +blockquote::before, +blockquote::after, +q::before, +q::after { + content: ""; + content: none; +} + +table { + border-spacing: 0; + border-collapse: collapse; } button { - border: none; width: auto; overflow: visible; + border: none; background-color: transparent; - line-height: inherit; - text-align: inherit; color: inherit; font-family: inherit; font-size: inherit; font-weight: inherit; -} - -ul, -ol { - list-style: none; + line-height: inherit; + text-align: inherit; } input, textarea { + padding: 0; + border: none; + background-color: inherit; + color: inherit; font-family: inherit; - line-height: inherit; font-size: inherit; + line-height: inherit; } -input[type='number'] { +input[type="number"] { appearance: textfield; } -input[type='number']::-webkit-outer-spin-button, -input[type='number']::-webkit-inner-spin-button { +input[type="number"]::-webkit-outer-spin-button, +input[type="number"]::-webkit-inner-spin-button { appearance: none; margin: 0; } -input[type='search']::-webkit-search-decoration, -input[type='search']::-webkit-search-cancel-button, -input[type='search']::-webkit-search-results-button, -input[type='search']::-webkit-search-results-decoration { +input[type="search"]::-webkit-search-decoration, +input[type="search"]::-webkit-search-cancel-button, +input[type="search"]::-webkit-search-results-button, +input[type="search"]::-webkit-search-results-decoration { display: none; } @@ -75,13 +172,9 @@ select { } a { - text-decoration: none; color: inherit; font-family: inherit; font-size: inherit; font-weight: inherit; -} - -img { - display: block; + text-decoration: none; } From 1719607a971c9f788597ba78da23c2ab820f50da Mon Sep 17 00:00:00 2001 From: Artsiom Shamsutdzinau Date: Wed, 30 Dec 2020 13:45:52 +0300 Subject: [PATCH 05/13] change opacity --- assets/css/app.scss | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assets/css/app.scss b/assets/css/app.scss index 72fa2e5..4897957 100644 --- a/assets/css/app.scss +++ b/assets/css/app.scss @@ -29,7 +29,7 @@ } .phx-click-loading { - opacity: 0.5; + opacity: 0.6; transition: opacity 1s ease-out; } From 095edcdd79ce9f93d6ce9a4ce896ec423031e191 Mon Sep 17 00:00:00 2001 From: Artsiom Shamsutdzinau Date: Sun, 24 Jan 2021 23:57:09 +0300 Subject: [PATCH 06/13] change readme --- README.md | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index ef1cecd..16a3e22 100644 --- a/README.md +++ b/README.md @@ -1,21 +1,25 @@ -# Docker Phoenix +# Simple. Uses Docker Phoenix ## Prerequisites + Install docker and docker-compose. Duplicate `.example.env` file and rename it to `.env` ## Motivation + I wanted to have a starter kit for Phoenix projects that I would be able to run anywhere in docker. Alpine linux is used for all the docker images. If you use vscode - all the necessary extensions for developing phoenix application will be installed automatically inside the container ## Set up for vscode users + 1. Install https://marketplace.visualstudio.com/items?itemName=ms-vscode-remote.vscode-remote-extensionpack 2. Open the folder in vscode and it should suggest you to reopen it inside the container 3. After setting up the database you can add connection in postresql explorer (use hostname `db`, user and password from `.env` file) 4. In `devcontainer.json` set `elixir.projectPath` and `elixirLS.projectDir` to the path to your project so elixir-ls extension starts working. ## Get started + 1. Start shell session inside the container. For vscode users - just open the terminal (Ctrl + J) - it will already be inside the container. For others - run e.g. `docker exec -it phoenix-docker_app_1 sh` 2. Create new phoenix project `mix phx.new your_project_name` and press enter to install dependencies when it prompts you 3. To set up postgres open `config/dev.exs`, change hostname to `"db"`, database to `"database"` and run `mix ecto.create` in your project folder From 28fa2fee444ab667efc8b309d60fe82b2ee4873b Mon Sep 17 00:00:00 2001 From: Artsiom Shamsutdzinau Date: Thu, 28 Jan 2021 21:39:09 +0300 Subject: [PATCH 07/13] Switch category on is_expense change, fix parsing --- config/dev.exs | 4 +- .../live/transaction_live/form_component.ex | 46 ++++++++++++++----- 2 files changed, 36 insertions(+), 14 deletions(-) diff --git a/config/dev.exs b/config/dev.exs index 12b631e..376e3af 100644 --- a/config/dev.exs +++ b/config/dev.exs @@ -2,8 +2,8 @@ use Mix.Config # Configure your database config :simp, Simp.Repo, - username: "postgres", - password: "postgres", + username: "postgres_user", + password: "postgres_password", database: "database", hostname: "db", show_sensitive_data_on_connection_error: true, diff --git a/lib/simp_web/live/transaction_live/form_component.ex b/lib/simp_web/live/transaction_live/form_component.ex index 5b07d79..d9b0a15 100644 --- a/lib/simp_web/live/transaction_live/form_component.ex +++ b/lib/simp_web/live/transaction_live/form_component.ex @@ -11,6 +11,7 @@ defmodule SimpWeb.TransactionLive.FormComponent do socket |> assign(assigns) |> assign(:changeset, changeset) + |> assign(:previous_is_expense, Ecto.Changeset.get_field(changeset, :is_expense)) |> set_data()} end @@ -18,16 +19,26 @@ defmodule SimpWeb.TransactionLive.FormComponent do %{ assigns: %{ current_user: current_user, - changeset: changeset + changeset: changeset, + previous_is_expense: previous_is_expense } } = socket ) do + is_expense = Ecto.Changeset.get_field(changeset, :is_expense) + categories = Transactions.list_categories( current_user, - Ecto.Changeset.get_field(changeset, :is_expense) + is_expense ) + changeset = + if previous_is_expense == is_expense do + changeset + else + Ecto.Changeset.change(changeset, category: List.first(categories) || "") + end + names = Transactions.list_names( current_user, @@ -37,7 +48,9 @@ defmodule SimpWeb.TransactionLive.FormComponent do assign(socket, categories: categories, names: names, - currencies: Transactions.list_currencies(current_user) + currencies: Transactions.list_currencies(current_user), + changeset: changeset, + previous_is_expense: is_expense ) end @@ -197,16 +210,25 @@ defmodule SimpWeb.TransactionLive.FormComponent do true -> if num === "" do - res + "" else - res + - if sign === "+" do - {parsed, _} = Float.parse(num) - parsed - else - {parsed, _} = Float.parse(num) - -parsed - end + res = + res + + if sign === "+" do + {parsed, _} = Float.parse(num) + parsed + else + {parsed, _} = Float.parse(num) + -parsed + end + + [integer_part, decimal_part] = String.split(Float.to_string(res), ".") + + if decimal_part == "0" do + String.to_integer(integer_part) + else + res + end end end end From ab8c22bc5bf5be7df724166b1b183231e8901d4b Mon Sep 17 00:00:00 2001 From: Artsiom Shamsutdzinau Date: Mon, 22 Feb 2021 12:07:47 +0300 Subject: [PATCH 08/13] change search top --- assets/css/components/transactions.scss | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assets/css/components/transactions.scss b/assets/css/components/transactions.scss index 59a8d00..03e9157 100644 --- a/assets/css/components/transactions.scss +++ b/assets/css/components/transactions.scss @@ -44,7 +44,7 @@ &__searchForm { border-bottom: 1px solid var(--c-gray-4); position: sticky; - top: 46px; + top: 45px; left: 0; background-color: var(--c-gray-1); z-index: 1; From 9da56be2978de1f93591de591d05926480d229d9 Mon Sep 17 00:00:00 2001 From: Artsiom Shamsutdzinau Date: Wed, 24 Mar 2021 08:22:35 +0300 Subject: [PATCH 09/13] change input padding --- assets/css/components/input.scss | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assets/css/components/input.scss b/assets/css/components/input.scss index d8936eb..28fae16 100644 --- a/assets/css/components/input.scss +++ b/assets/css/components/input.scss @@ -4,7 +4,7 @@ input { border: 1px solid var(--c-gray-6); border-radius: var(--bdrs-default); height: 30px; - padding-left: 7px; + padding-left: 6px; outline: none; &:focus { From e3777b54790a264f9fce45ff0a621c8cbc23f44c Mon Sep 17 00:00:00 2001 From: Artsiom Shamsutdzinau Date: Sun, 18 Apr 2021 12:59:46 +0300 Subject: [PATCH 10/13] Change padding --- assets/css/components/input.scss | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assets/css/components/input.scss b/assets/css/components/input.scss index 28fae16..49ae83b 100644 --- a/assets/css/components/input.scss +++ b/assets/css/components/input.scss @@ -4,7 +4,7 @@ input { border: 1px solid var(--c-gray-6); border-radius: var(--bdrs-default); height: 30px; - padding-left: 6px; + padding-left: 5px; outline: none; &:focus { From 5e60b5f7430e2d74ab000565f425e8209352f6a8 Mon Sep 17 00:00:00 2001 From: Artsiom Shamsutdzinau Date: Thu, 20 May 2021 12:59:54 +0300 Subject: [PATCH 11/13] change padding --- assets/css/components/modal.scss | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/assets/css/components/modal.scss b/assets/css/components/modal.scss index 43ac728..eeee9c7 100644 --- a/assets/css/components/modal.scss +++ b/assets/css/components/modal.scss @@ -1,5 +1,5 @@ .modal { - opacity: 1!important; + opacity: 1 !important; position: fixed; z-index: 2; left: 0; @@ -15,7 +15,7 @@ background-color: var(--c-gray-1); max-height: 100%; overflow-y: auto; - padding: 15px; + padding: 14px; width: 100%; max-width: var(--max-page-width); display: flex; From adca3bd72956c6002b5094860340208933c30062 Mon Sep 17 00:00:00 2001 From: Artsiom Shamsutdzinau Date: Tue, 15 Jun 2021 07:39:04 +0300 Subject: [PATCH 12/13] change padding --- assets/css/components/modal.scss | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assets/css/components/modal.scss b/assets/css/components/modal.scss index eeee9c7..7af779a 100644 --- a/assets/css/components/modal.scss +++ b/assets/css/components/modal.scss @@ -15,7 +15,7 @@ background-color: var(--c-gray-1); max-height: 100%; overflow-y: auto; - padding: 14px; + padding: 15px; width: 100%; max-width: var(--max-page-width); display: flex; From 3666d03a6961391c5f75cd70f8557ea9396316f6 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 12 Aug 2021 08:58:22 +0000 Subject: [PATCH 13/13] Bump path-parse from 1.0.6 to 1.0.7 in /assets Bumps [path-parse](https://github.com/jbgutierrez/path-parse) from 1.0.6 to 1.0.7. - [Release notes](https://github.com/jbgutierrez/path-parse/releases) - [Commits](https://github.com/jbgutierrez/path-parse/commits/v1.0.7) --- updated-dependencies: - dependency-name: path-parse dependency-type: indirect ... Signed-off-by: dependabot[bot] --- assets/package-lock.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/assets/package-lock.json b/assets/package-lock.json index 4517c82..b7887e7 100644 --- a/assets/package-lock.json +++ b/assets/package-lock.json @@ -5068,9 +5068,9 @@ "dev": true }, "path-parse": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.6.tgz", - "integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==", + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", "dev": true }, "path-type": {