From 45ea667b23f4dd3cce0d4fd9690d6c3d7158d82b Mon Sep 17 00:00:00 2001 From: Aditya Anand Date: Fri, 23 Feb 2018 20:20:05 +0530 Subject: [PATCH 1/5] html: removed left rails - removed left panel in /profile, /toolbox, /new/funding - replaces newletter and pushed it to the bottom Fixes: https://github.com/gitcoinco/web/issues/411 --- app/assets/v2/css/base.css | 4 + app/dashboard/templates/profile_details.html | 182 +++++++++---------- app/dashboard/templates/submit_bounty.html | 13 +- app/dashboard/templates/toolbox.html | 6 +- app/dashboard/views.py | 4 +- 5 files changed, 100 insertions(+), 109 deletions(-) diff --git a/app/assets/v2/css/base.css b/app/assets/v2/css/base.css index e112b7368ca..b02d91a6403 100644 --- a/app/assets/v2/css/base.css +++ b/app/assets/v2/css/base.css @@ -914,6 +914,10 @@ body.bounty_details #title { -o-filter: grayscale(0%); } +.body { + padding-bottom: 4em; +} + .profile_details .dot { border-radius: 6px; width: 12px; diff --git a/app/dashboard/templates/profile_details.html b/app/dashboard/templates/profile_details.html index fc4738c8e03..e798ed3b376 100644 --- a/app/dashboard/templates/profile_details.html +++ b/app/dashboard/templates/profile_details.html @@ -14,15 +14,8 @@ {% include 'shared/nav_internal.html' %}
-
- {% include 'shared/current_balance.html' %} - {% include 'shared/sidebar_search.html' %} -
-
- {% include 'shared/bounty_def.html' %} -
@@ -66,105 +59,108 @@

- {% if stats|length > 0 %} -
    - {% for stat in stats %} -
  • - {{stat.0}} - - {{stat.1}} - -
  • - {% endfor %} -
- {% endif %} -
-
-

{{profile.handle}} has Participated in these Funded Issues

- +
+ {% include 'shared/newsletter.html' %}
diff --git a/app/dashboard/templates/submit_bounty.html b/app/dashboard/templates/submit_bounty.html index 53d68906d8a..7b7b3715af9 100644 --- a/app/dashboard/templates/submit_bounty.html +++ b/app/dashboard/templates/submit_bounty.html @@ -30,19 +30,13 @@ {% include 'shared/nav_internal.html' %}
-
- {% include 'shared/current_balance.html' %} - {% include 'shared/sidebar_search.html' %} -
- -
+
- {% include 'shared/bounty_def.html' %}
{% include 'shared/no_metamask_error.html' %} {% include 'shared/zero_balance_error.html' %} {% include 'shared/unlock_metamask.html' %} -
+
{% include 'shared/bounty_nav.html' with active_item=1 %}
@@ -141,9 +135,8 @@

Fund an Issue

- + {% include 'shared/newsletter.html' %}
-
diff --git a/app/dashboard/templates/toolbox.html b/app/dashboard/templates/toolbox.html index bffd807cce0..85de1dc6193 100644 --- a/app/dashboard/templates/toolbox.html +++ b/app/dashboard/templates/toolbox.html @@ -29,12 +29,8 @@
{% include 'shared/nav_internal.html' %}
-
- {% include 'shared/current_balance.html' %} - {% include 'shared/sidebar_search.html' %} -
-
+
diff --git a/app/dashboard/views.py b/app/dashboard/views.py index 92bf566b6e0..27d81c65792 100644 --- a/app/dashboard/views.py +++ b/app/dashboard/views.py @@ -447,7 +447,8 @@ def new_bounty(request): 'eth_usd_conv_rate': eth_usd_conv_rate(), 'conf_time_spread': conf_time_spread(), 'from_email': request.session.get('email', ''), - 'from_handle': request.session.get('handle', '') + 'from_handle': request.session.get('handle', ''), + 'newsletter_headline': 'Be the first to know about new funded issues.' } return TemplateResponse(request, 'submit_bounty.html', params) @@ -575,6 +576,7 @@ def profile(request, handle): params = { 'title': 'Profile', 'active': 'profile_details', + 'newsletter_headline': "Be the first to know about new funded issues.", } profile = profile_helper(handle) From 53a5e49f915dd4b58be8e66532ecdc30de3bf477 Mon Sep 17 00:00:00 2001 From: Aditya Anand Date: Mon, 26 Feb 2018 11:32:18 +0530 Subject: [PATCH 2/5] css: added a few media queries to prettify page --- app/assets/v2/css/base.css | 33 ++++++++++++++++++++++ app/dashboard/templates/submit_bounty.html | 2 +- 2 files changed, 34 insertions(+), 1 deletion(-) diff --git a/app/assets/v2/css/base.css b/app/assets/v2/css/base.css index b02d91a6403..61f57d1055f 100644 --- a/app/assets/v2/css/base.css +++ b/app/assets/v2/css/base.css @@ -954,6 +954,7 @@ body.bounty_details #title { font-size: 32px; font-weight: bold; border-radius: 3px; + margin-top: 10px; } .profile_details #stats li span { @@ -1512,3 +1513,35 @@ body.bounty_details #title { font-size: .8rem; } } + +@media (max-width: 576px) { + .profile_details #stats { + padding-right: 10px; + } + + .profile_details .repos { + padding-right: 40px; + } + + .profile_details .repos li { + margin-bottom: 1em; + } + + .issue_details { + flex-direction: column; + } + + .issue_details div { + width: 100% !important; + } +} + +@media (max-width: 768px) { + .bounty_nav { + padding-left: 0; + } + + .bounty_nav li{ + display: block; + } +} diff --git a/app/dashboard/templates/submit_bounty.html b/app/dashboard/templates/submit_bounty.html index 7b7b3715af9..bcc5367c72a 100644 --- a/app/dashboard/templates/submit_bounty.html +++ b/app/dashboard/templates/submit_bounty.html @@ -94,7 +94,7 @@

Fund an Issue

-
+
-
- {% include 'shared/github_username.html' %} - {% include 'shared/notification_email.html' %} - {% include 'shared/name.html' %} -
- - -
- {% include 'shared/metamask_estimate.html' %} - - - -
- -
+
+
+
+ {% include 'shared/no_metamask_error.html' %} + {% include 'shared/zero_balance_error.html' %} + {% include 'shared/unlock_metamask.html' %} +
+
+ {% include 'shared/bounty_nav.html' with active_item=3 %} +
+

Submit Work

+ +
+ {% include 'shared/network_status.html' %} +
+ +
+ {% include 'shared/github_username.html' %} + {% include 'shared/notification_email.html' %} + {% include 'shared/name.html' %} +
+ + +
+ {% include 'shared/metamask_estimate.html' %} + + +
+
+
+
{% include 'shared/bottom_notification.html' %} {% include 'shared/analytics.html' %} {% include 'shared/footer_scripts.html' %} {% include 'shared/rollbar.html' %} {% include 'shared/footer.html' %} + - - - - -{% if is_legacy %} - - - - - -{% else %} - - - - - -{% endif %} - - + + {% if is_legacy %} + + + + + + {% else %} + + + + + + {% endif %} + + diff --git a/app/dashboard/templates/kill_bounty.html b/app/dashboard/templates/kill_bounty.html index 1ef3eeaffcd..eaaf530334b 100644 --- a/app/dashboard/templates/kill_bounty.html +++ b/app/dashboard/templates/kill_bounty.html @@ -18,77 +18,67 @@ {% load static %} - - + {% include 'shared/head.html' %} {% include 'shared/cards_pic.html' %} - - + + {% include 'shared/tag_manager_2.html' %}
{% include 'shared/nav_internal.html' %}
-
- {% include 'shared/current_balance.html' %} - {% include 'shared/sidebar_search.html' %} -
- -
-
- {% include 'shared/bounty_def.html' %} -
- {% include 'shared/no_metamask_error.html' %} - {% include 'shared/zero_balance_error.html' %} - {% include 'shared/unlock_metamask.html' %} -
-
-
-

Kill Bounty And Clawback Funds

-
(Issue Submitters only)
- -
- {% include 'shared/network_status.html' %} -
- - -
-
- - -
- {% include 'shared/metamask_estimate.html' %} - - -
- -
+
+
+
+ {% include 'shared/no_metamask_error.html' %} + {% include 'shared/zero_balance_error.html' %} + {% include 'shared/unlock_metamask.html' %} +
+
+
+

Cancel Bounty and Reclaim Funds

+
(Issue Submitters only)
+ +
+ {% include 'shared/network_status.html' %} +
+ +
+
+ + +
+ {% include 'shared/metamask_estimate.html' %} + +
+
+
+
{% include 'shared/bottom_notification.html' %} {% include 'shared/analytics.html' %} {% include 'shared/footer_scripts.html' %} {% include 'shared/rollbar.html' %} {% include 'shared/footer.html' %} + - - - - -{% if is_legacy %} - - - - -{% else %} - - - - - -{% endif %} + + {% if is_legacy %} + + + + + {% else %} + + + + + + {% endif %} diff --git a/app/dashboard/templates/process_bounty.html b/app/dashboard/templates/process_bounty.html index 81094e107f9..2da7ffe695f 100644 --- a/app/dashboard/templates/process_bounty.html +++ b/app/dashboard/templates/process_bounty.html @@ -18,96 +18,87 @@ {% load static %} - + {% include 'shared/head.html' %} {% include 'shared/cards.html' %} - + - + {% include 'shared/tag_manager_2.html' %}
- {% include 'shared/nav_internal.html' %} + {% include 'shared/nav_internal.html' %}
-
- {% include 'shared/current_balance.html' %} - {% include 'shared/sidebar_search.html' %} -
- -
-
- {% include 'shared/bounty_def.html' %} -
- {% include 'shared/no_metamask_error.html' %} - {% include 'shared/zero_balance_error.html' %} - {% include 'shared/unlock_metamask.html' %} -
-
- {% include 'shared/bounty_nav.html' with active_item=4 %} -
-

Accept Bounty Fulfillment

- -
- {% include 'shared/network_status.html' %} -
- - -
-
- - -
-
- - -
- {% include 'shared/metamask_estimate.html' %} - {% if not is_legacy %} - - {% else %} - - {% endif %} - - -
- -
+
+
+
+ {% include 'shared/no_metamask_error.html' %} + {% include 'shared/zero_balance_error.html' %} + {% include 'shared/unlock_metamask.html' %} +
+
+ {% include 'shared/bounty_nav.html' with active_item=4 %} +
+

Accept Bounty Fulfillment

+ +
+ {% include 'shared/network_status.html' %} +
+ + +
+
+ +
+
+ + +
+ {% include 'shared/metamask_estimate.html' %} + {% if not is_legacy %} + + {% else %} + + {% endif %} + +
+
+
+
{% include 'shared/bottom_notification.html' %} {% include 'shared/analytics.html' %} {% include 'shared/footer_scripts.html' %} {% include 'shared/rollbar.html' %} {% include 'shared/footer.html' %} + - - - - -{% if is_legacy %} - - - - -{% else %} - - - - - -{% endif %} + + {% if is_legacy %} + + + + + {% else %} + + + + + + {% endif %} From 1166bb0eed28f4fa4cea457562e7c8500a84d819 Mon Sep 17 00:00:00 2001 From: Aditya Anand Date: Wed, 28 Feb 2018 22:55:51 +0530 Subject: [PATCH 4/5] leaderboard: removed left rails + refactor + redindent --- app/assets/v2/css/leaderboard.css | 360 +++++++++++++------------- app/retail/templates/leaderboard.html | 188 +++++++------- 2 files changed, 276 insertions(+), 272 deletions(-) diff --git a/app/assets/v2/css/leaderboard.css b/app/assets/v2/css/leaderboard.css index 6f6c612cc22..6047fb1ba84 100644 --- a/app/assets/v2/css/leaderboard.css +++ b/app/assets/v2/css/leaderboard.css @@ -1,181 +1,195 @@ - #leaderboard .leaderboard_entry{ - padding: 10px 0px; - } - - #leaderboard .leaderboard_entry img{ - max-height: 100px; - border-radius: 50%; - } - #leaderboard .leaderboard_entry{ - color: black; - text-decoration: none; - } - - #leaderboard .leaderboard_entry a{ - color: #8b8b8b; - } - - #leaderboard .leaderboard_entry .item-amount{ - font-size:1.5em; - font-weight: bold; - color: #86eec4; - } - #leaderboard .leaderboard_entry .item-position{ - color: #8b8b8b; - } - - #leaderboard .table-striped tbody tr:nth-of-type(2n+1) { - background-color: #f8f8f8; - } - - #leaderboard .progress_container{ - padding-top: 2.5em; - } - - - #leaderboard #key{ - right: 0px; - display: block; - position: absolute; - margin-right: 10px; - margin-top: 5px; - } - +#leaderboard .leaderboard_entry{ + padding: 10px 0px; +} + +#leaderboard .leaderboard_entry img{ + max-height: 100px; + border-radius: 50%; +} + +#leaderboard .leaderboard_entry{ + color: black; + text-decoration: none; +} + +#leaderboard .leaderboard_entry a{ + color: #8b8b8b; +} + +#leaderboard .leaderboard_entry .item-amount{ + font-size:1.5em; + font-weight: bold; + color: #86eec4; +} + +#leaderboard .leaderboard_entry .item-position{ + color: #8b8b8b; +} + +#leaderboard .table-striped tbody tr:nth-of-type(2n+1) { + background-color: #f8f8f8; +} + +#leaderboard .progress_container{ + padding-top: 2.5em; +} + +#leaderboard #key{ + right: 0px; + display: block; + position: absolute; + margin-right: 10px; + margin-top: 5px; +} + #leaderboard .podium { - background: #f5136e; /* For browsers that do not support gradients */ - background: -webkit-gradient(linear, center top, center bottom, from(#f5136e), to(#0f023c)); - background: -webkit-linear-gradient(#f5136e, #0f023c); - background: -moz-linear-gradient(#f5136e, #0f023c); - background: -o-linear-gradient(#f5136e, #0f023c); - background: -ms-linear-gradient(#f5136e, #0f023c); - background: linear-gradient(#f5136e, #0f023c); - } - - - #leaderboard .winner { - position: relative; - padding: 0px; - } - - #leaderboard .winner-content { - top:40%; - left:0; - position: absolute; - } - - - - #leaderboard .winner-content .winner-position { - width: 100%; - min-height: 100px; - background-position: center; - background-repeat: no-repeat; - background-size: contain; - } - - #leaderboard .winner-content .winner-position-first { - background-image: url('/static/v2/images/leaderboard-1.png'); - } - - #leaderboard .winner-content .winner-position-second { - background-image: url('/static/v2/images/leaderboard-2.png'); - } - - #leaderboard .winner-content .winner-position-third { - background-image: url('/static/v2/images/leaderboard-3.png'); - } - - - #leaderboard .winner img{ - opacity: 0.5; - min-height: 23em; - } - - #leaderboard .winner img:hover{ - opacity: 0.55; - } - - #leaderboard .winner a{ - color:white; - } - - #leaderboard .clickable-row { - cursor: pointer; - } - - @media (max-width: 1300px) { - - #leaderboard .winner img{ - min-height: 20em; - } -} - - @media (max-width: 1025px) { - #leaderboard .leaderboard_entry div{ - width: 30%; - } - #leaderboard .leaderboard_entry div:nth-child(2){ - width: 30%; - } - #leaderboard .leaderboard_entry div.progress{ - width: 100%; - } - #leaderboard .winner img{ - min-height: 18em; - } + border-bottom-left-radius: 2px; + border-bottom-right-radius: 2px; + background: #f5136e; /* For browsers that do not support gradients */ + background: -webkit-gradient(linear, center top, center bottom, from(#f5136e), to(#0f023c)); + background: -webkit-linear-gradient(#f5136e, #0f023c); + background: -moz-linear-gradient(#f5136e, #0f023c); + background: -o-linear-gradient(#f5136e, #0f023c); + background: -ms-linear-gradient(#f5136e, #0f023c); + background: linear-gradient(#f5136e, #0f023c); +} + + +#leaderboard .winner { + position: relative; + padding: 0px; +} + +#leaderboard .winner-content { + top:40%; + left:0; + position: absolute; +} + +#leaderboard .winner-content .winner-position { + width: 100%; + min-height: 100px; + background-position: center; + background-repeat: no-repeat; + background-size: contain; +} + +#leaderboard .winner-content .winner-position-first { + background-image: url('/static/v2/images/leaderboard-1.png'); +} + +#leaderboard .winner-content .winner-position-second { + background-image: url('/static/v2/images/leaderboard-2.png'); +} + +#leaderboard .winner-content .winner-position-third { + background-image: url('/static/v2/images/leaderboard-3.png'); +} + +#leaderboard .winner img{ + opacity: 0.5; + min-height: 23em; +} + +#leaderboard .winner img:hover{ + opacity: 0.55; +} + +#leaderboard .winner a{ + color:white; +} + +#leaderboard .clickable-row { + cursor: pointer; +} + +@media (max-width: 1300px) { + #leaderboard .winner img{ + min-height: 20em; + } +} + +@media (max-width: 1025px) { + #leaderboard .leaderboard_entry div{ + width: 30%; + } + + #leaderboard .leaderboard_entry div:nth-child(2){ + width: 30%; + } + + #leaderboard .leaderboard_entry div.progress{ + width: 100%; + } + + #leaderboard .winner img{ + min-height: 18em; + } } + @media (max-width: 700px) { - #leaderboard .select{ - display: none; - } - #leaderboard h3{ - font-size: 1.3rem; - } - #leaderboard .leaderboard_entry h4{ - font-size: 22px; - } - #leaderboard .winner h2{ - font-size: 22px; - } - #leaderboard .winner h5{ - font-size: 18px; - } - #leaderboard .winner-content { - top:20%; - } - #leaderboard .winner img{ - min-height: 12em; - } - #leaderboard .col-6{ - flex: 0 0 25%; - max-width: 25%; - } - #leaderboard .col-2{ - flex: 0 0 30%; - max-width: 30%; - overflow-x: hidden;; - } - #leaderboard .progress_container{ - padding-top: 1.5em; - } + #leaderboard .select{ + display: none; + } + + #leaderboard h3{ + font-size: 1.3rem; + } + + #leaderboard .leaderboard_entry h4{ + font-size: 22px; + } + + #leaderboard .winner h2{ + font-size: 22px; + } + + #leaderboard .winner h5{ + font-size: 18px; + } + + #leaderboard .winner-content { + top:20%; + } + + #leaderboard .winner img { + min-height: 12em; + } + + #leaderboard .col-6 { + flex: 0 0 25%; + max-width: 25%; + } + + #leaderboard .col-2 { + flex: 0 0 30%; + max-width: 30%; + overflow-x: hidden; + } + + #leaderboard .progress_container{ + padding-top: 1.5em; + } } @media (max-width: 481px) { - #leaderboard .leaderboard_entry h4{ - font-size: 18px; - } - #leaderboard .winner h2{ - font-size: 18px; - } - #leaderboard .winner h5{ - font-size: 16px; - } - #leaderboard .winner-content { - top:20%; - } - #leaderboard .winner img{ - min-height: 6em; - } -} + #leaderboard .leaderboard_entry h4 { + font-size: 18px; + } + #leaderboard .winner h2 { + font-size: 18px; + } + #leaderboard .winner h5 { + font-size: 16px; + } + + #leaderboard .winner-content { + top: 20%; + } + + #leaderboard .winner img { + min-height: 6em; + } +} diff --git a/app/retail/templates/leaderboard.html b/app/retail/templates/leaderboard.html index b31219f4009..ac632991cd4 100644 --- a/app/retail/templates/leaderboard.html +++ b/app/retail/templates/leaderboard.html @@ -2,130 +2,120 @@ {% load static %} - - -{% include 'shared/head.html' %} -{% include 'shared/cards_pic.html' %} - - - - + + {% include 'shared/head.html' %} + {% include 'shared/cards_pic.html' %} + + + {% include 'shared/tag_manager_2.html' %}
- {% include 'shared/nav_internal.html' %} + {% include 'shared/nav_internal.html' %}
-
- {% include 'shared/current_balance.html' %} - {% include 'shared/sidebar_search.html' %} -
-
-
- {% include 'shared/bounty_def.html' %} -
- {% for podium_item in podium_items %} -
- -
-
- {% if forloop.counter == 1 %} -
- {% else %} - {% if forloop.counter == 2 %} -
- {% else %} - {% if forloop.counter == 3 %} -
- {% endif %}{% endif %}{% endif %} -
-
-
- - {{podium_item.github_username}} - -
-

${{podium_item.amount}}

-
-
+
+
+
+
+ {% for podium_item in podium_items %} +
+ +
+
+ {% if forloop.counter == 1 %} +
+ {% else %} + {% if forloop.counter == 2 %} +
+ {% else %} + {% if forloop.counter == 3 %} +
+ {% endif %}{% endif %}{% endif %} + +
+
+ + {{podium_item.github_username}} + +
+

${{podium_item.amount}}

+
+
- {% endfor %} + {% endfor %}
-
-

{{title}}

-
-
-
- -
+
+

{{title}}

+
+
+
+
+
{% if items|length == 0 %} -
- None found. -
+
+ None found. +
{% endif %} - - {% for item in items %} - - - - - - - - + + {% for item in items %} + + + + + + + {% endfor %} - -
#{{forloop.counter}} - - - - @{{item.github_username}} - - -
- {% with forloop.counter0 as index %} -
- {% endwith %} -
-
- ${{item.amount}} -
#{{forloop.counter}} + + + + @{{item.github_username}} + + +
+ {% with forloop.counter0 as index %} +
+
+ {% endwith %} +
+
+ ${{item.amount}} +
- + +
+
- {% include 'shared/bottom_notification.html' %} {% include 'shared/analytics.html' %} {% include 'shared/footer_scripts.html' %} {% include 'shared/rollbar.html' %} {% include 'shared/footer.html' %} - - - - - - - - - + + + + + + From 5daef05589accf5688c950eae5fc0373c4c73992 Mon Sep 17 00:00:00 2001 From: Aditya Anand Date: Fri, 2 Mar 2018 11:49:51 +0530 Subject: [PATCH 5/5] review: incorported review feedbacks - replaced double-quotes with single - removed left-rails on quote display --- app/assets/v2/js/pages/bounty_details.js | 13 ++++++------- app/dashboard/templates/bounty_details.html | 2 +- app/dashboard/views.py | 2 +- 3 files changed, 8 insertions(+), 9 deletions(-) diff --git a/app/assets/v2/js/pages/bounty_details.js b/app/assets/v2/js/pages/bounty_details.js index 9a54d7ce823..010d49b139d 100644 --- a/app/assets/v2/js/pages/bounty_details.js +++ b/app/assets/v2/js/pages/bounty_details.js @@ -161,6 +161,7 @@ var showWarningMessage = function (txid) { $('#transaction_url').attr("href", link_url); } + $(".left-rails").hide(); $("#bounty_details").hide(); $("#bounty_detail").hide(); @@ -200,7 +201,7 @@ var wait_for_tx_to_mine_and_then_ping_server = function(){ if(response.status == "200"){ console.log("success from sync/web", response); - // clear local data + // clear local data localStorage[document.issueURL] = ""; document.location.href = document.location.href; } else { @@ -359,9 +360,9 @@ pull_interest_list(result['pk'], function(is_interested){ actions.push(entry); } - render_actions(actions); + render_actions(actions); - }); + }); } var render_actions = function(actions){ @@ -370,7 +371,7 @@ var render_actions = function(actions){ var tmpl = $.templates("#action"); var html = tmpl.render(actions[l]); $("#"+target).append(html); - }; + }; } var pull_bounty_from_api = function(){ @@ -406,7 +407,7 @@ var pull_bounty_from_api = function(){ $("#primary_view").css('display','none'); }).always(function(){ $('.loading').css('display', 'none'); - }); + }); } var render_fulfillments = function(result){ @@ -492,5 +493,3 @@ var main = function(){ window.addEventListener('load', function() { main(); }); - - diff --git a/app/dashboard/templates/bounty_details.html b/app/dashboard/templates/bounty_details.html index 269be13e0ba..012669b2b80 100644 --- a/app/dashboard/templates/bounty_details.html +++ b/app/dashboard/templates/bounty_details.html @@ -13,7 +13,7 @@ {% include 'shared/nav_internal.html' %}
-
+
{% include 'shared/current_balance.html' %} {% include 'shared/sidebar_search.html' %}
diff --git a/app/dashboard/views.py b/app/dashboard/views.py index 27d81c65792..b66ce2055a5 100644 --- a/app/dashboard/views.py +++ b/app/dashboard/views.py @@ -576,7 +576,7 @@ def profile(request, handle): params = { 'title': 'Profile', 'active': 'profile_details', - 'newsletter_headline': "Be the first to know about new funded issues.", + 'newsletter_headline': 'Be the first to know about new funded issues.', } profile = profile_helper(handle)