diff --git a/Makefile b/Makefile index 61dd6ea492e6d26eb24371a49b0c9bcd6335f5e7..ff3edcf9c4fdd3b8859ea796ebdb98ee05a43e94 100644 --- a/Makefile +++ b/Makefile @@ -22,6 +22,9 @@ doc: bash-api: docker exec -it kuadrado_server bash +bash-mongo: + docker exec -it kuadradodb bash + build-website: npm run --prefix ./website build-prod diff --git a/admin-frontend/src/components/articles-list.js b/admin-frontend/src/components/articles-list.js index 477e13d964fe63efeb805aa7b1740b7960d37757..7dff1a01f6e4e4522ec37bec11dd4bd00747a46d 100644 --- a/admin-frontend/src/components/articles-list.js +++ b/admin-frontend/src/components/articles-list.js @@ -14,7 +14,7 @@ class ArticleList { fetch_list() { fetch_all_articles() .then(articles => { - this.state.articles = articles; + this.state.articles = articles.sort((a, b) => a.display_priority_index > b.display_priority_index); this.refresh_list(); }) .catch(err => console.log(err)) diff --git a/admin-frontend/src/components/create-article-form.js b/admin-frontend/src/components/create-article-form.js index 494687dfe9d13555cd1a693eddb6753b6b74a08a..7f5b5b2755df4023b9e097474b17e1581436285c 100644 --- a/admin-frontend/src/components/create-article-form.js +++ b/admin-frontend/src/components/create-article-form.js @@ -23,6 +23,10 @@ class CreateArticleForm { this.state.output[field] = e.target.value; } + handle_nb_input(field, e) { + this.state.output[field] = parseInt(e.target.value); + } + handle_del_detail(index) { this.state.output.details.splice(index, 1); this.refresh_details(); @@ -222,6 +226,10 @@ class CreateArticleForm { src: `${images_url}/${img}` } }) + }, + { + tag: "div", + contents: `Priority: ${article.display_priority_index}` } ] } @@ -276,20 +284,43 @@ class CreateArticleForm { oninput: this.handle_text_input.bind(this, "category") }, { - tag: "select", value: this.state.output.locale, - onchange: e => this.state.output.locale = e.target.value, - contents: [{ - tag: "option", - value: "", - contents: "-- LOCALE --" - }].concat(["fr", "en", "es"].map(loc => { - return { - tag: "option", - value: loc, - contents: loc, - selected: this.state.output.locale === loc + tag: "div", + style_rules: { + display: "grid", + gridTemplateColumns: "1fr auto", + gap: "10px", + }, + contents: [ + { + tag: "select", value: this.state.output.locale, + onchange: e => this.state.output.locale = e.target.value, + contents: [{ + tag: "option", + value: "", + contents: "-- LOCALE --" + }].concat(["fr", "en"].map(loc => { + return { + tag: "option", + value: loc, + contents: loc, + selected: this.state.output.locale === loc + } + })) + }, + { + tag: "div", + style_rules: { display: "grid", gap: "5px" }, + contents: [ + { tag: "label", contents: "Display priority" }, + { + tag: "input", type: "number", + step: 1, min: 0, max: 127, + value: this.state.output.display_priority_index || 1, + onchange: this.handle_nb_input.bind(this, "display_priority_index"), + }, + ] } - })) + ] }, { tag: "input", type: "text", diff --git a/admin-frontend/src/components/update-article-form.js b/admin-frontend/src/components/update-article-form.js index 1db58174b65074cbdd98e4f1006c807dae8805c4..f1310f5322fda8f9b2dd337de292f07308a848b5 100644 --- a/admin-frontend/src/components/update-article-form.js +++ b/admin-frontend/src/components/update-article-form.js @@ -1,6 +1,6 @@ "use strict"; -const { fetch_article_by_title, fetch_delete_article, fetch_article } = require("../xhr"); +const { fetch_delete_article, fetch_article } = require("../xhr"); const ArticleList = require("./articles-list"); const CreateArticleForm = require("./create-article-form"); diff --git a/dev.docker-compose.yml b/dev.docker-compose.yml index bc1bd9724d27d18a7bd42b25e01c36635c56fd0a..0adb1e276001171a192bd4f17e6e0c97f250e09d 100644 --- a/dev.docker-compose.yml +++ b/dev.docker-compose.yml @@ -31,5 +31,6 @@ services: volumes: - ./mongo/init-mongo.js:/docker-entrypoint-initdb.d/init-mongo.js:ro - /var/${DATABASE_NAME}-volume:/data/db + - ./mongo/scripts:/mongo-scripts ports: - "27017-27019:27017-27019" diff --git a/docker-compose.yml b/docker-compose.yml index 35cef6e09d669b7b328b8afc4ee37f9b9d572f8f..9bb27056ac8d5f468e91fe9bfdcb4d2d30ab6d39 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -28,5 +28,6 @@ services: volumes: - ./mongo/init-mongo.js:/docker-entrypoint-initdb.d/init-mongo.js:ro - /var/${DATABASE_NAME}-volume:/data/db + - ./mongo/scripts:/mongo-scripts ports: - "27017-27019:27017-27019" diff --git a/mongo/scripts/migration.js b/mongo/scripts/migration.js new file mode 100644 index 0000000000000000000000000000000000000000..33329ed1e729ddefed4f3fea43d260257c0672c5 --- /dev/null +++ b/mongo/scripts/migration.js @@ -0,0 +1,13 @@ +db = new Mongo().getDB("kuadradodb"); + +adminname = _getEnv("MONGO_INITDB_NON_ROOT_USERNAME"); +adminpwd = _getEnv("MONGO_INITDB_NON_ROOT_PASSWORD"); + +db.auth(adminname, adminpwd); + +articles = db.getCollection("articles"); + +articles.update({}, + { $set: { "display_priority_index": NumberInt(1) } }, + { upsert: false, multi: true } +); \ No newline at end of file diff --git a/src/model/article.rs b/src/model/article.rs index f96872206f99ff027fbfd8829363328b26d16f23..f080e53a5582557d5ffad2eba65807637b9c8ff8 100644 --- a/src/model/article.rs +++ b/src/model/article.rs @@ -25,6 +25,7 @@ pub struct Article { pub images: Vec<String>, pub category: String, pub locale: String, + pub display_priority_index: i8, } impl Article { @@ -49,6 +50,7 @@ impl Article { images: vec!["an_image.png".to_string()], category: "testing".to_string(), locale: "fr".to_string(), + display_priority_index: 1, } } } diff --git a/src/service/articles.rs b/src/service/articles.rs index 13219d6e1ef5e7a4f9886513634ae6ce23f46ad5..a1287cc0157e2d39f02899781c9297d112082314 100644 --- a/src/service/articles.rs +++ b/src/service/articles.rs @@ -126,14 +126,14 @@ pub async fn get_articles_by_category( Ok(article) => { results.push(article); } - Err(_) => { - return HttpResponse::InternalServerError().finish(); + Err(e) => { + return HttpResponse::InternalServerError().body(format!("{:#?}", e)); } } } HttpResponse::Ok().json(results) } - Err(_) => HttpResponse::InternalServerError().finish(), + Err(e) => HttpResponse::InternalServerError().body(format!("{:#?}", e)), } } @@ -187,14 +187,14 @@ pub async fn get_all_articles(app_state: Data<AppState>) -> impl Responder { Ok(article) => { results.push(article); } - Err(_) => { - return HttpResponse::InternalServerError().finish(); + Err(e) => { + return HttpResponse::InternalServerError().body(format!("{:#?}", e)); } } } HttpResponse::Ok().json(results) } - Err(_) => HttpResponse::InternalServerError().finish(), + Err(e) => HttpResponse::InternalServerError().body(format!("{:#?}", e)), } } diff --git a/website/src/lib/article-utils.js b/website/src/lib/article-utils.js index fbce5d4096d62bbe9affe2d6a2e90a935369b109..1dcb6c967438cd13b46d507ba28fc2431f255670 100644 --- a/website/src/lib/article-utils.js +++ b/website/src/lib/article-utils.js @@ -14,8 +14,13 @@ function loadArticles(category, locale) { return fetch_json_or_error_text(`/articles/${category}/${locale}`); } +function sortArticles(articles, byField, mode = "desc") { + return articles.sort((a, b) => mode === "desc" ? a[byField] > b[byField] : a[byField] < b[byField]) +} + module.exports = { loadArticles, getArticleBody, getArticleDate, + sortArticles, }; diff --git a/website/src/pages/education/components/edu-articles.js b/website/src/pages/education/components/edu-articles.js index 0c2ba4ede0f4ef12ec8349eea87a9538f085580b..0b79891fa10946c02df039882bf681bdebd581a5 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 } = require("../../../lib/article-utils"); +const { loadArticles, sortArticles } = require("../../../lib/article-utils"); const translator = require("ks-cheap-translator"); const t = translator.trad.bind(translator); const EduArticle = require("./edu-article"); @@ -18,7 +18,7 @@ class EduArticles { loadArticles() { loadArticles("education", translator.locale) .then(articles => { - this.state.articles = articles; + this.state.articles = sortArticles(articles, "display_priority_index"); }) .catch(e => console.log(e)) .finally(() => { diff --git a/website/src/pages/games/components/game-articles.js b/website/src/pages/games/components/game-articles.js index b47b186c4531d0c238ff8dc89bc127c29893585f..194904c6361acd901409d1e0a2d7427a79c5e24f 100644 --- a/website/src/pages/games/components/game-articles.js +++ b/website/src/pages/games/components/game-articles.js @@ -1,6 +1,6 @@ "use strict"; -const { loadArticles } = require("../../../lib/article-utils"); +const { loadArticles, sortArticles } = require("../../../lib/article-utils"); const GameArticle = require("./game-article"); const translator = require("ks-cheap-translator"); @@ -17,7 +17,7 @@ class GameArticles { loadArticles() { loadArticles("games", translator.locale) .then(articles => { - this.state.articles = articles; + this.state.articles = sortArticles(articles, "display_priority_index"); this.refresh(); }) .catch(e => console.log(e)); diff --git a/website/src/pages/software-development/components/software-articles.js b/website/src/pages/software-development/components/software-articles.js index 7ec6fce092a9b13a30e5432097d695519f9e20db..331c1831ce1b637ef3d49bdec81a5ccd401ac7bb 100644 --- a/website/src/pages/software-development/components/software-articles.js +++ b/website/src/pages/software-development/components/software-articles.js @@ -1,6 +1,6 @@ "use strict"; -const { loadArticles } = require("../../../lib/article-utils"); +const { loadArticles, sortArticles } = require("../../../lib/article-utils"); const SoftwareArticle = require("./software-article"); const translator = require("ks-cheap-translator"); @@ -15,11 +15,12 @@ class SoftwareArticles { } loadArticles() { - loadArticles("software", translator.locale).then(articles => { - this.state.articles = articles; - this.refresh(); - this.fixScroll(); - }).catch(e => console.log(e)) + loadArticles("software", translator.locale) + .then(articles => { + this.state.articles = sortArticles(articles, "display_priority_index");; + this.refresh(); + this.fixScroll(); + }).catch(e => console.log(e)) } renderPlaceholder() {