monologue 0.1.3 → 0.2.0.beta3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (76) hide show
  1. data/README.md +29 -21
  2. data/app/assets/javascripts/monologue/blog/twitter.js.coffee +32 -0
  3. data/app/assets/stylesheets/monologue/blog/application.css +3 -3
  4. data/app/assets/stylesheets/monologue/blog/monologue.css +150 -7
  5. data/app/controllers/monologue/admin/cache_controller.rb +27 -0
  6. data/app/controllers/monologue/admin/posts_controller.rb +28 -12
  7. data/app/controllers/monologue/admin/sessions_controller.rb +2 -2
  8. data/app/controllers/monologue/admin/users_controller.rb +13 -0
  9. data/app/controllers/monologue/application_controller.rb +22 -6
  10. data/app/controllers/monologue/posts_controller.rb +7 -7
  11. data/app/controllers/monologue/tags_controller.rb +12 -0
  12. data/app/helpers/monologue/application_helper.rb +76 -0
  13. data/app/helpers/monologue/tags_helper.rb +5 -0
  14. data/app/models/monologue/post.rb +43 -29
  15. data/app/models/monologue/posts_revision.rb +50 -52
  16. data/app/models/monologue/tag.rb +16 -0
  17. data/app/models/monologue/tagging.rb +4 -0
  18. data/app/models/monologue/user.rb +1 -0
  19. data/app/sweepers/monologue/posts_sweeper.rb +20 -4
  20. data/app/sweepers/monologue/total_sweeper.rb +5 -0
  21. data/app/views/layouts/monologue/admin/_nav_bar.html.erb +17 -6
  22. data/app/views/layouts/monologue/application.html.erb +15 -20
  23. data/app/views/layouts/monologue/application/_disqus.html.erb +18 -0
  24. data/app/views/layouts/monologue/application/_disqus_embed.html.erb +17 -0
  25. data/app/views/layouts/monologue/application/_fb_open_graph.html.erb +4 -1
  26. data/app/views/layouts/monologue/application/_gauge_analytics.html.erb +15 -0
  27. data/app/views/layouts/monologue/application/_google_analytics.html.erb +1 -1
  28. data/app/views/layouts/monologue/application/_head.html.erb +3 -2
  29. data/app/views/layouts/monologue/application/_sidebar.html.erb +5 -0
  30. data/app/views/layouts/monologue/application/_social_icons.html.erb +5 -0
  31. data/app/views/layouts/monologue/application/_twitter_cards.html.erb +7 -0
  32. data/app/views/monologue/admin/cache/_config.html.erb +18 -0
  33. data/app/views/monologue/admin/cache/how_to_enable.html.erb +6 -0
  34. data/app/views/monologue/admin/cache/show.html.erb +26 -0
  35. data/app/views/monologue/admin/posts/_form.html.erb +3 -2
  36. data/app/views/monologue/admin/posts/edit.html.erb +1 -1
  37. data/app/views/monologue/admin/posts/index.html.erb +1 -1
  38. data/app/views/monologue/admin/users/edit.html.erb +9 -0
  39. data/app/views/monologue/posts/_post.html.erb +14 -0
  40. data/app/views/monologue/posts/_revision_header.html.erb +9 -0
  41. data/app/views/monologue/posts/_social_sharing.html.erb +45 -36
  42. data/app/views/monologue/posts/index.html.erb +4 -17
  43. data/app/views/monologue/posts/show.html.erb +11 -24
  44. data/app/views/monologue/sidebar/_categories.html.erb +7 -0
  45. data/app/views/monologue/sidebar/_latest_posts.html.erb +7 -0
  46. data/app/views/monologue/sidebar/_latest_tweets.html.erb +8 -0
  47. data/app/views/monologue/sidebar/_tag_cloud.html.erb +5 -0
  48. data/app/views/monologue/tags/_tag.html.erb +1 -0
  49. data/app/views/monologue/tags/show.html.erb +4 -0
  50. data/config/locales/en.yml +54 -10
  51. data/config/locales/fr.yml +55 -11
  52. data/config/routes.rb +8 -2
  53. data/db/migrate/20120514164158_create_monologue_tags.rb +8 -0
  54. data/db/migrate/20120514194459_join_posts_and_tags.rb +7 -0
  55. data/db/migrate/20120604010152_rename_post_tags_table.rb +5 -0
  56. data/db/migrate/20120612013442_create_taggings.rb +11 -0
  57. data/db/migrate/20120612015727_delete_join_posts_tags.rb +11 -0
  58. data/db/migrate/20120612020023_add_index_to_tag_name.rb +5 -0
  59. data/deprecations.rb +10 -0
  60. data/lib/monologue.rb +20 -1
  61. data/lib/monologue/engine.rb +12 -1
  62. data/lib/monologue/version.rb +1 -1
  63. data/lib/tasks/monologue_cache.rake +26 -0
  64. data/vendor/assets/fonts/monologue/foundation_icons/social_foundicons.eot +0 -0
  65. data/vendor/assets/fonts/monologue/foundation_icons/social_foundicons.svg +15 -0
  66. data/vendor/assets/fonts/monologue/foundation_icons/social_foundicons.ttf +0 -0
  67. data/vendor/assets/fonts/monologue/foundation_icons/social_foundicons.woff +0 -0
  68. data/vendor/assets/javascripts/monologue/bootstrap/bootstrap.min.js +6 -1
  69. data/vendor/assets/stylesheets/monologue/bootstrap/bootstrap-responsive.min.css +9 -3
  70. data/vendor/assets/stylesheets/monologue/bootstrap/bootstrap.min.css +9 -610
  71. data/vendor/assets/stylesheets/monologue/foundation_icons/social_foundicons.css.erb +148 -0
  72. metadata +109 -10
  73. data/app/helpers/monologue/admin/admin_helper.rb +0 -4
  74. data/app/helpers/monologue/posts_helper.rb +0 -4
  75. data/app/helpers/monologue/sessions_helper.rb +0 -6
  76. data/lib/tasks/monologue_tasks.rake +0 -4
data/README.md CHANGED
@@ -4,20 +4,30 @@ Monologue is a basic mountable blogging engine in Rails built to be easily mount
4
4
  [![Build Status](https://secure.travis-ci.org/jipiboily/monologue.png)](http://travis-ci.org/jipiboily/monologue)
5
5
 
6
6
 
7
- ## Features
8
- - Rails mountable engine (fully named spaced)
7
+ ## Questions? Problems? Documentation?
8
+
9
+ [Questions here please](http://groups.google.com/forum/#!forum/monologue-rb)
10
+ [Issues and bugs](http://github.com/jipiboily/monologue/issues)
11
+ [Wiki](https://github.com/jipiboily/monologue/wiki/_pages)
12
+
13
+ ## Here are a few features
14
+ - Rails mountable engine (fully named spaced and mountable in an already existing app)
9
15
  - tested
10
16
  - back to basics: few features
11
17
  - it has post revisions (no UI to choose published revision yet, but it keeps your modification history)
18
+ - tags (or categories)
19
+ - RSS
20
+ - support for Google Analytics and Gaug.es tags
12
21
  - few external dependencies (no Devise or Sorcery, etc…) so we don't face problem integrating with existing Rails app.([Rails mountable engines: dependency nightmare?](http://jipiboily.com/2012/rails-mountable-engines-dependency-nightmare))
13
- - comments handled by disqus
14
- - enforcing [Rails cache](http://edgeguides.rubyonrails.org/caching_with_rails.html) for better performance (only support file store for now)
15
- - runs on Heroku
22
+ - comments are handled by [disqus](http://disqus.com/)
23
+ - enforcing [Rails cache](http://edgeguides.rubyonrails.org/caching_with_rails.html) for better performance (only support file store for now). [Read this to enable it](https://github.com/jipiboily/monologue/wiki/Configure-Monologue's-cache).
24
+ - more in the [CHANGELOG](https://github.com/jipiboily/monologue/blob/master/CHANGELOG.md)
25
+
26
+ - bonus: there is a `[monologue-markdown](https://github.com/jipiboily/monologue-markdown)` extension
16
27
 
17
28
  ### missing features
18
- - categories
19
29
  - UI for posts revisions and to manage user
20
- - much more…see issues!
30
+ - see [roadmap](https://github.com/jipiboily/monologue/wiki/Roadmap)!
21
31
 
22
32
 
23
33
  ## Installation
@@ -46,36 +56,27 @@ Run these commands:
46
56
  2. $`bundle exec rake db:create` (only if this is a new project)
47
57
  3. $`bundle exec rake db:migrate`
48
58
 
49
-
59
+
50
60
  ### 4. Create a user
51
61
  Open your development console with `rails c`, then:
52
62
  ```ruby
53
63
  Monologue::User.create(name: "monologue", email:"monologue@example.com", password:"my-password", password_confirmation: "my-password")
54
64
  ```
55
65
 
56
- ### 5. Configure Monologue.
66
+ ### 5. Configure Monologue.
57
67
  This is all done in an initializer file, say `config/initializers/monologue.rb`. More on this in the [Wiki - Configuration](https://github.com/jipiboily/monologue/wiki/Configuration).
58
68
 
59
69
  ### 6. Ready
60
70
  Start your server and head on [http://localhost:3000/monologue](http://localhost:3000/monologue) to log in the admin section.
61
71
 
62
- ### Note to Heroku users
72
+ ### Note to Heroku users
63
73
  Additionnal step: turn caching off in `config/environments/production.rb`:
64
74
  ```ruby
65
75
  config.action_controller.perform_caching = false
66
76
  ```
67
77
 
68
78
  ## Enable caching
69
- Just turn perform_caching to true in your environment config file (`config/environment/{environment}.rb):
70
- ```ruby
71
- config.action_controller.perform_caching = true
72
- ```
73
-
74
- **IMPORTANT**: if monologue is mounted at root ("/"), you must also add that in your `routes.rb` file, before the monologue mount:
75
-
76
- ```ruby
77
- root to: 'monologue/posts#index'
78
- ```
79
+ [See full caching doc here.](https://github.com/jipiboily/monologue/wiki/Configure-Monologue's-cache)
79
80
 
80
81
  ## Customization
81
82
  See the [Wiki - Customizations](https://github.com/jipiboily/monologue/wiki/Customizations).
@@ -85,4 +86,11 @@ See the [Wiki - Customizations](https://github.com/jipiboily/monologue/wiki/Cust
85
86
  - Database: MySQL & Postgres are supported but other databases might work too.
86
87
 
87
88
  ## Contribute
88
- Fork it, then pull request. Please add tests for your feature or bug fix.
89
+ Fork it, then pull request. Please add tests for your feature or bug fix.
90
+
91
+ You will need to install this before running the test suite:
92
+ - [https://github.com/thoughtbot/capybara-webkit/wiki/Installing-Qt-and-compiling-capybara-webkit](https://github.com/thoughtbot/capybara-webkit/wiki/Installing-Qt-and-compiling-capybara-webkit)
93
+
94
+ ## Thanks to
95
+
96
+ Zurb for the "social foundicons".
@@ -0,0 +1,32 @@
1
+ class window.TwitterWidget
2
+ @dom_cache: ->
3
+ @template = $("#tweet_template")
4
+ @latest_tweets = $("#latest_tweets")
5
+ @callback: (data) ->
6
+ @dom_cache()
7
+ for tweet in data
8
+ @add_tweet(tweet)
9
+ @add_tweet: (tweet) ->
10
+ tweet.text = tweet.text.parseTwitter()
11
+ @print(tweet)
12
+ @print: (tweet) ->
13
+ el = @template.clone().attr("id","")
14
+ el.html(el.html().replace("{{text}}", tweet.text)).show()
15
+ @latest_tweets.append(el)
16
+
17
+ String::parseUsername = ->
18
+ @replace /[@]+[A-Za-z0-9-_]+/g, (u) ->
19
+ username = u.replace("@", "")
20
+ u.link "http://twitter.com/" + username
21
+
22
+ String::parseHashtag = ->
23
+ @replace /[#]+[A-Za-z0-9-_]+/g, (t) ->
24
+ tag = t.replace("#", "%23")
25
+ t.link "http://search.twitter.com/search?q=" + tag
26
+
27
+ String::parseURL = ->
28
+ @replace /[A-Za-z]+:\/\/[A-Za-z0-9-_]+\.[A-Za-z0-9-_:%&~\?\/.=]+/g, (url) ->
29
+ url.link url
30
+
31
+ String::parseTwitter =->
32
+ @.parseURL().parseHashtag().parseUsername()
@@ -6,8 +6,8 @@
6
6
  *= require monologue/blog/skeleton/base
7
7
  *= require monologue/blog/skeleton/skeleton
8
8
  *= require monologue/blog/skeleton/layout
9
- *= require monologue/blog/custom
9
+ *= require monologue/foundation_icons/social_foundicons
10
+ *= require_tree .
10
11
  *= require monologue/blog/fonts
11
- *= require_tree .
12
- *= require_self
12
+ *= require monologue/blog/custom
13
13
  */
@@ -1,7 +1,41 @@
1
+ /* general */
2
+ a:hover {
3
+ color: #05C5FF;
4
+ }
5
+
6
+ ul {
7
+ list-style: square;
8
+ margin-left: 30px;
9
+ }
10
+
11
+ /* header */
1
12
  .main-header{
2
- margin: 20px 0 30px 0;
13
+ margin: 20px 0 0 0;
14
+ }
15
+
16
+ .main-header .social:first-of-type i {
17
+ float:right;
18
+ padding: 20px 0 0 0;
19
+ font-size: 50px;
20
+ text-decoration: none;
21
+ }
22
+
23
+ .main-header .social {
24
+ float: right;
25
+ margin: 0 2px 0 2px;
26
+ }
27
+
28
+ a.social {
29
+ text-decoration: none;
30
+ }
31
+
32
+ .social i {
33
+ font-size: 30px;
3
34
  }
4
35
 
36
+
37
+ /* pagination */
38
+
5
39
  #pagination {
6
40
  margin: 20px 0 0 0;
7
41
  border-top: 3px solid #000;
@@ -16,7 +50,10 @@
16
50
  float: right;
17
51
  }
18
52
 
19
- .content article h2, .content article h3, .content article h4, .content article h5, .content article h6 {
53
+ /* content */
54
+
55
+ .content article h2, .content article h3, .content article h4, .content article h5, .content article h6,
56
+ .content section h2, .content section h3, .content section h4, .content section h5, .content section h6 {
20
57
  font-size: 16px;
21
58
  text-transform: uppercase;
22
59
  font-weight: bold;
@@ -27,16 +64,122 @@
27
64
  font-weight: bold;
28
65
  }
29
66
 
30
- section header {
67
+ .content header {
68
+ border-bottom: solid black 1px;
69
+ border-top: solid black 1px;
70
+ }
71
+
72
+ .content header h1 {
73
+ margin: 0 0 0 10px;
74
+ }
75
+
76
+ .content header {
31
77
  margin: 0 0 5px 0;
32
78
  font-size: 12px;
79
+ text-align: center;
33
80
  }
34
81
 
35
- section header h1 {
82
+ .content header h1 {
36
83
  margin: 0 0 0 0;
37
84
  }
38
85
 
39
- ul {
40
- list-style: square;
41
- margin-left: 30px;
86
+ .content header .posted {
87
+ font-size: 12;
88
+ text-transform: uppercase;
89
+ font-weight: bold;
90
+ margin-bottom: 10px
91
+ }
92
+
93
+ /* tags */
94
+ #tags {
95
+ margin-top: 20px;
96
+ margin-bottom: 20px;
97
+ }
98
+
99
+ .tag {
100
+ background: #eeeeee;
101
+ -moz-border-radius: 4px;
102
+ -webkit-border-radius: 4px;
103
+ border:1px solid #d4d4d4;
104
+ border-radius:4px;
105
+ padding: 4px;
106
+ margin-right: 2px;
107
+ }
108
+
109
+ .tag-search,
110
+ .flash-notice {
111
+ padding:8px 35px 8px 14px;
112
+ margin-bottom:18px;
113
+ text-shadow:0 1px 0 rgba(255, 255, 255, 0.5);
114
+ background-color:#eeeeee;
115
+ border:1px solid #d4d4d4;
116
+ -webkit-border-radius:4px;
117
+ -moz-border-radius:4px;
118
+ border-radius:4px;
119
+ }
120
+
121
+ .label-size-1 {
122
+ font-size: 80%;
123
+ opacity: .8;
124
+ }
125
+
126
+ .label-size-2 {
127
+ font-size: 90%;
128
+ opacity: .9;
129
+ }
130
+ .label-size-3 {
131
+ font-size: 100%;
132
+ }
133
+ .label-size-4 {
134
+ font-size: 130%;
135
+ }
136
+ .label-size-5 {
137
+ font-size: 160%;
138
+ }
139
+
140
+ /* sidebar */
141
+ .widget header {
142
+ padding: 8px 35px 0 14px;
143
+ margin: 10px 0 10px 0;
144
+ text-shadow:0 1px 0 rgba(255, 255, 255, 0.5);
145
+ background-color:#eeeeee;
146
+ border:1px solid #d4d4d4;
147
+ -webkit-border-radius:4px;
148
+ -moz-border-radius:4px;
149
+ border-radius:4px;
150
+ }
151
+
152
+ .widget header:first-child {
153
+ margin-top: 0;
154
+ }
155
+
156
+ .widget header h1 {
157
+ font-size: 24px;
158
+ line-height: 32px;
159
+ margin-bottom: 4px;
160
+ }
161
+ none
162
+ /* footer */
163
+
164
+ .content article footer h1 {
165
+ margin-bottom: 10px;
166
+ font-size: 16px;
167
+ text-transform: uppercase;
168
+ text-align: center;
169
+ }
170
+
171
+ .monologue-social-sharing {
172
+ padding: 0 0 0 0;
173
+ border-top: solid black 1px;
174
+ }
175
+
176
+ #social-share {
177
+ /*text-align: center;*/
178
+ width: 100%;
179
+ }
180
+
181
+ #facebook, #twitter, #google-plus {
182
+ display: inline;
183
+ /*margin: 0 40px 0 40px;*/
184
+ /*padding: 0 0 0 0;*/
42
185
  }
@@ -0,0 +1,27 @@
1
+ class Monologue::Admin::CacheController < Monologue::Admin::BaseController
2
+ before_filter :prepare_file_list
3
+
4
+ def show
5
+ if ActionController::Base.perform_caching && Monologue::PageCache.enabled && Monologue::PageCache.wipe_enabled && ActionController::Base.page_cache_directory != Rails.public_path
6
+ render :show
7
+ else
8
+ render :how_to_enable
9
+ end
10
+ end
11
+
12
+ def destroy
13
+ Monologue::TotalSweeper.wipe_all
14
+ flash.notice = I18n.t("monologue.admin.cache.show.cache_wiped")
15
+ render :show
16
+ end
17
+
18
+ private
19
+ def prepare_file_list
20
+ @files = []
21
+ Dir.glob("#{ActionController::Base.page_cache_directory}/**/*").each do |file|
22
+ next if File.directory?(file)
23
+ @files << file.gsub(ActionController::Base.page_cache_directory,"")
24
+ end
25
+ @files
26
+ end
27
+ end
@@ -1,26 +1,27 @@
1
1
  class Monologue::Admin::PostsController < Monologue::Admin::BaseController
2
2
  respond_to :html
3
3
  cache_sweeper Monologue::PostsSweeper, :only => [:create, :update, :destroy]
4
-
4
+ before_filter :load_post_and_revisions, :only => [:edit, :update]
5
+
5
6
  def index
6
7
  @posts = Monologue::Post.default
7
8
  end
8
-
9
+
9
10
  def new
10
11
  @post = Monologue::Post.new
11
12
  @revision = @post.posts_revisions.build
12
13
  end
13
-
14
+
14
15
  def create
15
16
  params[:post][:posts_revisions_attributes] = {}
16
17
  params[:post][:posts_revisions_attributes][0] = params[:post][:posts_revision]
17
18
  params[:post].delete("posts_revision")
19
+ tags = params[:post].delete(:tag_list)
18
20
  @post = Monologue::Post.new(params[:post])
19
21
  @revision = @post.posts_revisions.first
20
22
  @revision.user_id = current_user.id
21
-
23
+ save_tags(tags)
22
24
  if @post.save
23
-
24
25
  if @revision.published_at > DateTime.now && @post.published && ActionController::Base.perform_caching
25
26
  flash[:warning] = I18n.t("monologue.admin.posts.create.created_with_future_date_and_cache")
26
27
  else
@@ -28,20 +29,19 @@ class Monologue::Admin::PostsController < Monologue::Admin::BaseController
28
29
  end
29
30
  redirect_to edit_admin_post_path(@post)
30
31
  else
31
- render :action => "new"
32
+ render :new
32
33
  end
33
34
  end
34
-
35
+
35
36
  def edit
36
- @post = Monologue::Post.includes(:posts_revisions).find(params[:id])
37
- @revision = @post.posts_revisions.last
37
+ @revision = @post.active_revision
38
38
  end
39
-
39
+
40
40
  def update
41
- @post = Monologue::Post.includes(:posts_revisions).find(params[:id])
42
41
  @post.published = params[:post][:published]
43
42
  @revision = @post.posts_revisions.build(params[:post][:posts_revision])
44
43
  @revision.user_id = current_user.id
44
+ save_tags(params[:post][:tag_list])
45
45
  if @post.save
46
46
  if @revision.published_at > DateTime.now && @post.published && ActionController::Base.perform_caching
47
47
  flash[:warning] = I18n.t("monologue.admin.posts.update.saved_with_future_date_and_cache")
@@ -53,7 +53,7 @@ class Monologue::Admin::PostsController < Monologue::Admin::BaseController
53
53
  render :edit
54
54
  end
55
55
  end
56
-
56
+
57
57
  def destroy
58
58
  post = Monologue::Post.find(params[:id])
59
59
  if post.destroy
@@ -62,4 +62,20 @@ class Monologue::Admin::PostsController < Monologue::Admin::BaseController
62
62
  redirect_to admin_posts_path, :alert => I18n.t("monologue.admin.posts.delete.failed")
63
63
  end
64
64
  end
65
+
66
+ private
67
+ def save_tags(tags)
68
+ @post.tag!(tags.split(","))
69
+ end
70
+
71
+ def load_post_and_revisions
72
+ @post = Monologue::Post.includes(:posts_revisions).find(params[:id])
73
+ end
74
+
75
+ helper_method :tag_list_for
76
+
77
+ def tag_list_for(tags)
78
+ tags.map { |tag| tag.name }.join(", ") if tags
79
+ end
80
+
65
81
  end
@@ -7,7 +7,7 @@ class Monologue::Admin::SessionsController < Monologue::Admin::BaseController
7
7
  def create
8
8
  user = Monologue::User.find_by_email(params[:email])
9
9
  if user && user.authenticate(params[:password])
10
- session[:user_id] = user.id
10
+ session[:monologue_user_id] = user.id
11
11
  redirect_to admin_url, :notice => t("monologue.admin.sessions.messages.logged_in")
12
12
  else
13
13
  flash.now.alert = t("monologue.admin.sessions.messages.invalid")
@@ -16,7 +16,7 @@ class Monologue::Admin::SessionsController < Monologue::Admin::BaseController
16
16
  end
17
17
 
18
18
  def destroy
19
- session[:user_id] = nil
19
+ session[:monologue_user_id] = nil
20
20
  redirect_to admin_url, :notice => t("monologue.admin.sessions.messages.logged_out")
21
21
  end
22
22
  end