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

Refactored projects that are shown in the home page #78

Merged
merged 2 commits into from
Oct 4, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@

use App\BusinessLogicLayer\gamification\ContributorBadge;
use App\BusinessLogicLayer\lkp\CrowdSourcingProjectStatusLkp;
use App\BusinessLogicLayer\lkp\QuestionnaireStatusLkp;
use App\BusinessLogicLayer\questionnaire\QuestionnaireGoalManager;
use App\BusinessLogicLayer\UserManager;
use App\Models\CrowdSourcingProject\CrowdSourcingProject;
Expand Down Expand Up @@ -67,28 +66,12 @@ public function __construct(CrowdSourcingProjectRepository $crowdSourcingProject

public function getCrowdSourcingProjectsForHomePage(): Collection {
$projects = $this->crowdSourcingProjectRepository->getActiveProjectsWithAtLeastOneQuestionnaireWithStatus();
$projectsWithFinalizedQuestionnaires = $this->crowdSourcingProjectRepository->getActiveProjectsWithAtLeastOneQuestionnaireWithStatus([], QuestionnaireStatusLkp::FINALIZED);
// for each project in the finalized ones,
// if it does not exist in the collection of the projects with active questionnaires,
// add it there.
foreach ($projectsWithFinalizedQuestionnaires as $project) {
if (!$projects->contains('id', $project->id)) {
$projects->push($project);
}
}

foreach ($projects as $project) {
$project->currentTranslation = $this->crowdSourcingProjectTranslationManager->getFieldsTranslationForProject($project);
$project->latestQuestionnaire = $project->questionnaires->last();
}

return $projects;
}

public function getPastCrowdSourcingProjectsForHomePage(): Collection {
$projects = $this->crowdSourcingProjectRepository->getPastProjects();
foreach ($projects as $project) {
$project->currentTranslation = $this->crowdSourcingProjectTranslationManager->getFieldsTranslationForProject($project);
if ($project->questionnaires->count() > 0) {
$project->latestQuestionnaire = $project->questionnaires->last();
}
}

return $projects;
Expand Down
3 changes: 1 addition & 2 deletions app/Http/Controllers/HomeController.php
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,8 @@ public function __construct(CrowdSourcingProjectManager $crowdSourcingProjectMan

public function showHomePage() {
$projects = $this->crowdSourcingProjectManager->getCrowdSourcingProjectsForHomePage();
$pastProjects = $this->crowdSourcingProjectManager->getPastCrowdSourcingProjectsForHomePage();

return view('home.home')->with(['projects' => $projects, 'pastProjects' => $pastProjects]);
return view('home.home')->with(['projects' => $projects]);
}

public function showTermsAndPrivacyPage() {
Expand Down
16 changes: 9 additions & 7 deletions app/Http/Controllers/Questionnaire/QuestionnaireController.php
Original file line number Diff line number Diff line change
Expand Up @@ -25,11 +25,11 @@ class QuestionnaireController extends Controller {
protected QuestionnaireTranslator $questionnaireTranslator;
protected QuestionnaireLanguageManager $questionnaireLanguageManager;

public function __construct(QuestionnaireManager $questionnaireManager,
UserQuestionnaireShareManager $questionnaireShareManager,
QuestionnaireVMProvider $questionnaireVMProvider,
QuestionnaireTranslator $questionnaireTranslator,
QuestionnaireLanguageManager $questionnaireLanguageManager) {
public function __construct(QuestionnaireManager $questionnaireManager,
UserQuestionnaireShareManager $questionnaireShareManager,
QuestionnaireVMProvider $questionnaireVMProvider,
QuestionnaireTranslator $questionnaireTranslator,
QuestionnaireLanguageManager $questionnaireLanguageManager) {
$this->questionnaireManager = $questionnaireManager;
$this->questionnaireShareManager = $questionnaireShareManager;
$this->questionnaireVMProvider = $questionnaireVMProvider;
Expand Down Expand Up @@ -60,8 +60,9 @@ public function createQuestionnaire() {

public function store(Request $request) {
$data = $request->all();
if (!isset($data['status_id']))
if (!isset($data['status_id'])) {
$data['status_id'] = QuestionnaireStatusLkp::DRAFT;
}

$this->validate($request, [
'type_id' => 'required|integer',
Expand All @@ -74,8 +75,9 @@ public function store(Request $request) {
'project_ids' => 'required|array',
]);
$questionnaire = $this->questionnaireManager->storeOrUpdateQuestionnaire($data);
if (isset($data['lang_codes']) && count($data['lang_codes']) > 0)
if (isset($data['lang_codes']) && count($data['lang_codes']) > 0) {
$this->questionnaireLanguageManager->saveLanguagesForQuestionnaire($data['lang_codes'], $questionnaire->id);
}

return $questionnaire;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
use App\BusinessLogicLayer\lkp\QuestionnaireStatusLkp;
use App\Models\CrowdSourcingProject\CrowdSourcingProject;
use App\Repository\Repository;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Support\Collection;

class CrowdSourcingProjectRepository extends Repository {
Expand All @@ -23,26 +22,19 @@ public function getActiveProjectsWithAtLeastOneQuestionnaireWithStatus(
$additionalRelationships = [], $questionnaireStatusId = QuestionnaireStatusLkp::PUBLISHED
): Collection {
$builder = CrowdSourcingProject::where(['status_id' => CrowdSourcingProjectStatusLkp::PUBLISHED])
->whereHas('questionnaires', function (Builder $query) use ($questionnaireStatusId) {
$query->where(['status_id' => $questionnaireStatusId]);
})
->with('questionnaires', function ($query) use ($questionnaireStatusId) {
$query->select(['id', 'prerequisite_order', 'status_id', 'default_language_id',
'goal', 'statistics_page_visibility_lkp_id', 'questionnaires.created_at as questionnaire_created', ])
->where(['status_id' => $questionnaireStatusId])
->withCount('responses')
->orderBy('prerequisite_order')
->orderBy('questionnaire_created', 'desc');
});
})->with('problems');

if (count($additionalRelationships)) {
$builder = $builder->with($additionalRelationships);
}

return $builder->get();
}

public function getPastProjects(): Collection {
return CrowdSourcingProject::where(['status_id' => CrowdSourcingProjectStatusLkp::FINALIZED])->get();
}
}
2 changes: 1 addition & 1 deletion resources/views/home/partials/projects-list-home.blade.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
{!! $project->currentTranslation->motto_title !!}
</div>
<div class="project-visit-btn">
@if($project->latestQuestionnaire && $project->latestQuestionnaire->status_id == \App\BusinessLogicLayer\lkp\QuestionnaireStatusLkp::PUBLISHED)
@if(($project->latestQuestionnaire && $project->latestQuestionnaire->status_id == \App\BusinessLogicLayer\lkp\QuestionnaireStatusLkp::PUBLISHED) || $project->problems)
<a href="/{{app()->getLocale() .'/'.$project->slug}}"
class="btn btn-block btn-primary call-to-action action-dark">
{{ isset($projectBtnText) ? $projectBtnText : 'Contribute' }}
Expand Down
15 changes: 1 addition & 14 deletions resources/views/home/partials/together/projects.blade.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,22 +6,9 @@
<p>The <b><i>"Together"</i></b> crowdsourcing platform hosts various projects. Please check below those
that are the currently active and waiting for your contribution.
Please visit a project's page and make an impact by answering just a couple of questions!</p>

@include('home.partials.projects-list-home')
</div>
</div>
</div>
</div>
@if(isset($pastProjects))
<section id="past-projects">
<div class="container py-5">
<div class="row">
<div class="col-md-6 col-xs-12 mx-auto text-center">
<h2>Check out our past projects:</h2>
</div>
</div>
<div class="row">
@include('home.partials.projects-list-home', ['projects' => $pastProjects, 'projectBtnText' => 'See more'])
</div>
</div>
</section>
@endif
72 changes: 38 additions & 34 deletions tests/Feature/Controllers/CrowdSourcingProjectControllerTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
use App\BusinessLogicLayer\CrowdSourcingProject\CrowdSourcingProjectManager;
use App\BusinessLogicLayer\lkp\CrowdSourcingProjectStatusLkp;
use App\BusinessLogicLayer\lkp\UserRolesLkp;
use App\Http\Middleware\VerifyCsrfToken;
use App\Models\CrowdSourcingProject\CrowdSourcingProject;
use App\Models\User;
use App\Models\UserRole;
Expand Down Expand Up @@ -282,13 +283,14 @@ public function adminCanAccessEditPage() {
* @test
*/
public function guestCannotStoreProject() {
$response = $this->post(route('projects.store'), [
'name' => 'Test Project',
'description' => 'Test Description',
'status_id' => 1,
'slug' => 'test-project',
'language_id' => 1,
]);
$response = $this->withoutMiddleware(VerifyCsrfToken::class)
->post(route('projects.store'), [
'name' => 'Test Project',
'description' => 'Test Description',
'status_id' => 1,
'slug' => 'test-project',
'language_id' => 1,
]);

$response->assertStatus(302);
$response->assertRedirect(route('login', ['locale' => 'en']));
Expand All @@ -298,16 +300,17 @@ public function guestCannotStoreProject() {
* @test
*/
public function authenticatedUserCannotStoreProject() {
$user = User::factory()->make();
$this->be($user);

$response = $this->post(route('projects.store'), [
'name' => 'Test Project',
'description' => 'Test Description',
'status_id' => 1,
'slug' => 'test-project',
'language_id' => 1,
]);
$user = User::factory()->create();
$this->actingAs($user);

$response = $this->withoutMiddleware(VerifyCsrfToken::class) // Disable CSRF only
->post(route('projects.store'), [
'name' => 'Test Project',
'description' => 'Test Description',
'status_id' => 1,
'slug' => 'test-project',
'language_id' => 1,
]);

$response->assertStatus(403);
}
Expand All @@ -323,17 +326,18 @@ public function adminCanStoreProjectWithValidData() {

$faker = Faker::create();

$response = $this->post(route('projects.store'), [
'name' => 'Valid Project',
'description' => 'Valid Description',
'status_id' => 1,
'slug' => 'valid-project',
'language_id' => 1,
'color_ids' => [1],
'color_names' => [$faker->name],
'color_codes' => [$faker->hexColor],
'motto_subtitle' => $faker->text,
]);
$response = $this->withoutMiddleware(VerifyCsrfToken::class)
->post(route('projects.store'), [
'name' => 'Valid Project',
'description' => 'Valid Description',
'status_id' => 1,
'slug' => 'valid-project',
'language_id' => 1,
'color_ids' => [1],
'color_names' => [$faker->name],
'color_codes' => [$faker->hexColor],
'motto_subtitle' => $faker->text,
]);

$response->assertStatus(302);
$response->assertSessionHas('flash_message_success', 'The project has been successfully created');
Expand All @@ -357,7 +361,7 @@ public function adminCannotStoreProjectWithExistingData() {

$project = CrowdSourcingProject::factory()->create();

$response = $this->post(route('projects.store'), [
$response = $this->withoutMiddleware(VerifyCsrfToken::class)->post(route('projects.store'), [
'name' => $project->defaultTranslation->name,
'description' => $project->defaultTranslation->description,
'status_id' => $project->status_id,
Expand All @@ -378,7 +382,7 @@ public function storeProjectWithInvalidData() {
->create();
$this->be($user);

$response = $this->post(route('projects.store'), [
$response = $this->withoutMiddleware(VerifyCsrfToken::class)->post(route('projects.store'), [
'name' => '',
'description' => '',
'status_id' => 'invalid',
Expand All @@ -396,7 +400,7 @@ public function storeProjectWithInvalidData() {
public function guestCannotUpdateProject() {
$project = CrowdSourcingProject::factory()->create();

$response = $this->put(route('projects.update', ['project' => $project->id]), [
$response = $this->withoutMiddleware(VerifyCsrfToken::class)->put(route('projects.update', ['project' => $project->id]), [
'name' => 'Updated Project',
'description' => 'Updated Description',
'status_id' => 1,
Expand All @@ -417,7 +421,7 @@ public function authenticatedUserCannotUpdateProject() {

$project = CrowdSourcingProject::factory()->create();

$response = $this->put(route('projects.update', ['project' => $project->id]), [
$response = $this->withoutMiddleware(VerifyCsrfToken::class)->put(route('projects.update', ['project' => $project->id]), [
'name' => 'Updated Project',
'description' => 'Updated Description',
'status_id' => 1,
Expand All @@ -439,7 +443,7 @@ public function adminCanUpdateProjectWithValidData() {

$project = CrowdSourcingProject::factory()->create();
$faker = Faker::create();
$response = $this->put(route('projects.update', ['project' => $project->id]), [
$response = $this->withoutMiddleware(VerifyCsrfToken::class)->put(route('projects.update', ['project' => $project->id]), [
'name' => 'Updated Project',
'description' => 'Updated Description',
'status_id' => 1,
Expand Down Expand Up @@ -475,7 +479,7 @@ public function adminCannotUpdateProjectWithInvalidData() {

$project = CrowdSourcingProject::factory()->create();

$response = $this->put(route('projects.update', ['project' => $project->id]), [
$response = $this->withoutMiddleware(VerifyCsrfToken::class)->put(route('projects.update', ['project' => $project->id]), [
'name' => '',
'description' => '',
'status_id' => 'invalid',
Expand Down
52 changes: 29 additions & 23 deletions tests/Feature/Controllers/FileControllerTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

namespace Tests\Feature\Controllers;

use App\Http\Middleware\VerifyCsrfToken;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Http\UploadedFile;
use Illuminate\Support\Facades\Storage;
Expand All @@ -20,11 +21,12 @@ public function uploadFilesSuccessfullyUploadsFiles() {
UploadedFile::fake()->image('photo2.jpg'),
];

$response = $this->postJson('/files/upload', [
'files' => $files,
'project_id' => 1,
'questionnaire_id' => 1,
]);
$response = $this->withoutMiddleware(VerifyCsrfToken::class)
->postJson('/files/upload', [
'files' => $files,
'project_id' => 1,
'questionnaire_id' => 1,
]);

$response->assertStatus(200);
$response->assertJsonCount(2);
Expand All @@ -42,11 +44,12 @@ public function uploadFilesFailsWithInvalidFileType() {
UploadedFile::fake()->create('document.txt', 100),
];

$response = $this->postJson('/files/upload', [
'files' => $files,
'project_id' => 1,
'questionnaire_id' => 1,
]);
$response = $this->withoutMiddleware(VerifyCsrfToken::class)
->postJson('/files/upload', [
'files' => $files,
'project_id' => 1,
'questionnaire_id' => 1,
]);

$response->assertStatus(422);
$response->assertJsonValidationErrors(['files.0']);
Expand All @@ -57,11 +60,12 @@ public function uploadFilesFailsWithTooManyFiles() {
Storage::fake('s3');
$files = array_fill(0, 9, UploadedFile::fake()->image('photo.jpg'));

$response = $this->postJson('/files/upload', [
'files' => $files,
'project_id' => 1,
'questionnaire_id' => 1,
]);
$response = $this->withoutMiddleware(VerifyCsrfToken::class)
->postJson('/files/upload', [
'files' => $files,
'project_id' => 1,
'questionnaire_id' => 1,
]);

$response->assertStatus(422);
$response->assertJsonValidationErrors(['files']);
Expand All @@ -74,10 +78,11 @@ public function uploadFilesFailsWithoutProjectId() {
UploadedFile::fake()->image('photo.jpg'),
];

$response = $this->postJson('/files/upload', [
'files' => $files,
'questionnaire_id' => 1,
]);
$response = $this->withoutMiddleware(VerifyCsrfToken::class)
->postJson('/files/upload', [
'files' => $files,
'questionnaire_id' => 1,
]);

$response->assertStatus(422);
$response->assertJsonValidationErrors(['project_id']);
Expand All @@ -90,10 +95,11 @@ public function uploadFilesFailsWithoutQuestionnaireId() {
UploadedFile::fake()->image('photo.jpg'),
];

$response = $this->postJson('/files/upload', [
'files' => $files,
'project_id' => 1,
]);
$response = $this->withoutMiddleware(VerifyCsrfToken::class)
->postJson('/files/upload', [
'files' => $files,
'project_id' => 1,
]);

$response->assertStatus(422);
$response->assertJsonValidationErrors(['questionnaire_id']);
Expand Down
Loading
Loading