diff --git a/app/Domains/AcademicProgram/Course/Models/Traits/Scope/CourseScope.php b/app/Domains/AcademicProgram/Course/Models/Traits/Scope/CourseScope.php index cc11480..6370a5f 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 eaa5a77..2e16317 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 15ee6b9..4b44456 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 fbb47ef..9fb98a0 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 94ba07b..1e04526 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 0000000..0456432 --- /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 4b15fea..1cca16e 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 07c11c7..57670b5 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