diff --git a/.gitignore b/.gitignore
index 0f2c82fccf..5575fbe70f 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,6 +1,8 @@
config/mail.yml
*.log
*~
+db/db_development
+db/db_test
db/*.sqlite*
db/schema.rb
.*.swp
diff --git a/Gemfile.lock b/Gemfile.lock
index 64eb36cc1c..637cf5f00d 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -1,5 +1,5 @@
GEM
- remote: http://rubygems.org/
+ remote: https://rubygems.org/
specs:
RedCloth (4.2.9)
abstract (1.0.0)
@@ -205,3 +205,6 @@ DEPENDENCIES
thin
uuidtools (~> 2.1.1)
webrat
+
+BUNDLED WITH
+ 1.11.2
diff --git a/app/controllers/admin/categories_controller.rb b/app/controllers/admin/categories_controller.rb
index b7026f8f29..d4895700b1 100644
--- a/app/controllers/admin/categories_controller.rb
+++ b/app/controllers/admin/categories_controller.rb
@@ -4,10 +4,10 @@ class Admin::CategoriesController < Admin::BaseController
def index; redirect_to :action => 'new' ; end
def edit; new_or_edit; end
- def new
+ def new
respond_to do |format|
format.html { new_or_edit }
- format.js {
+ format.js {
@category = Category.new
}
end
@@ -25,12 +25,17 @@ def destroy
def new_or_edit
@categories = Category.find(:all)
- @category = Category.find(params[:id])
+ @category = case params[:id]
+ when nil
+ Category.new
+ else
+ Category.find(params[:id])
+ end
@category.attributes = params[:category]
if request.post?
respond_to do |format|
format.html { save_category }
- format.js do
+ format.js do
@category.save
@article = Article.new
@article.categories << @category
@@ -43,7 +48,7 @@ def new_or_edit
end
def save_category
- if @category.save!
+ if @category.save
flash[:notice] = _('Category was successfully saved.')
else
flash[:error] = _('Category could not be saved.')
diff --git a/app/controllers/admin/content_controller.rb b/app/controllers/admin/content_controller.rb
index 6ef4ebf969..82d39b7554 100644
--- a/app/controllers/admin/content_controller.rb
+++ b/app/controllers/admin/content_controller.rb
@@ -13,7 +13,7 @@ def auto_complete_for_article_keywords
def index
@search = params[:search] ? params[:search] : {}
-
+
@articles = Article.search_with_pagination(@search, {:page => params[:page], :per_page => this_blog.admin_display_elements})
if request.xhr?
@@ -44,7 +44,7 @@ def destroy
flash[:error] = _("Error, you are not allowed to perform this action")
return(redirect_to :action => 'index')
end
-
+
return(render 'admin/shared/destroy') unless request.post?
@record.destroy
@@ -77,7 +77,7 @@ def attachment_box_add
def attachment_save(attachment)
begin
- Resource.create(:filename => attachment.original_filename, :mime => attachment.content_type.chomp,
+ Resource.create(:filename => attachment.original_filename, :mime => attachment.content_type.chomp,
:created_at => Time.now).write_to_disk(attachment)
rescue => e
logger.info(e.message)
@@ -92,7 +92,7 @@ def autosave
@article.text_filter = current_user.text_filter if current_user.simple_editor?
get_fresh_or_existing_draft_for_article
-
+
@article.attributes = params[:article]
@article.published = false
set_article_author
@@ -113,6 +113,22 @@ def autosave
render :text => nil
end
+ def merge
+ @article_1 = Article.find(params[:id])
+ # check to see that article with entered ID exists and isn't the same as the current article
+ if !Article.find_by_id(params[:merge_with]).nil? && (params[:merge_with] != params[:id])
+ @article_1.merge_with(params[:merge_with])
+ flash[:notice] = _('Article was successfully merged')
+ redirect_to :action => 'index'
+ elsif Article.find_by_id(params[:merge_with]).nil?
+ flash[:error] = _("An article doesn't exist with that ID! Please try again")
+ new_or_edit
+ else
+ flash[:error] = _("You can't merge this article with itself! Please try again")
+ new_or_edit
+ end
+ end
+
protected
def get_fresh_or_existing_draft_for_article
@@ -159,13 +175,13 @@ def new_or_edit
@article.keywords = Tag.collection_to_string @article.tags
@article.attributes = params[:article]
# TODO: Consider refactoring, because double rescue looks... weird.
-
+
@article.published_at = DateTime.strptime(params[:article][:published_at], "%B %e, %Y %I:%M %p GMT%z").utc rescue Time.parse(params[:article][:published_at]).utc rescue nil
if request.post?
set_article_author
save_attachments
-
+
@article.state = "draft" if @article.draft
if @article.save
diff --git a/app/models/article.rb b/app/models/article.rb
index c80469b734..52f7694cf8 100644
--- a/app/models/article.rb
+++ b/app/models/article.rb
@@ -104,10 +104,10 @@ def last_draft(article_id)
end
def search_with_pagination(search_hash, paginate_hash)
-
+
state = (search_hash[:state] and ["no_draft", "drafts", "published", "withdrawn", "pending"].include? search_hash[:state]) ? search_hash[:state] : 'no_draft'
-
-
+
+
list_function = ["Article.#{state}"] + function_search_no_draft(search_hash)
if search_hash[:category] and search_hash[:category].to_i > 0
@@ -416,6 +416,17 @@ def access_by?(user)
user.admin? || user_id == user.id
end
+ def merge_with(other_article_id)
+ # keep title and author from article 1 (self)
+ article_2 = Article.find(other_article_id.to_i)
+ # combine body and comments from both articles
+ self.body += " #{article_2.body}"
+ self.comments += article_2.comments
+ self.save
+ article_2.delete
+ return self
+ end
+
protected
def set_published_at
diff --git a/app/views/admin/content/_merge.html.erb b/app/views/admin/content/_merge.html.erb
new file mode 100644
index 0000000000..57c79b31e5
--- /dev/null
+++ b/app/views/admin/content/_merge.html.erb
@@ -0,0 +1,13 @@
+
diff --git a/app/views/admin/shared/_edit.html.erb b/app/views/admin/shared/_edit.html.erb
index a4f213ddb7..84159f8daa 100644
--- a/app/views/admin/shared/_edit.html.erb
+++ b/app/views/admin/shared/_edit.html.erb
@@ -4,3 +4,7 @@
<%= render :partial => "form" %>
<% end %>
+
+<% if params[:id] && @current_user.admin? %>
+ <%= render :partial => "merge" %>
+<% end %>
diff --git a/config/routes.rb b/config/routes.rb
index 082e0ea906..3bbbb57342 100644
--- a/config/routes.rb
+++ b/config/routes.rb
@@ -106,6 +106,7 @@
end
# Admin/XController
+
%w{advanced cache categories comments content profiles feedback general pages
resources sidebar textfilters themes trackbacks users settings tags redirects seo post_types }.each do |i|
match "/admin/#{i}", :to => "admin/#{i}#index", :format => false
diff --git a/features/create_category.feature b/features/create_category.feature
new file mode 100644
index 0000000000..9bd5ba4ece
--- /dev/null
+++ b/features/create_category.feature
@@ -0,0 +1,25 @@
+Feature: Create Categories
+ As a blog administrator
+ I want to be able to create Categories
+
+ Background:
+ Given the blog is set up
+ And I am logged into the admin panel
+
+ Scenario: Successfully create new Categories
+ When I click on Categories
+ Then I should be on the new category page
+ When I fill in "category_name" with "Meow Meow"
+ And I fill in "category_keywords" with "Cats"
+ And I fill in "category_description" with "I like cats"
+ And I press "Save"
+ Then I should see "Meow Meow"
+ And I should see "Cats"
+ And I should see "I like cats"
+
+ Scenario: Try to create a Category without a name
+ When I click on Categories
+ Then I should be on the new category page
+ When I fill in "category_name" with ""
+ And I press "Save"
+ Then page should have error message "Category could not be saved."
diff --git a/features/edit_category.feature b/features/edit_category.feature
new file mode 100644
index 0000000000..e0876a8fd2
--- /dev/null
+++ b/features/edit_category.feature
@@ -0,0 +1,30 @@
+Feature: Edit Categories
+ As a blog administrator
+ I want to be able to edit Categories
+
+ Background:
+ Given the blog is set up
+ And I am logged into the admin panel
+ And I have an existing Category named "Meow"
+
+ Scenario: Successfully edit existing Categories
+ When I click on Categories
+ Then I should be on the new category page
+ When I follow "Meow"
+ Then I should be on the edit category page
+ When I fill in "category_name" with "Meow Meow"
+ And I fill in "category_keywords" with "Cats Meow"
+ And I fill in "category_description" with "I really really like cats"
+ And I press "Save"
+ Then I should see "Meow Meow"
+ And I should see "Cats Meow"
+ And I should see "I really really like cats"
+
+ Scenario: Try to edit a Category and remove the name
+ When I click on Categories
+ Then I should be on the new category page
+ When I follow "Meow"
+ Then I should be on the edit category page
+ When I fill in "category_name" with ""
+ And I press "Save"
+ Then page should have error message "Category could not be saved."
diff --git a/features/merge_article.feature b/features/merge_article.feature
new file mode 100644
index 0000000000..6bdc6f1d30
--- /dev/null
+++ b/features/merge_article.feature
@@ -0,0 +1,23 @@
+Feature: Merge Articles
+ As a blog administrator
+ In order to keep the world spam-free
+ I want to be able to merge similar articles on my blog
+
+ Background:
+ Given the blog is set up
+ And I am logged into the admin panel
+ And an article exists with title "Entry 1" and text "This is entry 1" and author "I Like Cats"
+
+ Scenario: Admin can successfully merge articles
+ Given I am on the edit article page
+ Then I should see "Merge Articles"
+ When I fill in "merge_with" with "3"
+ And I press "Merge"
+ Then I should be on the admin content page
+ And I should see "Article was successfully merged"
+ And I should see "Hello World!"
+ And I should see "admin"
+ And I should not see "Entry 1"
+ And I should not see "I Like Cats"
+ When I follow "Hello World!"
+ Then I should see "Welcome to Typo. This is your first article. Edit or delete it, then start blogging! This is entry 1"
diff --git a/features/non_admins_cant_merge_articles.feature b/features/non_admins_cant_merge_articles.feature
new file mode 100644
index 0000000000..ad736987a7
--- /dev/null
+++ b/features/non_admins_cant_merge_articles.feature
@@ -0,0 +1,12 @@
+Feature: Merge Articles
+ As a non-admin blog user
+ I can't have special things
+ So I can't merge articles
+
+ Background:
+ Given the blog is set up
+ And an article exists with title "Entry 1" and text "This is entry 1" and author "I Like Cats"
+
+ Scenario: Non-admin cannot merge articles
+ Given I am on the edit article page
+ Then I should not see "Merge Articles"
diff --git a/features/step_definitions/web_steps.rb b/features/step_definitions/web_steps.rb
index 6315105872..27168644c6 100644
--- a/features/step_definitions/web_steps.rb
+++ b/features/step_definitions/web_steps.rb
@@ -250,7 +250,7 @@ def with_scope(locator)
end
end
end
-
+
Then /^(?:|I )should be on (.+)$/ do |page_name|
current_path = URI.parse(current_url).path
if current_path.respond_to? :should
@@ -264,8 +264,8 @@ def with_scope(locator)
query = URI.parse(current_url).query
actual_params = query ? CGI.parse(query) : {}
expected_params = {}
- expected_pairs.rows_hash.each_pair{|k,v| expected_params[k] = v.split(',')}
-
+ expected_pairs.rows_hash.each_pair{|k,v| expected_params[k] = v.split(',')}
+
if actual_params.respond_to? :should
actual_params.should == expected_params
else
@@ -276,3 +276,21 @@ def with_scope(locator)
Then /^show me the page$/ do
save_and_open_page
end
+
+When /^I click on Categories$/ do
+ click_link('Categories')
+end
+
+Given /^I have an existing Category named "(.*?)"$/ do |arg1|
+ Category.create!({:name => 'Meow'})
+end
+
+Then /^page should have error message "(.*?)"$/ do |arg1|
+ page.should have_content('Category could not be saved')
+end
+
+Given /^an article exists with title "(.*?)" and text "(.*?)" and author "(.*?)"$/ do |arg1, arg2, arg3|
+ Article.create!({:title => arg1,
+ :body => arg2,
+ :author => arg3})
+end
diff --git a/features/support/paths.rb b/features/support/paths.rb
index e7e00e5d89..214c895318 100644
--- a/features/support/paths.rb
+++ b/features/support/paths.rb
@@ -17,7 +17,15 @@ def path_to(page_name)
'/'
when /^the new article page$/
'/admin/content/new'
-
+ when /^the new category page$/
+ '/admin/categories/new'
+ when /^the edit category page$/
+ # there has to be a better way to do this...
+ '/admin/categories/edit/2'
+ when /^the edit article page$/
+ 'admin/content/edit/1'
+ when /^the article merge path$/
+ '/admin/content/merge/1'
# Add more mappings here.
# Here is an example that pulls values out of the Regexp:
#
diff --git a/public/javascripts/ckeditor/config.bak b/public/javascripts/ckeditor/config.bak
old mode 100644
new mode 100755
index 187db086f2..492800fd66
--- a/public/javascripts/ckeditor/config.bak
+++ b/public/javascripts/ckeditor/config.bak
@@ -8,7 +8,7 @@ CKEDITOR.editorConfig = function( config )
config.PreserveSessionOnFileBrowser = true;
// Define changes to default configuration here. For example:
//config.language = '';
- config.uiColor = '#E0ECFF';
+ config.uiColor = '#eee';
config.toolbar = 'Basic';
config.entities_greek = false;
config.entities_latin = false;
diff --git a/public/javascripts/ckeditor/config.js b/public/javascripts/ckeditor/config.js
old mode 100644
new mode 100755
index 187db086f2..492800fd66
--- a/public/javascripts/ckeditor/config.js
+++ b/public/javascripts/ckeditor/config.js
@@ -8,7 +8,7 @@ CKEDITOR.editorConfig = function( config )
config.PreserveSessionOnFileBrowser = true;
// Define changes to default configuration here. For example:
//config.language = '';
- config.uiColor = '#E0ECFF';
+ config.uiColor = '#eee';
config.toolbar = 'Basic';
config.entities_greek = false;
config.entities_latin = false;
diff --git a/spec/controllers/admin/categories_controller_spec.rb b/spec/controllers/admin/categories_controller_spec.rb
index bb290f4a0d..b7929e19a9 100644
--- a/spec/controllers/admin/categories_controller_spec.rb
+++ b/spec/controllers/admin/categories_controller_spec.rb
@@ -11,11 +11,22 @@
request.session = { :user => henri.id }
end
- it "test_index" do
+ it "index should redirect to new" do
get :index
- assert_response :redirect, :action => 'index'
+ assert_response :redirect, :action => 'new'
end
+ describe "test_new" do
+ before(:each) do
+ get :new
+ end
+
+ it 'should render template new' do
+ assert_template 'new'
+ end
+
+ end
+
describe "test_edit" do
before(:each) do
get :edit, :id => Factory(:category).id
@@ -48,7 +59,7 @@
it 'should render destroy template' do
assert_response :success
- assert_template 'destroy'
+ assert_template 'destroy'
end
end
@@ -62,5 +73,5 @@
assert_raise(ActiveRecord::RecordNotFound) { Category.find(test_id) }
end
-
+
end
diff --git a/spec/controllers/admin/content_controller_spec.rb b/spec/controllers/admin/content_controller_spec.rb
index 0bee946588..265dea403c 100644
--- a/spec/controllers/admin/content_controller_spec.rb
+++ b/spec/controllers/admin/content_controller_spec.rb
@@ -48,7 +48,7 @@
response.should render_template('index')
response.should be_success
end
-
+
it 'should restrict to withdrawn articles' do
article = Factory(:article, :state => 'withdrawn', :published_at => '2010-01-01')
get :index, :search => {:state => 'withdrawn'}
@@ -56,7 +56,7 @@
response.should render_template('index')
response.should be_success
end
-
+
it 'should restrict to withdrawn articles' do
article = Factory(:article, :state => 'withdrawn', :published_at => '2010-01-01')
get :index, :search => {:state => 'withdrawn'}
@@ -544,6 +544,14 @@ def base_article(options={})
Article.should_not be_exists({:id => draft.id})
Article.should_not be_exists({:id => draft_2.id})
end
+
+ it 'should allow an admin to merge two articles' do
+ article = @article
+ second_article = Factory(:second_article)
+ get :merge, 'id' => @article.id, 'merge_with' => second_article.id
+ article.body.should contain('A content with several data This article will be merged')
+ second_article.should_not be_exists
+ end
end
describe 'resource_add action' do
diff --git a/spec/controllers/admin/post_types_controller_spec.rb b/spec/controllers/admin/post_types_controller_spec.rb
index a1fbc43055..38db09a1cc 100644
--- a/spec/controllers/admin/post_types_controller_spec.rb
+++ b/spec/controllers/admin/post_types_controller_spec.rb
@@ -2,7 +2,7 @@
describe Admin::PostTypesController do
render_views
- before do
+ before do
Factory(:blog)
#TODO delete this after remove fixture
Profile.delete_all
@@ -10,7 +10,7 @@
request.session = { :user => @user.id }
end
- it "index shoudld redirect to new" do
+ it "index should redirect to new" do
get :index
assert_response :redirect, :action => 'new'
end
@@ -41,13 +41,13 @@
get :edit, :id => Factory.build(:post_type).id
assert_template 'new'
end
-
+
it "test_update" do
post :edit, :id => Factory(:post_type).id
assert_response :redirect, :action => 'index'
end
end
-
+
describe "test_destroy with GET" do
before(:each) do
test_id = Factory(:post_type).id
@@ -57,7 +57,7 @@
it 'should render destroy template' do
assert_response :success
- assert_template 'destroy'
+ assert_template 'destroy'
end
end
@@ -71,6 +71,6 @@
assert_raise(ActiveRecord::RecordNotFound) { PostType.find(test_id) }
end
-
+
end
diff --git a/spec/factories.rb b/spec/factories.rb
index 4fc9247d10..cea02dca32 100644
--- a/spec/factories.rb
+++ b/spec/factories.rb
@@ -116,6 +116,7 @@ def some_article
Factory.define :second_article, :parent => :article do |a|
a.title 'Another big article'
+ a.body 'This article will be merged'
a.published_at Time.now - 2.seconds
end