crowdblog 0.0.16 → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (93) hide show
  1. data/.gitignore +2 -0
  2. data/Gemfile +0 -10
  3. data/README.md +94 -3
  4. data/Rakefile +1 -7
  5. data/app/assets/images/crowdblog/logo.png +0 -0
  6. data/app/assets/javascripts/crowdblog/models/post.js.coffee +4 -9
  7. data/app/assets/javascripts/crowdblog/views/attachment_view.js.coffee +12 -0
  8. data/app/assets/javascripts/crowdblog/views/post_form_view.js.coffee +21 -0
  9. data/app/assets/javascripts/crowdblog/views/post_view.js.coffee +52 -0
  10. data/app/assets/javascripts/crowdblog.js +7 -11
  11. data/app/assets/stylesheets/crowdblog/posts.css.scss +26 -5
  12. data/app/assets/stylesheets/crowdblog.css +0 -1
  13. data/app/controllers/crowdblog/application_controller.rb +13 -0
  14. data/app/controllers/crowdblog/assets_controller.rb +2 -2
  15. data/app/controllers/crowdblog/authors_controller.rb +2 -2
  16. data/app/controllers/crowdblog/devise/sessions_controller.rb +3 -0
  17. data/app/controllers/crowdblog/posts_controller.rb +37 -16
  18. data/app/models/crowdblog/asset.rb +0 -1
  19. data/app/models/crowdblog/post.rb +15 -5
  20. data/app/models/crowdblog/user.rb +9 -1
  21. data/app/views/crowdblog/application/_navbar.html.slim +11 -0
  22. data/app/views/crowdblog/application/_notices.html.slim +6 -0
  23. data/app/views/crowdblog/authors/index.html.slim +2 -2
  24. data/app/views/crowdblog/devise/_links.erb +25 -0
  25. data/app/views/crowdblog/devise/sessions/new.html.erb +21 -0
  26. data/app/views/crowdblog/posts/_form.html.slim +31 -0
  27. data/app/views/crowdblog/posts/_post.html.slim +13 -0
  28. data/app/views/crowdblog/posts/edit.html.slim +14 -0
  29. data/app/views/crowdblog/posts/index.html.slim +12 -10
  30. data/app/views/crowdblog/posts/new.html.slim +12 -0
  31. data/app/views/crowdblog/posts/update.json.jbuilder +2 -0
  32. data/app/views/layouts/crowdblog/application.html.slim +20 -0
  33. data/config/initializers/date_formats.rb +1 -0
  34. data/config/initializers/devise.rb +16 -0
  35. data/config/locales/devise.en.yml +57 -0
  36. data/config/routes.rb +1 -0
  37. data/crowdblog.gemspec +4 -12
  38. data/db/migrate/20120215232711_create_crowdblog_users.rb +23 -0
  39. data/db/migrate/20120217213920_create_crowdblog_posts.rb +17 -0
  40. data/db/migrate/20120219071614_create_crowdblog_assets.rb +10 -0
  41. data/lib/crowdblog/devise/failure_app.rb +9 -0
  42. data/lib/crowdblog/rspec/crowdblog_shared_examples.rb +108 -0
  43. data/lib/crowdblog/rspec.rb +1 -0
  44. data/lib/crowdblog/version.rb +1 -1
  45. data/lib/crowdblog.rb +10 -0
  46. data/spec/dummy/app/controllers/application_controller.rb +0 -16
  47. data/spec/dummy/app/views/home/show.html.slim +1 -1
  48. data/spec/dummy/config/application.rb +0 -10
  49. data/spec/dummy/config/initializers/devise.rb +0 -7
  50. data/spec/dummy/config/routes.rb +1 -8
  51. data/spec/dummy/db/schema.rb +11 -11
  52. data/spec/dummy/db/seed.rb +6 -0
  53. data/spec/integration/crowdblog_spec.rb +5 -0
  54. data/spec/models/post_spec.rb +3 -3
  55. data/spec/models/user_spec.rb +25 -1
  56. data/spec/spec_helper.rb +17 -1
  57. data/vendor/assets/javascripts/backbone_rails_sync.js +69 -0
  58. data/vendor/assets/javascripts/uploader/jquery.html5uploader.js +148 -0
  59. metadata +40 -183
  60. data/Gemfile.lock +0 -280
  61. data/app/assets/javascripts/crowdblog/posts_main.js.coffee +0 -42
  62. data/app/assets/javascripts/crowdblog/templates/posts/attachment.jst.eco.slim +0 -1
  63. data/app/assets/javascripts/crowdblog/templates/posts/edit.jst.eco.slim +0 -36
  64. data/app/assets/javascripts/crowdblog/templates/posts/index.jst.eco.slim +0 -14
  65. data/app/assets/javascripts/crowdblog/templates/posts/post.jst.eco.slim +0 -14
  66. data/app/assets/javascripts/crowdblog/views/posts/attachment_view.js.coffee +0 -8
  67. data/app/assets/javascripts/crowdblog/views/posts/edit_post_view.js.coffee +0 -46
  68. data/app/assets/javascripts/crowdblog/views/posts/index.js.coffee +0 -28
  69. data/app/assets/javascripts/crowdblog/views/posts/post_view.js.coffee +0 -57
  70. data/app/assets/javascripts/crowdblog/xhr_fix.js.coffee +0 -4
  71. data/app/controllers/crowdblog/controller.rb +0 -10
  72. data/app/views/layouts/crowdblog/crowdblog.html.slim +0 -26
  73. data/db/migrate/20120215232711_create_users.rb +0 -10
  74. data/db/migrate/20120216154516_add_devise_to_users.rb +0 -56
  75. data/db/migrate/20120217213920_create_posts.rb +0 -13
  76. data/db/migrate/20120219014520_add_author_to_posts.rb +0 -6
  77. data/db/migrate/20120219040607_add_state_to_post.rb +0 -7
  78. data/db/migrate/20120219071614_create_assets.rb +0 -10
  79. data/db/migrate/20120219234253_add_alias_to_users.rb +0 -6
  80. data/db/migrate/20120229160314_add_review_fields_to_post.rb +0 -6
  81. data/features/posts/listing.feature +0 -32
  82. data/features/posts/manage.feature +0 -36
  83. data/features/posts/publish.feature +0 -17
  84. data/features/step_definitions/global_steps.rb +0 -23
  85. data/features/step_definitions/navigation_steps.rb +0 -45
  86. data/features/step_definitions/posts_steps.rb +0 -138
  87. data/features/step_definitions/review_steps.rb +0 -27
  88. data/features/support/env.rb +0 -76
  89. data/spec/dummy/app/models/user.rb +0 -17
  90. data/spec/fabricators/posts_fabricator.rb +0 -21
  91. data/spec/fabricators/users_fabricator.rb +0 -19
  92. data/vendor/assets/javascripts/swfobject.js +0 -4
  93. data/vendor/assets/swf/uploadify.swf +0 -0
data/.gitignore CHANGED
@@ -10,3 +10,5 @@ spec/dummy/tmp/
10
10
  spec/dummy/.sass-cache
11
11
 
12
12
  .sass-cache
13
+
14
+ Gemfile.lock
data/Gemfile CHANGED
@@ -7,16 +7,6 @@ gemspec
7
7
 
8
8
  # Gems used by the dummy application (needs to be here instead of the gemspec)
9
9
  gem "jquery-rails"
10
- gem 'backbone-rails'
11
- gem 'carrierwave'
12
- gem 'devise'
13
- gem 'gravtastic'
14
- gem 'less-rails-bootstrap'
15
- gem 'redcarpet'
16
- gem 'state_machine'
17
- gem 'slim_assets'
18
- gem 'slim-rails'
19
- gem 'eco'
20
10
 
21
11
  group :assets do
22
12
  gem 'coffee-rails'
data/README.md CHANGED
@@ -1,5 +1,4 @@
1
- CrowdBlog
2
- =======
1
+ # CrowdBlog
3
2
 
4
3
  CI:
5
4
  [![Build Status](https://secure.travis-ci.org/crowdint/crowdblog.png?branch=master)](http://travis-ci.org/crowdint/crowdblog)
@@ -7,4 +6,96 @@ CI:
7
6
  Code Climate:
8
7
  [![Code Climate](https://codeclimate.com/badge.png)](https://codeclimate.com/github/crowdint/crowdblog)
9
8
 
10
- **This project rocks!**
9
+ Generic Blog engine, currently in use by [blog.crowdint.com](blog.crowdint.com)
10
+ and [crowdint.com/careers](crowdint.com/careers), among others.
11
+
12
+ ## Installation
13
+
14
+ Gemfile
15
+
16
+ gem 'crowdblog'
17
+
18
+ Bundle
19
+
20
+ bundle install
21
+
22
+ Copy migrations
23
+
24
+ rake crowdblog:install:migrations
25
+
26
+ Run them
27
+
28
+ rake db:migrate
29
+
30
+ Mount
31
+
32
+ #
33
+ # routes.rb
34
+ #
35
+
36
+ mount Crowdblog::Engine => '/blog_admin'
37
+
38
+ Enjoy.
39
+
40
+ Your Rails App should implement the "client facing" pages. Read posts from the
41
+ Crowdblog::Post model.
42
+
43
+ ### Authentication
44
+
45
+ The gem includes a very basic Devise implementation. We use it in combination
46
+ with [this gem](https://github.com/crowdint/crowdint_auth) to authenticate
47
+ via our Google Apps accounts.
48
+
49
+ Take a look [at this code](https://github.com/crowdint/blog.crowdint.com) as an implementation example.
50
+
51
+ ## Testing: Use with caution
52
+
53
+ If you are using it as a 'vanilla' installation, that is, without a lot of
54
+ customizations, you can use some specs that are included with the gem to make
55
+ sure your blog behaves properly.
56
+
57
+ Add this on your spec_helper, right after you require `rspec/rails`:
58
+
59
+ require 'crowdblog/rspec'
60
+ require 'database_cleaner'
61
+
62
+ Your are going to need DatabaseCleaner to use truncation strategies for your
63
+ data. Add these lines to spec_helper.rb:
64
+
65
+ Rspec.configure do |config|
66
+
67
+ config.use_transactional_fixtures = false
68
+
69
+ config.before(:suite) do
70
+ DatabaseCleaner.strategy = :truncation
71
+ DatabaseCleaner.clean_with(:truncation)
72
+ end
73
+
74
+ config.before(:each) do
75
+ DatabaseCleaner.start
76
+ end
77
+
78
+ config.after(:each) do
79
+ DatabaseCleaner.clean
80
+ end
81
+ end
82
+
83
+ Now, create a crowdblog spec:
84
+
85
+ #
86
+ # spec/integration/crowdblog_spec.rb
87
+ #
88
+ require 'spec_helper'
89
+
90
+ describe "Crowdblog" do
91
+ it_behaves_like "a crowdblog"
92
+ end
93
+
94
+ And run your specs. It should test Crowdblog properly.
95
+
96
+ [Crowd Interactive](http://www.crowdint.com) is a leading Ruby and Rails consultancy
97
+ firm based in Mexico currently doing business with startups in the United States.
98
+ We specialize in building and growing your existing development team, by adding
99
+ engineers onsite or offsite. We pick our clients carefully, as we only work with
100
+ companies we believe in. Find out more about us on our [website](http://www.crowdint.com).
101
+
data/Rakefile CHANGED
@@ -26,10 +26,4 @@ load 'rails/tasks/engine.rake'
26
26
  Bundler::GemHelper.install_tasks
27
27
 
28
28
  require 'rspec/core/rake_task'
29
- RSpec::Core::RakeTask.new(:spec)
30
-
31
- # Alias for Cucumber
32
- task :cucumber => 'app:cucumber'
33
-
34
- # RSpec and Cucumber by default
35
- task :default => [:spec, :cucumber]
29
+ RSpec::Core::RakeTask.new(:default)
Binary file
@@ -1,11 +1,6 @@
1
- PostsApp.Post = Backbone.Model.extend
2
- url: ->
3
- if this.id
4
- '/admin/posts/' + this.id
5
- else
6
- '/admin/posts'
1
+ class Crowdblog.Models.Post extends Backbone.Model
2
+ paramRoot: 'post'
7
3
 
8
- PostsApp.PostCollection = Backbone.Collection.extend
9
- model: PostsApp.Post
4
+ url: ->
5
+ 'posts/' + @id
10
6
 
11
- url: '/admin/posts'
@@ -0,0 +1,12 @@
1
+ class Crowdblog.Views.AttachmentView extends Backbone.View
2
+ tagName: 'div'
3
+
4
+ className: 'attachment'
5
+
6
+ template:
7
+ _.template("![image alt](<%= attachment.url %>)")
8
+
9
+ render: ->
10
+ @$el.html @template($.parseJSON(@options))
11
+ @
12
+
@@ -0,0 +1,21 @@
1
+ class Crowdblog.Views.PostFormView extends Backbone.View
2
+ el: 'form'
3
+
4
+ initialize: ->
5
+ @$el.find('#post_body').change(@updatePreview)
6
+ @updatePreview()
7
+ $('#uploader').html5Uploader
8
+ postUrl: 'assets'
9
+ name: 'attachment'
10
+ onSuccess: @onUploadSuccess
11
+
12
+ events:
13
+ 'keyup #post_body' : 'updatePreview'
14
+
15
+ updatePreview: (e) ->
16
+ @$el.find('#post-preview .inner').html(markdown.toHTML($('#post_body').val()))
17
+
18
+ onUploadSuccess: (request, file, object) ->
19
+ attachmentView = new Crowdblog.Views.AttachmentView(object)
20
+ $('#assets').append attachmentView.render().el
21
+
@@ -0,0 +1,52 @@
1
+ class Crowdblog.Views.PostView extends Backbone.View
2
+ events:
3
+ 'click a.publish' : 'publishPost'
4
+ 'click a.review' : 'markForReview'
5
+
6
+ initialize: ->
7
+ @model = new Crowdblog.Models.Post
8
+ ready_for_review: (@$el.attr('data-ready-for-review') == 'true')
9
+
10
+ @model.id = @postId()
11
+ @model.bind('change:ready_for_review', @paintReviewButton)
12
+
13
+ publishPost: (e) ->
14
+ e.preventDefault()
15
+ if @postIsPublished()
16
+ @model.save 'transition', 'draft', { success: @paintPostRow }
17
+ else
18
+ @model.save 'transition', 'publish', { success: @paintPostRow }
19
+
20
+ postId: ->
21
+ @$el.attr('data-post-id')
22
+
23
+ paintPostRow: =>
24
+ if @model.get('transition') == 'publish'
25
+ @$el.find('a.publish').removeClass('btn-danger')
26
+ @$el.find('a.publish').addClass('btn-success')
27
+ @$el.attr('data-state', 'published')
28
+ else
29
+ @$el.find('a.publish').removeClass('btn-success')
30
+ @$el.find('a.publish').addClass('btn-danger')
31
+ @$el.attr('data-state', 'drafted')
32
+
33
+ @$el.find('td.published-at').html(@model.get('published_at'))
34
+
35
+ postIsPublished: ->
36
+ @$el.attr('data-state') == 'published'
37
+
38
+ markForReview: (e) ->
39
+ e.preventDefault()
40
+ ready_for_review = @model.get('ready_for_review')
41
+ if ready_for_review
42
+ ready_for_review = false
43
+ else
44
+ ready_for_review = true
45
+
46
+ @model.save 'ready_for_review', ready_for_review
47
+
48
+ paintReviewButton: (post) =>
49
+ if post.get('ready_for_review')
50
+ @$el.find('a.review').addClass('btn-warning')
51
+ else
52
+ @$el.find('a.review').removeClass('btn-warning')
@@ -1,17 +1,13 @@
1
1
  /*
2
- *= require 'jquery'
3
2
  *= require 'jquery_ujs'
4
- *= require 'underscore'
5
- *= require 'backbone'
6
- *= require 'swfobject'
7
- *= require 'jquery.uploadify'
3
+ *= require 'backbone_rails_sync'
8
4
  *= require 'markdown'
5
+ *= require 'uploader/jquery.html5uploader.js'
9
6
  *= require_self
10
- *= require_tree ./crowdblog/models
11
- *= require_tree ./crowdblog/views
12
- *= require_tree ./crowdblog/templates
13
- *= require ./crowdblog/posts_main
14
- *= require ./crowdblog/xhr_fix
7
+ *= require_tree ./crowdblog
15
8
  */
16
9
 
17
- window.PostsApp = {};
10
+ window.Crowdblog = {};
11
+ window.Crowdblog.Models = {};
12
+ window.Crowdblog.Views = {};
13
+
@@ -1,13 +1,34 @@
1
1
  /* Edit post */
2
- #post_preview {
3
- position: relative;
4
- top: 110px;
5
- height: 550px;
2
+ #post-preview {
3
+ height: 420px;
6
4
  overflow-y: scroll;
7
- padding: 0 25px 0 10px;
8
5
  background: #EBEBEB;
6
+
7
+ .inner {
8
+ padding: 5px;
9
+ }
9
10
  }
10
11
 
11
12
  form .clear {
12
13
  clear: both;
13
14
  }
15
+
16
+ .new-link {
17
+ padding: 5px 0 5px 0;
18
+ }
19
+
20
+ #uploader {
21
+ border: 3px #ebebeb dashed;
22
+
23
+ .inner {
24
+ padding: 20px;
25
+ }
26
+ }
27
+
28
+ #uploader:hover {
29
+ background-color: #ebebeb;
30
+ }
31
+
32
+ .form-box {
33
+ margin-top: 15px;
34
+ }
@@ -1,6 +1,5 @@
1
1
  /*
2
2
  *
3
- *= require twitter/bootstrap
4
3
  *= require_self
5
4
  *= require_tree ./crowdblog
6
5
  *
@@ -0,0 +1,13 @@
1
+ module Crowdblog
2
+ class ApplicationController < ActionController::Base
3
+ before_filter :authenticate_user!
4
+
5
+ def authentication_filter
6
+ authenticate_user!
7
+ end
8
+
9
+ def after_sign_out_path_for(resource_or_scope)
10
+ crowdblog.new_user_session_path
11
+ end
12
+ end
13
+ end
@@ -1,5 +1,5 @@
1
1
  module Crowdblog
2
- class AssetsController < Controller
2
+ class AssetsController < Crowdblog::ApplicationController
3
3
  # TODO: Skipping filters is the worst solution ever to this problem
4
4
  # Someone should fix the uploadify.js thing
5
5
  skip_before_filter :verify_authenticity_token, :only => :create
@@ -8,7 +8,7 @@ module Crowdblog
8
8
  def create
9
9
  @post = Post.find(params[:post_id])
10
10
  asset = @post.assets.build
11
- asset.attachment = params['Filedata']
11
+ asset.attachment = params['attachment']
12
12
  asset.save!
13
13
 
14
14
  render json: asset
@@ -1,8 +1,8 @@
1
1
  module Crowdblog
2
- class AuthorsController < Controller
2
+ class AuthorsController < Crowdblog::ApplicationController
3
3
 
4
4
  def index
5
- @authors = User.includes(:authored_posts).sort {|a,b| b.authored_posts.count <=> a.authored_posts.count}
5
+ @authors = User.includes(:published_posts).sort {|a,b| b.published_posts.size <=> a.published_posts.size}
6
6
  end
7
7
 
8
8
  end
@@ -0,0 +1,3 @@
1
+ class Crowdblog::Devise::SessionsController < Devise::SessionsController
2
+ layout 'crowdblog/application'
3
+ end
@@ -1,28 +1,36 @@
1
- module Crowdblog
2
- class PostsController < Controller
1
+ module Crowdblog
2
+ class PostsController < Crowdblog::ApplicationController
3
+ before_filter :authenticate_user!
4
+
3
5
  respond_to :html, :json
4
6
  cache_sweeper :post_sweeper
5
7
 
8
+ before_filter :load_post, :only => [ :edit, :update, :destroy ]
9
+
10
+ def new
11
+ @post = Post.new
12
+ @post.author = current_user
13
+ @post.save!
14
+ redirect_to edit_post_path(@post)
15
+ end
16
+
6
17
  def index
7
- @posts = Post.scoped_for(current_user).all_posts_json
8
- respond_to do |format|
9
- format.json { render json: @posts }
10
- format.html
11
- end
18
+ @posts = Post.scoped_for(current_user).for_admin_index
19
+ respond_with @posts
12
20
  end
13
21
 
14
22
  def create
15
- @post = Post.new(params[:post])
23
+ @post = Post.new(post_params)
16
24
  @post.author = current_user
17
25
  @post.regenerate_permalink
18
- @post.save
19
- respond_with @post
26
+ if @post.save
27
+ respond_with @post, :location => crowdblog.posts_path
28
+ end
20
29
  end
21
30
 
22
31
  def destroy
23
- @post = Post.scoped_for(current_user).find(params[:id])
24
32
  @post.destroy
25
- respond_with @post
33
+ respond_with @post, :location => crowdblog.posts_path
26
34
  end
27
35
 
28
36
  def show
@@ -32,17 +40,30 @@ module Crowdblog
32
40
  end
33
41
  end
34
42
 
43
+ def edit
44
+ end
45
+
35
46
  def update
36
- @post = Post.scoped_for(current_user).find(params[:id])
37
- @post.update_attributes(params[:post], updated_by: current_user)
47
+ @post.update_attributes(post_params, updated_by: current_user)
38
48
  if @post.allowed_to_update_permalink?
39
49
  @post.regenerate_permalink
40
50
  @post.save!
41
51
  end
42
52
 
43
- @post.publish_if_allowed(params[:transition], current_user) if params[:transition]
53
+ @post.publish_if_allowed(post_params[:transition], current_user) if post_params[:transition]
54
+
55
+ respond_with @post do |format|
56
+ format.html { redirect_to crowdblog.posts_path }
57
+ end
58
+ end
59
+
60
+ private
61
+ def load_post
62
+ @post = Post.scoped_for(current_user).find(params[:id])
63
+ end
44
64
 
45
- respond_with @post
65
+ def post_params
66
+ params.require(:post).permit(:title, :body, :updated_by, :ready_for_review, :transition)
46
67
  end
47
68
  end
48
69
  end
@@ -1,6 +1,5 @@
1
1
  module Crowdblog
2
2
  class Asset < ActiveRecord::Base
3
- self.table_name = :assets
4
3
  belongs_to :post
5
4
 
6
5
  mount_uploader :attachment, AttachmentUploader
@@ -1,6 +1,5 @@
1
1
  module Crowdblog
2
2
  class Post < ActiveRecord::Base
3
- self.table_name = :posts
4
3
  versioned
5
4
 
6
5
  belongs_to :author, class_name: 'User'
@@ -13,9 +12,8 @@ module Crowdblog
13
12
 
14
13
  delegate :year, to: :published_at
15
14
 
16
- validates :title, length: { minimum: 5, maximum: 90 }
17
-
18
- attr_accessible :title, :body, :updated_by, :ready_for_review
15
+ attr_accessor :transition
16
+ attr_accessible :title, :body, :updated_by, :ready_for_review, :transition
19
17
 
20
18
  LEGACY_TITLE_REGEXP = /(\d+-\d+-\d+)-(.*)/
21
19
 
@@ -28,6 +26,10 @@ module Crowdblog
28
26
  post.published_at ||= Time.now
29
27
  end
30
28
 
29
+ before_transition on: :draft do |post, transition|
30
+ post.published_at = nil
31
+ end
32
+
31
33
  event :draft do
32
34
  transition published: :drafted
33
35
  end
@@ -66,7 +68,15 @@ module Crowdblog
66
68
  end
67
69
 
68
70
  def scoped_for(user)
69
- user.is_publisher? ? Post : user.authored_posts
71
+ user.is_publisher? ? scoped : user.authored_posts
72
+ end
73
+
74
+ def for_admin_index
75
+ ordered_by_state.order_by_publish_date
76
+ end
77
+
78
+ def ordered_by_state
79
+ order(:state)
70
80
  end
71
81
  end
72
82
 
@@ -1,13 +1,17 @@
1
1
  module Crowdblog
2
2
  class User < ActiveRecord::Base
3
- self.table_name = :users
4
3
  include Gravtastic
5
4
 
6
5
  has_many :authored_posts, inverse_of: :author, foreign_key: 'author_id', class_name: 'Post'
6
+ has_many :published_posts, inverse_of: :author, foreign_key: 'author_id', class_name: 'Post', conditions: ['state = ?', 'published'], order: 'published_at DESC'
7
7
  has_one :last_post, class_name: 'Post', foreign_key: :author_id, conditions: ['state = ?', 'published'], order: 'published_at DESC, created_at DESC, id DESC'
8
8
 
9
9
  gravtastic :gravatar_email
10
+ devise :database_authenticatable, :token_authenticatable, :trackable
10
11
 
12
+ validate :email, uniqueness: true
13
+
14
+ attr_accessible :email, :password, :password_confirmation, :remember_me, :name, :is_publisher
11
15
 
12
16
  # INSTANCE METHODS
13
17
  def gravatar_email
@@ -18,6 +22,10 @@ module Crowdblog
18
22
  last_post.try(:published_at)
19
23
  end
20
24
 
25
+ def last_published_at
26
+ published_posts.first ? published_posts.first.published_at : nil
27
+ end
28
+
21
29
  def publisher!
22
30
  update_attribute(:is_publisher, true)
23
31
  end
@@ -0,0 +1,11 @@
1
+ .navbar
2
+ .navbar-inner
3
+ = link_to image_tag('crowdblog/logo.png', :width => 227, :height => 74), root_path, :class => 'brand'
4
+ - if current_user
5
+ ul.nav
6
+ li.brand= current_user.email
7
+ li= link_to 'Posts', posts_path
8
+ li= link_to 'Authors', authors_path
9
+ li= link_to 'Sign out', destroy_user_session_path
10
+
11
+
@@ -0,0 +1,6 @@
1
+ - if flash[:notice]
2
+ .alert.alert-success
3
+ = flash[:notice]
4
+ - if flash[:alert]
5
+ .alert
6
+ = flash[:alert]
@@ -14,5 +14,5 @@ table.table.table-striped
14
14
  th= image_tag author.gravatar_url
15
15
  td= author.name
16
16
  td= author.email
17
- td= author.authored_posts.count
18
- td= author.last_post_at
17
+ td= author.published_posts.size
18
+ td= author.last_published_at
@@ -0,0 +1,25 @@
1
+ <%- if controller_name != 'sessions' %>
2
+ <%= link_to "Sign in", new_session_path(resource_name) %><br />
3
+ <% end -%>
4
+
5
+ <%- if devise_mapping.registerable? && controller_name != 'registrations' %>
6
+ <%= link_to "Sign up", new_registration_path(resource_name) %><br />
7
+ <% end -%>
8
+
9
+ <%- if devise_mapping.recoverable? && controller_name != 'passwords' %>
10
+ <%= link_to "Forgot your password?", new_password_path(resource_name) %><br />
11
+ <% end -%>
12
+
13
+ <%- if devise_mapping.confirmable? && controller_name != 'confirmations' %>
14
+ <%= link_to "Didn't receive confirmation instructions?", new_confirmation_path(resource_name) %><br />
15
+ <% end -%>
16
+
17
+ <%- if devise_mapping.lockable? && resource_class.unlock_strategy_enabled?(:email) && controller_name != 'unlocks' %>
18
+ <%= link_to "Didn't receive unlock instructions?", new_unlock_path(resource_name) %><br />
19
+ <% end -%>
20
+
21
+ <%- if devise_mapping.omniauthable? %>
22
+ <%- resource_class.omniauth_providers.each do |provider| %>
23
+ <%= link_to "Sign in with #{provider.to_s.titleize}", omniauth_authorize_path(resource_name, provider) %><br />
24
+ <% end -%>
25
+ <% end -%>
@@ -0,0 +1,21 @@
1
+ <h2>Sign in</h2>
2
+
3
+ <div class="row">
4
+ <div class="span4">
5
+ <%= form_for(resource, :as => resource_name, :url => crowdblog.user_session_path) do |f| %>
6
+ <%= f.label :email %>
7
+ <%= f.email_field :email, :class => "span4" %>
8
+
9
+ <%= f.label :password %>
10
+ <%= f.password_field :password, :class => "span4" %>
11
+
12
+ <% if devise_mapping.rememberable? -%>
13
+ <%= f.check_box :remember_me %> <%= f.label :remember_me %>
14
+ <% end -%>
15
+
16
+ <div class="form-actions"><%= f.submit "Sign in", :class => "btn btn-primary" %></div>
17
+ <% end %>
18
+ </div>
19
+ </div>
20
+
21
+ <%= render "crowdblog/devise/links" %>
@@ -0,0 +1,31 @@
1
+ .row
2
+ .span12
3
+ .control-group.title
4
+ = f.label :title, :class => 'control-label'
5
+ .controls
6
+ = f.text_field :title, :class => "input-xlarge span5"
7
+ span.help-inline.title
8
+
9
+ .row
10
+ .control-group.body
11
+ .span12
12
+ = label_tag 'post_body', 'Body', class: 'control-label'
13
+ .controls.span5
14
+ = f.text_area :body, :class => "span5", :rows => 20
15
+ span.help-inline= link_to 'Markdown syntax', 'http://daringfireball.net/projects/markdown/syntax', target: '_BLANK'
16
+
17
+ #post-preview.span7
18
+ .inner
19
+
20
+ .row.form-box
21
+ .span5
22
+ #uploader
23
+ .inner Drop images...
24
+
25
+ .span7#assets
26
+ - f.object.assets.each do |asset|
27
+ .asset= "![image alt](#{asset.attachment_url})"
28
+
29
+ coffee:
30
+ $ ->
31
+ new Crowdblog.Views.PostFormView
@@ -0,0 +1,13 @@
1
+ = content_tag_for :tr, post, :"data-post-id" => post.id, :"data-state" => post.state, :"data-ready-for-review" => post.ready_for_review do
2
+ td= post.title
3
+ td= post.author_email
4
+ td.span2.published-at = post.published_at.try(:to_s, :crowdblog_short)
5
+ td.span1
6
+ - if current_user.is_publisher?
7
+ = link_to 'Publish', '#', :class => "btn btn-small publish #{(post.published? ? 'btn-success' : 'btn-danger')}"
8
+ td.span1
9
+ = link_to 'Review', '#', :class => "btn btn-small review #{(post.ready_for_review ? 'btn-warning' : '')}"
10
+ td.span1
11
+ = link_to 'Delete', crowdblog.post_path(post), :method => :delete, :confirm => 'Are you sure?', :class => "btn btn-small"
12
+ td.span1
13
+ = link_to 'Edit', crowdblog.edit_post_path(post), :class => "btn btn-small"