Skip to content

Commit

Permalink
notes: use utc timestamp in db and use indian time on application layer
Browse files Browse the repository at this point in the history
  • Loading branch information
aayushmau5 committed May 17, 2024
1 parent 5503ea2 commit 3d2d6d2
Show file tree
Hide file tree
Showing 8 changed files with 102 additions and 67 deletions.
3 changes: 3 additions & 0 deletions config/config.exs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@
# General application configuration
import Config

# Timezone config
config :elixir, :time_zone_database, TimeZoneInfo.TimeZoneDatabase

# Configures the endpoint
config :accumulator, AccumulatorWeb.Endpoint,
url: [host: "localhost"],
Expand Down
75 changes: 33 additions & 42 deletions lib/accumulator/notes.ex
Original file line number Diff line number Diff line change
Expand Up @@ -3,42 +3,35 @@ defmodule Accumulator.Notes do
alias Accumulator.Repo
import Ecto.Query

@timezone "Asia/Kolkata"

def get_note_by_id(id) do
Repo.get(Note, id)
Repo.get!(Note, id)
end

def get_notes_grouped_and_ordered_by_date(workspace_id, ending_date) do
date_tuple = ending_date |> Date.add(1) |> Date.to_erl()

ending_date_time =
NaiveDateTime.from_erl!({date_tuple, {0, 0, 0}}) |> NaiveDateTime.truncate(:second)

starting_date_time =
NaiveDateTime.add(ending_date_time, -10, :day) |> NaiveDateTime.truncate(:second)
def get_notes_grouped_and_ordered_by_date(workspace_id, ending_datetime) do
ending_datetime = ending_datetime |> DateTime.add(1)
starting_datetime = DateTime.add(ending_datetime, -10, :day)

# [ [date, [notes]], [date, [notes]] ]
# TODO: think about how to store date
result =
from(n in Note,
where: n.inserted_at >= ^starting_date_time,
where: n.inserted_at <= ^ending_date_time,
where: n.inserted_at >= ^starting_datetime,
where: n.inserted_at <= ^ending_datetime,
where: n.workspace_id == ^workspace_id,
order_by: [asc: n.id]
)
|> Repo.all()
|> group_and_sort_notes()

{result, NaiveDateTime.to_date(starting_date_time)}
{result, starting_datetime}
end

def get_notes_grouped_and_ordered_till_date(workspace_id, date) do
date_tuple = date |> Date.add(1) |> Date.to_erl()

date =
NaiveDateTime.from_erl!({date_tuple, {0, 0, 0}}) |> NaiveDateTime.truncate(:second)
def get_notes_grouped_and_ordered_till_date(workspace_id, datetime) do
datetime = datetime |> DateTime.add(1)

from(n in Note,
where: n.inserted_at >= ^date,
where: n.inserted_at >= ^datetime,
where: n.workspace_id == ^workspace_id,
order_by: [asc: n.id]
)
Expand All @@ -61,7 +54,7 @@ defmodule Accumulator.Notes do
end

def delete_note(id) do
Repo.get!(Note, id)
get_note_by_id(id)
|> Repo.delete()
end

Expand All @@ -79,25 +72,22 @@ defmodule Accumulator.Notes do

defp group_and_sort_notes(notes) do
notes
|> Enum.map(&convert_timestamps_tz/1)
|> Enum.group_by(fn %{inserted_at: inserted_at} ->
inserted_at |> NaiveDateTime.to_date() |> Date.to_string()
inserted_at |> DateTime.to_date() |> Date.to_string()
end)
|> Enum.map(fn {date, notes} -> [date, notes] end)
|> Enum.sort_by(fn [date, _] -> date end)
end

# Workspace stuff

# TODOs:
# Handling pagination in workspace through dates while getting notes in a workspace

def get_all_workspaces() do
Repo.all(Workspace)
Repo.all(Workspace) |> Enum.map(&convert_timestamps_tz/1)
end

def get_workspace_by_id(id) do
# Workspace or nil
Repo.get(Workspace, id)
Repo.get!(Workspace, id)
end

def create_new_workspace(params) do
Expand All @@ -112,13 +102,7 @@ defmodule Accumulator.Notes do
end

def delete_workspace(id) do
case get_workspace_by_id(id) do
nil ->
nil

workspace ->
Repo.delete(workspace)
end
get_workspace_by_id(id) |> Repo.delete()
end

def create_note(workspace_id, note_params) do
Expand All @@ -134,14 +118,21 @@ defmodule Accumulator.Notes do
|> Repo.update()
end

def get_notes_in_workspace(workspace_id) do
from(n in Note, where: n.workspace_id == ^workspace_id, order_by: [asc: n.id])
|> Repo.all()
defp convert_timestamps_tz(map) do
map
|> Map.update!(:inserted_at, fn utc_timestamp ->
DateTime.shift_zone!(utc_timestamp, @timezone)
end)
|> Map.update!(:updated_at, fn utc_timestamp ->
DateTime.shift_zone!(utc_timestamp, @timezone)
end)
end

# def assign_default_workspace_to_every_note() do
# from(n in Note, where: is_nil(n.workspace_id))
# |> Repo.all()
# |> Enum.map(fn n -> Note.changeset(n, %{workspace_id: 4}) |> Repo.update!() end)
# end
def get_utc_datetime_from_date(date \\ Date.utc_today()) do
date_tuple = date |> Date.to_erl()

NaiveDateTime.from_erl!({date_tuple, {0, 0, 0}})
|> NaiveDateTime.add(1, :day)
|> DateTime.from_naive!("Etc/UTC")
end
end
2 changes: 1 addition & 1 deletion lib/accumulator/notes/note.ex
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ defmodule Accumulator.Notes.Note do
schema "notes" do
field(:text, :string)
belongs_to(:workspace, Accumulator.Notes.Workspace)
timestamps()
timestamps(type: :utc_datetime)
end

def changeset(note, params \\ %{}) do
Expand Down
2 changes: 1 addition & 1 deletion lib/accumulator/notes/workspace.ex
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ defmodule Accumulator.Notes.Workspace do
schema "workspaces" do
field(:title, :string)
has_many(:notes, Accumulator.Notes.Note)
timestamps()
timestamps(type: :utc_datetime)
end

def changeset(workspace, params \\ %{}) do
Expand Down
55 changes: 33 additions & 22 deletions lib/accumulator_web/live/notes_live/notes_live.ex
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,11 @@ defmodule AccumulatorWeb.NotesLive do
workspaces = Notes.get_all_workspaces()
default_workspace = get_default_workspace(workspaces)

start_date = Date.utc_today()

{notes, pagination_date} =
Notes.get_notes_grouped_and_ordered_by_date(default_workspace.id, start_date)
Notes.get_notes_grouped_and_ordered_by_date(
default_workspace.id,
Notes.get_utc_datetime_from_date()
)

socket
|> stream_configure(:notes, dom_id: &Enum.at(&1, 0))
Expand Down Expand Up @@ -68,7 +69,11 @@ defmodule AccumulatorWeb.NotesLive do
socket =
case Notes.insert(note_changeset) do
{:ok, _note} ->
{notes, _} = Notes.get_notes_grouped_and_ordered_by_date(workspace_id, Date.utc_today())
{notes, _} =
Notes.get_notes_grouped_and_ordered_by_date(
workspace_id,
Notes.get_utc_datetime_from_date()
)

socket
|> assign(form: empty_form())
Expand Down Expand Up @@ -122,7 +127,10 @@ defmodule AccumulatorWeb.NotesLive do
with {:ok, _} <- Notes.update_note(note_id, note_params),
:ok <- update_note_workspace(note_id, new_workspace_id) do
{notes, _} =
Notes.get_notes_grouped_and_ordered_by_date(workspace_id, Date.utc_today())
Notes.get_notes_grouped_and_ordered_by_date(
workspace_id,
Notes.get_utc_datetime_from_date()
)

socket
|> stream(:notes, notes, reset: true)
Expand Down Expand Up @@ -166,7 +174,10 @@ defmodule AccumulatorWeb.NotesLive do
socket |> stream(:notes, notes, reset: true) |> push_event("new-note-scroll", %{})
else
{notes, pagination_date} =
Notes.get_notes_grouped_and_ordered_by_date(workspace_id, Date.utc_today())
Notes.get_notes_grouped_and_ordered_by_date(
workspace_id,
Notes.get_utc_datetime_from_date()
)

socket
|> stream(:notes, notes, reset: true)
Expand All @@ -183,7 +194,10 @@ defmodule AccumulatorWeb.NotesLive do
workspace = Notes.get_workspace_by_id(id)

{notes, pagination_date} =
Notes.get_notes_grouped_and_ordered_by_date(workspace.id, Date.utc_today())
Notes.get_notes_grouped_and_ordered_by_date(
workspace.id,
Notes.get_utc_datetime_from_date()
)

socket =
socket
Expand All @@ -210,22 +224,16 @@ defmodule AccumulatorWeb.NotesLive do
end

def handle_event("edit-workspace", %{"id" => id} = _params, socket) do
workspace = Notes.get_workspace_by_id(id)
workspace_form = Notes.get_workspace_by_id(id) |> Workspace.changeset() |> to_form()

socket =
if workspace != nil do
workspace_form = workspace |> Workspace.changeset() |> to_form()

socket
|> assign(workspace_edit_id: id)
|> assign(workspace_form: workspace_form)
|> push_event("notes-workspace-modal", %{
modal_id: "workspace-modal",
attr: "data-show-modal"
})
else
socket
end
socket
|> assign(workspace_edit_id: id)
|> assign(workspace_form: workspace_form)
|> push_event("notes-workspace-modal", %{
modal_id: "workspace-modal",
attr: "data-show-modal"
})

{:noreply, socket}
end
Expand Down Expand Up @@ -306,7 +314,10 @@ defmodule AccumulatorWeb.NotesLive do
workspace = get_default_workspace(socket.assigns.workspaces)

{notes, pagination_date} =
Notes.get_notes_grouped_and_ordered_by_date(workspace.id, Date.utc_today())
Notes.get_notes_grouped_and_ordered_by_date(
workspace.id,
Notes.get_utc_datetime_from_date()
)

socket =
socket
Expand Down
3 changes: 2 additions & 1 deletion mix.exs
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,8 @@ defmodule Accumulator.MixProject do
{:resend, "~> 0.4.1"},
{:ecto_psql_extras, "~> 0.6"},
{:libcluster, "~> 3.3"},
{:earmark, "~> 1.4"}
{:earmark, "~> 1.4"},
{:time_zone_info, "~> 0.7"}
]
end

Expand Down
2 changes: 2 additions & 0 deletions mix.lock
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
"mint": {:hex, :mint, "1.6.0", "88a4f91cd690508a04ff1c3e28952f322528934be541844d54e0ceb765f01d5e", [:mix], [{:castore, "~> 0.1.0 or ~> 1.0", [hex: :castore, repo: "hexpm", optional: true]}, {:hpax, "~> 0.1.1 or ~> 0.2.0", [hex: :hpax, repo: "hexpm", optional: false]}], "hexpm", "3c5ae85d90a5aca0a49c0d8b67360bbe407f3b54f1030a111047ff988e8fefaa"},
"nimble_options": {:hex, :nimble_options, "1.1.0", "3b31a57ede9cb1502071fade751ab0c7b8dbe75a9a4c2b5bbb0943a690b63172", [:mix], [], "hexpm", "8bbbb3941af3ca9acc7835f5655ea062111c9c27bcac53e004460dfd19008a99"},
"nimble_ownership": {:hex, :nimble_ownership, "0.3.1", "99d5244672fafdfac89bfad3d3ab8f0d367603ce1dc4855f86a1c75008bce56f", [:mix], [], "hexpm", "4bf510adedff0449a1d6e200e43e57a814794c8b5b6439071274d248d272a549"},
"nimble_parsec": {:hex, :nimble_parsec, "1.4.0", "51f9b613ea62cfa97b25ccc2c1b4216e81df970acd8e16e8d1bdc58fef21370d", [:mix], [], "hexpm", "9c565862810fb383e9838c1dd2d7d2c437b3d13b267414ba6af33e50d2d1cf28"},
"nimble_pool": {:hex, :nimble_pool, "1.1.0", "bf9c29fbdcba3564a8b800d1eeb5a3c58f36e1e11d7b7fb2e084a643f645f06b", [:mix], [], "hexpm", "af2e4e6b34197db81f7aad230c1118eac993acc0dae6bc83bac0126d4ae0813a"},
"parse_trans": {:hex, :parse_trans, "3.4.1", "6e6aa8167cb44cc8f39441d05193be6e6f4e7c2946cb2759f015f8c56b76e5ff", [:rebar3], [], "hexpm", "620a406ce75dada827b82e453c19cf06776be266f5a67cff34e1ef2cbb60e49a"},
"phoenix": {:hex, :phoenix, "1.7.12", "1cc589e0eab99f593a8aa38ec45f15d25297dd6187ee801c8de8947090b5a9d3", [:mix], [{:castore, ">= 0.0.0", [hex: :castore, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:phoenix_pubsub, "~> 2.1", [hex: :phoenix_pubsub, repo: "hexpm", optional: false]}, {:phoenix_template, "~> 1.0", [hex: :phoenix_template, repo: "hexpm", optional: false]}, {:phoenix_view, "~> 2.0", [hex: :phoenix_view, repo: "hexpm", optional: true]}, {:plug, "~> 1.14", [hex: :plug, repo: "hexpm", optional: false]}, {:plug_cowboy, "~> 2.7", [hex: :plug_cowboy, repo: "hexpm", optional: true]}, {:plug_crypto, "~> 1.2 or ~> 2.0", [hex: :plug_crypto, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}, {:websock_adapter, "~> 0.5.3", [hex: :websock_adapter, repo: "hexpm", optional: false]}], "hexpm", "d646192fbade9f485b01bc9920c139bfdd19d0f8df3d73fd8eaf2dfbe0d2837c"},
Expand All @@ -56,6 +57,7 @@
"telemetry_metrics": {:hex, :telemetry_metrics, "0.6.2", "2caabe9344ec17eafe5403304771c3539f3b6e2f7fb6a6f602558c825d0d0bfb", [:mix], [{:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "9b43db0dc33863930b9ef9d27137e78974756f5f198cae18409970ed6fa5b561"},
"telemetry_poller": {:hex, :telemetry_poller, "1.1.0", "58fa7c216257291caaf8d05678c8d01bd45f4bdbc1286838a28c4bb62ef32999", [:rebar3], [{:telemetry, "~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "9eb9d9cbfd81cbd7cdd24682f8711b6e2b691289a0de6826e58452f28c103c8f"},
"tesla": {:hex, :tesla, "1.9.0", "8c22db6a826e56a087eeb8cdef56889731287f53feeb3f361dec5d4c8efb6f14", [:mix], [{:castore, "~> 0.1 or ~> 1.0", [hex: :castore, repo: "hexpm", optional: true]}, {:exjsx, ">= 3.0.0", [hex: :exjsx, repo: "hexpm", optional: true]}, {:finch, "~> 0.13", [hex: :finch, repo: "hexpm", optional: true]}, {:fuse, "~> 2.4", [hex: :fuse, repo: "hexpm", optional: true]}, {:gun, ">= 1.0.0", [hex: :gun, repo: "hexpm", optional: true]}, {:hackney, "~> 1.6", [hex: :hackney, repo: "hexpm", optional: true]}, {:ibrowse, "4.4.2", [hex: :ibrowse, repo: "hexpm", optional: true]}, {:jason, ">= 1.0.0", [hex: :jason, repo: "hexpm", optional: true]}, {:mime, "~> 1.0 or ~> 2.0", [hex: :mime, repo: "hexpm", optional: false]}, {:mint, "~> 1.0", [hex: :mint, repo: "hexpm", optional: true]}, {:msgpax, "~> 2.3", [hex: :msgpax, repo: "hexpm", optional: true]}, {:poison, ">= 1.0.0", [hex: :poison, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: true]}], "hexpm", "7c240c67e855f7e63e795bf16d6b3f5115a81d1f44b7fe4eadbf656bae0fef8a"},
"time_zone_info": {:hex, :time_zone_info, "0.7.3", "ab0ca1c249aef55794b3a71a9ba7184121f99436410f35a2525f67035c86c899", [:mix], [{:castore, "~> 1.0", [hex: :castore, repo: "hexpm", optional: true]}, {:mint, "~> 1.0", [hex: :mint, repo: "hexpm", optional: true]}, {:nimble_parsec, "~> 1.3", [hex: :nimble_parsec, repo: "hexpm", optional: false]}], "hexpm", "7a549c7db4c7c1bd0fcac7dc8417c0b52a619950b0f495f4fb7c69a5302d1368"},
"unicode_util_compat": {:hex, :unicode_util_compat, "0.7.0", "bc84380c9ab48177092f43ac89e4dfa2c6d62b40b8bd132b1059ecc7232f9a78", [:rebar3], [], "hexpm", "25eee6d67df61960cf6a794239566599b09e17e668d3700247bc498638152521"},
"websock": {:hex, :websock, "0.5.3", "2f69a6ebe810328555b6fe5c831a851f485e303a7c8ce6c5f675abeb20ebdadc", [:mix], [], "hexpm", "6105453d7fac22c712ad66fab1d45abdf049868f253cf719b625151460b8b453"},
"websock_adapter": {:hex, :websock_adapter, "0.5.6", "0437fe56e093fd4ac422de33bf8fc89f7bc1416a3f2d732d8b2c8fd54792fe60", [:mix], [{:bandit, ">= 0.6.0", [hex: :bandit, repo: "hexpm", optional: true]}, {:plug, "~> 1.14", [hex: :plug, repo: "hexpm", optional: false]}, {:plug_cowboy, "~> 2.6", [hex: :plug_cowboy, repo: "hexpm", optional: true]}, {:websock, "~> 0.5", [hex: :websock, repo: "hexpm", optional: false]}], "hexpm", "e04378d26b0af627817ae84c92083b7e97aca3121196679b73c73b99d0d133ea"},
Expand Down
27 changes: 27 additions & 0 deletions priv/repo/migrations/20240515175433_notes_timezone.exs
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
defmodule Accumulator.Repo.Migrations.NotesTimezone do
use Ecto.Migration

def change do
alter table(:workspaces) do
modify(:inserted_at, :utc_datetime)
modify(:updated_at, :utc_datetime)
end

alter table(:notes) do
modify(:inserted_at, :utc_datetime)
modify(:updated_at, :utc_datetime)
end
end

def down() do
alter table(:workspaces) do
modify(:inserted_at, :naive_datetime)
modify(:updated_at, :naive_datetime)
end

alter table(:notes) do
modify(:inserted_at, :naive_datetime)
modify(:updated_at, :naive_datetime)
end
end
end

0 comments on commit 3d2d6d2

Please sign in to comment.