From a696c3a5c98b266d196ec5adf84065ff9d1b97d6 Mon Sep 17 00:00:00 2001 From: Martin Eyben Date: Wed, 4 Dec 2024 10:50:01 +0000 Subject: [PATCH] feat: add pagination --- back-end/src/static/js/paginator.js | 283 ++++++++++++++++++ back-end/src/static/js/table_pagination.js | 12 + back-end/src/templates/box.ejs | 45 +-- back-end/src/templates/boxes.ejs | 55 ++-- back-end/src/templates/member.ejs | 121 ++++---- back-end/src/templates/members.ejs | 52 ++-- back-end/src/templates/membersAndNbModels.ejs | 60 ++-- back-end/src/templates/model.ejs | 31 +- back-end/src/templates/models.ejs | 47 +-- back-end/src/templates/partials/links.ejs | 3 + back-end/src/templates/piece.ejs | 39 +-- back-end/src/templates/pieces.ejs | 45 +-- 12 files changed, 571 insertions(+), 222 deletions(-) create mode 100644 back-end/src/static/js/paginator.js create mode 100644 back-end/src/static/js/table_pagination.js diff --git a/back-end/src/static/js/paginator.js b/back-end/src/static/js/paginator.js new file mode 100644 index 0000000..1f9e139 --- /dev/null +++ b/back-end/src/static/js/paginator.js @@ -0,0 +1,283 @@ +/***************************************************** + * Paginator Function * + ***************************************************** + * config : { + * get_rows : function used to select rows to do pagination on + * If no function is provided, checks for a config.table element and looks for rows in there to page + * + * box : Empty element that will have page buttons added to it + * If no config.box is provided, but a config.table is, then the page buttons will be added using the table + * + * table : table element to be paginated + * not required if a get_rows function is provided + * + * rows_per_page : number of rows to display per page + * default number is 10 + * + * page: page to display + * default page is 1 + * + * box_mode: "list", "buttons", or function. determines how the page number buttons are built. + * "list" builds the page index in list format and adds class "pagination" to the ul element. Meant for use with bootstrap + * "buttons" builds the page index out of buttons + * if this field is a function, it will be passed the config object as its only param and assumed to build the page index buttons + * + * page_options: false or [{text: , value: }, ... ] used to set what the dropdown menu options are available, resets rows_per_page value + * false prevents the options from being displayed + * [{text: , value: }, ... ] allows you to customize what values can be chosen, a value of 0 will display all the table's rows. + * the default setup is + * [ + * { value: 5, text: '5' }, + * { value: 10, text: '10' }, + * { value: 20, text: '20' }, + * { value: 50, text: '50' }, + * { value: 100,text: '100' }, + * { value: 0, text: 'All' } + * ] + * + * active_class: set the class for page buttons to have when active. + * defaults to "active" + * + * disable: true or false, shows all rows of the table and hides pagination controlls if set to true. + * + * tail_call: function to be called after paginator is done. + * + * } + */ +function paginator(config) { + // throw errors if insufficient parameters were given + if (typeof config != "object") + throw "Paginator was expecting a config object!"; + if (typeof config.get_rows != "function" && !(config.table instanceof Element)) + throw "Paginator was expecting a table or get_row function!"; + + // get/set if things are disabled + if (typeof config.disable == "undefined") { + config.disable = false; + } + + // get/make an element for storing the page numbers in + var box; + if (!(config.box instanceof Element)) { + config.box = document.createElement("div"); + } + box = config.box; + + // get/make function for getting table's rows + if (typeof config.get_rows != "function") { + config.get_rows = function () { + var table = config.table + var tbody = table.getElementsByTagName("tbody")[0]||table; + + // get all the possible rows for paging + // exclude any rows that are just headers or empty + children = tbody.children; + var trs = []; + for (var i=0;i 0) { + trs.push(children[i]); + } + } + } + + return trs; + } + } + var get_rows = config.get_rows; + var trs = get_rows(); + + // get/set rows per page + if (typeof config.rows_per_page == "undefined") { + var selects = box.getElementsByTagName("select"); + if (typeof selects != "undefined" && (selects.length > 0 && typeof selects[0].selectedIndex != "undefined")) { + config.rows_per_page = selects[0].options[selects[0].selectedIndex].value; + } else { + config.rows_per_page = 10; + } + } + var rows_per_page = config.rows_per_page; + + // get/set current page + if (typeof config.page == "undefined") { + config.page = 1; + } + var page = config.page; + + // get page count + var pages = (rows_per_page > 0)? Math.ceil(trs.length / rows_per_page):1; + + // check that page and page count are sensible values + if (pages < 1) { + pages = 1; + } + if (page > pages) { + page = pages; + } + if (page < 1) { + page = 1; + } + config.page = page; + + // hide rows not on current page and show the rows that are + for (var i=0;i 0) { + if (i < page*rows_per_page && i >= (page-1)*rows_per_page) { + trs[i].style.display = trs[i]["data-display"]; + } else { + // Only hide if pagination is not disabled + if (!config.disable) { + trs[i].style.display = "none"; + } else { + trs[i].style.display = trs[i]["data-display"]; + } + } + } else { + trs[i].style.display = trs[i]["data-display"]; + } + } + + // page button maker functions + config.active_class = config.active_class||"active"; + if (typeof config.box_mode != "function" && config.box_mode != "list" && config.box_mode != "buttons") { + config.box_mode = "button"; + } + if (typeof config.box_mode == "function") { + config.box_mode(config); + } else { + var make_button; + if (config.box_mode == "list") { + make_button = function (symbol, index, config, disabled, active) { + var li = document.createElement("li"); + var a = document.createElement("a"); + a.href = "#"; + a.innerHTML = symbol; + a.addEventListener("click", function (event) { + event.preventDefault(); + this.parentNode.click(); + return false; + }, false); + li.appendChild(a); + + var classes = []; + if (disabled) { + classes.push("disabled"); + } + if (active) { + classes.push(config.active_class); + } + li.className = classes.join(" "); + li.addEventListener("click", function () { + if (this.className.split(" ").indexOf("disabled") == -1) { + config.page = index; + paginator(config); + } + }, false); + return li; + } + } else { + make_button = function (symbol, index, config, disabled, active) { + var button = document.createElement("button"); + button.innerHTML = symbol; + button.addEventListener("click", function (event) { + event.preventDefault(); + if (this.disabled != true) { + config.page = index; + paginator(config); + } + return false; + }, false); + if (disabled) { + button.disabled = true; + } + if (active) { + button.className = config.active_class; + } + return button; + } + } + + // make page button collection + var page_box = document.createElement(config.box_mode == "list"?"ul":"div"); + if (config.box_mode == "list") { + page_box.className = "pagination"; + } + + var left = make_button("«", (page>1?page-1:1), config, (page == 1), false); + page_box.appendChild(left); + + for (var i=1;i<=pages;i++) { + var li = make_button(i, i, config, false, (page == i)); + page_box.appendChild(li); + } + + var right = make_button("»", (pages>page?page+1:page), config, (page == pages), false); + page_box.appendChild(right); + if (box.childNodes.length) { + while (box.childNodes.length > 1) { + box.removeChild(box.childNodes[0]); + } + box.replaceChild(page_box, box.childNodes[0]); + } else { + box.appendChild(page_box); + } + } + + // make rows per page selector + if (!(typeof config.page_options == "boolean" && !config.page_options)) { + if (typeof config.page_options == "undefined") { + config.page_options = [ + { value: 5, text: '5' }, + { value: 10, text: '10' }, + { value: 20, text: '20' }, + { value: 50, text: '50' }, + { value: 100,text: '100' }, + { value: 0, text: 'All' } + ]; + } + var options = config.page_options; + var select = document.createElement("select"); + for (var i=0;i { + paginator({ + table: t.children[0], + box: t.children[1], + active_class: "color_page" + }); + }); +}, false); + diff --git a/back-end/src/templates/box.ejs b/back-end/src/templates/box.ejs index 56c2797..5d39e81 100644 --- a/back-end/src/templates/box.ejs +++ b/back-end/src/templates/box.ejs @@ -27,6 +27,8 @@ id : <%= box.id %> date : <%= box.date %>

Liste des pièces

+
+ @@ -45,25 +47,32 @@ <% }); %>
+
+
+

Liste des modèles constructibles

- - - - - - - - - - <% box.models.forEach(function(model) { %> - - - - - - <% }); %> - -
Id modèleNom
<%=model.id%><%=model.name%>
+
+ + + + + + + + + + + <% box.models.forEach(function(model) { %> + + + + + + <% }); %> + +
Id modèleNom
<%=model.id%><%=model.name%>
+
+

Ajouter une pièce

diff --git a/back-end/src/templates/boxes.ejs b/back-end/src/templates/boxes.ejs index fddfcb5..17e9e9e 100644 --- a/back-end/src/templates/boxes.ejs +++ b/back-end/src/templates/boxes.ejs @@ -32,33 +32,38 @@
- - - - - - - - - - - - <% boxes.forEach(function(box) { %> - - - - - - - +
+ +
IdNomNombre de piècesDate création
<%=box.id%><%=box.title%><%- box.pieces.reduce( - (p,q) => p + q.second, 0 - ) - -%><%=box.date.toLocaleDateString()%>
+ + + + + + + + + + + <% boxes.forEach(function(box) { %> + + + + + + + - <% }); %> + <% }); %> - -
IdNomNombre de piècesDate création
<%=box.id%><%=box.title%><%- box.pieces.reduce( + (p,q) => p + q.second, 0 + ) + -%><%=box.date.toLocaleDateString()%>
+ + +
+ + diff --git a/back-end/src/templates/member.ejs b/back-end/src/templates/member.ejs index a6d93dd..50a1d0d 100644 --- a/back-end/src/templates/member.ejs +++ b/back-end/src/templates/member.ejs @@ -30,6 +30,8 @@

Liste des boites enregistrées

+
+ @@ -63,74 +65,83 @@
+
+
+

Liste des pièces achetées

- - - - - - - - - - - - <% pieces.forEach(function(p) { %> +
+
Id PièceCouleurMotifFormeQuantité
+ - - - - - + + + + + + + + <% pieces.forEach(function(p) { %> + + + + + + + - <% }); %> - -
- <%=p.first.id_piece%> - - <%=p.first.colour.name%> (<%=p.first.colour.id_colour%>) - - <%=p.first.pattern.name%> (<%=p.first.pattern.id_pattern%>) - - <%=p.first.shape.name%> (<%=p.first.shape.id_shape%>) - - <%=p.second%> - Id PièceCouleurMotifFormeQuantité
+ <%=p.first.id_piece%> + + <%=p.first.colour.name%> (<%=p.first.colour.id_colour%>) + + <%=p.first.pattern.name%> (<%=p.first.pattern.id_pattern%>) + + <%=p.first.shape.name%> (<%=p.first.shape.id_shape%>) + + <%=p.second%> +
+ <% }); %> + + +
+

Liste des modèles faisables

- - - - - - - - - - - <% models.forEach(function(model) { %> +
+
Id modèleNom modèleProposé par
+ - - - - + + + + + + + <% models.forEach(function(model) { %> + + + + + + - <% }); %> + <% }); %> - -
- <%=model.id%> - - <%=model.name%> - - <%=model.creator%> - Id modèleNom modèleProposé par
+ <%=model.id%> + + <%=model.name%> + + <%=model.creator%> +
- + + +
+ + diff --git a/back-end/src/templates/members.ejs b/back-end/src/templates/members.ejs index e6a0997..3c7d50c 100644 --- a/back-end/src/templates/members.ejs +++ b/back-end/src/templates/members.ejs @@ -15,29 +15,39 @@ <%- include('partials/header.ejs') %>
-

- Liste des membres -

- - - - - - - - - +

+ Liste des membres +

+ +
+
Id MembreNom
+ + + + + + + + + + <% members.forEach(function(member) { %> + + + + + + + <% }); %> + +
Id MembreNom
+ <%=member.id_member%> + + <%=member.name%> +
+
+ - <% members.forEach(function(member) { %> - - <%=member.id_member%> - <%=member.name%> - - - <% }); %> - -
diff --git a/back-end/src/templates/membersAndNbModels.ejs b/back-end/src/templates/membersAndNbModels.ejs index e740567..eef43d2 100644 --- a/back-end/src/templates/membersAndNbModels.ejs +++ b/back-end/src/templates/membersAndNbModels.ejs @@ -20,39 +20,41 @@ Liste des membres qui ont proposés le plus de modèles - - - - - - - - <% members.forEach(function(member) { %> +
+
NomNombre de modèle proposés
+ - - - - + + + - <% }); %> + <% members.forEach(function(member) { %> + + + + - - + + <% }); %> + + + + + +
- - <%= member.name %> - - - <%= member.nb_models %> - - - - - NomNombre de modèle proposés
+ + <%= member.name %> + + + <%= member.nb_models %> + + + + +
+
+ - - -
    -
diff --git a/back-end/src/templates/model.ejs b/back-end/src/templates/model.ejs index af7c6e4..6bbd65e 100644 --- a/back-end/src/templates/model.ejs +++ b/back-end/src/templates/model.ejs @@ -26,22 +26,25 @@ creator : <%= model.creator.name %> inheritFrom : <%= model.inheritFrom %>

Liste des pièces nécessaires

- - - - - - - - - <% model.pieces.forEach(function(pair) { %> +
+
Id pièceQuantité pieces
+ - - + + - <% }); %> - -
<%= pair.first.id_piece%><%= pair.second%>Id pièceQuantité pieces
+ + + <% model.pieces.forEach(function(pair) { %> + + <%= pair.first.id_piece%> + <%= pair.second%> + + <% }); %> + + +
+ diff --git a/back-end/src/templates/models.ejs b/back-end/src/templates/models.ejs index 3d71d18..14baa7c 100644 --- a/back-end/src/templates/models.ejs +++ b/back-end/src/templates/models.ejs @@ -18,30 +18,33 @@ Liste des modeles - - - - - - - - - - - - <% models.forEach(function(model) { %> - - - - - - - +
+
Id modèleNom modèleProposé parAvis
<%=model.id%><%=model.name%> <%=model.creator.name%><%=model.review.first%>/5 (<%=model.review.second%> avis)
+ + + + + + + + + + + <% models.forEach(function(model) { %> + + + + + + + - <% }); %> + <% }); %> - -
Id modèleNom modèleProposé parAvis
<%=model.id%><%=model.name%> <%=model.creator.name%><%=model.review.first%>/5 (<%=model.review.second%> avis)
+ + +
+ diff --git a/back-end/src/templates/partials/links.ejs b/back-end/src/templates/partials/links.ejs index 7c16fd0..3078c04 100644 --- a/back-end/src/templates/partials/links.ejs +++ b/back-end/src/templates/partials/links.ejs @@ -4,3 +4,6 @@ + + + diff --git a/back-end/src/templates/piece.ejs b/back-end/src/templates/piece.ejs index 0d43a39..ebdda32 100644 --- a/back-end/src/templates/piece.ejs +++ b/back-end/src/templates/piece.ejs @@ -18,24 +18,27 @@

Information de la pièce

- - - - - - - - - - - - - - - - - -
Id PièceCouleurMotifForme
<%=piece.id_piece%><%=piece.colour.name%> (<%=piece.colour.id_colour%>)<%=piece.pattern.name%> (<%=piece.pattern.id_pattern%>)<%=piece.shape.name%> (<%=piece.shape.id_shape%>)
+
+ + + + + + + + + + + + + + + + + +
Id PièceCouleurMotifForme
<%=piece.id_piece%><%=piece.colour.name%> (<%=piece.colour.id_colour%>)<%=piece.pattern.name%> (<%=piece.pattern.id_pattern%>)<%=piece.shape.name%> (<%=piece.shape.id_shape%>)
+
+
diff --git a/back-end/src/templates/pieces.ejs b/back-end/src/templates/pieces.ejs index a1bfd89..8a5ad22 100644 --- a/back-end/src/templates/pieces.ejs +++ b/back-end/src/templates/pieces.ejs @@ -18,27 +18,32 @@

Liste des pièces

- - - - - - - - - - - <% pieces.forEach(function(p) { %> - - - - - - +
+ +
Id PièceCouleurMotifForme
<%=p.id_piece%><%=p.colour.name%> (<%=p.colour.id_colour%>)<%=p.pattern.name%> (<%=p.pattern.id_pattern%>)<%=p.shape.name%> (<%=p.shape.id_shape%>)
+ + + + + + + + + + <% pieces.forEach(function(p) { %> + + + + + + - <% }); %> - -
Id PièceCouleurMotifForme
<%=p.id_piece%><%=p.colour.name%> (<%=p.colour.id_colour%>)<%=p.pattern.name%> (<%=p.pattern.id_pattern%>)<%=p.shape.name%> (<%=p.shape.id_shape%>)
+ <% }); %> + + + +
+