From fde3bd94743b4ab64276aafe2c71b81b77615ba8 Mon Sep 17 00:00:00 2001 From: Florence Randaxhe <43472197+FlorenceRandaxhe@users.noreply.github.com> Date: Thu, 21 Aug 2025 17:29:53 +0200 Subject: [PATCH 1/4] added video component --- components/video/Component.php | 33 +++++++++++++ components/video/Layout.php | 73 +++++++++++++++++++++++++++++ components/video/js.js | 69 +++++++++++++++++++++++++++ components/video/style.scss | 52 ++++++++++++++++++++ components/video/view.blade.php | 16 +++++++ src/Components/Publishers/Video.php | 65 +++++++++++++++++++++++++ 6 files changed, 308 insertions(+) create mode 100644 components/video/Component.php create mode 100644 components/video/Layout.php create mode 100644 components/video/js.js create mode 100644 components/video/style.scss create mode 100644 components/video/view.blade.php create mode 100644 src/Components/Publishers/Video.php diff --git a/components/video/Component.php b/components/video/Component.php new file mode 100644 index 0000000..f64ca38 --- /dev/null +++ b/components/video/Component.php @@ -0,0 +1,33 @@ +image = $image; + $this->videoId = $videoId; + $this->caption = $caption; + } + + /** + * Get the view / contents that represent the component. + */ + public function render(): View|Closure|string + { + return view('components.video'); + } +} diff --git a/components/video/Layout.php b/components/video/Layout.php new file mode 100644 index 0000000..7d17cf1 --- /dev/null +++ b/components/video/Layout.php @@ -0,0 +1,73 @@ +fields([ + HikerImage::make('Cover image', 'image') + ->rules('required') + ->disk('public'), + + Text::make('YouTube identifier', 'videoId') + ->rules('required') + ->help('The YouTube identifier is the set of characters following the "watch?v=" in the video url. Ex: in the link https://www.youtube.com/watch?v=A6AxD9bUk1o, the identifier is A6AxD9bUk1o.'), + + Text::make('Caption', 'caption') + ->help('Optionnal.'), + ]), + ]; + } + + /** + * The layout's display components + */ + public function display(): array + { + return [ + DataList::make() + ->row('YouTube identifier', TextComponent::make($this->videoId)) + ->row('Image', ImageComponent::make(Storage::url($this->image))->aspectRatio('16/9')) + ->row('Caption', TextComponent::make($this->caption)) + ->row('Alternative text', TextComponent::make($this->alt)), + ]; + } + + /** + * Extract the values from the bag to store them in the database. + */ + public function fillAttributes(Baggage $bag): array + { + return $bag->only(['image', 'alt', 'caption', 'videoId']); + } +} diff --git a/components/video/js.js b/components/video/js.js new file mode 100644 index 0000000..443d56f --- /dev/null +++ b/components/video/js.js @@ -0,0 +1,69 @@ +export default class Video { + static selector = ".video"; + + constructor(el) { + this.el = el; + this.getElements(); + this.setEvents(); + this.player = null; + this.playerReady = false; + + this.initIframe(); + } + + getElements() { + this.overlay = this.el.querySelector(".video__overlay-container"); + this.playButton = this.el.querySelector(".video .button"); + this.videoIframe = this.el.querySelector(".video__iframe"); + } + + setEvents() { + this.playButton.addEventListener("click", (e) => { + e.preventDefault(); + this.toggleVideo(); + }); + } + + initIframe() { + const tag = document.createElement("script"); + tag.src = "https://www.youtube.com/iframe_api"; + const firstScriptTag = document.getElementsByTagName("script")[0]; + firstScriptTag.parentNode.insertBefore(tag, firstScriptTag); + } + + loadIframe() { + this.player = new YT.Player("player", { + height: "360", + width: "640", + videoId: this.el.dataset.videoId, + events: { + onReady: this.onPlayerReady, + onStateChange: this.onPlayerStateChange, + }, + }); + } + + toggleVideo() { + if (!this.player || !this.playerReady) return; + + this.overlay.classList.add("video__overlay-container--playing"); + + this.player.playVideo(); + } + + onPlayerReady = (event) => { + this.playerReady = true; + }; + + onPlayerStateChange = (event) => { + if (event.data === YT.PlayerState.ENDED) { + this.overlay.classList.remove("video__overlay-container--playing"); + } + }; +} + +function onYouTubeIframeAPIReady() { + window.app.pluton.call(".video", "loadIframe"); +} + +window.onYouTubeIframeAPIReady = onYouTubeIframeAPIReady; diff --git a/components/video/style.scss b/components/video/style.scss new file mode 100644 index 0000000..9f4a9c5 --- /dev/null +++ b/components/video/style.scss @@ -0,0 +1,52 @@ +.video { + margin: rem(54) 0; + + &__container { + position: relative; + } + + &__iframe-container { + @include respVideoContainer(12, 12); + } + + &__overlay-container { + position: absolute; + z-index: 10; + width: 100%; + padding-bottom: 56.25%; + height: 0; + transition: opacity 1s; + visibility: visible; + opacity: 1; + + &--playing { + opacity: 0; + transition: opacity 1s, visibility 0s 1s; + visibility: hidden; + } + } + + + &__overlay, + &__btn { + position: absolute; + display: grid; + align-items: center; + justify-items: center; + @include icon("elipse"); + } + + &__overlay { + background-size: cover; + background-position: center; + width: 100%; + height: 100%; + @include cover(); + } + + &__caption { + font-size: rem(12); + line-height: 130%; + margin-top: rem(8); + } +} diff --git a/components/video/view.blade.php b/components/video/view.blade.php new file mode 100644 index 0000000..3e5e00a --- /dev/null +++ b/components/video/view.blade.php @@ -0,0 +1,16 @@ +
+
+
+
+ +
+
+
+
+
+
+ @if($caption) +

{{ $caption }}

+ @endif +
diff --git a/src/Components/Publishers/Video.php b/src/Components/Publishers/Video.php new file mode 100644 index 0000000..2d0469e --- /dev/null +++ b/src/Components/Publishers/Video.php @@ -0,0 +1,65 @@ +`"; + } +} From dc1bd52424cdd37c7f08e59441512ec363f49c4c Mon Sep 17 00:00:00 2001 From: Florence Randaxhe <43472197+FlorenceRandaxhe@users.noreply.github.com> Date: Mon, 25 Aug 2025 10:55:02 +0200 Subject: [PATCH 2/4] updated video component --- components/video/Component.php | 1 - components/video/Layout.php | 5 ++--- components/video/js.js | 2 +- components/video/style.scss | 13 ++++++++++--- components/video/view.blade.php | 5 ++--- 5 files changed, 15 insertions(+), 11 deletions(-) diff --git a/components/video/Component.php b/components/video/Component.php index f64ca38..9f651fb 100644 --- a/components/video/Component.php +++ b/components/video/Component.php @@ -12,7 +12,6 @@ class Video extends Component public string $videoId; public ?string $caption = null; - /** * Create a new component instance. */ diff --git a/components/video/Layout.php b/components/video/Layout.php index 7d17cf1..d55f3a4 100644 --- a/components/video/Layout.php +++ b/components/video/Layout.php @@ -56,10 +56,9 @@ public function display(): array { return [ DataList::make() - ->row('YouTube identifier', TextComponent::make($this->videoId)) ->row('Image', ImageComponent::make(Storage::url($this->image))->aspectRatio('16/9')) + ->row('YouTube identifier', TextComponent::make($this->videoId)) ->row('Caption', TextComponent::make($this->caption)) - ->row('Alternative text', TextComponent::make($this->alt)), ]; } @@ -68,6 +67,6 @@ public function display(): array */ public function fillAttributes(Baggage $bag): array { - return $bag->only(['image', 'alt', 'caption', 'videoId']); + return $bag->only(['image', 'caption', 'videoId']); } } diff --git a/components/video/js.js b/components/video/js.js index 443d56f..28f19f6 100644 --- a/components/video/js.js +++ b/components/video/js.js @@ -13,7 +13,7 @@ export default class Video { getElements() { this.overlay = this.el.querySelector(".video__overlay-container"); - this.playButton = this.el.querySelector(".video .button"); + this.playButton = this.el.querySelector(".video .icon-button"); this.videoIframe = this.el.querySelector(".video__iframe"); } diff --git a/components/video/style.scss b/components/video/style.scss index 9f4a9c5..5946795 100644 --- a/components/video/style.scss +++ b/components/video/style.scss @@ -1,5 +1,6 @@ .video { - margin: rem(54) 0; + margin: 0 auto; + width: col(6, 12); &__container { position: relative; @@ -26,14 +27,12 @@ } } - &__overlay, &__btn { position: absolute; display: grid; align-items: center; justify-items: center; - @include icon("elipse"); } &__overlay { @@ -49,4 +48,12 @@ line-height: 130%; margin-top: rem(8); } + + @include mq($until: l) { + width: col(10, 12); + } + + @include mq($until: s) { + width: auto; + } } diff --git a/components/video/view.blade.php b/components/video/view.blade.php index 3e5e00a..5861e0f 100644 --- a/components/video/view.blade.php +++ b/components/video/view.blade.php @@ -1,9 +1,8 @@
-
- +
+ Click me
From c61be1762558ce107ce8cb1fae0f0c18c820c6d8 Mon Sep 17 00:00:00 2001 From: Florence Randaxhe <43472197+FlorenceRandaxhe@users.noreply.github.com> Date: Mon, 25 Aug 2025 11:21:59 +0200 Subject: [PATCH 3/4] Update style.scss --- components/video/style.scss | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/components/video/style.scss b/components/video/style.scss index 5946795..d181490 100644 --- a/components/video/style.scss +++ b/components/video/style.scss @@ -1,5 +1,5 @@ .video { - margin: 0 auto; + margin: rem(32) auto; width: col(6, 12); &__container { @@ -46,7 +46,7 @@ &__caption { font-size: rem(12); line-height: 130%; - margin-top: rem(8); + margin-top: rem(12); } @include mq($until: l) { From 1b6626ff242686f4b1c1391c62aa195c9ae1ba6f Mon Sep 17 00:00:00 2001 From: Florence Randaxhe <43472197+FlorenceRandaxhe@users.noreply.github.com> Date: Tue, 26 Aug 2025 14:57:37 +0200 Subject: [PATCH 4/4] updated thumb name --- components/video/Component.php | 6 +++--- components/video/Layout.php | 6 +++--- components/video/view.blade.php | 2 +- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/components/video/Component.php b/components/video/Component.php index 9f651fb..3184eb9 100644 --- a/components/video/Component.php +++ b/components/video/Component.php @@ -8,16 +8,16 @@ class Video extends Component { - public string $image; + public string $thumb; public string $videoId; public ?string $caption = null; /** * Create a new component instance. */ - public function __construct(string $image, string $videoId, string $caption = null) + public function __construct(string $thumb, string $videoId, string $caption = null) { - $this->image = $image; + $this->thumb = $thumb; $this->videoId = $videoId; $this->caption = $caption; } diff --git a/components/video/Layout.php b/components/video/Layout.php index d55f3a4..9e246e5 100644 --- a/components/video/Layout.php +++ b/components/video/Layout.php @@ -35,7 +35,7 @@ public function form(Baggage $bag): array return [ Step::make(static::label(), 'edit_video_layout') ->fields([ - HikerImage::make('Cover image', 'image') + HikerImage::make('Cover image', 'thumb') ->rules('required') ->disk('public'), @@ -56,7 +56,7 @@ public function display(): array { return [ DataList::make() - ->row('Image', ImageComponent::make(Storage::url($this->image))->aspectRatio('16/9')) + ->row('Cover image', ImageComponent::make(Storage::url($this->thumb))->aspectRatio('16/9')) ->row('YouTube identifier', TextComponent::make($this->videoId)) ->row('Caption', TextComponent::make($this->caption)) ]; @@ -67,6 +67,6 @@ public function display(): array */ public function fillAttributes(Baggage $bag): array { - return $bag->only(['image', 'caption', 'videoId']); + return $bag->only(['thumb', 'caption', 'videoId']); } } diff --git a/components/video/view.blade.php b/components/video/view.blade.php index 5861e0f..bda8b54 100644 --- a/components/video/view.blade.php +++ b/components/video/view.blade.php @@ -1,7 +1,7 @@
-
+
Click me