Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Topicos #122

Merged
merged 20 commits into from
Jul 2, 2024
28 changes: 19 additions & 9 deletions app/Http/Controllers/ExercicioController.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
use Illuminate\Http\Request;
use App\Models\Exercicio;
use App\Models\Teste;
use App\Models\Topico;
use App\Models\Impedimento;
use App\Utils\TmpFile;
use Illuminate\Support\Str;
Expand All @@ -26,17 +27,22 @@ class ExercicioController extends Controller
/**
* Display a listing of the resource.
*
* @return \Illuminate\Http\Response
*/
public function index()
{
$exercicios = Exercicio::orderBy('name');
/** @var \App\Models\User */
$user = Auth::user();
if (!$user || !$user->isAdmin()) {
$exercicios = $exercicios->published();
}
return View('exercicio.index')->with('exercicios', $exercicios->get());
$topicos = Topico::orderBy('order');
$semTopico = Exercicio::whereDoesntHave('topico')->orderBy('name');
/** @var \App\Models\User */
$user = Auth::user();
if (optional($user)->isAdmin()) {
$topicos = $topicos->with('exercicios');
} else {
$topicos = $topicos->with('exerciciosPublished');
$semTopico = $semTopico->published();
}

return View('exercicio.index')->with('topicos', $topicos->get())
->with('semTopico', $semTopico->get());
}

/**
Expand All @@ -47,7 +53,9 @@ public function index()
public function create()
{
$this->authorize('create', Exercicio::class);
return View('exercicio.create')->with('pacotesR', $this->getInstalledPackages());
return View('exercicio.create')
->with('pacotesR', $this->getInstalledPackages())
->with('topicos', Topico::orderBy('order'));
}

/**
Expand All @@ -62,6 +70,7 @@ private function validateExercicio(Request $request, Exercicio|null $exercicio)
'name' => 'required|string|unique:exercicios' . ($exercicio ? ',name,' . $exercicio->id : ''),
'description' => 'required',
'precondicoes' => 'sometimes',
'topico_id' => 'sometimes|int|exists:topicos,id|nullable',
'dicas' => 'array',
'condicoes' => 'array',
'pesos' => 'array',
Expand Down Expand Up @@ -370,6 +379,7 @@ public function edit(Exercicio $exercicio)
return View('exercicio.edit')
->with('exercicio', $exercicio)
->with('exercicio.testes', $exercicio->testes)
->with('topicos', Topico::orderBy('order')->get())
->with('pacotesR', $this->getInstalledPackages());
}

Expand Down
129 changes: 129 additions & 0 deletions app/Http/Controllers/TopicoController.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,129 @@
<?php

namespace App\Http\Controllers;

use App\Models\Topico;
use App\Models\Exercicio;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\DB;

class TopicoController extends Controller
{
/**
* Display a listing of the resource.
*/
public function index()
{
return redirect()->action([ExercicioController::class, 'index']);
}

/**
* Show the form for creating a new resource.
*/
public function create()
{
return View('topico.create');
}

/**
* Store a newly created resource in storage.
*/
public function store(Request $request)
{
$this->authorize('create', Topico::class);
$rules = array(
'name' => 'required',
);
$data = $request->validate($rules);

// set order of new Topico
$data['order'] = Topico::max('order') + 1;

// store
$topico = tap(new Topico($data))->save();

// redirect to show
return redirect()->action([get_class($this), 'show'], ['topico' => $topico]);
}

/**
* Display the specified resource.
*/
public function show(Topico $topico)
{
// index is the same for exercicio and topico
return redirect()->action([get_class($this), 'index']);
Lobz marked this conversation as resolved.
Show resolved Hide resolved
}

/**
* Show the form for editing the specified resource.
*/
public function edit(Topico $topico)
{
$this->authorize('edit', $topico);
return View('topico.edit')->with('topico', $topico);
}

/**
* Update the specified resource in storage.
*/
public function update(Request $request, Topico $topico)
{
$this->authorize('edit', $topico);

$rules = [
'name' => 'required',
];
$data = $request->validate($rules);
$topico->update(['name' => $data['name']]);
return redirect()->action([get_class($this), 'index']);
}

/**
* Remove the specified resource from storage.
*/
public function destroy(Topico $topico)
{
$this->authorize('delete', $topico);
// remove exercicios
$topico->exercicios()->detach();

$topico->delete();
return redirect()->action([get_class($this), 'index']);
}

/**
* Show form for reordering of Topico
*/
public function sort()
{
$this->authorize('sort', Topico::class);
$topicos = Topico::orderBy('order')->get();

return View('topico.sort')->with('topicos', $topicos);
}

/**
* Update order of topicos
*/
public function order(Request $request)
{
$this->authorize('sort', Topico::class);
$rules = [
'topico_id.*' => 'required|int',
];

$data = $request->validate($rules);

// We want to commit all changes at once
DB::beginTransaction();
foreach($data['topico_id'] as $i => $id) {
$model = Topico::find($id);
$model->update(['order' => $i]);
}
DB::commit();

return redirect()->action([get_class($this), 'index']);
}
}
7 changes: 7 additions & 0 deletions app/Models/Exercicio.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,10 @@ class Exercicio extends Model
{
use HasFactory;
protected $table = 'exercicios';

protected $fillable = [
'name',
'topico_id',
'description',
'precondicoes',
'draft'
Expand Down Expand Up @@ -69,6 +71,11 @@ public function notas()
return $this->hasMany(Nota::class);
}

public function topico()
{
return $this->belongsTo(Topico::class);
}

/** Generate exportable string
*
* @return String
Expand Down
24 changes: 24 additions & 0 deletions app/Models/Topico.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;

class Topico extends Model
{
use HasFactory;
protected $table = 'topicos';
protected $guarded = [];

// relationships
public function exercicios()
{
return $this->hasMany(Exercicio::class);
}
// scope published
public function exerciciosPublished()
{
return $this->hasMany(Exercicio::class)->published();
}
}
81 changes: 81 additions & 0 deletions app/Policies/TopicoPolicy.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
<?php

namespace App\Policies;

use App\Models\User;
use App\Models\Topico;
use Illuminate\Auth\Access\HandlesAuthorization;

class TopicoPolicy
{
use HandlesAuthorization;

/**
* Determine whether the user can view the list or index.
*
* @param \App\Models\User $user
* @return mixed
*/
public function list(User $user)
{
return true;
}

/**
* Determine whether the user can view the model.
*
* @param \App\Models\User $user
* @param \App\Models\Topico $topico
* @return mixed
*/
public function view(User $user, Topico $topico)
{
return true;
}

/**
* Determine whether the user can create models.
*
* @param \App\Models\User $user
* @return mixed
*/
public function create(User $user)
{
return $user->isAdmin();
}

/**
* Determine whether the user can update the model.
*
* @param \App\Models\User $user
* @param \App\Models\Topico $topico
* @return mixed
*/
public function edit(User $user, Topico $topico)
{
return $user->isAdmin();
}

/**
* Determine whether the user can delete the model.
*
* @param \App\Models\User $user
* @param \App\Models\Topico $topico
* @return mixed
*/
public function delete(User $user, Topico $topico)
{
return $user->isAdmin();
}

/**
* Determine whether the user can reorder the models.
*
* @param \App\Models\User $user
* @return mixed
*/
public function sort(User $user)
{
return $user->isAdmin();
}
}
31 changes: 31 additions & 0 deletions database/factories/TopicoFactory.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
<?php
Lobz marked this conversation as resolved.
Show resolved Hide resolved

namespace Database\Factories;
use App\Models\Topico;

use Illuminate\Database\Eloquent\Factories\Factory;

/**
* @extends \Illuminate\Database\Eloquent\Factories\Factory<\App\Models\Topico>
*/
class TopicoFactory extends Factory
{
/**
* The name of the factory's corresponding model.
*
* @var string
*/
protected $model = Topico::class;
/**
* Define the model's default state.
*
* @return array<string, mixed>
*/
public function definition(): array
{
return [
'name' => $this->faker->sentence(3),
'order' => $this->faker->randomNumber(1),
];
}
}
36 changes: 36 additions & 0 deletions database/migrations/2024_06_06_151506_create_topicos_table.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
<?php

use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::create('topicos', function (Blueprint $table) {
$table->id();
$table->string('name');
$table->integer('order')->unsigned();
$table->timestamps();
});
Schema::table('exercicios', function (Blueprint $table) {
$table->foreignId('topico_id')->nullable()->constrained();
});
}

/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::table('exercicios', function (Blueprint $table) {
$table->dropForeign(['topico_id']);
$table->dropColumn('topico_id');
});
Schema::dropIfExists('topicos');
}
};
Loading