Skip to content

Commit

Permalink
Merge pull request #62 from coursemology-collab/wangqiang/announcemen…
Browse files Browse the repository at this point in the history
…t-module-declaration

announcement pages
  • Loading branch information
lowjoel committed Jan 28, 2015
2 parents 63d6373 + 973d796 commit 007e7da
Show file tree
Hide file tree
Showing 12 changed files with 312 additions and 1 deletion.
47 changes: 47 additions & 0 deletions app/controllers/course/announcements_controller.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
class Course::AnnouncementsController < Course::ModuleController
load_and_authorize_resource :announcement, through: :course, class: Course::Announcement.name

def index #:nodoc:
@announcements = @announcements.includes(:creator).sorted_by_date
end

def show #:nodoc:
end

def new #:nodoc:
end

def edit #:nodoc:
end

def create #:nodoc:
if @announcement.save
redirect_to(course_announcements_path(@course),
notice: t('.notice', title: @announcement.title))
else
render 'new'
end
end

def update #:nodoc:
if @announcement.update_attributes(announcement_params)
redirect_to(course_announcements_path(@course),
notice: t('.notice', title: @announcement.title))
else
render 'edit'
end
end

def destroy #:nodoc:
if @announcement.destroy
redirect_to(course_announcements_path(@course),
notice: t('.notice', title: @announcement.title))
end
end

private

def announcement_params #:nodoc:
params.require(:course_announcement).permit(:title, :content, :valid_from, :valid_to)
end
end
12 changes: 12 additions & 0 deletions app/controllers/modules/course/announcements_module.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
class Course::AnnouncementsModule
include Course::CoursesController::Module

sidebar do
[
{
title: I18n.t('course.announcements.sidebar_title'),
unread: 0
}
]
end
end
8 changes: 8 additions & 0 deletions app/helpers/application_helper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -57,4 +57,12 @@ def link_to_user(user)
end
end
end

# Format the given datetime
#
# @param date [DateTime] The datetime to be formatted
# @return [String] the formatted datetime string
def format_datetime(date, format = :long)
date.to_formatted_s(format)
end
end
15 changes: 15 additions & 0 deletions app/models/course/announcement.rb
Original file line number Diff line number Diff line change
@@ -1,6 +1,21 @@
class Course::Announcement < ActiveRecord::Base
stampable

after_initialize :set_defaults, if: :new_record?

belongs_to :creator, class_name: User.name
belongs_to :course, inverse_of: :announcements

scope :sorted_by_date, -> { order(valid_from: :desc) }

# Set default values
def set_defaults
self.valid_from ||= Time.now
self.valid_to ||= 7.days.from_now
end

# return [Bool] True if valid_from is a future time
def valid_in_future?
valid_from > DateTime.now
end
end
21 changes: 21 additions & 0 deletions app/views/course/announcements/_announcement.html.slim
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
hr
div class=("announcement #{'future' if announcement.valid_in_future? }")
h2
= announcement.title

- if can?(:manage, Course::Announcement)
div.pull-right
= link_to edit_course_announcement_path(@course, announcement), class: 'btn btn-default' do
= fa_icon 'edit'

= link_to course_announcement_path(@course, announcement),
class: 'btn btn-danger', method: :delete do
= fa_icon 'trash'

div.timestamp
= format_datetime(announcement.valid_from)
| by
= link_to_user(announcement.creator)

div.content
= announcement.content
10 changes: 10 additions & 0 deletions app/views/course/announcements/_form.html.slim
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
= simple_form_for [@course, @announcement], resource: :course_announcement do |f|
= f.input :title

= f.input :content

= f.input :valid_from

= f.input :valid_to

= f.button :submit, class: 'btn-primary'
3 changes: 3 additions & 0 deletions app/views/course/announcements/edit.html.slim
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
h2= t('.header')

= render 'form'
7 changes: 7 additions & 0 deletions app/views/course/announcements/index.html.slim
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
h1 = t('.header')

- if can?(:create, Course::Announcement)
= link_to t('.new'), new_course_announcement_path(@course), class: 'btn btn-primary'

= render @announcements

3 changes: 3 additions & 0 deletions app/views/course/announcements/new.html.slim
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
h2= t('.header')

= render 'form'
16 changes: 16 additions & 0 deletions config/locales/en.yml
Original file line number Diff line number Diff line change
Expand Up @@ -46,3 +46,19 @@ en:
description_label: 'Give it an awesome backstory'
description_placeholder: 'e.g. Darth Vader is taking over the universe. We need you to save
the day!'
announcements:
sidebar_title: 'Announcements'
index:
header: 'Announcements'
new: 'New'
new:
header: 'New Announcement'
edit:
header: 'Edit Announcement'
create:
notice: "Announcement %{title} was created."
update:
notice: "Announcement %{title} was updated."
destroy:
notice: "Announcement %{title} was deleted."

4 changes: 3 additions & 1 deletion config/routes.rb
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,8 @@
end

scope module: 'course' do
resources :courses
resources :courses do
resources :announcements
end
end
end
167 changes: 167 additions & 0 deletions spec/features/course/announcement_management_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,167 @@
require 'rails_helper'

describe 'Announcement management' do
subject { page }

let!(:instance) { create(:instance) }

with_tenant(:instance) do
let!(:user) { create(:user, role: :administrator) }
let!(:course) { create(:course) }

before do
login_as(user, scope: :user)
end

describe 'announcement creation' do
before { visit new_course_announcement_path(course) }

context 'with invalid information' do
before { click_button 'Create' }

it 'stays on the same page' do
expect(page).to have_button('Create')
end

it 'shows errors' do
expect(page).to have_css('div.has-error')
end
end

context 'with valid information' do
let(:announcement) { build(:course_announcement, course: course) }

before do
fill_in 'course_announcement_title', with: announcement.title
fill_in 'course_announcement_content', with: announcement.content
end

it 'creates an announcement' do
expect { click_button 'Create' }.to change(Course::Announcement, :count).by(1)
end

context 'after creation' do
before { click_button 'Create' }

it 'shows the success message' do
expect(page).to have_selector('div',
text: I18n.translate('course.announcements.create.notice',
title: announcement.title))
end

it 'redirects the user to the index page' do
expect(current_path).to eq(course_announcements_path(course))
end
end
end
end

describe 'announcement editing' do
let!(:announcement) { create(:course_announcement, course: course) }

before { visit edit_course_announcement_path(course, announcement) }

context 'page rendering' do
it { is_expected.to have_field('course_announcement_title', with: announcement.title) }
it { is_expected.to have_field('course_announcement_content', with: announcement.content) }
it do
is_expected.to have_field('course_announcement[valid_from]',
with: announcement.valid_from)
end
it do
is_expected.to have_field('course_announcement[valid_to]', with: announcement.valid_to)
end
end

context 'with invalid information' do
before do
fill_in 'course_announcement_title', with: ''
click_button 'Update'
end

it 'stays on the same page' do
expect(page).to have_button('Update')
end

it 'shows errors' do
expect(page).to have_css('div.has-error')
end
end

context 'with valid information' do
let(:new_title) { 'New Title' }
let(:new_content) { 'New content' }

before do
fill_in 'course_announcement_title', with: new_title
fill_in 'course_announcement_content', with: new_content
click_button 'Update'
end

it 'redirects the user to index page' do
expect(current_path).to eq course_announcements_path(course)
end

it 'shows the success message' do
expect(page).to have_selector('div',
text: I18n.translate('course.announcements.update.notice',
title: new_title))
end

it 'changes the attributes' do
expect(announcement.reload.title).to eq(new_title)
expect(announcement.reload.content).to eq(new_content)
end
end
end

describe 'index' do
let!(:announcements) { create_list(:course_announcement, 10, course: course) }

before do
visit course_announcements_path(course)
end

context 'management buttons' do
it { is_expected.to have_link('New') }
end

it 'shows all announcements' do
announcements.each do |announcement|
expect(page).to have_selector('div', text: announcement.title)
expect(page).to have_selector('div', text: announcement.content)
end
end

it 'shows all management buttons' do
announcements.each do |announcement|
expect(page).to have_link('', href: edit_course_announcement_path(course, announcement))
expect(page).to have_link('', href: course_announcement_path(course, announcement))
end
end
end

describe 'announcement destruction' do
let!(:announcement) { create(:course_announcement, course: course) }
let(:announcement_path) { course_announcement_path(course, announcement) }

before { visit course_announcements_path(course) }

it 'deletes the announcement' do
expect do
find(:xpath, "//a[@href=\"#{ announcement_path }\"]").click
end.to change(Course::Announcement, :count).by(-1)
end

context 'after announcement deleted' do
before { find(:xpath, "//a[@href=\"#{ announcement_path }\"]").click }

it 'shows the notice message' do
expect(page).to have_selector('div',
text: I18n.translate('course.announcements.destroy.notice',
title: announcement.title))
end
end
end
end
end

0 comments on commit 007e7da

Please sign in to comment.