This commit is contained in:
guillaume91 2024-05-31 15:52:42 +02:00
parent 026e2601c4
commit e511cae64d
13 changed files with 158 additions and 20 deletions

View file

@ -3,6 +3,7 @@
namespace App\Jobs;
use App\Enums\Status;
use App\Livewire\Projects\Tabs\Mosaic;
use App\Models\Project;
use App\Models\ProjectDownload;
use App\Models\ProjectMosaic;
@ -88,8 +89,11 @@ public static function handleFor(Project $project, $year, $startWeekNumber)
],
[
'name' => sprintf('Week %d, %d', $startWeekNumber, $year),
'path' => sprintf('%s/%s/%s', $project->download_path, 'mosaics',
sprintf('week_%d_%d.tif', $startWeekNumber, $year)),
'path' => sprintf('%s/%s/%s',
$project->download_path,
'mosaics',
ProjectMosaic::getFilenameForYearAndWeek($year, $startWeekNumber)
),
'year' => $year,
'week' => $startWeekNumber,
]);

View file

@ -19,6 +19,11 @@ class ProjectMosaic extends Model
'status'
];
public static function getFilenameForYearAndWeek($year, $startWeekNumber)
{
return sprintf('week_%02d_%d.tif', $startWeekNumber, $year);
}
public function project()
{
return $this->belongsTo(Project::class);

View file

@ -14,6 +14,7 @@
"laravel/sanctum": "^4.0",
"laravel/telescope": "^5.0",
"laravel/tinker": "^2.9",
"leaflet/leaflet": "*",
"livewire/livewire": "^3.0",
"maatwebsite/excel": "^3.1",
"plesk/ext-laravel-integration": "^7.0"

View file

@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
"content-hash": "42be2af1c7ce17f827e0b68db75435e9",
"content-hash": "02a769bc324ca6d387d9e85c61229c6b",
"packages": [
{
"name": "bacon/bacon-qr-code",
@ -2264,6 +2264,32 @@
},
"time": "2024-01-04T16:10:04+00:00"
},
{
"name": "leaflet/leaflet",
"version": "v1.4.0",
"source": {
"type": "git",
"url": "https://github.com/aissasell/leaflet.git",
"reference": "7eadefcbd4d8bbb9af36a2b78186e6d068afa177"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/aissasell/leaflet/zipball/7eadefcbd4d8bbb9af36a2b78186e6d068afa177",
"reference": "7eadefcbd4d8bbb9af36a2b78186e6d068afa177",
"shasum": ""
},
"type": "library",
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-2-Clause"
],
"description": "an open-source JavaScript library for mobile-friendly interactive maps",
"support": {
"issues": "https://github.com/aissasell/leaflet/issues",
"source": "https://github.com/aissasell/leaflet/tree/v1.4.0"
},
"time": "2019-03-23T14:27:52+00:00"
},
{
"name": "league/commonmark",
"version": "2.4.2",

View file

@ -15,6 +15,7 @@
"@tailwindcss/aspect-ratio": "^0.4.2",
"alpinejs": "^3.13.3",
"flatpickr": "^4.6.13",
"leaflet": "^1.9.4",
"tailwindcss": "^3.3.3"
},
"devDependencies": {
@ -1150,6 +1151,11 @@
"vite": "^3.0.0 || ^4.0.0"
}
},
"node_modules/leaflet": {
"version": "1.9.4",
"resolved": "https://registry.npmjs.org/leaflet/-/leaflet-1.9.4.tgz",
"integrity": "sha512-nxS1ynzJOmOlHp+iL3FyWqK89GtNL8U8rvlMOsQdTTssxZwCXh8N2NB3GDQOL+YR3XnWyZAxwQixURb+FA74PA=="
},
"node_modules/lilconfig": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-2.1.0.tgz",

View file

@ -29,6 +29,7 @@
"@tailwindcss/aspect-ratio": "^0.4.2",
"alpinejs": "^3.13.3",
"flatpickr": "^4.6.13",
"leaflet": "^1.9.4",
"tailwindcss": "^3.3.3"
}
}

View file

@ -32,12 +32,12 @@
"src": "node_modules/@fortawesome/fontawesome-free/webfonts/fa-v4compatibility.woff2"
},
"resources/css/app.css": {
"file": "assets/app-93dd061f.css",
"file": "assets/app-df56bbfb.css",
"isEntry": true,
"src": "resources/css/app.css"
},
"resources/js/alpine.js": {
"file": "assets/alpine-e0ba2549.js",
"file": "assets/alpine-d6afa966.js",
"isDynamicEntry": true,
"src": "resources/js/alpine.js"
},
@ -45,7 +45,7 @@
"dynamicImports": [
"resources/js/alpine.js"
],
"file": "assets/app-eb81fffd.js",
"file": "assets/app-f5ffacbb.js",
"isEntry": true,
"src": "resources/js/app.js"
}

View file

@ -2,6 +2,7 @@
@import url('https://rsms.me/inter/inter.css');
@import '@fortawesome/fontawesome-free/css/all.css';
@import "@dasundev/livewire-dropzone-styles";
@import "leaflet/dist/leaflet.css";
@tailwind base;
@tailwind components;
@tailwind utilities;

View file

@ -1,5 +1,6 @@
import './bootstrap';
import('./alpine');
import flatpckr from 'flatpickr';
import leaflet from 'leaflet';
window.flatpckr = flatpckr;

View file

@ -39,6 +39,7 @@
<x-notification />
@stack('modals')
@stack('map')
@livewireScriptConfig
</body>

View file

@ -1,4 +1,44 @@
<div class="flex flex-col divide-y space-y-4 m-2">
@push('map')
@endpush
<div class="flex flex-col divide-y space-y-4 m-2"
x-data="{
processFile(file) {
let filetype = ['json','geojson'];
if(!filetype.includes(file.name.split('.').pop())) return;
const reader = new FileReader();
reader.onload = (event) => {
const data = event.target.result;
try {
this.showMap(JSON.parse(data));
} catch (error) {
console.error('Error parsing GeoJSON:', error);
}
};
reader.readAsText(file);
},
showMap(d){
try{
let map = document.getElementById('map');
map.style.height = '300px';
window.map = L.map('map').setView([51.505, -0.09], 13);
L.tileLayer('https://tile.openstreetmap.org/{z}/{x}/{y}.png', {
maxZoom: 19,
attribution: '&copy; <a href=`http://www.openstreetmap.org/copyright`>OpenStreetMap</a>'
}).addTo(window.map);
window.geoJsonLayer = L.geoJSON();
window.geoJsonLayer.addTo(window.map);
}catch(err){
console.log('Map already loaded');
}
window.geoJsonLayer.addData(d);
window.map.fitBounds(geoJsonLayer.getBounds());
map.focus();
console.log('added geojson.');
}
}"
x-on:livewire-upload-finish.document="processFile($event.target.files[0]);"
>
<div id="edit" class="flex flex-col md:flex-row gap-2">
<div class="flex flex-col md:w-1/3">
<div class="text-xl font-bold ">
@ -10,6 +50,9 @@
</div>
<div class="md:w-2/3">
<form>
<div id="map">
</div>
<!-- Token Name -->
<div class="mb-2">
<x-label for="name" value="{{ __('Name') }}"/>
@ -23,6 +66,7 @@
wire:model="pivotFiles"
:rules="['extensions:json,geojson','mimes:json,geojson']"
:key="'pivotFiles'"
wire:key="'pivotFiles'"
/>
</div>
@error('pivotFiles')
@ -36,6 +80,7 @@
wire:model="spanFiles"
:rules="['extensions:json,geojson','mimes:json,geojson']"
:key="'spanFiles'"
wire:key="'spanFiles'"
/>
</div>
@error('spanFiles')
@ -49,6 +94,7 @@
wire:model="harvestDataFiles"
:rules="['extensions:xls,xlsx,ods','mimes:xls,xlsx,ods','required']"
:key="'harvest_file'"
wire:key="'harvest_file'"
/>
</div>
@error('harvest_file')
@ -73,14 +119,16 @@ class="flex flex-col md:w-2/3"
> {{-- flex col--}}
<div class="flex justify-between my-4">
<div class="inline-flex items-center gap-2">
{{-- <span class="text-lg font-semibold dark:text-gray-300">{{__('Mail')}}</span>---}}
{{-- <span class="text-lg font-semibold dark:text-gray-300">{{__('Mail')}}</span>---}}
<div class=" text-md font-bold">
{{ __('Send a mail to recipients periodically') }}
</div>
</div>
<label class="inline-flex items-center cursor-pointer gap-4">
<input type="checkbox" class="sr-only peer" wire:model.live="formData.mail_scheduled" @click="showMail = $el.checked">
<div class="relative w-11 h-6 bg-gray-200 peer-focus:outline-none peer-focus:ring-4 peer-focus:ring-indigo-300 dark:peer-focus:ring-indigo-800 rounded-full peer dark:bg-gray-700 peer-checked:after:translate-x-full rtl:peer-checked:after:-translate-x-full peer-checked:after:border-white after:content-[''] after:absolute after:top-[2px] after:start-[2px] after:bg-white after:border-gray-300 after:border after:rounded-full after:h-5 after:w-5 after:transition-all dark:border-gray-600 peer-checked:bg-indigo-600"></div>
<input type="checkbox" class="sr-only peer" wire:model.live="formData.mail_scheduled"
@click="showMail = $el.checked">
<div
class="relative w-11 h-6 bg-gray-200 peer-focus:outline-none peer-focus:ring-4 peer-focus:ring-indigo-300 dark:peer-focus:ring-indigo-800 rounded-full peer dark:bg-gray-700 peer-checked:after:translate-x-full rtl:peer-checked:after:-translate-x-full peer-checked:after:border-white after:content-[''] after:absolute after:top-[2px] after:start-[2px] after:bg-white after:border-gray-300 after:border after:rounded-full after:h-5 after:w-5 after:transition-all dark:border-gray-600 peer-checked:bg-indigo-600"></div>
</label>
</div>
<div class="flex w-full ">

View file

@ -131,20 +131,20 @@ class="hidden"
@script
<script>
Alpine.data('dropzone', ({ _this, uuid, multiple }) => {
return ({
const process = {
isDragging: false,
isDropped: false,
isLoading: false,
onDrop(e) {
this.isDropped = true
this.isDragging = false
const file = multiple ? e.dataTransfer.files : e.dataTransfer.files[0]
this.isDropped = true;
this.isDragging = false;
const file = multiple ? e.dataTransfer.files : e.dataTransfer.files[0];
const args = ['upload', file, () => {
// Upload completed
this.isLoading = false
this.isLoading = false;
this.processFile(file);
}, (error) => {
// An error occurred while uploading
console.log('livewire-dropzone upload error', error);
@ -154,7 +154,7 @@ class="hidden"
}];
// Upload file(s)
multiple ? _this.uploadMultiple(...args) : _this.upload(...args)
multiple ? _this.uploadMultiple(...args) : _this.upload(...args);
},
onDragenter() {
if(!this.isDragging){
@ -174,8 +174,9 @@ class="hidden"
removeUpload(tmpFilename) {
// Dispatch an event to remove the temporarily uploaded file
_this.dispatch(uuid + ':fileRemoved', { tmpFilename })
},
});
}
};
return (process);
})
</script>
@endscript

View file

@ -0,0 +1,43 @@
<?php
namespace Tests\Unit\Models;
use App\Jobs\ProjectDownloadTiffJob;
use App\Jobs\ProjectMosiacGeneratorJob;
use App\Jobs\ProjectReportGeneratorJob;
use App\Models\Project;
use App\Models\ProjectMosaic;
use Illuminate\Bus\PendingBatch;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Support\Carbon;
use Illuminate\Support\Facades\Bus;
use Mockery;
use Tests\TestCase;
class ProjectMosaicTest extends TestCase
{
use RefreshDatabase;
/**
* @test
* @dataProvider filenameProvider
* */
public function it_should_return_the_correct_attachment_path($year,$week, $expected)
{
$this->assertEquals(
$expected,
ProjectMosaic::getFilenameForYearAndWeek($year, $week)
);
}
public static function filenameProvider(){
return [
[2022, 1, 'week_01_2022.tif'],
[2022, 10, 'week_10_2022.tif'],
];
}
}