2026-05-07 23:31:33 +02:00
|
|
|
<?php
|
|
|
|
|
|
|
|
|
|
namespace App\Livewire;
|
|
|
|
|
|
|
|
|
|
use Livewire\Component;
|
2026-05-09 21:17:36 +02:00
|
|
|
use Livewire\WithFileUploads;
|
|
|
|
|
use App\Models\Project;
|
|
|
|
|
use App\Models\Phase;
|
|
|
|
|
use App\Models\Layer;
|
|
|
|
|
use App\Models\Feature;
|
|
|
|
|
use App\Services\SpatialFileConverter;
|
|
|
|
|
use Illuminate\Support\Facades\Auth;
|
|
|
|
|
use Illuminate\Support\Facades\Storage;
|
2026-05-07 23:31:33 +02:00
|
|
|
|
|
|
|
|
class LayerUpload extends Component
|
|
|
|
|
{
|
2026-05-09 21:17:36 +02:00
|
|
|
use WithFileUploads;
|
|
|
|
|
|
|
|
|
|
public $projectId;
|
|
|
|
|
public $phaseId;
|
|
|
|
|
public $uploadFile = null;
|
|
|
|
|
public $layerName = '';
|
|
|
|
|
public $layerColor = '#3b82f6';
|
|
|
|
|
|
|
|
|
|
protected $rules = [
|
|
|
|
|
'uploadFile' => 'required|file|max:51200',
|
|
|
|
|
'layerName' => 'required|string|max:255',
|
|
|
|
|
'layerColor' => 'nullable|string|size:7',
|
|
|
|
|
];
|
|
|
|
|
|
|
|
|
|
public function mount($projectId = null, $phaseId = null)
|
|
|
|
|
{
|
|
|
|
|
$this->projectId = $projectId;
|
|
|
|
|
$this->phaseId = $phaseId;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public function upload()
|
|
|
|
|
{
|
|
|
|
|
$user = Auth::user();
|
|
|
|
|
if (!$user->can('upload layers') && !$user->hasRole('Admin')) {
|
|
|
|
|
session()->flash('error', 'Sin permisos.');
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
$this->validate();
|
|
|
|
|
|
|
|
|
|
if (!$this->projectId || !$this->phaseId) {
|
|
|
|
|
session()->flash('error', 'Faltan datos del proyecto/fase.');
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
$project = Project::findOrFail($this->projectId);
|
|
|
|
|
$phase = Phase::findOrFail($this->phaseId);
|
|
|
|
|
|
|
|
|
|
$extension = strtolower($this->uploadFile->getClientOriginalExtension());
|
|
|
|
|
$mime = $this->uploadFile->getMimeType();
|
|
|
|
|
|
|
|
|
|
$allowedExtensions = ['geojson', 'kmz', 'kml', 'shp', 'dwg', 'zip'];
|
|
|
|
|
$allowedMimes = [
|
|
|
|
|
'application/vnd.google-earth.kml+xml',
|
|
|
|
|
'application/vnd.google-earth.kmz',
|
|
|
|
|
'application/zip',
|
|
|
|
|
'application/x-zip-compressed',
|
|
|
|
|
'application/x-shapefile',
|
|
|
|
|
'image/vnd.dwg',
|
|
|
|
|
'application/acad',
|
|
|
|
|
'application/geo+json',
|
|
|
|
|
'text/xml',
|
|
|
|
|
'application/xml',
|
|
|
|
|
];
|
|
|
|
|
|
|
|
|
|
if (!in_array($extension, $allowedExtensions) && !in_array($mime, $allowedMimes)) {
|
|
|
|
|
session()->flash('error', 'Tipo de archivo no permitido.');
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
$projectDir = "uploads/projects/{$project->id}/layers";
|
|
|
|
|
$originalPath = $this->uploadFile->store($projectDir, 'public');
|
|
|
|
|
$geojson = SpatialFileConverter::convertToGeoJson($this->uploadFile);
|
|
|
|
|
|
|
|
|
|
if (!$geojson) {
|
|
|
|
|
session()->flash('error', 'Conversión fallida.');
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
$layerColor = $this->layerColor ?: '#3b82f6';
|
|
|
|
|
$geojson['style'] = ['color' => $layerColor];
|
|
|
|
|
|
|
|
|
|
$layer = Layer::create([
|
|
|
|
|
'project_id' => $project->id,
|
|
|
|
|
'phase_id' => $phase->id,
|
|
|
|
|
'name' => $this->layerName,
|
|
|
|
|
'color' => $layerColor,
|
|
|
|
|
'original_file' => $originalPath,
|
|
|
|
|
'uploaded_by' => $user->id,
|
|
|
|
|
]);
|
|
|
|
|
|
|
|
|
|
if (isset($geojson['features'])) {
|
|
|
|
|
foreach ($geojson['features'] as $featureData) {
|
|
|
|
|
Feature::create([
|
|
|
|
|
'layer_id' => $layer->id,
|
|
|
|
|
'name' => $featureData['properties']['name'] ?? null,
|
|
|
|
|
'geometry' => $featureData['geometry'],
|
|
|
|
|
'properties' => $featureData['properties'] ?? [],
|
|
|
|
|
'template_id' => $featureData['properties']['template_id'] ?? null,
|
|
|
|
|
'progress' => $featureData['properties']['progress'] ?? 0,
|
|
|
|
|
'responsible' => $featureData['properties']['responsible'] ?? null,
|
|
|
|
|
]);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
$this->reset(['uploadFile', 'layerName']);
|
|
|
|
|
session()->flash('message', "Capa '{$layer->name}' importada correctamente con " . count($geojson['features'] ?? []) . ' elementos.');
|
|
|
|
|
$this->dispatch('layerUploaded', projectId: $project->id);
|
|
|
|
|
}
|
|
|
|
|
|
2026-05-07 23:31:33 +02:00
|
|
|
public function render()
|
|
|
|
|
{
|
2026-05-09 21:17:36 +02:00
|
|
|
$projects = Project::accessibleBy(Auth::user())->get();
|
|
|
|
|
$phases = $this->projectId ? Phase::where('project_id', $this->projectId)->orderBy('order')->get() : collect();
|
|
|
|
|
|
|
|
|
|
return view('livewire.layer-upload', compact('projects', 'phases'));
|
2026-05-07 23:31:33 +02:00
|
|
|
}
|
2026-05-09 21:17:36 +02:00
|
|
|
}
|