commit 78ed7fb5305c090882badbd90747754c8f5e81b5 Author: Petko Bordjukov Date: Tue Oct 6 15:21:46 2015 +0300 Initial rough version diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..fcaff28 --- /dev/null +++ b/.gitignore @@ -0,0 +1,19 @@ +# See https://help.github.com/articles/ignoring-files for more about ignoring files. +# +# If you find yourself ignoring temporary files generated by your text editor +# or operating system, you probably want to add a global ignore instead: +# git config --global core.excludesfile '~/.gitignore_global' + +# Ignore bundler config. +/.bundle + +# Ignore the default SQLite database. +/db/*.sqlite3 +/db/*.sqlite3-journal + +# Ignore all logfiles and tempfiles. +/log/* +!/log/.keep +/tmp +db/schema.rb +config/secrets.yml diff --git a/Gemfile b/Gemfile new file mode 100644 index 0000000..67bb90c --- /dev/null +++ b/Gemfile @@ -0,0 +1,20 @@ +source 'https://rubygems.org' + +gem 'rails', '4.2.4' + +gem 'sqlite3' +gem 'sass-rails' +gem 'uglifier' +gem 'coffee-rails' +# gem 'therubyracer', platforms: :ruby + +gem 'jquery-rails' +gem 'jbuilder' + +gem 'activeresource', require: 'active_resource' + +gem 'pry-rails' + +group :development do + gem 'spring' +end diff --git a/Gemfile.lock b/Gemfile.lock new file mode 100644 index 0000000..ee56585 --- /dev/null +++ b/Gemfile.lock @@ -0,0 +1,154 @@ +GEM + remote: https://rubygems.org/ + specs: + actionmailer (4.2.4) + actionpack (= 4.2.4) + actionview (= 4.2.4) + activejob (= 4.2.4) + mail (~> 2.5, >= 2.5.4) + rails-dom-testing (~> 1.0, >= 1.0.5) + actionpack (4.2.4) + actionview (= 4.2.4) + activesupport (= 4.2.4) + rack (~> 1.6) + rack-test (~> 0.6.2) + rails-dom-testing (~> 1.0, >= 1.0.5) + rails-html-sanitizer (~> 1.0, >= 1.0.2) + actionview (4.2.4) + activesupport (= 4.2.4) + builder (~> 3.1) + erubis (~> 2.7.0) + rails-dom-testing (~> 1.0, >= 1.0.5) + rails-html-sanitizer (~> 1.0, >= 1.0.2) + activejob (4.2.4) + activesupport (= 4.2.4) + globalid (>= 0.3.0) + activemodel (4.2.4) + activesupport (= 4.2.4) + builder (~> 3.1) + activerecord (4.2.4) + activemodel (= 4.2.4) + activesupport (= 4.2.4) + arel (~> 6.0) + activeresource (4.0.0) + activemodel (~> 4.0) + activesupport (~> 4.0) + rails-observers (~> 0.1.1) + activesupport (4.2.4) + i18n (~> 0.7) + json (~> 1.7, >= 1.7.7) + minitest (~> 5.1) + thread_safe (~> 0.3, >= 0.3.4) + tzinfo (~> 1.1) + arel (6.0.3) + builder (3.2.2) + coderay (1.1.0) + coffee-rails (4.1.0) + coffee-script (>= 2.2.0) + railties (>= 4.0.0, < 5.0) + coffee-script (2.4.1) + coffee-script-source + execjs + coffee-script-source (1.9.1.1) + erubis (2.7.0) + execjs (2.6.0) + globalid (0.3.6) + activesupport (>= 4.1.0) + i18n (0.7.0) + jbuilder (2.3.2) + activesupport (>= 3.0.0, < 5) + multi_json (~> 1.2) + jquery-rails (4.0.5) + rails-dom-testing (~> 1.0) + railties (>= 4.2.0) + thor (>= 0.14, < 2.0) + json (1.8.3) + loofah (2.0.3) + nokogiri (>= 1.5.9) + mail (2.6.3) + mime-types (>= 1.16, < 3) + method_source (0.8.2) + mime-types (2.6.2) + mini_portile (0.6.2) + minitest (5.8.1) + multi_json (1.11.2) + nokogiri (1.6.6.2) + mini_portile (~> 0.6.0) + pry (0.10.2) + coderay (~> 1.1.0) + method_source (~> 0.8.1) + slop (~> 3.4) + pry-rails (0.3.4) + pry (>= 0.9.10) + rack (1.6.4) + rack-test (0.6.3) + rack (>= 1.0) + rails (4.2.4) + actionmailer (= 4.2.4) + actionpack (= 4.2.4) + actionview (= 4.2.4) + activejob (= 4.2.4) + activemodel (= 4.2.4) + activerecord (= 4.2.4) + activesupport (= 4.2.4) + bundler (>= 1.3.0, < 2.0) + railties (= 4.2.4) + sprockets-rails + rails-deprecated_sanitizer (1.0.3) + activesupport (>= 4.2.0.alpha) + rails-dom-testing (1.0.7) + activesupport (>= 4.2.0.beta, < 5.0) + nokogiri (~> 1.6.0) + rails-deprecated_sanitizer (>= 1.0.1) + rails-html-sanitizer (1.0.2) + loofah (~> 2.0) + rails-observers (0.1.2) + activemodel (~> 4.0) + railties (4.2.4) + actionpack (= 4.2.4) + activesupport (= 4.2.4) + rake (>= 0.8.7) + thor (>= 0.18.1, < 2.0) + rake (10.4.2) + sass (3.4.18) + sass-rails (5.0.4) + railties (>= 4.0.0, < 5.0) + sass (~> 3.1) + sprockets (>= 2.8, < 4.0) + sprockets-rails (>= 2.0, < 4.0) + tilt (>= 1.1, < 3) + slop (3.6.0) + spring (1.4.0) + sprockets (3.3.5) + rack (> 1, < 3) + sprockets-rails (2.3.3) + actionpack (>= 3.0) + activesupport (>= 3.0) + sprockets (>= 2.8, < 4.0) + sqlite3 (1.3.10) + thor (0.19.1) + thread_safe (0.3.5) + tilt (2.0.1) + tzinfo (1.2.2) + thread_safe (~> 0.1) + uglifier (2.7.2) + execjs (>= 0.3.0) + json (>= 1.8.0) + +PLATFORMS + ruby + +DEPENDENCIES + activeresource + coffee-rails + jbuilder + jquery-rails + pry-rails + rails (= 4.2.4) + sass-rails + spring + sqlite3 + uglifier + +BUNDLED WITH + 1.10.6 diff --git a/README.rdoc b/README.rdoc new file mode 100644 index 0000000..dd4e97e --- /dev/null +++ b/README.rdoc @@ -0,0 +1,28 @@ +== README + +This README would normally document whatever steps are necessary to get the +application up and running. + +Things you may want to cover: + +* Ruby version + +* System dependencies + +* Configuration + +* Database creation + +* Database initialization + +* How to run the test suite + +* Services (job queues, cache servers, search engines, etc.) + +* Deployment instructions + +* ... + + +Please feel free to use a different markup language if you do not plan to run +rake doc:app. diff --git a/Rakefile b/Rakefile new file mode 100644 index 0000000..ba6b733 --- /dev/null +++ b/Rakefile @@ -0,0 +1,6 @@ +# Add your own tasks in files placed in lib/tasks ending in .rake, +# for example lib/tasks/capistrano.rake, and they will automatically be available to Rake. + +require File.expand_path('../config/application', __FILE__) + +Rails.application.load_tasks diff --git a/app/assets/images/.keep b/app/assets/images/.keep new file mode 100644 index 0000000..e69de29 diff --git a/app/assets/javascripts/application.js b/app/assets/javascripts/application.js new file mode 100644 index 0000000..646c5ab --- /dev/null +++ b/app/assets/javascripts/application.js @@ -0,0 +1,15 @@ +// This is a manifest file that'll be compiled into application.js, which will include all the files +// listed below. +// +// Any JavaScript/Coffee file within this directory, lib/assets/javascripts, vendor/assets/javascripts, +// or any plugin's vendor/assets/javascripts directory can be referenced here using a relative path. +// +// It's not advisable to add code directly here, but if you do, it'll appear at the bottom of the +// compiled file. +// +// Read Sprockets README (https://github.com/rails/sprockets#sprockets-directives) for details +// about supported directives. +// +//= require jquery +//= require jquery_ujs +//= require_tree . diff --git a/app/assets/javascripts/halfnarp.js b/app/assets/javascripts/halfnarp.js new file mode 100644 index 0000000..ce8ba09 --- /dev/null +++ b/app/assets/javascripts/halfnarp.js @@ -0,0 +1,275 @@ +(function() { + function toggle_grid(isList) { + $('.room-label').toggleClass('hidden', isList ); + $('.track h2').toggleClass('hidden', !isList ); + $('.event').toggleClass('event-in-list', isList ); + $('.event').toggleClass('event-in-calendar', !isList ); + $('.event').toggleClass('hidden', !isList ); + $('.guide').toggleClass('hidden', isList ); + $('#qrcode').toggleClass('limit', !isList ); + } + + function do_the_halfnarp() { + var halfnarpAPI = '/talk_preferences'; + var halfnarpPubAPI = halfnarpAPI + '/'; + var isTouch = (('ontouchstart' in window) || (navigator.msMaxTouchPoints > 0)); + window.all_events = new Object(); + var myuid, mypid, newfriend = new Object(); + + $.extend($.expr[':'], { + 'containsi': function(elem, i, match, array) + { + return (elem.textContent || elem.innerText || '').toLowerCase() + .indexOf((match[3] || '').toLowerCase()) >= 0; + } + }); + + /* Add callback for submit click */ + $('.submit').click( function() { + var myapi; + + /* Get user's preferences and try to save them locally */ + var ids = $('.selected').map( function() { + return parseInt($(this).attr('event_id')); + }).get(); + try { + localStorage['OpenFest-gauge'] = ids; + myapi = localStorage['OpenFest-gauge-api']; + } catch(err) { + alert('Storing your choices locally is forbidden.'); + } + + /* Convert preferences to JSON and post them to backend */ + var request = {talk_preference: {'talks': ids}}; + if( !myapi || !myapi.length ) { + /* If we do not have resource URL, post data and get resource */ + $.post( halfnarpAPI, request, function( data ) { + $('.info span').text('submitted'); + $('.info').removeClass('hidden'); + try { + localStorage['OpenFest-gauge-api'] = data['update_url']; + localStorage['OpenFest-gauge-pid'] = mypid = data['hashed_uid']; + localStorage['OpenFest-gauge-uid'] = myuid = data['uid']; + window.location.hash = mypid; + } catch(err) {} + }, 'json' ).fail(function() { + $('.info span').text('failed :('); + $('.info').removeClass('hidden'); + }); + } else { + /* If we do have a resource URL, update resource */ + $.ajax({ + type: 'PUT', + url: myapi, + data: request, + dataType: 'json', + }).done(function(data) { + localStorage['OpenFest-gauge-uid'] = myuid = data['uid']; + if( localStorage['OpenFest-gauge-pid'] ) { + window.location.hash = localStorage['OpenFest-gauge-pid']; + } + $('.info span').text('updated'); + $('.info').removeClass('hidden'); + }).fail(function(msg) { + $('.info span').text('failed'); + $('.info').removeClass('hidden'); + }); + } + + /* Tell QRCode library to update and/or display preferences for Apps */ + // $('#qrcode').empty(); + // $('#qrcode').qrcode({width: 224, height: 224, text: request}); + // $('#qrcode').removeClass('hidden'); + + /* Export all preferences in ical events */ + // var now = new Date(); + // var calendar = 'BEGIN:VCALENDAR\r\nVERSION:2.0\r\nPRODID:-//events.ccc.de//halfnarp//EN\r\nX-WR-TIMEZONE:Europe/Berlin\r\n'; + // ids.forEach( function(id) { + // var item = all_events[id]; + // var start = new Date(item.start_time); + // calendar += 'BEGIN:VEVENT\r\n'; + // calendar += 'UID:'+myuid+item.event_id+'\r\n'; + // calendar += 'DTSTAMP:' + now.toISOString().replace(/-|;|:|\./g, '').replace(/...Z$/, 'Z') + '\r\n'; + // calendar += 'DTSTART:' + start.toISOString().replace(/-|;|:|\./g, '').replace(/...Z$/, 'Z') + '\r\n'; + // calendar += 'DURATION:PT' + item.duration + 'M\r\n'; + // calendar += 'LOCATION:' + item.room_name + '\r\n'; + // calendar += 'URL:http://events.ccc.de/congress/2014/Fahrplan/events/' + item.event_id + '.html\r\n'; + // calendar += 'DESCRIPTION:' + item.title + '\r\n'; + // calendar += 'SUMMARY:' + item.abstract.replace(/\n/g, '') + '\r\n'; + // console.log( 'id:' + id + ' ' + all_events[id] ); + // console.log( all_events[id].title ); + // calendar += 'END:VEVENT\r\n'; + // }); + // calendar += 'END:VCALENDAR\r\n'; + // $('.export-url-a').attr( 'href', "data:text/calendar;filename=OpenFest.ics," + encodeURIComponent(calendar) ); + // $('.export-url').removeClass( 'hidden' ); + }); + + /* Add handler for type ahead search input field */ + $('#filter').bind('paste cut keypress keydown keyup', function() { + var cnt = $(this).val(); + if( cnt.length ) { + $('.event').css('display', 'none'); + $('.event:containsi('+cnt+')').css('display', 'block'); + } else { + $('.event').css('display', 'block'); + } + }); + + /* Add click handlers for event div sizers */ + $('.smallboxes').click( function() { + $('#qrcode').css( 'margin-bottom', '0' ); + $('.event').removeClass('medium large'); + $('.event').addClass('small'); + }); + + $('.mediumboxes').click( function() { + $('#qrcode').css( 'margin-bottom', '62px' ); + $('.event').removeClass('small large'); + $('.event').addClass('medium'); + }); + + $('.largeboxes').click( function() { + $('#qrcode').css( 'margin-bottom', '124px' ); + $('.event').removeClass('small medium'); + $('.event').addClass('large'); + }); + + /* Add de-highlighter on touch interface devices */ + if( isTouch ) { + $('body').click( function() { + $('.highlighted').removeClass('highlighted'); + }); + } + + /* Add callbacks for view selector */ + $('.list').click( function() { + toggle_grid(true); + }); + $('.day1').click( function() { + toggle_grid(false); + $('.day_1').removeClass('hidden'); + }); + $('.day2').click( function() { + toggle_grid(false); + $('.day_2').removeClass('hidden'); + }); + $('.day3').click( function() { + toggle_grid(false); + $('.day_3').removeClass('hidden'); + }); + $('.day4').click( function() { + toggle_grid(false); + $('.day_4').removeClass('hidden'); + }); + + /* Create hour guides */ + for( var i = 11; i<26; ++i ) { + var elem = document.createElement('hr'); + $(elem).addClass('guide time_' + (i>23?'0':'') + i%24 + '00'); + $('body').append(elem); + elem = document.createElement('div'); + $(elem).text((i>23?'0':'') + i%24 + '00'); + $(elem).addClass('guide time_' + (i>23?'0':'') + i%24 + '00'); + $('body').append(elem); + } + + /* If we've been here before, try to get local preferences. They are authoratative */ + var selection = [], friends = { 'foo': undefined }; + try { + selection = localStorage['OpenFest-gauge'] || []; + friends = localStorage['OpenFest-gauge-friends'] || { 'foo': undefined }; + myuid = localStorage['OpenFest-gauge-uid'] || ''; + mypid = localStorage['OpenFest-gauge-pid'] || ''; + } catch(err) { + } + + /* Fetch list of lectures to display */ + $.getJSON( halfnarpAPI, { locale: $('html').attr('lang') }) + .done(function( data ) { + $.each( data, function( i, item ) { + /* Save event to all_events hash */ + all_events[item.event_id] = item; + + /* Take copy of hidden event template div and select them, if they're in + list of previous prereferences */ + var t = $( '#template' ).clone(true); + t.attr('event_id', item.event_id.toString()); + t.attr('id', 'event_' + item.event_id.toString()); + if( selection && selection.indexOf(item.event_id) != -1 ) { + t.addClass( 'selected' ); + } + + /* Sort textual info into event div */ + t.find('.title').text(item.title); + t.find('.event_type').text(item.event_type); + t.find('.abstract').text(item.abstract); + + /* start_time: 2014-12-29T21:15:00+01:00" */ + var start_time = new Date(item.start_time); + + var day = start_time.getDate()-26; + var hour = start_time.getHours(); + var mins = start_time.getMinutes(); + + /* After midnight: sort into yesterday */ + if( hour < 10 ) { + day--; + } + /* Apply attributes to sort events into calendar */ + t.addClass('small room_' + item.room_id + ' duration_' + item.duration + ' day_'+day + ' time_' + (hour<10?'0':'') + hour + '' + (mins<10?'0':'') + mins); + + t.click( function(event) { + /* Transition for touch devices is highlighted => selected => highlighted ... */ + if( isTouch ) { + if ( $( this ).hasClass('highlighted') ) { + $( this ).toggleClass('selected'); + $('.info').addClass('hidden'); + } else { + $('.highlighted').removeClass('highlighted'); + $( this ).addClass('highlighted'); + } + } else { + $( this ).toggleClass('selected'); + $('.info').addClass('hidden'); + } + event.stopPropagation(); + }); + /* Put new event into DOM tree. Track defaults to 'Other' */ + var d = $( '#' + item.track_id.toString() ); + if( !d.length ) { + d = $( '#Other' ); + } + d.append(t); + if( newfriend.pid ) { + newfriend.prefs.forEach( function( eventid ) { + $( '#event_' + eventid ).addClass( 'friend' ); + }); + } + }); + + /* Initially display as list */ + toggle_grid(true); + + /* Check for a new friends public uid in location's #hash */ + var shared = window.location.hash; + shared = shared ? shared.substr(1) : ''; + if( shared.length ) { + if ( ( friends[shared] ) || ( shared === mypid ) ) { + + } else { + $.getJSON( halfnarpPubAPI + shared, { locale: $('html').attr('lang') }) + .done(function( data ) { + newfriend.pid = shared; + newfriend.prefs = data.talk_ids; + newfriend.prefs.forEach( function( eventid ) { + $( '#event_' + eventid ).addClass( 'friend' ); + }); + }); + } + } + }); + } + + $(document).ready(function() {do_the_halfnarp()}); +}).call(this); diff --git a/app/assets/stylesheets/application.css b/app/assets/stylesheets/application.css new file mode 100644 index 0000000..f9cd5b3 --- /dev/null +++ b/app/assets/stylesheets/application.css @@ -0,0 +1,15 @@ +/* + * This is a manifest file that'll be compiled into application.css, which will include all the files + * listed below. + * + * Any CSS and SCSS file within this directory, lib/assets/stylesheets, vendor/assets/stylesheets, + * or any plugin's vendor/assets/stylesheets directory can be referenced here using a relative path. + * + * You're free to add application-wide styles to this file and they'll appear at the bottom of the + * compiled file so the styles you add here take precedence over styles defined in any styles + * defined in the other CSS/SCSS files in this directory. It is generally better to create a new + * file per style scope. + * + *= require_tree . + *= require_self + */ diff --git a/app/assets/stylesheets/halfnarp.css b/app/assets/stylesheets/halfnarp.css new file mode 100644 index 0000000..baef8cc --- /dev/null +++ b/app/assets/stylesheets/halfnarp.css @@ -0,0 +1,323 @@ +body { + font-family: "HelveticaNeueLight", "HelveticaNeue-Light", "Helvetica Neue Light", "HelveticaNeue", "Helvetica Neue", 'TeXGyreHerosRegular', "Helvetica", "Tahoma", "Geneva", "Arial", sans-serif; font-weight:300; font-stretch:normal; +} + +.header { + min-width: 640px; +} + +.headline { + font-size: 3em; + font-weight: bold; + text-align: center; + margin-bottom: 1em; +} + +.rightbox { + float: right; + max-width: 50%; +} + +.leftbox { + float: left; + max-width: 50%; +} + +.submit { + font-size: 2em; + text-align: center; + text-transform: uppercase; + + width: 6em; + height: 1em; + background: green; color: white; + + padding: 0.5em 0 0.5em 0; + border-radius: 5px; + float: right; + cursor: pointer; +} + +.info { + font-size: 2em; + text-align: center; + + height: 1em; + background: lightblue; + + margin-right: 0.2em; + border-radius: 5px; + padding: 0.5em; + float: right; +} + +.submit:hover { + background: GreenYellow; +} + +#filter { + font-size: 2em; + margin: 0 1em .3em 0; +} + +.clear { + clear: both; +} + +.explainer { + margin-top: 5em; + text-align: right; +} + +.explainer ul { + list-style-type: none; + padding:0; + margin:0; + height: 8em; + overflow: hidden; +} + +.boxer { + font-size: 1em; + float: left; + width: 2em; + height: 2em; + background: grey; + color: white; + text-align: center; + margin-right: 0.2em; + padding: 0.2em 0 0 0; + cursor: pointer; + border-radius: 5px; +} + +.allboxes { + clear: left; + margin-top: 3em; +} + +.mediumboxes { + width: 3em; + height: 3em; +} + +.largeboxes { + width: 4em; + height: 4em; +} + +.views { + float: left; + background: grey; + margin-right: 0.2em; + padding: 0.2em 0 0 0; + text-align: center; + color: white; + width: 3em; + height: 2em; + cursor: pointer; + border-radius: 5px; +} + +.views:hover, +.boxer:hover { + background: #eee; +} + +.track h2 { + text-align: center; + + border-bottom: 0.3em solid #4588ba; + + margin: 2em 0 1em 0; + clear: both; +} + +.event { + overflow: hidden; + + background: #eee; + border-radius: 5px; + + margin: 0 0.8em 0.8em 0; + cursor: pointer; +} + +.event-in-list { + display: inline-block; + float: left; +} + +.event-in-list.small { + width: 14em; + height: 14em; +} +.event-in-list.medium { + width: 17em; + height: 17em; +} +.event-in-list.large { + width: 20em; + height: 20em; +} + +.event-in-calendar, +.room-label { + position: absolute; + width: 18.75%; +} + +.room-label { + text-align: center; + font-size: 2em; + font-weight: bold; + top: 350px; +} +.day_1 { } +.day_2 { } +.day_3 { } +.day_4 { } + +.event-in-calendar.room_325, .room1 { left: 5.00%; } +.event-in-calendar.room_326, .room2 { left: 28.75%; } +.event-in-calendar.room_327, .roomg { left: 52.50%; } +.event-in-calendar.room_328, .room6 { left: 76.25% } + +.event-in-calendar.duration_1800 { height: 95px; } +.event-in-calendar.duration_3600 { height: 195px; } +.event-in-calendar.duration_5400 { height: 290px; } +.event-in-calendar.duration_7200 { height: 395px; } +.event-in-calendar.duration_8100 { height: 445px; } + +.guide { + position: absolute; + z-index: -1; + font-weight: bold; +} +hr.guide { + left: 4%; + width: 95%; +} + +.time_1100 { top: 400px; } +.time_1130 { top: 500px; } +.time_1200 { top: 600px; } +.time_1245 { top: 750px; } +.time_1300 { top: 800px; } +.time_1400 { top: 1000px; } +.time_1500 { top: 1200px; } +.time_1600 { top: 1400px; } +.time_1645 { top: 1550px; } +.time_1700 { top: 1600px; } +.time_1715 { top: 1650px; } +.time_1730 { top: 1700px; } +.time_1800 { top: 1800px; } +.time_1815 { top: 1850px; } +.time_1830 { top: 1900px; } +.time_1900 { top: 2000px; } +.time_2000 { top: 2200px; } +.time_2030 { top: 2300px; } +.time_2100 { top: 2400px; } +.time_2115 { top: 2450px; } +.time_2145 { top: 2550px; } +.time_2200 { top: 2600px; } +.time_2245 { top: 2750px; } +.time_2300 { top: 2800px; } +.time_2330 { top: 2900px; } +.time_0000 { top: 3000px; } +.time_0015 { top: 3050px; } +.time_0100 { top: 3200px; } +.time_0200 { top: 3400px; } + +.event-in-list:hover { + position: relative; + top: auto !important; +} + +.event:hover, +.highlighted { + overflow: visible; + z-index: 1; + background: grey; +} + +.selected { + background: red !important; +} +.selected.friend { + background-image: + repeating-linear-gradient( + 45deg, + purple, + purple 20px, + red 20px, + red 40px /* determines size */ + ) !important; + color: white; +} +.selected:hover, +.friend:hover { + background: pink !important; + color: black; +} +.friend { + background: purple; + color: white; +} + +.title { + font-weight: bold; + font-size: 1.1em; + padding: 0.2em 0.2em 0 0.2em; +} + +.event_type { + font-style: italic; + padding: 0 0.2em 0 0.1em; + margin-bottom: 0.2em; +} + +.event:hover .abstract, +.event.highlighted .abstract { + background: inherit; +} + +.abstract { + padding: 0 0.2em 0.2em 0.2em; + border-radius: 5px; +} + +.hidden { + visibility: hidden !important; + display: none !important; +} + +.export-url { + float: left; + padding: 0.2em 0 0 0; + border-radius: 5px; + text-align: center; + background: lightblue; + width: 6em; + height: 2em; +} + +#qrcode { + display: inline-block; + float: right; + + margin: 0 0.8em 0.8em 0; + width: 14em; + height: 14em; +} + +.limit#qrcode canvas { + width: 4em; + height: 4em; +} + +#qrcode:hover canvas, +.selected#qrcode canvas { + width: 224px !important; + height: 224px !important; +} diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb new file mode 100644 index 0000000..d83690e --- /dev/null +++ b/app/controllers/application_controller.rb @@ -0,0 +1,5 @@ +class ApplicationController < ActionController::Base + # Prevent CSRF attacks by raising an exception. + # For APIs, you may want to use :null_session instead. + protect_from_forgery with: :exception +end diff --git a/app/controllers/concerns/.keep b/app/controllers/concerns/.keep new file mode 100644 index 0000000..e69de29 diff --git a/app/controllers/home_controller.rb b/app/controllers/home_controller.rb new file mode 100644 index 0000000..95f2992 --- /dev/null +++ b/app/controllers/home_controller.rb @@ -0,0 +1,4 @@ +class HomeController < ApplicationController + def index + end +end diff --git a/app/controllers/talk_preferences_controller.rb b/app/controllers/talk_preferences_controller.rb new file mode 100644 index 0000000..8de38ad --- /dev/null +++ b/app/controllers/talk_preferences_controller.rb @@ -0,0 +1,44 @@ +class TalkPreferencesController < ApplicationController + def index + @talks = Talk.all(params: {locale: I18n.locale}) + end + + def show + @talk_preference = TalkPreference.find_by hashed_unique_id: params[:id] + render json: {talk_ids: @talk_preference.talks} + end + + def create + @talk_preference = TalkPreference.new talk_preference_params + + if @talk_preference.save + render json: { + update_url: talk_preference_url(@talk_preference), + hashed_uid: @talk_preference.hashed_unique_id, + uid: @talk_preference.id + }, status: :created + else + render status: :unprocessable_entity + end + end + + def update + @talk_preference = TalkPreference.find params[:id] + + if @talk_preference.update talk_preference_params + render json: { + update_url: talk_preference_url(@talk_preference), + hashed_uid: @talk_preference.hashed_unique_id, + uid: @talk_preference.id + } + else + render status: :unprocessable_entity + end + end + + private + + def talk_preference_params + params.require(:talk_preference).permit(talks: []) + end +end diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb new file mode 100644 index 0000000..de6be79 --- /dev/null +++ b/app/helpers/application_helper.rb @@ -0,0 +1,2 @@ +module ApplicationHelper +end diff --git a/app/mailers/.keep b/app/mailers/.keep new file mode 100644 index 0000000..e69de29 diff --git a/app/models/.keep b/app/models/.keep new file mode 100644 index 0000000..e69de29 diff --git a/app/models/concerns/.keep b/app/models/concerns/.keep new file mode 100644 index 0000000..e69de29 diff --git a/app/models/talk.rb b/app/models/talk.rb new file mode 100644 index 0000000..306b47d --- /dev/null +++ b/app/models/talk.rb @@ -0,0 +1,4 @@ +class Talk < ActiveResource::Base + self.site = "https://cfp.openfest.org/api/conferences/2" + self.element_name = "event" +end diff --git a/app/models/talk_preference.rb b/app/models/talk_preference.rb new file mode 100644 index 0000000..2797c48 --- /dev/null +++ b/app/models/talk_preference.rb @@ -0,0 +1,14 @@ +class TalkPreference < ActiveRecord::Base + self.primary_key = :unique_id + + serialize :talks, Array + + before_create :assign_new_unique_id + + private + + def assign_new_unique_id + self.unique_id = SecureRandom.uuid + self.hashed_unique_id = Digest::SHA1.hexdigest(self.unique_id) + end +end diff --git a/app/views/home/index.html.erb b/app/views/home/index.html.erb new file mode 100644 index 0000000..00a62e7 --- /dev/null +++ b/app/views/home/index.html.erb @@ -0,0 +1,41 @@ +
+
+
+
+
+
+
+ +
<%= t 'generic.title' %>
+
+
+
<%= t 'generic.submit' %>
+ +
+ +
    +
  • + <%= t 'generic.help_us_reduce_the_conflicts' %> +
  • +
  • + <%= t 'generic.click_on_the_talks_you_would_like_to_watch' %> +
  • +
  • + <%= t 'generic.press_submit' %> +
  • + +
+
+
+ +
+
size
Size
SIZE
+ +
+
+
+

Technical

+

OpenBiz

+

Civic Hacking

+

Social

+

Advanced Technical

diff --git a/app/views/layouts/application.html.erb b/app/views/layouts/application.html.erb new file mode 100644 index 0000000..d704341 --- /dev/null +++ b/app/views/layouts/application.html.erb @@ -0,0 +1,14 @@ + + + + <%= t 'generic.title' %> + <%= stylesheet_link_tag 'application', media: 'all' %> + <%= javascript_include_tag 'application' %> + <%= csrf_meta_tags %> + + + + <%= yield %> + + + diff --git a/app/views/talk_preferences/index.jbuilder b/app/views/talk_preferences/index.jbuilder new file mode 100644 index 0000000..8a8db92 --- /dev/null +++ b/app/views/talk_preferences/index.jbuilder @@ -0,0 +1,8 @@ +json.array! @talks do |talk| + json.title talk.title + json.abstract talk.abstract + json.track_id talk.track_id + json.track_name talk.track.name + json.event_id talk.id + json.event_type talk.event_type.name +end diff --git a/bin/bundle b/bin/bundle new file mode 100755 index 0000000..66e9889 --- /dev/null +++ b/bin/bundle @@ -0,0 +1,3 @@ +#!/usr/bin/env ruby +ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../../Gemfile', __FILE__) +load Gem.bin_path('bundler', 'bundle') diff --git a/bin/rails b/bin/rails new file mode 100755 index 0000000..4d608ed --- /dev/null +++ b/bin/rails @@ -0,0 +1,8 @@ +#!/usr/bin/env ruby +begin + load File.expand_path("../spring", __FILE__) +rescue LoadError +end +APP_PATH = File.expand_path('../../config/application', __FILE__) +require_relative '../config/boot' +require 'rails/commands' diff --git a/bin/rake b/bin/rake new file mode 100755 index 0000000..8017a02 --- /dev/null +++ b/bin/rake @@ -0,0 +1,8 @@ +#!/usr/bin/env ruby +begin + load File.expand_path("../spring", __FILE__) +rescue LoadError +end +require_relative '../config/boot' +require 'rake' +Rake.application.run diff --git a/bin/setup b/bin/setup new file mode 100755 index 0000000..acdb2c1 --- /dev/null +++ b/bin/setup @@ -0,0 +1,29 @@ +#!/usr/bin/env ruby +require 'pathname' + +# path to your application root. +APP_ROOT = Pathname.new File.expand_path('../../', __FILE__) + +Dir.chdir APP_ROOT do + # This script is a starting point to setup your application. + # Add necessary setup steps to this file: + + puts "== Installing dependencies ==" + system "gem install bundler --conservative" + system "bundle check || bundle install" + + # puts "\n== Copying sample files ==" + # unless File.exist?("config/database.yml") + # system "cp config/database.yml.sample config/database.yml" + # end + + puts "\n== Preparing database ==" + system "bin/rake db:setup" + + puts "\n== Removing old logs and tempfiles ==" + system "rm -f log/*" + system "rm -rf tmp/cache" + + puts "\n== Restarting application server ==" + system "touch tmp/restart.txt" +end diff --git a/bin/spring b/bin/spring new file mode 100755 index 0000000..5e7ecc4 --- /dev/null +++ b/bin/spring @@ -0,0 +1,15 @@ +#!/usr/bin/env ruby + +# This file loads spring without using Bundler, in order to be fast. +# It gets overwritten when you run the `spring binstub` command. + +unless defined?(Spring) + require "rubygems" + require "bundler" + + if (match = Bundler.default_lockfile.read.match(/^GEM$.*?^ (?: )*spring \((.*?)\)$.*?^$/m)) + Gem.paths = { "GEM_PATH" => [Bundler.bundle_path.to_s, *Gem.path].uniq } + gem "spring", match[1] + require "spring/binstub" + end +end diff --git a/config.ru b/config.ru new file mode 100644 index 0000000..bd83b25 --- /dev/null +++ b/config.ru @@ -0,0 +1,4 @@ +# This file is used by Rack-based servers to start the application. + +require ::File.expand_path('../config/environment', __FILE__) +run Rails.application diff --git a/config/application.rb b/config/application.rb new file mode 100644 index 0000000..bea26da --- /dev/null +++ b/config/application.rb @@ -0,0 +1,26 @@ +require File.expand_path('../boot', __FILE__) + +require 'rails/all' + +# Require the gems listed in Gemfile, including any gems +# you've limited to :test, :development, or :production. +Bundler.require(*Rails.groups) + +module Gauge + class Application < Rails::Application + # Settings in config/environments/* take precedence over those specified here. + # Application configuration should go into files in config/initializers + # -- all .rb files in that directory are automatically loaded. + + # Set Time.zone default to the specified zone and make Active Record auto-convert to this zone. + # Run "rake -D time" for a list of tasks for finding time zone names. Default is UTC. + # config.time_zone = 'Central Time (US & Canada)' + + # The default locale is :en and all translations from config/locales/*.rb,yml are auto loaded. + # config.i18n.load_path += Dir[Rails.root.join('my', 'locales', '*.{rb,yml}').to_s] + # config.i18n.default_locale = :de + + # Do not swallow errors in after_commit/after_rollback callbacks. + config.active_record.raise_in_transactional_callbacks = true + end +end diff --git a/config/boot.rb b/config/boot.rb new file mode 100644 index 0000000..6b750f0 --- /dev/null +++ b/config/boot.rb @@ -0,0 +1,3 @@ +ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../../Gemfile', __FILE__) + +require 'bundler/setup' # Set up gems listed in the Gemfile. diff --git a/config/database.yml b/config/database.yml new file mode 100644 index 0000000..1c1a37c --- /dev/null +++ b/config/database.yml @@ -0,0 +1,25 @@ +# SQLite version 3.x +# gem install sqlite3 +# +# Ensure the SQLite 3 gem is defined in your Gemfile +# gem 'sqlite3' +# +default: &default + adapter: sqlite3 + pool: 5 + timeout: 5000 + +development: + <<: *default + database: db/development.sqlite3 + +# Warning: The database defined as "test" will be erased and +# re-generated from your development database when you run "rake". +# Do not set this db to the same as development or production. +test: + <<: *default + database: db/test.sqlite3 + +production: + <<: *default + database: db/production.sqlite3 diff --git a/config/environment.rb b/config/environment.rb new file mode 100644 index 0000000..ee8d90d --- /dev/null +++ b/config/environment.rb @@ -0,0 +1,5 @@ +# Load the Rails application. +require File.expand_path('../application', __FILE__) + +# Initialize the Rails application. +Rails.application.initialize! diff --git a/config/environments/development.rb b/config/environments/development.rb new file mode 100644 index 0000000..b55e214 --- /dev/null +++ b/config/environments/development.rb @@ -0,0 +1,41 @@ +Rails.application.configure do + # Settings specified here will take precedence over those in config/application.rb. + + # In the development environment your application's code is reloaded on + # every request. This slows down response time but is perfect for development + # since you don't have to restart the web server when you make code changes. + config.cache_classes = false + + # Do not eager load code on boot. + config.eager_load = false + + # Show full error reports and disable caching. + config.consider_all_requests_local = true + config.action_controller.perform_caching = false + + # Don't care if the mailer can't send. + config.action_mailer.raise_delivery_errors = false + + # Print deprecation notices to the Rails logger. + config.active_support.deprecation = :log + + # Raise an error on page load if there are pending migrations. + config.active_record.migration_error = :page_load + + # Debug mode disables concatenation and preprocessing of assets. + # This option may cause significant delays in view rendering with a large + # number of complex assets. + config.assets.debug = true + + # Asset digests allow you to set far-future HTTP expiration dates on all assets, + # yet still be able to expire them through the digest params. + config.assets.digest = true + + # Adds additional error checking when serving assets at runtime. + # Checks for improperly declared sprockets dependencies. + # Raises helpful error messages. + config.assets.raise_runtime_errors = true + + # Raises error for missing translations + # config.action_view.raise_on_missing_translations = true +end diff --git a/config/environments/production.rb b/config/environments/production.rb new file mode 100644 index 0000000..5c1b32e --- /dev/null +++ b/config/environments/production.rb @@ -0,0 +1,79 @@ +Rails.application.configure do + # Settings specified here will take precedence over those in config/application.rb. + + # Code is not reloaded between requests. + config.cache_classes = true + + # Eager load code on boot. This eager loads most of Rails and + # your application in memory, allowing both threaded web servers + # and those relying on copy on write to perform better. + # Rake tasks automatically ignore this option for performance. + config.eager_load = true + + # Full error reports are disabled and caching is turned on. + config.consider_all_requests_local = false + config.action_controller.perform_caching = true + + # Enable Rack::Cache to put a simple HTTP cache in front of your application + # Add `rack-cache` to your Gemfile before enabling this. + # For large-scale production use, consider using a caching reverse proxy like + # NGINX, varnish or squid. + # config.action_dispatch.rack_cache = true + + # Disable serving static files from the `/public` folder by default since + # Apache or NGINX already handles this. + config.serve_static_files = ENV['RAILS_SERVE_STATIC_FILES'].present? + + # Compress JavaScripts and CSS. + config.assets.js_compressor = :uglifier + # config.assets.css_compressor = :sass + + # Do not fallback to assets pipeline if a precompiled asset is missed. + config.assets.compile = false + + # Asset digests allow you to set far-future HTTP expiration dates on all assets, + # yet still be able to expire them through the digest params. + config.assets.digest = true + + # `config.assets.precompile` and `config.assets.version` have moved to config/initializers/assets.rb + + # Specifies the header that your server uses for sending files. + # config.action_dispatch.x_sendfile_header = 'X-Sendfile' # for Apache + # config.action_dispatch.x_sendfile_header = 'X-Accel-Redirect' # for NGINX + + # Force all access to the app over SSL, use Strict-Transport-Security, and use secure cookies. + # config.force_ssl = true + + # Use the lowest log level to ensure availability of diagnostic information + # when problems arise. + config.log_level = :debug + + # Prepend all log lines with the following tags. + # config.log_tags = [ :subdomain, :uuid ] + + # Use a different logger for distributed setups. + # config.logger = ActiveSupport::TaggedLogging.new(SyslogLogger.new) + + # Use a different cache store in production. + # config.cache_store = :mem_cache_store + + # Enable serving of images, stylesheets, and JavaScripts from an asset server. + # config.action_controller.asset_host = 'http://assets.example.com' + + # Ignore bad email addresses and do not raise email delivery errors. + # Set this to true and configure the email server for immediate delivery to raise delivery errors. + # config.action_mailer.raise_delivery_errors = false + + # Enable locale fallbacks for I18n (makes lookups for any locale fall back to + # the I18n.default_locale when a translation cannot be found). + config.i18n.fallbacks = true + + # Send deprecation notices to registered listeners. + config.active_support.deprecation = :notify + + # Use default logging formatter so that PID and timestamp are not suppressed. + config.log_formatter = ::Logger::Formatter.new + + # Do not dump schema after migrations. + config.active_record.dump_schema_after_migration = false +end diff --git a/config/environments/test.rb b/config/environments/test.rb new file mode 100644 index 0000000..1c19f08 --- /dev/null +++ b/config/environments/test.rb @@ -0,0 +1,42 @@ +Rails.application.configure do + # Settings specified here will take precedence over those in config/application.rb. + + # The test environment is used exclusively to run your application's + # test suite. You never need to work with it otherwise. Remember that + # your test database is "scratch space" for the test suite and is wiped + # and recreated between test runs. Don't rely on the data there! + config.cache_classes = true + + # Do not eager load code on boot. This avoids loading your whole application + # just for the purpose of running a single test. If you are using a tool that + # preloads Rails for running tests, you may have to set it to true. + config.eager_load = false + + # Configure static file server for tests with Cache-Control for performance. + config.serve_static_files = true + config.static_cache_control = 'public, max-age=3600' + + # Show full error reports and disable caching. + config.consider_all_requests_local = true + config.action_controller.perform_caching = false + + # Raise exceptions instead of rendering exception templates. + config.action_dispatch.show_exceptions = false + + # Disable request forgery protection in test environment. + config.action_controller.allow_forgery_protection = false + + # Tell Action Mailer not to deliver emails to the real world. + # The :test delivery method accumulates sent emails in the + # ActionMailer::Base.deliveries array. + config.action_mailer.delivery_method = :test + + # Randomize the order test cases are executed. + config.active_support.test_order = :random + + # Print deprecation notices to the stderr. + config.active_support.deprecation = :stderr + + # Raises error for missing translations + # config.action_view.raise_on_missing_translations = true +end diff --git a/config/initializers/assets.rb b/config/initializers/assets.rb new file mode 100644 index 0000000..01ef3e6 --- /dev/null +++ b/config/initializers/assets.rb @@ -0,0 +1,11 @@ +# Be sure to restart your server when you modify this file. + +# Version of your assets, change this if you want to expire all your assets. +Rails.application.config.assets.version = '1.0' + +# Add additional assets to the asset load path +# Rails.application.config.assets.paths << Emoji.images_path + +# Precompile additional assets. +# application.js, application.css, and all non-JS/CSS in app/assets folder are already added. +# Rails.application.config.assets.precompile += %w( search.js ) diff --git a/config/initializers/backtrace_silencers.rb b/config/initializers/backtrace_silencers.rb new file mode 100644 index 0000000..59385cd --- /dev/null +++ b/config/initializers/backtrace_silencers.rb @@ -0,0 +1,7 @@ +# Be sure to restart your server when you modify this file. + +# You can add backtrace silencers for libraries that you're using but don't wish to see in your backtraces. +# Rails.backtrace_cleaner.add_silencer { |line| line =~ /my_noisy_library/ } + +# You can also remove all the silencers if you're trying to debug a problem that might stem from framework code. +# Rails.backtrace_cleaner.remove_silencers! diff --git a/config/initializers/cookies_serializer.rb b/config/initializers/cookies_serializer.rb new file mode 100644 index 0000000..7f70458 --- /dev/null +++ b/config/initializers/cookies_serializer.rb @@ -0,0 +1,3 @@ +# Be sure to restart your server when you modify this file. + +Rails.application.config.action_dispatch.cookies_serializer = :json diff --git a/config/initializers/filter_parameter_logging.rb b/config/initializers/filter_parameter_logging.rb new file mode 100644 index 0000000..4a994e1 --- /dev/null +++ b/config/initializers/filter_parameter_logging.rb @@ -0,0 +1,4 @@ +# Be sure to restart your server when you modify this file. + +# Configure sensitive parameters which will be filtered from the log file. +Rails.application.config.filter_parameters += [:password] diff --git a/config/initializers/inflections.rb b/config/initializers/inflections.rb new file mode 100644 index 0000000..ac033bf --- /dev/null +++ b/config/initializers/inflections.rb @@ -0,0 +1,16 @@ +# Be sure to restart your server when you modify this file. + +# Add new inflection rules using the following format. Inflections +# are locale specific, and you may define rules for as many different +# locales as you wish. All of these examples are active by default: +# ActiveSupport::Inflector.inflections(:en) do |inflect| +# inflect.plural /^(ox)$/i, '\1en' +# inflect.singular /^(ox)en/i, '\1' +# inflect.irregular 'person', 'people' +# inflect.uncountable %w( fish sheep ) +# end + +# These inflection rules are supported but not enabled by default: +# ActiveSupport::Inflector.inflections(:en) do |inflect| +# inflect.acronym 'RESTful' +# end diff --git a/config/initializers/mime_types.rb b/config/initializers/mime_types.rb new file mode 100644 index 0000000..dc18996 --- /dev/null +++ b/config/initializers/mime_types.rb @@ -0,0 +1,4 @@ +# Be sure to restart your server when you modify this file. + +# Add new mime types for use in respond_to blocks: +# Mime::Type.register "text/richtext", :rtf diff --git a/config/initializers/session_store.rb b/config/initializers/session_store.rb new file mode 100644 index 0000000..9eb85da --- /dev/null +++ b/config/initializers/session_store.rb @@ -0,0 +1,3 @@ +# Be sure to restart your server when you modify this file. + +Rails.application.config.session_store :cookie_store, key: '_gauge_session' diff --git a/config/initializers/wrap_parameters.rb b/config/initializers/wrap_parameters.rb new file mode 100644 index 0000000..33725e9 --- /dev/null +++ b/config/initializers/wrap_parameters.rb @@ -0,0 +1,14 @@ +# Be sure to restart your server when you modify this file. + +# This file contains settings for ActionController::ParamsWrapper which +# is enabled by default. + +# Enable parameter wrapping for JSON. You can disable this by setting :format to an empty array. +ActiveSupport.on_load(:action_controller) do + wrap_parameters format: [:json] if respond_to?(:wrap_parameters) +end + +# To enable root element in JSON for ActiveRecord objects. +# ActiveSupport.on_load(:active_record) do +# self.include_root_in_json = true +# end diff --git a/config/locales/en.yml b/config/locales/en.yml new file mode 100644 index 0000000..69b9fe8 --- /dev/null +++ b/config/locales/en.yml @@ -0,0 +1,9 @@ +en: + generic: + title: OpenFest 2015 Talk Preference Poll + submit: Submit + store_and_submit_changes: Store your changes locally and submit them if possible + help_us_reduce_the_conflicts: "Help us to reduce the conflicts in OpenFest's schedule" + click_on_the_talks_you_would_like_to_watch: Click on the talks you likely would like to watch. + press_submit: Press submit. + filter_events: Filter Events diff --git a/config/routes.rb b/config/routes.rb new file mode 100644 index 0000000..b7097bb --- /dev/null +++ b/config/routes.rb @@ -0,0 +1,4 @@ +Rails.application.routes.draw do + resources :talk_preferences, only: [:index, :show, :create, :update] + root to: 'home#index' +end diff --git a/config/secrets.yml b/config/secrets.yml new file mode 100644 index 0000000..e8e1443 --- /dev/null +++ b/config/secrets.yml @@ -0,0 +1,22 @@ +# Be sure to restart your server when you modify this file. + +# Your secret key is used for verifying the integrity of signed cookies. +# If you change this key, all old signed cookies will become invalid! + +# Make sure the secret is at least 30 characters and all random, +# no regular words or you'll be exposed to dictionary attacks. +# You can use `rake secret` to generate a secure secret key. + +# Make sure the secrets in this file are kept private +# if you're sharing your code publicly. + +development: + secret_key_base: 57b7cfee10d4ad296d1bb14d41478678e50c83e94c90152e58365639044c161fc220e5a81196399ba7db4834db40a6d2d8b064df1e9b14e1f7d66553aab0754d + +test: + secret_key_base: db04e8851f8622232428dc24f19e41dfe8191d512693932073c048870f907e502b8397360f3b4e5ae9603b53af8553c09300a6a64e83066756cfaf791eb410a3 + +# Do not keep production secrets in the repository, +# instead read values from the environment. +production: + secret_key_base: <%= ENV["SECRET_KEY_BASE"] %> diff --git a/db/migrate/20151005104151_create_talk_preferences.rb b/db/migrate/20151005104151_create_talk_preferences.rb new file mode 100644 index 0000000..1778c41 --- /dev/null +++ b/db/migrate/20151005104151_create_talk_preferences.rb @@ -0,0 +1,13 @@ +class CreateTalkPreferences < ActiveRecord::Migration + def change + create_table :talk_preferences, id: false do |t| + t.string :unique_id, null: false + t.string :ip_address + t.text :talks + + t.timestamps null: false + end + + add_index :talk_preferences, :unique_id, unique: true + end +end diff --git a/db/migrate/20151006120338_add_hashed_unique_id_to_talk_preferences.rb b/db/migrate/20151006120338_add_hashed_unique_id_to_talk_preferences.rb new file mode 100644 index 0000000..7785f3f --- /dev/null +++ b/db/migrate/20151006120338_add_hashed_unique_id_to_talk_preferences.rb @@ -0,0 +1,6 @@ +class AddHashedUniqueIdToTalkPreferences < ActiveRecord::Migration + def change + add_column :talk_preferences, :hashed_unique_id, :string + add_index :talk_preferences, :hashed_unique_id + end +end diff --git a/db/migrate/20151006121008_populate_hashed_unique_id_in_talk_preferences.rb b/db/migrate/20151006121008_populate_hashed_unique_id_in_talk_preferences.rb new file mode 100644 index 0000000..bd37328 --- /dev/null +++ b/db/migrate/20151006121008_populate_hashed_unique_id_in_talk_preferences.rb @@ -0,0 +1,19 @@ +class TalkPreference < ActiveRecord::Base + self.primary_key = :unique_id +end + +class PopulateHashedUniqueIdInTalkPreferences < ActiveRecord::Migration + def up + TalkPreference.all.each do |talk_preference| + talk_preference.hashed_unique_id = Digest::SHA1.hexdigest(talk_preference.unique_id) + talk_preference.save! + end + end + + def down + TalkPreference.all.each do |talk_preference| + talk_preference.hashed_unique_id = nil + talk_preference.save! + end + end +end diff --git a/db/seeds.rb b/db/seeds.rb new file mode 100644 index 0000000..4edb1e8 --- /dev/null +++ b/db/seeds.rb @@ -0,0 +1,7 @@ +# This file should contain all the record creation needed to seed the database with its default values. +# The data can then be loaded with the rake db:seed (or created alongside the db with db:setup). +# +# Examples: +# +# cities = City.create([{ name: 'Chicago' }, { name: 'Copenhagen' }]) +# Mayor.create(name: 'Emanuel', city: cities.first) diff --git a/lib/assets/.keep b/lib/assets/.keep new file mode 100644 index 0000000..e69de29 diff --git a/lib/tasks/.keep b/lib/tasks/.keep new file mode 100644 index 0000000..e69de29 diff --git a/log/.keep b/log/.keep new file mode 100644 index 0000000..e69de29 diff --git a/public/404.html b/public/404.html new file mode 100644 index 0000000..b612547 --- /dev/null +++ b/public/404.html @@ -0,0 +1,67 @@ + + + + The page you were looking for doesn't exist (404) + + + + + + +
+
+

The page you were looking for doesn't exist.

+

You may have mistyped the address or the page may have moved.

+
+

If you are the application owner check the logs for more information.

+
+ + diff --git a/public/422.html b/public/422.html new file mode 100644 index 0000000..a21f82b --- /dev/null +++ b/public/422.html @@ -0,0 +1,67 @@ + + + + The change you wanted was rejected (422) + + + + + + +
+
+

The change you wanted was rejected.

+

Maybe you tried to change something you didn't have access to.

+
+

If you are the application owner check the logs for more information.

+
+ + diff --git a/public/500.html b/public/500.html new file mode 100644 index 0000000..061abc5 --- /dev/null +++ b/public/500.html @@ -0,0 +1,66 @@ + + + + We're sorry, but something went wrong (500) + + + + + + +
+
+

We're sorry, but something went wrong.

+
+

If you are the application owner check the logs for more information.

+
+ + diff --git a/public/favicon.ico b/public/favicon.ico new file mode 100644 index 0000000..e69de29 diff --git a/public/robots.txt b/public/robots.txt new file mode 100644 index 0000000..3c9c7c0 --- /dev/null +++ b/public/robots.txt @@ -0,0 +1,5 @@ +# See http://www.robotstxt.org/robotstxt.html for documentation on how to use the robots.txt file +# +# To ban all spiders from the entire site uncomment the next two lines: +# User-agent: * +# Disallow: / diff --git a/vendor/assets/javascripts/.keep b/vendor/assets/javascripts/.keep new file mode 100644 index 0000000..e69de29 diff --git a/vendor/assets/stylesheets/.keep b/vendor/assets/stylesheets/.keep new file mode 100644 index 0000000..e69de29