Carto on Unveil ok
This commit is contained in:
parent
6cd2a87655
commit
afad70924b
17 changed files with 588 additions and 91 deletions
|
|
@ -21,6 +21,7 @@ use App\Models\StaticPage;
|
|||
use App\Models\Strip;
|
||||
use App\Models\Testimonial;
|
||||
use Illuminate\Support\Facades\Mail;
|
||||
use Illuminate\Support\Str;
|
||||
|
||||
class StaticPageController extends Controller
|
||||
{
|
||||
|
|
@ -80,18 +81,24 @@ class StaticPageController extends Controller
|
|||
$historySection = $sectionModels->where('section', PageSectionEnum::unveil_history)->first();
|
||||
$commitmentSection = $sectionModels->where('section', PageSectionEnum::unveil_commitments)->first();
|
||||
|
||||
// * Calcul Viewbox leaflet map.
|
||||
$viewBox = (object)[
|
||||
// @phpstan-ignore-next-line
|
||||
'lat' => \round($siteModelList->sum(fn (Site $siteModel) =>
|
||||
$siteModel->latitude) / $siteModelList->count(), 6),
|
||||
// @phpstan-ignore-next-line
|
||||
'lng' => \round($siteModelList->sum(fn (Site $siteModel) =>
|
||||
$siteModel->longitude) / $siteModelList->count(), 6)
|
||||
];
|
||||
$viewBox = null;
|
||||
$initialZoom = null;
|
||||
// * Calcul Viewbox leaflet map ().
|
||||
// Carte page “on se dévoile” : Point central = Laval + rayon = 100 km
|
||||
/** @var \App\Models\Site|null $lavalSite */
|
||||
// @phpstan-ignore-next-line
|
||||
$lavalSite = $siteModelList->first(fn (Site $site) => Str::contains($site->name, 'Laval'));
|
||||
if ($lavalSite) {
|
||||
$viewBox = (object)[
|
||||
'lat' => $lavalSite->latitude,
|
||||
'lng' => $lavalSite->longitude
|
||||
];
|
||||
$initialZoom = 9;
|
||||
}
|
||||
|
||||
return view('fo.pages.unveil', compact(
|
||||
'viewBox',
|
||||
'initialZoom',
|
||||
'staticPageModel',
|
||||
'sectionModels',
|
||||
'historicalMilestoneModels',
|
||||
|
|
@ -276,9 +283,17 @@ class StaticPageController extends Controller
|
|||
$nextSiteModel = Site::query()->orderBy('order')->where('order', '>', $site->order)->first();
|
||||
}
|
||||
|
||||
$viewBox = (object)[
|
||||
'lat' => $site->latitude,
|
||||
'lng' => $site->longitude
|
||||
];
|
||||
$initialZoom = 9;
|
||||
|
||||
return view('fo.pages.site', [
|
||||
'siteModel' => $site,
|
||||
'nextSiteModel' => $nextSiteModel
|
||||
'nextSiteModel' => $nextSiteModel,
|
||||
'viewBox' => $viewBox,
|
||||
'initialZoom' => $initialZoom,
|
||||
]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -80,7 +80,7 @@ class StoreSiteRequest extends FormRequest
|
|||
];
|
||||
return \array_merge(
|
||||
$rules,
|
||||
$this->pictureRules('logo', 300, 300, 300, 300, false),
|
||||
$this->pictureRules('logo', 1000, 727, 1000, 727, false),
|
||||
$this->pictureRules('picture_1', 1000, 562, 1000, 562, false),
|
||||
$this->pictureRules('picture_2', 1000, 562, 1000, 562, true),
|
||||
$this->pictureRules('picture_3', 1000, 562, 1000, 562, true),
|
||||
|
|
|
|||
|
|
@ -16,6 +16,7 @@
|
|||
"axlon/laravel-postal-code-validation": "^3.5",
|
||||
"diglactic/laravel-breadcrumbs": "^8.0",
|
||||
"guzzlehttp/guzzle": "^7.2",
|
||||
"kwaadpepper/image-resizer": "^2.1",
|
||||
"laravel/framework": "^10.0",
|
||||
"laravel/tinker": "^2.8",
|
||||
"laravel/ui": "^4.2",
|
||||
|
|
@ -28,7 +29,7 @@
|
|||
"fakerphp/faker": "^1.9.1",
|
||||
"kitloong/laravel-migrations-generator": "^6.8",
|
||||
"krlove/eloquent-model-generator": "dev-l10-compatibility",
|
||||
"larastan/larastan": "^2.6",
|
||||
"larastan/larastan": "^2.9",
|
||||
"laravel-lang/common": "^4.0",
|
||||
"laravel/pint": "^1.0",
|
||||
"laravel/sail": "^1.18",
|
||||
|
|
|
|||
279
composer.lock
generated
279
composer.lock
generated
|
|
@ -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": "4bf7c1fe3b307c9b2251f4ebcfbd0cd4",
|
||||
"content-hash": "1da5334945451015dfb5c5edc5c9b42f",
|
||||
"packages": [
|
||||
{
|
||||
"name": "axlon/laravel-postal-code-validation",
|
||||
|
|
@ -1422,6 +1422,158 @@
|
|||
],
|
||||
"time": "2023-12-03T19:50:20+00:00"
|
||||
},
|
||||
{
|
||||
"name": "intervention/image",
|
||||
"version": "2.7.2",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/Intervention/image.git",
|
||||
"reference": "04be355f8d6734c826045d02a1079ad658322dad"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/Intervention/image/zipball/04be355f8d6734c826045d02a1079ad658322dad",
|
||||
"reference": "04be355f8d6734c826045d02a1079ad658322dad",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"ext-fileinfo": "*",
|
||||
"guzzlehttp/psr7": "~1.1 || ^2.0",
|
||||
"php": ">=5.4.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"mockery/mockery": "~0.9.2",
|
||||
"phpunit/phpunit": "^4.8 || ^5.7 || ^7.5.15"
|
||||
},
|
||||
"suggest": {
|
||||
"ext-gd": "to use GD library based image processing.",
|
||||
"ext-imagick": "to use Imagick based image processing.",
|
||||
"intervention/imagecache": "Caching extension for the Intervention Image library"
|
||||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "2.4-dev"
|
||||
},
|
||||
"laravel": {
|
||||
"providers": [
|
||||
"Intervention\\Image\\ImageServiceProvider"
|
||||
],
|
||||
"aliases": {
|
||||
"Image": "Intervention\\Image\\Facades\\Image"
|
||||
}
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Intervention\\Image\\": "src/Intervention/Image"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Oliver Vogel",
|
||||
"email": "oliver@intervention.io",
|
||||
"homepage": "https://intervention.io/"
|
||||
}
|
||||
],
|
||||
"description": "Image handling and manipulation library with support for Laravel integration",
|
||||
"homepage": "http://image.intervention.io/",
|
||||
"keywords": [
|
||||
"gd",
|
||||
"image",
|
||||
"imagick",
|
||||
"laravel",
|
||||
"thumbnail",
|
||||
"watermark"
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/Intervention/image/issues",
|
||||
"source": "https://github.com/Intervention/image/tree/2.7.2"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
"url": "https://paypal.me/interventionio",
|
||||
"type": "custom"
|
||||
},
|
||||
{
|
||||
"url": "https://github.com/Intervention",
|
||||
"type": "github"
|
||||
}
|
||||
],
|
||||
"time": "2022-05-21T17:30:32+00:00"
|
||||
},
|
||||
{
|
||||
"name": "intervention/imagecache",
|
||||
"version": "2.6.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/Intervention/imagecache.git",
|
||||
"reference": "86136575a62d3634b51f196a998fce4a583b49bb"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/Intervention/imagecache/zipball/86136575a62d3634b51f196a998fce4a583b49bb",
|
||||
"reference": "86136575a62d3634b51f196a998fce4a583b49bb",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"illuminate/cache": "^5.5|~6|~7|~8|~9|~10",
|
||||
"illuminate/filesystem": "^5.5|~6|~7|~8|~9|~10",
|
||||
"intervention/image": "~2.2",
|
||||
"nesbot/carbon": "^2.39",
|
||||
"opis/closure": "^3.5",
|
||||
"php": "~7.2|~8"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpunit/phpunit": "^8.0"
|
||||
},
|
||||
"type": "library",
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Intervention\\Image\\": "src/Intervention/Image"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Oliver Vogel",
|
||||
"email": "oliver@intervention.io",
|
||||
"homepage": "http://intervention.io/"
|
||||
}
|
||||
],
|
||||
"description": "Caching extension for the Intervention Image Class",
|
||||
"homepage": "https://image.intervention.io",
|
||||
"keywords": [
|
||||
"cache",
|
||||
"gd",
|
||||
"image",
|
||||
"imagick",
|
||||
"laravel"
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/Intervention/imagecache/issues",
|
||||
"source": "https://github.com/Intervention/imagecache/tree/2.6.0"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
"url": "https://paypal.me/interventionio",
|
||||
"type": "custom"
|
||||
},
|
||||
{
|
||||
"url": "https://github.com/Intervention",
|
||||
"type": "github"
|
||||
}
|
||||
],
|
||||
"abandoned": true,
|
||||
"time": "2023-02-25T19:40:47+00:00"
|
||||
},
|
||||
{
|
||||
"name": "jean85/pretty-package-versions",
|
||||
"version": "2.0.6",
|
||||
|
|
@ -1481,6 +1633,66 @@
|
|||
},
|
||||
"time": "2024-03-08T09:58:59+00:00"
|
||||
},
|
||||
{
|
||||
"name": "kwaadpepper/image-resizer",
|
||||
"version": "2.1.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/Kwaadpepper/image-resizer.git",
|
||||
"reference": "2a14ad153b34916f437af50549bad47c018902df"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/Kwaadpepper/image-resizer/zipball/2a14ad153b34916f437af50549bad47c018902df",
|
||||
"reference": "2a14ad153b34916f437af50549bad47c018902df",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"illuminate/support": "~10",
|
||||
"intervention/image": "^2.7.2",
|
||||
"intervention/imagecache": "^2.6",
|
||||
"laravel/framework": "~10"
|
||||
},
|
||||
"require-dev": {
|
||||
"slevomat/coding-standard": "^8.11"
|
||||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"laravel": {
|
||||
"providers": [
|
||||
"Kwaadpepper\\ImageResizer\\ImageResizerServiceProvider"
|
||||
]
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Kwaadpepper\\ImageResizer\\": "src/"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Jérémy Munsch",
|
||||
"email": "github@jeremydev.ovh",
|
||||
"homepage": "https://jeremydev.ovh"
|
||||
}
|
||||
],
|
||||
"description": "Resize images on the fly and cache them",
|
||||
"homepage": "https://github.com/kwaadpepper/image-resizer",
|
||||
"keywords": [
|
||||
"images",
|
||||
"laravel",
|
||||
"resize"
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/Kwaadpepper/image-resizer/issues",
|
||||
"source": "https://github.com/Kwaadpepper/image-resizer/tree/2.1.0"
|
||||
},
|
||||
"time": "2023-06-08T12:07:24+00:00"
|
||||
},
|
||||
{
|
||||
"name": "laravel/framework",
|
||||
"version": "v10.48.3",
|
||||
|
|
@ -2982,6 +3194,71 @@
|
|||
],
|
||||
"time": "2023-11-13T09:31:12+00:00"
|
||||
},
|
||||
{
|
||||
"name": "opis/closure",
|
||||
"version": "3.6.3",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/opis/closure.git",
|
||||
"reference": "3d81e4309d2a927abbe66df935f4bb60082805ad"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/opis/closure/zipball/3d81e4309d2a927abbe66df935f4bb60082805ad",
|
||||
"reference": "3d81e4309d2a927abbe66df935f4bb60082805ad",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": "^5.4 || ^7.0 || ^8.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"jeremeamia/superclosure": "^2.0",
|
||||
"phpunit/phpunit": "^4.0 || ^5.0 || ^6.0 || ^7.0 || ^8.0 || ^9.0"
|
||||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "3.6.x-dev"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"files": [
|
||||
"functions.php"
|
||||
],
|
||||
"psr-4": {
|
||||
"Opis\\Closure\\": "src/"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Marius Sarca",
|
||||
"email": "marius.sarca@gmail.com"
|
||||
},
|
||||
{
|
||||
"name": "Sorin Sarca",
|
||||
"email": "sarca_sorin@hotmail.com"
|
||||
}
|
||||
],
|
||||
"description": "A library that can be used to serialize closures (anonymous functions) and arbitrary objects.",
|
||||
"homepage": "https://opis.io/closure",
|
||||
"keywords": [
|
||||
"anonymous functions",
|
||||
"closure",
|
||||
"function",
|
||||
"serializable",
|
||||
"serialization",
|
||||
"serialize"
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/opis/closure/issues",
|
||||
"source": "https://github.com/opis/closure/tree/3.6.3"
|
||||
},
|
||||
"time": "2022-01-27T09:35:39+00:00"
|
||||
},
|
||||
{
|
||||
"name": "phpoption/phpoption",
|
||||
"version": "1.9.2",
|
||||
|
|
|
|||
70
config/image-resizer.php
Normal file
70
config/image-resizer.php
Normal file
|
|
@ -0,0 +1,70 @@
|
|||
<?php
|
||||
|
||||
return [
|
||||
/**
|
||||
* The php image driver to use
|
||||
* this can be 'imagick' or 'gd'
|
||||
*/
|
||||
'driver' => 'imagick',
|
||||
|
||||
/**
|
||||
* The cache driver to use as defined
|
||||
* in config/cache of your app
|
||||
*/
|
||||
'cache' => 'file',
|
||||
|
||||
/**
|
||||
* The path where to store image in cache
|
||||
*/
|
||||
'cachePath' => 'cache/images',
|
||||
|
||||
/**
|
||||
* Image cache life time
|
||||
* This is given in minutes
|
||||
* Here the cache for images is
|
||||
* one hour
|
||||
*/
|
||||
'lifetime' => 60,
|
||||
|
||||
/**
|
||||
* Format can specifiy to which format save the image
|
||||
* JPEG PNG GIF TIF BMP ICO PSD WebP
|
||||
* GD ✔️ ✔️ ✔️ - - - - ✔️ *
|
||||
* Imagick ✔️ ✔️ ✔️ ✔️ ✔️ ✔️ ✔️ ✔️ *
|
||||
* For WebP support GD driver must be used with PHP 5 >= 5.5.0 or PHP 7
|
||||
* in order to use imagewebp(). If Imagick is used, it must be compiled
|
||||
* with libwebp for WebP support.
|
||||
* resize => will resize the image (boolean)
|
||||
* fit => Combine cropping and resizing to format image in a smart way (boolean)
|
||||
* keepRatio => will keep image ratio wile resizing (boolean)
|
||||
* trim => boolean to trim the image using border color
|
||||
* inCanvas => to make sure image boundarie is respected
|
||||
* format => select tha wantd ouput form, yan can just convert images if you want
|
||||
* example :
|
||||
* 'small' => [
|
||||
* 'height' => 500,
|
||||
* 'width' => 250,
|
||||
* 'inCanvas' => true,
|
||||
* 'trim' => ['transparent', null, 10]
|
||||
* ],
|
||||
* 'smallWebp' => [
|
||||
* 'height' => 500,
|
||||
* 'width' => 250,
|
||||
* 'inCanvas' => true,
|
||||
* 'format' => 'webp'
|
||||
* ],
|
||||
* 'justconvertImage' => [
|
||||
* 'format' => 'webp'
|
||||
* ]
|
||||
*/
|
||||
'templates' => [
|
||||
'cartoPicture' => [
|
||||
'height' => 140,
|
||||
'width' => 155,
|
||||
'fit' => true,
|
||||
'inCanvas' => true,
|
||||
'trim' => ['transparent', null, 10],
|
||||
'format' => 'webp',
|
||||
]
|
||||
]
|
||||
];
|
||||
BIN
database/factories/assets/sites/default-picture-1000x727.jpg
Normal file
BIN
database/factories/assets/sites/default-picture-1000x727.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 13 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 2.5 KiB |
|
|
@ -25,7 +25,7 @@ class SiteSeeder extends Seeder
|
|||
$site->logo = FileStorageHelper::storeFile(
|
||||
new Site(),
|
||||
new \SplFileInfo(\resource_path(
|
||||
'../database/factories/assets/sites/default-picture-300x300.png'
|
||||
'../database/factories/assets/sites/default-picture-1000x727.jpg'
|
||||
))
|
||||
);
|
||||
$site->picture_1 = FileStorageHelper::storeFile(
|
||||
|
|
|
|||
|
|
@ -176,3 +176,9 @@ $theme-colors: map.merge($theme-colors, $light-colors);
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
// .map-site-widget {
|
||||
// img {
|
||||
// width: 6rem;
|
||||
// }
|
||||
// }
|
||||
|
|
|
|||
|
|
@ -18,7 +18,15 @@
|
|||
|
||||
.sites {
|
||||
.embed-map {
|
||||
min-height: 20rem;
|
||||
min-height: 30rem;
|
||||
|
||||
@include media-breakpoint-up(sm) {
|
||||
min-height: 35rem;
|
||||
}
|
||||
|
||||
@include media-breakpoint-up(md) {
|
||||
min-height: 40rem;
|
||||
}
|
||||
|
||||
iframe {
|
||||
width: 100%;
|
||||
|
|
|
|||
|
|
@ -177,6 +177,27 @@ document.addEventListener("DOMContentLoaded", function () {
|
|||
},
|
||||
},
|
||||
},
|
||||
"swiper-sites-map": {
|
||||
centeredSlides: true,
|
||||
modules: [Keyboard],
|
||||
grabCursor: true,
|
||||
slidesPerView: 1,
|
||||
spaceBetween: 20,
|
||||
keyboard: {
|
||||
enabled: true,
|
||||
},
|
||||
breakpoints: {
|
||||
768: {
|
||||
slidesPerView: 1.5,
|
||||
},
|
||||
992: {
|
||||
slidesPerView: 1,
|
||||
},
|
||||
1200: {
|
||||
slidesPerView: 1.3,
|
||||
},
|
||||
},
|
||||
},
|
||||
"swiper-sites-pictures": {
|
||||
modules: [Navigation, Keyboard],
|
||||
grabCursor: true,
|
||||
|
|
@ -301,13 +322,8 @@ document.addEventListener("DOMContentLoaded", function () {
|
|||
},
|
||||
};
|
||||
|
||||
type SwiperSlider = {
|
||||
element: HTMLElement;
|
||||
swiper: Swiper;
|
||||
};
|
||||
|
||||
const swiperVol = document.getElementsByClassName("swiper") as HTMLCollectionOf<HTMLElement>,
|
||||
sliders: SwiperSlider[] = [];
|
||||
const swiperVol = document.getElementsByClassName("swiper") as HTMLCollectionOf<HTMLElement>;
|
||||
window.__SLIDERS = new Map<string,SwiperSlider>();
|
||||
|
||||
for (const htmlElt of swiperVol) {
|
||||
if (!swiperConfig[htmlElt.id as keyof typeof swiperConfig]) {
|
||||
|
|
@ -315,10 +331,12 @@ document.addEventListener("DOMContentLoaded", function () {
|
|||
}
|
||||
// @ts-ignore
|
||||
const swiper = new Swiper(htmlElt, swiperConfig[htmlElt.id as keyof typeof swiperConfig]);
|
||||
sliders.push({
|
||||
element: htmlElt,
|
||||
swiper: swiper,
|
||||
});
|
||||
window.__SLIDERS.set(
|
||||
htmlElt.id,
|
||||
{
|
||||
element: htmlElt,
|
||||
swiper: swiper,
|
||||
});
|
||||
if (swiper.el.id === "swiper-teams") {
|
||||
const btnPlayPause = document.querySelector(".swiper-pagination-playpause");
|
||||
btnPlayPause?.addEventListener("click", function () {
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@
|
|||
>
|
||||
<div
|
||||
ref="marker"
|
||||
class="d-none marker-pin text-bg-white px-3 py-1 d-flex justify-content-center align-items-center f-barlow rounded-pill border border-1 border-primary"
|
||||
class="d-none marker-pin bg-white text-primary px-3 py-1 d-flex justify-content-center align-items-center f-barlow rounded-pill border border-1 border-primary"
|
||||
>
|
||||
<img
|
||||
class="marker-logo mx-1"
|
||||
|
|
@ -13,25 +13,13 @@
|
|||
alt=""
|
||||
>
|
||||
<span>
|
||||
<span class="mx-1 marker-title text-primary fw-bold text-uppercase text-break" />
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<div
|
||||
ref="marker-pannel"
|
||||
class="d-none"
|
||||
>
|
||||
<span class="h4 marker-title" />
|
||||
<div class="marker-desc" />
|
||||
<span class="marker-people">
|
||||
<FontAwesomeIcon icon="fa-solid fa-users" />
|
||||
<span class="mx-1 marker-title fw-bold text-uppercase text-break" />
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { FontAwesomeIcon } from "@fortawesome/vue-fontawesome";
|
||||
import { DivIcon, Icon, Map, Marker, TileLayer, type LatLngExpression, type LatLngTuple } from "leaflet";
|
||||
// @ts-ignore
|
||||
import "overlapping-marker-spiderfier-leaflet";
|
||||
|
|
@ -55,30 +43,32 @@ type Site = {
|
|||
alt: string;
|
||||
title: string;
|
||||
},
|
||||
divIcon: DivIcon
|
||||
divIcon: DivIcon,
|
||||
marker: Marker|null
|
||||
};
|
||||
|
||||
export default defineComponent({
|
||||
name: "LeafletMapVueComponent",
|
||||
mixins: [trans],
|
||||
components: {FontAwesomeIcon},
|
||||
data(): {
|
||||
wrapperClasses: string[];
|
||||
map: Map;
|
||||
oms: OverlappingMarkerSpiderfier;
|
||||
initialPosition: LatLngExpression;
|
||||
initialPosition: LatLngExpression | null;
|
||||
initialZoom: number;
|
||||
siteList: Array<Site>;
|
||||
markerTextLength: number;
|
||||
controlSliderId: string|null;
|
||||
} {
|
||||
return {
|
||||
wrapperClasses:[],
|
||||
map: {} as Map,
|
||||
oms: {} as OverlappingMarkerSpiderfier,
|
||||
initialPosition: [0, 0],
|
||||
initialZoom: 3,
|
||||
initialPosition: null,
|
||||
initialZoom: 9,
|
||||
siteList: [],
|
||||
markerTextLength: 20
|
||||
markerTextLength: 20,
|
||||
controlSliderId: null
|
||||
};
|
||||
},
|
||||
computed: {},
|
||||
|
|
@ -86,7 +76,21 @@ export default defineComponent({
|
|||
const json = String(this.$attrs.json ?? "{}"),
|
||||
data = JSON.parse(json);
|
||||
this.wrapperClasses = data.wrapperClasses ?? [];
|
||||
this.initialPosition = [Number.parseFloat(data.coordinates.lat), Number.parseFloat(data.coordinates.lng)];
|
||||
|
||||
if(data.coordinates) {
|
||||
this.initialPosition = [
|
||||
Number.parseFloat(data.coordinates.lat),
|
||||
Number.parseFloat(data.coordinates.lng)
|
||||
];
|
||||
}
|
||||
if(data.initialZoom) {
|
||||
this.initialZoom = data.initialZoom;
|
||||
}
|
||||
|
||||
if(data.controlSliderId) {
|
||||
this.controlSliderId = String(data.controlSliderId);
|
||||
}
|
||||
console.log(data);
|
||||
|
||||
this.parseSiteModelList(data.siteModelList);
|
||||
|
||||
|
|
@ -108,8 +112,12 @@ export default defineComponent({
|
|||
(new TileLayer("https://tile.openstreetmap.org/{z}/{x}/{y}.png", {
|
||||
attribution: "© <a href=\"http://www.openstreetmap.org/copyright\">OpenStreetMap</a>"
|
||||
})).addTo(this.map as Map);
|
||||
// * Auto set viewbox
|
||||
(this.map as Map).fitBounds(this.siteList.map(site => Object.values(site.coords)) as LatLngTuple[]);
|
||||
if(!this.initialPosition) {
|
||||
// * Auto set viewbox
|
||||
(this.map as Map).fitBounds(this.siteList.map(site => Object.values(site.coords)) as LatLngTuple[]);
|
||||
} else {
|
||||
(this.map as Map).setView(this.initialPosition, this.initialZoom);
|
||||
}
|
||||
// * Setup OMS
|
||||
// @ts-ignore
|
||||
this.oms = new OverlappingMarkerSpiderfier(this.map as Map, {
|
||||
|
|
@ -130,14 +138,11 @@ export default defineComponent({
|
|||
// ditto
|
||||
spiralLengthFactor: 5,
|
||||
});
|
||||
this.oms.addListener("click", (marker: Marker) => {
|
||||
console.log(marker);
|
||||
});
|
||||
this.oms.addListener("spiderfy", () => {
|
||||
this.map.closePopup();
|
||||
});
|
||||
this.oms.addListener("click", this.selectedMarker);
|
||||
this.oms.addListener("spiderfy", this.clearSelectedMarkers);
|
||||
},
|
||||
parseSiteModelList(siteModelList: LaravelModelList) {
|
||||
const bodyFontSize = parseFloat(getComputedStyle(document.documentElement).fontSize);
|
||||
siteModelList.forEach((site) => {
|
||||
this.siteList.push({
|
||||
name: String(site.name),
|
||||
|
|
@ -152,6 +157,7 @@ export default defineComponent({
|
|||
alt: String(site.logo_alt),
|
||||
title: String(site.logo_title),
|
||||
},
|
||||
marker: null,
|
||||
divIcon: new DivIcon({
|
||||
className: "leaf-div-icon",
|
||||
html: this.fetchNewMarkerElement(
|
||||
|
|
@ -162,8 +168,7 @@ export default defineComponent({
|
|||
title: String(site.logo_title),
|
||||
}
|
||||
),
|
||||
iconSize: [30, 42],
|
||||
iconAnchor: [15, 42]
|
||||
iconSize: [10*bodyFontSize, 3*bodyFontSize],
|
||||
})
|
||||
});
|
||||
});
|
||||
|
|
@ -191,6 +196,7 @@ export default defineComponent({
|
|||
this.map.addLayer(marker);
|
||||
// @ts-ignore
|
||||
this.oms.addMarker(marker);
|
||||
site.marker = marker;
|
||||
});
|
||||
},
|
||||
truncateString(str: string, limit: number, end: string = "..") {
|
||||
|
|
@ -198,6 +204,37 @@ export default defineComponent({
|
|||
return str;
|
||||
}
|
||||
return str.slice(0, limit) + end;
|
||||
},
|
||||
selectedMarker(marker: Marker) {
|
||||
this.clearSelectedMarkers();
|
||||
const siteIndex = this.siteList.findIndex(site => site!.marker!.options.title === marker.options.title);
|
||||
if(siteIndex === -1) {
|
||||
throw new Error("Could not fetch related Site");
|
||||
}
|
||||
const pin = marker.getElement()!.firstChild as HTMLElement | null;
|
||||
if(!pin) {
|
||||
throw new Error("Missing Marker Pin");
|
||||
}
|
||||
pin.classList.add("bg-primary", "text-white");
|
||||
pin.classList.remove("bg-white", "text-primary");
|
||||
|
||||
if(this.controlSliderId) {
|
||||
const slider = window.__SLIDERS.get(this.controlSliderId);
|
||||
if(!slider) {
|
||||
throw new Error(`Missing slider to control ${this.controlSliderId}`);
|
||||
}
|
||||
slider.swiper.slideTo(siteIndex);
|
||||
}
|
||||
},
|
||||
clearSelectedMarkers() {
|
||||
this.siteList.forEach(site => {
|
||||
const pin = site.marker!.getElement()!.firstChild as HTMLElement | null;
|
||||
if(!pin) {
|
||||
throw new Error("Missing Marker Pin");
|
||||
}
|
||||
pin.classList.add("bg-white", "text-primary");
|
||||
pin.classList.remove("bg-primary", "text-white");
|
||||
});
|
||||
}
|
||||
},
|
||||
});
|
||||
|
|
@ -208,26 +245,29 @@ export default defineComponent({
|
|||
</style>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
|
||||
|
||||
@import "bootstrap/scss/functions";
|
||||
@import "bootstrap/scss/variables";
|
||||
@import "bootstrap/scss/variables-dark";
|
||||
@import "bootstrap/scss/maps";
|
||||
@import "bootstrap/scss/mixins";
|
||||
@import "bootstrap/scss/vendor/rfs";
|
||||
.leafleat-wrapper-class {
|
||||
.marker-pin {
|
||||
@include rfs(10rem, min-width);
|
||||
}
|
||||
.marker-logo {
|
||||
object-fit: contain;
|
||||
height: auto;
|
||||
|
||||
@include rfs(2rem, width);
|
||||
}
|
||||
.marker-title {
|
||||
@include rfs(0.8rem, font-size);
|
||||
}
|
||||
.leafleat-wrapper-class {
|
||||
.marker-pin {
|
||||
width: 10rem;
|
||||
height: 3rem;
|
||||
}
|
||||
.marker-logo {
|
||||
object-fit: contain;
|
||||
height: auto;
|
||||
width: 2rem;
|
||||
}
|
||||
.marker-title {
|
||||
@include rfs(0.8rem, font-size);
|
||||
overflow: hidden;
|
||||
display: -webkit-box;
|
||||
/* number of lines to show */
|
||||
-webkit-line-clamp: 2;
|
||||
-webkit-box-orient: vertical;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
|
|||
7
resources/ts/index.d.ts
vendored
7
resources/ts/index.d.ts
vendored
|
|
@ -1,6 +1,7 @@
|
|||
import CookieNotice from "@ldc-web/cookie-notice";
|
||||
import type VueTagsInput from "@sipec/vue3-tags-input";
|
||||
import { AxiosStatic } from "axios";
|
||||
import type Swiper from "swiper";
|
||||
export { };
|
||||
|
||||
// * Enum
|
||||
|
|
@ -71,11 +72,17 @@ declare global {
|
|||
|
||||
type Enum = EnumInterface;
|
||||
|
||||
type SwiperSlider = {
|
||||
element: HTMLElement;
|
||||
swiper: Swiper;
|
||||
};
|
||||
|
||||
interface Window {
|
||||
CookieNotice: typeof CookieNotice;
|
||||
axios: AxiosStatic;
|
||||
Swal: Function;
|
||||
vueDebug: boolean | undefined;
|
||||
__SLIDERS: Map<string, SwiperSlider>,
|
||||
__SYSTEM: {
|
||||
_asset: Record<string, string>;
|
||||
_locale: string;
|
||||
|
|
|
|||
|
|
@ -593,11 +593,11 @@
|
|||
'id' => 'siteLogo',
|
||||
'name' => 'logo',
|
||||
'width' => 1000,
|
||||
'height' => 562,
|
||||
'height' => 727,
|
||||
'model' => $siteModel ?? null,
|
||||
'helper' => __('crud.minicrud.dimensions_must_be', [
|
||||
'widthpx' => '1000px',
|
||||
'heightpx' => '562px',
|
||||
'heightpx' => '727px',
|
||||
]),
|
||||
'required' => true,
|
||||
'preview' => true,
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@
|
|||
</div>
|
||||
<div class="col-12">
|
||||
<div class="d-flex justify-content-between">
|
||||
<a href="{{ route('fo.home.show') }}" title="{{ __('Retour à la page d\'accueil') }}">
|
||||
<a href="{{ url()->previous() }}" title="{{ __('Retour à la page d\'accueil') }}">
|
||||
<img class="arrow-left" src="{{ Vite::asset('resources/assets/images/misc/blue-arrow.svg') }}"
|
||||
title="{{ __('Retour à la page d\'accueil') }}" alt="{{ __('Flèche vers la gauche') }}">
|
||||
{{ __('Retour') }}
|
||||
|
|
|
|||
|
|
@ -105,23 +105,17 @@
|
|||
</div>
|
||||
@endif
|
||||
</div>
|
||||
<div class="col-12 col-lg-6 order-lg-first d-flex justify-content-center">
|
||||
<div class="col-12 col-lg-6 order-lg-first d-flex justify-content-center position-relative g-0">
|
||||
@php
|
||||
$data = [
|
||||
'wrapperClasses' => 'rounded-3 embed-map w-100 my-3',
|
||||
'coordinates' => [
|
||||
'lat' => $viewBox->lat,
|
||||
'lng' => $viewBox->lng,
|
||||
],
|
||||
'siteModelList' => $siteModelList,
|
||||
];
|
||||
$carto = ['siteModelList' => $siteModelList];
|
||||
if (!empty($viewBox)) {
|
||||
$carto = $carto + compact('viewBox');
|
||||
}
|
||||
if (!empty($initialZoom)) {
|
||||
$carto['initialZoom'] = $initialZoom;
|
||||
}
|
||||
@endphp
|
||||
<div class="leaflet-map-vue w-100" data-json='@json($data)'></div>
|
||||
{{-- FIXME: Quelles coordonnées pour la map ? --}}
|
||||
{{-- <iframe class="rounded-3 embed-map w-100 my-3"
|
||||
src="https://www.google.com/maps/embed?pb=!1m18!1m12!1m3!1d10661.469000249905!2d-0.7577479264599797!3d48.083855231712434!2m3!1f0!2f0!3f0!3m2!1i1024!2i768!4f13.1!3m3!1m2!1s0x4809013bc7a7e43f%3A0xe01d7907f663610d!2sSNV%20Laval!5e0!3m2!1sfr!2sfr!4v1709025460315!5m2!1sfr!2sfr"
|
||||
title="{{ __('Carte de nos sites') }}" style="border:0;" allowfullscreen="" loading="lazy"
|
||||
referrerpolicy="no-referrer-when-downgrade"></iframe> --}}
|
||||
@include('fo.partials.carte', $carto)
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
61
resources/views/fo/partials/carte.blade.php
Normal file
61
resources/views/fo/partials/carte.blade.php
Normal file
|
|
@ -0,0 +1,61 @@
|
|||
{{-- Carte page “on se dévoile” : Point central = Laval + rayon = 100 km --}}
|
||||
{{-- Carte page “site ” : Point central = le site + rayon = 50 km --}}
|
||||
{{-- FIXME: USE COORDINATES TO CENTER MAP --}}
|
||||
@php
|
||||
$data = [
|
||||
'wrapperClasses' => 'rounded-3 embed-map w-100 my-3',
|
||||
'siteModelList' => $siteModelList,
|
||||
'controlSliderId' => 'swiper-sites-map',
|
||||
];
|
||||
if (!empty($viewBox)) {
|
||||
$data['coordinates'] = [
|
||||
'lat' => $viewBox->lat,
|
||||
'lng' => $viewBox->lng,
|
||||
];
|
||||
}
|
||||
if (!empty($initialZoom)) {
|
||||
$data['initialZoom'] = $initialZoom;
|
||||
}
|
||||
$colors = ['quint', 'secondary', 'sixt', 'quad'];
|
||||
@endphp
|
||||
<div class="leaflet-map-vue w-100 z-1" data-json='@json($data)'></div>
|
||||
<div class="swiper w-100 z-2 swiper-sites-map position-absolute bottom-0 mb-4 px-2 pt-2" id="swiper-sites-map">
|
||||
<div class="swiper-wrapper h-fit">
|
||||
@foreach ($siteModelList as $index => $siteModel)
|
||||
<div class="swiper-slide position-relative">
|
||||
<div
|
||||
class="d-flex map-site-widget justify-content-center align-items-stretch text-bg-white rounded-4 border-primary border-1 flex-row overflow-hidden border p-2">
|
||||
<div class="d-flex align-items-center justify-content-center">
|
||||
<img class="rounded-3" src="{{ asset(resize($siteModel->picture_1, 'cartoPicture')) }}"
|
||||
title="{{ $siteModel->picture_1_title }}" alt="{{ $siteModel->picture_1_alt }}">
|
||||
</div>
|
||||
<div class="flex-grow-1 d-flex flex-column ps-3">
|
||||
<div class="h4 text-uppercase fw-bold text-primary">{{ Str::limit($siteModel->name, 25, '...') }}</div>
|
||||
<div class="ck-content text-primary py-1">{{ Str::limit(strip_tags($siteModel->description), 150, '...') }}
|
||||
</div>
|
||||
<div class="flex-grow-1 d-flex justify-content-between align-items-end mt-2 flex-row pb-2">
|
||||
<span class="text-primary d-inline-block">
|
||||
<i class="fa-solid fa-users me-2"></i>
|
||||
<span>{{ $siteModel->employees }}</span>
|
||||
</span>
|
||||
<a class="text-bg-{{ $colors[$index % count($colors)] }} carto-link p-3"
|
||||
href="{{ route('fo.sites.show', $siteModel) }}" alt="{{ __('Voir la page du site') }}">
|
||||
<i class="fa fa-plus"></i>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@endforeach
|
||||
@push('styles')
|
||||
<style nonce="{{ $nonce }}">
|
||||
.carto-link {
|
||||
position: relative;
|
||||
bottom: -1.1rem;
|
||||
border-radius: 1rem 0 0 0;
|
||||
right: -.5rem;
|
||||
}
|
||||
</style>
|
||||
@endpush
|
||||
</div>
|
||||
</div>
|
||||
Loading…
Add table
Reference in a new issue