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 @@ +
+

Merge Articles

+
+
+ +
+ +
+
+
+ +
+
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