-
Notifications
You must be signed in to change notification settings - Fork 78
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #62 from coursemology-collab/wangqiang/announcemen…
…t-module-declaration announcement pages
- Loading branch information
Showing
12 changed files
with
312 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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' |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
h2= t('.header') | ||
|
||
= render 'form' |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
h2= t('.header') | ||
|
||
= render 'form' |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -61,6 +61,8 @@ | |
end | ||
|
||
scope module: 'course' do | ||
resources :courses | ||
resources :courses do | ||
resources :announcements | ||
end | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 |