workarea-blog 3.4.7

Sign up to get free protection for your applications and to get access to all the features.
Files changed (213) hide show
  1. checksums.yaml +7 -0
  2. data/.editorconfig +20 -0
  3. data/.eslintignore +2 -0
  4. data/.eslintrc +24 -0
  5. data/.github/ISSUE_TEMPLATE/bug_report.md +37 -0
  6. data/.github/ISSUE_TEMPLATE/documentation-request.md +17 -0
  7. data/.github/ISSUE_TEMPLATE/feature_request.md +20 -0
  8. data/.gitignore +16 -0
  9. data/.rspec +2 -0
  10. data/.scss-lint.yml +188 -0
  11. data/.tailor +180 -0
  12. data/.yardopts +1 -0
  13. data/CHANGELOG.md +1123 -0
  14. data/CODE_OF_CONDUCT.md +3 -0
  15. data/CONTRIBUTING.md +3 -0
  16. data/Gemfile +7 -0
  17. data/LICENSE +52 -0
  18. data/README.md +140 -0
  19. data/Rakefile +42 -0
  20. data/app/assets/images/workarea/admin/blog/content_block_types/blog_entry.svg +1 -0
  21. data/app/assets/images/workarea/admin/blog/icons/blog.svg +1 -0
  22. data/app/assets/images/workarea/admin/blog/icons/blog_entry.svg +1 -0
  23. data/app/assets/images/workarea/admin/blog/icons/blog_post_comment.svg +1 -0
  24. data/app/assets/javascripts/workarea/storefront/blog/modules/blog_comment_placeholder.js +33 -0
  25. data/app/assets/stylesheets/workarea/admin/blog/components/_blog_entry_card.scss +14 -0
  26. data/app/assets/stylesheets/workarea/storefront/blog/components/_blog_entry.scss +91 -0
  27. data/app/assets/stylesheets/workarea/storefront/blog/components/_blog_entry_summary.scss +74 -0
  28. data/app/assets/stylesheets/workarea/storefront/blog/components/_featured_entry_content_block.scss +22 -0
  29. data/app/controllers/workarea/admin/application_controller.decorator +5 -0
  30. data/app/controllers/workarea/admin/content_blog_comments_controller.rb +54 -0
  31. data/app/controllers/workarea/admin/content_blog_entries_controller.rb +70 -0
  32. data/app/controllers/workarea/admin/content_blogs_controller.rb +56 -0
  33. data/app/controllers/workarea/admin/create_content_blog_entries_controller.rb +69 -0
  34. data/app/controllers/workarea/storefront/blog_comments_controller.rb +14 -0
  35. data/app/controllers/workarea/storefront/blog_entries_controller.rb +48 -0
  36. data/app/controllers/workarea/storefront/blogs_controller.rb +19 -0
  37. data/app/helpers/workarea/admin/blogs_helper.rb +61 -0
  38. data/app/models/workarea/content/blog.rb +26 -0
  39. data/app/models/workarea/content/blog_comment.rb +67 -0
  40. data/app/models/workarea/content/blog_entry.rb +35 -0
  41. data/app/models/workarea/content/fields/blog_entry_id.rb +11 -0
  42. data/app/models/workarea/content/fields/blog_id.rb +8 -0
  43. data/app/models/workarea/search/admin/content_blog.rb +27 -0
  44. data/app/models/workarea/search/admin/content_blog_entry.rb +37 -0
  45. data/app/queries/workarea/metadata/content_blog.rb +6 -0
  46. data/app/queries/workarea/metadata/content_blog_entry.rb +6 -0
  47. data/app/queries/workarea/search/admin_blog_entries.rb +24 -0
  48. data/app/queries/workarea/search/admin_blogs.rb +20 -0
  49. data/app/seeds/workarea/blog_comments_seeds.rb +26 -0
  50. data/app/seeds/workarea/blog_entry_seeds.rb +73 -0
  51. data/app/seeds/workarea/blog_seeds.rb +53 -0
  52. data/app/services/workarea/search/queries/blog_admin.rb +20 -0
  53. data/app/services/workarea/search/queries/blog_entry_admin.rb +13 -0
  54. data/app/services/workarea/set_navigable.decorator +10 -0
  55. data/app/view_models/workarea/admin/blog_comments_view_model.rb +45 -0
  56. data/app/view_models/workarea/admin/blog_entries_view_model.rb +31 -0
  57. data/app/view_models/workarea/admin/blog_entry_view_model.rb +29 -0
  58. data/app/view_models/workarea/admin/blog_search_view_model.rb +6 -0
  59. data/app/view_models/workarea/admin/blog_view_model.rb +13 -0
  60. data/app/view_models/workarea/storefront/blog_entry_view_model.rb +43 -0
  61. data/app/view_models/workarea/storefront/blog_index_view_model.rb +17 -0
  62. data/app/view_models/workarea/storefront/blog_view_model.rb +83 -0
  63. data/app/view_models/workarea/storefront/content_blocks/blog_entry_content_block_view_model.rb +63 -0
  64. data/app/views/workarea/admin/activities/_content_blog_comment_create.html.haml +12 -0
  65. data/app/views/workarea/admin/activities/_content_blog_comment_destroy.html.haml +9 -0
  66. data/app/views/workarea/admin/activities/_content_blog_comment_update.html.haml +10 -0
  67. data/app/views/workarea/admin/activities/_content_blog_create.html.haml +12 -0
  68. data/app/views/workarea/admin/activities/_content_blog_destroy.html.haml +10 -0
  69. data/app/views/workarea/admin/activities/_content_blog_entry_create.html.haml +12 -0
  70. data/app/views/workarea/admin/activities/_content_blog_entry_destroy.html.haml +10 -0
  71. data/app/views/workarea/admin/activities/_content_blog_entry_update.html.haml +10 -0
  72. data/app/views/workarea/admin/activities/_content_blog_update.html.haml +10 -0
  73. data/app/views/workarea/admin/blog/_dashboard_navigation.html.haml +1 -0
  74. data/app/views/workarea/admin/blog/_menu.html.haml +13 -0
  75. data/app/views/workarea/admin/content_blocks/_blog_entry_id.html.haml +4 -0
  76. data/app/views/workarea/admin/content_blocks/_blog_id.html.haml +3 -0
  77. data/app/views/workarea/admin/content_blog_comments/_summary.html.haml +24 -0
  78. data/app/views/workarea/admin/content_blog_comments/edit.html.haml +60 -0
  79. data/app/views/workarea/admin/content_blog_comments/index.html.haml +49 -0
  80. data/app/views/workarea/admin/content_blog_entries/_aux_navigation.html.haml +4 -0
  81. data/app/views/workarea/admin/content_blog_entries/_cards.html.haml +113 -0
  82. data/app/views/workarea/admin/content_blog_entries/_summary.html.haml +10 -0
  83. data/app/views/workarea/admin/content_blog_entries/edit.html.haml +75 -0
  84. data/app/views/workarea/admin/content_blog_entries/index.html.haml +80 -0
  85. data/app/views/workarea/admin/content_blog_entries/index.json.jbuilder +5 -0
  86. data/app/views/workarea/admin/content_blog_entries/show.html.haml +20 -0
  87. data/app/views/workarea/admin/content_blog_entries/thumbnail_image.html.haml +55 -0
  88. data/app/views/workarea/admin/content_blogs/_aux_navigation.html.haml +2 -0
  89. data/app/views/workarea/admin/content_blogs/_cards.html.haml +58 -0
  90. data/app/views/workarea/admin/content_blogs/_summary.html.haml +6 -0
  91. data/app/views/workarea/admin/content_blogs/edit.html.haml +51 -0
  92. data/app/views/workarea/admin/content_blogs/index.html.haml +76 -0
  93. data/app/views/workarea/admin/content_blogs/index.json.jbuilder +4 -0
  94. data/app/views/workarea/admin/content_blogs/new.html.haml +33 -0
  95. data/app/views/workarea/admin/content_blogs/show.html.haml +19 -0
  96. data/app/views/workarea/admin/create_content_blog_entries/content.html.haml +28 -0
  97. data/app/views/workarea/admin/create_content_blog_entries/featured_products.html.haml +71 -0
  98. data/app/views/workarea/admin/create_content_blog_entries/publish.html.haml +51 -0
  99. data/app/views/workarea/admin/create_content_blog_entries/setup.html.haml +61 -0
  100. data/app/views/workarea/admin/create_content_blog_entries/thumbnail_image.html.haml +48 -0
  101. data/app/views/workarea/storefront/blog_comments/index.html.haml +31 -0
  102. data/app/views/workarea/storefront/blog_entries/_summary.html.haml +25 -0
  103. data/app/views/workarea/storefront/blog_entries/show.html.haml +85 -0
  104. data/app/views/workarea/storefront/blog_metadata/_publisher.html.haml +7 -0
  105. data/app/views/workarea/storefront/blogs/_blog_navigation.html.haml +7 -0
  106. data/app/views/workarea/storefront/blogs/index.html.haml +25 -0
  107. data/app/views/workarea/storefront/blogs/show.atom.builder +26 -0
  108. data/app/views/workarea/storefront/blogs/show.html.haml +31 -0
  109. data/app/views/workarea/storefront/content_blocks/_blog_entry.html.haml +20 -0
  110. data/app/workers/workarea/generate_content_metadata.decorator +15 -0
  111. data/bin/rails +18 -0
  112. data/config/initializers/appends.rb +26 -0
  113. data/config/initializers/content_block_types.rb +13 -0
  114. data/config/initializers/jump_to_navigation.rb +3 -0
  115. data/config/initializers/seeds.rb +5 -0
  116. data/config/initializers/workarea.rb +15 -0
  117. data/config/locales/en.yml +244 -0
  118. data/config/routes.rb +49 -0
  119. data/data/blog_thumbnails/thumbnail_1.png +0 -0
  120. data/data/blog_thumbnails/thumbnail_2.png +0 -0
  121. data/data/blog_thumbnails/thumbnail_3.png +0 -0
  122. data/lib/tasks/import_wordpress.rake +13 -0
  123. data/lib/tasks/import_wordpress_attachments.rake +18 -0
  124. data/lib/tasks/import_wordpress_pages.rake +21 -0
  125. data/lib/tasks/import_wordpress_posts.rake +25 -0
  126. data/lib/workarea/blog/engine.rb +8 -0
  127. data/lib/workarea/blog/import/wordpress/attachment.rb +40 -0
  128. data/lib/workarea/blog/import/wordpress/content_cleaner.rb +64 -0
  129. data/lib/workarea/blog/import/wordpress/entry.rb +76 -0
  130. data/lib/workarea/blog/import/wordpress/entry_parser.rb +64 -0
  131. data/lib/workarea/blog/import/wordpress/page.rb +69 -0
  132. data/lib/workarea/blog/import/wordpress/page_parser.rb +50 -0
  133. data/lib/workarea/blog/version.rb +5 -0
  134. data/lib/workarea/blog.rb +11 -0
  135. data/test/dummy/Rakefile +6 -0
  136. data/test/dummy/app/assets/config/manifest.js +4 -0
  137. data/test/dummy/app/assets/images/.keep +0 -0
  138. data/test/dummy/app/assets/javascripts/application.js +13 -0
  139. data/test/dummy/app/assets/stylesheets/application.css +15 -0
  140. data/test/dummy/app/controllers/application_controller.rb +3 -0
  141. data/test/dummy/app/controllers/concerns/.keep +0 -0
  142. data/test/dummy/app/helpers/application_helper.rb +2 -0
  143. data/test/dummy/app/jobs/application_job.rb +2 -0
  144. data/test/dummy/app/mailers/application_mailer.rb +4 -0
  145. data/test/dummy/app/models/concerns/.keep +0 -0
  146. data/test/dummy/app/views/layouts/application.html.erb +14 -0
  147. data/test/dummy/app/views/layouts/mailer.html.erb +13 -0
  148. data/test/dummy/app/views/layouts/mailer.text.erb +1 -0
  149. data/test/dummy/bin/bundle +3 -0
  150. data/test/dummy/bin/rails +4 -0
  151. data/test/dummy/bin/rake +4 -0
  152. data/test/dummy/bin/setup +34 -0
  153. data/test/dummy/bin/update +29 -0
  154. data/test/dummy/config/application.rb +26 -0
  155. data/test/dummy/config/boot.rb +5 -0
  156. data/test/dummy/config/cable.yml +9 -0
  157. data/test/dummy/config/environment.rb +5 -0
  158. data/test/dummy/config/environments/development.rb +59 -0
  159. data/test/dummy/config/environments/production.rb +86 -0
  160. data/test/dummy/config/environments/test.rb +43 -0
  161. data/test/dummy/config/initializers/application_controller_renderer.rb +6 -0
  162. data/test/dummy/config/initializers/assets.rb +11 -0
  163. data/test/dummy/config/initializers/backtrace_silencers.rb +7 -0
  164. data/test/dummy/config/initializers/cookies_serializer.rb +5 -0
  165. data/test/dummy/config/initializers/filter_parameter_logging.rb +4 -0
  166. data/test/dummy/config/initializers/inflections.rb +16 -0
  167. data/test/dummy/config/initializers/mime_types.rb +4 -0
  168. data/test/dummy/config/initializers/new_framework_defaults.rb +18 -0
  169. data/test/dummy/config/initializers/session_store.rb +3 -0
  170. data/test/dummy/config/initializers/workarea.rb +3 -0
  171. data/test/dummy/config/initializers/wrap_parameters.rb +14 -0
  172. data/test/dummy/config/locales/en.yml +23 -0
  173. data/test/dummy/config/puma.rb +47 -0
  174. data/test/dummy/config/routes.rb +5 -0
  175. data/test/dummy/config/secrets.yml +22 -0
  176. data/test/dummy/config/spring.rb +6 -0
  177. data/test/dummy/config.ru +5 -0
  178. data/test/dummy/db/seeds.rb +2 -0
  179. data/test/dummy/lib/assets/.keep +0 -0
  180. data/test/dummy/log/.keep +0 -0
  181. data/test/factories/blog.rb +33 -0
  182. data/test/factories/wordpress_import.rb +17 -0
  183. data/test/fixtures/test_wordpress.xml +493 -0
  184. data/test/integration/workarea/blog/admin_integration_test.rb +55 -0
  185. data/test/integration/workarea/blog/create_blog_entries_integration_test.rb +106 -0
  186. data/test/integration/workarea/blog/storefront_integration_test.rb +112 -0
  187. data/test/integration/workarea/blog/wordpress_import_integration_test.rb +26 -0
  188. data/test/lib/workarea/blog/import/wordpress/attachment_test.rb +20 -0
  189. data/test/lib/workarea/blog/import/wordpress/content_cleaner_test.rb +65 -0
  190. data/test/lib/workarea/blog/import/wordpress/entry_parser_test.rb +42 -0
  191. data/test/lib/workarea/blog/import/wordpress/entry_test.rb +61 -0
  192. data/test/lib/workarea/blog/import/wordpress/page_parser_test.rb +35 -0
  193. data/test/lib/workarea/blog/import/wordpress/page_test.rb +52 -0
  194. data/test/models/workarea/content/blog_comment_test.rb +57 -0
  195. data/test/models/workarea/content/blog_entry_test.rb +17 -0
  196. data/test/queries/workarea/metadata/content_blog_entry_test.rb +36 -0
  197. data/test/queries/workarea/metadata/content_blog_test.rb +36 -0
  198. data/test/support/workarea/blog/stub_wordpress_assets.rb +19 -0
  199. data/test/system/workarea/admin/blog_entries_system_test.rb +103 -0
  200. data/test/system/workarea/admin/blog_system_test.rb +93 -0
  201. data/test/system/workarea/admin/blog_taxonomy_system_test.rb +21 -0
  202. data/test/system/workarea/admin/blog_user_comments_system_test.rb +138 -0
  203. data/test/system/workarea/storefront/blog_content_block_system_test.rb +36 -0
  204. data/test/system/workarea/storefront/blog_system_test.rb +256 -0
  205. data/test/test_helper.rb +9 -0
  206. data/test/view_models/workarea/admin/blog_comments_view_model_test.rb +77 -0
  207. data/test/view_models/workarea/admin/blog_entries_view_model_test.rb +36 -0
  208. data/test/view_models/workarea/storefront/blog_entry_content_block_view_model_test.rb +100 -0
  209. data/test/view_models/workarea/storefront/blog_entry_view_model_test.rb +47 -0
  210. data/test/view_models/workarea/storefront/blog_view_model_test.rb +149 -0
  211. data/test/workers/workarea/generate_content_blog_metadata_test.rb +18 -0
  212. data/workarea-blog.gemspec +19 -0
  213. metadata +274 -0
@@ -0,0 +1,56 @@
1
+ module Workarea
2
+ module Admin
3
+ class ContentBlogsController < Admin::ApplicationController
4
+ required_permissions :marketing
5
+ before_action :find_blog, except: :index
6
+
7
+ def index
8
+ search = Search::AdminBlogs.new(
9
+ params.merge(autocomplete: request.xhr?)
10
+ )
11
+ @search = BlogSearchViewModel.new(search, params)
12
+ end
13
+
14
+ def show; end
15
+
16
+ def create
17
+ if @blog.save
18
+ flash[:success] = 'Blog has been created'
19
+ redirect_to edit_content_blog_path(@blog)
20
+ else
21
+ render :new
22
+ end
23
+ end
24
+
25
+ def update
26
+ if @blog.update_attributes(blog_params)
27
+ flash[:success] = 'Blog has been updated'
28
+ redirect_to edit_content_blog_path(@blog)
29
+ else
30
+ render :edit
31
+ end
32
+ end
33
+
34
+ def destroy
35
+ @blog.destroy
36
+ flash[:success] = 'This blog has been removed'
37
+ redirect_to content_blogs_path
38
+ end
39
+
40
+ private
41
+
42
+ def find_blog
43
+ @blog = if params[:id].present?
44
+ BlogViewModel.new(Workarea::Content::Blog.find_by(slug: params[:id]))
45
+ else
46
+ BlogViewModel.new(Workarea::Content::Blog.new(blog_params))
47
+ end
48
+ end
49
+
50
+ def blog_params
51
+ return {} unless params[:blog].present?
52
+ params[:blog].permit(:name, :slug, :navigation)
53
+ end
54
+ end
55
+ end
56
+ end
@@ -0,0 +1,69 @@
1
+ module Workarea
2
+ module Admin
3
+ class CreateContentBlogEntriesController < Admin::ApplicationController
4
+ required_permissions :marketing
5
+ before_action :find_blog_entry
6
+
7
+ def new
8
+ @blog = Admin::BlogViewModel.new(Workarea::Content::Blog.find_by(slug: params[:content_blog_id]))
9
+ render :setup
10
+ end
11
+
12
+ def create
13
+ @blog_entry.attributes = params[:blog_entry]
14
+
15
+ if @blog_entry.save
16
+ flash[:success] = t('workarea.admin.create_content_blog_entries.flash_messages.blog_entry_created')
17
+ redirect_to thumbnail_image_create_content_blog_entry_path(@blog_entry)
18
+ else
19
+ render :setup, status: :unprocessable_entity
20
+ end
21
+ end
22
+
23
+ def thumbnail_image
24
+ render :thumbnail_image
25
+ end
26
+
27
+ def save_thumbnail_image
28
+ @blog_entry.update_attributes(params[:blog_entry])
29
+ redirect_to content_create_content_blog_entry_path(@blog_entry)
30
+ end
31
+
32
+ def content
33
+ model = Content.for(@blog_entry.model)
34
+ @content = Admin::ContentViewModel.new(model, view_model_options)
35
+ end
36
+
37
+ def featured_products
38
+ search = Search::AdminProducts.new(view_model_options)
39
+ @search = SearchViewModel.new(search, view_model_options)
40
+ end
41
+
42
+ def publish; end
43
+
44
+ def save_publish
45
+ publish = SavePublishing.new(@blog_entry, params)
46
+
47
+ if publish.perform
48
+ flash[:success] = t('workarea.admin.create_content_blog_entries.flash_messages.blog_entry_created')
49
+ redirect_to content_blog_entry_path(@blog_entry)
50
+ else
51
+ flash[:error] = publish.errors.full_messages
52
+ render :publish
53
+ end
54
+ end
55
+
56
+ private
57
+
58
+ def find_blog_entry
59
+ model = if params[:id].present?
60
+ Content::BlogEntry.find_by(slug: params[:id])
61
+ else
62
+ Content::BlogEntry.new(blog_id: params[:content_blog_id])
63
+ end
64
+
65
+ @blog_entry = Admin::BlogEntryViewModel.new(model, view_model_options)
66
+ end
67
+ end
68
+ end
69
+ end
@@ -0,0 +1,14 @@
1
+ module Workarea
2
+ module Storefront
3
+ class BlogCommentsController < Storefront::ApplicationController
4
+ def index
5
+ @entry = Storefront::BlogEntryViewModel.new(
6
+ Content::BlogEntry.find_by(slug: params[:blog_entry_id]),
7
+ view_model_options
8
+ )
9
+
10
+ @comment = @entry.comments.build
11
+ end
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,48 @@
1
+ module Workarea
2
+ module Storefront
3
+ class BlogEntriesController < Storefront::ApplicationController
4
+ before_action :cache_page, only: :show
5
+ before_action :require_login, only: :add_comment
6
+
7
+ def show
8
+ model = Content::BlogEntry.find_by(slug: params[:id])
9
+ raise InvalidDisplay unless model.active?
10
+
11
+ @entry = Storefront::BlogEntryViewModel.new(model, view_model_options)
12
+ end
13
+
14
+ def add_comment
15
+ model = Content::BlogEntry.find_by(slug: params[:blog_entry_id])
16
+ @entry = Storefront::BlogEntryViewModel.new(model, view_model_options)
17
+
18
+ if current_user.public_info.blank?
19
+ if params[:first_name].blank? || params[:last_name].blank?
20
+ flash[:error] = 'First and last name are required'
21
+ render(:show) && return
22
+ else
23
+ current_user.update_attributes(params.permit(:first_name, :last_name))
24
+ end
25
+ end
26
+
27
+ @comment = model.comments.build(comment_params)
28
+
29
+ if @comment.save
30
+ flash[:success] = 'Your comment has been submitted. Thanks!'
31
+ redirect_to blog_entry_path(@entry)
32
+ else
33
+ flash[:error] = 'There was a problem saving your comment.'
34
+ render :show
35
+ end
36
+ end
37
+
38
+ private
39
+
40
+ def comment_params
41
+ params.permit(:body).merge(
42
+ user_id: current_user.id,
43
+ user_info: current_user.public_info
44
+ )
45
+ end
46
+ end
47
+ end
48
+ end
@@ -0,0 +1,19 @@
1
+ module Workarea
2
+ module Storefront
3
+ class BlogsController < Storefront::ApplicationController
4
+ before_action :cache_page
5
+
6
+ def index
7
+ blogs = Workarea::Content::Blog.all.map do |blog|
8
+ Storefront::BlogViewModel.new(blog, view_model_options)
9
+ end
10
+ @blog_index = Storefront::BlogIndexViewModel.new(blogs, view_model_options)
11
+ end
12
+
13
+ def show
14
+ model = Content::Blog.find_by(slug: params[:id])
15
+ @blog = Storefront::BlogViewModel.new(model, view_model_options)
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,61 @@
1
+ module Workarea
2
+ module Admin
3
+ module BlogsHelper
4
+ def navigable_types
5
+ super + [
6
+ [
7
+ t('workarea.admin.navigation_taxons.types.blog'),
8
+ 'blog',
9
+ { data: { new_navigation_taxon_endpoint: content_blogs_path } }
10
+ ],
11
+ [
12
+ t('workarea.admin.navigation_taxons.types.blog_entry'),
13
+ 'blog_entry',
14
+ { data: { new_navigation_taxon_endpoint: content_blog_entries_path } }
15
+ ]
16
+ ]
17
+ end
18
+
19
+ def taxon_icon(taxon, options = {})
20
+ if taxon.resource_name.blog?
21
+ inline_svg('workarea/admin/blog/icons/blog.svg', options)
22
+ elsif taxon.resource_name.blog_entry?
23
+ inline_svg('workarea/admin/blog/icons/blog_entry.svg', options)
24
+ else
25
+ super
26
+ end
27
+ end
28
+
29
+ def options_for_blogs(blog_id)
30
+ return nil unless blog_id.present?
31
+
32
+ model = Content::Blog.find(blog_id)
33
+ options_for_select({ model.name => model.id }, model.id)
34
+ end
35
+
36
+ def options_for_blog_entries(entry_ids)
37
+ return nil unless entry_ids.present?
38
+
39
+ entries = Content::BlogEntry.in(id: entry_ids)
40
+ options_from_collection_for_select(entries, 'id', 'name', entry_ids)
41
+ end
42
+
43
+ def storefront_content_preview_path(content)
44
+ without_blog = super
45
+ if without_blog.present?
46
+ without_blog
47
+ elsif content.contentable.is_a?(Content::Blog)
48
+ storefront.blog_path(content.contentable, draft_id: content.id)
49
+ end
50
+ end
51
+
52
+ def linkable_types
53
+ super << [
54
+ 'Blog',
55
+ 'blog',
56
+ { data: { new_navigation_link_endpoint: content_blogs_path(format: 'json') } }
57
+ ]
58
+ end
59
+ end
60
+ end
61
+ end
@@ -0,0 +1,26 @@
1
+ module Workarea
2
+ class Content::Blog
3
+ include ApplicationDocument
4
+ include Navigable
5
+ include Contentable
6
+ include Workarea::Releasable
7
+ include Commentable
8
+
9
+ field :name, type: String, localize: true
10
+ field :navigation, type: String
11
+
12
+ has_many :entries,
13
+ dependent: :destroy,
14
+ class_name: 'Workarea::Content::BlogEntry'
15
+
16
+ validates :name, presence: true
17
+
18
+ def tags
19
+ if entries.any?
20
+ entries.all_tags.map { |t| t[:name] }
21
+ else
22
+ []
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,67 @@
1
+ module Workarea
2
+ class Content::BlogComment
3
+ include ApplicationDocument
4
+
5
+ field :user_id, type: String
6
+ field :user_info, type: String
7
+ field :body, type: String
8
+ field :pending, type: Boolean, default: true
9
+ field :approved, type: Boolean, default: false
10
+
11
+ index(pending: 1)
12
+
13
+ validates :user_id, presence: true
14
+ validates :body, length: 10..500
15
+
16
+ belongs_to :entry,
17
+ class_name: 'Workarea::Content::BlogEntry',
18
+ inverse_of: :comments,
19
+ index: true
20
+
21
+ scope :approved, -> { where(approved: true, pending: false) }
22
+ scope :pending, -> { where(pending: true) }
23
+
24
+ delegate :blog, to: :entry
25
+ delegate :name, to: :entry, prefix: true
26
+ delegate :name, to: :blog, prefix: true
27
+
28
+ def self.sorts
29
+ [Sort.newest].tap do |sorts|
30
+ sorts.unshift Sort.pending if pending.any?
31
+ end
32
+ end
33
+
34
+ def save(*)
35
+ super.tap do |result|
36
+ update_count(result) if result
37
+ end
38
+ end
39
+
40
+ def destroy(*)
41
+ super.tap do |result|
42
+ update_count(result) if result
43
+ end
44
+ end
45
+
46
+ def approved=(*)
47
+ super.tap do
48
+ self.pending = false
49
+ end
50
+ end
51
+
52
+ def author
53
+ return @author if defined?(@author)
54
+
55
+ @author = if model = User.where(id: user_id).first
56
+ Workarea::Admin::UserViewModel.new(model)
57
+ end
58
+ end
59
+
60
+ private
61
+
62
+ def update_count(_result)
63
+ count = entry.comments.approved.count
64
+ entry.set(comment_count: count)
65
+ end
66
+ end
67
+ end
@@ -0,0 +1,35 @@
1
+ module Workarea
2
+ class Content::BlogEntry
3
+ include ApplicationDocument
4
+ include Mongoid::Document::Taggable
5
+ include Navigable
6
+ include Contentable
7
+ include FeaturedProducts
8
+ include Workarea::Releasable
9
+
10
+ field :name, type: String, localize: true
11
+ field :author, type: String
12
+ field :summary, type: String
13
+ field :comment_count, type: Integer, default: 0
14
+ field :featured, type: Boolean, default: false
15
+ field :written_at, type: DateTime, default: -> { Time.now }
16
+ field :thumbnail_image, type: String
17
+
18
+ belongs_to :blog,
19
+ class_name: 'Workarea::Content::Blog',
20
+ index: true
21
+
22
+ has_many :comments,
23
+ class_name: 'Workarea::Content::BlogComment',
24
+ inverse_of: :entry
25
+
26
+ validates :name, presence: true
27
+ validates :author, presence: true
28
+
29
+ scope :newest, -> { desc(:updated_at) }
30
+
31
+ def has_thumbnail_image?
32
+ thumbnail_image.present?
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,11 @@
1
+ module Workarea
2
+ class Content
3
+ module Fields
4
+ class BlogEntryId < Field
5
+ def typecast(value)
6
+ Array(value).map(&:to_s)
7
+ end
8
+ end
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,8 @@
1
+ module Workarea
2
+ class Content
3
+ module Fields
4
+ class BlogId < Field
5
+ end
6
+ end
7
+ end
8
+ end
@@ -0,0 +1,27 @@
1
+ module Workarea
2
+ module Search
3
+ class Admin
4
+ class ContentBlog < Search::Admin
5
+ def type
6
+ 'blog'
7
+ end
8
+
9
+ def status
10
+ 'active'
11
+ end
12
+
13
+ def jump_to_text
14
+ model.name
15
+ end
16
+
17
+ def jump_to_position
18
+ 6
19
+ end
20
+
21
+ def search_text
22
+ ['blog', model.name, model.entries.map(&:name)].flatten.join(' ')
23
+ end
24
+ end
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,37 @@
1
+ module Workarea
2
+ module Search
3
+ class Admin
4
+ class ContentBlogEntry < Search::Admin
5
+ include Admin::Releasable
6
+
7
+ def type
8
+ 'blog_entry'
9
+ end
10
+
11
+ def status
12
+ if model.active?
13
+ 'active'
14
+ else
15
+ 'inactive'
16
+ end
17
+ end
18
+
19
+ def facets
20
+ super.merge(blog_id: model.blog_id)
21
+ end
22
+
23
+ def jump_to_text
24
+ model.name
25
+ end
26
+
27
+ def jump_to_position
28
+ 7
29
+ end
30
+
31
+ def search_text
32
+ ['blog entry', model.name].flatten.join(' ')
33
+ end
34
+ end
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,6 @@
1
+ module Workarea
2
+ class Metadata
3
+ class ContentBlog < ContentPage
4
+ end
5
+ end
6
+ end
@@ -0,0 +1,6 @@
1
+ module Workarea
2
+ class Metadata
3
+ class ContentBlogEntry < ContentPage
4
+ end
5
+ end
6
+ end
@@ -0,0 +1,24 @@
1
+ module Workarea
2
+ module Search
3
+ class AdminBlogEntries
4
+ include Query
5
+ include AdminIndexSearch
6
+ include AdminSorting
7
+ include Pagination
8
+
9
+ document Search::Admin
10
+
11
+ def initialize(params = {})
12
+ super(params.merge(type: 'blog_entry'))
13
+ end
14
+
15
+ def facets
16
+ super + [TermsFacet.new(self, 'blog_id')]
17
+ end
18
+
19
+ def displayed_facets
20
+ facets.reject { |facet| facet.useless? || facet.name == 'blog_id' }
21
+ end
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,20 @@
1
+ module Workarea
2
+ module Search
3
+ class AdminBlogs
4
+ include Query
5
+ include AdminIndexSearch
6
+ include AdminSorting
7
+ include Pagination
8
+
9
+ document Search::Admin
10
+
11
+ def initialize(params = {})
12
+ super(params.merge(type: 'blog'))
13
+ end
14
+
15
+ def facets
16
+ super + [TermsFacet.new(self, 'issues')]
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,26 @@
1
+ module Workarea
2
+ class BlogCommentSeeds
3
+ def perform
4
+ puts 'Adding blog comments...'
5
+
6
+ Sidekiq::Callbacks.disable do
7
+ Content::BlogEntry.all.each do |entry|
8
+ 3.times do |_i|
9
+ user = Workarea::User.sample
10
+
11
+ comment = Content::BlogComment.create!(
12
+ user_id: user.id,
13
+ user_info: user.public_info,
14
+ body: Faker::Hipster.paragraph,
15
+ entry: entry,
16
+ pending: false,
17
+ approved: true
18
+ )
19
+
20
+ comment.save!
21
+ end
22
+ end
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,73 @@
1
+ module Workarea
2
+ class BlogEntrySeeds
3
+ def perform
4
+ puts 'Adding blog entries...'
5
+
6
+ Sidekiq::Callbacks.disable do
7
+ Content::Blog.all.each_with_index do |blog, blog_index|
8
+ 10.times do |entry_index|
9
+ entry = Content::BlogEntry.create!(
10
+ name: entry_titles[blog_index][entry_index],
11
+ summary: Faker::Hipster.paragraph,
12
+ author: Faker::Book.author,
13
+ # thumbnail_image: blog_thumbnail(entry_index),
14
+ tags: Faker::Hipster.words(3),
15
+ blog_id: blog.id
16
+ )
17
+
18
+ content = Content.for(entry)
19
+
20
+ content.blocks.create!(
21
+ area: 'blog_content',
22
+ type: 'text',
23
+ data: {
24
+ text: Faker::Hipster.paragraph(4)
25
+ }
26
+ )
27
+
28
+ entry.save!
29
+ end
30
+ end
31
+ end
32
+ end
33
+
34
+ def blog_thumbnail(entry_index)
35
+ thumbnail_dir = "#{Workarea::Blog::Engine.root}/data/blog_thumbnails"
36
+ thumbnail_count = Dir["#{thumbnail_dir}/*"].length
37
+ thumbnail_num = rand(thumbnail_count + 1)
38
+
39
+ File.new("#{thumbnail_dir}/thumbnail_#{thumbnail_num}.png") if thumbnail_num.nonzero?
40
+ end
41
+
42
+ private
43
+
44
+ def entry_titles
45
+ [
46
+ [
47
+ '3 Hot Fashion Tips For Fall',
48
+ '1 Neat Trick To Keep Your Look Fresh',
49
+ 'How To Dress Up A Pair Of Boots',
50
+ 'How To Tell If Your Shirt Is On Backwards',
51
+ 'No-Nonsense Nautical Style',
52
+ 'Rules For Wearing White After Labor Day',
53
+ 'Insane Fashion Tips For Millenials',
54
+ 'Signs You Might Need A New Pair Of Pants',
55
+ 'Ultimate Guide To Hats',
56
+ 'Hack Your Wardrobe'
57
+ ],
58
+ [
59
+ 'The Secret of Fashion',
60
+ '0 Tips That Will Make You Influential In Fashion',
61
+ 'How To Lose Money With Fashion',
62
+ 'The A - Z Guide Of Fashion',
63
+ 'Old School Fashion',
64
+ 'Fashion Strategies For Beginners',
65
+ '9 Ridiculous Rules About couture',
66
+ 'The Modern Rules Of Couture',
67
+ 'Five Items You Should Have In Your Wardrobe',
68
+ 'The 7 Secrets That You Shouldn\'t Know About Dresses'
69
+ ]
70
+ ]
71
+ end
72
+ end
73
+ end