spina 2.12.0 → 2.13.0
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.
- checksums.yaml +4 -4
- data/Rakefile +17 -17
- data/app/assets/builds/spina/tailwind.css +79 -47
- data/app/components/spina/application_component.rb +1 -1
- data/app/components/spina/forms/group_component.rb +2 -3
- data/app/components/spina/forms/label_component.rb +2 -3
- data/app/components/spina/forms/password_field_component.rb +1 -1
- data/app/components/spina/forms/switch_component.rb +2 -3
- data/app/components/spina/forms/text_field_component.rb +8 -9
- data/app/components/spina/forms/trix_toolbar_component.rb +1 -3
- data/app/components/spina/hooks/hook_component.rb +3 -5
- data/app/components/spina/hooks/partial_component.rb +4 -5
- data/app/components/spina/main_navigation/link_component.rb +1 -3
- data/app/components/spina/main_navigation/sub_nav_component.rb +6 -7
- data/app/components/spina/media_picker/image_component.rb +1 -3
- data/app/components/spina/media_picker/modal_component.rb +4 -6
- data/app/components/spina/pages/actions_component.rb +1 -3
- data/app/components/spina/pages/list_component.rb +3 -4
- data/app/components/spina/pages/location_component.rb +10 -11
- data/app/components/spina/pages/new_page_button_component.rb +4 -5
- data/app/components/spina/pages/page_component.rb +8 -9
- data/app/components/spina/pages/page_select_component.rb +3 -4
- data/app/components/spina/pages/tab_button_component.rb +1 -3
- data/app/components/spina/pages/translations_component.rb +9 -11
- data/app/components/spina/user_interface/dropdown_button_component.rb +4 -4
- data/app/components/spina/user_interface/dropdown_component.rb +8 -9
- data/app/components/spina/user_interface/flash_message_component.rb +3 -5
- data/app/components/spina/user_interface/header_component.rb +2 -2
- data/app/components/spina/user_interface/modal_component.rb +1 -3
- data/app/components/spina/user_interface/tab_link_component.rb +1 -3
- data/app/components/spina/user_interface/translations_component.rb +8 -10
- data/app/controllers/concerns/spina/api/paginable.rb +36 -37
- data/app/controllers/concerns/spina/current_spina_account.rb +1 -1
- data/app/controllers/concerns/spina/current_theme.rb +6 -7
- data/app/controllers/concerns/spina/frontend.rb +58 -44
- data/app/controllers/spina/admin/accounts_controller.rb +9 -10
- data/app/controllers/spina/admin/admin_controller.rb +18 -18
- data/app/controllers/spina/admin/attachments_controller.rb +15 -10
- data/app/controllers/spina/admin/embeds_controller.rb +17 -19
- data/app/controllers/spina/admin/images_controller.rb +24 -25
- data/app/controllers/spina/admin/layout_controller.rb +19 -20
- data/app/controllers/spina/admin/media_folders_controller.rb +4 -5
- data/app/controllers/spina/admin/media_picker_controller.rb +2 -4
- data/app/controllers/spina/admin/move_pages_controller.rb +8 -10
- data/app/controllers/spina/admin/navigation_items_controller.rb +13 -14
- data/app/controllers/spina/admin/navigations_controller.rb +26 -26
- data/app/controllers/spina/admin/page_translations_controller.rb +1 -3
- data/app/controllers/spina/admin/pages_controller.rb +34 -34
- data/app/controllers/spina/admin/parent_pages_controller.rb +1 -3
- data/app/controllers/spina/admin/password_resets_controller.rb +8 -9
- data/app/controllers/spina/admin/resources_controller.rb +14 -15
- data/app/controllers/spina/admin/sessions_controller.rb +2 -2
- data/app/controllers/spina/admin/settings_controller.rb +28 -29
- data/app/controllers/spina/admin/theme_controller.rb +10 -11
- data/app/controllers/spina/admin/users_controller.rb +28 -29
- data/app/controllers/spina/api/api_controller.rb +17 -17
- data/app/controllers/spina/api/images_controller.rb +1 -3
- data/app/controllers/spina/api/navigations_controller.rb +2 -4
- data/app/controllers/spina/api/pages_controller.rb +8 -9
- data/app/controllers/spina/api/resources_controller.rb +2 -4
- data/app/controllers/spina/application_controller.rb +4 -3
- data/app/controllers/spina/pages_controller.rb +4 -5
- data/app/controllers/spina/sitemaps_controller.rb +0 -2
- data/app/helpers/spina/admin/icons_helper.rb +151 -153
- data/app/helpers/spina/admin/images_helper.rb +0 -2
- data/app/helpers/spina/admin/pages_helper.rb +3 -5
- data/app/helpers/spina/attachments_helper.rb +1 -3
- data/app/helpers/spina/images_helper.rb +5 -7
- data/app/helpers/spina/pages_helper.rb +0 -2
- data/app/helpers/spina/spina_helper.rb +1 -3
- data/app/jobs/spina/replace_signed_id_job.rb +10 -11
- data/app/jobs/spina/resource_pages_update_job.rb +1 -1
- data/app/mailers/spina/application_mailer.rb +2 -2
- data/app/mailers/spina/user_mailer.rb +4 -6
- data/app/models/concerns/spina/gravatar.rb +11 -12
- data/app/models/concerns/spina/partable.rb +4 -6
- data/app/models/concerns/spina/translated_content.rb +5 -5
- data/app/models/spina/account.rb +9 -10
- data/app/models/spina/application_record.rb +2 -3
- data/app/models/spina/attachment.rb +3 -4
- data/app/models/spina/current.rb +1 -1
- data/app/models/spina/embeds/base.rb +2 -2
- data/app/models/spina/embeds/button.rb +4 -4
- data/app/models/spina/embeds/vimeo.rb +17 -18
- data/app/models/spina/embeds/youtube.rb +18 -19
- data/app/models/spina/image.rb +4 -4
- data/app/models/spina/media_folder.rb +1 -1
- data/app/models/spina/navigation.rb +1 -2
- data/app/models/spina/navigation_item.rb +2 -2
- data/app/models/spina/page.rb +32 -38
- data/app/models/spina/parts/attachment.rb +1 -2
- data/app/models/spina/parts/base.rb +5 -4
- data/app/models/spina/parts/image.rb +3 -4
- data/app/models/spina/parts/image_collection.rb +2 -3
- data/app/models/spina/parts/image_variant.rb +3 -4
- data/app/models/spina/parts/repeater_content.rb +2 -2
- data/app/models/spina/resource.rb +3 -4
- data/app/models/spina/rewrite_rule.rb +1 -1
- data/app/models/spina/setting.rb +0 -2
- data/app/models/spina/user.rb +3 -4
- data/app/presenters/spina/content_presenter.rb +11 -12
- data/app/presenters/spina/menu_presenter.rb +55 -55
- data/app/presenters/spina/rich_text_presenter.rb +28 -29
- data/app/serializers/spina/api/base_serializer.rb +1 -1
- data/app/serializers/spina/api/image_serializer.rb +6 -6
- data/app/serializers/spina/api/navigation_serializer.rb +4 -7
- data/app/serializers/spina/api/page_serializer.rb +9 -12
- data/app/serializers/spina/api/resource_serializer.rb +5 -5
- data/app/views/layouts/spina/admin/application.html.erb +1 -0
- data/app/views/spina/admin/parts/attachments/_attachment.html.erb +3 -0
- data/app/views/spina/admin/parts/attachments/_form.html.erb +22 -1
- data/app/views/spina/admin/parts/repeaters/_fields.html.erb +2 -2
- data/app/views/spina/admin/parts/repeaters/_form.html.erb +4 -4
- data/app/views/spina/admin/shared/_navigation.html.erb +3 -1
- data/app/views/spina/admin/shared/_version.html.erb +18 -0
- data/app/views/spina/sitemaps/show.xml.builder +1 -1
- data/config/initializers/importmap.rb +3 -3
- data/config/initializers/yaml_column_permitted_classes.rb +3 -3
- data/config/locales/de.yml +1 -0
- data/config/locales/en.yml +3 -0
- data/config/locales/nl.yml +4 -1
- data/config/routes.rb +10 -17
- data/db/migrate/1_create_spina_tables.rb +57 -57
- data/db/migrate/3_create_spina_navigations.rb +1 -1
- data/db/seeds.rb +0 -1
- data/lib/generators/spina/embed_generator.rb +5 -6
- data/lib/generators/spina/install_generator.rb +48 -41
- data/lib/generators/spina/tailwind_config_generator.rb +3 -4
- data/lib/generators/spina/templates/app/models/spina/embeds/embed.rb.tt +20 -18
- data/lib/generators/spina/templates/config/initializers/spina.rb +11 -11
- data/lib/generators/spina/templates/config/initializers/themes/default.rb +17 -17
- data/lib/generators/spina/templates/config/initializers/themes/demo.rb +22 -22
- data/lib/spina/admin_sectionable.rb +5 -8
- data/lib/spina/attr_json_monkeypatch.rb +4 -7
- data/lib/spina/attr_json_spina_parts_model.rb +1 -3
- data/lib/spina/authentication/basic.rb +9 -10
- data/lib/spina/authentication/sessions.rb +10 -11
- data/lib/spina/embeddable.rb +14 -17
- data/lib/spina/embeds/trix_conversion.rb +25 -26
- data/lib/spina/embeds.rb +1 -3
- data/lib/spina/engine.rb +18 -19
- data/lib/spina/part.rb +1 -6
- data/lib/spina/plugin.rb +9 -13
- data/lib/spina/railtie.rb +5 -7
- data/lib/spina/theme.rb +13 -17
- data/lib/spina/theme_reloader.rb +12 -13
- data/lib/spina/version.rb +1 -1
- data/lib/spina.rb +39 -40
- data/lib/tasks/install.rake +8 -14
- data/lib/tasks/tailwind.rake +10 -8
- metadata +18 -2
|
@@ -8,13 +8,13 @@ module Spina
|
|
|
8
8
|
|
|
9
9
|
# Configuration
|
|
10
10
|
config_accessor :menu_tag, :menu_css,
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
11
|
+
:list_tag, :list_css,
|
|
12
|
+
:list_item_tag, :list_item_css,
|
|
13
|
+
:link_tag_css,
|
|
14
|
+
:active_list_item_css,
|
|
15
|
+
:current_list_item_css,
|
|
16
|
+
:include_drafts,
|
|
17
|
+
:depth # root nodes are at depth 0
|
|
18
18
|
|
|
19
19
|
# Default configuration
|
|
20
20
|
self.menu_tag = :nav
|
|
@@ -32,67 +32,67 @@ module Spina
|
|
|
32
32
|
|
|
33
33
|
private
|
|
34
34
|
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
35
|
+
def roots
|
|
36
|
+
return collection.navigation_items.roots if collection.is_a?(Navigation)
|
|
37
|
+
collection.roots
|
|
38
|
+
end
|
|
39
39
|
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
end
|
|
40
|
+
def render_menu(collection)
|
|
41
|
+
content_tag(menu_tag, class: menu_css) do
|
|
42
|
+
render_items(scoped_collection(collection))
|
|
44
43
|
end
|
|
44
|
+
end
|
|
45
45
|
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
end
|
|
46
|
+
def render_items(collection)
|
|
47
|
+
content_tag(list_tag, class: list_css) do
|
|
48
|
+
collection.inject(ActiveSupport::SafeBuffer.new) do |buffer, item|
|
|
49
|
+
buffer << render_item(item)
|
|
51
50
|
end
|
|
52
51
|
end
|
|
52
|
+
end
|
|
53
53
|
|
|
54
|
-
|
|
55
|
-
|
|
54
|
+
def render_item(item)
|
|
55
|
+
return nil unless item.materialized_path
|
|
56
56
|
|
|
57
|
-
|
|
57
|
+
children = scoped_collection(item.children)
|
|
58
58
|
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
end
|
|
59
|
+
content_tag(list_item_tag, class: item_css(item), data: {page_id: item.page_id, draft: (true if item.draft?)}) do
|
|
60
|
+
buffer = ActiveSupport::SafeBuffer.new
|
|
61
|
+
buffer << link_to(item.menu_title, item.materialized_path, class: link_tag_css)
|
|
62
|
+
buffer << render_items(children) if render_children?(item) && children.any?
|
|
63
|
+
buffer
|
|
65
64
|
end
|
|
65
|
+
end
|
|
66
66
|
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
67
|
+
def scoped_collection(collection)
|
|
68
|
+
scoped = collection.regular_pages.active.in_menu.sorted
|
|
69
|
+
include_drafts ? scoped : scoped.live
|
|
70
|
+
end
|
|
71
71
|
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
def item_css(item)
|
|
78
|
-
return current_list_item_css if apply_current_css?(item)
|
|
79
|
-
return active_list_item_css if apply_active_css?(item)
|
|
80
|
-
list_item_css
|
|
81
|
-
end
|
|
72
|
+
def render_children?(item)
|
|
73
|
+
return true unless depth
|
|
74
|
+
item.depth < depth
|
|
75
|
+
end
|
|
82
76
|
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
77
|
+
def item_css(item)
|
|
78
|
+
return current_list_item_css if apply_current_css?(item)
|
|
79
|
+
return active_list_item_css if apply_active_css?(item)
|
|
80
|
+
list_item_css
|
|
81
|
+
end
|
|
87
82
|
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
83
|
+
def apply_current_css?(item)
|
|
84
|
+
return false if current_list_item_css.nil?
|
|
85
|
+
Spina::Current.page == item
|
|
86
|
+
end
|
|
92
87
|
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
88
|
+
def apply_active_css?(item)
|
|
89
|
+
return false if apply_current_css?(item)
|
|
90
|
+
parent_of_current?(item)
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
def parent_of_current?(item)
|
|
94
|
+
return false if item.homepage?
|
|
95
|
+
Spina::Current.page.materialized_path.starts_with? item.materialized_path
|
|
96
|
+
end
|
|
97
97
|
end
|
|
98
98
|
end
|
|
@@ -1,45 +1,44 @@
|
|
|
1
1
|
module Spina
|
|
2
2
|
class RichTextPresenter
|
|
3
3
|
attr_reader :html, :view_context
|
|
4
|
-
|
|
4
|
+
|
|
5
5
|
EMBED_CONTENT_TYPE = "application/vnd+spina.embed+html"
|
|
6
|
-
|
|
6
|
+
|
|
7
7
|
def initialize(view_context, html)
|
|
8
8
|
@view_context = view_context || Spina::Current.page&.view_context
|
|
9
9
|
@html = html
|
|
10
10
|
end
|
|
11
|
-
|
|
11
|
+
|
|
12
12
|
def to_s
|
|
13
13
|
ActiveSupport::SafeBuffer.new(render_embeds(html))
|
|
14
14
|
end
|
|
15
|
-
|
|
15
|
+
|
|
16
16
|
private
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
end
|
|
27
|
-
doc.to_s
|
|
28
|
-
end
|
|
29
|
-
|
|
30
|
-
def render_embed(element)
|
|
31
|
-
embeddable = element_to_embeddable(element)
|
|
32
|
-
view_context.render(embeddable)
|
|
33
|
-
end
|
|
34
|
-
|
|
35
|
-
def element_to_embeddable(element)
|
|
36
|
-
embeddable = Spina::Embeds.constantize(element["data-embed-type"])
|
|
37
|
-
embeddable&.from_json(element["data-embed-attributes"]) || null_object
|
|
38
|
-
end
|
|
39
|
-
|
|
40
|
-
def null_object
|
|
41
|
-
{inline: ""}
|
|
17
|
+
|
|
18
|
+
def embed_selector
|
|
19
|
+
"figure[data-trix-content-type=\"#{EMBED_CONTENT_TYPE}\"]"
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def render_embeds(html)
|
|
23
|
+
doc = Nokogiri::HTML.fragment(html)
|
|
24
|
+
doc.css(embed_selector).each do |node|
|
|
25
|
+
node.replace render_embed(node.first_element_child)
|
|
42
26
|
end
|
|
27
|
+
doc.to_s
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def render_embed(element)
|
|
31
|
+
embeddable = element_to_embeddable(element)
|
|
32
|
+
view_context.render(embeddable)
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def element_to_embeddable(element)
|
|
36
|
+
embeddable = Spina::Embeds.constantize(element["data-embed-type"])
|
|
37
|
+
embeddable&.from_json(element["data-embed-attributes"]) || null_object
|
|
38
|
+
end
|
|
43
39
|
|
|
40
|
+
def null_object
|
|
41
|
+
{inline: ""}
|
|
42
|
+
end
|
|
44
43
|
end
|
|
45
44
|
end
|
|
@@ -1,20 +1,20 @@
|
|
|
1
1
|
module Spina::Api
|
|
2
|
-
class ImageSerializer < BaseSerializer
|
|
2
|
+
class ImageSerializer < BaseSerializer
|
|
3
3
|
set_type :image
|
|
4
|
-
|
|
4
|
+
|
|
5
5
|
attributes :id
|
|
6
|
-
|
|
6
|
+
|
|
7
7
|
attribute :original_url do |image, params|
|
|
8
8
|
params[:view_context].main_app.url_for(image.file)
|
|
9
9
|
end
|
|
10
|
-
|
|
10
|
+
|
|
11
11
|
attribute :thumbnail_url do |image, params|
|
|
12
12
|
params[:view_context].main_app.url_for(image.variant(resize_to_fill: Spina.config.thumbnail_image_size))
|
|
13
13
|
end
|
|
14
|
-
|
|
14
|
+
|
|
15
15
|
attribute :embedded_image_size_url do |image, params|
|
|
16
16
|
resize_key = Spina.config.embedded_image_size.is_a?(Array) ? :resize_to_limit : :resize
|
|
17
|
-
params[:view_context].main_app.url_for(image.variant(
|
|
17
|
+
params[:view_context].main_app.url_for(image.variant({resize_key => Spina.config.embedded_image_size}))
|
|
18
18
|
end
|
|
19
19
|
end
|
|
20
20
|
end
|
|
@@ -1,15 +1,14 @@
|
|
|
1
1
|
module Spina::Api
|
|
2
|
-
class NavigationSerializer < BaseSerializer
|
|
2
|
+
class NavigationSerializer < BaseSerializer
|
|
3
3
|
set_type :navigation
|
|
4
|
-
|
|
4
|
+
|
|
5
5
|
attributes :name, :label
|
|
6
|
-
|
|
6
|
+
|
|
7
7
|
attribute :tree do |navigation|
|
|
8
8
|
items_to_tree(navigation.navigation_items.sorted.roots.in_menu.live.joins(:page))
|
|
9
9
|
end
|
|
10
|
-
|
|
10
|
+
|
|
11
11
|
class << self
|
|
12
|
-
|
|
13
12
|
def items_to_tree(collection)
|
|
14
13
|
collection.map do |item|
|
|
15
14
|
{
|
|
@@ -23,8 +22,6 @@ module Spina::Api
|
|
|
23
22
|
}
|
|
24
23
|
end
|
|
25
24
|
end
|
|
26
|
-
|
|
27
25
|
end
|
|
28
|
-
|
|
29
26
|
end
|
|
30
27
|
end
|
|
@@ -1,28 +1,25 @@
|
|
|
1
1
|
module Spina::Api
|
|
2
|
-
class PageSerializer < BaseSerializer
|
|
2
|
+
class PageSerializer < BaseSerializer
|
|
3
3
|
set_type :page
|
|
4
|
-
|
|
4
|
+
|
|
5
5
|
attributes :title, :seo_title, :menu_title, :materialized_path, :name, :description, :view_template
|
|
6
|
-
|
|
6
|
+
|
|
7
7
|
attribute(:content) { |page| page_content(page) }
|
|
8
|
-
|
|
8
|
+
|
|
9
9
|
belongs_to :resource
|
|
10
10
|
|
|
11
11
|
class << self
|
|
12
|
-
|
|
13
12
|
def page_content(page)
|
|
14
13
|
return [] unless view_template(page)
|
|
15
|
-
|
|
16
|
-
view_template(page)[:parts].map do |part|
|
|
17
|
-
{
|
|
14
|
+
|
|
15
|
+
view_template(page)[:parts].map do |part|
|
|
16
|
+
{part => page.content(part)}
|
|
18
17
|
end
|
|
19
18
|
end
|
|
20
|
-
|
|
19
|
+
|
|
21
20
|
def view_template(page)
|
|
22
|
-
Spina::Current.theme.view_templates.find{|view_template| view_template[:name] == page.view_template}
|
|
21
|
+
Spina::Current.theme.view_templates.find { |view_template| view_template[:name] == page.view_template }
|
|
23
22
|
end
|
|
24
|
-
|
|
25
23
|
end
|
|
26
|
-
|
|
27
24
|
end
|
|
28
25
|
end
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
module Spina::Api
|
|
2
2
|
class ResourceSerializer < BaseSerializer
|
|
3
3
|
set_type :resource
|
|
4
|
-
|
|
4
|
+
|
|
5
5
|
attributes :name, :label, :view_template, :order_by, :slug
|
|
6
|
-
|
|
6
|
+
|
|
7
7
|
has_many :pages, lazy_load_data: true, links: {
|
|
8
|
-
self: ->
|
|
9
|
-
related: ->
|
|
10
|
-
}, meta: ->
|
|
8
|
+
self: ->(object) { api_resource_path(object.id) },
|
|
9
|
+
related: ->(object) { api_resource_pages_path(object.id) }
|
|
10
|
+
}, meta: ->(resource) { {count: resource.pages.live.length} }
|
|
11
11
|
end
|
|
12
12
|
end
|
|
@@ -5,5 +5,26 @@
|
|
|
5
5
|
<%= f.hidden_field :signed_blob_id, data: {attachment_picker_target: 'signedBlobId'} %>
|
|
6
6
|
<%= f.hidden_field :filename, data: {attachment_picker_target: 'filename'} %>
|
|
7
7
|
|
|
8
|
-
|
|
8
|
+
<div class="flex items-center space-x-3 mt-1">
|
|
9
|
+
<% select_id = dom_id(f.object, f.object.object_id) %>
|
|
10
|
+
|
|
11
|
+
<%= f.select :attachment_id, Spina::Attachment.sorted.map{|attachment| [attachment.file&.filename, attachment.id, data: {signed_blob_id: attachment.file&.blob&.signed_id, filename: attachment.file&.filename}]}, {include_blank: t("spina.attachments.choose_attachment")}, {id: select_id, class: "form-select", data: {action: "attachment-picker#pick"}} %>
|
|
12
|
+
|
|
13
|
+
<div class="text-gray-400 font-medium text-sm">
|
|
14
|
+
<%=t 'spina.ui.or' %>
|
|
15
|
+
</div>
|
|
16
|
+
|
|
17
|
+
<%= form_with model: [:admin, Spina::Attachment.new], url: spina.inline_upload_admin_attachments_path, data: {controller: "form loading-button", loading_message: t('spina.media_library.uploading'), action: "turbo:submit-end->loading-button#doneLoading"} do |f| %>
|
|
18
|
+
<%= hidden_field_tag :select_id, select_id %>
|
|
19
|
+
<% file_field_id = "file_#{f.object.object_id}" %>
|
|
20
|
+
|
|
21
|
+
<%= f.file_field :file, id: file_field_id, class: 'hidden', data: {action: "loading-button#loading form#requestSubmit"} %>
|
|
22
|
+
|
|
23
|
+
<button type="button" class="btn btn-default" data-controller="delegate-click" data-action="delegate-click#click" data-loading-button-target="button" data-delegate-click-target="#<%= file_field_id %>">
|
|
24
|
+
<%= heroicon("upload", style: :solid, class: "w-4 h-4 -ml-1 mr-1") %>
|
|
25
|
+
<%=t 'spina.attachments.upload_one' %>
|
|
26
|
+
</button>
|
|
27
|
+
<% end %>
|
|
28
|
+
|
|
29
|
+
</div>
|
|
9
30
|
</div>
|
|
@@ -13,6 +13,6 @@
|
|
|
13
13
|
<% end %>
|
|
14
14
|
|
|
15
15
|
<div class="text-right">
|
|
16
|
-
<%= button_tag t('spina.ui.
|
|
16
|
+
<%= button_tag t('spina.ui.delete_item', item: item_name), type: :button, class: 'btn btn-default bg-transparent hover:bg-white hover:text-red-500 h-8 px-3 inline-block mt-3', data: {action: "repeater#removeFields", id: "pane_#{f.object.object_id}"} %>
|
|
17
17
|
</div>
|
|
18
|
-
</div>
|
|
18
|
+
</div>
|
|
@@ -4,11 +4,11 @@
|
|
|
4
4
|
|
|
5
5
|
<div class="-mt-4 flex flex-col md:flex-row" data-controller="tabs" data-tabs-active="bg-spina-dark bg-opacity-10 text-gray-900" data-tabs-inactive="text-gray-500">
|
|
6
6
|
<div class="md:w-64 md:pr-6">
|
|
7
|
-
<%
|
|
7
|
+
<%
|
|
8
8
|
# Fields
|
|
9
9
|
repeater_content = Spina::Parts::RepeaterContent.new(name: f.object.name, title: f.object.title)
|
|
10
10
|
fields = f.fields_for(:content, [repeater_content], child_index: repeater_content.object_id) do |builder|
|
|
11
|
-
render("spina/admin/parts/repeaters/fields", f: builder)
|
|
11
|
+
render("spina/admin/parts/repeaters/fields", f: builder, item_name: f.object.item_name)
|
|
12
12
|
end.gsub("\n", "")
|
|
13
13
|
%>
|
|
14
14
|
|
|
@@ -31,8 +31,8 @@
|
|
|
31
31
|
|
|
32
32
|
<div class="flex-1 pl-6 md:pl-0" data-repeater-target="content">
|
|
33
33
|
<%= f.fields_for :content do |ff| %>
|
|
34
|
-
<%= render 'spina/admin/parts/repeaters/fields', f: ff %>
|
|
34
|
+
<%= render 'spina/admin/parts/repeaters/fields', f: ff, item_name: f.object.item_name %>
|
|
35
35
|
<% end %>
|
|
36
36
|
</div>
|
|
37
37
|
</div>
|
|
38
|
-
</div>
|
|
38
|
+
</div>
|
|
@@ -61,7 +61,9 @@
|
|
|
61
61
|
<ul class="md:block">
|
|
62
62
|
<li>
|
|
63
63
|
<%= link_to logout_path, class: 'p-3 w-14 block flex justify-center opacity-50 hover:opacity-100 transition duration-200 ease', data: {turbo: false} do %>
|
|
64
|
-
|
|
64
|
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256 256" fill="currentColor" class="h-7 w-7 text-white">
|
|
65
|
+
<path fill-rule="evenodd" d="M128,256 C93.81,256 61.666,242.686 37.49,218.509 C13.315,194.334 0,162.19 0,128 C0,93.81 13.315,61.668 37.49,37.491 C43.739,31.242 53.869,31.242 60.118,37.491 C66.367,43.739 66.367,53.87 60.118,60.118 C41.985,78.25 32,102.357 32,128 C32,153.643 41.985,177.75 60.118,195.882 C78.25,214.014 102.357,224 128,224 C153.643,224 177.75,214.014 195.882,195.882 C214.015,177.75 224,153.643 224,128 C224,102.357 214.015,78.25 195.882,60.118 C189.633,53.87 189.633,43.739 195.882,37.491 C202.13,31.243 212.261,31.243 218.51,37.491 C242.686,61.668 256,93.809 256,128 C256,162.191 242.685,194.334 218.51,218.509 C194.334,242.686 162.19,256 128,256 L128,256 L128,256 Z M128,144 C136.837,144 144,136.837 144,128 L144,16 C144,7.163 136.837,0 128,0 C119.163,0 112,7.163 112,16 L112,128 C112,136.837 119.163,144 128,144 L128,144 L128,144 Z" clip-rule="evenodd" />
|
|
66
|
+
</svg>
|
|
65
67
|
<% end %>
|
|
66
68
|
</li>
|
|
67
69
|
</ul>
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
<% unless defined?(Spina::Pro) %>
|
|
2
|
+
<%= link_to "https://spinacms.com/pro", class: "fixed bottom-0 right-0 px-5 py-4 group text-gray-400 text-xs font-medium", target: :blank do %>
|
|
3
|
+
<div class="flex items-center justify-end">
|
|
4
|
+
<svg viewBox="0 0 100 100" class="h-3 w-3 mr-1 text-gray-400 group-hover:text-spina" xmlns="http://www.w3.org/2000/svg" fill="currentColor">
|
|
5
|
+
<path d="M48.6582924,96.1623174 L0.472662785,39.1647593 C-0.121452015,38.4619959 -0.159345587,37.4445295 0.380849751,36.699521 L20.3780861,9.12040239 C20.6765111,8.70883071 21.1204689,8.42634978 21.6197077,8.33038495 L49.1629705,3.03595601 C49.3934881,2.99164538 49.6300066,2.9882617 49.8616974,3.02595987 L78.3181435,7.65607741 C78.8410521,7.74115931 79.30884,8.0302376 79.6188319,8.45986224 L99.9955684,36.7004267 C100.533013,37.4452826 100.494021,38.460456 99.9010274,39.1618937 L51.7129756,96.1623174 C50.999859,97.0058449 49.7379497,97.1115638 48.8944223,96.3984473 C48.8092674,96.3264575 48.7302822,96.2474723 48.6582924,96.1623174 Z"></path>
|
|
6
|
+
</svg>
|
|
7
|
+
|
|
8
|
+
Spina CMS v<%= Spina::VERSION %>
|
|
9
|
+
</div>
|
|
10
|
+
|
|
11
|
+
<div class="mt-1">
|
|
12
|
+
Upgrade to Spina
|
|
13
|
+
<span class="bg-gray-400 group-hover:bg-pink-500 text-white rounded px-1 py-0.5 uppercase tracking-wider" style="font-size: 10px">
|
|
14
|
+
Pro
|
|
15
|
+
</span>
|
|
16
|
+
</div>
|
|
17
|
+
<% end %>
|
|
18
|
+
<% end %>
|
|
@@ -3,10 +3,10 @@ Spina.config.importmap.draw do
|
|
|
3
3
|
pin "@hotwired/stimulus", to: "stimulus.js"
|
|
4
4
|
pin "@hotwired/stimulus-loading", to: "stimulus-loading.js"
|
|
5
5
|
pin "@hotwired/turbo-rails", to: "turbo.js"
|
|
6
|
-
|
|
6
|
+
|
|
7
7
|
# Spina entrypoint
|
|
8
8
|
pin "application", to: "spina/application.js"
|
|
9
|
-
|
|
9
|
+
|
|
10
10
|
pin_all_from Spina::Engine.root.join("app/assets/javascripts/spina/controllers"), under: "controllers", to: "spina/controllers"
|
|
11
11
|
pin_all_from Spina::Engine.root.join("app/assets/javascripts/spina/libraries"), under: "libraries", to: "spina/libraries"
|
|
12
|
-
end
|
|
12
|
+
end
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
# CVE-2022-32224 RAILS
|
|
2
|
-
#
|
|
2
|
+
#
|
|
3
3
|
# There was a bug in Rails allowing YAML-serialized data to be vulnerable to RCE.
|
|
4
4
|
# Spina uses the serialize method to store various preferences stored using symbols.
|
|
5
5
|
# We've now changed this so preferences are stored with strings as keys instead of
|
|
6
|
-
# symbols, but in order to not break existing projects we're adding 'Symbol' to the
|
|
6
|
+
# symbols, but in order to not break existing projects we're adding 'Symbol' to the
|
|
7
7
|
# list of permitted classes.
|
|
8
8
|
# This can be removed in the future.
|
|
9
|
-
#
|
|
9
|
+
#
|
|
10
10
|
# More information:
|
|
11
11
|
# https://discuss.rubyonrails.org/t/cve-2022-32224-possible-rce-escalation-bug-with-serialized-columns-in-active-record/81017
|
|
12
12
|
|
data/config/locales/de.yml
CHANGED
data/config/locales/en.yml
CHANGED
|
@@ -131,6 +131,7 @@ en:
|
|
|
131
131
|
insert: Insert document
|
|
132
132
|
insert_multiple: Insert documents
|
|
133
133
|
upload: Upload files
|
|
134
|
+
upload_one: Upload file
|
|
134
135
|
cancel: Cancel
|
|
135
136
|
choose_from_library: Choose from library
|
|
136
137
|
close: Close
|
|
@@ -344,10 +345,12 @@ en:
|
|
|
344
345
|
ui:
|
|
345
346
|
cancel: Cancel
|
|
346
347
|
delete: Delete
|
|
348
|
+
delete_item: "Delete %{item}"
|
|
347
349
|
load_more: Load more
|
|
348
350
|
move_to: Move to
|
|
349
351
|
new_entry: New entry
|
|
350
352
|
optional: Optional
|
|
353
|
+
or: or
|
|
351
354
|
rename: Rename
|
|
352
355
|
replace: Replace
|
|
353
356
|
save_changes: Save changes
|
data/config/locales/nl.yml
CHANGED
|
@@ -108,7 +108,8 @@ nl:
|
|
|
108
108
|
delete_confirmation_html: Weet je het zeker? Het kan zijn dat dit document in gebruik is op een pagina.
|
|
109
109
|
insert: Document toevoegen
|
|
110
110
|
insert_multiple: Documenten toevoegen
|
|
111
|
-
upload:
|
|
111
|
+
upload: Upload documenten
|
|
112
|
+
upload_one: Upload document
|
|
112
113
|
cancel: Annuleren
|
|
113
114
|
choose_from_library: Kies uit bibliotheek
|
|
114
115
|
close: Sluiten
|
|
@@ -315,10 +316,12 @@ nl:
|
|
|
315
316
|
ui:
|
|
316
317
|
cancel: Annuleer
|
|
317
318
|
delete: Verwijder
|
|
319
|
+
delete_item: "Verwijder %{item}"
|
|
318
320
|
load_more: Meer laden
|
|
319
321
|
move_to: Verplaats naar
|
|
320
322
|
new_entry: Nieuw item
|
|
321
323
|
optional: Optioneel
|
|
324
|
+
or: of
|
|
322
325
|
rename: Hernoemen
|
|
323
326
|
replace: Vervangen
|
|
324
327
|
save_changes: Wijzigingen opslaan
|
data/config/routes.rb
CHANGED
|
@@ -11,7 +11,6 @@ Rails.application.routes.draw do
|
|
|
11
11
|
end
|
|
12
12
|
|
|
13
13
|
Spina::Engine.routes.draw do
|
|
14
|
-
|
|
15
14
|
# API
|
|
16
15
|
namespace :api, path: Spina.config.api_path do
|
|
17
16
|
resources :pages, only: [:index, :show]
|
|
@@ -33,7 +32,7 @@ Spina::Engine.routes.draw do
|
|
|
33
32
|
patch "/settings/:plugin", to: "settings#update", as: :settings
|
|
34
33
|
|
|
35
34
|
resources :users
|
|
36
|
-
|
|
35
|
+
|
|
37
36
|
# Sessions
|
|
38
37
|
resources :sessions
|
|
39
38
|
get "login" => "sessions#new"
|
|
@@ -48,7 +47,7 @@ Spina::Engine.routes.draw do
|
|
|
48
47
|
get :edit_template
|
|
49
48
|
get :children
|
|
50
49
|
end
|
|
51
|
-
|
|
50
|
+
|
|
52
51
|
resource :move, controller: "move_pages"
|
|
53
52
|
|
|
54
53
|
post :sort, on: :collection
|
|
@@ -60,18 +59,13 @@ Spina::Engine.routes.draw do
|
|
|
60
59
|
|
|
61
60
|
resources :resources, only: [:show, :edit, :update]
|
|
62
61
|
|
|
63
|
-
resources :navigations do
|
|
62
|
+
resources :navigations, only: [:index, :edit, :update] do
|
|
64
63
|
post :sort, on: :member
|
|
65
64
|
resources :navigation_items
|
|
66
65
|
end
|
|
67
66
|
|
|
68
67
|
resources :attachments do
|
|
69
|
-
collection
|
|
70
|
-
get 'select/:page_part_id' => 'attachments#select', as: :select
|
|
71
|
-
post 'insert/:page_part_id' => 'attachments#insert', as: :insert
|
|
72
|
-
get 'select_collection/:page_part_id' => 'attachments#select_collection', as: :select_collection
|
|
73
|
-
post 'insert_collection/:page_part_id' => 'attachments#insert_collection', as: :insert_collection
|
|
74
|
-
end
|
|
68
|
+
post :inline_upload, on: :collection
|
|
75
69
|
end
|
|
76
70
|
resources :rename_files
|
|
77
71
|
|
|
@@ -80,9 +74,9 @@ Spina::Engine.routes.draw do
|
|
|
80
74
|
end
|
|
81
75
|
|
|
82
76
|
resources :images
|
|
83
|
-
|
|
77
|
+
|
|
84
78
|
resource :media_picker, controller: "media_picker", only: [:show]
|
|
85
|
-
|
|
79
|
+
|
|
86
80
|
resources :embeds, only: [:new, :create]
|
|
87
81
|
end
|
|
88
82
|
|
|
@@ -94,12 +88,11 @@ Spina::Engine.routes.draw do
|
|
|
94
88
|
root to: "pages#homepage"
|
|
95
89
|
|
|
96
90
|
# Pages
|
|
97
|
-
get
|
|
98
|
-
get
|
|
99
|
-
get
|
|
91
|
+
get "/:locale/*id" => "pages#show", :constraints => {locale: /#{Spina.locales.join('|')}/}
|
|
92
|
+
get "/:locale/" => "pages#homepage", :constraints => {locale: /#{Spina.locales.join('|')}/}
|
|
93
|
+
get "/*id" => "pages#show", :as => "page", :controller => "pages", :constraints => ->(request) {
|
|
100
94
|
request.path.exclude?(ActiveStorage.routes_prefix) &&
|
|
101
|
-
|
|
95
|
+
!(Rails.env.development? && request.path.starts_with?("/rails/"))
|
|
102
96
|
}
|
|
103
97
|
end
|
|
104
|
-
|
|
105
98
|
end
|