updates to document handling and code editing features
This commit is contained in:
@@ -68,6 +68,8 @@ class DocumentController extends Controller
|
||||
|
||||
$document->url = Storage::url($document->file_path);
|
||||
|
||||
$document->load('user');
|
||||
|
||||
return view('documents.show', [
|
||||
'document' => $document,
|
||||
'versions' => $document->versions()->latest()->get(),
|
||||
@@ -108,7 +110,7 @@ class DocumentController extends Controller
|
||||
foreach ($request->file('files') as $file) {
|
||||
$document = $project->documents()->create([
|
||||
'name' => $file->getClientOriginalName(),
|
||||
'status' => 'pending'
|
||||
'status' => 0
|
||||
]);
|
||||
|
||||
$this->createVersion($document, $file);
|
||||
@@ -125,4 +127,331 @@ class DocumentController extends Controller
|
||||
|
||||
$document->update(['current_version_id' => $version->id]);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Actualizar PDF con anotaciones, firmas y sellos
|
||||
*/
|
||||
public function updatePdf(Request $request, Document $document)
|
||||
{
|
||||
$this->authorize('update', $document);
|
||||
|
||||
$request->validate([
|
||||
'pdf_data' => 'required|string', // PDF modificado en base64
|
||||
'annotations' => 'sometimes|array',
|
||||
'signatures' => 'sometimes|array',
|
||||
'stamps' => 'sometimes|array',
|
||||
]);
|
||||
|
||||
try {
|
||||
// Procesar el PDF modificado
|
||||
$modifiedPdf = $this->processPdfData($request->pdf_data);
|
||||
|
||||
// Reemplazar el archivo original (sin crear nueva versión si no quieres)
|
||||
$this->replaceOriginalPdf($document, $modifiedPdf);
|
||||
|
||||
// Opcional: también crear una nueva versión para historial
|
||||
$newVersion = $this->createNewVersion($document, $modifiedPdf, $request->all());
|
||||
|
||||
return response()->json([
|
||||
'success' => true,
|
||||
'message' => 'PDF actualizado correctamente',
|
||||
'version_id' => $newVersion->id ?? null,
|
||||
]);
|
||||
|
||||
} catch (\Exception $e) {
|
||||
\Log::error('Error updating PDF: ' . $e->getMessage());
|
||||
|
||||
return response()->json([
|
||||
'success' => false,
|
||||
'message' => 'Error al actualizar el PDF: ' . $e->getMessage()
|
||||
], 500);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Procesar datos del PDF en base64
|
||||
*/
|
||||
private function processPdfData($pdfData)
|
||||
{
|
||||
// Eliminar el prefijo data:application/pdf;base64, si existe
|
||||
$pdfData = preg_replace('/^data:application\/pdf;base64,/', '', $pdfData);
|
||||
|
||||
// Decodificar base64
|
||||
$pdfContent = base64_decode($pdfData);
|
||||
|
||||
if (!$pdfContent) {
|
||||
throw new \Exception('Datos PDF inválidos');
|
||||
}
|
||||
|
||||
return $pdfContent;
|
||||
}
|
||||
|
||||
/**
|
||||
* Procesar PDF con anotaciones (método alternativo)
|
||||
*/
|
||||
private function processPdfWithAnnotations($document, $data)
|
||||
{
|
||||
// Aquí integrarías una librería PHP para PDF como spatie/pdf-to-image o setasign/fpdi
|
||||
// Por ahora, devolvemos el contenido del archivo original
|
||||
// En producción, implementarías la lógica de modificación
|
||||
|
||||
if ($document->currentVersion) {
|
||||
$filePath = $document->currentVersion->file_path;
|
||||
} else {
|
||||
$filePath = $document->getFirstMedia('documents')->getPath();
|
||||
}
|
||||
|
||||
if (!Storage::exists($filePath)) {
|
||||
throw new \Exception('Archivo PDF no encontrado');
|
||||
}
|
||||
|
||||
return Storage::get($filePath);
|
||||
}
|
||||
|
||||
/**
|
||||
* Reemplazar el PDF original
|
||||
*/
|
||||
private function replaceOriginalPdf($document, $pdfContent)
|
||||
{
|
||||
// Obtener la ruta del archivo original
|
||||
$filePath = $document->file_path;
|
||||
|
||||
// Si el documento usa media library
|
||||
if ($document->getFirstMedia('documents')) {
|
||||
$media = $document->getFirstMedia('documents');
|
||||
$media->update([
|
||||
'file_name' => $document->name . '.pdf',
|
||||
'size' => strlen($pdfContent),
|
||||
]);
|
||||
|
||||
// Reemplazar el archivo
|
||||
Storage::put($media->getPath(), $pdfContent);
|
||||
} else {
|
||||
// Si usas file_path directo
|
||||
Storage::put($filePath, $pdfContent);
|
||||
|
||||
// Actualizar metadata del documento
|
||||
$document->update([
|
||||
'file_size' => strlen($pdfContent),
|
||||
'updated_at' => now(),
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Crear nueva versión del documento
|
||||
*/
|
||||
private function createNewVersion($document, $pdfContent, $data = [])
|
||||
{
|
||||
$versionNumber = $document->versions()->count() + 1;
|
||||
$fileName = "documents/{$document->id}/v{$versionNumber}.pdf";
|
||||
|
||||
// Guardar el nuevo PDF
|
||||
Storage::put($fileName, $pdfContent);
|
||||
|
||||
// Crear registro de versión
|
||||
$version = $document->versions()->create([
|
||||
'version_number' => $versionNumber,
|
||||
'file_path' => $fileName,
|
||||
'file_size' => strlen($pdfContent),
|
||||
'hash' => hash('sha256', $pdfContent),
|
||||
'created_by' => auth()->id(),
|
||||
'metadata' => [
|
||||
'annotations_count' => count($data['annotations'] ?? []),
|
||||
'signatures_count' => count($data['signatures'] ?? []),
|
||||
'stamps_count' => count($data['stamps'] ?? []),
|
||||
'edited_at' => now()->toISOString(),
|
||||
'edited_by' => auth()->user()->name
|
||||
]
|
||||
]);
|
||||
|
||||
return $version;
|
||||
}
|
||||
|
||||
/**
|
||||
* Guardar metadatos de anotaciones
|
||||
*/
|
||||
private function saveAnnotationsMetadata($version, $data)
|
||||
{
|
||||
// Guardar anotaciones en la base de datos si es necesario
|
||||
if (!empty($data['annotations'])) {
|
||||
foreach ($data['annotations'] as $annotation) {
|
||||
$version->annotations()->create([
|
||||
'type' => $annotation['type'] ?? 'text',
|
||||
'content' => $annotation['content'] ?? '',
|
||||
'position' => $annotation['position'] ?? [],
|
||||
'page' => $annotation['page'] ?? 1,
|
||||
'created_by' => auth()->id()
|
||||
]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Subir firma
|
||||
*/
|
||||
public function uploadSignature(Request $request)
|
||||
{
|
||||
$request->validate([
|
||||
'signature' => 'required|image|max:2048|mimes:png,jpg,jpeg'
|
||||
]);
|
||||
|
||||
try {
|
||||
$user = auth()->user();
|
||||
$path = $request->file('signature')->store("signatures/{$user->id}", 'public');
|
||||
|
||||
// Opcional: Guardar en base de datos
|
||||
$user->signatures()->create([
|
||||
'file_path' => $path,
|
||||
'file_name' => $request->file('signature')->getClientOriginalName()
|
||||
]);
|
||||
|
||||
return response()->json([
|
||||
'success' => true,
|
||||
'path' => Storage::url($path),
|
||||
'filename' => basename($path)
|
||||
]);
|
||||
|
||||
} catch (\Exception $e) {
|
||||
\Log::error('Error uploading signature: ' . $e->getMessage());
|
||||
|
||||
return response()->json([
|
||||
'success' => false,
|
||||
'message' => 'Error al subir la firma'
|
||||
], 500);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Subir sello
|
||||
*/
|
||||
public function uploadStamp(Request $request)
|
||||
{
|
||||
$request->validate([
|
||||
'stamp' => 'required|image|max:2048|mimes:png,jpg,jpeg'
|
||||
]);
|
||||
|
||||
try {
|
||||
$user = auth()->user();
|
||||
$path = $request->file('stamp')->store("stamps/{$user->id}", 'public');
|
||||
|
||||
// Opcional: Guardar en base de datos
|
||||
$user->stamps()->create([
|
||||
'file_path' => $path,
|
||||
'file_name' => $request->file('stamp')->getClientOriginalName(),
|
||||
'type' => $request->type ?? 'custom'
|
||||
]);
|
||||
|
||||
return response()->json([
|
||||
'success' => true,
|
||||
'path' => Storage::url($path),
|
||||
'filename' => basename($path)
|
||||
]);
|
||||
|
||||
} catch (\Exception $e) {
|
||||
\Log::error('Error uploading stamp: ' . $e->getMessage());
|
||||
|
||||
return response()->json([
|
||||
'success' => false,
|
||||
'message' => 'Error al subir el sello'
|
||||
], 500);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Obtener firmas del usuario
|
||||
*/
|
||||
public function getSignatures()
|
||||
{
|
||||
$user = auth()->user();
|
||||
$signatures = $user->signatures()->get()->map(function($signature) {
|
||||
return [
|
||||
'id' => $signature->id,
|
||||
'url' => Storage::url($signature->file_path),
|
||||
'name' => $signature->file_name
|
||||
];
|
||||
});
|
||||
|
||||
return response()->json([
|
||||
'success' => true,
|
||||
'signatures' => $signatures
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Obtener sellos del usuario
|
||||
*/
|
||||
public function getStamps()
|
||||
{
|
||||
$user = auth()->user();
|
||||
$stamps = $user->stamps()->get()->map(function($stamp) {
|
||||
return [
|
||||
'id' => $stamp->id,
|
||||
'url' => Storage::url($stamp->file_path),
|
||||
'name' => $stamp->file_name,
|
||||
'type' => $stamp->type
|
||||
];
|
||||
});
|
||||
|
||||
return response()->json([
|
||||
'success' => true,
|
||||
'stamps' => $stamps
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Descargar documento
|
||||
*/
|
||||
public function download(Document $document, $versionId = null)
|
||||
{
|
||||
$this->authorize('view', $document);
|
||||
|
||||
$version = $versionId ?
|
||||
$document->versions()->findOrFail($versionId) :
|
||||
$document->currentVersion;
|
||||
|
||||
if (!$version || !Storage::exists($version->file_path)) {
|
||||
abort(404);
|
||||
}
|
||||
|
||||
return Storage::download($version->file_path, $document->name . '.pdf');
|
||||
}
|
||||
|
||||
/**
|
||||
* Obtener el PDF actual para edición
|
||||
*/
|
||||
public function getPdfForEditing(Document $document)
|
||||
{
|
||||
$this->authorize('view', $document);
|
||||
|
||||
try {
|
||||
if ($document->getFirstMedia('documents')) {
|
||||
$filePath = $document->getFirstMedia('documents')->getPath();
|
||||
} else {
|
||||
$filePath = $document->file_path;
|
||||
}
|
||||
|
||||
if (!Storage::exists($filePath)) {
|
||||
abort(404);
|
||||
}
|
||||
|
||||
$pdfContent = Storage::get($filePath);
|
||||
$base64Pdf = base64_encode($pdfContent);
|
||||
|
||||
return response()->json([
|
||||
'success' => true,
|
||||
'pdf_data' => $base64Pdf,
|
||||
'document_name' => $document->name
|
||||
]);
|
||||
|
||||
} catch (\Exception $e) {
|
||||
\Log::error('Error getting PDF for editing: ' . $e->getMessage());
|
||||
|
||||
return response()->json([
|
||||
'success' => false,
|
||||
'message' => 'Error al cargar el PDF'
|
||||
], 500);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
namespace App\Http\Controllers;
|
||||
|
||||
use App\Models\Category;
|
||||
use App\Models\Folder;
|
||||
use App\Models\Project;
|
||||
use App\Models\User;
|
||||
use Illuminate\Foundation\Auth\Access\AuthorizesRequests;
|
||||
@@ -11,7 +12,7 @@ use Illuminate\Support\Facades\Storage;
|
||||
|
||||
class ProjectController extends Controller
|
||||
{
|
||||
use AuthorizesRequests; // ← Añadir este trait
|
||||
use AuthorizesRequests;
|
||||
|
||||
/**
|
||||
* Display a listing of the resource.
|
||||
@@ -43,7 +44,7 @@ class ProjectController extends Controller
|
||||
'project' => $project,
|
||||
'categories' => Category::orderBy('name')->get(),
|
||||
'users' => User::where('id', '!=', auth()->id())->get(),
|
||||
'companies' => \App\Models\Company::all(), // Pass companies to the view
|
||||
'companies' => \App\Models\Company::all(), // Pass companies to the view,
|
||||
]);
|
||||
}
|
||||
|
||||
@@ -93,6 +94,12 @@ class ProjectController extends Controller
|
||||
if($request->has('categories')) {
|
||||
$project->categories()->sync($request->categories);
|
||||
}
|
||||
|
||||
Folder::create([
|
||||
'name' => 'Project',
|
||||
'project_id' => $project->id,
|
||||
'parent_id' => null,
|
||||
]);
|
||||
|
||||
return redirect()->route('projects.show', $project)->with('success', 'Proyecto creado exitosamente');
|
||||
|
||||
@@ -172,6 +179,9 @@ class ProjectController extends Controller
|
||||
//
|
||||
}
|
||||
|
||||
/**
|
||||
* Display the specified resource.
|
||||
*/
|
||||
public function __invoke(Project $project)
|
||||
{
|
||||
return view('projects.show', [
|
||||
|
||||
Reference in New Issue
Block a user