para 0.8.9 → 0.8.14
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 +5 -5
- data/app/assets/stylesheets/para/admin/src/_list.sass +7 -3
- data/app/helpers/para/admin/components_helper.rb +4 -2
- data/app/helpers/para/admin/page_helper.rb +30 -3
- 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/job/base.rb +2 -2
- 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: 4fdbe5ef6d030b3f6aca6f18209211742914f15de7965bc583190a4480921e0e
|
4
|
+
data.tar.gz: aa514928922edf16906fb54f40027a9afc208e5327c00e1fee34ac24c66bb748
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 242dee3461cd57765d4f3b57e32073cb0a30a863e6bb59858891b621c989a36a1c189924bd78f237b25cc6890149816ab9a4f189b9d093465f7483664f525ac7
|
7
|
+
data.tar.gz: a15d5cdab40b3a00b46401b405bd007774bc119dceaf7d6f8423808a2673fafc2e5abf20961bf5176892e6ba670e88c61637d3d9d4a6f10a63ffae3b4f90b5f5
|
@@ -9,7 +9,11 @@
|
|
9
9
|
.actions-control
|
10
10
|
list-style: none
|
11
11
|
padding: 0
|
12
|
-
margin: 0
|
12
|
+
margin: 0 15px 0 0
|
13
|
+
|
14
|
+
&:last-child
|
15
|
+
margin-right: 0
|
16
|
+
|
13
17
|
li
|
14
18
|
+inline-block
|
15
19
|
padding: 0 5px
|
@@ -42,7 +46,7 @@
|
|
42
46
|
|
43
47
|
.page-list-heading
|
44
48
|
border-bottom: 1px solid $gray-light
|
45
|
-
|
49
|
+
|
46
50
|
.page-list-body:last-child
|
47
51
|
padding-bottom: 0
|
48
52
|
|
@@ -76,7 +80,7 @@
|
|
76
80
|
color: $gray
|
77
81
|
border-color: transparent
|
78
82
|
&:hover
|
79
|
-
color: $gray-dark
|
83
|
+
color: $gray-dark
|
80
84
|
|
81
85
|
|
82
86
|
.page-entries-info
|
@@ -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
|
@@ -2,18 +2,25 @@ 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)
|
15
|
-
|
16
|
-
|
19
|
+
link_options = action.fetch(:link_options, {})
|
20
|
+
link_options[:class] ||= "btn btn-default btn-shadow"
|
21
|
+
|
22
|
+
content_tag(:div, class: 'actions-control pull-right') do
|
23
|
+
link_to(action[:url], link_options) do
|
17
24
|
(
|
18
25
|
(fa_icon(action[:icon], class: 'fa-fw') if action[:icon]) +
|
19
26
|
action[:label]
|
@@ -27,6 +34,26 @@ module Para
|
|
27
34
|
instance_eval(&action)
|
28
35
|
end.compact
|
29
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
|
30
57
|
end
|
31
58
|
end
|
32
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: (@component == component) && 'active' }
|
19
|
-
= link_to component.
|
18
|
+
%li.component-item{ class: (@component == component || @component.parent_component == component) && 'active' }
|
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
|
data/lib/para/job/base.rb
CHANGED
@@ -33,9 +33,9 @@ module Para
|
|
33
33
|
end
|
34
34
|
|
35
35
|
def ensure_total_progress
|
36
|
-
return if @
|
36
|
+
return if @_total_progress
|
37
37
|
|
38
|
-
@
|
38
|
+
@_total_progress ||= if respond_to?(:total_progress, true)
|
39
39
|
progress.total = total_progress
|
40
40
|
else
|
41
41
|
progress[:total]
|
@@ -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.14
|
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-21 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
|