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

#37 - After filling test, the user should receive email about that #126

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
87c84cf
create mail for close quiz action
AmonDeShir Dec 10, 2024
3c574d7
add queue:listen to makefile
AmonDeShir Dec 10, 2024
20a334b
remove duplicate recipes
AmonDeShir Dec 10, 2024
c075f49
split quiz controller logic into action files
AmonDeShir Dec 10, 2024
5eeeeba
add tests for actions
AmonDeShir Dec 10, 2024
6aa38f6
test user model
AmonDeShir Dec 10, 2024
e10768f
remove randomness from test
AmonDeShir Dec 10, 2024
364a5a6
fix command name
AmonDeShir Dec 10, 2024
c854524
implement sending notification when quiz is closed
AmonDeShir Dec 10, 2024
aedc2a3
fix wasClosedManually method
AmonDeShir Dec 11, 2024
029c95e
prepare quizzes for testing
AmonDeShir Dec 11, 2024
bad26cd
fix filterArchivedQuizzes method
AmonDeShir Dec 11, 2024
3a18bfa
add archived quiz to seeder
AmonDeShir Dec 11, 2024
0cc5238
fix code style
AmonDeShir Dec 11, 2024
95ffc26
fix no answer warning
AmonDeShir Dec 11, 2024
4d2b34b
change number to int
AmonDeShir Dec 12, 2024
0c02cfe
add return type
AmonDeShir Dec 12, 2024
01a65da
move isClosingToday logic to sql
AmonDeShir Dec 12, 2024
a867f29
Merge branch 'main' into 37-tests-after-filling-test-the-user-should-…
AmonDeShir Dec 12, 2024
5849139
Merge branch 'main' into 37-tests-after-filling-test-the-user-should-…
AmonDeShir Dec 12, 2024
f00b874
revert to non-SQL version
AmonDeShir Dec 12, 2024
ebed49f
Merge branch '37-tests-after-filling-test-the-user-should-receive-ema…
AmonDeShir Dec 12, 2024
1b876fb
Merge branch 'main' of https://github.com/blumilksoftware/interns2024…
AmonDeShir Dec 12, 2024
6edda89
Revert "- Update all non-major dependencies with digest and pinDigest…
AmonDeShir Dec 12, 2024
ce51f7e
fix namespaces
AmonDeShir Dec 12, 2024
04796ad
fix code style
AmonDeShir Dec 12, 2024
93eac0e
replace nunomaduro/larastan with larastan/larastan
AmonDeShir Dec 12, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions .github/workflows/test-and-lint-js.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,17 +19,17 @@ jobs:
runs-on: ubuntu-latest

steps:
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 # https://github.com/actions/checkout
- uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 # v4.2.0 # https://github.com/actions/checkout

- name: Cache dependencies
uses: actions/cache@1bd1e32a3bdc45362d1e726936510720a7c30a57 # v4.2.0 # https://github.com/actions/cache
uses: actions/cache@0c45773b623bea8c8e75f6c82b208c3cf94ea4f9 # v4.0.2 # https://github.com/actions/cache
with:
path: node_modules
key: ${{ runner.os }}-npm-dependencies-${{ hashFiles('package.lock') }}
restore-keys: ${{ runner.os }}-npm-dependencies

- name: Set up node
uses: actions/setup-node@39370e3970a6d050c480ffad4ff0ed4d3fdee5af # v4.1.0 # https://github.com/actions/setup-node
uses: actions/setup-node@0a44ba7841725637a19e28fa30b79a866c81b0a6 # v4.0.4 # https://github.com/actions/setup-node
with:
node-version: 21

Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/test-and-lint-php.yml
Original file line number Diff line number Diff line change
Expand Up @@ -34,13 +34,13 @@ jobs:
- 5432:5432

steps:
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 # https://github.com/actions/checkout
- uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 # v4.2.0 # https://github.com/actions/checkout

- name: Validate composer.json and composer.lock
run: composer validate

- name: Cache dependencies
uses: actions/cache@1bd1e32a3bdc45362d1e726936510720a7c30a57 # v4.2.0 # https://github.com/actions/cache
uses: actions/cache@0c45773b623bea8c8e75f6c82b208c3cf94ea4f9 # v4.0.2 # https://github.com/actions/cache
with:
path: vendor
key: ${{ runner.os }}-composer-dependencies-${{ hashFiles('composer.lock') }}
Expand Down
8 changes: 4 additions & 4 deletions app/Actions/AssignToQuizAction.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,12 @@
class AssignToQuizAction
{
/**
* @param Collection<User> $users
* @param Collection<int> $userIds
*/
public function execute(Quiz $quiz, Collection $users): void
public function execute(Quiz $quiz, Collection $userIds): void
{
$assignedUsers = $quiz->assignedUsers;
$users = User::query()->whereIn("id", $users)->get();
$assignedUsers = $quiz->assignedUsers()->get();
$users = User::query()->whereIn("id", $userIds)->get();

$users = $users->filter(fn(User $user) => !$assignedUsers->contains($user));
$quiz->assignedUsers()->attach($users);
Expand Down
3 changes: 3 additions & 0 deletions app/Actions/CloseUserQuizAction.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

namespace App\Actions;

use App\Events\UserQuizClosed;
use App\Models\UserQuiz;
use Carbon\Carbon;

Expand All @@ -13,5 +14,7 @@ public function execute(UserQuiz $userQuiz): void
{
$userQuiz->closed_at = Carbon::now();
$userQuiz->save();

event(new UserQuizClosed($userQuiz));
}
}
22 changes: 22 additions & 0 deletions app/Actions/CreateUserQuestionAction.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
<?php

declare(strict_types=1);

namespace App\Actions;

use App\Models\Question;
use App\Models\UserQuestion;
use App\Models\UserQuiz;

class CreateUserQuestionAction
{
public function execute(Question $question, UserQuiz $userQuiz): UserQuestion
{
$userQuestion = new UserQuestion();
$userQuestion->userQuiz()->associate($userQuiz);
$userQuestion->question()->associate($question);
$userQuestion->save();

return $userQuestion;
}
}
31 changes: 31 additions & 0 deletions app/Actions/CreateUserQuizAction.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
<?php

declare(strict_types=1);

namespace App\Actions;

use App\Models\Quiz;
use App\Models\User;
use App\Models\UserQuiz;

class CreateUserQuizAction
{
public function __construct(
protected CreateUserQuestionAction $action,
) {}

public function execute(Quiz $quiz, User $user): UserQuiz
{
$userQuiz = new UserQuiz();
$userQuiz->closed_at = $quiz->closeAt;
$userQuiz->quiz()->associate($quiz);
$userQuiz->user()->associate($user);
$userQuiz->save();

foreach ($quiz->questions as $question) {
$this->action->execute($question, $userQuiz);
}

return $userQuiz;
}
}
22 changes: 22 additions & 0 deletions app/Actions/LockQuizAction.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
<?php

declare(strict_types=1);

namespace App\Actions;

use App\Jobs\CloseUserQuizJob;
use App\Models\Quiz;
use Carbon\Carbon;

class LockQuizAction
{
public function execute(Quiz $quiz): void
{
$quiz->locked_at = Carbon::now();
$quiz->save();

if ($quiz->isClosingToday()) {
CloseUserQuizJob::dispatch($quiz)->delay($quiz->closeAt);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
use App\Models\User;
use Illuminate\Support\Collection;

class UnassignToQuizAction
class UnassignFromQuizAction
{
/**
* @param Collection<User> $users
Expand All @@ -17,7 +17,8 @@ public function execute(Quiz $quiz, Collection $users): void
{
$assignedUsers = $quiz->assignedUsers;
$users = User::query()->whereIn("id", $users)->get();
$users = $users->filter(fn(User $user) => $assignedUsers->contains($user));

$users = $users->filter(fn(User $user): bool => $assignedUsers->contains($user));
$quiz->assignedUsers()->detach($users);
}
}
16 changes: 16 additions & 0 deletions app/Actions/UnlockQuizAction.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
<?php

declare(strict_types=1);

namespace App\Actions;

use App\Models\Quiz;

class UnlockQuizAction
{
public function execute(Quiz $quiz): void
{
$quiz->locked_at = null;
$quiz->save();
}
}
24 changes: 24 additions & 0 deletions app/Console/Commands/DispatchUserQuizClosedEvent.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
<?php

declare(strict_types=1);

namespace App\Console\Commands;

use App\Jobs\CloseUserQuizJob;
use App\Models\Quiz;
use Illuminate\Console\Command;

class DispatchUserQuizClosedEvent extends Command
{
protected $signature = "app:dispatch-user-quiz-closed-event";
protected $description = "Dispatches the UserQuizClosed event for quizzes that are closing today.";

public function handle(): void
{
foreach (Quiz::all() as $quiz) {
EwelinaSkrzypacz marked this conversation as resolved.
Show resolved Hide resolved
if ($quiz->isClosingToday()) {
CloseUserQuizJob::dispatch($quiz)->delay($quiz->closeAt);
}
}
}
}
23 changes: 23 additions & 0 deletions app/Events/AssignedQuizClosed.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
<?php

declare(strict_types=1);

namespace App\Events;

use App\Models\Quiz;
use App\Models\User;
use Illuminate\Broadcasting\InteractsWithSockets;
use Illuminate\Foundation\Events\Dispatchable;
use Illuminate\Queue\SerializesModels;

class AssignedQuizClosed
{
use Dispatchable;
use InteractsWithSockets;
use SerializesModels;

public function __construct(
public Quiz $quiz,
public User $user,
) {}
}
21 changes: 21 additions & 0 deletions app/Events/UserQuizClosed.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
<?php

declare(strict_types=1);

namespace App\Events;

use App\Models\UserQuiz;
use Illuminate\Broadcasting\InteractsWithSockets;
use Illuminate\Foundation\Events\Dispatchable;
use Illuminate\Queue\SerializesModels;

class UserQuizClosed
{
use Dispatchable;
use InteractsWithSockets;
use SerializesModels;

public function __construct(
public UserQuiz $userQuiz,
) {}
}
4 changes: 2 additions & 2 deletions app/Http/Controllers/InviteController.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
namespace App\Http\Controllers;

use App\Actions\AssignToQuizAction;
use App\Actions\UnassignToQuizAction;
use App\Actions\UnassignFromQuizAction;
use App\Helpers\SortHelper;
use App\Http\Requests\InviteQuizRequest;
use App\Http\Resources\QuizResource;
Expand Down Expand Up @@ -51,7 +51,7 @@ public function assign(Quiz $quiz, InviteQuizRequest $request, AssignToQuizActio
->with("status", "Użytkownicy zostali przypisani do quizu.");
}

public function unassign(Quiz $quiz, InviteQuizRequest $request, UnassignToQuizAction $unassignAction): RedirectResponse
public function unassign(Quiz $quiz, InviteQuizRequest $request, UnassignFromQuizAction $unassignAction): RedirectResponse
{
$this->authorize("invite", $quiz);

Expand Down
5 changes: 3 additions & 2 deletions app/Http/Controllers/QuestionAnswerController.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
use App\Http\Requests\AnswerRequest;
use App\Models\Answer;
use App\Models\Question;
use App\Services\QuizCloneService;
use Illuminate\Http\RedirectResponse;

class QuestionAnswerController extends Controller
Expand Down Expand Up @@ -52,9 +53,9 @@ public function destroy(Answer $answer): RedirectResponse
return redirect()->back();
}

public function clone(Answer $answer, Question $question): RedirectResponse
public function clone(QuizCloneService $service, Answer $answer, Question $question): RedirectResponse
{
$answer->cloneTo($question);
$service->cloneAnswer($answer, $question);

return redirect()
->back()
Expand Down
33 changes: 17 additions & 16 deletions app/Http/Controllers/QuizController.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,16 @@

namespace App\Http\Controllers;

use App\Actions\AssignToQuizAction;
use App\Actions\CreateUserQuizAction;
use App\Actions\LockQuizAction;
use App\Actions\UnlockQuizAction;
use App\Helpers\SortHelper;
use App\Http\Requests\QuizRequest;
use App\Http\Requests\UpdateQuizRequest;
use App\Http\Resources\QuizResource;
use App\Models\Quiz;
use App\Services\QuizCloneService;
use App\Services\QuizUpdateService;
use Carbon\Carbon;
use Illuminate\Database\Eloquent\Builder;
Expand All @@ -17,6 +22,7 @@
use Inertia\Inertia;
use Inertia\Response;

use function collect;
use function redirect;

class QuizController extends Controller
Expand Down Expand Up @@ -60,48 +66,43 @@ public function destroy(Quiz $quiz): RedirectResponse
return redirect()->back();
}

public function clone(Quiz $quiz): RedirectResponse
public function clone(QuizCloneService $service, Quiz $quiz): RedirectResponse
{
$quiz->clone();
$service->cloneQuiz($quiz);

return redirect()
->back()
->with("status", "Test został skopiowany");
}

public function lock(Quiz $quiz): RedirectResponse
public function lock(LockQuizAction $action, Quiz $quiz): RedirectResponse
{
$quiz->locked_at = Carbon::now();
$quiz->save();
$action->execute($quiz);

return redirect()
->back()
->with("status", "Test oznaczony jako gotowy do publikacji");
}

public function unlock(Quiz $quiz): RedirectResponse
public function unlock(UnlockQuizAction $action, Quiz $quiz): RedirectResponse
{
$quiz->locked_at = null;
$quiz->save();
$action->execute($quiz);

return redirect()
->back()
->with("status", "Publikacja testu została wycofana");
}

public function createUserQuiz(Request $request, Quiz $quiz): RedirectResponse
public function createUserQuiz(CreateUserQuizAction $action, Request $request, Quiz $quiz): RedirectResponse
{
$user = $request->user();
$userQuiz = $quiz->createUserQuiz($user);
$userQuiz = $action->execute($quiz, $request->user());

return redirect("/quizzes/{$userQuiz->id}/");
}

public function assign(Request $request, Quiz $quiz): RedirectResponse
public function assign(AssignToQuizAction $action, Request $request, Quiz $quiz): RedirectResponse
{
$user = $request->user();
$quiz->assignedUsers()->attach($user);
$quiz->save();
$action->execute($quiz, collect([$request->user()->id]));

return redirect()
->back()
Expand All @@ -113,7 +114,7 @@ private function filterArchivedQuizzes(Builder $query, Request $request): Builde
$showArchived = $request->query("archived", "false") === "true";

if (!$showArchived) {
return $query->orWhere(fn(Builder $query) => $query->whereNull("locked_at")->orWhereDate("scheduled_at", ">", Carbon::now()));
return $query->orWhere(fn(Builder $query) => $query->whereNull("locked_at")->orWhere("scheduled_at", ">", Carbon::now()));
}

return $query;
Expand Down
Loading
Loading