123 lines
4.2 KiB
PHP
123 lines
4.2 KiB
PHP
<?php
|
|
|
|
namespace App\Http\Controllers\User;
|
|
|
|
use App\Http\Controllers\Controller;
|
|
use App\Http\Requests\User\CreateProjectRequest;
|
|
use App\Jobs\TranscribeAudioJob;
|
|
use App\Models\TranscriptionProject;
|
|
use App\Services\AuditLogService;
|
|
use App\Services\StorageService;
|
|
use Illuminate\Http\JsonResponse;
|
|
use Illuminate\Http\RedirectResponse;
|
|
use Illuminate\Support\Facades\Auth;
|
|
use Illuminate\View\View;
|
|
|
|
class ProjectController extends Controller
|
|
{
|
|
public function create(): View
|
|
{
|
|
$this->authorize('create', TranscriptionProject::class);
|
|
|
|
return view('user.projects.create');
|
|
}
|
|
|
|
public function store(CreateProjectRequest $request, StorageService $storage, AuditLogService $audit): RedirectResponse
|
|
{
|
|
$this->authorize('create', TranscriptionProject::class);
|
|
|
|
$file = $request->file('audio');
|
|
$uuid = (string) \Illuminate\Support\Str::uuid();
|
|
$path = $storage->storeAudio($file, $uuid);
|
|
|
|
$project = TranscriptionProject::create([
|
|
'uuid' => $uuid,
|
|
'title' => $request->title,
|
|
'description' => $request->description,
|
|
'owner_user_id' => Auth::id(),
|
|
'original_filename' => $file->getClientOriginalName(),
|
|
'stored_audio_path' => $path,
|
|
'mime_type' => $file->getMimeType(),
|
|
'file_size' => $file->getSize(),
|
|
'language' => $request->language ?? 'ms',
|
|
'transcription_status' => 'pending',
|
|
'transcription_engine' => config('speech2text.transcription.engine'),
|
|
]);
|
|
|
|
$audit->log('project_created', [
|
|
'project_id' => $project->id,
|
|
'new_values' => ['title' => $project->title, 'uuid' => $project->uuid],
|
|
]);
|
|
|
|
$audit->log('audio_uploaded', [
|
|
'project_id' => $project->id,
|
|
'new_values' => [
|
|
'original_filename' => $project->original_filename,
|
|
'file_size' => $project->file_size,
|
|
'mime_type' => $project->mime_type,
|
|
],
|
|
]);
|
|
|
|
TranscribeAudioJob::dispatch($project);
|
|
|
|
return redirect()->route('user.projects.show', $project)
|
|
->with('success', 'Projek berjaya dicipta. Audio sedang dalam barisan untuk ditranskripkan.');
|
|
}
|
|
|
|
public function show(TranscriptionProject $project): View
|
|
{
|
|
$this->authorize('view', $project);
|
|
|
|
$project->load(['owner', 'collaborators.department', 'transcriptVersions.editor', 'comments.user']);
|
|
|
|
return view('user.projects.show', compact('project'));
|
|
}
|
|
|
|
// Endpoint polling status — JSON, tidak mendedahkan transcript
|
|
public function status(TranscriptionProject $project): JsonResponse
|
|
{
|
|
$this->authorize('view', $project);
|
|
|
|
return response()->json([
|
|
'status' => $project->transcription_status,
|
|
'duration_seconds' => $project->duration_seconds,
|
|
'processed_at' => $project->processed_at?->format('d/m/Y H:i'),
|
|
'error_message' => $project->isFailed() ? $project->error_message : null,
|
|
]);
|
|
}
|
|
|
|
public function retry(TranscriptionProject $project, AuditLogService $audit): RedirectResponse
|
|
{
|
|
$this->authorize('retryTranscription', $project);
|
|
|
|
$project->update([
|
|
'transcription_status' => 'pending',
|
|
'error_message' => null,
|
|
]);
|
|
|
|
$audit->log('transcription_started', [
|
|
'project_id' => $project->id,
|
|
'new_values' => ['retry' => true],
|
|
]);
|
|
|
|
TranscribeAudioJob::dispatch($project);
|
|
|
|
return back()->with('success', 'Transkripsi sedang dicuba semula.');
|
|
}
|
|
|
|
public function destroy(TranscriptionProject $project, AuditLogService $audit): RedirectResponse
|
|
{
|
|
$this->authorize('delete', $project);
|
|
|
|
$audit->log('project_deleted', [
|
|
'project_id' => $project->id,
|
|
'old_values' => ['title' => $project->title, 'uuid' => $project->uuid],
|
|
]);
|
|
|
|
$project->delete();
|
|
|
|
return redirect()->route('user.dashboard')
|
|
->with('success', 'Projek berjaya dipadam.');
|
|
}
|
|
}
|