From e3355494bb4ad7f4daac9df1655bf03d13a21f28 Mon Sep 17 00:00:00 2001 From: Luke Baker Date: Wed, 19 Mar 2014 17:17:23 -0400 Subject: [PATCH 1/7] alter name used to identify CSV exports Use ISO 8601 to indicate time that the CSV was requested. Reduce random string at the end of the URL to 4 characters. When specifying the filename in the download, strip off the 4 character random string. Old style URL: /export/export_970_votes_1386004584_9740b7bbda7f26de814a47a0b81250f38b524d25 Old style filename: export_970_votes_1386004584_9740b7bbda7f26de814a47a0b81250f38b524d25.csv New style URL: /export/wikisurvey_970_votes_2014-03-19T21:06:09Z_fyqO New style filename: wikisurvey_970_votes_2014-03-19T21:06:09Z.csv [#61486250] --- app/controllers/exports_controller.rb | 4 +++- app/controllers/questions_controller.rb | 5 +++-- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/app/controllers/exports_controller.rb b/app/controllers/exports_controller.rb index cf0df733f..512c47f33 100644 --- a/app/controllers/exports_controller.rb +++ b/app/controllers/exports_controller.rb @@ -13,7 +13,9 @@ def download else data = e.data end - send_data(data, :type => 'text/csv; charset=utf-8; header=present', :filename => "#{e.name}.csv") + # strip off 4 character random string at end of name + filename = e.name.gsub(/_[A-Za-z]{4}$/, "") + ".csv" + send_data(data, :type => 'text/csv; charset=utf-8; header=present', :filename => filename) end end diff --git a/app/controllers/questions_controller.rb b/app/controllers/questions_controller.rb index 9935f798d..9eaaaf603 100644 --- a/app/controllers/questions_controller.rb +++ b/app/controllers/questions_controller.rb @@ -1193,8 +1193,9 @@ def export else question = @earl.question - redis_key = "export_#{@earl.question_id}_#{type}_#{Time.now.to_i}" - redis_key += "_#{Digest::SHA1.hexdigest(redis_key + rand(10000000).to_s)}" + o = [('a'..'z'), ('A'..'Z')].map { |i| i.to_a }.flatten + randstring = (0...4).map { o[rand(o.length)] }.join + redis_key = "wikisurvey_#{@earl.question_id}_#{type.gsub("_", "")}_#{Time.now.utc.iso8601}_#{randstring}" question.post(:export, :type => type, :response_type => 'redis', :redis_key => redis_key) From b3fc8112389e753ff3a753da410ca61869f5ca62 Mon Sep 17 00:00:00 2001 From: Luke Baker Date: Thu, 20 Mar 2014 15:32:48 -0400 Subject: [PATCH 2/7] when reading in CSV string from redis, force UTF-8 Previous default was ASCII-8BIT, but all our data should be UTF-8. [#58508452] --- lib/munge_and_notify_job.rb | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/lib/munge_and_notify_job.rb b/lib/munge_and_notify_job.rb index 19f4444cc..a39ed0315 100644 --- a/lib/munge_and_notify_job.rb +++ b/lib/munge_and_notify_job.rb @@ -22,7 +22,7 @@ def perform r.del(redis_key) # client is responsible for deleting key zstream = Zlib::Inflate.new - csvdata = zstream.inflate(zlibcsv) + csvdata = zstream.inflate(zlibcsv).force_encoding('UTF-8') zstream.finish zstream.close @@ -142,9 +142,8 @@ def perform row << ['Hashed IP Address', Digest::MD5.hexdigest([user_session.ip_addr, APP_CONFIG[:IP_ADDR_HASH_SALT]].join(""))] - # we've had some referrers be UTF-8, rest of CSV is ASCII-8BIT - row << ['URL Alias', url_alias.force_encoding('ASCII-8BIT')] - row << ['User Agent', user_session.user_agent.try(:force_encoding, 'ASCII-8BIT')] + row << ['URL Alias', url_alias] + row << ['User Agent', user_session.user_agent] # grab most recent referrer from clicks # that is older than this current vote @@ -158,7 +157,7 @@ def perform referrer = (session_start) ? session_start.referrer : 'REFERRER_NOT_FOUND' referrer = 'DIRECT_VISIT' if referrer == '/' # we've had some referrers be UTF-8, rest of CSV is ASCII-8BIT - row << ['Referrer', referrer.force_encoding('ASCII-8BIT')] + row << ['Referrer', referrer] vote_click = user_session.find_click_for_vote(row) widget = (vote_click.widget?) ? 'TRUE' : 'FALSE' @@ -166,7 +165,7 @@ def perform info = user_session.find_info_value(row) info = 'NA' unless info - row << ['Info', info.force_encoding('ASCII-8BIT')] + row << ['Info', info] if current_user.admin? #row << ['Geolocation Info', user_session.loc_info.to_s] From 6dccec3ff964d1a72645674a91b907cf57fde7f5 Mon Sep 17 00:00:00 2001 From: Luke Baker Date: Thu, 20 Mar 2014 16:06:43 -0400 Subject: [PATCH 3/7] alter layout of CSV file request links [#60135898] --- app/views/questions/admin.html.haml | 36 ++++++++++++++++------------- public/javascripts/application.js | 1 - public/stylesheets/sass/screen.sass | 4 ---- public/stylesheets/screen.css | 2 +- 4 files changed, 21 insertions(+), 22 deletions(-) diff --git a/app/views/questions/admin.html.haml b/app/views/questions/admin.html.haml index 9697e9c7e..8f82b9e71 100644 --- a/app/views/questions/admin.html.haml +++ b/app/views/questions/admin.html.haml @@ -101,22 +101,26 @@ %a.btn{:href => ""} Cancel - %table.table.csv-links - %thead - %tr - %th - = t('admin.download_idea_marketplace_data') - = link_to('', 'http://blog.allourideas.org/post/2739358388/download-your-data', :target=> '_blank', :class => 'glyphicon glyphicon-question-sign') - %tbody - %tr - %td.title - = link_to(t('admin.list_of_ideas_csv'), {:action => :export, :params => {:type => :ideas}}, :"data-toggle" => 'modal-ajax', :id => 'ideas_request_link') - %tr - %td.title - = link_to(t('admin.list_of_votes_csv'), {:action => :export, :params => {:type => :votes}}, :"data-toggle" => 'modal-ajax',:id => 'votes_request_link') - %tr - %td.title - = link_to(t('admin.list_of_non_votes_csv'), {:action => :export, :params => {:type => :non_votes}}, :"data-toggle" => 'modal-ajax', :id => 'non_votes_request_link') + .form-horizontal + %fieldset + %legend + = t('admin.download_idea_marketplace_data') + %small= link_to('', 'http://blog.allourideas.org/post/2739358388/download-your-data', :target=> '_blank', :class => 'glyphicon glyphicon-question-sign') + .control-group + %label.control-label + = t('admin.list_of_ideas_csv') + .controls + = link_to(t('admin.request'), {:action => :export, :params => {:type => :ideas}}, :"data-toggle" => 'modal-ajax', :class => "btn btn-primary") + .control-group + %label.control-label + = t('admin.list_of_votes_csv') + .controls + = link_to(t('admin.request'), {:action => :export, :params => {:type => :votes}}, :"data-toggle" => 'modal-ajax', :class => "btn btn-primary") + .control-group + %label.control-label + = t('admin.list_of_non_votes_csv') + .controls + = link_to(t('admin.request'), {:action => :export, :params => {:type => :non_votes}}, :"data-toggle" => 'modal-ajax', :class => "btn btn-primary") #cant-edit-question.modal.hide.fade .modal-body diff --git a/public/javascripts/application.js b/public/javascripts/application.js index e05807550..c2a56c166 100644 --- a/public/javascripts/application.js +++ b/public/javascripts/application.js @@ -15,7 +15,6 @@ AOI.app = (function($) { modalAjax(); preventDefaultLinks(); makeRowsClickable('.ideas-table tbody tr'); - makeRowsClickable('.csv-links tbody tr'); dataVisualizationOpen(); }; diff --git a/public/stylesheets/sass/screen.sass b/public/stylesheets/sass/screen.sass index fac485c58..e9aa98c60 100644 --- a/public/stylesheets/sass/screen.sass +++ b/public/stylesheets/sass/screen.sass @@ -433,10 +433,6 @@ p.add-idea width: 80% .score font-size: 120% -.csv-links - tbody - tr - cursor: pointer .vote-count-span text-align: center diff --git a/public/stylesheets/screen.css b/public/stylesheets/screen.css index ce7e59ddf..a382262ff 100644 --- a/public/stylesheets/screen.css +++ b/public/stylesheets/screen.css @@ -1 +1 @@ -a img,a:active{border:none}.center{text-align:center}.full{width:100%}.half{width:50%}.ninety{width:90%}input.text{border:1px solid #919191;padding:3px 3px 2px}.padding{margin:5px 0px}table{text-align:left;border-collapse:collapse}table td,table th{padding:5px}table .row0{background-color:#3198c1;color:#fff}table .row0 a{color:#fff;text-decoration:underline}table .row0 th.score{width:95px}table .row1{background-color:#fafafa}table .row2{background-color:#fefefe}table .thin td{padding:2px 5px;height:2px}table .votes{min-width:90px}table.recent-winners td{text-align:center}table.item td:last-child{font-weight:bold}table.left{margin:0}table.signup td{max-width:400px}.create-question h2{padding-bottom:0px}.create-question p{padding:15px 25px;font-size:14px}.create-question p.ideas{padding-bottom:10px;padding-right:400px}.create-question .fieldWithErrors{padding:2px 0 3px;border:1px solid #ff6464}.errorExplanation{color:#fff;background:#ff6464;padding:8px 5px;border:1px solid #000}.errorExplanation h2{color:#fff}.errorExplanation ul li{margin-left:40px}.header.row-fluid{margin-top:10px}.header.row-fluid .nav{margin-top:10px;text-transform:uppercase}.header.row-fluid a.logo{display:block;margin-bottom:1em}.header.row-fluid a.logo:hover{border:none}.bread-crumb{color:#54afe2}.body{padding:0 0 30px}.body .center img{padding:0px 0px 30px 0px}.body .triple-left{min-height:150px}.body #body .triple-center,.body #body .triple-right{min-height:150px}.triple-left,.triple-center,.triple-right,.double-left{float:left}.noborder{border:none}.image-example{border:2px solid #eee;width:250px;margin:0px 0px 10px}.button{border:1px solid #3198c1;width:125px;padding:2px 0px;background-color:#54afe2;text-align:center;float:left}.button-link{color:#fff}.button:hover{border:1px solid #3198c1}.triple-left{border-right:1px dotted #d8dbdc;padding:0px 15px 2px 0px;width:264px}.triple-center{border-right:1px dotted #d8dbdc;padding:0px 15px 2px 15px;width:249px}.triple-right{padding:0px 0px 2px 15px;width:265px}.double-left{padding:0px 15px 2px 0px;width:545px}.vote-question{background-color:#fff;text-align:center;padding:15px 15px;color:#333;border-radius:7px;-webkit-border-radius:7px;-moz-border-radius:7px}.votebox{margin-top:20px}.skip{margin:10px 0}.right-border{border-right:1px dotted #d8dbdc}.footer{border-top:1px solid #d9d9d9;background-color:#f2f2f2;color:#989898;padding:20px;font-size:12px;line-height:13px}.footer a{color:#989898}.footer .breadcrumb{padding-left:0;background-color:inherit;margin-bottom:0}div.bar-chart{border:1px solid #ccc;width:250px;margin:2px 5px 2px 0;padding:1px;float:left;background:#fff}div.bar-chart>div{background-color:#797979;height:12px;margin:0}hr{border:none;border-bottom:1px dotted #bbb;margin:0 0 15px 0}.form-btn{color:#000}.error,.notice,.vote-notice{color:#fff;background-color:#ff6464;margin:-10px 10em 25px;text-align:center;font-size:13px}.notice{background-color:#ffc;border:1px solid #797979;color:#797979;text-align:left;padding:5px 10px;margin:0 40px 25px}.notice span.close{display:block;text-align:right}.notice span.close:hover{border:none}.vote-notice{background-color:#0b0}.border *,.border-thick *,.round-filled *,.round-filled-grey *{font-size:0.01px;line-height:0.01px;display:block;height:1px;overflow:hidden;padding:0px}.border-top,.border-bottom,.border2,.round-filled-top,.round-filled-bottom,.round-filled-grey-top,round-filled-grey-top{padding-left:1px;padding-right:1px}.border-top,.border-bottom{margin-left:3px;margin-right:3px}.border-top{border-bottom:1px solid #e9e9e9}.border-bottom{border-top:1px solid #e9e9e9}.border2,.border3,.border4,.border5,.borderfg{border-left:1px solid #e9e9e9;border-right:1px solid #e9e9e9}.border2,.border3{margin-left:1px;margin-right:1px}.border-thick-top{border-bottom:2px solid #e9e9e9}.border-thick-bottom{border-top:2px solid #e9e9e9}.border-thick2,.border-thick3,.border-thick4,.border-thick5,.border-thickfg{border-left:2px solid #e9e9e9;border-right:2px solid #e9e9e9}.round-filled-top,.round-filled-bottom{margin-left:3px;margin-right:3px;border-left:1px solid #3198c1;border-right:1px solid #3198c1;background:#3198c1}.round-filled-grey-top,.round-filled-grey-bottom{margin-left:3px;margin-right:3px;border-left:1px solid #ccc;border-right:1px solid #ccc;background:#ccc}.round-filled-grey2,.round-filled-grey3,.round-filled-grey4,.round-filled-grey5,.round-filled-greyfg{border-left:1px solid #ccc;border-right:1px solid #ccc;background:#ccc;color:#686868}.round-filled2,.round-filled3,.round-filled4,.round-filled5,.round-filledfg{border-left:1px solid #3198c1;border-right:1px solid #3198c1;background:#3198c1}.rounded{border-radius:5px;-moz-border-radius:5px}.round-filled2,.round-filled3,.round-filled-grey2,.round-filled-grey3{margin-left:1px;margin-right:1px}div.form_field{position:relative;float:left}label.over-apply{color:#ccc;position:absolute;top:0px;left:5px}table.tablesorter thead tr .header{padding-right:12px;background-image:url(../images/bg-invert.gif);background-repeat:no-repeat;background-position:center right;cursor:pointer}table.tablesorter tbody td{color:#3d3d3d;padding:4px;vertical-align:top}table.tablesorter tbody tr.odd td{background-color:#fafafa}table.tablesorter tbody tr.even td{background-color:#fefefe}table.tablesorter thead tr .headerSortUp{background-image:url(../images/asc-invert.gif)}table.tablesorter thead tr .headerSortDown{background-image:url(../images/desc-invert.gif)}.twenty_pixel_font{font-size:20px}.sixteen_pixel_font{font-size:16px}.twelve_pixel_font{font-size:12px}.active{color:#000}.firsttime{position:fixed;top:0;left:0;width:100%;z-index:100;background:#4dbae6;color:#185b75;font-size:15px;font-weight:bold;text-align:center;border-bottom:1px solid #1f7293;padding:4px;margin-bottom:8px;display:none}.cant-decide{text-align:center}#cant_decide_options .cd_options{width:100%;overflow:auto}.wider{color:#000}.wider td{padding:5px !important}.wider td.no_bottom_padding{padding-bottom:0px !important}.wider td.no_top_padding{padding-top:0px !important;vertical-align:top}.wider h2{font-weight:bold;color:#3198c1}.cd_submit_button{padding:5px 10px 5px 10px;background:#3198c1;cursor:pointer;color:#fff}.cd_submit_button:hover{background-color:#2b88ad}.add-idea-row{border-top:10px solid #fff;padding:0 5%}p.add-idea{margin-top:30px}.add_idea{margin:0}.add_idea a.add-idea-link{text-decoration:none;display:block;width:300px}.add_idea .add_idea_button{padding:5px 10px 5px 10px;width:265px;height:3em;display:table-cell;vertical-align:middle;color:#fff;font-size:16px;cursor:pointer;background:#01bb00}.add_idea .add_idea_button a{color:#fff}.add_idea .add_idea_button:hover{background:#228b53}.add_container{height:12em}.no_bottom_padding{padding-bottom:0px !important}.question-admin-form{margin-top:20px}.question-admin-form .form-horizontal .controls{margin-left:190px}.question-admin-form .form-horizontal .control-label{width:170px}.ideas-table tbody tr{cursor:pointer}.ideas-table td.choice-progress .progress{margin-bottom:0;float:left;width:80%}.ideas-table td.choice-progress .score{font-size:120%}.csv-links tbody tr{cursor:pointer}.vote-count-span{text-align:center}.rightside .flag{text-align:right}@media (max-width: 767px){.rightside .flag{text-align:left}}.navbar-aoi .btn-navbar{float:right}.navbar-aoi .navbar-inner{-webkit-border-radius:0;-moz-border-radius:0;border-radius:0;background-color:#333;background-image:-moz-linear-gradient(top, #3d3d3d, #2c2c2c);background-image:-ms-linear-gradient(top, #3d3d3d, #2c2c2c);background-image:-webkit-gradient(linear, 0 0, 0 100%, from(#3d3d3d), to(#2c2c2c));background-image:-webkit-linear-gradient(top, #3d3d3d, #2c2c2c);background-image:-o-linear-gradient(top, #3d3d3d, #2c2c2c);background-image:linear-gradient(top, #3d3d3d,#2c2c2c);background-repeat:repeat-x;filter:progid:dximagetransform.microsoft.gradient(startColorstr='#3d3d3d', endColorstr='#2c2c2c', GradientType=0)}.navbar-aoi .nav .active>a,.navbar-aoi .nav .active>a:hover,.navbar-aoi .nav .active>a:focus{background-color:transparent}.navbar-aoi .nav>li>a,.navbar-aoi .nav-collapse .dropdown-menu a{color:#999}.navbar-aoi .nav-collapse .nav>li>a:hover,.navbar-aoi .nav-collapse .dropdown-menu a:hover{color:#f2f2f2}@media (max-width: 767px){.navbar-aoi{margin-left:-20px;margin-right:-20px}}.votebox.row{height:128px;margin-bottom:10px;overflow:hidden}.vote-table-div{overflow:hidden}.vote-table{table-layout:fixed;width:100%;border-collapse:separate;*border-collapse:collapse;border-spacing:0}.table-cell-btn{font-size:20px;height:126px;padding:0 10px;display:table-cell}.progress-gray .bar{background-color:#ddd;background-image:-ms-linear-gradient(top, #ddd, #b5b5b5);background-image:-webkit-gradient(linear, 0 0, 0 100%, from(#ddd), to(#b5b5b5));background-image:-webkit-linear-gradient(top, #ddd, #b5b5b5);background-image:-o-linear-gradient(top, #ddd, #b5b5b5);background-image:linear-gradient(top, #dddddd,#b5b5b5);background-image:-moz-linear-gradient(top, #ddd, #b5b5b5);background-repeat:repeat-x;filter:progid:dximagetransform.microsoft.gradient(startColorstr='#dddddd', endColorstr='#b5b5b5', GradientType=0)}.results-table-header{background-color:#f2f2f2}.results-table-header h3{margin-top:0;background-color:#000;text-align:center;color:#fefefe;-moz-border-top-left-radius:10px;-webkit-border-top-left-radius:10px;border-top-left-radius:10px;-khtml-border-top-left-radius:10px;-moz-border-top-right-radius:10px;-webkit-border-top-right-radius:10px;border-top-right-radius:10px;-khtml-border-top-right-radius:10px}@media (max-width: 767px){.nav-tabs.vote-tabs{float:none;padding-right:0;border-bottom:0;margin-bottom:1em}.nav-tabs.vote-tabs li{float:none}.nav-tabs.vote-tabs li>a{border:1px solid #ddd;border-radius:0;-webkit-border-radius:0;-moz-border-radius:0;margin-right:0}.nav-tabs.vote-tabs li:first-child>a{-webkit-border-top-right-radius:4px;-moz-border-top-right-radius:4px;border-top-right-radius:4px;-webkit-border-top-left-radius:4px;-moz-border-top-left-radius:4px;border-top-left-radius:4px}.nav-tabs.vote-tabs li:last-child>a{-webkit-border-bottom-right-radius:4px;-moz-border-bottom-right-radius:4px;border-bottom-right-radius:4px;-webkit-border-bottom-left-radius:4px;-moz-border-bottom-left-radius:4px;border-bottom-left-radius:4px}.nav-tabs.vote-tabs li>a:hover{z-index:2;border-color:#ddd}}.survey-image-col{margin-top:-40px}.survey-image-col .survey-image{position:relative;padding-right:10px;bottom:-30px}.survey-image-col .survey-image-links{margin-top:12px}@media (max-width: 767px){.survey-image-col{margin:0}.survey-image-col .survey-image{position:static;margin-bottom:10px}}#new_idea_field{font-size:18px;line-height:27px}.data-vis-header{padding-left:15px}.aoi-hero-unit{text-align:center}.aoi-hero-unit .headline{font-weight:200;margin:1.5em 0 0.5em}.aoi-hero-unit .sub-headline{font-size:20px;font-weight:200;color:#666;line-height:1.3;max-width:680px;margin-left:auto;margin-right:auto}.aoi-hero-unit .headline-buttons{margin-top:2em}.descriptions h3{margin-bottom:0;font-weight:normal;line-height:1}.descriptions .row-fluid{margin-bottom:6em}.descriptions .image{text-align:center}.descriptions .math-formula{margin-top:3em}@media (max-width: 480px){.descriptions .row-fluid{margin-bottom:3em}.descriptions .math-formula,.descriptions .tux{margin:0 0 1em 0}}.how-it-works{margin:3em 0 6em;text-align:center}.how-it-works .divider-holder{position:relative}.how-it-works .divider{width:78px;height:350px;background-image:url("../images/homepage/arrow.png");display:block;position:absolute;top:-20px;right:-50px}.how-it-works .participate-holder{padding:0 30px;height:200px}.how-it-works h3.title{color:#7d7d7d;text-transform:uppercase;font-weight:200;line-height:1em;font-size:20px}.how-it-works .boxes{padding-top:1em;background-color:#f2f2f2;border-radius:10px;-moz-border-radius:10px;-webkit-border-radius:10px}.how-it-works .boxes h3{margin-bottom:0;line-height:1em;color:#48a1db;padding:0 20px}.how-it-works .boxes h3 a{color:#48a1db}.how-it-works .boxes h3 a:hover{text-decoration:none}.how-it-works .boxes p{padding:0 20px}.overall-stats{font-weight:200;text-align:center}.overall-stats .wiki-surveys-count,.overall-stats .votes-count,.overall-stats .ideas-count{font-weight:bold;font-size:130%}.flexslider{padding:0 70px;padding-background-color:#f5f5f5}.flexslider .slides{padding:10px 0;background-color:#f5f5f5}.flexslider .slides li{padding:0 10px}.flexslider .flex-direction-nav a{color:#fff;text-decoration:none}@media (max-width: 480px){.flexslider{padding:0 45px}.flex-direction-nav a{width:45px}} +a img,a:active{border:none}.center{text-align:center}.full{width:100%}.half{width:50%}.ninety{width:90%}input.text{border:1px solid #919191;padding:3px 3px 2px}.padding{margin:5px 0px}table{text-align:left;border-collapse:collapse}table td,table th{padding:5px}table .row0{background-color:#3198c1;color:#fff}table .row0 a{color:#fff;text-decoration:underline}table .row0 th.score{width:95px}table .row1{background-color:#fafafa}table .row2{background-color:#fefefe}table .thin td{padding:2px 5px;height:2px}table .votes{min-width:90px}table.recent-winners td{text-align:center}table.item td:last-child{font-weight:bold}table.left{margin:0}table.signup td{max-width:400px}.create-question h2{padding-bottom:0px}.create-question p{padding:15px 25px;font-size:14px}.create-question p.ideas{padding-bottom:10px;padding-right:400px}.create-question .fieldWithErrors{padding:2px 0 3px;border:1px solid #ff6464}.errorExplanation{color:#fff;background:#ff6464;padding:8px 5px;border:1px solid #000}.errorExplanation h2{color:#fff}.errorExplanation ul li{margin-left:40px}.header.row-fluid{margin-top:10px}.header.row-fluid .nav{margin-top:10px;text-transform:uppercase}.header.row-fluid a.logo{display:block;margin-bottom:1em}.header.row-fluid a.logo:hover{border:none}.bread-crumb{color:#54afe2}.body{padding:0 0 30px}.body .center img{padding:0px 0px 30px 0px}.body .triple-left{min-height:150px}.body #body .triple-center,.body #body .triple-right{min-height:150px}.triple-left,.triple-center,.triple-right,.double-left{float:left}.noborder{border:none}.image-example{border:2px solid #eee;width:250px;margin:0px 0px 10px}.button{border:1px solid #3198c1;width:125px;padding:2px 0px;background-color:#54afe2;text-align:center;float:left}.button-link{color:#fff}.button:hover{border:1px solid #3198c1}.triple-left{border-right:1px dotted #d8dbdc;padding:0px 15px 2px 0px;width:264px}.triple-center{border-right:1px dotted #d8dbdc;padding:0px 15px 2px 15px;width:249px}.triple-right{padding:0px 0px 2px 15px;width:265px}.double-left{padding:0px 15px 2px 0px;width:545px}.vote-question{background-color:#fff;text-align:center;padding:15px 15px;color:#333;border-radius:7px;-webkit-border-radius:7px;-moz-border-radius:7px}.votebox{margin-top:20px}.skip{margin:10px 0}.right-border{border-right:1px dotted #d8dbdc}.footer{border-top:1px solid #d9d9d9;background-color:#f2f2f2;color:#989898;padding:20px;font-size:12px;line-height:13px}.footer a{color:#989898}.footer .breadcrumb{padding-left:0;background-color:inherit;margin-bottom:0}div.bar-chart{border:1px solid #ccc;width:250px;margin:2px 5px 2px 0;padding:1px;float:left;background:#fff}div.bar-chart>div{background-color:#797979;height:12px;margin:0}hr{border:none;border-bottom:1px dotted #bbb;margin:0 0 15px 0}.form-btn{color:#000}.error,.notice,.vote-notice{color:#fff;background-color:#ff6464;margin:-10px 10em 25px;text-align:center;font-size:13px}.notice{background-color:#ffc;border:1px solid #797979;color:#797979;text-align:left;padding:5px 10px;margin:0 40px 25px}.notice span.close{display:block;text-align:right}.notice span.close:hover{border:none}.vote-notice{background-color:#0b0}.border *,.border-thick *,.round-filled *,.round-filled-grey *{font-size:0.01px;line-height:0.01px;display:block;height:1px;overflow:hidden;padding:0px}.border-top,.border-bottom,.border2,.round-filled-top,.round-filled-bottom,.round-filled-grey-top,round-filled-grey-top{padding-left:1px;padding-right:1px}.border-top,.border-bottom{margin-left:3px;margin-right:3px}.border-top{border-bottom:1px solid #e9e9e9}.border-bottom{border-top:1px solid #e9e9e9}.border2,.border3,.border4,.border5,.borderfg{border-left:1px solid #e9e9e9;border-right:1px solid #e9e9e9}.border2,.border3{margin-left:1px;margin-right:1px}.border-thick-top{border-bottom:2px solid #e9e9e9}.border-thick-bottom{border-top:2px solid #e9e9e9}.border-thick2,.border-thick3,.border-thick4,.border-thick5,.border-thickfg{border-left:2px solid #e9e9e9;border-right:2px solid #e9e9e9}.round-filled-top,.round-filled-bottom{margin-left:3px;margin-right:3px;border-left:1px solid #3198c1;border-right:1px solid #3198c1;background:#3198c1}.round-filled-grey-top,.round-filled-grey-bottom{margin-left:3px;margin-right:3px;border-left:1px solid #ccc;border-right:1px solid #ccc;background:#ccc}.round-filled-grey2,.round-filled-grey3,.round-filled-grey4,.round-filled-grey5,.round-filled-greyfg{border-left:1px solid #ccc;border-right:1px solid #ccc;background:#ccc;color:#686868}.round-filled2,.round-filled3,.round-filled4,.round-filled5,.round-filledfg{border-left:1px solid #3198c1;border-right:1px solid #3198c1;background:#3198c1}.rounded{border-radius:5px;-moz-border-radius:5px}.round-filled2,.round-filled3,.round-filled-grey2,.round-filled-grey3{margin-left:1px;margin-right:1px}div.form_field{position:relative;float:left}label.over-apply{color:#ccc;position:absolute;top:0px;left:5px}table.tablesorter thead tr .header{padding-right:12px;background-image:url(../images/bg-invert.gif);background-repeat:no-repeat;background-position:center right;cursor:pointer}table.tablesorter tbody td{color:#3d3d3d;padding:4px;vertical-align:top}table.tablesorter tbody tr.odd td{background-color:#fafafa}table.tablesorter tbody tr.even td{background-color:#fefefe}table.tablesorter thead tr .headerSortUp{background-image:url(../images/asc-invert.gif)}table.tablesorter thead tr .headerSortDown{background-image:url(../images/desc-invert.gif)}.twenty_pixel_font{font-size:20px}.sixteen_pixel_font{font-size:16px}.twelve_pixel_font{font-size:12px}.active{color:#000}.firsttime{position:fixed;top:0;left:0;width:100%;z-index:100;background:#4dbae6;color:#185b75;font-size:15px;font-weight:bold;text-align:center;border-bottom:1px solid #1f7293;padding:4px;margin-bottom:8px;display:none}.cant-decide{text-align:center}#cant_decide_options .cd_options{width:100%;overflow:auto}.wider{color:#000}.wider td{padding:5px !important}.wider td.no_bottom_padding{padding-bottom:0px !important}.wider td.no_top_padding{padding-top:0px !important;vertical-align:top}.wider h2{font-weight:bold;color:#3198c1}.cd_submit_button{padding:5px 10px 5px 10px;background:#3198c1;cursor:pointer;color:#fff}.cd_submit_button:hover{background-color:#2b88ad}.add-idea-row{border-top:10px solid #fff;padding:0 5%}p.add-idea{margin-top:30px}.add_idea{margin:0}.add_idea a.add-idea-link{text-decoration:none;display:block;width:300px}.add_idea .add_idea_button{padding:5px 10px 5px 10px;width:265px;height:3em;display:table-cell;vertical-align:middle;color:#fff;font-size:16px;cursor:pointer;background:#01bb00}.add_idea .add_idea_button a{color:#fff}.add_idea .add_idea_button:hover{background:#228b53}.add_container{height:12em}.no_bottom_padding{padding-bottom:0px !important}.question-admin-form{margin-top:20px}.question-admin-form .form-horizontal .controls{margin-left:190px}.question-admin-form .form-horizontal .control-label{width:170px}.ideas-table tbody tr{cursor:pointer}.ideas-table td.choice-progress .progress{margin-bottom:0;float:left;width:80%}.ideas-table td.choice-progress .score{font-size:120%}.vote-count-span{text-align:center}.rightside .flag{text-align:right}@media (max-width: 767px){.rightside .flag{text-align:left}}.navbar-aoi .btn-navbar{float:right}.navbar-aoi .navbar-inner{-webkit-border-radius:0;-moz-border-radius:0;border-radius:0;background-color:#333;background-image:-moz-linear-gradient(top, #3d3d3d, #2c2c2c);background-image:-ms-linear-gradient(top, #3d3d3d, #2c2c2c);background-image:-webkit-gradient(linear, 0 0, 0 100%, from(#3d3d3d), to(#2c2c2c));background-image:-webkit-linear-gradient(top, #3d3d3d, #2c2c2c);background-image:-o-linear-gradient(top, #3d3d3d, #2c2c2c);background-image:linear-gradient(top, #3d3d3d,#2c2c2c);background-repeat:repeat-x;filter:progid:dximagetransform.microsoft.gradient(startColorstr='#3d3d3d', endColorstr='#2c2c2c', GradientType=0)}.navbar-aoi .nav .active>a,.navbar-aoi .nav .active>a:hover,.navbar-aoi .nav .active>a:focus{background-color:transparent}.navbar-aoi .nav>li>a,.navbar-aoi .nav-collapse .dropdown-menu a{color:#999}.navbar-aoi .nav-collapse .nav>li>a:hover,.navbar-aoi .nav-collapse .dropdown-menu a:hover{color:#f2f2f2}@media (max-width: 767px){.navbar-aoi{margin-left:-20px;margin-right:-20px}}.votebox.row{height:128px;margin-bottom:10px;overflow:hidden}.vote-table-div{overflow:hidden}.vote-table{table-layout:fixed;width:100%;border-collapse:separate;*border-collapse:collapse;border-spacing:0}.table-cell-btn{font-size:20px;height:126px;padding:0 10px;display:table-cell}.progress-gray .bar{background-color:#ddd;background-image:-ms-linear-gradient(top, #ddd, #b5b5b5);background-image:-webkit-gradient(linear, 0 0, 0 100%, from(#ddd), to(#b5b5b5));background-image:-webkit-linear-gradient(top, #ddd, #b5b5b5);background-image:-o-linear-gradient(top, #ddd, #b5b5b5);background-image:linear-gradient(top, #dddddd,#b5b5b5);background-image:-moz-linear-gradient(top, #ddd, #b5b5b5);background-repeat:repeat-x;filter:progid:dximagetransform.microsoft.gradient(startColorstr='#dddddd', endColorstr='#b5b5b5', GradientType=0)}.results-table-header{background-color:#f2f2f2}.results-table-header h3{margin-top:0;background-color:#000;text-align:center;color:#fefefe;-moz-border-top-left-radius:10px;-webkit-border-top-left-radius:10px;border-top-left-radius:10px;-khtml-border-top-left-radius:10px;-moz-border-top-right-radius:10px;-webkit-border-top-right-radius:10px;border-top-right-radius:10px;-khtml-border-top-right-radius:10px}@media (max-width: 767px){.nav-tabs.vote-tabs{float:none;padding-right:0;border-bottom:0;margin-bottom:1em}.nav-tabs.vote-tabs li{float:none}.nav-tabs.vote-tabs li>a{border:1px solid #ddd;border-radius:0;-webkit-border-radius:0;-moz-border-radius:0;margin-right:0}.nav-tabs.vote-tabs li:first-child>a{-webkit-border-top-right-radius:4px;-moz-border-top-right-radius:4px;border-top-right-radius:4px;-webkit-border-top-left-radius:4px;-moz-border-top-left-radius:4px;border-top-left-radius:4px}.nav-tabs.vote-tabs li:last-child>a{-webkit-border-bottom-right-radius:4px;-moz-border-bottom-right-radius:4px;border-bottom-right-radius:4px;-webkit-border-bottom-left-radius:4px;-moz-border-bottom-left-radius:4px;border-bottom-left-radius:4px}.nav-tabs.vote-tabs li>a:hover{z-index:2;border-color:#ddd}}.survey-image-col{margin-top:-40px}.survey-image-col .survey-image{position:relative;padding-right:10px;bottom:-30px}.survey-image-col .survey-image-links{margin-top:12px}@media (max-width: 767px){.survey-image-col{margin:0}.survey-image-col .survey-image{position:static;margin-bottom:10px}}#new_idea_field{font-size:18px;line-height:27px}.data-vis-header{padding-left:15px}.aoi-hero-unit{text-align:center}.aoi-hero-unit .headline{font-weight:200;margin:1.5em 0 0.5em}.aoi-hero-unit .sub-headline{font-size:20px;font-weight:200;color:#666;line-height:1.3;max-width:680px;margin-left:auto;margin-right:auto}.aoi-hero-unit .headline-buttons{margin-top:2em}.descriptions h3{margin-bottom:0;font-weight:normal;line-height:1}.descriptions .row-fluid{margin-bottom:6em}.descriptions .image{text-align:center}.descriptions .math-formula{margin-top:3em}@media (max-width: 480px){.descriptions .row-fluid{margin-bottom:3em}.descriptions .math-formula,.descriptions .tux{margin:0 0 1em 0}}.how-it-works{margin:3em 0 6em;text-align:center}.how-it-works .divider-holder{position:relative}.how-it-works .divider{width:78px;height:350px;background-image:url("../images/homepage/arrow.png");display:block;position:absolute;top:-20px;right:-50px}.how-it-works .participate-holder{padding:0 30px;height:200px}.how-it-works h3.title{color:#7d7d7d;text-transform:uppercase;font-weight:200;line-height:1em;font-size:20px}.how-it-works .boxes{padding-top:1em;background-color:#f2f2f2;border-radius:10px;-moz-border-radius:10px;-webkit-border-radius:10px}.how-it-works .boxes h3{margin-bottom:0;line-height:1em;color:#48a1db;padding:0 20px}.how-it-works .boxes h3 a{color:#48a1db}.how-it-works .boxes h3 a:hover{text-decoration:none}.how-it-works .boxes p{padding:0 20px}.overall-stats{font-weight:200;text-align:center}.overall-stats .wiki-surveys-count,.overall-stats .votes-count,.overall-stats .ideas-count{font-weight:bold;font-size:130%}.flexslider{padding:0 70px;padding-background-color:#f5f5f5}.flexslider .slides{padding:10px 0;background-color:#f5f5f5}.flexslider .slides li{padding:0 10px}.flexslider .flex-direction-nav a{color:#fff;text-decoration:none}@media (max-width: 480px){.flexslider{padding:0 45px}.flex-direction-nav a{width:45px}} From 3d13dbf2c1131405be003171b31bfd5241ec8e12 Mon Sep 17 00:00:00 2001 From: Luke Baker Date: Fri, 21 Mar 2014 10:46:08 -0400 Subject: [PATCH 4/7] replace idea marketplace with wiki survey update markup for download links --- app/views/questions/admin.html.haml | 39 ++++++++++++++--------------- config/locales/allourideas/ar.yml | 2 +- config/locales/allourideas/en.yml | 2 +- public/stylesheets/sass/styles.scss | 8 ++++++ public/stylesheets/styles.css | 2 +- 5 files changed, 30 insertions(+), 23 deletions(-) diff --git a/app/views/questions/admin.html.haml b/app/views/questions/admin.html.haml index 8f82b9e71..209cdf364 100644 --- a/app/views/questions/admin.html.haml +++ b/app/views/questions/admin.html.haml @@ -101,26 +101,25 @@ %a.btn{:href => ""} Cancel - .form-horizontal - %fieldset - %legend - = t('admin.download_idea_marketplace_data') - %small= link_to('', 'http://blog.allourideas.org/post/2739358388/download-your-data', :target=> '_blank', :class => 'glyphicon glyphicon-question-sign') - .control-group - %label.control-label - = t('admin.list_of_ideas_csv') - .controls - = link_to(t('admin.request'), {:action => :export, :params => {:type => :ideas}}, :"data-toggle" => 'modal-ajax', :class => "btn btn-primary") - .control-group - %label.control-label - = t('admin.list_of_votes_csv') - .controls - = link_to(t('admin.request'), {:action => :export, :params => {:type => :votes}}, :"data-toggle" => 'modal-ajax', :class => "btn btn-primary") - .control-group - %label.control-label - = t('admin.list_of_non_votes_csv') - .controls - = link_to(t('admin.request'), {:action => :export, :params => {:type => :non_votes}}, :"data-toggle" => 'modal-ajax', :class => "btn btn-primary") + %fieldset.download-data + %legend + = t('admin.download_idea_marketplace_data') + %small= link_to('', 'http://blog.allourideas.org/post/2739358388/download-your-data', :target=> '_blank', :class => 'glyphicon glyphicon-question-sign') + .row-fluid + .span4.title + = t('admin.list_of_ideas_csv') + .span2 + = link_to(t('admin.request'), {:action => :export, :params => {:type => :ideas}}, :"data-toggle" => 'modal-ajax', :class => "btn btn-primary") + .row-fluid + .span4.title + = t('admin.list_of_votes_csv') + .span2 + = link_to(t('admin.request'), {:action => :export, :params => {:type => :votes}}, :"data-toggle" => 'modal-ajax', :class => "btn btn-primary") + .row-fluid + .span4.title + = t('admin.list_of_non_votes_csv') + .span2 + = link_to(t('admin.request'), {:action => :export, :params => {:type => :non_votes}}, :"data-toggle" => 'modal-ajax', :class => "btn btn-primary") #cant-edit-question.modal.hide.fade .modal-body diff --git a/config/locales/allourideas/ar.yml b/config/locales/allourideas/ar.yml index 9ac8ebb94..e15ef198c 100644 --- a/config/locales/allourideas/ar.yml +++ b/config/locales/allourideas/ar.yml @@ -295,7 +295,7 @@ ar: allow_flag_as_inappropriate: Allow users to flag individual ideas as inappropriate. allow_flag_as_inappropriate_exp: This setting will allow users to flag ideas as inappropriate or offtopic. After a user submits a flag request, the idea will be automatically deactivated and an email will be sent to the owner of the idea marketplace. The email will contain whatever explanation the user provided along with the option to quickly re-activate an idea. default_lang_exp: Change the default language of the voting page interface - download_idea_marketplace_data: Download Idea Marketplace Data + download_idea_marketplace_data: Download Wiki Survey Data list_of_ideas_csv: List of Ideas (CSV File) list_of_votes_csv: List of Votes (CSV File) list_of_non_votes_csv: List of Non Vote Actions (CSV File) diff --git a/config/locales/allourideas/en.yml b/config/locales/allourideas/en.yml index d678d5e9d..d9ed3742e 100644 --- a/config/locales/allourideas/en.yml +++ b/config/locales/allourideas/en.yml @@ -300,7 +300,7 @@ en: allow_flag_as_inappropriate: Allow users to flag individual ideas as inappropriate. allow_flag_as_inappropriate_exp: This setting will allow users to flag ideas as inappropriate or offtopic. After a user submits a flag request, the idea will be automatically deactivated and an email will be sent to the owner of the wiki survey. The email will contain whatever explanation the user provided along with the option to quickly re-activate an idea. default_lang_exp: Change the default language of the voting page interface - download_idea_marketplace_data: Download Idea Marketplace Data + download_idea_marketplace_data: Download Wiki Survey Data list_of_ideas_csv: List of Ideas (CSV File) list_of_votes_csv: List of Votes (CSV File) list_of_non_votes_csv: List of Non Vote Actions (CSV File) diff --git a/public/stylesheets/sass/styles.scss b/public/stylesheets/sass/styles.scss index 26b77f729..24a92ac3a 100644 --- a/public/stylesheets/sass/styles.scss +++ b/public/stylesheets/sass/styles.scss @@ -425,3 +425,11 @@ a i.glyphicon { text-decoration: none; } } +.download-data { + .row-fluid { + margin-bottom: 0.5em; + } + .title { + text-align: right; + } +} diff --git a/public/stylesheets/styles.css b/public/stylesheets/styles.css index 2aa24e0a1..8de57c1b5 100644 --- a/public/stylesheets/styles.css +++ b/public/stylesheets/styles.css @@ -11,4 +11,4 @@ * */.container-fluid{max-width:1200px;margin-right:auto;margin-left:auto}/* * AOI CSS - */html{-webkit-overflow-scrolling:touch}body.modal-open{overflow:hidden}.logo{margin-top:1em}@media (max-width: 767px){h2{font-size:21px;line-height:30px}}@media (max-width: 767px){.pagination ul li.current{display:none}}.navbar-static-top{width:auto;min-width:100%}form#new_question_form fieldset legend{padding-top:1em}.vote-tabs{margin-bottom:0;border-bottom:none;padding-right:2em}.vote-tabs>li.active>a,.vote-tabs>li.active a:hover{background-color:#F2F2F2}.tab-content{background-color:#F2F2F2;padding:2em 0;border-radius:7px;-moz-border-radius:7px;-webkit-border-radius:7px;position:relative}#cookies-failed{position:absolute;top:0;width:100%;height:100%;background-color:rgba(0,0,0,0.8);border-radius:7px;-moz-border-radius:7px;-webkit-border-radius:7px}#cookies-failed>div{margin:4em 4em;padding:1em;background-color:#ffffff;border-radius:7px;-moz-border-radius:7px;-webkit-border-radius:7px}#cookies-failed h2{padding-left:25px;background:url(../images/blocked_cookies.png) no-repeat left center}.interior-content{background-color:white;margin:0 2em;padding:0 2em;border-radius:7px;-moz-border-radius:7px;-webkit-border-radius:7px}@media (max-width: 767px){.welcome-message .alert{margin-left:5%;margin-right:5%}}.vote-question{text-align:center}@media (max-width: 480px){.vote-question{font-size:18px;line-height:24px}}@media (max-width: 767px){.vote-question{margin:0 5%}}@media (max-width: 767px){.answers{margin:0;padding:0 5%;width:100%;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}.answers li{width:100%;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;margin-left:auto;margin-right:auto;margin-bottom:1em}}.vote_stats{text-align:center;color:#666666;font-size:12px;clear:both}.btn-vote{display:table-cell;vertical-align:middle;min-height:8em;width:100%}@media (max-width: 480px){.btn-vote{font-size:16px}}.cant_decide{text-align:center}@media (max-width: 767px){#cant_decide_btn{width:intrinsic;min-width:50%;display:block;margin-left:auto;margin-right:auto}}#cant_decide_options button.btn-primary,#cant_decide_options button.btn-vote{width:100%;min-height:3.6em}@media (min-width: 1200px){#cant_decide_options{width:600px}}@media (max-width: 979px) and (min-width: 768px){#cant_decide_options{width:500px}#cant_decide_options .span6{width:100%;margin-left:0}}@media (max-width: 767px){#cant_decide_options{position:fixed;top:10px;bottom:10px;left:10px;right:10px;width:auto}#cant_decide_options h2{font-size:14px;line-height:21px}#cant_decide_options button.btn-primary,#cant_decide_options button.btn-vote{min-height:auto}#cant_decide_options .modal-body{bottom:0px;top:60px;position:absolute;max-height:100%;height:auto;-webkit-overflow-scrolling:touch}#cant_decide_options .close{font-size:40px;line-height:30px}}#the_add_box h3{color:#367bbe}#the_add_box #new_idea_field{width:100%;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;min-height:4em}.choice-progress .progress{width:85%;float:left;margin-right:1em}@media (max-width: 767px){#data-vis{display:none;visibility:hidden}}@media (max-width: 767px){body .row-fluid .offset1{margin-left:0}body .row-fluid .offset1:first-child{margin-left:0}body .row-fluid .offset2{margin-left:0}body .row-fluid .offset2:first-child{margin-left:0}body .row-fluid .offset3{margin-left:0}body .row-fluid .offset3:first-child{margin-left:0}body .row-fluid .offset4{margin-left:0}body .row-fluid .offset4:first-child{margin-left:0}body .row-fluid .offset5{margin-left:0}body .row-fluid .offset5:first-child{margin-left:0}body .row-fluid .offset6{margin-left:0}body .row-fluid .offset6:first-child{margin-left:0}body .row-fluid .offset7{margin-left:0}body .row-fluid .offset7:first-child{margin-left:0}body .row-fluid .offset8{margin-left:0}body .row-fluid .offset8:first-child{margin-left:0}body .row-fluid .offset9{margin-left:0}body .row-fluid .offset9:first-child{margin-left:0}body .row-fluid .offset10{margin-left:0}body .row-fluid .offset10:first-child{margin-left:0}body .row-fluid .offset11{margin-left:0}body .row-fluid .offset11:first-child{margin-left:0}body .row-fluid .offset12{margin-left:0}body .row-fluid .offset12:first-child{margin-left:0}body.container-fluid{padding-left:1em;padding-right:1em}}ul.footer-social-icons{list-style:none;margin-left:0;overflow:hidden;width:128px}ul.footer-social-icons li a{display:block;text-indent:-9999px;background:url(../images/social_icons.png) no-repeat;background-size:152px 64px;float:left;width:32px;height:32px;white-space:nowrap}ul.footer-social-icons li.fb a:hover{background-position:0 -32px}ul.footer-social-icons li.twitter a{background-position:-40px 0}ul.footer-social-icons li.twitter a:hover{background-position:-40px -32px}ul.footer-social-icons li.github a{background-position:-80px 0}ul.footer-social-icons li.github a:hover{background-position:-80px -32px}ul.footer-social-icons li.blog a{background-position:-120px 0}ul.footer-social-icons li.blog a:hover{background-position:-120px -32px}@media only screen and (-webkit-min-device-pixel-ratio: 1.5), only screen and (-o-min-device-pixel-ratio: 3 / 2), only screen and (min--moz-device-pixel-ratio: 1.5), only screen and (min-device-pixel-ratio: 1.5){ul.footer-social-icons li a{background-image:url(../images/social_icons@2x.png)}}.navbar .brand{padding-top:1px;padding-bottom:1px}.powered-by{text-indent:-9999px;display:block;width:139px;height:29px;background:url(../images/powered-by-aoi.gif) no-repeat;font-size:0}.powered-by:hover{background-position:0 -29px}@media (max-width: 767px){.footer{margin-left:-20px;margin-right:-20px;text-align:center}.footer .powered-by{margin:0 auto}.footer .footer-right{float:none}.footer .footer-social-icons{margin:0 auto}.footer .generous-grantees{margin-bottom:40px}}.tooltip{font-size:14px}a.glyphicon{color:black}a.glyphicon:hover{text-decoration:none}a i.glyphicon{color:black}a i.glyphicon:hover{text-decoration:none} + */html{-webkit-overflow-scrolling:touch}body.modal-open{overflow:hidden}.logo{margin-top:1em}@media (max-width: 767px){h2{font-size:21px;line-height:30px}}@media (max-width: 767px){.pagination ul li.current{display:none}}.navbar-static-top{width:auto;min-width:100%}form#new_question_form fieldset legend{padding-top:1em}.vote-tabs{margin-bottom:0;border-bottom:none;padding-right:2em}.vote-tabs>li.active>a,.vote-tabs>li.active a:hover{background-color:#F2F2F2}.tab-content{background-color:#F2F2F2;padding:2em 0;border-radius:7px;-moz-border-radius:7px;-webkit-border-radius:7px;position:relative}#cookies-failed{position:absolute;top:0;width:100%;height:100%;background-color:rgba(0,0,0,0.8);border-radius:7px;-moz-border-radius:7px;-webkit-border-radius:7px}#cookies-failed>div{margin:4em 4em;padding:1em;background-color:#ffffff;border-radius:7px;-moz-border-radius:7px;-webkit-border-radius:7px}#cookies-failed h2{padding-left:25px;background:url(../images/blocked_cookies.png) no-repeat left center}.interior-content{background-color:white;margin:0 2em;padding:0 2em;border-radius:7px;-moz-border-radius:7px;-webkit-border-radius:7px}@media (max-width: 767px){.welcome-message .alert{margin-left:5%;margin-right:5%}}.vote-question{text-align:center}@media (max-width: 480px){.vote-question{font-size:18px;line-height:24px}}@media (max-width: 767px){.vote-question{margin:0 5%}}@media (max-width: 767px){.answers{margin:0;padding:0 5%;width:100%;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}.answers li{width:100%;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;margin-left:auto;margin-right:auto;margin-bottom:1em}}.vote_stats{text-align:center;color:#666666;font-size:12px;clear:both}.btn-vote{display:table-cell;vertical-align:middle;min-height:8em;width:100%}@media (max-width: 480px){.btn-vote{font-size:16px}}.cant_decide{text-align:center}@media (max-width: 767px){#cant_decide_btn{width:intrinsic;min-width:50%;display:block;margin-left:auto;margin-right:auto}}#cant_decide_options button.btn-primary,#cant_decide_options button.btn-vote{width:100%;min-height:3.6em}@media (min-width: 1200px){#cant_decide_options{width:600px}}@media (max-width: 979px) and (min-width: 768px){#cant_decide_options{width:500px}#cant_decide_options .span6{width:100%;margin-left:0}}@media (max-width: 767px){#cant_decide_options{position:fixed;top:10px;bottom:10px;left:10px;right:10px;width:auto}#cant_decide_options h2{font-size:14px;line-height:21px}#cant_decide_options button.btn-primary,#cant_decide_options button.btn-vote{min-height:auto}#cant_decide_options .modal-body{bottom:0px;top:60px;position:absolute;max-height:100%;height:auto;-webkit-overflow-scrolling:touch}#cant_decide_options .close{font-size:40px;line-height:30px}}#the_add_box h3{color:#367bbe}#the_add_box #new_idea_field{width:100%;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;min-height:4em}.choice-progress .progress{width:85%;float:left;margin-right:1em}@media (max-width: 767px){#data-vis{display:none;visibility:hidden}}@media (max-width: 767px){body .row-fluid .offset1{margin-left:0}body .row-fluid .offset1:first-child{margin-left:0}body .row-fluid .offset2{margin-left:0}body .row-fluid .offset2:first-child{margin-left:0}body .row-fluid .offset3{margin-left:0}body .row-fluid .offset3:first-child{margin-left:0}body .row-fluid .offset4{margin-left:0}body .row-fluid .offset4:first-child{margin-left:0}body .row-fluid .offset5{margin-left:0}body .row-fluid .offset5:first-child{margin-left:0}body .row-fluid .offset6{margin-left:0}body .row-fluid .offset6:first-child{margin-left:0}body .row-fluid .offset7{margin-left:0}body .row-fluid .offset7:first-child{margin-left:0}body .row-fluid .offset8{margin-left:0}body .row-fluid .offset8:first-child{margin-left:0}body .row-fluid .offset9{margin-left:0}body .row-fluid .offset9:first-child{margin-left:0}body .row-fluid .offset10{margin-left:0}body .row-fluid .offset10:first-child{margin-left:0}body .row-fluid .offset11{margin-left:0}body .row-fluid .offset11:first-child{margin-left:0}body .row-fluid .offset12{margin-left:0}body .row-fluid .offset12:first-child{margin-left:0}body.container-fluid{padding-left:1em;padding-right:1em}}ul.footer-social-icons{list-style:none;margin-left:0;overflow:hidden;width:128px}ul.footer-social-icons li a{display:block;text-indent:-9999px;background:url(../images/social_icons.png) no-repeat;background-size:152px 64px;float:left;width:32px;height:32px;white-space:nowrap}ul.footer-social-icons li.fb a:hover{background-position:0 -32px}ul.footer-social-icons li.twitter a{background-position:-40px 0}ul.footer-social-icons li.twitter a:hover{background-position:-40px -32px}ul.footer-social-icons li.github a{background-position:-80px 0}ul.footer-social-icons li.github a:hover{background-position:-80px -32px}ul.footer-social-icons li.blog a{background-position:-120px 0}ul.footer-social-icons li.blog a:hover{background-position:-120px -32px}@media only screen and (-webkit-min-device-pixel-ratio: 1.5), only screen and (-o-min-device-pixel-ratio: 3 / 2), only screen and (min--moz-device-pixel-ratio: 1.5), only screen and (min-device-pixel-ratio: 1.5){ul.footer-social-icons li a{background-image:url(../images/social_icons@2x.png)}}.navbar .brand{padding-top:1px;padding-bottom:1px}.powered-by{text-indent:-9999px;display:block;width:139px;height:29px;background:url(../images/powered-by-aoi.gif) no-repeat;font-size:0}.powered-by:hover{background-position:0 -29px}@media (max-width: 767px){.footer{margin-left:-20px;margin-right:-20px;text-align:center}.footer .powered-by{margin:0 auto}.footer .footer-right{float:none}.footer .footer-social-icons{margin:0 auto}.footer .generous-grantees{margin-bottom:40px}}.tooltip{font-size:14px}a.glyphicon{color:black}a.glyphicon:hover{text-decoration:none}a i.glyphicon{color:black}a i.glyphicon:hover{text-decoration:none}.download-data .row-fluid{margin-bottom:0.5em}.download-data .title{text-align:right} From 550849a820d245ba046ad4414b7d159a199e47a6 Mon Sep 17 00:00:00 2001 From: Luke Baker Date: Fri, 21 Mar 2014 11:19:38 -0400 Subject: [PATCH 5/7] re-add id to vote button for test --- app/views/questions/admin.html.haml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/views/questions/admin.html.haml b/app/views/questions/admin.html.haml index 209cdf364..233566108 100644 --- a/app/views/questions/admin.html.haml +++ b/app/views/questions/admin.html.haml @@ -114,7 +114,7 @@ .span4.title = t('admin.list_of_votes_csv') .span2 - = link_to(t('admin.request'), {:action => :export, :params => {:type => :votes}}, :"data-toggle" => 'modal-ajax', :class => "btn btn-primary") + = link_to(t('admin.request'), {:action => :export, :params => {:type => :votes}}, :"data-toggle" => 'modal-ajax', :class => "btn btn-primary", :id => "votes_request_link") .row-fluid .span4.title = t('admin.list_of_non_votes_csv') From b1c33747fca323aa92c8ab6c1d1551bd164ca279 Mon Sep 17 00:00:00 2001 From: Luke Baker Date: Wed, 26 Mar 2014 15:51:22 -0400 Subject: [PATCH 6/7] include more information in CSV error email We want to inform the user which CSV file failed and when they requested it. [#61313486] New Example: Hello, The ideas export you requested on March 19, 2014 21:06 (UTC) from the All Our Ideas site has failed. We've been notified of the problem and will be working on a fix. --- app/models/idea_mailer.rb | 4 +++- app/views/idea_mailer/export_failed.text.html.erb | 2 +- app/views/idea_mailer/export_failed.text.plain.erb | 2 +- lib/munge_and_notify_job.rb | 3 ++- 4 files changed, 7 insertions(+), 4 deletions(-) diff --git a/app/models/idea_mailer.rb b/app/models/idea_mailer.rb index 39987db57..92092aebf 100644 --- a/app/models/idea_mailer.rb +++ b/app/models/idea_mailer.rb @@ -68,11 +68,13 @@ def export_data_ready(email, link, photocracy=false) @body[:photocracy] = photocracy end - def export_failed(email, photocracy=false) + def export_failed(email, type, date_requested, photocracy=false) setup_email(nil, photocracy) @recipients = email @subject += "Data export failed" @body[:photocracy] = photocracy + @body[:date_requested] = date_requested + @body[:type] = type end protected diff --git a/app/views/idea_mailer/export_failed.text.html.erb b/app/views/idea_mailer/export_failed.text.html.erb index 8da8036a7..820db02f4 100644 --- a/app/views/idea_mailer/export_failed.text.html.erb +++ b/app/views/idea_mailer/export_failed.text.html.erb @@ -1,6 +1,6 @@

<%= t('items.email.hello') %>

-

Your requested export of data from the <%= @photocracy ? 'Photocracy' : 'All Our Ideas'%> site has failed. We've been notified of the problem and will be working on a fix.

+

The <%= @type %> CSV export you requested on <%= @date_requested.to_formatted_s(:long) %> (UTC) from the <%= @photocracy ? 'Photocracy' : 'All Our Ideas'%> site has failed. We've been notified of the problem and will be working on a fix.

<%= t('items.email.thanks') %>

<%= render :partial => 'idea_mailer/signature' %> diff --git a/app/views/idea_mailer/export_failed.text.plain.erb b/app/views/idea_mailer/export_failed.text.plain.erb index 76f5f3432..ef87edfe1 100644 --- a/app/views/idea_mailer/export_failed.text.plain.erb +++ b/app/views/idea_mailer/export_failed.text.plain.erb @@ -1,6 +1,6 @@ <%= t('items.email.hello') %> -Your requested export of data from the <%= @photocracy ? 'Photocracy' : 'All Our Ideas'%> site has failed. We've been notified of the problem and will be working on a fix. +The <%= @type %> CSV export you requested on <%= @date_requested.to_formatted_s(:long) %> (UTC) from the <%= @photocracy ? 'Photocracy' : 'All Our Ideas'%> site has failed. We've been notified of the problem and will be working on a fix. <%= t('items.email.thanks') %> <%= render :partial => 'idea_mailer/signature' %> diff --git a/lib/munge_and_notify_job.rb b/lib/munge_and_notify_job.rb index 19f4444cc..0bab9ee90 100644 --- a/lib/munge_and_notify_job.rb +++ b/lib/munge_and_notify_job.rb @@ -2,7 +2,8 @@ class MungeAndNotifyJob def on_permanent_failure - IdeaMailer.deliver_export_failed([APP_CONFIG[:ERRORS_EMAIL], email], photocracy) + date_requested = DateTime.iso8601(redis_key.split('_')[-2]) + IdeaMailer.deliver_export_failed([APP_CONFIG[:ERRORS_EMAIL], email], type, date_requested, photocracy) end # munges CSV file generated by pairwise to augment or remove the CSV From d1620b3bfaaa42fed941b255f1e4e558bce53cf5 Mon Sep 17 00:00:00 2001 From: Luke Baker Date: Fri, 28 Mar 2014 09:52:12 -0400 Subject: [PATCH 7/7] remove redis requirement for CSV generation Instead of checking for pairwise CSV in redis, check the exports URL on pairwise. [#39385987] --- app/controllers/questions_controller.rb | 6 ++--- lib/munge_and_notify_job.rb | 33 +++++++++++++------------ 2 files changed, 20 insertions(+), 19 deletions(-) diff --git a/app/controllers/questions_controller.rb b/app/controllers/questions_controller.rb index 9eaaaf603..1bae2fd9b 100644 --- a/app/controllers/questions_controller.rb +++ b/app/controllers/questions_controller.rb @@ -1195,11 +1195,11 @@ def export o = [('a'..'z'), ('A'..'Z')].map { |i| i.to_a }.flatten randstring = (0...4).map { o[rand(o.length)] }.join - redis_key = "wikisurvey_#{@earl.question_id}_#{type.gsub("_", "")}_#{Time.now.utc.iso8601}_#{randstring}" + export_key = "wikisurvey_#{@earl.question_id}_#{type.gsub("_", "")}_#{Time.now.utc.iso8601}_#{randstring}" - question.post(:export, :type => type, :response_type => 'redis', :redis_key => redis_key) + question.post(:export, :type => type, :key => export_key) - Delayed::Job.enqueue MungeAndNotifyJob.new(@earl.id, type, current_user.email, @photocracy, redis_key), 15 + Delayed::Job.enqueue MungeAndNotifyJob.new(@earl.id, type, current_user.email, @photocracy, export_key), 15 end diff --git a/lib/munge_and_notify_job.rb b/lib/munge_and_notify_job.rb index 0bab9ee90..32d70c3ce 100644 --- a/lib/munge_and_notify_job.rb +++ b/lib/munge_and_notify_job.rb @@ -1,8 +1,8 @@ -MungeAndNotifyJob = Struct.new(:earl_id, :type, :email, :photocracy, :redis_key) +MungeAndNotifyJob = Struct.new(:earl_id, :type, :email, :photocracy, :export_key) class MungeAndNotifyJob def on_permanent_failure - date_requested = DateTime.iso8601(redis_key.split('_')[-2]) + date_requested = DateTime.iso8601(export_key.split('_')[-2]) IdeaMailer.deliver_export_failed([APP_CONFIG[:ERRORS_EMAIL], email], type, date_requested, photocracy) end @@ -16,16 +16,17 @@ def perform # so we do this manually current_user = User.find_by_email(email) - r = Redis.new(:host => REDIS_CONFIG['hostname']) - - thekey, zlibcsv = r.blpop(redis_key, (60*10).to_s) # Timeout - 10 minutes - - r.del(redis_key) # client is responsible for deleting key - - zstream = Zlib::Inflate.new - csvdata = zstream.inflate(zlibcsv) - zstream.finish - zstream.close + # make HTTP request to pairwise to get export data + url = URI.parse("#{APP_CONFIG[:API_HOST]}/exports/#{export_key}") + req = Net::HTTP::Get.new(url.path) + # important to trigger basic HTTP Auth on pairwise + req["Accept"] = "text/csv" + req.basic_auth APP_CONFIG[:PAIRWISE_USERNAME], APP_CONFIG[:PAIRWISE_PASSWORD] + res = Net::HTTP.start(url.host, url.port) { |http| http.request(req) } + if res.code != "200" + raise "Export URL returned response code of #{res.code} for #{url.to_s}" + end + csvdata = res.body # for creating zlibed CSV at the end zoutput = Zlib::Deflate.new @@ -37,7 +38,7 @@ def perform num_slugs = earl.slugs.size - modified_csv = CSVBridge.generate do |csv| + CSVBridge.generate do |csv| CSVBridge.parse(csvdata, {:headers => :first_row, :return_headers => true}) do |row| if row.header_row? @@ -173,7 +174,7 @@ def perform #row << ['Geolocation Info', user_session.loc_info.to_s] end end - end + end # Zlib the CSV as we create it znewcsv << zoutput.deflate(row.to_csv, Zlib::SYNC_FLUSH) end @@ -182,9 +183,9 @@ def perform znewcsv << zoutput.finish zoutput.close - export_id = Export.connection.insert("INSERT INTO `exports` (`name`, `data`, `compressed`) VALUES (#{Export.connection.quote(redis_key)}, #{Export.connection.quote(znewcsv)}, 1)") + export_id = Export.connection.insert("INSERT INTO `exports` (`name`, `data`, `compressed`) VALUES (#{Export.connection.quote(export_key)}, #{Export.connection.quote(znewcsv)}, 1)") Delayed::Job.enqueue DestroyOldExportJob.new(export_id), 20, 3.days.from_now - url = "/export/#{redis_key}" + url = "/export/#{export_key}" IdeaMailer.deliver_export_data_ready(email, url, photocracy) return true