diff --git a/src/static_view.rs b/src/static_view.rs index 41e3d63c4c22280990e120e3bc35a6fb5ccb1b1d..6e6da6692bb3ef74230eaa81aed05b6c070813ed 100644 --- a/src/static_view.rs +++ b/src/static_view.rs @@ -67,7 +67,7 @@ pub fn create_static_view(app_state: &AppState, article: &Article) -> Result<(), <meta name='image' content='{art_image_uri}'/> <meta name='description' content='{description}'> <link rel='icon' type='image/svg+xml' href='/favicon.svg' /> - <title>{title}</title> + <title>Kuadrado Software | {title}</title> <link href='/style/style.css' rel='stylesheet' /> <script type='application/json' id='article-json'>{art_json}</script> </head> diff --git a/website/src/article-vew-components/software-article.js b/website/src/article-vew-components/software-article.js new file mode 100644 index 0000000000000000000000000000000000000000..977964798571ba4a8a915e7ffe737ea2363c2ca5 --- /dev/null +++ b/website/src/article-vew-components/software-article.js @@ -0,0 +1,96 @@ +"use strict"; + +const ImageCarousel = require("../generic-components/image-carousel"); +const translator = require("ks-cheap-translator"); +const { images_url } = require("../../constants"); +const { getArticleBody } = require("../lib/article-utils"); +const t = translator.trad.bind(translator); + + +class SoftwareArticle { + constructor(data) { + this.data = data; + this.body = getArticleBody(data.body); + } + + render() { + const { + images, + title, + subtitle, + details, + } = this.data; + + const trad_ready = Object.keys(translator.translations).length > 0; + + const logo = images[0]; + const screens = [...images]; + screens.shift(); + + return { + tag: "article", + class: "software-article page-contents-center", + contents: [ + { + tag: "img", + src: `${images_url}/${logo}` + }, + { + tag: "h1", + contents: title, + class: "header-text h1", + }, + { + tag: "h2", + contents: subtitle, + class: "header-text h2", + }, + { + tag: "div", + id: "article-contents", + contents: [ + { + tag: "div", + id: "article-body", + contents: [ + { + tag: "p", + contents: this.body + } + ], + }, + trad_ready && screens.length > 0 && new ImageCarousel({ images: screens.map(img => `${images_url}/${img}`) }).render(), + details.length > 0 && { + tag: "div", + class: "article-details", + contents: [ + { + tag: "ul", + class: "details-list", + contents: details.map(detail => { + return { + tag: "li", + class: "detail", + contents: [ + { tag: "label", contents: detail.label }, + { + tag: "div", + class: "detail-value", + contents: detail.value, + }, + ], + }; + }), + }, + ], + }, + ] + }, + + + ], + }; + } +} + +module.exports = SoftwareArticle; diff --git a/website/src/article-view.js b/website/src/article-view.js index 3ea0a59e1716c80d7c8e63e540221f895542ee05..923f9a82a493936139a696272083c35f4d294840 100644 --- a/website/src/article-view.js +++ b/website/src/article-view.js @@ -1,6 +1,7 @@ "use strict"; const GameArticle = require("./article-vew-components/game-article"); +const SoftwareArticle = require("./article-vew-components/software-article"); const WebPage = require("./lib/web-page"); const runPage = require("./run-page"); @@ -14,10 +15,10 @@ class ArticlePage extends WebPage { switch (this.article.category) { case "games": return new GameArticle(this.article).render(); - case "education": - return; - case "software": - return; + // case "education": + // return; + case "software-development": + return new SoftwareArticle(this.article).render(); } } diff --git a/website/src/article-view.scss b/website/src/article-view.scss index 767cb8bd0201f9f7c92f388c0705156a0eed8051..73fc23dd6e9f96c5c6b6dbe7e0627ecb5b46ede3 100644 --- a/website/src/article-view.scss +++ b/website/src/article-view.scss @@ -2,9 +2,9 @@ position: relative; article { - background-color: black; - &.game-article { + background-color: black; + #article-banner { width: 100%; height: 500px; diff --git a/website/src/lib/article-utils.js b/website/src/lib/article-utils.js index 1dcb6c967438cd13b46d507ba28fc2431f255670..66cc5539f5606ffe7e13e325d9ab67f408481b0f 100644 --- a/website/src/lib/article-utils.js +++ b/website/src/lib/article-utils.js @@ -18,9 +18,17 @@ function sortArticles(articles, byField, mode = "desc") { return articles.sort((a, b) => mode === "desc" ? a[byField] > b[byField] : a[byField] < b[byField]) } +function renderPlaceholders(n) { + return Array.from({ length: n }).map(() => { + return { tag: "div", class: "thumb-placeholder" } + }); +} + + module.exports = { loadArticles, getArticleBody, getArticleDate, sortArticles, + renderPlaceholders, }; diff --git a/website/src/pages/education/components/edu-articles.js b/website/src/pages/education/components/edu-articles.js index 0b79891fa10946c02df039882bf681bdebd581a5..c3b41b39069d483540c4c227308edc230e3bd729 100644 --- a/website/src/pages/education/components/edu-articles.js +++ b/website/src/pages/education/components/edu-articles.js @@ -1,5 +1,5 @@ "use strict"; -const { loadArticles, sortArticles } = require("../../../lib/article-utils"); +const { loadArticles, sortArticles, renderPlaceholders } = require("../../../lib/article-utils"); const translator = require("ks-cheap-translator"); const t = translator.trad.bind(translator); const EduArticle = require("./edu-article"); @@ -27,14 +27,6 @@ class EduArticles { }); } - renderPlaceholder() { - return { - tag: "article", - class: "placeholder", - contents: [{ tag: "div" }, { tag: "div" }, { tag: "div" }, { tag: "div" }], - }; - } - refresh() { obj2htm.subRender(this.render(), document.getElementById(this.id), { mode: "replace", @@ -52,7 +44,7 @@ class EduArticles { ? articles.map(article => new EduArticle({ ...article }).render()) : loaded && articles.length === 0 ? [ { tag: "p", contents: t("Rien de prévu pour le moment") } - ] : [this.renderPlaceholder()], + ] : renderPlaceholders(2), }; } } diff --git a/website/src/pages/education/education.scss b/website/src/pages/education/education.scss index f9dc3f968c596cae7886580b7b479314df8b6570..42bf4faa82525cac75bfcc5a4f6c2deb38fa31d2 100644 --- a/website/src/pages/education/education.scss +++ b/website/src/pages/education/education.scss @@ -4,6 +4,7 @@ font-size: 30px; } } + .title-banner { display: flex; justify-content: flex-end; @@ -14,6 +15,7 @@ background-size: cover; background-repeat: no-repeat; background-position: center; + h2 { color: white; font-size: 2.5em; @@ -21,11 +23,14 @@ text-shadow: 0 0 6px #0003; } } + .special-announcement { background-color: $yellow_2; + .page-contents-center { padding: 0 20px; @include flex-center; + p { color: $dark_3; font-size: 20px; @@ -43,6 +48,7 @@ align-items: center; white-space: nowrap; gap: 15px; + &::after { content: ""; display: block; @@ -57,9 +63,11 @@ gap: 50px; font-family: monospace; padding: 40px 0; + .edu-theme { display: grid; grid-template-columns: auto 1fr; + h3 { color: $blue_2; grid-row: 1; @@ -68,10 +76,12 @@ display: flex; align-items: center; } + img { width: 100%; grid-row: 1 / span 2; } + p { text-align: justify; grid-row: 2; @@ -86,6 +96,7 @@ flex-direction: column; gap: 40px; margin: 20px auto; + article.edu-article { display: grid; grid-template-columns: auto 1fr auto; @@ -101,6 +112,7 @@ height: 150px; overflow: hidden; border-radius: 100%; + img { max-width: 100%; max-height: 400px; @@ -124,6 +136,7 @@ grid-column: 2; text-align: justify; margin: 10px; + ul { list-style-type: unset; margin-left: 30px; @@ -134,10 +147,12 @@ grid-column: 3; width: 30vw; max-width: 500px; + .image-carousel { width: 100%; height: 20vw; max-height: 400px; + img { width: 100%; } @@ -150,22 +165,27 @@ @media screen and (max-width: 1050px) { grid-template-columns: auto 1fr; + .edu-art-title { grid-column: 2; } + .edu-art-image { grid-row: 1 / span 2; } + .edu-art-carousel { width: 100%; max-width: unset; grid-column: 1 / span 2; grid-row: 3; + .image-carousel { height: 40vw; max-height: 400px; } } + .edu-art-subtitle { grid-column: 2; grid-row: 2; @@ -189,35 +209,18 @@ .edu-art-subtitle { grid-column: 1 / span 2; } + .edu-art-image { width: 100px; height: 100px; grid-row: 1; } + // .edu-art-carousel { // grid-column: 1 / span 2; // } } } - - article.placeholder { - display: grid; - grid-template-columns: 200px auto; - grid-template-rows: 100px 100px 200px; - gap: 10px; - margin: 30px; - * { - background-color: $light_0; - flex: 1; - &:first-child { - // image - grid-row: 1 / span 2; - } - &:last-child { - grid-column: 1 / span 2; - } - } - } } @media screen and (max-width: 1200px) { @@ -236,6 +239,7 @@ height: auto; grid-row: 1; } + p { grid-row: 2; grid-column: 1 / span 2; @@ -244,4 +248,4 @@ } } } -} +} \ No newline at end of file diff --git a/website/src/pages/games/components/game-articles.js b/website/src/pages/games/components/game-articles.js index 4ba58ab848d998cefa73e87ad64b875bb54184c3..4f4ced68750f01f17f7ff191253eaed3fc77f927 100644 --- a/website/src/pages/games/components/game-articles.js +++ b/website/src/pages/games/components/game-articles.js @@ -1,6 +1,10 @@ "use strict"; -const { loadArticles, sortArticles } = require("../../../lib/article-utils"); +const { + loadArticles, + sortArticles, + renderPlaceholders +} = require("../../../lib/article-utils"); const GameThumb = require("./game-thumb"); const translator = require("ks-cheap-translator"); @@ -23,14 +27,6 @@ class GameArticles { .catch(e => console.log(e)); } - renderPlaceholder() { - return { - tag: "article", - class: "placeholder", - contents: [{ tag: "div" }, { tag: "div" }], - }; - } - refresh() { obj2htm.subRender(this.render(), document.getElementById(this.id), { mode: "replace", @@ -46,7 +42,7 @@ class GameArticles { contents: articles.length > 0 ? articles.map(article => new GameThumb({ ...article }).render()) - : [this.renderPlaceholder()], + : renderPlaceholders(4), }; } } diff --git a/website/src/pages/games/components/game-thumb.js b/website/src/pages/games/components/game-thumb.js index f2c31385bf7ba2f8abbb2d0531906a1b4ece4974..1ce8674e4e6327847ebdb27c094bee717b656b67 100644 --- a/website/src/pages/games/components/game-thumb.js +++ b/website/src/pages/games/components/game-thumb.js @@ -33,7 +33,6 @@ class GameThumb { class: "game-title", contents: title, }, - { tag: "strong", class: "game-subtitle", @@ -44,7 +43,7 @@ class GameThumb { class: "game-description", contents: metadata.description }, - ] + ], }, ], }; diff --git a/website/src/pages/games/games.scss b/website/src/pages/games/games.scss index d8ed283223d19c14b456988606b77fd92354ad5b..3b8777b6ad30c1ae86e994ed963f3983d63dadb4 100644 --- a/website/src/pages/games/games.scss +++ b/website/src/pages/games/games.scss @@ -5,6 +5,10 @@ grid-template-columns: 1fr 1fr; padding: 40px; + .thumb-placeholder { + height: 350px; + } + .game-thumb { min-width: 350px; overflow: hidden; diff --git a/website/src/pages/software-development/components/software-article.js b/website/src/pages/software-development/components/software-article.js deleted file mode 100644 index 71da71bf542b7ddaa11a63e026cb5308aaea34b7..0000000000000000000000000000000000000000 --- a/website/src/pages/software-development/components/software-article.js +++ /dev/null @@ -1,79 +0,0 @@ -"use strict"; - -const { images_url } = require("../../../../../admin-frontend/src/constants"); -const { getArticleBody } = require("../../../lib/article-utils"); - -class SoftwareArticle { - constructor(props) { - this.props = props; - } - - render() { - const { title, body, subtitle, images, details = [] } = this.props; - - return { - tag: "article", - class: "software-article", - typeof: "SoftwareApplication", - additionalType: "Article", - contents: [ - { - tag: "h2", - class: "software-title", - contents: title, - property: "name", - }, - { - tag: "div", class: "software-image", - contents: [ - { - tag: "img", src: `${images_url}/${images[0]}` - } - ] - }, - { - tag: "h3", - class: "software-subtitle", - contents: subtitle, - property: "alternativeHeadline", - }, - { - tag: "div", - class: "software-description", - contents: getArticleBody(body), - property: "description", - }, - details.length > 0 && { - tag: "div", - class: "article-details", - contents: [ - { - tag: "h2", - contents: "Details", - }, - { - tag: "ul", - class: "details-list", - contents: details.map(detail => { - return { - tag: "li", - class: "detail", - contents: [ - { tag: "label", contents: detail.label }, - { - tag: "div", - class: "detail-value", - contents: detail.value - }, - ], - }; - }), - }, - ], - }, - ], - }; - } -} - -module.exports = SoftwareArticle; \ No newline at end of file diff --git a/website/src/pages/software-development/components/software-articles.js b/website/src/pages/software-development/components/software-articles.js index 331c1831ce1b637ef3d49bdec81a5ccd401ac7bb..36a5a0476909284479a60079a51753a1dc417f3c 100644 --- a/website/src/pages/software-development/components/software-articles.js +++ b/website/src/pages/software-development/components/software-articles.js @@ -1,7 +1,7 @@ "use strict"; -const { loadArticles, sortArticles } = require("../../../lib/article-utils"); -const SoftwareArticle = require("./software-article"); +const { loadArticles, sortArticles, renderPlaceholders } = require("../../../lib/article-utils"); +const SoftwareThumb = require("./software-thumb"); const translator = require("ks-cheap-translator"); class SoftwareArticles { @@ -15,52 +15,27 @@ class SoftwareArticles { } loadArticles() { - loadArticles("software", translator.locale) + loadArticles("software-development", translator.locale) .then(articles => { this.state.articles = sortArticles(articles, "display_priority_index");; this.refresh(); - this.fixScroll(); }).catch(e => console.log(e)) } - - renderPlaceholder() { - return { - tag: "article", - class: "placeholder", - contents: [ - { tag: "div", class: "title" }, - { tag: "div", class: "body" }, - { tag: "div", class: "details" }, - ], - }; - } - refresh() { obj2htm.subRender(this.render(), document.getElementById(this.id), { mode: "replace", }); } - fixScroll() { - if (window.location.href.includes("#")) { - window.scrollTo( - 0, - document.getElementById(window.location.href.match(/#.+/)[0].replace("#", "")) - .offsetTop - ); - } - } - render() { const { articles } = this.state; return { tag: "section", class: "software-articles page-contents-center", id: this.id, - contents: - articles.length > 0 - ? articles.map(article => new SoftwareArticle({ ...article }).render()) - : [this.renderPlaceholder()], + contents: articles.length > 0 + ? articles.map(article => new SoftwareThumb({ ...article }).render()) + : renderPlaceholders(4), }; } } diff --git a/website/src/pages/software-development/components/software-thumb.js b/website/src/pages/software-development/components/software-thumb.js new file mode 100644 index 0000000000000000000000000000000000000000..04fbb425bdfec6cbed7976d4a38d1213fad3344b --- /dev/null +++ b/website/src/pages/software-development/components/software-thumb.js @@ -0,0 +1,48 @@ +"use strict"; + +const { images_url } = require("../../../../../admin-frontend/src/constants"); + +class SoftwareThumb { + constructor(props) { + this.props = props; + } + + render() { + const { + title, + subtitle, + images, + metadata, + } = this.props; + + return { + tag: metadata.view_uri ? "a" : "div", + href: metadata.view_uri, + target: "_blank", + class: "software-thumb", + contents: [ + { + tag: "div", + class: "software-image", + contents: [ + { + tag: "img", src: `${images_url}/${images[0]}` + } + ] + }, + { + tag: "strong", + class: "software-title", + contents: title, + }, + { + tag: "span", + class: "software-subtitle", + contents: subtitle, + } + ], + }; + } +} + +module.exports = SoftwareThumb; \ No newline at end of file diff --git a/website/src/pages/software-development/software-development.scss b/website/src/pages/software-development/software-development.scss index 5bb087a404f73952c74c52f5de90ac79b30ae23a..1f2ba1b675fa43c0e1d84bd8e73fd41617a329aa 100644 --- a/website/src/pages/software-development/software-development.scss +++ b/website/src/pages/software-development/software-development.scss @@ -1,29 +1,33 @@ #software-page { .software-articles { - margin: 20px auto 50px; - article.software-article { + display: flex; + flex-wrap: wrap; + justify-content: center; + gap: 20px; + padding: 40px; + + .thumb-placeholder { + height: 300px; + width: 300px; + } + + .software-thumb { + width: 350px; display: grid; grid-template-columns: auto 1fr; - margin: 0 0 50px; - gap: 10px 30px; + gap: 20px; + padding: 20px; + border: 1px solid #eee; .software-title { grid-column: 2; - color: $light_2; - margin: 0; - padding: 10px; - } - - .software-subtitle { - grid-column: 2; - margin: 10px; + font-size: 20px; color: $medium_grey; } - .software-description { + .software-subtitle { grid-column: 2; - text-align: justify; - margin: 10px; + font-size: 17px; } .software-image { @@ -32,49 +36,40 @@ grid-column: 1; grid-row: 1 / span 3; @include flex-center; - width: 200px; - height: 200px; + width: 120px; + height: 120px; overflow: hidden; border-radius: 100%; + img { max-width: 100%; max-height: 400px; } } - @media screen and (max-width: $screen_l) { - .software-title { - display: flex; - align-items: center; - } - .software-subtitle, - .software-description { - grid-column: 1 / span 2; - } + transition: transform 0.3s; + + &:hover { + transform: scale(1.03); + } + } + + @media screen and (max-width: 1100px) { + .software-thumb { + width: 500px; + .software-image { - width: 100px; - height: 100px; - grid-row: 1; + width: 180px; + height: 180px; } } } - article.placeholder { - display: flex; - flex-direction: column; - gap: 10px; - margin: 30px; - * { - background-color: $light_0; - } - .title { - height: 60px; - } - .body { - height: 400px; - } - .details { - height: 200px; + + + @media screen and (max-width: 900px) { + .software-thumb { + width: 100%; } } } -} +} \ No newline at end of file diff --git a/website/src/style.scss b/website/src/style.scss index 2998612270742b2aeab06d856d23e63b05e5550c..a4a12a2e05f570b754b8b29f70641d736bcbf8e6 100644 --- a/website/src/style.scss +++ b/website/src/style.scss @@ -72,6 +72,10 @@ main { align-items: center; min-height: 100vh; + .thumb-placeholder { + background-color: $light_0; + } + .warning-banner { background: url("/assets/images/wallpaper_warning.svg"); width: 100%; @@ -461,40 +465,6 @@ main { @include page-contents-center; } - // .article-details { - // grid-column: 1 / span 2; - - // h2 { - // color: $medium_grey; - // margin: 0 10px; - // padding: 10px 0 0; - // font-size: 16px; - // } - - // ul.details-list { - // margin: 10px; - - // .detail { - // display: grid; - // grid-template-columns: 1fr auto; - // gap: 20px; - // font-size: 12px; - // border-bottom: 1px solid $light_0; - // padding: 5px 0; - - // label { - // font-weight: bold; - // color: $medium_grey; - // white-space: nowrap; - // } - - // .detail-value { - // text-align: right; - // } - // } - // } - // } - @import "./homepage.scss"; @import "./pages/education/education.scss"; @import "./pages/games/games.scss";