From 43fa4aa3fd97df8c0588c9b4ff1b0048966da996 Mon Sep 17 00:00:00 2001 From: NuwanJ Date: Thu, 17 Oct 2024 11:32:56 +0530 Subject: [PATCH 1/5] Taxonomy Preview implementation --- .../Models/Traits/Scope/CourseScope.php | 2 +- app/Domains/Taxonomy/Models/Taxonomy.php | 19 +++++- app/Domains/Taxonomy/Models/TaxonomyTerm.php | 60 +++++++++++++++++-- .../Backend/TaxonomyController.php | 47 +++++++++------ .../taxonomy/index-table-row.blade.php | 12 ++-- .../views/backend/taxonomy/view.blade.php | 23 +++++++ routes/api.php | 17 +++++- routes/backend/taxonomy.php | 14 ++++- 8 files changed, 159 insertions(+), 35 deletions(-) create mode 100644 resources/views/backend/taxonomy/view.blade.php diff --git a/app/Domains/AcademicProgram/Course/Models/Traits/Scope/CourseScope.php b/app/Domains/AcademicProgram/Course/Models/Traits/Scope/CourseScope.php index cc11480e..6370a5f4 100644 --- a/app/Domains/AcademicProgram/Course/Models/Traits/Scope/CourseScope.php +++ b/app/Domains/AcademicProgram/Course/Models/Traits/Scope/CourseScope.php @@ -54,4 +54,4 @@ public function scopeOfVersion($query, $version) { return $query->where('version', $version); } -} \ No newline at end of file +} diff --git a/app/Domains/Taxonomy/Models/Taxonomy.php b/app/Domains/Taxonomy/Models/Taxonomy.php index eaa5a77e..2e16317b 100644 --- a/app/Domains/Taxonomy/Models/Taxonomy.php +++ b/app/Domains/Taxonomy/Models/Taxonomy.php @@ -23,9 +23,6 @@ class Taxonomy extends Model protected static $logFillable = true; protected static $logOnlyDirty = true; - /** - * @var string[] - */ protected $fillable = [ 'code', 'name', @@ -44,6 +41,11 @@ class Taxonomy extends Model 'image' => 'Image' ]; + protected $casts = [ + 'created_at' => 'datetime', + 'updated_at' => 'datetime', + ]; + public function user() { return $this->belongsTo(User::class, 'created_by'); @@ -64,6 +66,17 @@ public function terms() return $this->hasMany(TaxonomyTerm::class, 'taxonomy_id'); } + public function to_dict() + { + $taxonomy = $this->toArray(); + foreach (['properties', 'created_at', 'updated_at', 'created_by', 'updated_by'] as $attribute) { + unset($taxonomy[$attribute]); + } + $taxonomy['properties'] = json_decode($this->properties); + $taxonomy['terms'] = TaxonomyTerm::getByTaxonomy($this->id); + return $taxonomy; + } + protected static function newFactory() { return TaxonomyFactory::new(); diff --git a/app/Domains/Taxonomy/Models/TaxonomyTerm.php b/app/Domains/Taxonomy/Models/TaxonomyTerm.php index 15ee6b98..4b44456f 100644 --- a/app/Domains/Taxonomy/Models/TaxonomyTerm.php +++ b/app/Domains/Taxonomy/Models/TaxonomyTerm.php @@ -16,22 +16,37 @@ class TaxonomyTerm extends Model use HasFactory, LogsActivity; - protected static $logFillable = true; protected static $logOnlyDirty = true; - /** - * @var string[] - */ protected $fillable = [ 'code', 'name', 'metadata', 'taxonomy_id', 'parent_id', + ]; + protected $casts = [ + 'metadata' => 'json', + 'created_at' => 'datetime', + 'updated_at' => 'datetime', ]; + public function getFormattedMetadataAttribute() + { + $response = array(); + $filteredMetadata = array_filter($this->metadata, function ($value) { + return !is_null($value['value']); + }); + + foreach ($filteredMetadata as $metadata) { + $response[$metadata['code']] = $metadata['value']; + } + + return $response; + } + public function user() { return $this->belongsTo(User::class, 'created_by'); @@ -68,7 +83,7 @@ public function getMetadata($code) if (is_array($metadata)) { foreach ($metadata as $item) { - if ($item['code'] === $code) { + if ($item['code'] === $code && $item['value'] != null) { return $item['value']; } } @@ -76,6 +91,41 @@ public function getMetadata($code) return null; } + public static function getByTaxonomy($taxonomyId, $parent = null) + { + + if ($parent == null) { + $res = TaxonomyTerm::where(function ($query) use ($taxonomyId) { + $query->whereNull('parent_id')->whereAnd('parent_id', $taxonomyId); + }); + } else { + $res = TaxonomyTerm::where(function ($query) use ($taxonomyId, $parent) { + $query->where('parent_id', $parent)->whereAnd('parent_id', $taxonomyId); + }); + } + + $taxonomyTerms = []; + foreach ($res->get() as $term) { + $termData = $term->to_dict(); + + if ($term->children()->count() > 0) { + $termData['terms'] = $term->getByTaxonomy($taxonomyId, $term->id); + } + array_push($taxonomyTerms, $termData); + } + return $taxonomyTerms; + } + + public function to_dict() + { + $taxonomyTerm = $this->toArray(); + foreach (['id', 'taxonomy_id', 'parent_id', 'metadata', 'created_at', 'updated_at', 'created_by', 'updated_by'] as $attribute) { + unset($taxonomyTerm[$attribute]); + } + $taxonomyTerm['metadata'] = $this->formatted_metadata; + return $taxonomyTerm; + } + protected static function newFactory() { return TaxonomyTermFactory::new(); diff --git a/app/Http/Controllers/Backend/TaxonomyController.php b/app/Http/Controllers/Backend/TaxonomyController.php index fbb47efa..9fb98a0a 100644 --- a/app/Http/Controllers/Backend/TaxonomyController.php +++ b/app/Http/Controllers/Backend/TaxonomyController.php @@ -17,13 +17,26 @@ class TaxonomyController extends Controller */ public function create() { - try{ + try { return view('backend.taxonomy.create'); - }catch (\Exception $ex) { - Log::error('Failed to load taxonomy creation page', ['error' => $ex->getMessage()]); + } catch (\Exception $ex) { + Log::error('Failed to load taxonomy creation page', ['error' => $ex->getMessage()]); return abort(500); - } + } + } + + /** + * Preview the resource . + * + * @param \App\Domains\Taxonomy\Models\Taxonomy $taxonomy + * @return \Illuminate\Contracts\Foundation\Application|\Illuminate\Contracts\View\Factory|\Illuminate\Contracts\View\View + */ + public function view(Taxonomy $taxonomy) + { + $taxonomyData = $taxonomy->to_dict(); + return view('backend.taxonomy.view', compact('taxonomyData')); } + /** * Store a newly created resource in storage. * @@ -32,19 +45,19 @@ public function create() */ public function store(Request $request) { - $validatedData =$request->validate([ + $validatedData = $request->validate([ 'code' => 'required|unique:taxonomies', 'name' => 'required', 'description' => 'nullable', ]); - - try{ + + try { $taxonomy = new Taxonomy($validatedData); $taxonomy->properties = $request->properties; $taxonomy->created_by = Auth::user()->id; $taxonomy->save(); return redirect()->route('dashboard.taxonomy.index')->with('Success', 'Taxonomy created successfully'); - }catch (\Exception $ex) { + } catch (\Exception $ex) { Log::error('Failed to create taxonomy', ['error' => $ex->getMessage()]); return abort(500); } @@ -66,7 +79,7 @@ public function edit(Taxonomy $taxonomy) return abort(500); } } - + /** * Update the specified resource in storage. @@ -80,22 +93,21 @@ public function update(Request $request, Taxonomy $taxonomy) $data = $request->validate([ 'code' => 'required', 'name' => 'required', - 'description' => 'nullable', + 'description' => 'nullable', ]); - - try{ + + try { $taxonomy->update($data); $taxonomy->properties = $request->properties; - $taxonomy->updated_by = Auth::user()->id; + $taxonomy->updated_by = Auth::user()->id; $taxonomy->save(); return redirect()->route('dashboard.taxonomy.index')->with('Success', 'Taxonomy updated successfully'); - }catch (\Exception $ex) { + } catch (\Exception $ex) { Log::error('Failed to update taxonomy', ['error' => $ex->getMessage()]); return abort(500); } - } - /** + /** * Confirm to delete the specified resource from storage. * * @param \App\Domains\Taxonomy\Models\Taxonomy $taxonomy @@ -123,5 +135,4 @@ public function destroy(Taxonomy $taxonomy) return abort(500); } } -} - +} \ No newline at end of file diff --git a/resources/views/backend/taxonomy/index-table-row.blade.php b/resources/views/backend/taxonomy/index-table-row.blade.php index 94ba07b0..1e04526a 100644 --- a/resources/views/backend/taxonomy/index-table-row.blade.php +++ b/resources/views/backend/taxonomy/index-table-row.blade.php @@ -26,16 +26,16 @@
+ + + + +
- {{-- + - --}} - - - - diff --git a/resources/views/backend/taxonomy/view.blade.php b/resources/views/backend/taxonomy/view.blade.php new file mode 100644 index 00000000..04564325 --- /dev/null +++ b/resources/views/backend/taxonomy/view.blade.php @@ -0,0 +1,23 @@ +@extends('backend.layouts.app') + +@section('title', __('View Taxonomy')) + +@section('content') + +
+ +

Taxonomy: {{ $taxonomyData['name'] }} ({{ $taxonomyData['code'] }})

+ +

API Endpoint: + + {{ route('api.taxonomy.get', ['taxonomy_code' => $taxonomyData['code']]) }} + +

+ +

Response:

+
+{{ json_encode($taxonomyData, JSON_PRETTY_PRINT) }}
+        
+
+ +@endsection diff --git a/routes/api.php b/routes/api.php index 4b15fea4..1cca16e0 100644 --- a/routes/api.php +++ b/routes/api.php @@ -22,4 +22,19 @@ Route::get('/semesters', [SemesterApiController::class, 'index']); }); -// TODO: Implement postgraduate courses API \ No newline at end of file +// TODO: Implement postgraduate courses API + + +Route::group(['prefix' => 'taxonomy/v1/', 'as' => 'api.taxonomy.'], function () { + Route::get('/{taxonomy_code}', function ($taxonomy_code) { + // TODO implement via a Controller + return []; + })->name('get'); + Route::get( + '/term/{taxonomy_term_code}', + function ($taxonomy_term_code) { + // TODO implement via a Controller + return []; + } + )->name('term.get'); +}); \ No newline at end of file diff --git a/routes/backend/taxonomy.php b/routes/backend/taxonomy.php index 07c11c7b..57670b58 100644 --- a/routes/backend/taxonomy.php +++ b/routes/backend/taxonomy.php @@ -35,6 +35,7 @@ ->breadcrumbs(function (Trail $trail, $taxonomy) { $trail->push(__('Home'), route('dashboard.home')) ->push(__('Taxonomy'), route('dashboard.taxonomy.index')) + ->push($taxonomy->name) ->push(__('Edit'), route('dashboard.taxonomy.edit', $taxonomy)); }); @@ -48,9 +49,20 @@ ->breadcrumbs(function (Trail $trail, $taxonomy) { $trail->push(__('Home'), route('dashboard.home')) ->push(__('Taxonomy'), route('dashboard.taxonomy.index')) + ->push($taxonomy->name) ->push(__('Delete')); }); + + // View + Route::get('taxonomy/view/{taxonomy}', [TaxonomyController::class, 'view']) + ->name('taxonomy.view')->breadcrumbs(function (Trail $trail, $taxonomy) { + $trail->push(__('Home'), route('dashboard.home')) + ->push(__('Taxonomy'), route('dashboard.taxonomy.index')) + ->push($taxonomy->name) + ->push(__('View')); + }); + // Destroy Route::delete('taxonomy/{taxonomy}', [TaxonomyController::class, 'destroy']) ->name('taxonomy.destroy'); @@ -112,4 +124,4 @@ Route::delete('/{term}', [TaxonomyTermController::class, 'destroy']) ->name('taxonomy.terms.destroy'); }); -}); +}); \ No newline at end of file From 2fdd0bc948ea04d2e023c5a04e3d8f378b4bc359 Mon Sep 17 00:00:00 2001 From: NuwanJ Date: Thu, 17 Oct 2024 11:53:11 +0530 Subject: [PATCH 2/5] Correction --- app/Domains/Taxonomy/Models/TaxonomyTerm.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/Domains/Taxonomy/Models/TaxonomyTerm.php b/app/Domains/Taxonomy/Models/TaxonomyTerm.php index 4b44456f..66948ab3 100644 --- a/app/Domains/Taxonomy/Models/TaxonomyTerm.php +++ b/app/Domains/Taxonomy/Models/TaxonomyTerm.php @@ -96,11 +96,11 @@ public static function getByTaxonomy($taxonomyId, $parent = null) if ($parent == null) { $res = TaxonomyTerm::where(function ($query) use ($taxonomyId) { - $query->whereNull('parent_id')->whereAnd('parent_id', $taxonomyId); + $query->whereNull('parent_id')->whereAnd('taxonomy_id', $taxonomyId); }); } else { $res = TaxonomyTerm::where(function ($query) use ($taxonomyId, $parent) { - $query->where('parent_id', $parent)->whereAnd('parent_id', $taxonomyId); + $query->where('parent_id', $parent)->whereAnd('taxonomy_id', $taxonomyId); }); } From 3aff0fa47d743bafea92ff9e8f24024dd17e33bf Mon Sep 17 00:00:00 2001 From: NuwanJ Date: Thu, 17 Oct 2024 11:59:01 +0530 Subject: [PATCH 3/5] Query correction --- app/Domains/Taxonomy/Models/TaxonomyTerm.php | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/app/Domains/Taxonomy/Models/TaxonomyTerm.php b/app/Domains/Taxonomy/Models/TaxonomyTerm.php index 66948ab3..f8eb1dda 100644 --- a/app/Domains/Taxonomy/Models/TaxonomyTerm.php +++ b/app/Domains/Taxonomy/Models/TaxonomyTerm.php @@ -93,15 +93,10 @@ public function getMetadata($code) public static function getByTaxonomy($taxonomyId, $parent = null) { - if ($parent == null) { - $res = TaxonomyTerm::where(function ($query) use ($taxonomyId) { - $query->whereNull('parent_id')->whereAnd('taxonomy_id', $taxonomyId); - }); + $res = TaxonomyTerm::where('taxonomy_id', $taxonomyId)->whereNull('parent_id'); } else { - $res = TaxonomyTerm::where(function ($query) use ($taxonomyId, $parent) { - $query->where('parent_id', $parent)->whereAnd('taxonomy_id', $taxonomyId); - }); + $res = TaxonomyTerm::where('taxonomy_id', $taxonomyId)->where('parent_id', $parent); } $taxonomyTerms = []; From 62f22e5c29457f13bdb096f8374afdcbf761a5c5 Mon Sep 17 00:00:00 2001 From: NuwanJ Date: Thu, 17 Oct 2024 12:06:59 +0530 Subject: [PATCH 4/5] Easy filtering the taxonomy terms --- app/Http/Livewire/Backend/TaxonomyTermTable.php | 4 ++-- .../views/backend/taxonomy/terms/index-table-row.blade.php | 4 +++- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/app/Http/Livewire/Backend/TaxonomyTermTable.php b/app/Http/Livewire/Backend/TaxonomyTermTable.php index 7de107b3..e21ea266 100644 --- a/app/Http/Livewire/Backend/TaxonomyTermTable.php +++ b/app/Http/Livewire/Backend/TaxonomyTermTable.php @@ -47,8 +47,8 @@ public function query(): Builder { return TaxonomyTerm::query() ->where('taxonomy_id', $this->taxonomy->id) - ->when($this->getFilter('taxonomy_term'), fn($query, $type) => $query->where('parent_id', $type)) - ->with('user'); + ->when($this->getFilter('taxonomy_term'), fn($query, $type) => $query->where('parent_id', $type)->orWhere('id', $type)) + ->with('user')->orderBy('parent_id'); } public function filters(): array diff --git a/resources/views/backend/taxonomy/terms/index-table-row.blade.php b/resources/views/backend/taxonomy/terms/index-table-row.blade.php index 75a4fa21..769c6744 100644 --- a/resources/views/backend/taxonomy/terms/index-table-row.blade.php +++ b/resources/views/backend/taxonomy/terms/index-table-row.blade.php @@ -10,7 +10,9 @@ @if ($row->parent_id != null) - {{ $row->parent->name }} + + {{ $row->parent->name }} + @else N/A @endif From 0430d07a84b4f6e71470caad8901dfc43e96d39f Mon Sep 17 00:00:00 2001 From: IsharaEkanayaka Date: Fri, 18 Oct 2024 10:15:18 +0530 Subject: [PATCH 5/5] fix: null argument for array_filter function --- app/Domains/Taxonomy/Models/TaxonomyTerm.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/Domains/Taxonomy/Models/TaxonomyTerm.php b/app/Domains/Taxonomy/Models/TaxonomyTerm.php index f8eb1dda..0cdbc5ab 100644 --- a/app/Domains/Taxonomy/Models/TaxonomyTerm.php +++ b/app/Domains/Taxonomy/Models/TaxonomyTerm.php @@ -36,7 +36,7 @@ class TaxonomyTerm extends Model public function getFormattedMetadataAttribute() { $response = array(); - $filteredMetadata = array_filter($this->metadata, function ($value) { + $filteredMetadata = array_filter(json_decode($this->metadata, true), function ($value) { return !is_null($value['value']); });