From 880da0485892c05a10b8756ce6522a4f804daeaa Mon Sep 17 00:00:00 2001 From: Paul Isaris Date: Thu, 14 Nov 2024 11:06:13 +0200 Subject: [PATCH] Added bookmarks for problems and table styling --- .../CrowdSourcingProjectManager.php | 4 --- .../CrowdSourcingProjectProblemManager.php | 4 +++ .../CrowdSourcingProjectController.php | 8 ----- .../CrowdSourcingProjectProblemController.php | 8 +++++ ...ngProjectProblemUserBookmarkController.php | 15 ++++++++ .../Problem/CrowdSourcingProjectProblem.php | 4 +++ ...rowdSourcingProjectProblemUserBookmark.php | 30 ++++++++++++++++ .../CrowdSourcingProjectProblemRepository.php | 3 +- ...g_project_problem_user_bookmarks_table.php | 35 +++++++++++++++++++ .../problem/ProblemsManagement.vue | 21 ++++++----- routes/api.php | 2 +- 11 files changed, 112 insertions(+), 22 deletions(-) create mode 100644 app/Http/Controllers/CrowdSourcingProject/Problem/CrowdSourcingProjectProblemUserBookmarkController.php create mode 100644 app/Models/CrowdSourcingProject/Problem/CrowdSourcingProjectProblemUserBookmark.php create mode 100644 database/migrations/2024_11_14_104154_create_crowd_sourcing_project_problem_user_bookmarks_table.php diff --git a/app/BusinessLogicLayer/CrowdSourcingProject/CrowdSourcingProjectManager.php b/app/BusinessLogicLayer/CrowdSourcingProject/CrowdSourcingProjectManager.php index 250ab11f..8480f1ed 100644 --- a/app/BusinessLogicLayer/CrowdSourcingProject/CrowdSourcingProjectManager.php +++ b/app/BusinessLogicLayer/CrowdSourcingProject/CrowdSourcingProjectManager.php @@ -468,8 +468,4 @@ public function getCrowdSourcingProjectsForProblems(): Collection { // get all projects that have at least one problem return $this->crowdSourcingProjectRepository->getProjectsForProblems(); } - - public function getProblemsForCrowdSourcingProjectForManagement(int $projectId): Collection { - return $this->crowdSourcingProjectProblemRepository->getProblemsForCrowdSourcingProjectForManagement($projectId); - } } diff --git a/app/BusinessLogicLayer/CrowdSourcingProject/Problem/CrowdSourcingProjectProblemManager.php b/app/BusinessLogicLayer/CrowdSourcingProject/Problem/CrowdSourcingProjectProblemManager.php index 6d3c2e9e..e97e0ab9 100644 --- a/app/BusinessLogicLayer/CrowdSourcingProject/Problem/CrowdSourcingProjectProblemManager.php +++ b/app/BusinessLogicLayer/CrowdSourcingProject/Problem/CrowdSourcingProjectProblemManager.php @@ -144,4 +144,8 @@ public function getProblemStatusesForManagementPage(): Collection { public function updateProblemStatus(int $id, int $status_id) { return $this->crowdSourcingProjectProblemRepository->update(['status_id' => $status_id], $id); } + + public function getProblemsForCrowdSourcingProjectForManagement(int $projectId): Collection { + return $this->crowdSourcingProjectProblemRepository->getProblemsForCrowdSourcingProjectForManagement($projectId); + } } diff --git a/app/Http/Controllers/CrowdSourcingProject/CrowdSourcingProjectController.php b/app/Http/Controllers/CrowdSourcingProject/CrowdSourcingProjectController.php index 7c0c0d00..3f64068e 100644 --- a/app/Http/Controllers/CrowdSourcingProject/CrowdSourcingProjectController.php +++ b/app/Http/Controllers/CrowdSourcingProject/CrowdSourcingProjectController.php @@ -145,12 +145,4 @@ public function clone(int $id): RedirectResponse { public function getCrowdSourcingProjectsForProblems(): JsonResponse { return response()->json($this->crowdSourcingProjectManager->getCrowdSourcingProjectsForProblems()); } - - public function getProblemsForCrowdSourcingProjectForManagement(): JsonResponse { - $this->validate(request(), [ - 'projectId' => 'required|numeric|exists:crowd_sourcing_projects,id', - ]); - - return response()->json($this->crowdSourcingProjectManager->getProblemsForCrowdSourcingProjectForManagement(request('projectId'))); - } } diff --git a/app/Http/Controllers/CrowdSourcingProject/Problem/CrowdSourcingProjectProblemController.php b/app/Http/Controllers/CrowdSourcingProject/Problem/CrowdSourcingProjectProblemController.php index 0e59c769..ac532b4b 100644 --- a/app/Http/Controllers/CrowdSourcingProject/Problem/CrowdSourcingProjectProblemController.php +++ b/app/Http/Controllers/CrowdSourcingProject/Problem/CrowdSourcingProjectProblemController.php @@ -115,4 +115,12 @@ public function updateStatus(Request $request, int $id): JsonResponse { return response()->json($this->crowdSourcingProjectProblemManager->updateProblemStatus($id, $request->status_id)); } + + public function getProblemsForCrowdSourcingProjectForManagement(): JsonResponse { + $this->validate(request(), [ + 'projectId' => 'required|numeric|exists:crowd_sourcing_projects,id', + ]); + + return response()->json($this->crowdSourcingProjectProblemManager->getProblemsForCrowdSourcingProjectForManagement(request('projectId'))); + } } diff --git a/app/Http/Controllers/CrowdSourcingProject/Problem/CrowdSourcingProjectProblemUserBookmarkController.php b/app/Http/Controllers/CrowdSourcingProject/Problem/CrowdSourcingProjectProblemUserBookmarkController.php new file mode 100644 index 00000000..0ad8d4cc --- /dev/null +++ b/app/Http/Controllers/CrowdSourcingProject/Problem/CrowdSourcingProjectProblemUserBookmarkController.php @@ -0,0 +1,15 @@ +hasOne(CrowdSourcingProjectProblemStatusLkp::class, 'id', 'status_id'); } + + public function bookmarks(): HasMany { + return $this->hasMany(CrowdSourcingProjectProblemUserBookmark::class, 'problem_id', 'id'); + } } diff --git a/app/Models/CrowdSourcingProject/Problem/CrowdSourcingProjectProblemUserBookmark.php b/app/Models/CrowdSourcingProject/Problem/CrowdSourcingProjectProblemUserBookmark.php new file mode 100644 index 00000000..433c6e5a --- /dev/null +++ b/app/Models/CrowdSourcingProject/Problem/CrowdSourcingProjectProblemUserBookmark.php @@ -0,0 +1,30 @@ +belongsTo(CrowdSourcingProjectProblem::class, 'problem_id', 'id'); + } + + public function user(): BelongsTo { + return $this->belongsTo(User::class, 'user_id', 'id'); + } + + public function language(): BelongsTo { + return $this->belongsTo(Language::class, 'problem_bookmark_language_id', 'id'); + } +} diff --git a/app/Repository/CrowdSourcingProject/Problem/CrowdSourcingProjectProblemRepository.php b/app/Repository/CrowdSourcingProject/Problem/CrowdSourcingProjectProblemRepository.php index 5a199cf9..4a231149 100644 --- a/app/Repository/CrowdSourcingProject/Problem/CrowdSourcingProjectProblemRepository.php +++ b/app/Repository/CrowdSourcingProject/Problem/CrowdSourcingProjectProblemRepository.php @@ -30,6 +30,7 @@ public function projectHasPublishedProblems(int $project_id): bool { } public function getProblemsForCrowdSourcingProjectForManagement(int $projectId): Collection { - return CrowdSourcingProjectProblem::where('project_id', $projectId)->with(['defaultTranslation', 'translations', 'translations.language', 'status'])->get(); + return CrowdSourcingProjectProblem::where('project_id', $projectId) + ->with(['defaultTranslation', 'translations', 'translations.language', 'status', 'bookmarks'])->get(); } } diff --git a/database/migrations/2024_11_14_104154_create_crowd_sourcing_project_problem_user_bookmarks_table.php b/database/migrations/2024_11_14_104154_create_crowd_sourcing_project_problem_user_bookmarks_table.php new file mode 100644 index 00000000..ba52392f --- /dev/null +++ b/database/migrations/2024_11_14_104154_create_crowd_sourcing_project_problem_user_bookmarks_table.php @@ -0,0 +1,35 @@ +unsignedBigInteger('problem_id'); + $table->foreign('problem_id')->references('id')->on('crowd_sourcing_project_problems'); + + $table->unsignedInteger('user_id'); + $table->foreign('user_id')->references('id')->on('users'); + + $table->primary(['problem_id', 'user_id'], 'csp_problem_user_bookmarks_primary'); + + // the language in which the user bookmarked the problem + $table->unsignedInteger('problem_bookmark_language_id'); + $table->foreign('problem_bookmark_language_id')->references('id')->on('languages_lkp'); + + $table->timestamps(); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void { + Schema::dropIfExists('csp_problem_user_bookmarks'); + } +}; diff --git a/resources/assets/js/vue-components/loggedin-environment/management/crowd-sourcing-project/problem/ProblemsManagement.vue b/resources/assets/js/vue-components/loggedin-environment/management/crowd-sourcing-project/problem/ProblemsManagement.vue index f66f9964..29023297 100644 --- a/resources/assets/js/vue-components/loggedin-environment/management/crowd-sourcing-project/problem/ProblemsManagement.vue +++ b/resources/assets/js/vue-components/loggedin-environment/management/crowd-sourcing-project/problem/ProblemsManagement.vue @@ -191,20 +191,25 @@ export default { await this.$nextTick(() => { this.dataTableInstance = $("#problemsTable").DataTable({ pageLength: 5, + autoWidth: false, data: [], columns: [ - { title: "#", data: null }, - { title: "Title", data: "title" }, - { title: "Bookmarks", data: "bookmarks" }, - { title: "Languages", data: "languages" }, - { title: "Status", data: "status" }, - { title: "Actions", data: "actions" }, + { title: "#", data: null, width: "5%" }, + { title: "Title", data: "title", width: "30%" }, + { title: "Bookmarks", data: "bookmarks", width: "5%" }, + { title: "Languages", data: "languages", width: "20%" }, + { title: "Status", data: "status", width: "20%" }, + { title: "Actions", data: "actions", width: "20%" }, ], columnDefs: [ { targets: 0, render: (data, type, row, meta) => meta.row + 1, }, + { + targets: [0, 2, 4, 5], // Indices of columns to center + className: "text-center", + }, ], }); @@ -293,12 +298,12 @@ export default { this.dataTableInstance.clear(); const tableData = this.filteredProblems.map((problem, index) => ({ title: problem.default_translation.title, - bookmarks: "TODO", + bookmarks: problem.bookmarks.length, languages: problem.translations ? problem.translations.map((t) => t.language.language_name).join(", ") : "", status: ` + class="p-2 w-75 badge ${this.getBadgeClassForProblemStatus(problem.status)}"> ${problem.status.title}`, actions: `