monologue 0.1.0
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.
- data/MIT-LICENSE +20 -0
- data/README.md +73 -0
- data/Rakefile +32 -0
- data/app/assets/javascripts/monologue/admin/application.js +13 -0
- data/app/assets/javascripts/monologue/admin/tinymce-config.js +21 -0
- data/app/assets/javascripts/monologue/blog/application.js +9 -0
- data/app/assets/stylesheets/monologue/admin/application.css +10 -0
- data/app/assets/stylesheets/monologue/blog/application.css +13 -0
- data/app/assets/stylesheets/monologue/blog/custom.css +1 -0
- data/app/assets/stylesheets/monologue/blog/fonts.css +1 -0
- data/app/assets/stylesheets/monologue/blog/monologue.css +37 -0
- data/app/assets/stylesheets/monologue/blog/skeleton/base.css +343 -0
- data/app/assets/stylesheets/monologue/blog/skeleton/layout.css +58 -0
- data/app/assets/stylesheets/monologue/blog/skeleton/skeleton.css +242 -0
- data/app/controllers/monologue/admin/base_controller.rb +12 -0
- data/app/controllers/monologue/admin/posts_controller.rb +54 -0
- data/app/controllers/monologue/admin/sessions_controller.rb +22 -0
- data/app/controllers/monologue/application_controller.rb +22 -0
- data/app/controllers/monologue/posts_controller.rb +25 -0
- data/app/form_builders/monologue_admin_form_builder.rb +61 -0
- data/app/helpers/monologue/admin/admin_helper.rb +4 -0
- data/app/helpers/monologue/application_helper.rb +8 -0
- data/app/helpers/monologue/posts_helper.rb +4 -0
- data/app/helpers/monologue/sessions_helper.rb +6 -0
- data/app/models/monologue/post.rb +40 -0
- data/app/models/monologue/posts_revision.rb +34 -0
- data/app/models/monologue/user.rb +6 -0
- data/app/sweepers/monologue/posts_sweeper.rb +28 -0
- data/app/views/layouts/monologue/_google_analytics.html.erb +15 -0
- data/app/views/layouts/monologue/admin.html.erb +21 -0
- data/app/views/layouts/monologue/admin/_nav_bar.html.erb +24 -0
- data/app/views/layouts/monologue/application.html.erb +60 -0
- data/app/views/monologue/admin/posts/_form.html.erb +16 -0
- data/app/views/monologue/admin/posts/edit.html.erb +4 -0
- data/app/views/monologue/admin/posts/index.html.erb +20 -0
- data/app/views/monologue/admin/posts/new.html.erb +4 -0
- data/app/views/monologue/admin/sessions/new.html.erb +13 -0
- data/app/views/monologue/posts/404.html.erb +9 -0
- data/app/views/monologue/posts/_pagination.html.erb +9 -0
- data/app/views/monologue/posts/_social_sharing.html.erb +42 -0
- data/app/views/monologue/posts/feed.rss.builder +19 -0
- data/app/views/monologue/posts/index.html.erb +18 -0
- data/app/views/monologue/posts/show.html.erb +38 -0
- data/config/locales/en.yml +106 -0
- data/config/locales/fr.yml +106 -0
- data/config/routes.rb +15 -0
- data/db/migrate/20120114001001_create_monologue_users.rb +11 -0
- data/db/migrate/20120120193858_create_monologue_posts_revisions.rb +18 -0
- data/db/migrate/20120120193907_create_monologue_posts.rb +10 -0
- data/db/seeds.rb +1 -0
- data/lib/monologue.rb +17 -0
- data/lib/monologue/engine.rb +11 -0
- data/lib/monologue/version.rb +3 -0
- data/lib/tasks/monologue_tasks.rake +4 -0
- data/vendor/assets/images/monologue/bootstrap/glyphicons-halflings-white.png +0 -0
- data/vendor/assets/images/monologue/bootstrap/glyphicons-halflings.png +0 -0
- data/vendor/assets/javascripts/monologue/bootstrap/bootstrap-datepicker-fr.js +9 -0
- data/vendor/assets/javascripts/monologue/bootstrap/bootstrap-datepicker.js +338 -0
- data/vendor/assets/javascripts/monologue/bootstrap/bootstrap.min.js +1 -0
- data/vendor/assets/stylesheets/monologue/bootstrap/bootstrap-datepicker.css +130 -0
- data/vendor/assets/stylesheets/monologue/bootstrap/bootstrap-responsive.min.css +3 -0
- data/vendor/assets/stylesheets/monologue/bootstrap/bootstrap.min.css +610 -0
- metadata +285 -0
@@ -0,0 +1,40 @@
|
|
1
|
+
module Monologue
|
2
|
+
class Post < ActiveRecord::Base
|
3
|
+
has_many :posts_revisions, :dependent => :destroy
|
4
|
+
|
5
|
+
accepts_nested_attributes_for :posts_revisions
|
6
|
+
attr_accessible :posts_revisions_attributes
|
7
|
+
attr_accessible :published
|
8
|
+
|
9
|
+
|
10
|
+
|
11
|
+
scope :default, includes(:posts_revisions).where("posts_revision_id = monologue_posts_revisions.id").order("published_at DESC")
|
12
|
+
scope :published, default.where(:published => true)
|
13
|
+
|
14
|
+
validates :posts_revision_id, :uniqueness => true
|
15
|
+
|
16
|
+
def just_the_revision_one_before
|
17
|
+
self.posts_revisions.where("post_id = ?", self.id).order("monologue_posts_revisions.updated_at DESC").offset(1).limit(1).first
|
18
|
+
end
|
19
|
+
|
20
|
+
def latest_revision
|
21
|
+
self.posts_revisions.where("post_id = ?", self.id).order("monologue_posts_revisions.updated_at DESC").limit(1).first
|
22
|
+
end
|
23
|
+
|
24
|
+
def self.page p
|
25
|
+
per_page = Monologue.posts_per_page || 10
|
26
|
+
set_total_pages(per_page)
|
27
|
+
p = (p.nil? ? 0 : p.to_i - 1)
|
28
|
+
offset = (p==0 ? 0 : p * per_page)
|
29
|
+
self.limit(per_page).offset(offset)
|
30
|
+
end
|
31
|
+
|
32
|
+
def self.total_pages
|
33
|
+
@number_of_pages
|
34
|
+
end
|
35
|
+
|
36
|
+
def self.set_total_pages per_page
|
37
|
+
@number_of_pages = self.count / per_page + ( self.count % per_page == 0 ? 0 : 1 )
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
module Monologue
|
2
|
+
class PostsRevision < ActiveRecord::Base
|
3
|
+
attr_accessible :title, :content, :url, :published_at
|
4
|
+
|
5
|
+
before_validation :generate_url
|
6
|
+
|
7
|
+
|
8
|
+
after_save :latest_revision_is_current
|
9
|
+
|
10
|
+
belongs_to :post
|
11
|
+
belongs_to :user
|
12
|
+
|
13
|
+
validates :title, :presence => true
|
14
|
+
validates :content, :presence => true
|
15
|
+
validates :url, :presence => true
|
16
|
+
validates :user_id, :presence => true
|
17
|
+
# validates :post_id, :presence => true # TODO: do something about this validation on the first creation of a POST
|
18
|
+
validates :published_at, :presence => true
|
19
|
+
|
20
|
+
def latest_revision_is_current
|
21
|
+
post = Monologue::Post.find(self.post_id)
|
22
|
+
post.posts_revision_id = self.id
|
23
|
+
post.save!
|
24
|
+
end
|
25
|
+
|
26
|
+
private
|
27
|
+
|
28
|
+
def generate_url
|
29
|
+
year = self.published_at.class == ActiveSupport::TimeWithZone ? self.published_at.year : DateTime.now.year
|
30
|
+
self.title = "" if self.title.nil?
|
31
|
+
self.url = "#{Monologue::Engine.routes.url_helpers.root_path}#{year}/#{self.title.parameterize}" if self.url.nil? || self.url.strip == ""
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
class Monologue::PostsSweeper < ActionController::Caching::Sweeper
|
2
|
+
observe Monologue::Post
|
3
|
+
|
4
|
+
|
5
|
+
def sweep(post)
|
6
|
+
root_path = Monologue::Engine.routes.url_helpers.root_path if root_path.nil? # TODO: why do I have to do this to make tests pass? There must be something much more clean to make tests pass
|
7
|
+
page_cache_directory = Rails.public_path if page_cache_directory.nil? # TODO: we should not need this either...
|
8
|
+
if post.posts_revisions.count > 0
|
9
|
+
current_post_path = "#{page_cache_directory}#{post.just_the_revision_one_before.url}.html" unless post.just_the_revision_one_before.nil?
|
10
|
+
current_post_path = "#{page_cache_directory}#{post.posts_revisions.last.url}.html" if post.posts_revisions.count == 1
|
11
|
+
File.delete current_post_path if File.exists? current_post_path
|
12
|
+
end
|
13
|
+
|
14
|
+
feed_file_path = "#{page_cache_directory}#{root_path}feed.rss"
|
15
|
+
File.delete feed_file_path if File.exists? feed_file_path
|
16
|
+
|
17
|
+
root_file_path = "#{page_cache_directory}#{root_path.chomp("/")}.html"
|
18
|
+
root_file_path = "#{page_cache_directory}/index.html" if root_path.chomp("/") == "" # TODO: add test for that? It would need another dummy app mounted at root...?
|
19
|
+
File.delete root_file_path if File.exists? root_file_path
|
20
|
+
|
21
|
+
FileUtils.rm_rf "#{page_cache_directory}/page" # remove pages
|
22
|
+
end
|
23
|
+
|
24
|
+
alias_method :after_create, :sweep
|
25
|
+
alias_method :after_update, :sweep
|
26
|
+
alias_method :after_destroy, :sweep
|
27
|
+
|
28
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
<% if defined? Monologue.google_analytics_id %>
|
2
|
+
<script type="text/javascript">
|
3
|
+
|
4
|
+
var _gaq = _gaq || [];
|
5
|
+
_gaq.push(['_setAccount', '<%= Monologue.google_analytics_id %>']);
|
6
|
+
_gaq.push(['_trackPageview']);
|
7
|
+
|
8
|
+
(function() {
|
9
|
+
var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
|
10
|
+
ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
|
11
|
+
var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
|
12
|
+
})();
|
13
|
+
|
14
|
+
</script>
|
15
|
+
<% end %>
|
@@ -0,0 +1,21 @@
|
|
1
|
+
<!DOCTYPE html>
|
2
|
+
<html>
|
3
|
+
<head>
|
4
|
+
<title>Monologue</title>
|
5
|
+
<%= stylesheet_link_tag "monologue/admin/application" %>
|
6
|
+
<%= javascript_include_tag "monologue/admin/application" %>
|
7
|
+
<%= csrf_meta_tags %>
|
8
|
+
</head>
|
9
|
+
<body>
|
10
|
+
<% if current_user %>
|
11
|
+
<%= render "layouts/monologue/admin/nav_bar" %>
|
12
|
+
<% end %>
|
13
|
+
<div class="container">
|
14
|
+
<% flash.each do |name, msg| %>
|
15
|
+
<%= content_tag :div, msg, :id => "flash_#{name}", :class => (name == :notice ? "alert alert-info" : "alert alert-error") %>
|
16
|
+
<% end %>
|
17
|
+
|
18
|
+
<%= yield %>
|
19
|
+
</div>
|
20
|
+
</body>
|
21
|
+
</html>
|
@@ -0,0 +1,24 @@
|
|
1
|
+
<div class="navbar">
|
2
|
+
<div class="navbar-inner">
|
3
|
+
<div class="container">
|
4
|
+
<%= link_to "Monologue", admin_path, :class => "brand" %>
|
5
|
+
<ul class="nav pull-left">
|
6
|
+
|
7
|
+
<li class="<%= request.fullpath === new_admin_post_path ? "active":"" %>">
|
8
|
+
<a href="<%= new_admin_post_path %>"><%=t(".add_a_monologue")%></a>
|
9
|
+
</li>
|
10
|
+
<li class="<%= request.fullpath === admin_posts_path || request.fullpath === admin_path ? "active":"" %>">
|
11
|
+
<a href="<%= admin_posts_path %>"><%=t(".list_monologues")%></a>
|
12
|
+
</li>
|
13
|
+
<li>
|
14
|
+
<a href="#"><%=t(".comments")%></a>
|
15
|
+
</li>
|
16
|
+
</ul>
|
17
|
+
<ul class="nav pull-right">
|
18
|
+
<li><a href="#"><%=t(".logged_in_as")%> <%= current_user.email %>.</a></li>
|
19
|
+
<li><%= link_to t(".log_out"), admin_logout_path %></li>
|
20
|
+
</ul>
|
21
|
+
|
22
|
+
</div>
|
23
|
+
</div>
|
24
|
+
</div>
|
@@ -0,0 +1,60 @@
|
|
1
|
+
<!DOCTYPE html>
|
2
|
+
<!--[if lt IE 7 ]><html class="ie ie6" lang="en"> <![endif]-->
|
3
|
+
<!--[if IE 7 ]><html class="ie ie7" lang="en"> <![endif]-->
|
4
|
+
<!--[if IE 8 ]><html class="ie ie8" lang="en"> <![endif]-->
|
5
|
+
<!--[if (gte IE 9)|!(IE)]><!--><html lang="en"> <!--<![endif]-->
|
6
|
+
<head>
|
7
|
+
<title>
|
8
|
+
<%= content_for?(:title) ? ((yield :title) + " | #{Monologue.site_name}") : Monologue.site_name %>
|
9
|
+
</title>
|
10
|
+
<meta charset="utf-8" />
|
11
|
+
<meta name="description" content="<%= content_for?(:meta_description) ? yield(:meta_description) : Monologue.meta_description %>" />
|
12
|
+
<meta name="keyword" content="<%=Monologue.meta_keyword%>">
|
13
|
+
|
14
|
+
<meta http-equiv="content-type" content="text/html;charset=utf-8">
|
15
|
+
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
|
16
|
+
|
17
|
+
<%= stylesheet_link_tag "monologue/blog/application" %>
|
18
|
+
<%= javascript_include_tag "monologue/blog/application" %>
|
19
|
+
|
20
|
+
<!-- Mobile Specific Metas
|
21
|
+
================================================== -->
|
22
|
+
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
|
23
|
+
|
24
|
+
<link href="/feed" rel="alternate" title="RSS" type="application/rss+xml" >
|
25
|
+
<%= render "layouts/monologue/google_analytics" %>
|
26
|
+
</head>
|
27
|
+
<body>
|
28
|
+
<div class="container">
|
29
|
+
<header class="main-header sixteen columns clearfix">
|
30
|
+
<h1><a href="<%= root_path %>"><%=Monologue.site_name%></a></h1>
|
31
|
+
<h2><%=Monologue.site_subtitle%></h2>
|
32
|
+
</header>
|
33
|
+
|
34
|
+
<div class="content sixteen columns">
|
35
|
+
<%= yield %>
|
36
|
+
</div>
|
37
|
+
</div>
|
38
|
+
<footer>
|
39
|
+
<%= yield :footer %>
|
40
|
+
</footer>
|
41
|
+
|
42
|
+
<script type="text/javascript">
|
43
|
+
/* * * CONFIGURATION VARIABLES: EDIT BEFORE PASTING INTO YOUR WEBPAGE * * */
|
44
|
+
var disqus_shortname = '<%= Monologue.disqus_shortname%>'; // required: replace example with your forum shortname
|
45
|
+
|
46
|
+
<% if Rails.env.development? %>
|
47
|
+
var disqus_developer = 1; // developer mode is on
|
48
|
+
<% end %>
|
49
|
+
|
50
|
+
|
51
|
+
/* * * DON'T EDIT BELOW THIS LINE * * */
|
52
|
+
(function () {
|
53
|
+
var s = document.createElement('script'); s.async = true;
|
54
|
+
s.type = 'text/javascript';
|
55
|
+
s.src = 'http://' + disqus_shortname + '.disqus.com/count.js';
|
56
|
+
(document.getElementsByTagName('HEAD')[0] || document.getElementsByTagName('BODY')[0]).appendChild(s);
|
57
|
+
}());
|
58
|
+
</script>
|
59
|
+
</body>
|
60
|
+
</html>
|
@@ -0,0 +1,16 @@
|
|
1
|
+
<%= post.error_messages %>
|
2
|
+
<%= post.fields_for @revision do |revision| %>
|
3
|
+
<%= revision.text_field :title, :label => t(".title"), :class => "span6" %>
|
4
|
+
<%= revision.text_area :content, :label => t(".content"), :class => "span12 ckeditor" %>
|
5
|
+
<%= revision.text_field :url, :label => raw("#{t(".url.before_generated_url")} '#{monologue.root_path}#{DateTime.now.year}/#{t(".url.generated_title")}'#{t(".url.after_generated_url")}") %>
|
6
|
+
<%= revision.text_field :published_at, :label => t(".published_at"), :data => {:datepicker => "datepicker"}, :value => revision.object.published_at.nil? ? "" : revision.object.published_at.strftime("%Y-%m-%d") %>
|
7
|
+
<% end %>
|
8
|
+
<%= post.check_box :published, :label => t(".published") %>
|
9
|
+
|
10
|
+
<%= post.submit t(".save"), :class => "btn btn-large btn-primary" %> <a href="<%= @revision.url %>" target="_blank" class="btn btn-large"><%= t(".preview") %></a>
|
11
|
+
|
12
|
+
<script>
|
13
|
+
if($.fn.datepicker.defaults_<%= I18n.locale %>){
|
14
|
+
$.fn.datepicker.defaults = $.fn.datepicker.defaults_<%= I18n.locale %>;
|
15
|
+
}
|
16
|
+
</script>
|
@@ -0,0 +1,20 @@
|
|
1
|
+
<table class="table table-striped table-bordered">
|
2
|
+
<thead>
|
3
|
+
<tr>
|
4
|
+
<th><%= t(".title")%></th>
|
5
|
+
<th><%= t(".status")%></th>
|
6
|
+
<th></th>
|
7
|
+
<th></th>
|
8
|
+
</tr>
|
9
|
+
</thead>
|
10
|
+
<tbody>
|
11
|
+
<% @posts.each do |post|%>
|
12
|
+
<tr>
|
13
|
+
<td><%= link_to post.posts_revisions.last.title, edit_admin_post_path(post) %></td>
|
14
|
+
<td><span class="label label-<%= post.published ? "success" : "important" %>"><%= post.published ? t(".published") : t(".not_published") %></span></td>
|
15
|
+
<td><%= link_to t(".edit"), edit_admin_post_path(post), :class => "btn btn-small" %></td>
|
16
|
+
<td><%= link_to t(".delete"), ["admin", post], :confirm => 'Are you sure?', :method => :delete, :class => "btn btn-small btn-danger" %></td>
|
17
|
+
</tr>
|
18
|
+
<% end %>
|
19
|
+
</tbody>
|
20
|
+
</table>
|
@@ -0,0 +1,13 @@
|
|
1
|
+
<h1><%= t(".title") %></h1>
|
2
|
+
|
3
|
+
<%= form_tag admin_sessions_path do %>
|
4
|
+
<div class="field">
|
5
|
+
<%= label_tag :email, t(".email") %>
|
6
|
+
<%= text_field_tag :email, params[:email] %>
|
7
|
+
</div>
|
8
|
+
<div class="field">
|
9
|
+
<%= label_tag :password, t(".password") %>
|
10
|
+
<%= password_field_tag :password %>
|
11
|
+
</div>
|
12
|
+
<div class="actions"><%= submit_tag t(".button"), :class => "btn btn-large btn-primary" %></div>
|
13
|
+
<% end %>
|
@@ -0,0 +1,9 @@
|
|
1
|
+
<div id="pagination">
|
2
|
+
<% if @posts.total_pages > 1 && @posts.total_pages != @page.to_i %>
|
3
|
+
<%= link_to t(".older_posts"), posts_page_path(@page.to_i+1), :class => "older_posts" %>
|
4
|
+
<% end %>
|
5
|
+
|
6
|
+
<% if @posts.total_pages > 1 && @page.to_i > 1 %>
|
7
|
+
<%= link_to t(".newer_posts"), posts_page_path(@page.to_i-1), :class => "newer_posts" %>
|
8
|
+
<% end %>
|
9
|
+
</div>
|
@@ -0,0 +1,42 @@
|
|
1
|
+
<footer class="monologue-social-sharing well">
|
2
|
+
<h2><%= t(".tagline") %></h2>
|
3
|
+
<!-- FACEBOOK LIKE -->
|
4
|
+
|
5
|
+
<div id="fb-root"></div>
|
6
|
+
<script>(function(d, s, id) {
|
7
|
+
var js, fjs = d.getElementsByTagName(s)[0];
|
8
|
+
if (d.getElementById(id)) return;
|
9
|
+
js = d.createElement(s); js.id = id;
|
10
|
+
js.src = "//connect.facebook.net/<%= Monologue.facebook_like_locale || "en_US" %>/all.js#xfbml=1&appId=288133081204194";
|
11
|
+
fjs.parentNode.insertBefore(js, fjs);
|
12
|
+
}(document, 'script', 'facebook-jssdk'));</script>
|
13
|
+
<div class="fb-like" data-layout="box_count" data-show-faces="true" data-font="verdana"></div>
|
14
|
+
<!-- /FACEBOOK LIKE -->
|
15
|
+
|
16
|
+
<!-- TWITTER -->
|
17
|
+
<a href="https://twitter.com/share" class="twitter-share-button"
|
18
|
+
data-lang="<%= Monologue.twitter_locale || "en" %>"
|
19
|
+
data-url="<%= request.url %>"
|
20
|
+
data-via="<%=Monologue.twitter_username%>"
|
21
|
+
data-text="<%=@revision.title%>"
|
22
|
+
data-count="vertical">Tweet</a>
|
23
|
+
|
24
|
+
<script>!function(d,s,id){var js,fjs=d.getElementsByTagName(s)[0];if(!d.getElementById(id)){js=d.createElement(s);js.id=id;js.src="//platform.twitter.com/widgets.js";fjs.parentNode.insertBefore(js,fjs);}}(document,"script","twitter-wjs");</script>
|
25
|
+
<!-- /TWITTER -->
|
26
|
+
|
27
|
+
<!-- GOOGLE +1 -->
|
28
|
+
<!-- Placez cette balise là où vous souhaitez positionner le bouton +1. -->
|
29
|
+
<g:plusone size="tall"></g:plusone>
|
30
|
+
|
31
|
+
<!-- Placez cet appel d'affichage à l'endroit approprié. -->
|
32
|
+
<script type="text/javascript">
|
33
|
+
window.___gcfg = {lang: '<%=Monologue.google_plusone_locale || "en" %>'};
|
34
|
+
|
35
|
+
(function() {
|
36
|
+
var po = document.createElement('script'); po.type = 'text/javascript'; po.async = true;
|
37
|
+
po.src = 'https://apis.google.com/js/plusone.js';
|
38
|
+
var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(po, s);
|
39
|
+
})();
|
40
|
+
</script>
|
41
|
+
<!-- /GOOGLE +1 -->
|
42
|
+
</footer>
|
@@ -0,0 +1,19 @@
|
|
1
|
+
xml.instruct! :xml, :version => "1.0"
|
2
|
+
xml.rss :version => "2.0" do
|
3
|
+
xml.channel do
|
4
|
+
xml.title Monologue.site_name
|
5
|
+
xml.description Monologue.meta_description
|
6
|
+
xml.link root_url
|
7
|
+
|
8
|
+
for post in @posts
|
9
|
+
revision = post.posts_revisions.last
|
10
|
+
xml.item do
|
11
|
+
xml.title revision.title
|
12
|
+
xml.description raw(revision.content)
|
13
|
+
xml.pubDate revision.published_at.to_s(:rfc822)
|
14
|
+
xml.link Monologue.site_url + revision.url
|
15
|
+
xml.guid Monologue.site_url + revision.url
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
<% @posts.each do |post| %>
|
2
|
+
<% revision = post.posts_revisions.first %>
|
3
|
+
|
4
|
+
<section>
|
5
|
+
<header>
|
6
|
+
<h1><%= link_to revision.title, revision.url %></h1>
|
7
|
+
<time datetime="<%= revision.published_at %>">
|
8
|
+
<%= revision.published_at.to_date.to_formatted_s(:long_ordinal) %>
|
9
|
+
</time> | <%= revision.user.name %> | <a href="<%= revision.url + "#disqus_thread" %>"></a>
|
10
|
+
</header>
|
11
|
+
|
12
|
+
<p><%= raw truncate(strip_tags(revision.content), :length => 1000) %></p>
|
13
|
+
|
14
|
+
<%= link_to t(".readmore"), revision.url, :class => "btn alignleft" %>
|
15
|
+
</section>
|
16
|
+
<% end %>
|
17
|
+
|
18
|
+
<%= render "pagination" %>
|