From b2060c47e29f921945a546c092196c18155ac17d Mon Sep 17 00:00:00 2001 From: Sallu9007 Date: Mon, 31 Mar 2025 20:25:18 +0530 Subject: [PATCH] Feat: Publication --- app/Http/Controllers/AdminController.php | 4 + .../Controllers/CoordinatorController.php | 5 + app/Http/Controllers/FacultyController.php | 84 ++++++- .../Controllers/PublicationsController.php | 194 ++++++++++++++++ app/Models/Publication.php | 69 ++++++ ...03_31_130003_create_publications_table.php | 53 +++++ .../views/faculty/publications-form.blade.php | 166 ++++++++++++++ resources/views/layouts/navigation.blade.php | 21 ++ resources/views/publications/edit.blade.php | 189 +++++++++++++++ resources/views/publications/index.blade.php | 216 ++++++++++++++++++ routes/web.php | 26 +++ 11 files changed, 1026 insertions(+), 1 deletion(-) create mode 100644 app/Http/Controllers/PublicationsController.php create mode 100644 app/Models/Publication.php create mode 100644 database/migrations/2025_03_31_130003_create_publications_table.php create mode 100644 resources/views/faculty/publications-form.blade.php create mode 100644 resources/views/publications/edit.blade.php create mode 100644 resources/views/publications/index.blade.php diff --git a/app/Http/Controllers/AdminController.php b/app/Http/Controllers/AdminController.php index 1e5ed67..39b6348 100644 --- a/app/Http/Controllers/AdminController.php +++ b/app/Http/Controllers/AdminController.php @@ -30,5 +30,9 @@ class AdminController extends Controller { return view('iv-organised.index'); } + public function viewPublicationsResponses() + { + return view('publications.index'); + } } diff --git a/app/Http/Controllers/CoordinatorController.php b/app/Http/Controllers/CoordinatorController.php index dab6be4..4a5c856 100644 --- a/app/Http/Controllers/CoordinatorController.php +++ b/app/Http/Controllers/CoordinatorController.php @@ -31,4 +31,9 @@ class CoordinatorController extends Controller return view('iv-organised.index'); } + public function viewPublicationsResponses() + { + return view('publications.index'); + } + } diff --git a/app/Http/Controllers/FacultyController.php b/app/Http/Controllers/FacultyController.php index 37cf60c..0d522ef 100644 --- a/app/Http/Controllers/FacultyController.php +++ b/app/Http/Controllers/FacultyController.php @@ -6,6 +6,7 @@ use Illuminate\Http\Request; use App\Models\ActivitiesAttended; use App\Models\ActivitiesOrganised; use App\Models\IvOrganised; +use App\Models\Publication; class FacultyController extends Controller { @@ -48,9 +49,19 @@ class FacultyController extends Controller return view('iv-organised.index'); } + public function PublicationsForm() + { + // Logic to show the response form + return view('faculty.publications-form'); + } + + public function viewPublicationsResponses() + { + return view('publications.index'); + } + public function ActivitiesAttendedFormResponse(Request $request) { - // dd($request->all(),"hello"); try { // Validate the request data $validated = $request->validate([ @@ -257,4 +268,75 @@ class FacultyController extends Controller return back()->withErrors('An error occurred while submitting your response: ' . $e->getMessage()); } } + + public function PublicationsFormResponse(Request $request) +{ + try { + // Validate the request data + $validated = $request->validate([ + 'first_author_name' => 'required|string', + 'co_authors' => 'nullable|string', + 'start_date' => 'required|date', + 'start_time' => 'required|date_format:H:i', + 'end_date' => 'required|date', + 'end_time' => 'required|date_format:H:i', + 'num_days' => 'required|integer', + 'activity_type' => 'required|string', + 'title' => 'required|string', + 'affiliation' => 'required|string', + 'organizing_institute' => 'required|string', + 'venue_address' => 'required|string', + 'is_peer_reviewed' => 'required|in:yes,no', + 'scopus_link' => 'nullable|url', + 'sci_link' => 'nullable|url', + 'paper_file' => 'nullable|mimes:jpg,jpeg,png,pdf,doc,docx,zip', + ]); + + // Combine start date and time + $startDateTime = date('Y-m-d H:i:s', strtotime("{$validated['start_date']} {$validated['start_time']}")); + $endDateTime = date('Y-m-d H:i:s', strtotime("{$validated['end_date']} {$validated['end_time']}")); + + // Handle the file upload + $paperFilePath = null; + if ($request->hasFile('paper_file')) { + $originalName = $request->file('paper_file')->getClientOriginalName(); + $username = auth()->user()->name; + $fileName = $username . '_' . $originalName; + + // Extract year from start_date + $year = date('Y', strtotime($validated['start_date'])); + + // Create path structure: year/faculty_name/Publications + $folderPath = 'proofs/' . $year . '/' . $username . '/Publications'; + + // Store file in the specified path + $paperFilePath = $request->file('paper_file')->storeAs($folderPath, $fileName, 'public'); + } + + // Save the response to the database + Publication::create([ + 'department_id' => auth()->user()->department->id, + 'first_author_name' => $validated['first_author_name'], + 'co_authors' => $validated['co_authors'], + 'start_date' => $startDateTime, + 'end_date' => $endDateTime, + 'num_days' => $validated['num_days'], + 'activity_type' => $validated['activity_type'], + 'title' => $validated['title'], + 'affiliation' => $validated['affiliation'], + 'organizing_institute' => $validated['organizing_institute'], + 'venue_address' => $validated['venue_address'], + 'is_peer_reviewed' => $validated['is_peer_reviewed'], + 'scopus_link' => $validated['scopus_link'], + 'sci_link' => $validated['sci_link'], + 'paper_file' => $paperFilePath, + 'faculty_id' => auth()->user()->id, + ]); + + return redirect()->route('faculty.dashboard')->with('status', 'Publication details submitted successfully'); + } catch (\Exception $e) { + // Handle the exception and provide an error message + return back()->withErrors('An error occurred while submitting your publication: ' . $e->getMessage()); + } +} } diff --git a/app/Http/Controllers/PublicationsController.php b/app/Http/Controllers/PublicationsController.php new file mode 100644 index 0000000..c794fa3 --- /dev/null +++ b/app/Http/Controllers/PublicationsController.php @@ -0,0 +1,194 @@ +validate([ + 'first_author_name' => 'required|string', + 'co_authors' => 'nullable|string', + 'start_date' => 'required|date', + 'start_time' => 'required|date_format:H:i', + 'end_date' => 'required|date', + 'end_time' => 'required|date_format:H:i', + 'num_days' => 'required|integer', + 'activity_type' => 'required|string', + 'title' => 'required|string', + 'affiliation' => 'required|string', + 'organizing_institute' => 'required|string', + 'venue_address' => 'required|string', + 'is_peer_reviewed' => 'required|in:yes,no', + 'scopus_link' => 'nullable|url', + 'sci_link' => 'nullable|url', + 'paper_file' => 'nullable|mimes:jpg,jpeg,png,pdf,doc,docx,zip', + ]); + + // Combine start date and time + $startDateTime = date('Y-m-d H:i:s', strtotime("{$validated['start_date']} {$validated['start_time']}")); + $endDateTime = date('Y-m-d H:i:s', strtotime("{$validated['end_date']} {$validated['end_time']}")); + + // Handle the file upload if a new file is provided + if ($request->hasFile('paper_file')) { + // Delete old file if exists + if ($publication->paper_file && Storage::disk('public')->exists($publication->paper_file)) { + Storage::disk('public')->delete($publication->paper_file); + } + + // Extract year from start_date + $year = date('Y', strtotime($validated['start_date'])); + $username = $publication->user->name; + + $originalName = $request->file('paper_file')->getClientOriginalName(); + $fileName = $username . '_' . $originalName; + + // Create path structure: year/faculty_name/Publications + $folderPath = 'proofs/' . $year . '/' . $username . '/Publications'; + + // Store file in the specified path + $paperFilePath = $request->file('paper_file')->storeAs($folderPath, $fileName, 'public'); + + $publication->paper_file = $paperFilePath; + } + + // Update other fields + $publication->first_author_name = $validated['first_author_name']; + $publication->co_authors = $validated['co_authors']; + $publication->start_date = $startDateTime; + $publication->end_date = $endDateTime; + $publication->num_days = $validated['num_days']; + $publication->activity_type = $validated['activity_type']; + $publication->title = $validated['title']; + $publication->affiliation = $validated['affiliation']; + $publication->organizing_institute = $validated['organizing_institute']; + $publication->venue_address = $validated['venue_address']; + $publication->is_peer_reviewed = $validated['is_peer_reviewed']; + $publication->scopus_link = $validated['scopus_link']; + $publication->sci_link = $validated['sci_link']; + + $publication->save(); + + $userRole = auth()->user()->role->name; + + if ($userRole === 'Admin') { + return redirect()->route('admin.PublicationsResponses') + ->with('status', 'Publication updated successfully'); + } elseif ($userRole === 'Coordinator') { + return redirect()->route('coordinator.PublicationsResponses') + ->with('status', 'Publication updated successfully'); + } else { + // For regular users + return redirect()->route('faculty.PublicationsResponses') + ->with('status', 'Publication updated successfully'); + } + } + + public function destroy($id) + { + $publication = Publication::findOrFail($id); + + // Delete the file if it exists + if ($publication->paper_file && Storage::disk('public')->exists($publication->paper_file)) { + Storage::disk('public')->delete($publication->paper_file); + } + + $publication->delete(); + + return response()->json(['success' => 'Publication deleted successfully']); + } + + public function getPublicationsResponses() + { + $user = auth()->user(); + $isAdmin = $user->role->name === 'Admin'; + $isCoordinator = $user->role->name === 'Coordinator'; + + // Query based on role + if ($isAdmin) { + // Admin sees all records + $publications = Publication::with('user', 'department'); + } elseif ($isCoordinator) { + // Coordinator sees only their department's records + $publications = Publication::with('user', 'department') + ->whereHas('user', function ($query) use ($user) { + $query->where('department_id', $user->department_id); + }); + } else { + // Regular users see only their own records + $publications = Publication::with('user', 'department') + ->where('faculty_id', $user->id); + } + + return DataTables::of($publications) + ->addColumn('user_name', function ($publication) { + return $publication->user->name ?? 'Unknown'; + }) + ->addColumn('department_name', function ($publication) { + return $publication->department->name ?? 'Unknown'; + }) + ->addColumn('start_date', function ($publication) { + return \Carbon\Carbon::parse($publication->start_date)->format('d-m-Y'); + }) + ->addColumn('start_time', function ($publication) { + return \Carbon\Carbon::parse($publication->start_date)->format('h:i A'); + }) + ->addColumn('end_date', function ($publication) { + return \Carbon\Carbon::parse($publication->end_date)->format('d-m-Y'); + }) + ->addColumn('end_time', function ($publication) { + return \Carbon\Carbon::parse($publication->end_date)->format('h:i A'); + }) + ->addColumn('is_scopus_indexed', function ($publication) { + return $publication->isScopusIndexed() ? 'Yes' : 'No'; + }) + ->addColumn('is_sci_indexed', function ($publication) { + return $publication->isSciIndexed() ? 'Yes' : 'No'; + }) + ->addColumn('action', function ($publication) { + $actions = []; + + // View paper_file button for everyone + if ($publication->paper_file) { + $actions[] = 'View Paper'; + } else { + $actions[] = 'No Paper'; + } + + // Edit button with role-appropriate route + $userRole = auth()->user()->role->name; + // Determine the appropriate route based on user role + if ($userRole === 'Admin') { + $editRoute = route('admin.Publications.edit', $publication->id); + } elseif ($userRole === 'Coordinator') { + $editRoute = route('coordinator.Publications.edit', $publication->id); + } else { + $editRoute = route('faculty.Publications.edit', $publication->id); + } + + $actions[] = 'Edit'; + + $deleteRoute = route('publications.destroy', $publication->id); + $actions[] = ''; + + return implode(' ', $actions); + }) + ->rawColumns(['action']) + ->make(true); + } +} \ No newline at end of file diff --git a/app/Models/Publication.php b/app/Models/Publication.php new file mode 100644 index 0000000..5778cbc --- /dev/null +++ b/app/Models/Publication.php @@ -0,0 +1,69 @@ + 'datetime', + 'end_date' => 'datetime', + 'num_days' => 'integer', + 'is_peer_reviewed' => 'string' + ]; + + /** + * Get the department that owns the publication. + */ + public function department() + { + return $this->belongsTo(Department::class); + } + + /** + * Get the faculty user that owns the publication. + */ + public function user() + { + return $this->belongsTo(User::class, 'faculty_id'); + } + + /** + * Check if the publication is Scopus indexed. + */ + public function isScopusIndexed() + { + return !is_null($this->scopus_link); + } + + /** + * Check if the publication is SCI indexed. + */ + public function isSciIndexed() + { + return !is_null($this->sci_link); + } +} \ No newline at end of file diff --git a/database/migrations/2025_03_31_130003_create_publications_table.php b/database/migrations/2025_03_31_130003_create_publications_table.php new file mode 100644 index 0000000..c3173ce --- /dev/null +++ b/database/migrations/2025_03_31_130003_create_publications_table.php @@ -0,0 +1,53 @@ +id(); + $table->unsignedBigInteger('department_id'); + $table->string('first_author_name'); + $table->text('co_authors')->nullable(); // For storing multiple co-author names + $table->dateTime('start_date'); + $table->dateTime('end_date'); + $table->integer('num_days'); + $table->string('activity_type'); + $table->string('title'); + $table->text('affiliation'); // Name of conference/journal + $table->string('organizing_institute'); + $table->text('venue_address'); + $table->enum('is_peer_reviewed', ['yes', 'no'])->default('no'); + $table->text('scopus_link')->nullable(); // Null means not Scopus indexed + $table->text('sci_link')->nullable(); // Null means not SCI indexed + $table->string('paper_file')->nullable(); // For file path + $table->unsignedBigInteger('faculty_id'); // Faculty who uploaded the publication + + // Foreign keys + $table->foreign('department_id')->references('id')->on('departments')->onDelete('cascade'); + $table->foreign('faculty_id')->references('id')->on('users')->onDelete('cascade'); + + // Indexes for better performance + $table->index('department_id'); + $table->index('faculty_id'); + $table->index(['start_date', 'end_date']); + + $table->timestamps(); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::dropIfExists('publications'); + } +}; \ No newline at end of file diff --git a/resources/views/faculty/publications-form.blade.php b/resources/views/faculty/publications-form.blade.php new file mode 100644 index 0000000..6dc561e --- /dev/null +++ b/resources/views/faculty/publications-form.blade.php @@ -0,0 +1,166 @@ +@extends('layouts.app') + +@section('content') +
+
+
+

+ Submit Publication Details +

+

+ Fill in the details of your publication. +

+
+
+
+ @csrf +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+ + +
+ + +
+
+ + +
+
+ + +
+
+ +
+ + +
+ + +
+
+ + +
+
+ + + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+ + +
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+ + +

Accepted formats: JPG, JPEG, PNG, PDF, DOC, DOCX, ZIP

+
+
+
+ + +
+ +
+ +
+
+
+
+ + +@endsection \ No newline at end of file diff --git a/resources/views/layouts/navigation.blade.php b/resources/views/layouts/navigation.blade.php index 2149324..9e26039 100644 --- a/resources/views/layouts/navigation.blade.php +++ b/resources/views/layouts/navigation.blade.php @@ -27,6 +27,9 @@ {{ __('IV Organised') }} + + {{ __('Publications') }} + @elseif(auth()->user()->role->name === 'Coordinator') @@ -39,6 +42,9 @@ {{ __('IV Organised') }} + + {{ __('Publications') }} + @elseif(auth()->user()->role->name === 'Faculty') @@ -91,6 +97,21 @@ + +
+ + +
@endif diff --git a/resources/views/publications/edit.blade.php b/resources/views/publications/edit.blade.php new file mode 100644 index 0000000..99ff791 --- /dev/null +++ b/resources/views/publications/edit.blade.php @@ -0,0 +1,189 @@ +@extends('layouts.app') + +@section('content') +
+
+
+

+ Edit Publication +

+
+ +
+ @if ($errors->any()) +
+
    + @foreach ($errors->all() as $error) +
  • {{ $error }}
  • + @endforeach +
+
+ @endif + +
+ @csrf + @method('PUT') +
+ +
+
+ + +
+
+ + +
+
+ + +
+ + +
+ + +
+
+ + +
+
+ + +
+
+ +
+ + +
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+ + +
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+ + @if ($publication->paper_file) +
+ Current file: + View +
+ @endif + +

Accepted formats: JPG, JPEG, PNG, PDF, DOC, DOCX, ZIP

+
+
+ + +
+ + Cancel + + +
+
+
+
+
+ + +@endsection \ No newline at end of file diff --git a/resources/views/publications/index.blade.php b/resources/views/publications/index.blade.php new file mode 100644 index 0000000..4641c80 --- /dev/null +++ b/resources/views/publications/index.blade.php @@ -0,0 +1,216 @@ +@extends('layouts.app') + +@section('content') +
+
+
+

+ All Publications +

+
+
+
+ + + + + + + + + + + + + + + + + + + + +
IDTitleFirst AuthorTypeJournal/ConferenceFacultyDepartmentStart DateEnd DatePeer ReviewedScopusSCIActions
+
+
+
+
+@endsection + +@section('scripts') + + + + + + + + + + + +@endsection \ No newline at end of file diff --git a/routes/web.php b/routes/web.php index 7f6653d..ecd060d 100644 --- a/routes/web.php +++ b/routes/web.php @@ -11,6 +11,7 @@ use App\Http\Controllers\AdminController; use App\Http\Controllers\CoordinatorController; use App\Http\Controllers\FacultyController; use App\Http\Controllers\IvOrganisedController; +use App\Http\Controllers\PublicationsController; use App\Http\Middleware\CheckRole; Route::get('/', function () { @@ -48,6 +49,9 @@ Route::delete('/activities-organised/{id}', [ActivitiesOrganisedController::clas // Iv Organised common routes Route::delete('/iv-organised/{id}', [IvOrganisedController::class, 'destroy'])->name('ivOrganised.destroy'); +// Publications common routes +Route::delete('/publication/{id}', [PublicationsController::class, 'destroy'])->name('publications.destroy'); + // Admin routes Route::middleware(['auth', CheckRole::class . ':Admin'])->group(function () { Route::get('/admin', [AdminController::class, 'index'])->name('admin.dashboard'); @@ -72,6 +76,13 @@ Route::middleware(['auth', CheckRole::class . ':Admin'])->group(function () { Route::get('/admin/iv-organised/{id}/edit', [IvOrganisedController::class, 'edit'])->name('admin.IvOrganised.edit'); Route::put('/admin/iv-organised/{id}', [IvOrganisedController::class, 'update'])->name('admin.IvOrganised.update'); Route::delete('/admin/iv-organised/{id}', [IvOrganisedController::class, 'destroy'])->name('admin.IvOrganised.destroy'); + + // Publications Routes + Route::get('/admin/PublicationsResponses', [AdminController::class, 'viewPublicationsResponses'])->name('admin.PublicationsResponses'); + Route::get('/admin/PublicationsResponses/data', [PublicationsController::class, 'getPublicationsResponses'])->name('admin.PublicationsResponses.data'); + Route::get('/admin/publication/{id}/edit', [PublicationsController::class, 'edit'])->name('admin.Publications.edit'); + Route::put('/admin/publication/{id}', [PublicationsController::class, 'update'])->name('admin.Publications.update'); + Route::delete('/admin/publication/{id}', [PublicationsController::class, 'destroy'])->name('admin.Publications.destroy'); }); // Coordinator routes @@ -98,6 +109,13 @@ Route::middleware(['auth', CheckRole::class . ':Coordinator'])->group(function ( Route::get('/coordinator/iv-organised/{id}/edit', [IvOrganisedController::class, 'edit'])->name('coordinator.IvOrganised.edit'); Route::put('/coordinator/iv-organised/{id}', [IvOrganisedController::class, 'update'])->name('coordinator.IvOrganised.update'); Route::delete('/coordinator/iv-organised/{id}', [IvOrganisedController::class, 'destroy'])->name('coordinator.IvOrganised.destroy'); + + // Publications Routes + Route::get('/coordinator/PublicationsResponses', [CoordinatorController::class, 'viewPublicationsResponses'])->name('coordinator.PublicationsResponses'); + Route::get('/coordinator/PublicationsResponses/data', [PublicationsController::class, 'getPublicationsResponses'])->name('coordinator.PublicationsResponses.data'); + Route::get('/coordinator/publication/{id}/edit', [PublicationsController::class, 'edit'])->name('coordinator.Publications.edit'); + Route::put('/coordinator/publication/{id}', [PublicationsController::class, 'update'])->name('coordinator.Publications.update'); + Route::delete('/coordinator/publication/{id}', [PublicationsController::class, 'destroy'])->name('coordinator.Publications.destroy'); }); // Faculty routes @@ -127,6 +145,14 @@ Route::middleware(['auth', CheckRole::class . ':Faculty'])->group(function () { Route::get('/faculty/IvOrganisedResponses/data', [IvOrganisedController::class, 'getIvOrganisedResponses'])->name('faculty.IvOrganisedResponses.data'); Route::get('/faculty/iv-organised/{id}/edit', [IvOrganisedController::class, 'edit'])->name('faculty.IvOrganised.edit'); Route::put('/faculty/iv-organised/{id}', [IvOrganisedController::class, 'update'])->name('faculty.IvOrganised.update'); + + // Publications Routes + Route::get('/faculty/PublicationsForm', [FacultyController::class, 'PublicationsForm'])->name('faculty.PublicationsForm'); + Route::post('/faculty/PublicationsFormResponse', [FacultyController::class, 'PublicationsFormResponse'])->name('faculty.PublicationsFormResponse'); + Route::get('/faculty/PublicationsResponses', [FacultyController::class, 'viewPublicationsResponses'])->name('faculty.PublicationsResponses'); + Route::get('/faculty/PublicationsResponses/data', [PublicationsController::class, 'getPublicationsResponses'])->name('faculty.PublicationsResponses.data'); + Route::get('/faculty/publication/{id}/edit', [PublicationsController::class, 'edit'])->name('faculty.Publications.edit'); + Route::put('/faculty/publication/{id}', [PublicationsController::class, 'update'])->name('faculty.Publications.update'); }); // API Resources