First commit
This commit is contained in:
152
app/Http/Controllers/Admin/KnowledgeItemController.php
Normal file
152
app/Http/Controllers/Admin/KnowledgeItemController.php
Normal file
@@ -0,0 +1,152 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Admin;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Http\Requests\Admin\StoreKnowledgeItemRequest;
|
||||
use App\Jobs\ReindexKnowledgeItemJob;
|
||||
use App\Models\Category;
|
||||
use App\Models\KnowledgeItem;
|
||||
use App\Services\KnowledgeBase\AuditService;
|
||||
use App\Services\KnowledgeBase\IngestionService;
|
||||
use Illuminate\Http\RedirectResponse;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\View\View;
|
||||
use RuntimeException;
|
||||
|
||||
class KnowledgeItemController extends Controller
|
||||
{
|
||||
public function __construct(
|
||||
private readonly AuditService $auditService,
|
||||
private readonly IngestionService $ingestionService,
|
||||
) {}
|
||||
|
||||
public function index(Request $request): View
|
||||
{
|
||||
$query = KnowledgeItem::with('category')
|
||||
->withTrashed();
|
||||
|
||||
if ($request->filled('category_id')) {
|
||||
$query->where('category_id', $request->category_id);
|
||||
}
|
||||
|
||||
if ($request->filled('item_type')) {
|
||||
$query->where('item_type', $request->item_type);
|
||||
}
|
||||
|
||||
if ($request->filled('search')) {
|
||||
$query->where(function ($q) use ($request) {
|
||||
$q->where('title', 'like', '%' . $request->search . '%')
|
||||
->orWhere('content', 'like', '%' . $request->search . '%');
|
||||
});
|
||||
}
|
||||
|
||||
$items = $query->latest()->paginate(20)->withQueryString();
|
||||
$categories = Category::active()->ordered()->get();
|
||||
$typeLabels = KnowledgeItem::typeLabels();
|
||||
|
||||
return view('admin.knowledge-items.index', compact('items', 'categories', 'typeLabels'));
|
||||
}
|
||||
|
||||
public function create(Request $request): View
|
||||
{
|
||||
$categories = Category::active()->ordered()->get();
|
||||
$typeLabels = KnowledgeItem::typeLabels();
|
||||
$prefillData = $request->only(['category_id', 'item_type', 'title', 'content']);
|
||||
// prefillData berguna bila convert dari feedback
|
||||
|
||||
return view('admin.knowledge-items.create', compact('categories', 'typeLabels', 'prefillData'));
|
||||
}
|
||||
|
||||
public function store(StoreKnowledgeItemRequest $request): RedirectResponse
|
||||
{
|
||||
$data = $request->validated();
|
||||
$data['created_by'] = auth()->id();
|
||||
$data['updated_by'] = auth()->id();
|
||||
|
||||
$item = KnowledgeItem::create($data);
|
||||
|
||||
$this->auditService->knowledgeItemCreated($item);
|
||||
|
||||
// Embed secara async
|
||||
ReindexKnowledgeItemJob::dispatch($item->id);
|
||||
|
||||
return redirect()
|
||||
->route('admin.knowledge-items.show', $item)
|
||||
->with('success', "Knowledge item '{$item->title}' berjaya dicipta dan sedang di-embed.");
|
||||
}
|
||||
|
||||
public function show(KnowledgeItem $knowledgeItem): View
|
||||
{
|
||||
$knowledgeItem->load('category', 'creator');
|
||||
|
||||
return view('admin.knowledge-items.show', compact('knowledgeItem'));
|
||||
}
|
||||
|
||||
public function edit(KnowledgeItem $knowledgeItem): View
|
||||
{
|
||||
$categories = Category::active()->ordered()->get();
|
||||
$typeLabels = KnowledgeItem::typeLabels();
|
||||
|
||||
return view('admin.knowledge-items.edit', compact('knowledgeItem', 'categories', 'typeLabels'));
|
||||
}
|
||||
|
||||
public function update(StoreKnowledgeItemRequest $request, KnowledgeItem $knowledgeItem): RedirectResponse
|
||||
{
|
||||
$oldValues = $knowledgeItem->only(['title', 'content', 'is_active']);
|
||||
|
||||
$data = $request->validated();
|
||||
$data['updated_by'] = auth()->id();
|
||||
|
||||
$knowledgeItem->update($data);
|
||||
|
||||
$this->auditService->knowledgeItemUpdated($knowledgeItem, $oldValues);
|
||||
|
||||
// Re-embed kerana kandungan mungkin berubah
|
||||
ReindexKnowledgeItemJob::dispatch($knowledgeItem->id);
|
||||
|
||||
return redirect()
|
||||
->route('admin.knowledge-items.show', $knowledgeItem)
|
||||
->with('success', 'Knowledge item berjaya dikemaskini dan sedang di-embed semula.');
|
||||
}
|
||||
|
||||
public function toggleStatus(KnowledgeItem $knowledgeItem): RedirectResponse
|
||||
{
|
||||
$newStatus = !$knowledgeItem->is_active;
|
||||
|
||||
$knowledgeItem->update(['is_active' => $newStatus]);
|
||||
|
||||
if (!$newStatus && $knowledgeItem->qdrant_point_id) {
|
||||
$this->ingestionService->deactivateKnowledgeItemInQdrant($knowledgeItem);
|
||||
$this->auditService->knowledgeItemDeactivated($knowledgeItem);
|
||||
} elseif ($newStatus) {
|
||||
// Reactivate — update payload Qdrant
|
||||
ReindexKnowledgeItemJob::dispatch($knowledgeItem->id);
|
||||
}
|
||||
|
||||
$status = $newStatus ? 'diaktifkan' : 'dinyahaktifkan';
|
||||
|
||||
return back()->with('success', "Item '{$knowledgeItem->title}' telah {$status}.");
|
||||
}
|
||||
|
||||
public function reindex(KnowledgeItem $knowledgeItem): RedirectResponse
|
||||
{
|
||||
ReindexKnowledgeItemJob::dispatch($knowledgeItem->id);
|
||||
|
||||
return back()->with('success', 'Re-embed telah dimulakan.');
|
||||
}
|
||||
|
||||
public function destroy(KnowledgeItem $knowledgeItem): RedirectResponse
|
||||
{
|
||||
// Deactivate dalam Qdrant dulu
|
||||
if ($knowledgeItem->qdrant_point_id) {
|
||||
$this->ingestionService->deactivateKnowledgeItemInQdrant($knowledgeItem);
|
||||
}
|
||||
|
||||
$knowledgeItem->delete(); // SoftDelete
|
||||
|
||||
return redirect()
|
||||
->route('admin.knowledge-items.index')
|
||||
->with('success', 'Knowledge item telah dipadam.');
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user