Implement poll editing
这个提交包含在:
父节点
f96a3ba685
当前提交
2742e6380a
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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>
|
||||
|
||||
|
|
|
@ -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
|
|
@ -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;
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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; });
|
||||
|
|
|
@ -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');
|
||||
|
|
正在加载...
在新工单中引用