Skip to content

Commit

Permalink
Merge pull request #165 from scify/master
Browse files Browse the repository at this point in the history
Supervisor task
  • Loading branch information
PavlosIsaris authored Nov 27, 2024
2 parents bff7a91 + a96b098 commit 2b205de
Show file tree
Hide file tree
Showing 7 changed files with 224 additions and 10 deletions.
43 changes: 39 additions & 4 deletions app/BusinessLogicLayer/Solution/SolutionManager.php
Original file line number Diff line number Diff line change
Expand Up @@ -37,11 +37,18 @@ public function __construct(
$this->languageRepository = $languageRepository;
}

public function getCreateEditSolutionViewModel(int $problem_id, ?int $id = null): CreateEditSolution {
$problem = $this->problemRepository->find($problem_id);
/**
* In create mode $problem_id is passed to fn & $solution_id is null
* In edit mode $problem_id is null & $solution_id is passed to fn
*/
public function getCreateEditSolutionViewModel(?int $problem_id, ?int $solution_id = null): CreateEditSolution {
if ($problem_id) {
$problem = $this->problemRepository->find($problem_id);
}

if ($id) {
$solution = $this->solutionRepository->find($id);
if ($solution_id) {
$solution = $this->solutionRepository->find($solution_id);
$problem = $solution->problem;
} else {
$solution = new Solution;
$solution->setRelation('defaultTranslation', new SolutionTranslation);
Expand Down Expand Up @@ -99,4 +106,32 @@ public function storeSolution(array $attributes): int {
DB::rollBack();
}
}

/**
* @throws RepositoryException
*/
public function updateSolution(int $id, array $attributes) {
if (isset($attributes['solution-image']) && $attributes['solution-image']->isValid()) {
$imgPath = FileHandler::uploadAndGetPath($attributes['solution-image'], 'solution_img');
} else {
$imgPath = self::DEFAULT_IMAGE_PATH;
}

$modelAttributes['problem_id'] = $attributes['solution-owner-problem'];
$modelAttributes['slug'] = $attributes['solution-slug'];
$modelAttributes['status_id'] = $attributes['solution-status'];
$modelAttributes['img_url'] = $imgPath;
$this->solutionRepository->update($modelAttributes, $id);

$default_language_id = $this->problemRepository->find($modelAttributes['problem_id'])->default_language_id;

$defaultTranslation = [
'language_id' => $default_language_id,
'title' => $attributes['solution-title'],
'description' => $attributes['solution-description'],
];
$extraTranslations = isset($attributes['extra_translations']) ? json_decode($attributes['extra_translations']) : [];
$this->solutionTranslationManager
->updateSolutionTranslations($id, $defaultTranslation, $extraTranslations);
}
}
108 changes: 108 additions & 0 deletions app/BusinessLogicLayer/Solution/SolutionTranslationManager.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,21 @@
namespace App\BusinessLogicLayer\Solution;

use App\Models\Solution\Solution;
use App\Repository\Solution\SolutionRepository;
use App\Repository\Solution\SolutionTranslationRepository;
use Exception;
use Illuminate\Support\Collection;

class SolutionTranslationManager {
protected SolutionTranslationRepository $solutionTranslationRepository;
protected SolutionRepository $solutionRepository;

public function __construct(
SolutionTranslationRepository $solutionTranslationRepository,
SolutionRepository $solutionRepository,
) {
$this->solutionTranslationRepository = $solutionTranslationRepository;
$this->solutionRepository = $solutionRepository;
}

/**
Expand All @@ -37,4 +42,107 @@ public function getTranslationsForSolution(int|Solution $input): Collection {

return $this->solutionTranslationRepository->allWhere(['solution_id' => $id]);
}

/**
* @throws RepositoryException
*/
public function updateSolutionTranslations(int $solutionId, array $defaultTranslation, array $extraTranslations): void {
$this->updateSolutionDefaultTranslation($solutionId, $defaultTranslation);

$this->updateSolutionExtraTranslations($solutionId, $extraTranslations);
}

/**
* Updates the default translation for a solution.
*/
protected function updateSolutionDefaultTranslation(int $solutionId, array $defaultTranslation): void {
$this->solutionTranslationRepository->updateOrCreate(
[
'solution_id' => $solutionId,
'language_id' => $defaultTranslation['language_id'],
],
[
'title' => $defaultTranslation['title'],
'description' => $defaultTranslation['description'],
]
);
}

/**
* Updates the extra translations for a solution.
*
* @throws \App\Repository\RepositoryException
*/
protected function updateSolutionExtraTranslations(int $solutionId, array $newExtraTranslations): void {
$solutionDefaultTranslationId = $this->solutionRepository->find($solutionId)->default_language_id;
$oldExtraTranslations = $this->getTranslationsForSolution($solutionId)->whereNotIn('language_id', $solutionDefaultTranslationId);
$alreadyUpdatedExtraTranslations = [];

// for each of the already existing translations
foreach ($oldExtraTranslations as $oldExtraTranslation) {
// if there is a new translation, update the already existing translation in DB
if ($this->translationExistsInTranslationsArray($oldExtraTranslation, $newExtraTranslations)) {
$newExtraTranslation = $this->getTranslationFromTranslationsArrayViaLanguageId($newExtraTranslations, $oldExtraTranslation->language_id);
$solutionAndLanguage = [
'solution_id' => $solutionId,
'language_id' => $oldExtraTranslation['language_id'],
];
$this->solutionTranslationRepository->update(
array_merge($solutionAndLanguage, [
'title' => $newExtraTranslation->title,
'description' => $newExtraTranslation->description,
]),
$solutionAndLanguage,
$solutionAndLanguage
);

// keep track that the translation has already been updated in the DB
$alreadyUpdatedExtraTranslations[] = $newExtraTranslation;
} else {
// else delete the already existing translation from the DB
$this->solutionTranslationRepository->deleteTranslation($solutionId, $oldExtraTranslation['language_id']);
}
}

// now we need to add the new translations
foreach ($newExtraTranslations as $newExtraTranslation) {
// if not already updated, create the record in the DB
if (!$this->translationExistsInTranslationsArray($newExtraTranslation, $alreadyUpdatedExtraTranslations)) {
$this->solutionTranslationRepository->create(
[
'solution_id' => $solutionId,
'language_id' => $newExtraTranslation->language_id,
'title' => $newExtraTranslation->title,
'description' => $newExtraTranslation->description,
],
);
}
}
}

/**
* Check if the translation exists in the translations array.
*/
protected function translationExistsInTranslationsArray(object $inputTranslation, array $translations): bool {
foreach ($translations as $translation) {
if ($translation->language_id === $inputTranslation->language_id) {
return true;
}
}

return false;
}

/**
* Get the translation from the translations array via the language_id.
* @throws Exception If the translation with the given language_id is not found in the translations array.
*/
protected function getTranslationFromTranslationsArrayViaLanguageId(array $translations, int $id): object {
foreach ($translations as $translation) {
if ($translation->language_id === $id) {
return $translation;
}
}
throw new Exception("Translation with language_id: {$id} not found in translations array.");
}
}
13 changes: 12 additions & 1 deletion app/Console/Commands/RunAdminTasks.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

namespace App\Console\Commands;

use App\Jobs\TranslateQuestionnaireResponse;
use App\Models\Questionnaire\QuestionnaireResponse;
use App\Models\User\User;
use App\Notifications\UserRegistered;
use App\Utils\Translator;
Expand All @@ -26,7 +28,7 @@ class RunAdminTasks extends Command {
* Execute the console command.
*/
public function handle() {
$task = $this->choice('Which task would you like to test?', ['Translate service', 'Test email', 'Test Sentry error']);
$task = $this->choice('Which task would you like to test?', ['Translate service', 'Test email', 'Test Sentry error', 'Test supervisor']);

if ($task === 'Translate service') {
$this->info('Testing the translation service...');
Expand All @@ -47,6 +49,15 @@ public function handle() {
$this->info('Testing the Sentry error reporting service...');
$message = $this->ask('Enter the message for the Sentry error:');
throw new \Exception('Test Sentry error: ' . $message);
} elseif ($task === 'Test supervisor') {
$this->info('Testing the supervisor service...');
$this->info('Supervisor version: ' . shell_exec('supervisord -v'));
$this->info('Trying to send a test Questionnaire Response Translation event to supervisor...');
$questionnaire_response = QuestionnaireResponse::first();
$questionnaire_response->response_json_translated = null;
$questionnaire_response->save();
TranslateQuestionnaireResponse::dispatch($questionnaire_response->id);
$this->info('The test Questionnaire Response Translation event has been sent to supervisor.');
}
}
}
41 changes: 38 additions & 3 deletions app/Http/Controllers/Solution/SolutionController.php
Original file line number Diff line number Diff line change
Expand Up @@ -77,15 +77,50 @@ public function store(Request $request): RedirectResponse {
/**
* Show the form for editing the specified resource.
*/
public function edit(string $locale, int $id) {
//
public function edit(Request $request, string $locale, int $id) {
$validator = Validator::make([
'solution_id' => $id,
], [
'solution_id' => 'required|different:execute_solution|exists:solutions,id',
]);
if ($validator->fails()) {
abort(ResponseAlias::HTTP_NOT_FOUND);
}
try {
$viewModel = $this->solutionManager->getCreateEditSolutionViewModel(null, $id);

return view('backoffice.management.solution.create-edit.form-page', ['viewModel' => $viewModel]);
} catch (\Throwable $th) { // bookmark3 - 'ModelNotFoundException $e' or '\Exception $e' or '\Throwable $th'???
abort(ResponseAlias::HTTP_NOT_FOUND);
}
}

/**
* Update the specified resource in storage.
*/
public function update(Request $request, string $locale, int $id) {
//
$this->validate($request, [
'solution-title' => ['required', 'string', 'max:100'],
'solution-description' => ['required', 'string', 'max:400'],
'solution-status' => ['required'],
'solution-slug' => 'required|string|alpha_dash|unique:solutions,slug,' . $id . '|max:111',
'solution-image' => 'nullable|image|mimes:jpeg,png,jpg|max:2048',
'solution-owner-problem' => ['required'],
]);

$attributes = $request->all();

try {
$this->solutionManager->updateSolution($id, $attributes);
} catch (\Exception $e) {
session()->flash('flash_message_error', 'Error: ' . $e->getCode() . ' ' . $e->getMessage());

return back()->withInput();
}

session()->flash('flash_message_success', 'The problem has been successfully updated.');

return back();
}

/**
Expand Down
23 changes: 23 additions & 0 deletions app/Repository/Solution/SolutionTranslationRepository.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,35 @@

use App\Models\Solution\SolutionTranslation;
use App\Repository\Repository;
use App\Repository\RepositoryException;
use Illuminate\Container\Container as App;
use Illuminate\Support\Facades\DB;

class SolutionTranslationRepository extends Repository {
protected SolutionRepository $solutionRepository;

public function __construct(
App $app,
SolutionRepository $solutionRepository
) {
parent::__construct($app);
$this->solutionRepository = $solutionRepository;
}

/**
* {@inheritDoc}
*/
public function getModelClassName() {
return SolutionTranslation::class;
}

public function deleteTranslation($solution_id, $language_id): int {
$solutionDefaultTranslationId = $this->solutionRepository->find($solution_id)->default_language_id;
if ($language_id === $solutionDefaultTranslationId) {
throw new RepositoryException("Cannot delete translation with ['solution_id' => {$solution_id}, 'language_id' => {$language_id}] - it is the defaultTranslation for the solution.");
}

return DB::delete('DELETE FROM solution_translations
WHERE solution_id = ? and language_id = ?;', [$solution_id, $language_id]);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,9 @@

@csrf

<input type="hidden" name="solution-owner-problem" value="{{ request()->problem_id}}">
@if ( (!$viewModel->isEditMode()) && (request()->problem_id) )
<input type="hidden" name="solution-owner-problem" value="{{ request()->problem_id}}">
@endif

<div class="container-fluid p-0">
<ul class="nav nav-tabs mt-4" id="myTab" role="tablist">
Expand Down
2 changes: 1 addition & 1 deletion resources/views/problem/landing-page.blade.php
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
@extends('crowdsourcing-project.layout')
@push('css')
@vite('resources/assets/sass/project/problem/landing-page.scss')
@vite('resources/assets/sass/problem/landing-page.scss')
<style>
:root {
--project-primary-color: {{ $viewModel->project->lp_primary_color}};
Expand Down

0 comments on commit 2b205de

Please sign in to comment.