forked from miguel456/rbrecruiter
Add save & update functionality to positions
Tooltips also added, as well as a general configuration file for Mojang Status URL. Relationships were also added between forms and Vacancies. Status verification for the dashboard was moved to a Service Provider, where it adds log entries when cache expires. Authentication controllers were also updated to reflect the new dashboard URL.
This commit is contained in:
parent
290104eea7
commit
a4e415943a
|
@ -13,4 +13,9 @@ class Form extends Model
|
|||
'formStatus'
|
||||
|
||||
];
|
||||
|
||||
public function vacancy()
|
||||
{
|
||||
return $this->hasMany('App\Vacancy', 'vacancyFormID');
|
||||
}
|
||||
}
|
||||
|
|
|
@ -26,7 +26,7 @@ class ConfirmPasswordController extends Controller
|
|||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $redirectTo = RouteServiceProvider::HOME;
|
||||
protected $redirectTo = '/dashboard';
|
||||
|
||||
/**
|
||||
* Create a new controller instance.
|
||||
|
|
|
@ -26,5 +26,5 @@ class ResetPasswordController extends Controller
|
|||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $redirectTo = RouteServiceProvider::HOME;
|
||||
protected $redirectTo = '/dashboard';
|
||||
}
|
||||
|
|
|
@ -26,7 +26,7 @@ class VerificationController extends Controller
|
|||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $redirectTo = RouteServiceProvider::HOME;
|
||||
protected $redirectTo = '/dashboard';
|
||||
|
||||
/**
|
||||
* Create a new controller instance.
|
||||
|
|
|
@ -5,23 +5,14 @@ namespace App\Http\Controllers;
|
|||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\Cache;
|
||||
use Illuminate\Support\Facades\Http;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
|
||||
class DashboardController extends Controller
|
||||
{
|
||||
|
||||
public function index()
|
||||
{
|
||||
// TODO: Switch status checking to provider, share with all views
|
||||
|
||||
// Mojang status for informational purposes
|
||||
if (!Cache::has('mojang_status'))
|
||||
{
|
||||
$mcstatus = Http::get('https://status.mojang.com/check');
|
||||
Cache::put('mojang_status', base64_encode($mcstatus->body()), now()->addMinutes(60));
|
||||
}
|
||||
|
||||
return view('dashboard.dashboard')
|
||||
->with('mcstatus', json_decode(base64_decode(Cache::get('mojang_status')), true));
|
||||
return view('dashboard.dashboard');
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -2,14 +2,86 @@
|
|||
|
||||
namespace App\Http\Controllers;
|
||||
|
||||
use App\Form;
|
||||
use App\Http\Requests\VacancyRequest;
|
||||
use App\Vacancy;
|
||||
use Illuminate\Http\Request;
|
||||
|
||||
class VacancyController extends Controller
|
||||
{
|
||||
|
||||
public function index()
|
||||
{
|
||||
return view('dashboard.administration.positions');
|
||||
return view('dashboard.administration.positions')
|
||||
->with([
|
||||
'forms' => Form::all(),
|
||||
'vacancies' => Vacancy::all()
|
||||
]);
|
||||
}
|
||||
|
||||
public function store(VacancyRequest $request)
|
||||
{
|
||||
$form = Form::find($request->vacancyFormID);
|
||||
|
||||
if (!is_null($form))
|
||||
{
|
||||
Vacancy::create([
|
||||
|
||||
'vacancyName' => $request->vacancyName,
|
||||
'vacancyDescription' => $request->vacancyDescription,
|
||||
'permissionGroupName' => $request->permissionGroup,
|
||||
'discordRoleID' => $request->discordRole,
|
||||
'vacancyFormID' => $request->vacancyFormID,
|
||||
'vacancyCount' => $request->vacancyCount
|
||||
|
||||
]);
|
||||
|
||||
$request->session()->flash('success', 'Vacancy successfully opened. It will now show in the home page.');
|
||||
}
|
||||
else
|
||||
{
|
||||
$request->session()->flash('error', 'You cannot create a vacancy without a valid form.');
|
||||
}
|
||||
|
||||
return redirect()->back();
|
||||
|
||||
}
|
||||
|
||||
public function updatePositionAvailability(Request $request, $status, $id)
|
||||
{
|
||||
$vacancy = Vacancy::find($id);
|
||||
|
||||
if (!is_null($vacancy))
|
||||
{
|
||||
$type = 'success';
|
||||
|
||||
switch ($status)
|
||||
{
|
||||
case 'open':
|
||||
$vacancy->open();
|
||||
$message = "Position successfully opened!";
|
||||
|
||||
break;
|
||||
|
||||
case 'close':
|
||||
$vacancy->close();
|
||||
$message = "Position successfully closed!";
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
$message = "Please do not tamper with the button's URLs. To report a bug, please contact an administrator.";
|
||||
$type = 'error';
|
||||
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
$message = "The position you're trying to update doesn't exist!";
|
||||
$type = "error";
|
||||
}
|
||||
|
||||
$request->session()->flash($type, $message);
|
||||
return redirect()->back();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1,35 @@
|
|||
<?php
|
||||
|
||||
namespace App\Http\Requests;
|
||||
|
||||
use Illuminate\Foundation\Http\FormRequest;
|
||||
|
||||
class VacancyRequest extends FormRequest
|
||||
{
|
||||
/**
|
||||
* Determine if the user is authorized to make this request.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function authorize()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the validation rules that apply to the request.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function rules()
|
||||
{
|
||||
return [
|
||||
'vacancyName' => 'required|string',
|
||||
'vacancyDescription' => 'required|string',
|
||||
'permissionGroup' => 'required|string',
|
||||
'discordRole' => 'required|string',
|
||||
'vacancyCount' => 'required|integer',
|
||||
'vacancyFormID' => 'required|integer'
|
||||
];
|
||||
}
|
||||
}
|
|
@ -1,28 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace App\Providers;
|
||||
|
||||
use Illuminate\Support\ServiceProvider;
|
||||
|
||||
class GuzzleServiceProvider extends ServiceProvider
|
||||
{
|
||||
/**
|
||||
* Register services.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function register()
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
/**
|
||||
* Bootstrap services.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function boot()
|
||||
{
|
||||
//
|
||||
}
|
||||
}
|
|
@ -0,0 +1,41 @@
|
|||
<?php
|
||||
|
||||
namespace App\Providers;
|
||||
|
||||
use Illuminate\Support\Facades\Cache;
|
||||
use Illuminate\Support\Facades\Http;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
use Illuminate\Support\ServiceProvider;
|
||||
use Illuminate\Support\Facades\View;
|
||||
|
||||
class MojangStatusProvider extends ServiceProvider
|
||||
{
|
||||
/**
|
||||
* Register services.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function register()
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
/**
|
||||
* Bootstrap services.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function boot()
|
||||
{
|
||||
|
||||
if (!Cache::has('mojang_status'))
|
||||
{
|
||||
Log::info("Mojang Status Provider: Mojang Status not found in the cache; Sending new request.");
|
||||
|
||||
$mcstatus = Http::get(config('general.urls.mojang.statuscheck'));
|
||||
Cache::put('mojang_status', base64_encode($mcstatus->body()), now()->addMinutes(60));
|
||||
}
|
||||
|
||||
View::share('mcstatus', json_decode(base64_decode(Cache::get('mojang_status')), true));
|
||||
}
|
||||
}
|
|
@ -3,8 +3,45 @@
|
|||
namespace App;
|
||||
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
|
||||
class Vacancy extends Model
|
||||
{
|
||||
//
|
||||
public $fillable = [
|
||||
|
||||
'permissionGroupName',
|
||||
'vacancyName',
|
||||
'vacancyDescription',
|
||||
'discordRoleID',
|
||||
'vacancyFormID',
|
||||
'vacancyCount',
|
||||
'vacancyStatus'
|
||||
|
||||
];
|
||||
|
||||
public function forms()
|
||||
{
|
||||
return $this->belongsTo('App\Form');
|
||||
}
|
||||
|
||||
public function open()
|
||||
{
|
||||
$this->update([
|
||||
'vacancyStatus' => 'OPEN'
|
||||
]);
|
||||
|
||||
Log::info("Vacancies: Vacancy " . $this->id . " (" . $this->vacancyName . ") opened by " . Auth::user()->name);
|
||||
}
|
||||
|
||||
public function close()
|
||||
{
|
||||
$this->update([
|
||||
'vacancyStatus' => 'CLOSED'
|
||||
]);
|
||||
|
||||
Log::warning("Vacancies: Vacancy " . $this->id . " (" . $this->vacancyName . ") closed by " . Auth::user()->name);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -446,6 +446,17 @@ return [
|
|||
'location' => 'https://cdnjs.cloudflare.com/ajax/libs/toastr.js/latest/toastr.min.css'
|
||||
]
|
||||
]
|
||||
],
|
||||
[
|
||||
'name' => 'GlobalTooltip',
|
||||
'active' => 'true',
|
||||
'files' => [
|
||||
[
|
||||
'type' => 'js',
|
||||
'asset' => false,
|
||||
'location' => '/js/globaltooltip.js'
|
||||
]
|
||||
]
|
||||
]
|
||||
],
|
||||
];
|
||||
|
|
|
@ -174,6 +174,7 @@ return [
|
|||
// App\Providers\BroadcastServiceProvider::class,
|
||||
App\Providers\EventServiceProvider::class,
|
||||
App\Providers\RouteServiceProvider::class,
|
||||
\App\Providers\MojangStatusProvider::class,
|
||||
|
||||
],
|
||||
|
||||
|
|
|
@ -0,0 +1,15 @@
|
|||
<?php
|
||||
|
||||
return [
|
||||
|
||||
'urls' =>
|
||||
[
|
||||
|
||||
'mojang' => [
|
||||
|
||||
'statuscheck' => env('MOJANG_STATUS_URL') ?? 'https://status.mojang.com/check'
|
||||
|
||||
]
|
||||
]
|
||||
|
||||
];
|
|
@ -22,6 +22,8 @@ class CreateVacanciesTable extends Migration
|
|||
$table->bigInteger('vacancyFormID')->unsigned();
|
||||
$table->integer('vacancyCount')->default(3);
|
||||
$table->timestamps();
|
||||
|
||||
$table->foreign('vacancyFormID')->references('id')->on('forms');
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,35 @@
|
|||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
class AddStatusToVacancies extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function up()
|
||||
{
|
||||
Schema::table('vacancies', function (Blueprint $table) {
|
||||
$table->enum('vacancyStatus', [
|
||||
'OPEN',
|
||||
'CLOSED'
|
||||
])->after('vacancyCount');
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function down()
|
||||
{
|
||||
Schema::table('vacancies', function (Blueprint $table) {
|
||||
$table->dropColumn('vacancyStatus');
|
||||
});
|
||||
}
|
||||
}
|
|
@ -0,0 +1,3 @@
|
|||
$(document).ready(function() {
|
||||
$('input[rel="txtTooltip"]').tooltip();
|
||||
});
|
|
@ -8,8 +8,114 @@
|
|||
|
||||
@stop
|
||||
|
||||
@section('js')
|
||||
|
||||
@if (session()->has('success'))
|
||||
|
||||
<script>
|
||||
toastr.success("{{session('success')}}")
|
||||
</script>
|
||||
|
||||
@elseif(session()->has('error'))
|
||||
<script>
|
||||
toastr.error("{{session('error')}}")
|
||||
</script>
|
||||
@endif
|
||||
|
||||
@if($errors->any())
|
||||
|
||||
@foreach ($errors->all() as $error)
|
||||
<script>toastr.error('{{$error}}', 'Validation error!')</script>
|
||||
@endforeach
|
||||
|
||||
@endif
|
||||
|
||||
@stop
|
||||
|
||||
@section('content')
|
||||
|
||||
<div class="modal fade" tabindex="-1" id="newVacancyForm" role="dialog" aria-labelledby="modalFormLabel" aria-hidden="true">
|
||||
<div class="modal-dialog" role="document">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title" id="modalFormLabel">New Vacancy</h5>
|
||||
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
|
||||
<span aria-hidden="true">×</span>
|
||||
</button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
|
||||
@if(!$forms->isEmpty())
|
||||
|
||||
<form id="savePositionForm" action="{{route('savePosition')}}" method="POST">
|
||||
@csrf
|
||||
<label for="vacancyName">Vacancy name (e.g. Helper)</label>
|
||||
<input type="text" id="vacancyName" name="vacancyName" class="form-control">
|
||||
|
||||
<label for="vacancyDescription">Vacancy Description</label>
|
||||
<input type="text" id="vacancyDescription" name="vacancyDescription" class="form-control">
|
||||
|
||||
<div class="row mt-3">
|
||||
|
||||
<div class="col">
|
||||
<label for="pgroup">Permission Group Name</label>
|
||||
<input rel="txtTooltip" title="The permission group from your server/network's permissions manager. Compatible with Luckperms and PEX." data-toggle="tooltip" data-placement="bottom" type="text" id="pgroup" name="permissionGroup" class="form-control">
|
||||
</div>
|
||||
|
||||
<div class="col">
|
||||
<label for="discordrole">Discord Role ID (*)</label>
|
||||
<input rel="txtTooltip" title="Discord Desktop: Go to your Account Settings > Appearance -> Advanced and toggle Developer Mode. On your server's roles tab, right click any role to copy it's ID." data-toggle="tooltip" data-placement="bottom" type="text" id="discordrole" name="discordRole" class="form-control">
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="form-group mt-4">
|
||||
|
||||
<label for="associatedForm">Application form</label>
|
||||
<select class="custom-select" name="vacancyFormID" id="associatedForm">
|
||||
|
||||
<option disabled>Select a form...</option>
|
||||
@foreach($forms as $form)
|
||||
|
||||
<option value="{{$form->id}}">{{$form->formName}}</option>
|
||||
|
||||
@endforeach
|
||||
|
||||
</select>
|
||||
|
||||
<label for="vacancyCount">Free slots</label>
|
||||
<input rel="txtTooltip" title="How many submissions before the vacancy stops accepting new applicants?" data-toggle="tooltip" data-placement="bottom" type="text" id="vacancyCount" name="vacancyCount" class="form-control">
|
||||
|
||||
|
||||
</div>
|
||||
</form>
|
||||
|
||||
@else
|
||||
|
||||
<div class="alert alert-danger">
|
||||
|
||||
<p>
|
||||
You cannot create a vacancy without any forms with which people would apply.
|
||||
Please create a form first, then, create a vacancy.
|
||||
A single form is allowed to have multiple vacancies, so you can attach future vacancies to the same form if you'd like.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
@endif
|
||||
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
|
||||
@if(!$forms->isEmpty())
|
||||
<button type="button" class="btn btn-primary" onclick="document.getElementById('savePositionForm').submit()">Add Vacancy</button>
|
||||
@endif
|
||||
|
||||
<button type="button" class="btn btn-secondary" data-dismiss="modal">Close</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
|
||||
<div class="col-md-4 offset-md-4 text-center">
|
||||
|
@ -18,7 +124,7 @@
|
|||
|
||||
<div class="card-body">
|
||||
|
||||
<button type="button" class="btn btn-primary">NEW POSITION</button>
|
||||
<button type="button" class="btn btn-primary" onclick="$('#newVacancyForm').modal('show')">NEW POSITION</button>
|
||||
|
||||
</div>
|
||||
|
||||
|
@ -40,40 +146,79 @@
|
|||
|
||||
<div class="card-body">
|
||||
|
||||
<table class="table table-active table-borderless">
|
||||
@if(!$vacancies->isEmpty())
|
||||
|
||||
<thead>
|
||||
<table class="table table-active table-borderless" style="white-space: nowrap">
|
||||
|
||||
<thead>
|
||||
|
||||
<tr>
|
||||
<th>#</th>
|
||||
<th>Vacancy Name</th>
|
||||
<th>Vacancy Description</th>
|
||||
<th>Date Created</th>
|
||||
<th>Date Updated</th>
|
||||
<th>Total Applicants</th>
|
||||
<th>Discord Role ID</th>
|
||||
<th>Perm. Group Name</th>
|
||||
<th>Open Slots</th>
|
||||
<th>Status</th>
|
||||
<th>Created On</th>
|
||||
<th>Actions</th>
|
||||
</tr>
|
||||
|
||||
</thead>
|
||||
</thead>
|
||||
|
||||
<tbody>
|
||||
<tbody>
|
||||
|
||||
<tr>
|
||||
<td>1</td>
|
||||
<td>Helper</td>
|
||||
<td>Help manage the server</td>
|
||||
<td>2020-04-03</td>
|
||||
<td>2020-05-01</td>
|
||||
<td>10</td>
|
||||
<td>
|
||||
<button type="button" class="btn btn-sm btn-danger"><i class="fa fa-ban"></i> Close Position</button>
|
||||
</td>
|
||||
</tr>
|
||||
@foreach($vacancies as $vacancy)
|
||||
|
||||
</tbody>
|
||||
<tr>
|
||||
|
||||
</table>
|
||||
<td>{{$vacancy->id}}</td>
|
||||
<td>{{$vacancy->vacancyName}}</td>
|
||||
<td>{{$vacancy->vacancyDescription}}</td>
|
||||
<td><span class="badge badge-success">{{$vacancy->discordRoleID}}</span></td>
|
||||
<td><span class="badge badge-success">{{$vacancy->permissionGroupName}}</span></td>
|
||||
<td>{{$vacancy->vacancyCount}}</td>
|
||||
@if($vacancy->vacancyStatus == 'OPEN')
|
||||
<td><span class="badge badge-success">OPEN</span></td>
|
||||
@else
|
||||
<td><span class="badge badge-danger">CLOSED</span></td>
|
||||
@endif
|
||||
<td>{{$vacancy->created_at}}</td>
|
||||
<td>
|
||||
@if ($vacancy->vacancyStatus == 'OPEN')
|
||||
|
||||
<form action="{{route('updatePositionAvailability', ['status' => 'close', 'id' => $vacancy->id])}}" method="POST" id="closePosition">
|
||||
@csrf
|
||||
@method('PATCH')
|
||||
<button type="submit" class="btn btn-sm btn-danger"><i class="fa fa-ban"></i> Close</button>
|
||||
</form>
|
||||
|
||||
@else
|
||||
|
||||
<form action="{{route('updatePositionAvailability', ['status' => 'open', 'id' => $vacancy->id])}}" method="POST" id="openPosition">
|
||||
@csrf
|
||||
@method('PATCH')
|
||||
<button type="submit" class="btn btn-sm btn-success"><i class="fa fa-check"></i> Open</button>
|
||||
</form>
|
||||
|
||||
@endif
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
@endforeach
|
||||
|
||||
</tbody>
|
||||
|
||||
</table>
|
||||
|
||||
@else
|
||||
|
||||
<div class="alert alert-warning">
|
||||
<p>Nothing to see here! Open some vacancies first. This will get applicants pouring in! (hopefully)</p>
|
||||
</div>
|
||||
|
||||
@endif
|
||||
</div>
|
||||
|
||||
<div class="card-footer">
|
||||
|
|
|
@ -65,7 +65,16 @@ Route::group(['middleware' => 'auth'], function(){
|
|||
|
||||
Route::group(['prefix' => 'admin'], function (){
|
||||
|
||||
Route::resource('positions', 'VacancyController');
|
||||
Route::get('positions', 'VacancyController@index')
|
||||
->name('showPositions');
|
||||
|
||||
Route::post('positions/save', 'VacancyController@store')
|
||||
->name('savePosition');
|
||||
|
||||
|
||||
Route::patch('positions/availability/{status}/{id}', 'VacancyController@updatePositionAvailability')
|
||||
->name('updatePositionAvailability');
|
||||
|
||||
|
||||
Route::get('forms/builder', 'FormController@showFormBuilder')
|
||||
->name('showFormBuilder');
|
||||
|
|
Loading…
Reference in New Issue