This commit is contained in:
Martin Folkerts 2024-01-09 10:49:25 +01:00
parent 84d8bc1d74
commit da9d94880f
19 changed files with 233 additions and 27 deletions

15
.idea/codeception.xml Normal file
View file

@ -0,0 +1,15 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="Codeception">
<option name="configurations">
<list>
<Configuration>
<option name="path" value="$PROJECT_DIR$/tests" />
</Configuration>
<Configuration>
<option name="path" value="$PROJECT_DIR$/laravel_app/tests" />
</Configuration>
</list>
</option>
</component>
</project>

View file

@ -12,7 +12,6 @@
</component>
<component name="PhpIncludePathManager">
<include_path>
<path value="$PROJECT_DIR$/laravel_app/vendor/jaybizzle/crawler-detect" />
<path value="$PROJECT_DIR$/laravel_app/vendor/psr/event-dispatcher" />
<path value="$PROJECT_DIR$/laravel_app/vendor/psr/http-message" />
<path value="$PROJECT_DIR$/laravel_app/vendor/psr/log" />
@ -33,7 +32,6 @@
<path value="$PROJECT_DIR$/laravel_app/vendor/ramsey/collection" />
<path value="$PROJECT_DIR$/laravel_app/vendor/league/flysystem" />
<path value="$PROJECT_DIR$/laravel_app/vendor/league/commonmark" />
<path value="$PROJECT_DIR$/laravel_app/vendor/jenssegers/agent" />
<path value="$PROJECT_DIR$/laravel_app/vendor/ramsey/uuid" />
<path value="$PROJECT_DIR$/laravel_app/vendor/dflydev/dot-access-data" />
<path value="$PROJECT_DIR$/laravel_app/vendor/pragmarx/google2fa" />
@ -135,6 +133,7 @@
<path value="$PROJECT_DIR$/laravel_app/vendor/dasprid/enum" />
<path value="$PROJECT_DIR$/laravel_app/vendor/_laravel_idea" />
<path value="$PROJECT_DIR$/laravel_app/vendor/laravel/telescope" />
<path value="$PROJECT_DIR$/laravel_app/vendor/carbonphp/carbon-doctrine-types" />
</include_path>
</component>
<component name="PhpProjectSharedConfiguration" php_language_level="8.1" />

13
.idea/phpspec.xml Normal file
View file

@ -0,0 +1,13 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="PHPSpec">
<suites>
<PhpSpecSuiteConfiguration>
<option name="myPath" value="$PROJECT_DIR$" />
</PhpSpecSuiteConfiguration>
<PhpSpecSuiteConfiguration>
<option name="myPath" value="$PROJECT_DIR$/laravel_app" />
</PhpSpecSuiteConfiguration>
</suites>
</component>
</project>

View file

@ -6,6 +6,9 @@
<sourceFolder url="file://$MODULE_DIR$/laravel_app/database/factories" isTestSource="false" packagePrefix="Database\Factories\" />
<sourceFolder url="file://$MODULE_DIR$/laravel_app/database/seeders" isTestSource="false" packagePrefix="Database\Seeders\" />
<sourceFolder url="file://$MODULE_DIR$/laravel_app/tests" isTestSource="true" packagePrefix="Tests\" />
<sourceFolder url="file://$MODULE_DIR$/laravel_app/spec" isTestSource="true" />
<sourceFolder url="file://$MODULE_DIR$/spec" isTestSource="true" />
<sourceFolder url="file://$MODULE_DIR$/tests" isTestSource="true" />
<excludeFolder url="file://$MODULE_DIR$/laravel_app/vendor/bacon/bacon-qr-code" />
<excludeFolder url="file://$MODULE_DIR$/laravel_app/vendor/brick/math" />
<excludeFolder url="file://$MODULE_DIR$/laravel_app/vendor/composer" />
@ -24,8 +27,6 @@
<excludeFolder url="file://$MODULE_DIR$/laravel_app/vendor/guzzlehttp/psr7" />
<excludeFolder url="file://$MODULE_DIR$/laravel_app/vendor/guzzlehttp/uri-template" />
<excludeFolder url="file://$MODULE_DIR$/laravel_app/vendor/hamcrest/hamcrest-php" />
<excludeFolder url="file://$MODULE_DIR$/laravel_app/vendor/jaybizzle/crawler-detect" />
<excludeFolder url="file://$MODULE_DIR$/laravel_app/vendor/jenssegers/agent" />
<excludeFolder url="file://$MODULE_DIR$/laravel_app/vendor/laravel/fortify" />
<excludeFolder url="file://$MODULE_DIR$/laravel_app/vendor/laravel/framework" />
<excludeFolder url="file://$MODULE_DIR$/laravel_app/vendor/laravel/jetstream" />
@ -132,6 +133,7 @@
<excludeFolder url="file://$MODULE_DIR$/venv" />
<excludeFolder url="file://$MODULE_DIR$/laravel_app/vendor/_laravel_idea" />
<excludeFolder url="file://$MODULE_DIR$/laravel_app/vendor/laravel/telescope" />
<excludeFolder url="file://$MODULE_DIR$/laravel_app/vendor/carbonphp/carbon-doctrine-types" />
</content>
<orderEntry type="jdk" jdkName="Python 3.9 (smartCane)" jdkType="Python SDK" />
<orderEntry type="sourceFolder" forTests="false" />

View file

@ -47,5 +47,5 @@ echo 'zx28tb' | /usr/bin/sudo -S launchctl load -w /System/Library/LaunchAgents/
cd /Users/mfolkerts/smartCane/r_app
#Rscript -e "rmarkdown::render('/Users/mfolkerts/smartCane/r_app/CI_Report_dashboard_planet.Rmd', 'all')"
#Rscript 1_harvest_data_EcoFarm_v2.R
Rscript 2_CI_data_prep.R $weeks_ago
#Rscript 2_CI_data_prep.R $weeks_ago
Rscript -e "rmarkdown::render('CI_report_dashboard_planet.Rmd', output_file='$filename', params=list(ref='$ref', report_date='$report_date'))"

View file

@ -25,7 +25,7 @@ class ProjectDownloadTiffJob implements ShouldQueue
/**
* Create a new job instance.
*/
public function __construct(ProjectDownload $download, Carbon $date, )
public function __construct(ProjectDownload $download, Carbon $date,)
{
$this->date = $date;
$this->download = $download;
@ -36,7 +36,7 @@ public function __construct(ProjectDownload $download, Carbon $date, )
*/
public function handle(): void
{
$projectFolder = base_path('../');
$projectFolder = base_path('../');
$command = [
sprintf('%srunpython.sh', $projectFolder),
@ -51,7 +51,7 @@ public function handle(): void
$process->start();
try {
$process->wait(function ($type, $buffer) use (&$myOutput){
$process->wait(function ($type, $buffer) use (&$myOutput) {
logger($buffer);
});
} catch (ProcessFailedException $exception) {
@ -62,4 +62,21 @@ public function handle(): void
'status' => 'completed',
]);
}
public static function handleForDate(Project $project, Carbon $date)
{
if ($project->downloads()->where(['status' => 'completed', 'date' => $date])->count() > 0) {
return;
}
$filename = sprintf('%s.tif', $date->format('Y-m-d'));
$path = sprintf('%s/%s/%s', $project->download_path, 'merged_final_tif', $filename);
return new self(
$project->downloads()->create([
'name' => $filename,
'path' => $path,
'status' => 'completed',
]),
$date
);
}
}

View file

@ -68,4 +68,16 @@ public function handle(): void
'status' => 'complete',
]);
}
public static function handleFor(Project $project, $year, $startWeekNumber) {
if ($project->mosaics()->where(['status' => 'complete', 'year' => $year, 'week' => $startWeekNumber])->count() > 0) {
return;
}
$mosaic = $project->mosaics()->create([
'year' => $year,
'week' => $startWeekNumber,
'status' => 'pending',
]);
return new self($mosaic);
}
}

View file

@ -63,7 +63,7 @@ public function saveDownloads()
public function render()
{
$downloads = $this->project->downloads()->orderBy('name', 'desc')->paginate();
$downloads = $this->project->downloads()->orderBy('name', 'desc')->paginate(10, pageName: 'downloadPage');
return view('livewire.projects.download-manager',
compact('downloads')

View file

@ -5,9 +5,12 @@
use App\Models\Project;
use App\Models\ProjectMailing;
use Livewire\Component;
use Livewire\WithPagination;
class MailingManager extends Component
{
use WithPagination;
public $project;
public $mailingDetailsModal = false;
@ -22,12 +25,7 @@ public function mount(Project $project)
$this->resetFormData();
}
public function render()
{
return view('livewire.projects.mailing-manager', [
'mailings' => $this->project->mailings()->orderBy('created_at', 'desc')->get(),
]);
}
public function showMailingDetailsModal(ProjectMailing $mailing)
{
@ -54,4 +52,10 @@ private function resetFormData()
'recipients' => [],
];
}
public function render()
{
return view('livewire.projects.mailing-manager', [
'mailings' => $this->project->mailings()->orderBy('created_at', 'desc')->paginate(10, pageName: 'mailingPage'),
]);
}
}

View file

@ -2,6 +2,9 @@
namespace App\Models;
use App\Jobs\ProjectDownloadTiffJob;
use App\Jobs\ProjectMosiacGeneratorJob;
use Carbon\CarbonPeriod;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Carbon;
@ -78,4 +81,39 @@ public function deleteMe()
}
$this->delete();
}
public static function schedule($year, $week)
{
Bus::chain([
Bus::batch(self::getFileDownloadsFor($year, $week)),
Bus::batch(self::getMosiacsFor($year, $week)),
Bus::batch(self::getReport($year, $week)),
]);
}
public static function getFileDownloadsFor($project, $year, $startWeekNumber)
{
$endOfRange = Carbon::now()->setISODate($year, $startWeekNumber)->endOfWeek();
$startOfRange = (clone $endOfRange)->subWeeks(2)->startOfWeek();
$dateRange = CarbonPeriod::create($startOfRange, $endOfRange);
return collect($dateRange)
->map(fn ($date) => ProjectDownloadTiffJob::handleForDate($project, $date))
->filter();
}
public static function getMosaicsFor($project, $year, $startWeekNumber)
{
$jobs = [];
foreach (range(0,2) as $weekDiff) {
$job = ProjectMosiacGeneratorJob::handleFor($project, $year, $startWeekNumber - $weekDiff);
if ($job) {
$jobs[] = $job;
}
}
return $jobs;
}
}

View file

@ -0,0 +1,6 @@
<svg {{ $attributes }} width="4" height="14" xmlns="http://www.w3.org/2000/svg">
<g class="fill-current" fill-rule="evenodd">
<path d="M1.615 0h.77A1.5 1.5 0 013.88 1.61l-.45 6.06a1.436 1.436 0 01-2.863 0L.12 1.61A1.5 1.5 0 011.615 0z"/>
<circle cx="2" cy="12" r="2"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 306 B

View file

@ -0,0 +1,3 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="currentColor" class="w-5 h-5">
<path fill-rule="evenodd" d="M9 3.5a5.5 5.5 0 100 11 5.5 5.5 0 000-11zM2 9a7 7 0 1112.452 4.391l3.328 3.329a.75.75 0 11-1.06 1.06l-3.329-3.328A7 7 0 012 9z" clip-rule="evenodd" />
</svg>

After

Width:  |  Height:  |  Size: 288 B

View file

@ -0,0 +1,58 @@
@props(['notificationTimeout' => 5000])
<div
x-data="{
messages: [],
remove(message) {
this.messages.splice(this.messages.indexOf(message), 1)
},
}"
@notify.window="let message = $event.detail; messages.push(message); setTimeout(() => { remove(message) }, {{ $notificationTimeout }})"
class="fixed inset-0 flex flex-col items-end justify-center px-4 py-6 pointer-events-none sm:p-6 sm:justify-start space-y-4"
style="z-index:1000"
>
<template x-for="message in messages" :key="messages.indexOf(message)">
<div
x-transition:enter="transform ease-out duration-300 transition"
x-transition:enter-start="translate-y-2 opacity-0 sm:translate-y-0 sm:translate-x-2"
x-transition:enter-end="translate-y-0 opacity-100 sm:translate-x-0"
x-transition:leave="transition ease-in duration-100"
x-transition:leave-start="opacity-100"
x-transition:leave-end="opacity-0"
class="max-w-sm w-full bg-white shadow-lg rounded-lg pointer-events-auto"
>
<div class="rounded-lg shadow-xs overflow-hidden border border-light-grey">
<div class="p-4">
<div class="flex items-center">
<div class="flex-shrink-0">
<template x-if="message.type != 'error'">
<svg class="h-6 w-6 text-green-400" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
d="M9 12l2 2 4-4m6 2a9 9 0 11-18 0 9 9 0 0118 0z"></path>
</svg>
</template>
<template x-if="message.type == 'error'">
<div class="fraud-detection rounded-full bg-all-red text-white flex justify-center items-center"
style="width:30px;height:30px">
<x-icon.exclamation style="transform: scale(1.5)"/>
</div>
</template>
</div>
<div class="ml-3 w-0 flex-1 pt-0.5">
<p x-text="message.message" class="text-sm leading-5 font-medium text-gray-900"></p>
</div>
<div class="ml-4 flex-shrink-0 flex">
<button @click="remove(message)"
class="inline-flex text-gray-400 focus:outline-none focus:text-gray-500 transition ease-in-out duration-150">
<svg class="h-5 w-5" viewBox="0 0 20 20" fill="currentColor">
<path fill-rule="evenodd"
d="M4.293 4.293a1 1 0 011.414 0L10 8.586l4.293-4.293a1 1 0 111.414 1.414L11.414 10l4.293 4.293a1 1 0 01-1.414 1.414L10 11.414l-4.293 4.293a1 1 0 01-1.414-1.414L8.586 10 4.293 5.707a1 1 0 010-1.414z"
clip-rule="evenodd"></path>
</svg>
</button>
</div>
</div>
</div>
</div>
</div>
</template>
</div>

View file

@ -0,0 +1,7 @@
<div class="relative text-sm text-gray-800 col-span-3">
<div class="absolute pl-2 left-0 top-0 bottom-0 flex items-center pointer-events-none text-gray-500">
<x-icon.magnifying-glass />
</div>
<input wire:model.live="search" type="text" placeholder="@lang('Search')" class="block w-full rounded-lg border-0 py-1.5 pl-10 text-gray-900 ring-1 ring-inset ring-gray-200 placeholder:text-gray-400 focus:ring-2 focus:ring-inset focus:ring-indigo-600 sm:text-sm sm:leading-6">
</div>

View file

@ -36,6 +36,7 @@
{{ $slot }}
</main>
</div>
<x-notification />
@stack('modals')

View file

@ -4,8 +4,8 @@
@endif
>
<div class="px-4 sm:px-6 lg:px-8">
<div class="sm:flex sm:items-center">
<div class="sm:flex-auto">
<div class="sm:flex sm:flex-col sm:items-center">
<div class="w-full">
<h1 class="text-base font-semibold leading-6 text-gray-900">Downloads</h1>
<p class="mt-2 text-sm text-gray-700">
@if ($project->hasPendingDownload())
@ -13,9 +13,10 @@
@endif
</p>
</div>
<div class="mt-4 sm:ml-16 sm:mt-0 sm:flex-none">
<div class="mt-4 sm:mt-0 sm:flex sm:justify-between w-full">
<x-search></x-search>
<x-button wire:click="openDownloadModal"
class="block rounded-md bg-indigo-600 px-3 py-2 text-center text-sm font-semibold text-white shadow-sm hover:bg-indigo-500 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-indigo-600">
class="rounded-md bg-indigo-600 px-3 py-2 text-center text-sm font-semibold text-white shadow-sm hover:bg-indigo-500 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-indigo-600">
{{ __('Create Download') }}
</x-button>
</div>

View file

@ -24,7 +24,7 @@ class="px-3 py-3.5 text-left text-sm font-semibold text-gray-900">@lang('Attachm
</tr>
</thead>
<tbody class="divide-y divide-gray-200">
@foreach($project->mailings as $mail)
@foreach($mailings as $mail)
<tr>
<td class="whitespace-nowrap py-4 pl-4 pr-3 text-sm font-medium text-gray-900 sm:pl-6 lg:pl-8">{{ $mail->id }}</td>
<td class="whitespace-nowrap px-3 py-4 text-sm text-gray-500">{{ $mail->subject }}</td>
@ -43,6 +43,13 @@ class="text-indigo-600 hover:text-indigo-900">Show
</tbody>
</table>
</div>
<div class="pt-4 flex justify-between items-center">
<div class="text-gray-700 text-sm">
Results: {{ \Illuminate\Support\Number::format($mailings->total()) }}
</div>
{{ $mailings->links('livewire.pagination') }}
</div>

View file

@ -2,11 +2,13 @@
namespace Tests\Unit\Models;
use App\Jobs\ProjectDownloadTiffJob;
use App\Models\Project;
use App\Models\ProjectReport;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Support\Carbon;
use Illuminate\Support\Collection;
use Mockery;
use Tests\TestCase;
@ -86,16 +88,37 @@ public function it_can_return_the_reportDate($expected, $mail_day, $week, $year)
public static function reportDateProvider()
{
return [
'monday' => ['2023-12-10' , 'monday', 50, 2023],
'tuesday' => ['2023-12-11' , 'tuesday', 50, 2023],
'wednesday' => ['2023-12-12' , 'wednesday', 50, 2023],
'thursday' => ['2023-12-13' , 'thursday', 50, 2023],
'friday' => ['2023-12-14' , 'friday', 50, 2023],
'saturday' => ['2023-12-15' , 'saturday', 50, 2023],
'sunday' => ['2023-12-16' , 'sunday', 50, 2023],
'monday' => ['2023-12-10', 'monday', 50, 2023],
'tuesday' => ['2023-12-11', 'tuesday', 50, 2023],
'wednesday' => ['2023-12-12', 'wednesday', 50, 2023],
'thursday' => ['2023-12-13', 'thursday', 50, 2023],
'friday' => ['2023-12-14', 'friday', 50, 2023],
'saturday' => ['2023-12-15', 'saturday', 50, 2023],
'sunday' => ['2023-12-16', 'sunday', 50, 2023],
];
}
/** @test */
public function it_can_calculate_mosaic_dependencies()
{
$project = Project::create([
'name' => 'project_name',
'download_path' => 'project_download_path',
]);
$projectReport = $project->reports()->create([
'name' => 'name',
'year' => 2021,
'week' => 25,
'path' => 'path/doc.pdf',
]);
Bus::fake();
$projectReport->schedule();
}
}

Binary file not shown.