wip
This commit is contained in:
parent
b92677cd75
commit
486476d326
27
laravel_app/app/Helper.php
Normal file
27
laravel_app/app/Helper.php
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
<?php
|
||||
|
||||
namespace App;
|
||||
|
||||
class Helper
|
||||
{
|
||||
public static function getDays(): \Illuminate\Support\Collection
|
||||
{
|
||||
$startOfWeek = now()->startOfWeek();
|
||||
|
||||
$daysOfWeek = collect([]);
|
||||
for ($i = 0; $i < 7; $i++) {
|
||||
$daysOfWeek->add($startOfWeek->copy()->addDays($i)->format('l'));
|
||||
}
|
||||
|
||||
return $daysOfWeek;
|
||||
}
|
||||
|
||||
public static function getMailFrequencies(): \Illuminate\Support\Collection
|
||||
{
|
||||
return collect([
|
||||
'Weekly',
|
||||
'Monthly',
|
||||
]);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
namespace App\Http\Controllers;
|
||||
|
||||
use App\Models\Project;
|
||||
use Illuminate\Http\Request;
|
||||
|
||||
class ProjectController extends Controller
|
||||
|
|
@ -10,5 +11,10 @@ public function index()
|
|||
{
|
||||
return view('projects.index');
|
||||
}
|
||||
|
||||
public function show(Project $project)
|
||||
{
|
||||
return view('projects.show', compact('project'));
|
||||
}
|
||||
//
|
||||
}
|
||||
|
|
|
|||
21
laravel_app/app/Livewire/Projects/DownloadManager.php
Normal file
21
laravel_app/app/Livewire/Projects/DownloadManager.php
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
<?php
|
||||
|
||||
namespace App\Livewire\Projects;
|
||||
|
||||
use App\Models\Project;
|
||||
use Livewire\Component;
|
||||
|
||||
class DownloadManager extends Component
|
||||
{
|
||||
public $project;
|
||||
public function mount(Project $project) {
|
||||
$this->path = $project->download_path;
|
||||
}
|
||||
|
||||
public function render()
|
||||
{
|
||||
return view('livewire.projects.download-manager', [
|
||||
'downloads' => $this->project
|
||||
]);
|
||||
}
|
||||
}
|
||||
23
laravel_app/app/Livewire/Projects/MailingManager.php
Normal file
23
laravel_app/app/Livewire/Projects/MailingManager.php
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
<?php
|
||||
|
||||
namespace App\Livewire\Projects;
|
||||
|
||||
use App\Models\Project;
|
||||
use Livewire\Component;
|
||||
|
||||
class MailingManager extends Component
|
||||
{
|
||||
public $project;
|
||||
|
||||
public function mount(Project $project)
|
||||
{
|
||||
$this->project = $project;
|
||||
}
|
||||
|
||||
public function render()
|
||||
{
|
||||
return view('livewire.projects.mailing-manager', [
|
||||
'mailings' => $this->project->mailings()->orderBy('created_at', 'desc')->get(),
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
|
@ -4,10 +4,10 @@
|
|||
|
||||
use App\Models\Project;
|
||||
use App\Models\ProjectBoundingBox;
|
||||
use App\Models\Report;
|
||||
use App\Models\ProjectEmailRecipient;
|
||||
use Illuminate\Support\Facades\Validator;
|
||||
use Illuminate\Validation\Rule;
|
||||
use Livewire\Component;
|
||||
use Symfony\Component\Process\Process;
|
||||
|
||||
class ProjectManager extends Component
|
||||
{
|
||||
|
|
@ -20,6 +20,8 @@ class ProjectManager extends Component
|
|||
|
||||
public $showProjectModal = false;
|
||||
|
||||
public $showMailSettingsModal = false;
|
||||
|
||||
public $projectIdBeingDeleted;
|
||||
|
||||
/**
|
||||
|
|
@ -29,64 +31,59 @@ class ProjectManager extends Component
|
|||
*/
|
||||
public function mount()
|
||||
{
|
||||
$this->addBoundingBox();
|
||||
$this->resetFormData();
|
||||
}
|
||||
|
||||
public function editProject(Project $project) {
|
||||
public function editProject(Project $project)
|
||||
{
|
||||
$this->showProjectModal = true;
|
||||
$this->loadFormData($project);
|
||||
}
|
||||
|
||||
public function editMailSettings(Project $project)
|
||||
{
|
||||
$this->showMailSettingsModal = true;
|
||||
$this->loadFormData($project);
|
||||
}
|
||||
|
||||
private function loadFormData(Project $project)
|
||||
{
|
||||
$this->formData = $project->toArray();
|
||||
$this->formData['boundingBoxes'] = $project->boundingBoxes->toArray();
|
||||
$this->formData['mail_recipients'] = $project->emailRecipients->toArray() ?: [
|
||||
[
|
||||
'name' => '',
|
||||
'email' => '',
|
||||
]
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new API token.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function createProject()
|
||||
public function openCreateProjectModal()
|
||||
{
|
||||
$this->resetFormData();
|
||||
$this->showProjectModal = true;
|
||||
}
|
||||
|
||||
public function saveProject()
|
||||
{
|
||||
$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->validateForm();
|
||||
Project::saveWithFormData($this->formData);
|
||||
$this->resetFormData();
|
||||
$this->showProjectModal = false;
|
||||
$this->dispatch('saved');
|
||||
}
|
||||
|
||||
public function saveMailSettings()
|
||||
{
|
||||
$this->resetErrorBag();
|
||||
$this->validateEmailSettingsForm();
|
||||
Project::saveWithFormData($this->formData);
|
||||
$this->resetFormData();
|
||||
$this->showMailSettingsModal = false;
|
||||
$this->dispatch('saved');
|
||||
}
|
||||
|
||||
public function addBoundingBox()
|
||||
{
|
||||
$this->formData['boundingBoxes'][] =
|
||||
|
|
@ -99,9 +96,19 @@ public function addBoundingBox()
|
|||
];
|
||||
}
|
||||
|
||||
public function addEmailRecipient()
|
||||
{
|
||||
$this->formData['mail_recipients'][] =
|
||||
[
|
||||
'name' => '',
|
||||
'email' => '',
|
||||
];
|
||||
}
|
||||
|
||||
|
||||
public function deleteBoundingBox($index)
|
||||
{
|
||||
if(array_key_exists('id', $this->formData['boundingBoxes'][$index])) {
|
||||
if (array_key_exists('id', $this->formData['boundingBoxes'][$index])) {
|
||||
ProjectBoundingBox::whereId($this->formData['boundingBoxes'][$index]['id'])->delete();
|
||||
}
|
||||
unset($this->formData['boundingBoxes'][$index]);
|
||||
|
|
@ -109,6 +116,16 @@ public function deleteBoundingBox($index)
|
|||
$this->dispatch('saved');
|
||||
}
|
||||
|
||||
public function deleteEmailRecipient($index)
|
||||
{
|
||||
if (array_key_exists('id', $this->formData['mail_recipients'][$index])) {
|
||||
ProjectEmailRecipient::whereId($this->formData['mail_recipients'][$index]['id'])->delete();
|
||||
}
|
||||
unset($this->formData['mail_recipients'][$index]);
|
||||
$this->formData['mail_recipients'] = array_values($this->formData['mail_recipients']);
|
||||
$this->dispatch('saved');
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Confirm that the given Project should be deleted.
|
||||
|
|
@ -154,9 +171,57 @@ public function render()
|
|||
private function resetFormData()
|
||||
{
|
||||
$this->formData = [
|
||||
'name' => '',
|
||||
'boundingBoxes' => [],
|
||||
'name' => '',
|
||||
'boundingBoxes' => [],
|
||||
'mail_subject' => '',
|
||||
'mail_template' => '',
|
||||
'mail_frequency' => '',
|
||||
'mail_day' => '',
|
||||
'mail_recipients' => [],
|
||||
];
|
||||
$this->addBoundingBox();
|
||||
$this->addEmailRecipient();
|
||||
}
|
||||
|
||||
private function validateForm()
|
||||
{
|
||||
$projectIdentifier = $this->formData['id'] ?? null;
|
||||
|
||||
Validator::make([
|
||||
'name' => $this->formData['name'],
|
||||
'boundingBoxes' => $this->formData['boundingBoxes'],
|
||||
], [
|
||||
'name' => [
|
||||
'required',
|
||||
Rule::unique('projects')->ignore($projectIdentifier),
|
||||
'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('saveProject');
|
||||
}
|
||||
|
||||
private function validateEmailSettingsForm()
|
||||
{
|
||||
Validator::make([
|
||||
'mail_template' => $this->formData['mail_template'],
|
||||
'mail_subject' => $this->formData['mail_subject'],
|
||||
'mail_frequency' => $this->formData['mail_frequency'],
|
||||
'mail_day' => $this->formData['mail_day'],
|
||||
'mail_recipients' => $this->formData['mail_recipients'],
|
||||
], [
|
||||
'mail_template' => ['required', 'string',],
|
||||
'mail_subject' => ['required', 'string',],
|
||||
'mail_frequency' => ['required', 'string',],
|
||||
'mail_day' => ['required', 'string',],
|
||||
'mail_recipients' => ['required', 'array', 'min:1'],
|
||||
'mail_recipients.*.name' => ['required', 'string', 'max:255'],
|
||||
'mail_recipients.*.email' => ['required', 'email'],
|
||||
])->validateWithBag('saveEmailSettingsForm');
|
||||
}
|
||||
}
|
||||
|
|
|
|||
13
laravel_app/app/Livewire/Projects/ReportManager.php
Normal file
13
laravel_app/app/Livewire/Projects/ReportManager.php
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
<?php
|
||||
|
||||
namespace App\Livewire\Projects;
|
||||
|
||||
use Livewire\Component;
|
||||
|
||||
class ReportManager extends Component
|
||||
{
|
||||
public function render()
|
||||
{
|
||||
return view('livewire.projects.report-manager');
|
||||
}
|
||||
}
|
||||
|
|
@ -8,16 +8,75 @@
|
|||
class Project extends Model
|
||||
{
|
||||
use HasFactory;
|
||||
|
||||
protected $fillable = [
|
||||
|
||||
'name',
|
||||
'mail_template',
|
||||
'mail_subject',
|
||||
'mail_frequency',
|
||||
'mail_day',
|
||||
];
|
||||
|
||||
public static function saveWithFormData(mixed $formData)
|
||||
{
|
||||
$uniqueIdentifier = ['id' => $formData['id'] ?? null];
|
||||
$project = Project::updateOrCreate($uniqueIdentifier, $formData);
|
||||
$project->upsertBoundingBox($formData);
|
||||
$project->upsertMailRecipients($formData);
|
||||
}
|
||||
|
||||
private function upsertBoundingBox($formData)
|
||||
{
|
||||
$boundingBoxesData = array_map(function ($boundingBox) {
|
||||
$boundingBox['project_id'] = $this->id;
|
||||
unset($boundingBox['created_at']);
|
||||
unset($boundingBox['updated_at']);
|
||||
$boundingBox['id'] ??= null;
|
||||
return $boundingBox;
|
||||
}, $formData['boundingBoxes'] ?? []);
|
||||
|
||||
ProjectBoundingBox::upsert(
|
||||
$boundingBoxesData,
|
||||
['id', 'project_id'],
|
||||
[
|
||||
'name',
|
||||
'top_left_latitude',
|
||||
'top_left_longitude',
|
||||
'bottom_right_latitude',
|
||||
'bottom_right_longitude'
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
private function upsertMailRecipients($formData)
|
||||
{
|
||||
$mailRecipientsData = array_map(function ($mailRecipient) {
|
||||
$mailRecipient['project_id'] = $this->id;
|
||||
unset($mailRecipient['created_at']);
|
||||
unset($mailRecipient['updated_at']);
|
||||
$mailRecipient['id'] ??= null;
|
||||
return $mailRecipient;
|
||||
}, $formData['mail_recipients'] ?? []);
|
||||
ProjectEmailRecipient::upsert(
|
||||
$mailRecipientsData,
|
||||
['id', 'project_id'],
|
||||
['name', 'email',]
|
||||
);
|
||||
}
|
||||
|
||||
protected static function boot()
|
||||
{
|
||||
parent::boot(); // TODO: Change the autogenerated stub
|
||||
|
||||
static::deleting(function ($project) {
|
||||
$project->boundingBoxes()->delete();
|
||||
$project->emailRecipients()->delete();
|
||||
$project->mailings()->each(function ($mailing) {
|
||||
$mailing->attachments()->delete();
|
||||
$mailing->recipients()->delete();
|
||||
});
|
||||
$project->mailings()->delete();
|
||||
});
|
||||
}
|
||||
|
||||
|
|
@ -25,4 +84,19 @@ public function boundingBoxes()
|
|||
{
|
||||
return $this->hasMany(ProjectBoundingBox::class);
|
||||
}
|
||||
|
||||
public function emailRecipients()
|
||||
{
|
||||
return $this->hasMany(ProjectEmailRecipient::class);
|
||||
}
|
||||
|
||||
public function mailings()
|
||||
{
|
||||
return $this->hasMany(ProjectMailing::class);
|
||||
}
|
||||
|
||||
public function downloads()
|
||||
{
|
||||
return $this->hasMany(ProjectDownload::class);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
11
laravel_app/app/Models/ProjectDownload.php
Normal file
11
laravel_app/app/Models/ProjectDownload.php
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
<?php
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
|
||||
class ProjectDownload extends Model
|
||||
{
|
||||
use HasFactory;
|
||||
}
|
||||
16
laravel_app/app/Models/ProjectEmailRecipient.php
Normal file
16
laravel_app/app/Models/ProjectEmailRecipient.php
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
<?php
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
|
||||
class ProjectEmailRecipient extends Model
|
||||
{
|
||||
use HasFactory;
|
||||
|
||||
protected $fillable = [
|
||||
'name',
|
||||
'email',
|
||||
];
|
||||
}
|
||||
31
laravel_app/app/Models/ProjectMailing.php
Normal file
31
laravel_app/app/Models/ProjectMailing.php
Normal file
|
|
@ -0,0 +1,31 @@
|
|||
<?php
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
|
||||
class ProjectMailing extends Model
|
||||
{
|
||||
use HasFactory;
|
||||
|
||||
protected $fillable = [
|
||||
'subject',
|
||||
'message',
|
||||
];
|
||||
|
||||
public function project()
|
||||
{
|
||||
return $this->belongsTo(Project::class);
|
||||
}
|
||||
|
||||
public function recipients()
|
||||
{
|
||||
return $this->hasMany(ProjectMailingRecipient::class);
|
||||
}
|
||||
|
||||
public function attachments()
|
||||
{
|
||||
return $this->hasMany(ProjectMailingAttachment::class);
|
||||
}
|
||||
}
|
||||
16
laravel_app/app/Models/ProjectMailingAttachment.php
Normal file
16
laravel_app/app/Models/ProjectMailingAttachment.php
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
<?php
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
|
||||
class ProjectMailingAttachment extends Model
|
||||
{
|
||||
use HasFactory;
|
||||
|
||||
protected $fillable = [
|
||||
'name',
|
||||
'path',
|
||||
];
|
||||
}
|
||||
11
laravel_app/app/Models/ProjectMailingRecipient.php
Normal file
11
laravel_app/app/Models/ProjectMailingRecipient.php
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
<?php
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
|
||||
class ProjectMailingRecipient extends Model
|
||||
{
|
||||
use HasFactory;
|
||||
}
|
||||
|
|
@ -16,8 +16,9 @@ public function up(): void
|
|||
$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->string('mail_frequency')->default('Weekly');
|
||||
$table->string('download_path')->unique();
|
||||
$table->string('mail_day')->default('Friday');
|
||||
$table->timestamps();
|
||||
});
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,31 @@
|
|||
<?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_email_recipients', function (Blueprint $table) {
|
||||
$table->id();
|
||||
$table->foreignIdFor(Project::class);
|
||||
$table->string('email');
|
||||
$table->string('name');
|
||||
$table->timestamps();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*/
|
||||
public function down(): void
|
||||
{
|
||||
Schema::dropIfExists('project_email_recipients');
|
||||
}
|
||||
};
|
||||
|
|
@ -0,0 +1,31 @@
|
|||
<?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('project_mailings', function (Blueprint $table) {
|
||||
$table->id();
|
||||
$table->foreignId('project_id');
|
||||
$table->string('subject');
|
||||
$table->text('message');
|
||||
// $table->text('recipients');
|
||||
$table->timestamps();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*/
|
||||
public function down(): void
|
||||
{
|
||||
Schema::dropIfExists('project_mailings');
|
||||
}
|
||||
};
|
||||
|
|
@ -0,0 +1,30 @@
|
|||
<?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('project_mailing_recipients', function (Blueprint $table) {
|
||||
$table->id();
|
||||
$table->foreignId('project_mailing_id');
|
||||
$table->string('email');
|
||||
$table->string('name')->nullable();
|
||||
$table->timestamps();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*/
|
||||
public function down(): void
|
||||
{
|
||||
Schema::dropIfExists('project_mailing_recipients');
|
||||
}
|
||||
};
|
||||
|
|
@ -0,0 +1,30 @@
|
|||
<?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('project_mailing_attachments', function (Blueprint $table) {
|
||||
$table->id();
|
||||
$table->foreignId('project_mailing_id');
|
||||
$table->string('name');
|
||||
$table->string('path');
|
||||
$table->timestamps();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*/
|
||||
public function down(): void
|
||||
{
|
||||
Schema::dropIfExists('project_mailing_attachments');
|
||||
}
|
||||
};
|
||||
|
|
@ -0,0 +1,30 @@
|
|||
<?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('project_downloads', function (Blueprint $table) {
|
||||
$table->id();
|
||||
$table->foreignId('project_id');
|
||||
$table->string('name');
|
||||
$table->string('path');
|
||||
$table->timestamps();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*/
|
||||
public function down(): void
|
||||
{
|
||||
Schema::dropIfExists('project_downloads');
|
||||
}
|
||||
};
|
||||
|
|
@ -14,11 +14,244 @@ public function run(): void
|
|||
{
|
||||
// \App\Models\User::factory(10)->create();
|
||||
|
||||
\App\Models\User::factory()->create([
|
||||
'name' => 'Martin Folkerts',
|
||||
'email' => 'martin@sobit.nl',
|
||||
'password' => '$2y$10$hZZaAaiv1KXmCqq5vZ6PEeRWzvwGbaHKcfqeEMlTn.y22EEPVtofi',
|
||||
\App\Models\User::factory()->create([
|
||||
'name' => 'Martin Folkerts',
|
||||
'email' => 'martin@sobit.nl',
|
||||
'password' => '$2y$10$hZZaAaiv1KXmCqq5vZ6PEeRWzvwGbaHKcfqeEMlTn.y22EEPVtofi',
|
||||
]);
|
||||
|
||||
]);
|
||||
$this->createChembaProject();
|
||||
$this->createXinavaneProject();
|
||||
$this->createKakiraProject();
|
||||
|
||||
|
||||
}
|
||||
|
||||
private function createChembaProject()
|
||||
{
|
||||
$chembaProject = \App\Models\Project::create([
|
||||
'name' => 'Chemba',
|
||||
'mail_template' => 'Mail template for Chemba',
|
||||
'mail_subject' => 'SmartCane update Chemba for {date}',
|
||||
'mail_frequency' => 'Weekly',
|
||||
'mail_day' => 'Friday',
|
||||
'download_path' => 'chemba',
|
||||
'created_at' => '2021-01-01 00:00:00',
|
||||
'updated_at' => '2021-01-01 00:00:00',
|
||||
]);
|
||||
|
||||
$chembaProject->boundingBoxes()->createMany([
|
||||
[
|
||||
'name' => 'Chemba West',
|
||||
'top_left_latitude' => 34.9460,
|
||||
'top_left_longitude' => -17.3516,
|
||||
'bottom_right_latitude' => 34.9380,
|
||||
'bottom_right_longitude' => -17.2917,
|
||||
'created_at' => '2021-01-01 00:00:00',
|
||||
'updated_at' => '2021-01-01 00:00:00',
|
||||
],
|
||||
[
|
||||
'name' => 'Chemba East',
|
||||
'top_left_latitude' => 34.8830,
|
||||
'top_left_longitude' => -17.3516,
|
||||
'bottom_right_latitude' => 34.9380,
|
||||
'bottom_right_longitude' => -17.2917,
|
||||
'created_at' => '2021-01-01 00:00:00',
|
||||
'updated_at' => '2021-01-01 00:00:00',
|
||||
],
|
||||
]);
|
||||
|
||||
$chembaProject->emailRecipients()->createMany([
|
||||
[
|
||||
'name' => 'Martin Folkerts',
|
||||
'email' => 'martin@sobit.nl',
|
||||
'created_at' => '2021-01-01 00:00:00',
|
||||
'updated_at' => '2021-01-01 00:00:00',
|
||||
], [
|
||||
'name' => 'Timon Weitkamp',
|
||||
'email' => 'timon@smartfarmingtech.com',
|
||||
'created_at' => '2021-01-01 00:00:00',
|
||||
'updated_at' => '2021-01-01 00:00:00',
|
||||
],
|
||||
]);
|
||||
|
||||
$chembaProject->mailings()->createMany([
|
||||
[
|
||||
'subject' => 'Chemba 2021-01-01',
|
||||
'message' => 'Chemba 2021-01-01',
|
||||
'created_at' => '2021-01-01 00:00:00',
|
||||
'updated_at' => '2021-01-01 00:00:00',
|
||||
], [
|
||||
'subject' => 'Chemba 2021-01-08',
|
||||
'message' => 'Chemba 2021-01-08',
|
||||
'created_at' => '2021-01-08 00:00:00',
|
||||
'updated_at' => '2021-01-08 00:00:00',
|
||||
],
|
||||
]);
|
||||
|
||||
foreach ($chembaProject->mailings as $mailing) {
|
||||
$mailing->recipients()->createMany([
|
||||
[
|
||||
'name' => 'Martin Folkerts',
|
||||
'email' => 'martin@sobit.nl',
|
||||
'created_at' => $mailing->created_at,
|
||||
'updated_at' => $mailing->updated_at,
|
||||
], [
|
||||
'name' => 'Timon Weitkamp',
|
||||
'email' => 'timon@smartfarmingtech.com',
|
||||
'created_at' => $mailing->created_at,
|
||||
'updated_at' => $mailing->updated_at,
|
||||
],
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
private function createXinavaneProject()
|
||||
{
|
||||
$project = \App\Models\Project::create([
|
||||
'name' => 'Xinavane',
|
||||
'mail_template' => 'Mail template for Xinavane',
|
||||
'mail_subject' => 'SmartCane update Xinavane for {date}',
|
||||
'mail_frequency' => 'Weekly',
|
||||
'mail_day' => 'Friday',
|
||||
'download_path' => 'xinavane',
|
||||
'created_at' => '2021-01-01 00:00:00',
|
||||
'updated_at' => '2021-01-01 00:00:00',
|
||||
]);
|
||||
|
||||
$project->boundingBoxes()->createMany([
|
||||
[
|
||||
'name' => 'Xinavane West',
|
||||
'top_left_latitude' => 32.6213,
|
||||
'top_left_longitude' => -25.0647,
|
||||
'bottom_right_latitude' => 32.6284,
|
||||
'bottom_right_longitude' => -25.0570,
|
||||
'created_at' => '2021-01-01 00:00:00',
|
||||
'updated_at' => '2021-01-01 00:00:00',
|
||||
],
|
||||
[
|
||||
'name' => 'Xinavane East',
|
||||
'top_left_latitude' => 32.6790,
|
||||
'top_left_longitude' => -25.0333,
|
||||
'bottom_right_latitude' => 32.7453,
|
||||
'bottom_right_longitude' => -25.0235,
|
||||
'created_at' => '2021-01-01 00:00:00',
|
||||
'updated_at' => '2021-01-01 00:00:00',
|
||||
],
|
||||
]);
|
||||
|
||||
$project->emailRecipients()->createMany([
|
||||
[
|
||||
'name' => 'Martin Folkerts',
|
||||
'email' => 'martin@sobit.nl',
|
||||
'created_at' => '2021-01-01 00:00:00',
|
||||
'updated_at' => '2021-01-01 00:00:00',
|
||||
], [
|
||||
'name' => 'Timon Weitkamp',
|
||||
'email' => 'timon@smartfarmingtech.com',
|
||||
'created_at' => '2021-01-01 00:00:00',
|
||||
'updated_at' => '2021-01-01 00:00:00',
|
||||
],
|
||||
]);
|
||||
|
||||
$project->mailings()->createMany([
|
||||
[
|
||||
'subject' => 'Xinavane 2021-01-01',
|
||||
'message' => 'Xinavane 2021-01-01',
|
||||
'created_at' => '2021-01-01 00:00:00',
|
||||
'updated_at' => '2021-01-01 00:00:00',
|
||||
], [
|
||||
'subject' => 'Xinavane 2021-01-08',
|
||||
'message' => 'Xinavane 2021-01-08',
|
||||
'created_at' => '2021-01-08 00:00:00',
|
||||
'updated_at' => '2021-01-08 00:00:00',
|
||||
],
|
||||
]);
|
||||
|
||||
foreach ($project->mailings as $mailing) {
|
||||
$mailing->recipients()->createMany([
|
||||
[
|
||||
'name' => 'Martin Folkerts',
|
||||
'email' => 'martin@sobit.nl',
|
||||
'created_at' => $mailing->created_at,
|
||||
'updated_at' => $mailing->updated_at,
|
||||
], [
|
||||
'name' => 'Timon Weitkamp',
|
||||
'email' => 'timon@smartfarmingtech.com',
|
||||
'created_at' => $mailing->created_at,
|
||||
'updated_at' => $mailing->updated_at,
|
||||
],
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
private function createKakiraProject()
|
||||
{
|
||||
$project = \App\Models\Project::create([
|
||||
'name' => 'Kakira',
|
||||
'mail_template' => 'Mail template for Kakira',
|
||||
'mail_subject' => 'SmartCane update Kakira for {date}',
|
||||
'mail_frequency' => 'Weekly',
|
||||
'mail_day' => 'Friday',
|
||||
'download_path' => 'kakira',
|
||||
'created_at' => '2021-01-01 00:00:00',
|
||||
'updated_at' => '2021-01-01 00:00:00',
|
||||
]);
|
||||
|
||||
$project->boundingBoxes()->createMany([
|
||||
[
|
||||
'name' => 'kakira_demo',
|
||||
'top_left_latitude' => 33.289993827426535,
|
||||
'top_left_longitude' => 0.491981861534345,
|
||||
'bottom_right_latitude' => 33.32572075441914,
|
||||
'bottom_right_longitude' => 0.5144195937114393,
|
||||
'created_at' => '2021-01-01 00:00:00',
|
||||
'updated_at' => '2021-01-01 00:00:00',
|
||||
],
|
||||
]);
|
||||
|
||||
$project->emailRecipients()->createMany([
|
||||
[
|
||||
'name' => 'Martin Folkerts',
|
||||
'email' => 'martin@sobit.nl',
|
||||
'created_at' => '2021-01-01 00:00:00',
|
||||
'updated_at' => '2021-01-01 00:00:00',
|
||||
], [
|
||||
'name' => 'Timon Weitkamp',
|
||||
'email' => 'timon@smartfarmingtech.com',
|
||||
'created_at' => '2021-01-01 00:00:00',
|
||||
'updated_at' => '2021-01-01 00:00:00',
|
||||
],
|
||||
]);
|
||||
|
||||
$project->mailings()->createMany([
|
||||
[
|
||||
'subject' => 'Kakira 2021-01-01',
|
||||
'message' => 'Kakira 2021-01-01',
|
||||
'created_at' => '2021-01-01 00:00:00',
|
||||
'updated_at' => '2021-01-01 00:00:00',
|
||||
], [
|
||||
'subject' => 'Kakira 2021-01-08',
|
||||
'message' => 'Kakira 2021-01-08',
|
||||
'created_at' => '2021-01-08 00:00:00',
|
||||
'updated_at' => '2021-01-08 00:00:00',
|
||||
],
|
||||
]);
|
||||
|
||||
foreach ($project->mailings as $mailing) {
|
||||
$mailing->recipients()->createMany([
|
||||
[
|
||||
'name' => 'Martin Folkerts',
|
||||
'email' => 'martin@sobit.nl',
|
||||
'created_at' => $mailing->created_at,
|
||||
'updated_at' => $mailing->updated_at,
|
||||
], [
|
||||
'name' => 'Timon Weitkamp',
|
||||
'email' => 'timon@smartfarmingtech.com',
|
||||
'created_at' => $mailing->created_at,
|
||||
'updated_at' => $mailing->updated_at,
|
||||
],
|
||||
]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
25
laravel_app/resources/views/components/form-modal.blade.php
Normal file
25
laravel_app/resources/views/components/form-modal.blade.php
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
@props(['submit'])
|
||||
|
||||
<div {{ $attributes->merge(['class' => 'md:grid md:grid-cols-1 md:gap-6']) }}>
|
||||
<div class="mt-5 px-6">
|
||||
<h2>{{ $title }}</h2>
|
||||
|
||||
<span name="description">{{ $description }}</span>
|
||||
</div>
|
||||
|
||||
<div class="mt-5 md:mt-0 md:col-span-1">
|
||||
<form wire:submit="{{ $submit }}">
|
||||
<div class="px-4 py-5 bg-white sm:p-6 shadow {{ isset($actions) ? 'sm:rounded-tl-md sm:rounded-tr-md' : 'sm:rounded-md' }}">
|
||||
<div class="grid grid-cols-6 gap-6">
|
||||
{{ $form }}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@if (isset($actions))
|
||||
<div class="flex items-center justify-end px-4 py-3 bg-gray-50 text-right sm:px-6 shadow sm:rounded-bl-md sm:rounded-br-md">
|
||||
{{ $actions }}
|
||||
</div>
|
||||
@endif
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -9,6 +9,8 @@
|
|||
'lg' => 'sm:max-w-lg',
|
||||
'xl' => 'sm:max-w-xl',
|
||||
'2xl' => 'sm:max-w-2xl',
|
||||
'4xl' => 'sm:max-w-4xl',
|
||||
'6xl' => 'sm:max-w-6xl',
|
||||
][$maxWidth ?? '2xl'];
|
||||
@endphp
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,19 @@
|
|||
<x-confirmation-modal wire:model.live="confirmingReportDeletion" {{ $attributes }}>
|
||||
<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>
|
||||
|
|
@ -0,0 +1,45 @@
|
|||
@props([
|
||||
/** @var \App\Livewire\Projects\ProjectManager */
|
||||
'projectManager'
|
||||
])
|
||||
|
||||
<div {{ $attributes->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>
|
||||
|
||||
<x-slot name="content">
|
||||
<div class="space-y-6">
|
||||
<x-secondary-button wire:click="openCreateProjectModal">
|
||||
{{ __('Create Project') }}
|
||||
</x-secondary-button>
|
||||
@foreach ($projectManager->projects->sortBy('name') as $project)
|
||||
<div class="flex items-center justify-between">
|
||||
<div class="break-all">
|
||||
<a href="{!! route('project.show', $project->id) !!}">{{ $project->name }}</a>
|
||||
</div>
|
||||
<div class="flex items-center ml-2">
|
||||
<button class="cursor-pointer ml-6 text-sm text-gray-500"
|
||||
wire:click="editMailSettings({{ $project->id }})">
|
||||
{{ __('Mail') }}
|
||||
</button>
|
||||
<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>
|
||||
|
|
@ -0,0 +1,104 @@
|
|||
@props([
|
||||
/** @var \App\Livewire\Projects\ProjectManager */
|
||||
'projectManager'
|
||||
])
|
||||
|
||||
<x-modal max-width="4xl" wire:model.live="showMailSettingsModal" {{ $attributes }}>
|
||||
<x-form-modal submit="saveMailSettings">
|
||||
<x-slot name="title">
|
||||
{{ __('Project') }} : {{ $projectManager->formData['name'] ?? '' }}
|
||||
</x-slot>
|
||||
|
||||
<x-slot name="description">
|
||||
{{ __('Email settings for project.') }}
|
||||
</x-slot>
|
||||
|
||||
<x-slot name="form">
|
||||
<div class="col-span-6 sm:col-span-4">
|
||||
<x-label for="email_subject" value="{{ __('Subject') }}"/>
|
||||
<x-input id="email_subject" type="text" class="mt-1 block w-full" wire:model="formData.mail_subject" autofocus/>
|
||||
<x-input-error for="mail_subject" class="mt-2"/>
|
||||
</div>
|
||||
<div class="col-span-6 sm:col-span-4">
|
||||
<x-label for="email_template" value="{{ __('Template') }}"/>
|
||||
<textarea id="email_template" type="text" class="mt-1 block w-full h-[200px] 'border-gray-300 focus:border-indigo-500 focus:ring-indigo-500 rounded-md shadow-sm" wire:model="formData.mail_template" autofocus></textarea>
|
||||
<x-input-error for="mail_template" class="mt-2"/>
|
||||
</div>
|
||||
<div class="col-span-6 sm:col-span-4">
|
||||
<x-label for="email_frequency" value="{{ __('Frequency') }}"/>
|
||||
<select id="email_frequency" class="mt-1 block w-full" wire:model="formData.mail_frequency">
|
||||
@foreach(App\Helper::getMailFrequencies() as $frequency)
|
||||
<option value="{{ $frequency }}">{{ $frequency }}</option>
|
||||
@endforeach
|
||||
</select>
|
||||
<x-input-error for="mail_frequency" class="mt-2"/>
|
||||
</div>
|
||||
<div class="col-span-6 sm:col-span-4">
|
||||
<x-label for="mail_day" value="{{ __('Day') }}"/>
|
||||
<select id="mail_day" wire:model="formData.mail_day" class="mt-1 block w-full">
|
||||
@foreach(App\Helper::getDays() as $day)
|
||||
<option value="{{ $day }}">{{ $day }}</option>
|
||||
@endforeach
|
||||
</select>
|
||||
<x-input-error for="mail_day" class="mt-2"/>
|
||||
</div>
|
||||
<div class="col-span-6 sm:col-span-4">
|
||||
{{ __('Recipients') }}
|
||||
</div>
|
||||
@foreach($projectManager->formData['mail_recipients'] as $key => $email_recipient)
|
||||
<div class="col-span-6 sm:colspan-4 grid grid-cols-6 gap-1">
|
||||
<div class="col-span-2">
|
||||
<x-label for="mail_recipient_{{ $key }}_name" value="{{ __('Name') }}"/>
|
||||
<x-input id="mail_recipient_{{ $key }}_name" type="text" class="mt-1 block w-full"
|
||||
wire:model="formData.mail_recipients.{{ $key }}.name" autofocus/>
|
||||
<x-input-error for="mail_recipients.{{ $key }}.name" class="mt-2"/>
|
||||
</div>
|
||||
|
||||
<div class="col-span-3">
|
||||
<x-label for="bounding_box_{{ $key }}_top_left_latitude"
|
||||
value="{{ __('Email') }}"/>
|
||||
<x-input id="bounding_box_{{ $key }}_top_left_latitude" type="text"
|
||||
class="mt-1 block w-full"
|
||||
wire:model="formData.mail_recipients.{{ $key }}.email"
|
||||
autofocus/>
|
||||
<x-input-error for="mail_recipients.{{ $key }}.email" class="mt-2"/>
|
||||
</div>
|
||||
<div class="col-span-1 flex">
|
||||
@if( count($projectManager->formData['mail_recipients']) > 1)
|
||||
<button
|
||||
class="cursor-pointer ml-6 text-sm text-red-500 py-3 self-end"
|
||||
type="button"
|
||||
wire:click="deleteEmailRecipient({{ $key }})"
|
||||
wire:confirm="{{ __('Are you sure you want to delete this Recipient?') }}"
|
||||
>
|
||||
Delete
|
||||
</button>
|
||||
@endif
|
||||
</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="addEmailRecipient"
|
||||
>
|
||||
{{ __('Add recipient') }}
|
||||
</x-secondary-button>
|
||||
<x-secondary-button class="mr-3"
|
||||
type="button"
|
||||
x-on:click="$wire.showMailSettingsModal = false"
|
||||
>
|
||||
{{ __('Cancel') }}
|
||||
</x-secondary-button>
|
||||
<x-button>
|
||||
{{ __('Save') }}
|
||||
</x-button>
|
||||
|
||||
</x-slot>
|
||||
</x-form-modal>
|
||||
</x-modal>
|
||||
|
|
@ -0,0 +1,106 @@
|
|||
@props([
|
||||
'formData',
|
||||
/** @var \App\Livewire\Projects\ProjectManager */
|
||||
'projectManager'
|
||||
])
|
||||
|
||||
<x-modal wire:model.live="showProjectModal" {{ $attributes }}>
|
||||
<x-form-modal submit="saveProject">
|
||||
<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($projectManager->formData['boundingBoxes'] as $key => $boundingBox)
|
||||
{{-- <div wire:key="bounding_box_{{ $key }}">--}}
|
||||
<div class="col-span-6 sm:col-span-4">
|
||||
{{ __('Bounding box') }}
|
||||
@if( count($projectManager->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 grid grid-cols-6 gap-1">
|
||||
<div class="col-span-3">
|
||||
<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="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-3">
|
||||
<x-label for="bounding_box_{{ $key }}_top_left_longitude" value="{{ __('Longitude') }}"/>
|
||||
<x-input id="name" type="text" class="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-3">
|
||||
<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="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-3">
|
||||
<x-label for="boundingBox_{{ $key }}_bottom_right_longitude" value="{{ __('Longitude') }}"/>
|
||||
<x-input id="boundingBox_{{ $key }}_bottom_right_longitude" type="text"
|
||||
class="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-modal>
|
||||
</x-modal>
|
||||
23
laravel_app/resources/views/components/tab-section.blade.php
Normal file
23
laravel_app/resources/views/components/tab-section.blade.php
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
|
||||
<div {{ $attributes->merge(['class' => 'md:grid md:grid-cols-1 md:gap-6']) }}>
|
||||
<div class="mt-5 px-6">
|
||||
<h2>{{ $title }}</h2>
|
||||
|
||||
<span name="description">{{ $description }}</span>
|
||||
</div>
|
||||
|
||||
<div class="mt-5 md:mt-0 md:col-span-2">
|
||||
<div class="px-4 py-5 bg-white sm:p-6 shadow {{ isset($actions) ? 'sm:rounded-tl-md sm:rounded-tr-md' : 'sm:rounded-md' }}">
|
||||
<div class="grid grid-cols-1" >
|
||||
{{ $form }}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@if (isset($actions))
|
||||
<div class="flex items-center justify-end px-4 py-3 bg-gray-50 text-right sm:px-6 shadow sm:rounded-bl-md sm:rounded-br-md">
|
||||
{{ $actions }}
|
||||
</div>
|
||||
@endif
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -1,165 +1,7 @@
|
|||
<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>
|
||||
<x-project-manager-mail-settings-modal :projectManager="$this"/>
|
||||
<x-project-manager-properties-modal :projectManager="$this"/>
|
||||
<x-project-manager-grid :projectManager="$this"/>
|
||||
<x-project-manager-delete-confirmation-modal/>
|
||||
</div>
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,16 @@
|
|||
<x-tab-section>
|
||||
<x-slot name="title">Download details</x-slot>
|
||||
<x-slot name="description">Lorem ipsum dolor sit amet, consectetur adipisicing elit. Ipsa, reprehenderit.</x-slot>
|
||||
<x-slot name="form">
|
||||
<div class="max-w-7xl mx-auto py-10 sm:px-6 lg:px-8">
|
||||
<div class="mt-10 sm:mt-0">
|
||||
@livewire('download.download-grid')
|
||||
</div>
|
||||
<x-section-border />
|
||||
|
||||
<div class="mt-10 sm:mt-0">
|
||||
@livewire('download.download-form')
|
||||
</div>
|
||||
</div>
|
||||
</x-slot>
|
||||
</x-tab-section>
|
||||
|
|
@ -0,0 +1,40 @@
|
|||
<x-tab-section>
|
||||
<x-slot name="title">Mailing Details</x-slot>
|
||||
<x-slot name="description">...</x-slot>
|
||||
|
||||
<x-slot name="form">
|
||||
<div class="inline-block min-w-full py-2 align-middle sm:px-6 lg:px-8">
|
||||
<table class="min-w-full divide-y divide-gray-300">
|
||||
<thead>
|
||||
<tr>
|
||||
<th scope="col" class="py-3.5 pl-4 pr-3 text-left text-sm font-semibold text-gray-900 sm:pl-0">Id
|
||||
</th>
|
||||
<th scope="col" class="px-3 py-3.5 text-left text-sm font-semibold text-gray-900">Created</th>
|
||||
<th scope="col" class="px-3 py-3.5 text-left text-sm font-semibold text-gray-900">Subject</th>
|
||||
<th scope="col" class="px-3 py-3.5 text-left text-sm font-semibold text-gray-900">#</th>
|
||||
<th scope="col" class="px-3 py-3.5 text-left text-sm font-semibold text-gray-900">Attachment</th>
|
||||
<th scope="col" class="relative py-3.5 pl-3 pr-4 sm:pr-0">
|
||||
<span class="sr-only">Edit</span>
|
||||
</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody class="divide-y divide-gray-200">
|
||||
@foreach($project->mailings as $mail)
|
||||
<tr>
|
||||
<td class="whitespace-nowrap py-4 pl-4 pr-3 text-sm font-medium text-gray-900 sm:pl-0">{{ $mail->id }}</td>
|
||||
<td class="whitespace-nowrap px-3 py-4 text-sm text-gray-500">{{ $mail->created_at }}</td>
|
||||
<td class="whitespace-nowrap px-3 py-4 text-sm text-gray-500">{{ $mail->subject }}</td>
|
||||
<td class="whitespace-nowrap px-3 py-4 text-sm text-gray-500">{{ $mail->recipients()->count() }}</td>
|
||||
<td class="whitespace-nowrap px-3 py-4 text-sm text-gray-500">{{ $mail->attachments()->get('name')->implode(', ') }}</td>
|
||||
<td class="relative whitespace-nowrap py-4 pl-3 pr-4 text-right text-sm font-medium sm:pr-0">
|
||||
<button type="button" class="text-indigo-600 hover:text-indigo-900">Show</button>
|
||||
</td>
|
||||
</tr>
|
||||
@endforeach
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</tbody>
|
||||
</table>
|
||||
</x-slot>
|
||||
</x-tab-section>
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
<x-tab-section>
|
||||
<x-slot name="title">Report Details</x-slot>
|
||||
<x-slot name="description">..</x-slot>
|
||||
|
||||
<x-slot name="form">
|
||||
|
||||
|
||||
</x-slot>
|
||||
</x-tab-section>
|
||||
68
laravel_app/resources/views/projects/show.blade.php
Normal file
68
laravel_app/resources/views/projects/show.blade.php
Normal file
|
|
@ -0,0 +1,68 @@
|
|||
<x-app-layout>
|
||||
<x-slot name="header">
|
||||
<h2 class="font-semibold text-xl text-gray-800 leading-tight">
|
||||
{{ __('Project') }} {{ $project->name }}
|
||||
</h2>
|
||||
</x-slot>
|
||||
|
||||
<div>
|
||||
<div class="max-w-7xl mx-auto py-10 sm:px-6 lg:px-8" x-data="{openTab: 1}">
|
||||
|
||||
<div class="mt-10 sm:mt-0">
|
||||
<div class="flex w-full space-x-6 mb-5 border-b border-secondary max-h-[50px]" selid="tabs">
|
||||
<div :class="{'border-b-2 border-indigo-500 -mb-px text-indigo-500' : openTab === 1}" selid="tab-question">
|
||||
<button
|
||||
style="color:inherit"
|
||||
x-on:click="openTab = 1"
|
||||
>
|
||||
<span>{{ __('Mailing') }}</span>
|
||||
</button>
|
||||
</div>
|
||||
<div class="" :class="{'border-b-2 border-indigo-500 -mb-px text-indigo-500' : openTab === 2}"
|
||||
selid="tab-settings">
|
||||
<button
|
||||
style="color:inherit"
|
||||
x-on:click="openTab = 2;"
|
||||
>
|
||||
<span>{{ __('Downloads') }}</span>
|
||||
</button>
|
||||
</div>
|
||||
<div class="" :class="{'border-b-2 border-indigo-500 -mb-px text-indigo-500' : openTab === 3}"
|
||||
selid="tab-statistics">
|
||||
<button
|
||||
style="color:inherit"
|
||||
x-on:click="openTab = 3;"
|
||||
>
|
||||
<span>{{ __('Reports') }}</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="flex flex-col flex-1 pb-5 space-y-4 relative" x-show="openTab === 2"
|
||||
x-transition:enter="transition duration-200"
|
||||
x-transition:enter-start="opacity-0 delay-200"
|
||||
x-transition:enter-end="opacity-100"
|
||||
>
|
||||
@livewire('projects.download-manager', ['project' => $project]);
|
||||
</div>
|
||||
<div class="flex flex-col flex-1 pb-5 space-y-4 relative" x-show="openTab === 1"
|
||||
x-transition:enter="transition duration-200"
|
||||
x-transition:enter-start="opacity-0 delay-200"
|
||||
x-transition:enter-end="opacity-100"
|
||||
>
|
||||
@livewire('projects.mailing-manager', ['project' => $project]);
|
||||
|
||||
|
||||
</div>
|
||||
<div class="flex flex-col flex-1 pb-5 space-y-4 relative" x-show="openTab === 3"
|
||||
x-transition:enter="transition duration-200"
|
||||
x-transition:enter-start="opacity-0 delay-200"
|
||||
x-transition:enter-end="opacity-100"
|
||||
>
|
||||
@livewire('projects.report-manager', ['project' => $project]);
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</x-app-layout>
|
||||
|
|
@ -28,5 +28,6 @@
|
|||
|
||||
Route::get('/download', [\App\Http\Controllers\DownloadController::class, 'show'])->name('download');
|
||||
Route::get('/report', [\App\Http\Controllers\ReportController::class, 'index'])->name('report');
|
||||
Route::get('/project', [\App\Http\Controllers\ProjectController::class, 'index'])->name('project');
|
||||
Route::get('/projects/{project}', [\App\Http\Controllers\ProjectController::class, 'show'])->name('project.show');
|
||||
Route::get('/projects', [\App\Http\Controllers\ProjectController::class, 'index'])->name('project');
|
||||
});
|
||||
|
|
|
|||
Loading…
Reference in a new issue