diff --git a/build.js b/build.js index 8fb487fc2392357576964b995c29b65b9cc293e7..616d21b8e3810200e7f02cf40f077146dc598f8b 100644 --- a/build.js +++ b/build.js @@ -3,7 +3,7 @@ "use strict"; const build_conf = { - protected_dirs: ["assets", "style", "articles"], + protected_dirs: ["assets", "style", "news-articles", "game-articles", "software-articles"], }; const fs = require("fs"); diff --git a/config.js b/config.js index bdaf34374091a05af107cca712d3c890055c7e51..2f677c61bc76a98d868dd805a3ee69803d66d649 100644 --- a/config.js +++ b/config.js @@ -10,4 +10,4 @@ switch (ENV) { server_url = "http://kuadrado-software.fr"; } -module.exports = { server_url }; +module.exports = { server_url, in_construction: true }; diff --git a/constants.js b/constants.js index fd8b9bd8a32e15fd08a8612c718d299b3241bf27..50ac463a0fe060ae6a0b7e8785835b0f58480e95 100644 --- a/constants.js +++ b/constants.js @@ -2,5 +2,7 @@ const { server_url } = require("./config"); module.exports = { images_url: `${server_url}/assets/images`, - articles_url: `${server_url}/articles`, + news_articles_url: `${server_url}/news-articles`, + game_articles_url: `${server_url}/game-articles`, + software_articles_url: `${server_url}/software-articles`, }; diff --git a/nginx.conf b/nginx.conf index 266e0bfff1acea1139655dc0e38a34e0415eb9ec..f9dfe32359e324b3ba1160364bd91575072a781c 100644 --- a/nginx.conf +++ b/nginx.conf @@ -28,8 +28,12 @@ http { include /etc/nginx/conf.d/*.conf; - # server { - # add_header 'Access-Control-Allow-Origin' '*'; - # } + server { + server_name kuadrado-software.fr www.kuadrado-software.fr; + location / { + add_header Access-Control-Allow-Origin *; + } + } + } diff --git a/public/assets/images/wallpaper_warning.svg b/public/assets/images/wallpaper_warning.svg new file mode 100644 index 0000000000000000000000000000000000000000..ab639d4cf8f9d60e423555f67dced45e5442f6c9 --- /dev/null +++ b/public/assets/images/wallpaper_warning.svg @@ -0,0 +1,74 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<svg + xmlns:dc="http://purl.org/dc/elements/1.1/" + xmlns:cc="http://creativecommons.org/ns#" + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:svg="http://www.w3.org/2000/svg" + xmlns="http://www.w3.org/2000/svg" + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" + width="79.375mm" + height="79.375mm" + viewBox="0 0 79.375 79.375" + version="1.1" + id="svg8" + inkscape:version="1.0.1 (0767f8302a, 2020-10-17)" + sodipodi:docname="wallpaper_warning.svg"> + <defs + id="defs2" /> + <sodipodi:namedview + id="base" + pagecolor="#ffffff" + bordercolor="#666666" + borderopacity="1.0" + inkscape:pageopacity="0.0" + inkscape:pageshadow="2" + inkscape:zoom="2.8284271" + inkscape:cx="166.22215" + inkscape:cy="210.50122" + inkscape:document-units="mm" + inkscape:current-layer="layer1" + inkscape:document-rotation="0" + showgrid="false" + fit-margin-top="0" + fit-margin-left="0" + fit-margin-right="0" + fit-margin-bottom="0" + inkscape:window-width="1920" + inkscape:window-height="966" + inkscape:window-x="1920" + inkscape:window-y="27" + inkscape:window-maximized="1" /> + <metadata + id="metadata5"> + <rdf:RDF> + <cc:Work + rdf:about=""> + <dc:format>image/svg+xml</dc:format> + <dc:type + rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> + <dc:title></dc:title> + </cc:Work> + </rdf:RDF> + </metadata> + <g + inkscape:label="Calque 1" + inkscape:groupmode="layer" + id="layer1" + transform="translate(-68.684253,-89.92156)"> + <g + id="g847" + transform="translate(22.712161,-53.33137)"> + <path + style="fill:#fece00;stroke-width:0.264583" + d="m 125.34553,143.25255 c 3.9e-4,-2e-5 0.002,39.63184 0.002,39.63184 l -39.636437,39.74407 -39.737207,-0.0117 c 26.12056,-26.62352 52.901255,-52.96121 79.371964,-79.36422 z m -79.373459,3.8e-4 39.742018,0 c 0,0 -39.533678,39.4967 -39.743925,39.4967 z" + id="path851" + sodipodi:nodetypes="cccccccccc" /> + <path + style="fill:#d79400;stroke-width:0.264583" + d="m 45.970159,182.74963 39.743932,-39.4967 39.631439,-3.8e-4 c 0,0 -52.907028,53.09226 -79.371964,79.36422 z m 39.740934,39.87883 39.636437,-39.74407 -3.9e-4,39.74354 z" + id="path849" + sodipodi:nodetypes="ccccccccc" /> + </g> + </g> +</svg> diff --git a/public/education/education.js b/public/education/education.js index 75582984892951582798ccff04f88e0a44ffb995..7000373e2c802703d2df725f2a96e5b26d1830a9 100644 --- a/public/education/education.js +++ b/public/education/education.js @@ -11,14 +11,16 @@ switch (ENV) { server_url = "http://kuadrado-software.fr"; } -module.exports = { server_url }; +module.exports = { server_url, in_construction: true }; },{}],2:[function(require,module,exports){ const { server_url } = require("./config"); module.exports = { images_url: `${server_url}/assets/images`, - articles_url: `${server_url}/articles`, + news_articles_url: `${server_url}/news-articles`, + game_articles_url: `${server_url}/game-articles`, + software_articles_url: `${server_url}/software-articles`, }; },{"./config":1}],3:[function(require,module,exports){ @@ -828,6 +830,7 @@ module.exports = NavBar; },{"../../../constants":2}],10:[function(require,module,exports){ "use strict"; +const { in_construction } = require("../../config"); const { images_url } = require("../../constants"); const NavBar = require("./components/navbar"); @@ -843,8 +846,19 @@ class Template { tag: "header", contents: [new NavBar().render()], }, + in_construction && { + tag: "section", + class: "warning-banner", + contents: [ + { + tag: "strong", + class: "page-contents-center", + contents: "Site en construction ...", + }, + ], + }, { - tag: "div", + tag: "section", id: "page-container", contents: [this.props.page.render()], }, @@ -861,14 +875,15 @@ class Template { }, { tag: "img", - class:"text-logo", + class: "text-logo", src: `${images_url}/logo_kuadrado_txt.svg`, }, ], }, { - tag:"span", - contents: "Toutes les images du site ont été réalisées par nos soins et peuvent être réutilisées pour un usage personnel." + tag: "span", + contents: + "Toutes les images du site ont été réalisées par nos soins et peuvent être réutilisées pour un usage personnel.", }, { tag: "a", @@ -884,4 +899,4 @@ class Template { module.exports = Template; -},{"../../constants":2,"./components/navbar":9}]},{},[7]); +},{"../../config":1,"../../constants":2,"./components/navbar":9}]},{},[7]); diff --git a/public/game-articles/fantom_quest/fantom_quest.json b/public/game-articles/fantom_quest/fantom_quest.json new file mode 100644 index 0000000000000000000000000000000000000000..62c6e4a4721414a9b5f139c8c6e623847d42c990 --- /dev/null +++ b/public/game-articles/fantom_quest/fantom_quest.json @@ -0,0 +1,27 @@ +{ + "title": "Fantom Quest", + "subtitle": "Le labyrinthe de la quête d'identité", + "tags": ["jeu web", "pixelart", "javascript", "labyrinthe"], + "body": "<file>fantom_quest.txt", + "images": [ + "screen_fantom_quest_1.jpg", + "screen_fantom_quest_2.jpg", + "screen_fantom_quest_3.jpg", + "screen_fantom_quest_4.jpg", + "screen_fantom_quest_5.jpg" + ], + "team_subarticles": [ + { + "title": "Lucie Ventadour", + "subtitle": "Artiste 2D, illustratice, artiste peintre", + "body": "<file>lucie_ventadour.txt", + "images": ["lucipix.png"] + }, + { + "title": "Pierre Jarriges", + "subtitle": "Auteur BD, dessinateur, compositeur, développeur.", + "body": "<file>pijar.txt", + "images": ["pijarpix.png"] + } + ] +} diff --git a/public/game-articles/fantom_quest/fantom_quest.txt b/public/game-articles/fantom_quest/fantom_quest.txt new file mode 100644 index 0000000000000000000000000000000000000000..86e588e6928d1a42f24f714ac4830f2f04436f71 --- /dev/null +++ b/public/game-articles/fantom_quest/fantom_quest.txt @@ -0,0 +1,9 @@ +Un petit fantôme en quête d'identité va devoir gravir chaque étage d'un donjon afin de rencontrer la sorcière qui lui révélera sa vraie nature. + +Ce petit jeu de quête minimaliste en forme de labyrinthe sera jouable directement sur navigateur ou à télécharger sur pc. +Sortie prévue : Mars 2021 (si on y arrive !) + +Concept original et graphismes : Lucie Ventadour ( http://lucipix.canalblog.com/||site_web ). +Programmation Javascript et bande son: Pierre Jarriges + +https://lab.frogg.it/peter_rabbit/fantom-quest||Dépôt_du_code_source diff --git a/public/game-articles/fantom_quest/images/lucipix.png b/public/game-articles/fantom_quest/images/lucipix.png new file mode 100644 index 0000000000000000000000000000000000000000..f2016e3cb8a2879daf03a15bbcb9eca16a944cab Binary files /dev/null and b/public/game-articles/fantom_quest/images/lucipix.png differ diff --git a/public/game-articles/fantom_quest/images/pijarpix.png b/public/game-articles/fantom_quest/images/pijarpix.png new file mode 100644 index 0000000000000000000000000000000000000000..fd32b420ec5b3361fb522bab67fab21dfc8241e1 Binary files /dev/null and b/public/game-articles/fantom_quest/images/pijarpix.png differ diff --git a/public/game-articles/fantom_quest/images/screen_fantom_quest_1.jpg b/public/game-articles/fantom_quest/images/screen_fantom_quest_1.jpg new file mode 100644 index 0000000000000000000000000000000000000000..733ebe66d706739b8968e2ea9cf39b55edb300d8 Binary files /dev/null and b/public/game-articles/fantom_quest/images/screen_fantom_quest_1.jpg differ diff --git a/public/game-articles/fantom_quest/images/screen_fantom_quest_2.jpg b/public/game-articles/fantom_quest/images/screen_fantom_quest_2.jpg new file mode 100644 index 0000000000000000000000000000000000000000..419a54956086d4bf932e1a1fc7bb30310f4151c0 Binary files /dev/null and b/public/game-articles/fantom_quest/images/screen_fantom_quest_2.jpg differ diff --git a/public/game-articles/fantom_quest/images/screen_fantom_quest_3.jpg b/public/game-articles/fantom_quest/images/screen_fantom_quest_3.jpg new file mode 100644 index 0000000000000000000000000000000000000000..b76c04a8cc1c05ef5e96cf2c94d525b1a17b0a27 Binary files /dev/null and b/public/game-articles/fantom_quest/images/screen_fantom_quest_3.jpg differ diff --git a/public/game-articles/fantom_quest/images/screen_fantom_quest_4.jpg b/public/game-articles/fantom_quest/images/screen_fantom_quest_4.jpg new file mode 100644 index 0000000000000000000000000000000000000000..1f2ab664d3e99f3fab911879e70c7bd37b8cac57 Binary files /dev/null and b/public/game-articles/fantom_quest/images/screen_fantom_quest_4.jpg differ diff --git a/public/game-articles/fantom_quest/images/screen_fantom_quest_5.jpg b/public/game-articles/fantom_quest/images/screen_fantom_quest_5.jpg new file mode 100644 index 0000000000000000000000000000000000000000..57a6e6ba3f07aa7bdff4695ec7c159524eb6f366 Binary files /dev/null and b/public/game-articles/fantom_quest/images/screen_fantom_quest_5.jpg differ diff --git a/public/game-articles/fantom_quest/lucie_ventadour.txt b/public/game-articles/fantom_quest/lucie_ventadour.txt new file mode 100644 index 0000000000000000000000000000000000000000..9c20aae109ac7292c035a6bb0d997576e7d0f32d --- /dev/null +++ b/public/game-articles/fantom_quest/lucie_ventadour.txt @@ -0,0 +1,2 @@ +Salut moi c'est lucette, je suis une geek et je vois la vie en pixels >< et ouais. +https://www.lucieventadour.com/||Mon_site | http://lucipix.canalblog.com/||Mon_blog_pix \ No newline at end of file diff --git a/public/game-articles/fantom_quest/pijar.txt b/public/game-articles/fantom_quest/pijar.txt new file mode 100644 index 0000000000000000000000000000000000000000..afc7e86ad39df6cdcd2141cf1936c69877a5bcb6 --- /dev/null +++ b/public/game-articles/fantom_quest/pijar.txt @@ -0,0 +1,4 @@ +Salut moi c'est pijar. Je fais des trucs. + +J'aime bien le code. +Et je fais du dessin et tout. \ No newline at end of file diff --git a/public/game-articles/index.json b/public/game-articles/index.json new file mode 100644 index 0000000000000000000000000000000000000000..b6bc394a7c546e147834a8f29597b6f62428c3a5 --- /dev/null +++ b/public/game-articles/index.json @@ -0,0 +1 @@ +["fantom_quest/fantom_quest.json"] diff --git a/public/games/games.js b/public/games/games.js index 64c83346ffc44445a68d9cd9e27dfabdac2b3233..97d9444dd8c79ed23d48b6902225d424bd12519c 100644 --- a/public/games/games.js +++ b/public/games/games.js @@ -11,19 +11,184 @@ switch (ENV) { server_url = "http://kuadrado-software.fr"; } -module.exports = { server_url }; +module.exports = { server_url, in_construction: true }; },{}],2:[function(require,module,exports){ const { server_url } = require("./config"); module.exports = { images_url: `${server_url}/assets/images`, - articles_url: `${server_url}/articles`, + news_articles_url: `${server_url}/news-articles`, + game_articles_url: `${server_url}/game-articles`, + software_articles_url: `${server_url}/software-articles`, }; },{"./config":1}],3:[function(require,module,exports){ "use strict"; +const objectHtmlRenderer = require("../lib/object-html-renderer"); + +class ImageCarousel { + constructor(props) { + this.props = props; + this.id = performance.now(); + this.state = { + showImageIndex: 0, + }; + this.RUN_INTERVAL = 5000; + this.run(); + } + + run() { + this.runningInterval = setInterval(() => { + let { showImageIndex } = this.state; + const { images } = this.props; + this.state.showImageIndex = showImageIndex < images.length - 1 ? ++showImageIndex : 0; + this.refreshImage(); + }, this.RUN_INTERVAL); + } + + setImageIndex(i) { + clearInterval(this.runningInterval); + this.state.showImageIndex = i; + this.refreshImage(); + } + + refreshImage() { + objectHtmlRenderer.subRender(this.render(), document.getElementById(this.id), { + mode: "replace", + }); + } + + render() { + const { showImageIndex } = this.state; + const { images } = this.props; + return { + tag: "div", + id: this.id, + class: "image-carousel", + contents: [ + { tag: "img", src: images[showImageIndex] }, + images.length > 1 && { + tag: "div", + class: "carousel-bullets", + contents: images.map((_, i) => { + const active = showImageIndex === i; + return { + tag: "span", + class: `bullet ${active ? "active" : ""}`, + onclick: this.setImageIndex.bind(this, i), + }; + }), + }, + ], + }; + } +} + +module.exports = ImageCarousel; + +},{"../lib/object-html-renderer":6}],4:[function(require,module,exports){ +"use strict"; + +const { fetchjson, fetchtext } = require("./fetch"); + +function getArticleBody(text) { + return text + .split(" ") + .map(word => { + if (word.includes("http://") || word.includes("https://")) { + const splitword = word.split("||"); + const href = splitword[0].match(/http.+/); + const text = splitword.length > 1 ? splitword[1].replaceAll("_", " ") : href; + return word.replace(/http.*/, `<a href=${href} target="_blank">${text}</a>`); + } else return word; + }) + .join(" ") + .replaceAll("\n", "<br/>"); +} + +function getArticleDate(date) { + return `${date.getDate()}-${date.getMonth() + 1}-${date.getFullYear()}`; +} + +function loadArticles(dir_url) { + return new Promise((resolve, reject) => { + fetchjson(`${dir_url}/index.json`) + .then(json => { + Promise.all( + json.map(async articlePath => { + const art = await fetchjson(`${dir_url}/${articlePath}`); + const tmpSplit = articlePath.split("/"); + tmpSplit.pop(); + const absArtPath = `${dir_url}/${tmpSplit.join("/")}`; + return Object.assign(art, { path: absArtPath }); + }) + ) + .then(articles => { + populateArticles(articles) + .then(completeArticles => resolve(completeArticles)) + .catch(e => reject(e)); + }) + .catch(e => reject(e)); + }) + .catch(e => console.log(e)); + }); +} + +function populateArticles(articles) { + return new Promise((resolve, reject) => { + Promise.all( + articles.map(async article => { + if (article.body.indexOf("<file>") !== -1) { + const txtPath = article.body.replace("<file>", ""); + const textValue = await fetchtext(`${article.path}/${txtPath}`); + article.body = textValue; + article.date = article.date ? new Date(article.date) : undefined; + } + return article; + }) + ) + .then(completeArticles => resolve(completeArticles.sort((a, b) => a.date - b.date))) + .catch(e => reject(e)); + }); +} + +module.exports = { + loadArticles, + getArticleBody, + getArticleDate, + populateArticles, +}; + +},{"./fetch":5}],5:[function(require,module,exports){ +"use strict"; + +function fetchjson(url) { + return new Promise((resolve, reject) => { + fetch(url) + .then(r => r.json()) + .then(r => resolve(r)) + .catch(e => reject(e)); + }); +}; + +function fetchtext(url) { + return new Promise((resolve, reject) => { + fetch(url) + .then(r => r.text()) + .then(r => resolve(r)) + .catch(e => reject(e)); + }); +}; + +module.exports = { + fetchjson, fetchtext +} + +},{}],6:[function(require,module,exports){ +"use strict"; + module.exports = { setRenderCycleRoot(renderCycleRoot) { this.renderCycleRoot = renderCycleRoot; @@ -107,9 +272,179 @@ module.exports = { }, }; -},{}],4:[function(require,module,exports){ +},{}],7:[function(require,module,exports){ +"use strict"; + +const ImageCarousel = require("../../../generic-components/image-carousel"); +const { getArticleBody } = require("../../../lib/article-utils"); + +class TeamMember { + constructor(props) { + this.props = props; + } + + render() { + const { title, subtitle, body, images, path } = this.props; + return { + tag: "div", + class: "team-member", + contents: [ + { + tag: "div", + class: "team-member-img", + contents: [{ tag: "img", src: images.map(im => `${path}/images/${im}`)[0] }], + }, + { + tag: "h3", + class: "team-member-title", + contents: title, + }, + { + tag: "strong", + class: "team-member-subtitle", + contents: subtitle, + }, + { + tag: "p", + class: "team-member-body", + contents: getArticleBody(body), + }, + ], + }; + } +} + +class GameArticle { + constructor(props) { + this.props = props; + } + + render() { + const { title, tags, body, subtitle, images, path, team_subarticles } = this.props; + return { + tag: "article", + class: "game-article", + contents: [ + { + tag: "h2", + class: "game-title", + contents: title, + }, + { + tag: "div", + class: "game-tags", + contents: tags.map(tag => { + return { tag: "span", contents: tag }; + }), + }, + { + tag: "h3", + class: "game-subtitle", + contents: subtitle, + }, + { + tag: "div", + class: "game-description", + contents: getArticleBody(body), + }, + new ImageCarousel({ images: images.map(img => `${path}/images/${img}`) }).render(), + { + tag: "div", + class: "game-team", + contents: [ + { + tag: "h2", + contents: "L'équipe", + }, + { + tag: "div", + class: "team-members", + contents: team_subarticles.map(tsa => + new TeamMember({ ...tsa }).render() + ), + }, + ], + }, + ], + }; + } +} + +module.exports = GameArticle; + +},{"../../../generic-components/image-carousel":3,"../../../lib/article-utils":4}],8:[function(require,module,exports){ +"use strict"; + +const { game_articles_url } = require("../../../../constants"); +const { loadArticles, populateArticles } = require("../../../lib/article-utils"); +const objectHtmlRenderer = require("../../../lib/object-html-renderer"); +const GameArticle = require("./game-article"); + +class GameArticles { + constructor(props) { + this.props = props; + this.state = { + articles: [], + }; + this.id = performance.now(); + this.loadArticles(); + } + + loadArticles() { + loadArticles(game_articles_url) + .then(articles => { + Promise.all( + articles.map(async a => { + if (a.team_subarticles) { + a.team_subarticles = await populateArticles( + a.team_subarticles.map(sa => Object.assign(sa, { path: a.path })) + ); + } + return a; + }) + ).then(completeArticles => { + this.state.articles = completeArticles; + this.refresh(); + }); + }) + .catch(e => console.log(e)); + } + + renderPlaceholder() { + return { + tag: "article", + class: "placeholder", + contents: [{ tag: "div" }, { tag: "div" }], + }; + } + + refresh() { + objectHtmlRenderer.subRender(this.render(), document.getElementById(this.id), { + mode: "replace", + }); + } + + render() { + const { articles } = this.state; + return { + tag: "section", + class: "game-articles page-contents-center", + id: this.id, + contents: + articles.length > 0 + ? articles.map(article => new GameArticle({ ...article }).render()) + : [this.renderPlaceholder()], + }; + } +} + +module.exports = GameArticles; + +},{"../../../../constants":2,"../../../lib/article-utils":4,"../../../lib/object-html-renderer":6,"./game-article":7}],9:[function(require,module,exports){ "use strict"; +const GameArticles = require("./components/game-articles"); + class GamesPage { constructor(args) { Object.assign(this, args); @@ -118,14 +453,22 @@ class GamesPage { render() { return { tag: "div", + id:"games-page", contents: [ { tag: "div", class: "page-header", contents: [ - { tag: "h1", contents: "Jeux", class: "page-contents-center" } + { tag: "h1", contents: "Jeux", class: "page-contents-center" }, + { + tag: "p", + class: "page-contents-center", + contents: `Créer des jeux vidéos c'est cœur de ce qui nous passionne. + <br/>Retrouvez ici nos créations, à jouer en ligne ou à télécharger, et découvrez nos projets en cours.`, + }, ], }, + new GameArticles().render(), ], }; } @@ -133,7 +476,7 @@ class GamesPage { module.exports = GamesPage; -},{}],5:[function(require,module,exports){ +},{"./components/game-articles":8}],10:[function(require,module,exports){ "use strict"; "use strict"; @@ -141,7 +484,7 @@ const runPage = require("../../run-page"); const GamesPage = require("./games"); runPage(GamesPage); -},{"../../run-page":6,"./games":4}],6:[function(require,module,exports){ +},{"../../run-page":11,"./games":9}],11:[function(require,module,exports){ "use strict"; const objectHtmlRenderer = require("./lib/object-html-renderer"); @@ -153,7 +496,7 @@ module.exports = function runPage(PageComponent) { objectHtmlRenderer.renderCycle(); }; -},{"./lib/object-html-renderer":3,"./template/template":8}],7:[function(require,module,exports){ +},{"./lib/object-html-renderer":6,"./template/template":13}],12:[function(require,module,exports){ "use strict"; const { images_url } = require("../../../constants"); @@ -259,9 +602,10 @@ class NavBar { module.exports = NavBar; -},{"../../../constants":2}],8:[function(require,module,exports){ +},{"../../../constants":2}],13:[function(require,module,exports){ "use strict"; +const { in_construction } = require("../../config"); const { images_url } = require("../../constants"); const NavBar = require("./components/navbar"); @@ -277,8 +621,19 @@ class Template { tag: "header", contents: [new NavBar().render()], }, + in_construction && { + tag: "section", + class: "warning-banner", + contents: [ + { + tag: "strong", + class: "page-contents-center", + contents: "Site en construction ...", + }, + ], + }, { - tag: "div", + tag: "section", id: "page-container", contents: [this.props.page.render()], }, @@ -295,14 +650,15 @@ class Template { }, { tag: "img", - class:"text-logo", + class: "text-logo", src: `${images_url}/logo_kuadrado_txt.svg`, }, ], }, { - tag:"span", - contents: "Toutes les images du site ont été réalisées par nos soins et peuvent être réutilisées pour un usage personnel." + tag: "span", + contents: + "Toutes les images du site ont été réalisées par nos soins et peuvent être réutilisées pour un usage personnel.", }, { tag: "a", @@ -318,4 +674,4 @@ class Template { module.exports = Template; -},{"../../constants":2,"./components/navbar":7}]},{},[5]); +},{"../../config":1,"../../constants":2,"./components/navbar":12}]},{},[10]); diff --git a/public/main.js b/public/main.js index accb62f23d9a11b9fc15850565cd50bb210ca459..523eb03fbc5a086a49bf5644a2854534c85a1b2f 100644 --- a/public/main.js +++ b/public/main.js @@ -11,25 +11,92 @@ switch (ENV) { server_url = "http://kuadrado-software.fr"; } -module.exports = { server_url }; +module.exports = { server_url, in_construction: true }; },{}],2:[function(require,module,exports){ const { server_url } = require("./config"); module.exports = { images_url: `${server_url}/assets/images`, - articles_url: `${server_url}/articles`, + news_articles_url: `${server_url}/news-articles`, + game_articles_url: `${server_url}/game-articles`, + software_articles_url: `${server_url}/software-articles`, }; },{"./config":1}],3:[function(require,module,exports){ "use strict"; -const { articles_url } = require("../../constants"); -const { fetchjson, fetchtext } = require("../lib/fetch"); const objectHtmlRenderer = require("../lib/object-html-renderer"); -const ImageCarousel = require("./image-carousel"); -class Articles { +class ImageCarousel { + constructor(props) { + this.props = props; + this.id = performance.now(); + this.state = { + showImageIndex: 0, + }; + this.RUN_INTERVAL = 5000; + this.run(); + } + + run() { + this.runningInterval = setInterval(() => { + let { showImageIndex } = this.state; + const { images } = this.props; + this.state.showImageIndex = showImageIndex < images.length - 1 ? ++showImageIndex : 0; + this.refreshImage(); + }, this.RUN_INTERVAL); + } + + setImageIndex(i) { + clearInterval(this.runningInterval); + this.state.showImageIndex = i; + this.refreshImage(); + } + + refreshImage() { + objectHtmlRenderer.subRender(this.render(), document.getElementById(this.id), { + mode: "replace", + }); + } + + render() { + const { showImageIndex } = this.state; + const { images } = this.props; + return { + tag: "div", + id: this.id, + class: "image-carousel", + contents: [ + { tag: "img", src: images[showImageIndex] }, + images.length > 1 && { + tag: "div", + class: "carousel-bullets", + contents: images.map((_, i) => { + const active = showImageIndex === i; + return { + tag: "span", + class: `bullet ${active ? "active" : ""}`, + onclick: this.setImageIndex.bind(this, i), + }; + }), + }, + ], + }; + } +} + +module.exports = ImageCarousel; + +},{"../lib/object-html-renderer":9}],4:[function(require,module,exports){ +"use strict"; + +const { news_articles_url } = require("../../constants"); +const objectHtmlRenderer = require("../lib/object-html-renderer"); +const ImageCarousel = require("../generic-components/image-carousel"); +const { loadArticles, getArticleDate, getArticleBody } = require("../lib/article-utils"); + +class NewsArticles { constructor() { this.id = performance.now().toString(); this.state = { @@ -41,35 +108,11 @@ class Articles { } loadArticles() { - fetchjson(`${articles_url}/index.json`) - .then(json => { - Promise.all( - json.map(async articlePath => { - const art = await fetchjson(`${articles_url}/${articlePath}`); - const tmpSplit = articlePath.split("/"); - tmpSplit.pop(); - const absArtPath = `${articles_url}/${tmpSplit.join("/")}`; - return Object.assign(art, { path: absArtPath }); - }) - ) - .then(articles => this.setArticles(articles)) - .catch(e => console.log(e)); - }) - .catch(e => console.log(e)); - } - - async setArticles(articles) { - for (const article of articles) { - if (article.content_text.indexOf("<file>") !== -1) { - const txtPath = article.content_text.replace("<file>", ""); - const txtValue = await fetchtext(`${article.path}/${txtPath}`); - article.content_text = txtValue; - } - article.date = new Date(article.date); - } - this.state.articles = articles.sort((a, b) => a.date - b.date); - this.state.showArticleIndex = this.state.articles.length - 1; - this.refresh(); + loadArticles(news_articles_url).then(articles => { + this.state.articles = articles; + this.state.showArticleIndex = this.state.articles.length - 1; + this.refresh(); + }); } refresh() { @@ -78,25 +121,6 @@ class Articles { }); } - getArticleDate(date) { - return `${date.getDate()}-${date.getMonth() + 1}-${date.getFullYear()}`; - } - - getArticleBody(text) { - return text - .split(" ") - .map(word => { - if (word.includes("http://") || word.includes("https://")) { - const splitword = word.split("||"); - const href = splitword[0]; - const text = splitword.length > 1 ? splitword[1] : href; - return `<a href=${href} target="_blank">${text}</a>`; - } else return word; - }) - .join(" ") - .replaceAll("\n", "<br/>"); - } - renderArticle(articleData) { return { tag: "article", @@ -104,7 +128,7 @@ class Articles { { tag: "div", class: "date", - contents: [{ tag: "span", contents: this.getArticleDate(articleData.date) }], + contents: [{ tag: "span", contents: getArticleDate(articleData.date) }], }, { tag: "div", @@ -132,7 +156,7 @@ class Articles { contents: [ { tag: "p", - contents: this.getArticleBody(articleData.content_text), + contents: getArticleBody(articleData.body), }, ], }, @@ -182,91 +206,34 @@ class Articles { contents: articles.length > 0 ? [ - { - tag: "button", - class: `prev-btn ${!showPrev ? "disabled" : "active"}`, - onclick: this.handleChangeArticle.bind(this, "prev"), - }, this.renderArticle(articles[showArticleIndex]), { - tag: "button", - class: `next-btn ${!showNext ? "disabled" : "active"}`, - onclick: this.handleChangeArticle.bind(this, "next"), + tag: "div", + class: "prev-next-buttons", + contents: [ + { + tag: "button", + class: `prev-btn ${!showPrev ? "disabled" : "active"}`, + contents: "Précédent", + onclick: this.handleChangeArticle.bind(this, "prev"), + }, + { + tag: "button", + class: `next-btn ${!showNext ? "disabled" : "active"}`, + contents: "Suivant", + onclick: this.handleChangeArticle.bind(this, "next"), + }, + ], }, ] - : [{tag:"div"},this.renderArticlePlaceholder(), {tag:"div"}], + : [this.renderArticlePlaceholder()], }; } } -module.exports = Articles; +module.exports = NewsArticles; -},{"../../constants":2,"../lib/fetch":7,"../lib/object-html-renderer":8,"./image-carousel":4}],4:[function(require,module,exports){ -"use strict"; - -const objectHtmlRenderer = require("../lib/object-html-renderer"); - -class ImageCarousel { - constructor(props) { - this.props = props; - this.id = performance.now(); - this.state = { - showImageIndex: 0, - }; - this.RUN_INTERVAL = 5000; - this.run(); - } - - run() { - this.runningInterval = setInterval(() => { - let { showImageIndex } = this.state; - const { images } = this.props; - this.state.showImageIndex = showImageIndex < images.length - 1 ? ++showImageIndex : 0; - this.refreshImage(); - }, this.RUN_INTERVAL); - } - - setImageIndex(i) { - clearInterval(this.runningInterval); - this.state.showImageIndex = i; - this.refreshImage(); - } - - refreshImage() { - objectHtmlRenderer.subRender(this.render(), document.getElementById(this.id), { - mode: "replace", - }); - } - - render() { - const { showImageIndex } = this.state; - const { images } = this.props; - return { - tag: "div", - id: this.id, - class: "image-carousel", - contents: [ - { tag: "img", src: images[showImageIndex] }, - { - tag: "div", - class: "carousel-bullets", - contents: images.map((_, i) => { - const active = showImageIndex === i; - return { - tag: "span", - class: `bullet ${active ? "active" : ""}`, - onclick: this.setImageIndex.bind(this, i), - }; - }), - }, - ], - }; - } -} - -module.exports = ImageCarousel; - -},{"../lib/object-html-renderer":8}],5:[function(require,module,exports){ +},{"../../constants":2,"../generic-components/image-carousel":3,"../lib/article-utils":7,"../lib/object-html-renderer":9}],5:[function(require,module,exports){ "use strict"; const { images_url } = require("../../constants"); @@ -307,7 +274,8 @@ module.exports = ThemeCard; },{"../../constants":2}],6:[function(require,module,exports){ "use strict"; -const Articles = require("./home-page-components/articles"); +const { images_url } = require("../constants"); +const NewsArticles = require("./home-page-components/news-articles"); const ThemeCard = require("./home-page-components/theme-card"); class HomePage { @@ -324,6 +292,18 @@ class HomePage { tag: "div", class: "page-header", contents: [ + { + tag: "div", + class: "big-logo page-contents-center", + contents: [ + { tag: "img", src: `${images_url}/logo_kuadrado.svg` }, + { + tag: "img", + class: "logo-text", + src: `${images_url}/logo_kuadrado_txt.svg`, + }, + ], + }, { tag: "h1", contents: "Kuadrado Software", class: "page-contents-center" }, { tag: "p", @@ -340,7 +320,7 @@ class HomePage { class: "page-contents-center", contents: [ { tag: "h2", contents: "Actu", class: "section-title bg-blue" }, - new Articles().render(), + new NewsArticles().render(), ], }, { @@ -377,7 +357,80 @@ class HomePage { module.exports = HomePage; -},{"./home-page-components/articles":3,"./home-page-components/theme-card":5}],7:[function(require,module,exports){ +},{"../constants":2,"./home-page-components/news-articles":4,"./home-page-components/theme-card":5}],7:[function(require,module,exports){ +"use strict"; + +const { fetchjson, fetchtext } = require("./fetch"); + +function getArticleBody(text) { + return text + .split(" ") + .map(word => { + if (word.includes("http://") || word.includes("https://")) { + const splitword = word.split("||"); + const href = splitword[0].match(/http.+/); + const text = splitword.length > 1 ? splitword[1].replaceAll("_", " ") : href; + return word.replace(/http.*/, `<a href=${href} target="_blank">${text}</a>`); + } else return word; + }) + .join(" ") + .replaceAll("\n", "<br/>"); +} + +function getArticleDate(date) { + return `${date.getDate()}-${date.getMonth() + 1}-${date.getFullYear()}`; +} + +function loadArticles(dir_url) { + return new Promise((resolve, reject) => { + fetchjson(`${dir_url}/index.json`) + .then(json => { + Promise.all( + json.map(async articlePath => { + const art = await fetchjson(`${dir_url}/${articlePath}`); + const tmpSplit = articlePath.split("/"); + tmpSplit.pop(); + const absArtPath = `${dir_url}/${tmpSplit.join("/")}`; + return Object.assign(art, { path: absArtPath }); + }) + ) + .then(articles => { + populateArticles(articles) + .then(completeArticles => resolve(completeArticles)) + .catch(e => reject(e)); + }) + .catch(e => reject(e)); + }) + .catch(e => console.log(e)); + }); +} + +function populateArticles(articles) { + return new Promise((resolve, reject) => { + Promise.all( + articles.map(async article => { + if (article.body.indexOf("<file>") !== -1) { + const txtPath = article.body.replace("<file>", ""); + const textValue = await fetchtext(`${article.path}/${txtPath}`); + article.body = textValue; + article.date = article.date ? new Date(article.date) : undefined; + } + return article; + }) + ) + .then(completeArticles => resolve(completeArticles.sort((a, b) => a.date - b.date))) + .catch(e => reject(e)); + }); +} + +module.exports = { + loadArticles, + getArticleBody, + getArticleDate, + populateArticles, +}; + +},{"./fetch":8}],8:[function(require,module,exports){ "use strict"; function fetchjson(url) { @@ -402,7 +455,7 @@ module.exports = { fetchjson, fetchtext } -},{}],8:[function(require,module,exports){ +},{}],9:[function(require,module,exports){ "use strict"; module.exports = { @@ -488,7 +541,7 @@ module.exports = { }, }; -},{}],9:[function(require,module,exports){ +},{}],10:[function(require,module,exports){ "use strict"; const HomePage = require("./homepage"); @@ -496,7 +549,7 @@ const runPage = require("./run-page"); runPage(HomePage); -},{"./homepage":6,"./run-page":10}],10:[function(require,module,exports){ +},{"./homepage":6,"./run-page":11}],11:[function(require,module,exports){ "use strict"; const objectHtmlRenderer = require("./lib/object-html-renderer"); @@ -508,7 +561,7 @@ module.exports = function runPage(PageComponent) { objectHtmlRenderer.renderCycle(); }; -},{"./lib/object-html-renderer":8,"./template/template":12}],11:[function(require,module,exports){ +},{"./lib/object-html-renderer":9,"./template/template":13}],12:[function(require,module,exports){ "use strict"; const { images_url } = require("../../../constants"); @@ -614,9 +667,10 @@ class NavBar { module.exports = NavBar; -},{"../../../constants":2}],12:[function(require,module,exports){ +},{"../../../constants":2}],13:[function(require,module,exports){ "use strict"; +const { in_construction } = require("../../config"); const { images_url } = require("../../constants"); const NavBar = require("./components/navbar"); @@ -632,8 +686,19 @@ class Template { tag: "header", contents: [new NavBar().render()], }, + in_construction && { + tag: "section", + class: "warning-banner", + contents: [ + { + tag: "strong", + class: "page-contents-center", + contents: "Site en construction ...", + }, + ], + }, { - tag: "div", + tag: "section", id: "page-container", contents: [this.props.page.render()], }, @@ -650,14 +715,15 @@ class Template { }, { tag: "img", - class:"text-logo", + class: "text-logo", src: `${images_url}/logo_kuadrado_txt.svg`, }, ], }, { - tag:"span", - contents: "Toutes les images du site ont été réalisées par nos soins et peuvent être réutilisées pour un usage personnel." + tag: "span", + contents: + "Toutes les images du site ont été réalisées par nos soins et peuvent être réutilisées pour un usage personnel.", }, { tag: "a", @@ -673,4 +739,4 @@ class Template { module.exports = Template; -},{"../../constants":2,"./components/navbar":11}]},{},[9]); +},{"../../config":1,"../../constants":2,"./components/navbar":12}]},{},[10]); diff --git a/public/articles/index.json b/public/news-articles/index.json similarity index 100% rename from public/articles/index.json rename to public/news-articles/index.json diff --git a/public/articles/nested/article-nested.json b/public/news-articles/nested/article-nested.json similarity index 81% rename from public/articles/nested/article-nested.json rename to public/news-articles/nested/article-nested.json index 8c147f61e8ffe0e4e48892d2aef83892ce07e6ea..7fc343b351e3e2195db56bfaa655197da2d785f7 100644 --- a/public/articles/nested/article-nested.json +++ b/public/news-articles/nested/article-nested.json @@ -2,6 +2,6 @@ "title": "Kuadrado Software mange des burgers", "date": "1954/02/25", "subtitle": "Ouaiis on est vraiment contents", - "content_text": "<file>my-content-text.txt", + "body": "<file>my-content-text.txt", "images": ["screen_1.png", "screen_2.png", "screen_3.png", "screen_4.png"] } diff --git a/public/articles/nested/images/screen_1.png b/public/news-articles/nested/images/screen_1.png similarity index 100% rename from public/articles/nested/images/screen_1.png rename to public/news-articles/nested/images/screen_1.png diff --git a/public/articles/nested/images/screen_2.png b/public/news-articles/nested/images/screen_2.png similarity index 100% rename from public/articles/nested/images/screen_2.png rename to public/news-articles/nested/images/screen_2.png diff --git a/public/articles/nested/images/screen_3.png b/public/news-articles/nested/images/screen_3.png similarity index 100% rename from public/articles/nested/images/screen_3.png rename to public/news-articles/nested/images/screen_3.png diff --git a/public/articles/nested/images/screen_4.png b/public/news-articles/nested/images/screen_4.png similarity index 100% rename from public/articles/nested/images/screen_4.png rename to public/news-articles/nested/images/screen_4.png diff --git a/public/articles/nested/my-content-text.txt b/public/news-articles/nested/my-content-text.txt similarity index 100% rename from public/articles/nested/my-content-text.txt rename to public/news-articles/nested/my-content-text.txt diff --git a/public/articles/test/article-test.json b/public/news-articles/test/article-test.json similarity index 86% rename from public/articles/test/article-test.json rename to public/news-articles/test/article-test.json index a2afa7c8e7bafa66610c2a1f65f7b152d40a7ba4..ed7c6ac63937bec0c84f431aea10c445bbf50cea 100644 --- a/public/articles/test/article-test.json +++ b/public/news-articles/test/article-test.json @@ -2,7 +2,7 @@ "title": "Kuadrado Software ouvre ses portes", "date": "2032/08/25", "subtitle": "Ouaiis on est vraiment contents", - "content_text": "<file>content-text.txt", + "body": "<file>content-text.txt", "images": [ "screen_l1_1.jpg", "screen_l1_2.jpg", diff --git a/public/articles/test/content-text.txt b/public/news-articles/test/content-text.txt similarity index 100% rename from public/articles/test/content-text.txt rename to public/news-articles/test/content-text.txt diff --git a/public/articles/test/images/screen_l1_1.jpg b/public/news-articles/test/images/screen_l1_1.jpg similarity index 100% rename from public/articles/test/images/screen_l1_1.jpg rename to public/news-articles/test/images/screen_l1_1.jpg diff --git a/public/articles/test/images/screen_l1_2.jpg b/public/news-articles/test/images/screen_l1_2.jpg similarity index 100% rename from public/articles/test/images/screen_l1_2.jpg rename to public/news-articles/test/images/screen_l1_2.jpg diff --git a/public/articles/test/images/screen_l2.jpg b/public/news-articles/test/images/screen_l2.jpg similarity index 100% rename from public/articles/test/images/screen_l2.jpg rename to public/news-articles/test/images/screen_l2.jpg diff --git a/public/articles/test/images/screen_l3.jpg b/public/news-articles/test/images/screen_l3.jpg similarity index 100% rename from public/articles/test/images/screen_l3.jpg rename to public/news-articles/test/images/screen_l3.jpg diff --git a/public/articles/test/images/screen_secret.jpg b/public/news-articles/test/images/screen_secret.jpg similarity index 100% rename from public/articles/test/images/screen_secret.jpg rename to public/news-articles/test/images/screen_secret.jpg diff --git a/public/software-articles/index.json b/public/software-articles/index.json new file mode 100644 index 0000000000000000000000000000000000000000..0637a088a01e8ddab3bf3fa98dbe804cbde1a0dc --- /dev/null +++ b/public/software-articles/index.json @@ -0,0 +1 @@ +[] \ No newline at end of file diff --git a/public/software-development/software-development.js b/public/software-development/software-development.js index a3470c5597d37b553dee011dadbc611af708ce8b..277576e7b60d69e058267fb083eeed73da82106a 100644 --- a/public/software-development/software-development.js +++ b/public/software-development/software-development.js @@ -11,14 +11,16 @@ switch (ENV) { server_url = "http://kuadrado-software.fr"; } -module.exports = { server_url }; +module.exports = { server_url, in_construction: true }; },{}],2:[function(require,module,exports){ const { server_url } = require("./config"); module.exports = { images_url: `${server_url}/assets/images`, - articles_url: `${server_url}/articles`, + news_articles_url: `${server_url}/news-articles`, + game_articles_url: `${server_url}/game-articles`, + software_articles_url: `${server_url}/software-articles`, }; },{"./config":1}],3:[function(require,module,exports){ @@ -260,6 +262,7 @@ module.exports = NavBar; },{"../../../constants":2}],8:[function(require,module,exports){ "use strict"; +const { in_construction } = require("../../config"); const { images_url } = require("../../constants"); const NavBar = require("./components/navbar"); @@ -275,8 +278,19 @@ class Template { tag: "header", contents: [new NavBar().render()], }, + in_construction && { + tag: "section", + class: "warning-banner", + contents: [ + { + tag: "strong", + class: "page-contents-center", + contents: "Site en construction ...", + }, + ], + }, { - tag: "div", + tag: "section", id: "page-container", contents: [this.props.page.render()], }, @@ -293,14 +307,15 @@ class Template { }, { tag: "img", - class:"text-logo", + class: "text-logo", src: `${images_url}/logo_kuadrado_txt.svg`, }, ], }, { - tag:"span", - contents: "Toutes les images du site ont été réalisées par nos soins et peuvent être réutilisées pour un usage personnel." + tag: "span", + contents: + "Toutes les images du site ont été réalisées par nos soins et peuvent être réutilisées pour un usage personnel.", }, { tag: "a", @@ -316,4 +331,4 @@ class Template { module.exports = Template; -},{"../../constants":2,"./components/navbar":7}]},{},[5]); +},{"../../config":1,"../../constants":2,"./components/navbar":7}]},{},[5]); diff --git a/public/style/homepage.css b/public/style/homepage.css index b62211788fbfc53f0f8a32dab02bd7751ab679c4..4376425cad2370421d7ab814e02caa62fab70caf 100644 --- a/public/style/homepage.css +++ b/public/style/homepage.css @@ -1,9 +1,9 @@ -/* Error: Undefined variable. +/* Error: Undefined mixin. * , - * 9 | background-color: $light_0; - * | ^^^^^^^^ + * 8 | @include flex-center; + * | ^^^^^^^^^^^^^^^^^^^^ * ' - * src/homepage.scss 9:27 root stylesheet */ + * src/homepage.scss 8:13 root stylesheet */ body::before { font-family: "Source Code Pro", "SF Mono", Monaco, Inconsolata, "Fira Mono", @@ -13,5 +13,5 @@ body::before { padding: 1em; margin-bottom: 1em; border-bottom: 2px solid black; - content: "Error: Undefined variable.\a \2577 \a 9 \2502 background-color: $light_0;\a \2502 ^^^^^^^^\a \2575 \a src/homepage.scss 9:27 root stylesheet"; + content: "Error: Undefined mixin.\a \2577 \a 8 \2502 @include flex-center;\a \2502 ^^^^^^^^^^^^^^^^^^^^\a \2575 \a src/homepage.scss 8:13 root stylesheet"; } diff --git a/public/style/pages/games/games.css b/public/style/pages/games/games.css new file mode 100644 index 0000000000000000000000000000000000000000..a172391064087fc34a6de0b591042e19bc1d77b9 --- /dev/null +++ b/public/style/pages/games/games.css @@ -0,0 +1,17 @@ +/* Error: Undefined variable. + * , + * 10 | background-color: $dark_2; + * | ^^^^^^^ + * ' + * src/pages/games/games.scss 10:35 root stylesheet */ + +body::before { + font-family: "Source Code Pro", "SF Mono", Monaco, Inconsolata, "Fira Mono", + "Droid Sans Mono", monospace, monospace; + white-space: pre; + display: block; + padding: 1em; + margin-bottom: 1em; + border-bottom: 2px solid black; + content: "Error: Undefined variable.\a \2577 \a 10 \2502 background-color: $dark_2;\a \2502 ^^^^^^^\a \2575 \a src/pages/games/games.scss 10:35 root stylesheet"; +} diff --git a/public/style/style.css b/public/style/style.css index c498e8b5416c990d2a06ddaabbf6c5538660103e..6866c243acd807e659a167021a9aed1af0304151 100644 --- a/public/style/style.css +++ b/public/style/style.css @@ -36,6 +36,64 @@ main { align-items: center; min-height: 100vh; } +main .warning-banner { + background: url("/assets/images/wallpaper_warning.svg"); + width: 100%; + height: 40px; + padding: 20px 10%; + display: flex; + justify-content: center; + align-items: center; + flex-direction: row; +} +main .warning-banner strong { + font-size: 18px; + color: #1c3db2; +} +main .image-carousel { + overflow: hidden; + display: flex; + justify-content: center; + align-items: center; + flex-direction: row; + background-color: black; + position: relative; +} +main .image-carousel img { + position: absolute; + max-width: 100%; + max-height: 400px; +} +main .image-carousel .carousel-bullets { + position: absolute; + bottom: 0; + padding: 20px; + display: flex; + gap: 10px; +} +main .image-carousel .carousel-bullets .bullet { + cursor: pointer; + width: 8px; + height: 8px; + background-color: #6b7880; + border-radius: 100%; + box-shadow: 0 0 3px black; +} +main .image-carousel .carousel-bullets .bullet.active { + background-color: #d4d9dd; +} +@media screen and (max-width: 900px) { + main .image-carousel img { + max-height: 100%; + } + main .image-carousel .carousel-bullets { + gap: 15px; + } + main .image-carousel .carousel-bullets .bullet { + width: 12px; + height: 12px; + } +} main header { width: 100%; } @@ -95,7 +153,7 @@ main header nav ul li .submenu { } main header nav ul li.active a { color: #3c4144; - border-bottom: 1px solid; + border-bottom: 2px solid; } main header nav ul li:hover a { color: #3c4144; @@ -175,7 +233,7 @@ main #page-container { } main #page-container .page-header { background-image: url("/assets/images/wallpaper_binary.png"); - padding: 10px 0; + padding: 50px 0; } main #page-container .page-header h1 { padding: 15px 40px 0; @@ -197,7 +255,8 @@ main #page-container .page-header p * { padding: 15px 20px 0; } main #page-container .page-header p { - padding: 15px; + padding: 20px 20px 30px 40px; + text-align: justify; } } main #page-container .page-contents-center { @@ -211,6 +270,27 @@ main #page-container #home-page { gap: 20px; margin-bottom: 60px; } +main #page-container #home-page .page-header .big-logo { + display: flex; + justify-content: center; + align-items: center; + flex-direction: row; + gap: 20px; + padding: 20px; +} +main #page-container #home-page .page-header .big-logo img { + width: 200px; + max-width: 100%; +} +main #page-container #home-page .page-header .big-logo img.logo-text { + width: 300px; + max-width: 100%; +} +@media screen and (max-width: 560px) { + main #page-container #home-page .page-header .big-logo { + flex-direction: column; + } +} main #page-container #home-page .section-title { padding: 10px; margin: 0; @@ -219,53 +299,57 @@ main #page-container #home-page .section-title { } main #page-container #home-page .articles-displayer { margin: 0 auto 40px; - display: grid; - grid-template-columns: 50px auto 50px; } -main #page-container #home-page .articles-displayer .prev-btn, -main #page-container #home-page .articles-displayer .next-btn { +main #page-container #home-page .articles-displayer .prev-next-buttons { + display: flex; + justify-content: space-between; +} +main #page-container #home-page .articles-displayer .prev-next-buttons .prev-btn, +main #page-container #home-page .articles-displayer .prev-next-buttons .next-btn { border: none; - background-image: url("/assets/images/wallpaper_binary.png"); + background: none; + display: flex; + align-items: center; + gap: 10px; + padding: 5px 0; } -main #page-container #home-page .articles-displayer .prev-btn.disabled, -main #page-container #home-page .articles-displayer .next-btn.disabled { +main #page-container #home-page .articles-displayer .prev-next-buttons .prev-btn.disabled, +main #page-container #home-page .articles-displayer .prev-next-buttons .next-btn.disabled { + visibility: hidden; pointer-events: none; } -main #page-container #home-page .articles-displayer .prev-btn.active, -main #page-container #home-page .articles-displayer .next-btn.active { +main #page-container #home-page .articles-displayer .prev-next-buttons .prev-btn.active, +main #page-container #home-page .articles-displayer .prev-next-buttons .next-btn.active { cursor: pointer; color: #6b7880; } -main #page-container #home-page .articles-displayer .prev-btn.active:hover, -main #page-container #home-page .articles-displayer .next-btn.active:hover { - color: #d4d9dd; +main #page-container #home-page .articles-displayer .prev-next-buttons .prev-btn.active:hover, +main #page-container #home-page .articles-displayer .prev-next-buttons .next-btn.active:hover { + color: #3c4144; } -main #page-container #home-page .articles-displayer .next-btn.active::before { +main #page-container #home-page .articles-displayer .prev-next-buttons .next-btn.active::after { content: " "; border-style: solid; - border-width: 4px 4px 0 0; - width: 20px; - height: 20px; + border-width: 2px 2px 0 0; + width: 8px; + height: 8px; transform: rotate(45deg); display: flex; justify-content: center; align-items: center; flex-direction: row; - position: relative; } -main #page-container #home-page .articles-displayer .prev-btn.active::before { +main #page-container #home-page .articles-displayer .prev-next-buttons .prev-btn.active::before { content: " "; border-style: solid; - border-width: 4px 4px 0 0; - width: 20px; - height: 20px; + border-width: 2px 2px 0 0; + width: 8px; + height: 8px; transform: rotate(-135deg); display: flex; justify-content: center; align-items: center; flex-direction: row; - position: relative; - left: 8px; } main #page-container #home-page .articles-displayer article { display: grid; @@ -303,40 +387,11 @@ main #page-container #home-page .articles-displayer article .body { grid-row: 4; min-height: 250px; padding-bottom: 40px; + text-align: justify; } main #page-container #home-page .articles-displayer article .image-carousel { grid-row: 1/span 4; grid-column: 2; - overflow: hidden; - display: flex; - justify-content: center; - align-items: center; - flex-direction: row; - background-color: black; - position: relative; -} -main #page-container #home-page .articles-displayer article .image-carousel img { - position: absolute; - max-width: 100%; - max-height: 400px; -} -main #page-container #home-page .articles-displayer article .image-carousel .carousel-bullets { - position: absolute; - bottom: 0; - padding: 20px; - display: flex; - gap: 10px; -} -main #page-container #home-page .articles-displayer article .image-carousel .carousel-bullets .bullet { - cursor: pointer; - width: 8px; - height: 8px; - background-color: #6b7880; - border-radius: 100%; - box-shadow: 0 0 3px black; -} -main #page-container #home-page .articles-displayer article .image-carousel .carousel-bullets .bullet.active { - background-color: #d4d9dd; } main #page-container #home-page .articles-displayer article.article-placeholder { padding: 0; @@ -354,9 +409,6 @@ main #page-container #home-page .articles-displayer article.article-placeholder height: 30px; } @media screen and (max-width: 900px) { - main #page-container #home-page .articles-displayer { - grid-template-columns: 40px auto 40px; - } main #page-container #home-page .articles-displayer article { gap: 5px; grid-template-columns: 1fr; @@ -383,16 +435,6 @@ main #page-container #home-page .articles-displayer article.article-placeholder grid-row: 1; grid-column: 1; } - main #page-container #home-page .articles-displayer article .image-carousel img { - max-height: 100%; - } - main #page-container #home-page .articles-displayer article .image-carousel .carousel-bullets { - gap: 15px; - } - main #page-container #home-page .articles-displayer article .image-carousel .carousel-bullets .bullet { - width: 12px; - height: 12px; - } } main #page-container #home-page .grid-3 { gap: 30px; @@ -432,7 +474,7 @@ main #page-container #home-page .grid-3 .theme-card .card-title h2 { main #page-container #home-page .grid-3 .theme-card .card-description { background-image: url("/assets/images/wallpaper_binary.png"); flex: 1; - padding: 20px 30px 30px; + padding: 30px 20px; } main #page-container #home-page .grid-3 .theme-card .card-description p { margin: 0; @@ -463,7 +505,7 @@ main #page-container #home-page .grid-3 .theme-card:hover { main #page-container #home-page .grid-3 .theme-card .card-description { background-image: url("/assets/images/wallpaper_binary.png"); flex: 1; - padding: 10px 10px 20px; + padding: 20px 30px; } main #page-container #home-page .grid-3 .theme-card .card-description p { margin: 0; @@ -737,6 +779,137 @@ main #page-container #education-page .section-contents .infos-inscriptions .pric padding: 10px; } } +main #page-container #games-page .game-articles article { + display: grid; + grid-template-columns: 0.7fr 1fr; + gap: 0 20px; + margin: 20px; +} +main #page-container #games-page .game-articles article.game-article { + grid-template-rows: repeat(6, auto); + background-color: #3c4144; +} +main #page-container #games-page .game-articles article.game-article *:not(a) { + color: #d4d9dd; +} +main #page-container #games-page .game-articles article.game-article .game-title { + grid-column: 1/span 2; + background-color: #d4d9dd; + margin: 0; + padding: 30px 20px; + color: #6b7880; + font-size: 35px; + font-style: italic; +} +main #page-container #games-page .game-articles article.game-article .game-tags { + grid-column: 1; + display: flex; + gap: 10px; + flex-wrap: wrap; + margin: 10px 20px; +} +main #page-container #games-page .game-articles article.game-article .game-tags span { + font-size: 12px; + padding: 6px; + background-color: #ffd000; + color: #6b7880; + border-radius: 5px; + font-weight: 600; +} +main #page-container #games-page .game-articles article.game-article .game-subtitle { + grid-column: 1; + margin: 10px 20px 30px; +} +main #page-container #games-page .game-articles article.game-article .game-description { + grid-column: 1; + text-align: justify; + margin: 10px 20px 30px; +} +main #page-container #games-page .game-articles article.game-article .image-carousel { + grid-column: 2; + grid-row: 2/span 4; + height: 400px; +} +main #page-container #games-page .game-articles article.game-article .game-team { + grid-column: 1/span 2; +} +main #page-container #games-page .game-articles article.game-article .game-team h2 { + background-color: #d4d9dd; + color: #6b7880; + padding: 10px 20px; + font-style: italic; + font-size: 20px; + margin: 0; +} +main #page-container #games-page .game-articles article.game-article .game-team .team-members { + display: flex; + flex-direction: column; + gap: 30px; +} +main #page-container #games-page .game-articles article.game-article .game-team .team-members .team-member { + display: grid; + grid-template-columns: 150px 1fr; + grid-template-rows: auto auto 1fr; +} +main #page-container #games-page .game-articles article.game-article .game-team .team-members .team-member .team-member-img { + grid-row: 1/span 3; + overflow: hidden; +} +main #page-container #games-page .game-articles article.game-article .game-team .team-members .team-member .team-member-img img { + image-rendering: crisp-edges; + image-rendering: -moz-crisp-edges; + image-rendering: pixelated; + width: 100%; +} +main #page-container #games-page .game-articles article.game-article .game-team .team-members .team-member .team-member-title { + margin: 10px 10px 5px; +} +main #page-container #games-page .game-articles article.game-article .game-team .team-members .team-member .team-member-subtitle { + margin: 0 10px; + font-size: 14px; + color: #96a5ae; + font-style: italic; +} +main #page-container #games-page .game-articles article.game-article .game-team .team-members .team-member .team-member-body { + margin: 20px 10px 20px 30px; + text-align: justify; +} +main #page-container #games-page .game-articles article.placeholder { + height: 400px; +} +main #page-container #games-page .game-articles article.placeholder * { + background-color: #d4d9dd; +} +@media screen and (max-width: 900px) { + main #page-container #games-page .game-articles article { + grid-template-columns: 1fr; + } + main #page-container #games-page .game-articles article.game-article { + grid-template-rows: repeat(5, auto); + } + main #page-container #games-page .game-articles article.game-article .game-title { + grid-column: 1; + padding: 20px; + font-size: 25px; + } + main #page-container #games-page .game-articles article.game-article .image-carousel { + grid-column: 1; + grid-row: 2; + } + main #page-container #games-page .game-articles article.game-article .game-team { + grid-column: 1; + } + main #page-container #games-page .game-articles article.game-article .game-team .team-members .team-member { + grid-template-columns: 70px 1fr; + } + main #page-container #games-page .game-articles article.game-article .game-team .team-members .team-member .team-member-img { + grid-row: 1/span 2; + margin: 10px; + } + main #page-container #games-page .game-articles article.game-article .game-team .team-members .team-member .team-member-body { + grid-column: 1/span 2; + } +} main footer { display: flex; justify-content: center; @@ -745,12 +918,13 @@ main footer { flex-direction: column; width: 100%; background-image: url("/assets/images/wallpaper_binary.png"); - padding: 20px; + padding: 40px 20px; gap: 20px; font-size: 12px; } main footer span { color: #96a5ae; + text-align: center; } main footer .logo { display: flex; diff --git a/src/home-page-components/image-carousel.js b/src/generic-components/image-carousel.js similarity index 97% rename from src/home-page-components/image-carousel.js rename to src/generic-components/image-carousel.js index f32b41c70bc4a0471442a493806df662eb2b69b3..531caa68828c88ecc4df23a370c9d32f254506ed 100644 --- a/src/home-page-components/image-carousel.js +++ b/src/generic-components/image-carousel.js @@ -43,7 +43,7 @@ class ImageCarousel { class: "image-carousel", contents: [ { tag: "img", src: images[showImageIndex] }, - { + images.length > 1 && { tag: "div", class: "carousel-bullets", contents: images.map((_, i) => { diff --git a/src/home-page-components/articles.js b/src/home-page-components/news-articles.js similarity index 52% rename from src/home-page-components/articles.js rename to src/home-page-components/news-articles.js index ee3dd7e64d35db8930ea873556fa6b6db304df4d..57eacfb7a5a7b5f7192fed5538fff1e5d23cf9d4 100644 --- a/src/home-page-components/articles.js +++ b/src/home-page-components/news-articles.js @@ -1,11 +1,11 @@ "use strict"; -const { articles_url } = require("../../constants"); -const { fetchjson, fetchtext } = require("../lib/fetch"); +const { news_articles_url } = require("../../constants"); const objectHtmlRenderer = require("../lib/object-html-renderer"); -const ImageCarousel = require("./image-carousel"); +const ImageCarousel = require("../generic-components/image-carousel"); +const { loadArticles, getArticleDate, getArticleBody } = require("../lib/article-utils"); -class Articles { +class NewsArticles { constructor() { this.id = performance.now().toString(); this.state = { @@ -17,35 +17,11 @@ class Articles { } loadArticles() { - fetchjson(`${articles_url}/index.json`) - .then(json => { - Promise.all( - json.map(async articlePath => { - const art = await fetchjson(`${articles_url}/${articlePath}`); - const tmpSplit = articlePath.split("/"); - tmpSplit.pop(); - const absArtPath = `${articles_url}/${tmpSplit.join("/")}`; - return Object.assign(art, { path: absArtPath }); - }) - ) - .then(articles => this.setArticles(articles)) - .catch(e => console.log(e)); - }) - .catch(e => console.log(e)); - } - - async setArticles(articles) { - for (const article of articles) { - if (article.content_text.indexOf("<file>") !== -1) { - const txtPath = article.content_text.replace("<file>", ""); - const txtValue = await fetchtext(`${article.path}/${txtPath}`); - article.content_text = txtValue; - } - article.date = new Date(article.date); - } - this.state.articles = articles.sort((a, b) => a.date - b.date); - this.state.showArticleIndex = this.state.articles.length - 1; - this.refresh(); + loadArticles(news_articles_url).then(articles => { + this.state.articles = articles; + this.state.showArticleIndex = this.state.articles.length - 1; + this.refresh(); + }); } refresh() { @@ -54,25 +30,6 @@ class Articles { }); } - getArticleDate(date) { - return `${date.getDate()}-${date.getMonth() + 1}-${date.getFullYear()}`; - } - - getArticleBody(text) { - return text - .split(" ") - .map(word => { - if (word.includes("http://") || word.includes("https://")) { - const splitword = word.split("||"); - const href = splitword[0]; - const text = splitword.length > 1 ? splitword[1] : href; - return `<a href=${href} target="_blank">${text}</a>`; - } else return word; - }) - .join(" ") - .replaceAll("\n", "<br/>"); - } - renderArticle(articleData) { return { tag: "article", @@ -80,7 +37,7 @@ class Articles { { tag: "div", class: "date", - contents: [{ tag: "span", contents: this.getArticleDate(articleData.date) }], + contents: [{ tag: "span", contents: getArticleDate(articleData.date) }], }, { tag: "div", @@ -108,7 +65,7 @@ class Articles { contents: [ { tag: "p", - contents: this.getArticleBody(articleData.content_text), + contents: getArticleBody(articleData.body), }, ], }, @@ -158,21 +115,29 @@ class Articles { contents: articles.length > 0 ? [ - { - tag: "button", - class: `prev-btn ${!showPrev ? "disabled" : "active"}`, - onclick: this.handleChangeArticle.bind(this, "prev"), - }, this.renderArticle(articles[showArticleIndex]), { - tag: "button", - class: `next-btn ${!showNext ? "disabled" : "active"}`, - onclick: this.handleChangeArticle.bind(this, "next"), + tag: "div", + class: "prev-next-buttons", + contents: [ + { + tag: "button", + class: `prev-btn ${!showPrev ? "disabled" : "active"}`, + contents: "Précédent", + onclick: this.handleChangeArticle.bind(this, "prev"), + }, + { + tag: "button", + class: `next-btn ${!showNext ? "disabled" : "active"}`, + contents: "Suivant", + onclick: this.handleChangeArticle.bind(this, "next"), + }, + ], }, ] - : [{tag:"div"},this.renderArticlePlaceholder(), {tag:"div"}], + : [this.renderArticlePlaceholder()], }; } } -module.exports = Articles; +module.exports = NewsArticles; diff --git a/src/homepage.js b/src/homepage.js index a7b183010d17afcf5cfb51bfc9be57c9120646df..5bf52e5b45bd6d3360938fa2ba3eb5dcd613a93d 100644 --- a/src/homepage.js +++ b/src/homepage.js @@ -1,6 +1,7 @@ "use strict"; -const Articles = require("./home-page-components/articles"); +const { images_url } = require("../constants"); +const NewsArticles = require("./home-page-components/news-articles"); const ThemeCard = require("./home-page-components/theme-card"); class HomePage { @@ -17,6 +18,18 @@ class HomePage { tag: "div", class: "page-header", contents: [ + { + tag: "div", + class: "big-logo page-contents-center", + contents: [ + { tag: "img", src: `${images_url}/logo_kuadrado.svg` }, + { + tag: "img", + class: "logo-text", + src: `${images_url}/logo_kuadrado_txt.svg`, + }, + ], + }, { tag: "h1", contents: "Kuadrado Software", class: "page-contents-center" }, { tag: "p", @@ -33,7 +46,7 @@ class HomePage { class: "page-contents-center", contents: [ { tag: "h2", contents: "Actu", class: "section-title bg-blue" }, - new Articles().render(), + new NewsArticles().render(), ], }, { diff --git a/src/homepage.scss b/src/homepage.scss index 8ee0bc2554b60555ebae85bd7e81cda82603dcb3..b1a4555bcc9d94e16efa6548b3d0871d625743a6 100644 --- a/src/homepage.scss +++ b/src/homepage.scss @@ -3,6 +3,24 @@ flex-direction: column; gap: 20px; margin-bottom: 60px; + .page-header { + .big-logo { + @include flex-center; + gap: 20px; + padding: 20px; + img { + width: 200px; + max-width: 100%; + &.logo-text { + width: 300px; + max-width: 100%; + } + } + @media screen and (max-width: $screen_s) { + flex-direction: column; + } + } + } .section-title { padding: 10px; margin: 0; @@ -12,52 +30,57 @@ .articles-displayer { margin: 0 auto 40px; - display: grid; - grid-template-columns: 50px auto 50px; - .prev-btn, - .next-btn { - border: none; - background-image: url("/assets/images/wallpaper_binary.png"); - &.disabled { - pointer-events: none; - } - &.active { - cursor: pointer; - color: $medium_grey; - &:hover { - color: $light_0; + .prev-next-buttons { + display: flex; + justify-content: space-between; + .prev-btn, + .next-btn { + border: none; + background: none; + display: flex; + align-items: center; + gap: 10px; + padding: 5px 0; + &.disabled { + visibility: hidden; + pointer-events: none; + } + &.active { + cursor: pointer; + color: $medium_grey; + &:hover { + color: $dark_2; + } } } - } - .next-btn { - &.active { - &::before { - content: " "; - border-style: solid; - border-width: 4px 4px 0 0; - width: 20px; - height: 20px; - transform: rotate(45deg); - @include flex-center; - position: relative; + .next-btn { + &.active { + &::after { + content: " "; + border-style: solid; + border-width: 2px 2px 0 0; + width: 8px; + height: 8px; + transform: rotate(45deg); + @include flex-center; + } } } - } - .prev-btn { - &.active { - &::before { - content: " "; - border-style: solid; - border-width: 4px 4px 0 0; - width: 20px; - height: 20px; - transform: rotate(-135deg); - @include flex-center; - position: relative; - left: 8px; + .prev-btn { + &.active { + &::before { + content: " "; + border-style: solid; + border-width: 2px 2px 0 0; + width: 8px; + height: 8px; + transform: rotate(-135deg); + @include flex-center; + } } } } + article { display: grid; gap: 5px 20px; @@ -93,37 +116,11 @@ grid-row: 4; min-height: 250px; padding-bottom: 40px; + text-align: justify; } .image-carousel { grid-row: 1 / span 4; grid-column: 2; - overflow: hidden; - @include flex-center; - background-color: black; - position: relative; - img { - position: absolute; - max-width: 100%; - max-height: 400px; - } - .carousel-bullets { - position: absolute; - bottom: 0; - padding: 20px; - display: flex; - gap: 10px; - .bullet { - cursor: pointer; - width: 8px; - height: 8px; - background-color: $medium_grey; - border-radius: 100%; - box-shadow: 0 0 3px black; - &.active { - background-color: $light_0; - } - } - } } &.article-placeholder { padding: 0; @@ -142,7 +139,6 @@ } } @media screen and (max-width: $screen_l) { - grid-template-columns: 40px auto 40px; article { gap: 5px; grid-template-columns: 1fr; @@ -167,16 +163,6 @@ .image-carousel { grid-row: 1; grid-column: 1; - img { - max-height: 100%; - } - .carousel-bullets { - gap: 15px; - .bullet { - width: 12px; - height: 12px; - } - } } } } @@ -215,7 +201,7 @@ .card-description { background-image: url("/assets/images/wallpaper_binary.png"); flex: 1; - padding: 20px 30px 30px; + padding: 30px 20px; p { margin: 0; color: $blue_3; @@ -248,7 +234,7 @@ .card-description { background-image: url("/assets/images/wallpaper_binary.png"); flex: 1; - padding: 10px 10px 20px; + padding: 20px 30px; p { margin: 0; color: $blue_3; diff --git a/src/lib/article-utils.js b/src/lib/article-utils.js new file mode 100644 index 0000000000000000000000000000000000000000..0d68c2a85baef65b0e91f30949c2b6fc11f04142 --- /dev/null +++ b/src/lib/article-utils.js @@ -0,0 +1,71 @@ +"use strict"; + +const { fetchjson, fetchtext } = require("./fetch"); + +function getArticleBody(text) { + return text + .split(" ") + .map(word => { + if (word.includes("http://") || word.includes("https://")) { + const splitword = word.split("||"); + const href = splitword[0].match(/http.+/); + const text = splitword.length > 1 ? splitword[1].replaceAll("_", " ") : href; + return word.replace(/http.*/, `<a href=${href} target="_blank">${text}</a>`); + } else return word; + }) + .join(" ") + .replaceAll("\n", "<br/>"); +} + +function getArticleDate(date) { + return `${date.getDate()}-${date.getMonth() + 1}-${date.getFullYear()}`; +} + +function loadArticles(dir_url) { + return new Promise((resolve, reject) => { + fetchjson(`${dir_url}/index.json`) + .then(json => { + Promise.all( + json.map(async articlePath => { + const art = await fetchjson(`${dir_url}/${articlePath}`); + const tmpSplit = articlePath.split("/"); + tmpSplit.pop(); + const absArtPath = `${dir_url}/${tmpSplit.join("/")}`; + return Object.assign(art, { path: absArtPath }); + }) + ) + .then(articles => { + populateArticles(articles) + .then(completeArticles => resolve(completeArticles)) + .catch(e => reject(e)); + }) + .catch(e => reject(e)); + }) + .catch(e => console.log(e)); + }); +} + +function populateArticles(articles) { + return new Promise((resolve, reject) => { + Promise.all( + articles.map(async article => { + if (article.body.indexOf("<file>") !== -1) { + const txtPath = article.body.replace("<file>", ""); + const textValue = await fetchtext(`${article.path}/${txtPath}`); + article.body = textValue; + article.date = article.date ? new Date(article.date) : undefined; + } + return article; + }) + ) + .then(completeArticles => resolve(completeArticles.sort((a, b) => a.date - b.date))) + .catch(e => reject(e)); + }); +} + +module.exports = { + loadArticles, + getArticleBody, + getArticleDate, + populateArticles, +}; diff --git a/src/pages/games/components/game-article.js b/src/pages/games/components/game-article.js new file mode 100644 index 0000000000000000000000000000000000000000..12401599e47e332948016da93f589ca471bb19f8 --- /dev/null +++ b/src/pages/games/components/game-article.js @@ -0,0 +1,98 @@ +"use strict"; + +const ImageCarousel = require("../../../generic-components/image-carousel"); +const { getArticleBody } = require("../../../lib/article-utils"); + +class TeamMember { + constructor(props) { + this.props = props; + } + + render() { + const { title, subtitle, body, images, path } = this.props; + return { + tag: "div", + class: "team-member", + contents: [ + { + tag: "div", + class: "team-member-img", + contents: [{ tag: "img", src: images.map(im => `${path}/images/${im}`)[0] }], + }, + { + tag: "h3", + class: "team-member-title", + contents: title, + }, + { + tag: "strong", + class: "team-member-subtitle", + contents: subtitle, + }, + { + tag: "p", + class: "team-member-body", + contents: getArticleBody(body), + }, + ], + }; + } +} + +class GameArticle { + constructor(props) { + this.props = props; + } + + render() { + const { title, tags, body, subtitle, images, path, team_subarticles } = this.props; + return { + tag: "article", + class: "game-article", + contents: [ + { + tag: "h2", + class: "game-title", + contents: title, + }, + { + tag: "div", + class: "game-tags", + contents: tags.map(tag => { + return { tag: "span", contents: tag }; + }), + }, + { + tag: "h3", + class: "game-subtitle", + contents: subtitle, + }, + { + tag: "div", + class: "game-description", + contents: getArticleBody(body), + }, + new ImageCarousel({ images: images.map(img => `${path}/images/${img}`) }).render(), + { + tag: "div", + class: "game-team", + contents: [ + { + tag: "h2", + contents: "L'équipe", + }, + { + tag: "div", + class: "team-members", + contents: team_subarticles.map(tsa => + new TeamMember({ ...tsa }).render() + ), + }, + ], + }, + ], + }; + } +} + +module.exports = GameArticle; diff --git a/src/pages/games/components/game-articles.js b/src/pages/games/components/game-articles.js new file mode 100644 index 0000000000000000000000000000000000000000..6f7fb8541a6a899e83e07738c9c81b8b5de96c23 --- /dev/null +++ b/src/pages/games/components/game-articles.js @@ -0,0 +1,66 @@ +"use strict"; + +const { game_articles_url } = require("../../../../constants"); +const { loadArticles, populateArticles } = require("../../../lib/article-utils"); +const objectHtmlRenderer = require("../../../lib/object-html-renderer"); +const GameArticle = require("./game-article"); + +class GameArticles { + constructor(props) { + this.props = props; + this.state = { + articles: [], + }; + this.id = performance.now(); + this.loadArticles(); + } + + loadArticles() { + loadArticles(game_articles_url) + .then(articles => { + Promise.all( + articles.map(async a => { + if (a.team_subarticles) { + a.team_subarticles = await populateArticles( + a.team_subarticles.map(sa => Object.assign(sa, { path: a.path })) + ); + } + return a; + }) + ).then(completeArticles => { + this.state.articles = completeArticles; + this.refresh(); + }); + }) + .catch(e => console.log(e)); + } + + renderPlaceholder() { + return { + tag: "article", + class: "placeholder", + contents: [{ tag: "div" }, { tag: "div" }], + }; + } + + refresh() { + objectHtmlRenderer.subRender(this.render(), document.getElementById(this.id), { + mode: "replace", + }); + } + + render() { + const { articles } = this.state; + return { + tag: "section", + class: "game-articles page-contents-center", + id: this.id, + contents: + articles.length > 0 + ? articles.map(article => new GameArticle({ ...article }).render()) + : [this.renderPlaceholder()], + }; + } +} + +module.exports = GameArticles; diff --git a/src/pages/games/games.js b/src/pages/games/games.js index c39b9d68572130f79b4d59860bc8d80fc0bf49fc..1e83cc0b8edf5bc1fae7094eee75454ae15b5fb0 100644 --- a/src/pages/games/games.js +++ b/src/pages/games/games.js @@ -1,5 +1,7 @@ "use strict"; +const GameArticles = require("./components/game-articles"); + class GamesPage { constructor(args) { Object.assign(this, args); @@ -8,14 +10,22 @@ class GamesPage { render() { return { tag: "div", + id:"games-page", contents: [ { tag: "div", class: "page-header", contents: [ - { tag: "h1", contents: "Jeux", class: "page-contents-center" } + { tag: "h1", contents: "Jeux", class: "page-contents-center" }, + { + tag: "p", + class: "page-contents-center", + contents: `Créer des jeux vidéos c'est cœur de ce qui nous passionne. + <br/>Retrouvez ici nos créations, à jouer en ligne ou à télécharger, et découvrez nos projets en cours.`, + }, ], }, + new GameArticles().render(), ], }; } diff --git a/src/pages/games/games.scss b/src/pages/games/games.scss new file mode 100644 index 0000000000000000000000000000000000000000..ce231c7004a6b2022fc9164f477351a5b01d7e48 --- /dev/null +++ b/src/pages/games/games.scss @@ -0,0 +1,137 @@ +#games-page { + .game-articles { + article { + display: grid; + grid-template-columns: 0.7fr 1fr; + gap: 0 20px; + margin: 20px; + &.game-article { + grid-template-rows: repeat(6, auto); + background-color: $dark_2; + *:not(a) { + color: $light_0; + } + .game-title { + grid-column: 1 / span 2; + background-color: $light_0; + margin: 0; + padding: 30px 20px; + color: $medium_grey; + font-size: 35px; + font-style: italic; + } + .game-tags { + grid-column: 1; + display: flex; + gap: 10px; + flex-wrap: wrap; + margin: 10px 20px; + span { + font-size: 12px; + padding: 6px; + background-color: $yellow_2; + color: $medium_grey; + border-radius: 5px; + font-weight: 600; + } + } + .game-subtitle { + grid-column: 1; + margin: 10px 20px 30px; + } + .game-description { + grid-column: 1; + text-align: justify; + margin: 10px 20px 30px; + } + + .image-carousel { + grid-column: 2; + grid-row: 2 / span 4; + height: 400px; + } + .game-team { + grid-column: 1 / span 2; + h2 { + background-color: $light_0; + color: $medium_grey; + padding: 10px 20px; + font-style: italic; + font-size: 20px; + margin: 0; + } + .team-members { + display: flex; + flex-direction: column; + gap: 30px; + .team-member { + display: grid; + grid-template-columns: 150px 1fr; + grid-template-rows: auto auto 1fr; + .team-member-img { + grid-row: 1 / span 3; + overflow: hidden; + img { + image-rendering: crisp-edges; + image-rendering: -moz-crisp-edges; + image-rendering: pixelated; + width: 100%; + } + } + .team-member-title { + margin: 10px 10px 5px; + } + .team-member-subtitle { + margin: 0 10px; + font-size: 14px; + color: $light_1; + font-style: italic; + } + .team-member-body { + margin: 20px 10px 20px 30px; + text-align: justify; + } + } + } + } + } + &.placeholder { + * { + background-color: $light_0; + } + height: 400px; + } + @media screen and (max-width: $screen_l) { + grid-template-columns: 1fr; + &.game-article { + grid-template-rows: repeat(5, auto); + .game-title { + grid-column: 1; + padding: 20px; + font-size: 25px; + } + + .image-carousel { + grid-column: 1; + grid-row: 2; + } + .game-team { + grid-column: 1; + .team-members { + .team-member { + grid-template-columns: 70px 1fr; + .team-member-img { + grid-row: 1 / span 2; + margin: 10px; + } + .team-member-body { + grid-column: 1 / span 2; + } + } + } + } + } + } + } + } +} diff --git a/src/style.scss b/src/style.scss index 40794a19af717b926dbb88ad10d387a4c798e124..787e57edea7320e547e3c6409666b8c4dd0cdfcd 100644 --- a/src/style.scss +++ b/src/style.scss @@ -40,6 +40,61 @@ main { flex-direction: column; align-items: center; min-height: 100vh; + + .warning-banner { + background: url("/assets/images/wallpaper_warning.svg"); + width: 100%; + height: 40px; + padding: 20px 10%; + @include flex-center; + strong { + font-size: 18px; + color: $blue_1; + } + } + + .image-carousel { + overflow: hidden; + @include flex-center; + background-color: black; + position: relative; + img { + position: absolute; + max-width: 100%; + max-height: 400px; + } + .carousel-bullets { + position: absolute; + bottom: 0; + padding: 20px; + display: flex; + gap: 10px; + .bullet { + cursor: pointer; + width: 8px; + height: 8px; + background-color: $medium_grey; + border-radius: 100%; + box-shadow: 0 0 3px black; + &.active { + background-color: $light_0; + } + } + } + @media screen and (max-width: $screen_l) { + img { + max-height: 100%; + } + .carousel-bullets { + gap: 15px; + .bullet { + width: 12px; + height: 12px; + } + } + } + } + header { width: 100%; nav { @@ -97,7 +152,7 @@ main { &.active { a { color: $dark_2; - border-bottom: 1px solid; + border-bottom: 2px solid; } } &:hover { @@ -194,16 +249,18 @@ main { } @import "./homepage.scss"; @import "./pages/education/education.scss"; + @import "./pages/games/games.scss"; } footer { @include flex-center-col; width: 100%; background-image: url("/assets/images/wallpaper_binary.png"); - padding: 20px; + padding: 40px 20px; gap: 20px; font-size: 12px; span { color: $light_1; + text-align: center; } .logo { @include flex-center; diff --git a/src/template/template.js b/src/template/template.js index 74a5dbcffb09cf1b8cd32deac39ebd5cf8e78d37..ab81e0b593b094345ef51561a5f0126872fb1899 100644 --- a/src/template/template.js +++ b/src/template/template.js @@ -1,5 +1,6 @@ "use strict"; +const { in_construction } = require("../../config"); const { images_url } = require("../../constants"); const NavBar = require("./components/navbar"); @@ -15,8 +16,19 @@ class Template { tag: "header", contents: [new NavBar().render()], }, + in_construction && { + tag: "section", + class: "warning-banner", + contents: [ + { + tag: "strong", + class: "page-contents-center", + contents: "Site en construction ...", + }, + ], + }, { - tag: "div", + tag: "section", id: "page-container", contents: [this.props.page.render()], }, @@ -33,14 +45,15 @@ class Template { }, { tag: "img", - class:"text-logo", + class: "text-logo", src: `${images_url}/logo_kuadrado_txt.svg`, }, ], }, { - tag:"span", - contents: "Toutes les images du site ont été réalisées par nos soins et peuvent être réutilisées pour un usage personnel." + tag: "span", + contents: + "Toutes les images du site ont été réalisées par nos soins et peuvent être réutilisées pour un usage personnel.", }, { tag: "a", diff --git a/src/theme.scss b/src/theme.scss index e7ae8e2f43eb36d7f81e5b80c66e2d8bc265d445..54e0053f7128de9facf8a14a397e7ef68577236b 100644 --- a/src/theme.scss +++ b/src/theme.scss @@ -36,7 +36,7 @@ $page_contents_center_width: 1300px; @mixin page-header { background-image: url("/assets/images/wallpaper_binary.png"); - padding: 10px 0; + padding: 50px 0; h1 { padding: 15px 40px 0; font-size: 25px; @@ -57,7 +57,8 @@ $page_contents_center_width: 1300px; padding: 15px 20px 0; } p { - padding: 15px; + padding: 20px 20px 30px 40px; + text-align: justify; } } }