spina-admin-conferences-blog 0.1.4 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (60) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +11 -0
  3. data/app/controllers/spina/admin/conferences/blog/categories_controller.rb +5 -4
  4. data/app/controllers/spina/admin/conferences/blog/posts_controller.rb +4 -4
  5. data/app/views/layouts/default/application.html.erb +1 -0
  6. data/app/views/spina/admin/conferences/blog/categories/_category.html.erb +13 -0
  7. data/app/views/spina/admin/conferences/blog/categories/_form.html.erb +38 -0
  8. data/app/views/spina/admin/conferences/blog/categories/edit.html.erb +1 -0
  9. data/app/views/spina/admin/conferences/blog/categories/index.html.erb +19 -0
  10. data/app/views/spina/admin/conferences/blog/categories/new.html.erb +1 -0
  11. data/app/views/spina/admin/conferences/blog/posts/_form.html.erb +66 -0
  12. data/app/views/spina/admin/conferences/blog/posts/_form_post_configuration.html.erb +46 -0
  13. data/app/views/spina/admin/conferences/blog/posts/_form_post_content.html.erb +59 -0
  14. data/app/views/spina/admin/conferences/blog/posts/_form_post_seo.html.erb +7 -0
  15. data/app/views/spina/admin/conferences/blog/posts/_post.html.erb +30 -0
  16. data/app/views/spina/admin/conferences/blog/posts/edit.html.erb +1 -0
  17. data/app/views/spina/admin/conferences/blog/posts/index.html.erb +33 -0
  18. data/app/views/spina/admin/conferences/blog/posts/new.html.erb +1 -0
  19. data/app/views/spina/admin/hooks/conferences/blog/_primary_navigation.html.erb +14 -0
  20. data/config/locales/en.yml +7 -0
  21. data/config/locales/nl.yml +7 -0
  22. data/config/locales/pt-BR.yml +7 -0
  23. data/lib/spina/admin/conferences/blog/engine.rb +4 -1
  24. data/lib/spina/admin/conferences/blog/version.rb +1 -1
  25. data/spec/controllers/spina/admin/conferences/blog/categories_controller_spec.rb +1 -0
  26. data/spec/controllers/spina/admin/conferences/blog/posts_controller_spec.rb +1 -0
  27. data/spec/dummy/app/assets/config/manifest.js +2 -1
  28. data/spec/dummy/app/assets/stylesheets/default/{application.css.sass → application.css} +0 -0
  29. data/spec/dummy/config/environments/development.rb +3 -0
  30. data/spec/dummy/config/environments/test.rb +4 -0
  31. data/spec/dummy/config/initializers/mobility.rb +1 -0
  32. data/spec/dummy/config/storage.yml +7 -0
  33. data/spec/dummy/db/migrate/20210403091403_add_url_title_to_spina_page_translations.spina.rb +6 -0
  34. data/spec/dummy/db/migrate/20210403091404_add_json_attributes_to_spina_accounts.spina.rb +6 -0
  35. data/spec/dummy/db/migrate/20210403091405_add_json_attributes_to_spina_pages.spina.rb +6 -0
  36. data/spec/dummy/db/migrate/20210403091406_add_slug_to_spina_resources.spina.rb +6 -0
  37. data/spec/dummy/db/migrate/20210404093002_create_active_storage_tables.active_storage.rb +36 -0
  38. data/spec/dummy/db/schema.rb +35 -1
  39. data/spec/factories/spina/admin/conferences/blog/posts.rb +1 -0
  40. data/spec/factories/spina/users.rb +10 -0
  41. data/spec/support/controller_helpers.rb +4 -3
  42. data/spec/support/system_tests.rb +1 -1
  43. data/spec/system/spina/admin/conferences/blog/posts_spec.rb +5 -7
  44. metadata +134 -117
  45. data/app/views/layouts/spina/admin/conferences/blog/blog.html.haml +0 -29
  46. data/app/views/layouts/spina/admin/conferences/blog/categories.html.haml +0 -10
  47. data/app/views/spina/admin/conferences/blog/categories/_category.html.haml +0 -8
  48. data/app/views/spina/admin/conferences/blog/categories/_form.html.haml +0 -42
  49. data/app/views/spina/admin/conferences/blog/categories/edit.html.haml +0 -3
  50. data/app/views/spina/admin/conferences/blog/categories/index.html.haml +0 -23
  51. data/app/views/spina/admin/conferences/blog/categories/new.html.haml +0 -2
  52. data/app/views/spina/admin/conferences/blog/posts/_form.html.haml +0 -43
  53. data/app/views/spina/admin/conferences/blog/posts/_form_post_configuration.html.haml +0 -50
  54. data/app/views/spina/admin/conferences/blog/posts/_form_post_content.html.haml +0 -46
  55. data/app/views/spina/admin/conferences/blog/posts/_form_post_seo.html.haml +0 -14
  56. data/app/views/spina/admin/conferences/blog/posts/_post.html.haml +0 -15
  57. data/app/views/spina/admin/conferences/blog/posts/edit.html.haml +0 -3
  58. data/app/views/spina/admin/conferences/blog/posts/index.html.haml +0 -23
  59. data/app/views/spina/admin/conferences/blog/posts/new.html.haml +0 -2
  60. data/app/views/spina/admin/hooks/conferences/blog/_primary_navigation.html.haml +0 -10
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 32a1cc07daafacb1eb7344c1d35d4be93339ea5b0156440cf7404c086175ac14
4
- data.tar.gz: 848dc6793b90832804748ad0328956e13bc5629c81afe405e6f67196c1985185
3
+ metadata.gz: 56f5087c62079b206816f460255574064b89f79066de8bffd15f4b0cb4021a71
4
+ data.tar.gz: 21cdedbf64861cfcb2302db194e3167127752df667d48aa8a649ad0adef0bd6b
5
5
  SHA512:
6
- metadata.gz: be8428d166b4e9b753ca2279813545c08065827c3f4972621ef449ee6fc6195df5eeb18928ee9fb66401b04c7147df9bc81450800f43993301c9bd34ff1e71e1
7
- data.tar.gz: 9325413c57ba96711b3c3b84d61d45a89334c5adf007862c250e92a712fa1a7f280b4f38bcfb55f8e8a0732d072de45668f039130683cc0042e4260137f7c377
6
+ metadata.gz: f8026cd8ee752dec7244eee77d324182985216a4c8763d0a795275a500c722a8359d618f0db60da1e16b49a22fd3449bbac43479653279aba56466f57d492549
7
+ data.tar.gz: 4f1deafa6264a4dde45fb3b869d53e5d207c745928bff253335f4fd528517015f51ea863fca1c444af4f94a37678166af0ea030556d5e838cf650e4d7dbedd44
data/README.md CHANGED
@@ -28,6 +28,17 @@ Or install it yourself as:
28
28
  $ gem install spina-blog
29
29
  ```
30
30
 
31
+ Add to your Spina theme:
32
+ ```ruby
33
+ # config/initializers/themes/theme.rb
34
+
35
+ Spina::Theme.register do |theme|
36
+ # ...
37
+ theme.plugins = ['blog']
38
+ end
39
+
40
+ ```
41
+
31
42
  ## Contributing
32
43
  The version of Spina to develop this engine against is defined in the gemspec. To override the version of refinery to develop against, edit the project Gemfile to point to a local path containing a clone of Spina CMS.
33
44
 
@@ -8,11 +8,11 @@ module Spina
8
8
  before_action :category, except: %i[new create index]
9
9
  before_action :set_breadcrumb
10
10
  before_action :set_locale
11
+
12
+ admin_section :blog
11
13
 
12
14
  decorates_assigned :category
13
15
 
14
- layout 'spina/admin/conferences/blog/categories'
15
-
16
16
  def index
17
17
  @categories = Spina::Admin::Conferences::Blog::Category.order(:name)
18
18
  end
@@ -30,7 +30,7 @@ module Spina
30
30
  notice: t('spina.blog.categories.saved')
31
31
  else
32
32
  add_breadcrumb I18n.t('spina.blog.categories.new')
33
- render :new, layout: 'spina/admin/admin'
33
+ render :new, status: :unprocessable_entity
34
34
  end
35
35
  end
36
36
 
@@ -40,13 +40,14 @@ module Spina
40
40
  end
41
41
 
42
42
  def update
43
+ add_breadcrumb @category.name
43
44
  if @category.update(category_params)
44
45
  add_breadcrumb @category.name
45
46
  redirect_to spina.edit_admin_conferences_blog_category_url(
46
47
  @category.id, params: { locale: @locale }
47
48
  ), notice: t('spina.blog.categories.saved')
48
49
  else
49
- render :edit, layout: 'spina/admin/admin'
50
+ render :edit, status: :unprocessable_entity
50
51
  end
51
52
  end
52
53
 
@@ -9,11 +9,11 @@ module Spina
9
9
  before_action :set_breadcrumb
10
10
  before_action :set_tabs, only: %i[new create edit update]
11
11
  before_action :set_locale
12
+
13
+ admin_section :blog
12
14
 
13
15
  decorates_assigned :post
14
16
 
15
- layout 'spina/admin/conferences/blog/blog'
16
-
17
17
  def index
18
18
  @posts = Spina::Admin::Conferences::Blog::Post.order(created_at: :desc)
19
19
  end
@@ -46,7 +46,7 @@ module Spina
46
46
  notice: t('spina.blog.posts.saved')
47
47
  else
48
48
  add_breadcrumb I18n.t('spina.blog.posts.new')
49
- render :new, layout: 'spina/admin/admin'
49
+ render :new, status: :unprocessable_entity
50
50
  end
51
51
  end
52
52
 
@@ -62,7 +62,7 @@ module Spina
62
62
  @post.id, params: { locale: @locale }
63
63
  ), notice: t('spina.blog.posts.saved')
64
64
  else
65
- render :edit, layout: 'spina/admin/admin'
65
+ render :edit, status: :unprocessable_entity
66
66
  end
67
67
  end
68
68
 
@@ -0,0 +1 @@
1
+ <%= yield %>
@@ -0,0 +1,13 @@
1
+ <div class="border-b border-gray-200 flex items-center justify-between space-x-8 pr-2">
2
+ <%= link_to spina.edit_admin_conferences_blog_category_path(category.id), class: 'block text-spina text-sm p-4 hover:text-spina-dark font-medium' do %>
3
+ <%= category.name %>
4
+ <% end %>
5
+
6
+ <div class="flex-1"></div>
7
+
8
+ <div>
9
+ <%= link_to spina.edit_admin_conferences_blog_category_path(category.id), class: "btn btn-default px-3" do %>
10
+ <%= heroicon('pencil', style: :solid, class: 'w-4 h-4') %>
11
+ <% end %>
12
+ </div>
13
+ </div>
@@ -0,0 +1,38 @@
1
+ <%= render Spina::UserInterface::HeaderComponent.new do |header| %>
2
+ <% header.actions do %>
3
+
4
+ <% if @category.persisted? %>
5
+ <!-- Translations -->
6
+ <%= render Spina::Pages::TranslationsComponent.new(@category, label: @locale.upcase) %>
7
+
8
+ <%= render Spina::UserInterface::DropdownComponent.new do |dropdown| %>
9
+ <% dropdown.button(classes: "btn btn-default px-3") do %>
10
+ <%= heroicon('dots-horizontal', style: :solid, class: "w-5 h-5 text-gray-600") %>
11
+ <% end %>
12
+
13
+ <% dropdown.menu do %>
14
+ <%= button_to t('spina.permanently_delete'), spina.admin_conferences_blog_category_path(@category.id), method: :delete, class: "block w-full text-left px-4 py-2 text-sm leading-5 font-medium text-red-500 cursor-pointer bg-white hover:bg-red-100 hover:bg-opacity-50 hover:text-red-500 focus:outline-none focus:bg-gray-100 focus:text-gray-900", form: {data: {controller: "confirm", confirm_message: t('spina.blog.categories.delete_confirmation', subject: @category.name)}} %>
15
+ <% end %>
16
+ <% end %>
17
+ <% end %>
18
+
19
+ <%= button_tag type: :submit, form: dom_id(@category), class: 'btn btn-primary', data: {controller: "button", action: "button#loading", loading_message: t('spina.ui.saving')} do %>
20
+ <%= heroicon('check', style: :solid, class: 'w-5 h-5 mr-1 -ml-2') %>
21
+ <%=t 'spina.blog.categories.save' %>
22
+ <% end %>
23
+ <% end %>
24
+ <% end %>
25
+
26
+ <div class="p-8">
27
+
28
+ <%= form_with model: @category, url: @category.new_record? ? spina.admin_conferences_blog_categories_path : spina.admin_conferences_blog_category_path(@category.id), id: dom_id(@category) do |f| %>
29
+ <%= hidden_field_tag :locale, @locale %>
30
+ <% Mobility.with_locale(@locale) do %>
31
+ <%= render Spina::Forms::GroupComponent.new(label: Spina::Admin::Conferences::Blog::Category.human_attribute_name(:name)) do %>
32
+ <%= render Spina::Forms::LabelComponent.new(f, :name) %>
33
+ <%= render Spina::Forms::TextFieldComponent.new(f, :name, autofocus: @category.name.blank?) %>
34
+ <% end %>
35
+ <% end %>
36
+ <% end %>
37
+
38
+ </div>
@@ -0,0 +1 @@
1
+ <%= render 'form' %>
@@ -0,0 +1,19 @@
1
+ <%= render Spina::UserInterface::HeaderComponent.new do |header| %>
2
+ <% header.after_breadcrumbs do %>
3
+ <%= link_to spina.new_admin_conferences_blog_category_path, class: 'btn btn-default h-8 px-2 ml-3' do %>
4
+ <%= heroicon('plus', style: :solid, class: 'w-6 h-6') %>
5
+ <% end %>
6
+ <% end %>
7
+ <% end %>
8
+
9
+ <div class="p-8">
10
+ <% if @categories.any? %>
11
+ <div class="shadow-sm border border-gray-200 bg-white rounded-lg">
12
+ <%= render partial: 'category', collection: @categories, as: :category %>
13
+ </div>
14
+ <% else %>
15
+ <div class="text-gray-700 italic">
16
+ There are no categories yet. Create your first one!
17
+ </div>
18
+ <% end %>
19
+ </div>
@@ -0,0 +1 @@
1
+ <%= render 'form' %>
@@ -0,0 +1,66 @@
1
+ <div data-controller="tabs" data-tabs-active="cursor-default text-gray-900 bg-spina-dark bg-opacity-10" data-tabs-inactive="cursor-pointer bg-transparent text-gray-400 border-transparent">
2
+ <%= render Spina::UserInterface::HeaderComponent.new do |header| %>
3
+ <% header.actions do %>
4
+
5
+ <% if @post.persisted? %>
6
+ <!-- Translations -->
7
+ <%= render Spina::Pages::TranslationsComponent.new(@post, label: @locale.upcase) %>
8
+
9
+ <%= render Spina::UserInterface::DropdownComponent.new do |dropdown| %>
10
+ <% dropdown.button(classes: "btn btn-default px-3") do %>
11
+ <%= heroicon('dots-horizontal', style: :solid, class: "w-5 h-5 text-gray-600") %>
12
+ <% end %>
13
+
14
+ <% dropdown.menu do %>
15
+ <%= button_to t('spina.permanently_delete'), spina.admin_conferences_blog_post_path(@post.id), method: :delete, class: "block w-full text-left px-4 py-2 text-sm leading-5 font-medium text-red-500 cursor-pointer bg-white hover:bg-red-100 hover:bg-opacity-50 hover:text-red-500 focus:outline-none focus:bg-gray-100 focus:text-gray-900", form: {data: {controller: "confirm", confirm_message: t('spina.blog.posts.delete_confirmation', subject: @post.title)}} %>
16
+ <% end %>
17
+ <% end %>
18
+ <% end %>
19
+
20
+ <%= button_tag type: :submit, form: dom_id(@post), class: 'btn btn-primary', data: {controller: "button", action: "button#loading", loading_message: t('spina.ui.saving')} do %>
21
+ <%= heroicon('check', style: :solid, class: 'w-5 h-5 mr-1 -ml-2') %>
22
+ <%=t 'spina.blog.posts.save' %>
23
+ <% end %>
24
+
25
+ <% end %>
26
+
27
+ <% header.navigation do %>
28
+ <nav class="-mb-3 mt-4">
29
+ <ul class="inline-flex w-auto rounded-md bg-white">
30
+ <% @tabs.each do |tab| %>
31
+ <button type="button" class="block px-3 leading-relaxed py-1 hover:text-gray-800 rounded-md text-gray-400 font-medium text-sm flex items-center whitespace-nowrap" data-action="tabs#show" data-tabs-target="button" data-pane-id="<%= tab %>">
32
+ <%= t("spina.blog.posts.#{tab}") %>
33
+ </button>
34
+ <% end %>
35
+ </ul>
36
+ </nav>
37
+ <% end %>
38
+ <% end %>
39
+
40
+ <div class="p-8">
41
+
42
+ <%= form_with model: @post, url: @post.new_record? ? spina.admin_conferences_blog_posts_path : spina.admin_conferences_blog_post_path(@post.id), id: dom_id(@post) do |f| %>
43
+ <%= hidden_field_tag :locale, @locale %>
44
+
45
+ <% if f.object.errors %>
46
+ <ul class="text-red-500 font-medium">
47
+ <% f.object.errors.full_messages.each do |message| %>
48
+ <li><%= message %></li>
49
+ <% end %>
50
+ </ul>
51
+ <% end %>
52
+
53
+ <% Mobility.with_locale(@locale) do %>
54
+
55
+ <% @tabs.each do |tab| %>
56
+ <div data-tabs-target="pane" id="<%= tab %>">
57
+ <%= render "form_#{tab}", f: f %>
58
+ </div>
59
+ <% end %>
60
+
61
+ <% end %>
62
+
63
+ <% end %>
64
+
65
+ </div>
66
+ </div>
@@ -0,0 +1,46 @@
1
+ <%= render Spina::Forms::GroupComponent.new(label: Spina::Admin::Conferences::Blog::Category.human_attribute_name(:category)) do %>
2
+ <%= render Spina::Forms::LabelComponent.new(f, :category) %>
3
+ <%= f.select :category_id, Spina::Admin::Conferences::Blog::Category.all.collect{|u| [u.name, u.id]}, {prompt: true}, class: 'form-select', data: {controller: "select-placeholder", action: "select-placeholder#update"} %>
4
+ <% end %>
5
+
6
+ <div class="border-t border-gray-200 my-6"></div>
7
+
8
+ <%= render Spina::Forms::GroupComponent.new(label: Spina::Admin::Conferences::Blog::Category.human_attribute_name(:draft), description: Spina::Admin::Conferences::Blog::Post.human_attribute_name(:draft_description)) do %>
9
+ <%= render Spina::Forms::LabelComponent.new(f, :draft) %>
10
+ <%= render Spina::Forms::SwitchComponent.new(f, :draft) %>
11
+ <% end %>
12
+
13
+ <div class="border-t border-gray-200 my-6"></div>
14
+
15
+ <%= render Spina::Forms::GroupComponent.new(label: Spina::Admin::Conferences::Blog::Category.human_attribute_name(:featured), description: Spina::Admin::Conferences::Blog::Post.human_attribute_name(:featured_description)) do %>
16
+ <%= render Spina::Forms::LabelComponent.new(f, :featured) %>
17
+ <%= render Spina::Forms::SwitchComponent.new(f, :featured) %>
18
+ <% end %>
19
+
20
+ <div class="border-t border-gray-200 my-6"></div>
21
+
22
+ <%= render Spina::Forms::GroupComponent.new(label: Spina::Admin::Conferences::Blog::Category.human_attribute_name(:slug), description: Spina::Admin::Conferences::Blog::Category.human_attribute_name(:slug_description)) do %>
23
+ <%= render Spina::Forms::LabelComponent.new(f, :slug) %>
24
+ <%= render Spina::Forms::TextFieldComponent.new(f, :slug) %>
25
+
26
+ <% if @post.slug %>
27
+ <div class="text-gray-400 text-xs mt-2">
28
+ Current permalink:
29
+ /blog/posts/<%= @post.slug %>
30
+ </div>
31
+ <% end %>
32
+ <% end %>
33
+
34
+ <div class="border-t border-gray-200 my-6"></div>
35
+
36
+ <%= render Spina::Forms::GroupComponent.new(label: Spina::Admin::Conferences::Blog::Category.human_attribute_name(:published_at)) do %>
37
+ <%= render Spina::Forms::LabelComponent.new(f, :published_at) %>
38
+ <%= render Spina::Forms::TextFieldComponent.new(f, :published_at) %>
39
+ <% end %>
40
+
41
+ <div class="border-t border-gray-200 my-6"></div>
42
+
43
+ <%= render Spina::Forms::GroupComponent.new(label: Spina::Admin::Conferences::Blog::Category.human_attribute_name(:spina_user)) do %>
44
+ <%= render Spina::Forms::LabelComponent.new(f, :spina_user) %>
45
+ <%= f.select :user_id, Spina::User.all.collect{|u| [u.name, u.id]}, {prompt: true}, class: 'form-select', data: {controller: "select-placeholder", action: "select-placeholder#update"} %>
46
+ <% end %>
@@ -0,0 +1,59 @@
1
+ <%= render Spina::Forms::LabelComponent.new(f, :title) %>
2
+ <%= render Spina::Forms::TextFieldComponent.new(f, :title, size: "lg", autofocus: f.object.title.blank?) %>
3
+
4
+ <div class="mt-6">
5
+ <%= render Spina::Forms::LabelComponent.new(f, :excerpt) %>
6
+
7
+ <div class="mt-1 relative">
8
+ <%= f.hidden_field :excerpt, id: "excerpt_input" %>
9
+
10
+ <div class="relative form-textarea p-4 shadow-sm max-w-5xl" data-controller="trix" id="insert_excerpt_trix-toolbar" data-action="media-picker:done->trix#insertAttachment">
11
+ <%= render Spina::Forms::TrixToolbarComponent.new("excerpt_trix-toolbar") %>
12
+
13
+ <trix-editor class="prose prose-sm focus:outline-none max-w-3xl xl:border-r border-dashed border-gray-200 pr-3" toolbar="excerpt_trix-toolbar" input="excerpt_input" data-trix-target="editor" data-action="trix-file-accept->trix#preventDefault"></trix-editor>
14
+ </div>
15
+ </div>
16
+ </div>
17
+
18
+ <div class="mt-6">
19
+ <%= render Spina::Forms::LabelComponent.new(f, :content) %>
20
+ <div class="mt-1 relative">
21
+
22
+ <%= f.hidden_field :content, id: "content_input" %>
23
+
24
+ <div class="relative form-textarea p-4 shadow-sm max-w-5xl" data-controller="trix" id="insert_content_trix-toolbar" data-action="media-picker:done->trix#insertAttachment">
25
+ <%= render Spina::Forms::TrixToolbarComponent.new("content_trix-toolbar") %>
26
+
27
+ <trix-editor class="prose prose-sm focus:outline-none max-w-3xl xl:border-r border-dashed border-gray-200 pr-3" toolbar="content_trix-toolbar" input="content_input" data-trix-target="editor" data-action="trix-file-accept->trix#preventDefault"></trix-editor>
28
+ </div>
29
+ </div>
30
+ </div>
31
+
32
+ <div class="mt-6 relative" data-controller="media-picker" id="<%= dom_id(f.object, f.object.object_id) %>" data-action="media-picker:done->media-picker#handleDone">
33
+ <label class="block text-sm leading-5 font-medium text-gray-700">
34
+ <%= Spina::Admin::Conferences::Blog::Post.human_attribute_name(:image) %>
35
+ </label>
36
+
37
+ <%= f.hidden_field :image_id, data: {media_picker_target: "imageId"} %>
38
+
39
+ <button class="absolute mt-3 ml-2 z-10 cursor-pointer flex items-center h-9 px-2 rounded-md bg-gray-700 bg-opacity-50 border-gray-300 active:shadow-inner text-gray-200 hover:text-white text-sm font-medium leading-none leading-none shadow-sm" data-action="media-picker#removeImage" data-media-picker-target="clearButton" type="button">
40
+ <svg class="w-5 h-5" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor">
41
+ <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 7l-.867 12.142A2 2 0 0116.138 21H7.862a2 2 0 01-1.995-1.858L5 7m5 4v6m4-6v6m1-10V4a1 1 0 00-1-1h-4a1 1 0 00-1 1v3M4 7h16" />
42
+ </svg>
43
+ </button>
44
+
45
+ <%= link_to spina.admin_media_picker_path(target: dom_id(f.object, f.object.object_id)), class: "block relative mt-1 w-full", data: {turbo_frame: "modal"} do %>
46
+ <div class="w-36 h-36 bg-transparent border-2 border-dashed border-gray-300 rounded-lg flex items-center flex-col justify-center">
47
+ <svg class="mx-auto h-12 w-12 text-gray-400" stroke="currentColor" fill="none" viewBox="0 0 48 48">
48
+ <path d="M28 8H12a4 4 0 00-4 4v20m32-12v8m0 0v8a4 4 0 01-4 4H12a4 4 0 01-4-4v-4m32-4l-3.172-3.172a4 4 0 00-5.656 0L28 28M8 32l9.172-9.172a4 4 0 015.656 0L28 28m0 0l4 4m4-24h8m-4-4v8m-12 4h.02" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" />
49
+ </svg>
50
+ <div class="text-gray-400 font-medium text-sm"><%=t 'spina.images.choose_image' %></div>
51
+ </div>
52
+
53
+ <div class="border absolute inset-0 w-36 h-36 bg-gray-100 rounded-lg shadow-md overflow-hidden" data-media-picker-target="thumbnail">
54
+ <% if f.object.image.present? %>
55
+ <%= image_tag thumbnail_url(f.object.image), class: 'object-contain h-36 w-full', data: {controller: "image-fade-in"} %>
56
+ <% end %>
57
+ </div>
58
+ <% end %>
59
+ </div>
@@ -0,0 +1,7 @@
1
+ <%= render Spina::Forms::GroupComponent.new(label: Spina::Admin::Conferences::Blog::Post.human_attribute_name(:seo_title), description: Spina::Admin::Conferences::Blog::Post.human_attribute_name(:description)) do %>
2
+ <%= render Spina::Forms::TextFieldComponent.new(f, :seo_title) %>
3
+
4
+ <div class="mt-5">
5
+ <%= render Spina::Forms::TextFieldComponent.new(f, :description) %>
6
+ </div>
7
+ <% end %>
@@ -0,0 +1,30 @@
1
+ <div class="border-b border-gray-200 flex items-center justify-between space-x-8 pr-2">
2
+
3
+ <%= link_to spina.edit_admin_conferences_blog_post_path(post.id), class: 'flex items-center text-spina text-sm p-4 hover:text-spina-dark font-medium' do %>
4
+ <% if post.featured? %>
5
+ <%= heroicon('star', style: :solid, class: 'w-6 h-6 text-yellow-500 mr-3') %>
6
+ <% end %>
7
+ <div>
8
+ <%= post.title %>
9
+ <div class="text-gray-400 text-xs"><%= time_ago_in_words(post.created_at) %> ago</div>
10
+ </div>
11
+ <% end %>
12
+
13
+ <div class="flex-1"></div>
14
+
15
+ <div>
16
+ <% if post.draft? %>
17
+ <span class="text-sm text-gray-400"><%=t 'spina.blog.posts.concept' %></span>
18
+ <% elsif post.published_at and post.published_at > Time.now %>
19
+ <span class="text-sm text-gray-400">
20
+ Will be published on <%= post.decorate.published_date %>
21
+ </span>
22
+ <% end %>
23
+ </div>
24
+
25
+ <div>
26
+ <%= link_to spina.edit_admin_conferences_blog_post_path(post.id), class: "btn btn-default px-3" do %>
27
+ <%= heroicon('pencil', style: :solid, class: 'w-4 h-4') %>
28
+ <% end %>
29
+ </div>
30
+ </div>
@@ -0,0 +1 @@
1
+ <%= render 'form' %>
@@ -0,0 +1,33 @@
1
+ <%= render Spina::UserInterface::HeaderComponent.new do |header| %>
2
+ <% header.after_breadcrumbs do %>
3
+ <%= link_to spina.new_admin_conferences_blog_post_path, class: 'btn btn-default h-8 px-2 ml-3' do %>
4
+ <%= heroicon('plus', style: :solid, class: 'w-6 h-6') %>
5
+ <% end %>
6
+ <% end %>
7
+
8
+ <% header.navigation do %>
9
+ <nav class="-mb-3 mt-4">
10
+ <ul class="inline-flex w-auto rounded-md bg-white">
11
+ <%= render Spina::UserInterface::TabLinkComponent.new(t('spina.blog.posts.all_posts'), spina.admin_conferences_blog_posts_path, active: action_name == 'index') %>
12
+
13
+ <%= render Spina::UserInterface::TabLinkComponent.new(t('spina.blog.posts.live_posts'), spina.live_admin_conferences_blog_posts_path, active: action_name == 'live') %>
14
+
15
+ <%= render Spina::UserInterface::TabLinkComponent.new(t('spina.blog.posts.draft_posts'), spina.draft_admin_conferences_blog_posts_path, active: action_name == 'draft') %>
16
+
17
+ <%= render Spina::UserInterface::TabLinkComponent.new(t('spina.blog.posts.scheduled_posts'), spina.future_admin_conferences_blog_posts_path, active: action_name == 'future') %>
18
+ </ul>
19
+ </nav>
20
+ <% end %>
21
+ <% end %>
22
+
23
+ <div class="p-8">
24
+ <% if @posts.any? %>
25
+ <div class="shadow-sm border border-gray-200 bg-white rounded-lg">
26
+ <%= render partial: 'post', collection: @posts, as: :post %>
27
+ </div>
28
+ <% else %>
29
+ <div class="text-gray-700 italic">
30
+ There are no posts yet. Create your first one!
31
+ </div>
32
+ <% end %>
33
+ </div>
@@ -0,0 +1 @@
1
+ <%= render 'form' %>
@@ -0,0 +1,14 @@
1
+ <%= render Spina::MainNavigation::SubNavComponent.new(:blog) do |nav| %>
2
+ <% nav.icon do %>
3
+ <%= heroicon('pencil', style: :solid, class: 'w-8 h-8 text-white md:mr-3') %>
4
+
5
+ <div class="text-white font-semibold hidden md:block transform -translate-x-2 ease-in-out duration-300 absolute md:relative opacity-0 transition-all" data-navigation-target="label">
6
+ <%=t 'spina.blog.title' %>
7
+ </div>
8
+ <% end %>
9
+
10
+ <% nav.links do %>
11
+ <%= render Spina::MainNavigation::LinkComponent.new(t('spina.blog.posts.title'), spina.admin_conferences_blog_posts_path, active: request.path.start_with?("/#{Spina.config.backend_path}/conferences/blog/posts")) %>
12
+ <%= render Spina::MainNavigation::LinkComponent.new(t('spina.blog.categories.title'), spina.admin_conferences_blog_categories_path, active: request.path.start_with?("/#{Spina.config.backend_path}/conferences/blog/categories")) %>
13
+ <% end %>
14
+ <% end %>
@@ -14,6 +14,12 @@ en:
14
14
  post_content: Content
15
15
  post_configuration: Settings
16
16
  concept: Draft
17
+ all_posts: All Posts
18
+ delete_confirmation: Are you sure you want to delete <strong>%{subject}</strong>?
19
+ draft_posts: Draft Posts
20
+ live_posts: Live Posts
21
+ post_seo: Post SEO
22
+ scheduled_posts: Scheduled Posts
17
23
 
18
24
  categories:
19
25
  title: Categories
@@ -22,6 +28,7 @@ en:
22
28
  save: Save category
23
29
  saving: Saving...
24
30
  saved: Category saved
31
+ delete_confirmation: Are you sure you want to delete <strong>%{subject}</strong>?
25
32
 
26
33
  activerecord:
27
34
  attributes:
@@ -14,6 +14,12 @@ nl:
14
14
  post_content: Inhoud
15
15
  post_configuration: Instellingen
16
16
  concept: Concept
17
+ all_posts: All Posts
18
+ delete_confirmation: Are you sure you want to delete <strong>%{subject}</strong>?
19
+ draft_posts: Draft Posts
20
+ live_posts: Live Posts
21
+ post_seo: Post SEO
22
+ scheduled_posts: Scheduled Posts
17
23
 
18
24
  categories:
19
25
  title: Categorieën
@@ -22,6 +28,7 @@ nl:
22
28
  save: Categorie opslaan
23
29
  saving: Opslaan...
24
30
  saved: Categorie opgeslagen
31
+ delete_confirmation: Are you sure you want to delete <strong>%{subject}</strong>?
25
32
 
26
33
  activerecord:
27
34
  attributes:
@@ -14,6 +14,12 @@ pt-BR:
14
14
  post_content: Conteúdo
15
15
  post_configuration: Configurações
16
16
  concept: Rascunho
17
+ all_posts: All Posts
18
+ delete_confirmation: Are you sure you want to delete <strong>%{subject}</strong>?
19
+ draft_posts: Draft Posts
20
+ live_posts: Live Posts
21
+ post_seo: Post SEO
22
+ scheduled_posts: Scheduled Posts
17
23
 
18
24
  categories:
19
25
  title: Categorias
@@ -22,6 +28,7 @@ pt-BR:
22
28
  save: Salvar categoria
23
29
  saving: Salvando...
24
30
  saved: Categoria salva
31
+ delete_confirmation: Are you sure you want to delete <strong>%{subject}</strong>?
25
32
 
26
33
  activerecord:
27
34
  attributes:
@@ -2,7 +2,7 @@
2
2
 
3
3
  module Spina
4
4
  module Admin::Conferences::Blog
5
- # Spina::Blog::Engine
5
+ # Spina::Admin::Conferences::Blog::Engine
6
6
  class Engine < ::Rails::Engine
7
7
  isolate_namespace Spina::Admin::Conferences::Blog
8
8
 
@@ -11,6 +11,9 @@ module Spina
11
11
  plugin.name = 'conferences-blog'
12
12
  plugin.namespace = 'conferences/blog'
13
13
  end
14
+
15
+ # Add views for purging Tailwind classes
16
+ ::Spina.config.tailwind_content.concat Spina::Admin::Conferences::Blog::Engine.root.glob("app/views/**/*.*")
14
17
  end
15
18
 
16
19
  config.generators do |g|
@@ -5,7 +5,7 @@ module Spina
5
5
  module Admin
6
6
  module Conferences
7
7
  module Blog
8
- VERSION = '0.1.4'
8
+ VERSION = '0.2.0'
9
9
  end
10
10
  end
11
11
  end
@@ -90,6 +90,7 @@ RSpec.describe Spina::Admin::Conferences::Blog::CategoriesController, type: :con
90
90
  end
91
91
 
92
92
  context 'signed out' do
93
+ before { Spina::Account.create name: 'My Website', theme: 'default' }
93
94
  describe 'GET #index' do
94
95
  subject { get :index }
95
96
  it { is_expected.to have_http_status :redirect }
@@ -143,6 +143,7 @@ RSpec.describe Spina::Admin::Conferences::Blog::PostsController, type: :controll
143
143
  end
144
144
 
145
145
  context 'signed out' do
146
+ before { Spina::Account.create name: 'My Website', theme: 'default' }
146
147
  describe 'GET #index' do
147
148
  subject { get :index }
148
149
  it { is_expected.to have_http_status :redirect }
@@ -1,4 +1,5 @@
1
1
 
2
2
  //= link_tree ../images
3
3
  //= link_directory ../javascripts .js
4
- //= link_directory ../stylesheets .css
4
+ //= link_tree ../stylesheets .css
5
+
@@ -27,6 +27,9 @@ Rails.application.configure do
27
27
 
28
28
  config.cache_store = :null_store
29
29
  end
30
+
31
+ config.active_storage.service = :local
32
+ config.active_storage.resolve_model_to_route = :rails_storage_proxy
30
33
 
31
34
  # Don't care if the mailer can't send.
32
35
  config.action_mailer.raise_delivery_errors = false
@@ -29,6 +29,10 @@ Rails.application.configure do
29
29
 
30
30
  # Disable request forgery protection in test environment.
31
31
  config.action_controller.allow_forgery_protection = false
32
+
33
+ config.active_storage.service = :test
34
+ config.active_storage.resolve_model_to_route = :rails_storage_proxy
35
+
32
36
  config.action_mailer.perform_caching = false
33
37
 
34
38
  # Tell Action Mailer not to deliver emails to the real world.
@@ -11,6 +11,7 @@ Mobility.configure do
11
11
  cache
12
12
  presence
13
13
  fallbacks false # default to false, enable if passed fallbacks: true
14
+ locale_accessors
14
15
  default
15
16
  end
16
17
  end
@@ -0,0 +1,7 @@
1
+ test:
2
+ service: Disk
3
+ root: <%= Rails.root.join("tmp/storage") %>
4
+
5
+ local:
6
+ service: Disk
7
+ root: <%= Rails.root.join("storage") %>
@@ -0,0 +1,6 @@
1
+ # This migration comes from spina (originally 12)
2
+ class AddUrlTitleToSpinaPageTranslations < ActiveRecord::Migration[5.2]
3
+ def change
4
+ add_column :spina_page_translations, :url_title, :string
5
+ end
6
+ end
@@ -0,0 +1,6 @@
1
+ # This migration comes from spina (originally 13)
2
+ class AddJsonAttributesToSpinaAccounts < ActiveRecord::Migration[5.2]
3
+ def change
4
+ add_column :spina_accounts, :json_attributes, :jsonb
5
+ end
6
+ end
@@ -0,0 +1,6 @@
1
+ # This migration comes from spina (originally 14)
2
+ class AddJsonAttributesToSpinaPages < ActiveRecord::Migration[5.2]
3
+ def change
4
+ add_column :spina_pages, :json_attributes, :jsonb
5
+ end
6
+ end