ecm_blog 1.0.2 → 1.2.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: de632ffe27ad033f830a1959baf29d7a78d99ab4
4
- data.tar.gz: 389d767abee60c6d20f4bb42cb6da3f3fd40e589
3
+ metadata.gz: 843e5ebb68cbbe18d01e5a23cdf95e7baca769fb
4
+ data.tar.gz: 823084d2f9afe1478db9a69437e1ed0c9b0b4142
5
5
  SHA512:
6
- metadata.gz: 593e54f330468a25548c635155144b41d189b9101060105b22be0dc72c36a50b6c85fb1889e2f826e9704b79339318c09383195e3bf4d72264a7e14c67759b8f
7
- data.tar.gz: 90d9832e83a280efefd21ca37324be37a041d4125cc5d82557fbb1626747a730d052fa97e8ca0c64a06ff9c97746ccaa231a799a8ef86687a0af4812ea427859
6
+ metadata.gz: 04062aaf40066b9bdc681b9f334783c80254e8932a30abaaa277a7d4a414ea93c804ce155e852aa065452c556b767c6a1210ae1d9024ccc40eddfee8656bc2e4
7
+ data.tar.gz: a78b270146ff4129e97b8f992b090ad151f134d46984d6306b543c07cf04861880a731612268a74e0a7292c395d1c3d387d5976048d8f8da26f783e667995b5e
@@ -6,6 +6,7 @@ module Ecm
6
6
  include ResourcesController::RestResourceUrls
7
7
  include ResourcesController::RestActions
8
8
  include ResourcesController::Kaminari
9
+ include ResourcesController::LocationHistory
9
10
 
10
11
  helper Ecm::Comments::ApplicationHelper
11
12
 
@@ -16,7 +17,7 @@ module Ecm
16
17
  private
17
18
 
18
19
  def load_collection_scope
19
- super.published.friendly.order(updated_at: :desc)
20
+ super.published.friendly.order(created_at: :desc)
20
21
  end
21
22
 
22
23
  def load_resource_scope
@@ -0,0 +1,8 @@
1
+ module Ecm
2
+ module Blog
3
+ class ApplicationService < Rails::AddOns::Service::Base
4
+ class Result < Rails::AddOns::Service::Result::Base
5
+ end
6
+ end
7
+ end
8
+ end
@@ -0,0 +1,147 @@
1
+ require 'csv'
2
+
3
+ module Ecm
4
+ module Blog
5
+ # Example:
6
+ #
7
+ # You selected joomla posts from your database like this:
8
+ #
9
+ # SELECT joomla_content.title, joomla_content.fulltext, joomla_content.created, joomla_content.modified, joomla_users.email
10
+ # FROM joomla_content, joomla_users
11
+ # where created_by = joomla_users.id;
12
+ #
13
+ # And exported the data into a csv file like this:
14
+ #
15
+ # # tmp/old_posts.csv
16
+ # title;fulltext;created;modified;email
17
+ # "My first Post";"This is the body";"2013-02-12 14:22:23";"2013-02-12 21:58:54";john.doe@example.com
18
+ #
19
+ # You can import this csv file from the rails console:
20
+ #
21
+ # # rails console
22
+ # Ecm::Blog::ImportPostsService.call({ filename: 'tmp/old_posts.csv', column_map: :joomla, body_source_format: :html }, autosave: true)
23
+ #
24
+ class ImportPostsService < ApplicationService
25
+ class Result < ApplicationService::Result
26
+ attr_accessor :filename, :column_map, :body_source_format, :csv_data, :posts
27
+ end
28
+
29
+ COLUMN_MAPS = {
30
+ joomla: {
31
+ title: :title,
32
+ body: :fulltext,
33
+ created_at: :created,
34
+ updated_at: :modified,
35
+ # published_at: ->(row) { Time.zone.now },
36
+ published_at: :created,
37
+ creator_email: :email
38
+ }
39
+ }
40
+
41
+ def self.column_maps
42
+ COLUMN_MAPS
43
+ end
44
+
45
+ BODY_SOURCE_FORMATS = [:markdown, :html]
46
+
47
+ def self.body_source_formats
48
+ BODY_SOURCE_FORMATS
49
+ end
50
+
51
+ attr_accessor :filename, :column_map, :body_source_format
52
+
53
+ validates :filename, presence: true
54
+ validates :column_map, presence: true, inclusion: column_maps.keys
55
+ validates :body_source_format, presence: true, inclusion: body_source_formats
56
+
57
+ private
58
+
59
+ def after_initialize
60
+ @creators = {}
61
+ @body_source_format ||= :markdown
62
+ end
63
+
64
+ def _perform
65
+ @csv_data = load_csv_data!
66
+ @posts = build_posts!
67
+
68
+ ActiveRecord::Base.transaction { @posts.map(&:save!) } if autosave?
69
+
70
+ @result.csv_data = @csv_data
71
+ @result.posts = @posts
72
+ @result.filename = @filename
73
+ @result.column_map = @column_map
74
+ @result.body_source_format = @body_source_format
75
+ end
76
+
77
+ def load_csv_data!
78
+ CSV.read(@filename, csv_options)
79
+ end
80
+
81
+ def csv_options
82
+ { col_sep: ';', headers: true }
83
+ end
84
+
85
+ def build_posts!
86
+ say "Building posts" do
87
+ @csv_data.each_with_index.collect do |row, index|
88
+ build_post(row, index)
89
+ end
90
+ end
91
+ end
92
+
93
+ def build_post(row, index)
94
+ say "Building post [#{index}]" do
95
+ attrs = build_post_attributes(row.to_h)
96
+ Ecm::Blog::Post.new(attrs)
97
+ end
98
+ end
99
+
100
+ def build_post_attributes(row)
101
+ attrs = column_mapping.each_with_object({}) do |(post_attribute_name, value_key_or_proc), result|
102
+ result[post_attribute_name] = case value_key_or_proc
103
+ when Symbol, String
104
+ row[value_key_or_proc.to_s]
105
+ when Proc
106
+ value_key_or_proc.call(row)
107
+ else
108
+ nil
109
+ end
110
+ end
111
+ attrs[:creator] = load_creator(attrs.delete(:creator_email))
112
+ attrs[:body] = transform_body(attrs.delete(:body) || '') unless @body_source_format == :markdown
113
+ attrs
114
+ end
115
+
116
+ def column_maps
117
+ self.class.column_maps
118
+ end
119
+
120
+ def column_mapping
121
+ column_maps[@column_map]
122
+ end
123
+
124
+ def post_attribute_for_imported_key(key)
125
+ column_mapping.invert[key.to_sym]
126
+ end
127
+
128
+ def load_creator(email)
129
+ creator = Ecm::Blog::Configuration.creator_class_name.constantize.where(email: email).first_or_initialize { |u| u.password = u.password_confirmation = SecureRandom.uuid }
130
+ if creator.persisted?
131
+ @creators[email] ||= creator
132
+ else
133
+ creator
134
+ end
135
+ end
136
+
137
+ def transform_body(body)
138
+ case @body_source_format
139
+ when :html
140
+ HTMLPage.new(contents: body).markdown
141
+ else
142
+ body
143
+ end
144
+ end
145
+ end
146
+ end
147
+ end
@@ -1,8 +1,14 @@
1
1
  %div{ id: dom_id(post), class: dom_class(post) }
2
2
  %h1.post-title
3
- = post.title
4
- %small.post-creation-information.pull-right
3
+ = link_to(post.title, ecm_blog.url_for(post))
4
+ %small
5
+ %span.post-creation-information.text-muted
5
6
  = "#{l(post.created_at)} | #{post.creator.try(:human)}"
6
- %p.post-tags= tag_labels_for(post)
7
+ |
8
+ %span.comments-information
9
+ = link_to(t('ecm.comments.commentable.comments_information', comments_count: post.comments.count), ecm_blog.post_url(post, anchor: 'comments'))
10
+ |
11
+ %span.post-tags
12
+ = tag_labels_for(post)
7
13
 
8
14
  %p.post-body= post.body(format: :html).html_safe
@@ -1,12 +1,14 @@
1
1
  %div{ id: dom_id(post), class: "#{dom_class(post)} bottom-margin-5" }
2
2
  %h2.post-title
3
3
  = link_to(post.title, ecm_blog.url_for(post))
4
- %small.post-creation-information.pull-right
4
+ %small
5
+ %span.post-creation-information.text-muted
5
6
  = "#{l(post.created_at)} | #{post.creator.try(:human)}"
6
- %p
7
- %span.post-tags<= tag_labels_for(post)
8
7
  |
9
8
  %span.comments-information
10
9
  = link_to(t('ecm.comments.commentable.comments_information', comments_count: post.comments.count), ecm_blog.post_url(post, anchor: 'comments'))
10
+ |
11
+ %span.post-tags
12
+ = tag_labels_for(post)
11
13
 
12
14
  %p.post-body= post.body(format: :html).html_safe
@@ -1,6 +1,7 @@
1
- %h1#page-title= resource_class.model_name.human(count: :other)
1
+ %h1#page-title= Ecm::Blog::Configuration.posts_index_page_title_proc.call(self)
2
2
 
3
3
  = render partial: "post_in_index", collection: @collection, as: :post
4
4
 
5
- .col-lg.12.text-center
6
- = bootstrap_paginate(@collection)
5
+ .row
6
+ .col-lg-12.text-center
7
+ = paginate(@collection, Ecm::Blog::Configuration.pagination_options_proc.call(self))
data/config/routes.rb CHANGED
@@ -1,7 +1,9 @@
1
1
  Ecm::Blog::Engine.routes.draw do
2
2
  localized do
3
3
  scope :ecm_blog_engine do
4
- resources :posts, only: [:index, :show]
4
+ resources :posts, only: [:index, :show] do
5
+ get 'page/:page', action: :index, on: :collection
6
+ end
5
7
 
6
8
  root to: 'posts#index'
7
9
  end
@@ -11,6 +11,8 @@ module Ecm
11
11
 
12
12
  mattr_accessor(:base_controller) { '::FrontendController' }
13
13
  mattr_accessor(:creator_class_name) { 'User' }
14
+ mattr_accessor(:posts_index_page_title_proc) { ->(view) { view.resource_class.model_name.human(count: :other) } }
15
+ mattr_accessor(:pagination_options_proc) { ->(view) { { theme: 'twitter-bootstrap-3' } } }
14
16
  end
15
17
  end
16
18
  end
@@ -1,5 +1,5 @@
1
1
  module Ecm
2
2
  module Blog
3
- VERSION = '1.0.2'.freeze
3
+ VERSION = '1.2.0'.freeze
4
4
  end
5
5
  end
data/lib/ecm_blog.rb CHANGED
@@ -1,6 +1,7 @@
1
1
  require 'ecm_comments'
2
2
  require 'acts_as_published'
3
3
  require 'friendly_id'
4
+ require 'html2markdown'
4
5
  require 'kaminari'
5
6
  require 'kramdown'
6
7
 
@@ -4,6 +4,33 @@ Ecm::Blog.configure do |config|
4
4
  # Default: config.base_controller = '<%= base_controller_class_name %>'
5
5
  #
6
6
  config.base_controller = '<%= base_controller_class_name %>'
7
-
7
+
8
+ # Class to use for creators and updaters.
9
+ #
10
+ # default: config.creator_class_name = 'User'
11
+ #
8
12
  config.creator_class_name = 'User'
13
+
14
+ # Set the page title for the posts index page. Useful for when you use
15
+ # the blog posts index as main app root page.
16
+ #
17
+ # example: config.posts_index_page_title_proc = ->(view) { view.t('.welcome') }
18
+ #
19
+ # default: config.posts_index_page_title_proc = ->(view) { view.resource_class.model_name.human(count: :other) }
20
+ #
21
+ config.posts_index_page_title_proc = ->(view) { view.resource_class.model_name.human(count: :other) }
22
+
23
+ # Set options that will be passed to the paginate call.
24
+ #
25
+ # example for bootstrap 3 (You will need to add the bootstrap3-kaminari-views gem to your Gemfile):
26
+ #
27
+ # config.pagination_options_proc = ->(view) { { theme: 'twitter-bootstrap-3' }
28
+ #
29
+ # example for bootstrap 4 (You will need to add the bootstrap4-kaminari-views gem to your Gemfile):
30
+ #
31
+ # config.pagination_options_proc = ->(view) { { theme: 'twitter-bootstrap-4' }
32
+ #
33
+ # default: config.pagination_options_proc = ->(view) { { theme: 'twitter-bootstrap-4', pagination_class: 'justify-content-center' } }
34
+ #
35
+ config.pagination_options_proc = ->(view) { { theme: 'twitter-bootstrap-4', pagination_class: 'justify-content-center' } }
9
36
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ecm_blog
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.2
4
+ version: 1.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Roberto Vasquez Angel
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2018-03-10 00:00:00.000000000 Z
11
+ date: 2018-03-25 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rails
@@ -38,6 +38,20 @@ dependencies:
38
38
  - - ">="
39
39
  - !ruby/object:Gem::Version
40
40
  version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: html2markdown
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
41
55
  - !ruby/object:Gem::Dependency
42
56
  name: kaminari
43
57
  requirement: !ruby/object:Gem::Requirement
@@ -102,7 +116,6 @@ extensions: []
102
116
  extra_rdoc_files: []
103
117
  files:
104
118
  - MIT-LICENSE
105
- - README.rdoc
106
119
  - Rakefile
107
120
  - app/assets/javascripts/ecm/blog/application.js
108
121
  - app/assets/stylesheets/ecm/blog/application.css
@@ -110,6 +123,8 @@ files:
110
123
  - app/controllers/ecm/blog/posts_controller.rb
111
124
  - app/helpers/ecm/blog/application_helper.rb
112
125
  - app/models/ecm/blog/post.rb
126
+ - app/services/ecm/blog/application_service.rb
127
+ - app/services/ecm/blog/import_posts_service.rb
113
128
  - app/views/ecm/blog/posts/_post.haml
114
129
  - app/views/ecm/blog/posts/_post_in_index.haml
115
130
  - app/views/ecm/blog/posts/index.haml
data/README.rdoc DELETED
@@ -1,3 +0,0 @@
1
- = Ecm::Blog
2
-
3
- This project rocks and uses MIT-LICENSE.