From 41369f738ea60dfee147515054ceb9cc1cef3c26 Mon Sep 17 00:00:00 2001 From: Julien Constant Date: Wed, 15 Jun 2022 01:42:17 +0200 Subject: [PATCH 1/3] Improved Elections CSS for the table --- core/static/core/election.scss | 263 ++++++++++++ core/static/core/js/shorten.min.js | 107 ++++- .../templates/election/election_detail.jinja | 382 ++++-------------- 3 files changed, 456 insertions(+), 296 deletions(-) create mode 100644 core/static/core/election.scss diff --git a/core/static/core/election.scss b/core/static/core/election.scss new file mode 100644 index 00000000..2a5edd4a --- /dev/null +++ b/core/static/core/election.scss @@ -0,0 +1,263 @@ +$padding: 15px; + +.error { + color: red !important; +} + +.radio-btn { + display: flex; + flex-direction: row; + gap: 5px; + + > input, + > label { + margin: 0; + } + + &:hover { + cursor: pointer; + } +} + +.election_table { + width: 100%; + + >.lists { + display: flex; + flex-direction: row; + + >tr { + display: flex; + flex-direction: row; + width: 100%; + + >.column { + display: flex; + flex-direction: column-reverse; + align-items: center; + justify-content: space-between; + padding: $padding; + border: 0.5px solid black; + border-collapse: collapse; + + >a{ + margin-left: $padding; + width: 20px; + height: 20px; + text-align: center; + padding: 5px; + border-radius: 25%; + margin: 0; + display: flex; + align-items: center; + justify-content: center; + + &:hover { + background-color: #ddd; + } + } + } + } + } + + >.role { + display: flex; + flex-direction: column; + + >tr { + display: flex; + flex-direction: row; + background-color: lightgrey; + + &:hover { + background-color: lightgrey; + } + + >.role_title { + display: flex; + flex-direction: row; + align-items: center; + justify-content: space-between; + margin: 0; + padding: $padding; + width: 100%; + + + >.role_text { + >h4 { + margin: 0; + } + >p { + margin-top: .5em; + } + } + + >.role_buttons { + display: flex; + flex-direction: row; + align-items: center; + gap: 5px; + + > button, + > button > i, + > a { + width: 20px; + height: 20px; + background-color: #e9e9e9; + text-align: center; + padding: 5px; + border-radius: 25%; + margin: 0; + display: flex; + align-items: center; + justify-content: center; + + &:hover, + &:hover > i { + background-color: #fff; + } + } + + > button { + width: 30px; + height: 30px; + } + + > button[disabled] { + background-color: #eee; + cursor: not-allowed; + + >i, + &:hover, + &:hover > i { + background-color: #eee; + } + } + } + } + + >.list_per_role { + display: flex; + flex-direction: row; + justify-content: center; + border: 0.5px solid black; + border-collapse: collapse; + background-color: #fff; + padding: $padding; + margin: 0; + + >.candidates { + margin: 0; + display: flex; + flex-direction: row; + flex-wrap: wrap; + justify-content: center; + gap: 10px; + + >.candidate { + display: flex; + flex-direction: column; + align-items: center; + + list-style-type: none; + gap: 10px; + + >input[type="radio"]:checked + label, + >input[type="checkbox"]:checked + label { + background-color: lightgray; + border-radius: 10px; + } + + >label>figure, + >figure { + position: relative; + display: flex; + flex-direction: column; + align-items: center; + gap: 10px; + padding: 10px; + + >img { + max-width: 100%; + } + + >figcaption { + h5 { + margin: 0; + text-align: center; + } + q { + margin: 5px 0; + } + } + + >.edit_btns { + position: absolute; + display: flex; + flex-direction: column; + top: 5px; + right: 5px; + gap: 5px; + + > a { + width: 20px; + height: 20px; + background-color: #e9e9e9; + text-align: center; + padding: 5px; + border-radius: 25%; + margin: 0; + display: flex; + align-items: center; + justify-content: center; + + &:hover { + background-color: #fff; + } + } + } + } + } + } + } + } + } +} + +.election_details { + margin: .5em 0; +} + +.buttons { + display: flex; + flex-direction: row; + flex-wrap: wrap; + align-items: center; + justify-content: center; + gap: 5px; +} + +.button { + border: none; + color: black; + text-decoration: none; + background-color: #f2f2f2; + padding: 0.4em; + margin: 0.1em; + font-size: 1.18em; + border-radius: 5px; + box-shadow: #dfdfdf 0px 0px 1px; + cursor: pointer; + + &:hover { + color: black; + background: #d4d4d4; + } + + &_send { + background-color: #59aee2; + &:hover { + background-color: rgb(130, 186, 235); + } + } +} \ No newline at end of file diff --git a/core/static/core/js/shorten.min.js b/core/static/core/js/shorten.min.js index 5e79d040..48f4f4ce 100644 --- a/core/static/core/js/shorten.min.js +++ b/core/static/core/js/shorten.min.js @@ -19,4 +19,109 @@ // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -!function(e){e.fn.shorten=function(s){"use strict";var t={showChars:100,minHideChars:10,ellipsesText:"...",moreText:"more",lessText:"less",onLess:function(){},onMore:function(){},errMsg:null,force:!1};return s&&e.extend(t,s),e(this).data("jquery.shorten")&&!t.force?!1:(e(this).data("jquery.shorten",!0),e(document).off("click",".morelink"),e(document).on({click:function(){var s=e(this);return s.hasClass("less")?(s.removeClass("less"),s.html(t.moreText),s.parent().prev().animate({height:"0%"},function(){s.parent().prev().prev().show()}).hide("fast",function(){t.onLess()})):(s.addClass("less"),s.html(t.lessText),s.parent().prev().animate({height:"100%"},function(){s.parent().prev().prev().hide()}).show("fast",function(){t.onMore()})),!1}},".morelink"),this.each(function(){var s=e(this),n=s.html(),r=s.text().length;if(r>t.showChars+t.minHideChars){var o=n.substr(0,t.showChars);if(o.indexOf("<")>=0){for(var a=!1,i="",h=0,l=[],c=null,f=0,u=0;u<=t.showChars;f++)if("<"!=n[f]||a||(a=!0,c=n.substring(f+1,n.indexOf(">",f)),"/"==c[0]?c!="/"+l[0]?t.errMsg="ERROR en HTML: the top of the stack should be the tag that closes":l.shift():"br"!=c.toLowerCase()&&l.unshift(c)),a&&">"==n[f]&&(a=!1),a)i+=n.charAt(f);else if(u++,h<=t.showChars)i+=n.charAt(f),h++;else if(l.length>0){for(j=0;j";break}o=e("
").html(i+''+t.ellipsesText+"").html()}else o+=t.ellipsesText;var m='
'+o+'
'+n+'
'+t.moreText+"";s.html(m),s.find(".allcontent").hide(),e(".shortcontent p:last",s).css("margin-bottom",0)}}))}}(jQuery); +!(function (e) { + e.fn.shorten = function (s) { + "use strict"; + var t = { + showChars: 100, + minHideChars: 10, + ellipsesText: "...", + moreText: "more", + lessText: "less", + onLess: function () {}, + onMore: function () {}, + errMsg: null, + force: !1, + }; + return ( + s && e.extend(t, s), + e(this).data("jquery.shorten") && !t.force + ? !1 + : (e(this).data("jquery.shorten", !0), + e(document).off("click", ".morelink"), + e(document).on( + { + click: function () { + var s = e(this); + return ( + s.hasClass("less") + ? (s.removeClass("less"), + s.html(t.moreText), + s + .parent() + .prev() + .animate({ height: "0%" }, function () { + s.parent().prev().prev().show(); + }) + .hide("fast", function () { + t.onLess(); + })) + : (s.addClass("less"), + s.html(t.lessText), + s + .parent() + .prev() + .animate({ }, function () { + s.parent().prev().prev().hide(); + }) + .show("fast", function () { + t.onMore(); + })), + !1 + ); + }, + }, + ".morelink" + ), + this.each(function () { + var s = e(this), + n = s.html(), + r = s.text().length; + if (r > t.showChars + t.minHideChars) { + var o = n.substr(0, t.showChars); + if (o.indexOf("<") >= 0) { + for ( + var a = !1, i = "", h = 0, l = [], c = null, f = 0, u = 0; + u <= t.showChars; + f++ + ) + if ( + ("<" != n[f] || + a || + ((a = !0), + (c = n.substring(f + 1, n.indexOf(">", f))), + "/" == c[0] + ? c != "/" + l[0] + ? (t.errMsg = + "ERROR en HTML: the top of the stack should be the tag that closes") + : l.shift() + : "br" != c.toLowerCase() && l.unshift(c)), + a && ">" == n[f] && (a = !1), + a) + ) + i += n.charAt(f); + else if ((u++, h <= t.showChars)) (i += n.charAt(f)), h++; + else if (l.length > 0) { + for (j = 0; j < l.length; j++) i += ""; + break; + } + o = e("
") + .html(i + '' + t.ellipsesText + "") + .html(); + } else o += t.ellipsesText; + var m = + '
' + + o + + '
' + + n + + '
' + + t.moreText + + ""; + s.html(m), + s.find(".allcontent").hide(), + e(".shortcontent p:last", s).css("margin-bottom", 0); + } + })) + ); + }; +})(jQuery); diff --git a/election/templates/election/election_detail.jinja b/election/templates/election/election_detail.jinja index cf79003f..8dff608c 100644 --- a/election/templates/election/election_detail.jinja +++ b/election/templates/election/election_detail.jinja @@ -6,232 +6,14 @@ {% block head %} {{ super() -}} - + {%- endblock %} {% block content %}

{{ election.title }}

{{ election.description }}


-
+

{%- if election.is_vote_active %} {% trans %}Polls close {% endtrans %} @@ -259,32 +41,46 @@ th {

{% csrf_token %} - +
{%- set election_lists = election.election_lists.all() -%} - - - {%- for election_list in election_lists %} - - {%- endfor %} + + + + {%- for election_list in election_lists %} + + {%- endfor %} + {%- set role_list = election.roles.order_by('order').all() %} {%- for role in role_list %} {%- set count = [0] %} {%- set role_data = election_form.data.getlist(role.title) if role.title in election_form.data else [] %} - - + - {%- for election_list in election_lists %} -
{% trans %}Blank vote{% endtrans %} - {{ election_list.title }} - {% if user.can_edit(election_list) and election.is_vote_editable -%} - - {% trans %}Delete{% endtrans %} - {% endif %} -
{% trans %}Blank vote{% endtrans %} + {{ election_list.title }} + {% if user.can_edit(election_list) and election.is_vote_editable -%} + + {% endif %} +
- {{ role.title }} +
+
+

{{ role.title }}

+

{{ role.description }}

+ {%- if role.max_choice > 1 and not election.has_voted(user) and election.can_vote(user) %} + {% trans %}You may choose up to{% endtrans %} {{ role.max_choice }} {% trans %}people.{% endtrans %} + {%- endif %} + + {%- if election_form.errors[role.title] is defined %} + {%- for error in election_form.errors.as_data()[role.title] %} + {{ error.message }} + {%- endfor %} + {%- endif %} +
{% if user.can_edit(role) and election.is_vote_editable -%} - {% trans %}Edit{% endtrans %} - {% trans %}Delete{% endtrans %} - +
+ ✏️ + {%- if role == role_list.last() %} @@ -299,27 +95,19 @@ th { {% endif %} - +
{%- endif -%} -

{{ role.description }}

- {%- if role.max_choice > 1 and not election.has_voted(user) and election.can_vote(user) %} -
- {% trans %}You may choose up to{% endtrans %} {{ role.max_choice }} {% trans %}people.{% endtrans %} - {%- endif %} - {%- if election_form.errors[role.title] is defined %} - {%- for error in election_form.errors.as_data()[role.title] %} - {{ error.message }} - {%- endfor %} - {%- endif %}
+ {%- if role.max_choice == 1 and election.can_vote(user) %} - - +
+ + +
{%- set _ = count.append(count.pop() + 1) %} {%- endif %} {%- if election.is_vote_finished %} @@ -330,36 +118,39 @@ th { {%- endif %}
-
    +
+
    {%- for candidature in election_list.candidatures.filter(role=role) %} -
  • -
    -
    - {%- if candidature.user.profile_pict and user.is_subscriber_viewable %} - {% trans %}Profile{% endtrans %} - {%- endif %} -
    -
    - {{ candidature.user.first_name }} {{candidature.user.nick_name or ''}} {{ candidature.user.last_name }} - {%- if user.can_edit(candidature) -%} - {% if election.is_vote_editable %} - {% trans %}Edit{% endtrans %} - {% endif %} - {% if election.is_vote_editable -%} - {% trans %}Delete{% endtrans %} - {%- endif -%} - {%- endif -%} - {%- if not election.is_vote_finished %} - {{ candidature.program | markdown or '' }} - {%- endif %} -
    -
    +
  • {%- if election.can_vote(user) %} - - + + {%- set _ = count.append(count.pop() + 1) %} {%- endif %} {%- if election.is_vote_finished %} @@ -379,39 +170,40 @@ th {
- {%- if not election.has_voted(user) and election.can_vote(user) %} -
- -
- {%- endif %} -
+
{%- if (election.can_candidate(user) and election.is_candidature_active) or (user.can_edit(election) and election.is_vote_editable) %} - {% trans %}Candidate{% endtrans %} + {% trans %}Candidate{% endtrans %} {%- endif %} {%- if election.is_vote_editable %} - {% trans %}Add a new list{% endtrans %} + {% trans %}Add a new list{% endtrans %} {%- endif %} {%- if user.can_edit(election) %} {% if election.is_vote_editable %} - {% trans %}Add a new role{% endtrans %} + {% trans %}Add a new role{% endtrans %} {% endif %} - {% trans %}Edit{% endtrans %} + {% trans %}Edit{% endtrans %} {%- endif %} {%- if user.is_root %} - {% trans %}Delete{% endtrans %} + {% trans %}Delete{% endtrans %} {%- endif %}
+ {%- if not election.has_voted(user) and election.can_vote(user) %} +
+ +
+ {%- endif %} {% endblock %} {% block script %} {{ super() }}