para 0.5.4 → 0.6.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/app/assets/javascripts/para/admin/async-progress.coffee +29 -0
- data/app/assets/javascripts/para/admin/filters-form.coffee +1 -1
- data/app/assets/javascripts/para/admin/importers.coffee +38 -0
- data/app/assets/javascripts/para/admin/table.coffee +1 -1
- data/app/assets/javascripts/para/admin/tabs.coffee +1 -1
- data/app/assets/javascripts/para/admin/theme_actions.coffee +1 -1
- data/app/assets/javascripts/para/admin/tree.coffee +5 -5
- data/app/assets/javascripts/para/admin.coffee +2 -1
- data/app/assets/javascripts/para/inputs/nested_many.coffee +1 -1
- data/app/assets/javascripts/para/lib/remote-file-forms.coffee +60 -0
- data/app/assets/javascripts/para/lib/turbolinks-loading.coffee +1 -1
- data/app/assets/javascripts/para/lib/turbolinks-reloader.coffee +19 -0
- data/app/assets/stylesheets/para/admin/src/datetimepicker.sass +3 -1
- data/app/assets/stylesheets/para/admin/src/fuelux.sass +4 -2
- data/app/assets/stylesheets/para/admin/src/nested_many.sass +5 -0
- data/app/assets/stylesheets/para/admin/src/redactor.sass +8 -5
- data/app/assets/stylesheets/para/admin/src/selectize.sass +7 -4
- data/app/assets/stylesheets/para/admin/theme/_breadcrumb.sass +20 -12
- data/app/assets/stylesheets/para/admin/theme/_buttons.sass +6 -2
- data/app/assets/stylesheets/para/admin/theme/_checkable.sass +4 -2
- data/app/assets/stylesheets/para/admin/theme/_commonds.sass +6 -3
- data/app/assets/stylesheets/para/admin/theme/_dropdown.sass +3 -1
- data/app/assets/stylesheets/para/admin/theme/_form.sass +4 -2
- data/app/assets/stylesheets/para/admin/theme/_list.sass +7 -5
- data/app/assets/stylesheets/para/admin/theme/_navigation.sass +12 -66
- data/app/assets/stylesheets/para/admin/theme/_navtabs.sass +18 -14
- data/app/assets/stylesheets/para/admin/theme/_orderable.sass +7 -3
- data/app/assets/stylesheets/para/admin/theme/_panel.sass +19 -13
- data/app/assets/stylesheets/para/admin/theme/_tree.sass +4 -2
- data/app/assets/stylesheets/para/overrides/theme.sass +14 -10
- data/app/controllers/para/admin/base_controller.rb +0 -5
- data/app/controllers/para/admin/crud_resources_controller.rb +5 -19
- data/app/controllers/para/admin/{singleton_resources_controller.rb → form_resources_controller.rb} +4 -4
- data/app/controllers/para/admin/imports_controller.rb +68 -0
- data/app/controllers/para/admin/resources_controller.rb +0 -1
- data/app/decorators/para/component/base_decorator.rb +6 -18
- data/app/decorators/para/component/crud_decorator.rb +3 -3
- data/app/decorators/para/component/{singleton_resource_decorator.rb → form_decorator.rb} +6 -6
- data/app/helpers/para/admin/components_helper.rb +12 -1
- data/app/helpers/para/admin/decorators_helper.rb +13 -0
- data/app/helpers/para/markup_helper.rb +4 -0
- data/app/helpers/para/search_helper.rb +1 -4
- data/app/models/para/component/base.rb +17 -14
- data/app/models/para/component/crud.rb +17 -0
- data/app/models/para/component/form.rb +36 -0
- data/app/models/para/component/resource.rb +9 -20
- data/app/models/para/component/settings.rb +1 -1
- data/app/models/para/library/file.rb +23 -0
- data/app/models/para/library.rb +5 -0
- data/app/views/para/admin/form_resources/show.html.haml +4 -0
- data/app/views/para/admin/imports/_completed.html.haml +16 -0
- data/app/views/para/admin/imports/_failed.html.haml +7 -0
- data/app/views/para/admin/imports/_progress.html.haml +5 -0
- data/app/views/para/admin/imports/new.html.haml +14 -0
- data/app/views/para/admin/imports/show.html.haml +10 -0
- data/app/views/para/admin/resources/_fields.html.haml +1 -4
- data/app/views/para/admin/resources/_imports_menu.html.haml +17 -20
- data/app/views/para/admin/resources/_tree.html.haml +1 -1
- data/app/views/para/admin/shared/_breadcrumbs.html.haml +1 -4
- data/app/views/para/admin/shared/_navigation.html.haml +2 -2
- data/app/views/para/form/_tabs.html.haml +1 -1
- data/config/locales/en.yml +10 -0
- data/config/locales/fr.yml +12 -2
- data/db/migrate/20160905134106_create_para_library_files.rb +9 -0
- data/lib/generators/para/importer/templates/base_importer.rb +8 -1
- data/lib/generators/para/install/install_generator.rb +1 -2
- data/lib/generators/para/install/templates/components.rb +9 -5
- data/lib/generators/para/tree_item/tree_item_generator.rb +17 -0
- data/lib/para/attribute_field/base.rb +12 -4
- data/lib/para/attribute_field/enum.rb +7 -3
- data/lib/para/component/importable.rb +4 -4
- data/lib/para/component.rb +1 -1
- data/lib/para/components_cleaner.rb +66 -0
- data/lib/para/components_configuration.rb +3 -1
- data/lib/para/engine.rb +36 -3
- data/lib/para/ext/active_job_status.rb +13 -0
- data/lib/para/ext/paperclip.rb +10 -0
- data/lib/para/ext/simple_form_extension.rb +6 -0
- data/lib/para/ext.rb +1 -0
- data/lib/para/form_builder/nested_form.rb +5 -2
- data/lib/para/importer/base.rb +84 -7
- data/lib/para/inputs/nested_many_input.rb +1 -1
- data/lib/para/logging/active_job_log_subscriber.rb +48 -0
- data/lib/para/logging.rb +8 -0
- data/lib/para/markup/resources_table.rb +2 -4
- data/lib/para/model_field_parsers/enums.rb +19 -0
- data/lib/para/model_field_parsers/relations.rb +1 -1
- data/lib/para/model_field_parsers/store.rb +1 -1
- data/lib/para/model_field_parsers.rb +1 -0
- data/lib/para/plugins/routes.rb +2 -4
- data/lib/para/postgres_extensions_checker.rb +30 -0
- data/lib/para/routes.rb +5 -4
- data/lib/para/routing/component_controller_constraint.rb +36 -0
- data/lib/para/routing.rb +7 -0
- data/lib/para/sti/root_model.rb +8 -2
- data/lib/para/version.rb +1 -1
- data/lib/para.rb +10 -0
- data/lib/rails/routing_mapper.rb +59 -27
- data/lib/tasks/para_tasks.rake +21 -11
- metadata +73 -15
- data/app/models/para/component/singleton_resource.rb +0 -35
- data/app/views/para/admin/singleton_resources/show.html.haml +0 -4
@@ -1,23 +1,23 @@
|
|
1
1
|
module Para
|
2
2
|
module Component
|
3
|
-
module
|
3
|
+
module FormDecorator
|
4
4
|
include Para::Component::BaseDecorator
|
5
5
|
|
6
|
-
def path(
|
7
|
-
find_path([:admin, self,
|
6
|
+
def path(namespace: :resource, **options)
|
7
|
+
find_path([:admin, self, namespace], options)
|
8
8
|
end
|
9
9
|
|
10
10
|
def relation_path(controller_or_resource, *nested_resources, **options)
|
11
11
|
nested = nested_resources.any?
|
12
|
-
nested_resources << :resource unless nested
|
13
12
|
|
14
13
|
if Hash === controller_or_resource
|
15
14
|
options = controller_or_resource
|
16
15
|
end
|
17
16
|
|
18
17
|
options[:action] = action_option_for(options, nested: nested)
|
19
|
-
data = [:admin, self, *nested_resources]
|
20
|
-
|
18
|
+
data = [:admin, self, :resource, *nested_resources]
|
19
|
+
|
20
|
+
find_path(data, options)
|
21
21
|
end
|
22
22
|
|
23
23
|
def action_option_for(options, nested: false)
|
@@ -1,7 +1,18 @@
|
|
1
1
|
module Para
|
2
2
|
module Admin::ComponentsHelper
|
3
|
+
# Return the sections / components structure, with components properly
|
4
|
+
# decorated
|
5
|
+
#
|
6
|
+
def admin_component_sections
|
7
|
+
@admin_component_sections ||= begin
|
8
|
+
Para::ComponentSection.ordered.includes(:components).tap do |sections|
|
9
|
+
sections.flat_map(&:components).each(&method(:decorate))
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
3
14
|
def ordered_components
|
4
|
-
|
15
|
+
admin_component_sections.each_with_object([]) do |section, components|
|
5
16
|
section.components.each do |component|
|
6
17
|
components << component if can?(:read, component)
|
7
18
|
end
|
@@ -9,10 +9,7 @@ module Para
|
|
9
9
|
end
|
10
10
|
|
11
11
|
def searchable_attributes(attributes)
|
12
|
-
whitelist = attributes.select
|
13
|
-
[:string, :text].include?(attribute.type.to_sym) &&
|
14
|
-
!attribute.name.match(/password/)
|
15
|
-
end
|
12
|
+
whitelist = attributes.select(&:searchable?)
|
16
13
|
|
17
14
|
whitelist.map do |attribute|
|
18
15
|
attribute.attribute_column_path.join('_')
|
@@ -3,13 +3,19 @@ module Para
|
|
3
3
|
class Base < ActiveRecord::Base
|
4
4
|
self.table_name = 'para_components'
|
5
5
|
|
6
|
-
class_attribute :component_name
|
6
|
+
class_attribute :component_name
|
7
7
|
|
8
8
|
def self.register(name, component)
|
9
9
|
self.component_name = name
|
10
10
|
Para::Component.registered_components[name] = component
|
11
11
|
end
|
12
12
|
|
13
|
+
def self.configurable_on(key, options = {})
|
14
|
+
store_accessor(:configuration, key)
|
15
|
+
end
|
16
|
+
|
17
|
+
configurable_on :controller
|
18
|
+
|
13
19
|
belongs_to :component_section, class_name: 'Para::ComponentSection'
|
14
20
|
|
15
21
|
validates :identifier, :type, presence: true
|
@@ -37,19 +43,6 @@ module Para
|
|
37
43
|
@model_name ||= ModelName.new(self)
|
38
44
|
end
|
39
45
|
|
40
|
-
def self.configurable_on(key, options = {})
|
41
|
-
store_accessor(:configuration, key)
|
42
|
-
configurable_attributes[key] = options
|
43
|
-
end
|
44
|
-
|
45
|
-
def self.configurable?
|
46
|
-
configurable_attributes.length > 0
|
47
|
-
end
|
48
|
-
|
49
|
-
def self.configurable_attributes
|
50
|
-
@configurable_attributes ||= {}
|
51
|
-
end
|
52
|
-
|
53
46
|
def default_form_actions
|
54
47
|
[:submit, :submit_and_edit, :submit_and_add_another, :cancel]
|
55
48
|
end
|
@@ -58,6 +51,16 @@ module Para
|
|
58
51
|
slug
|
59
52
|
end
|
60
53
|
|
54
|
+
# This method is used by the components configuration system to assign
|
55
|
+
# updated attributes from the config file to the component.
|
56
|
+
#
|
57
|
+
# This is meant to be overriden by components that have to define specific
|
58
|
+
# behavior, like for the Crud component
|
59
|
+
#
|
60
|
+
def update_with(attributes)
|
61
|
+
assign_attributes(attributes)
|
62
|
+
end
|
63
|
+
|
61
64
|
private
|
62
65
|
|
63
66
|
def ensure_slug
|
@@ -13,6 +13,8 @@ module Para
|
|
13
13
|
has_many :component_resources, class_name: 'Para::ComponentResource',
|
14
14
|
foreign_key: :component_id, autosave: true, dependent: :destroy
|
15
15
|
|
16
|
+
before_validation :ensure_model_type
|
17
|
+
|
16
18
|
def namespaced?
|
17
19
|
case namespaced
|
18
20
|
when 'true' then true
|
@@ -32,6 +34,17 @@ module Para
|
|
32
34
|
component_resources.where(resource: resource).first.destroy
|
33
35
|
end
|
34
36
|
|
37
|
+
def update_with(attributes)
|
38
|
+
# If no model_type is provided in the configuration file, default to
|
39
|
+
# the singular and camelized version of the identifier, allowing to
|
40
|
+
# create crud components without setting the :model_type option, when
|
41
|
+
# given a conventional name
|
42
|
+
attributes[:model_type] ||= identifier.to_s.camelize.singularize if identifier
|
43
|
+
attributes[:controller] ||= '/para/admin/crud_resources'
|
44
|
+
|
45
|
+
super
|
46
|
+
end
|
47
|
+
|
35
48
|
private
|
36
49
|
|
37
50
|
def namespaced_resources
|
@@ -42,6 +55,10 @@ module Para
|
|
42
55
|
para_component_resources: { component_id: id }
|
43
56
|
)
|
44
57
|
end
|
58
|
+
|
59
|
+
def ensure_model_type
|
60
|
+
self.model_type ||= identifier
|
61
|
+
end
|
45
62
|
end
|
46
63
|
end
|
47
64
|
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
module Para
|
2
|
+
module Component
|
3
|
+
class Form < Para::Component::Resource
|
4
|
+
register :form, self
|
5
|
+
|
6
|
+
configurable_on :model_type
|
7
|
+
|
8
|
+
has_one :component_resource, class_name: 'Para::ComponentResource',
|
9
|
+
foreign_key: :component_id, autosave: true, dependent: :destroy
|
10
|
+
|
11
|
+
def resource
|
12
|
+
build_component_resource(resource: model.new) unless component_resource
|
13
|
+
component_resource.resource ||= model.new
|
14
|
+
end
|
15
|
+
|
16
|
+
def resource=(value)
|
17
|
+
build_component_resource(resource: value) unless component_resource
|
18
|
+
end
|
19
|
+
|
20
|
+
def default_form_actions
|
21
|
+
[:submit]
|
22
|
+
end
|
23
|
+
|
24
|
+
def update_with(attributes)
|
25
|
+
# If no model_type is provided in the configuration file, default to
|
26
|
+
# the camelized version of the identifier, allowing to create
|
27
|
+
# form components without setting the :model_type option,
|
28
|
+
# when given a conventional name
|
29
|
+
attributes[:model_type] ||= identifier.to_s.camelize.singularize if identifier
|
30
|
+
attributes[:controller] ||= '/para/admin/form_resources'
|
31
|
+
|
32
|
+
super
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -1,33 +1,22 @@
|
|
1
1
|
module Para
|
2
2
|
module Component
|
3
3
|
class Resource < Para::Component::Base
|
4
|
+
class ModelNotFound < NameError; end
|
5
|
+
|
4
6
|
def model
|
5
7
|
@model ||= model_type.presence && model_type.constantize
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
next true if name.match(/^HABTM_/)
|
14
|
-
next true if name.match(/Component$/)
|
15
|
-
next true if name.match(/^Para::Component/)
|
16
|
-
next true if excluded_models.include?(name)
|
17
|
-
|
18
|
-
false
|
19
|
-
end
|
8
|
+
rescue NameError
|
9
|
+
raise ModelNotFound,
|
10
|
+
"The model #{ model_type } was not found. You may need to set " +
|
11
|
+
"the :model_type option in your component definition in the " +
|
12
|
+
"config/components.rb file. If no component should actually " +
|
13
|
+
"reference this model, you may need to run the " +
|
14
|
+
"`rake para:components:clean` task to clean up your components index."
|
20
15
|
end
|
21
16
|
|
22
17
|
def model_table_name
|
23
18
|
model && model.table_name
|
24
19
|
end
|
25
|
-
|
26
|
-
private
|
27
|
-
|
28
|
-
def excluded_models
|
29
|
-
%w(FriendlyId::Slug)
|
30
|
-
end
|
31
20
|
end
|
32
21
|
end
|
33
22
|
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
module Para
|
2
|
+
module Library
|
3
|
+
class File < ActiveRecord::Base
|
4
|
+
has_attached_file :attachment
|
5
|
+
|
6
|
+
validates :attachment, presence: true
|
7
|
+
do_not_validate_attachment_file_type :attachment
|
8
|
+
|
9
|
+
# Return attachment.path or attachment.url depending on the storage
|
10
|
+
# backend, allowing 'openuri' and 'roo' libraries to load easily the
|
11
|
+
# file at the right path, on filesystem or othe storage systems, like S3.
|
12
|
+
#
|
13
|
+
def attachment_path
|
14
|
+
return unless attachment?
|
15
|
+
|
16
|
+
case attachment.options[:storage]
|
17
|
+
when :filesystem then attachment.path
|
18
|
+
else attachment.url
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
= modal.body do
|
2
|
+
- if status[:errors].any?
|
3
|
+
.alert.alert-warning
|
4
|
+
= t('para.flash.shared.import.success_with_errors')
|
5
|
+
|
6
|
+
%ul
|
7
|
+
- status[:errors].each do |message|
|
8
|
+
%li= message.html_safe
|
9
|
+
|
10
|
+
- else
|
11
|
+
.alert.alert-success
|
12
|
+
= t('para.flash.shared.import.success')
|
13
|
+
|
14
|
+
= modal.footer do
|
15
|
+
%button.btn.btn-default{ data: { dismiss: 'modal' } }
|
16
|
+
= t('para.shared.close')
|
@@ -0,0 +1,14 @@
|
|
1
|
+
= modal id: "component-import-#{ @importer.model_name.route_key }" do |modal|
|
2
|
+
= modal.header do
|
3
|
+
= @importer.model_name.human
|
4
|
+
|
5
|
+
= simple_form_for @file, as: :file, url: @component.path(namespace: :imports, importer: @importer.name), remote: true do |form|
|
6
|
+
= modal.body do
|
7
|
+
%p= t('para.import.help_text')
|
8
|
+
|
9
|
+
= form.input :attachment, label: false, placeholder: t('para.import.placeholder')
|
10
|
+
|
11
|
+
= modal.footer do
|
12
|
+
%button.btn.btn-primary{ type: 'submit' }
|
13
|
+
= fa_icon 'upload'
|
14
|
+
= t('para.import.name')
|
@@ -0,0 +1,10 @@
|
|
1
|
+
= modal id: "component-import-#{ @importer.model_name.route_key }", data: { :'import-status-url' => @component.path(namespace: :import, importer: @importer.name, id: @status.job_id) } do |modal|
|
2
|
+
= modal.header do
|
3
|
+
= @importer.model_name.human
|
4
|
+
|
5
|
+
- if @status.failed?
|
6
|
+
= render partial: 'failed', locals: { modal: modal }
|
7
|
+
- elsif @status.completed?
|
8
|
+
= render partial: 'completed', locals: { modal: modal, status: @status }
|
9
|
+
- else
|
10
|
+
= render partial: 'progress', locals: { modal: modal, status: @status }
|
@@ -1,22 +1,19 @@
|
|
1
1
|
- if component.importable?
|
2
|
-
- component.
|
3
|
-
=
|
4
|
-
.fileinput.fileinput-new.input-group{ data: { provides: 'fileinput' } }
|
5
|
-
.form-control.uneditable-input{ data: { trigger: 'fileinput' } }
|
6
|
-
%span.fileinput-placeholder
|
7
|
-
= t('para.import.placeholder')
|
8
|
-
= fa_icon 'file', class: 'fileinput-exists'
|
9
|
-
%span.fileinput-filename
|
10
|
-
.input-group-btn
|
11
|
-
.btn.btn-default.btn-file
|
12
|
-
%span.fileinput-new
|
13
|
-
= t('para.import.select')
|
14
|
-
%span.fileinput-exists
|
15
|
-
= t('para.import.change')
|
16
|
-
= file_field_tag 'file', class: 'file file-upload'
|
17
|
-
.btn.btn-danger.fileinput-exists{ type: 'button', data: { dismiss: 'fileinput' } }
|
18
|
-
= fa_icon 'times'
|
2
|
+
- if component.importers.length == 1
|
3
|
+
- importer = component.importers.first
|
19
4
|
|
20
|
-
|
21
|
-
|
22
|
-
|
5
|
+
= link_to component.path(namespace: :import, action: :new, importer: importer.model_name.singular_route_key), class: 'btn btn-default', remote: true, data: { :'importer-button' => true } do
|
6
|
+
= fa_icon 'upload'
|
7
|
+
= importer.model_name.human
|
8
|
+
|
9
|
+
- else
|
10
|
+
.btn-group
|
11
|
+
%button.btn.btn-default{ type: 'button', data: { toggle: 'dropdown' } }
|
12
|
+
= fa_icon 'upload'
|
13
|
+
= t('para.import.name')
|
14
|
+
%span.caret
|
15
|
+
%ul.dropdown-menu
|
16
|
+
- component.importers.each do |importer|
|
17
|
+
%li
|
18
|
+
= link_to component.path(:imports, action: :new, importer: importer.model_name.singular_route_key), remote: true, data: { :'importer-button' => true } do
|
19
|
+
= importer.model_name.human
|
@@ -1,7 +1,7 @@
|
|
1
1
|
.page-content-wrap
|
2
2
|
= panel do |panel|
|
3
3
|
= panel.header do
|
4
|
-
=
|
4
|
+
= render partial: find_partial_for(relation, :actions), locals: { relation: relation, component: component, model: model, allow_adding_resource: allow_adding_resource }
|
5
5
|
|
6
6
|
- if resources.length > 0
|
7
7
|
= panel.body do
|
@@ -3,8 +3,8 @@
|
|
3
3
|
= link_to admin_path do
|
4
4
|
= t('para.admin.title')
|
5
5
|
|
6
|
-
- if
|
7
|
-
-
|
6
|
+
- if admin_component_sections.any?
|
7
|
+
- admin_component_sections.each do |component_section|
|
8
8
|
- next unless component_section.components.any? { |component| can?(:manage, component) }
|
9
9
|
|
10
10
|
%li.component-section-item
|
data/config/locales/en.yml
CHANGED
@@ -14,6 +14,9 @@ en:
|
|
14
14
|
|
15
15
|
admin:
|
16
16
|
title: "Admin"
|
17
|
+
toggle_navigation: "Open navigation"
|
18
|
+
back_to_app: "Back to app"
|
19
|
+
sign_out: "Sign out"
|
17
20
|
|
18
21
|
confirmation:
|
19
22
|
shared:
|
@@ -28,6 +31,9 @@ en:
|
|
28
31
|
singleton_resource:
|
29
32
|
name: "Resource form"
|
30
33
|
|
34
|
+
dashboard:
|
35
|
+
title: "Dashboard"
|
36
|
+
|
31
37
|
component_section:
|
32
38
|
add: "Add a component section"
|
33
39
|
edit: 'Edit section'
|
@@ -73,6 +79,10 @@ en:
|
|
73
79
|
"true": "Yes"
|
74
80
|
"false": "No"
|
75
81
|
|
82
|
+
admin:
|
83
|
+
breadcrumbs:
|
84
|
+
home: "Dashboard"
|
85
|
+
|
76
86
|
activerecord:
|
77
87
|
errors:
|
78
88
|
relation_length_is_smaller: "must contain at least %{minimum} elements"
|
data/config/locales/fr.yml
CHANGED
@@ -15,8 +15,12 @@ fr:
|
|
15
15
|
success: "%{model} cloné(e)"
|
16
16
|
error: "Impossible de cloner le(a) %{model}"
|
17
17
|
import:
|
18
|
-
success: "
|
19
|
-
|
18
|
+
success: "L'import du fichier a été effectué avec succès"
|
19
|
+
success_with_errors: |
|
20
|
+
L'import du fichier a été effectué, mais certaines lignes n'ont pas
|
21
|
+
été prises en compte à causes d'erreurs :
|
22
|
+
other_errors: "<br>Et <b>%{count}</b> autres erreurs ..."
|
23
|
+
error: "Le fichier choisi contient des erreurs et n'a pu être importé"
|
20
24
|
|
21
25
|
admin:
|
22
26
|
title: "Administration"
|
@@ -60,7 +64,12 @@ fr:
|
|
60
64
|
name: Importer
|
61
65
|
select: "Sélectionnez un fichier"
|
62
66
|
change: "Changer"
|
67
|
+
help_text: |
|
68
|
+
Sélectionnez un fichier Excel (.xls, .xlsx) ou CSV (.csv) à importer et
|
69
|
+
cliquez sur le bouton "Importer".
|
63
70
|
placeholder: Fichier au format ( .csv .xlsx )
|
71
|
+
row_error_prefix: "Ligne %{number} :"
|
72
|
+
importing_file: "Le fichier est en cours d'import, merci de patienter quelques instants ..."
|
64
73
|
|
65
74
|
shared:
|
66
75
|
save: "Enregistrer"
|
@@ -70,6 +79,7 @@ fr:
|
|
70
79
|
save_and_edit: "Enregistrer et éditer"
|
71
80
|
save_and_add_another_button: "Enregistrer et créer un(e) autre"
|
72
81
|
destroy: "Supprimer"
|
82
|
+
close: "Fermer"
|
73
83
|
|
74
84
|
types:
|
75
85
|
boolean:
|
@@ -1,5 +1,12 @@
|
|
1
1
|
class <%= model_importer_name %> < Para::Importer::Base
|
2
|
+
# Let the importer rescue ActiveRecord::RecordInvalid errors and display them
|
3
|
+
# as flash messages after importing valid records
|
4
|
+
#
|
5
|
+
# Remove or comment this line to disable this behavior
|
6
|
+
#
|
7
|
+
allow_import_errors!
|
8
|
+
|
2
9
|
def import_from_row(row)
|
3
10
|
# Add your import logic here
|
4
11
|
end
|
5
|
-
end
|
12
|
+
end
|
@@ -24,7 +24,7 @@ module Para
|
|
24
24
|
gemfile_contents = File.read(Rails.root.join('Gemfile'))
|
25
25
|
|
26
26
|
[
|
27
|
-
['devise', '
|
27
|
+
['devise', '>= 3.0'],
|
28
28
|
# Allows for installing default wrappers and bootstrap adapters
|
29
29
|
# This should be avoided when add an initializer namespaced to the
|
30
30
|
# para environment
|
@@ -32,7 +32,6 @@ module Para
|
|
32
32
|
['simple_form_extension'],
|
33
33
|
# Pull requests are pending, and I don't want to release the gem
|
34
34
|
# under another name to be able to depend on it
|
35
|
-
['active_decorator', github: 'glyph-fr/active_decorator', branch: 'dev'],
|
36
35
|
['kaminari', '>= 0.16.1'],
|
37
36
|
['ransack', '>= 1.4.1'],
|
38
37
|
['bootstrap-kaminari-views', '>= 0.0.5']
|
@@ -3,11 +3,15 @@ Para.components.draw do
|
|
3
3
|
# You can translate the section title at: components.section.menu
|
4
4
|
#
|
5
5
|
# section :menu do
|
6
|
-
#
|
7
|
-
# #
|
8
|
-
#
|
9
|
-
#
|
6
|
+
# # Creating crud components can be done the following way
|
7
|
+
# #
|
8
|
+
# component :pages, :crud
|
9
|
+
# component :members, :crud, model_type: 'User'
|
10
|
+
# component :news, :crud, model_type: 'Page', namespaced: true
|
11
|
+
|
12
|
+
# # Creating a component allowing you to edit a single resource is done
|
13
|
+
# # with the `singleton_resource` component, the following way
|
10
14
|
# #
|
11
|
-
# component :
|
15
|
+
# component :home, :singleton_resource, model_type: 'HomePage'
|
12
16
|
# end
|
13
17
|
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
module Para
|
2
|
+
class TreeItemGenerator < Para::Generators::NamedBase
|
3
|
+
include Para::Admin::BaseHelper
|
4
|
+
include Para::Generators::FieldHelpers
|
5
|
+
|
6
|
+
source_root File.expand_path('../../../../../app/views/para/admin/resources', __FILE__)
|
7
|
+
|
8
|
+
desc 'Para resource tree item generator'
|
9
|
+
|
10
|
+
def generate_table
|
11
|
+
template(
|
12
|
+
'_tree_item.html.haml',
|
13
|
+
"app/views/admin/#{ plural_namespaced_path }/_tree_item.haml"
|
14
|
+
)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -4,7 +4,7 @@ module Para
|
|
4
4
|
class_attribute :_field_options
|
5
5
|
cattr_accessor :_field_types
|
6
6
|
|
7
|
-
attr_reader :model, :name, :type, :field_type, :field_method
|
7
|
+
attr_reader :model, :name, :type, :field_type, :field_method, :options
|
8
8
|
|
9
9
|
def self.field_option(key, method_name, options = {})
|
10
10
|
self._field_options ||= []
|
@@ -43,9 +43,10 @@ module Para
|
|
43
43
|
|
44
44
|
def initialize(model, options = {})
|
45
45
|
@model = model
|
46
|
-
@name = options
|
47
|
-
@type = options
|
48
|
-
@field_type = options
|
46
|
+
@name = options.delete(:name)
|
47
|
+
@type = options.delete(:type)
|
48
|
+
@field_type = options.delete(:field_type)
|
49
|
+
@options = options
|
49
50
|
|
50
51
|
determine_name_and_field_method!
|
51
52
|
end
|
@@ -70,6 +71,13 @@ module Para
|
|
70
71
|
instance.send(name)
|
71
72
|
end
|
72
73
|
|
74
|
+
#
|
75
|
+
def searchable?
|
76
|
+
options[:searchable] != false && (
|
77
|
+
[:string, :text].include?(type.to_sym) && !name.match(/password/)
|
78
|
+
)
|
79
|
+
end
|
80
|
+
|
73
81
|
# Allows parsing input params before they're passed to the model, so
|
74
82
|
# it can be easy to edit them according to some field type specific
|
75
83
|
# behavior
|