workarea-blog 3.4.7

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 (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