Skip to content

Commit

Permalink
Merge branch 'dev'
Browse files Browse the repository at this point in the history
  • Loading branch information
alxlion committed Apr 21, 2023
2 parents 64cd399 + 736c4a3 commit c1939c5
Show file tree
Hide file tree
Showing 71 changed files with 4,502 additions and 2,320 deletions.
1 change: 1 addition & 0 deletions .env.sample
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
PRESENTATION_STORAGE=local
MAX_FILE_SIZE_MB=15

AWS_ACCESS_KEY_ID=xxx
AWS_SECRET_ACCESS_KEY=xxx
Expand Down
5 changes: 3 additions & 2 deletions .formatter.exs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
[
import_deps: [:ecto, :phoenix],
inputs: ["*.{ex,exs}", "priv/*/seeds.exs", "{config,lib,test}/**/*.{ex,exs}"],
subdirectories: ["priv/*/migrations"]
inputs: ["*.{heex,ex,exs}", "{config,lib,test}/**/*.{heex,ex,exs}", "priv/*/seeds.exs"],
subdirectories: ["priv/*/migrations"],
plugins: [Phoenix.LiveView.HTMLFormatter]
]
49 changes: 32 additions & 17 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,14 +1,30 @@
## v1.0.0
## v1.4.0

This is the first version of the open-source project. Feel free to contribute!
- Migrate to Phoenix 1.7
- Migrate to Liveview 0.18
- Add multiple choice poll
- Add feature to import all interactions from another presentation
- Add MAX_FILE_SIZE_MB environment variable to limit file upload size
- Add feature to deactivate messages during a presentation

## v1.1.0

- Added password authentication
- Removed passwordless authentication
- Disabled email verification
- Added new `ENABLE_ACCOUNT_CREATION` environment variable to enable or disable user registration
- Improved french localization
## v1.3.0

- Add Form feature to collect data from your public
- Improve docs for Docker Compose
- Improve Docker Compose file reference


## v1.2.1

- Fix presenter url (400 error in production)


## v1.2.0

- Added password change form in settings
- Added more documentation on deployment in production


## v1.1.1

Expand All @@ -17,17 +33,16 @@ _Security updates_
- Added `ENABLE_MAILBOX_ROUTE`, `MAILBOX_USER` and `MAILBOX_PASSWORD` environment variables to enable/disable route to local mailbox (`/dev/mailbox`) and basic auth (optional)
- Restricted `/users/register` route if `ENABLE_ACCOUNT_CREATION` is false

## v1.2.0

- Added password change form in settings
- Added more documentation on deployment in production
## v1.1.0

## v1.2.1
- Added password authentication
- Removed passwordless authentication
- Disabled email verification
- Added new `ENABLE_ACCOUNT_CREATION` environment variable to enable or disable user registration
- Improved french localization

- Fix presenter url (400 error in production)

## v1.3.0
## v1.0.0

- Add Form feature to collect data from your public
- Improve docs for Docker Compose
- Improve Docker Compose file reference
This is the first version of the open-source project. Feel free to contribute!
12 changes: 8 additions & 4 deletions assets/js/app.js
Original file line number Diff line number Diff line change
Expand Up @@ -148,8 +148,10 @@ Hooks.PostForm = {
mounted() {
const submitBtn = document.getElementById("submitBtn")
const TA = document.getElementById("postFormTA")
submitBtn.addEventListener("click", (e) => this.onSubmit(e, TA))
TA.addEventListener("keydown", (e) => this.onPress(e, submitBtn, TA))
if (submitBtn && TA) {
submitBtn.addEventListener("click", (e) => this.onSubmit(e, TA))
TA.addEventListener("keydown", (e) => this.onPress(e, submitBtn, TA))
}
},
updated() {
const submitBtn = document.getElementById("submitBtn")
Expand All @@ -165,8 +167,10 @@ Hooks.PostForm = {
destroyed() {
const submitBtn = document.getElementById("submitBtn")
const TA = document.getElementById("postFormTA")
TA.removeEventListener("keydown", (e) => this.onPress(e, submitBtn, TA))
submitBtn.removeEventListener("click", (e) => this.onSubmit(e, TA))
if (submitBtn && TA) {
TA.removeEventListener("keydown", (e) => this.onPress(e, submitBtn, TA))
submitBtn.removeEventListener("click", (e) => this.onSubmit(e, TA))
}
}
}

Expand Down
4 changes: 3 additions & 1 deletion config/config.exs
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ config :claper, Claper.Mailer, adapter: Swoosh.Adapters.Local
config :swoosh, :api_client, false

config :dart_sass,
version: "1.54.0",
version: "1.58.0",
default: [
args: ~w(css/custom.scss ../priv/static/assets/custom.css),
cd: Path.expand("../assets", __DIR__)
Expand Down Expand Up @@ -66,6 +66,8 @@ config :ex_aws,
region: {:system, "AWS_REGION"},
normalize_path: false

config :claper, max_file_size: System.get_env("MAX_FILE_SIZE_MB") || 15

# Import environment specific config. This must remain at the bottom
# of this file so it overrides the configuration defined above.
import_config "#{config_env()}.exs"
1 change: 1 addition & 0 deletions guides/introduction/configuration.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ MAILBOX_PASSWORD | - | - | - | Basic auth password for mailbox route
Variable | Values | Default | Required | Description
--- | --- | --- | --- | ---
ENABLE_ACCOUNT_CREATION | true, false | true | - | Enable/disable user registration
MAX_FILE_SIZE_MB | - | 15 | - | Max file size to upload in MB

## Production / Docker

Expand Down
2 changes: 2 additions & 0 deletions guides/usage/features.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ When you create a new presentation, click on **Present/Customize**, select the s

During your presentation, enable **Active poll results** on the dashboard to see the poll results in real time.

You can choose between single choice and multiple choice polls.

<img src="assets/feature1.png" width="300"/>

## Forms
Expand Down
68 changes: 68 additions & 0 deletions lib/claper/events.ex
Original file line number Diff line number Diff line change
Expand Up @@ -258,6 +258,74 @@ defmodule Claper.Events do
end
end

@doc """
Import interactions from another event
## Examples
iex> import(user_id, from_event_uuid, to_event_uuid)
{:ok, %Event{}}
iex> import(user_id, from_event_uuid, to_event_uuid)
{:error, %Ecto.Changeset{}}
"""
def import(user_id, from_event_uuid, to_event_uuid) do
case Ecto.Multi.new()
|> Ecto.Multi.run(:from_event, fn _repo, _changes ->
{:ok,
get_user_event!(user_id, from_event_uuid,
presentation_file: [polls: [:poll_opts], forms: []]
)}
end)
|> Ecto.Multi.run(:to_event, fn _repo, _changes ->
{:ok, get_user_event!(user_id, to_event_uuid, presentation_file: [:polls, :forms])}
end)
|> Ecto.Multi.run(:polls, fn _repo, %{from_event: from_event, to_event: to_event} ->
{:ok,
from_event.presentation_file.polls
|> Enum.each(fn poll ->
if poll.position < to_event.presentation_file.length do
Claper.Polls.create_poll(%{
title: poll.title,
position: poll.position,
enabled: poll.enabled,
multiple: poll.multiple,
poll_opts:
Enum.map(poll.poll_opts, fn opt ->
%{content: opt.content, vote_count: 0}
end),
presentation_file_id: to_event.presentation_file.id
})
end
end)}
end)
|> Ecto.Multi.run(:forms, fn _repo, %{from_event: from_event, to_event: to_event} ->
{:ok,
from_event.presentation_file.forms
|> Enum.each(fn form ->
if form.position < to_event.presentation_file.length do
Claper.Forms.create_form(%{
title: form.title,
position: form.position,
enabled: form.enabled,
fields:
Enum.map(form.fields, fn field ->
%{
name: field.name,
type: field.type
}
end),
presentation_file_id: to_event.presentation_file.id
})
end
end)}
end)
|> Repo.transaction() do
{:ok, %{to_event: to_event}} -> {:ok, to_event}
end
end

@doc """
Deletes a event.
Expand Down
2 changes: 1 addition & 1 deletion lib/claper/forms/form.ex
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ defmodule Claper.Forms.Form do
schema "forms" do
field :enabled, :boolean, default: true
field :position, :integer, default: 0
field :title, :string, null: false
field :title, :string
embeds_many :fields, Claper.Forms.Field, on_replace: :delete

belongs_to :presentation_file, Claper.Presentations.PresentationFile
Expand Down
109 changes: 55 additions & 54 deletions lib/claper/polls.ex
Original file line number Diff line number Diff line change
Expand Up @@ -221,59 +221,50 @@ defmodule Claper.Polls do
)
end

def vote(user_id, event_uuid, %PollOpt{} = poll_opt, poll_id) when is_number(user_id) do
case Ecto.Multi.new()
|> Ecto.Multi.update(
:poll_opt,
PollOpt.changeset(poll_opt, %{"vote_count" => poll_opt.vote_count + 1})
)
|> Ecto.Multi.insert(:poll_vote, %PollVote{
user_id: user_id,
poll_opt_id: poll_opt.id,
poll_id: poll_id
})
def vote(user_id, event_uuid, poll_opts, poll_id)
when is_number(user_id) and is_list(poll_opts) do
case Enum.reduce(poll_opts, Ecto.Multi.new(), fn opt, multi ->
Ecto.Multi.update(
multi,
{:update_poll_opt, opt.id},
PollOpt.changeset(opt, %{"vote_count" => opt.vote_count + 1})
)
|> Ecto.Multi.insert(
{:insert_poll_vote, opt.id},
PollVote.changeset(%PollVote{}, %{
user_id: user_id,
poll_opt_id: opt.id,
poll_id: poll_id
})
)
end)
|> Repo.transaction() do
{:ok, %{poll_opt: opt}} ->
opt =
Repo.preload(opt,
poll: [
poll_opts:
from(
o in PollOpt,
order_by: [asc: o.id]
)
]
)

broadcast({:ok, opt.poll |> set_percentages, event_uuid}, :poll_updated)
{:ok, _} ->
poll = get_poll!(poll_id)
broadcast({:ok, poll, event_uuid}, :poll_updated)
end
end

def vote(attendee_identifier, event_uuid, %PollOpt{} = poll_opt, poll_id) do
case Ecto.Multi.new()
|> Ecto.Multi.update(
:poll_opt,
PollOpt.changeset(poll_opt, %{"vote_count" => poll_opt.vote_count + 1})
)
|> Ecto.Multi.insert(:poll_vote, %PollVote{
attendee_identifier: attendee_identifier,
poll_opt_id: poll_opt.id,
poll_id: poll_id
})
def vote(attendee_identifier, event_uuid, poll_opts, poll_id) when is_list(poll_opts) do
case Enum.reduce(poll_opts, Ecto.Multi.new(), fn opt, multi ->
Ecto.Multi.update(
multi,
{:update_poll_opt, opt.id},
PollOpt.changeset(opt, %{"vote_count" => opt.vote_count + 1})
)
|> Ecto.Multi.insert(
{:insert_poll_vote, opt.id},
PollVote.changeset(%PollVote{}, %{
attendee_identifier: attendee_identifier,
poll_opt_id: opt.id,
poll_id: poll_id
})
)
end)
|> Repo.transaction() do
{:ok, %{poll_opt: opt}} ->
opt =
Repo.preload(opt,
poll: [
poll_opts:
from(
o in PollOpt,
order_by: [asc: o.id]
)
]
)

broadcast({:ok, opt.poll |> set_percentages, event_uuid}, :poll_updated)
{:ok, _} ->
poll = get_poll!(poll_id)
broadcast({:ok, poll, event_uuid}, :poll_updated)
end
end

Expand Down Expand Up @@ -313,20 +304,30 @@ defmodule Claper.Polls do
end

@doc """
Gets a single poll_vote.
Gets a all poll_vote.
## Examples
iex> get_poll_vote!(321, 123)
%PollVote{}
[%PollVote{}]
"""
def get_poll_vote(user_id, poll_id) when is_number(user_id),
do: Repo.get_by(PollVote, poll_id: poll_id, user_id: user_id)
def get_poll_vote(user_id, poll_id) when is_number(user_id) do
from(p in PollVote,
where: p.poll_id == ^poll_id and p.user_id == ^user_id,
order_by: [asc: p.id]
)
|> Repo.all()
end

def get_poll_vote(attendee_identifier, poll_id),
do: Repo.get_by(PollVote, poll_id: poll_id, attendee_identifier: attendee_identifier)
def get_poll_vote(attendee_identifier, poll_id) do
from(p in PollVote,
where: p.poll_id == ^poll_id and p.attendee_identifier == ^attendee_identifier,
order_by: [asc: p.id]
)
|> Repo.all()
end

@doc """
Creates a poll_vote.
Expand Down
3 changes: 2 additions & 1 deletion lib/claper/polls/poll.ex
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ defmodule Claper.Polls.Poll do
field :position, :integer
field :total, :integer, virtual: true
field :enabled, :boolean
field :multiple, :boolean

belongs_to :presentation_file, Claper.Presentations.PresentationFile
has_many :poll_opts, Claper.Polls.PollOpt, on_replace: :delete
Expand All @@ -19,7 +20,7 @@ defmodule Claper.Polls.Poll do
@doc false
def changeset(poll, attrs) do
poll
|> cast(attrs, [:title, :presentation_file_id, :position, :enabled, :total])
|> cast(attrs, [:title, :presentation_file_id, :position, :enabled, :total, :multiple])
|> cast_assoc(:poll_opts, required: true)
|> validate_required([:title, :presentation_file_id, :position])
end
Expand Down
Loading

0 comments on commit c1939c5

Please sign in to comment.