diff --git a/pgml-dashboard/src/components/cards/marketing/mod.rs b/pgml-dashboard/src/components/cards/marketing/mod.rs new file mode 100644 index 000000000..1864f5280 --- /dev/null +++ b/pgml-dashboard/src/components/cards/marketing/mod.rs @@ -0,0 +1,10 @@ +// This file is automatically generated. +// You shouldn't modify it manually. + +// src/components/cards/marketing/slider +pub mod slider; +pub use slider::Slider; + +// src/components/cards/marketing/twitter_testimonial +pub mod twitter_testimonial; +pub use twitter_testimonial::TwitterTestimonial; diff --git a/pgml-dashboard/src/components/cards/marketing/slider/mod.rs b/pgml-dashboard/src/components/cards/marketing/slider/mod.rs new file mode 100644 index 000000000..a7b7b380b --- /dev/null +++ b/pgml-dashboard/src/components/cards/marketing/slider/mod.rs @@ -0,0 +1,56 @@ +use pgml_components::component; +use sailfish::TemplateOnce; + +#[derive(TemplateOnce, Default, Clone)] +#[template(path = "cards/marketing/slider/template.html")] +pub struct Slider { + title: String, + link: String, + image: String, + bullets: Vec, + state: String, +} + +impl Slider { + pub fn new() -> Slider { + Slider { + title: String::new(), + link: String::new(), + image: String::new(), + bullets: Vec::new(), + state: String::new(), + } + } + + pub fn title(mut self, title: &str) -> Self { + self.title = title.to_string(); + self + } + + pub fn link(mut self, link: &str) -> Self { + self.link = link.to_string(); + self + } + + pub fn image(mut self, image: &str) -> Self { + self.image = image.to_string(); + self + } + + pub fn bullets(mut self, bullets: Vec) -> Self { + self.bullets = bullets; + self + } + + pub fn active(mut self) -> Self { + self.state = String::from("active"); + self + } + + pub fn disabled(mut self) -> Self { + self.state = String::from("disabled"); + self + } +} + +component!(Slider); diff --git a/pgml-dashboard/src/components/cards/marketing/slider/slider.scss b/pgml-dashboard/src/components/cards/marketing/slider/slider.scss new file mode 100644 index 000000000..822fbcea7 --- /dev/null +++ b/pgml-dashboard/src/components/cards/marketing/slider/slider.scss @@ -0,0 +1,57 @@ +div[data-controller="cards-marketing-slider"] { + .card { + display: flex; + max-width: 440px; + padding: 38px 24px; + flex-direction: column; + align-items: flex-start; + gap: 24px; + border-radius: 20px; + transition: transform 0.3s; + + width: 440px; + height: 100%; + min-height: 550px; + background: #{$gray-700}; + + &.disabled { + transform: scale(0.9); + background: #{$gray-800} !important; + min-height: 492px; + } + } + @include media-breakpoint-down(sm) { + .card, .card.disabled { + width: 100%; + } + } + + .card-body { + gap: 24px; + } + + .link { + display: flex; + width: fit-content; + } +} + +.disabled { + div[data-controller="cards-marketing-slider"] { + .card { + transform: scale(0.9); + background: #{$gray-800} !important; + min-height: 492px; + + .card-body, .title { + color: #{$gray-300}; + } + + .link { + visibility: hidden; + } + } + } +} + + diff --git a/pgml-dashboard/src/components/cards/marketing/slider/template.html b/pgml-dashboard/src/components/cards/marketing/slider/template.html new file mode 100644 index 000000000..b9609870c --- /dev/null +++ b/pgml-dashboard/src/components/cards/marketing/slider/template.html @@ -0,0 +1,23 @@ +<% + use crate::components::icons::Checkmark; +%> +
+
+
+ feature image +
+
<%- title %>
+
    + <% for bullet in bullets {%> +
    + <%+ Checkmark::new().active() %>
    <%- bullet %>
    +
    + <% } %> +
+ <% if link.len() > 0 {%> + Learn More arrow_forward + <% } %> +
+
+
+
diff --git a/pgml-dashboard/src/components/cards/marketing/twitter_testimonial/mod.rs b/pgml-dashboard/src/components/cards/marketing/twitter_testimonial/mod.rs new file mode 100644 index 000000000..ffdb2afaf --- /dev/null +++ b/pgml-dashboard/src/components/cards/marketing/twitter_testimonial/mod.rs @@ -0,0 +1,51 @@ +use pgml_components::component; +use sailfish::TemplateOnce; + +#[derive(TemplateOnce, Default, Clone)] +#[template(path = "cards/marketing/twitter_testimonial/template.html")] +pub struct TwitterTestimonial { + statement: String, + image: String, + name: String, + handle: String, + verified: bool, +} + +impl TwitterTestimonial { + pub fn new() -> TwitterTestimonial { + TwitterTestimonial { + statement: String::from("src/components/cards/marketing/twitter_testimonial"), + image: String::new(), + name: String::new(), + handle: String::new(), + verified: false, + } + } + + pub fn statement(mut self, statement: &str) -> Self { + self.statement = statement.to_owned(); + self + } + + pub fn image(mut self, image: &str) -> Self { + self.image = image.to_owned(); + self + } + + pub fn name(mut self, name: &str) -> Self { + self.name = name.to_owned(); + self + } + + pub fn handle(mut self, handle: &str) -> Self { + self.handle = handle.to_owned(); + self + } + + pub fn verified(mut self) -> Self { + self.verified = true; + self + } +} + +component!(TwitterTestimonial); diff --git a/pgml-dashboard/src/components/cards/marketing/twitter_testimonial/template.html b/pgml-dashboard/src/components/cards/marketing/twitter_testimonial/template.html new file mode 100644 index 000000000..ebb0762a3 --- /dev/null +++ b/pgml-dashboard/src/components/cards/marketing/twitter_testimonial/template.html @@ -0,0 +1,20 @@ +<% + use crate::components::icons::Twitter as twitter_icon; + use crate::components::icons::Checkmark; +%> + +
+
+

<%- statement %>

+
+
+ <%= name %> +
+

<%- name %>

<% if verified {%><%+ Checkmark::new().twitter() %><% } %>
+

@<%- handle %>

+
+
+ <%+ twitter_icon::new() %> +
+
+
diff --git a/pgml-dashboard/src/components/cards/marketing/twitter_testimonial/twitter_testimonial.scss b/pgml-dashboard/src/components/cards/marketing/twitter_testimonial/twitter_testimonial.scss new file mode 100644 index 000000000..30459cb00 --- /dev/null +++ b/pgml-dashboard/src/components/cards/marketing/twitter_testimonial/twitter_testimonial.scss @@ -0,0 +1,6 @@ +div[data-controller="cards-marketing-twitter-testimonial"] { + .card { + padding: 32px 24px; + min-width: 288px; + } +} diff --git a/pgml-dashboard/src/components/cards/mod.rs b/pgml-dashboard/src/components/cards/mod.rs index 2c6661725..909e96cc9 100644 --- a/pgml-dashboard/src/components/cards/mod.rs +++ b/pgml-dashboard/src/components/cards/mod.rs @@ -4,6 +4,9 @@ // src/components/cards/blog pub mod blog; +// src/components/cards/marketing +pub mod marketing; + // src/components/cards/newsletter_subscribe pub mod newsletter_subscribe; pub use newsletter_subscribe::NewsletterSubscribe; diff --git a/pgml-dashboard/src/components/carousel/carousel.scss b/pgml-dashboard/src/components/carousel/carousel.scss index 9d02a3867..7b2dbd34e 100644 --- a/pgml-dashboard/src/components/carousel/carousel.scss +++ b/pgml-dashboard/src/components/carousel/carousel.scss @@ -4,45 +4,4 @@ div[data-controller="carousel"] { transition-property: margin-left; transition-duration: 700ms; } - - .carousel-indicator { - display: flex; - gap: 11px; - justify-content: center; - align-items: center; - } - - .timer-container { - width: 1rem; - height: 1rem; - background-color: #{$gray-700}; - border-radius: 1rem; - transition: width 0.25s; - } - - .timer-active { - .timer { - background-color: #00E0FF; - animation: TimerGrow 5000ms; - } - } - - .timer { - width: 1rem; - height: 1rem; - border-radius: 1rem; - background-color: #{$gray-700}; - animation-fill-mode: forwards; - } - - @keyframes TimerGrow { - from {width: 1rem;} - to {width: 4rem;} - } - - .timer-pause { - .timer { - animation-play-state: paused !important; - } - } } diff --git a/pgml-dashboard/src/components/carousel/carousel_controller.js b/pgml-dashboard/src/components/carousel/carousel_controller.js index 367a3ea49..9461ac81b 100644 --- a/pgml-dashboard/src/components/carousel/carousel_controller.js +++ b/pgml-dashboard/src/components/carousel/carousel_controller.js @@ -3,6 +3,10 @@ import { Controller } from "@hotwired/stimulus"; export default class extends Controller { static targets = ["carousel", "carouselTimer", "template"]; + static values = { + identifier: Number, + }; + initialize() { this.paused = false; this.runtime = 0; @@ -30,27 +34,20 @@ export default class extends Controller { } } - changeIndicator(current, next) { - let timers = this.carouselTimerTargets; - let currentTimer = timers[current]; - let nextTimer = timers[next]; - - if (currentTimer) { - currentTimer.classList.remove("timer-active"); - currentTimer.style.width = "1rem"; - } - if (nextTimer) { - nextTimer.style.width = "4rem"; - nextTimer.classList.add("timer-active"); - } - } - Pause() { this.paused = true; + let pause = new CustomEvent("paginatePause", { + detail: { identifier: this.identifierValue }, + }); + window.dispatchEvent(pause); } Resume() { this.paused = false; + let resume = new CustomEvent("paginateResume", { + detail: { identifier: this.identifierValue }, + }); + window.dispatchEvent(resume); } cycle() { @@ -58,22 +55,11 @@ export default class extends Controller { // maintain paused state through entire loop let paused = this.paused; - let activeTimer = document.getElementsByClassName("timer-active")[0]; - if (paused) { - if (activeTimer) { - activeTimer.classList.add("timer-pause"); - } - } else { - if (activeTimer && activeTimer.classList.contains("timer-pause")) { - activeTimer.classList.remove("timer-pause"); - } - } - if (!paused && this.runtime % 5 == 0) { let currentIndex = this.times % this.templateTargets.length; let nextIndex = (this.times + 1) % this.templateTargets.length; - this.changeIndicator(currentIndex, nextIndex); + this.changePagination(currentIndex, nextIndex); this.changeFeatured(this.templateTargets[nextIndex]); this.times++; } @@ -84,6 +70,17 @@ export default class extends Controller { }, 1000); } + changePagination(current, next) { + let event = new CustomEvent("paginateNext", { + detail: { + current: current, + next: next, + identifier: this.identifierValue, + }, + }); + window.dispatchEvent(event); + } + disconnect() { clearInterval(this.interval); } diff --git a/pgml-dashboard/src/components/carousel/template.html b/pgml-dashboard/src/components/carousel/template.html index 4228ba03e..649046589 100644 --- a/pgml-dashboard/src/components/carousel/template.html +++ b/pgml-dashboard/src/components/carousel/template.html @@ -1,4 +1,12 @@ -
+<% + use crate::components::Pagination; + let items_len = items.len(); + use rand::Rng; + let mut rng = rand::thread_rng(); + let identifier = rng.gen::(); +%> + +
<% for item in &items {%>