├── .rspec ├── app ├── decorators │ ├── models │ │ └── refinery │ │ │ └── .gitkeep │ └── controllers │ │ └── refinery │ │ └── .gitkeep ├── views │ ├── refinery │ │ └── calendar │ │ │ ├── admin │ │ │ ├── events │ │ │ │ ├── new.html.erb │ │ │ │ ├── edit.html.erb │ │ │ │ ├── _events.html.erb │ │ │ │ ├── _sortable_list.html.erb │ │ │ │ ├── index.html.erb │ │ │ │ ├── _records.html.erb │ │ │ │ ├── _event.html.erb │ │ │ │ ├── _actions.html.erb │ │ │ │ └── _form.html.erb │ │ │ ├── venues │ │ │ │ ├── new.html.erb │ │ │ │ ├── edit.html.erb │ │ │ │ ├── _venues.html.erb │ │ │ │ ├── _sortable_list.html.erb │ │ │ │ ├── index.html.erb │ │ │ │ ├── _records.html.erb │ │ │ │ ├── _venue.html.erb │ │ │ │ ├── _actions.html.erb │ │ │ │ └── _form.html.erb │ │ │ └── shared │ │ │ │ └── _links.html.erb │ │ │ ├── events │ │ │ ├── index.html.erb │ │ │ ├── _event.html.erb │ │ │ └── show.html.erb │ │ │ └── venues │ │ │ ├── index.html.erb │ │ │ └── show.html.erb │ └── sitemap │ │ └── index.xml.builder ├── controllers │ └── refinery │ │ └── calendar │ │ ├── venues_controller.rb │ │ ├── admin │ │ ├── venues_controller.rb │ │ └── events_controller.rb │ │ └── events_controller.rb └── models │ └── refinery │ └── calendar │ ├── venue.rb │ └── event.rb ├── lib ├── refinerycms-calendar.rb ├── tasks │ └── refinery │ │ └── calendar.rake ├── refinery │ ├── venues │ │ └── engine.rb │ ├── events.rb │ ├── venues.rb │ └── events │ │ └── engine.rb └── generators │ └── refinery │ └── calendar_generator.rb ├── features ├── support │ ├── factories │ │ ├── event_categories.rb │ │ └── events.rb │ └── paths.rb ├── step_definitions │ └── event_steps.rb └── manage_events.feature ├── vendor └── assets │ ├── images │ └── chosen-sprite.png │ ├── stylesheets │ └── chosen.css │ └── javascripts │ └── chosen.jquery.min.js ├── tasks ├── rspec.rake └── testing.rake ├── spec ├── support │ └── factories │ │ └── refinery │ │ ├── venues.rb │ │ └── events.rb ├── models │ └── refinery │ │ └── calendar │ │ ├── venue_spec.rb │ │ └── event_spec.rb ├── spec_helper.rb └── requests │ └── refinery │ └── calendar │ └── admin │ ├── venues_spec.rb │ └── events_spec.rb ├── config ├── initializers │ └── refinery │ │ ├── authentication.rb │ │ ├── resources.rb │ │ ├── pages.rb │ │ ├── core.rb │ │ └── images.rb ├── database.yml.mysql ├── database.yml.sqlite3 ├── routes.rb ├── database.yml.postgresql └── locales │ ├── es.yml │ ├── en.yml │ ├── nb.yml │ ├── fr.yml │ └── nl.yml ├── readme.md ├── script └── rails ├── Rakefile ├── db ├── migrate │ ├── 2_create_calendar_venues.rb │ └── 1_create_calendar_events.rb └── seeds.rb ├── refinerycms-calendar.gemspec ├── .gitignore ├── public └── stylesheets │ └── refinerycms-events.css ├── Guardfile ├── changelog.md ├── Gemfile └── Gemfile.lock /.rspec: -------------------------------------------------------------------------------- 1 | --color 2 | --format progress 3 | -------------------------------------------------------------------------------- /app/decorators/models/refinery/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /app/decorators/controllers/refinery/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /app/views/refinery/calendar/admin/events/new.html.erb: -------------------------------------------------------------------------------- 1 | <%= render 'form' %> 2 | -------------------------------------------------------------------------------- /app/views/refinery/calendar/admin/venues/new.html.erb: -------------------------------------------------------------------------------- 1 | <%= render 'form' %> 2 | -------------------------------------------------------------------------------- /app/views/refinery/calendar/admin/events/edit.html.erb: -------------------------------------------------------------------------------- 1 | <%= render 'form' %> 2 | -------------------------------------------------------------------------------- /app/views/refinery/calendar/admin/venues/edit.html.erb: -------------------------------------------------------------------------------- 1 | <%= render 'form' %> 2 | -------------------------------------------------------------------------------- /lib/refinerycms-calendar.rb: -------------------------------------------------------------------------------- 1 | require 'refinery/events' 2 | require 'refinery/venues' 3 | -------------------------------------------------------------------------------- /features/support/factories/event_categories.rb: -------------------------------------------------------------------------------- 1 | Factory.define :event_category do |f| 2 | f.sequence(:name) { |n| "Class/Lecture #{n}" } 3 | end -------------------------------------------------------------------------------- /vendor/assets/images/chosen-sprite.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/progressbar/refinerycms-calendar/master/vendor/assets/images/chosen-sprite.png -------------------------------------------------------------------------------- /tasks/rspec.rake: -------------------------------------------------------------------------------- 1 | require 'rspec/core/rake_task' 2 | 3 | desc "Run specs" 4 | RSpec::Core::RakeTask.new do |t| 5 | t.pattern = "./spec" 6 | end 7 | -------------------------------------------------------------------------------- /app/controllers/refinery/calendar/venues_controller.rb: -------------------------------------------------------------------------------- 1 | module Refinery 2 | module Calendar 3 | class VenuesController < ::ApplicationController 4 | end 5 | end 6 | end 7 | -------------------------------------------------------------------------------- /app/views/refinery/calendar/admin/events/_events.html.erb: -------------------------------------------------------------------------------- 1 | <%= will_paginate @events if Refinery::Calendar::Admin::EventsController.pageable? %> 2 | <%= render 'sortable_list' %> 3 | -------------------------------------------------------------------------------- /app/views/refinery/calendar/admin/venues/_venues.html.erb: -------------------------------------------------------------------------------- 1 | <%= will_paginate @venues if Refinery::Calendar::Admin::VenuesController.pageable? %> 2 | <%= render 'sortable_list' %> 3 | -------------------------------------------------------------------------------- /spec/support/factories/refinery/venues.rb: -------------------------------------------------------------------------------- 1 | 2 | FactoryGirl.define do 3 | factory :venue, :class => Refinery::Calendar::Venue do 4 | sequence(:name) { |n| "refinery#{n}" } 5 | end 6 | end 7 | 8 | -------------------------------------------------------------------------------- /spec/support/factories/refinery/events.rb: -------------------------------------------------------------------------------- 1 | 2 | FactoryGirl.define do 3 | factory :event, :class => Refinery::Calendar::Event do 4 | sequence(:title) { |n| "refinery#{n}" } 5 | end 6 | end 7 | 8 | -------------------------------------------------------------------------------- /config/initializers/refinery/authentication.rb: -------------------------------------------------------------------------------- 1 | Refinery::Authentication.configure do |config| 2 | # Configure whether to allow superuser to assign roles 3 | # config.superuser_can_assign_roles = false 4 | end 5 | -------------------------------------------------------------------------------- /app/views/refinery/calendar/events/index.html.erb: -------------------------------------------------------------------------------- 1 | <% content_for :body_content_left do %> 2 |
3 | <%= render @events %> 4 |
5 | <% end %> 6 | 7 | <% content_for :stylesheets, stylesheet_link_tag('events') %> 8 | 9 | <%= render '/refinery/content_page' %> 10 | -------------------------------------------------------------------------------- /tasks/testing.rake: -------------------------------------------------------------------------------- 1 | namespace :refinery do 2 | namespace :testing do 3 | # Put any code in here that you want run when you test this extension against a dummy app. 4 | # For example, the call to require your gem and start your generator. 5 | task :setup_extension do 6 | end 7 | end 8 | end 9 | -------------------------------------------------------------------------------- /app/models/refinery/calendar/venue.rb: -------------------------------------------------------------------------------- 1 | module Refinery 2 | module Calendar 3 | class Venue < Refinery::Core::BaseModel 4 | has_many :events 5 | validates :name, :presence => true, :uniqueness => true 6 | attr_accessible :name, :address, :url, :phone, :position 7 | end 8 | end 9 | end 10 | -------------------------------------------------------------------------------- /app/views/refinery/calendar/admin/events/_sortable_list.html.erb: -------------------------------------------------------------------------------- 1 | 4 | <%= render '/refinery/admin/sortable_list', 5 | :continue_reordering => (local_assigns.keys.include?(:continue_reordering)) ? continue_reordering : true %> 6 | -------------------------------------------------------------------------------- /app/views/refinery/calendar/admin/venues/_sortable_list.html.erb: -------------------------------------------------------------------------------- 1 | 4 | <%= render '/refinery/admin/sortable_list', 5 | :continue_reordering => (local_assigns.keys.include?(:continue_reordering)) ? continue_reordering : true %> 6 | -------------------------------------------------------------------------------- /app/views/refinery/calendar/events/_event.html.erb: -------------------------------------------------------------------------------- 1 | <%= div_for event do -%> 2 | 5 | 6 |

<%= link_to event.title, refinery.calendar_event_path(event) %>

7 |

<%= event.excerpt %>

8 | <% end -%> 9 | -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 | # Calendar extension for Refinery CMS. 2 | 3 | ## Installation 4 | 5 | ```ruby 6 | # in Gemfile: 7 | gem 'refinerycms-calendar', '~>2.0.0' 8 | ``` 9 | 10 | ``` 11 | # in console: 12 | 13 | bundle 14 | rails g refinery:calendar 15 | rake db:migrate db:seed db:test:prepare 16 | ``` 17 | 18 | Restart the server 19 | -------------------------------------------------------------------------------- /lib/tasks/refinery/calendar.rake: -------------------------------------------------------------------------------- 1 | namespace :refinery do 2 | 3 | namespace :calendar do 4 | 5 | # call this task by running: rake refinery:calendar:my_task 6 | # desc "Description of my task below" 7 | # task :my_task => :environment do 8 | # # add your logic here 9 | # end 10 | 11 | end 12 | 13 | end -------------------------------------------------------------------------------- /app/views/refinery/calendar/admin/shared/_links.html.erb: -------------------------------------------------------------------------------- 1 |
  • 2 | <%= link_to t('.manage_events'), refinery.calendar_admin_events_path, 3 | :class => "manage_icon" %> 4 |
  • 5 |
  • 6 | <%= link_to t('.manage_venues'), refinery.calendar_admin_venues_path, 7 | :class => "manage_icon" %> 8 |
  • 9 | -------------------------------------------------------------------------------- /features/support/factories/events.rb: -------------------------------------------------------------------------------- 1 | Factory.define :event do |f| 2 | f.sequence(:title) { |n| "Top #{n} Shopping Centers in Chicago" } 3 | f.description "These are the top ten shopping centers in Chicago. You're going to read a long blog post about them. Come to peace with it." 4 | f.start_at Time.now 5 | f.end_at Time.now.advance(:hours => 1) 6 | end -------------------------------------------------------------------------------- /app/views/refinery/calendar/venues/index.html.erb: -------------------------------------------------------------------------------- 1 | <% content_for :body_content_left do %> 2 | 9 | <% end %> 10 | 11 | <%= render '/refinery/content_page' %> 12 | -------------------------------------------------------------------------------- /lib/refinery/venues/engine.rb: -------------------------------------------------------------------------------- 1 | module Refinery 2 | module Calendar 3 | class Engine < Rails::Engine 4 | include Refinery::Engine 5 | isolate_namespace Refinery::Calendar 6 | 7 | engine_name :refinery_calendar 8 | 9 | config.after_initialize do 10 | Refinery.register_extension(Refinery::Venues) 11 | end 12 | end 13 | end 14 | end 15 | -------------------------------------------------------------------------------- /app/views/refinery/calendar/admin/events/index.html.erb: -------------------------------------------------------------------------------- 1 |
    2 |

    Calendar: Events

    3 | <%= render 'records' %> 4 |
    5 | 8 | <%= render '/refinery/admin/make_sortable', :tree => false if !searching? and ::Refinery::Calendar::Admin::EventsController.sortable? and ::Refinery::Calendar::Event.count > 1 %> 9 | -------------------------------------------------------------------------------- /app/views/refinery/calendar/admin/venues/index.html.erb: -------------------------------------------------------------------------------- 1 |
    2 |

    Calendar: Venues

    3 | <%= render 'records' %> 4 |
    5 | 8 | <%= render '/refinery/admin/make_sortable', :tree => false if !searching? and ::Refinery::Calendar::Admin::VenuesController.sortable? and ::Refinery::Calendar::Venue.count > 1 %> 9 | -------------------------------------------------------------------------------- /features/support/paths.rb: -------------------------------------------------------------------------------- 1 | module NavigationHelpers 2 | module Refinery 3 | module Events 4 | def path_to(page_name) 5 | case page_name 6 | when /the list of events/ 7 | admin_events_path 8 | 9 | when /the new event form/ 10 | new_admin_event_path 11 | else 12 | nil 13 | end 14 | end 15 | end 16 | end 17 | end 18 | -------------------------------------------------------------------------------- /features/step_definitions/event_steps.rb: -------------------------------------------------------------------------------- 1 | Given /^I have no events$/ do 2 | Event.delete_all 3 | end 4 | 5 | Given /^I (only )?have events titled "?([^\"]*)"?$/ do |only, titles| 6 | Event.delete_all if only 7 | titles.split(', ').each do |title| 8 | Factory(:event, :title => title) 9 | end 10 | end 11 | 12 | Then /^I should have ([0-9]+) events?$/ do |count| 13 | Event.count.should == count.to_i 14 | end 15 | -------------------------------------------------------------------------------- /app/controllers/refinery/calendar/admin/venues_controller.rb: -------------------------------------------------------------------------------- 1 | module Refinery 2 | module Calendar 3 | module Admin 4 | class VenuesController < ::Refinery::AdminController 5 | 6 | crudify :'refinery/calendar/venue', 7 | :title_attribute => 'name', 8 | :xhr_paging => true, 9 | :sortable => false, 10 | :order => 'created_at DESC' 11 | end 12 | end 13 | end 14 | end 15 | -------------------------------------------------------------------------------- /spec/models/refinery/calendar/venue_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | 3 | module Refinery 4 | module Calendar 5 | describe Venue do 6 | describe "validations" do 7 | subject do 8 | FactoryGirl.create(:venue, 9 | :name => "Refinery CMS") 10 | end 11 | 12 | it { should be_valid } 13 | its(:errors) { should be_empty } 14 | its(:name) { should == "Refinery CMS" } 15 | end 16 | end 17 | end 18 | end 19 | -------------------------------------------------------------------------------- /spec/models/refinery/calendar/event_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | 3 | module Refinery 4 | module Calendar 5 | describe Event do 6 | describe "validations" do 7 | subject do 8 | FactoryGirl.create(:event, 9 | :title => "Refinery CMS") 10 | end 11 | 12 | it { should be_valid } 13 | its(:errors) { should be_empty } 14 | its(:title) { should == "Refinery CMS" } 15 | end 16 | end 17 | end 18 | end 19 | -------------------------------------------------------------------------------- /script/rails: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | # This command will automatically be run when you run "rails" with Rails 3 gems installed from the root of your application. 3 | 4 | ENGINE_PATH = File.expand_path('../..', __FILE__) 5 | dummy_rails_path = File.expand_path('../../spec/dummy/script/rails', __FILE__) 6 | if File.exist?(dummy_rails_path) 7 | load dummy_rails_path 8 | else 9 | puts "Please first run 'rake refinery:testing:dummy_app' to create a dummy Refinery CMS application." 10 | end 11 | -------------------------------------------------------------------------------- /config/database.yml.mysql: -------------------------------------------------------------------------------- 1 | development: &development 2 | adapter: mysql2 3 | host: localhost 4 | username: root 5 | password: 6 | database: your_local_database 7 | 8 | test: &test 9 | adapter: mysql2 10 | host: localhost 11 | username: root 12 | password: 13 | database: your_test_database 14 | 15 | production: &production 16 | adapter: mysql2 17 | host: localhost 18 | database: your_production_database 19 | username: your_production_database_login 20 | password: your_production_database_password 21 | -------------------------------------------------------------------------------- /lib/refinery/events.rb: -------------------------------------------------------------------------------- 1 | require 'refinerycms-core' 2 | 3 | module Refinery 4 | autoload :CalendarGenerator, 'generators/refinery/calendar_generator' 5 | 6 | module Events 7 | require 'refinery/events/engine' 8 | 9 | class << self 10 | attr_writer :root 11 | 12 | def root 13 | @root ||= Pathname.new(File.expand_path('../../../', __FILE__)) 14 | end 15 | 16 | def factory_paths 17 | @factory_paths ||= [ root.join('spec', 'factories').to_s ] 18 | end 19 | end 20 | end 21 | end 22 | -------------------------------------------------------------------------------- /lib/refinery/venues.rb: -------------------------------------------------------------------------------- 1 | require 'refinerycms-core' 2 | 3 | module Refinery 4 | autoload :CalendarGenerator, 'generators/refinery/calendar_generator' 5 | 6 | module Venues 7 | require 'refinery/venues/engine' 8 | 9 | class << self 10 | attr_writer :root 11 | 12 | def root 13 | @root ||= Pathname.new(File.expand_path('../../../', __FILE__)) 14 | end 15 | 16 | def factory_paths 17 | @factory_paths ||= [ root.join('spec', 'factories').to_s ] 18 | end 19 | end 20 | end 21 | end 22 | -------------------------------------------------------------------------------- /lib/generators/refinery/calendar_generator.rb: -------------------------------------------------------------------------------- 1 | module Refinery 2 | class CalendarGenerator < Rails::Generators::Base 3 | 4 | def rake_db 5 | rake("refinery_calendar:install:migrations") 6 | end 7 | 8 | def append_load_seed_data 9 | create_file 'db/seeds.rb' unless File.exists?(File.join(destination_root, 'db', 'seeds.rb')) 10 | append_file 'db/seeds.rb', :verbose => true do 11 | <<-EOH 12 | 13 | # Added by Refinery CMS Venues extension 14 | Refinery::Calendar::Engine.load_seed 15 | EOH 16 | end 17 | end 18 | end 19 | end 20 | -------------------------------------------------------------------------------- /app/controllers/refinery/calendar/admin/events_controller.rb: -------------------------------------------------------------------------------- 1 | module Refinery 2 | module Calendar 3 | module Admin 4 | class EventsController < ::Refinery::AdminController 5 | before_filter :find_venues, :except => [:index, :destroy] 6 | 7 | crudify :'refinery/calendar/event', 8 | :xhr_paging => true, 9 | :sortable => false, 10 | :order => "'from' DESC" 11 | 12 | private 13 | def find_venues 14 | @venues = Venue.order('name') 15 | end 16 | end 17 | end 18 | end 19 | end 20 | -------------------------------------------------------------------------------- /app/views/refinery/calendar/admin/events/_records.html.erb: -------------------------------------------------------------------------------- 1 | <% if searching? %> 2 |

    <%= t('results_for', :scope => 'refinery.admin.search', :query => params[:search]) %>

    3 | <% end %> 4 |
    5 | <% if @events.any? %> 6 | <%= render 'events' %> 7 | <% else %> 8 |

    9 | <% unless searching? %> 10 | 11 | <%= t('.no_items_yet') %> 12 | 13 | <% else %> 14 | <%= t('no_results', :scope => 'refinery.admin.search') %> 15 | <% end %> 16 |

    17 | <% end %> 18 |
    19 | -------------------------------------------------------------------------------- /app/views/refinery/calendar/admin/venues/_records.html.erb: -------------------------------------------------------------------------------- 1 | <% if searching? %> 2 |

    <%= t('results_for', :scope => 'refinery.admin.search', :query => params[:search]) %>

    3 | <% end %> 4 |
    5 | <% if @venues.any? %> 6 | <%= render 'venues' %> 7 | <% else %> 8 |

    9 | <% unless searching? %> 10 | 11 | <%= t('.no_items_yet') %> 12 | 13 | <% else %> 14 | <%= t('no_results', :scope => 'refinery.admin.search') %> 15 | <% end %> 16 |

    17 | <% end %> 18 |
    19 | -------------------------------------------------------------------------------- /Rakefile: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env rake 2 | begin 3 | require 'bundler/setup' 4 | rescue LoadError 5 | puts 'You must `gem install bundler` and `bundle install` to run rake tasks' 6 | end 7 | 8 | ENGINE_PATH = File.dirname(__FILE__) 9 | APP_RAKEFILE = File.expand_path("../spec/dummy/Rakefile", __FILE__) 10 | 11 | if File.exists?(APP_RAKEFILE) 12 | load 'rails/tasks/engine.rake' 13 | end 14 | 15 | require "refinerycms-testing" 16 | Refinery::Testing::Railtie.load_tasks 17 | Refinery::Testing::Railtie.load_dummy_tasks(ENGINE_PATH) 18 | 19 | load File.expand_path('../tasks/testing.rake', __FILE__) 20 | load File.expand_path('../tasks/rspec.rake', __FILE__) 21 | -------------------------------------------------------------------------------- /config/database.yml.sqlite3: -------------------------------------------------------------------------------- 1 | # SQLite version 3.x 2 | development: 3 | adapter: <%= "jdbc" if defined?(JRUBY_PLATFORM) %>sqlite3 4 | database: db/development.sqlite3 5 | timeout: 5000 6 | 7 | # Warning: The database defined as 'test' will be erased and 8 | # re-generated from your development database when you run 'rake'. 9 | # Do not set this db to the same as development or production. 10 | test: 11 | adapter: <%= "jdbc" if defined?(JRUBY_PLATFORM) %>sqlite3 12 | database: db/test.sqlite3 13 | timeout: 5000 14 | 15 | production: 16 | adapter: <%= "jdbc" if defined?(JRUBY_PLATFORM) %>sqlite3 17 | database: db/production.sqlite3 18 | timeout: 5000 19 | -------------------------------------------------------------------------------- /db/migrate/2_create_calendar_venues.rb: -------------------------------------------------------------------------------- 1 | class CreateCalendarVenues < ActiveRecord::Migration 2 | 3 | def up 4 | create_table :refinery_calendar_venues do |t| 5 | t.string :name 6 | t.string :address 7 | t.string :url 8 | t.string :phone 9 | t.integer :position 10 | 11 | t.timestamps 12 | end 13 | 14 | end 15 | 16 | def down 17 | if defined?(::Refinery::UserPlugin) 18 | ::Refinery::UserPlugin.destroy_all({:name => "refinerycms-calendar"}) 19 | end 20 | 21 | if defined?(::Refinery::Page) 22 | ::Refinery::Page.delete_all({:link_url => "/calendar/venues"}) 23 | end 24 | 25 | drop_table :refinery_calendar_venues 26 | 27 | end 28 | 29 | end 30 | -------------------------------------------------------------------------------- /refinerycms-calendar.gemspec: -------------------------------------------------------------------------------- 1 | # Encoding: UTF-8 2 | 3 | Gem::Specification.new do |s| 4 | s.platform = Gem::Platform::RUBY 5 | s.name = 'refinerycms-calendar' 6 | s.authors = ['Joe Sak', 'Philip Arndt'] 7 | s.version = '2.0.0' 8 | s.description = 'Ruby on Rails Calendar extension for Refinery CMS' 9 | s.date = '2012-04-23' 10 | s.summary = 'Calendar extension for Refinery CMS' 11 | s.require_paths = %w(lib) 12 | s.files = Dir["{app,config,db,lib}/**/*"] + ["readme.md"] 13 | 14 | # Runtime dependencies 15 | s.add_dependency 'refinerycms-core', '~> 2.0.3' 16 | 17 | # Development dependencies (usually used for testing) 18 | s.add_development_dependency 'refinerycms-testing', '~> 2.0.3' 19 | end 20 | -------------------------------------------------------------------------------- /db/migrate/1_create_calendar_events.rb: -------------------------------------------------------------------------------- 1 | class CreateCalendarEvents < ActiveRecord::Migration 2 | 3 | def up 4 | create_table :refinery_calendar_events do |t| 5 | t.string :title 6 | t.date :from 7 | t.date :to 8 | t.string :registration_link 9 | t.string :excerpt 10 | t.text :description 11 | t.integer :position 12 | t.boolean :featured 13 | t.string :slug 14 | t.integer :venue_id 15 | 16 | t.timestamps 17 | end 18 | 19 | end 20 | 21 | def down 22 | if defined?(::Refinery::UserPlugin) 23 | ::Refinery::UserPlugin.destroy_all({:name => "refinerycms-calendar"}) 24 | end 25 | 26 | if defined?(::Refinery::Page) 27 | ::Refinery::Page.delete_all({:link_url => "/calendar/events"}) 28 | end 29 | 30 | drop_table :refinery_calendar_events 31 | 32 | end 33 | 34 | end 35 | -------------------------------------------------------------------------------- /lib/refinery/events/engine.rb: -------------------------------------------------------------------------------- 1 | module Refinery 2 | module Calendar 3 | class Engine < Rails::Engine 4 | include Refinery::Engine 5 | isolate_namespace Refinery::Calendar 6 | 7 | engine_name :refinery_calendar 8 | 9 | initializer "register refinerycms_events plugin" do 10 | Refinery::Plugin.register do |plugin| 11 | plugin.name = "calendar" 12 | plugin.url = proc { Refinery::Core::Engine.routes.url_helpers.calendar_admin_events_path } 13 | plugin.pathname = root 14 | plugin.activity = { 15 | :class_name => :'refinery/calendar/event' 16 | } 17 | plugin.menu_match = %r{refinery/calendar(/.*)?$} 18 | end 19 | end 20 | 21 | config.after_initialize do 22 | Refinery.register_extension(Refinery::Events) 23 | end 24 | end 25 | end 26 | end 27 | -------------------------------------------------------------------------------- /app/views/refinery/calendar/admin/events/_event.html.erb: -------------------------------------------------------------------------------- 1 |
  • 2 | 3 | <%= event.title %> 4 | 5 | 6 | 7 | 8 | <%= link_to refinery_icon_tag("application_go.png"), refinery.calendar_event_path(event), 9 | :title => t('.view_live_html'), 10 | :target => "_blank" %> 11 | 12 | <%= link_to refinery_icon_tag("application_edit.png"), refinery.edit_calendar_admin_event_path(event), 13 | :title => t('.edit') %> 14 | <%= link_to refinery_icon_tag("delete.png"), refinery.calendar_admin_event_path(event), 15 | :class => "cancel confirm-delete", 16 | :title => t('.delete'), 17 | :confirm => t('message', :scope => 'refinery.admin.delete', :title => event.title), 18 | :method => :delete %> 19 | 20 |
  • 21 | -------------------------------------------------------------------------------- /db/seeds.rb: -------------------------------------------------------------------------------- 1 | if defined?(::Refinery::User) 2 | ::Refinery::User.all.each do |user| 3 | if user.plugins.where(:name => 'refinerycms-calendar').blank? 4 | user.plugins.create(:name => 'refinerycms-calendar', 5 | :position => (user.plugins.maximum(:position) || -1) +1) 6 | end 7 | end 8 | end 9 | 10 | 11 | url = "/calendar/venues" 12 | if defined?(::Refinery::Page) && ::Refinery::Page.where(:link_url => url).empty? 13 | page = ::Refinery::Page.create( 14 | :title => 'Venues', 15 | :link_url => url, 16 | :deletable => false, 17 | :menu_match => "^#{url}(\/|\/.+?|)$" 18 | ) 19 | Refinery::Pages.default_parts.each_with_index do |default_page_part, index| 20 | page.parts.create(:title => default_page_part, :body => nil, :position => index) 21 | end 22 | end 23 | 24 | 25 | # Added by Refinery CMS Pages extension 26 | Refinery::Pages::Engine.load_seed 27 | -------------------------------------------------------------------------------- /app/views/refinery/calendar/admin/venues/_venue.html.erb: -------------------------------------------------------------------------------- 1 |
  • 2 | 3 | <%= venue.name %> 4 | 5 | 6 | 7 | 8 | <%= link_to refinery_icon_tag("application_go.png"), refinery.calendar_venue_path(venue), 9 | :title => t('.view_live_html'), 10 | :target => "_blank" %> 11 | 12 | <%= link_to refinery_icon_tag("application_edit.png"), refinery.edit_calendar_admin_venue_path(venue), 13 | :title => t('.edit') %> 14 | <%= link_to refinery_icon_tag("delete.png"), refinery.calendar_admin_venue_path(venue), 15 | :class => "cancel confirm-delete", 16 | :title => t('.delete'), 17 | :confirm => t('message', :scope => 'refinery.admin.delete', :title => venue.name), 18 | :method => :delete %> 19 | 20 |
  • 21 | -------------------------------------------------------------------------------- /app/views/sitemap/index.xml.builder: -------------------------------------------------------------------------------- 1 | xml.instruct! 2 | 3 | xml.urlset "xmlns" => "http://www.sitemaps.org/schemas/sitemap/0.9" do 4 | 5 | @locales.each do |locale| 6 | ::I18n.locale = locale 7 | ::Refinery::Page.live.in_menu.includes(:parts).each do |page| 8 | # exclude sites that are external to our own domain. 9 | page_url = if page.url.is_a?(Hash) 10 | # This is how most pages work without being overriden by link_url 11 | page.url.merge({:only_path => false}) 12 | elsif page.url.to_s !~ /^http/ 13 | # handle relative link_url addresses. 14 | [request.protocol, request.host_with_port, page.url].join 15 | end 16 | 17 | # Add XML entry only if there is a valid page_url found above. 18 | xml.url do 19 | xml.loc url_for(page_url) 20 | xml.lastmod page.updated_at.to_date 21 | end if page_url.present? and page.show_in_menu? 22 | end 23 | end 24 | 25 | end 26 | -------------------------------------------------------------------------------- /config/routes.rb: -------------------------------------------------------------------------------- 1 | Refinery::Core::Engine.routes.append do 2 | 3 | # Frontend routes 4 | namespace :calendar, :path => 'connect' do 5 | get 'events/archive' => 'events#archive' 6 | resources :events, :only => [:index, :show] 7 | end 8 | 9 | # Admin routes 10 | namespace :calendar, :path => '' do 11 | namespace :admin, :path => 'refinery/calendar' do 12 | resources :events, :except => :show do 13 | collection do 14 | post :update_positions 15 | end 16 | end 17 | end 18 | end 19 | 20 | 21 | # Frontend routes 22 | namespace :calendar do 23 | resources :venues, :only => [:index, :show] 24 | end 25 | 26 | # Admin routes 27 | namespace :calendar, :path => '' do 28 | namespace :admin, :path => 'refinery/calendar' do 29 | resources :venues, :except => :show do 30 | collection do 31 | post :update_positions 32 | end 33 | end 34 | end 35 | end 36 | 37 | end 38 | -------------------------------------------------------------------------------- /app/models/refinery/calendar/event.rb: -------------------------------------------------------------------------------- 1 | module Refinery 2 | module Calendar 3 | class Event < Refinery::Core::BaseModel 4 | extend FriendlyId 5 | 6 | friendly_id :title, :use => :slugged 7 | 8 | belongs_to :venue 9 | 10 | validates :title, :presence => true, :uniqueness => true 11 | 12 | attr_accessible :title, :from, :to, :registration_link, 13 | :venue_id, :excerpt, :description, 14 | :featured, :position 15 | 16 | delegate :name, :address, 17 | :to => :venue, 18 | :prefix => true, 19 | :allow_nil => true 20 | 21 | class << self 22 | def upcoming 23 | where('refinery_calendar_events.from >= ?', Time.now) 24 | end 25 | 26 | def featured 27 | where(:featured => true) 28 | end 29 | 30 | def archive 31 | where('refinery_calendar_events.from < ?', Time.now) 32 | end 33 | end 34 | end 35 | end 36 | end 37 | -------------------------------------------------------------------------------- /app/views/refinery/calendar/events/show.html.erb: -------------------------------------------------------------------------------- 1 | <% content_for :body_content_title do %> 2 | <%= @event.title %> 3 | <% end %> 4 | 5 | <% content_for :body_content_left do %> 6 |

    Event details

    7 |
    <%= @event.venue_name %>
    8 | 9 |

    From <%= @event.from.strftime('%B %d, %Y %I:%M%p') %> to 10 |
    <%= @event.to.strftime('%B %d, %Y %I:%M%p') %>

    11 | 12 | <% if @event.registration_link.present? %> 13 |

    <%= link_to 'Register for this event', @event.registration_link %>

    14 | <% end -%> 15 | 16 | <% if @event.venue_address.present? %> 17 |

    <%= link_to 'View it on a map', "http://maps.google.com/maps?f=q&source=s_q&hl=en&geocode=&q=#{CGI::escape(@event.venue.address)}&ie=UTF8&z=16" %>

    18 | <% end -%> 19 | 20 |
    21 |

    <%= @event.excerpt %>

    22 | <%=raw @event.description %> 23 |
    24 | <% end %> 25 | 26 | <% content_for :stylesheets, stylesheet_link_tag('events') %> 27 | 28 | <%= render '/refinery/content_page' %> 29 | -------------------------------------------------------------------------------- /app/views/refinery/calendar/venues/show.html.erb: -------------------------------------------------------------------------------- 1 | <% content_for :body_content_title do %> 2 | <%= @venue.name %> 3 | <% end %> 4 | 5 | <% content_for :body_content_left do %> 6 |
    7 |

    Name

    8 |

    9 | <%=raw @venue.name %> 10 |

    11 |
    12 |
    13 |

    Address

    14 |

    15 | <%=raw @venue.address %> 16 |

    17 |
    18 |
    19 |

    Url

    20 |

    21 | <%=raw @venue.url %> 22 |

    23 |
    24 |
    25 |

    Phone

    26 |

    27 | <%=raw @venue.phone %> 28 |

    29 |
    30 | <% end %> 31 | 32 | <% content_for :body_content_right do %> 33 | 43 | <% end %> 44 | 45 | <%= render '/refinery/content_page' %> 46 | -------------------------------------------------------------------------------- /app/controllers/refinery/calendar/events_controller.rb: -------------------------------------------------------------------------------- 1 | module Refinery 2 | module Calendar 3 | class EventsController < ::ApplicationController 4 | def index 5 | @events = Event.upcoming.order('refinery_calendar_events.from DESC') 6 | 7 | # you can use meta fields from your model instead (e.g. browser_title) 8 | # by swapping @page for @event in the line below: 9 | present(@page) 10 | end 11 | 12 | def show 13 | @event = Event.find(params[:id]) 14 | 15 | # you can use meta fields from your model instead (e.g. browser_title) 16 | # by swapping @page for @event in the line below: 17 | present(@page) 18 | end 19 | 20 | def archive 21 | @events = Event.archive.order('refinery_calendar_events.from DESC') 22 | render :template => 'refinery/calendar/events/index' 23 | end 24 | 25 | protected 26 | def find_page 27 | @page = ::Refinery::Page.where(:link_url => "/connect/events").first 28 | end 29 | 30 | end 31 | end 32 | end 33 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | spec/dummy 2 | *.gem# Rails 3 | .bundle 4 | db/*.sqlite3 5 | db/*.sqlite3-journal 6 | *.log 7 | tmp 8 | tmp/**/* 9 | 10 | # Documentation 11 | doc/api 12 | doc/app 13 | .yardoc 14 | .yardopts 15 | coverage 16 | 17 | # Public Uploads 18 | public/system/* 19 | public/themes/* 20 | 21 | # Public Cache 22 | public/javascripts/cache 23 | public/stylesheets/cache 24 | 25 | # Vendor Cache 26 | vendor/cache 27 | 28 | # Acts as Indexed 29 | index/**/* 30 | 31 | # Refinery Specific 32 | *.tmproj 33 | *.autobackupbyrefinery.* 34 | refinerycms-*.gem 35 | 36 | # Mac 37 | .DS_Store 38 | 39 | # Windows 40 | Thumbs.db 41 | 42 | # NetBeans 43 | nbproject 44 | 45 | # Eclipse 46 | .project 47 | 48 | # Redcar 49 | .redcar 50 | 51 | # Rubinius 52 | *.rbc 53 | 54 | # Vim 55 | *.swp 56 | *.swo 57 | 58 | # RubyMine 59 | .idea 60 | 61 | # E-texteditor 62 | .eprj 63 | 64 | # Backup 65 | *~ 66 | 67 | # Capybara Bug 68 | capybara-*html 69 | 70 | # sass 71 | .sass-cache 72 | .sass-cache/* 73 | 74 | #rvm 75 | .rvmrc 76 | .rvmrc.* 77 | 78 | # vendor/extensions dummy applications. 79 | vendor/extensions/**/spec/dummy 80 | 81 | -------------------------------------------------------------------------------- /app/views/refinery/calendar/admin/events/_actions.html.erb: -------------------------------------------------------------------------------- 1 | 27 | -------------------------------------------------------------------------------- /app/views/refinery/calendar/admin/venues/_actions.html.erb: -------------------------------------------------------------------------------- 1 | 27 | -------------------------------------------------------------------------------- /app/views/refinery/calendar/admin/venues/_form.html.erb: -------------------------------------------------------------------------------- 1 | <%= form_for [refinery, :calendar_admin, @venue] do |f| -%> 2 | <%= render '/refinery/admin/error_messages', 3 | :object => @venue, 4 | :include_object_name => true %> 5 | 6 | 7 |
    8 | <%= f.label :name -%> 9 | <%= f.text_field :name, :class => 'larger widest' -%> 10 | 11 |
    12 | 13 |
    14 | <%= f.label :address -%> 15 | <%= f.text_field :address, :class => 'larger' -%> 16 | 17 |
    18 | 19 |
    20 | <%= f.label :url -%> 21 | <%= f.text_field :url, :class => 'larger' -%> 22 | 23 |
    24 | 25 |
    26 | <%= f.label :phone -%> 27 | <%= f.text_field :phone -%> 28 | 29 |
    30 | 31 | <%= render '/refinery/admin/form_actions', :f => f, 32 | :continue_editing => false, 33 | :delete_title => t('delete', :scope => 'refinery.venues.admin.venues.venue'), 34 | :delete_confirmation => t('message', :scope => 'refinery.admin.delete', :title => @venue.name) %> 35 | <% end -%> 36 | -------------------------------------------------------------------------------- /config/initializers/refinery/resources.rb: -------------------------------------------------------------------------------- 1 | Refinery::Resources.configure do |config| 2 | # Configures the maximum allowed upload size (in bytes) for a file upload 3 | # config.max_file_size = 52428800 4 | 5 | # Configure how many resources per page should be displayed when a dialog is presented that contains resources 6 | # config.pages_per_dialog = 12 7 | 8 | # Configure how many resources per page should be displayed in the list of resources in the admin area 9 | # config.pages_per_admin_index = 20 10 | 11 | # Configure S3 (you can also use ENV for this) 12 | # The s3_backend setting by default defers to the core setting for this but can be set just for resources. 13 | # config.s3_backend = Refinery::Core.s3_backend 14 | # config.s3_bucket_name = ENV['S3_BUCKET'] 15 | # config.s3_access_key_id = ENV['S3_KEY'] 16 | # config.s3_secret_access_key = ENV['S3_SECRET'] 17 | # config.s3_region = ENV['S3_REGION] 18 | 19 | # Configure Dragonfly 20 | # This is where in the middleware stack to insert the Dragonfly middleware 21 | # config.dragonfly_insert_before = "ActionDispatch::Callbacks" 22 | # config.dragonfly_secret = "3133e393cf9a9c61355f3511ea078802e3fbb313245f1154" 23 | # config.dragonfly_url_format = "/system/resources/:job/:basename.:format" 24 | # config.datastore_root_path = "/Users/joe/code/refinerycms-calendar/spec/dummy/public/system/refinery/resources" 25 | 26 | end 27 | -------------------------------------------------------------------------------- /public/stylesheets/refinerycms-events.css: -------------------------------------------------------------------------------- 1 | .individual_event { 2 | padding: 15px; 3 | margin: 0 0 10px; 4 | background-color: #f4f4f4; 5 | } 6 | .individual_event h1 { 7 | margin: 0 0 10px; 8 | padding: 0; 9 | } 10 | .individual_event .event_image { 11 | float: left; 12 | margin: 0 15px 10px 0; 13 | } 14 | #featured_events h2 { 15 | margin: 15px 0 10px; 16 | } 17 | 18 | .sidebar_module { 19 | padding: 15px; 20 | } 21 | .sidebar_module h2 { 22 | margin: 0 0 10px; 23 | } 24 | .categories a { 25 | display: block; 26 | margin: 5px 0; 27 | } 28 | .sidebar_module ul { 29 | list-style: square; 30 | padding: 0 0 0 26px; 31 | margin: 0; 32 | } 33 | .sidebar_module ul li { 34 | margin: 2px 0; 35 | padding: 2px 0; 36 | } 37 | 38 | #share_this_event { 39 | border-top: 1px solid #ddd; 40 | border-bottom: 1px solid #ddd; 41 | padding: 20px 0; 42 | margin: 20px 0; 43 | } 44 | #share_this_event ul { 45 | list-style: none; 46 | border: 0; 47 | padding: 0; 48 | margin: 0; 49 | } 50 | #share_this_event ul li { 51 | float: left; 52 | height: 70px; 53 | margin: 0 15px 0 0; 54 | } 55 | 56 | #prevnext_nav { 57 | clear: both; 58 | display: block; 59 | height: 100px; 60 | } 61 | #prevnext_nav .prev { 62 | width: 33%; 63 | float: left; 64 | } 65 | #prevnext_nav .home { 66 | width: 33%; 67 | float: left; 68 | } 69 | #prevnext_nav .next { 70 | width: 33%; 71 | float: left; 72 | } 73 | #event_map { 74 | width: 400px; 75 | height: 200px; 76 | } -------------------------------------------------------------------------------- /Guardfile: -------------------------------------------------------------------------------- 1 | guard 'spork', :wait => 60, :cucumber => false, :rspec_env => { 'RAILS_ENV' => 'test' } do 2 | watch('config/application.rb') 3 | watch('config/environment.rb') 4 | watch(%r{^config/environments/.+\.rb$}) 5 | watch(%r{^config/initializers/.+\.rb$}) 6 | watch('spec/spec_helper.rb') 7 | watch(%r{^spec/support/.+\.rb$}) 8 | watch(%r{^vendor/extensions/(.+)/spec/support/.+\.rb$}) 9 | end 10 | 11 | guard 'rspec', :version => 2, :cli => "--color --drb --format Fuubar", :all_on_start => false, :all_after_pass => false do 12 | watch(%r{^spec/.+_spec\.rb$}) 13 | watch(%r{^lib/(.+)\.rb$}) { |m| "spec/lib/#{m[1]}_spec.rb" } 14 | watch('spec/spec_helper.rb') { "spec" } 15 | 16 | # Rails example 17 | watch(%r{^spec/.+_spec\.rb$}) 18 | watch(%r{^app/(.+)\.rb$}) { |m| "spec/#{m[1]}_spec.rb" } 19 | watch(%r{^lib/(.+)\.rb$}) { |m| "spec/lib/#{m[1]}_spec.rb" } 20 | watch(%r{^app/controllers/(.+)_(controller)\.rb$}) { |m| ["spec/routing/#{m[1]}_routing_spec.rb", "spec/#{m[2]}s/#{m[1]}_#{m[2]}_spec.rb", "spec/requests/#{m[1]}_spec.rb"] } 21 | watch(%r{^spec/support/(.+)\.rb$}) { "spec" } 22 | watch('spec/spec_helper.rb') { "spec" } 23 | watch('config/routes.rb') { "spec/routing" } 24 | watch('app/controllers/application_controller.rb') { "spec/controllers" } 25 | # Capybara request specs 26 | watch(%r{^app/views/(.+)/.*\.(erb|haml)$}) { |m| "spec/requests/#{m[1]}_spec.rb" } 27 | end 28 | -------------------------------------------------------------------------------- /changelog.md: -------------------------------------------------------------------------------- 1 | ## 1.2 [UNRELEASED] 2 | 3 | ## 1.1.1 [UNRELEASED] 4 | * Controller & view template refactoring [joemsak](https://github.com/joemsak) 5 | 6 | ## 1.1 [07 July 2011] 7 | * No more unique titles [joemsak](https://github.com/joemsak) 8 | * Cached slugs for performance boost [joemsak](https://github.com/joemsak) 9 | * Easy multi-day or single-day detection for date formatting [mdoel](https://github.com/mdoel) 10 | * iCal (ics) export [joemsak](https://github.com/joemsak) 11 | * Google map of venue address [joemsak](https://github.com/joemsak) 12 | 13 | ## 1.0.4 [02 June 2011] 14 | * Archive listing should be reversed 15 | 16 | 17 | ## 1.0 [13 March 2011] 18 | 19 | * Venue Details 20 | * Ticket Pricing & Link 21 | * Feature-ability 22 | * Image attachment 23 | * Ticket price requires a number 24 | * Datetime select defaults noon to 1pm 25 | * Scopes: featured, not_featured, upcoming & current 26 | * Friendly ID based on titles 27 | * Archiving 28 | * Admin screen separates events by their status (TODO: pagination somehow) 29 | * Reasonable validations 30 | * Practical instance methods to check against scopes 31 | * Next & previous navigation on individual event pages. 32 | * has_many :categories, :through => :categorizations, :source => :event_category 33 | * RSS feed of current, upcoming & featured events 34 | * RSS in sidebar && autodiscovery 35 | * Basic layout and styling to get started immediately [blake0102](http://github.com/blake0102) 36 | * Easily hook onto a few semantic CSS classes built into the markup [blake0102](http://github.com/blake0102) 37 | * Basic Facebook & Twitter sharing interface -------------------------------------------------------------------------------- /spec/spec_helper.rb: -------------------------------------------------------------------------------- 1 | def setup_environment 2 | # Configure Rails Environment 3 | ENV["RAILS_ENV"] ||= 'test' 4 | 5 | require File.expand_path("../dummy/config/environment", __FILE__) 6 | 7 | require 'rspec/rails' 8 | require 'capybara/rspec' 9 | 10 | Rails.backtrace_cleaner.remove_silencers! 11 | 12 | RSpec.configure do |config| 13 | config.mock_with :rspec 14 | config.treat_symbols_as_metadata_keys_with_true_values = true 15 | config.filter_run :focus => true 16 | config.run_all_when_everything_filtered = true 17 | end 18 | end 19 | 20 | def each_run 21 | Rails.cache.clear 22 | ActiveSupport::Dependencies.clear 23 | FactoryGirl.reload 24 | 25 | # Requires supporting files with custom matchers and macros, etc, 26 | # in ./support/ and its subdirectories including factories. 27 | ([Rails.root.to_s] | ::Refinery::Plugins.registered.pathnames).map{|p| 28 | Dir[File.join(p, 'spec', 'support', '**', '*.rb').to_s] 29 | }.flatten.sort.each do |support_file| 30 | require support_file 31 | end 32 | end 33 | 34 | # If spork is available in the Gemfile it'll be used but we don't force it. 35 | unless (begin; require 'spork'; rescue LoadError; nil end).nil? 36 | Spork.prefork do 37 | # Loading more in this block will cause your tests to run faster. However, 38 | # if you change any configuration or code from libraries loaded here, you'll 39 | # need to restart spork for it take effect. 40 | setup_environment 41 | end 42 | 43 | Spork.each_run do 44 | # This code will be run each time you run your specs. 45 | each_run 46 | end 47 | else 48 | setup_environment 49 | each_run 50 | end 51 | -------------------------------------------------------------------------------- /Gemfile: -------------------------------------------------------------------------------- 1 | source "http://rubygems.org" 2 | 3 | gemspec 4 | 5 | gem 'refinerycms', '~> 2.0.0' 6 | 7 | # Refinery/rails should pull in the proper versions of these 8 | group :assets do 9 | gem 'sass-rails' 10 | gem 'coffee-rails' 11 | gem 'uglifier' 12 | end 13 | 14 | gem 'jquery-rails' 15 | 16 | group :development, :test do 17 | gem 'refinerycms-testing', '~> 2.0.0' 18 | gem 'factory_girl_rails' 19 | gem 'generator_spec' 20 | 21 | require 'rbconfig' 22 | 23 | platforms :jruby do 24 | gem 'activerecord-jdbcsqlite3-adapter' 25 | gem 'activerecord-jdbcmysql-adapter' 26 | gem 'activerecord-jdbcpostgresql-adapter' 27 | gem 'jruby-openssl' 28 | end 29 | 30 | unless defined?(JRUBY_VERSION) 31 | group :development, :test do 32 | gem 'sqlite3' 33 | end 34 | gem 'mysql2' 35 | gem 'pg' 36 | end 37 | 38 | platforms :mswin, :mingw do 39 | gem 'win32console' 40 | gem 'rb-fchange', '~> 0.0.5' 41 | gem 'rb-notifu', '~> 0.0.4' 42 | end 43 | 44 | platforms :ruby do 45 | gem 'spork', '0.9.0.rc9' 46 | gem 'guard-spork' 47 | 48 | unless ENV['TRAVIS'] 49 | if RbConfig::CONFIG['target_os'] =~ /darwin/i 50 | gem 'rb-fsevent', '>= 0.3.9' 51 | gem 'growl', '~> 1.0.3' 52 | end 53 | if RbConfig::CONFIG['target_os'] =~ /linux/i 54 | gem 'rb-inotify', '>= 0.5.1' 55 | gem 'libnotify', '~> 0.1.3' 56 | end 57 | end 58 | end 59 | 60 | platforms :jruby do 61 | unless ENV['TRAVIS'] 62 | if RbConfig::CONFIG['target_os'] =~ /darwin/i 63 | gem 'growl', '~> 1.0.3' 64 | end 65 | if RbConfig::CONFIG['target_os'] =~ /linux/i 66 | gem 'rb-inotify', '>= 0.5.1' 67 | gem 'libnotify', '~> 0.1.3' 68 | end 69 | end 70 | end 71 | end 72 | -------------------------------------------------------------------------------- /config/database.yml.postgresql: -------------------------------------------------------------------------------- 1 | # PostgreSQL. Versions 7.4 and 8.x are supported. 2 | # 3 | # Install the pg driver: 4 | # gem install pg 5 | # On Mac OS X with macports: 6 | # gem install pg -- --with-pg-config=/opt/local/lib/postgresql84/bin/pg_config 7 | # On Windows: 8 | # gem install pg 9 | # Choose the win32 build. 10 | # Install PostgreSQL and put its /bin directory on your path. 11 | # 12 | # Configure Using Gemfile 13 | # gem 'pg' 14 | # 15 | development: 16 | adapter: postgresql 17 | encoding: unicode 18 | database: refinery_database_development 19 | pool: 5 20 | username: postgres 21 | password: postgres 22 | min_messages: warning 23 | 24 | # Connect on a TCP socket. Omitted by default since the client uses a 25 | # domain socket that doesn't need configuration. Windows does not have 26 | # domain sockets, so uncomment these lines. 27 | #host: localhost 28 | #port: 5432 29 | 30 | # Schema search path. The server defaults to $user,public 31 | #schema_search_path: myapp,sharedapp,public 32 | 33 | # Minimum log levels, in increasing order: 34 | # debug5, debug4, debug3, debug2, debug1, 35 | # log, notice, warning, error, fatal, and panic 36 | # The server defaults to notice. 37 | #min_messages: warning 38 | 39 | # Warning: The database defined as "test" will be erased and 40 | # re-generated from your development database when you run "rake". 41 | # Do not set this db to the same as development or production. 42 | test: 43 | adapter: postgresql 44 | encoding: unicode 45 | database: refinery_database_test 46 | pool: 5 47 | username: postgres 48 | password: postgres 49 | min_messages: warning 50 | 51 | production: 52 | adapter: postgresql 53 | encoding: unicode 54 | database: refinery_database_production 55 | pool: 5 56 | username: postgres 57 | password: postgres 58 | min_messages: warning 59 | -------------------------------------------------------------------------------- /features/manage_events.feature: -------------------------------------------------------------------------------- 1 | @events 2 | Feature: Events 3 | In order to have events on my website 4 | As an administrator 5 | I want to manage events 6 | 7 | Background: 8 | Given I am a logged in refinery user 9 | And I have no events 10 | 11 | @events-list @list 12 | Scenario: Events List 13 | Given I have events titled UniqueTitleOne, UniqueTitleTwo 14 | When I go to the list of events 15 | # And show me the page 16 | Then I should see "UniqueTitleOne" 17 | And I should see "UniqueTitleTwo" 18 | 19 | @events-valid @valid 20 | Scenario: Create Valid Event 21 | When I go to the list of events 22 | And I follow "Add New Event" 23 | And I fill in "Title" with "This is a test of the first string field" 24 | And I press "Save" 25 | Then I should see "'This is a test of the first string field' was successfully added." 26 | And I should have 1 event 27 | 28 | @events-invalid @invalid 29 | Scenario: Create Invalid Event (without title) 30 | When I go to the list of events 31 | And I follow "Add New Event" 32 | And I press "Save" 33 | Then I should see "Title can't be blank" 34 | And I should have 0 events 35 | 36 | @events-edit @edit 37 | Scenario: Edit Existing Event 38 | Given I have events titled "A title" 39 | When I go to the list of events 40 | And I follow "Edit this event" within ".actions" 41 | Then I fill in "Title" with "A different title" 42 | And I press "Save" 43 | Then I should see "'A different title' was successfully updated." 44 | And I should be on the list of events 45 | And I should not see "A title" 46 | 47 | @events-delete @delete 48 | Scenario: Delete Event 49 | Given I only have events titled UniqueTitleOne 50 | When I go to the list of events 51 | And I follow "Remove this event forever" 52 | Then I should see "'UniqueTitleOne' was successfully removed." 53 | And I should have 0 events 54 | -------------------------------------------------------------------------------- /config/initializers/refinery/pages.rb: -------------------------------------------------------------------------------- 1 | Refinery::Pages.configure do |config| 2 | # Configure specific page templates 3 | # config.types.register :home do |home| 4 | # home.parts = %w[intro body] 5 | # end 6 | 7 | # Configure global page default parts 8 | # config.default_parts = ["Body", "Side Body"] 9 | 10 | # Configure whether to allow adding new page parts 11 | # config.new_page_parts = false 12 | 13 | # Configure whether to enable marketable_urls 14 | # config.marketable_urls = true 15 | 16 | # Configure how many pages per page should be displayed when a dialog is presented that contains a links to pages 17 | # config.pages_per_dialog = 14 18 | 19 | # Configure how many pages per page should be displayed in the list of pages in the admin area 20 | # config.pages_per_admin_index = 20 21 | 22 | # Configure whether to strip diacritics from Western characters 23 | # config.approximate_ascii = false 24 | 25 | # Configure whether to strip non-ASCII characters from the friendly_id string 26 | # config.strip_non_ascii = false 27 | 28 | # Set this to true if you want to override slug which automatically gets generated 29 | # when you create a page 30 | # config.use_custom_slugs = false 31 | 32 | # Set this to true if you want backend pages to be cached 33 | # config.cache_pages_backend = false 34 | 35 | # Set this to true to activate full-page-cache 36 | # config.cache_pages_full = false 37 | 38 | # Set this to true to fully expand the page hierarchy in the admin 39 | # config.auto_expand_admin_tree = true 40 | 41 | # config.layout_template_whitelist = ["application"] 42 | 43 | # config.view_template_whitelist = ["home", "show"] 44 | 45 | # config.use_layout_templates = false 46 | 47 | # config.use_view_templates = false 48 | 49 | # config.page_title = {:chain_page_title=>false, :ancestors=>{:separator=>" | ", :class=>"ancestors", :tag=>"span"}, :page_title=>{:class=>nil, :tag=>nil, :wrap_if_not_chained=>false}} 50 | 51 | # config.absolute_page_links = false 52 | end 53 | -------------------------------------------------------------------------------- /config/locales/es.yml: -------------------------------------------------------------------------------- 1 | es: 2 | refinery: 3 | plugins: 4 | venues: 5 | title: Venues 6 | events: 7 | title: Events 8 | calendar: 9 | admin: 10 | venues: 11 | actions: 12 | create_new: Crear nuevo venue 13 | reorder: Reordenar venues 14 | reorder_done: Reordenación de venues completada 15 | records: 16 | title: Venues 17 | sorry_no_results: Lo siento, no hay resultados 18 | no_items_yet: No hay venues todavía. Pulsa en "Crear nuevo Venue" para 19 | crear tu primer venue. 20 | venue: 21 | view_live_html: Ver este venue como abierto al público
    (abre 22 | en ventana nueva) 23 | edit: Editar este venue 24 | delete: Borrar este venue para siempre 25 | events: 26 | actions: 27 | create_new: Crear nuevo event 28 | reorder: Reordenar events 29 | reorder_done: Reordenación de events completada 30 | records: 31 | title: Events 32 | sorry_no_results: Lo siento, no hay resultados 33 | no_items_yet: No hay events todavía. Pulsa en "Crear nuevo Event" para 34 | crear tu primer event. 35 | event: 36 | view_live_html: Ver este event como abierto al público
    (abre 37 | en ventana nueva) 38 | edit: Editar este event 39 | delete: Borrar este event para siempre 40 | venues: 41 | show: 42 | other: Otros venues 43 | events: 44 | show: 45 | other: Otros events 46 | activerecord: 47 | attributes: 48 | refinery/calendar/venue: 49 | name: Name 50 | address: Address 51 | url: Url 52 | phone: Phone 53 | refinery/calendar/event: 54 | title: Title 55 | from: From 56 | to: To 57 | registration_link: Registration Link 58 | excerpt: Excerpt 59 | description: Description 60 | -------------------------------------------------------------------------------- /config/locales/en.yml: -------------------------------------------------------------------------------- 1 | en: 2 | refinery: 3 | plugins: 4 | venues: 5 | title: Venues 6 | calendar: 7 | title: Calendar 8 | calendar: 9 | admin: 10 | shared: 11 | links: 12 | manage_events: Manage Events 13 | manage_venues: Manage Venues 14 | venues: 15 | actions: 16 | create_new: Add New Venue 17 | reorder: Reorder Venues 18 | reorder_done: Done Reordering Venues 19 | records: 20 | title: Venues 21 | sorry_no_results: Sorry! There are no results found. 22 | no_items_yet: There are no Venues yet. Click "Add New Venue" to add your 23 | first venue. 24 | venue: 25 | view_live_html: View this venue live
    (opens in a new window) 26 | edit: Edit this venue 27 | delete: Remove this venue forever 28 | events: 29 | actions: 30 | create_new: Add New Event 31 | reorder: Reorder Events 32 | reorder_done: Done Reordering Events 33 | records: 34 | title: Events 35 | sorry_no_results: Sorry! There are no results found. 36 | no_items_yet: There are no Events yet. Click "Add New Event" to add your 37 | first event. 38 | event: 39 | view_live_html: View this event live
    (opens in a new window) 40 | edit: Edit this event 41 | delete: Remove this event forever 42 | venues: 43 | show: 44 | other: Other Venues 45 | events: 46 | show: 47 | other: Other Events 48 | activerecord: 49 | attributes: 50 | refinery/calendar/venue: 51 | name: Name 52 | address: Address 53 | url: Url 54 | phone: Phone 55 | refinery/calendar/event: 56 | title: Title 57 | from: From 58 | to: To 59 | registration_link: Registration Link 60 | excerpt: Excerpt 61 | description: Description 62 | -------------------------------------------------------------------------------- /config/locales/nb.yml: -------------------------------------------------------------------------------- 1 | nb: 2 | refinery: 3 | plugins: 4 | venues: 5 | title: Venues 6 | events: 7 | title: Events 8 | calendar: 9 | admin: 10 | venues: 11 | actions: 12 | create_new: Lag en ny Venue 13 | reorder: Endre rekkefølgen på Venues 14 | reorder_done: Ferdig å endre rekkefølgen Venues 15 | records: 16 | title: Venues 17 | sorry_no_results: Beklager! Vi fant ikke noen resultater. 18 | no_items_yet: Det er ingen Venues enda. Klikk på "Lag en ny Venue" for 19 | å legge til din første venue. 20 | venue: 21 | view_live_html: Vis hvordan denne venue ser ut offentlig
    (åpner 22 | i et nytt vindu) 23 | edit: Rediger denne venue 24 | delete: Fjern denne venue permanent 25 | events: 26 | actions: 27 | create_new: Lag en ny Event 28 | reorder: Endre rekkefølgen på Events 29 | reorder_done: Ferdig å endre rekkefølgen Events 30 | records: 31 | title: Events 32 | sorry_no_results: Beklager! Vi fant ikke noen resultater. 33 | no_items_yet: Det er ingen Events enda. Klikk på "Lag en ny Event" for 34 | å legge til din første event. 35 | event: 36 | view_live_html: Vis hvordan denne event ser ut offentlig
    (åpner 37 | i et nytt vindu) 38 | edit: Rediger denne event 39 | delete: Fjern denne event permanent 40 | venues: 41 | show: 42 | other: Andre Venues 43 | events: 44 | show: 45 | other: Andre Events 46 | activerecord: 47 | attributes: 48 | refinery/calendar/venue: 49 | name: Name 50 | address: Address 51 | url: Url 52 | phone: Phone 53 | refinery/calendar/event: 54 | title: Title 55 | from: From 56 | to: To 57 | registration_link: Registration Link 58 | excerpt: Excerpt 59 | description: Description 60 | -------------------------------------------------------------------------------- /config/initializers/refinery/core.rb: -------------------------------------------------------------------------------- 1 | Refinery::Core.configure do |config| 2 | # When true will rescue all not found errors and display a friendly error page 3 | config.rescue_not_found = Rails.env.production? 4 | 5 | # When true will use Amazon's Simple Storage Service instead of 6 | # the default file system for storing resources and images 7 | config.s3_backend = !(ENV['S3_KEY'].nil? || ENV['S3_SECRET'].nil?) 8 | 9 | # Whenever Refinery caches anything and can set a cache key, it will add 10 | # a prefix to the cache key containing the string you set here. 11 | # config.base_cache_key = :refinery 12 | 13 | # Site name 14 | # config.site_name = "Company Name" 15 | 16 | # This activates Google Analytics tracking within your website. If this 17 | # config is left blank or set to UA-xxxxxx-x then no remote calls to 18 | # Google Analytics are made. 19 | # config.google_analytics_page_code = "UA-xxxxxx-x" 20 | 21 | # Enable/disable authenticity token on frontend 22 | # config.authenticity_token_on_frontend = true 23 | 24 | # Hide/show child pages in menu 25 | # config.menu_hide_children = false 26 | 27 | # CSS class selectors for menu helper 28 | # config.menu_css = {:selected=>"selected", :first=>"first", :last=>"last"} 29 | 30 | # Should set this if concerned about DOS attacks. See 31 | # http://markevans.github.com/dragonfly/file.Configuration.html#Configuration 32 | # config.dragonfly_secret = "3133e393cf9a9c61355f3511ea078802e3fbb313245f1154" 33 | 34 | # Show/hide IE6 upgrade message in the backend 35 | # config.ie6_upgrade_message_enabled = true 36 | 37 | # Show/hide browser update message in the backend 38 | # config.show_internet_explorer_upgrade_message = false 39 | 40 | # Add extra tags to the wymeditor whitelist e.g. = {'tag' => {'attributes' => {'1' => 'href'}}} or just {'tag' => {}} 41 | # config.wymeditor_whitelist_tags = {} 42 | 43 | # Register extra javascript for backend 44 | # config.register_javascript "prototype-rails" 45 | 46 | # Register extra stylesheet for backend (optional options) 47 | # config.register_stylesheet "custom", :media => 'screen' 48 | end 49 | -------------------------------------------------------------------------------- /config/initializers/refinery/images.rb: -------------------------------------------------------------------------------- 1 | Refinery::Images.configure do |config| 2 | # Configures the maximum allowed upload size (in bytes) for an image 3 | # config.max_image_size = 5242880 4 | 5 | # Configure how many images per page should be displayed when a dialog is presented that contains images 6 | # config.pages_per_dialog = 18 7 | 8 | # Configure how many images per page should be displayed when a dialog is presented that 9 | # contains images and image resize options 10 | # config.pages_per_dialog_that_have_size_options = 12 11 | 12 | # Configure how many images per page should be displayed in the list of images in the admin area 13 | # config.pages_per_admin_index = 20 14 | 15 | # Configure image sizes 16 | # config.user_image_sizes = {:small=>"110x110>", :medium=>"225x255>", :large=>"450x450>"} 17 | 18 | # Configure white-listed mime types for validation 19 | # config.whitelisted_mime_types = ["image/jpeg", "image/png", "image/gif", "image/tiff"] 20 | 21 | # Configure image view options 22 | # config.image_views = [:grid, :list] 23 | 24 | # Configure default image view 25 | # config.preferred_image_view = :grid 26 | 27 | # Configure S3 (you can also use ENV for this) 28 | # The s3_backend setting by default defers to the core setting for this but can be set just for images. 29 | # config.s3_backend = Refinery::Core.s3_backend 30 | # config.s3_bucket_name = ENV['S3_BUCKET'] 31 | # config.s3_access_key_id = ENV['S3_KEY'] 32 | # config.s3_secret_access_key = ENV['S3_SECRET'] 33 | # config.s3_region = ENV['S3_REGION] 34 | 35 | # Configure Dragonfly 36 | # This is where in the middleware stack to insert the Dragonfly middleware 37 | # config.dragonfly_insert_before = "ActionDispatch::Callbacks" 38 | # config.dragonfly_secret = "3133e393cf9a9c61355f3511ea078802e3fbb313245f1154" 39 | # If you decide to trust file extensions replace :ext below with :format 40 | # config.dragonfly_url_format = "/system/images/:job/:basename.:ext" 41 | # config.datastore_root_path = "/Users/joe/code/refinerycms-calendar/spec/dummy/public/system/refinery/images" 42 | # config.trust_file_extensions = false 43 | 44 | end 45 | -------------------------------------------------------------------------------- /config/locales/fr.yml: -------------------------------------------------------------------------------- 1 | fr: 2 | refinery: 3 | plugins: 4 | venues: 5 | title: Venues 6 | events: 7 | title: Events 8 | calendar: 9 | admin: 10 | venues: 11 | actions: 12 | create_new: Créer un(e) nouve(au/l/lle) Venue 13 | reorder: Réordonner les Venues 14 | reorder_done: Fin de réordonnancement des Venues 15 | records: 16 | title: Venues 17 | sorry_no_results: Désolé ! Aucun résultat. 18 | no_items_yet: Il n'y a actuellement aucun(e) Venue. Cliquer sur "Créer 19 | un(e) nouve(au/l/lle) Venue" pour créer votre premi(er/ère) venue. 20 | venue: 21 | view_live_html: Voir ce(t/tte) venue
    (Ouvre une nouvelle fenêtre) 22 | edit: Modifier ce(t/tte) venue 23 | delete: Supprimer définitivement ce(t/tte) venue 24 | events: 25 | actions: 26 | create_new: Créer un(e) nouve(au/l/lle) Event 27 | reorder: Réordonner les Events 28 | reorder_done: Fin de réordonnancement des Events 29 | records: 30 | title: Events 31 | sorry_no_results: Désolé ! Aucun résultat. 32 | no_items_yet: Il n'y a actuellement aucun(e) Event. Cliquer sur "Créer 33 | un(e) nouve(au/l/lle) Event" pour créer votre premi(er/ère) event. 34 | event: 35 | view_live_html: Voir ce(t/tte) event
    (Ouvre une nouvelle fenêtre) 36 | edit: Modifier ce(t/tte) event 37 | delete: Supprimer définitivement ce(t/tte) event 38 | venues: 39 | show: 40 | other: Autres Venues 41 | events: 42 | show: 43 | other: Autres Events 44 | activerecord: 45 | attributes: 46 | refinery/calendar/venue: 47 | name: Name 48 | address: Address 49 | url: Url 50 | phone: Phone 51 | refinery/calendar/event: 52 | title: Title 53 | from: From 54 | to: To 55 | registration_link: Registration Link 56 | excerpt: Excerpt 57 | description: Description 58 | -------------------------------------------------------------------------------- /config/locales/nl.yml: -------------------------------------------------------------------------------- 1 | nl: 2 | refinery: 3 | plugins: 4 | venues: 5 | title: Venues 6 | events: 7 | title: Events 8 | calendar: 9 | admin: 10 | venues: 11 | actions: 12 | create_new: Maak een nieuwe Venue 13 | reorder: Wijzig de volgorde van de Venues 14 | reorder_done: Klaar met het wijzingen van de volgorde van de Venues 15 | records: 16 | title: Venues 17 | sorry_no_results: Helaas! Er zijn geen resultaten gevonden. 18 | no_items_yet: Er zijn nog geen Venues. Druk op 'Maak een nieuwe Venue' 19 | om de eerste aan te maken. 20 | venue: 21 | view_live_html: Bekijk deze venue op de website
    (opent een nieuw 22 | venster) 23 | edit: Bewerk deze venue 24 | delete: Verwijder deze venue voor eeuwig 25 | events: 26 | actions: 27 | create_new: Maak een nieuwe Event 28 | reorder: Wijzig de volgorde van de Events 29 | reorder_done: Klaar met het wijzingen van de volgorde van de Events 30 | records: 31 | title: Events 32 | sorry_no_results: Helaas! Er zijn geen resultaten gevonden. 33 | no_items_yet: Er zijn nog geen Events. Druk op 'Maak een nieuwe Event' 34 | om de eerste aan te maken. 35 | event: 36 | view_live_html: Bekijk deze event op de website
    (opent een nieuw 37 | venster) 38 | edit: Bewerk deze event 39 | delete: Verwijder deze event voor eeuwig 40 | venues: 41 | show: 42 | other: Andere Venues 43 | events: 44 | show: 45 | other: Andere Events 46 | activerecord: 47 | attributes: 48 | refinery/calendar/venue: 49 | name: Name 50 | address: Address 51 | url: Url 52 | phone: Phone 53 | refinery/calendar/event: 54 | title: Title 55 | from: From 56 | to: To 57 | registration_link: Registration Link 58 | excerpt: Excerpt 59 | description: Description 60 | -------------------------------------------------------------------------------- /app/views/refinery/calendar/admin/events/_form.html.erb: -------------------------------------------------------------------------------- 1 | <%= form_for [refinery, :calendar_admin, @event] do |f| -%> 2 | <%= render '/refinery/admin/error_messages', 3 | :object => @event, 4 | :include_object_name => true %> 5 | 6 | 7 |
    8 | <%= f.label :title -%> 9 | <%= f.text_field :title, :class => 'larger widest' -%> 10 |
    11 | 12 |
    13 |

    14 | <%= f.check_box :featured %> 15 | <%= f.label :featured, :class => 'stripped' %> 16 |

    17 |
    18 | 19 |
    20 | <%= f.label :from -%> 21 | <%= f.text_field :from, :class => 'datetime_range' -%> 22 |
    23 | 24 |
    25 | <%= f.label :to -%> 26 | <%= f.text_field :to, :class => 'datetime_range' -%> 27 |
    28 | 29 |
    30 | <%= f.label :registration_link -%> 31 | <%= f.text_field :registration_link, :class => 'larger' -%> 32 |
    33 | 34 |
    35 | <%= f.label :venue_id, 'Venue' %> 36 | <%= f.collection_select :venue_id, @venues, :id, :name, { :include_blank => 'None' }, :class => 'chzn-select', :'data-placeholder' => 'Search Venues', :style => 'width: 300px;' %> 37 |
    38 | 39 |
    40 | <%= f.label :excerpt -%> 41 | <%= f.text_area :excerpt, :size => '65x5' -%> 42 |
    43 | 44 |
    45 |
    46 | 53 |
    54 | <% [:description].each do |part| %> 55 |
    56 | <%= f.text_area part, :rows => 20, :class => 'wymeditor widest' -%> 57 |
    58 | <% end %> 59 |
    60 |
    61 | 62 |
    63 | 64 | <%= render '/refinery/admin/form_actions', :f => f, 65 | :continue_editing => false, 66 | :delete_title => t('delete', :scope => 'refinery.events.admin.events.event'), 67 | :delete_confirmation => t('message', :scope => 'refinery.admin.delete', :title => @event.title) %> 68 | <% end -%> 69 | <% content_for :stylesheets do %> 70 | <%= stylesheet_link_tag 'chosen' %> 71 | <% end %> 72 | 73 | <% content_for :javascripts do %> 74 | <%= javascript_include_tag 'chosen.jquery.min' %> 75 | 85 | <% end %> 86 | -------------------------------------------------------------------------------- /spec/requests/refinery/calendar/admin/venues_spec.rb: -------------------------------------------------------------------------------- 1 | # encoding: utf-8 2 | require "spec_helper" 3 | 4 | describe Refinery do 5 | describe "Calendar" do 6 | describe "Admin" do 7 | describe "venues" do 8 | login_refinery_user 9 | 10 | describe "venues list" do 11 | before(:each) do 12 | FactoryGirl.create(:venue, :name => "UniqueTitleOne") 13 | FactoryGirl.create(:venue, :name => "UniqueTitleTwo") 14 | end 15 | 16 | it "shows two items" do 17 | visit refinery.calendar_admin_venues_path 18 | page.should have_content("UniqueTitleOne") 19 | page.should have_content("UniqueTitleTwo") 20 | end 21 | end 22 | 23 | describe "create" do 24 | before(:each) do 25 | visit refinery.calendar_admin_venues_path 26 | 27 | click_link "Add New Venue" 28 | end 29 | 30 | context "valid data" do 31 | it "should succeed" do 32 | fill_in "Name", :with => "This is a test of the first string field" 33 | click_button "Save" 34 | 35 | page.should have_content("'This is a test of the first string field' was successfully added.") 36 | Refinery::Calendar::Venue.count.should == 1 37 | end 38 | end 39 | 40 | context "invalid data" do 41 | it "should fail" do 42 | click_button "Save" 43 | 44 | page.should have_content("Name can't be blank") 45 | Refinery::Calendar::Venue.count.should == 0 46 | end 47 | end 48 | 49 | context "duplicate" do 50 | before(:each) { FactoryGirl.create(:venue, :name => "UniqueTitle") } 51 | 52 | it "should fail" do 53 | visit refinery.calendar_admin_venues_path 54 | 55 | click_link "Add New Venue" 56 | 57 | fill_in "Name", :with => "UniqueTitle" 58 | click_button "Save" 59 | 60 | page.should have_content("There were problems") 61 | Refinery::Calendar::Venue.count.should == 1 62 | end 63 | end 64 | 65 | end 66 | 67 | describe "edit" do 68 | before(:each) { FactoryGirl.create(:venue, :name => "A name") } 69 | 70 | it "should succeed" do 71 | visit refinery.calendar_admin_venues_path 72 | 73 | within ".actions" do 74 | click_link "Edit this venue" 75 | end 76 | 77 | fill_in "Name", :with => "A different name" 78 | click_button "Save" 79 | 80 | page.should have_content("'A different name' was successfully updated.") 81 | page.should have_no_content("A name") 82 | end 83 | end 84 | 85 | describe "destroy" do 86 | before(:each) { FactoryGirl.create(:venue, :name => "UniqueTitleOne") } 87 | 88 | it "should succeed" do 89 | visit refinery.calendar_admin_venues_path 90 | 91 | click_link "Remove this venue forever" 92 | 93 | page.should have_content("'UniqueTitleOne' was successfully removed.") 94 | Refinery::Calendar::Venue.count.should == 0 95 | end 96 | end 97 | 98 | end 99 | end 100 | end 101 | end 102 | -------------------------------------------------------------------------------- /spec/requests/refinery/calendar/admin/events_spec.rb: -------------------------------------------------------------------------------- 1 | # encoding: utf-8 2 | require "spec_helper" 3 | 4 | describe Refinery do 5 | describe "Calendar" do 6 | describe "Admin" do 7 | describe "events" do 8 | login_refinery_user 9 | 10 | describe "events list" do 11 | before(:each) do 12 | FactoryGirl.create(:event, :title => "UniqueTitleOne") 13 | FactoryGirl.create(:event, :title => "UniqueTitleTwo") 14 | end 15 | 16 | it "shows two items" do 17 | visit refinery.calendar_admin_events_path 18 | page.should have_content("UniqueTitleOne") 19 | page.should have_content("UniqueTitleTwo") 20 | end 21 | end 22 | 23 | describe "create" do 24 | before(:each) do 25 | visit refinery.calendar_admin_events_path 26 | 27 | click_link "Add New Event" 28 | end 29 | 30 | context "valid data" do 31 | it "should succeed" do 32 | fill_in "Title", :with => "This is a test of the first string field" 33 | click_button "Save" 34 | 35 | page.should have_content("'This is a test of the first string field' was successfully added.") 36 | Refinery::Calendar::Event.count.should == 1 37 | end 38 | end 39 | 40 | context "invalid data" do 41 | it "should fail" do 42 | click_button "Save" 43 | 44 | page.should have_content("Title can't be blank") 45 | Refinery::Calendar::Event.count.should == 0 46 | end 47 | end 48 | 49 | context "duplicate" do 50 | before(:each) { FactoryGirl.create(:event, :title => "UniqueTitle") } 51 | 52 | it "should fail" do 53 | visit refinery.calendar_admin_events_path 54 | 55 | click_link "Add New Event" 56 | 57 | fill_in "Title", :with => "UniqueTitle" 58 | click_button "Save" 59 | 60 | page.should have_content("There were problems") 61 | Refinery::Calendar::Event.count.should == 1 62 | end 63 | end 64 | 65 | end 66 | 67 | describe "edit" do 68 | before(:each) { FactoryGirl.create(:event, :title => "A title") } 69 | 70 | it "should succeed" do 71 | visit refinery.calendar_admin_events_path 72 | 73 | within ".actions" do 74 | click_link "Edit this event" 75 | end 76 | 77 | fill_in "Title", :with => "A different title" 78 | click_button "Save" 79 | 80 | page.should have_content("'A different title' was successfully updated.") 81 | page.should have_no_content("A title") 82 | end 83 | end 84 | 85 | describe "destroy" do 86 | before(:each) { FactoryGirl.create(:event, :title => "UniqueTitleOne") } 87 | 88 | it "should succeed" do 89 | visit refinery.calendar_admin_events_path 90 | 91 | click_link "Remove this event forever" 92 | 93 | page.should have_content("'UniqueTitleOne' was successfully removed.") 94 | Refinery::Calendar::Event.count.should == 0 95 | end 96 | end 97 | 98 | end 99 | end 100 | end 101 | end 102 | -------------------------------------------------------------------------------- /Gemfile.lock: -------------------------------------------------------------------------------- 1 | PATH 2 | remote: . 3 | specs: 4 | refinerycms-calendar (2.0.0) 5 | refinerycms-core (~> 2.0.3) 6 | 7 | GEM 8 | remote: http://rubygems.org/ 9 | specs: 10 | actionmailer (3.2.3) 11 | actionpack (= 3.2.3) 12 | mail (~> 2.4.4) 13 | actionpack (3.2.3) 14 | activemodel (= 3.2.3) 15 | activesupport (= 3.2.3) 16 | builder (~> 3.0.0) 17 | erubis (~> 2.7.0) 18 | journey (~> 1.0.1) 19 | rack (~> 1.4.0) 20 | rack-cache (~> 1.2) 21 | rack-test (~> 0.6.1) 22 | sprockets (~> 2.1.2) 23 | activemodel (3.2.3) 24 | activesupport (= 3.2.3) 25 | builder (~> 3.0.0) 26 | activerecord (3.2.3) 27 | activemodel (= 3.2.3) 28 | activesupport (= 3.2.3) 29 | arel (~> 3.0.2) 30 | tzinfo (~> 0.3.29) 31 | activeresource (3.2.3) 32 | activemodel (= 3.2.3) 33 | activesupport (= 3.2.3) 34 | activesupport (3.2.3) 35 | i18n (~> 0.6) 36 | multi_json (~> 1.0) 37 | acts_as_indexed (0.7.8) 38 | addressable (2.2.8) 39 | arel (3.0.2) 40 | awesome_nested_set (2.1.3) 41 | activerecord (>= 3.0.0) 42 | babosa (0.3.7) 43 | bcrypt-ruby (3.0.1) 44 | builder (3.0.0) 45 | capybara (1.1.2) 46 | mime-types (>= 1.16) 47 | nokogiri (>= 1.3.3) 48 | rack (>= 1.0.0) 49 | rack-test (>= 0.5.4) 50 | selenium-webdriver (~> 2.0) 51 | xpath (~> 0.1.4) 52 | childprocess (0.3.2) 53 | ffi (~> 1.0.6) 54 | coffee-rails (3.2.2) 55 | coffee-script (>= 2.2.0) 56 | railties (~> 3.2.0) 57 | coffee-script (2.2.0) 58 | coffee-script-source 59 | execjs 60 | coffee-script-source (1.3.3) 61 | database_cleaner (0.7.2) 62 | devise (2.0.4) 63 | bcrypt-ruby (~> 3.0) 64 | orm_adapter (~> 0.0.3) 65 | railties (~> 3.1) 66 | warden (~> 1.1.1) 67 | diff-lcs (1.1.3) 68 | dragonfly (0.9.12) 69 | rack 70 | erubis (2.7.0) 71 | execjs (1.4.0) 72 | multi_json (~> 1.0) 73 | factory_girl (2.6.4) 74 | activesupport (>= 2.3.9) 75 | factory_girl_rails (1.7.0) 76 | factory_girl (~> 2.6.0) 77 | railties (>= 3.0.0) 78 | ffi (1.0.11) 79 | friendly_id (4.0.6) 80 | generator_spec (0.8.5) 81 | rails (>= 3.0, < 4.0) 82 | rspec-rails 83 | globalize3 (0.2.0) 84 | activemodel (>= 3.0.0) 85 | activerecord (>= 3.0.0) 86 | paper_trail (~> 2) 87 | growl (1.0.3) 88 | guard (1.0.3) 89 | ffi (>= 0.5.0) 90 | thor (>= 0.14.6) 91 | guard-spork (0.5.2) 92 | guard (>= 0.10.0) 93 | spork (>= 0.8.4) 94 | hike (1.2.1) 95 | i18n (0.6.0) 96 | journey (1.0.3) 97 | jquery-rails (2.0.2) 98 | railties (>= 3.2.0, < 5.0) 99 | thor (~> 0.14) 100 | json (1.7.3) 101 | libwebsocket (0.1.3) 102 | addressable 103 | mail (2.4.4) 104 | i18n (>= 0.4.0) 105 | mime-types (~> 1.16) 106 | treetop (~> 1.4.8) 107 | mime-types (1.18) 108 | multi_json (1.3.5) 109 | mysql2 (0.3.11) 110 | nokogiri (1.5.2) 111 | orm_adapter (0.0.7) 112 | paper_trail (2.6.3) 113 | activerecord (~> 3.0) 114 | railties (~> 3.0) 115 | pg (0.13.2) 116 | polyglot (0.3.3) 117 | rack (1.4.1) 118 | rack-cache (1.2) 119 | rack (>= 0.4) 120 | rack-ssl (1.3.2) 121 | rack 122 | rack-test (0.6.1) 123 | rack (>= 1.0) 124 | rails (3.2.3) 125 | actionmailer (= 3.2.3) 126 | actionpack (= 3.2.3) 127 | activerecord (= 3.2.3) 128 | activeresource (= 3.2.3) 129 | activesupport (= 3.2.3) 130 | bundler (~> 1.0) 131 | railties (= 3.2.3) 132 | railties (3.2.3) 133 | actionpack (= 3.2.3) 134 | activesupport (= 3.2.3) 135 | rack-ssl (~> 1.3.2) 136 | rake (>= 0.8.7) 137 | rdoc (~> 3.4) 138 | thor (~> 0.14.6) 139 | rake (0.9.2.2) 140 | rb-fsevent (0.9.1) 141 | rdoc (3.12) 142 | json (~> 1.4) 143 | refinerycms (2.0.3) 144 | bundler (~> 1.0) 145 | refinerycms-authentication (= 2.0.3) 146 | refinerycms-core (= 2.0.3) 147 | refinerycms-dashboard (= 2.0.3) 148 | refinerycms-images (= 2.0.3) 149 | refinerycms-pages (= 2.0.3) 150 | refinerycms-resources (= 2.0.3) 151 | refinerycms-authentication (2.0.3) 152 | devise (~> 2.0.0) 153 | orm_adapter (~> 0.0.7) 154 | refinerycms-core (= 2.0.3) 155 | refinerycms-core (2.0.3) 156 | acts_as_indexed (~> 0.7.7) 157 | awesome_nested_set (~> 2.1.0) 158 | coffee-rails (~> 3.2.1) 159 | friendly_id (~> 4.0.1) 160 | globalize3 (~> 0.2.0) 161 | jquery-rails (~> 2.0.0) 162 | rails (>= 3.1.3, < 3.3) 163 | sass-rails (~> 3.2.3) 164 | truncate_html (~> 0.5) 165 | uglifier (>= 1.0.3) 166 | will_paginate (~> 3.0.2) 167 | refinerycms-dashboard (2.0.3) 168 | refinerycms-core (= 2.0.3) 169 | refinerycms-images (2.0.3) 170 | dragonfly (~> 0.9.8) 171 | rack-cache (>= 0.5.3) 172 | refinerycms-core (= 2.0.3) 173 | refinerycms-pages (2.0.3) 174 | awesome_nested_set (~> 2.1.0) 175 | babosa (!= 0.3.6) 176 | refinerycms-core (= 2.0.3) 177 | seo_meta (~> 1.3.0) 178 | refinerycms-resources (2.0.3) 179 | dragonfly (~> 0.9.8) 180 | rack-cache (>= 0.5.3) 181 | refinerycms-core (= 2.0.3) 182 | refinerycms-testing (2.0.3) 183 | capybara (~> 1.1.0) 184 | database_cleaner (~> 0.7.1) 185 | factory_girl_rails (~> 1.7.0) 186 | rack-test (~> 0.6.0) 187 | refinerycms-core (= 2.0.3) 188 | rspec-rails (~> 2.8.1) 189 | rspec (2.8.0) 190 | rspec-core (~> 2.8.0) 191 | rspec-expectations (~> 2.8.0) 192 | rspec-mocks (~> 2.8.0) 193 | rspec-core (2.8.0) 194 | rspec-expectations (2.8.0) 195 | diff-lcs (~> 1.1.2) 196 | rspec-mocks (2.8.0) 197 | rspec-rails (2.8.1) 198 | actionpack (>= 3.0) 199 | activesupport (>= 3.0) 200 | railties (>= 3.0) 201 | rspec (~> 2.8.0) 202 | rubyzip (0.9.8) 203 | sass (3.1.18) 204 | sass-rails (3.2.5) 205 | railties (~> 3.2.0) 206 | sass (>= 3.1.10) 207 | tilt (~> 1.3) 208 | selenium-webdriver (2.21.2) 209 | childprocess (>= 0.2.5) 210 | ffi (~> 1.0) 211 | libwebsocket (~> 0.1.3) 212 | multi_json (~> 1.0) 213 | rubyzip 214 | seo_meta (1.3.0) 215 | railties (>= 3.0.0) 216 | spork (0.9.0.rc9) 217 | sprockets (2.1.3) 218 | hike (~> 1.2) 219 | rack (~> 1.0) 220 | tilt (~> 1.1, != 1.3.0) 221 | sqlite3 (1.3.6) 222 | thor (0.14.6) 223 | tilt (1.3.3) 224 | treetop (1.4.10) 225 | polyglot 226 | polyglot (>= 0.3.1) 227 | truncate_html (0.5.5) 228 | tzinfo (0.3.33) 229 | uglifier (1.2.4) 230 | execjs (>= 0.3.0) 231 | multi_json (>= 1.0.2) 232 | warden (1.1.1) 233 | rack (>= 1.0) 234 | will_paginate (3.0.3) 235 | xpath (0.1.4) 236 | nokogiri (~> 1.3) 237 | 238 | PLATFORMS 239 | ruby 240 | 241 | DEPENDENCIES 242 | activerecord-jdbcmysql-adapter 243 | activerecord-jdbcpostgresql-adapter 244 | activerecord-jdbcsqlite3-adapter 245 | coffee-rails 246 | factory_girl_rails 247 | generator_spec 248 | growl (~> 1.0.3) 249 | guard-spork 250 | jquery-rails 251 | jruby-openssl 252 | mysql2 253 | pg 254 | rb-fchange (~> 0.0.5) 255 | rb-fsevent (>= 0.3.9) 256 | rb-notifu (~> 0.0.4) 257 | refinerycms (~> 2.0.0) 258 | refinerycms-calendar! 259 | refinerycms-testing (~> 2.0.0) 260 | sass-rails 261 | spork (= 0.9.0.rc9) 262 | sqlite3 263 | uglifier 264 | win32console 265 | -------------------------------------------------------------------------------- /vendor/assets/stylesheets/chosen.css: -------------------------------------------------------------------------------- 1 | /* @group Base */ 2 | .chzn-container { 3 | font-size: 13px; 4 | position: relative; 5 | display: inline-block; 6 | zoom: 1; 7 | *display: inline; 8 | } 9 | .chzn-container .chzn-drop { 10 | background: #fff; 11 | border: 1px solid #aaa; 12 | border-top: 0; 13 | position: absolute; 14 | top: 29px; 15 | left: 0; 16 | -webkit-box-shadow: 0 4px 5px rgba(0,0,0,.15); 17 | -moz-box-shadow : 0 4px 5px rgba(0,0,0,.15); 18 | -o-box-shadow : 0 4px 5px rgba(0,0,0,.15); 19 | box-shadow : 0 4px 5px rgba(0,0,0,.15); 20 | z-index: 999; 21 | } 22 | /* @end */ 23 | 24 | /* @group Single Chosen */ 25 | .chzn-container-single .chzn-single { 26 | background-color: #fff; 27 | background-image: -webkit-gradient(linear, left bottom, left top, color-stop(0, #eeeeee), color-stop(0.5, white)); 28 | background-image: -webkit-linear-gradient(center bottom, #eeeeee 0%, white 50%); 29 | background-image: -moz-linear-gradient(center bottom, #eeeeee 0%, white 50%); 30 | background-image: -o-linear-gradient(top, #eeeeee 0%,#ffffff 50%); 31 | background-image: -ms-linear-gradient(top, #eeeeee 0%,#ffffff 50%); 32 | filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#eeeeee', endColorstr='#ffffff',GradientType=0 ); 33 | background-image: linear-gradient(top, #eeeeee 0%,#ffffff 50%); 34 | -webkit-border-radius: 4px; 35 | -moz-border-radius : 4px; 36 | border-radius : 4px; 37 | -moz-background-clip : padding; 38 | -webkit-background-clip: padding-box; 39 | background-clip : padding-box; 40 | border: 1px solid #aaa; 41 | display: block; 42 | overflow: hidden; 43 | white-space: nowrap; 44 | position: relative; 45 | height: 26px; 46 | line-height: 26px; 47 | padding: 0 0 0 8px; 48 | color: #444; 49 | text-decoration: none; 50 | } 51 | .chzn-container-single .chzn-single span { 52 | margin-right: 26px; 53 | display: block; 54 | overflow: hidden; 55 | white-space: nowrap; 56 | -o-text-overflow: ellipsis; 57 | -ms-text-overflow: ellipsis; 58 | text-overflow: ellipsis; 59 | } 60 | .chzn-container-single .chzn-single abbr { 61 | display: block; 62 | position: absolute; 63 | right: 26px; 64 | top: 8px; 65 | width: 12px; 66 | height: 13px; 67 | font-size: 1px; 68 | background: url(/assets/chosen-sprite.png) right top no-repeat; 69 | } 70 | .chzn-container-single .chzn-single abbr:hover { 71 | background-position: right -11px; 72 | } 73 | .chzn-container-single .chzn-single div { 74 | -webkit-border-radius: 0 4px 4px 0; 75 | -moz-border-radius : 0 4px 4px 0; 76 | border-radius : 0 4px 4px 0; 77 | -moz-background-clip : padding; 78 | -webkit-background-clip: padding-box; 79 | background-clip : padding-box; 80 | background: #ccc; 81 | background-image: -webkit-gradient(linear, left bottom, left top, color-stop(0, #ccc), color-stop(0.6, #eee)); 82 | background-image: -webkit-linear-gradient(center bottom, #ccc 0%, #eee 60%); 83 | background-image: -moz-linear-gradient(center bottom, #ccc 0%, #eee 60%); 84 | background-image: -o-linear-gradient(bottom, #ccc 0%, #eee 60%); 85 | background-image: -ms-linear-gradient(top, #cccccc 0%,#eeeeee 60%); 86 | filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#cccccc', endColorstr='#eeeeee',GradientType=0 ); 87 | background-image: linear-gradient(top, #cccccc 0%,#eeeeee 60%); 88 | border-left: 1px solid #aaa; 89 | position: absolute; 90 | right: 0; 91 | top: 0; 92 | display: block; 93 | height: 100%; 94 | width: 18px; 95 | } 96 | .chzn-container-single .chzn-single div b { 97 | background: url('/assets/chosen-sprite.png') no-repeat 0 1px; 98 | display: block; 99 | width: 100%; 100 | height: 100%; 101 | } 102 | .chzn-container-single .chzn-search { 103 | padding: 3px 4px; 104 | position: relative; 105 | margin: 0; 106 | white-space: nowrap; 107 | z-index: 1010; 108 | } 109 | .chzn-container-single .chzn-search input { 110 | background: #fff url('/assets/chosen-sprite.png') no-repeat 100% -22px; 111 | background: url('/assets/chosen-sprite.png') no-repeat 100% -22px, -webkit-gradient(linear, left bottom, left top, color-stop(0.85, white), color-stop(0.99, #eeeeee)); 112 | background: url('/assets/chosen-sprite.png') no-repeat 100% -22px, -webkit-linear-gradient(center bottom, white 85%, #eeeeee 99%); 113 | background: url('/assets/chosen-sprite.png') no-repeat 100% -22px, -moz-linear-gradient(center bottom, white 85%, #eeeeee 99%); 114 | background: url('/assets/chosen-sprite.png') no-repeat 100% -22px, -o-linear-gradient(bottom, white 85%, #eeeeee 99%); 115 | background: url('/assets/chosen-sprite.png') no-repeat 100% -22px, -ms-linear-gradient(top, #ffffff 85%,#eeeeee 99%); 116 | background: url('/assets/chosen-sprite.png') no-repeat 100% -22px, linear-gradient(top, #ffffff 85%,#eeeeee 99%); 117 | margin: 1px 0; 118 | padding: 4px 20px 4px 5px; 119 | outline: 0; 120 | border: 1px solid #aaa; 121 | font-family: sans-serif; 122 | font-size: 1em; 123 | } 124 | .chzn-container-single .chzn-drop { 125 | -webkit-border-radius: 0 0 4px 4px; 126 | -moz-border-radius : 0 0 4px 4px; 127 | border-radius : 0 0 4px 4px; 128 | -moz-background-clip : padding; 129 | -webkit-background-clip: padding-box; 130 | background-clip : padding-box; 131 | } 132 | /* @end */ 133 | 134 | .chzn-container-single-nosearch .chzn-search input { 135 | position: absolute; 136 | left: -9000px; 137 | } 138 | 139 | /* @group Multi Chosen */ 140 | .chzn-container-multi .chzn-choices { 141 | background-color: #fff; 142 | background-image: -webkit-gradient(linear, left bottom, left top, color-stop(0.85, white), color-stop(0.99, #eeeeee)); 143 | background-image: -webkit-linear-gradient(center bottom, white 85%, #eeeeee 99%); 144 | background-image: -moz-linear-gradient(center bottom, white 85%, #eeeeee 99%); 145 | background-image: -o-linear-gradient(bottom, white 85%, #eeeeee 99%); 146 | background-image: -ms-linear-gradient(top, #ffffff 85%,#eeeeee 99%); 147 | filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#ffffff', endColorstr='#eeeeee',GradientType=0 ); 148 | background-image: linear-gradient(top, #ffffff 85%,#eeeeee 99%); 149 | border: 1px solid #aaa; 150 | margin: 0; 151 | padding: 0; 152 | cursor: text; 153 | overflow: hidden; 154 | height: auto !important; 155 | height: 1%; 156 | position: relative; 157 | } 158 | .chzn-container-multi .chzn-choices li { 159 | float: left; 160 | list-style: none; 161 | } 162 | .chzn-container-multi .chzn-choices .search-field { 163 | white-space: nowrap; 164 | margin: 0; 165 | padding: 0; 166 | } 167 | .chzn-container-multi .chzn-choices .search-field input { 168 | color: #666; 169 | background: transparent !important; 170 | border: 0 !important; 171 | padding: 5px; 172 | margin: 1px 0; 173 | outline: 0; 174 | -webkit-box-shadow: none; 175 | -moz-box-shadow : none; 176 | -o-box-shadow : none; 177 | box-shadow : none; 178 | } 179 | .chzn-container-multi .chzn-choices .search-field .default { 180 | color: #999; 181 | } 182 | .chzn-container-multi .chzn-choices .search-choice { 183 | -webkit-border-radius: 3px; 184 | -moz-border-radius : 3px; 185 | border-radius : 3px; 186 | -moz-background-clip : padding; 187 | -webkit-background-clip: padding-box; 188 | background-clip : padding-box; 189 | background-color: #e4e4e4; 190 | background-image: -webkit-gradient(linear, left bottom, left top, color-stop(0, #e4e4e4), color-stop(0.7, #eeeeee)); 191 | background-image: -webkit-linear-gradient(center bottom, #e4e4e4 0%, #eeeeee 70%); 192 | background-image: -moz-linear-gradient(center bottom, #e4e4e4 0%, #eeeeee 70%); 193 | background-image: -o-linear-gradient(bottom, #e4e4e4 0%, #eeeeee 70%); 194 | background-image: -ms-linear-gradient(top, #e4e4e4 0%,#eeeeee 70%); 195 | filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#e4e4e4', endColorstr='#eeeeee',GradientType=0 ); 196 | background-image: linear-gradient(top, #e4e4e4 0%,#eeeeee 70%); 197 | color: #333; 198 | border: 1px solid #b4b4b4; 199 | line-height: 13px; 200 | padding: 3px 19px 3px 6px; 201 | margin: 3px 0 3px 5px; 202 | position: relative; 203 | } 204 | .chzn-container-multi .chzn-choices .search-choice span { 205 | cursor: default; 206 | } 207 | .chzn-container-multi .chzn-choices .search-choice-focus { 208 | background: #d4d4d4; 209 | } 210 | #content .chzn-container-multi .chzn-choices .search-choice .search-choice-close { 211 | border:0; 212 | display: block; 213 | position: absolute; 214 | right: 3px; 215 | top: 4px; 216 | width: 12px; 217 | height: 13px; 218 | font-size: 1px; 219 | background: url(/assets/chosen-sprite.png) right top no-repeat; 220 | } 221 | .chzn-container-multi .chzn-choices .search-choice .search-choice-close:hover { 222 | background-position: right -11px; 223 | } 224 | .chzn-container-multi .chzn-choices .search-choice-focus .search-choice-close { 225 | background-position: right -11px; 226 | } 227 | /* @end */ 228 | 229 | /* @group Results */ 230 | .chzn-container .chzn-results { 231 | margin: 0 4px 4px 0; 232 | max-height: 190px; 233 | padding: 0 0 0 4px; 234 | position: relative; 235 | overflow-x: hidden; 236 | overflow-y: auto; 237 | } 238 | .chzn-container-multi .chzn-results { 239 | margin: -1px 0 0; 240 | padding: 0; 241 | } 242 | .chzn-container .chzn-results li { 243 | display: none; 244 | line-height: 80%; 245 | padding: 7px 7px 8px; 246 | margin: 0; 247 | list-style: none; 248 | } 249 | .chzn-container .chzn-results .active-result { 250 | cursor: pointer; 251 | display: list-item; 252 | } 253 | .chzn-container .chzn-results .highlighted { 254 | background: #3875d7; 255 | color: #fff; 256 | } 257 | .chzn-container .chzn-results li em { 258 | background: #feffde; 259 | font-style: normal; 260 | } 261 | .chzn-container .chzn-results .highlighted em { 262 | background: transparent; 263 | } 264 | .chzn-container .chzn-results .no-results { 265 | background: #f4f4f4; 266 | display: list-item; 267 | } 268 | .chzn-container .chzn-results .group-result { 269 | cursor: default; 270 | color: #999; 271 | font-weight: bold; 272 | } 273 | .chzn-container .chzn-results .group-option { 274 | padding-left: 20px; 275 | } 276 | .chzn-container-multi .chzn-drop .result-selected { 277 | display: none; 278 | } 279 | /* @end */ 280 | 281 | /* @group Active */ 282 | .chzn-container-active .chzn-single { 283 | -webkit-box-shadow: 0 0 5px rgba(0,0,0,.3); 284 | -moz-box-shadow : 0 0 5px rgba(0,0,0,.3); 285 | -o-box-shadow : 0 0 5px rgba(0,0,0,.3); 286 | box-shadow : 0 0 5px rgba(0,0,0,.3); 287 | border: 1px solid #5897fb; 288 | } 289 | .chzn-container-active .chzn-single-with-drop { 290 | border: 1px solid #aaa; 291 | -webkit-box-shadow: 0 1px 0 #fff inset; 292 | -moz-box-shadow : 0 1px 0 #fff inset; 293 | -o-box-shadow : 0 1px 0 #fff inset; 294 | box-shadow : 0 1px 0 #fff inset; 295 | background-color: #eee; 296 | background-image: -webkit-gradient(linear, left bottom, left top, color-stop(0, white), color-stop(0.5, #eeeeee)); 297 | background-image: -webkit-linear-gradient(center bottom, white 0%, #eeeeee 50%); 298 | background-image: -moz-linear-gradient(center bottom, white 0%, #eeeeee 50%); 299 | background-image: -o-linear-gradient(bottom, white 0%, #eeeeee 50%); 300 | background-image: -ms-linear-gradient(top, #ffffff 0%,#eeeeee 50%); 301 | filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#ffffff', endColorstr='#eeeeee',GradientType=0 ); 302 | background-image: linear-gradient(top, #ffffff 0%,#eeeeee 50%); 303 | -webkit-border-bottom-left-radius : 0; 304 | -webkit-border-bottom-right-radius: 0; 305 | -moz-border-radius-bottomleft : 0; 306 | -moz-border-radius-bottomright: 0; 307 | border-bottom-left-radius : 0; 308 | border-bottom-right-radius: 0; 309 | } 310 | .chzn-container-active .chzn-single-with-drop div { 311 | background: transparent; 312 | border-left: none; 313 | } 314 | .chzn-container-active .chzn-single-with-drop div b { 315 | background-position: -18px 1px; 316 | } 317 | .chzn-container-active .chzn-choices { 318 | -webkit-box-shadow: 0 0 5px rgba(0,0,0,.3); 319 | -moz-box-shadow : 0 0 5px rgba(0,0,0,.3); 320 | -o-box-shadow : 0 0 5px rgba(0,0,0,.3); 321 | box-shadow : 0 0 5px rgba(0,0,0,.3); 322 | border: 1px solid #5897fb; 323 | } 324 | .chzn-container-active .chzn-choices .search-field input { 325 | color: #111 !important; 326 | } 327 | /* @end */ 328 | 329 | /* @group Disabled Support */ 330 | .chzn-disabled { 331 | cursor: default; 332 | opacity:0.5 !important; 333 | } 334 | .chzn-disabled .chzn-single { 335 | cursor: default; 336 | } 337 | .chzn-disabled .chzn-choices .search-choice .search-choice-close { 338 | cursor: default; 339 | } 340 | 341 | /* @group Right to Left */ 342 | .chzn-rtl { direction:rtl;text-align: right; } 343 | .chzn-rtl .chzn-single { padding-left: 0; padding-right: 8px; } 344 | .chzn-rtl .chzn-single span { margin-left: 26px; margin-right: 0; } 345 | .chzn-rtl .chzn-single div { 346 | left: 0; right: auto; 347 | border-left: none; border-right: 1px solid #aaaaaa; 348 | -webkit-border-radius: 4px 0 0 4px; 349 | -moz-border-radius : 4px 0 0 4px; 350 | border-radius : 4px 0 0 4px; 351 | } 352 | .chzn-rtl .chzn-single abbr { 353 | left: 26px; 354 | right: auto; 355 | } 356 | .chzn-rtl .chzn-choices li { float: right; } 357 | .chzn-rtl .chzn-choices .search-choice { padding: 3px 6px 3px 19px; margin: 3px 5px 3px 0; } 358 | .chzn-rtl .chzn-choices .search-choice .search-choice-close { left: 5px; right: auto; background-position: right top;} 359 | .chzn-rtl.chzn-container-single .chzn-results { margin-left: 4px; margin-right: 0; padding-left: 0; padding-right: 4px; } 360 | .chzn-rtl .chzn-results .group-option { padding-left: 0; padding-right: 20px; } 361 | .chzn-rtl.chzn-container-active .chzn-single-with-drop div { border-right: none; } 362 | .chzn-rtl .chzn-search input { 363 | background: url('/assets/chosen-sprite.png') no-repeat -38px -22px, #ffffff; 364 | background: url('/assets/chosen-sprite.png') no-repeat -38px -22px, -webkit-gradient(linear, left bottom, left top, color-stop(0.85, white), color-stop(0.99, #eeeeee)); 365 | background: url('/assets/chosen-sprite.png') no-repeat -38px -22px, -webkit-linear-gradient(center bottom, white 85%, #eeeeee 99%); 366 | background: url('/assets/chosen-sprite.png') no-repeat -38px -22px, -moz-linear-gradient(center bottom, white 85%, #eeeeee 99%); 367 | background: url('/assets/chosen-sprite.png') no-repeat -38px -22px, -o-linear-gradient(bottom, white 85%, #eeeeee 99%); 368 | background: url('/assets/chosen-sprite.png') no-repeat -38px -22px, -ms-linear-gradient(top, #ffffff 85%,#eeeeee 99%); 369 | background: url('/assets/chosen-sprite.png') no-repeat -38px -22px, linear-gradient(top, #ffffff 85%,#eeeeee 99%); 370 | padding: 4px 5px 4px 20px; 371 | } 372 | /* @end */ 373 | -------------------------------------------------------------------------------- /vendor/assets/javascripts/chosen.jquery.min.js: -------------------------------------------------------------------------------- 1 | // Chosen, a Select Box Enhancer for jQuery and Protoype 2 | // by Patrick Filler for Harvest, http://getharvest.com 3 | // 4 | // Version 0.9.5 5 | // Full source at https://github.com/harvesthq/chosen 6 | // Copyright (c) 2011 Harvest http://getharvest.com 7 | 8 | // MIT License, https://github.com/harvesthq/chosen/blob/master/LICENSE.md 9 | // This file is generated by `cake build`, do not edit it by hand. 10 | (function(){var a;a=function(){function a(){this.options_index=0,this.parsed=[]}return a.prototype.add_node=function(a){return a.nodeName==="OPTGROUP"?this.add_group(a):this.add_option(a)},a.prototype.add_group=function(a){var b,c,d,e,f,g;b=this.parsed.length,this.parsed.push({array_index:b,group:!0,label:a.label,children:0,disabled:a.disabled}),f=a.childNodes,g=[];for(d=0,e=f.length;d"+a.html+"")},a.prototype.results_update_field=function(){return this.result_clear_highlight(),this.result_single_selected=null,this.results_build()},a.prototype.results_toggle=function(){return this.results_showing?this.results_hide():this.results_show()},a.prototype.results_search=function(a){return this.results_showing?this.winnow_results():this.results_show()},a.prototype.keyup_checker=function(a){var b,c;b=(c=a.which)!=null?c:a.keyCode,this.search_field_scale();switch(b){case 8:if(this.is_multiple&&this.backstroke_length<1&&this.choices>0)return this.keydown_backstroke();if(!this.pending_backstroke)return this.result_clear_highlight(),this.results_search();break;case 13:a.preventDefault();if(this.results_showing)return this.result_select(a);break;case 27:if(this.results_showing)return this.results_hide();break;case 9:case 38:case 40:case 16:case 91:case 17:break;default:return this.results_search()}},a.prototype.generate_field_id=function(){var a;return a=this.generate_random_id(),this.form_field.id=a,a},a.prototype.generate_random_char=function(){var a,b,c;return a="0123456789ABCDEFGHIJKLMNOPQRSTUVWXTZ",c=Math.floor(Math.random()*a.length),b=a.substring(c,c+1)},a}(),b.AbstractChosen=a}.call(this),function(){var a,b,c,d,e=Object.prototype.hasOwnProperty,f=function(a,b){function d(){this.constructor=a}for(var c in b)e.call(b,c)&&(a[c]=b[c]);return d.prototype=b.prototype,a.prototype=new d,a.__super__=b.prototype,a},g=function(a,b){return function(){return a.apply(b,arguments)}};d=this,a=jQuery,a.fn.extend({chosen:function(c){return!a.browser.msie||a.browser.version!=="6.0"&&a.browser.version!=="7.0"?a(this).each(function(d){if(!a(this).hasClass("chzn-done"))return new b(this,c)}):this}}),b=function(){function b(){b.__super__.constructor.apply(this,arguments)}return f(b,AbstractChosen),b.prototype.setup=function(){return this.form_field_jq=a(this.form_field),this.is_rtl=this.form_field_jq.hasClass("chzn-rtl")},b.prototype.finish_setup=function(){return this.form_field_jq.addClass("chzn-done")},b.prototype.set_up_html=function(){var b,d,e,f;return this.container_id=this.form_field.id.length?this.form_field.id.replace(/(:|\.)/g,"_"):this.generate_field_id(),this.container_id+="_chzn",this.f_width=this.form_field_jq.outerWidth(),this.default_text=this.form_field_jq.data("placeholder")?this.form_field_jq.data("placeholder"):this.default_text_default,b=a("
    ",{id:this.container_id,"class":"chzn-container"+(this.is_rtl?" chzn-rtl":""),style:"width: "+this.f_width+"px;"}),this.is_multiple?b.html('
      '):b.html(''+this.default_text+'
        '),this.form_field_jq.hide().after(b),this.container=a("#"+this.container_id),this.container.addClass("chzn-container-"+(this.is_multiple?"multi":"single")),this.dropdown=this.container.find("div.chzn-drop").first(),d=this.container.height(),e=this.f_width-c(this.dropdown),this.dropdown.css({width:e+"px",top:d+"px"}),this.search_field=this.container.find("input").first(),this.search_results=this.container.find("ul.chzn-results").first(),this.search_field_scale(),this.search_no_results=this.container.find("li.no-results").first(),this.is_multiple?(this.search_choices=this.container.find("ul.chzn-choices").first(),this.search_container=this.container.find("li.search-field").first()):(this.search_container=this.container.find("div.chzn-search").first(),this.selected_item=this.container.find(".chzn-single").first(),f=e-c(this.search_container)-c(this.search_field),this.search_field.css({width:f+"px"})),this.results_build(),this.set_tab_index(),this.form_field_jq.trigger("liszt:ready",{chosen:this})},b.prototype.register_observers=function(){this.container.mousedown(g(function(a){return this.container_mousedown(a)},this)),this.container.mouseup(g(function(a){return this.container_mouseup(a)},this)),this.container.mouseenter(g(function(a){return this.mouse_enter(a)},this)),this.container.mouseleave(g(function(a){return this.mouse_leave(a)},this)),this.search_results.mouseup(g(function(a){return this.search_results_mouseup(a)},this)),this.search_results.mouseover(g(function(a){return this.search_results_mouseover(a)},this)),this.search_results.mouseout(g(function(a){return this.search_results_mouseout(a)},this)),this.form_field_jq.bind("liszt:updated",g(function(a){return this.results_update_field(a)},this)),this.search_field.blur(g(function(a){return this.input_blur(a)},this)),this.search_field.keyup(g(function(a){return this.keyup_checker(a)},this)),this.search_field.keydown(g(function(a){return this.keydown_checker(a)},this));if(this.is_multiple)return this.search_choices.click(g(function(a){return this.choices_click(a)},this)),this.search_field.focus(g(function(a){return this.input_focus(a)},this))},b.prototype.search_field_disabled=function(){this.is_disabled=this.form_field_jq[0].disabled;if(this.is_disabled)return this.container.addClass("chzn-disabled"),this.search_field[0].disabled=!0,this.is_multiple||this.selected_item.unbind("focus",this.activate_action),this.close_field();this.container.removeClass("chzn-disabled"),this.search_field[0].disabled=!1;if(!this.is_multiple)return this.selected_item.bind("focus",this.activate_action)},b.prototype.container_mousedown=function(b){var c;if(!this.is_disabled)return c=b!=null?a(b.target).hasClass("search-choice-close"):!1,b&&b.type==="mousedown"&&b.stopPropagation(),!this.pending_destroy_click&&!c?(this.active_field?!this.is_multiple&&b&&(a(b.target)[0]===this.selected_item[0]||a(b.target).parents("a.chzn-single").length)&&(b.preventDefault(),this.results_toggle()):(this.is_multiple&&this.search_field.val(""),a(document).click(this.click_test_action),this.results_show()),this.activate_field()):this.pending_destroy_click=!1},b.prototype.container_mouseup=function(a){if(a.target.nodeName==="ABBR")return this.results_reset(a)},b.prototype.blur_test=function(a){if(!this.active_field&&this.container.hasClass("chzn-container-active"))return this.close_field()},b.prototype.close_field=function(){return a(document).unbind("click",this.click_test_action),this.is_multiple||(this.selected_item.attr("tabindex",this.search_field.attr("tabindex")),this.search_field.attr("tabindex",-1)),this.active_field=!1,this.results_hide(),this.container.removeClass("chzn-container-active"),this.winnow_results_clear(),this.clear_backstroke(),this.show_search_field_default(),this.search_field_scale()},b.prototype.activate_field=function(){return!this.is_multiple&&!this.active_field&&(this.search_field.attr("tabindex",this.selected_item.attr("tabindex")),this.selected_item.attr("tabindex",-1)),this.container.addClass("chzn-container-active"),this.active_field=!0,this.search_field.val(this.search_field.val()),this.search_field.focus()},b.prototype.test_active_click=function(b){return a(b.target).parents("#"+this.container_id).length?this.active_field=!0:this.close_field()},b.prototype.results_build=function(){var a,b,c,e,f;this.parsing=!0,this.results_data=d.SelectParser.select_to_array(this.form_field),this.is_multiple&&this.choices>0?(this.search_choices.find("li.search-choice").remove(),this.choices=0):this.is_multiple||(this.selected_item.find("span").text(this.default_text),this.form_field.options.length>this.disable_search_threshold?this.container.removeClass("chzn-container-single-nosearch"):this.container.addClass("chzn-container-single-nosearch")),a="",f=this.results_data;for(c=0,e=f.length;c'+a("
        ").text(b.label).html()+"")},b.prototype.result_do_highlight=function(a){var b,c,d,e,f;if(a.length){this.result_clear_highlight(),this.result_highlight=a,this.result_highlight.addClass("highlighted"),d=parseInt(this.search_results.css("maxHeight"),10),f=this.search_results.scrollTop(),e=d+f,c=this.result_highlight.position().top+this.search_results.scrollTop(),b=c+this.result_highlight.outerHeight();if(b>=e)return this.search_results.scrollTop(b-d>0?b-d:0);if(c'+b.html+''),d=a("#"+c).find("a").first(),d.click(g(function(a){return this.choice_destroy_link_click(a)},this))},b.prototype.choice_destroy_link_click=function(b){return b.preventDefault(),this.is_disabled?b.stopPropagation:(this.pending_destroy_click=!0,this.choice_destroy(a(b.target)))},b.prototype.choice_destroy=function(a){return this.choices-=1,this.show_search_field_default(),this.is_multiple&&this.choices>0&&this.search_field.val().length<1&&this.results_hide(),this.result_deselect(a.attr("rel")),a.parents("li").first().remove()},b.prototype.results_reset=function(b){this.form_field.options[0].selected=!0,this.selected_item.find("span").text(this.default_text),this.show_search_field_default(),a(b.target).remove(),this.form_field_jq.trigger("change");if(this.active_field)return this.results_hide()},b.prototype.result_select=function(a){var b,c,d,e;if(this.result_highlight)return b=this.result_highlight,c=b.attr("id"),this.result_clear_highlight(),this.is_multiple?this.result_deactivate(b):(this.search_results.find(".result-selected").removeClass("result-selected"),this.result_single_selected=b),b.addClass("result-selected"),e=c.substr(c.lastIndexOf("_")+1),d=this.results_data[e],d.selected=!0,this.form_field.options[d.options_index].selected=!0,this.is_multiple?this.choice_build(d):(this.selected_item.find("span").first().text(d.text),this.allow_single_deselect&&this.single_deselect_control_build()),(!a.metaKey||!this.is_multiple)&&this.results_hide(),this.search_field.val(""),this.form_field_jq.trigger("change"),this.search_field_scale()},b.prototype.result_activate=function(a){return a.addClass("active-result")},b.prototype.result_deactivate=function(a){return a.removeClass("active-result")},b.prototype.result_deselect=function(b){var c,d;return d=this.results_data[b],d.selected=!1,this.form_field.options[d.options_index].selected=!1,c=a("#"+this.container_id+"_o_"+b),c.removeClass("result-selected").addClass("active-result").show(),this.result_clear_highlight(),this.winnow_results(),this.form_field_jq.trigger("change"),this.search_field_scale()},b.prototype.single_deselect_control_build=function(){if(this.allow_single_deselect&&this.selected_item.find("abbr").length<1)return this.selected_item.find("span").first().after('')},b.prototype.winnow_results=function(){var b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r;this.no_results_clear(),i=0,j=this.search_field.val()===this.default_text?"":a("
        ").text(a.trim(this.search_field.val())).html(),f=new RegExp("^"+j.replace(/[-[\]{}()*+?.,\\^$|#\s]/g,"\\$&"),"i"),m=new RegExp(j.replace(/[-[\]{}()*+?.,\\^$|#\s]/g,"\\$&"),"i"),r=this.results_data;for(n=0,p=r.length;n=0||c.html.indexOf("[")===0){e=c.html.replace(/\[|\]/g,"").split(" ");if(e.length)for(o=0,q=e.length;o"+c.html.substr(k+j.length),l=l.substr(0,k)+""+l.substr(k)):l=c.html,g.html(l),this.result_activate(g),c.group_array_index!=null&&a("#"+this.results_data[c.group_array_index].dom_id).css("display","list-item")):(this.result_highlight&&h===this.result_highlight.attr("id")&&this.result_clear_highlight(),this.result_deactivate(g))}}return i<1&&j.length?this.no_results(j):this.winnow_results_set_highlight()},b.prototype.winnow_results_clear=function(){var b,c,d,e,f;this.search_field.val(""),c=this.search_results.find("li"),f=[];for(d=0,e=c.length;d'+this.results_none_found+' ""'),c.find("span").first().html(b),this.search_results.append(c)},b.prototype.no_results_clear=function(){return this.search_results.find(".no-results").remove()},b.prototype.keydown_arrow=function(){var b,c;this.result_highlight?this.results_showing&&(c=this.result_highlight.nextAll("li.active-result").first(),c&&this.result_do_highlight(c)):(b=this.search_results.find("li.active-result").first(),b&&this.result_do_highlight(a(b)));if(!this.results_showing)return this.results_show()},b.prototype.keyup_arrow=function(){var a;if(!this.results_showing&&!this.is_multiple)return this.results_show();if(this.result_highlight)return a=this.result_highlight.prevAll("li.active-result"),a.length?this.result_do_highlight(a.first()):(this.choices>0&&this.results_hide(),this.result_clear_highlight())},b.prototype.keydown_backstroke=function(){return this.pending_backstroke?(this.choice_destroy(this.pending_backstroke.find("a").first()),this.clear_backstroke()):(this.pending_backstroke=this.search_container.siblings("li.search-choice").last(),this.pending_backstroke.addClass("search-choice-focus"))},b.prototype.clear_backstroke=function(){return this.pending_backstroke&&this.pending_backstroke.removeClass("search-choice-focus"),this.pending_backstroke=null},b.prototype.keydown_checker=function(a){var b,c;b=(c=a.which)!=null?c:a.keyCode,this.search_field_scale(),b!==8&&this.pending_backstroke&&this.clear_backstroke();switch(b){case 8:this.backstroke_length=this.search_field.val().length;break;case 9:this.results_showing&&!this.is_multiple&&this.result_select(a),this.mouse_on_container=!1;break;case 13:a.preventDefault();break;case 38:a.preventDefault(),this.keyup_arrow();break;case 40:this.keydown_arrow()}},b.prototype.search_field_scale=function(){var b,c,d,e,f,g,h,i,j;if(this.is_multiple){d=0,h=0,f="position:absolute; left: -1000px; top: -1000px; display:none;",g=["font-size","font-style","font-weight","font-family","line-height","text-transform","letter-spacing"];for(i=0,j=g.length;i",{style:f}),c.text(this.search_field.val()),a("body").append(c),h=c.width()+25,c.remove(),h>this.f_width-10&&(h=this.f_width-10),this.search_field.css({width:h+"px"}),b=this.container.height(),this.dropdown.css({top:b+"px"})}},b.prototype.generate_random_id=function(){var b;b="sel"+this.generate_random_char()+this.generate_random_char()+this.generate_random_char();while(a("#"+b).length>0)b+=this.generate_random_char();return b},b}(),c=function(a){var b;return b=a.outerWidth()-a.width()},d.get_side_border_padding=c}.call(this) --------------------------------------------------------------------------------