activeadmin-blog 0.4.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +20 -0
- data/Gemfile +4 -0
- data/Gemfile.lock +215 -0
- data/README.md +162 -0
- data/Rakefile +7 -0
- data/activeadmin-blog.gemspec +30 -0
- data/app/controllers/activeadmin_blog/posts_controller.rb +50 -0
- data/app/models/activeadmin_blog/blog_category.rb +23 -0
- data/app/models/activeadmin_blog/blog_post.rb +81 -0
- data/app/views/activeadmin_blog/posts/_footer.html.erb +10 -0
- data/app/views/activeadmin_blog/posts/_header.html.erb +11 -0
- data/app/views/activeadmin_blog/posts/_post.html.erb +31 -0
- data/app/views/activeadmin_blog/posts/archive.html.erb +9 -0
- data/app/views/activeadmin_blog/posts/category.html.erb +9 -0
- data/app/views/activeadmin_blog/posts/feed.rss.builder +18 -0
- data/app/views/activeadmin_blog/posts/index.html.erb +9 -0
- data/app/views/activeadmin_blog/posts/search.html.erb +9 -0
- data/app/views/activeadmin_blog/posts/show.html.erb +35 -0
- data/app/views/activeadmin_blog/posts/tag.html.erb +9 -0
- data/app/views/admin/categories/_form.html.erb +26 -0
- data/app/views/admin/posts/_categories.html.erb +18 -0
- data/config/routes.rb +9 -0
- data/install.sh +160 -0
- data/lib/activeadmin-blog.rb +8 -0
- data/lib/activeadmin-blog/engine.rb +5 -0
- data/lib/activeadmin-blog/version.rb +3 -0
- data/lib/generators/activeadmin_blog/install_generator.rb +40 -0
- data/lib/generators/activeadmin_blog/templates/README +5 -0
- data/lib/generators/activeadmin_blog/templates/admin/blog_categories.rb +86 -0
- data/lib/generators/activeadmin_blog/templates/admin/blog_posts.rb +101 -0
- data/lib/generators/activeadmin_blog/views_generator.rb +16 -0
- data/vendor/assets/javascripts/activeadmin_blog.js.coffee +56 -0
- data/vendor/assets/stylesheets/activeadmin_blog.css.scss +51 -0
- metadata +180 -0
@@ -0,0 +1,23 @@
|
|
1
|
+
class ActiveadminBlog::BlogCategory
|
2
|
+
include Mongoid::Document
|
3
|
+
include Mongoid::Timestamps
|
4
|
+
include Mongoid::Slug
|
5
|
+
include Mongoid::Reorder
|
6
|
+
|
7
|
+
# Fields
|
8
|
+
field :name
|
9
|
+
field :_position, :type => Float, :default => 0.0
|
10
|
+
|
11
|
+
# Validations
|
12
|
+
validates_presence_of :name
|
13
|
+
validates_uniqueness_of :name
|
14
|
+
|
15
|
+
# Features
|
16
|
+
slug :name, :as => :permalink, :permanent => true
|
17
|
+
|
18
|
+
# Relations
|
19
|
+
has_and_belongs_to_many :blog_posts, :class_name => "ActiveadminBlog::BlogPost"
|
20
|
+
|
21
|
+
# Scope
|
22
|
+
default_scope order_by(:_position => :desc)
|
23
|
+
end
|
@@ -0,0 +1,81 @@
|
|
1
|
+
class ActiveadminBlog::BlogPost
|
2
|
+
include Mongoid::Document
|
3
|
+
include Mongoid::Timestamps
|
4
|
+
include Mongoid::Slug
|
5
|
+
include Mongoid::Search
|
6
|
+
|
7
|
+
include ActionView::Helpers::TextHelper
|
8
|
+
|
9
|
+
# Fields
|
10
|
+
field :title
|
11
|
+
field :content
|
12
|
+
field :tags, :default => ""
|
13
|
+
field :published, :type => Boolean, :default => false
|
14
|
+
field :date, :type => Date
|
15
|
+
|
16
|
+
# Validations
|
17
|
+
validates_presence_of :title
|
18
|
+
validates_uniqueness_of :title
|
19
|
+
|
20
|
+
# Features
|
21
|
+
slug :title, :as => :permalink, :permanent => true
|
22
|
+
search_in :title, :content, :tags
|
23
|
+
mount_uploader :featured_image, ActiveadminSettings::RedactorPictureUploader
|
24
|
+
paginates_per 6
|
25
|
+
|
26
|
+
# Relations
|
27
|
+
has_and_belongs_to_many :categories, :class_name => "ActiveadminBlog::BlogCategory"
|
28
|
+
|
29
|
+
# Scopes
|
30
|
+
default_scope order_by(:date => :desc)
|
31
|
+
scope :ideas, where(published: false)
|
32
|
+
scope :published, where(published: true)
|
33
|
+
|
34
|
+
# Helpers
|
35
|
+
def has_featured_image?
|
36
|
+
not featured_image.to_s.empty?
|
37
|
+
end
|
38
|
+
|
39
|
+
def excerpt
|
40
|
+
html = Nokogiri::HTML(content)
|
41
|
+
begin
|
42
|
+
html.css('p').select{|p| not p.content.empty? }.first.content
|
43
|
+
rescue
|
44
|
+
""
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
def page_description
|
49
|
+
Nokogiri::HTML(excerpt).text
|
50
|
+
end
|
51
|
+
|
52
|
+
# Class methods
|
53
|
+
def self.published_in_category(category_slug)
|
54
|
+
category = ActiveadminBlog::BlogCategory.find_by_permalink!(category_slug)
|
55
|
+
category.blog_posts.published
|
56
|
+
end
|
57
|
+
|
58
|
+
def self.published_in_month(month, year)
|
59
|
+
begin
|
60
|
+
start_date = Date.new(year, month, 1)
|
61
|
+
end_date = start_date + 1.month
|
62
|
+
rescue
|
63
|
+
self.published
|
64
|
+
end
|
65
|
+
self.published.where(:date=>{'$gte' => start_date,'$lt' => end_date})
|
66
|
+
end
|
67
|
+
|
68
|
+
def self.blog_search(query)
|
69
|
+
self.search(query).published
|
70
|
+
end
|
71
|
+
|
72
|
+
def self.archive
|
73
|
+
self.all.collect do |p|
|
74
|
+
[p.date.month, p.date.year]
|
75
|
+
end.uniq
|
76
|
+
end
|
77
|
+
|
78
|
+
def self.tagged_with(tag)
|
79
|
+
self.published
|
80
|
+
end
|
81
|
+
end
|
@@ -0,0 +1,10 @@
|
|
1
|
+
<footer>
|
2
|
+
<form class="well form-search" action="<%= blog_search_path %>" method="GET">
|
3
|
+
<input name="q" type="text" class="input-medium search-query">
|
4
|
+
<button type="submit" class="btn">Search</button>
|
5
|
+
</form>
|
6
|
+
<p>
|
7
|
+
<a href="<%= blog_rss_feed_path %>.rss" title="RSS Feed">RSS Feed</a></br>
|
8
|
+
Dlivered by <%= settings_link_value "Delivered By", :target => "_blank" %>
|
9
|
+
</p>
|
10
|
+
</footer>
|
@@ -0,0 +1,11 @@
|
|
1
|
+
<header style="margin-bottom:2em;">
|
2
|
+
<h1><%= settings_value "Blog Title" %></h1>
|
3
|
+
<p>
|
4
|
+
<ul>
|
5
|
+
<li><a href="<%= blog_path %>" title="All Posts">All Posts</a></li>
|
6
|
+
<% @categories.all.each do |c| %>
|
7
|
+
<li><a href="<%= blog_category_path(c) %>" title="<%= c.name %>"><%= c.name %></a></li>
|
8
|
+
<% end %>
|
9
|
+
</ul>
|
10
|
+
</p>
|
11
|
+
</header>
|
@@ -0,0 +1,31 @@
|
|
1
|
+
<div style="margin-bottom:2em;">
|
2
|
+
<!-- TITLE -->
|
3
|
+
<a href="<%= blog_post_path(post) %>" title="Read this post"><h2><%= post.title %></h2></a>
|
4
|
+
|
5
|
+
<!-- DATE & CATEGORIES -->
|
6
|
+
<p>
|
7
|
+
<span>Published at <em><%= post.date %></em> <% if post.categories.size > 0 %>in:<% end %></span>
|
8
|
+
<% if post.categories.size > 0 %>
|
9
|
+
<ul>
|
10
|
+
<% post.categories.each do |c| %>
|
11
|
+
<li><a href="<%= blog_category_path(c) %>" title="<%= c.name %>"><%= c.name %></a></li>
|
12
|
+
<% end %>
|
13
|
+
</ul>
|
14
|
+
<% end %>
|
15
|
+
</p>
|
16
|
+
|
17
|
+
<!-- FEATURED IMAGE LINK -->
|
18
|
+
<% if post.has_featured_image? %>
|
19
|
+
<p>
|
20
|
+
<a href="<%= blog_post_path(post) %>" title="Read More">
|
21
|
+
<%= image_tag post.featured_image_url, :alt=>post.title %>
|
22
|
+
</a>
|
23
|
+
</p>
|
24
|
+
<% end %>
|
25
|
+
|
26
|
+
<!-- EXCERPT -->
|
27
|
+
<p><%= post.excerpt %></p>
|
28
|
+
|
29
|
+
<!-- READ MORE -->
|
30
|
+
<a href="<%= blog_post_path(post) %>" title="Read More">Read More</a>
|
31
|
+
</div>
|
@@ -0,0 +1,18 @@
|
|
1
|
+
xml.instruct! :xml, :version => "1.0"
|
2
|
+
xml.rss :version => "2.0" do
|
3
|
+
xml.channel do
|
4
|
+
xml.title "Blog title goes here"
|
5
|
+
xml.description "Blog description goes here"
|
6
|
+
xml.link blog_url
|
7
|
+
|
8
|
+
for post in @posts
|
9
|
+
xml.item do
|
10
|
+
xml.title post.title
|
11
|
+
xml.description post.excerpt
|
12
|
+
xml.pubDate post.date.to_s(:rfc822)
|
13
|
+
xml.link blog_post_url(post)
|
14
|
+
xml.guid blog_post_url(post)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
<div class="container">
|
2
|
+
<%= render :partial => "header" %>
|
3
|
+
|
4
|
+
<div style="margin-bottom:2em;">
|
5
|
+
<!-- TITLE -->
|
6
|
+
<h2><%= @post.title %></h2>
|
7
|
+
|
8
|
+
<!-- DATE & CATEGORIES -->
|
9
|
+
<p>
|
10
|
+
<span>Published at <em><%= @post.date %></em> <% if @post.categories.size > 0 %>in:<% end %></span>
|
11
|
+
<% if @post.categories.size > 0 %>
|
12
|
+
<ul>
|
13
|
+
<% @post.categories.each do |c| %>
|
14
|
+
<li><a href="<%= blog_category_path(c) %>" title="<%= c.name %>"><%= c.name %></a></li>
|
15
|
+
<% end %>
|
16
|
+
</ul>
|
17
|
+
<% end %>
|
18
|
+
</p>
|
19
|
+
|
20
|
+
<!-- CONTENT -->
|
21
|
+
<div><%= @post.content.html_safe %></div>
|
22
|
+
|
23
|
+
<!-- TAGS -->
|
24
|
+
<% if @post.tags? %>
|
25
|
+
<span>Tags:</span>
|
26
|
+
<ul>
|
27
|
+
<% @post.tags.split(',').each do |t| %>
|
28
|
+
<li><%= link_to t, blog_tag_path(t) %></li>
|
29
|
+
<% end %>
|
30
|
+
</ul>
|
31
|
+
<% end %>
|
32
|
+
</div>
|
33
|
+
|
34
|
+
<%= render :partial => "footer" %>
|
35
|
+
</div>
|
@@ -0,0 +1,26 @@
|
|
1
|
+
<fieldset class="inputs"><legend><span>Details</span></legend><ol>
|
2
|
+
<%= f.input :name, :required => true %>
|
3
|
+
<%= f.input :permalink %>
|
4
|
+
</ol></fieldset>
|
5
|
+
|
6
|
+
<fieldset class="buttons">
|
7
|
+
<ol>
|
8
|
+
<li class="commit button">
|
9
|
+
<input class="update" id="proposal_submit" name="commit" type="submit"
|
10
|
+
value="<% if f.object.new? %>Create<% else %>Update<% end %> Category">
|
11
|
+
</li>
|
12
|
+
<li class="cancel">
|
13
|
+
<a href="<%= admin_posts_path %>">Cancel</a>
|
14
|
+
</li>
|
15
|
+
<!--
|
16
|
+
<% if not f.object.new? %>
|
17
|
+
<li style="float:right;">
|
18
|
+
<%= link_to "Delete Category", resource_path(f.object),
|
19
|
+
:method => :delete,
|
20
|
+
:confirm => "Are you sure, you want to delte this category?",
|
21
|
+
:class => "delete button" %>
|
22
|
+
</li>
|
23
|
+
<% end %>
|
24
|
+
-->
|
25
|
+
</ol>
|
26
|
+
</fieldset>
|
@@ -0,0 +1,18 @@
|
|
1
|
+
<% if categories.size > 0 %>
|
2
|
+
<ul id="blog_categories_list">
|
3
|
+
<% categories.each do |c| %>
|
4
|
+
<li id="category_<%= c.id %>">
|
5
|
+
<span>
|
6
|
+
<%= link_to c.name, admin_category_path(c) %>
|
7
|
+
<% if c.blog_posts.size > 0 %>(<%= c.blog_posts.size %>)<% end %>
|
8
|
+
</span>
|
9
|
+
<span class="action-buttons">
|
10
|
+
<%= link_to "Edit", edit_admin_category_path(c) %>
|
11
|
+
</span>
|
12
|
+
</li>
|
13
|
+
<% end %>
|
14
|
+
</ul>
|
15
|
+
<br/>
|
16
|
+
<% end %>
|
17
|
+
|
18
|
+
<%= link_to "New Category", new_admin_category_path %>
|
data/config/routes.rb
ADDED
@@ -0,0 +1,9 @@
|
|
1
|
+
ActiveadminBlog::Engine.routes.draw do
|
2
|
+
get '/' => 'posts#index', :as => :blog
|
3
|
+
get '/search' => 'posts#search', :as => :blog_search
|
4
|
+
get '/feed' => 'posts#feed', :as => :blog_rss_feed
|
5
|
+
get '/archive/:y/:m' => 'posts#archive', :as => :blog_archive
|
6
|
+
get '/tags/:tag' => 'posts#tag', :as => :blog_tag
|
7
|
+
get '/posts/:slug' => 'posts#show', :as => :blog_post
|
8
|
+
get '/:slug' => 'posts#category', :as => :blog_category
|
9
|
+
end
|
data/install.sh
ADDED
@@ -0,0 +1,160 @@
|
|
1
|
+
#!/bin/sh
|
2
|
+
|
3
|
+
|
4
|
+
# === activeadmin-mongoid-blog ===
|
5
|
+
# https://github.com/alexkravets/activeadmin-blog
|
6
|
+
#
|
7
|
+
# Description:
|
8
|
+
# Blog app on the top of activeadmin and mongoid.
|
9
|
+
#
|
10
|
+
# Installation:
|
11
|
+
# export project_name=new_blog ; curl https://raw.github.com/alexkravets/activeadmin-blog/master/install.sh | sh
|
12
|
+
|
13
|
+
|
14
|
+
set -e
|
15
|
+
|
16
|
+
rails new $project_name -T -O --skip-bundle
|
17
|
+
cd $project_name
|
18
|
+
|
19
|
+
|
20
|
+
# Gems
|
21
|
+
echo '
|
22
|
+
# Activeadmin
|
23
|
+
gem "bson_ext"
|
24
|
+
gem "mongoid"
|
25
|
+
gem "devise"
|
26
|
+
gem "activeadmin-mongoid"
|
27
|
+
|
28
|
+
# Blog
|
29
|
+
gem "activeadmin-blog"
|
30
|
+
|
31
|
+
# Bootstrap styles
|
32
|
+
gem "therubyracer"
|
33
|
+
gem "twitter-bootstrap-rails"
|
34
|
+
|
35
|
+
# Assets
|
36
|
+
gem "asset_sync"
|
37
|
+
' >> Gemfile
|
38
|
+
|
39
|
+
|
40
|
+
bundle
|
41
|
+
|
42
|
+
|
43
|
+
rails g mongoid:config
|
44
|
+
rails g devise:install
|
45
|
+
rails g active_admin:install
|
46
|
+
rails g activeadmin_settings:install
|
47
|
+
rails g activeadmin_blog:install blog
|
48
|
+
rails g bootstrap:install
|
49
|
+
|
50
|
+
|
51
|
+
# Add blog settings
|
52
|
+
echo '\nGeneral:
|
53
|
+
Blog Title:
|
54
|
+
description: You can change blog title with this setting
|
55
|
+
default_value: <%= Rails.application.class.parent_name %>
|
56
|
+
|
57
|
+
Delivered By:
|
58
|
+
description: Link in the footer of the website
|
59
|
+
default_value: (Slate Studio) http://slatestudio.com
|
60
|
+
type: link' >> config/activeadmin_settings.yml
|
61
|
+
|
62
|
+
|
63
|
+
# Tweak application.css.scss
|
64
|
+
echo '/*
|
65
|
+
*= require bootstrap_and_overrides
|
66
|
+
*= require_self
|
67
|
+
*/
|
68
|
+
|
69
|
+
.pagination .page.current {
|
70
|
+
float:left;
|
71
|
+
padding:0 14px;
|
72
|
+
line-height:34px;
|
73
|
+
text-decoration:none;
|
74
|
+
border:1px solid #DDD;
|
75
|
+
border-left-width:0;
|
76
|
+
color:#999;
|
77
|
+
cursor:default;
|
78
|
+
background-color:whiteSmoke;
|
79
|
+
}
|
80
|
+
.pagination span:first-child, .pagination .first a { border-left-width:1px; }' > app/assets/stylesheets/application.css
|
81
|
+
|
82
|
+
|
83
|
+
# Tweak application.js
|
84
|
+
echo '//= require jquery
|
85
|
+
//= require jquery_ujs
|
86
|
+
//= require twitter/bootstrap
|
87
|
+
//= require bootstrap
|
88
|
+
' > app/assets/javascripts/application.js
|
89
|
+
|
90
|
+
|
91
|
+
# Fix default mongoid.yml
|
92
|
+
echo 'development:
|
93
|
+
host: localhost
|
94
|
+
database: '$project_name'
|
95
|
+
|
96
|
+
test:
|
97
|
+
host: localhost
|
98
|
+
database: '$project_name'_test
|
99
|
+
|
100
|
+
production:
|
101
|
+
uri: <%= ENV["MONGO_URL"] %>' > config/mongoid.yml
|
102
|
+
|
103
|
+
|
104
|
+
# Remove migrations, we don't need them with mongoid
|
105
|
+
rm -Rfd db/migrate
|
106
|
+
|
107
|
+
|
108
|
+
# Fix seeds.rb file to generate first admin user
|
109
|
+
echo 'puts "EMPTY THE MONGODB DATABASE"
|
110
|
+
Mongoid.master.collections.reject { |c| c.name =~ /^system/}.each(&:drop)
|
111
|
+
|
112
|
+
puts "SETTING UP DEFAULT ADMIN USER"
|
113
|
+
Rake::Task["activeadmin:settings:create_admin"].invoke
|
114
|
+
' > db/seeds.rb
|
115
|
+
|
116
|
+
|
117
|
+
# Create default admin user
|
118
|
+
rake db:seed
|
119
|
+
|
120
|
+
|
121
|
+
# Create carrierwave default configuration
|
122
|
+
echo 'CarrierWave.configure do |config|
|
123
|
+
config.cache_dir = File.join(Rails.root, "tmp", "uploads")
|
124
|
+
config.storage = :fog
|
125
|
+
|
126
|
+
config.fog_credentials = {
|
127
|
+
:provider => "AWS",
|
128
|
+
:aws_access_key_id => ENV["AWS_ACCESS_KEY_ID"],
|
129
|
+
:aws_secret_access_key => ENV["AWS_SECRET_ACCESS_KEY"]
|
130
|
+
}
|
131
|
+
|
132
|
+
case Rails.env.to_sym
|
133
|
+
when :development
|
134
|
+
config.storage = :file
|
135
|
+
when :production
|
136
|
+
config.fog_directory = ENV["FOG_MEDIA_DIRECTORY"]
|
137
|
+
config.fog_host = "//#{ ENV["FOG_MEDIA_DIRECTORY"] }.s3.amazonaws.com"
|
138
|
+
config.fog_attributes = {"Cache-Control"=>"max-age=315576000"} # optional, defaults to {}
|
139
|
+
end
|
140
|
+
end' > config/initializers/carrierwave.rb
|
141
|
+
|
142
|
+
|
143
|
+
# Fix production assets to include all required files
|
144
|
+
mv config/environments/production.rb config/environments/production-old.rb
|
145
|
+
sed '/# config.assets.precompile += %w( search.js )/ a\
|
146
|
+
config.assets.precompile += ["active_admin.js", "active_admin.css", "redactor/css/style.css"]' config/environments/production-old.rb 1> config/environments/production.rb
|
147
|
+
rm config/environments/production-old.rb
|
148
|
+
|
149
|
+
|
150
|
+
echo ""
|
151
|
+
echo "Please make sure you've set Heroku environment settings:"
|
152
|
+
echo " FOG_MEDIA_DIRECTORY"
|
153
|
+
echo " AWS_ACCESS_KEY_ID"
|
154
|
+
echo " AWS_SECRET_ACCESS_KEY"
|
155
|
+
echo " MONGO_URL"
|
156
|
+
echo ""
|
157
|
+
|
158
|
+
|
159
|
+
|
160
|
+
|