Browse Source

Implement poll editing

master
Les De Ridder 1 year ago
parent
commit
2742e6380a

+ 64
- 5
app/Http/Controllers/PollController.php View File

@@ -87,7 +87,8 @@ class PollController extends Controller
return view('view_poll')
->with('poll', $poll)
->with('new', $new)
->with('hasVoted', $this->hasVoted($request, $poll));
->with('hasVoted', $this->hasVoted($request, $poll))
->with('code', $request->query('code', null));
}
}

@@ -208,7 +209,10 @@ class PollController extends Controller
public function vote(Request $request, Poll $poll)
{
if($this->hasVoted($request, $poll)) {
return null;
return view('view_poll')
->with('poll', $poll)
->with('new', false)
->with('hasVoted', true);
}

if($poll->allow_multiple_answers) {
@@ -224,12 +228,10 @@ class PollController extends Controller
DB::beginTransaction();
foreach($validatedInput['options'] as $option)
{
//TODO: Properly display errors

if($poll->options()->find($option) == null) {
DB::rollBack();

return null;
return redirect()->action('PollController@view', ['poll' => $poll]);
}

$vote = new PollVote;
@@ -241,6 +243,8 @@ class PollController extends Controller
if($poll->duplicate_vote_checking == 'cookies') {
$request->session()->put($poll->id, null);
} else if($poll->duplicate_vote_checking == 'codes') {
$code = PollVotingCode::find($request->query('code'));

$code->used = true;
$code->save();
}
@@ -250,9 +254,64 @@ class PollController extends Controller

public function admin(Request $request, Poll $poll)
{
$changed = $request->session()->pull('changed', false);
$extraCodes = $request->session()->pull('extra_codes', null);

if($poll->admin_password == null || $request->query('password') != $poll->admin_password) {
return redirect()->action('PollController@view', ['poll' => $poll]);
}

return view('edit_poll')->with('poll', $poll)->with('changed', $changed)->with('extra_codes', $extraCodes);
}

public function edit(Request $request, Poll $poll)
{
if($request->has('extra_codes')) {
if($poll->duplicate_vote_checking != 'codes') {
return redirect()->action('PollController@view', ['poll' => $poll]);
}

$validatedInput = $request->validate([
'extra_codes' => 'integer|min:1'
]);

$codes = $poll->createVotingCodes($validatedInput['extra_codes']);

return redirect()
->action('PollController@admin', ['poll' => $poll, 'password' => $poll->admin_password])
->with('extra_codes', $codes);
} else {
$request['allow_multiple_answers'] = $request->has('allow_multiple_answers');
$request['hide_results_until_closed'] = $request->has('hide_results_until_closed');
$request['automatically_close_poll'] = $request->has('automatically_close_poll');
$request['set_admin_password'] = $request->has('set_admin_password');

if($request['automatically_close_poll'] && $request['automatically_close_poll_datetime'] == 'now') {
//HACK: The validation rule 'date' doesn't accept 'now' as a valid date

$request['automatically_close_poll_datetime'] = Carbon::now()->format('Y-m-d\TH:i');
}

$validatedInput = $request->validate([
'hide_results_until_closed' => 'required|boolean',
'automatically_close_poll' => 'required|boolean',
'automatically_close_poll_datetime' => 'required_if:automatically_close_poll,true|date|after_or_equal:1 minute ago',
'set_admin_password' => 'required|boolean',
'admin_password' => 'required_if:set_admin_password,true|nullable|string',
]);

$poll->hide_results_until_closed = $validatedInput['hide_results_until_closed'];
$poll->closes_at = $validatedInput['automatically_close_poll'] ? Carbon::parse($validatedInput['automatically_close_poll_datetime']) : null;
$poll->admin_password = $validatedInput['set_admin_password'] ? $validatedInput['admin_password'] : null;
$poll->save();

if($poll->closed || $poll->admin_password == null) {
return redirect()->action('PollController@viewResults', ['poll' => $poll]);
} else {
return redirect()
->action('PollController@admin', ['poll' => $poll, 'password' => $poll->admin_password])
->with('changed', true);
}
}
}
}

+ 7
- 1
app/Poll.php View File

@@ -58,8 +58,14 @@ class Poll extends Model
return $codes;
}

public function getClosedAttribute()
{
return ($this->closes_at != null && Carbon::parse($this->closes_at)->isPast()) ||
($this->duplicate_vote_checking == 'codes' && $this->voting_codes()->where('used', false)->count() == 0);
}

public function getResultsVisibleAttribute()
{
return !$this->hide_results_until_closed || ($this->closes_at != null && Carbon::parse($this->closes_at)->isPast());
return !$this->hide_results_until_closed || $this->closed;
}
}

+ 0
- 2
resources/views/create_poll.blade.php View File

@@ -60,7 +60,6 @@
<input type="checkbox" name="set_admin_password">
<span class="checkbox__label">Set an admin password: </span>
<input type="text" name="admin_password" class="inline-text">
<span class="post-input-label"></span>
</label>

<div class="text-browser"><br></div>
@@ -88,7 +87,6 @@
<input type="number" min="2" max="1000" value="10" name="number_of_codes">
<span class="radio__label">codes</span>
</label>

</div>
</section>


+ 111
- 0
resources/views/edit_poll.blade.php View File

@@ -0,0 +1,111 @@
@extends('layouts.app')

@section('title', "Edit poll '" . $poll->question . "'")

@section('content')
@if ($poll->closed)
<div class="primary-box">
<span>The poll is closed and can no longer be edited.</span>
</div>
@else
@if ($changed || $extra_codes != null)
@php (debug($changed))
@php (debug($extra_codes))

<div class="primary-box">
@if ($changed)
<span>Your changes have been saved.</span>
@elseif ($extra_codes != null)
<span>Your extra voting URLs have been generated:</span>
<textarea class="copyarea" readonly>{{collect($extra_codes)->map(function($c) use($poll) { return action('PollController@view', ['poll' => $poll, 'code' => $c]); })->implode("\n")}}</textarea>
@endif
</div>

<div class="text-browser"><br></div>
@endif

<section class="grid grid--large">
<div class="some-top-margin">
<form action="{{ action('PollController@edit', ['poll' => $poll, 'password' => $poll->password]) }}" method="post">
@method('PATCH')

@csrf

<div class="some-bottom-margin">
<span>Change settings:</span>
</div>
<label class="checkbox no-bottom-margin">
<input type="checkbox" name="hide_results_until_closed" @if($poll->hide_results_until_closed) checked @endif>
<span class="checkbox__label">Hide results until poll is closed</span>
</label>
<br>
<label class="checkbox no-bottom-margin">
<input type="checkbox" name="automatically_close_poll" @if($poll->closes_at != null) checked @endif>
<span class="checkbox__label">Automatically close poll at </span>
<input type="datetime-local" name="automatically_close_poll_datetime" class="inline-block" value="{{ $poll->closes_at != null ? Carbon\Carbon::parse($poll->closes_at)->format('Y-m-d\TH:i') : Carbon\Carbon::now()->addHour()->format('Y-m-d\TH:i') }}" min="{{ Carbon\Carbon::now()->format('Y-m-d\TH:i') }}">
</label>
<br>
<label class="checkbox no-bottom-margin">
<input type="checkbox" name="set_admin_password" @if($poll->admin_password != null) checked @endif>
<span class="checkbox__label">Set an admin password: </span>
<input type="text" name="admin_password" class="inline-text" @if($poll->admin_password != null) value="{{ $poll->admin_password}}" @endif>
</label>
<br>
<div class="some-top-margin">
<input type="submit" class="btn" value="Confirm">
</div>
</form>

<div class="text-browser"><br></div>
</div>

@if ($poll->duplicate_vote_checking == 'codes')
<div class="some-top-margin">
<form action="{{ action('PollController@edit', ['poll' => $poll, 'password' => $poll->password]) }}" method="post">
@method('PATCH')

@csrf

<div class="some-bottom-margin">
<span>Generate extra voting codes: </span>
</div>
<label class="free-number">
<input type="number" min="1" max="1000" value="10" name="extra_codes">
<span class="radio__label">codes</span>
</label>
<br>
<div class="some-top-margin">
<input type="submit" class="btn" value="Confirm">
</div>
</form>
</div>
@endif
</section>

<div class="text-browser"><br></div>

<section>
<form action="{{ action('PollController@edit', ['poll' => $poll, 'password' => $poll->password]) }}" method="post">
@method('PATCH')

@csrf

<div class="some-top-margin">
@if ($poll->hide_results_until_closed)
<input type="hidden" name="hide_results_until_closed" value="1">
@endif

@if ($poll->admin_password != null)
<input type="hidden" name="set_admin_password" value="1">
<input type="hidden" name="admin_password" value="{{ $poll->admin_password }}">
@endif

<input type="hidden" name="automatically_close_poll" value="1">
<input type="hidden" name="automatically_close_poll_datetime" value="now">

<input type="submit" class="btn" style="width:100%" value="Close poll now">
</div>
</form>
</section>
@endif
@endsection

+ 20
- 0
resources/views/layouts/app.blade.php View File

@@ -67,6 +67,26 @@
outline: 0;
}

.free-number {
display: inline-block;
margin-bottom: 0;
padding: 0 1rem 0 0;
position: relative;
}

.free-number > input[type="number"] {
display: inline-block;
border: 1px solid #7d7d7e;
margin-top: 0.5rem;
margin-left: 0;
}

.free-number > input[type="number"]:focus {
border-color: #e83fb8;
box-shadow: 0 1px 2px 0 #dededf inset;
outline: 0;
}

input[type="datetime-local"] {
margin-top: 0.2rem;
margin-bottom: 0.2rem;

+ 14
- 1
resources/views/view_poll.blade.php View File

@@ -13,6 +13,14 @@ $type = $poll->allow_multiple_answers ? "checkbox" : "radio";

<div class="text-browser"><br></div>

@if ($poll->admin_password != null)
<div class="some-top-margin">
<span>Admin URL: <a href="{{ action('PollController@admin', ['poll' => $poll, 'password' => $poll->admin_password]) }}">{{ action('PollController@admin', ['poll' => $poll, 'password' => $poll->admin_password]) }}</a></span>
</div>

<div class="text-browser"><br></div>
@endif

<div class="some-top-margin">
@if ($poll->duplicate_vote_checking == 'codes')
<span>Voting URLs:</span>
@@ -42,7 +50,12 @@ $type = $poll->allow_multiple_answers ? "checkbox" : "radio";
@else
<div class="text-browser"><br></div>

<form action="{{ action('PollController@vote', ['poll' => $poll]) }}" method="post">
@if ($code != null)
<form action="{{ action('PollController@vote', ['poll' => $poll, 'code' => $code]) }}" method="post">
@else
<form action="{{ action('PollController@vote', ['poll' => $poll]) }}" method="post">
@endif

@csrf

@foreach ($poll->options as $option)

+ 1
- 1
resources/views/view_poll_results.blade.php View File

@@ -11,7 +11,7 @@
<div class="text-browser"><br></div>
@endif

@if($poll->results_visible)
@if ($poll->results_visible)
@php
$sortedOptions = $poll->options->sortByDesc(function($option) use($poll) { return $poll->votes->where('poll_option_id', $option->id)->count(); });
$nonZeroOptions = $sortedOptions->filter(function($option) use($poll) { return $poll->votes->where('poll_option_id', $option->id)->count() > 0; });

+ 2
- 4
routes/web.php View File

@@ -20,11 +20,9 @@ Route::post('/poll', 'PollController@create');

Route::get('/poll/{poll}', 'PollController@view');

//TODO: Add admin GET route
Route::get('/poll/{poll}/edit', 'PollController@admin');
Route::patch('/poll/{poll}', 'PollController@edit');

Route::get('/poll/{poll}/results', 'PollController@viewResults');

Route::post('/poll/{poll}/vote', 'PollController@vote');

Route::get('/poll/{poll}/edit', 'PollController@admin');
Route::get('/poll/{poll}/results', 'PollController@viewResults');

Loading…
Cancel
Save