Browse Source

Added semi-functional administration pages

development
Godwin 9 years ago
parent
commit
b719b2c8ef
  1. BIN
      app/assets/images/logo-original.png
  2. 317
      app/assets/images/logo-original.svg
  3. 2407
      app/assets/images/logo.ai
  4. BIN
      app/assets/images/runes.jpg
  5. 19
      app/assets/javascripts/editor.js
  6. 82
      app/assets/javascripts/housing.js
  7. 119
      app/assets/javascripts/main.js
  8. 585
      app/assets/stylesheets/_application.scss
  9. 12
      app/assets/stylesheets/user-mailer.scss
  10. 39
      app/controllers/application_controller.rb
  11. 306
      app/controllers/conferences_controller.rb
  12. 273
      app/helpers/application_helper.rb
  13. 2
      app/models/conference.rb
  14. 3
      app/models/event.rb
  15. 23
      app/models/event_location.rb
  16. 13
      app/models/user.rb
  17. 8
      app/models/workshop.rb
  18. 2
      app/views/application/_header.html.haml
  19. 4
      app/views/application/locale_not_available.html.haml
  20. 7
      app/views/conferences/_administration.html.haml
  21. 2
      app/views/conferences/_contact_info.html.haml
  22. 11
      app/views/conferences/_hosting.html.haml
  23. 19
      app/views/conferences/admin/_broadcast.html.haml
  24. 1
      app/views/conferences/admin/_broadcast_sent.html.haml
  25. 7
      app/views/conferences/admin/_edit.html.haml
  26. 36
      app/views/conferences/admin/_events.html.haml
  27. 26
      app/views/conferences/admin/_housing.html.haml
  28. 35
      app/views/conferences/admin/_locations.html.haml
  29. 30
      app/views/conferences/admin/_meals.html.haml
  30. 0
      app/views/conferences/admin/_schedule.html.haml
  31. 0
      app/views/conferences/admin/_stats.html.haml
  32. 23
      app/views/conferences/register.html.haml
  33. 1
      app/views/layouts/application.html.haml
  34. 4
      app/views/shared/_footer.html.haml
  35. 2
      app/views/user_mailer/broadcast.html.haml
  36. 12
      app/views/workshops/new.html.haml
  37. 2
      config/initializers/assets.rb
  38. 59
      config/locales/en.yml
  39. 2
      config/routes.rb
  40. 5
      db/migrate/20160621020123_add_space_to_event_locations.rb
  41. 5
      db/migrate/20160621051912_add_meals_to_conferences.rb
  42. 5
      db/migrate/20160622011811_add_locale_to_events.rb
  43. 5
      db/schema.rb

BIN
app/assets/images/logo-original.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 75 KiB

317
app/assets/images/logo-original.svg

@ -0,0 +1,317 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 19.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 792 612" style="enable-background:new 0 0 792 612;" xml:space="preserve">
<style type="text/css">
.st0{fill:#00ADEF;}
.st1{fill:#FFFFFF;}
.st2{fill:#333333;}
</style>
<path class="st0" d="M384.502,298.637c-8.782,0.887-16.889-5.133-18.436-13.966c-1.549-8.842,4.046-17.271,12.623-19.408
c-1.61-5.4-3.523-10.67-5.725-15.786c-7.953,3.86-17.648,0.982-22.131-6.797c-4.477-7.771-2.113-17.596,5.199-22.545
c-3.349-4.494-6.955-8.785-10.79-12.858c-6.153,6.325-16.229,6.93-23.095,1.163c-6.867-5.77-8.009-15.809-2.832-22.962
c-4.662-3.073-9.51-5.887-14.526-8.416c-3.608,8.067-12.881,12.098-21.315,9.025c-8.434-3.073-12.942-12.125-10.514-20.625
c-5.402-1.273-10.922-2.242-16.537-2.895c-0.64,8.806-7.969,15.756-16.938,15.756c-8.969,0-16.298-6.95-16.938-15.756
c-5.481,0.637-10.873,1.571-16.151,2.801c2.407,8.509-2.128,17.547-10.571,20.598c-8.441,3.049-17.701-1.007-21.289-9.08
c-5.022,2.516-9.879,5.313-14.549,8.373c5.156,7.17,3.986,17.202-2.896,22.953c-6.881,5.748-16.956,5.115-23.093-1.225
c-3.846,4.061-7.462,8.343-10.822,12.828c7.299,4.972,9.634,14.798,5.136,22.558c-4.504,7.767-14.204,10.617-22.146,6.739
c-2.216,5.11-4.146,10.373-5.771,15.768c8.57,2.164,14.141,10.603,12.568,19.442c-1.57,8.828-9.691,14.824-18.469,13.916
c-0.166,2.843-0.26,5.706-0.26,8.591c0,2.75,0.084,5.48,0.234,8.192c8.781-0.883,16.887,5.136,18.434,13.97
c1.548,8.842-4.047,17.266-12.621,19.404c1.61,5.4,3.522,10.669,5.725,15.785c7.952-3.857,17.646-0.979,22.129,6.801
c4.479,7.771,2.113,17.593-5.197,22.542c3.348,4.494,6.954,8.784,10.789,12.857c6.154-6.322,16.23-6.926,23.096-1.159
c6.866,5.77,8.007,15.806,2.831,22.959c4.663,3.073,9.511,5.887,14.527,8.417c3.609-8.066,12.882-12.097,21.315-9.024
c8.433,3.073,12.941,12.124,10.514,20.623c5.402,1.274,10.921,2.243,16.537,2.895c0.64-8.806,7.969-15.756,16.938-15.756
c8.969,0,16.298,6.95,16.938,15.756c5.48-0.637,10.871-1.57,16.148-2.801c-2.409-8.508,2.123-17.549,10.566-20.598
c8.44-3.049,17.708,1.005,21.293,9.082c5.023-2.516,9.88-5.314,14.551-8.373c-5.159-7.168-3.993-17.203,2.892-22.954
c6.881-5.748,16.962-5.118,23.098,1.226c3.847-4.062,7.463-8.344,10.824-12.829c-7.302-4.968-9.641-14.796-5.142-22.557
c4.503-7.765,14.209-10.621,22.15-6.74c2.216-5.11,4.147-10.372,5.772-15.768c-8.573-2.161-14.145-10.601-12.572-19.44
c1.57-8.827,9.694-14.829,18.473-13.918c0.166-2.844,0.26-5.707,0.26-8.592C384.736,304.079,384.652,301.349,384.502,298.637z"/>
<g>
<path class="st1" d="M270.605,343.041c-0.125,1.505-0.598,3.401-1.421,5.696c-0.825,2.293-1.543,4.059-2.151,5.291
c-0.612,1.234-1.204,2.401-1.779,3.506c-0.576,1.103-1.197,2.125-1.867,3.061c-4.484,5.786-10.153,9.994-17.006,12.628
c-2.637,0.97-5.372,1.672-8.211,2.097c-2.839,0.428-5.817,0.715-8.927,0.856c-1.576,0.139-3.169,0.094-4.785-0.13
c-1.617-0.223-3.179-0.397-4.681-0.52c-0.688-0.044-1.323-0.146-1.91-0.304c-0.586-0.157-1.225-0.256-1.911-0.303
c-0.557-0.007-1.11-0.155-1.661-0.445c-0.553-0.284-1.19-0.387-1.911-0.302c-0.557-0.008-1.12-0.123-1.688-0.348
c-0.569-0.221-1.181-0.42-1.831-0.595l-57.096-15.299c-2.218-0.595-4.049-1.19-5.494-1.786c-1.448-0.599-2.288-1.766-2.52-3.504
c-0.111-1.148,0.151-2.789,0.795-4.922c0.641-2.134,1.154-3.915,1.539-5.352l30.755-114.777c0.419-1.564,0.831-3.235,1.237-5.012
c0.404-1.778,1.073-3.1,2.007-3.969c0.763-0.77,1.916-1.162,3.457-1.169c0.294-0.06,0.563-0.023,0.808,0.111
c0.242,0.137,0.511,0.173,0.809,0.111l58.268,15.613c0.911,0.244,1.833,0.459,2.765,0.636c0.927,0.181,1.767,0.441,2.516,0.779
c0.58,0.438,1.214,0.676,1.902,0.72c0.686,0.045,1.337,0.22,1.955,0.524l1.174,0.314c0.712,0.471,1.498,0.787,2.365,0.947
c0.864,0.163,1.718,0.497,2.561,1.001c0.971,0.542,1.93,1.009,2.873,1.398c0.942,0.395,1.898,0.859,2.874,1.4
c2.231,1.575,4.34,3.084,6.332,4.525c1.987,1.443,3.719,3.059,5.196,4.85c2.116,2.525,3.657,5.381,4.619,8.573
c0.959,3.19,1.49,6.687,1.592,10.485c0.015,0.982-0.068,1.939-0.244,2.869c-0.182,0.931-0.281,1.951-0.298,3.063
c-0.012,0.557-0.118,1.088-0.321,1.591c-0.208,0.504-0.315,1.036-0.322,1.59c0.023,0.426-0.072,0.923-0.295,1.493
c-0.224,0.569-0.436,0.966-0.634,1.192l-0.472,1.76c-0.104,0.391-0.261,0.84-0.464,1.343c-0.208,0.505-0.343,0.888-0.411,1.146
c-0.509,0.843-0.89,1.614-1.145,2.314c-0.258,0.699-0.605,1.341-1.039,1.922c-2.953,4.238-6.198,7.491-9.739,9.755
c-1.157,0.669-2.344,1.189-3.561,1.562c-1.219,0.373-2.357,0.975-3.418,1.808c-0.334,0.192-0.722,0.472-1.168,0.839
c-0.45,0.371-0.632,0.916-0.544,1.637c-0.02,1.114,0.591,2.221,1.835,3.32c1.24,1.103,2.294,2.119,3.165,3.049
c2.891,3.289,5.023,6.795,6.402,10.518c1.281,3.558,1.969,7.515,2.06,11.867c0.112,1.15,0.083,2.295-0.081,3.437
c-0.17,1.144-0.263,2.271-0.278,3.383L270.605,343.041z"/>
<path class="st1" d="M305.286,368.469c0.606,0.864,0.818,1.896,0.635,3.105c-0.186,1.208-0.468,2.53-0.853,3.963l-3.771,14.078
c-0.385,1.436-0.801,2.72-1.244,3.858c-0.445,1.138-1.081,1.947-1.905,2.423c-1.091,0.409-2.294,0.469-3.613,0.185
c-1.322-0.282-2.7-0.618-4.132-1.002l-13.102-3.511c-1.436-0.385-2.797-0.783-4.079-1.198c-1.288-0.413-2.151-1.099-2.593-2.056
c-0.445-0.958-0.565-2.071-0.36-3.346c0.199-1.273,0.493-2.625,0.877-4.061l3.302-12.319c0.349-1.302,0.688-2.572,1.021-3.813
c0.331-1.237,0.862-2.18,1.594-2.82c0.729-0.645,1.881-1.033,3.457-1.171c0.295-0.059,0.598-0.014,0.906,0.139
c0.306,0.154,0.608,0.199,0.905,0.138l15.447,4.139c1.565,0.419,3.022,0.846,4.374,1.277
C303.504,366.911,304.547,367.574,305.286,368.469z M296.025,294.316c0.114-3.042,0.658-6.249,1.635-9.623
c0.973-3.371,1.914-6.75,2.822-10.141l4.035-15.057c0.383-1.433,0.75-2.802,1.1-4.105c0.349-1.303,0.97-2.324,1.868-3.063
c0.86-0.608,1.913-0.883,3.156-0.831c0.295-0.06,0.563-0.023,0.809,0.111c0.241,0.137,0.511,0.173,0.808,0.111l15.057,4.034
c1.564,0.42,3.013,0.879,4.348,1.376c1.332,0.497,2.201,1.29,2.61,2.376c0.311,0.921,0.312,1.97-0.003,3.143
c-0.314,1.173-0.647,2.414-0.995,3.715l-5.815,21.705c-0.21,0.781-0.382,1.678-0.512,2.691c-0.135,1.011-0.417,1.811-0.851,2.391
l-0.576,2.152c-0.508,0.843-0.858,1.761-1.054,2.756c-0.197,0.995-0.531,1.85-1,2.561c-0.438,0.583-0.701,1.174-0.791,1.778
c-0.094,0.604-0.356,1.198-0.791,1.779c-0.578,1.103-1.012,2.211-1.308,3.316c-0.298,1.11-0.718,2.15-1.257,3.122
c-0.27,0.487-0.466,0.959-0.588,1.414c-0.123,0.458-0.321,0.93-0.589,1.414c-0.717,1.626-1.384,3.332-2.001,5.122
c-0.621,1.792-1.352,3.482-2.197,5.07c-0.507,0.844-0.832,1.664-0.975,2.463c-0.145,0.8-0.488,1.686-1.025,2.659
c-1.151,2.206-2.101,4.571-2.846,7.097c-0.748,2.523-1.761,4.872-3.04,7.045c-0.88,1.723-1.607,3.518-2.177,5.389
c-0.574,1.873-1.635,3.092-3.181,3.654c-0.46,0.157-0.972,0.23-1.525,0.22c-0.558-0.009-1.179-0.035-1.864-0.081l-2.737-0.733
c-1.305-0.35-2.411-0.784-3.317-1.308c-0.908-0.522-1.537-1.18-1.883-1.971c-0.442-0.958-0.54-1.892-0.295-2.805
c0.243-0.91,0.373-1.924,0.395-3.038c-0.008-1.538,0.166-3.099,0.521-4.68c0.351-1.583,0.526-3.14,0.521-4.682
c0.279-1.041,0.404-1.776,0.381-2.203c0.078-0.817,0.224-1.616,0.434-2.399c0.209-0.78,0.351-1.582,0.432-2.398
c-0.032-1.964,0.19-3.964,0.667-6.003c0.474-2.038,0.763-4.021,0.86-5.952c0.044-0.687,0.146-1.323,0.303-1.909
c0.157-0.587,0.256-1.222,0.303-1.911c0.051-1.242,0.221-2.523,0.507-3.846c0.281-1.32,0.468-2.667,0.558-4.042
c0.07-0.26,0.107-0.527,0.113-0.808c0.001-0.277,0.041-0.545,0.111-0.809c0.016-1.113,0.159-2.157,0.421-3.135
C295.867,296.473,296.005,295.43,296.025,294.316z"/>
</g>
<g>
<path class="st2" d="M471.32,265.018c0.166,0.499,0.25,1.352,0.25,2.555c0,1.206-0.044,2.057-0.125,2.555
c0,0.418-0.021,0.77-0.063,1.06c-0.043,0.292-0.063,0.645-0.063,1.06c-0.168,0.666-0.249,1.309-0.249,1.932
c0,0.624-0.084,1.268-0.25,1.933c0,0.333-0.083,0.915-0.249,1.745c-0.249,0.997-0.48,2.016-0.686,3.054
c-0.208,1.041-0.52,2.017-0.935,2.93c-1.496,3.74-3.366,6.98-5.609,9.724c-2.244,2.742-5.195,4.904-8.852,6.482
c-0.748,0.333-1.517,0.602-2.306,0.81c-0.791,0.207-1.642,0.437-2.556,0.686c-0.499,0.166-1.019,0.25-1.559,0.25
c-0.541,0-1.06,0.041-1.559,0.124h-1.121c-0.499,0.166-1.165,0.229-1.995,0.188c-0.832-0.043-1.495-0.145-1.994-0.311h-0.748
c-0.417-0.084-0.872-0.146-1.371-0.186c-0.499-0.044-0.998-0.105-1.496-0.188c-1.579-0.417-3.034-0.832-4.363-1.246
c-1.33-0.416-2.576-0.998-3.739-1.746c-0.499-0.331-0.978-0.664-1.434-0.997c-0.458-0.331-0.895-0.705-1.31-1.122
c-0.249-0.165-0.498-0.331-0.747-0.499c-0.25-0.165-0.499-0.289-0.749-0.373c-0.748-0.25-1.205-0.082-1.371,0.498
c-0.417,0.583-0.685,1.269-0.81,2.057c-0.125,0.791-0.436,1.393-0.935,1.809c-0.498,0.332-1.081,0.52-1.745,0.56
c-0.666,0.043-1.414,0.063-2.243,0.063h-5.984c-0.582,0-1.185,0.02-1.808,0.061c-0.623,0.042-1.185-0.021-1.683-0.186
c-1.165-0.415-1.808-1.184-1.933-2.307c-0.124-1.121-0.186-2.388-0.186-3.802v-76.042c0-0.914,0-1.87,0-2.867
c0-0.997,0.206-1.786,0.623-2.369c0.331-0.581,0.913-0.955,1.745-1.122c0.166-0.082,0.353-0.103,0.562-0.062
c0.206,0.042,0.392,0.021,0.561-0.063h7.853c1.496,0,2.783,0.063,3.864,0.187c1.079,0.124,1.786,0.77,2.119,1.932
c0.25,0.832,0.332,1.932,0.25,3.304c-0.084,1.371-0.125,2.555-0.125,3.553v13.587c0,0.915,0,1.83,0,2.743
c0,0.915,0.082,1.704,0.249,2.368c0.082,0.417,0.166,0.77,0.249,1.06c0.083,0.292,0.291,0.479,0.624,0.561
c0.166,0.168,0.393,0.249,0.685,0.249c0.29,0,0.518-0.04,0.686-0.124c0.581-0.331,1.122-0.686,1.62-1.06
c0.499-0.374,1.039-0.768,1.621-1.185c1.079-0.748,2.201-1.391,3.365-1.933c1.163-0.54,2.451-1.016,3.865-1.434
c0.664-0.249,1.328-0.393,1.994-0.436c0.664-0.041,1.329-0.144,1.994-0.312c0.581-0.165,1.204-0.249,1.87-0.249
c0.665,0,1.329,0,1.995,0h1.246c0.249,0.083,0.54,0.104,0.873,0.062c0.331-0.041,0.664-0.02,0.997,0.062
c0.914,0.249,1.765,0.437,2.556,0.562c0.789,0.124,1.558,0.354,2.307,0.685c3.821,1.58,6.938,3.616,9.349,6.109
c2.41,2.493,4.445,5.609,6.108,9.349c0.415,0.997,0.768,2.037,1.06,3.116c0.291,1.081,0.602,2.204,0.935,3.366
c0.166,0.582,0.27,1.144,0.313,1.683c0.041,0.541,0.143,1.143,0.311,1.808c0.165,0.417,0.228,0.873,0.186,1.371
c-0.042,0.499-0.021,0.998,0.063,1.496V265.018z"/>
<path class="st2" d="M493.883,212.411c0.58,0.666,0.873,1.663,0.873,2.992c0,1.331,0,2.618,0,3.864c0,1.081,0,2.203,0,3.366
c0,1.165-0.293,1.954-0.873,2.369c-0.498,0.417-1.143,0.665-1.932,0.747c-0.791,0.083-1.643,0.125-2.556,0.125h-6.981
c-0.915,0-1.726-0.042-2.431-0.125c-0.707-0.082-1.309-0.331-1.808-0.747c-0.333-0.25-0.561-0.727-0.686-1.434
c-0.124-0.705-0.208-1.497-0.249-2.369c-0.043-0.872-0.043-1.765,0-2.68c0.041-0.913,0.063-1.703,0.063-2.369
c0-0.664,0.019-1.266,0.063-1.808c0.04-0.54,0.186-1.017,0.436-1.434c0.166-0.331,0.393-0.581,0.685-0.748
c0.29-0.166,0.603-0.331,0.936-0.499c0.165,0,0.374-0.02,0.623-0.063c0.249-0.04,0.456-0.062,0.623-0.062h9.101
c0.83,0,1.62,0.042,2.368,0.124C492.886,211.747,493.467,211.996,493.883,212.411z M494.756,293.565
c0,1.663-0.043,3.075-0.125,4.238c-0.083,1.165-0.831,1.953-2.243,2.369c-0.499,0.167-1.04,0.229-1.621,0.186
c-0.583-0.041-1.206-0.063-1.87-0.063h-6.98c-0.748,0-1.477-0.041-2.182-0.124c-0.707-0.082-1.228-0.332-1.559-0.749
c-0.498-0.58-0.77-1.309-0.81-2.182c-0.044-0.872-0.063-1.807-0.063-2.805v-52.606c0-0.83,0-1.661,0-2.493
c0-0.83,0.165-1.496,0.498-1.995c0.499-0.58,1.204-0.955,2.119-1.122c0.166-0.081,0.394-0.103,0.686-0.062
c0.289,0.042,0.518,0.021,0.686-0.063h6.232c0.499,0,1.06-0.019,1.683-0.063c0.624-0.041,1.142-0.02,1.559,0.063h0.997
c0.499,0.168,0.955,0.292,1.371,0.374c0.415,0.083,0.748,0.333,0.997,0.748c0.331,0.416,0.519,0.997,0.562,1.745
c0.041,0.748,0.063,1.539,0.063,2.369V293.565z"/>
<path class="st2" d="M507.471,211.539h9.1c0.914,0,1.746,0.042,2.493,0.124c0.748,0.084,1.328,0.333,1.746,0.748
c0.663,0.748,0.976,1.954,0.935,3.615c-0.043,1.663-0.063,3.2-0.063,4.612v21.067v7.604c0,0.582-0.043,1.206-0.125,1.87
c-0.084,0.666-0.042,1.289,0.125,1.87v1.122c0.165,0.416,0.29,0.854,0.374,1.309c0.082,0.458,0.331,0.77,0.748,0.935
c0.249,0.168,0.58,0.187,0.997,0.062c0.415-0.125,0.705-0.269,0.872-0.436c0.83-0.58,1.558-1.246,2.182-1.995
c0.624-0.748,1.267-1.453,1.933-2.119c0.664-0.663,1.371-1.35,2.119-2.057c0.748-0.705,1.412-1.474,1.994-2.306
c0.25-0.165,0.54-0.414,0.873-0.748c0.415-0.415,0.83-0.851,1.246-1.309c0.416-0.456,0.83-0.892,1.247-1.309l2.867-2.867
c0.166-0.331,0.393-0.602,0.685-0.81c0.29-0.207,0.562-0.478,0.811-0.811c0.664-0.83,1.391-1.559,2.182-2.182
c0.788-0.624,1.765-1.06,2.929-1.309c0.416-0.081,0.998-0.124,1.746-0.124c0.331-0.082,0.664-0.103,0.997-0.063
c0.331,0.043,0.705,0.063,1.122,0.063h4.113c0.665,0,1.475-0.041,2.432-0.125c0.954-0.082,1.764-0.041,2.431,0.125h1.371
c0.415,0.168,0.829,0.27,1.247,0.312c0.414,0.043,0.705,0.229,0.872,0.561c0.166,0.249,0.188,0.582,0.063,0.997
c-0.125,0.417-0.271,0.707-0.437,0.873c-0.498,0.831-1.122,1.558-1.87,2.181c-0.748,0.624-1.455,1.268-2.119,1.933
c-0.582,0.582-1.143,1.165-1.683,1.745c-0.541,0.583-1.144,1.122-1.808,1.621c-0.417,0.333-0.77,0.686-1.06,1.059
c-0.292,0.374-0.645,0.729-1.06,1.06c-0.417,0.249-0.791,0.583-1.122,0.997c-0.333,0.417-0.707,0.791-1.122,1.122l-4.737,4.737
c-0.582,0.499-1.102,0.978-1.558,1.434c-0.458,0.458-0.895,1.019-1.309,1.683c-0.168,0.249-0.334,0.561-0.499,0.935
c-0.168,0.374-0.168,0.769,0,1.185c0.165,0.916,0.477,1.663,0.934,2.244c0.456,0.582,0.893,1.206,1.309,1.87
c0.665,0.916,1.267,1.829,1.809,2.742c0.539,0.916,1.141,1.829,1.808,2.742l13.089,19.821c0.83,1.165,1.64,2.327,2.431,3.49
c0.789,1.165,1.516,2.328,2.182,3.49c0.249,0.417,0.394,0.916,0.435,1.496c0.041,0.583-0.146,1.041-0.56,1.372
c-0.333,0.167-0.666,0.249-0.997,0.249c-0.333,0-0.707,0.083-1.122,0.249c-0.333,0.084-0.707,0.105-1.122,0.063
c-0.416-0.041-0.831-0.063-1.246-0.063h-4.862c-1.33,0-2.91,0.022-4.736,0.063c-1.829,0.043-3.201-0.145-4.114-0.56
c-0.915-0.416-1.704-1.185-2.368-2.307c-0.666-1.122-1.289-2.139-1.87-3.055c-1.414-2.243-2.826-4.507-4.238-6.794
c-1.414-2.284-2.826-4.55-4.238-6.794c-0.667-1.079-1.31-2.16-1.933-3.241c-0.623-1.079-1.308-2.119-2.057-3.116
c-0.168-0.249-0.458-0.58-0.873-0.997c-0.417-0.415-0.872-0.54-1.371-0.374c-0.748,0.168-1.309,0.417-1.683,0.748
c-0.374,0.333-0.769,0.707-1.185,1.122c-0.666,0.498-1.289,1.081-1.869,1.745c-0.583,0.666-1.041,1.455-1.372,2.369
c-0.167,0.665-0.249,1.392-0.249,2.181c0,0.791,0,1.559,0,2.307v7.729c0,0.582,0.02,1.228,0.063,1.933
c0.041,0.707,0.063,1.434,0.063,2.182c0,0.747-0.043,1.434-0.125,2.057c-0.084,0.623-0.249,1.103-0.498,1.434
c-0.334,0.498-0.854,0.853-1.559,1.06c-0.707,0.208-1.518,0.333-2.432,0.374c-0.915,0.043-1.869,0.043-2.867,0
c-0.997-0.041-1.869-0.063-2.617-0.063c-0.915,0-1.913,0.022-2.992,0.063c-1.081,0.043-1.953-0.063-2.618-0.311
c-1.081-0.415-1.663-1.163-1.745-2.244c-0.083-1.079-0.124-2.326-0.124-3.74v-14.335v-49.989v-11.593
c0-0.914-0.021-1.87-0.063-2.867c-0.043-0.997,0.103-1.786,0.436-2.369c0.331-0.581,0.913-0.997,1.745-1.247
c0.166,0,0.353-0.02,0.561-0.063C507.116,211.56,507.303,211.539,507.471,211.539z"/>
<path class="st2" d="M628.888,267.635c0.165,0.667,0.165,1.414,0,2.244c-0.168,0.832-0.458,1.372-0.873,1.621
c-0.417,0.333-1.018,0.561-1.808,0.686c-0.79,0.125-1.663,0.208-2.618,0.25c-0.956,0.043-1.912,0.043-2.867,0
c-0.956-0.041-1.808-0.063-2.555-0.063H587.75c-0.583,0-1.144,0-1.684,0c-0.541,0-1.018,0.083-1.434,0.25
c-0.665,0.333-1.081,0.666-1.246,0.997c-0.168,0.167-0.333,0.48-0.499,0.935c-0.167,0.458-0.208,0.894-0.124,1.309
c0.165,0.499,0.268,0.978,0.312,1.435c0.041,0.457,0.144,0.935,0.311,1.434c0.664,1.994,1.475,3.636,2.431,4.924
c0.954,1.289,2.264,2.431,3.927,3.428c0.664,0.417,1.35,0.686,2.057,0.811c0.705,0.125,1.434,0.311,2.182,0.56
c0.664,0.168,1.578,0.293,2.743,0.374c1.162,0.084,2.16,0.043,2.991-0.125h1.122c0.83-0.165,1.6-0.352,2.307-0.56
c0.705-0.206,1.391-0.436,2.057-0.686c0.83-0.415,1.765-0.954,2.805-1.621c1.038-0.663,1.808-1.328,2.307-1.994
c0.414-0.58,0.851-1.142,1.309-1.683c0.456-0.54,1.017-0.936,1.683-1.185c0.83-0.415,1.89-0.602,3.18-0.561
c1.287,0.042,2.471,0.062,3.552,0.062c0.499,0,1.017-0.02,1.559-0.062c0.539-0.041,1.017,0.022,1.434,0.187h1.247
c0.829,0.168,1.412,0.374,1.745,0.623c0.331,0.168,0.518,0.542,0.561,1.122c0.041,0.583-0.021,1.081-0.187,1.496
c-0.417,1.165-0.873,2.203-1.372,3.117c-0.498,0.915-1.081,1.828-1.745,2.742c-1.829,2.742-3.907,4.945-6.232,6.606
c-2.328,1.663-5.236,3.075-8.727,4.239c-0.915,0.331-1.828,0.539-2.742,0.623c-0.916,0.082-1.87,0.249-2.867,0.498
c-0.333,0.082-0.686,0.104-1.06,0.063c-0.374-0.043-0.729-0.021-1.06,0.063h-1.371c-0.417,0.166-0.895,0.228-1.434,0.186
c-0.542-0.043-1.02-0.104-1.434-0.186c-0.666-0.084-1.247-0.084-1.746,0c-0.498,0.082-1.04,0.041-1.62-0.125
c-0.417-0.167-0.872-0.249-1.371-0.249c-0.498,0-0.956-0.084-1.371-0.249c-0.915-0.168-1.829-0.355-2.743-0.562
c-0.915-0.206-1.744-0.518-2.493-0.934c-0.915-0.331-1.767-0.644-2.556-0.935c-0.79-0.291-1.517-0.644-2.181-1.06
c-2.661-1.662-5.029-3.594-7.106-5.797c-2.078-2.201-3.782-4.757-5.11-7.667c-0.417-0.913-0.748-1.849-0.997-2.805
c-0.25-0.955-0.582-1.933-0.998-2.93c-0.083-0.331-0.124-0.643-0.124-0.935c0-0.291-0.043-0.602-0.125-0.935
c-0.333-0.997-0.541-2.076-0.623-3.241c-0.084-1.163-0.168-2.326-0.249-3.491c0-0.415-0.021-0.873-0.063-1.371
c-0.043-0.499-0.021-0.955,0.063-1.371v-1.496l0.373-2.992c0.332-1.412,0.624-2.783,0.873-4.114
c0.249-1.328,0.623-2.575,1.122-3.739c3.572-8.643,9.64-14.751,18.2-18.325c1.163-0.499,2.347-0.851,3.553-1.06
c1.204-0.206,2.472-0.477,3.802-0.811c0.665-0.081,1.288-0.124,1.87-0.124c0.581,0,1.204-0.042,1.87-0.125
c4.238-0.082,7.873,0.395,10.907,1.434c3.033,1.04,5.755,2.39,8.166,4.052c0.747,0.499,1.495,1.06,2.244,1.683
c0.747,0.624,1.412,1.268,1.994,1.932c0.249,0.417,0.58,0.748,0.997,0.997c0.664,0.916,1.288,1.85,1.87,2.805
c0.58,0.957,1.204,1.932,1.869,2.93c0.416,0.748,0.769,1.517,1.06,2.306c0.291,0.79,0.602,1.642,0.936,2.555
c0.415,1.081,0.748,2.203,0.997,3.366c0.249,1.165,0.54,2.328,0.873,3.49c0.165,0.666,0.228,1.393,0.187,2.182
c-0.043,0.79,0.019,1.517,0.188,2.182V267.635z"/>
<path class="st2" d="M652.571,282.096c0.499,0.417,0.789,0.997,0.873,1.745c0.081,0.748,0.124,1.58,0.124,2.493v8.976
c0,0.916-0.043,1.745-0.124,2.493c-0.084,0.748-0.333,1.33-0.748,1.745c-0.583,0.417-1.29,0.645-2.119,0.685
c-0.832,0.043-1.705,0.063-2.618,0.063h-8.353c-0.915,0-1.788-0.02-2.617-0.063c-0.832-0.041-1.456-0.311-1.87-0.81
c-0.417-0.498-0.666-1.141-0.748-1.932c-0.084-0.789-0.125-1.641-0.125-2.556v-7.853c0-0.829,0-1.64,0-2.431
c0-0.789,0.166-1.434,0.499-1.933c0.331-0.498,0.954-0.913,1.87-1.246c0.165-0.082,0.353-0.104,0.561-0.063
c0.207,0.043,0.393,0.021,0.562-0.063h9.848c0.997,0,1.933,0.021,2.805,0.063C651.263,281.453,651.989,281.681,652.571,282.096z
M635.244,239.462c-0.417-1.828-0.604-3.822-0.562-5.984c0.041-2.16,0.063-4.32,0.063-6.482v-9.599c0-0.914,0-1.786,0-2.618
c0-0.83,0.206-1.537,0.623-2.12c0.415-0.499,0.997-0.83,1.745-0.997c0.166-0.082,0.331-0.103,0.499-0.063
c0.165,0.043,0.331,0.021,0.499-0.062h9.599c0.997,0,1.932,0.042,2.805,0.124c0.872,0.084,1.516,0.417,1.932,0.997
c0.331,0.499,0.499,1.122,0.499,1.87c0,0.748,0,1.538,0,2.369v13.837c0,0.499,0.041,1.06,0.125,1.683
c0.081,0.624,0.041,1.144-0.125,1.558v1.372c-0.168,0.582-0.23,1.184-0.188,1.808c0.041,0.623-0.021,1.184-0.187,1.683
c-0.167,0.417-0.229,0.811-0.187,1.185c0.04,0.374-0.021,0.769-0.188,1.184c-0.167,0.749-0.249,1.477-0.249,2.182
c0,0.707-0.084,1.392-0.249,2.057c-0.084,0.333-0.125,0.645-0.125,0.935c0,0.292-0.043,0.604-0.125,0.936
c-0.167,1.081-0.292,2.203-0.374,3.365c-0.084,1.165-0.249,2.287-0.498,3.366c-0.168,0.583-0.23,1.122-0.188,1.621
c0.041,0.499-0.021,1.081-0.187,1.746c-0.333,1.496-0.521,3.054-0.561,4.675c-0.043,1.62-0.271,3.179-0.686,4.675
c-0.249,1.164-0.396,2.349-0.437,3.552c-0.043,1.206-0.478,2.1-1.309,2.68c-0.25,0.168-0.541,0.293-0.873,0.375
c-0.333,0.083-0.707,0.167-1.121,0.249h-1.746c-0.831,0-1.558-0.082-2.181-0.249c-0.624-0.165-1.102-0.456-1.434-0.872
c-0.417-0.499-0.624-1.038-0.624-1.621c0-0.581-0.083-1.204-0.249-1.87c-0.249-0.913-0.396-1.87-0.437-2.867
c-0.043-0.998-0.186-1.952-0.436-2.867c0-0.664-0.043-1.122-0.125-1.371c-0.084-0.499-0.125-0.997-0.125-1.496
c0-0.498-0.043-0.998-0.124-1.496c-0.333-1.163-0.521-2.388-0.562-3.678c-0.043-1.287-0.187-2.513-0.437-3.678
c-0.083-0.414-0.124-0.81-0.124-1.184c0-0.374-0.043-0.768-0.125-1.185c-0.168-0.748-0.271-1.537-0.311-2.369
c-0.043-0.83-0.147-1.661-0.312-2.493c0-0.165-0.021-0.331-0.063-0.499c-0.043-0.165-0.063-0.331-0.063-0.499
c-0.167-0.664-0.249-1.309-0.249-1.932C635.493,240.771,635.409,240.128,635.244,239.462z"/>
</g>
<g>
<path class="st2" d="M471.32,363.343c0.166,0.499,0.25,1.352,0.25,2.556c0,1.206-0.044,2.057-0.125,2.555
c0,0.418-0.021,0.771-0.063,1.06c-0.043,0.293-0.063,0.646-0.063,1.061c-0.168,0.666-0.249,1.309-0.249,1.933
c0,0.623-0.084,1.268-0.25,1.932c0,0.333-0.083,0.916-0.249,1.745c-0.249,0.998-0.48,2.017-0.686,3.055
c-0.208,1.04-0.52,2.016-0.935,2.93c-1.496,3.739-3.366,6.98-5.609,9.723c-2.244,2.743-5.195,4.905-8.852,6.483
c-0.748,0.333-1.517,0.603-2.306,0.81c-0.791,0.207-1.642,0.438-2.556,0.687c-0.499,0.166-1.019,0.249-1.559,0.249
c-0.541,0-1.06,0.041-1.559,0.124h-1.121c-0.499,0.167-1.165,0.228-1.995,0.188c-0.832-0.042-1.495-0.146-1.994-0.312h-0.748
c-0.417-0.083-0.872-0.145-1.371-0.186c-0.499-0.044-0.998-0.105-1.496-0.188c-1.579-0.416-3.034-0.831-4.363-1.246
c-1.33-0.415-2.576-0.997-3.739-1.745c-0.499-0.331-0.978-0.664-1.434-0.997c-0.458-0.332-0.895-0.705-1.31-1.122
c-0.249-0.166-0.498-0.331-0.747-0.499c-0.25-0.165-0.499-0.29-0.749-0.374c-0.748-0.249-1.205-0.082-1.371,0.499
c-0.417,0.582-0.685,1.268-0.81,2.056c-0.125,0.792-0.436,1.393-0.935,1.808c-0.498,0.332-1.081,0.52-1.745,0.561
c-0.666,0.043-1.414,0.063-2.243,0.063h-5.984c-0.582,0-1.185,0.02-1.808,0.061c-0.623,0.042-1.185-0.02-1.683-0.185
c-1.165-0.415-1.808-1.185-1.933-2.308c-0.124-1.121-0.186-2.387-0.186-3.801v-76.043c0-0.914,0-1.869,0-2.867
c0-0.997,0.206-1.786,0.623-2.368c0.331-0.581,0.913-0.955,1.745-1.122c0.166-0.082,0.353-0.103,0.562-0.063
c0.206,0.043,0.392,0.021,0.561-0.062h7.853c1.496,0,2.783,0.062,3.864,0.187c1.079,0.124,1.786,0.77,2.119,1.933
c0.25,0.831,0.332,1.932,0.25,3.303c-0.084,1.372-0.125,2.556-0.125,3.553v13.588c0,0.915,0,1.829,0,2.743
c0,0.915,0.082,1.703,0.249,2.368c0.082,0.416,0.166,0.769,0.249,1.06c0.083,0.292,0.291,0.479,0.624,0.562
c0.166,0.167,0.393,0.248,0.685,0.248c0.29,0,0.518-0.041,0.686-0.124c0.581-0.331,1.122-0.686,1.62-1.06
c0.499-0.374,1.039-0.768,1.621-1.184c1.079-0.748,2.201-1.392,3.365-1.934c1.163-0.539,2.451-1.016,3.865-1.434
c0.664-0.248,1.328-0.393,1.994-0.436c0.664-0.041,1.329-0.143,1.994-0.311c0.581-0.165,1.204-0.249,1.87-0.249
c0.665,0,1.329,0,1.995,0h1.246c0.249,0.084,0.54,0.105,0.873,0.063c0.331-0.041,0.664-0.02,0.997,0.062
c0.914,0.25,1.765,0.436,2.556,0.561c0.789,0.124,1.558,0.354,2.307,0.685c3.821,1.58,6.938,3.616,9.349,6.109
c2.41,2.493,4.445,5.609,6.108,9.35c0.415,0.997,0.768,2.036,1.06,3.115c0.291,1.081,0.602,2.204,0.935,3.366
c0.166,0.583,0.27,1.144,0.313,1.684c0.041,0.541,0.143,1.144,0.311,1.808c0.165,0.417,0.228,0.872,0.186,1.37
c-0.042,0.499-0.021,0.998,0.063,1.497V363.343z"/>
<path class="st2" d="M493.883,310.736c0.58,0.667,0.873,1.664,0.873,2.992c0,1.33,0,2.618,0,3.864c0,1.081,0,2.203,0,3.365
c0,1.166-0.293,1.954-0.873,2.369c-0.498,0.417-1.143,0.666-1.932,0.748c-0.791,0.083-1.643,0.125-2.556,0.125h-6.981
c-0.915,0-1.726-0.042-2.431-0.125c-0.707-0.082-1.309-0.331-1.808-0.748c-0.333-0.25-0.561-0.727-0.686-1.434
c-0.124-0.705-0.208-1.496-0.249-2.369c-0.043-0.872-0.043-1.764,0-2.68c0.041-0.913,0.063-1.702,0.063-2.369
c0-0.663,0.019-1.265,0.063-1.807c0.04-0.539,0.186-1.017,0.436-1.434c0.166-0.332,0.393-0.581,0.685-0.748
c0.29-0.165,0.603-0.331,0.936-0.498c0.165,0,0.374-0.02,0.623-0.063c0.249-0.041,0.456-0.063,0.623-0.063h9.101
c0.83,0,1.62,0.043,2.368,0.125C492.886,310.072,493.467,310.322,493.883,310.736z M494.756,391.89
c0,1.664-0.043,3.076-0.125,4.238c-0.083,1.165-0.831,1.954-2.243,2.369c-0.499,0.167-1.04,0.229-1.621,0.186
c-0.583-0.041-1.206-0.061-1.87-0.061h-6.98c-0.748,0-1.477-0.041-2.182-0.125c-0.707-0.082-1.228-0.331-1.559-0.749
c-0.498-0.579-0.77-1.308-0.81-2.181c-0.044-0.872-0.063-1.808-0.063-2.806v-52.605c0-0.83,0-1.661,0-2.493
c0-0.83,0.165-1.496,0.498-1.994c0.499-0.581,1.204-0.955,2.119-1.123c0.166-0.081,0.394-0.103,0.686-0.061
c0.289,0.042,0.518,0.021,0.686-0.063h6.232c0.499,0,1.06-0.02,1.683-0.063c0.624-0.041,1.142-0.02,1.559,0.063h0.997
c0.499,0.168,0.955,0.292,1.371,0.374c0.415,0.083,0.748,0.333,0.997,0.748c0.331,0.416,0.519,0.997,0.562,1.745
c0.041,0.748,0.063,1.538,0.063,2.369V391.89z"/>
<path class="st2" d="M507.471,309.864h9.1c0.914,0,1.746,0.043,2.493,0.125c0.748,0.083,1.328,0.333,1.746,0.747
c0.663,0.748,0.976,1.954,0.935,3.615c-0.043,1.663-0.063,3.2-0.063,4.612v21.068v7.604c0,0.583-0.043,1.206-0.125,1.869
c-0.084,0.667-0.042,1.29,0.125,1.871v1.122c0.165,0.416,0.29,0.853,0.374,1.308c0.082,0.459,0.331,0.771,0.748,0.936
c0.249,0.168,0.58,0.188,0.997,0.063c0.415-0.125,0.705-0.27,0.872-0.437c0.83-0.581,1.558-1.246,2.182-1.995
c0.624-0.747,1.267-1.452,1.933-2.119c0.664-0.663,1.371-1.349,2.119-2.056c0.748-0.705,1.412-1.475,1.994-2.307
c0.25-0.165,0.54-0.415,0.873-0.748c0.415-0.415,0.83-0.851,1.246-1.309c0.416-0.456,0.83-0.893,1.247-1.309l2.867-2.867
c0.166-0.332,0.393-0.603,0.685-0.811c0.29-0.207,0.562-0.478,0.811-0.811c0.664-0.83,1.391-1.559,2.182-2.182
c0.788-0.624,1.765-1.06,2.929-1.31c0.416-0.081,0.998-0.124,1.746-0.124c0.331-0.082,0.664-0.104,0.997-0.063
c0.331,0.043,0.705,0.063,1.122,0.063h4.113c0.665,0,1.475-0.041,2.432-0.124c0.954-0.082,1.764-0.041,2.431,0.124h1.371
c0.415,0.168,0.829,0.271,1.247,0.311c0.414,0.043,0.705,0.23,0.872,0.561c0.166,0.249,0.188,0.582,0.063,0.996
c-0.125,0.418-0.271,0.707-0.437,0.874c-0.498,0.831-1.122,1.558-1.87,2.181c-0.748,0.624-1.455,1.268-2.119,1.933
c-0.582,0.582-1.143,1.165-1.683,1.745c-0.541,0.582-1.144,1.121-1.808,1.621c-0.417,0.333-0.77,0.686-1.06,1.06
c-0.292,0.374-0.645,0.728-1.06,1.06c-0.417,0.248-0.791,0.582-1.122,0.996c-0.333,0.418-0.707,0.792-1.122,1.123l-4.737,4.736
c-0.582,0.499-1.102,0.979-1.558,1.434c-0.458,0.458-0.895,1.02-1.309,1.684c-0.168,0.249-0.334,0.561-0.499,0.935
c-0.168,0.374-0.168,0.769,0,1.185c0.165,0.915,0.477,1.663,0.934,2.244c0.456,0.581,0.893,1.205,1.309,1.869
c0.665,0.916,1.267,1.829,1.809,2.743c0.539,0.915,1.141,1.828,1.808,2.741l13.089,19.821c0.83,1.165,1.64,2.327,2.431,3.491
c0.789,1.164,1.516,2.327,2.182,3.489c0.249,0.418,0.394,0.916,0.435,1.497c0.041,0.582-0.146,1.04-0.56,1.371
c-0.333,0.167-0.666,0.249-0.997,0.249c-0.333,0-0.707,0.083-1.122,0.25c-0.333,0.083-0.707,0.104-1.122,0.061
c-0.416-0.041-0.831-0.061-1.246-0.061h-4.862c-1.33,0-2.91,0.021-4.736,0.061c-1.829,0.043-3.201-0.144-4.114-0.561
c-0.915-0.415-1.704-1.184-2.368-2.307c-0.666-1.121-1.289-2.139-1.87-3.055c-1.414-2.243-2.826-4.506-4.238-6.794
c-1.414-2.284-2.826-4.549-4.238-6.794c-0.667-1.079-1.31-2.159-1.933-3.24c-0.623-1.079-1.308-2.12-2.057-3.116
c-0.168-0.25-0.458-0.581-0.873-0.997c-0.417-0.415-0.872-0.54-1.371-0.374c-0.748,0.167-1.309,0.416-1.683,0.747
c-0.374,0.334-0.769,0.708-1.185,1.122c-0.666,0.498-1.289,1.081-1.869,1.745c-0.583,0.667-1.041,1.455-1.372,2.369
c-0.167,0.665-0.249,1.392-0.249,2.182c0,0.791,0,1.558,0,2.306v7.73c0,0.582,0.02,1.226,0.063,1.932
c0.041,0.707,0.063,1.434,0.063,2.182c0,0.748-0.043,1.434-0.125,2.057c-0.084,0.624-0.249,1.103-0.498,1.434
c-0.334,0.498-0.854,0.853-1.559,1.06c-0.707,0.209-1.518,0.333-2.432,0.374c-0.915,0.043-1.869,0.043-2.867,0
c-0.997-0.041-1.869-0.061-2.617-0.061c-0.915,0-1.913,0.021-2.992,0.061c-1.081,0.043-1.953-0.061-2.618-0.311
c-1.081-0.415-1.663-1.163-1.745-2.244c-0.083-1.078-0.124-2.326-0.124-3.74v-14.335v-49.989v-11.593
c0-0.914-0.021-1.869-0.063-2.867c-0.043-0.997,0.103-1.786,0.436-2.368c0.331-0.581,0.913-0.997,1.745-1.246
c0.166,0,0.353-0.02,0.561-0.063C507.116,309.886,507.303,309.864,507.471,309.864z"/>
<path class="st2" d="M628.888,365.96c0.165,0.667,0.165,1.414,0,2.245c-0.168,0.831-0.458,1.371-0.873,1.62
c-0.417,0.333-1.018,0.561-1.808,0.686c-0.79,0.125-1.663,0.209-2.618,0.25c-0.956,0.042-1.912,0.042-2.867,0
c-0.956-0.041-1.808-0.063-2.555-0.063H587.75c-0.583,0-1.144,0-1.684,0c-0.541,0-1.018,0.083-1.434,0.248
c-0.665,0.334-1.081,0.667-1.246,0.998c-0.168,0.168-0.333,0.479-0.499,0.936c-0.167,0.457-0.208,0.893-0.124,1.308
c0.165,0.499,0.268,0.978,0.312,1.435c0.041,0.458,0.144,0.935,0.311,1.434c0.664,1.994,1.475,3.637,2.431,4.924
c0.954,1.289,2.264,2.431,3.927,3.428c0.664,0.417,1.35,0.687,2.057,0.811c0.705,0.125,1.434,0.311,2.182,0.561
c0.664,0.167,1.578,0.292,2.743,0.374c1.162,0.083,2.16,0.043,2.991-0.126h1.122c0.83-0.165,1.6-0.353,2.307-0.56
c0.705-0.207,1.391-0.436,2.057-0.686c0.83-0.414,1.765-0.954,2.805-1.62c1.038-0.664,1.808-1.328,2.307-1.994
c0.414-0.581,0.851-1.142,1.309-1.684c0.456-0.539,1.017-0.935,1.683-1.184c0.83-0.415,1.89-0.603,3.18-0.561
c1.287,0.043,2.471,0.061,3.552,0.061c0.499,0,1.017-0.018,1.559-0.061c0.539-0.041,1.017,0.021,1.434,0.188h1.247
c0.829,0.167,1.412,0.374,1.745,0.622c0.331,0.168,0.518,0.542,0.561,1.123c0.041,0.582-0.021,1.081-0.187,1.496
c-0.417,1.164-0.873,2.202-1.372,3.116c-0.498,0.915-1.081,1.829-1.745,2.742c-1.829,2.743-3.907,4.945-6.232,6.607
c-2.328,1.663-5.236,3.075-8.727,4.238c-0.915,0.331-1.828,0.539-2.742,0.623c-0.916,0.082-1.87,0.249-2.867,0.499
c-0.333,0.081-0.686,0.103-1.06,0.063c-0.374-0.043-0.729-0.021-1.06,0.061h-1.371c-0.417,0.166-0.895,0.229-1.434,0.188
c-0.542-0.044-1.02-0.105-1.434-0.188c-0.666-0.083-1.247-0.083-1.746,0c-0.498,0.082-1.04,0.041-1.62-0.124
c-0.417-0.168-0.872-0.25-1.371-0.25c-0.498,0-0.956-0.083-1.371-0.249c-0.915-0.167-1.829-0.355-2.743-0.561
c-0.915-0.207-1.744-0.519-2.493-0.936c-0.915-0.331-1.767-0.642-2.556-0.934c-0.79-0.29-1.517-0.643-2.181-1.06
c-2.661-1.661-5.029-3.594-7.106-5.797c-2.078-2.201-3.782-4.757-5.11-7.666c-0.417-0.914-0.748-1.849-0.997-2.806
c-0.25-0.954-0.582-1.932-0.998-2.929c-0.083-0.331-0.124-0.644-0.124-0.936c0-0.29-0.043-0.602-0.125-0.935
c-0.333-0.997-0.541-2.076-0.623-3.241c-0.084-1.163-0.168-2.326-0.249-3.49c0-0.415-0.021-0.873-0.063-1.372
c-0.043-0.498-0.021-0.954,0.063-1.371v-1.496l0.373-2.992c0.332-1.411,0.624-2.782,0.873-4.113
c0.249-1.328,0.623-2.574,1.122-3.739c3.572-8.643,9.64-14.751,18.2-18.325c1.163-0.498,2.347-0.851,3.553-1.06
c1.204-0.206,2.472-0.478,3.802-0.81c0.665-0.081,1.288-0.124,1.87-0.124c0.581,0,1.204-0.042,1.87-0.125
c4.238-0.082,7.873,0.395,10.907,1.434c3.033,1.04,5.755,2.39,8.166,4.052c0.747,0.498,1.495,1.06,2.244,1.683
c0.747,0.623,1.412,1.268,1.994,1.933c0.249,0.416,0.58,0.748,0.997,0.997c0.664,0.915,1.288,1.851,1.87,2.804
c0.58,0.957,1.204,1.934,1.869,2.931c0.416,0.748,0.769,1.518,1.06,2.306c0.291,0.791,0.602,1.642,0.936,2.556
c0.415,1.081,0.748,2.203,0.997,3.366c0.249,1.164,0.54,2.327,0.873,3.489c0.165,0.667,0.228,1.394,0.187,2.183
c-0.043,0.791,0.019,1.518,0.188,2.182V365.96z"/>
<path class="st2" d="M652.571,380.421c0.499,0.417,0.789,0.998,0.873,1.746c0.081,0.747,0.124,1.579,0.124,2.493v8.975
c0,0.916-0.043,1.746-0.124,2.493c-0.084,0.748-0.333,1.331-0.748,1.746c-0.583,0.416-1.29,0.645-2.119,0.686
c-0.832,0.043-1.705,0.063-2.618,0.063h-8.353c-0.915,0-1.788-0.02-2.617-0.063c-0.832-0.041-1.456-0.312-1.87-0.812
c-0.417-0.498-0.666-1.141-0.748-1.932c-0.084-0.788-0.125-1.641-0.125-2.555v-7.854c0-0.829,0-1.64,0-2.431
c0-0.788,0.166-1.434,0.499-1.932c0.331-0.499,0.954-0.914,1.87-1.247c0.165-0.082,0.353-0.104,0.561-0.063
c0.207,0.043,0.393,0.021,0.562-0.062h9.848c0.997,0,1.933,0.021,2.805,0.062C651.263,379.778,651.989,380.007,652.571,380.421z
M635.244,337.788c-0.417-1.828-0.604-3.822-0.562-5.983c0.041-2.16,0.063-4.32,0.063-6.482v-9.599c0-0.914,0-1.786,0-2.618
c0-0.83,0.206-1.537,0.623-2.119c0.415-0.499,0.997-0.83,1.745-0.997c0.166-0.082,0.331-0.104,0.499-0.063
c0.165,0.043,0.331,0.021,0.499-0.063h9.599c0.997,0,1.932,0.043,2.805,0.125c0.872,0.083,1.516,0.416,1.932,0.997
c0.331,0.498,0.499,1.122,0.499,1.87c0,0.747,0,1.538,0,2.368v13.837c0,0.499,0.041,1.06,0.125,1.683
c0.081,0.624,0.041,1.144-0.125,1.559v1.371c-0.168,0.583-0.23,1.184-0.188,1.808c0.041,0.623-0.021,1.184-0.187,1.684
c-0.167,0.416-0.229,0.81-0.187,1.184c0.04,0.374-0.021,0.77-0.188,1.184c-0.167,0.749-0.249,1.478-0.249,2.183
c0,0.707-0.084,1.392-0.249,2.057c-0.084,0.333-0.125,0.644-0.125,0.935c0,0.293-0.043,0.604-0.125,0.936
c-0.167,1.081-0.292,2.203-0.374,3.365c-0.084,1.165-0.249,2.286-0.498,3.365c-0.168,0.583-0.23,1.123-0.188,1.621
c0.041,0.499-0.021,1.081-0.187,1.746c-0.333,1.495-0.521,3.053-0.561,4.674c-0.043,1.62-0.271,3.18-0.686,4.675
c-0.249,1.165-0.396,2.35-0.437,3.553c-0.043,1.206-0.478,2.101-1.309,2.68c-0.25,0.168-0.541,0.293-0.873,0.375
c-0.333,0.084-0.707,0.167-1.121,0.249h-1.746c-0.831,0-1.558-0.082-2.181-0.249c-0.624-0.166-1.102-0.456-1.434-0.873
c-0.417-0.498-0.624-1.038-0.624-1.62c0-0.581-0.083-1.204-0.249-1.87c-0.249-0.913-0.396-1.87-0.437-2.867
c-0.043-0.998-0.186-1.951-0.436-2.867c0-0.665-0.043-1.122-0.125-1.372c-0.084-0.498-0.125-0.996-0.125-1.495
c0-0.498-0.043-0.998-0.124-1.496c-0.333-1.162-0.521-2.388-0.562-3.677c-0.043-1.288-0.187-2.513-0.437-3.679
c-0.083-0.414-0.124-0.81-0.124-1.184c0-0.374-0.043-0.768-0.125-1.184c-0.168-0.748-0.271-1.538-0.311-2.369
c-0.043-0.829-0.147-1.661-0.312-2.493c0-0.165-0.021-0.331-0.063-0.498c-0.043-0.166-0.063-0.332-0.063-0.5
c-0.167-0.663-0.249-1.308-0.249-1.932C635.493,339.097,635.409,338.453,635.244,337.788z"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 33 KiB

2407
app/assets/images/logo.ai

File diff suppressed because one or more lines are too long

BIN
app/assets/images/runes.jpg

Binary file not shown.

After

Width:  |  Height:  |  Size: 59 KiB

19
app/assets/javascripts/editor.js

@ -2,7 +2,19 @@
var pens = {}; var pens = {};
Array.prototype.forEach.call(document.querySelectorAll('.textarea'), function(editor) { Array.prototype.forEach.call(document.querySelectorAll('.textarea'), function(editor) {
startEditing(editor); var event= editor.dataset.editOn;
if (event == 'load') {
startEditing(editor);
} else {
editor.addEventListener(event, function() {
if (editor.getAttribute('contenteditable') !== 'true') {
startEditing(editor);
// for content editable, we need to refocus to show the caret
editor.blur();
editor.focus();
}
});
}
}); });
function startEditing(editor) { function startEditing(editor) {
@ -27,6 +39,7 @@
'insertimage': 'Image' 'insertimage': 'Image'
} }
}); });
return pens[name];
} }
Array.prototype.forEach.call(document.querySelectorAll('form'), function(form) { Array.prototype.forEach.call(document.querySelectorAll('form'), function(form) {
@ -45,7 +58,9 @@
form.appendChild(textarea); form.appendChild(textarea);
} }
textarea.value = editor.innerHTML; textarea.value = editor.innerHTML;
pens[name].destroy(); if (pens[name]) {
pens[name].destroy();
}
}); });
}, false); }, false);
Array.prototype.forEach.call(form.querySelectorAll('button'), function(button) { Array.prototype.forEach.call(form.querySelectorAll('button'), function(button) {

82
app/assets/javascripts/housing.js

@ -0,0 +1,82 @@
(function() {
function closeOnTop() {
document.documentElement.removeAttribute('data-ontop');
document.getElementById('guest_id').value = '';
var target = document.querySelector('.on-top-target');
target.removeAttribute('style');
document.querySelector('body').removeAttribute('style');
forEachElement('.on-top-control', function(control) {
control.classList.remove('on-top-control');
});
}
forEachElement('#guests .guest', function(guest) {
var button = guest.querySelector('.set-host');
button.addEventListener('click', function(event) {
var target = document.querySelector('.on-top-target');
var body = document.querySelector('body');
// maintain our current height
body.setAttribute('style', 'height: ' + body.clientHeight + 'px');
document.documentElement.setAttribute('data-ontop', 'set-host');
guest.classList.add('on-top-control');
target.setAttribute('style', 'bottom: ' + guest.clientHeight + 'px');
document.getElementById('guest_id').value = guest.dataset.id;
});
});
forEachElement('#hosts .host', function(host) {
initHost(host);
});
function initHost(host) {
forEachElement('.place-guest', function(button) {
button.addEventListener('click', function(event) {
var guest_id = document.getElementById('guest_id').value;
if (guest_id) {
var guest = document.getElementById('guest-' + guest_id);
var form = document.getElementById('hosts');
var data = new FormData(form);
host.classList.add('requesting');
if (guest.dataset.affectedHosts) {
data.append('affected-hosts', guest.dataset.affectedHosts);
forEach(guest.dataset.affectedHosts.split(','), function(host_id) {
h = document.getElementById('host-' + host_id);
if (h) {
h.classList.add('requesting');
}
});
}
data.append('button', button.value);
var request = new XMLHttpRequest();
request.onreadystatechange = function() {
if (request.readyState == 4) {
if (request.status == 200) {
var response = JSON.parse(request.responseText);
for (var host_id in response.hosts) {
host_element = document.getElementById('host-' + host_id);
widget = response.hosts[host_id];
host_element.className = widget.class;
host_element.querySelector('.guests').innerHTML = widget.html;
initHost(host_element);
host_element.classList.remove('requesting');
}
for (var guest_id in response.affected_hosts) {
guest_element = document.getElementById('guest-' + guest_id);
if (guest_element) {
guest_element.setAttribute('data-affected-hosts', response.affected_hosts[guest_id].join(','));
}
}
}
}
}
request.open('POST', form.getAttribute('action'), true);
request.setRequestHeader('X-Requested-With', 'XMLHttpRequest');
request.send(data);
}
});
}, host);
}
forEachElement('.on-top-close', function(button) {
button.addEventListener('click', closeOnTop);
});
})();

119
app/assets/javascripts/main.js

@ -12,7 +12,10 @@
); );
return false; return false;
}; };
Array.prototype.forEach.call(document.querySelectorAll('.number-field,.email-field,.text-field'), function(field) { window.forEach = function(a, f) { Array.prototype.forEach.call(a, f) };
window.forEachElement = function(s, f, p) { forEach((p || document).querySelectorAll(s), f) };
forEachElement('.number-field,.email-field,.text-field', function(field) {
var input = field.querySelector('input'); var input = field.querySelector('input');
var positionLabel = function(input) { var positionLabel = function(input) {
field.classList[input.value ? 'remove' : 'add']('empty'); field.classList[input.value ? 'remove' : 'add']('empty');
@ -29,53 +32,74 @@
field.classList.add('focused'); field.classList.add('focused');
}); });
}); });
var body = document.querySelector('body');
var primaryContent = document.getElementById('primary-content');
var overlay = document.getElementById('content-overlay'); var overlay = document.getElementById('content-overlay');
primaryContent.addEventListener('keydown', function(event) { if (overlay) {
if (body.classList.contains('has-overlay')) { var body = document.querySelector('body');
event.stopPropagation(); var primaryContent = document.getElementById('primary-content');
return false; primaryContent.addEventListener('keydown', function(event) {
if (body.classList.contains('has-overlay')) {
event.stopPropagation();
return false;
}
});
document.addEventListener('focus', function(event) {
if (overlay.querySelector('.dlg.open') && !overlay.querySelector('.dlg.open :focus')) {
overlay.querySelector('.dlg.open').focus();
}
}, true);
function openDlg(dlg, link) {
body.setAttribute('style', 'width: ' + body.clientWidth + 'px');
dlg.querySelector('.message').innerHTML = decodeURI(link.dataset.confirmation);
dlg.querySelector('.confirm').addEventListener('click', function(event) {
event.preventDefault();
if (link.tagName == 'BUTTON') {
var form = link.parentElement
while (form && form.tagName != 'FORM') {
var form = form.parentElement
}
if (form) {
var input = document.createElement('input');
input.type = 'hidden';
input.name = 'button';
input.value = link.value;
form.appendChild(input);
form.submit();
}
} else {
window.location.href = link.getAttribute('href');
}
});
primaryContent.setAttribute('aria-hidden', 'true');
document.getElementById('overlay').onclick =
dlg.querySelector('.delete').onclick = function() { closeDlg(dlg); };
body.classList.add('has-overlay');
dlg.removeAttribute('aria-hidden');
dlg.setAttribute('role', 'alertdialog');
dlg.setAttribute('tabindex', '0');
dlg.focus();
setTimeout(function() { dlg.classList.add('open'); }, 100);
} }
}); function closeDlg(dlg) {
document.addEventListener('focus', function(event) { setTimeout(function() {
if (overlay.querySelector('.dlg.open') && !overlay.querySelector('.dlg.open :focus')) { body.classList.remove('has-overlay');
overlay.querySelector('.dlg.open').focus(); body.removeAttribute('style');
}, 250);
primaryContent.removeAttribute('aria-hidden');
dlg.setAttribute('aria-hidden', 'true');
dlg.removeAttribute('tabindex');
dlg.classList.remove('open');
dlg.removeAttribute('role');
} }
}, true); var confirmationDlg = document.getElementById('confirmation-dlg');
function openDlg(dlg, link) { forEachElement('[data-confirmation]', function(link) {
body.setAttribute('style', 'width: ' + body.clientWidth + 'px'); link.addEventListener('click', function(event) {
dlg.querySelector('.message').innerHTML = decodeURI(link.dataset.confirmation); event.preventDefault();
dlg.querySelector('.confirm').setAttribute('href', link.getAttribute('href')); openDlg(confirmationDlg, link);
primaryContent.setAttribute('aria-hidden', 'true'); return false;
document.getElementById('overlay').onclick = });
dlg.querySelector('.delete').onclick = function() { closeDlg(dlg); };
body.classList.add('has-overlay');
dlg.removeAttribute('aria-hidden');
dlg.setAttribute('role', 'alertdialog');
dlg.setAttribute('tabindex', '0');
dlg.focus();
setTimeout(function() { dlg.classList.add('open'); }, 100);
}
function closeDlg(dlg) {
setTimeout(function() {
body.classList.remove('has-overlay');
body.removeAttribute('style');
}, 250);
primaryContent.removeAttribute('aria-hidden');
dlg.setAttribute('aria-hidden', 'true');
dlg.removeAttribute('tabindex');
dlg.classList.remove('open');
dlg.removeAttribute('role');
}
var confirmationDlg = document.getElementById('confirmation-dlg');
Array.prototype.forEach.call(document.querySelectorAll('a[data-confirmation]'), function(link) {
link.addEventListener('click', function(event) {
event.preventDefault();
openDlg(confirmationDlg, link);
return false;
}); });
}); }
var errorField = document.querySelector('.input-field.has-error input, .input-field.has-error textarea'); var errorField = document.querySelector('.input-field.has-error input, .input-field.has-error textarea');
if (errorField) { if (errorField) {
@ -85,9 +109,8 @@
var htmlNode = document.documentElement; var htmlNode = document.documentElement;
document.addEventListener('keydown', function(event) { document.addEventListener('keydown', function(event) {
if (htmlNode.dataset.input != 'kb' && if (htmlNode.dataset.input != 'kb' &&
!["input", "textarea", "select", "option"].includes(event.target.nodeName.toLowerCase()) && ((!["input", "textarea", "select", "option"].includes(event.target.nodeName.toLowerCase()) &&
!event.target.attributes.contenteditable) { !event.target.attributes.contenteditable) || event.key == "Tab")) {
console.log()
htmlNode.setAttribute('data-input', 'kb'); htmlNode.setAttribute('data-input', 'kb');
} }
}); });
@ -97,7 +120,7 @@
htmlNode.setAttribute('data-input', 'mouse'); htmlNode.setAttribute('data-input', 'mouse');
} }
}); });
Array.prototype.forEach.call(document.querySelectorAll('form.js-xhr'), function(form) { forEachElement('form.js-xhr', function(form) {
if (form.addEventListener) { if (form.addEventListener) {
form.addEventListener('submit', function(event) { form.addEventListener('submit', function(event) {
event.preventDefault(); event.preventDefault();

585
app/assets/stylesheets/_application.scss

@ -23,6 +23,10 @@ h2 {
font-size: 6vw; font-size: 6vw;
} }
h3.subtitle {
font-size: 1.5em;
}
p { p {
font-size: 4vw; font-size: 4vw;
} }
@ -69,13 +73,14 @@ a {
table { table {
margin-bottom: 2em; margin-bottom: 2em;
margin-left: 1em; margin-left: 1em;
background-color: #F8F8F8; // background-color: #F8F8F8;
width: 100%; // width: 100%;
@include default-box-shadow(top, 2, true); // @include default-box-shadow(top, 2, true);
th, td { th, td {
text-align: left; text-align: left;
padding: 0.25em 0.5em; padding: 0.25em 0.5em;
border: 0.1em solid #EEE;
&:first-child { &:first-child {
padding-left: 1em; padding-left: 1em;
@ -85,6 +90,10 @@ table {
padding-right: 1em; padding-right: 1em;
} }
} }
th {
background-color: #F8F8F8;
}
} }
button, button,
@ -132,6 +141,10 @@ button,
&.facebook { &.facebook {
background-color: #3A5795; background-color: #3A5795;
} }
&.small {
font-size: 0.9em;
}
} }
a.button { a.button {
@ -214,6 +227,11 @@ textarea, .textarea {
@include _(transition, box-shadow 200ms ease-in-out); @include _(transition, box-shadow 200ms ease-in-out);
will-change: box-shadow; will-change: box-shadow;
&[data-edit-on="click"],
&[data-edit-on="focus"] {
cursor: text;
}
&:hover, &:focus, &:active { &:hover, &:focus, &:active {
@include _(box-shadow, 0 0 0 0.3em rgba(0,0,0,0.05)); @include _(box-shadow, 0 0 0 0.3em rgba(0,0,0,0.05));
} }
@ -366,6 +384,12 @@ input {
margin-right: 0; margin-right: 0;
} }
} }
&.small select,
&.small input {
font-size: 1em;
@include font-family(secondary)
}
} }
.input-field.other-field label { .input-field.other-field label {
@ -416,6 +440,8 @@ input {
.input-field-help { .input-field-help {
margin-bottom: 1em; margin-bottom: 1em;
margin-left: 1em; margin-left: 1em;
line-height: 1.3333em;
font-size: 1.25em;
} }
.check-box-field, .check-box-field,
@ -590,13 +616,13 @@ input {
} }
} }
.requesting {
opacity: 0.5;
-webkit-filter: blur(5px);
}
form { form {
@include _(transition, 'opacity 250ms ease-in-out, filter 250ms ease-in-out, -webkit-filter 250ms ease-in-out'); @include _(transition, 'opacity 250ms ease-in-out, filter 250ms ease-in-out, -webkit-filter 250ms ease-in-out');
&.requesting {
opacity: 0.5;
-webkit-filter: blur(5px);
}
&.composition { &.composition {
textarea { textarea {
@ -619,6 +645,28 @@ form {
} }
} }
#main .columns th form {
display: inline;
vertical-align: super;
margin: 0 0 0 0.5em;
button {
float: right;
}
}
#main .columns th.form {
display: none;
}
#main .columns td.form {
border: 0;
form {
margin: 0;
}
}
fieldset { fieldset {
margin: 0; margin: 0;
padding: 0; padding: 0;
@ -654,6 +702,27 @@ fieldset {
} }
} }
.flex-inputs {
@include _-(display, flex);
@include _(align-items, flex-end);
@include _(flex-wrap, wrap);
@include _(justify-content, flex-end);
margin-bottom: 2em;
.input-field {
margin: 0 0.5em;
}
.stretch-item {
@include _(flex, 1);
@include _(flex-basis, 100%);
select {
width: 100%;
}
}
}
.actions { .actions {
text-align: center; text-align: center;
margin: 0 1em; margin: 0 1em;
@ -682,6 +751,16 @@ fieldset {
} }
} }
&.fill {
@include _-(display, flex);
@include _(flex-wrap, wrap);
> button, > .button {
flex: 1;
margin-bottom: 0;
}
}
.conferences-view_workshop & { .conferences-view_workshop & {
margin-bottom: 5em; margin-bottom: 5em;
} }
@ -691,6 +770,7 @@ fieldset {
@include _(flex-wrap, wrap); @include _(flex-wrap, wrap);
@include _(flex-direction, row-reverse); @include _(flex-direction, row-reverse);
margin: 0; margin: 0;
clear: both;
button, .button { button, .button {
margin-bottom: 1em; margin-bottom: 1em;
@ -698,6 +778,27 @@ fieldset {
} }
} }
.test-preview {
padding: 0 1em;
border: 0.1em solid #CCC;
background-color: #F8F8F8;
h4 {
border-bottom: 0.1rem solid #CCC;
padding: 1em 0 0.75em;
font-size: 1.5em;
margin: 0 0 1em 0;
}
h5 {
font-size: 1.25em;
}
h6, p {
font-size: 1.125em;
}
}
ul.warnings { ul.warnings {
list-style: none; list-style: none;
padding: 0; padding: 0;
@ -871,17 +972,16 @@ ul.warnings li,
} }
} }
#registration-steps { .flow-steps {
ul { ul {
display: block; display: block;
position: relative; position: relative;
list-style: none; list-style: none;
padding: 0; padding: 0;
margin-top: -1em; margin-top: -1em;
overflow: hidden; //overflow: hidden;
text-align: center; text-align: center;
@include default-box-shadow(top, 2); @include default-box-shadow(top, 2);
@include _(border-radius, 0.15em);
@include clearfix; @include clearfix;
} }
@ -897,38 +997,16 @@ ul.warnings li,
outline: 0; outline: 0;
cursor: default; cursor: default;
@include _(text-stroke, 1px rgba(0, 0, 0, 0.25)); @include _(text-stroke, 1px rgba(0, 0, 0, 0.25));
@include after {
content: '';
position: absolute;
z-index: 1;
top: 2.25em;
left: 0;
right: 0;
width: 1.25em;
height: 1.25em;
margin: auto;
border: 0 solid;
border-width: 0.1em 0.1em 0 0;
background-color: inherit;
@include _(transform, rotate(135deg));
@include _(transition, 'transform 200ms ease-in-out, background-color 200ms ease-in-out');
@include _(box-shadow, 0.2em -0.4em 0.8em -0.4em #000);
}
&.enabled { &:last-child {
background-color: $colour-5; @include _(border-radius, 0 0 0.15em 0.15em);
}
&.current {
background-color: lighten(desaturate($colour-5, 33%), 15%);
} }
&:last-child { &.enabled {
padding-right: 1.5em; background-color: $colour-1;
@include after { &.current {
display: none; background-color: lighten(desaturate($colour-1, 33%), 15%);
} }
} }
} }
@ -946,9 +1024,285 @@ ul.warnings li,
left: 0; left: 0;
} }
@include after {
border-bottom: 0 solid rgba(0,0,0,0.25);
}
@include after {
border-bottom: 0.2em solid rgba(0,0,0,0.25);
}
}
#registration-steps {
li {
&:first-child {
@include _(border-radius, 0.15em 0.15em 0 0);
}
&:last-child {
@include _(border-radius, 0);
}
&.enabled {
background-color: $colour-5;
&.current {
background-color: lighten(desaturate($colour-5, 33%), 15%);
//text-decoration: underline;
}
}
@include after {
content: '';
position: absolute;
z-index: 1;
top: 2.25em;
left: 0;
right: 0;
width: 1.25em;
height: 1.25em;
margin: auto;
border: 0 solid;
border-width: 0.1em 0.1em 0 0;
background-color: inherit;
@include _(transform, rotate(135deg));
@include _(transition, 'transform 200ms ease-in-out, background-color 200ms ease-in-out');
@include _(box-shadow, 0.2em -0.4em 0.8em -0.4em #000);
}
}
}
}
#main article #registration-admin-menu {
margin: 1em 0 0;
padding: 0;
list-style: none;
border: 0.1em solid #EEE;
background-color: #F8F8F8;
a {
display: block;
padding: 0.5em 0.75em;
@include font-family(secondary);
border-bottom: 0.1em solid #CCC;
@include after { @include after {
display: none; display: none;
} }
&:hover {
background-color: #EEE;
}
}
li {
margin: 0;
&:last-child a {
border: 0;
}
&.current {
a {
color: $white;
background-color: $colour-5;
}
}
}
}
.admin-blocks {
@include _-(display, inline-flex);
@include _(flex-wrap, wrap);
@include _(align-items, flex-start);
@include _(justify-content, flex-start);
list-style: none;
padding: 0;
> li {
max-width: 25em;
border: 0.1rem solid #EEE;
padding: 1em;
margin: 0.25em;
@include _(flex, 1);
background-color: #F8F8F8;
@include default-box-shadow(top, 2);
}
.actions {
margin: 0 auto;
}
.title {
margin: 0 0 1em;
padding: 0 0 0.5em;
border-bottom: 0.1rem solid #EEE;
}
.details {
display: table;
width: 100%;
}
.data-set {
display: table-row;
}
.data-set-key, .data-set-value {
display: table-cell;
padding: 0.25em 0.5em;
vertical-align: top;
border-bottom: 0.1rem solid #EEE;
}
.data-set:last-child {
.data-set-key, .data-set-value {
border: 0;
}
}
.space, .address {
.data-set-key, .data-set-value {
white-space: nowrap;
}
}
.amenities {
list-style: none;
padding: 0;
> li {
font-weight: bold;
white-space: nowrap;
display: inline-block;
padding: 0 0.5em;
line-height: 1.5em;
font-size: 0.8em;
border: 0.1rem solid #CCC;
background-color: #EEE;
@include _(border-radius, 0.125rem);
}
}
}
#admin-housing {
#hosts {
background-color: $white;
ul {
list-style: none;
padding: 0;
}
.host {
padding: 0.5em;
border: 0.1em solid #EEE;
background-color: #F8F8F8;
&.status-good {
background-color: rgba($colour-5, 0.1);
}
&.status-warning {
background-color: rgba($colour-3, 0.1);
}
&.status-error {
background-color: rgba($colour-2, 0.1);
}
}
h4 {
margin: 0 0.5em 0 0;
float: left;
}
h5 {
margin: 1em 0 0;
}
.email {
color: #888;
@include before {
content: '(';
}
@include after {
content: ')';
}
}
.guests {
clear: left;
@include _-(display, flex);
}
.space {
@include _(flex, 1);
}
.place-guest {
background-color: $colour-5;
&.booked {
background-color: $colour-4;
}
&.unwanted {
background-color: #888;
}
&.overbooked {
background-color: $colour-2;
}
}
.warning, .error {
display: inline-block;
font-style: italic;
padding: 0 0.5em;
margin-left: 0.5em;
border: 0.1em solid rgba($black, 0.25);
@include _(border-radius, 0.125em);
@include _(transform, skewX(-15deg));
@include _(transform-origin, 0 100%);
@include _(animation, bend ease-in-out 500ms infinite alternate both);
}
.warning {
background-color: lighten($colour-3, 25%);
}
.error {
background-color: lighten($colour-2, 25%);
}
}
#guests {
.guests {
@include _-(display, flex);
@include _(align-items, flex-start);
@include _(flex-wrap, wrap);
list-style: none;
padding: 0;
}
.guest {
flex: 1;
margin: 0.5em;
border: 0.1rem solid #EEE;
background-color: #F8F8F8;
padding: 0.5em;
}
h4 {
margin: 0 0 0.5em;
}
.set-host {
width: 100%;
}
} }
} }
@ -1190,6 +1544,10 @@ $header-tilt: 8deg;
font-size: 1.5em; font-size: 1.5em;
} }
body.error-locale-not-available & {
background-color: $colour-5;
}
body.error-500 & { body.error-500 & {
background-position: 50% 50%; background-position: 50% 50%;
background-color: $colour-2; background-color: $colour-2;
@ -2311,7 +2669,7 @@ html[data-lingua-franca-example="html"] {
font-family: inherit; font-family: inherit;
font-size: 1.5em; font-size: 1.5em;
padding: 0 0.5em; padding: 0 0.5em;
border: 0.1em solid #333; border: 0.1rem solid #CCC;
cursor: pointer; cursor: pointer;
@include default-box-shadow(top, 1.5, false); @include default-box-shadow(top, 1.5, false);
} }
@ -2332,6 +2690,61 @@ html[data-lingua-franca-example="html"] {
} }
} }
.on-top-only, .on-top-controls {
display: none !important;
}
html[data-ontop] {
body {
overflow: hidden;
}
.on-top-target {
position: fixed;
top: 0;
right: 0;
bottom: 0;
left: 0;
padding: 1em;
margin: 0 !important;
z-index: 100;
overflow: auto;
}
.on-top-control {
position: fixed;
right: 0;
bottom: 0;
left: 0;
z-index: 101;
margin: 0 !important;
padding: 1em;
background-color: #F8F8F8;
@include default-box-shadow(bottom, 2);
}
.on-top-controls {
overflow: auto;
.on-top-close {
float: right;
background-color: $colour-4;
}
}
.on-top-only, .on-top-controls {
display: inherit !important;
&.space {
display: block !important;
}
}
.not-on-top {
display: none !important;
}
}
@include breakpoint(medium) { @include breakpoint(medium) {
:focus, :focus,
input[type="submit"]:focus, input[type="submit"]:focus,
@ -2386,10 +2799,8 @@ html[data-lingua-franca-example="html"] {
} }
} }
.number-field, .input-field {
.email-field, &.big select,
.telephone-field,
.text-field {
&.big input { &.big input {
font-size: 2em; font-size: 2em;
} }
@ -2416,6 +2827,13 @@ html[data-lingua-franca-example="html"] {
} }
} }
.flex-inputs {
.stretch-item {
@include _(flex, 1);
@include _(flex-basis, auto);
}
}
#main-nav { #main-nav {
.logo { .logo {
margin-top: 0.25em; margin-top: 0.25em;
@ -2573,32 +2991,68 @@ html[data-lingua-franca-example="html"] {
} }
} }
#registration-steps { .flow-steps {
#registration-steps {
li {
display: inline-block;
text-align: center;
float: left;
@include after {
content: '';
top: 1.125em;
left: auto;
right: -0.25em;
@include _(transform, rotate(45deg));
}
/*&.enabled:hover,
&.enabled:hover ~ li {
@include after {
@include _(transform, rotate(-135deg));
background-color: transparent;
}
}*/
&:first-child {
@include _(border-radius, 0.15em 0 0 0.15em);
}
&:last-child {
@include _(border-radius, 0);
}
}
}
#post-registration-steps {
margin-bottom: -2em;
li {
&:first-child {
@include _(border-radius, 0 0.15em 0 0);
}
&:last-child {
@include _(border-radius, 0 0 0.15em 0.15em);
}
}
}
ul { ul {
display: inline-block; display: inline-block;
text-align: left; text-align: left;
margin-top: -4em; margin-top: -4em;
vertical-align: top;
} }
li { li {
display: inline-block; text-align: center;
float: left; }
}
@include after {
content: '';
top: 1.125em;
left: auto;
right: -0.25em;
@include _(transform, rotate(45deg));
}
&.enabled:hover, #registration-admin-menu {
&.enabled:hover ~ li { a {
@include after { margin: 0;
@include _(transform, rotate(-135deg));
background-color: transparent;
}
}
} }
} }
@ -2741,6 +3195,13 @@ html[data-lingua-franca-example="html"] {
border: 0.1em solid; border: 0.1em solid;
} }
} }
.admin-blocks {
> li {
@include _(flex, none);
min-width: 12em;
}
}
} }
@include breakpoint(large) { @include breakpoint(large) {

12
app/assets/stylesheets/user-mailer.scss

@ -78,6 +78,18 @@ p, blockquote {
line-height: 1.3333em; line-height: 1.3333em;
} }
h1 {
font-size: 2.5em;
line-height: 1.25em;
padding-bottom: 1em;
}
h2 {
font-size: 1.8em;
line-height: 1.25em;
padding-bottom: 1em;
}
blockquote { blockquote {
font-style: italic; font-style: italic;
margin-bottom: 2em; margin-bottom: 2em;

39
app/controllers/application_controller.rb

@ -28,6 +28,9 @@ class ApplicationController < LinguaFrancaApplicationController
# add the translations stylesheet if translating # add the translations stylesheet if translating
@stylesheets << params[:controller] if params[:controller] == 'translations' @stylesheets << params[:controller] if params[:controller] == 'translations'
@_inline_scripts ||= []
@_inline_scripts << Rails.application.assets.find_asset('main.js').to_s
ActionMailer::Base.default_url_options = {:host => "#{request.protocol}#{request.host_with_port}"} ActionMailer::Base.default_url_options = {:host => "#{request.protocol}#{request.host_with_port}"}
if request.post? && params[:action] == 'do_confirm' if request.post? && params[:action] == 'do_confirm'
@ -161,6 +164,20 @@ class ApplicationController < LinguaFrancaApplicationController
end end
end end
def locale_not_enabled!(locale = nil)
locale_not_available!(locale)
end
def locale_not_available!(locale = nil)
# set_default_locale
params[:_original_action] = params[:action]
params[:action] = 'error-locale-not-available'
@page_title = 'page_titles.404.Locale_Not_Available'
@main_title_vars = { vars: { language: view_context.language(locale) } }
@main_title = 'error.locale_not_available.title'
render 'application/locale_not_available', status: 404
end
rescue_from StandardError do |exception| rescue_from StandardError do |exception|
# log the error # log the error
logger.info exception.to_s logger.info exception.to_s
@ -191,7 +208,7 @@ class ApplicationController < LinguaFrancaApplicationController
user = User.find_by_email(user) user = User.find_by_email(user)
# if the user doesn't exist, just show them a 403 # if the user doesn't exist, just show them a 403
do_403 unless user do_403 unless user.present?
end end
expiry ||= (Time.now + 12.hours) expiry ||= (Time.now + 12.hours)
session[:confirm_uid] = user.id session[:confirm_uid] = user.id
@ -292,10 +309,12 @@ class ApplicationController < LinguaFrancaApplicationController
translator = User.find(translator_id) translator = User.find(translator_id)
mailer = "#{object.class.table_name.singularize}_translated" mailer = "#{object.class.table_name.singularize}_translated"
object.get_translators(data, locale).each do |id, user| if object.respond_to?(:get_translators)
if user.id != current_user.id && user.id != translator_id object.get_translators(data, locale).each do |id, user|
UserMailer.send_mail mailer do if user.id != current_user.id && user.id != translator_id
{ :args => [object, data, locale, user, translator] } UserMailer.send_mail mailer do
{ :args => [object, data, locale, user, translator] }
end
end end
end end
end end
@ -304,10 +323,12 @@ class ApplicationController < LinguaFrancaApplicationController
def on_translatable_content_change(object, data) def on_translatable_content_change(object, data)
mailer = "#{object.class.table_name.singularize}_original_content_changed" mailer = "#{object.class.table_name.singularize}_original_content_changed"
object.get_translators(data).each do |id, user| if object.respond_to?(:get_translators)
if user.id != current_user.id object.get_translators(data).each do |id, user|
UserMailer.send_mail mailer do if user.id != current_user.id
{ :args => [object, data, user, current_user] } UserMailer.send_mail mailer do
{ :args => [object, data, user, current_user] }
end
end end
end end
end end

306
app/controllers/conferences_controller.rb

@ -535,6 +535,8 @@ class ConferencesController < ApplicationController
steps = registration_steps steps = registration_steps
return do_404 unless steps.present? return do_404 unless steps.present?
@register_template = :administration if params[:admin_step].present?
@errors = {} @errors = {}
@warnings = [] @warnings = []
@ -588,7 +590,7 @@ class ConferencesController < ApplicationController
floor_space: params[:floor_space], floor_space: params[:floor_space],
tent_space: params[:tent_space], tent_space: params[:tent_space],
}, },
considerations: params[:considerations].keys, considerations: (params[:considerations] || {}).keys,
availability: [ params[:first_day], params[:last_day] ], availability: [ params[:first_day], params[:last_day] ],
notes: params[:notes] notes: params[:notes]
} }
@ -623,9 +625,17 @@ class ConferencesController < ApplicationController
@register_template ||= (params[:step] || current_step).to_sym @register_template ||= (params[:step] || current_step).to_sym
return redirect_to register_path(@this_conference.slug) if if logged_in?
logged_in? && @register_template != current_step && # if we're logged in
!@registration.steps_completed.include?(@register_template.to_s) if !steps.include?(@register_template)
# and we are not viewing a valid step
return redirect_to register_path(@this_conference.slug)
elsif @register_template != current_step && !registration_complete? && !@registration.steps_completed.include?(@register_template.to_s)
# or the step hasn't been reached, registration is not yet complete, and we're not viewing the latest incomplete step
return redirect_to register_path(@this_conference.slug)
end
# then we'll redirect to the current registration step
end
# process data from the last view # process data from the last view
# case (params[:button] || '').to_sym # case (params[:button] || '').to_sym
@ -782,12 +792,281 @@ class ConferencesController < ApplicationController
@hosting_data['considerations'] ||= Array.new @hosting_data['considerations'] ||= Array.new
when :policy when :policy
@page_title = 'articles.conference_registration.headings.Policy_Agreement' @page_title = 'articles.conference_registration.headings.Policy_Agreement'
when :administration
@admin_step = params[:admin_step] || 'edit'
return do_404 unless view_context.valid_admin_steps.include?(@admin_step.to_sym)
@page_title = 'articles.conference_registration.headings.Administration'
case @admin_step.to_sym
when :housing
# do a full analysis
analyze_housing
when :locations
@locations = EventLocation.where(:conference_id => @this_conference.id)
when :events
@event = Event.new(locale: I18n.locale)
@events = Event.where(:conference_id => @this_conference.id)
@day = nil
@time = nil
@length = 1.5
end
when :done when :done
@amount = ((@registration.registration_fees_paid || 0) * 100).to_i.to_s.gsub(/^(.*)(\d\d)$/, '\1.\2') @amount = ((@registration.registration_fees_paid || 0) * 100).to_i.to_s.gsub(/^(.*)(\d\d)$/, '\1.\2')
end end
end end
def get_housing_data
@hosts = {}
@guests = {}
ConferenceRegistration.where(:conference_id => @this_conference.id).each do | registration |
if registration.can_provide_housing
@hosts[registration.id] = registration
else
@guests[registration.id] = registration
end
end
end
def analyze_housing
get_housing_data unless @hosts.present? && @guests.present?
@housing_data = {}
@hosts_affected_by_guests = {}
@hosts.each do | id, host |
@hosts[id].housing_data ||= {}
@housing_data[id] = { guests: {}, space: {} }
@hosts[id].housing_data['space'] ||= {}
@hosts[id].housing_data['space'].each do | s, size |
size = (size || 0).to_i
@housing_data[id][:guests][s.to_sym] = {}
@housing_data[id][:space][s.to_sym] = size
end
end
@guests.each do | guest_id, guest |
data = guest.housing_data || {}
@hosts_affected_by_guests[guest_id] ||= []
if data['host']
host_id = (data['host'].present? ? data['host'].to_i : nil)
host = host_id.present? ? @hosts[host_id] : nil
# make sure the host was found and that they are still accepting guests
if host.present? && host.can_provide_housing
@hosts_affected_by_guests[guest_id] << host_id
space = (data['space'] || :bed).to_sym
@housing_data[host_id] ||= {}
host_data = host.housing_data
unless @housing_data[host_id][:guests][space].present?
@housing_data[host_id][:guests][space] ||= {}
@housing_data[host_id][:space][space] ||= 0
end
@housing_data[host_id][:guests][space][guest_id] = { guest: guest }
# make sure the host isn't overbooked
space_available = ((host_data['space'] || {})[space.to_s] || 0).to_i
if @housing_data[host_id][:guests][space].size > space_available
@housing_data[host_id][:warnings] ||= {}
@housing_data[host_id][:warnings][:space] ||= {}
@housing_data[host_id][:warnings][:space][space] ||= []
@housing_data[host_id][:warnings][:space][space] << :overbooked
end
companions = data['companions'] || []
companions.each do | companion |
user = User.find_by_email(companion)
if user.present?
reg = ConferenceRegistration.find_by(
:user_id => user.id,
:conference_id => @this_conference.id
)
housing_data = reg.housing_data || {}
companion_host = housing_data['host'].present? ? housing_data['host'].to_i : nil
if companion_host.blank?
@hosts_affected_by_guests[guest_id] << companion_host
if companion_host != host_id
# set this as an error if the guest has selected only one other to stay with, but if they have requested to stay with more, make this only a warning
status = companions.size > 1 ? :warnings : :errors
@housing_data[host_id][:guests][guest][status] ||= {}
@housing_data[host_id][:guests][guest][status][:companions] ||= []
@housing_data[host_id][:guests][guest][status][:companions] << reg.id
end
end
end
end
else
# make sure the housing data is empty if the host wasn't found, just in case something happened to the host
@guests[guest_id].housing_data ||= {}
@guests[guest_id].housing_data['host'] = nil
@guests[guest_id].housing_data['space'] = nil
end
end
end
return @hosts_affected_by_guests
end
def admin_update
set_conference
set_conference_registration
return do_403 unless @this_conference.host? current_user
# set the page title in case we render instead of redirecting
@page_title = 'articles.conference_registration.headings.Administration'
@register_template = :administration
@admin_step = params[:admin_step]
case params[:admin_step]
when 'edit'
@this_conference.info = LinguaFranca::ActiveRecord::UntranslatedValue.new(params[:info]) unless @this_conference.info! == params[:info]
params[:info_translations].each do | locale, value |
@this_conference.set_column_for_locale(:info, locale, value, current_user.id) unless value = @this_conference._info(locale)
end
@this_conference.save
return redirect_to register_step_path(@this_conference.slug, :administration)
when 'housing'
space = params[:button].split(':')[0]
host_id = params[:button].split(':')[1].to_i
guest_id = params[:guest_id].to_i
get_housing_data
# modify the guest data
@guests[guest_id].housing_data ||= {}
@guests[guest_id].housing_data['space'] = space
@guests[guest_id].housing_data['host'] = host_id
@guests[guest_id].save!
if request.xhr?
analyze_housing
# get the hosts that need updating
affected_hosts = {}
affected_hosts[host_id] = @hosts[host_id]
if params['affected-hosts'].present?
params['affected-hosts'].split(',').each do | id |
affected_hosts[id.to_i] = @hosts[id.to_i]
end
end
@hosts_affected_by_guests[guest_id].each do | id |
affected_hosts[id] ||= @hosts[id]
end
json = { hosts: {}, affected_hosts: @hosts_affected_by_guests }
puts @hosts_affected_by_guests[guest_id].to_json.to_s
affected_hosts.each do | id, host |
json[:hosts][id] = view_context.host_guests_widget(host)
end
return render json: json
end
return redirect_to administration_step_path(@this_conference.slug, :housing)
when 'broadcast'
@subject = params[:subject]
@body = params[:body]
@register_template = :administration
if params[:button] == 'send'
return redirect_to administration_step_path(@this_conference.slug, :broadcast_sent)
elsif params[:button] == 'preview'
@broadcast_step = :preview
elsif params[:button] == 'test'
@broadcast_step = :test
UserMailer.broadcast(
"#{request.protocol}#{request.host_with_port}",
@subject,
@body,
current_user,
@this_conference).deliver_now
end
return render 'conferences/register'
when 'locations'
case params[:button]
when 'edit'
@location = EventLocation.find_by! id: params[:id].to_i, conference_id: @this_conference.id
return render 'conferences/register'
when 'save'
location = EventLocation.find_by! id: params[:id].to_i, conference_id: @this_conference.id
location.title = params[:title]
location.address = params[:address]
location.amenities = (params[:needs] || {}).keys.to_json
location.space = params[:space]
location.save!
return redirect_to administration_step_path(@this_conference.slug, :locations)
when 'cancel'
return redirect_to administration_step_path(@this_conference.slug, :locations)
when 'delete'
location = EventLocation.find_by! id: params[:id].to_i, conference_id: @this_conference.id
location.destroy
return redirect_to administration_step_path(@this_conference.slug, :locations)
when 'create'
EventLocation.create(
conference_id: @this_conference.id,
title: params[:title],
address: params[:address],
amenities: (params[:needs] || {}).keys.to_json,
space: params[:space]
)
return redirect_to administration_step_path(@this_conference.slug, :locations)
end
when 'meals'
case params[:button]
when 'add_meal'
@this_conference.meals ||= {}
@this_conference.meals[(Date.parse(params[:day]) + params[:time].to_f.hours).to_time.to_i] = {
title: params[:title],
info: params[:info],
location: params[:event_location],
day: params[:day],
time: params[:time]
}
@this_conference.save!
return redirect_to administration_step_path(@this_conference.slug, :meals)
when 'delete'
@this_conference.meals ||= {}
@this_conference.meals.delete params[:meal]
@this_conference.save!
return redirect_to administration_step_path(@this_conference.slug, :meals)
end
when 'events'
case params[:button]
when 'edit'
@event = Event.find_by!(conference_id: @this_conference.id, id: params[:id])
@day = @event.start_time.midnight
@time = view_context.hour_span(@day, @event.start_time)
@length = view_context.hour_span(@event.start_time, @event.end_time)
return render 'conferences/register'
when 'save'
if params[:id].present?
event = Event.find_by!(conference_id: @this_conference.id, id: params[:id])
else
event = Event.new(conference_id: @this_conference.id, locale: I18n.locale)
end
# save title and info
event.title = LinguaFranca::ActiveRecord::UntranslatedValue.new(params[:title]) unless event.title! == params[:title]
event.info = LinguaFranca::ActiveRecord::UntranslatedValue.new(params[:info]) unless event.info! == params[:info]
# save schedule data
event.event_location_id = params[:event_location]
event.start_time = Date.parse(params[:day]) + params[:time].to_f.hours
event.end_time = event.start_time + params[:time_span].to_f.hours
# save translations
(params[:info_translations] || {}).each do | locale, value |
event.set_column_for_locale(:title, locale, value, current_user.id) unless value = event._title(locale)
event.set_column_for_locale(:info, locale, value, current_user.id) unless value = event._info(locale)
end
event.save
return redirect_to administration_step_path(@this_conference.slug, :events)
end
end
do_404
end
def registrations def registrations
registrations = ConferenceRegistration.where(:conference_id => @conference.id) registrations = ConferenceRegistration.where(:conference_id => @conference.id)
@registrations = registrations @registrations = registrations
@ -1219,7 +1498,7 @@ class ConferencesController < ApplicationController
set_conference set_conference
return do_404 unless @this_conference.workshop_schedule_published || @this_conference.host?(current_user) return do_404 unless @this_conference.workshop_schedule_published || @this_conference.host?(current_user)
@events = Event.where(:conference_id => @this_conference.id) @events = Event.where(:conference_id => @this_conference.id).order(start_time: :asc)
@locations = EventLocation.where(:conference_id => @this_conference.id) @locations = EventLocation.where(:conference_id => @this_conference.id)
render 'schedule/show' render 'schedule/show'
@ -1491,10 +1770,21 @@ class ConferencesController < ApplicationController
status = conference.registration_status status = conference.registration_status
return [] unless status == :pre || status == :open return [] unless status == :pre || status == :open
steps = [:policy, :contact_info, :questions, :hosting, :payment, :workshops] steps = [
:policy,
:contact_info,
:questions,
:hosting,
:payment,
:workshops,
:administration
]
steps -= [:questions, :payment] unless status == :open steps -= [:questions, :payment] unless status == :open
steps -= [:hosting] unless @registration.present? && view_context.same_city?(@registration.city, @conference.location) steps -= [:hosting] unless @registration.present? && view_context.same_city?(@registration.city, @conference.location)
steps -= [:administration] unless @registration.present? && @conference.host?(current_user)
return steps return steps
end end
@ -1507,6 +1797,7 @@ class ConferencesController < ApplicationController
def registration_complete?(registration = @registration) def registration_complete?(registration = @registration)
completed_steps = registration.steps_completed || [] completed_steps = registration.steps_completed || []
required_steps(registration.conference).each do | step | required_steps(registration.conference).each do | step |
return true if step == :workshops
return false unless completed_steps.include?(step.to_s) return false unless completed_steps.include?(step.to_s)
end end
return true return true
@ -1519,9 +1810,10 @@ class ConferencesController < ApplicationController
current_steps = [] current_steps = []
disable_steps = false disable_steps = false
completed_steps = registration.steps_completed || [] completed_steps = registration.steps_completed || []
registration_complete = registration_complete?(registration)
steps.each do | step | steps.each do | step |
# disable the step if we've already found an incomplete step # disable the step if we've already found an incomplete step
enabled = !disable_steps enabled = !disable_steps || registration_complete
# record whether or not we've found an incomplete step # record whether or not we've found an incomplete step
disable_steps ||= !completed_steps.include?(step.to_s) disable_steps ||= !completed_steps.include?(step.to_s)

273
app/helpers/application_helper.rb

@ -100,7 +100,7 @@ module ApplicationHelper
def add_stylesheet(sheet) def add_stylesheet(sheet)
@stylesheets ||= [] @stylesheets ||= []
@stylesheets << sheet @stylesheets << sheet unless @stylesheets.include?(sheet)
end end
def stylesheets def stylesheets
@ -119,7 +119,8 @@ module ApplicationHelper
def add_inline_script(script) def add_inline_script(script)
@_inline_scripts ||= [] @_inline_scripts ||= []
@_inline_scripts << Rails.application.assets.find_asset("#{script.to_s}.js").to_s script = Rails.application.assets.find_asset("#{script.to_s}.js").to_s
@_inline_scripts << script unless @_inline_scripts.include?(script)
end end
def inline_scripts def inline_scripts
@ -644,8 +645,22 @@ module ApplicationHelper
link_to "<span class=\"title\">#{title}</span>".html_safe, link, :class => classes link_to "<span class=\"title\">#{title}</span>".html_safe, link, :class => classes
end end
def language(locale, original_language = false)
_("languages.#{locale}", locale: original_language ? locale : nil)
end
def date(date, format = :long) def date(date, format = :long)
I18n.l(date, :format => format) # default, long, short I18n.l(date.is_a?(String) ? Date.parse(date) : date, :format => format)
end
def time(time, format = :short)
if time.is_a?(String)
time = Date.parse(time)
elsif time.is_a?(Float) || time.is_a?(Integer)
time = DateTime.now.midnight + time.hours
end
I18n.l(time, :format => format)
end end
def date_span(date1, date2) def date_span(date1, date2)
@ -660,6 +675,22 @@ module ApplicationHelper
_('date.date_span', vars: {:date_1 => d1, :date_2 => d2}) _('date.date_span', vars: {:date_1 => d1, :date_2 => d2})
end end
def time_length(length)
hours = length.to_i
minutes = ((length - hours) * 60).to_i
hours = hours > 0 ? (I18n.t 'datetime.distance_in_words.x_hours', count: hours) : nil
minutes = minutes > 0 ? (I18n.t 'datetime.distance_in_words.x_minutes', count: minutes) : nil
return hours.present? ? (minutes.present? ? (I18n.t 'datetime.distance_in_words.x_and_y', x: hours, y: minutes) : hours) : minutes
end
def hour_span(time1, time2)
(time2 - time1) / 3600
end
def hours(time1, time2)
time_length hour_span(time1, time2)
end
def generate_confirmation(user, url, expiry = nil) def generate_confirmation(user, url, expiry = nil)
ApplicationController::generate_confirmation(user, url, expiry) ApplicationController::generate_confirmation(user, url, expiry)
end end
@ -674,7 +705,18 @@ module ApplicationHelper
_!((p * 10000).to_i.to_s.gsub(/^(.*)(\d\d)$/, '\1.\2%')) _!((p * 10000).to_i.to_s.gsub(/^(.*)(\d\d)$/, '\1.\2%'))
end end
def conference_housing_options(conference = nil) def data_set(header_type, header_key, attributes = {}, &block)
attributes[:class] = attributes[:class].split(' ') if attributes[:class].is_a?(String)
attributes[:class] = [attributes[:class].to_s] if attributes[:class].is_a?(Symbol)
attributes[:class] ||= []
attributes[:class] << 'data-set'
content_tag(:div, attributes) do
content_tag(header_type, _(header_key), class: 'data-set-key') +
content_tag(:div, class: 'data-set-value', &block)
end
end
def conference_days_options(conference = nil)
conference ||= @this_conference || @conference conference ||= @this_conference || @conference
return [] unless conference return [] unless conference
@ -690,22 +732,135 @@ module ApplicationHelper
return dates return dates
end end
def conference_housing_options_list(period, conference = nil) def conference_days_options_list(period, conference = nil, format = nil)
conference ||= @this_conference || @conference conference ||= @this_conference || @conference
return [] unless conference return [] unless conference
days = [] days = []
conference_housing_options(conference).each do |day| conference_days_options(conference).each do |day|
belongs_to_periods = [] belongs_to_periods = []
belongs_to_periods << :before if day <= conference.start_date belongs_to_periods << :before if day <= conference.start_date
belongs_to_periods << :after if day >= conference.end_date belongs_to_periods << :after if day >= conference.end_date
belongs_to_periods << :during if day >= conference.start_date && day <= conference.end_date belongs_to_periods << :during if day >= conference.start_date && day <= conference.end_date
days << [date(day.to_date, :span_same_year_date_1), day] if belongs_to_periods.include?(period) days << [date(day.to_date, format || :span_same_year_date_1), day] if belongs_to_periods.include?(period)
end end
return days return days
end end
def day_select(value = nil, args = {})
selectfield :day, value, conference_days_options_list(:during, nil, args[:format]), args
end
def time_select(value = nil, args = {}, start_time = 8, end_time = 23.5, step = 0.5)
time = start_time
times = []
while time <= end_time
times << [time(DateTime.now.midnight + time.hours), time]
time += step
end
selectfield :time, value, times, args
end
def length_select(value = nil, args = {}, min_length = 0.5, max_length = 6, step = 0.5)
length = min_length
lengths = []
while length <= max_length
lengths << [time_length(length), length]
length += step
end
selectfield :time_span, value, lengths, args
end
def location_select(value = nil, args = {})
locations = []
if @this_conference.event_locations.present?
@this_conference.event_locations.each do | location |
locations << [ location.title, location.id ]
end
end
selectfield :event_location, value, locations, args
end
def location_name(id)
location = EventLocation.find(id)
return '' unless location.present?
return location.title
end
def host_options_list(hosts)
options = [[nil, nil]]
hosts.each do | id, registration |
options << [registration.user.name, id]
end
return options
end
def registration_step_menu
steps = current_registration_steps(@registration)
return '' unless steps.present?
pre_registration_steps = ''
post_registration_steps = ''
post_registration = false
steps.each do | step |
text = _"articles.conference_registration.headings.#{step[:name].to_s}"
h = content_tag :li, class: [step[:enabled] ? :enabled : nil, @register_template == step[:name] ? :current : nil] do
if step[:enabled]
content_tag :div, (link_to text, register_step_path(@this_conference.slug, step[:name])).html_safe, class: :step
else
content_tag :div, text, class: :step
end
end
if step[:name] == :workshops
post_registration = true
end
if post_registration
post_registration_steps += h.html_safe
else
pre_registration_steps += h.html_safe
end
end
html = (
row class: 'flow-steps' do
columns do
(content_tag :ul, id: 'registration-steps' do
pre_registration_steps.html_safe
end).html_safe +
(content_tag :ul, id: 'post-registration-steps' do
post_registration_steps.html_safe
end).html_safe
end
end
)
return html.html_safe
end
def admin_steps
[:edit, :stats, :broadcast, :housing, :locations, :meals, :events, :schedule]
end
def valid_admin_steps
admin_steps + [:broadcast_sent]
end
def admin_menu
steps = ''
admin_steps.each do | step |
steps += content_tag(:li, class: (step.to_s == @admin_step ? :current : nil)) do
link_to _("menu.submenu.admin.#{step.to_s.titlecase}"), step == :edit ?
register_step_path(@this_conference.slug, :administration) :
administration_step_path(@this_conference.slug, step.to_s)
end
end
content_tag :ul, steps.html_safe, id: 'registration-admin-menu'
end
def interest_button(workshop) def interest_button(workshop)
interested = workshop.interested?(current_user) ? :remove_interest : :show_interest interested = workshop.interested?(current_user) ? :remove_interest : :show_interest
id = "#{interested.to_s.gsub('_', '-')}-#{workshop.id}" id = "#{interested.to_s.gsub('_', '-')}-#{workshop.id}"
@ -713,6 +868,36 @@ module ApplicationHelper
(button_tag interested, :value => :toggle_interest, :class => (workshop.interested?(current_user) ? :delete : :add), aria: { labelledby: id }) (button_tag interested, :value => :toggle_interest, :class => (workshop.interested?(current_user) ? :delete : :add), aria: { labelledby: id })
end end
def host_guests_widget(registration)
html = ''
classes = ['host']
id = registration.id
@housing_data[id][:guests].each do | area, guests |
max_space = @housing_data[id][:space][area] || 0
area_name = (_"forms.labels.generic.#{area}")
status_html = ''
if @housing_data[id][:warnings].present? && @housing_data[id][:warnings][:space].present? && @housing_data[id][:warnings][:space][area].present?
@housing_data[id][:warnings][:space][area].each do | w |
status_html += content_tag(:div, _("warnings.housing.space.#{w.to_s}"), class: 'warning')
end
end
space_html = content_tag(:h5, area_name + _!(" (#{guests.size.to_s}/#{max_space.to_s})") + status_html.html_safe)
guest_items = ''
guests.each do | guest_id, guest |
guest_items += content_tag(:li, guest[:guest].user.name, id: "hosted-guest-#{guest_id}")
end
space_html += content_tag(:ul, guest_items.html_safe)
space_html += button_tag :place_guest, type: :button, value: "#{area}:#{id}", class: [:small, 'place-guest', 'on-top-only', guests.size >= max_space ? (guests.size > max_space ? :overbooked : :booked) : nil, max_space > 0 ? nil : :unwanted]
html += content_tag(:div, space_html, class: [:space, area, max_space > 0 || guests.size > 0 ? nil : 'on-top-only'])
end
classes << 'status-warning' if @housing_data[id][:warnings].present?
classes << 'status-error' if @housing_data[id][:errors].present?
return { html: html.html_safe, class: classes.join(' ') }
end
def link_with_confirmation(link_text, confirmation_text, path, args = {}) def link_with_confirmation(link_text, confirmation_text, path, args = {})
@confirmation_dlg ||= true @confirmation_dlg ||= true
args[:data] ||= {} args[:data] ||= {}
@ -720,6 +905,13 @@ module ApplicationHelper
link_to link_text, path, args link_to link_text, path, args
end end
def button_with_confirmation(button_name, confirmation_text, args = {})
@confirmation_dlg ||= true
args[:data] ||= {}
args[:data][:confirmation] = CGI::escapeHTML(confirmation_text)
button_tag button_name, args
end
def richtext(text, reduce_headings = 2) def richtext(text, reduce_headings = 2)
return '' unless text.present? return '' unless text.present?
return _!(text). return _!(text).
@ -731,31 +923,45 @@ module ApplicationHelper
end end
def textarea(name, value, options = {}) def textarea(name, value, options = {})
label_id = "#{name.to_s}-label" id = name.to_s.gsub('[', '_').gsub(']', '')
label_id = "#{id}-label"
description_id = nil description_id = nil
html = label_tag(name, nil, id: label_id)
if options[:label].present?
html = label_tag(id, nil, id: label_id) do
_(options[:label], :t, vars: options[:vars] || {})
end
else
html = label_tag(id, nil, id: label_id)
end
if options[:help].present? if options[:help].present?
description_id ||= "#{name.to_s}-desc" description_id ||= "#{id}-desc"
html += content_tag(:div, _(options[:help], :s, 2), id: description_id, class: 'input-field-help') html += content_tag(:div, _(options[:help], :s, 2), id: description_id, class: 'input-field-help')
end end
if options[:warning].present? if options[:warning].present?
description_id ||= "#{name.to_s}-desc" description_id ||= "#{id}-desc"
html += content_tag(:div, _(options[:warning], :s, 2), id: description_id, class: 'warning-info') html += content_tag(:div, _(options[:warning], :s, 2), id: description_id, class: 'warning-info')
end end
html += content_tag(:div, value.present? ? value.html_safe : '', html += content_tag(:div, value.present? ? value.html_safe : '',
id: name, id: id,
class: 'textarea', class: 'textarea',
data: { name: name }, data: { name: name, 'edit-on': options[:edit_on] || :load },
lang: options[:lang], lang: options[:lang],
aria: { labeledby: label_id, describedby: description_id } aria: { labeledby: label_id, describedby: description_id },
tabindex: 0
) )
html = content_tag(:div, html, class: ['text-area-field', 'input-field']).html_safe html = content_tag(:div, html, class: ['text-area-field', 'input-field']).html_safe
html += _original_content(options[:original_value], options[:original_lang]) if options[:original_value].present? html += _original_content(options[:original_value], options[:original_lang]) if options[:original_value].present?
add_stylesheet :editor
add_inline_script :pen
add_inline_script :markdown
add_inline_script :editor
return html.html_safe return html.html_safe
end end
@ -766,7 +972,7 @@ module ApplicationHelper
if options[:heading].present? if options[:heading].present?
label_id ||= "#{name.to_s}-label" label_id ||= "#{name.to_s}-label"
html += content_tag(:h3, _(options[:heading], :t), id: label_id) html += content_tag(:h3, _(options[:heading], :t, vars: options[:vars] || {}), id: label_id)
end end
if options[:help].present? if options[:help].present?
@ -797,27 +1003,50 @@ module ApplicationHelper
def textfield(name, value, options = {}) def textfield(name, value, options = {})
html = '' html = ''
id = name.to_s.gsub('[', '_').gsub(']', '')
description_id = nil description_id = nil
if options[:heading].present? if options[:heading].present?
description_id ||= "#{name.to_s}-desc" description_id ||= "#{id.to_s}-desc"
html += content_tag(:h3, _(options[:heading], :t), id: description_id) html += content_tag(:h3, _(options[:heading], :t, vars: options[:vars] || {}), id: description_id)
end end
if options[:help].present? if options[:help].present?
description_id ||= "#{name.to_s}-desc" description_id ||= "#{id.to_s}-desc"
html += content_tag(:div, _(options[:help], :s, 2), class: 'input-field-help', id: description_id) html += content_tag(:div, _(options[:help], :s, 2, vars: options[:vars] || {}), class: 'input-field-help', id: description_id)
end end
html += show_errors name, value html += show_errors name, value
html += label_tag name
if options[:label].present?
html += label_tag(id) do
_(options[:label], :t, vars: options[:vars] || {})
end
elsif options[:label] != false
html += label_tag id
end
input_options = { input_options = {
id: id,
required: options[:required], required: options[:required],
lang: options[:lang], lang: options[:lang],
min: options[:min], min: options[:min],
max: options[:max], max: options[:max],
aria: { describedby: description_id } aria: description_id ? { describedby: description_id } : nil
} }
case name
when :address
input_options[:autocomplete] = 'address-line1'
when :name
input_options[:autocomplete] = 'name'
when :location
input_options[:autocomplete] = 'address-level2'
when :email
input_options[:autocomplete] = 'email'
when :phone
input_options[:autocomplete] = 'tel'
end
case options[:type] case options[:type]
when :select when :select
html += select_tag(name, options_for_select(options[:options], value), input_options) html += select_tag(name, options_for_select(options[:options], value), input_options)
@ -830,6 +1059,8 @@ module ApplicationHelper
"#{(options[:type] || :text).to_s}-field", "#{(options[:type] || :text).to_s}-field",
'input-field', 'input-field',
options[:big] ? 'big' : nil, options[:big] ? 'big' : nil,
options[:small] ? 'small' : nil,
options[:stretch] ? 'stretch-item' : nil,
(@errors || {})[name].present? ? 'has-error' : nil (@errors || {})[name].present? ? 'has-error' : nil
]) ])

2
app/models/conference.rb

@ -8,6 +8,7 @@ class Conference < ActiveRecord::Base
has_many :conference_host_organizations, :dependent => :destroy has_many :conference_host_organizations, :dependent => :destroy
has_many :organizations, :through => :conference_host_organizations has_many :organizations, :through => :conference_host_organizations
has_many :event_locations
#has_many :conference_registration_form_fields, :order => 'position ASC', :dependent => :destroy#, :class_name => '::ConferenceRegistrationFormField' #has_many :conference_registration_form_fields, :order => 'position ASC', :dependent => :destroy#, :class_name => '::ConferenceRegistrationFormField'
#has_many :registration_form_fields, :through => :conference_registration_form_fields #has_many :registration_form_fields, :through => :conference_registration_form_fields
@ -21,6 +22,7 @@ class Conference < ActiveRecord::Base
end end
def host?(user) def host?(user)
return false unless user.present?
organizations.each do |o| organizations.each do |o|
return true if o.host?(user) return true if o.host?(user)
end end

3
app/models/event.rb

@ -1,5 +1,8 @@
class Event < ActiveRecord::Base class Event < ActiveRecord::Base
translates :info, :title
belongs_to :conference belongs_to :conference
belongs_to :event_location
def conference_day def conference_day
return nil unless start_time.present? && end_time.present? return nil unless start_time.present? && end_time.present?

23
app/models/event_location.rb

@ -1,2 +1,25 @@
require 'geocoder'
require 'geocoder/railtie'
Geocoder::Railtie.insert
class EventLocation < ActiveRecord::Base class EventLocation < ActiveRecord::Base
belongs_to :conference
geocoded_by :full_address
reverse_geocoded_by :latitude, :longitude, :address => :full_address
after_validation :geocode, if: ->(obj){ obj.address_changed? }
def full_address
l = conference.location
[address, l.city, l.territory, l.country].join(', ')
end
def self.all_spaces
Workshop.all_spaces + [:event_space]
end
def self.all_amenities
Workshop.all_needs
end
end end

13
app/models/user.rb

@ -3,17 +3,8 @@ class User < ActiveRecord::Base
config.authentications_class = Authentication config.authentications_class = Authentication
end end
#validates :password, presence: true, confirmation: true, length: { minimum: 3 }, unless: ("id?" || "password_confirmation?")
#validates :password_confirmation, presence: true, unless: ("id?" || "password?")
validates :email, uniqueness: true validates :email, uniqueness: true
#validates_presence_of :avatar
#validates_integrity_of :avatar
#validates_processing_of :avatar
#has_secure_password validations: false
mount_uploader :avatar, AvatarUploader mount_uploader :avatar, AvatarUploader
has_many :user_organization_relationships has_many :user_organization_relationships
@ -21,6 +12,10 @@ class User < ActiveRecord::Base
has_many :authentications, :dependent => :destroy has_many :authentications, :dependent => :destroy
accepts_nested_attributes_for :authentications accepts_nested_attributes_for :authentications
before_save do |user|
user.locale = I18n.locale
end
def can_translate?(to_locale = nil, from_locale = nil) def can_translate?(to_locale = nil, from_locale = nil)
is_translator unless to_locale.present? is_translator unless to_locale.present?

8
app/models/workshop.rb

@ -115,6 +115,14 @@ class Workshop < ActiveRecord::Base
[:race_gender, :mechanics, :funding, :organization, :community] [:race_gender, :mechanics, :funding, :organization, :community]
end end
def self.all_spaces
[:meeting_room, :workshop, :outdoor_meeting]
end
def self.all_needs
[:sound, :projector, :tools]
end
def get_translators(data, loc = nil) def get_translators(data, loc = nil)
notify_list = {} notify_list = {}
active_facilitators.each do |facilitator| active_facilitators.each do |facilitator|

2
app/views/application/_header.html.haml

@ -15,4 +15,4 @@
=@page_title.present? ? I18n.t(@page_title, @page_title_vars) : I18n.t("page_titles.#{page_group.to_s}.#{page_key.to_s}") =@page_title.present? ? I18n.t(@page_title, @page_title_vars) : I18n.t("page_titles.#{page_group.to_s}.#{page_key.to_s}")
= row do = row do
= columns do = columns do
%h1=_(@main_title || "page_titles.#{page_group.to_s}.#{page_key.to_s}") %h1=_(@main_title || "page_titles.#{page_group.to_s}.#{page_key.to_s}", :t, @main_title_vars)

4
app/views/application/locale_not_available.html.haml

@ -0,0 +1,4 @@
= render :partial => 'application/header', :locals => {:image_file => 'runes.jpg'}
= row do
= columns(medium: 12) do
= paragraph(_'error.locale_not_available.description', :p, @main_title_vars)

7
app/views/conferences/_administration.html.haml

@ -0,0 +1,7 @@
= columns(medium: 12) do
%h2=_(@page_title)
= columns(medium: 3, large: 2) do
= admin_menu
= columns(medium: 9, large: 10) do
%h3.subtitle=_("menu.submenu.admin.#{@admin_step.titlecase}")
%div{id: "admin-#{@admin_step}"}= render "conferences/admin/#{@admin_step}"

2
app/views/conferences/_contact_info.html.haml

@ -5,7 +5,7 @@
= form_tag register_path(@this_conference.slug) do = form_tag register_path(@this_conference.slug) do
= textfield :name, @name, required: true, heading: 'articles.conference_registration.headings.name', big: true = textfield :name, @name, required: true, heading: 'articles.conference_registration.headings.name', big: true
= textfield :location, (params[:location] || @registration.city || location(lookup_ip_location)), required: true, heading: 'articles.conference_registration.headings.location' = textfield :location, (params[:location] || @registration.city || location(lookup_ip_location)), required: true, heading: 'articles.conference_registration.headings.location'
= checkboxes :languages, [:en, :es, :fr], current_user.languages, 'languages', heading: 'articles.conference_registration.headings.languages' = checkboxes :languages, [:en, :es, :fr], current_user.languages || [I18n.locale], 'languages', heading: 'articles.conference_registration.headings.languages'
.actions.next-prev .actions.next-prev
= button_tag (params[:step] == :save ? :save : :next), value: :contact_info = button_tag (params[:step] == :save ? :save : :next), value: :contact_info
= button_tag :previous, value: :prev_contact_info, class: :subdued, formnovalidate: true = button_tag :previous, value: :prev_contact_info, class: :subdued, formnovalidate: true

11
app/views/conferences/_hosting.html.haml

@ -1,8 +1,3 @@
- add_stylesheet :editor
- add_inline_script :pen
- add_inline_script :markdown
- add_inline_script :editor
= columns(medium: 12) do = columns(medium: 12) do
%h2=_(@page_title) %h2=_(@page_title)
= columns(medium: 12) do = columns(medium: 12) do
@ -15,10 +10,10 @@
- [:bed_space, :floor_space, :tent_space].each do | space | - [:bed_space, :floor_space, :tent_space].each do | space |
= numberfield space, @hosting_data['space'][space.to_s] || 0, min: 0, required: true = numberfield space, @hosting_data['space'][space.to_s] || 0, min: 0, required: true
= fieldset :hosting_dates, heading: 'articles.conference_registration.headings.host.availability', help: 'articles.conference_registration.paragraphs.host.availability' do = fieldset :hosting_dates, heading: 'articles.conference_registration.headings.host.availability', help: 'articles.conference_registration.paragraphs.host.availability' do
= selectfield :first_day, @hosting_data['availability'][0] || @this_conference.start_date, conference_housing_options_list(:before) = selectfield :first_day, @hosting_data['availability'][0] || @this_conference.start_date, conference_days_options_list(:before)
= selectfield :last_day, @hosting_data['availability'][1] || @this_conference.start_date, conference_housing_options_list(:after) = selectfield :last_day, @hosting_data['availability'][1] || @this_conference.start_date, conference_days_options_list(:after)
= checkboxes :considerations, [:vegan, :smoking, :pets, :quiet], @hosting_data['considerations'], 'articles.conference_registration.host.considerations', heading: 'articles.conference_registration.headings.host.considerations', help: 'articles.conference_registration.paragraphs.host.considerations', vertical: true = checkboxes :considerations, [:vegan, :smoking, :pets, :quiet], @hosting_data['considerations'], 'articles.conference_registration.host.considerations', heading: 'articles.conference_registration.headings.host.considerations', help: 'articles.conference_registration.paragraphs.host.considerations', vertical: true
= textarea :notes, @hosting_data['notes'], heading: 'articles.conference_registration.headings.host.notes', help: 'articles.conference_registration.paragraphs.host.notes' = textarea :notes, @hosting_data['notes'], heading: 'articles.conference_registration.headings.host.notes', help: 'articles.conference_registration.paragraphs.host.notes', edit_on: :focus
.actions.next-prev .actions.next-prev
= button_tag (params[:step] == :save ? :save : :next), value: :hosting = button_tag (params[:step] == :save ? :save : :next), value: :hosting
= button_tag :previous, value: :prev_contact_info, class: :subdued, formnovalidate: true = button_tag :previous, value: :prev_contact_info, class: :subdued, formnovalidate: true

19
app/views/conferences/admin/_broadcast.html.haml

@ -0,0 +1,19 @@
= form_tag administration_update_path(@this_conference.slug, :broadcast) do
- if @broadcast_step == :preview || @broadcast_step == :test
= hidden_field_tag :subject, @subject
= hidden_field_tag :body, @body
.test-preview
%h4=@subject
= richtext @body, 4
.actions.right
= button_tag :test, value: :test, class: :secondary if @broadcast_step == :preview
= button_with_confirmation :send, (_'modals.admin.broadcast.confirm', vars: { number: @subscriber_count || 0 }), value: :send, class: :delete if @broadcast_step == :test
= button_tag :edit, value: :edit
- else
= textfield :subject, @subject, required: true, big: true
= textarea :body, @body, heading: 'articles.conference_registration.headings.admin.edit.info', help: 'articles.conference_registration.paragraphs.admin.edit.info', lang: @this_conference.locale, edit_on: :focus
.actions.right
= button_tag :preview, value: :preview
-# I18n.backend.enabled_locales.each do | locale |
-# if locale.to_s != @this_conference.locale.to_s
-#= textarea "info_translations[#{locale.to_s}]", (richtext @this_conference._info(locale)), label: 'translate.pages.Locale_Translation', vars: { language: _("languages.#{locale}") }, lang: locale

1
app/views/conferences/admin/_broadcast_sent.html.haml

@ -0,0 +1 @@
Sent.

7
app/views/conferences/admin/_edit.html.haml

@ -0,0 +1,7 @@
= form_tag administration_update_path(@this_conference.slug, :edit) do
= textarea :info, @this_conference.info!, heading: 'articles.conference_registration.headings.admin.edit.info', help: 'articles.conference_registration.paragraphs.admin.edit.info', lang: @this_conference.locale, edit_on: :focus
- I18n.backend.enabled_locales.each do | locale |
- if locale.to_s != @this_conference.locale.to_s
= textarea "info_translations[#{locale.to_s}]", @this_conference._info(locale), label: 'translate.pages.Locale_Translation', vars: { language: _("languages.#{locale}") }, lang: locale, edit_on: :focus
.actions.right
= button_tag :save, value: :save

36
app/views/conferences/admin/_events.html.haml

@ -0,0 +1,36 @@
- if @events.present?
%ul.events.admin-blocks
- @events.each do | event |
%li
%h4.title=event.title
.details
= data_set(:h5, 'forms.labels.generic.event_location', class: :location) do
=event.event_location.present? ? event.event_location.title : ''
= data_set(:h5, 'forms.labels.generic.day', class: :day) do
= date(event.start_time.to_date, :weekday)
= data_set(:h5, 'forms.labels.generic.time', class: :time) do
= time(event.start_time, :short)
= data_set(:h5, 'forms.labels.generic.time_span', class: 'time-span') do
= hours(event.start_time, event.end_time)
= form_tag administration_update_path(@this_conference.slug, :events), class: [:actions, :fill] do
= hidden_field_tag :id, event.id
= button_with_confirmation :delete, (_'modals.admin.generic.delete.confirm', :p, vars: { title: event.title }), value: :delete, class: [:delete, :small]
= button_tag :edit, value: :edit, class: [:small]
%h4=_"articles.admin.locations.headings.#{@event.id.present? ? 'edit' : 'add'}_event", :t
= form_tag administration_update_path(@this_conference.slug, :events) do
= hidden_field_tag :id, @event.id if @event.id.present?
= textfield :title, @event.title!, required: true, big: true, lang: @event.locale
= textarea :info, @event.info!, heading: 'articles.conference_registration.headings.admin.edit.info', help: 'articles.conference_registration.paragraphs.admin.edit.info', lang: @event.locale, edit_on: :focus
.flex-inputs
= location_select @event.event_location_id, small: true, stretch: true
= day_select @day, small: true, format: :weekday
= time_select @time, small: true
= length_select @length, small: true
- I18n.backend.enabled_locales.each do | locale |
- if locale.to_s != @event.locale.to_s
= textfield "title_translations[#{locale.to_s}]", @event._title(locale), big: true, heading: 'translate.pages.Locale_Translation', vars: { language: _("languages.#{locale}") }, label: 'forms.labels.generic.title', lang: locale
= textarea "info_translations[#{locale.to_s}]", @event._info(locale), lang: locale, label: 'forms.labels.generic.info', edit_on: :focus
.actions.next-prev
= button_tag :save, value: :save
= button_tag :cancel, value: :cancel, class: :subdued, formnovalidate: true if @event.id.present?

26
app/views/conferences/admin/_housing.html.haml

@ -0,0 +1,26 @@
- add_inline_script :housing
= form_tag administration_update_path(@this_conference.slug, :housing), id: :hosts, class: 'on-top-target' do
= hidden_field_tag :guest_id
.on-top-controls
= button_tag :close, type: :button, class: ['on-top-close']
%ul
- @hosts.each do | id, registration |
- if registration.user.present?
- widget_data = host_guests_widget(registration)
%li{id: "host-#{id}", class: widget_data[:class]}
%h4=registration.user.name
.email=registration.user.email
.address=registration.housing_data['address']
.guests=widget_data[:html]
#guests
%h4=_'articles.admin.housing.headings.guests', :t
%ul.guests
- @guests.each do | id, registration |
- if registration.user.present?
%li.guest{id: "guest-#{id}", data: { id: id, 'affected-hosts': @hosts_affected_by_guests[id].join(',') }}
%h4= registration.user.name
.city.on-top-only=registration.city
.email.on-top-only=registration.user.email
= button_tag :set_host, type: :button, class: [:small, 'set-host', 'not-on-top']

35
app/views/conferences/admin/_locations.html.haml

@ -0,0 +1,35 @@
- unless @location.present?
%ul.locations.admin-blocks
- @locations.each do | location |
%li
%h4.title=location.title
.details
= data_set(:h5, 'forms.labels.generic.address', class: :address) do
=location.address
= data_set(:h5, 'articles.workshops.headings.space', class: :space) do
= _"workshop.options.space.#{location.space}"
- amenities = location.amenities.present? ? JSON.parse(location.amenities) : []
- if amenities.present?
= data_set(:h5, 'articles.admin.locations.headings.amenities', class: :amenities) do
%ul.amenities
- amenities.each do | amenity |
%li=_"workshop.options.needs.#{amenity}"
= form_tag administration_update_path(@this_conference.slug, :locations), class: [:actions, :fill] do
= hidden_field_tag :id, location.id
= button_tag :edit, value: :edit, class: :small
= button_with_confirmation :delete, (_'modals.admin.generic.delete.confirm', :p, vars: { title: location.title }), value: :delete, class: [:delete, :small]
%h4=_"articles.admin.locations.headings.#{@location.present? ? 'edit' : 'add'}_location", :t
= form_tag administration_update_path(@this_conference.slug, :locations) do
= hidden_field_tag :id, @location.id if @location.present?
= textfield :title, @location.present? ? @location.title : nil, required: true, big: true
= textfield :address, @location.present? ? @location.address : nil, required: true
= columns(medium: 6) do
= radiobuttons :space, EventLocation.all_spaces, @location.present? ? @location.space : nil, 'workshop.options.space', vertical: true, heading: 'articles.workshops.headings.space'
= columns(medium: 6) do
= checkboxes :needs, EventLocation.all_amenities, @location.present? ? JSON.parse(@location.amenities) : [], 'workshop.options.needs', vertical: true, heading: 'articles.admin.locations.headings.amenities'
.actions.next-prev
- if @location.present?
= button_tag :save, value: :save
= button_tag :cancel, value: :cancel, class: :subdued, formnovalidate: true
- else
= button_tag :create, value: :create

30
app/views/conferences/admin/_meals.html.haml

@ -0,0 +1,30 @@
- if @this_conference.meals.present?
%table.meals
%tr
%th=_'forms.labels.generic.title'
%th=_'forms.labels.generic.info'
%th=_'forms.labels.generic.event_location'
%th=_'forms.labels.generic.day'
%th=_'forms.labels.generic.time'
%th.form
- Hash[@this_conference.meals.map{ |k, v| [k.to_i, v] }].sort.to_h.each do | time, meal |
%tr
%th
=_!(meal['title'] || '')
%td=_!(meal['info'] || '')
%td=_!location_name(meal['location'].to_i)
%td=date(meal['day'], :weekday)
%td=time(meal['time'].to_f)
%td.form
= form_tag administration_update_path(@this_conference.slug, :meals) do
= hidden_field_tag :meal, time
= button_tag :delete, value: :delete, class: [:small, :delete]
= form_tag administration_update_path(@this_conference.slug, :meals) do
.flex-inputs
= location_select nil, small: true, stretch: true
= day_select nil, small: true, format: :weekday
= time_select nil, small: true
= textfield :title, nil, required: true, big: true
= textfield :info, nil
.actions.next-prev
= button_tag :add_meal, value: :add_meal

0
app/views/conferences/admin/_schedule.html.haml

0
app/views/conferences/admin/_stats.html.haml

23
app/views/conferences/register.html.haml

@ -1,15 +1,16 @@
= render :partial => 'page_header', :locals => {:page_key => 'Conference_Registration'} = render :partial => 'page_header', :locals => {:page_key => 'Conference_Registration'}
- if (steps = current_registration_steps(@registration)) = registration_step_menu
= row id: 'registration-steps', class: 'flow-steps' do -#- if (steps = current_registration_steps(@registration))
= columns do -# = row id: 'registration-steps', class: 'flow-steps' do
%ul -# = columns do
- current_registration_steps.each do | step | -# %ul
- text = _"articles.conference_registration.headings.#{step[:name].to_s}" -# - current_registration_steps.each do | step |
%li{class: [step[:enabled] ? :enabled : nil, @register_template == step[:name] ? :current : nil]} -# - text = _"articles.conference_registration.headings.#{step[:name].to_s}"
- if step[:enabled] -# %li{class: [step[:enabled] ? :enabled : nil, @register_template == step[:name] ? :current : nil]}
.step= link_to text, register_step_path(@this_conference.slug, step[:name]) -# - if step[:enabled]
- else -# .step= link_to text, register_step_path(@this_conference.slug, step[:name])
.step= text -# - else
-# .step= text
- if @warnings.present? - if @warnings.present?
= row class: 'warnings', tag: :ul do = row class: 'warnings', tag: :ul do
- @warnings.each do | warning | - @warnings.each do | warning |

1
app/views/layouts/application.html.haml

@ -52,5 +52,4 @@
%button.delete=_'modals.no_button' %button.delete=_'modals.no_button'
= yield :footer_scripts if content_for?(:footer_scripts) = yield :footer_scripts if content_for?(:footer_scripts)
- add_inline_script :main
= inline_scripts = inline_scripts

4
app/views/shared/_footer.html.haml

@ -12,9 +12,9 @@
%ul.locales %ul.locales
- @alt_lang_urls.each do |locale, url| - @alt_lang_urls.each do |locale, url|
%li %li
- locale_translation = _("languages.#{locale}", locale: locale) - locale_translation = language(locale, true)
%a{href: url, lang: locale} %a{href: url, lang: locale}
=_'translate.content.change_locale', "Read in #{locale_translation}", vars: {language: locale_translation}, locale: locale if locale != I18n.locale.to_s =_'translate.content.change_locale', "Read in #{locale_translation}", vars: {language: locale_translation}, locale: locale if locale != I18n.locale.to_s
.copy .copy
=_'links.footer.help_text.contributors', 'Who contributed to building this website' do |title| =_'links.footer.help_text.contributors', 'Who contributed to building this website' do |title|
=link_to :humans_txt, {title: title} do =link_to :humans_txt, {title: title} do

2
app/views/user_mailer/broadcast.html.haml

@ -1 +1 @@
=markdown @content =@content.html_safe

12
app/views/workshops/new.html.haml

@ -1,9 +1,3 @@
- add_stylesheet :editor
- add_inline_script :pen
- add_inline_script :markdown
- add_inline_script :editor
-#= render 'conferences/page_header', :page_key => (@workshop.id.present? ? 'Edit_Workshop' : 'Create_Workshop')
= render 'conferences/page_header', :page_key => 'Conference_Registration' = render 'conferences/page_header', :page_key => 'Conference_Registration'
%article %article
@ -19,15 +13,15 @@
%h2=_@page_title, :t %h2=_@page_title, :t
- else - else
%h2=_@page_title, :t %h2=_@page_title, :t
= textfield :title, @title, required: true, lang: @translation, big: true, original_value: @is_translating ? @workshop.title! : nil, original_lang: @workshop.locale = textfield :title, @title, required: true, lang: @translation, big: true, original_value: @is_translating ? @workshop.title! : nil, original_lang: @workshop.locale
= textarea :info, @info, help: 'articles.workshops.paragraphs.info', lang: @translation, original_value: @is_translating ? richtext(@workshop.info!, 4).html_safe : nil, original_lang: @workshop.locale = textarea :info, @info, help: 'articles.workshops.paragraphs.info', lang: @translation, original_value: @is_translating ? richtext(@workshop.info!, 4).html_safe : nil, original_lang: @workshop.locale
- if !@is_translating && (@workshop.id.blank? || @can_edit) - if !@is_translating && (@workshop.id.blank? || @can_edit)
= columns(medium: 6) do = columns(medium: 6) do
= checkboxes :languages, [:en, :es, :fr], @languages, 'languages', vertical: true, heading: 'articles.workshops.headings.languages', help: 'articles.workshops.paragraphs.languages' = checkboxes :languages, [:en, :es, :fr], @languages, 'languages', vertical: true, heading: 'articles.workshops.headings.languages', help: 'articles.workshops.paragraphs.languages'
= radiobuttons :theme, Workshop.all_themes, @workshop.theme, 'workshop.options.theme', vertical: true, heading: 'articles.workshops.headings.theme', help: 'articles.workshops.paragraphs.theme', other: true = radiobuttons :theme, Workshop.all_themes, @workshop.theme, 'workshop.options.theme', vertical: true, heading: 'articles.workshops.headings.theme', help: 'articles.workshops.paragraphs.theme', other: true
= columns(medium: 6) do = columns(medium: 6) do
= checkboxes :needs, [:sound, :projector, :tools], JSON.parse(@workshop.needs || '[]'), 'workshop.options.needs', vertical: true, heading: 'articles.workshops.headings.needs', help: 'articles.workshops.paragraphs.needs' = checkboxes :needs, Workshop.all_needs, JSON.parse(@workshop.needs || '[]'), 'workshop.options.needs', vertical: true, heading: 'articles.workshops.headings.needs', help: 'articles.workshops.paragraphs.needs'
= radiobuttons :space, [:meeting_room, :workshop, :outdoor_meeting], @workshop.space, 'workshop.options.space', vertical: true, heading: 'articles.workshops.headings.space', help: 'articles.workshops.paragraphs.space' = radiobuttons :space, Workshop.all_spaces, @workshop.space, 'workshop.options.space', vertical: true, heading: 'articles.workshops.headings.space', help: 'articles.workshops.paragraphs.space'
%h3#needs_facilitators-label=_'articles.workshops.headings.needs_facilitators','Looking for help?' %h3#needs_facilitators-label=_'articles.workshops.headings.needs_facilitators','Looking for help?'
.input-field-help#needs_facilitators-desc=_'articles.workshops.paragraphs.needs_facilitators', :s, 2 .input-field-help#needs_facilitators-desc=_'articles.workshops.paragraphs.needs_facilitators', :s, 2

2
config/initializers/assets.rb

@ -8,4 +8,4 @@ Rails.application.config.assets.version = '1.0'
# Precompile additional assets. # Precompile additional assets.
# application.js, application.css, and all non-JS/CSS in app/assets folder are already added. # application.js, application.css, and all non-JS/CSS in app/assets folder are already added.
Rails.application.config.assets.precompile += %w( user-mailer.css map.js pen.js editor.js markdown.js main.js favicon.ico ) Rails.application.config.assets.precompile += %w( user-mailer.css map.js pen.js editor.js markdown.js main.js housing.js favicon.ico )

59
config/locales/en.yml

@ -35,6 +35,7 @@ en:
default: "%Y-%m-%d" default: "%Y-%m-%d"
long: "%B %d, %Y" long: "%B %d, %Y"
short: "%b %d" short: "%b %d"
weekday: "%A"
span_same_month_date_1: "%B %e" span_same_month_date_1: "%B %e"
span_same_month_date_2: "%e, %Y" span_same_month_date_2: "%e, %Y"
span_same_year_date_1: "%B %e" span_same_year_date_1: "%B %e"
@ -87,6 +88,9 @@ en:
x_days: x_days:
one: 1 day one: 1 day
other: "%{count} days" other: "%{count} days"
x_hours:
one: 1 hour
other: "%{count} hours"
x_minutes: x_minutes:
one: 1 minute one: 1 minute
other: "%{count} minutes" other: "%{count} minutes"
@ -96,6 +100,7 @@ en:
x_seconds: x_seconds:
one: 1 second one: 1 second
other: "%{count} seconds" other: "%{count} seconds"
x_and_y: "%{x} %{y}"
prompts: prompts:
day: Day day: Day
hour: Hour hour: Hour
@ -162,6 +167,10 @@ en:
header: header:
one: 1 error prohibited this %{model} from being saved one: 1 error prohibited this %{model} from being saved
other: "%{count} errors prohibited this %{model} from being saved" other: "%{count} errors prohibited this %{model} from being saved"
warnings:
housing:
space:
overbooked: Overbooked
helpers: helpers:
select: select:
prompt: Please select prompt: Please select
@ -5205,7 +5214,7 @@ en:
explain_zero_fallback: This translation will use the plural version for the explain_zero_fallback: This translation will use the plural version for the
number 0 number 0
History: History History: History
Locale_Translation: "%%{language} Translation" Locale_Translation: "%{language} Translation"
Save: Save Save: Save
content: content:
needs_translations: This page contains untranslated content needs_translations: This page contains untranslated content
@ -5275,7 +5284,24 @@ en:
confirm_remove_self: Are you sure you would like to remove yourself as a facilitator of this workshop? confirm_remove_self: Are you sure you would like to remove yourself as a facilitator of this workshop?
confirm_cancel_request: Are you sure you would like to cancel your request to become a facilitator of this workshop? confirm_cancel_request: Are you sure you would like to cancel your request to become a facilitator of this workshop?
confirm_transfer_ownership: By transferring ownership, you will lose administrative capabilities such as deletion and approving new facilitators. Are you sure you want to transfer ownership to %{user_name}? confirm_transfer_ownership: By transferring ownership, you will lose administrative capabilities such as deletion and approving new facilitators. Are you sure you want to transfer ownership to %{user_name}?
admin:
broadcast:
confirm: You are about to send this email to %{number} people. Are you sure you want to continue?
generic:
delete:
confirm: You are about to delete ‘%{title}’. Are you sure you want to continue?
articles: articles:
admin:
housing:
headings:
guests: Guests
locations:
headings:
add_event: Add Event
add_location: Add Location
amenities: Amenities
edit_event: Edit Event
edit_location: Edit Location
policy: policy:
headings: headings:
The_Agreement: The Agreement The_Agreement: The Agreement
@ -5310,6 +5336,8 @@ en:
peaceful: We are peaceful and honest. peaceful: We are peaceful and honest.
conference_registration: conference_registration:
headings: headings:
Administration: Administration
administration: Administration
Policy_Agreement: Safer Space Agreement Policy_Agreement: Safer Space Agreement
policy: Policy policy: Policy
arrival_and_departure: For what days will you need housing? (If you don't arrival_and_departure: For what days will you need housing? (If you don't
@ -5409,6 +5437,9 @@ en:
availability: The most common arrival and departure dates for attendees are the first and last day of the conference but people often arrive earlier or later. When will your space be available? availability: The most common arrival and departure dates for attendees are the first and last day of the conference but people often arrive earlier or later. When will your space be available?
considerations: Organizers will do their best to match up hosts and guests, what considerations should organizers keep in mind when selecting guests to stay in your home? considerations: Organizers will do their best to match up hosts and guests, what considerations should organizers keep in mind when selecting guests to stay in your home?
notes: Leave a message for organizers should take into consideration when selecting guests for your household. notes: Leave a message for organizers should take into consideration when selecting guests for your household.
admin:
edit:
info: This is the copy that is displayed on the front page of the site.
host: host:
considerations: considerations:
vegan: Vegan or vegetarian only vegan: Vegan or vegetarian only
@ -5587,11 +5618,16 @@ en:
message: 'Your Message:' message: 'Your Message:'
address: Street Address address: Street Address
phone: Phone number phone: Phone number
bed_space: Bed/Couch Spaec bed_space: Bed/Couch Space
floor_space: Floor Space floor_space: Floor Space
tent_space: Tent Space tent_space: Tent Space
first_day: From first_day: From
last_day: To last_day: To
body: Body
day: Day
event_location: Location
time: Time
time_span: Length
actions: actions:
generic: generic:
login: Sign In login: Sign In
@ -5616,6 +5652,11 @@ en:
next: Next next: Next
continue: Continue continue: Continue
facebook_sign_in: Facebook Sign In facebook_sign_in: Facebook Sign In
add_meal: Add
create: Create
delete: Delete
place_guest: Place Guest
set_host: Set Host
aria: aria:
remove_interest: Click if you are no longer interested in this workshop remove_interest: Click if you are no longer interested in this workshop
show_interest: Click if you are interested in this workshop show_interest: Click if you are interested in this workshop
@ -5646,6 +5687,7 @@ en:
Safer_Spaces_Policy: Safer Space Agreement Safer_Spaces_Policy: Safer Space Agreement
'404': '404':
Page_Not_Found: Page Not Found Page_Not_Found: Page Not Found
Locale_Not_Available: Locale Not Available
Policy: 'Policy' Policy: 'Policy'
About: 'About' About: 'About'
Register: 'Register' Register: 'Register'
@ -5676,6 +5718,15 @@ en:
Stats: Stats Stats: Stats
Broadcast: Broadcast Broadcast: Broadcast
Edit: Edit Conference Edit: Edit Conference
admin:
Edit: Edit
Stats: Stats
Broadcast: Broadcast
Housing: Housing
Locations: Locations
Meals: Meals
Events: Events
Schedule: Schedule
actions: actions:
workshops: workshops:
create: New Workshop create: New Workshop
@ -5702,6 +5753,9 @@ en:
believe that it should exist please contact admin@bikebike.org or file an believe that it should exist please contact admin@bikebike.org or file an
issue on github: https://github.com/bikebike/BikeBike/issues issue on github: https://github.com/bikebike/BikeBike/issues
title: '404: This page doesn''t exist' title: '404: This page doesn''t exist'
locale_not_available:
description: This site has yet to be translated into %{language}. We are actively looking for volunteers who can translate existing copy and new copy as we add new features. If you think you can help, please contact us!
title: '404: %{language} Translations Missing'
'500': '500':
title: There is a problem title: There is a problem
description: 'An error has occurred, details about the error have been sent to our development team. In addition, you may contact us or report an issue.' description: 'An error has occurred, details about the error have been sent to our development team. In addition, you may contact us or report an issue.'
@ -5723,6 +5777,7 @@ en:
meeting_room: Meeting Room meeting_room: Meeting Room
outdoor_meeting: Outdoor Space outdoor_meeting: Outdoor Space
workshop: Repair Space workshop: Repair Space
event_space: Event Space
theme: theme:
community: Community Outreach community: Community Outreach
funding: Funding funding: Funding

2
config/routes.rb

@ -7,6 +7,8 @@ BikeBike::Application.routes.draw do
match '/conferences/:slug/register' => 'conferences#register', :as => :register, via: [:get, :post] match '/conferences/:slug/register' => 'conferences#register', :as => :register, via: [:get, :post]
get '/conferences/:slug/register/:step' => 'conferences#register', :as => :register_step get '/conferences/:slug/register/:step' => 'conferences#register', :as => :register_step
get '/conferences/:slug/register/administration/:admin_step' => 'conferences#register', :as => :administration_step
post '/conferences/:slug/register/administration/update/:admin_step' => 'conferences#admin_update', :as => :administration_update
match '/conferences/:slug/broadcast' => 'conferences#broadcast', :as => :broadcast, via: [:get, :post] match '/conferences/:slug/broadcast' => 'conferences#broadcast', :as => :broadcast, via: [:get, :post]
get '/conferences/:slug/stats' => 'conferences#stats', :as => :stats get '/conferences/:slug/stats' => 'conferences#stats', :as => :stats
get '/conferences/:slug/register/:button/:confirmation_token' => 'conferences#register', :as => :register_paypal_confirm get '/conferences/:slug/register/:button/:confirmation_token' => 'conferences#register', :as => :register_paypal_confirm

5
db/migrate/20160621020123_add_space_to_event_locations.rb

@ -0,0 +1,5 @@
class AddSpaceToEventLocations < ActiveRecord::Migration
def change
add_column :event_locations, :space, :string
end
end

5
db/migrate/20160621051912_add_meals_to_conferences.rb

@ -0,0 +1,5 @@
class AddMealsToConferences < ActiveRecord::Migration
def change
add_column :conferences, :meals, :json
end
end

5
db/migrate/20160622011811_add_locale_to_events.rb

@ -0,0 +1,5 @@
class AddLocaleToEvents < ActiveRecord::Migration
def change
add_column :events, :locale, :string
end
end

5
db/schema.rb

@ -11,7 +11,7 @@
# #
# It's strongly recommended that you check this file into your version control system. # It's strongly recommended that you check this file into your version control system.
ActiveRecord::Schema.define(version: 20160604221432) do ActiveRecord::Schema.define(version: 20160622011811) do
# These are extensions that must be enabled in order to support this database # These are extensions that must be enabled in order to support this database
enable_extension "plpgsql" enable_extension "plpgsql"
@ -126,6 +126,7 @@ ActiveRecord::Schema.define(version: 20160604221432) do
t.string "paypal_signature" t.string "paypal_signature"
t.string "day_parts" t.string "day_parts"
t.string "registration_status" t.string "registration_status"
t.json "meals"
end end
create_table "delayed_jobs", force: :cascade do |t| create_table "delayed_jobs", force: :cascade do |t|
@ -172,6 +173,7 @@ ActiveRecord::Schema.define(version: 20160604221432) do
t.string "amenities" t.string "amenities"
t.datetime "created_at", null: false t.datetime "created_at", null: false
t.datetime "updated_at", null: false t.datetime "updated_at", null: false
t.string "space"
end end
create_table "event_types", force: :cascade do |t| create_table "event_types", force: :cascade do |t|
@ -194,6 +196,7 @@ ActiveRecord::Schema.define(version: 20160604221432) do
t.datetime "updated_at" t.datetime "updated_at"
t.integer "event_location_id" t.integer "event_location_id"
t.string "event_type" t.string "event_type"
t.string "locale"
end end
create_table "locations", force: :cascade do |t| create_table "locations", force: :cascade do |t|

Loading…
Cancel
Save