Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Removed otp version #18

Merged
merged 5 commits into from
Aug 4, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15,550 changes: 15,550 additions & 0 deletions .elixir-tools/next-ls.log

Large diffs are not rendered by default.

9 changes: 8 additions & 1 deletion .github/workflows/check-format-and-test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,18 @@ jobs:
uses: actions/checkout@v3

- name: Set up Elixir
uses: erlef/setup-elixir@v2
uses: erlef/setup-elixir@v1
with:
elixir-version: '1.14'
otp-version: '25'

- name: Debug Environment
run: |
mix --version
elixir --version
# Remove the otp command, as it does not exist
env

- name: Install dependencies
run: mix deps.get

Expand Down
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -35,3 +35,6 @@ polly-*.tar
npm-debug.log
/assets/node_modules/

.elixir_ls/
*.plt
credo_report/
4 changes: 4 additions & 0 deletions config/dev.exs
Original file line number Diff line number Diff line change
Expand Up @@ -67,3 +67,7 @@ config :phoenix, :plug_init_mode, :runtime

# Disable swoosh api client as it is only required for production adapters.
config :swoosh, :api_client, false

config :polly, PollyWeb.Endpoint,
http: [port: 4000],
server: true
73 changes: 48 additions & 25 deletions lib/polly/polls.ex
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ defmodule Polly.Polls do
@moduledoc """
This module holds functions related to CRUD operations for Polls
"""
alias Polly.Schema.Poll
alias Polly.Schema.{Poll}

@spec list_polls() :: [Poll.t()]
def list_polls() do
Expand All @@ -19,6 +19,15 @@ defmodule Polly.Polls do
end
end

def has_option?(poll_id, option_id) do
poll_id
|> Polly.PollsManager.get_poll!(false)
|> Map.fetch!(:options)
|> Enum.any?(fn option ->
option.id == option_id
end)
end

@spec get_poll!(binary()) :: Poll.t()
def get_poll!(id) do
Polly.PollsManager.get_poll_simple!(id)
Expand All @@ -31,34 +40,48 @@ defmodule Polly.Polls do
|> do_create_poll()
end

defp do_create_poll({:ok, %Poll{} = poll}) do
:ok = Polly.PollsManager.add_poll(poll)
{:ok, poll}
end
def create_poll(params) do
%Poll{}
|> Poll.changeset(params)
|> apply_action(:insert)
|> case do
{:ok, poll} ->
PollsManager.add_poll(poll)
{:ok, poll}

defp do_create_poll({:error, changeset}) do
{:error, changeset}
{:error, changeset} ->
{:error, changeset}
end
end
end

@spec update_poll(Poll.t(), map()) :: {:ok, Poll.t()} | {:error, Ecto.Changeset.t()}
def update_poll(%Poll{} = poll, attrs) do
poll
|> Poll.changeset(attrs)
|> Ecto.Changeset.apply_action(:update)
|> do_update_poll(poll)
end
defp do_create_poll({:ok, %Poll{} = poll}) do
:ok = Polly.PollsManager.add_poll(poll)
{:ok, poll}
end

defp do_update_poll({:ok, %Poll{} = updated_poll}, _poll) do
:ok = Polly.PollsManager.update_poll(updated_poll)
{:ok, updated_poll}
end
defp do_create_poll({:error, changeset}) do
{:error, changeset}
end

defp do_update_poll({:error, changeset}, _poll) do
{:error, changeset}
end
@spec update_poll(Poll.t(), map()) :: {:ok, Poll.t()} | {:error, Ecto.Changeset.t()}
def update_poll(%Poll{} = poll, attrs) do
poll
|> Poll.changeset(attrs)
|> Ecto.Changeset.apply_action(:update)
|> do_update_poll(poll)
end

@spec change_poll(Poll.t(), map()) :: Ecto.Changeset.t()
def change_poll(%Poll{} = poll, attrs \\ %{}) do
Poll.changeset(poll, attrs)
end
defp do_update_poll({:ok, %Poll{} = updated_poll}, _poll) do
:ok = Polly.PollsManager.update_poll(updated_poll.id, updated_poll)
{:ok, updated_poll}
end

defp do_update_poll({:error, changeset}, _poll) do
{:error, changeset}
end

@spec change_poll(Poll.t(), map()) :: Ecto.Changeset.t()
def change_poll(%Poll{} = poll, attrs \\ %{}) do
Poll.changeset(poll, attrs)
end
18 changes: 9 additions & 9 deletions lib/polly/polls_manager.ex
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ defmodule Polly.PollsManager do
# alias Polly.StorageBehaviour

@storage_module Application.compile_env(:polly, :storage_module, Polly.ETSStorage)

def init() do
@storage_module.init()
end
Expand Down Expand Up @@ -31,9 +32,14 @@ defmodule Polly.PollsManager do

@spec get_poll!(binary(), boolean()) :: Poll.t()
def get_poll!(poll_id, with_option_votes \\ false) do
@storage_module.get_poll!(poll_id, with_option_votes)
|> Map.replace(:total_votes, get_poll_votes!(poll_id))
|> replace_option_votes(with_option_votes)
case @storage_module.get_poll!(poll_id, with_option_votes) do
nil ->
raise ArgumentError, message: "Poll with ID #{poll_id} not found"

poll ->
Map.replace(poll, :total_votes, get_poll_votes!(poll_id))
|> replace_option_votes(with_option_votes)
end
end

@spec get_poll_simple!(binary()) :: Poll.t()
Expand Down Expand Up @@ -84,10 +90,4 @@ defmodule Polly.PollsManager do
def change_poll(%Poll{} = poll, attrs \\ %{}) do
Poll.changeset(poll, attrs)
end


@spec update_poll(Poll.t()) :: :ok | {:error, any()}
def update_poll(%Poll{} = _poll) do
# Your ETS or other storage logic to update the poll
end
end
10 changes: 4 additions & 6 deletions lib/polly/schema/poll.ex
Original file line number Diff line number Diff line change
Expand Up @@ -46,10 +46,8 @@ defmodule Polly.Schema.Poll do
changeset
end

# def changeset(poll, attrs) do
# poll
# |> cast(attrs, [:title, :description])
# |> validate_required([:title, :description])
# end
# defstruct title: nil, options: [], total_votes: 0, created_at: nil
@spec has_option?(t(), binary()) :: boolean()
def has_option?(%Poll{options: options}, option_id) do
Enum.any?(options, fn option -> option.id == option_id end)
end
end
1 change: 0 additions & 1 deletion lib/polly/storage/behaviour.ex
Original file line number Diff line number Diff line change
Expand Up @@ -11,5 +11,4 @@ defmodule Polly.StorageBehaviour do
@callback safe_lookup_element(binary()) :: integer()
@callback update_poll(binary(), Poll.t()) :: :ok | {:error, atom()}
# @callback replace_option_votes(Poll.t(), boolean()) :: Poll.t()

end
46 changes: 40 additions & 6 deletions lib/polly/storage/ets_storage.ex
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,21 @@ defmodule Polly.ETSStorage do
@impl Polly.StorageBehaviour
def init() do
:ets.new(@polls, [:public, :named_table, write_concurrency: true, read_concurrency: true])
:ets.new(@polls_votes, [:public, :named_table, write_concurrency: true, read_concurrency: true])
:ets.new(@polls_options_votes, [:public, :named_table, write_concurrency: true, read_concurrency: true])

:ets.new(@polls_votes, [
:public,
:named_table,
write_concurrency: true,
read_concurrency: true
])

:ets.new(@polls_options_votes, [
:public,
:named_table,
write_concurrency: true,
read_concurrency: true
])

:ok
end

Expand Down Expand Up @@ -46,21 +59,31 @@ defmodule Polly.ETSStorage do

@impl Polly.StorageBehaviour
def get_poll!(poll_id, with_option_votes \\ false) do
:ets.lookup_element(@polls, poll_id, 2)
|> Map.replace(:total_votes, get_poll_votes!(poll_id))
|> replace_option_votes(with_option_votes)
case :ets.lookup(@polls, poll_id) do
[{^poll_id, poll}] ->
poll
|> Map.replace(:total_votes, get_poll_votes!(poll_id))
|> replace_option_votes(with_option_votes)

[] ->
nil
end
end

@impl Polly.StorageBehaviour
def get_poll_votes!(poll_id) do
:ets.lookup_element(@polls_votes, poll_id, 2)
case :ets.lookup(@polls_votes, poll_id) do
[{^poll_id, votes}] -> votes
[] -> 0
end
end

def replace_option_votes(poll, true) do
updated_options =
Enum.map(poll.options, fn option ->
Map.replace(option, :votes, safe_lookup_element(option.id))
end)

Map.replace(poll, :options, updated_options)
end

Expand Down Expand Up @@ -93,4 +116,15 @@ defmodule Polly.ETSStorage do
{:error, :poll_not_found}
end
end

def poll_exists?(poll_id) do
case :ets.lookup(@polls, poll_id) do
[{^poll_id, _poll}] -> true
_ -> false
end
end

def list_all_polls do
:ets.tab2list(@polls)
end
end
27 changes: 19 additions & 8 deletions lib/polly_web/components/core_components.ex
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@ defmodule PollyWeb.CoreComponents do
<.icon name="hero-x-mark-solid" class="h-5 w-5" />
</button>
</div>

<div id={"#{@id}-content"}>
<%= render_slot(@inner_block) %>
</div>
Expand Down Expand Up @@ -121,10 +122,11 @@ defmodule PollyWeb.CoreComponents do
>
<p :if={@title} class="flex items-center gap-1.5 text-sm font-semibold leading-6">
<.icon :if={@kind == :info} name="hero-information-circle-mini" class="h-4 w-4" />
<.icon :if={@kind == :error} name="hero-exclamation-circle-mini" class="h-4 w-4" />
<%= @title %>
<.icon :if={@kind == :error} name="hero-exclamation-circle-mini" class="h-4 w-4" /> <%= @title %>
</p>

<p class="mt-2 text-sm leading-5"><%= msg %></p>

<button type="button" class="group absolute top-1 right-1 p-2" aria-label={gettext("close")}>
<.icon name="hero-x-mark-solid" class="h-5 w-5 opacity-40 group-hover:opacity-70" />
</button>
Expand Down Expand Up @@ -286,9 +288,9 @@ defmodule PollyWeb.CoreComponents do
checked={@checked}
class="rounded border-zinc-300 text-zinc-900 focus:ring-0"
{@rest}
/>
<%= @label %>
/> <%= @label %>
</label>

<.error :for={msg <- @errors}><%= msg %></.error>
</div>
"""
Expand All @@ -298,6 +300,7 @@ defmodule PollyWeb.CoreComponents do
~H"""
<div phx-feedback-for={@name}>
<.label for={@id}><%= @label %></.label>

<select
id={@id}
name={@name}
Expand All @@ -308,6 +311,7 @@ defmodule PollyWeb.CoreComponents do
<option :if={@prompt} value=""><%= @prompt %></option>
<%= Phoenix.HTML.Form.options_for_select(@options, @value) %>
</select>

<.error :for={msg <- @errors}><%= msg %></.error>
</div>
"""
Expand Down Expand Up @@ -338,6 +342,7 @@ defmodule PollyWeb.CoreComponents do
~H"""
<div phx-feedback-for={@name}>
<.label for={@id}><%= @label %></.label>

<input
type={@type}
name={@name}
Expand Down Expand Up @@ -378,8 +383,9 @@ defmodule PollyWeb.CoreComponents do
def error(assigns) do
~H"""
<p class="mt-3 flex gap-3 text-sm leading-6 text-rose-600 phx-no-feedback:hidden">
<.icon name="hero-exclamation-circle-mini" class="mt-0.5 h-5 w-5 flex-none" />
<%= render_slot(@inner_block) %>
<.icon name="hero-exclamation-circle-mini" class="mt-0.5 h-5 w-5 flex-none" /> <%= render_slot(
@inner_block
) %>
</p>
"""
end
Expand All @@ -400,10 +406,12 @@ defmodule PollyWeb.CoreComponents do
<h1 class="text-xl font-semibold leading-8 text-zinc-800">
<%= render_slot(@inner_block) %>
</h1>

<p :if={@subtitle != []} class="mt-2 text-md leading-6 text-zinc-600">
<%= render_slot(@subtitle) %>
</p>
</div>

<div class="flex-none"><%= render_slot(@actions) %></div>
</header>
"""
Expand Down Expand Up @@ -446,9 +454,11 @@ defmodule PollyWeb.CoreComponents do
<thead class="text-sm text-left leading-6 text-zinc-500">
<tr>
<th :for={col <- @col} class="p-0 pr-6 pb-4 font-normal"><%= col[:label] %></th>

<th class="relative p-0 pb-4"><span class="sr-only"><%= gettext("Actions") %></span></th>
</tr>
</thead>

<tbody
id={@id}
phx-update={match?(%Phoenix.LiveView.LiveStream{}, @rows) && "stream"}
Expand All @@ -467,6 +477,7 @@ defmodule PollyWeb.CoreComponents do
</span>
</div>
</td>

<td :if={@action != []} class="relative w-14 p-0">
<div class="relative whitespace-nowrap py-4 text-right text-sm font-medium">
<span class="absolute -inset-y-px -right-4 left-0 group-hover:bg-zinc-50 sm:rounded-r-xl" />
Expand Down Expand Up @@ -505,6 +516,7 @@ defmodule PollyWeb.CoreComponents do
<dl class="-my-4 divide-y divide-zinc-100">
<div :for={item <- @item} class="flex gap-4 py-4 text-sm leading-6 sm:gap-8">
<dt class="w-1/4 flex-none text-zinc-500"><%= item.title %></dt>

<dd class="text-zinc-700"><%= render_slot(item) %></dd>
</div>
</dl>
Expand All @@ -529,8 +541,7 @@ defmodule PollyWeb.CoreComponents do
navigate={@navigate}
class="text-sm font-semibold leading-6 text-zinc-900 hover:text-zinc-700"
>
<.icon name="hero-arrow-left-solid" class="h-3 w-3" />
<%= render_slot(@inner_block) %>
<.icon name="hero-arrow-left-solid" class="h-3 w-3" /> <%= render_slot(@inner_block) %>
</.link>
</div>
"""
Expand Down
Loading
Loading