Closes #32 Add youtube video on Homepage
+ remove Unused video Frame + FIX Video Inlaid in Cookie Notice
This commit is contained in:
parent
f06e87daf5
commit
608629307f
11 changed files with 218 additions and 94 deletions
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
namespace App\Http\Requests\Bo\Homepage;
|
||||
|
||||
use App\Rules\IsValidYoutubeId;
|
||||
use App\Traits\Requests\HasPicture;
|
||||
use Illuminate\Foundation\Http\FormRequest;
|
||||
|
||||
|
|
@ -26,6 +27,9 @@ class UpdateHomepageRequest extends FormRequest
|
|||
*/
|
||||
protected function prepareForValidation()
|
||||
{
|
||||
$this->merge([
|
||||
'display_video' => $this->boolean('display_video')
|
||||
]);
|
||||
$this->mergePicture('picture');
|
||||
}
|
||||
|
||||
|
|
@ -44,10 +48,15 @@ class UpdateHomepageRequest extends FormRequest
|
|||
'picture_title' => 'required|string|between:3,255',
|
||||
'presentation_title' => 'required|string|between:3,255',
|
||||
'presentation_content' => 'required|string',
|
||||
'display_video' => 'present|boolean',
|
||||
'youtube_video_id' => [
|
||||
'nullable', 'required_if:display_video,true',
|
||||
new IsValidYoutubeId()
|
||||
],
|
||||
];
|
||||
return \array_merge(
|
||||
$rules,
|
||||
$this->pictureRules('picture', 640, 390, 640, 390, false),
|
||||
$this->pictureRules('picture', 640, 390, 640, 390, true, requiredIf: 'display_video,false'),
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -11,9 +11,11 @@ use Illuminate\Database\Eloquent\Model;
|
|||
* @property string $title_part1 Title part 1.
|
||||
* @property string $title_part2 Title part 2.
|
||||
* @property string $title_part3 Title part 3.
|
||||
* @property string $picture Path of the picture (640px * 390px).
|
||||
* @property string|null $picture Path of the picture (640px * 390px).
|
||||
* @property string $picture_alt Picture alt attribute.
|
||||
* @property string $picture_title Picture title attribute.
|
||||
* @property string $youtube_video_id The youtube video Id.
|
||||
* @property boolean $display_video Wether to display video or picture.
|
||||
* @property string $presentation_title Presentation title.
|
||||
* @property string $presentation_content WYSIWYG - Presentation content.
|
||||
* @property-read \Carbon\Carbon $created_at Created date.
|
||||
|
|
@ -38,6 +40,17 @@ class Homepage extends Model
|
|||
'picture_title',
|
||||
'presentation_title',
|
||||
'presentation_content',
|
||||
'youtube_video_id',
|
||||
'display_video',
|
||||
];
|
||||
|
||||
/**
|
||||
* The attributes that should be cast.
|
||||
*
|
||||
* @var string[]
|
||||
*/
|
||||
protected $casts = [
|
||||
'display_video' => 'bool'
|
||||
];
|
||||
|
||||
/**
|
||||
|
|
|
|||
33
app/Rules/IsValidYoutubeId.php
Normal file
33
app/Rules/IsValidYoutubeId.php
Normal file
|
|
@ -0,0 +1,33 @@
|
|||
<?php
|
||||
|
||||
namespace App\Rules;
|
||||
|
||||
use Illuminate\Contracts\Validation\ValidationRule;
|
||||
use Illuminate\Support\Str;
|
||||
|
||||
/**
|
||||
* Validate a youtube ID regex
|
||||
*
|
||||
* @url https://webapps.stackexchange.com/questions/54443/format-for-id-of-youtube-video
|
||||
* @package App\Rules
|
||||
*/
|
||||
class IsValidYoutubeId implements ValidationRule
|
||||
{
|
||||
/**
|
||||
* Run the validation rule.
|
||||
*
|
||||
* @param string $attribute
|
||||
* @param mixed $value
|
||||
* @param \Closure(string):\Illuminate\Translation\PotentiallyTranslatedString $fail
|
||||
* @return void
|
||||
* @phpcs:disable Generic.CodeAnalysis.UnusedFunctionParameter.FoundInImplementedInterfaceBeforeLastUsed
|
||||
* @phpcs:disable Squiz.Commenting.FunctionComment.IncorrectTypeHint
|
||||
*/
|
||||
public function validate(string $attribute, mixed $value, \Closure $fail): void
|
||||
{
|
||||
// phpcs:enable
|
||||
if (!Str::of($value)->isMatch('/[0-9A-Za-z_-]{10}[048AEIMQUYcgkosw]/')) {
|
||||
$fail(trans('validation.youtube_id'));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,43 @@
|
|||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function up(): void
|
||||
{
|
||||
Schema::table('homepages', function (Blueprint $table) {
|
||||
$table->string('picture')->nullable()->change()
|
||||
->comment('Path de l\'image de la page d\'accueil (640px * 390px)');
|
||||
$table->string('youtube_video_id')->after('picture_title')
|
||||
->nullable()
|
||||
->default(null)
|
||||
->comment('L\ídentifiant de la vidéo Youtube');
|
||||
$table->boolean('display_video')->after('youtube_video_id')
|
||||
->default(false)
|
||||
->comment('Afficher la video ou l\'image');
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function down(): void
|
||||
{
|
||||
Schema::table('homepages', function (Blueprint $table) {
|
||||
$table->string('picture')->change()
|
||||
->comment('Path de l\'image de la page d\'accueil (640px * 390px)');
|
||||
$table->dropColumn('youtube_video_id');
|
||||
$table->dropColumn('display_video');
|
||||
});
|
||||
}
|
||||
};
|
||||
|
|
@ -215,6 +215,9 @@ return [
|
|||
'year' => 'year',
|
||||
'url' => 'URL',
|
||||
],
|
||||
|
||||
'youtube_id' => ':attribute must be a valid Youtube video ID',
|
||||
|
||||
'custom' => [
|
||||
'of_the' => [
|
||||
'male' => 'of the ',
|
||||
|
|
|
|||
|
|
@ -217,6 +217,9 @@ return [
|
|||
'year' => 'année',
|
||||
'url' => 'URL',
|
||||
],
|
||||
|
||||
'youtube_id' => ':attribute doit être un ID de vidéo Youtube valide',
|
||||
|
||||
'custom' => [
|
||||
'of_the' => [
|
||||
'male' => 'du ',
|
||||
|
|
@ -287,5 +290,7 @@ return [
|
|||
'unpublish_at' => 'date de fin de publication',
|
||||
'unpublish_at' => 'date de fin de publication',
|
||||
'video_id' => 'ID de la vidéo',
|
||||
'youtube_video_id' => 'ID de la vidéo youtube',
|
||||
'display_video' => 'affichage de la vidéo',
|
||||
],
|
||||
];
|
||||
|
|
|
|||
|
|
@ -2,74 +2,6 @@ import Swiper from "swiper";
|
|||
import { Navigation } from "swiper/modules";
|
||||
|
||||
document.addEventListener("DOMContentLoaded", function () {
|
||||
// * Video frames.
|
||||
const videoFrameList = document.querySelectorAll(
|
||||
".video-frame"
|
||||
) as NodeListOf<HTMLLinkElement>;
|
||||
for (const videoLink of videoFrameList) {
|
||||
if (!videoLink.dataset.type) {
|
||||
throw new Error("Missing dataset type");
|
||||
}
|
||||
if (!videoLink.dataset.frame) {
|
||||
throw new Error("Missing dataset frame");
|
||||
}
|
||||
// @ts-ignore
|
||||
window.__CN_VIDEO = window.__CN_VIDEO ?? {};
|
||||
|
||||
const newIframe = document.createElement("iframe");
|
||||
newIframe.frameBorder = "0";
|
||||
newIframe.allow = "fullscreen";
|
||||
newIframe.width = "1920px";
|
||||
newIframe.height = "1080px";
|
||||
newIframe.setAttribute("allowfullscreen", "allowfullscreen");
|
||||
|
||||
// @ts-ignore
|
||||
const instance = new FsLightbox();
|
||||
instance.props.sources = [newIframe];
|
||||
|
||||
setTimeout(() => {
|
||||
videoLink.addEventListener("click", (e) => {
|
||||
e.preventDefault();
|
||||
|
||||
// * This comes fslightbox lib
|
||||
// @ts-ignore
|
||||
instance.open();
|
||||
setTimeout(function () {
|
||||
// @ts-ignore
|
||||
newIframe.src = window.__CN_VIDEO[videoLink.dataset.type]
|
||||
? String(videoLink.href)
|
||||
: String(videoLink.dataset.frame);
|
||||
}, 50);
|
||||
return false;
|
||||
});
|
||||
}, 300);
|
||||
}
|
||||
// * Video inlaid.
|
||||
const videoInlaidList = document.querySelectorAll(
|
||||
".video-inlaid"
|
||||
) as NodeListOf<HTMLLinkElement>;
|
||||
for (const videoLink of videoInlaidList) {
|
||||
if (!videoLink.getAttribute("type")) {
|
||||
throw new Error("Missing attribute type");
|
||||
}
|
||||
if (!videoLink.getAttribute("href")) {
|
||||
throw new Error("Missing attribute href");
|
||||
}
|
||||
// @ts-ignore
|
||||
if (window.__CN_VIDEO[videoLink.getAttribute("type")]) {
|
||||
videoLink.innerHTML = "";
|
||||
const newIframe = document.createElement("iframe");
|
||||
newIframe.frameBorder = "0";
|
||||
newIframe.allow = "fullscreen";
|
||||
newIframe.width = "1920px";
|
||||
newIframe.height = "1080px";
|
||||
newIframe.classList.add("w-100");
|
||||
newIframe.classList.add("h-100");
|
||||
newIframe.setAttribute("allowfullscreen", "allowfullscreen");
|
||||
newIframe.src = String(videoLink.getAttribute("href"));
|
||||
videoLink.appendChild(newIframe);
|
||||
}
|
||||
}
|
||||
// SWIPER
|
||||
const swiperConfig = {
|
||||
"swiper-homepage-news": {
|
||||
|
|
|
|||
|
|
@ -162,13 +162,67 @@
|
|||
'widthpx' => '640px',
|
||||
'heightpx' => '390px',
|
||||
]),
|
||||
'required' => true,
|
||||
'required' => false,
|
||||
'preview' => true,
|
||||
])
|
||||
</div>
|
||||
</div>
|
||||
</fieldset>
|
||||
</div>
|
||||
|
||||
{{-- YOUTUBE VIDEO ID --}}
|
||||
<div class="col-12 col-md-6 mb-3">
|
||||
<fieldset class="h-100 border p-3">
|
||||
<legend>{{ Str::ucfirst(__('validation.custom.youtube_video_id')) }}</legend>
|
||||
<div class="row">
|
||||
<div class="col-12">
|
||||
@include('bo.partials.inputs.varchar', [
|
||||
'id' => 'homepageVideoUrl',
|
||||
'label' => __(':field :inter:model', [
|
||||
'field' => Str::ucfirst(__('validation.custom.youtube_video_id')),
|
||||
'inter' => __('validation.custom.of_the.female'),
|
||||
'model' => __('models.classes.homepage'),
|
||||
]),
|
||||
'hasWordCounter' => true,
|
||||
'name' => 'youtube_video_id',
|
||||
'required' => false,
|
||||
'model' => $homepageModel ?? null,
|
||||
'helper' =>
|
||||
__('validation.between.string', [
|
||||
'attribute' => __(':field :inter:model', [
|
||||
'field' => __('validation.custom.youtube_video_id'),
|
||||
'inter' => __('validation.custom.of_the.female'),
|
||||
'model' => __('models.classes.homepage'),
|
||||
]),
|
||||
'min' => 11,
|
||||
'max' => 12,
|
||||
]) . __("Doit être l\'id de la vidéo Youtube eg:\u{00A0}(MH19CxWqluY)."),
|
||||
'placeholder' => 'MH19CxWqluY',
|
||||
])
|
||||
</div>
|
||||
</div>
|
||||
</fieldset>
|
||||
</div>
|
||||
|
||||
{{-- DISPLAY VIDEO --}}
|
||||
<div class="col-12 col-md-6 mb-3">
|
||||
<fieldset class="h-100 border p-3">
|
||||
<legend>{{ Str::ucfirst(__('validation.custom.display_video')) }}</legend>
|
||||
<div class="row">
|
||||
<div class="col-12">
|
||||
@include('bo.partials.inputs.tinyint-boolean', [
|
||||
'id' => 'homepageDisplayVideo',
|
||||
'name' => 'display_video',
|
||||
'model' => $homepageModel ?? null,
|
||||
'label' => __('validation.custom.display_video'),
|
||||
'label' => __('crud.minicrud.visibility_label'),
|
||||
'helper' => __('crud.minicrud.visibility_helper'),
|
||||
])
|
||||
</div>
|
||||
</div>
|
||||
</fieldset>
|
||||
</div>
|
||||
|
||||
{{-- PRESENTATION TITLE --}}
|
||||
<div class="col-12 col-md-6 mb-3">
|
||||
<fieldset class="h-100 border p-3">
|
||||
|
|
|
|||
|
|
@ -1,14 +0,0 @@
|
|||
@php $uniqueID = uniqid(); @endphp
|
||||
<a
|
||||
class="video-frame relative w-full"
|
||||
href="{{ $link }}"
|
||||
data-type="{{ $type }}"
|
||||
data-frame="{{ route('front.frame', ['frame' => $type]) }}"
|
||||
target="_blank">
|
||||
<img
|
||||
class="relative w-full"
|
||||
src="{{ $picture }}"
|
||||
alt="{{ $alt }}"
|
||||
title="{{ $title }}">
|
||||
<i class="youtube-play-button absolute top-50 left-50 fa-regular fa-circle-play"></i>
|
||||
</a>
|
||||
|
|
@ -9,8 +9,8 @@
|
|||
<section class="homepage">
|
||||
<!-- TITLE CARD -->
|
||||
<div class="title-card container-fluid my-xl-5 my-0 px-4">
|
||||
<div class="d-flex flex-column flex-xl-row justify-content-center align-items-center w-100 flex-wrap">
|
||||
<div class="bg-agis-yellow p-xl-5 p-4 px-5">
|
||||
<div class="row justify-content-center align-items-center">
|
||||
<div class="col-12 col-md-6 col-lg-5 col-xl-4 bg-agis-yellow p-xl-5 g-0 p-4 px-5">
|
||||
<h1 class="my-2 text-center">
|
||||
<p class="fs-title-xxl f-sheldon text-uppercase m-0">{{ $homepageModel->title_part1 }}</p>
|
||||
<span class="divide d-block w-100 mt-xl-3 my-2"></span>
|
||||
|
|
@ -19,9 +19,22 @@
|
|||
<p class="fs-title-l f-rufina fw-semibold m-0">{{ Str::of($homepageModel->title_part3)->ucFirst()->value() }}</p>
|
||||
</h1>
|
||||
</div>
|
||||
<div class="m-xl-0 my-4 mb-5">
|
||||
<img src="{{ asset($homepageModel->picture) }}" title="{{ $homepageModel->picture_title }}"
|
||||
alt="{{ $homepageModel->picture_alt }}">
|
||||
<div class="col-12 col-md-6 col-lg-5 col-xl-4 m-xl-0 g-0 my-4">
|
||||
@if ($homepageModel->display_video)
|
||||
<div class="ratio ratio-16x9 y-video">
|
||||
<div class="video-inlaid" type="youtube"
|
||||
href="https://www.youtube.com/embed/{{ $homepageModel->youtube_video_id }}">
|
||||
<a class="cn-cookie-link" id="youtube-warning" href="" rel="nofollow">
|
||||
<strong class="text-underline text-bold text-normal text-danger">
|
||||
{{ __('cookie-notice.custom.youtube.warning') }}
|
||||
</strong>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
@else
|
||||
<img class="img-fluid" src="{{ asset($homepageModel->picture) }}" title="{{ $homepageModel->picture_title }}"
|
||||
alt="{{ $homepageModel->picture_alt }}">
|
||||
@endif
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
41
resources/views/vendor/cn-cookies.blade.php
vendored
41
resources/views/vendor/cn-cookies.blade.php
vendored
|
|
@ -43,14 +43,47 @@ $cookies['youtube'] = [
|
|||
|
||||
$cookies['youtube']['script'] = <<<SCRIPT
|
||||
function () {
|
||||
window.__CN_VIDEO = window.__CN_VIDEO ?? {};
|
||||
window.__CN_VIDEO.youtube = true;
|
||||
// * Video inlaid.
|
||||
const videoInlaidList = document.querySelectorAll(".video-inlaid");
|
||||
for (const videoLink of videoInlaidList) {
|
||||
if (!videoLink.getAttribute("type")) {
|
||||
throw new Error("Missing attribute type");
|
||||
}
|
||||
if (!videoLink.getAttribute("href")) {
|
||||
throw new Error("Missing attribute href");
|
||||
}
|
||||
videoLink.innerHTML = "";
|
||||
const newIframe = document.createElement("iframe");
|
||||
newIframe.frameBorder = "0";
|
||||
newIframe.allow = "fullscreen";
|
||||
newIframe.width = "1920px";
|
||||
newIframe.height = "1080px";
|
||||
newIframe.classList.add("w-100");
|
||||
newIframe.classList.add("h-100");
|
||||
newIframe.setAttribute("allowfullscreen", "allowfullscreen");
|
||||
newIframe.src = String(videoLink.getAttribute("href"));
|
||||
videoLink.appendChild(newIframe);
|
||||
}
|
||||
}
|
||||
SCRIPT;
|
||||
$cookies['youtube']['fallback'] = <<<FALLBACK
|
||||
function () {
|
||||
window.__CN_VIDEO = window.__CN_VIDEO ?? {};
|
||||
window.__CN_VIDEO.youtube = false;
|
||||
// * Video inlaid.
|
||||
const videoInlaidList = document.querySelectorAll(".video-inlaid");
|
||||
for (const item of videoInlaidList) {
|
||||
let a = document.createElement('a');
|
||||
a.innerText = 'Autoriser';
|
||||
a.classList.add('cn-cookie-link');
|
||||
a.setAttribute('role', 'button');
|
||||
a.onclick = function () {
|
||||
WebCookieNotice.openCookieModalToCookiePage();
|
||||
};
|
||||
let e = document.createElement('p');
|
||||
e.innerHTML = 'Youtube est désactivé. ';
|
||||
item.innerHTML = "";
|
||||
e.appendChild(a);
|
||||
item.appendChild(e);
|
||||
}
|
||||
}
|
||||
FALLBACK;
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue