diff --git a/build_mosaic.sh b/build_mosaic.sh
index 4ec725d..efe24e8 100755
--- a/build_mosaic.sh
+++ b/build_mosaic.sh
@@ -19,12 +19,12 @@ while [ "$#" -gt 0 ]; do
done
# Controleer of de vereiste argumenten zijn ingesteld
-if [ -z "$filename" ] || [ -z "$weeks_ago" ] || [ -z $report_date ]; then
- echo "Missende argumenten. Gebruik: build_reports.sh --filename=hello.txt --weeks_ago=3 --report_date=2020-01-01"
+if [ -z "$weeks_ago" ]; then
+ echo "Missende argumenten. Gebruik: build_mosiac.sh --weeks_ago=3"
exit 1
fi
echo "Weeks ago: $weeks_ago"
cd /Users/mfolkerts/smartCane/r_app
-Rscript 2_CI_data_prep.R $weeks_ago
\ No newline at end of file
+Rscript 2_CI_data_prep.R $weeks_ago
diff --git a/laravel_app/app/Http/Controllers/DownloadController.php b/laravel_app/app/Http/Controllers/DownloadController.php
deleted file mode 100644
index 774bc5e..0000000
--- a/laravel_app/app/Http/Controllers/DownloadController.php
+++ /dev/null
@@ -1,13 +0,0 @@
- $project]);
- }
- //
-}
diff --git a/laravel_app/app/Jobs/ProjectDownloadTiffJob.php b/laravel_app/app/Jobs/ProjectDownloadTiffJob.php
new file mode 100644
index 0000000..9a7d9fb
--- /dev/null
+++ b/laravel_app/app/Jobs/ProjectDownloadTiffJob.php
@@ -0,0 +1,65 @@
+date = $date;
+ $this->download = $download;
+ }
+
+ /**
+ * Execute the job.
+ */
+ public function handle(): void
+ {
+ $projectFolder = base_path('../');
+
+ $command = [
+ sprintf('%srunpython.sh', $projectFolder),
+ sprintf('--date=%s', $this->date->format('Y-m-d')),
+ sprintf('--days=%d', $this->days),
+ ];
+
+ // Convert commands array to a single string
+
+ $process = new Process($command);
+ $process->setTimeout(3600); // stel een geschikte timeout in
+ $process->start();
+
+ try {
+ $process->wait(function ($type, $buffer) use (&$myOutput){
+ logger($buffer);
+ });
+ } catch (ProcessFailedException $exception) {
+ logger('error', $exception->getMessage());
+ }
+
+ $this->download->update([
+ 'status' => 'completed',
+ ]);
+ }
+}
diff --git a/laravel_app/app/Jobs/ProjectMosiacGeneratorJob.php b/laravel_app/app/Jobs/ProjectMosiacGeneratorJob.php
index f13ce40..49474e8 100644
--- a/laravel_app/app/Jobs/ProjectMosiacGeneratorJob.php
+++ b/laravel_app/app/Jobs/ProjectMosiacGeneratorJob.php
@@ -3,6 +3,8 @@
namespace App\Jobs;
use App\Models\Project;
+use App\Models\ProjectDownload;
+use App\Models\ProjectMosaic;
use App\Models\ProjectReport;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldBeUnique;
@@ -16,18 +18,16 @@ class ProjectMosiacGeneratorJob implements ShouldQueue
{
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
+ public ProjectMosaic $mosaic;
+
+ protected $timeout = 120;
- public $year;
- public $week;
- public Project $project;
/**
* Create a new job instance.
*/
- public function __construct(Project $project, $year, $week)
+ public function __construct(ProjectMosaic $mosaic)
{
- $this->year = $year;
- $this->week = $week;
- //
+ $this->mosaic = $mosaic;
}
/**
@@ -35,7 +35,7 @@ public function __construct(Project $project, $year, $week)
*/
public function handle(): void
{
- $weeksAgo = ProjectReport::weeksAgoForYearAndWeek($this->year, $this->week);
+ $weeksAgo = ProjectReport::weeksAgoForYearAndWeek($this->mosaic->year, $this->mosaic->week);
$projectFolder = base_path('../');
@@ -63,7 +63,9 @@ public function handle(): void
} catch (ProcessFailedException $exception) {
echo $exception->getMessage();
-
}
+ $this->mosaic->update([
+ 'status' => 'complete',
+ ]);
}
}
diff --git a/laravel_app/app/Livewire/Download/DownloadForm.php b/laravel_app/app/Livewire/Download/DownloadForm.php
deleted file mode 100644
index e38ac62..0000000
--- a/laravel_app/app/Livewire/Download/DownloadForm.php
+++ /dev/null
@@ -1,61 +0,0 @@
-buttonText = __('Start');
- }
-
- public function start()
- {
- $this->buttonText = __('Downloading...');
-
- // Commands to run
- $projectFolder = base_path('../');
-
- $command = [
- sprintf('%srunpython.sh', $projectFolder),
- sprintf('--days=%d', $this->days),
- ];
-
- // Convert commands array to a single string
-
- $process = new Process($command);
- $process->setTimeout(3600); // stel een geschikte timeout in
- $process->start();
-
- try {
- $myOutput = [];
- $process->wait(function ($type, $buffer) use (&$myOutput){
- $this->stream(to: 'output', content: $buffer);
- $myOutput[] = $buffer;
- });
- $this->output = collect($myOutput)->join('
- {{ __('Vul een aantal dagen in en druk op start om de betreffende sateliet data te downloaden') }}
-
- {{ __('') }}
-
');
-
- } catch (ProcessFailedException $exception) {
-
- logger('error', $exception->getMessage());
- echo $exception->getMessage();
- }
- $this->buttonText = __('Done');
- }
-
-
-
-
- public function render()
- {
- return view('livewire.download.download-form');
- }
-}
diff --git a/laravel_app/app/Livewire/Download/DownloadGrid.php b/laravel_app/app/Livewire/Download/DownloadGrid.php
deleted file mode 100644
index c625446..0000000
--- a/laravel_app/app/Livewire/Download/DownloadGrid.php
+++ /dev/null
@@ -1,22 +0,0 @@
-files = $project->getMosaicList();
-// dd($this->directories);
- }
-
- public function render()
- {
- return view('livewire.download.download-grid')->with(['files' => $this->files]);
- }
-}
diff --git a/laravel_app/app/Livewire/Projects/DownloadManager.php b/laravel_app/app/Livewire/Projects/DownloadManager.php
index c47bb8f..bc067e6 100644
--- a/laravel_app/app/Livewire/Projects/DownloadManager.php
+++ b/laravel_app/app/Livewire/Projects/DownloadManager.php
@@ -3,15 +3,61 @@
namespace App\Livewire\Projects;
use App\Models\Project;
+use App\Rules\DownloadDateRangeRule;
+use Carbon\Carbon;
+use Carbon\CarbonPeriod;
use Livewire\Component;
+use Symfony\Component\Process\Process;
class DownloadManager extends Component
{
public $project;
- public function mount(Project $project) {
+ public $formData;
+
+
+ public $showDownloadModal = false;
+
+ public function mount(Project $project)
+ {
$this->path = $project->download_path;
+ $this->formData = [
+ 'dateRange' => sprintf('%s to %s',
+ now()->subDays(6)->format('Y/m/d'),
+ now()->format('Y/m/d')
+ )
+ ];
}
+ public function openDownloadModal()
+ {
+ $this->showDownloadModal = true;
+ }
+
+ public function saveDownloads()
+ {
+ $this->validate([
+ 'formData.dateRange' => [
+ 'required',
+ new DownloadDateRangeRule(),
+ ]
+ ]);
+
+ $dateRange = explode(' to ', $this->formData['dateRange']);
+
+ $period = CarbonPeriod::create(
+ Carbon::parse($dateRange[0]),
+ Carbon::parse($dateRange[1])
+ );
+
+ collect($period)->each(function ($date) {
+ $this->project->startDownload($date);
+ });
+
+
+ $this->showDownloadModal = false;
+ }
+
+
public function render()
{
return view('livewire.projects.download-manager', [
diff --git a/laravel_app/app/Livewire/Projects/MosaicManager.php b/laravel_app/app/Livewire/Projects/MosaicManager.php
index e784de8..cda3692 100644
--- a/laravel_app/app/Livewire/Projects/MosaicManager.php
+++ b/laravel_app/app/Livewire/Projects/MosaicManager.php
@@ -33,7 +33,16 @@ public function saveMosiac(){
'formData.week' => 'required',
]);
- ProjectMosiacGeneratorJob::dispatch($this->project, $this->formData['year'], $this->formData['week']);
+ $mosaic = $this->project->mosaics()->updateOrCreate([
+ 'name' => sprintf('Week %s, %s', $this->formData['week'], $this->formData['year']),
+ 'year' => $this->formData['year'],
+ 'week' => $this->formData['week'],
+ ],[
+ 'status' => 'pending',
+ 'path' => $this->project->getMosaicPath(),
+ ]);
+
+ ProjectMosiacGeneratorJob::dispatch($mosaic);
$this->showCreateModal = false;
}
diff --git a/laravel_app/app/Models/Project.php b/laravel_app/app/Models/Project.php
index 30478d2..e968ed6 100644
--- a/laravel_app/app/Models/Project.php
+++ b/laravel_app/app/Models/Project.php
@@ -2,9 +2,10 @@
namespace App\Models;
+use App\Jobs\ProjectDownloadTiffJob;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
-use Illuminate\Support\Carbon;
+use Carbon\Carbon;
use Illuminate\Support\Collection;
use Illuminate\Support\Facades\Storage;
use Illuminate\Support\Str;
@@ -69,7 +70,7 @@ private function upsertMailRecipients($formData)
);
}
- private function getMosaicPath()
+ public function getMosaicPath()
{
return sprintf('%s/%s', $this->download_path, 'weekly_mosaic');
}
@@ -129,12 +130,18 @@ public function mailings()
return $this->hasMany(ProjectMailing::class);
}
- public function downloads()
+ public function downloads(): \Illuminate\Database\Eloquent\Relations\HasMany
{
return $this->hasMany(ProjectDownload::class);
}
- public function allMosaicsPresent(Carbon $endDate)
+ public function mosaics() : \Illuminate\Database\Eloquent\Relations\HasMany
+ {
+ return $this->hasMany(ProjectMosaic::class);
+ }
+
+
+ public function allMosaicsPresent(Carbon $endDate): bool
{
// end date is in the future
if ($endDate->isFuture()) {
@@ -220,6 +227,38 @@ public function allMergedTiffsPresent(Collection $haystack, Collection $needles)
public function getMergedTiffList()
{
- return collect([]);;
+ return collect(Storage::files($this->download_path.'/merged_final_tif'))
+ ->filter(fn($file) => Str::endsWith($file, '.tif'))
+ ->sortByDesc(function ($file) {
+ $parts = explode('_', str_replace('.tif', '', $file));
+ $date = $parts[1];
+ return $date;
+ })
+ ->values();
+ }
+
+ public function hasPendingDownload() : bool
+ {
+ return $this->downloads()->where('status', 'pending')->count() > 0;
+ }
+
+ public function hasPendingMosaic() : bool
+ {
+ return $this->mosaics()->where('status', 'pending')->count() > 0;
+ }
+
+ public function startDownload(Carbon $date)
+ {
+ $downloadRequest = $this->downloads()->updateOrCreate(
+ [
+ 'project_id' => $this->id, // of een andere manier om project_id te bepalen
+ 'name' => sprintf('%s.tif', $date->format('Y-m-d')),
+ ],
+ [
+ 'path' => sprintf('%s/%s/%s.tif', $this->download_path, 'merged_final_tif', $date->format('Y-m-d')),
+ 'status' => 'pending',
+ ]
+ );
+ ProjectDownloadTiffJob::dispatch($downloadRequest, $date);
}
}
diff --git a/laravel_app/app/Models/ProjectDownload.php b/laravel_app/app/Models/ProjectDownload.php
index e7c39f4..acee947 100644
--- a/laravel_app/app/Models/ProjectDownload.php
+++ b/laravel_app/app/Models/ProjectDownload.php
@@ -8,4 +8,10 @@
class ProjectDownload extends Model
{
use HasFactory;
+
+ protected $fillable = [
+ 'name',
+ 'path',
+ 'status',
+ ];
}
diff --git a/laravel_app/app/Models/ProjectMosaic.php b/laravel_app/app/Models/ProjectMosaic.php
new file mode 100644
index 0000000..d2cc1b8
--- /dev/null
+++ b/laravel_app/app/Models/ProjectMosaic.php
@@ -0,0 +1,25 @@
+belongsTo(Project::class);
+ }
+
+}
diff --git a/laravel_app/app/Rules/AllMergedTiffsPresentRule.php b/laravel_app/app/Rules/AllMergedTiffsPresentRule.php
index c81c437..5ba0554 100644
--- a/laravel_app/app/Rules/AllMergedTiffsPresentRule.php
+++ b/laravel_app/app/Rules/AllMergedTiffsPresentRule.php
@@ -2,35 +2,30 @@
namespace App\Rules;
-use Illuminate\Contracts\Validation\Rule;
+use Closure;
+use Illuminate\Contracts\Validation\ValidationRule;
use App\Models\Project;
use App\Models\ProjectReport;
-class AllMergedTiffsPresentRule implements Rule
+class AllMergedTiffsPresentRule implements ValidationRule
{
- protected $project;
- protected $errorMessage = '';
+ protected Project $project;
public function __construct(Project $project)
{
$this->project = $project;
}
- public function passes($attribute, $value)
+ public function validate(string $attribute, mixed $value, Closure $fail): void
{
try {
- return $this->project->allMergedTiffsPresent(
+ $this->project->allMergedTiffsPresent(
$this->project->getMergedTiffList(),
Project::getAllDatesOfWeeksInYear($value['year'], $value['week'])
);
} catch (\Exception $e) {
- $this->errorMessage = $e->getMessage();
- return false;
+ $fail($e->getMessage());
}
}
- public function message()
- {
- return $this->errorMessage;
- }
}
diff --git a/laravel_app/app/Rules/DownloadDateRangeRule.php b/laravel_app/app/Rules/DownloadDateRangeRule.php
new file mode 100644
index 0000000..0c3c554
--- /dev/null
+++ b/laravel_app/app/Rules/DownloadDateRangeRule.php
@@ -0,0 +1,45 @@
+validateDateString($value)) {
+ $fail('Date range must be in the format YYYY/MM/DD to YYYY/MM/DD.');
+ return;
+ }
+
+ if (!$this->startDate->isPast() || !$this->endDate->isPast()) {
+ $fail('Date range cannot be in the future.');
+ return;
+ }
+
+ if ($this->startDate->greaterThan($this->endDate)) {
+ $fail('Start date must be before end date.');
+ }
+ }
+
+ function validateDateString($dateString): bool
+ {
+ $regex = '/^(\d{4}\/\d{2}\/\d{2}) to (\d{4}\/\d{2}\/\d{2})$/';
+ if (preg_match($regex, $dateString, $matches)) {
+ $this->startDate = Carbon::parse($matches[1]);
+ $this->endDate = Carbon::parse($matches[2]);
+ return true;
+ }
+ return false;
+ }
+
+
+}
diff --git a/laravel_app/database/migrations/2023_11_21_142339_create_project_downloads_table.php b/laravel_app/database/migrations/2023_11_21_142339_create_project_downloads_table.php
index 0735dd9..315260f 100644
--- a/laravel_app/database/migrations/2023_11_21_142339_create_project_downloads_table.php
+++ b/laravel_app/database/migrations/2023_11_21_142339_create_project_downloads_table.php
@@ -16,6 +16,7 @@ public function up(): void
$table->foreignId('project_id');
$table->string('name');
$table->string('path');
+ $table->string('status')->default('pending');
$table->timestamps();
});
}
diff --git a/laravel_app/database/migrations/2024_01_03_190141_project_mosaics_table.php b/laravel_app/database/migrations/2024_01_03_190141_project_mosaics_table.php
new file mode 100644
index 0000000..8852bc6
--- /dev/null
+++ b/laravel_app/database/migrations/2024_01_03_190141_project_mosaics_table.php
@@ -0,0 +1,33 @@
+id();
+ $table->foreignId('project_id');
+ $table->string('week');
+ $table->string('name');
+ $table->string('year');
+ $table->string('path');
+ $table->string('status')->default('pending');
+ $table->timestamps();
+ }); //
+ }
+
+ /**
+ * Reverse the migrations.
+ */
+ public function down(): void
+ {
+ Schema::dropIfExists('project_mosaics');
+ }
+};
diff --git a/laravel_app/database/seeders/DatabaseSeeder.php b/laravel_app/database/seeders/DatabaseSeeder.php
index edb27e0..96b88b0 100644
--- a/laravel_app/database/seeders/DatabaseSeeder.php
+++ b/laravel_app/database/seeders/DatabaseSeeder.php
@@ -61,6 +61,16 @@ private function createChembaProject()
],
]);
+ foreach($chembaProject->getMergedTiffList() as $mergedTiff) {
+ $chembaProject->downloads()->create([
+ 'name' => basename($mergedTiff),
+ 'path' => $mergedTiff,
+ 'status' => 'completed',
+ 'created_at' => '2021-01-01 00:00:00',
+ 'updated_at' => '2021-01-01 00:00:00'
+ ]);
+ }
+
$chembaProject->emailRecipients()->createMany([
[
'name' => 'Martin Folkerts',
diff --git a/laravel_app/package-lock.json b/laravel_app/package-lock.json
index b9a5dbb..e0902fb 100644
--- a/laravel_app/package-lock.json
+++ b/laravel_app/package-lock.json
@@ -12,6 +12,7 @@
"@ryangjchandler/alpine-clipboard": "^2.3.0",
"@tailwindcss/aspect-ratio": "^0.4.2",
"alpinejs": "^3.13.3",
+ "flatpickr": "^4.6.13",
"tailwindcss": "^3.3.3"
},
"devDependencies": {
@@ -919,6 +920,11 @@
"node": ">=8"
}
},
+ "node_modules/flatpickr": {
+ "version": "4.6.13",
+ "resolved": "https://registry.npmjs.org/flatpickr/-/flatpickr-4.6.13.tgz",
+ "integrity": "sha512-97PMG/aywoYpB4IvbvUJi0RQi8vearvU0oov1WW3k0WZPBMrTQVqekSX5CjSG/M4Q3i6A/0FKXC7RyAoAUUSPw=="
+ },
"node_modules/focus-trap": {
"version": "6.9.4",
"resolved": "https://registry.npmjs.org/focus-trap/-/focus-trap-6.9.4.tgz",
diff --git a/laravel_app/package.json b/laravel_app/package.json
index 4c11eae..127599c 100644
--- a/laravel_app/package.json
+++ b/laravel_app/package.json
@@ -23,6 +23,7 @@
"@ryangjchandler/alpine-clipboard": "^2.3.0",
"@tailwindcss/aspect-ratio": "^0.4.2",
"alpinejs": "^3.13.3",
+ "flatpickr": "^4.6.13",
"tailwindcss": "^3.3.3"
}
}
diff --git a/laravel_app/resources/css/app.css b/laravel_app/resources/css/app.css
index 34ca985..9c1d151 100644
--- a/laravel_app/resources/css/app.css
+++ b/laravel_app/resources/css/app.css
@@ -1,9 +1,9 @@
+@import 'flatpickr/dist/flatpickr.css';
@import url('https://rsms.me/inter/inter.css');
@tailwind base;
@tailwind components;
@tailwind utilities;
-
[x-cloak] {
display: none;
}
diff --git a/laravel_app/resources/js/app.js b/laravel_app/resources/js/app.js
index 861ee70..a111dc0 100644
--- a/laravel_app/resources/js/app.js
+++ b/laravel_app/resources/js/app.js
@@ -1,2 +1,4 @@
import './bootstrap';
import('./alpine');
+import flatpckr from 'flatpickr';
+window.flatpckr = flatpckr;
diff --git a/laravel_app/resources/views/components/download-create-modal.blade.php b/laravel_app/resources/views/components/download-create-modal.blade.php
new file mode 100644
index 0000000..271b154
--- /dev/null
+++ b/laravel_app/resources/views/components/download-create-modal.blade.php
@@ -0,0 +1,68 @@
+@props([
+ 'formData',
+ /** @var \App\Livewire\Projects\MosaicManager */
+ 'manager'
+])
+
+
- {{ __('Download') }}
-
-
- {{ __('Download satellite data') }}
-
-
-
+ @if ($project->hasPendingDownload()) + Pending downloads for this project: {{ $project->downloads()->where('status', 'pending')->count() }} + @endif +
| + Name + | ++ Status + | ++ Edit + | +
|---|---|---|
| {{ $download->name }} | ++ {{ $download->path }} + | +
+ |
+