Skip to content

Commit

Permalink
#147 - Google CSV import to grades
Browse files Browse the repository at this point in the history
  • Loading branch information
krzysztofrewak committed Sep 19, 2024
1 parent 53ae281 commit fa6da11
Show file tree
Hide file tree
Showing 16 changed files with 245 additions and 49 deletions.
15 changes: 15 additions & 0 deletions .phpstorm.meta.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
<?php

namespace Illuminate\Database\Eloquent {
use Illuminate\Contracts\Database\Eloquent\Builder as BuilderContract;

class Builder implements BuilderContract {
public function whereLikeUnaccentInsensitive(string $column, mixed $value): static {
return $intance;
}

public function orWhereLikeUnaccentInsensitive(string $column, mixed $value): static {
return $intance;
}
}
}
12 changes: 6 additions & 6 deletions app/Http/Controllers/Dashboard/GradeController.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@
use Illuminate\Http\Request;
use Inertia\Response;
use Keating\DTOs\CourseSemesterData;
use Keating\Http\Requests\UpdateGrade;
use Keating\Http\Requests\UpdateGradeColumn;
use Keating\Http\Requests\UpdateGradeColumnRequest;
use Keating\Http\Requests\UpdateGradeRequest;
use Keating\Models\CourseSemester;
use Keating\Models\GradeColumn;
use Keating\Models\Group;
Expand Down Expand Up @@ -40,31 +40,31 @@ public function index(Request $request, CourseSemester $course, Group $group): R
]);
}

public function store(UpdateGradeColumn $request, CourseSemester $course, Group $group): RedirectResponse
public function store(UpdateGradeColumnRequest $request, CourseSemester $course, Group $group): RedirectResponse
{
$group->gradeColumns()->create($request->getData());

return redirect()->back()
->with("success", "Dodano kolumnę");
}

public function update(UpdateGradeColumn $request, CourseSemester $course, Group $group, GradeColumn $gradeColumn): RedirectResponse
public function update(UpdateGradeColumnRequest $request, CourseSemester $course, Group $group, GradeColumn $gradeColumn): RedirectResponse
{
$gradeColumn->update($request->getData());

return redirect()->back()
->with("success", "Zaktualizowano kolumnę");
}

public function storeGrade(UpdateGrade $request, CourseSemester $course, Group $group, GradeColumn $gradeColumn): RedirectResponse
public function storeGrade(UpdateGradeRequest $request, CourseSemester $course, Group $group, GradeColumn $gradeColumn): RedirectResponse
{
$gradeColumn->grades()
->create($request->getData());

return redirect()->back();
}

public function updateGrade(UpdateGrade $request, CourseSemester $course, Group $group, GradeColumn $gradeColumn): RedirectResponse
public function updateGrade(UpdateGradeRequest $request, CourseSemester $course, Group $group, GradeColumn $gradeColumn): RedirectResponse
{
$grade = $gradeColumn->grades()
->where("student_id", $request->get("student_id"))
Expand Down
50 changes: 50 additions & 0 deletions app/Http/Controllers/Dashboard/GradeImportController.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
<?php

declare(strict_types=1);

namespace Keating\Http\Controllers\Dashboard;

use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Routing\ResponseFactory;
use Inertia\Response;
use Keating\DTOs\CourseSemesterData;
use Keating\Models\CourseSemester;
use Keating\Models\Grade;
use Keating\Models\GradeColumn;
use Keating\Models\Group;

class GradeImportController
{
public function index(CourseSemester $course, Group $group, GradeColumn $column): Response
{
return inertia("Dashboard/CourseSemester/Grade/Import", [
"course" => CourseSemesterData::fromModel($course),
"group" => $group,
"column" => $column,
"csrfToken" => csrf_token(),
]);
}

public function prepare(Request $request, CourseSemester $course, Group $group, GradeColumn $column, ResponseFactory $response): JsonResponse
{
$students = $request;

return $response->json([
"students" => $column->refresh()->grades->map(fn(Grade $grade): array => [
"id" => $grade->id,
"column" => [
"id" => $column->id,
],
"student" => [
"id" => $grade->student->id,
"name" => $grade->student->fullName,
"indexNumber" => $grade->student->index_number,
],
"status" => $grade->status,
"value" => $grade->value,
"imported" => rand(0, 1) > .5,
]),
]);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

use Illuminate\Foundation\Http\FormRequest;

class UpdateGradeColumn extends FormRequest
class UpdateGradeColumnRequest extends FormRequest
{
public function rules(): array
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

use Illuminate\Foundation\Http\FormRequest;

class UpdateGrade extends FormRequest
class UpdateGradeRequest extends FormRequest
{
public function rules(): array
{
Expand Down
5 changes: 5 additions & 0 deletions app/Models/Grade.php
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,10 @@
* @property string $id
* @property ?boolean $status
* @property ?string $value
* @property string $student_id
* @property Student $student
* @property string $grade_column_id
* @property GradeColumn $gradeColumn
* @property Carbon $created_at
* @property Carbon $updated_at
*/
Expand All @@ -27,6 +31,7 @@ class Grade extends Model
"status",
"value",
"student_id",
"grade_column_id",
];
protected $casts = [
"status" => "boolean",
Expand Down
4 changes: 4 additions & 0 deletions app/Models/Group.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
namespace Keating\Models;

use Carbon\Carbon;
use Illuminate\Database\Eloquent\Collection;
use Illuminate\Database\Eloquent\Concerns\HasUlids;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
Expand All @@ -18,6 +19,9 @@
* @property string $name
* @property string $course_semester_id
* @property StudyForm $form
* @property CourseSemester course
* @property Collection<Student> students
* @property Collection<GradeColumn> gradeColumns
* @property Carbon $created_at
* @property Carbon $updated_at
*/
Expand Down
9 changes: 9 additions & 0 deletions app/Models/Student.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
namespace Keating\Models;

use Carbon\Carbon;
use Illuminate\Database\Eloquent\Casts\Attribute;
use Illuminate\Database\Eloquent\Concerns\HasUlids;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
Expand All @@ -16,6 +17,7 @@
* @property string $first_name
* @property string $surname
* @property string $index_number
* @property-read string $fullName
* @property Carbon $created_at
* @property Carbon $updated_at
*/
Expand All @@ -30,6 +32,13 @@ class Student extends Model
"index_number",
];

public function fullName(): Attribute
{
return new Attribute(
get: fn(): string => $this->first_name . " " . $this->surname,
);
}

public function groups(): BelongsToMany
{
return $this->belongsToMany(Group::class, "student_group");
Expand Down
14 changes: 12 additions & 2 deletions app/Providers/BuilderServiceProvider.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,19 @@

class BuilderServiceProvider extends ServiceProvider
{
/**
* all macros are also registered in .phpstorm.meta.php file
*/
public function boot(): void
{
Builder::macro("whereLikeUnaccentInsensitive", fn($column, $search): Builder => $this->whereRaw("unaccent($column) ILIKE unaccent(?)", ["%{$search}%"]));
Builder::macro("orWhereLikeUnaccentInsensitive", fn($column, $search): Builder => $this->orWhereRaw("unaccent($column) ILIKE unaccent(?)", ["%{$search}%"]));
Builder::macro(
"whereLikeUnaccentInsensitive",
fn($column, $search): Builder => $this->whereRaw("unaccent($column) ILIKE unaccent(?)", ["%{$search}%"]),
);

Builder::macro(
"orWhereLikeUnaccentInsensitive",
fn($column, $search): Builder => $this->orWhereRaw("unaccent($column) ILIKE unaccent(?)", ["%{$search}%"]),
);
}
}
2 changes: 0 additions & 2 deletions codestyle.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,12 @@
use Blumilk\Codestyle\Config;
use Blumilk\Codestyle\Configuration\Defaults\CommonRules;
use Blumilk\Codestyle\Configuration\Defaults\LaravelPaths;
use PhpCsFixer\Fixer\LanguageConstruct\ClassKeywordFixer;

$paths = new LaravelPaths();
$rules = new CommonRules();

$config = new Config(
paths: $paths->add("codestyle.php"),
rules: $rules->filter(ClassKeywordFixer::class),
);

return $config->config();
2 changes: 1 addition & 1 deletion database/factories/GradeColumnFactory.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ class GradeColumnFactory extends Factory
public function definition(): array
{
return [
"name" => fake()->asciify("***"),
"name" => fake()->numerify("W#"),
"active" => fake()->boolean,
"priority" => fake()->numberBetween(1, 100),
"group_id" => Group::factory(),
Expand Down
96 changes: 96 additions & 0 deletions resources/js/Pages/Dashboard/CourseSemester/Grade/Import.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
<script setup>
import DashboardLayout from '@/Layouts/DashboardLayout.vue'
import ManagementHeader from '@/Shared/Components/ManagementHeader.vue'
import Section from '@/Shared/Components/Section.vue'
import SubmitButton from '@/Shared/Components/Buttons/SubmitButton.vue'
import FormGroup from '@/Shared/Forms/FormGroup.vue'
import FormLabel from '@/Shared/Forms/FormLabel.vue'
import { useForm } from '@inertiajs/inertia-vue3'
import FormError from '@/Shared/Forms/FormError.vue'
import TableWrapper from '@/Shared/Components/Table/Public/TableWrapper.vue'
import TableRow from '@/Shared/Components/Table/Public/TableRow.vue'
import TableCell from '@/Shared/Components/Table/Public/TableCell.vue'
import GradeCell from '@/Shared/Components/GradeCell.vue'
const props = defineProps({
course: Object,
group: Object,
column: Object,
csrfToken: String,
})
const preparationForm = useForm({
content: '',
})
const gradesForm = useForm({
grades: '',
})
function prepareStudentsList() {
fetch(`/dashboard/semester-courses/${props.course.id}/groups/${props.group.id}/grades/${props.column.id}/prepare`)
.then(response => response.json())
.then(data => {
gradesForm.grades = data['students']
})
}
</script>

<template>
<DashboardLayout>
<div class="flex flex-col gap-8">
<ManagementHeader>
<template #header>
Import aktywności studentów
<span class="text-gray-500">{{ group.name }}</span>
<br> dla kursu
<span class="text-gray-500">{{ course.course }}</span>
dla oceny
<span class="text-gray-500">{{ column.name }}</span>
</template>
</ManagementHeader>
<div class="grid grid-cols-2 gap-8">
<Section>
<form class="flex flex-col justify-between gap-4" @submit.prevent="prepareStudentsList()">
<FormGroup>
<FormLabel for="content">
Lista studentów do zaimportowania
<span class="text-gray-500">(z pliku CSV przysłanego z Google Workspace)</span>
</FormLabel>
<textarea v-model="preparationForm.content" class="block h-[320px] w-full rounded-md border-0 py-1.5 text-gray-900 shadow-sm ring-1 ring-inset ring-gray-300 placeholder:text-gray-400 sm:text-sm sm:leading-6" />
<FormError :error="preparationForm.errors.content" />
</FormGroup>
<div class="mt-4 flex justify-end">
<SubmitButton>
przygotuj
</SubmitButton>
</div>
</form>
</Section>
<Section>
<FormLabel for="content">
Lista ocen
</FormLabel>
<TableWrapper class="mt-2">
<template #body>
<TableRow v-for="data in gradesForm.grades" :key="data.student.id">
<TableCell class="h-[70px] w-1 cursor-pointer flex-row border-2">
<div class="text-nowrap font-bold">
{{ data.student.name }}
</div>
<div>
({{ data.student.indexNumber }})
</div>
</TableCell>
<GradeCell :grade="data" :grade-column="data.column" :student="data.student" class="cursor-pointer border-2" @create-grade="createGrade" @update-grade="updateGrade" />
<TableCell class="h-[70px] w-1 cursor-pointer flex-row border-2">
<span v-if="data.imported">zaimportowane</span>
</TableCell>
</TableRow>
</template>
</TableWrapper>
</Section>
</div>
</div>
</DashboardLayout>
</template>
Loading

0 comments on commit fa6da11

Please sign in to comment.