153 lines
5.1 KiB
PHP
153 lines
5.1 KiB
PHP
<?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.');
|
|
}
|
|
}
|