diff --git a/app/assets/images/icons/check.png b/app/assets/images/icons/check.png new file mode 100644 index 0000000..c03bf76 Binary files /dev/null and b/app/assets/images/icons/check.png differ diff --git a/app/assets/stylesheets/application.css.sass b/app/assets/stylesheets/application.css.sass index ed58eae..720d94c 100644 --- a/app/assets/stylesheets/application.css.sass +++ b/app/assets/stylesheets/application.css.sass @@ -32,3 +32,4 @@ $blueprint-grid-columns: 20 @import partials/pagination @import partials/fonts @import partials/articles +@import partials/activities diff --git a/app/assets/stylesheets/partials/_activities.sass b/app/assets/stylesheets/partials/_activities.sass new file mode 100644 index 0000000..004fe84 --- /dev/null +++ b/app/assets/stylesheets/partials/_activities.sass @@ -0,0 +1,37 @@ +div.activity + +container + div.activity_title + +column(20) + font-size: 1.5em + font-family: $display-font + margin-bottom: 1em + line-height: 0.9 + span.registration + float: right + color: #666 + a + font-size: 0.75em + color: #333 + &.participating:before + content: "" + float: left + width: 26px + height: 1em + background: asset-url("icons/check.png", image) no-repeat + &:hover + color: #333 + a + color: $link-active-color + &:hover + color: $link-color + + div.activity_content + +column(15) + h1, h2, h3, h4 + font-size: 1em + div.activity_info + +column(5, true) + text-align: right + div.control-bar + +column(20) + margin-bottom: 0 \ No newline at end of file diff --git a/app/assets/stylesheets/partials/_articles.sass b/app/assets/stylesheets/partials/_articles.sass index ece08c9..c2f3bab 100644 --- a/app/assets/stylesheets/partials/_articles.sass +++ b/app/assets/stylesheets/partials/_articles.sass @@ -32,17 +32,3 @@ article div.control-bar +column(20) margin-bottom: 0 - -hr.separator - border: none - height: 1px - background-color: #ccc - color: #ccc - margin: 2em 0 - -a#back-link - border-top: 1px solid #ccc - padding-top: 1em - margin-top: 1em - display: block - font-family: $display-font \ No newline at end of file diff --git a/app/assets/stylesheets/partials/_base.sass b/app/assets/stylesheets/partials/_base.sass index 51635c2..ccddecd 100644 --- a/app/assets/stylesheets/partials/_base.sass +++ b/app/assets/stylesheets/partials/_base.sass @@ -35,3 +35,17 @@ a.warn margin: 1em 0 a, input, button margin-right: 0.5em + +hr.separator + border: none + height: 1px + background-color: #ccc + color: #ccc + margin: 2em 0 + +a#back-link + border-top: 1px solid #ccc + padding-top: 1em + margin-top: 1em + display: block + font-family: $display-font \ No newline at end of file diff --git a/app/controllers/activities_controller.rb b/app/controllers/activities_controller.rb new file mode 100644 index 0000000..ae63d12 --- /dev/null +++ b/app/controllers/activities_controller.rb @@ -0,0 +1,33 @@ +class ActivitiesController < ApplicationController + before_filter :user_required + before_filter :find_activity, :only => [:show, :edit, :update, :destroy, :register] + + def index + @activities = Activity.includes(:author).order("created_at desc"). + paginate(:page => params[:page]) + @activities = ActivityDecorator.decorate(@activities) + end + + def register + registration = @activity.activity_registrations. + where(:user_id => current_user.id) + + if registration.any? + registration.first.destroy + else + registration.create + end + + @activity = ActivityDecorator.decorate(@activity) + + respond_to do |format| + format.js + end + end + + private + + def find_activity + @activity = Activity.find_by_slug(params[:id]) + end +end diff --git a/app/decorators/activity_decorator.rb b/app/decorators/activity_decorator.rb new file mode 100644 index 0000000..870a4e8 --- /dev/null +++ b/app/decorators/activity_decorator.rb @@ -0,0 +1,43 @@ +class ActivityDecorator < ApplicationDecorator + decorates :activity + + def registration_button + h.content_tag(:span, :class => "registration") do + if activity.registration_open? + if activity.approved_participants.include?(h.current_user) + text = "Participating" + css_class = "participating" + elsif activity.users.include?(h.current_user) + text = "Pending Approval" + else + text = "Participate" + end + + h.link_to(text, h.register_activity_path(activity), + :class => "clean-gray #{css_class if css_class}", + :method => :post, :remote => true) + else + "Registration Closed" + end + end + end + + def created_at + h.l activity.created_at.to_date, :format => :long + end + + def author_link + "by #{h.link_to(activity.author.name, h.person_path(activity.author))}".html_safe + end + + def participants_link + participants = activity.approved_participants + + if participants.any? + link = h.link_to h.pluralize(participants.count, 'participant'), + h.activity_path(activity, :anchor => "participants") + end + + h.content_tag(:div, link || "", :class => "participants").html_safe + end +end diff --git a/app/decorators/application_decorator.rb b/app/decorators/application_decorator.rb index 4ab1fed..dcb494b 100644 --- a/app/decorators/application_decorator.rb +++ b/app/decorators/application_decorator.rb @@ -1,28 +1,12 @@ class ApplicationDecorator < Draper::Base - # Lazy Helpers - # PRO: Call Rails helpers without the h. proxy - # ex: number_to_currency(model.price) - # CON: Add a bazillion methods into your decorator's namespace - # and probably sacrifice performance/memory - # - # Enable them by uncommenting this line: - # lazy_helpers - # Shared Decorations - # Consider defining shared methods common to all your models. - # - # Example: standardize the formatting of timestamps - # - # def formatted_timestamp(time) - # h.content_tag :span, time.strftime("%a %m/%d/%y"), - # :class => 'timestamp' - # end - # - # def created_at - # formatted_timestamp(model.created_at) - # end - # - # def updated_at - # formatted_timestamp(model.updated_at) - # end + def bottom(collection, collection_path) + if collection + h.tag(:hr, :class => "separator") if model != collection.last + else + h.link_to "« There is more where that came from".html_safe, + collection_path, :id => "back-link" + end + end + end \ No newline at end of file diff --git a/app/decorators/article_decorator.rb b/app/decorators/article_decorator.rb index b6fd4bf..15125d8 100644 --- a/app/decorators/article_decorator.rb +++ b/app/decorators/article_decorator.rb @@ -10,15 +10,6 @@ def body h.md(article.body) end - def bottom(articles) - if articles - h.tag(:hr, :class => "separator") if article != articles.last - else - h.link_to "« There is more where that came from".html_safe, - h.articles_path, :id => "back-link" - end - end - def twitter via = "via @" + article.author.twitter unless article.author.twitter.blank? url = short_url diff --git a/app/models/activity.rb b/app/models/activity.rb new file mode 100644 index 0000000..c5f558d --- /dev/null +++ b/app/models/activity.rb @@ -0,0 +1,20 @@ +class Activity < ActiveRecord::Base + + belongs_to :author, :class_name => "User" + has_many :activity_registrations + has_many :users, :through => :activity_registrations + + has_slug 'title', :max_length => 40, + :on_conflict => :append_id + + validates_presence_of :title, :body, :author + + def to_param + slug + end + + def approved_participants + users.includes(:activity_registrations). + where("activity_registrations.approved = true") + end +end diff --git a/app/models/activity_registration.rb b/app/models/activity_registration.rb new file mode 100644 index 0000000..e27a2a9 --- /dev/null +++ b/app/models/activity_registration.rb @@ -0,0 +1,16 @@ +class ActivityRegistration < ActiveRecord::Base + before_create :set_approval + + belongs_to :user + belongs_to :activity + + attr_protected :approved + + private + + def set_approval + self.approved = !activity.participation_moderated? + + return true + end +end diff --git a/app/models/user.rb b/app/models/user.rb index e1207fb..7c562a9 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -1,7 +1,9 @@ class User < ActiveRecord::Base before_save :clean_website - has_many :articles, :foreign_key => :author_id + has_many :articles, :foreign_key => :author_id + has_many :activities, :foreign_key => :author_id + has_many :activity_registrations GITHUB_FORMAT = { :with => /^(?!-)[a-z\d-]+/i, diff --git a/app/views/activities/_activity.html.haml b/app/views/activities/_activity.html.haml new file mode 100644 index 0000000..cd8c02b --- /dev/null +++ b/app/views/activities/_activity.html.haml @@ -0,0 +1,25 @@ += content_tag_for :div, activity do + .activity_title + - if @activities + = link_to activity.title, activity_path(activity) + - else + = activity.title + + = activity.registration_button + + .activity_content= activity.body + + .activity_info + = activity.participants_link + = activity.author_link + %br + = activity.created_at + + - if false #activity.editable_by?(current_user) + .control-bar + = link_to 'Edit', edit_activity_path(activity), :class => "clean-gray" + = link_to 'Destroy', activity, :confirm => 'Are you sure?', + :method => :delete, :class => "clean-gray warn" + += activity.bottom(@activities, activities_path) + diff --git a/app/views/activities/index.html.haml b/app/views/activities/index.html.haml new file mode 100644 index 0000000..35f0f23 --- /dev/null +++ b/app/views/activities/index.html.haml @@ -0,0 +1,3 @@ +#activities= render :partial => "activity", :collection => @activities + += will_paginate @activities \ No newline at end of file diff --git a/app/views/activities/register.js.erb b/app/views/activities/register.js.erb new file mode 100644 index 0000000..eb84cdd --- /dev/null +++ b/app/views/activities/register.js.erb @@ -0,0 +1,5 @@ +var button = '<%= escape_javascript @activity.registration_button %>'; +var participants = '<%= escape_javascript @activity.participants_link %>'; + +$('#activity_<%= @activity.id %> span.registration').replaceWith(button); +$('#activity_<%= @activity.id %> div.participants').replaceWith(participants); \ No newline at end of file diff --git a/app/views/articles/_article.html.haml b/app/views/articles/_article.html.haml index 695e4ff..925498e 100644 --- a/app/views/articles/_article.html.haml +++ b/app/views/articles/_article.html.haml @@ -9,5 +9,4 @@ = render 'user_info', :article => article, :profile_size => "100" -= article.bottom(@articles) - += article.bottom(@articles, articles_path) diff --git a/app/views/shared/_navigation.html.haml b/app/views/shared/_navigation.html.haml index c6ec8d5..6473cf7 100644 --- a/app/views/shared/_navigation.html.haml +++ b/app/views/shared/_navigation.html.haml @@ -5,6 +5,7 @@ = render :partial => "shared/flash", :locals => { :flash => flash } %span.nav = link_to "Updates", articles_path + = link_to("Activities", activities_path) if current_user = link_to "About", about_path %span#account - if current_user diff --git a/config/routes.rb b/config/routes.rb index bdc853d..7b48d8c 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -8,6 +8,11 @@ resources :people resources :articles + resources :activities do + member do + post :register + end + end namespace :admin do resources :pages diff --git a/db/migrate/20120113160904_create_activities.rb b/db/migrate/20120113160904_create_activities.rb new file mode 100644 index 0000000..ac30a9d --- /dev/null +++ b/db/migrate/20120113160904_create_activities.rb @@ -0,0 +1,15 @@ +class CreateActivities < ActiveRecord::Migration + def change + create_table :activities do |t| + t.integer :author_id + t.string :title + t.string :slug + t.text :body + + t.boolean :registration_open, :null => false + t.boolean :participation_moderated, :null => false + + t.timestamps + end + end +end diff --git a/db/migrate/20120113162402_create_activity_registrations.rb b/db/migrate/20120113162402_create_activity_registrations.rb new file mode 100644 index 0000000..268625a --- /dev/null +++ b/db/migrate/20120113162402_create_activity_registrations.rb @@ -0,0 +1,12 @@ +class CreateActivityRegistrations < ActiveRecord::Migration + def change + create_table :activity_registrations do |t| + t.belongs_to :user + t.belongs_to :activity + + t.boolean :approved, :null => false + + t.timestamps + end + end +end diff --git a/db/schema.rb b/db/schema.rb index cc1d094..d1b87bd 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -11,7 +11,26 @@ # # It's strongly recommended to check this file into your version control system. -ActiveRecord::Schema.define(:version => 20120116220134) do +ActiveRecord::Schema.define(:version => 20120113162402) do + + create_table "activities", :force => true do |t| + t.integer "author_id" + t.string "title" + t.string "slug" + t.text "body" + t.boolean "registration_open", :null => false + t.boolean "participation_moderated", :null => false + t.datetime "created_at" + t.datetime "updated_at" + end + + create_table "activity_registrations", :force => true do |t| + t.integer "user_id" + t.integer "activity_id" + t.boolean "approved", :null => false + t.datetime "created_at" + t.datetime "updated_at" + end create_table "articles", :force => true do |t| t.integer "author_id"