wip
This commit is contained in:
parent
3fe61f8ab8
commit
b92677cd75
14
laravel_app/app/Http/Controllers/ProjectController.php
Normal file
14
laravel_app/app/Http/Controllers/ProjectController.php
Normal file
|
|
@ -0,0 +1,14 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Controllers;
|
||||||
|
|
||||||
|
use Illuminate\Http\Request;
|
||||||
|
|
||||||
|
class ProjectController extends Controller
|
||||||
|
{
|
||||||
|
public function index()
|
||||||
|
{
|
||||||
|
return view('projects.index');
|
||||||
|
}
|
||||||
|
//
|
||||||
|
}
|
||||||
162
laravel_app/app/Livewire/Projects/ProjectManager.php
Normal file
162
laravel_app/app/Livewire/Projects/ProjectManager.php
Normal file
|
|
@ -0,0 +1,162 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Livewire\Projects;
|
||||||
|
|
||||||
|
use App\Models\Project;
|
||||||
|
use App\Models\ProjectBoundingBox;
|
||||||
|
use App\Models\Report;
|
||||||
|
use Illuminate\Support\Facades\Validator;
|
||||||
|
use Livewire\Component;
|
||||||
|
use Symfony\Component\Process\Process;
|
||||||
|
|
||||||
|
class ProjectManager extends Component
|
||||||
|
{
|
||||||
|
|
||||||
|
public $formData = [];
|
||||||
|
|
||||||
|
public $processOutput = '';
|
||||||
|
|
||||||
|
public $confirmingReportDeletion = false;
|
||||||
|
|
||||||
|
public $showProjectModal = false;
|
||||||
|
|
||||||
|
public $projectIdBeingDeleted;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Mount the component.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function mount()
|
||||||
|
{
|
||||||
|
$this->addBoundingBox();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function editProject(Project $project) {
|
||||||
|
$this->showProjectModal = true;
|
||||||
|
$this->formData = $project->toArray();
|
||||||
|
$this->formData['boundingBoxes'] = $project->boundingBoxes->toArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new API token.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function createProject()
|
||||||
|
{
|
||||||
|
$this->resetErrorBag();
|
||||||
|
Validator::make([
|
||||||
|
'name' => $this->formData['name'],
|
||||||
|
'boundingBoxes' => $this->formData['boundingBoxes'],
|
||||||
|
], [
|
||||||
|
'name' => ['required', 'string', 'max:255'],
|
||||||
|
'boundingBoxes' => ['required', 'array', 'min:1'],
|
||||||
|
'boundingBoxes.*.name' => ['required', 'string', 'max:255'],
|
||||||
|
'boundingBoxes.*.top_left_latitude' => ['required', 'string'],
|
||||||
|
'boundingBoxes.*.top_left_longitude' => ['required', 'string'],
|
||||||
|
'boundingBoxes.*.bottom_right_latitude' => ['required', 'string'],
|
||||||
|
'boundingBoxes.*.bottom_right_longitude' => ['required', 'string'],
|
||||||
|
])->validateWithBag('createProject');
|
||||||
|
|
||||||
|
|
||||||
|
// Define the unique identifier for the Project (for example, 'id')
|
||||||
|
$uniqueIdentifier = ['id' =>$this->formData['id'] ?? null];
|
||||||
|
|
||||||
|
// Using updateOrCreate to either update an existing project or create a new one
|
||||||
|
$project = Project::updateOrCreate($uniqueIdentifier, $this->formData);
|
||||||
|
|
||||||
|
// Preparing the bounding boxes data for upsert
|
||||||
|
// Ensure that each bounding box data array includes a 'project_id' field
|
||||||
|
$boundingBoxesData = array_map(function ($boundingBox) use ($project) {
|
||||||
|
$boundingBox['project_id'] = $project->id;
|
||||||
|
unset($boundingBox['created_at']);
|
||||||
|
unset($boundingBox['updated_at']);
|
||||||
|
if (!array_key_exists('id', $boundingBox)) {
|
||||||
|
$boundingBox['id'] = null;
|
||||||
|
}
|
||||||
|
return $boundingBox;
|
||||||
|
}, $this->formData['boundingBoxes'] ?? []);
|
||||||
|
|
||||||
|
// Using upsert to update or create bounding boxes
|
||||||
|
// You need to specify the unique fields and the fields to be updated
|
||||||
|
ProjectBoundingBox::upsert($boundingBoxesData, ['id', 'project_id'], ['name', 'top_left_latitude', 'top_left_longitude', 'bottom_right_latitude', 'bottom_right_longitude']);
|
||||||
|
|
||||||
|
$this->resetFormData();
|
||||||
|
$this->showProjectModal = false;
|
||||||
|
$this->dispatch('saved');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function addBoundingBox()
|
||||||
|
{
|
||||||
|
$this->formData['boundingBoxes'][] =
|
||||||
|
[
|
||||||
|
'name' => '',
|
||||||
|
'top_left_latitude' => '',
|
||||||
|
'top_left_longitude' => '',
|
||||||
|
'bottom_right_latitude' => '',
|
||||||
|
'bottom_right_longitude' => '',
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
public function deleteBoundingBox($index)
|
||||||
|
{
|
||||||
|
if(array_key_exists('id', $this->formData['boundingBoxes'][$index])) {
|
||||||
|
ProjectBoundingBox::whereId($this->formData['boundingBoxes'][$index]['id'])->delete();
|
||||||
|
}
|
||||||
|
unset($this->formData['boundingBoxes'][$index]);
|
||||||
|
$this->formData['boundingBoxes'] = array_values($this->formData['boundingBoxes']);
|
||||||
|
$this->dispatch('saved');
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Confirm that the given Project should be deleted.
|
||||||
|
*
|
||||||
|
* @param int $reportId
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function confirmReportDeletion($reportId)
|
||||||
|
{
|
||||||
|
$this->confirmingReportDeletion = true;
|
||||||
|
|
||||||
|
$this->reportIdBeingDeleted = $reportId;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Delete the project
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function deleteProject()
|
||||||
|
{
|
||||||
|
Project::whereId($this->reportIdBeingDeleted)->first()->delete();
|
||||||
|
$this->resetFormData();
|
||||||
|
|
||||||
|
$this->confirmingReportDeletion = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the current user of the application.
|
||||||
|
*
|
||||||
|
* @return mixed
|
||||||
|
*/
|
||||||
|
public function getProjectsProperty()
|
||||||
|
{
|
||||||
|
return Project::all();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function render()
|
||||||
|
{
|
||||||
|
return view('livewire.project-manager');
|
||||||
|
}
|
||||||
|
|
||||||
|
private function resetFormData()
|
||||||
|
{
|
||||||
|
$this->formData = [
|
||||||
|
'name' => '',
|
||||||
|
'boundingBoxes' => [],
|
||||||
|
];
|
||||||
|
$this->addBoundingBox();
|
||||||
|
}
|
||||||
|
}
|
||||||
28
laravel_app/app/Models/Project.php
Normal file
28
laravel_app/app/Models/Project.php
Normal file
|
|
@ -0,0 +1,28 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Models;
|
||||||
|
|
||||||
|
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||||
|
use Illuminate\Database\Eloquent\Model;
|
||||||
|
|
||||||
|
class Project extends Model
|
||||||
|
{
|
||||||
|
use HasFactory;
|
||||||
|
protected $fillable = [
|
||||||
|
'name',
|
||||||
|
];
|
||||||
|
|
||||||
|
protected static function boot()
|
||||||
|
{
|
||||||
|
parent::boot(); // TODO: Change the autogenerated stub
|
||||||
|
|
||||||
|
static::deleting(function ($project) {
|
||||||
|
$project->boundingBoxes()->delete();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public function boundingBoxes()
|
||||||
|
{
|
||||||
|
return $this->hasMany(ProjectBoundingBox::class);
|
||||||
|
}
|
||||||
|
}
|
||||||
24
laravel_app/app/Models/ProjectBoundingBox.php
Normal file
24
laravel_app/app/Models/ProjectBoundingBox.php
Normal file
|
|
@ -0,0 +1,24 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Models;
|
||||||
|
|
||||||
|
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||||
|
use Illuminate\Database\Eloquent\Model;
|
||||||
|
|
||||||
|
class ProjectBoundingBox extends Model
|
||||||
|
{
|
||||||
|
use HasFactory;
|
||||||
|
|
||||||
|
protected $fillable = [
|
||||||
|
'name',
|
||||||
|
'top_left_latitude',
|
||||||
|
'top_left_longitude',
|
||||||
|
'bottom_right_latitude',
|
||||||
|
'bottom_right_longitude',
|
||||||
|
];
|
||||||
|
|
||||||
|
public function project()
|
||||||
|
{
|
||||||
|
return $this->belongsTo(Project::class);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,32 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
use Illuminate\Database\Migrations\Migration;
|
||||||
|
use Illuminate\Database\Schema\Blueprint;
|
||||||
|
use Illuminate\Support\Facades\Schema;
|
||||||
|
|
||||||
|
return new class extends Migration
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Run the migrations.
|
||||||
|
*/
|
||||||
|
public function up(): void
|
||||||
|
{
|
||||||
|
Schema::create('projects', function (Blueprint $table) {
|
||||||
|
$table->id();
|
||||||
|
$table->string('name')->unique();
|
||||||
|
$table->text('mail_template')->nullable();
|
||||||
|
$table->string('mail_subject')->nullable();
|
||||||
|
$table->string('mail_frequentie')->default('weekly');
|
||||||
|
$table->string('mail_day')->default('friday');
|
||||||
|
$table->timestamps();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reverse the migrations.
|
||||||
|
*/
|
||||||
|
public function down(): void
|
||||||
|
{
|
||||||
|
Schema::dropIfExists('projects');
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
@ -0,0 +1,34 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
use App\Models\Project;
|
||||||
|
use Illuminate\Database\Migrations\Migration;
|
||||||
|
use Illuminate\Database\Schema\Blueprint;
|
||||||
|
use Illuminate\Support\Facades\Schema;
|
||||||
|
|
||||||
|
return new class extends Migration
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Run the migrations.
|
||||||
|
*/
|
||||||
|
public function up(): void
|
||||||
|
{
|
||||||
|
Schema::create('project_bounding_boxes', function (Blueprint $table) {
|
||||||
|
$table->id();
|
||||||
|
$table->foreignIdFor(Project::class);
|
||||||
|
$table->string('name');
|
||||||
|
$table->string('top_left_latitude');
|
||||||
|
$table->string('top_left_longitude');
|
||||||
|
$table->string('bottom_right_latitude');
|
||||||
|
$table->string('bottom_right_longitude');
|
||||||
|
$table->timestamps();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reverse the migrations.
|
||||||
|
*/
|
||||||
|
public function down(): void
|
||||||
|
{
|
||||||
|
Schema::dropIfExists('project_bounding_boxes');
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
@ -12,6 +12,7 @@
|
||||||
<x-slot name="form">
|
<x-slot name="form">
|
||||||
<!-- Token Name -->
|
<!-- Token Name -->
|
||||||
<div class="col-span-6 sm:col-span-4">
|
<div class="col-span-6 sm:col-span-4">
|
||||||
|
|
||||||
<x-label for="name" value="{{ __('Token Name') }}" />
|
<x-label for="name" value="{{ __('Token Name') }}" />
|
||||||
<x-input id="name" type="text" class="mt-1 block w-full" wire:model="createApiTokenForm.name" autofocus />
|
<x-input id="name" type="text" class="mt-1 block w-full" wire:model="createApiTokenForm.name" autofocus />
|
||||||
<x-input-error for="name" class="mt-2" />
|
<x-input-error for="name" class="mt-2" />
|
||||||
|
|
|
||||||
165
laravel_app/resources/views/livewire/project-manager.blade.php
Normal file
165
laravel_app/resources/views/livewire/project-manager.blade.php
Normal file
|
|
@ -0,0 +1,165 @@
|
||||||
|
<div>
|
||||||
|
<x-modal wire:model.live="showProjectModal">
|
||||||
|
<x-form-section submit="createProject">
|
||||||
|
<x-slot name="title">
|
||||||
|
{{ __('Project') }}
|
||||||
|
</x-slot>
|
||||||
|
|
||||||
|
<x-slot name="description">
|
||||||
|
{{ __('Report generator for generating reports') }}
|
||||||
|
</x-slot>
|
||||||
|
|
||||||
|
<x-slot name="form">
|
||||||
|
<!-- Token Name -->
|
||||||
|
<div class="col-span-6 sm:col-span-4">
|
||||||
|
<x-label for="name" value="{{ __('Name') }}"/>
|
||||||
|
<x-input id="name" type="text" class="mt-1 block w-full" wire:model="formData.name" autofocus/>
|
||||||
|
<x-input-error for="name" class="mt-2"/>
|
||||||
|
</div>
|
||||||
|
@foreach($formData['boundingBoxes'] as $key => $boundingBox)
|
||||||
|
{{-- <div wire:key="bounding_box_{{ $key }}">--}}
|
||||||
|
<div class="col-span-6 sm:col-span-4">
|
||||||
|
{{ __('Bounding box') }}
|
||||||
|
@if( count($this->formData['boundingBoxes']) > 1)
|
||||||
|
<button
|
||||||
|
class="cursor-pointer ml-6 text-sm text-red-500"
|
||||||
|
type="button"
|
||||||
|
wire:click="deleteBoundingBox({{ $key }})"
|
||||||
|
wire:confirm="{{ __('Are you sure you want to delete this BoundingBox?') }}"
|
||||||
|
>
|
||||||
|
Delete
|
||||||
|
</button>
|
||||||
|
@endif
|
||||||
|
</div>
|
||||||
|
<div class="col-span-6 sm:col-span-4">
|
||||||
|
<x-label for="bounding_box_{{ $key }}_name" value="{{ __('Name') }}"/>
|
||||||
|
<x-input id="bounding_box_{{ $key }}_name" type="text" class="mt-1 block w-full"
|
||||||
|
wire:model="formData.boundingBoxes.{{ $key }}.name" autofocus/>
|
||||||
|
<x-input-error for="boundingBoxes.{{ $key }}.name" class="mt-2"/>
|
||||||
|
</div>
|
||||||
|
<div class="col-span-6 sm:colspan-4 grid grid-cols-6">
|
||||||
|
<div class="col-span-6 sm:col-span-3 mr-1">
|
||||||
|
<x-label for="bounding_box_{{ $key }}_top_left_latitude"
|
||||||
|
value="{{ __('Top left Latitude') }}"/>
|
||||||
|
<x-input id="bounding_box_{{ $key }}_top_left_latitude" type="text"
|
||||||
|
class="mt-1 block w-full"
|
||||||
|
wire:model="formData.boundingBoxes.{{ $key }}.top_left_latitude"
|
||||||
|
autofocus/>
|
||||||
|
<x-input-error for="boundingBoxes.{{ $key }}.top_left_latitude" class="mt-2"/>
|
||||||
|
</div>
|
||||||
|
<div class="col-span-6 sm:col-span-3">
|
||||||
|
<x-label for="bounding_box_{{ $key }}_top_left_longitude" value="{{ __('Longitude') }}"/>
|
||||||
|
<x-input id="name" type="text" class="mt-1 block w-full"
|
||||||
|
wire:model="formData.boundingBoxes.{{ $key }}.top_left_longitude"
|
||||||
|
autofocus/>
|
||||||
|
<x-input-error for="boundingBoxes.{{ $key }}.top_left_longitude" class="mt-2"/>
|
||||||
|
</div>
|
||||||
|
<div class="col-span-6 sm:col-span-3 mr-1">
|
||||||
|
<x-label for="bounding_box_{{ $key }}_bottom_right_latitude"
|
||||||
|
value="{{ __('Bottom right Latitude') }}"/>
|
||||||
|
<x-input id="bounding_box_{{ $key }}_bottom_right_latitude" type="text"
|
||||||
|
class="mt-1 block w-full"
|
||||||
|
wire:model="formData.boundingBoxes.{{ $key }}.bottom_right_latitude"
|
||||||
|
autofocus/>
|
||||||
|
<x-input-error for="boundingBoxes.{{ $key }}.bottom_right_latitude" class="mt-2"/>
|
||||||
|
</div>
|
||||||
|
<div class="col-span-6 sm:col-span-3">
|
||||||
|
<x-label for="boundingBox_{{ $key }}_bottom_right_longitude" value="{{ __('Longitude') }}"/>
|
||||||
|
<x-input id="boundingBox_{{ $key }}_bottom_right_longitude" type="text"
|
||||||
|
class="mt-1 block w-full"
|
||||||
|
wire:model="formData.boundingBoxes.{{ $key }}.bottom_right_longitude"
|
||||||
|
autofocus/>
|
||||||
|
<x-input-error for="boundingBoxes.{{ $key }}.bottom_right_longitude" class="mt-2"/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{{-- </div>--}}
|
||||||
|
@endforeach
|
||||||
|
</x-slot>
|
||||||
|
|
||||||
|
<x-slot name="actions">
|
||||||
|
<x-action-message class="mr-3" on="saved">
|
||||||
|
{{ __('Saved.') }}
|
||||||
|
</x-action-message>
|
||||||
|
<x-secondary-button class="mr-3"
|
||||||
|
type="button"
|
||||||
|
wire:click="addBoundingBox"
|
||||||
|
>
|
||||||
|
{{ __('Add Bounding box') }}
|
||||||
|
</x-secondary-button>
|
||||||
|
<x-secondary-button class="mr-3"
|
||||||
|
type="button"
|
||||||
|
x-on:click="$wire.showProjectModal = false"
|
||||||
|
>
|
||||||
|
{{ __('Cancel') }}
|
||||||
|
</x-secondary-button>
|
||||||
|
<x-button>
|
||||||
|
{{ __('Save') }}
|
||||||
|
</x-button>
|
||||||
|
|
||||||
|
</x-slot>
|
||||||
|
</x-form-section>
|
||||||
|
</x-modal>
|
||||||
|
|
||||||
|
<!-- Manage API Tokens -->
|
||||||
|
<div class="mt-10 sm:mt-0">
|
||||||
|
<x-action-section>
|
||||||
|
<x-slot name="title">
|
||||||
|
{{ __('Manage projects') }}
|
||||||
|
</x-slot>
|
||||||
|
|
||||||
|
<x-slot name="description">
|
||||||
|
{{ __('You may delete any of your projects if they are no longer needed.') }}
|
||||||
|
</x-slot>
|
||||||
|
|
||||||
|
<!-- API Token List -->
|
||||||
|
<x-slot name="content">
|
||||||
|
<div class="space-y-6">
|
||||||
|
<x-secondary-button x-on:click="$wire.showProjectModal = true">
|
||||||
|
{{ __('Create Project') }}
|
||||||
|
</x-secondary-button>
|
||||||
|
@foreach ($this->projects->sortBy('name') as $project)
|
||||||
|
<div class="flex items-center justify-between">
|
||||||
|
<div class="break-all">
|
||||||
|
{{ $project->name }}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="flex items-center ml-2">
|
||||||
|
<button class="cursor-pointer ml-6 text-sm text-gray-500"
|
||||||
|
wire:click="editProject({{ $project->id }})">
|
||||||
|
{{ __('Edit') }}
|
||||||
|
</button>
|
||||||
|
<button class="cursor-pointer ml-6 text-sm text-red-500"
|
||||||
|
wire:click="confirmReportDeletion({{ $project->id }})">
|
||||||
|
{{ __('Delete') }}
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
@endforeach
|
||||||
|
</div>
|
||||||
|
</x-slot>
|
||||||
|
</x-action-section>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
<!-- Delete Token Report Modal -->
|
||||||
|
<x-confirmation-modal wire:model.live="confirmingReportDeletion">
|
||||||
|
<x-slot name="title">
|
||||||
|
{{ __('Delete Project') }}
|
||||||
|
</x-slot>
|
||||||
|
|
||||||
|
<x-slot name="content">
|
||||||
|
{{ __('Are you sure you would like to delete this Project?') }}
|
||||||
|
</x-slot>
|
||||||
|
|
||||||
|
<x-slot name="footer">
|
||||||
|
<x-secondary-button wire:click="$toggle('confirmingReportDeletion')" wire:loading.attr="disabled">
|
||||||
|
{{ __('Cancel') }}
|
||||||
|
</x-secondary-button>
|
||||||
|
|
||||||
|
<x-danger-button class="ml-3" wire:click="deleteProject" wire:loading.attr="disabled">
|
||||||
|
{{ __('Delete') }}
|
||||||
|
</x-danger-button>
|
||||||
|
</x-slot>
|
||||||
|
</x-confirmation-modal>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
<div>
|
<div>
|
||||||
<!-- Generate API Token -->
|
|
||||||
<x-form-section submit="createReport">
|
<x-form-section submit="createReport">
|
||||||
<x-slot name="title">
|
<x-slot name="title">
|
||||||
{{ __('Create report') }}
|
{{ __('Create report') }}
|
||||||
|
|
|
||||||
|
|
@ -21,6 +21,9 @@
|
||||||
<x-nav-link href="{{ route('report') }}" :active="request()->routeIs('report')">
|
<x-nav-link href="{{ route('report') }}" :active="request()->routeIs('report')">
|
||||||
{{ __('Report') }}
|
{{ __('Report') }}
|
||||||
</x-nav-link>
|
</x-nav-link>
|
||||||
|
<x-nav-link href="{{ route('project') }}" :active="request()->routeIs('project')">
|
||||||
|
{{ __('Project') }}
|
||||||
|
</x-nav-link>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
|
||||||
16
laravel_app/resources/views/projects/index.blade.php
Normal file
16
laravel_app/resources/views/projects/index.blade.php
Normal file
|
|
@ -0,0 +1,16 @@
|
||||||
|
<x-app-layout>
|
||||||
|
<x-slot name="header">
|
||||||
|
<h2 class="font-semibold text-xl text-gray-800 leading-tight">
|
||||||
|
{{ __('Project') }}
|
||||||
|
</h2>
|
||||||
|
</x-slot>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<div class="max-w-7xl mx-auto py-10 sm:px-6 lg:px-8">
|
||||||
|
|
||||||
|
<div class="mt-10 sm:mt-0">
|
||||||
|
@livewire('projects.project-manager')
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</x-app-layout>
|
||||||
|
|
@ -28,4 +28,5 @@
|
||||||
|
|
||||||
Route::get('/download', [\App\Http\Controllers\DownloadController::class, 'show'])->name('download');
|
Route::get('/download', [\App\Http\Controllers\DownloadController::class, 'show'])->name('download');
|
||||||
Route::get('/report', [\App\Http\Controllers\ReportController::class, 'index'])->name('report');
|
Route::get('/report', [\App\Http\Controllers\ReportController::class, 'index'])->name('report');
|
||||||
|
Route::get('/project', [\App\Http\Controllers\ProjectController::class, 'index'])->name('project');
|
||||||
});
|
});
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue