para 0.11.4 → 0.12.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/app/assets/stylesheets/para/admin/main.scss +31 -0
- data/app/assets/stylesheets/para/admin/src/_affix.scss +7 -0
- data/app/assets/stylesheets/para/admin/src/_alert.scss +35 -0
- data/app/assets/stylesheets/para/admin/src/_base.scss +63 -0
- data/app/assets/stylesheets/para/admin/src/_bootstrap-variables.scss +766 -379
- data/app/assets/stylesheets/para/admin/src/_breadcrumb.scss +37 -0
- data/app/assets/stylesheets/para/admin/src/_buttons.scss +128 -0
- data/app/assets/stylesheets/para/admin/src/_checkable.scss +106 -0
- data/app/assets/stylesheets/para/admin/src/_common.scss +250 -0
- data/app/assets/stylesheets/para/admin/src/_dropdown.scss +52 -0
- data/app/assets/stylesheets/para/admin/src/_form.scss +359 -0
- data/app/assets/stylesheets/para/admin/src/_list.scss +96 -0
- data/app/assets/stylesheets/para/admin/src/_mixins.scss +109 -0
- data/app/assets/stylesheets/para/admin/src/_multi-select.scss +110 -0
- data/app/assets/stylesheets/para/admin/src/_navigation.scss +210 -0
- data/app/assets/stylesheets/para/admin/src/_navtabs.scss +68 -0
- data/app/assets/stylesheets/para/admin/src/_nested-many.scss +87 -0
- data/app/assets/stylesheets/para/admin/src/_nested_one.scss +26 -0
- data/app/assets/stylesheets/para/admin/src/_orderable.scss +48 -0
- data/app/assets/stylesheets/para/admin/src/_page-loading.scss +40 -0
- data/app/assets/stylesheets/para/admin/src/_pagination.scss +39 -0
- data/app/assets/stylesheets/para/admin/src/_panel.scss +61 -0
- data/app/assets/stylesheets/para/admin/src/_responsive.scss +133 -0
- data/app/assets/stylesheets/para/admin/src/_sorting.scss +43 -0
- data/app/assets/stylesheets/para/admin/src/_statcard.scss +46 -0
- data/app/assets/stylesheets/para/admin/src/_table.scss +36 -0
- data/app/assets/stylesheets/para/admin/src/_tree.scss +60 -0
- data/app/assets/stylesheets/para/admin/src/{_variables.sass → _variables.scss} +7 -7
- data/app/assets/stylesheets/para/admin/src/{_well.sass → _well.scss} +5 -4
- data/app/assets/stylesheets/para/admin.scss +15 -0
- data/app/assets/stylesheets/para/index.scss +1 -0
- data/app/assets/stylesheets/para/lib/datetimepicker.scss +15 -0
- data/app/assets/stylesheets/para/lib/fuelux.scss +46 -0
- data/app/assets/stylesheets/para/lib/jasny-bootstrap.scss +100 -0
- data/app/assets/stylesheets/para/lib/selectize.scss +129 -0
- data/app/assets/stylesheets/para/lib/slider.scss +14 -0
- data/app/controllers/para/admin/crud_resources_controller.rb +16 -9
- data/app/controllers/para/admin/imports_controller.rb +9 -9
- data/app/controllers/para/admin/jobs_controller.rb +7 -1
- data/app/controllers/para/admin/resources_controller.rb +17 -18
- data/app/controllers/para/admin/settings_component_controller.rb +2 -2
- data/app/helpers/para/admin/base_helper.rb +36 -25
- data/app/helpers/para/admin/page_helper.rb +8 -9
- data/app/helpers/para/flash_helper.rb +7 -28
- data/app/helpers/para/model_helper.rb +5 -8
- data/app/helpers/para/tree_helper.rb +4 -4
- data/app/javascripts/para/admin/async-progress.js +58 -0
- data/app/javascripts/para/admin/filters-form.js +12 -0
- data/app/javascripts/para/admin/job-tracker.js +33 -0
- data/app/javascripts/para/admin/table.js +58 -0
- data/app/javascripts/para/admin/tabs.js +110 -0
- data/app/javascripts/para/admin/theme_actions.js +39 -0
- data/app/javascripts/para/admin/tree.js +124 -0
- data/app/javascripts/para/application.js +2 -0
- data/app/javascripts/para/controllers/application.js +17 -0
- data/app/javascripts/para/controllers/index.js +10 -0
- data/app/javascripts/para/controllers/para_admin_flash_message_controller.js +48 -0
- data/app/javascripts/para/controllers/para_admin_modal_controller.js +43 -0
- data/app/javascripts/para/controllers/selectize_field_controller.js +142 -0
- data/app/javascripts/para/index.js +31 -0
- data/app/javascripts/para/inputs/material-input.js +7 -0
- data/app/javascripts/para/inputs/multi-select-input.js +343 -0
- data/app/javascripts/para/inputs/nested_many.js +151 -0
- data/app/javascripts/para/lib/fetch.js +41 -0
- data/app/javascripts/para/lib/page-loading.js +42 -0
- data/app/javascripts/para/simple_form_extension/colorpicker.js +30 -0
- data/app/javascripts/para/simple_form_extension/datetimepicker.js +115 -0
- data/app/javascripts/para/simple_form_extension/fileinput.js +57 -0
- data/app/javascripts/para/simple_form_extension/index.js +12 -0
- data/app/javascripts/para/simple_form_extension/selectize.js +160 -0
- data/app/javascripts/para/simple_form_extension/simple_form_extension_initialization.js +62 -0
- data/app/javascripts/para/simple_form_extension/slider.js +43 -0
- data/app/javascripts/para/simple_form_extension/spinbox.js +35 -0
- data/app/javascripts/para/vendor/bootstrap-colorpicker.js +1025 -0
- data/app/javascripts/para/vendor/bootstrap-slider.js +1610 -0
- data/app/javascripts/para/vendor/cocoon.js +150 -0
- data/app/javascripts/para/vendor/jquery.datetimepicker.js +2156 -0
- data/app/javascripts/para/vendor/jquery.js +3 -0
- data/app/javascripts/para/vendor/spinbox.js +438 -0
- data/app/javascripts/para/vendor/vertebra.js +224 -0
- data/app/views/admin/para/exporter/bases/_completed.html.haml +1 -1
- data/app/views/layouts/para/admin.html.haml +4 -2
- data/app/views/para/admin/imports/new.html.haml +12 -11
- data/app/views/para/admin/jobs/_completed.html.haml +1 -1
- data/app/views/para/admin/jobs/_failed.html.haml +1 -1
- data/app/views/para/admin/jobs/_job.html.haml +11 -0
- data/app/views/para/admin/jobs/show.html.haml +1 -10
- data/app/views/para/admin/resources/_add_button.html.haml +1 -1
- data/app/views/para/admin/resources/_exports_menu.html.haml +2 -2
- data/app/views/para/admin/resources/_filters.html.haml +1 -1
- data/app/views/para/admin/resources/_imports_menu.html.haml +2 -2
- data/app/views/para/admin/resources/_list.html.haml +27 -26
- data/app/views/para/admin/resources/_navigation.html.haml +10 -11
- data/app/views/para/admin/resources/_subclassable_add_button.html.haml +1 -1
- data/app/views/para/admin/shared/_flash.html.haml +18 -0
- data/app/views/para/admin/shared/_header.html.haml +1 -1
- data/app/views/para/form/_tabs.html.haml +1 -1
- data/app/views/para/inputs/_nested_many.html.haml +3 -3
- data/app/views/para/inputs/nested_many/_add.html.haml +1 -1
- data/app/views/para/inputs/nested_many/_add_with_subclasses.html.haml +2 -2
- data/app/views/para/inputs/nested_many/_container.html.haml +1 -1
- data/config/locales/fr.yml +1 -0
- data/lib/generators/para/install/install_generator.rb +10 -14
- data/lib/para/attribute_field/base.rb +3 -0
- data/lib/para/attribute_field/wysiwyg_editor.rb +15 -0
- data/lib/para/attribute_field.rb +1 -1
- data/lib/para/components_configuration.rb +1 -1
- data/lib/para/engine.rb +20 -22
- data/lib/para/ext/turbo_stream.rb +13 -0
- data/lib/para/ext.rb +1 -1
- data/lib/para/form_builder/containers.rb +33 -22
- data/lib/para/form_builder/nested_form.rb +6 -5
- data/lib/para/inputs/nested_many_input.rb +5 -0
- data/lib/para/markup/modal.rb +30 -15
- data/lib/para/markup/resources_buttons.rb +15 -11
- data/lib/para/model_field_parsers/wysiwyg_editor.rb +19 -0
- data/lib/para/model_field_parsers.rb +1 -1
- data/lib/para/version.rb +1 -1
- data/lib/para.rb +2 -8
- data/lib/simple_form_extension/components/icons.rb +13 -0
- data/lib/simple_form_extension/components/popovers.rb +46 -0
- data/lib/simple_form_extension/components.rb +8 -0
- data/lib/simple_form_extension/ext/form_builder.rb +20 -0
- data/lib/simple_form_extension/file_concern.rb +74 -0
- data/lib/simple_form_extension/inputs/boolean_input.rb +16 -0
- data/lib/simple_form_extension/inputs/collection_check_boxes_input.rb +15 -0
- data/lib/simple_form_extension/inputs/collection_radio_buttons_input.rb +15 -0
- data/lib/simple_form_extension/inputs/color_input.rb +37 -0
- data/lib/simple_form_extension/inputs/date_time_input.rb +48 -0
- data/lib/simple_form_extension/inputs/file_input.rb +41 -0
- data/lib/simple_form_extension/inputs/image_input.rb +110 -0
- data/lib/simple_form_extension/inputs/numeric_input.rb +27 -0
- data/lib/simple_form_extension/inputs/selectize_input.rb +210 -0
- data/lib/simple_form_extension/inputs/slider_input.rb +30 -0
- data/lib/simple_form_extension/inputs.rb +16 -0
- data/lib/simple_form_extension/railtie.rb +21 -0
- data/lib/simple_form_extension/resource_name_helper.rb +9 -0
- data/lib/simple_form_extension/translations.rb +7 -0
- data/lib/simple_form_extension/version.rb +3 -0
- data/lib/simple_form_extension.rb +30 -0
- data/vendor/assets/images/simple_form_extension/bootstrap-colorpicker/alpha-horizontal.png +0 -0
- data/vendor/assets/images/simple_form_extension/bootstrap-colorpicker/alpha.png +0 -0
- data/vendor/assets/images/simple_form_extension/bootstrap-colorpicker/hue-horizontal.png +0 -0
- data/vendor/assets/images/simple_form_extension/bootstrap-colorpicker/hue.png +0 -0
- data/vendor/assets/images/simple_form_extension/bootstrap-colorpicker/saturation.png +0 -0
- data/vendor/assets/stylesheets/bootstrap-colorpicker.scss +227 -0
- data/vendor/assets/stylesheets/bootstrap-slider.scss +246 -0
- data/vendor/assets/stylesheets/bootstrap.scss +6032 -0
- data/vendor/assets/stylesheets/jquery.datetimepicker.scss +568 -0
- metadata +120 -188
- data/app/assets/javascripts/admin/app.coffee +0 -1
- data/app/assets/javascripts/para/admin/async-progress.coffee +0 -29
- data/app/assets/javascripts/para/admin/filters-form.coffee +0 -11
- data/app/assets/javascripts/para/admin/job-tracker.coffee +0 -39
- data/app/assets/javascripts/para/admin/table.coffee +0 -44
- data/app/assets/javascripts/para/admin/tabs.coffee +0 -63
- data/app/assets/javascripts/para/admin/theme_actions.coffee +0 -25
- data/app/assets/javascripts/para/admin/tree.coffee +0 -105
- data/app/assets/javascripts/para/admin.coffee +0 -22
- data/app/assets/javascripts/para/application.js +0 -13
- data/app/assets/javascripts/para/inputs/material-input.coffee +0 -4
- data/app/assets/javascripts/para/inputs/multi-select-input.coffee +0 -174
- data/app/assets/javascripts/para/inputs/nested_many.coffee +0 -108
- data/app/assets/javascripts/para/lib/ajax.coffee +0 -11
- data/app/assets/javascripts/para/lib/remote-file-forms.coffee +0 -59
- data/app/assets/javascripts/para/lib/turbolinks-forms.coffee +0 -23
- data/app/assets/javascripts/para/lib/turbolinks-loading.coffee +0 -25
- data/app/assets/javascripts/para/lib/turbolinks-reloader.coffee +0 -19
- data/app/assets/stylesheets/para/admin/main.sass +0 -33
- data/app/assets/stylesheets/para/admin/src/_affix.sass +0 -4
- data/app/assets/stylesheets/para/admin/src/_alert.sass +0 -17
- data/app/assets/stylesheets/para/admin/src/_base.sass +0 -54
- data/app/assets/stylesheets/para/admin/src/_breadcrumb.sass +0 -32
- data/app/assets/stylesheets/para/admin/src/_buttons.sass +0 -107
- data/app/assets/stylesheets/para/admin/src/_checkable.sass +0 -94
- data/app/assets/stylesheets/para/admin/src/_common.sass +0 -202
- data/app/assets/stylesheets/para/admin/src/_dropdown.sass +0 -40
- data/app/assets/stylesheets/para/admin/src/_form.sass +0 -299
- data/app/assets/stylesheets/para/admin/src/_list.sass +0 -89
- data/app/assets/stylesheets/para/admin/src/_mixins.sass +0 -113
- data/app/assets/stylesheets/para/admin/src/_multi-select.sass +0 -91
- data/app/assets/stylesheets/para/admin/src/_navigation.sass +0 -171
- data/app/assets/stylesheets/para/admin/src/_navtabs.sass +0 -58
- data/app/assets/stylesheets/para/admin/src/_nested-many.sass +0 -75
- data/app/assets/stylesheets/para/admin/src/_nested_one.sass +0 -22
- data/app/assets/stylesheets/para/admin/src/_orderable.sass +0 -44
- data/app/assets/stylesheets/para/admin/src/_page-loading.sass +0 -39
- data/app/assets/stylesheets/para/admin/src/_pagination.sass +0 -34
- data/app/assets/stylesheets/para/admin/src/_panel.sass +0 -55
- data/app/assets/stylesheets/para/admin/src/_responsive.sass +0 -117
- data/app/assets/stylesheets/para/admin/src/_sorting.sass +0 -36
- data/app/assets/stylesheets/para/admin/src/_statcard.sass +0 -41
- data/app/assets/stylesheets/para/admin/src/_table.sass +0 -33
- data/app/assets/stylesheets/para/admin/src/_tree.sass +0 -52
- data/app/assets/stylesheets/para/admin.sass +0 -12
- data/app/assets/stylesheets/para/lib/compass/_support.scss +0 -447
- data/app/assets/stylesheets/para/lib/compass/css3/_box-shadow.scss +0 -88
- data/app/assets/stylesheets/para/lib/compass/css3/_images.scss +0 -152
- data/app/assets/stylesheets/para/lib/compass/css3/_inline-block.scss +0 -31
- data/app/assets/stylesheets/para/lib/compass/css3/_text-shadow.scss +0 -82
- data/app/assets/stylesheets/para/lib/compass/css3/_transform.scss +0 -590
- data/app/assets/stylesheets/para/lib/compass/css3/_transition.scss +0 -190
- data/app/assets/stylesheets/para/lib/compass/css3/_user-interface.scss +0 -71
- data/app/assets/stylesheets/para/lib/compass/utilities/general/_hacks.scss +0 -65
- data/app/assets/stylesheets/para/lib/datetimepicker.sass +0 -15
- data/app/assets/stylesheets/para/lib/fuelux.sass +0 -40
- data/app/assets/stylesheets/para/lib/jasny-bootstrap.sass +0 -97
- data/app/assets/stylesheets/para/lib/redactor.sass +0 -86
- data/app/assets/stylesheets/para/lib/selectize.sass +0 -111
- data/app/assets/stylesheets/para/lib/slider.sass +0 -12
- data/app/assets/stylesheets/para/plugins-includes.sass.erb +0 -1
- data/lib/para/attribute_field/redactor.rb +0 -22
- data/lib/para/ext/request_iframe_xhr.rb +0 -17
- data/lib/para/iframe_transport/middleware.rb +0 -58
- data/lib/para/iframe_transport.rb +0 -7
- data/lib/para/model_field_parsers/redactor.rb +0 -19
- data/vendor/assets/javascripts/jquery.iframe-transport.js +0 -260
- data/vendor/assets/javascripts/jquery.remote-modal-form.coffee +0 -145
- /data/app/assets/stylesheets/admin/{app.sass → app.scss} +0 -0
- /data/app/{assets/javascripts → javascripts}/para/plugins-includes.js.erb +0 -0
- /data/{vendor/assets/javascripts → app/javascripts/para/vendor}/Sortable.js +0 -0
- /data/{vendor/assets/javascripts → app/javascripts/para/vendor}/jasny-bootstrap.js +0 -0
- /data/{vendor/assets/javascripts → app/javascripts/para/vendor}/jquery.scrollto.js +0 -0
- /data/{vendor/assets/javascripts → app/javascripts/para/vendor}/jquery.sortable.js +0 -0
- /data/vendor/assets/stylesheets/{animate.css → animate.scss} +0 -0
- /data/vendor/assets/stylesheets/{hint.css → hint.scss} +0 -0
- /data/vendor/assets/stylesheets/{jasny-bootstrap.css → jasny-bootstrap.scss} +0 -0
@@ -25,10 +25,10 @@ module Para
|
|
25
25
|
|
26
26
|
if resource.save
|
27
27
|
flash_message(:success, resource)
|
28
|
-
redirect_to after_form_submit_path
|
28
|
+
redirect_to after_form_submit_path, status: 303
|
29
29
|
else
|
30
30
|
flash_message(:error, resource)
|
31
|
-
render 'new'
|
31
|
+
render 'new', status: 422
|
32
32
|
end
|
33
33
|
end
|
34
34
|
|
@@ -39,17 +39,17 @@ module Para
|
|
39
39
|
def update
|
40
40
|
if resource.update(resource_params)
|
41
41
|
flash_message(:success, resource)
|
42
|
-
redirect_to after_form_submit_path
|
42
|
+
redirect_to after_form_submit_path, status: 303
|
43
43
|
else
|
44
44
|
flash_message(:error, resource)
|
45
|
-
render 'edit'
|
45
|
+
render 'edit', status: 422
|
46
46
|
end
|
47
47
|
end
|
48
48
|
|
49
49
|
def destroy
|
50
50
|
resource.destroy
|
51
51
|
flash_message(:success, resource)
|
52
|
-
redirect_to after_form_submit_path
|
52
|
+
redirect_to after_form_submit_path, status: 303
|
53
53
|
end
|
54
54
|
|
55
55
|
def order
|
@@ -86,7 +86,12 @@ module Para
|
|
86
86
|
host_redirect_params.merge(
|
87
87
|
action: 'edit',
|
88
88
|
id: resource.id,
|
89
|
-
anchor
|
89
|
+
# The `anchor` doesn't work with javascript's `fetch` async requests so we
|
90
|
+
# can't redirect an XHR request to an anchor, we need to pass it as an
|
91
|
+
# explicit param.
|
92
|
+
# See : https://github.com/hotwired/turbo/issues/211
|
93
|
+
_current_anchor: params[:_current_anchor].presence,
|
94
|
+
return_to: params[:return_to].presence
|
90
95
|
)
|
91
96
|
elsif params[:_save_and_add_another]
|
92
97
|
host_redirect_params.merge(
|
@@ -160,12 +165,12 @@ module Para
|
|
160
165
|
end
|
161
166
|
|
162
167
|
def self.ensure_resource_name_defined!
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
168
|
+
return if resource_name.presence
|
169
|
+
|
170
|
+
raise 'Resource not defined in your controller. ' \
|
171
|
+
'You can define the resource of your controller with the ' \
|
172
|
+
'`resource :resource_name` macro when subclassing ' \
|
173
|
+
'Para::Admin::ResourcesController'
|
169
174
|
end
|
170
175
|
|
171
176
|
def resources_data
|
@@ -182,12 +187,6 @@ module Para
|
|
182
187
|
end
|
183
188
|
end
|
184
189
|
end
|
185
|
-
|
186
|
-
def current_anchor
|
187
|
-
@current_anchor ||= if (current_anchor = params[:_current_anchor]).presence
|
188
|
-
current_anchor.gsub(/^\#/, '')
|
189
|
-
end
|
190
|
-
end
|
191
190
|
end
|
192
191
|
end
|
193
192
|
end
|
@@ -10,13 +10,13 @@ module Para
|
|
10
10
|
form.settings_attributes = settings_params[:settings_attributes]
|
11
11
|
form.save
|
12
12
|
flash_message(:success, form)
|
13
|
-
redirect_to admin_settings_path(@component)
|
13
|
+
redirect_to admin_settings_path(@component), status: 303
|
14
14
|
end
|
15
15
|
|
16
16
|
private
|
17
17
|
|
18
18
|
def settings_params
|
19
|
-
params.require(:resource).permit(settings_attributes: [
|
19
|
+
params.require(:resource).permit(settings_attributes: %i[key _type value])
|
20
20
|
end
|
21
21
|
end
|
22
22
|
end
|
@@ -5,10 +5,10 @@ module Para
|
|
5
5
|
|
6
6
|
def find_partial_for(relation, partial, partial_dir: 'admin/resources')
|
7
7
|
relation_class = if model?(relation.class)
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
8
|
+
relation = relation.class
|
9
|
+
elsif model?(relation)
|
10
|
+
relation
|
11
|
+
end
|
12
12
|
|
13
13
|
relation_name = find_relation_name_for(
|
14
14
|
plural_file_path_for(relation), partial,
|
@@ -17,9 +17,9 @@ module Para
|
|
17
17
|
)
|
18
18
|
|
19
19
|
if relation_name
|
20
|
-
"admin/#{
|
20
|
+
"admin/#{relation_name}/#{partial}"
|
21
21
|
else
|
22
|
-
"para/#{
|
22
|
+
"para/#{partial_dir}/#{partial}"
|
23
23
|
end
|
24
24
|
end
|
25
25
|
|
@@ -40,7 +40,7 @@ module Para
|
|
40
40
|
|
41
41
|
def template_path_lookup(*paths)
|
42
42
|
path = paths.find { |path| lookup_context.find_all(path).any? }
|
43
|
-
path&.gsub(
|
43
|
+
path&.gsub(%r{/_([^/]+)\z}, '/\1')
|
44
44
|
end
|
45
45
|
|
46
46
|
def resource_title_for(resource)
|
@@ -56,26 +56,37 @@ module Para
|
|
56
56
|
def registered_components_options
|
57
57
|
Para::Component.registered_components.keys.map do |identifier|
|
58
58
|
[
|
59
|
-
t("para.component.#{
|
59
|
+
t("para.component.#{identifier}.name", default: identifier.to_s.humanize),
|
60
60
|
identifier
|
61
61
|
]
|
62
62
|
end
|
63
63
|
end
|
64
64
|
|
65
|
-
def flash_message(type, resource = nil)
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
65
|
+
def flash_message(type, resource = nil, now: false)
|
66
|
+
flash_shared_key = 'para.flash.shared'
|
67
|
+
key_suffix = "#{params[:action]}.#{type}"
|
68
|
+
|
69
|
+
shared_key = "#{flash_shared_key}.#{key_suffix}"
|
70
|
+
|
71
|
+
shared_translation =
|
72
|
+
if resource
|
73
|
+
::I18n.t(shared_key, model: resource.class.model_name.human)
|
74
|
+
else
|
75
|
+
::I18n.t(shared_key)
|
76
|
+
end
|
77
|
+
|
78
|
+
translation =
|
79
|
+
if resource
|
80
|
+
::I18n.t(
|
81
|
+
"para.flash.#{resource.class.base_class.model_name.i18n_key}.#{key_suffix}",
|
82
|
+
default: shared_translation
|
83
|
+
)
|
84
|
+
else
|
85
|
+
shared_translation
|
86
|
+
end
|
87
|
+
|
88
|
+
flash_receiver = now ? flash.now : flash
|
89
|
+
flash_receiver[type] = translation
|
79
90
|
end
|
80
91
|
|
81
92
|
private
|
@@ -88,10 +99,10 @@ module Para
|
|
88
99
|
object.respond_to?(:model_name)
|
89
100
|
end
|
90
101
|
|
91
|
-
def partial_exists?(relation, partial, overrides_root: 'admin', **
|
102
|
+
def partial_exists?(relation, partial, overrides_root: 'admin', **_options)
|
92
103
|
partial_path = partial.to_s.split('/')
|
93
|
-
partial_path[-1] = "_#{
|
94
|
-
lookup_context.find_all("#{
|
104
|
+
partial_path[-1] = "_#{partial_path.last}"
|
105
|
+
lookup_context.find_all("#{overrides_root}/#{relation}/#{partial_path.join('/')}").any?
|
95
106
|
end
|
96
107
|
end
|
97
108
|
end
|
@@ -4,10 +4,9 @@ module Para
|
|
4
4
|
def page_top_bar(options = {})
|
5
5
|
top_bar = content_tag(:div, class: 'page-title row') do
|
6
6
|
content_tag(:h1, options[:title]) +
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
end
|
7
|
+
if (actions = actions_for(options[:type]))
|
8
|
+
actions.map(&method(:build_action)).join('').html_safe
|
9
|
+
end
|
11
10
|
end
|
12
11
|
|
13
12
|
# Return both top bar and component navigation to be displayed at the top of the
|
@@ -17,7 +16,7 @@ module Para
|
|
17
16
|
|
18
17
|
def build_action(action)
|
19
18
|
link_options = action.fetch(:link_options, {})
|
20
|
-
link_options[:class] ||=
|
19
|
+
link_options[:class] ||= 'btn btn-default btn-shadow btn-sm'
|
21
20
|
|
22
21
|
content_tag(:div, class: 'actions-control pull-right') do
|
23
22
|
link_to(action[:url], link_options) do
|
@@ -49,10 +48,10 @@ module Para
|
|
49
48
|
partial_target = parent_component.try(:model_type) || parent_component
|
50
49
|
|
51
50
|
render partial: find_partial_for(partial_target, :navigation),
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
51
|
+
locals: {
|
52
|
+
parent_component: parent_component,
|
53
|
+
active_component: @component
|
54
|
+
}
|
56
55
|
end
|
57
56
|
end
|
58
57
|
end
|
@@ -1,34 +1,13 @@
|
|
1
1
|
module Para
|
2
2
|
module FlashHelper
|
3
|
-
def
|
4
|
-
|
5
|
-
return "" if flash.empty?
|
6
|
-
|
7
|
-
# Make a div.alert for each message and join the whole
|
8
|
-
messages = flash.map do |type, message|
|
9
|
-
flash.delete(type)
|
10
|
-
type = homogenize_flash_type(type)
|
11
|
-
|
12
|
-
icon = content_tag(:div, class: "alert-icon-container pull-left") do
|
13
|
-
content_tag(:i, "", class: "fa #{ icon_class_for(type) }") +
|
14
|
-
' '.html_safe
|
15
|
-
end
|
16
|
-
|
17
|
-
alert(type: type) do
|
18
|
-
icon + content_tag(:p, message.html_safe)
|
19
|
-
end
|
20
|
-
end
|
21
|
-
|
22
|
-
# Join the messages and make sure markup is correctly displayed
|
23
|
-
messages.join.html_safe
|
3
|
+
def flash_partial_path
|
4
|
+
template_path_lookup('admin/shared/_flash', 'para/admin/shared/_flash')
|
24
5
|
end
|
25
6
|
|
26
|
-
private
|
27
|
-
|
28
7
|
# Converts flash types to :success or :error to conform to what
|
29
8
|
# twitter bootstrap can handle
|
30
9
|
#
|
31
|
-
def homogenize_flash_type
|
10
|
+
def homogenize_flash_type(type)
|
32
11
|
case type.to_sym
|
33
12
|
when :notice then :success
|
34
13
|
when :alert then :warning
|
@@ -37,11 +16,11 @@ module Para
|
|
37
16
|
end
|
38
17
|
end
|
39
18
|
|
40
|
-
def icon_class_for
|
19
|
+
def icon_class_for(type)
|
41
20
|
case type
|
42
|
-
when :success then
|
43
|
-
when :error then
|
44
|
-
else
|
21
|
+
when :success then 'fa-check'
|
22
|
+
when :error then 'fa-warning'
|
23
|
+
else 'fa-exclamation-triangle'
|
45
24
|
end
|
46
25
|
end
|
47
26
|
end
|
@@ -46,15 +46,12 @@ module Para
|
|
46
46
|
end
|
47
47
|
|
48
48
|
def excerpt_value_for(value)
|
49
|
-
return value unless value.
|
49
|
+
return value unless value.is_a?(String)
|
50
50
|
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
else
|
56
|
-
value
|
57
|
-
end
|
51
|
+
truncate(
|
52
|
+
sanitize(value, tags: []),
|
53
|
+
length: 100
|
54
|
+
)
|
58
55
|
end
|
59
56
|
end
|
60
57
|
end
|
@@ -19,7 +19,7 @@ module Para
|
|
19
19
|
),
|
20
20
|
class: 'btn btn-sm btn-icon-primary btn-shadow hint--left',
|
21
21
|
aria: {
|
22
|
-
label: ::I18n.t('para.shared.edit')
|
22
|
+
label: ::I18n.t('para.shared.edit')
|
23
23
|
}
|
24
24
|
) do
|
25
25
|
content_tag(:i, '', class: 'fa fa-pencil')
|
@@ -29,13 +29,13 @@ module Para
|
|
29
29
|
def delete_button(resource)
|
30
30
|
link_to(
|
31
31
|
component.relation_path(resource),
|
32
|
-
method: :delete,
|
33
32
|
data: {
|
34
|
-
|
33
|
+
'turbo-method': :delete,
|
34
|
+
'turbo-confirm': ::I18n.t('para.list.delete_confirmation')
|
35
35
|
},
|
36
36
|
class: 'btn btn-sm btn-icon-danger btn-shadow hint--left',
|
37
37
|
aria: {
|
38
|
-
label: ::I18n.t('para.shared.destroy')
|
38
|
+
label: ::I18n.t('para.shared.destroy')
|
39
39
|
}
|
40
40
|
) do
|
41
41
|
content_tag(:i, '', class: 'fa fa-times')
|
@@ -0,0 +1,58 @@
|
|
1
|
+
var ref,
|
2
|
+
boundMethodCheck = function(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new Error('Bound instance method accessed before binding'); } };
|
3
|
+
|
4
|
+
ref = Para.AsyncProgress = class AsyncProgress extends Vertebra.View {
|
5
|
+
initialize(options) {
|
6
|
+
this.trackProgress = this.trackProgress.bind(this);
|
7
|
+
this.onTrackingDataReceived = this.onTrackingDataReceived.bind(this);
|
8
|
+
this.onJobError = this.onJobError.bind(this);
|
9
|
+
|
10
|
+
this.targetUrl = options.progressUrl || this.$el.data('async-progress-url');
|
11
|
+
this.$progressBar = this.$el.find('.progress-bar');
|
12
|
+
return this.trackProgress();
|
13
|
+
}
|
14
|
+
|
15
|
+
trackProgress() {
|
16
|
+
boundMethodCheck(this, ref);
|
17
|
+
return $.get(this.targetUrl).done(this.onTrackingDataReceived).fail(this.onJobError);
|
18
|
+
}
|
19
|
+
|
20
|
+
stop() {
|
21
|
+
return clearTimeout(this.progressTimeout);
|
22
|
+
}
|
23
|
+
|
24
|
+
onTrackingDataReceived(data) {
|
25
|
+
boundMethodCheck(this, ref);
|
26
|
+
if (data.status === 'completed') {
|
27
|
+
return this.completed();
|
28
|
+
} else {
|
29
|
+
return this.setProgress(data.progress);
|
30
|
+
}
|
31
|
+
}
|
32
|
+
|
33
|
+
setProgress(progress) {
|
34
|
+
this.$progressBar.css({
|
35
|
+
width: `${progress}%`
|
36
|
+
});
|
37
|
+
this.progressTimeout = setTimeout(this.trackProgress, 1500);
|
38
|
+
return this.trigger('progress');
|
39
|
+
}
|
40
|
+
|
41
|
+
completed() {
|
42
|
+
this.$progressBar.css({
|
43
|
+
width: "100%"
|
44
|
+
});
|
45
|
+
this.$progressBar.removeClass('progress-bar-striped').addClass('progress-bar-success');
|
46
|
+
return this.trigger('completed');
|
47
|
+
}
|
48
|
+
|
49
|
+
onJobError() {
|
50
|
+
boundMethodCheck(this, ref);
|
51
|
+
this.$progressBar.css({
|
52
|
+
width: "100%"
|
53
|
+
});
|
54
|
+
this.$progressBar.removeClass('progress-bar-striped').addClass('progress-bar-error');
|
55
|
+
return this.trigger('failed');
|
56
|
+
}
|
57
|
+
|
58
|
+
};
|
@@ -0,0 +1,12 @@
|
|
1
|
+
function initializeFiltersFormSubmit() {
|
2
|
+
setTimeout(function() {
|
3
|
+
document.querySelectorAll('[data-filters-form]').forEach(function(form) {
|
4
|
+
$(form).on("change", "input, select, textarea", function() {
|
5
|
+
form.requestSubmit();
|
6
|
+
});
|
7
|
+
});
|
8
|
+
}, 0);
|
9
|
+
}
|
10
|
+
|
11
|
+
document.documentElement.addEventListener('turbo:load', initializeFiltersFormSubmit);
|
12
|
+
document.documentElement.addEventListener('turbo:frame-load', initializeFiltersFormSubmit);
|
@@ -0,0 +1,33 @@
|
|
1
|
+
function trackProgressFor(element, jobStatusUrl) {
|
2
|
+
var progressBar = element.querySelector('[data-async-progress]');
|
3
|
+
if (!progressBar) return;
|
4
|
+
|
5
|
+
var progress = new Para.AsyncProgress({ el: progressBar, progressUrl: jobStatusUrl });
|
6
|
+
|
7
|
+
function handleComplete() {
|
8
|
+
$(element).modal('hide');
|
9
|
+
|
10
|
+
var parentFrame = element.parentNode;
|
11
|
+
|
12
|
+
parentFrame.addEventListener('turbo:frame-render', function() {
|
13
|
+
parentFrame.dispatchEvent(new Event('job:progress:complete'));
|
14
|
+
});
|
15
|
+
|
16
|
+
parentFrame.src = jobStatusUrl;
|
17
|
+
|
18
|
+
};
|
19
|
+
|
20
|
+
progress.on('completed', handleComplete);
|
21
|
+
progress.on('failed', handleComplete);
|
22
|
+
}
|
23
|
+
|
24
|
+
document.documentElement.addEventListener('turbo:frame-load', function(e) {
|
25
|
+
if (e.target.id != 'para_admin_modal') return;
|
26
|
+
|
27
|
+
loadedElement = e.target.childNodes[0];
|
28
|
+
|
29
|
+
var jobStatusUrl = loadedElement && loadedElement.dataset.jobStatusUrl;
|
30
|
+
if (!jobStatusUrl) return;
|
31
|
+
|
32
|
+
trackProgressFor(loadedElement, jobStatusUrl);
|
33
|
+
});
|
@@ -0,0 +1,58 @@
|
|
1
|
+
import { PATCH, fetch } from "../lib/fetch";
|
2
|
+
|
3
|
+
Para.ResourceTable = class ResourceTable {
|
4
|
+
constructor($table) {
|
5
|
+
this.$table = $table;
|
6
|
+
this.$tbody = this.$table.find('tbody');
|
7
|
+
this.initializeOrderable();
|
8
|
+
}
|
9
|
+
|
10
|
+
initializeOrderable() {
|
11
|
+
this.orderable = this.$table.hasClass('orderable');
|
12
|
+
if (!this.orderable) {
|
13
|
+
return;
|
14
|
+
}
|
15
|
+
this.orderUrl = this.$table.data('order-url');
|
16
|
+
return this.$tbody.sortable({
|
17
|
+
handle: '.order-anchor',
|
18
|
+
draggable: 'tr',
|
19
|
+
ghostClass: 'sortable-placeholder',
|
20
|
+
onUpdate: $.proxy(this.sortUpdate, this)
|
21
|
+
});
|
22
|
+
}
|
23
|
+
|
24
|
+
sortUpdate() {
|
25
|
+
this.$tbody.find('tr').each(function(i, el) {
|
26
|
+
return $(el).find('.resource-position-field').val(i);
|
27
|
+
});
|
28
|
+
return this.updateOrder();
|
29
|
+
}
|
30
|
+
|
31
|
+
updateOrder() {
|
32
|
+
fetch(this.orderUrl, {
|
33
|
+
method: PATCH,
|
34
|
+
body: this.buildOrderedData()
|
35
|
+
});
|
36
|
+
}
|
37
|
+
|
38
|
+
buildOrderedData() {
|
39
|
+
const data = new FormData();
|
40
|
+
|
41
|
+
this.$tbody.find('.resource-position-field').each((i, el) => {
|
42
|
+
const $field = $(el);
|
43
|
+
const resourceKey = `resources[${i}]`;
|
44
|
+
|
45
|
+
data.append(`${resourceKey}[id]`, $field.closest('.order-anchor').data('id'));
|
46
|
+
data.append(`${resourceKey}[position]`, $field.val());
|
47
|
+
});
|
48
|
+
|
49
|
+
return data;
|
50
|
+
}
|
51
|
+
};
|
52
|
+
|
53
|
+
// TODO: Add flash message to display ordering success
|
54
|
+
$(document).on('turbo:load turbo:frame-load', function() {
|
55
|
+
return $('.para-component-relation-table').each(function(i, el) {
|
56
|
+
return new Para.ResourceTable($(el));
|
57
|
+
});
|
58
|
+
});
|
@@ -0,0 +1,110 @@
|
|
1
|
+
// Tabs hash management adapted from SO answer :
|
2
|
+
// http://stackoverflow.com/a/21443271/685925
|
3
|
+
|
4
|
+
var ref,
|
5
|
+
boundMethodCheck = function(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new Error('Bound instance method accessed before binding'); } };
|
6
|
+
|
7
|
+
ref = Para.Tabs = (function() {
|
8
|
+
class Tabs extends Vertebra.View {
|
9
|
+
initialize(options = {}) {
|
10
|
+
this.onTabShown = this.onTabShown.bind(this);
|
11
|
+
|
12
|
+
this.$anchorInput = options.$anchorInput;
|
13
|
+
this.showActiveTab();
|
14
|
+
this.refreshTabsErrors();
|
15
|
+
return this.initializeAffix();
|
16
|
+
}
|
17
|
+
|
18
|
+
showActiveTab() {
|
19
|
+
var hash, ref1;
|
20
|
+
if ((hash = location.hash || ((ref1 = this.$anchorInput) != null ? ref1.val() : void 0))) {
|
21
|
+
return this.findTab(hash).tab('show');
|
22
|
+
}
|
23
|
+
}
|
24
|
+
|
25
|
+
onTabShown(e) {
|
26
|
+
var $tab, tabHash;
|
27
|
+
boundMethodCheck(this, ref);
|
28
|
+
$tab = $(e.target);
|
29
|
+
if (!$tab.closest('[data-form-tabs]').is('[data-top-level-tabs]')) {
|
30
|
+
return;
|
31
|
+
}
|
32
|
+
tabHash = $tab.attr('href');
|
33
|
+
history.pushState(null, null, tabHash);
|
34
|
+
return this.updateAnchorInput();
|
35
|
+
}
|
36
|
+
|
37
|
+
updateAnchorInput() {
|
38
|
+
if (this.$anchorInput.length) {
|
39
|
+
return this.$anchorInput.val(location.hash);
|
40
|
+
}
|
41
|
+
}
|
42
|
+
|
43
|
+
refreshTabsErrors() {
|
44
|
+
return this.$('[data-toggle="tab"]').each((i, tab) => {
|
45
|
+
return this.refreshTabErrors($(tab));
|
46
|
+
});
|
47
|
+
}
|
48
|
+
|
49
|
+
refreshTabErrors($tab) {
|
50
|
+
var $panel;
|
51
|
+
$panel = this.$($tab.attr('href'));
|
52
|
+
if ($panel.find('.has-error').length) {
|
53
|
+
return $tab.addClass('has-error');
|
54
|
+
}
|
55
|
+
}
|
56
|
+
|
57
|
+
|
58
|
+
initializeAffix() {
|
59
|
+
var headerHeight, offsetTop, sidebarWidth;
|
60
|
+
if (!(this.$nav = this.$('[data-affix-header="tabs"]')).length) {
|
61
|
+
return;
|
62
|
+
}
|
63
|
+
headerHeight = $('[data-header]').outerHeight();
|
64
|
+
offsetTop = this.$nav.offset().top - headerHeight;
|
65
|
+
sidebarWidth = $('[data-admin-left-sidebar]').outerWidth();
|
66
|
+
this.$nav.affix({
|
67
|
+
offset: {
|
68
|
+
top: offsetTop
|
69
|
+
}
|
70
|
+
}).css({
|
71
|
+
top: headerHeight,
|
72
|
+
left: sidebarWidth
|
73
|
+
});
|
74
|
+
// Fix parent wrapper height to maintain the same scroll position when the
|
75
|
+
// nav tabs are fixed to top
|
76
|
+
return this.$nav.closest('[data-nav-tabs-wrapper]').height(this.$nav.outerHeight());
|
77
|
+
}
|
78
|
+
|
79
|
+
onFormInputUpdate(e) {
|
80
|
+
var $tab;
|
81
|
+
$tab = this.findTab($(e.currentTarget).attr('id'));
|
82
|
+
return this.refreshTabErrors($tab);
|
83
|
+
}
|
84
|
+
|
85
|
+
findTab(id) {
|
86
|
+
if (!(id.indexOf('#') >= 0)) {
|
87
|
+
id = `#${id}`;
|
88
|
+
}
|
89
|
+
return this.$('a[href="' + id + '"]');
|
90
|
+
}
|
91
|
+
|
92
|
+
};
|
93
|
+
|
94
|
+
Tabs.prototype.events = {
|
95
|
+
'shown.bs.tab a[data-toggle="tab"]': 'onTabShown',
|
96
|
+
'change .tab-pane': 'onFormInputUpdate'
|
97
|
+
};
|
98
|
+
|
99
|
+
return Tabs;
|
100
|
+
|
101
|
+
}).call(this);
|
102
|
+
|
103
|
+
$(document).on('turbo:load turbo:frame-load', function() {
|
104
|
+
return $('[data-form-tabs]').each(function(i, el) {
|
105
|
+
return new Para.Tabs({
|
106
|
+
el: el,
|
107
|
+
$anchorInput: $('[data-current-anchor]')
|
108
|
+
});
|
109
|
+
});
|
110
|
+
});
|
@@ -0,0 +1,39 @@
|
|
1
|
+
var responsive_sidebar_navigation, scrollToComponentSection;
|
2
|
+
|
3
|
+
scrollToComponentSection = function($component, duration = 0) {
|
4
|
+
var headerHeight, sectionOffset;
|
5
|
+
sectionOffset = $component.closest('.component-section-item').offset().top + $('.navmenu').scrollTop();
|
6
|
+
headerHeight = $('.navmenu .navmenu-brand').outerHeight();
|
7
|
+
return $('.navmenu-nav').scrollTo(sectionOffset - headerHeight, {
|
8
|
+
duration: duration
|
9
|
+
});
|
10
|
+
};
|
11
|
+
|
12
|
+
responsive_sidebar_navigation = function() {
|
13
|
+
var $activeItem;
|
14
|
+
// Scroll to active element's section on page change
|
15
|
+
if (($activeItem = $('.component-item.active')).length) {
|
16
|
+
scrollToComponentSection($activeItem);
|
17
|
+
}
|
18
|
+
return $('.component-item').on('click', 'a', function(e) {
|
19
|
+
return scrollToComponentSection($(e.currentTarget), 150);
|
20
|
+
});
|
21
|
+
};
|
22
|
+
|
23
|
+
$(document).on('turbo:load turbo:frame-load', function() {
|
24
|
+
responsive_sidebar_navigation();
|
25
|
+
return $(".selectize-tags").selectize({
|
26
|
+
delimiter: ",",
|
27
|
+
persist: false,
|
28
|
+
create: function(input) {
|
29
|
+
return {
|
30
|
+
value: input,
|
31
|
+
text: input
|
32
|
+
};
|
33
|
+
}
|
34
|
+
});
|
35
|
+
});
|
36
|
+
|
37
|
+
$(window).resize(function() {
|
38
|
+
return responsive_sidebar_navigation();
|
39
|
+
});
|