calagator 0.0.1.pre1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (384) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE.txt +23 -0
  3. data/README.md +75 -0
  4. data/Rakefile +12 -0
  5. data/app/assets/images/confused-alligator-sm.png +0 -0
  6. data/app/assets/images/disk.png +0 -0
  7. data/app/assets/images/edit.png +0 -0
  8. data/app/assets/images/external_sites/epdx.png +0 -0
  9. data/app/assets/images/external_sites/external.gif +0 -0
  10. data/app/assets/images/external_sites/facebook.png +0 -0
  11. data/app/assets/images/external_sites/foursquare.png +0 -0
  12. data/app/assets/images/external_sites/gowalla.png +0 -0
  13. data/app/assets/images/external_sites/lanyrd.png +0 -0
  14. data/app/assets/images/external_sites/meetup.png +0 -0
  15. data/app/assets/images/external_sites/plancast.png +0 -0
  16. data/app/assets/images/external_sites/shizzow.png +0 -0
  17. data/app/assets/images/external_sites/upcoming.png +0 -0
  18. data/app/assets/images/external_sites/yelp.png +0 -0
  19. data/app/assets/images/feed.png +0 -0
  20. data/app/assets/images/heart.png +0 -0
  21. data/app/assets/images/icon_ical.gif +0 -0
  22. data/app/assets/images/information.png +0 -0
  23. data/app/assets/images/nav_marker.gif +0 -0
  24. data/app/assets/images/nav_marker.png +0 -0
  25. data/app/assets/images/plus.png +0 -0
  26. data/app/assets/images/redx.png +0 -0
  27. data/app/assets/images/site-icon.png +0 -0
  28. data/app/assets/images/spinner.gif +0 -0
  29. data/app/assets/images/star.png +0 -0
  30. data/app/assets/images/subnav_marker.gif +0 -0
  31. data/app/assets/images/subnav_marker.png +0 -0
  32. data/app/assets/images/tag_blue.png +0 -0
  33. data/app/assets/images/tag_icons/angular.png +0 -0
  34. data/app/assets/images/tag_icons/beer.png +0 -0
  35. data/app/assets/images/tag_icons/bitcoin.png +0 -0
  36. data/app/assets/images/tag_icons/free.png +0 -0
  37. data/app/assets/images/tag_icons/golang.png +0 -0
  38. data/app/assets/images/tag_icons/html.png +0 -0
  39. data/app/assets/images/tag_icons/javascript.png +0 -0
  40. data/app/assets/images/tag_icons/linux.png +0 -0
  41. data/app/assets/images/tag_icons/php.png +0 -0
  42. data/app/assets/images/tag_icons/pizza.png +0 -0
  43. data/app/assets/images/tag_icons/python.png +0 -0
  44. data/app/assets/images/tag_icons/rails.png +0 -0
  45. data/app/assets/images/tag_icons/ruby.png +0 -0
  46. data/app/assets/images/tag_icons/sass.png +0 -0
  47. data/app/assets/images/tag_icons/swift.png +0 -0
  48. data/app/assets/images/transmit_blue.png +0 -0
  49. data/app/assets/images/weekday_background.gif +0 -0
  50. data/app/assets/javascripts/calagator.js +18 -0
  51. data/app/assets/javascripts/calagator/forms.js +60 -0
  52. data/app/assets/stylesheets/calagator.scss +8 -0
  53. data/app/assets/stylesheets/calagator/common.scss +14 -0
  54. data/app/assets/stylesheets/calagator/datepicker.scss +177 -0
  55. data/app/assets/stylesheets/calagator/errors.css +110 -0
  56. data/app/assets/stylesheets/calagator/forms.scss +4 -0
  57. data/app/assets/stylesheets/calagator/reset.css +40 -0
  58. data/app/assets/stylesheets/calagator/theme.css +0 -0
  59. data/app/controllers/calagator/admin_controller.rb +27 -0
  60. data/app/controllers/calagator/application_controller.rb +82 -0
  61. data/app/controllers/calagator/events_controller.rb +171 -0
  62. data/app/controllers/calagator/site_controller.rb +35 -0
  63. data/app/controllers/calagator/sources_controller.rb +94 -0
  64. data/app/controllers/calagator/venues_controller.rb +133 -0
  65. data/app/controllers/calagator/versions_controller.rb +20 -0
  66. data/app/helpers/calagator/application_helper.rb +128 -0
  67. data/app/helpers/calagator/events_helper.rb +184 -0
  68. data/app/helpers/calagator/google_event_export_helper.rb +67 -0
  69. data/app/helpers/calagator/mapping_helper.rb +103 -0
  70. data/app/helpers/calagator/sources_helper.rb +10 -0
  71. data/app/helpers/calagator/tags_helper.rb +42 -0
  72. data/app/helpers/calagator/time_range_helper.rb +166 -0
  73. data/app/models/calagator/event.rb +246 -0
  74. data/app/models/calagator/event/cloner.rb +39 -0
  75. data/app/models/calagator/event/ical_renderer.rb +155 -0
  76. data/app/models/calagator/event/overview.rb +45 -0
  77. data/app/models/calagator/event/saver.rb +58 -0
  78. data/app/models/calagator/event/search.rb +72 -0
  79. data/app/models/calagator/event/search_engine.rb +28 -0
  80. data/app/models/calagator/event/search_engine/apache_sunspot.rb +106 -0
  81. data/app/models/calagator/event/search_engine/sql.rb +107 -0
  82. data/app/models/calagator/source.rb +115 -0
  83. data/app/models/calagator/source/importer.rb +46 -0
  84. data/app/models/calagator/source/parser.rb +128 -0
  85. data/app/models/calagator/source/parser/facebook.rb +67 -0
  86. data/app/models/calagator/source/parser/hcal.rb +108 -0
  87. data/app/models/calagator/source/parser/http_authentication_required_error.rb +6 -0
  88. data/app/models/calagator/source/parser/ical.rb +186 -0
  89. data/app/models/calagator/source/parser/meetup.rb +72 -0
  90. data/app/models/calagator/source/parser/not_found.rb +9 -0
  91. data/app/models/calagator/source/parser/plancast.rb +59 -0
  92. data/app/models/calagator/venue.rb +161 -0
  93. data/app/models/calagator/venue/geocoder.rb +51 -0
  94. data/app/models/calagator/venue/search.rb +63 -0
  95. data/app/models/calagator/venue/search_engine.rb +24 -0
  96. data/app/models/calagator/venue/search_engine/apache_sunspot.rb +85 -0
  97. data/app/models/calagator/venue/search_engine/sql.rb +68 -0
  98. data/app/models/event/search_engine/base.rb +0 -0
  99. data/app/observers/calagator/cache_observer.rb +37 -0
  100. data/app/views/calagator/admin/events.html.erb +28 -0
  101. data/app/views/calagator/admin/index.html.erb +8 -0
  102. data/app/views/calagator/events/_feed_item.html.erb +62 -0
  103. data/app/views/calagator/events/_form.html.erb +63 -0
  104. data/app/views/calagator/events/_gcal_reminder.html.erb +1 -0
  105. data/app/views/calagator/events/_hcal.html.erb +41 -0
  106. data/app/views/calagator/events/_item.html.erb +120 -0
  107. data/app/views/calagator/events/_list.html.erb +30 -0
  108. data/app/views/calagator/events/_list_item.html.erb +37 -0
  109. data/app/views/calagator/events/_search_section.html.erb +15 -0
  110. data/app/views/calagator/events/_subnav.html.erb +13 -0
  111. data/app/views/calagator/events/_table.html.erb +74 -0
  112. data/app/views/calagator/events/duplicates.html.erb +58 -0
  113. data/app/views/calagator/events/edit.html.erb +3 -0
  114. data/app/views/calagator/events/index.atom.builder +32 -0
  115. data/app/views/calagator/events/index.html.erb +51 -0
  116. data/app/views/calagator/events/index.kml.erb +20 -0
  117. data/app/views/calagator/events/new.html.erb +7 -0
  118. data/app/views/calagator/events/search.html.erb +25 -0
  119. data/app/views/calagator/events/show.html.erb +81 -0
  120. data/app/views/calagator/site/_appropriateness_message.html.erb +15 -0
  121. data/app/views/calagator/site/_description.html.erb +3 -0
  122. data/app/views/calagator/site/about.html.erb +7 -0
  123. data/app/views/calagator/site/defunct.html.erb +15 -0
  124. data/app/views/calagator/site/export.html.erb +4 -0
  125. data/app/views/calagator/site/index.html.erb +40 -0
  126. data/app/views/calagator/site/opensearch.xml.builder +8 -0
  127. data/app/views/calagator/sources/_subnav.html.erb +0 -0
  128. data/app/views/calagator/sources/edit.html.erb +12 -0
  129. data/app/views/calagator/sources/import.html.erb +10 -0
  130. data/app/views/calagator/sources/index.html.erb +22 -0
  131. data/app/views/calagator/sources/new.html.erb +32 -0
  132. data/app/views/calagator/sources/show.html.erb +16 -0
  133. data/app/views/calagator/venues/_form.html.erb +57 -0
  134. data/app/views/calagator/venues/_subnav.html.erb +10 -0
  135. data/app/views/calagator/venues/duplicates.html.erb +65 -0
  136. data/app/views/calagator/venues/edit.html.erb +3 -0
  137. data/app/views/calagator/venues/index.html.erb +93 -0
  138. data/app/views/calagator/venues/index.kml.erb +15 -0
  139. data/app/views/calagator/venues/map.html.erb +4 -0
  140. data/app/views/calagator/venues/new.html.erb +5 -0
  141. data/app/views/calagator/venues/show.html.erb +113 -0
  142. data/app/views/calagator/versions/_chooser.html.erb +28 -0
  143. data/app/views/calagator/versions/_edit_with_chooser.html.erb +16 -0
  144. data/app/views/layouts/calagator/application.html.erb +110 -0
  145. data/config/deploy/local.rb +37 -0
  146. data/config/deploy/lucca.rb +33 -0
  147. data/config/initializers/dates.rb +7 -0
  148. data/config/initializers/formtastic.rb +82 -0
  149. data/config/initializers/geokit.rb +74 -0
  150. data/config/initializers/ics_renderer.rb +6 -0
  151. data/config/initializers/load_tag_model_extensions.rb +3 -0
  152. data/config/initializers/mime_types.rb +9 -0
  153. data/config/initializers/observers.rb +1 -0
  154. data/config/initializers/search_engine.rb +4 -0
  155. data/config/initializers/set_default_url_host.rb +5 -0
  156. data/config/initializers/time_get_zone.rb +8 -0
  157. data/config/locales/en.yml +5 -0
  158. data/config/routes.rb +55 -0
  159. data/config/secrets.yml.blag +75 -0
  160. data/config/sunspot.yml +23 -0
  161. data/db/development.sqlite3 +0 -0
  162. data/db/development.sqlite3.bak +0 -0
  163. data/db/development.sqlite3.old +0 -0
  164. data/db/development~20111112@110950.sqlite3 +0 -0
  165. data/db/migrate/001_create_events.rb +17 -0
  166. data/db/migrate/002_create_venues.rb +17 -0
  167. data/db/migrate/003_create_sources.rb +16 -0
  168. data/db/migrate/004_add_detailed_fields_to_venue.rb +19 -0
  169. data/db/migrate/005_add_end_time_to_events.rb +9 -0
  170. data/db/migrate/006_add_source_id_to_events.rb +9 -0
  171. data/db/migrate/008_add_source_id_to_venues.rb +10 -0
  172. data/db/migrate/009_add_duplicate_of_column_to_venues.rb +9 -0
  173. data/db/migrate/010_add_duplicate_of_column_to_events.rb +9 -0
  174. data/db/migrate/011_change_lat_long_type.rb +12 -0
  175. data/db/migrate/012_add_source_reimport.rb +9 -0
  176. data/db/migrate/013_change_end_time_to_duration.rb +11 -0
  177. data/db/migrate/014_remove_format_type_from_source.rb +9 -0
  178. data/db/migrate/015_create_updates.rb +15 -0
  179. data/db/migrate/016_remove_next_update_from_source.rb +9 -0
  180. data/db/migrate/20080705163959_change_duration_to_end_time.rb +11 -0
  181. data/db/migrate/20080705164959_create_tags_and_taggings.rb +28 -0
  182. data/db/migrate/20081011181519_create_versioned_events.rb +25 -0
  183. data/db/migrate/20081011193124_create_versioned_venues.rb +32 -0
  184. data/db/migrate/20081115190515_add_rrule_to_events.rb +15 -0
  185. data/db/migrate/20090912082129_create_versions.rb +18 -0
  186. data/db/migrate/20110219205156_add_closed_flag_to_venues.rb +9 -0
  187. data/db/migrate/20110220001008_add_wifi_flag_to_venues.rb +9 -0
  188. data/db/migrate/20110220011427_add_access_notes_to_venues.rb +9 -0
  189. data/db/migrate/20110220031117_add_events_count_to_venues.rb +8 -0
  190. data/db/migrate/20110604174521_add_venue_details_to_events.rb +9 -0
  191. data/db/migrate/20110717231316_acts_as_taggable_on_migration.rb +50 -0
  192. data/db/migrate/20120709092821_cleanup.rb +14 -0
  193. data/db/migrate/20120831234448_specify_venues_latitude_and_longitude_precision.rb +11 -0
  194. data/db/migrate/20150206085809_remove_updates.rb +13 -0
  195. data/db/migrate/20150207231355_add_locked_status_to_events.rb +5 -0
  196. data/db/production.sqlite3 +0 -0
  197. data/db/schema.rb +102 -0
  198. data/db/seeds.rb +16 -0
  199. data/db/test.sqlite3 +0 -0
  200. data/db/test2.sqlite3 +0 -0
  201. data/lib/calagator.rb +30 -0
  202. data/lib/calagator/blacklist_validator.rb +69 -0
  203. data/lib/calagator/decode_html_entities_hack.rb +33 -0
  204. data/lib/calagator/duplicate_checking.rb +133 -0
  205. data/lib/calagator/duplicate_checking/controller_actions.rb +38 -0
  206. data/lib/calagator/duplicate_checking/duplicate_finder.rb +83 -0
  207. data/lib/calagator/duplicate_checking/duplicate_squasher.rb +74 -0
  208. data/lib/calagator/engine.rb +30 -0
  209. data/lib/calagator/strip_whitespace.rb +19 -0
  210. data/lib/calagator/tag_model_extensions.rb +104 -0
  211. data/lib/calagator/url_prefixer.rb +9 -0
  212. data/lib/calagator/version.rb +3 -0
  213. data/lib/generators/calagator/install_generator.rb +39 -0
  214. data/lib/generators/calagator/templates/config/calagator.rb +26 -0
  215. data/lib/generators/calagator/templates/config/secrets.yml.sample +83 -0
  216. data/lib/secrets_reader.rb +76 -0
  217. data/lib/tasks/spec_db.rake +53 -0
  218. data/lib/tasks/sunspot_reindex_calagator.rake +6 -0
  219. data/lib/tasks/sunspot_solr_restart_enhancements.rake +19 -0
  220. data/lib/tasks/update_counter_caches.rake +13 -0
  221. data/lib/templates/erb/scaffold/_form.html.erb +11 -0
  222. data/lib/theme_reader.rb +17 -0
  223. data/lib/wait_for_solr.rb +25 -0
  224. data/spec/controllers/calagator/application_controller_spec.rb +47 -0
  225. data/spec/controllers/calagator/events_controller_spec.rb +794 -0
  226. data/spec/controllers/calagator/site_controller_spec.rb +59 -0
  227. data/spec/controllers/calagator/sources_controller_spec.rb +439 -0
  228. data/spec/controllers/calagator/venues_controller_spec.rb +319 -0
  229. data/spec/controllers/calagator/versions_controller_spec.rb +82 -0
  230. data/spec/controllers/squash_many_duplicates_examples.rb +49 -0
  231. data/spec/dummy/Gemfile +39 -0
  232. data/spec/dummy/Gemfile.lock +195 -0
  233. data/spec/dummy/README.rdoc +261 -0
  234. data/spec/dummy/Rakefile +7 -0
  235. data/spec/dummy/app/assets/images/rails.png +0 -0
  236. data/spec/dummy/app/assets/javascripts/application.js +16 -0
  237. data/spec/dummy/app/assets/stylesheets/application.css +14 -0
  238. data/spec/dummy/app/controllers/application_controller.rb +3 -0
  239. data/spec/dummy/app/helpers/application_helper.rb +2 -0
  240. data/spec/dummy/app/views/layouts/application.html.erb +14 -0
  241. data/spec/dummy/config.ru +4 -0
  242. data/spec/dummy/config/application.rb +62 -0
  243. data/spec/dummy/config/boot.rb +6 -0
  244. data/spec/dummy/config/database.yml +25 -0
  245. data/spec/dummy/config/environment.rb +5 -0
  246. data/spec/dummy/config/environments/development.rb +37 -0
  247. data/spec/dummy/config/environments/production.rb +67 -0
  248. data/spec/dummy/config/environments/test.rb +37 -0
  249. data/spec/dummy/config/initializers/backtrace_silencers.rb +7 -0
  250. data/spec/dummy/config/initializers/calagator.rb +26 -0
  251. data/spec/dummy/config/initializers/inflections.rb +15 -0
  252. data/spec/dummy/config/initializers/mime_types.rb +5 -0
  253. data/spec/dummy/config/initializers/secret_token.rb +7 -0
  254. data/spec/dummy/config/initializers/session_store.rb +8 -0
  255. data/spec/dummy/config/initializers/wrap_parameters.rb +14 -0
  256. data/spec/dummy/config/locales/en.yml +5 -0
  257. data/spec/dummy/config/routes.rb +59 -0
  258. data/spec/dummy/config/secrets.yml +83 -0
  259. data/spec/dummy/db/development.sqlite3 +0 -0
  260. data/spec/dummy/db/migrate/20150309023304_create_events.calagator.rb +18 -0
  261. data/spec/dummy/db/migrate/20150309023305_create_venues.calagator.rb +18 -0
  262. data/spec/dummy/db/migrate/20150309023306_create_sources.calagator.rb +17 -0
  263. data/spec/dummy/db/migrate/20150309023307_add_detailed_fields_to_venue.calagator.rb +20 -0
  264. data/spec/dummy/db/migrate/20150309023308_add_end_time_to_events.calagator.rb +10 -0
  265. data/spec/dummy/db/migrate/20150309023309_add_source_id_to_events.calagator.rb +10 -0
  266. data/spec/dummy/db/migrate/20150309023310_add_source_id_to_venues.calagator.rb +11 -0
  267. data/spec/dummy/db/migrate/20150309023311_add_duplicate_of_column_to_venues.calagator.rb +10 -0
  268. data/spec/dummy/db/migrate/20150309023312_add_duplicate_of_column_to_events.calagator.rb +10 -0
  269. data/spec/dummy/db/migrate/20150309023313_change_lat_long_type.calagator.rb +13 -0
  270. data/spec/dummy/db/migrate/20150309023314_add_source_reimport.calagator.rb +10 -0
  271. data/spec/dummy/db/migrate/20150309023315_change_end_time_to_duration.calagator.rb +12 -0
  272. data/spec/dummy/db/migrate/20150309023316_remove_format_type_from_source.calagator.rb +10 -0
  273. data/spec/dummy/db/migrate/20150309023317_create_updates.calagator.rb +16 -0
  274. data/spec/dummy/db/migrate/20150309023318_remove_next_update_from_source.calagator.rb +10 -0
  275. data/spec/dummy/db/migrate/20150309023319_change_duration_to_end_time.calagator.rb +12 -0
  276. data/spec/dummy/db/migrate/20150309023320_create_tags_and_taggings.calagator.rb +29 -0
  277. data/spec/dummy/db/migrate/20150309023321_create_versioned_events.calagator.rb +26 -0
  278. data/spec/dummy/db/migrate/20150309023322_create_versioned_venues.calagator.rb +33 -0
  279. data/spec/dummy/db/migrate/20150309023323_add_rrule_to_events.calagator.rb +16 -0
  280. data/spec/dummy/db/migrate/20150309023324_create_versions.calagator.rb +19 -0
  281. data/spec/dummy/db/migrate/20150309023325_add_closed_flag_to_venues.calagator.rb +10 -0
  282. data/spec/dummy/db/migrate/20150309023326_add_wifi_flag_to_venues.calagator.rb +10 -0
  283. data/spec/dummy/db/migrate/20150309023327_add_access_notes_to_venues.calagator.rb +10 -0
  284. data/spec/dummy/db/migrate/20150309023328_add_events_count_to_venues.calagator.rb +9 -0
  285. data/spec/dummy/db/migrate/20150309023329_add_venue_details_to_events.calagator.rb +10 -0
  286. data/spec/dummy/db/migrate/20150309023330_acts_as_taggable_on_migration.calagator.rb +51 -0
  287. data/spec/dummy/db/migrate/20150309023331_cleanup.calagator.rb +15 -0
  288. data/spec/dummy/db/migrate/20150309023332_specify_venues_latitude_and_longitude_precision.calagator.rb +12 -0
  289. data/spec/dummy/db/migrate/20150309023333_remove_updates.calagator.rb +14 -0
  290. data/spec/dummy/db/migrate/20150309023334_add_locked_status_to_events.calagator.rb +6 -0
  291. data/spec/dummy/db/schema.rb +95 -0
  292. data/spec/dummy/db/seeds.rb +7 -0
  293. data/spec/dummy/db/test.sqlite3 +0 -0
  294. data/spec/dummy/doc/README_FOR_APP +2 -0
  295. data/spec/dummy/log/development.log +273 -0
  296. data/spec/dummy/public/404.html +26 -0
  297. data/spec/dummy/public/422.html +26 -0
  298. data/spec/dummy/public/500.html +25 -0
  299. data/spec/dummy/public/favicon.ico +0 -0
  300. data/spec/dummy/public/robots.txt +5 -0
  301. data/spec/dummy/script/rails +6 -0
  302. data/spec/dummy/test/performance/browsing_test.rb +12 -0
  303. data/spec/dummy/test/test_helper.rb +13 -0
  304. data/spec/factories.rb +93 -0
  305. data/spec/features/add_event_spec.rb +99 -0
  306. data/spec/features/add_venue_spec.rb +34 -0
  307. data/spec/features/admin_auth_spec.rb +22 -0
  308. data/spec/features/admin_lock_event_spec.rb +41 -0
  309. data/spec/features/import_events_from_feed_spec.rb +43 -0
  310. data/spec/features/managing_event_spec.rb +111 -0
  311. data/spec/features/managing_venue_spec.rb +71 -0
  312. data/spec/features/search_event_spec.rb +27 -0
  313. data/spec/helpers/calagator/application_helper_spec.rb +82 -0
  314. data/spec/helpers/calagator/events_helper_spec.rb +172 -0
  315. data/spec/helpers/calagator/google_event_export_helper_spec.rb +70 -0
  316. data/spec/helpers/calagator/sources_helper_spec.rb +12 -0
  317. data/spec/helpers/calagator/tags_helper_spec.rb +85 -0
  318. data/spec/helpers/calagator/time_range_helper_spec.rb +59 -0
  319. data/spec/lib/calagator/blacklist_validator_spec.rb +65 -0
  320. data/spec/lib/calagator/decode_html_entities_hack_spec.rb +54 -0
  321. data/spec/lib/calagator/settings_spec.rb +20 -0
  322. data/spec/lib/calagator/url_prefixer_spec.rb +33 -0
  323. data/spec/lib/secrets_reader_spec.rb +65 -0
  324. data/spec/models/calagator/event/cloner_spec.rb +43 -0
  325. data/spec/models/calagator/event/overview_spec.rb +79 -0
  326. data/spec/models/calagator/event/search_spec.rb +103 -0
  327. data/spec/models/calagator/event_search_spec.rb +149 -0
  328. data/spec/models/calagator/event_spec.rb +859 -0
  329. data/spec/models/calagator/source/parser_facebook_spec.rb +73 -0
  330. data/spec/models/calagator/source/parser_hcal_spec.rb +69 -0
  331. data/spec/models/calagator/source/parser_ical_non_standard_spec.rb +91 -0
  332. data/spec/models/calagator/source/parser_ical_spec.rb +322 -0
  333. data/spec/models/calagator/source/parser_meetup_spec.rb +69 -0
  334. data/spec/models/calagator/source/parser_plancast_spec.rb +53 -0
  335. data/spec/models/calagator/source/parser_spec.rb +238 -0
  336. data/spec/models/calagator/source_spec.rb +135 -0
  337. data/spec/models/calagator/venue/search_spec.rb +92 -0
  338. data/spec/models/calagator/venue_search_spec.rb +124 -0
  339. data/spec/models/calagator/venue_spec.rb +346 -0
  340. data/spec/models/tag_spec.rb +35 -0
  341. data/spec/rails_helper.rb +39 -0
  342. data/spec/spec_helper.rb +140 -0
  343. data/spec/support/disable_geocoding.rb +1 -0
  344. data/spec/support/http_samples.rb +5 -0
  345. data/spec/support/samples/facebook.json +23 -0
  346. data/spec/support/samples/hcal_basic.xml +6 -0
  347. data/spec/support/samples/hcal_dup_event_dup_venue.xml +13 -0
  348. data/spec/support/samples/hcal_event_duplicates_fixture.xml +13 -0
  349. data/spec/support/samples/hcal_event_wo_lat_and_long.xml +14 -0
  350. data/spec/support/samples/hcal_multiple.xml +16 -0
  351. data/spec/support/samples/hcal_same_event_twice_with_different_venues.xml +12 -0
  352. data/spec/support/samples/hcal_single.xml +8 -0
  353. data/spec/support/samples/hcal_two_identical_events.xml +14 -0
  354. data/spec/support/samples/hcal_upcoming_v1.html +412 -0
  355. data/spec/support/samples/hcal_upcoming_v2.html +749 -0
  356. data/spec/support/samples/hcal_upcoming_v3.html +685 -0
  357. data/spec/support/samples/hcal_upcoming_v4.html +761 -0
  358. data/spec/support/samples/ical_apple.ics +22 -0
  359. data/spec/support/samples/ical_apple_v3.ics +37 -0
  360. data/spec/support/samples/ical_basic.ics +15 -0
  361. data/spec/support/samples/ical_basic_with_duration.ics +16 -0
  362. data/spec/support/samples/ical_event_with_squashed_venue.ics +12 -0
  363. data/spec/support/samples/ical_eventful_many.ics +504 -0
  364. data/spec/support/samples/ical_gmt.ics +12 -0
  365. data/spec/support/samples/ical_google.ics +786 -0
  366. data/spec/support/samples/ical_multiple_calendars.ics +111 -0
  367. data/spec/support/samples/ical_upcoming.ics +36 -0
  368. data/spec/support/samples/ical_upcoming_many.ics +682 -0
  369. data/spec/support/samples/ical_upcoming_v2.ics +43 -0
  370. data/spec/support/samples/ical_z.ics +10 -0
  371. data/spec/support/samples/meetup.ics +16 -0
  372. data/spec/support/samples/meetup.json +31 -0
  373. data/spec/support/samples/plancast.ics +59 -0
  374. data/spec/support/samples/plancast.json +51 -0
  375. data/spec/support/samples/plancast_with_missing_venue.json +39 -0
  376. data/spec/support/samples/upcoming_v1.xml +8 -0
  377. data/spec/support/samples/upcoming_v2_with_invalid_utc_dates.xml +8 -0
  378. data/spec/support/time_convenience_methods.rb +8 -0
  379. data/spec/support/time_zones.rb +12 -0
  380. data/spec/support/url_helpers.rb +5 -0
  381. data/spec/support/wait_for_ajax.rb +15 -0
  382. data/spec/support/webmock.rb +8 -0
  383. data/spec/travis_spec.rb +7 -0
  384. metadata +1194 -0
@@ -0,0 +1,110 @@
1
+ @import url(https://fonts.googleapis.com/css?family=Sanchez);
2
+
3
+ body {
4
+ background: #BEF598;
5
+ color: #445545;
6
+ text-align: center;
7
+ font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
8
+ font-size: 18px;
9
+ margin: 2em 0;
10
+ }
11
+ h1, h2 {
12
+ font-family: Sanchez;
13
+ line-height: 1.1;
14
+ }
15
+ h1 {
16
+ font-size: 150%;
17
+ }
18
+ h2 {
19
+ font-size: 120%;
20
+ color: #377B15;
21
+ }
22
+ a {
23
+ color: #fff;
24
+ background: #377B15;
25
+ text-decoration: none;
26
+ display: inline-block;
27
+ border-radius: .5em;
28
+ padding: .5em;
29
+ font-weight: bold;
30
+ }
31
+ #alligator {
32
+ background: #fff;
33
+ border-radius: 50%;
34
+ border: 1px solid #9CD579;
35
+ position: relative;
36
+ width: 340px;
37
+ height: 340px;
38
+ margin: 2em auto 1.5em;
39
+ }
40
+ #alligator:before {
41
+ content: " ";
42
+ position: absolute;
43
+ top: 10px;
44
+ left: 10px;
45
+ right: 10px;
46
+ bottom: 10px;
47
+ border: 2px solid #7FAB4C;
48
+ border-radius: 50%;
49
+ }
50
+ #alligator img {
51
+ z-index: 10;
52
+ position: absolute;
53
+ top: 35px;
54
+ left: 30px;
55
+ width: 300px;
56
+ }
57
+ .guide {
58
+ border: 1px solid #9CD579;
59
+ padding: 2em;
60
+ background: #fff;
61
+ }
62
+
63
+ @-webkit-keyframes confused {
64
+ 20% {
65
+ -webkit-transform: rotate3d(0, 0, 1, 2deg);
66
+ transform: rotate3d(0, 0, 1, 2deg);
67
+ }
68
+
69
+ 60% {
70
+ -webkit-transform: rotate3d(0, 0, 1, -5deg);
71
+ transform: rotate3d(0, 0, 1, -5deg);
72
+ }
73
+
74
+ 100% {
75
+ -webkit-transform: rotate3d(0, 0, 1, 0deg);
76
+ transform: rotate3d(0, 0, 1, 0deg);
77
+ }
78
+ }
79
+
80
+ @keyframes confused {
81
+ 20% {
82
+ -webkit-transform: rotate3d(0, 0, 1, 2deg);
83
+ -ms-transform: rotate3d(0, 0, 1, 2deg);
84
+ transform: rotate3d(0, 0, 1, 2deg);
85
+ }
86
+
87
+ 60% {
88
+ -webkit-transform: rotate3d(0, 0, 1, -5deg);
89
+ -ms-transform: rotate3d(0, 0, 1, -5deg);
90
+ transform: rotate3d(0, 0, 1, -5deg);
91
+ }
92
+
93
+ 100% {
94
+ -webkit-transform: rotate3d(0, 0, 1, 0deg);
95
+ -ms-transform: rotate3d(0, 0, 1, 0deg);
96
+ transform: rotate3d(0, 0, 1, 0deg);
97
+ }
98
+ }
99
+
100
+ #alligator img {
101
+ -webkit-transform-origin: 100px 300px;
102
+ -ms-transform-origin: top center;
103
+ transform-origin: top center;
104
+ -webkit-animation-name: confused;
105
+ animation-name: confused;
106
+ -webkit-animation-duration: 6s;
107
+ -webkit-animation-delay: 0s;
108
+ -webkit-animation-iteration-count: infinite;
109
+ }
110
+
@@ -0,0 +1,4 @@
1
+ /*
2
+ *= require calagator/datepicker
3
+ *= require jquery.timepicker
4
+ */
@@ -0,0 +1,40 @@
1
+ /* ##############################################################
2
+
3
+ reset.css
4
+ * Resets default browser CSS.
5
+
6
+ Originally from blueprint-css v0.7.1
7
+
8
+ ############################################################## */
9
+
10
+ html, body, div, span, object, iframe,
11
+ h1, h2, h3, h4, h5, h6, p, blockquote, pre,
12
+ a, abbr, acronym, address, code,
13
+ del, dfn, em, img, q, dl, dt, dd, ol, ul, li,
14
+ fieldset, form, label, legend,
15
+ table, caption, tbody, tfoot, thead, tr, th, td {
16
+ margin: 0;
17
+ padding: 0;
18
+ border: 0;
19
+ font-weight: inherit;
20
+ font-style: inherit;
21
+ font-size: 100%;
22
+ font-family: inherit;
23
+ vertical-align: baseline;
24
+ }
25
+
26
+ body {
27
+ line-height: 1.5;
28
+ }
29
+
30
+ /* Tables still need 'cellspacing="0"' in the markup. */
31
+ table { border-collapse: separate; border-spacing: 0; }
32
+ caption, th, td { text-align: left; font-weight: normal; }
33
+ table, td, th { vertical-align: middle; }
34
+
35
+ /* Remove possible quote marks (") from <q>, <blockquote>. */
36
+ blockquote:before, blockquote:after, q:before, q:after { content: ""; }
37
+ blockquote, q { quotes: "" ""; }
38
+
39
+ /* Remove annoying border on linked images. */
40
+ a img { border: none; }
@@ -0,0 +1,27 @@
1
+ module Calagator
2
+
3
+ class AdminController < ApplicationController
4
+ require_admin
5
+
6
+ def index
7
+ end
8
+
9
+ def events
10
+ @events = Event.future
11
+ end
12
+
13
+ def lock_event
14
+ @event = Event.find(params[:event_id])
15
+ if @event.locked?
16
+ @event.unlock_editing!
17
+ flash[:success] = "Unlocked event #{@event.title} (#{@event.id})"
18
+ else
19
+ @event.lock_editing!
20
+ flash[:success] = "Locked event #{@event.title} (#{@event.id})"
21
+ end
22
+ redirect_to :action => :events
23
+ end
24
+
25
+ end
26
+
27
+ end
@@ -0,0 +1,82 @@
1
+ # Filters added to this controller apply to all controllers in the application.
2
+ # Likewise, all the methods added will be available for all controllers.
3
+
4
+ module Calagator
5
+
6
+ class ApplicationController < ActionController::Base
7
+ helper Calagator::EventsHelper
8
+ helper Calagator::ApplicationHelper
9
+ helper Calagator::EventsHelper
10
+ helper Calagator::GoogleEventExportHelper
11
+ helper Calagator::MappingHelper
12
+ helper Calagator::SourcesHelper
13
+ helper Calagator::TagsHelper
14
+ helper Calagator::TimeRangeHelper
15
+
16
+ helper :all # include all helpers, all the time
17
+
18
+ # See ActionController::RequestForgeryProtection for details
19
+ # Uncomment the :secret if you're not using the cookie session store
20
+ protect_from_forgery # :secret => '8813a7fec0bb4fbffd283a3868998eed'
21
+
22
+ # Setup theme
23
+
24
+ protected
25
+
26
+ def self.require_admin(options = {})
27
+ http_basic_authenticate_with(
28
+ options.reverse_merge(
29
+ :name => SECRETS.admin_username,
30
+ :password => SECRETS.admin_password,
31
+ :if => Proc.new { SECRETS.admin_username && SECRETS.admin_password }
32
+ )
33
+ )
34
+ end
35
+
36
+ #---[ Helpers ]---------------------------------------------------------
37
+
38
+ # Returns a data structure used for telling the CSS menu which part of the
39
+ # site the user is on. The structure's keys are the symbol names of resources
40
+ # and their values are either "active" or nil.
41
+ def link_class
42
+ return @_link_class_cache ||= {
43
+ :events => (( controller_name == 'events' ||
44
+ controller_name == 'sources' ||
45
+ controller_name == 'site') && 'active'),
46
+ :venues => (controller_name == 'venues' && 'active'),
47
+ }
48
+ end
49
+ helper_method :link_class
50
+
51
+ #---[ Misc ]------------------------------------------------------------
52
+
53
+ # Set or append flash +message+ (e.g. "OMG!") to flash key with the name
54
+ # +kind+ (e.g. :failure).
55
+ def append_flash(kind, message)
56
+ kind = kind.to_sym
57
+ if leaf = flash[kind]
58
+ flash[kind] = "#{leaf} #{message}"
59
+ else
60
+ flash[kind] = "#{message}"
61
+ end
62
+ end
63
+
64
+ # Make it possible to use helpers in controllers
65
+ # http://www.johnyerhot.com/2008/01/10/rails-using-helpers-in-you-controller/
66
+ class Helper
67
+ include Singleton
68
+ include ActionView::Helpers::UrlHelper # Provide: #link_to
69
+ include ActionView::Helpers::TagHelper # Provide: #escape_once (which #link_to needs)
70
+ end
71
+
72
+ def help
73
+ Helper.instance
74
+ end
75
+
76
+ # Return string with contents HTML escaped once.
77
+ def escape_once(*args)
78
+ help.escape_once(*args)
79
+ end
80
+ end
81
+
82
+ end
@@ -0,0 +1,171 @@
1
+ require "calagator/duplicate_checking/controller_actions"
2
+
3
+ module Calagator
4
+
5
+ class EventsController < ApplicationController
6
+ # Provides #duplicates and #squash_many_duplicates
7
+ include DuplicateChecking::ControllerActions
8
+ require_admin only: [:duplicates, :squash_many_duplicates]
9
+
10
+ before_filter :find_and_redirect_if_locked, :only => [:edit, :update, :destroy]
11
+
12
+ # GET /events
13
+ # GET /events.xml
14
+ def index
15
+ @start_date = date_or_default_for(:start)
16
+ @end_date = date_or_default_for(:end)
17
+
18
+ query = Event.non_duplicates.ordered_by_ui_field(params[:order]).includes(:venue, :tags)
19
+ @events = params[:date] ?
20
+ query.within_dates(@start_date, @end_date) :
21
+ query.future
22
+
23
+ @perform_caching = params[:order].blank? && params[:date].blank?
24
+
25
+ render_events @events
26
+ end
27
+
28
+ # GET /events/1
29
+ # GET /events/1.xml
30
+ def show
31
+ @event = Event.find(params[:id])
32
+ return redirect_to(@event.progenitor) if @event.duplicate?
33
+
34
+ render_event @event
35
+ rescue ActiveRecord::RecordNotFound => e
36
+ return redirect_to events_path, flash: { failure: e.to_s }
37
+ end
38
+
39
+ # GET /events/new
40
+ # GET /events/new.xml
41
+ def new
42
+ @event = Event.new(params[:event])
43
+ end
44
+
45
+ # GET /events/1/edit
46
+ def edit
47
+ end
48
+
49
+ # POST /events
50
+ # POST /events.xml
51
+ def create
52
+ @event = Event.new
53
+ create_or_update
54
+ end
55
+
56
+ # PUT /events/1
57
+ # PUT /events/1.xml
58
+ def update
59
+ create_or_update
60
+ end
61
+
62
+ def create_or_update
63
+ saver = Event::Saver.new(@event, params)
64
+ respond_to do |format|
65
+ if saver.save
66
+ format.html {
67
+ flash[:success] = 'Event was successfully saved.'
68
+ if saver.has_new_venue?
69
+ flash[:success] += " Please tell us more about where it's being held."
70
+ redirect_to edit_venue_url(@event.venue, from_event: @event.id)
71
+ else
72
+ redirect_to @event
73
+ end
74
+ }
75
+ format.xml { render :xml => @event, :status => :created, :location => @event }
76
+ else
77
+ format.html {
78
+ flash[:failure] = saver.failure
79
+ render action: @event.new_record? ? "new" : "edit"
80
+ }
81
+ format.xml { render :xml => @event.errors, :status => :unprocessable_entity }
82
+ end
83
+ end
84
+ end
85
+
86
+ # DELETE /events/1
87
+ # DELETE /events/1.xml
88
+ def destroy
89
+ @event.destroy
90
+
91
+ respond_to do |format|
92
+ format.html { redirect_to(events_url, :flash => {:success => "\"#{@event.title}\" has been deleted"}) }
93
+ format.xml { head :ok }
94
+ end
95
+ end
96
+
97
+ # GET /events/search
98
+ def search
99
+ @search = Event::Search.new(params)
100
+
101
+ flash[:failure] = @search.failure_message
102
+ return redirect_to root_path if @search.hard_failure?
103
+
104
+ # setting @events so that we can reuse the index atom builder
105
+ @events = @search.events
106
+
107
+ render_events(@events)
108
+ end
109
+
110
+ def clone
111
+ @event = Event::Cloner.clone(Event.find(params[:id]))
112
+ flash[:success] = "This is a new event cloned from an existing one. Please update the fields, like the time and description."
113
+ render "new"
114
+ end
115
+
116
+ private
117
+
118
+ def render_event(event)
119
+ respond_to do |format|
120
+ format.html # show.html.erb
121
+ format.xml { render :xml => event.to_xml(root: "events", :include => :venue) }
122
+ format.json { render :json => event.to_json(:include => :venue), :callback => params[:callback] }
123
+ format.ics { render :ics => [event] }
124
+ end
125
+ end
126
+
127
+ # Render +events+ for a particular format.
128
+ def render_events(events)
129
+ respond_to do |format|
130
+ format.html # *.html.erb
131
+ format.kml # *.kml.erb
132
+ format.ics { render :ics => events || Event.future.non_duplicates }
133
+ format.atom { render :template => 'calagator/events/index' }
134
+ format.xml { render :xml => events.to_xml(root: "events", :include => :venue) }
135
+ format.json { render :json => events.to_json(:include => :venue), :callback => params[:callback] }
136
+ end
137
+ end
138
+
139
+ # Return the default start date.
140
+ def default_start_date
141
+ Time.zone.today
142
+ end
143
+
144
+ # Return the default end date.
145
+ def default_end_date
146
+ Time.zone.today + 3.months
147
+ end
148
+
149
+ # Return a date parsed from user arguments or a default date. The +kind+
150
+ # is a value like :start, which refers to the `params[:date][+kind+]` value.
151
+ # If there's an error, set an error message to flash.
152
+ def date_or_default_for(kind)
153
+ default = send("default_#{kind}_date")
154
+ return default unless params[:date].present?
155
+
156
+ Date.parse(params[:date][kind])
157
+ rescue NoMethodError, ArgumentError, TypeError
158
+ append_flash :failure, "Can't filter by an invalid #{kind} date."
159
+ default
160
+ end
161
+
162
+ def find_and_redirect_if_locked
163
+ @event = Event.find(params[:id])
164
+ if @event.locked?
165
+ flash[:failure] = "You are not permitted to modify this event."
166
+ redirect_to root_path
167
+ end
168
+ end
169
+ end
170
+
171
+ end
@@ -0,0 +1,35 @@
1
+ module Calagator
2
+
3
+ class SiteController < ApplicationController
4
+ # Raise exception, mostly for confirming that exception_notification works
5
+ def omfg
6
+ raise ArgumentError, "OMFG"
7
+ end
8
+
9
+ # Render something to help benchmark stack without the views
10
+ def hello
11
+ render :text => "hello"
12
+ end
13
+
14
+ def index
15
+ @overview = Event::Overview.new
16
+ respond_to do |format|
17
+ format.html { }
18
+ format.any { redirect_to events_path(format: params[:format]) }
19
+ end
20
+ end
21
+
22
+ # Displays the about page.
23
+ def about; end
24
+
25
+ def opensearch
26
+ respond_to do |format|
27
+ format.xml { render :content_type => 'application/opensearchdescription+xml' }
28
+ end
29
+ end
30
+
31
+ def defunct
32
+ end
33
+ end
34
+
35
+ end