Skip to content
Open
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
13 changes: 8 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,15 @@ Polling web app, where admin selects one question, and the audience can see/answ

## Screens

![polls](html/screenshots/polls.jpg)
![question](html/screenshots/question.jpg)
![answers](html/screenshots/answers.jpg)
![edit](html/screenshots/edit_poll.jpg)
![polls](_html/screenshots/polls.jpg)

## Deploy procedure
![question](_html/screenshots/question.jpg)

![answers](_html/screenshots/answers.jpg)

![edit](_html/screenshots/edit_poll.jpg)

## Deploy

Refer to Gigalixir [documentation](https://gigalixir.readthedocs.io/en/latest/main.html#deploy)

Expand Down
26 changes: 24 additions & 2 deletions TODO.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,24 @@
# TODO

Step 1 - Manage

* UI: Button "Pull" question - set `active` to `true`; and redirect_back
- show
- index
* UI: Button "Stop" finds active question and set `active` to FALSE

Step 2 - Public

* Navigate(of refresh) `poll_page(:id)` displays currently active question
1) Poll does not have active question: display welcoming text
2) Poll has active question: display question

Step 3 - Public when question has been answered

* to be continued...

# Plane

- Build application with Phoenix framework
* mix.new app
* models
Expand Down Expand Up @@ -42,13 +61,16 @@
* Submit answer
* Show answers
- admin
* CRUD poll. Need for grouping questions. Public-side does not know about quiz.
* CRUD poll. Need for grouping questions.
Each poll consists of questions.
Only one question can be active(per poll).
* CRUD question
Each question consists of answers.
Answers can be "radio buttons" or "check boxes".
Each question has one answer "Other" - input[type=text]. Optional.
Each question has special answer: "Other" input[type=text]. Optional.
* Show question answers
- "Pull"-action button
- Next/Prev links

```example
Question:
Expand Down
File renamed without changes.
File renamed without changes.
File renamed without changes.
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@
<a href="#">&larr; Prev</a>
</div>
<div class="float-right">
<a href="#">Next &rarr;</a>
<a href="admin_index.html">Next &rarr;</a>
</div>
</div>

Expand Down
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes
File renamed without changes
File renamed without changes
File renamed without changes
File renamed without changes
File renamed without changes.
109 changes: 15 additions & 94 deletions assets/css/app.css
Original file line number Diff line number Diff line change
@@ -1,6 +1,14 @@
/* This file is for your main application css. */

/* theme_default.css */

.row-no-media {
flex-direction: row;
}
.row-no-media .column {
margin-bottom: inherit;
}

.title-adaptive {
font-size: calc(24px + (36 - 24) * ((100vw - 320px) / 680));
}
Expand Down Expand Up @@ -45,6 +53,13 @@
border-left: .3rem solid #f53131;
}

.text-center {
text-align: center;
}

.text-right {
text-align: right;
}



Expand Down Expand Up @@ -277,66 +292,6 @@
}
}

.prettyprint.code {
border: 0;
border-left: .3rem solid #9b4dca;
color: #655d5d
}

.prettyprint.code .str {
color: #4b8b8b
}

.prettyprint.code .kwd {
color: #8464c4
}

.prettyprint.code .com {
color: #adadad
}

.prettyprint.code .typ {
color: #7272ca
}

.prettyprint.code .lit {
color: #9b4dca
}

.prettyprint.code .pun {
color: #5485b6
}

.prettyprint.code .clo,
.prettyprint.code .opn {
color: #f4ecec
}

.prettyprint.code .atn,
.prettyprint.code .tag {
color: #9b4dca
}

.prettyprint.code .atv {
color: #5485b6
}

.prettyprint.code .dec {
color: #b45a3c
}

.prettyprint.code .var {
color: #ca4949
}

.prettyprint.code .fun {
color: #7272ca
}

.prettyprint.code.lang-md * {
color: #655d5d
}

.carbonads {
background-color: #f4f5f6;
border-radius: 4px;
Expand Down Expand Up @@ -388,30 +343,6 @@
margin-bottom: 0
}

.example {
margin-top: 4rem;
position: relative
}

.example .example-header {
font-weight: 600;
margin-bottom: .5rem;
margin-top: 1.5rem
}

.example h1,
.example h2,
.example h3,
.example h4,
.example h5,
.example h6 {
margin-bottom: 1rem
}

.example form {
margin-bottom: 0
}

.heading-font-size {
color: #999;
font-size: 1.2rem;
Expand Down Expand Up @@ -460,13 +391,3 @@
text-align: center;
text-transform: uppercase
}

.example .container {
padding-left: 0;
padding-right: 0
}

.example.row,
.example .row {
margin-bottom: 0
}
22 changes: 22 additions & 0 deletions lib/instant_poll/ecto_type/strings_list.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
defmodule InstantPoll.EctoType.StringsList do

@behaviour Ecto.Type
def type, do: {:array, :string}

def cast(nil), do: {:ok, []}
def cast(arr) when is_list(arr) do
{:ok, reject_blank(arr)}
end

def dump(val), do: {:ok, val}
def load(val), do: {:ok, val}


defp reject_blank(collection) do
Enum.reject(collection, fn(s) -> is_blank(s) end)
end

defp is_blank(str) do
String.length(String.trim(str)) == 0
end
end
2 changes: 1 addition & 1 deletion lib/instant_poll/polls/poll.ex
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,12 @@ defmodule InstantPoll.Polls.Poll do
schema "polls" do
field :archived, :boolean, default: false
field :name, :string
belongs_to :active_question, Question
has_many :questions, Question

timestamps()
end

@doc false
def changeset(%Poll{} = poll, attrs) do
poll
|> cast(attrs, [:name, :archived])
Expand Down
71 changes: 0 additions & 71 deletions lib/instant_poll/polls/polls.ex
Original file line number Diff line number Diff line change
@@ -1,106 +1,35 @@
defmodule InstantPoll.Polls do
@moduledoc """
The Polls context.
"""

import Ecto.Query, warn: false
alias InstantPoll.Repo

alias InstantPoll.Polls.Poll
alias InstantPoll.Polls.Question

@doc """
Returns the list of polls.

## Examples

iex> list_polls()
[%Poll{}, ...]

"""
def list_polls do
Poll
|> order_by(desc: :id)
|> Repo.all
end

@doc """
Gets a single poll.

Raises `Ecto.NoResultsError` if the Poll does not exist.

## Examples

iex> get_poll!(123)
%Poll{}

iex> get_poll!(456)
** (Ecto.NoResultsError)

"""
def get_poll!(id), do: Repo.get!(Poll, id)

@doc """
Creates a poll.

## Examples

iex> create_poll(%{field: value})
{:ok, %Poll{}}

iex> create_poll(%{field: bad_value})
{:error, %Ecto.Changeset{}}

"""
def create_poll(attrs \\ %{}) do
%Poll{}
|> Poll.changeset(attrs)
|> Repo.insert()
end

@doc """
Updates a poll.

## Examples

iex> update_poll(poll, %{field: new_value})
{:ok, %Poll{}}

iex> update_poll(poll, %{field: bad_value})
{:error, %Ecto.Changeset{}}

"""
def update_poll(%Poll{} = poll, attrs) do
poll
|> Poll.changeset(attrs)
|> Repo.update()
end

@doc """
Deletes a Poll.

## Examples

iex> delete_poll(poll)
{:ok, %Poll{}}

iex> delete_poll(poll)
{:error, %Ecto.Changeset{}}

"""
def delete_poll(%Poll{} = poll) do
Repo.delete(poll)
end

@doc """
Returns an `%Ecto.Changeset{}` for tracking poll changes.

## Examples

iex> change_poll(poll)
%Ecto.Changeset{source: %Poll{}}

"""
def change_poll(%Poll{} = poll) do
Poll.changeset(poll, %{})
end
Expand Down
13 changes: 4 additions & 9 deletions lib/instant_poll/polls/question.ex
Original file line number Diff line number Diff line change
Expand Up @@ -3,27 +3,22 @@ defmodule InstantPoll.Polls.Question do
import Ecto.Changeset
alias InstantPoll.Polls.Question
alias InstantPoll.Polls.Poll
alias InstantPoll.EctoType.StringsList


schema "questions" do
field :answers, {:array, :string}
field :multiple, :boolean, default: false
field :name, :string
field :answers, StringsList, default: []
field :multiple, :boolean, default: false
field :other_answer, :boolean, default: false
belongs_to :poll, Poll

timestamps()
end

@doc false
def changeset(%Question{} = question, attrs) do
question
|> cast(attrs, [:name, :poll_id, :multiple, :answers, :other_answer])
|> put_change(
:answers,
attrs["answers"] == nil ||
Enum.reject(attrs["answers"], fn(s) -> String.length(String.trim s) == 0 end)
)
|> cast(attrs, [:name, :answers, :poll_id, :multiple, :other_answer])
|> validate_required([:name, :poll_id, :multiple, :other_answer])
end
end
Loading