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.
- checksums.yaml +4 -4
- data/README.md +11 -0
- data/app/controllers/spina/admin/conferences/blog/categories_controller.rb +5 -4
- data/app/controllers/spina/admin/conferences/blog/posts_controller.rb +4 -4
- data/app/views/layouts/default/application.html.erb +1 -0
- data/app/views/spina/admin/conferences/blog/categories/_category.html.erb +13 -0
- data/app/views/spina/admin/conferences/blog/categories/_form.html.erb +38 -0
- data/app/views/spina/admin/conferences/blog/categories/edit.html.erb +1 -0
- data/app/views/spina/admin/conferences/blog/categories/index.html.erb +19 -0
- data/app/views/spina/admin/conferences/blog/categories/new.html.erb +1 -0
- data/app/views/spina/admin/conferences/blog/posts/_form.html.erb +66 -0
- data/app/views/spina/admin/conferences/blog/posts/_form_post_configuration.html.erb +46 -0
- data/app/views/spina/admin/conferences/blog/posts/_form_post_content.html.erb +59 -0
- data/app/views/spina/admin/conferences/blog/posts/_form_post_seo.html.erb +7 -0
- data/app/views/spina/admin/conferences/blog/posts/_post.html.erb +30 -0
- data/app/views/spina/admin/conferences/blog/posts/edit.html.erb +1 -0
- data/app/views/spina/admin/conferences/blog/posts/index.html.erb +33 -0
- data/app/views/spina/admin/conferences/blog/posts/new.html.erb +1 -0
- data/app/views/spina/admin/hooks/conferences/blog/_primary_navigation.html.erb +14 -0
- data/config/locales/en.yml +7 -0
- data/config/locales/nl.yml +7 -0
- data/config/locales/pt-BR.yml +7 -0
- data/lib/spina/admin/conferences/blog/engine.rb +4 -1
- data/lib/spina/admin/conferences/blog/version.rb +1 -1
- data/spec/controllers/spina/admin/conferences/blog/categories_controller_spec.rb +1 -0
- data/spec/controllers/spina/admin/conferences/blog/posts_controller_spec.rb +1 -0
- data/spec/dummy/app/assets/config/manifest.js +2 -1
- data/spec/dummy/app/assets/stylesheets/default/{application.css.sass → application.css} +0 -0
- data/spec/dummy/config/environments/development.rb +3 -0
- data/spec/dummy/config/environments/test.rb +4 -0
- data/spec/dummy/config/initializers/mobility.rb +1 -0
- data/spec/dummy/config/storage.yml +7 -0
- data/spec/dummy/db/migrate/20210403091403_add_url_title_to_spina_page_translations.spina.rb +6 -0
- data/spec/dummy/db/migrate/20210403091404_add_json_attributes_to_spina_accounts.spina.rb +6 -0
- data/spec/dummy/db/migrate/20210403091405_add_json_attributes_to_spina_pages.spina.rb +6 -0
- data/spec/dummy/db/migrate/20210403091406_add_slug_to_spina_resources.spina.rb +6 -0
- data/spec/dummy/db/migrate/20210404093002_create_active_storage_tables.active_storage.rb +36 -0
- data/spec/dummy/db/schema.rb +35 -1
- data/spec/factories/spina/admin/conferences/blog/posts.rb +1 -0
- data/spec/factories/spina/users.rb +10 -0
- data/spec/support/controller_helpers.rb +4 -3
- data/spec/support/system_tests.rb +1 -1
- data/spec/system/spina/admin/conferences/blog/posts_spec.rb +5 -7
- metadata +134 -117
- data/app/views/layouts/spina/admin/conferences/blog/blog.html.haml +0 -29
- data/app/views/layouts/spina/admin/conferences/blog/categories.html.haml +0 -10
- data/app/views/spina/admin/conferences/blog/categories/_category.html.haml +0 -8
- data/app/views/spina/admin/conferences/blog/categories/_form.html.haml +0 -42
- data/app/views/spina/admin/conferences/blog/categories/edit.html.haml +0 -3
- data/app/views/spina/admin/conferences/blog/categories/index.html.haml +0 -23
- data/app/views/spina/admin/conferences/blog/categories/new.html.haml +0 -2
- data/app/views/spina/admin/conferences/blog/posts/_form.html.haml +0 -43
- data/app/views/spina/admin/conferences/blog/posts/_form_post_configuration.html.haml +0 -50
- data/app/views/spina/admin/conferences/blog/posts/_form_post_content.html.haml +0 -46
- data/app/views/spina/admin/conferences/blog/posts/_form_post_seo.html.haml +0 -14
- data/app/views/spina/admin/conferences/blog/posts/_post.html.haml +0 -15
- data/app/views/spina/admin/conferences/blog/posts/edit.html.haml +0 -3
- data/app/views/spina/admin/conferences/blog/posts/index.html.haml +0 -23
- data/app/views/spina/admin/conferences/blog/posts/new.html.haml +0 -2
- 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:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 56f5087c62079b206816f460255574064b89f79066de8bffd15f4b0cb4021a71
|
4
|
+
data.tar.gz: 21cdedbf64861cfcb2302db194e3167127752df667d48aa8a649ad0adef0bd6b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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,
|
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,
|
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,
|
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,
|
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 %>
|
data/config/locales/en.yml
CHANGED
@@ -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:
|
data/config/locales/nl.yml
CHANGED
@@ -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:
|
data/config/locales/pt-BR.yml
CHANGED
@@ -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|
|
@@ -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 }
|
File without changes
|
@@ -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.
|