GithubHelp home page GithubHelp logo

dwyl / mvp Goto Github PK

View Code? Open in Web Editor NEW
83.0 6.0 2.0 2.01 MB

📲 simplest version of the @dwyl app

Home Page: https://mvp.fly.dev

License: GNU General Public License v2.0

Elixir 78.15% CSS 0.90% JavaScript 1.81% HTML 18.16% Dockerfile 0.89% Shell 0.05% Batchfile 0.03%
alpinejs example minimum-viable-product mvp phoenix phoenix-framework phoenix-liveview tailwindcss tutorial examples

mvp's Introduction

@dwyl App MVP 💡 ⏳ ✅

The most basic version of the @dwyl App MVP feature set.

Please try it: mvp.fly.dev 🙏

And help us to ...

MVP Loop

GitHub Workflow Status codecov.io Hex.pm contributions welcome HitCount


Why? 🤷‍♀️

Our goal with this MVP is to build the minimal usable App
that covers our basic "Capture, Categorize, Complete" workflow.
It is well-documented, tested and easy for a beginner to run & understand.

We shipped the App to Fly: mvp.fly.dev and use/test it (internally).
After collecting initial feedback, we will integrate it into the main dwyl/app repo.
We maintain this repo as a reference for new joiners
wanting the most basic version to learn from.

What? 💭

A mobile-first hybrid task and activity (time) tracking tool.

MVP? 🚧

A Minimum Viable Product (MVP), as its' name suggests, is the minimum we can do to test the idea.

If you're new to MVPs, the Wikipedia article is a good starting point: wikipedia.org/wiki/Minimum_viable_product
Or listen to Eric Ries describe it in 3 minutes: https://youtu.be/1FoCbbbcYT8
Validate your business idea: THE LEAN STARTUP by Eric Ries: https://youtu.be/QaoVWtLX038
Building Minimal Viable Product with Michael Seibel UC Berkeley Course: https://youtu.be/m4isFputh68?t=75
How Not To Start A Startup | Michael Seibel: https://youtu.be/9tq-lTjTu2Q?t=413

Two Apps in One ✌️

We've found it tedious to use several separate apps for task and time tracking 🤦‍♂️
and think it's logical to combine the functionality. This MVP combines two apps into one. 💡

In our journey to understand the features we want from first principles, we built the two separate apps:

  1. Todo list: github.com/dwyl/phoenix-liveview-todo-list
  2. Stop Watch (Timer): github.com/dwyl/phoenix-liveview-stopwatch

We encourage you to read and understand the individual feature Apps before trying to run the MVP. 👀
But our hope is that the UI/UX in the MVP is sufficiently intuitive that it immediately makes sense. 🤞

Proposed MVP UI/UX 💡

This is our wireframe UI/UX we used as the guide to create the MVP functionality:

mvp-proposed-ux

The idea is a todo list that tracks how much time we spend on a task.

It's deliberately "basic" and "ugly" so we don't focus on aesthetics. 🚀
It will definitely change over time as we use the App and collect feedback. 💬
If you want to help make it better, share your thoughts! 🙏

More detail on the MVP features: dwyl/app/issues/265


Who? 👥

This MVP has two target audiences:

  1. @dwyl team to "dogfood" the basic workflow in our App.
    It's meant to work for us and have just enough functionality to solve our basic needs.

  2. Wider community of people who want to see a fully-functioning Phoenix app with good documentation and testing.

Longer term, the MVP will help future @dwyl team members get up-to-speed on our App & Stack much faster.

Feedback! 🙏

Your feedback is very much encouraged/welcome! 💬
If you find the repo interesting/useful, please ⭐ on GitHub.
And if you have any questions, please open an issue: app-mvp/issues

Perform Some Actions in the App 📱

Please visit mvp.fly.dev (or run the app on your localhost - see below)
and perform some actions to test the App:

  1. Create a todo list item;

    Note: this item is public (anyone can see it!)
    If you want private items you need to login.

  2. Start a timer for the (public) item
  3. Stop the timer for the item (press start)
  4. Mark the item as done (press/tap the checkbox to the left of the item.text)
  5. Click on the done tab and archive the item (it will disappear)
  6. Click on the archived tab and you will see your archived item
  7. Create a new (public) item.
  8. Start a timer for the (public) item and leave it running
  9. Login using your GitHub or Google account.
  10. Create a todo list item while logged-in with a tag.
  11. Start a timer for the item
  12. Stop the timer
  13. Resume the timer that you just stopped.
  14. Create a new (private) todo list item while logged-in with a different tag
  15. Start a timer for the item
  16. Open a second web browser and watch the realtime sync!
  17. Click on the first private item tag and see the filtered list of items with that tag
  18. Click on the active tab or go back in the browser
  19. Mark the first item you created as done
  20. Edit the remaining item text for the timer that is already running.
  21. Mark the (private) item as done and see the time it took.
  22. Archive the item
  23. Click on the tags label on the navbar to check the tags created.
  24. Go back
  25. Logout of the app
  26. View the (public) item you created earlier with the timer still running.

That's it. The MVP in a nutshell. Here's a GIF if you're low on time:

speedrun

The GIF showcases the (todo list) items, tag filtering and timers being synched across 2 browsers (one desktop and another mimicking mobile) in realtime.


How? 💻

Our goal is to document as much of the implementation as possible, so that anyone can follow along.

If you spot a gap in the docs, please let us know!

Tech Stack? 🧰

This MVP app uses the PETAL Stack described in: dwyl/technology-stack

Going through the individual feature apps listed above will give you the knowledge to understand this MVP.

If you have any coding skills (e.g: JavaScript, Java, Python, Ruby, PHP, SQL, etc.)
you will be able to follow along without much difficulty as the code is deliberately simple.

Run the MVP App on your localhost ⬇️

Note: You will need to have Elixir and Postgres installed,
see: learn-elixir#installation and learn-postgresql#installation

Tip: check the prerequisites in: /phoenix-chat-example

On your localhost, run the following commands in your terminal:

git clone [email protected]:dwyl/app-mvp.git && cd app-mvp
source .env_sample
mix setup

That will load up the necessary env variables to run the app, download the code, install dependencies, and create the necessary database + tables.

The line source .env_sample loads the environment variables required to run the App.

Once the mix setup command completes, you can run the app with:

mix s

Open the App in your web browser localhost:4000 and start your tour!


Build It! 👷‍♀️

If you want to understand how to build the MVP, please see: BUILDIT.md


Contributing 👩‍💻

All contributions from typo fixes to feature requests are always welcome! 🙌

Please start by:
a. Star the repo on GitHub so you have a "bookmark" you can return to. ⭐
b. Fork the repo so you have a copy you can "hack" on. 🍴
c. Clone the repo to your localhost and run it! (see below) 👩‍💻

For more detail, please see: dwyl/contributing

More Features? 🔔

Please note that our goal with this MVP is not to have all the features; again, it's deliberately simple.
We will be adding lots more features to the full App.
If you have feature ideas, that's great! 🎉
Please share them: app/issues

mvp's People

Contributors

arhell avatar dependabot[bot] avatar duldr avatar iteles avatar luchoturtle avatar nelsonic avatar panoramix360 avatar seaneady avatar simonlab avatar stavares843 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar

mvp's Issues

Avoid Displaying Negative Time Counter

At present when the timer on the original MVP reaches the end of the 25min estimate,
the time elapsed counter continues counting up (that's desirable) but the time remaining (countdown) timer continues counting down into negative numbers ... 🤦‍♂
image

We need to write a test for this and avoid displaying negative countdown time.
And/or figure out a way to show people that they have gone over their original estimate
without showing a negative timer ... showing people they are over their estimate might be a separate issue we need to explore the UX for ... let's keep the acceptance criteria simple here. 😉

Acceptance Criteria

  • Once time estimate (e.g 25 mins) has been exceeded, stop counting down.

Cookie SameSite Warnings

Got this warning in the Firefox Developer Console:

Some cookies are misusing the recommended “SameSite“ attribute 3
Cookie “_app_key” will be soon rejected because it has the “SameSite” attribute set to “None” or an invalid value, without the “secure” attribute. To know more about the “SameSite“ attribute, read https://developer.mozilla.org/docs/Web/HTTP/Headers/Set-Cookie/SameSite new
Cookie “__cfduid” has been rejected because it is in a cross-site context and its “SameSite” is “Lax” or “Strict”. 2 android-icon-192x192.png
Cookie “__cfduid” has been rejected because it is in a cross-site context and its “SameSite” is “Lax” or “Strict”. 2 favicon-16x16.png

image

The _app_key cookie is under our control: dwyl/auth_plug#28
and the other two are because we are sourcing the two icons from the dwyl.com website which is fronted by CloudFlare https://support.cloudflare.com/hc/en-us/articles/200170156-Understanding-the-Cloudflare-Cookies
We can easily overcome this by hosting the icons ourself in the phoenix assets instead of getting them from the dwyl website.

Add pre-commit hook to run mix test on localhost?

I've just pushed a commit on my branch thinking the tests were passing (I didn't check)
and then watched them fail on Travis-CI 🤦‍♂

Should we be using https://github.com/dwyl/elixir-pre-commit to prevent failing commits? 👮
Or is one of the benefits of CI that it offloads running tests to someone else's computer? 💻

@SimonLab how do you feel about pre-commit hooks that run tests on localhost before pushing to GitHub? Is it better to know sooner that tests are failing or to be informed by CI? 🤔

** (ErlangError) Erlang error: {:badarg, {'aead.c', 90}, 'Unknown cipher or invalid key size'}

https://github.com/dwyl/app-mvp-phoenix/runs/7276485713?check_suite_focus=true#step:7:173
image

** (ErlangError) Erlang error: {:badarg, {'aead.c', 90}, 'Unknown cipher or invalid key size'}
    (crypto 5.1) crypto.erl:982: :crypto.crypto_one_time_aead(:aes_256_gcm, "", <<34, 41, 227, 244, 55, 153, 210, 169, 201, 246, 127, 207, 37, 31, 38, 23>>, "Beyoncé", "AES256GCM", 16, true)
    (fields 2.9.0) lib/aes.ex:36: Fields.AES.encrypt/1
    (fields 2.9.0) lib/encrypted.ex:21: Fields.Encrypted.dump/1
    (ecto 3.8.4) lib/ecto/type.ex:938: Ecto.Type.process_dumpers/3
    (ecto 3.8.4) lib/ecto/repo/schema.ex:996: Ecto.Repo.Schema.dump_field!/6
    (ecto 3.8.4) lib/ecto/repo/schema.ex:1009: anonymous fn/6 in Ecto.Repo.Schema.dump_fields!/5
    (stdlib 4.0) maps.erl:411: :maps.fold_1/3
    (ecto 3.8.4) lib/ecto/repo/schema.ex:1007: Ecto.Repo.Schema.dump_fields!/5

Debugging this ...

Always display timer even when no active timer is counting

At present when a timer is stopped it disappears from the UI:
mvp-timer-accumulation

This is lame because we cannot see how much time has been spent on a given item.
A much better UX would be to always have the time elapsed visible in the UI.

Todo

  • Keep the timer visible when stopped
  • Change the button label to "Resume if there have been previous timers.
  • Avoid cluttering the UI with an all-zeros timer i.e. should not be visible if no timers exist for an item

image

CHORE: DRY/componentize `app_live.html.heex`

At present the lib/app_web/live/app_live.html.heex file has a few bits of repeated nearly identical code. 🙄
This was done in the interest of speed but is not very maintainable and requires lots of scrolling.

Todo

  • split out the various tags e.g. <form>, <button> and timer into reusable components.

Please see: https://hexdocs.pm/phoenix_live_view/Phoenix.LiveComponent.html
Note: please wait for #89 / #90 to be complete/merged before tackling this. 🙏 ⏳
And if you are undertaking this chore, please document all the steps with instructions in the README.md 📝

Do not display Google Login button when already logged in

At the moment when visiting the / endpoint the Google signin button is always displayed even when the user is already loggedin:

image

  • Check if user is loggedin
  • Redirect to user information page when loggedin
  • Display Google signin if not loggedin

This require the index view of the goog_auth_controller to be on its self user information controller to be able to redirect the user if already loggedin

  • Create info endpoint which display basic info of the loggedin user

Configure CORS for api endpoints

While testing the Elm PWA which send a post request to the Phoenix api a CORS error appeared:
image

This means that at the moment the server doesn't allow request which are not from it's own origin (ie coming from a page rendered previously by the server itself). Because I'm testing the Elm PWA on localhost:8000 the origin of the request is different to https://dwylapp.herokuapp.com which produce the error.

The following elixir package can be used to configure what origns are allowed to send request to your server

I'm going to try cors_plug to allow temporarily request from localhost while testing. Once the Elm application is hosted we can update the origin to only allow requests from this server.

Clicking/Tapping the "done" Checkbox Should Stop Timer

It's just occurred to me that clicking the checkbox to say an item is "done" does not stop the timer.
Let's fix that!

Todo

  • create a function that looks for active timers for a given item_id
  • update the code in handle_event("toggle") event to stop the active timer if there is one.
  • if there is no active timer (because some people will "do" a task without timing it 🙄) then ignore

EPIC: Update MVP App to Latest `Phoenix` with `auth_plug`

This project is a bit out-of-date.
Let's fix that and add @dependabot to keep it up-to-date!

Todo

  • Create ERD #89 (comment)
  • Map out all existing functions/functionality [read through the docs + update!] #89 (comment)
  • Create a branch
  • Nuke all the code! 🙊
  • Create a new [email protected] project 🆕
  • Re-create the schemas as per the ERD
    • Simplify them along the way!
  • Add auth_plug so we leverage auth from the start. #104
    • auth is not required to create items. i.e optional.
  • #100
    • create an item using basic interface
    • items are automatically added to a single list (separate lists can follow later)
    • all items are considered to be tasks for now and thus have a timer (start) button next to them in the UI/UX
    • Render counting timer using Alpine.js #99
    • Accumulate timers #103
    • Edit timer.text #102
    • Add icons to buttons #101
    • sync to connected devices
  • Android/Apple Shortcut icons (for add to home screen) #111
  • Create PR! #90
  • Deploy to Fly.io (fast!) #109 🚀
  • Rename timer.end to timer.stop: #114
  • Implement upsert_people/1 function #115 to create or update a person record. c77d43a
  • DELETE people schema/table from the project! #118
  • Update the README.md
    • Add brief section on MVPs #91
  • Assign to Simon
  • Iterate!! > GOTO: #119

Add Auth (AuthPlug) to MVP

Now that we have Auth working https://dwylauth.herokuapp.com 🚀 we can add it to the MVP to simplify the App.

Todo

  • Add auth_plug to mix.exs see: https://github.com/dwyl/auth_plug
  • Enable auth_plug in router.ex
  • Enable AuthPlugOptional in router.ex for any routes where auth is optional
  • Remove all personally identifiable information from the MVP
    • Keep people table with bare minimum data to allow FK in items table to work.
  • Remove any auth related tests and let auth_plug handle all of that!
  • Ensure that everything still works as expected (tests for creating items should all still pass)
  • Get back to building the features we actually want! dwyl/app#266

App does not show a Google login option on localhost:4000

I followed the directions in the README and got past all the installation steps. But when I start the app, I don't see something resembling the screenshot in the README, which has a login button for Google. In fact, I noticed that there is no package relating to Google OAuth installed in the deps/ folder. This is what I see instead:
M1 2021-10-07 at 5 21 52 PM

Accumulate `timers`

At present when we stop a timer it disappears from the UI. 🤦‍♂️
Then when we start a new one it does not reflect the previous timers (if there are any) ...
This is obviously not the desired behaviour.
What we want is to:

  • Display time elapsed in UI when timer stopped. #106
  • Accumulate the time elapsed (timer.end - timer.start) for all previous timers
  • Subtract accumulated time from the current timer.start so that timers continue counting.

Seeds are not idempotent (duplicate status created)

Because there is no code to check if the status already exists in seeds.exs:
https://github.com/dwyl/app-mvp-phoenix/blob/4c96ce38ea935149257c879686abfb522b3e283b/priv/repo/seeds.exs#L1-L2

It's possible to have duplicate statusus:
image

When I run MIX_ENV=test mix ecto.reset
followed by mix test on my localhost I see this error:
image
Indicating that there are duplicate records for status being created.

@SimonLab can you help investigate tomorrow morning? (Thanks!) ✨

Environment Variables Required on localhost!

If you git clone [email protected]:dwyl/app-mvp-phoenix.git and attempt to mix deps.get
(or any other mix command) you will see the following error:

** (FunctionClauseError) no function clause matching in String.replace/4

image

Confusingly the error stack trace gives us zero indication where String.replace/4 is being invoked so if you were a complete beginner trying to run this code you definitely have a "WTF" moment!

This is because in config/config.exs#L31-L35 the ENCRYPTION_KEYS environment variable is required:

https://github.com/dwyl/app-mvp-phoenix/blob/a7f57a1f0002d6f2b7c5a97ed1d01883e9a4779e/config/config.exs#L31-L35

This is actually invoking String.replace/3 but if the ENCRYPTION_KEYS environment variable is not set, then System.get_env("ENCRYPTION_KEYS") will return nil which chokes the string replace.

image

At present the Run the app on localhost in the README.md is incomplete:
image
We need to provide people with more detailed instructions for getting the app running.
specifically we need an .env_sample file with all the environment variables necessary for running the app on Localhost. Similar to dwyl/elixir-auth-google-demo/.env_sample

Furthermore given that we are using elixir_auth_google for Google Auth:
https://github.com/dwyl/app-mvp-phoenix/blob/a7f57a1f0002d6f2b7c5a97ed1d01883e9a4779e/mix.exs#L52
We also need to have the Google GOOGLE_CLIENT_ID and GOOGLE_CLIENT_SECRET environment variables. This is not reflected in the README.md 🤷‍♂

Todo

  • Update instructions in README.md to include all required environment variables.

Add routes for API capture

To be able to test the capture feature (ie saving text in database) from dwyl/app#254 and https://github.com/dwyl/elm-pwa-example we need

  • the /api/capture endpoint which will receive a post request with json data text
{
  "capture": "capture text..."
}

The logic of the capture api endpoint will be similar to:
https://github.com/dwyl/app-mvp-phoenix/blob/d746db8bb33d874f6433550b865d47162b554fc6/lib/app_web/controllers/captures_controller.ex#L12-L22

We need to make sure the Ctx module can handle json

  • the /api/items/show endpoint which returns all the existing capture in a json format

https://github.com/dwyl/app-mvp-phoenix/blob/d746db8bb33d874f6433550b865d47162b554fc6/lib/app_web/controllers/item_controller.ex#L29-L32

Ecto.CastError: map with mixed keys

Ecto.CastError at POST /items
expected params to be a map with atoms or string keys, got a map with mixed keys: %{:person_id => 1, "text" => "test again"}

image

🙄

Should we restrict items to only be on one list or can an item be on multiple lists?

At present the code is setup such that a list can has_many :items
but an item can only has_one :list ...
This is operating under the assumption that an item can only be added/belong to one list.
Can we envisage a scenario where we would want to add an item to multiple lists?

For example:
would we want to add an item to the todo list of two different people?
or would we have a "shared" list whereby two (or more) people can view the same list?
ultimately an item can/should only be assigned to a single person for accountability,
but imagine two people were pair-programming on a feature,
we would want them to be able to start two independent timers related to the single item?
Or would we copy (make a duplicate) of the item?
I personally prefer the idea of being able to add the same (todo) item to the individual daily todo list of two separate people and allow them to both log time against that item.

Thoughts are very welcome on this.

Change people fields from binary to Field values

Our schema can use the Fields value instead of the default binary

  schema "people" do
    field :email, Fields.EmailEncrypted
    field :email_hash, Fields.EmailHash
    field :familyName, Fields.Encrypted
    field :givenName, Fields.Encrypted
    field :password_hash, Fields.Password
    field :username, Fields.Encrypted
    field :username_hash, Fields.Hash
    field :status, :id
    field :tag, :id
    field :key_id, :integer

    has_many :sessions, App.Ctx.Session
    timestamps()
  end

Error when Using Google Singin

an Internal Server Error is displayed when attempting to login with Google.
We don't have much more information on the server log on Heroku.
My first thought is to check that the callback url might not be defined to https://dwylapp.herokuapp.com/auth/google/callback on the Google application

@nelsonic when you have time can you check this value on the Application? Thanks

BUG: New Person inserted each time I authenticate with Google

Minor issue: the App.Ctx.get_person_by_email invoked in google_auth_controller.ex
does not do what we expect it to ...
https://github.com/dwyl/app-mvp-phoenix/blob/5a9a0fddb2d908de48b2b4de9853dbcaef63a0e5/lib/app_web/controllers/google_auth_controller.ex#L15

This is never going to work in a world where the email field is encrypted ...
(i.e. each time the email address [email protected] is encrypted/inserted the ciphertext is different ...)
https://github.com/dwyl/app-mvp-phoenix/blob/5a9a0fddb2d908de48b2b4de9853dbcaef63a0e5/lib/app/ctx.ex#L238

The result is that a new person record is inserted each time the person uses Google Auth:
image

🙄

Todo

  • Ensure that the people schema has field :email_hash, Fields.EmailHash defined
    • Confirm that all tests still pass after updating the field definition.
  • modify the App.Ctx.get_person_by_email/1 function to:
    • Use Fields.EmailHash.dump(email) to hash the email address before attempting to look it up.
    • Lookup an email by the email_hash not the email (Fields.EmailEncrypted)
def get_person_by_email(email) do
  email_hash = Fields.EmailHash.dump(email)
  Repo.get_by(Person, email_hash: email_hash)
end 

Insert Person following Auth

As part of the migration to auth_plug #65 we also need to insert the person into the database when the person has successfully authenticated. That means we need to either pass the App.Person.upsert_person function to auth_plug directly, or we need to inset the person as part of creating the first item ... 🤷

At the moment I'm leaning towards having a function that checks for a JWT in the URL query params
and upserts the person based on the JWT-verified data. 💭

Need to think about this a bit more. 🤔

image

 Ecto.ConstraintError at POST /items
constraint error when attempting to insert struct:

    * items_person_id_fkey (foreign_key_constraint)

Add excoveralls + Codecov to track test coverage

As a developer wanting to confirm that we don't have untested/unused code,
I want to track coverage for the project so that we know if things are on track.

This is a nice-to-have technical feature that only indirectly affects "users" further down the line.
We should work on this in our "down time" after the sprint is complete 👍

Upgrade Heroku App to Latest Stack

At the end of the Heroku Build log we see the following info:

       https://dwylapp.herokuapp.com/ deployed to Heroku
               _                  __ _  _     ______ ____  _
              | |                /_ | || |   |  ____/ __ \| |
   ___ ___  __| | __ _ _ __ ______| | || |_  | |__ | |  | | |
  / __/ _ \/ _` |/ _` | '__|______| |__   _| |  __|| |  | | |
 | (_|  __/ (_| | (_| | |         | |  | |   | |___| |__| | |____
  \___\___|\__,_|\__,_|_|         |_|  |_|   |______\____/|______|
This application is still using the Cedar-14 stack for which the end-of-life window began May 1, 2019:
https://devcenter.heroku.com/changelog-items/1603
The end-of-life window ends on May 1, 2020 after which Cedar-14 will no longer
receive security updates and Cedar-14 app builds will be disabled.
Please upgrade to the latest stack by following these instructions:
https://devcenter.heroku.com/articles/upgrading-to-the-latest-stack

Todo

This task should only be done when we have "down time" and are tidying up the stack.

`mix deps.get` crashes on new cloned project

  1. I cloned the repo
  2. I switched to the same version of elixir specified in the mix.exs file
  3. I tried to run mix deps.get
  4. I got ** (FunctionClauseError) no function clause matching in String.replace/4 along with an ugly crash

Entity Relationship (ER) Diagram

Having an Entity Relationship (ER) Diagram is really helpful for a beginner (anyone new to the project) to understand the Data in an app. See: "Categorising Items using Tags"
image

The last time the ER Diagram was updated was 3 months ago: ⏳
image

Meanwhile then the sessions table has been created but the ERD was not updated ...
Here is the updated diagram:
image

There is no effort to create an ER Diagram, simply export it from Dbeaver dwyl/learn-postgresql#43
image

Todo

  • Add the latest ER Diagram to the README.md

Add `auth_plug`

At present while we've been rebuilding the MVP we've avoided Authentication for speed.
But to be a useful MVP we need to have Auth so that people can "own" their own items.
Thankfully, we've comprehensively solved this problem before:
https://github.com/dwyl/phoenix-liveview-chat-example#12-authentication

Todo 📝

  • Borrow the code we've previously written.
  • Update the code in lib/app_web/live/app_live.ex
  • Update tests as necessary

Lotsa Warnings + Postgrex.Error 42P07 😕

While attempting to run the stock tests the app compilation fails:

Compiling 35 files (.ex)
warning: function AppWeb.Router.Helpers.item_path/2 is undefined or private. Did you mean one of:

      * page_path/2
      * page_path/3

Found at 6 locations:
  lib/app_web/controllers/item_controller.ex:60
  lib/app_web/templates/item/edit.html.eex:5
  lib/app_web/templates/item/index.html.eex:26
  lib/app_web/templates/item/new.html.eex:3
  lib/app_web/templates/item/new.html.eex:5
  lib/app_web/templates/item/show.html.eex:13

warning: function AppWeb.Router.Helpers.item_path/3 is undefined or private. Did you mean one of:

      * page_path/2
      * page_path/3

Found at 7 locations:
  lib/app_web/controllers/item_controller.ex:22
  lib/app_web/controllers/item_controller.ex:47
  lib/app_web/templates/item/edit.html.eex:3
  lib/app_web/templates/item/index.html.eex:17
  lib/app_web/templates/item/index.html.eex:18
  lib/app_web/templates/item/index.html.eex:19
  lib/app_web/templates/item/show.html.eex:12

warning: function AppWeb.Router.Helpers.kind_path/2 is undefined or private
Found at 6 locations:
  lib/app_web/controllers/kind_controller.ex:60
  lib/app_web/templates/kind/edit.html.eex:5
  lib/app_web/templates/kind/index.html.eex:26
  lib/app_web/templates/kind/new.html.eex:3
  lib/app_web/templates/kind/new.html.eex:5
  lib/app_web/templates/kind/show.html.eex:13

warning: function AppWeb.Router.Helpers.kind_path/3 is undefined or private
Found at 7 locations:
  lib/app_web/controllers/kind_controller.ex:22
  lib/app_web/controllers/kind_controller.ex:47
  lib/app_web/templates/kind/edit.html.eex:3
  lib/app_web/templates/kind/index.html.eex:17
  lib/app_web/templates/kind/index.html.eex:18
  lib/app_web/templates/kind/index.html.eex:19
  lib/app_web/templates/kind/show.html.eex:12

warning: function AppWeb.Router.Helpers.list_path/2 is undefined or private. Did you mean one of:

      * static_path/2

Found at 6 locations:
  lib/app_web/controllers/list_controller.ex:60
  lib/app_web/templates/list/edit.html.eex:5
  lib/app_web/templates/list/index.html.eex:26
  lib/app_web/templates/list/new.html.eex:3
  lib/app_web/templates/list/new.html.eex:5
  lib/app_web/templates/list/show.html.eex:13

warning: function AppWeb.Router.Helpers.list_path/3 is undefined or private. Did you mean one of:

      * static_path/2

Found at 7 locations:
  lib/app_web/controllers/list_controller.ex:22
  lib/app_web/controllers/list_controller.ex:47
  lib/app_web/templates/list/edit.html.eex:3
  lib/app_web/templates/list/index.html.eex:17
  lib/app_web/templates/list/index.html.eex:18
  lib/app_web/templates/list/index.html.eex:19
  lib/app_web/templates/list/show.html.eex:12

warning: function AppWeb.Router.Helpers.person_path/2 is undefined or private. Did you mean one of:

      * page_path/2
      * page_path/3

Found at 6 locations:
  lib/app_web/controllers/person_controller.ex:60
  lib/app_web/templates/person/edit.html.eex:5
  lib/app_web/templates/person/index.html.eex:40
  lib/app_web/templates/person/new.html.eex:3
  lib/app_web/templates/person/new.html.eex:5
  lib/app_web/templates/person/show.html.eex:48

warning: function AppWeb.Router.Helpers.person_path/3 is undefined or private. Did you mean one of:

      * page_path/2
      * page_path/3

Found at 7 locations:
  lib/app_web/controllers/person_controller.ex:22
  lib/app_web/controllers/person_controller.ex:47
  lib/app_web/templates/person/edit.html.eex:3
  lib/app_web/templates/person/index.html.eex:31
  lib/app_web/templates/person/index.html.eex:32
  lib/app_web/templates/person/index.html.eex:33
  lib/app_web/templates/person/show.html.eex:47

warning: function AppWeb.Router.Helpers.status_path/2 is undefined or private. Did you mean one of:

      * static_path/2

Found at 6 locations:
  lib/app_web/controllers/status_controller.ex:60
  lib/app_web/templates/status/edit.html.eex:5
  lib/app_web/templates/status/index.html.eex:26
  lib/app_web/templates/status/new.html.eex:3
  lib/app_web/templates/status/new.html.eex:5
  lib/app_web/templates/status/show.html.eex:13

warning: function AppWeb.Router.Helpers.status_path/3 is undefined or private. Did you mean one of:

      * static_path/2

Found at 7 locations:
  lib/app_web/controllers/status_controller.ex:22
  lib/app_web/controllers/status_controller.ex:47
  lib/app_web/templates/status/edit.html.eex:3
  lib/app_web/templates/status/index.html.eex:17
  lib/app_web/templates/status/index.html.eex:18
  lib/app_web/templates/status/index.html.eex:19
  lib/app_web/templates/status/show.html.eex:12

warning: function AppWeb.Router.Helpers.timer_path/2 is undefined or private. Did you mean one of:

      * static_path/2

Found at 6 locations:
  lib/app_web/controllers/timer_controller.ex:60
  lib/app_web/templates/timer/edit.html.eex:5
  lib/app_web/templates/timer/index.html.eex:28
  lib/app_web/templates/timer/new.html.eex:3
  lib/app_web/templates/timer/new.html.eex:5
  lib/app_web/templates/timer/show.html.eex:18

warning: function AppWeb.Router.Helpers.timer_path/3 is undefined or private. Did you mean one of:

      * static_path/2

Found at 7 locations:
  lib/app_web/controllers/timer_controller.ex:22
  lib/app_web/controllers/timer_controller.ex:47
  lib/app_web/templates/timer/edit.html.eex:3
  lib/app_web/templates/timer/index.html.eex:19
  lib/app_web/templates/timer/index.html.eex:20
  lib/app_web/templates/timer/index.html.eex:21
  lib/app_web/templates/timer/show.html.eex:17

Generated app app
** (Postgrex.Error) ERROR 42P07 (duplicate_table) relation "kinds" already exists
    (ecto_sql) lib/ecto/adapters/sql.ex:629: Ecto.Adapters.SQL.raise_sql_call_error/1
    (elixir) lib/enum.ex:1336: Enum."-map/2-lists^map/1-0-"/2
    (ecto_sql) lib/ecto/adapters/sql.ex:716: Ecto.Adapters.SQL.execute_ddl/4
    (ecto_sql) lib/ecto/migration/runner.ex:338: Ecto.Migration.Runner.log_and_execute_ddl/3
    (ecto_sql) lib/ecto/migration/runner.ex:117: anonymous fn/6 in Ecto.Migration.Runner.flush/0
    (elixir) lib/enum.ex:1948: Enum."-reduce/3-lists^foldl/2-0-"/3
    (ecto_sql) lib/ecto/migration/runner.ex:116: Ecto.Migration.Runner.flush/0
    (stdlib) timer.erl:166: :timer.tc/1

Going to debug it but wanted to open an issue to log my progress first. 👍

Transfer to @dwyl

I want to add issues from this repo to my @dwyl list github.com/orgs/dwyl/projects/11
For that I need to transfer the repo to @dwyl ...

Note: I don't think this is anywhere near "alpha" I still want to tidy up quite a lot!
But by moving it to @dwyl others might be more inclined to colab/comment on the issues
and then there's no question about who "owns" the repo #2 ...

Why?

Why? 🤷‍♂️

I built the "original" MVP in ("Vanilla") JavaScript without any frameworks and using just "core" Node.js + PostgreSQL: https://github.com/nelsonic/time-mvp it worked and allowed me to showcase the MVP functionality. It was good practice writing the bare minimum code but it was not easy to extend and the tests left a lot to be desired. 🙄I consider that MVP very "rough" and not a good example for others to follow. It's more of a "hackathon" to get something to show others and use myself.

I feel that I can do much better in Phoenix and can even result in some re-useable code!

What? 💭

A tutorial/example of building a basic but functional Pomodoro Timer in Phoenix.

How? 🚧

Let's get to it!

Add UI Icons to Buttons

Definitely not high priority but a super-nice-to-have for aesthetics.
Use: https://www.flaticon.com/uicons
Borrow from: https://postsrc.com/components/buttons/button-with-icon

example:

<button class="inline-flex items-center px-4 py-2 mr-2
 bg-gray-200 hover:bg-gray-300 text-gray-800 rounded-md"
  phx-click="delete" phx-value-id={item.id}>
	<svg xmlns="http://www.w3.org/2000/svg" 
    class="h-5 w-5 mr-2" fill="none" 
    viewBox="0 0 24 24" stroke="currentColor">
	  <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" 
      d="M5 8h14M5 8a2 2 0 110-4h14a2 2 0 110 4M5 8v10a2 2 0 002 2h10a2 2 0 002-2V8m-9 4h4" />
	</svg>
  Archive
</button>

Which outputs:

image

The hard part is to select the appropriate icon for each situation:

  • Save
  • Start
  • Stop
  • Archive

Todo

  • Get feedback on icons from @iteles

mix setup fail

Running mix setup fails:
image

I think this might be linked to the following commit change: 0fd80f1

I'm going to look how to fix the setup command

Elm PWA on Capture page

ref: dwyl/app#254
At the moment the capture page is displayed with Phoenix template. To test PWA we can create an simple Elm app which will allow the user to capture the text via Elm.

  • Create a Browser.element application which will compiled and bundle to the main app.js script file

  • Nest this application on a specific elm capture page

  • Send post request to the api endpoint (see #53) to save the text

Once this checkbox for the main structure of the Elm nested app have been implemented we can enhance the application by adding offline feature with PWA

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.