para 0.8.10 → 0.8.15
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/app/helpers/para/admin/components_helper.rb +10 -2
- data/app/helpers/para/admin/page_helper.rb +25 -1
- data/app/helpers/para/tag_helper.rb +6 -2
- data/app/models/application_record.rb +3 -0
- data/app/models/para/application_record.rb +20 -0
- data/app/models/para/cache/item.rb +1 -1
- data/app/models/para/component/base.rb +16 -2
- data/app/models/para/component_resource.rb +1 -1
- data/app/models/para/component_section.rb +1 -1
- data/app/models/para/library/file.rb +1 -1
- data/app/models/para/page/section.rb +3 -10
- data/app/models/para/page/section_resource.rb +1 -1
- data/app/views/para/admin/resources/_navigation.html.haml +10 -0
- data/app/views/para/admin/shared/_navigation.html.haml +2 -2
- data/config/locales/en.yml +4 -7
- data/db/migrate/20201210152223_add_parent_component_to_para_components.rb +6 -0
- data/lib/para/components_configuration.rb +64 -13
- data/lib/para/markup/resources_table.rb +2 -2
- data/lib/para/version.rb +1 -1
- metadata +6 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: eaabbc24f0c6d28e69cf3ebc0d837ffb52dc6abd1286a2ab6c23b0c8767e7a9d
|
4
|
+
data.tar.gz: 5f7e0609618d87d13d27b8132c2a6a7aa6a46e365c4dc9c7ac1a687f843ceca7
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 2d16ba804ed07daac026531e17c0f669a2cada924db5a22d87bff4b44018c3720dcf2177600bd6133dcba9c6da97a2a0a0253e3fbe6111ae24036f12596010be
|
7
|
+
data.tar.gz: 31cf72e15c979a0b24f1aa18cb736b9d1c56b4af88057fe730b5375dd3b8e7fe4bbd034f5f38232ffb900cc6b591480dacfdff4742fdd36f23d3c56a14a116c6
|
@@ -5,8 +5,10 @@ module Para
|
|
5
5
|
#
|
6
6
|
def admin_component_sections
|
7
7
|
@admin_component_sections ||= begin
|
8
|
-
Para::ComponentSection.ordered.includes(:components)
|
9
|
-
|
8
|
+
sections = Para::ComponentSection.ordered.includes(:components, :parent_component)
|
9
|
+
|
10
|
+
sections.tap do |loaded_sections|
|
11
|
+
loaded_sections.flat_map(&:components).each(&method(:decorate))
|
10
12
|
end
|
11
13
|
end
|
12
14
|
end
|
@@ -23,5 +25,11 @@ module Para
|
|
23
25
|
config = Para.components.component_configuration_for(component.identifier)
|
24
26
|
!config.shown_if || instance_exec(&config.shown_if)
|
25
27
|
end
|
28
|
+
|
29
|
+
def current_component_or_parent?(component)
|
30
|
+
return false unless @component
|
31
|
+
|
32
|
+
@component == component || @component.parent_component == component
|
33
|
+
end
|
26
34
|
end
|
27
35
|
end
|
@@ -2,13 +2,17 @@ module Para
|
|
2
2
|
module Admin
|
3
3
|
module PageHelper
|
4
4
|
def page_top_bar(options = {})
|
5
|
-
content_tag(:div, class: 'page-title row') do
|
5
|
+
top_bar = content_tag(:div, class: 'page-title row') do
|
6
6
|
content_tag(:h1, options[:title]) +
|
7
7
|
|
8
8
|
if (actions = actions_for(options[:type]))
|
9
9
|
actions.map(&method(:build_action)).join('').html_safe
|
10
10
|
end
|
11
11
|
end
|
12
|
+
|
13
|
+
# Return both top bar and component navigation to be displayed at the top of the
|
14
|
+
# page.
|
15
|
+
top_bar + component_navigation
|
12
16
|
end
|
13
17
|
|
14
18
|
def build_action(action)
|
@@ -30,6 +34,26 @@ module Para
|
|
30
34
|
instance_eval(&action)
|
31
35
|
end.compact
|
32
36
|
end
|
37
|
+
|
38
|
+
def component_navigation
|
39
|
+
parent_component = @component && (
|
40
|
+
@component.parent_component ||
|
41
|
+
@component.child_components.any? && @component
|
42
|
+
)
|
43
|
+
|
44
|
+
return unless parent_component
|
45
|
+
|
46
|
+
# If the component has a `model_type` option, therefore, an associated model,
|
47
|
+
# we try to render the partial from the relative path of the model, else we
|
48
|
+
# use the component class as the base target path
|
49
|
+
partial_target = parent_component.try(:model_type) || parent_component
|
50
|
+
|
51
|
+
render partial: find_partial_for(partial_target, :navigation),
|
52
|
+
locals: {
|
53
|
+
parent_component: parent_component,
|
54
|
+
active_component: @component
|
55
|
+
}
|
56
|
+
end
|
33
57
|
end
|
34
58
|
end
|
35
59
|
end
|
@@ -19,9 +19,13 @@ module Para
|
|
19
19
|
attributes = model_field_mappings(model).fields
|
20
20
|
relation = options.fetch(:relation, model.name.to_s.underscore.pluralize)
|
21
21
|
allow_adding_resource = options.fetch(:addable, true)
|
22
|
+
force_list = options.fetch(:force_list, false)
|
22
23
|
|
23
|
-
partial = :
|
24
|
-
|
24
|
+
partial = if !force_list && model.respond_to?(:roots) && can?(:tree, model)
|
25
|
+
:tree
|
26
|
+
else
|
27
|
+
:list
|
28
|
+
end
|
25
29
|
|
26
30
|
render(
|
27
31
|
partial: find_partial_for(relation, partial),
|
@@ -0,0 +1,20 @@
|
|
1
|
+
module Para
|
2
|
+
# Base class for all para-specific models.
|
3
|
+
#
|
4
|
+
class ApplicationRecord < ActiveRecord::Base
|
5
|
+
self.abstract_class = true
|
6
|
+
|
7
|
+
private
|
8
|
+
|
9
|
+
# Adds the `optional: true` option to the belongs_to calls inside the provided block,
|
10
|
+
# but only for Rails 5.1+
|
11
|
+
#
|
12
|
+
def self.with_belongs_to_optional_option_if_needed(&block)
|
13
|
+
if ActiveRecord::Associations::Builder::BelongsTo.valid_options({}).include?(:optional)
|
14
|
+
with_options(optional: true, &block)
|
15
|
+
else
|
16
|
+
block.call
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -1,6 +1,6 @@
|
|
1
1
|
module Para
|
2
2
|
module Component
|
3
|
-
class Base <
|
3
|
+
class Base < Para::ApplicationRecord
|
4
4
|
self.table_name = 'para_components'
|
5
5
|
|
6
6
|
class_attribute :component_name
|
@@ -16,7 +16,14 @@ module Para
|
|
16
16
|
|
17
17
|
configurable_on :controller
|
18
18
|
|
19
|
-
|
19
|
+
with_belongs_to_optional_option_if_needed do
|
20
|
+
belongs_to :component_section, class_name: 'Para::ComponentSection'
|
21
|
+
belongs_to :parent_component, class_name: 'Para::Component::Base'
|
22
|
+
end
|
23
|
+
|
24
|
+
has_many :child_components, -> { ordered },
|
25
|
+
class_name: 'Para::Component::Base',
|
26
|
+
foreign_key: 'parent_component_id'
|
20
27
|
|
21
28
|
validates :identifier, :type, presence: true
|
22
29
|
|
@@ -31,6 +38,13 @@ module Para
|
|
31
38
|
)
|
32
39
|
end
|
33
40
|
|
41
|
+
def main_navigation_name
|
42
|
+
::I18n.t(
|
43
|
+
"components.main_navigation.#{ identifier }",
|
44
|
+
default: name
|
45
|
+
)
|
46
|
+
end
|
47
|
+
|
34
48
|
def exportable?
|
35
49
|
false
|
36
50
|
end
|
@@ -1,21 +1,14 @@
|
|
1
1
|
module Para
|
2
2
|
module Page
|
3
|
-
class Section <
|
3
|
+
class Section < Para::ApplicationRecord
|
4
4
|
self.table_name = 'para_page_sections'
|
5
5
|
|
6
6
|
acts_as_orderable parent: :page, as: :sections
|
7
7
|
|
8
|
-
|
9
|
-
|
10
|
-
# Make Rails 5+ belongs_to relation optional for the parent page, to allow
|
11
|
-
# using sections in other contexts that directly included into pages
|
12
|
-
#
|
13
|
-
if ActiveRecord::Associations::Builder::BelongsTo.valid_options({}).include?(:optional)
|
14
|
-
page_relation_options[:optional] = true
|
8
|
+
with_belongs_to_optional_option_if_needed do
|
9
|
+
belongs_to :page, polymorphic: true
|
15
10
|
end
|
16
11
|
|
17
|
-
belongs_to :page, page_relation_options
|
18
|
-
|
19
12
|
def css_class
|
20
13
|
@css_class ||= self.class.name.demodulize.underscore.gsub(/_/, '-')
|
21
14
|
end
|
@@ -0,0 +1,10 @@
|
|
1
|
+
.top-nav-tabs-affix-placeholder
|
2
|
+
%ul.top-nav-tabs-affix.nav.nav-tabs{ role: "tablist", "data-top-level-affix": true }
|
3
|
+
%li{ class: ("active" if active_component == parent_component) }
|
4
|
+
= link_to parent_component.path do
|
5
|
+
= parent_component.name
|
6
|
+
|
7
|
+
- parent_component.child_components.each do |child_component|
|
8
|
+
%li{ class: ("active" if active_component == child_component) }
|
9
|
+
= link_to child_component.path do
|
10
|
+
= child_component.name
|
@@ -15,8 +15,8 @@
|
|
15
15
|
%ul.component-section-list-items.collapse.in{ id: "collapse-section-#{index}" }
|
16
16
|
- component_section.components.each do |component|
|
17
17
|
- if can?(:manage, component) && show_component?(component)
|
18
|
-
%li.component-item{ class: (
|
19
|
-
= link_to component.
|
18
|
+
%li.component-item{ class: ('active' if current_component_or_parent?(component)) }
|
19
|
+
= link_to component.main_navigation_name, component.path
|
20
20
|
|
21
21
|
- else
|
22
22
|
%li.component-section-item
|
data/config/locales/en.yml
CHANGED
@@ -13,14 +13,14 @@ en:
|
|
13
13
|
error: "Could not delete %{model}"
|
14
14
|
clone:
|
15
15
|
success: "%{model} cloned"
|
16
|
-
error: "Could not clone %{model}"
|
17
|
-
|
16
|
+
error: "Could not clone %{model}"
|
17
|
+
|
18
18
|
jobs:
|
19
19
|
para/importer/base:
|
20
20
|
progressing: "The file is being imported, please wait a few moments ..."
|
21
21
|
success: "The import of the file was successfully completed"
|
22
22
|
success_with_errors: |
|
23
|
-
The import of the file was done, but some lines
|
23
|
+
The import of the file was done, but some lines
|
24
24
|
were not taken into account due to errors :
|
25
25
|
other_errors: "<br>And <b>%{count}</b> others errors ..."
|
26
26
|
error: "The selected file contains errors and could not be imported"
|
@@ -40,9 +40,6 @@ en:
|
|
40
40
|
confirmation:
|
41
41
|
shared:
|
42
42
|
destroy: 'Are you sure that you want to delete %{model} ?'
|
43
|
-
|
44
|
-
component:
|
45
|
-
none_created: "No components yet ..."
|
46
43
|
|
47
44
|
component:
|
48
45
|
create: "Create a component"
|
@@ -146,7 +143,7 @@ en:
|
|
146
143
|
type: "Type"
|
147
144
|
model_type: "Resource"
|
148
145
|
namespaced: "Only list component's resources"
|
149
|
-
|
146
|
+
|
150
147
|
activemodel:
|
151
148
|
models:
|
152
149
|
settings_rails/form:
|
@@ -1,7 +1,7 @@
|
|
1
1
|
module Para
|
2
2
|
class ComponentsConfiguration
|
3
|
-
class UndefinedComponentTypeError < StandardError
|
4
|
-
end
|
3
|
+
class UndefinedComponentTypeError < StandardError; end
|
4
|
+
class ComponentTooDeepError < StandardError; end
|
5
5
|
|
6
6
|
def draw(&block)
|
7
7
|
return unless components_installed?
|
@@ -48,7 +48,24 @@ module Para
|
|
48
48
|
end
|
49
49
|
|
50
50
|
def component_configuration_for(identifier)
|
51
|
-
sections.
|
51
|
+
sections.each do |section|
|
52
|
+
section.components.each do |component|
|
53
|
+
# If one of the section component has the searched identifier return it
|
54
|
+
if component.identifier.to_s == identifier.to_s
|
55
|
+
return component
|
56
|
+
else
|
57
|
+
component.child_components.each do |child_component|
|
58
|
+
# If one of the component children has the searched identifier return it
|
59
|
+
if child_component.identifier.to_s == identifier.to_s
|
60
|
+
return child_component
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
# Return nil if the identifier was not found
|
68
|
+
nil
|
52
69
|
end
|
53
70
|
|
54
71
|
private
|
@@ -60,6 +77,10 @@ module Para
|
|
60
77
|
|
61
78
|
section.components.each do |component|
|
62
79
|
components_ids_hash[component.identifier] = component.model.id
|
80
|
+
|
81
|
+
component.child_components.each do |child_component|
|
82
|
+
components_ids_hash[child_component.identifier] = child_component.model.id
|
83
|
+
end
|
63
84
|
end
|
64
85
|
end
|
65
86
|
end
|
@@ -129,8 +150,8 @@ module Para
|
|
129
150
|
instance_eval(&block)
|
130
151
|
end
|
131
152
|
|
132
|
-
def component(*args)
|
133
|
-
components << Component.new(*args)
|
153
|
+
def component(*args, &block)
|
154
|
+
components << Component.new(*args, &block)
|
134
155
|
end
|
135
156
|
|
136
157
|
def components
|
@@ -149,13 +170,17 @@ module Para
|
|
149
170
|
end
|
150
171
|
|
151
172
|
class Component
|
152
|
-
attr_accessor :identifier, :type, :shown_if, :options, :model
|
173
|
+
attr_accessor :identifier, :type, :shown_if, :options, :model, :parent
|
153
174
|
|
154
|
-
def initialize(identifier, type_identifier, shown_if: nil, **options)
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
175
|
+
def initialize(identifier, type_identifier, shown_if: nil, **options, &block)
|
176
|
+
@identifier = identifier.to_s
|
177
|
+
@type = Para::Component.registered_components[type_identifier]
|
178
|
+
@options = options
|
179
|
+
@shown_if = shown_if
|
180
|
+
@parent = options.delete(:parent)
|
181
|
+
|
182
|
+
# Build child components if a block is provided
|
183
|
+
instance_eval(&block) if block
|
159
184
|
|
160
185
|
unless type
|
161
186
|
raise UndefinedComponentTypeError.new(
|
@@ -165,10 +190,29 @@ module Para
|
|
165
190
|
end
|
166
191
|
end
|
167
192
|
|
193
|
+
def component(*args, **child_options, &block)
|
194
|
+
# Do not allow nesting components more than one level as the display of illimited
|
195
|
+
# child nesting deepness is not implemented
|
196
|
+
if parent
|
197
|
+
raise ComponentTooDeepError, "Cannot nest components more than one level"
|
198
|
+
end
|
199
|
+
|
200
|
+
child_component_options = child_options.merge(parent: self)
|
201
|
+
child_components << Component.new(*args, **child_component_options, &block)
|
202
|
+
end
|
203
|
+
|
204
|
+
def child_components
|
205
|
+
@child_components ||= []
|
206
|
+
end
|
207
|
+
|
168
208
|
def refresh(attributes = {})
|
169
|
-
|
209
|
+
@model = type.where(identifier: identifier).first_or_initialize
|
170
210
|
model.update_with(attributes.merge(options_with_defaults))
|
171
211
|
model.save!
|
212
|
+
|
213
|
+
child_components.each_with_index do |child_component, child_index|
|
214
|
+
child_component.refresh(component_section: nil, position: child_index)
|
215
|
+
end
|
172
216
|
end
|
173
217
|
|
174
218
|
# Ensures unset :configuration store options are set to nil to allow
|
@@ -179,7 +223,14 @@ module Para
|
|
179
223
|
configurable_keys += options.keys
|
180
224
|
configurable_keys.uniq!
|
181
225
|
|
182
|
-
|
226
|
+
options_with_defaults = {}
|
227
|
+
|
228
|
+
# Assign parent component resource to the final attribute options, assigning nil
|
229
|
+
# if the `:parent` option is empty, to allow extracting a component from its
|
230
|
+
# parent by just moving the component call outside of its parent block.
|
231
|
+
options_with_defaults[:parent_component] = parent&.model
|
232
|
+
|
233
|
+
configurable_keys.each_with_object(options_with_defaults) do |key, hash|
|
183
234
|
hash[key] = options[key]
|
184
235
|
end
|
185
236
|
end
|
@@ -92,9 +92,9 @@ module Para
|
|
92
92
|
end
|
93
93
|
|
94
94
|
content_tag(:th, options) do
|
95
|
-
if (sort = options.delete(:sort))
|
95
|
+
if search && (sort = options.delete(:sort))
|
96
96
|
view.sort_link(search, *sort, label, hide_indicator: true)
|
97
|
-
elsif searchable?(field_name)
|
97
|
+
elsif search && searchable?(field_name)
|
98
98
|
view.sort_link(search, field_name, label, hide_indicator: true)
|
99
99
|
else
|
100
100
|
label
|
data/lib/para/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: para
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.8.
|
4
|
+
version: 0.8.15
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Valentin Ballestrino
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2020-
|
11
|
+
date: 2020-12-22 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rails
|
@@ -595,6 +595,7 @@ files:
|
|
595
595
|
- app/helpers/para/tree_helper.rb
|
596
596
|
- app/models/application_record.rb
|
597
597
|
- app/models/para/ability.rb
|
598
|
+
- app/models/para/application_record.rb
|
598
599
|
- app/models/para/cache/item.rb
|
599
600
|
- app/models/para/component/base.rb
|
600
601
|
- app/models/para/component/crud.rb
|
@@ -629,6 +630,7 @@ files:
|
|
629
630
|
- app/views/para/admin/resources/_form.html.haml
|
630
631
|
- app/views/para/admin/resources/_imports_menu.html.haml
|
631
632
|
- app/views/para/admin/resources/_list.html.haml
|
633
|
+
- app/views/para/admin/resources/_navigation.html.haml
|
632
634
|
- app/views/para/admin/resources/_per_page_select.html.haml
|
633
635
|
- app/views/para/admin/resources/_remote_nested_form.html.haml
|
634
636
|
- app/views/para/admin/resources/_subclassable_add_button.html.haml
|
@@ -670,6 +672,7 @@ files:
|
|
670
672
|
- db/migrate/20160905134106_create_para_library_files.rb
|
671
673
|
- db/migrate/20161006105728_create_para_cache_items.rb
|
672
674
|
- db/migrate/20170324125547_create_para_page_section_resources.rb
|
675
|
+
- db/migrate/20201210152223_add_parent_component_to_para_components.rb
|
673
676
|
- lib/generators/para/admin_user/admin_user_generator.rb
|
674
677
|
- lib/generators/para/component/component_generator.rb
|
675
678
|
- lib/generators/para/component/crud/crud_generator.rb
|
@@ -851,8 +854,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
851
854
|
- !ruby/object:Gem::Version
|
852
855
|
version: '0'
|
853
856
|
requirements: []
|
854
|
-
|
855
|
-
rubygems_version: 2.6.11
|
857
|
+
rubygems_version: 3.1.4
|
856
858
|
signing_key:
|
857
859
|
specification_version: 4
|
858
860
|
summary: Rails admin engine
|