para 0.5.1 → 0.5.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (56) hide show
  1. checksums.yaml +4 -4
  2. data/app/assets/javascripts/para/inputs/nested_many.coffee +2 -1
  3. data/app/assets/stylesheets/para/admin/src/page-top-bar.sass +9 -0
  4. data/app/assets/stylesheets/para/admin/theme/_base.sass +1 -0
  5. data/app/controllers/para/admin/crud_resources_controller.rb +7 -1
  6. data/app/controllers/para/admin/settings_component_controller.rb +14 -0
  7. data/app/decorators/para/component/crud_decorator.rb +8 -4
  8. data/app/helpers/para/admin/base_helper.rb +5 -3
  9. data/app/helpers/para/admin/page_helper.rb +32 -0
  10. data/app/helpers/para/tree_helper.rb +2 -2
  11. data/app/models/para/component/base.rb +1 -1
  12. data/app/models/para/component_section.rb +1 -1
  13. data/app/models/para/page/section.rb +21 -0
  14. data/app/views/layouts/para/admin.html.haml +2 -2
  15. data/app/views/para/admin/crud_resources/index.html.haml +1 -2
  16. data/app/views/para/admin/dashboard.html.haml +1 -2
  17. data/app/views/para/admin/resources/_table.html.haml +2 -2
  18. data/app/views/para/admin/resources/_tree_item.html.haml +7 -4
  19. data/app/views/para/admin/resources/edit.html.haml +1 -3
  20. data/app/views/para/admin/resources/new.html.haml +1 -3
  21. data/app/views/para/admin/settings_component/show.html.haml +2 -3
  22. data/app/views/para/admin/singleton_resources/show.html.haml +1 -2
  23. data/app/views/para/inputs/_nested_many.html.haml +1 -2
  24. data/app/views/para/inputs/nested_many/_container.html.haml +2 -1
  25. data/db/migrate/20160419145254_create_para_page_sections.rb +12 -0
  26. data/lib/generators/para/component/templates/show.html.haml +1 -2
  27. data/lib/generators/para/install/templates/initializer.rb +5 -1
  28. data/lib/generators/para/nested_fields/nested_fields_generator.rb +2 -2
  29. data/lib/generators/para/page/section/section_generator.rb +28 -0
  30. data/lib/generators/para/page/section/templates/section.rb.erb +6 -0
  31. data/lib/para/attribute_field/boolean.rb +1 -1
  32. data/lib/para/attribute_field/enum.rb +1 -1
  33. data/lib/para/breadcrumbs/breadcrumb.rb +1 -1
  34. data/lib/para/config.rb +21 -2
  35. data/lib/para/engine.rb +12 -0
  36. data/lib/para/ext/simple_form_extension.rb +21 -0
  37. data/lib/para/ext.rb +1 -0
  38. data/lib/para/form_builder/containers.rb +4 -4
  39. data/lib/para/form_builder/nested_form.rb +2 -2
  40. data/lib/para/form_builder/tabs.rb +1 -1
  41. data/lib/para/generators/field_helpers.rb +10 -3
  42. data/lib/para/inputs/nested_many_input.rb +2 -0
  43. data/lib/para/markup/resources_table.rb +15 -10
  44. data/lib/para/model_field_parsers/store.rb +24 -1
  45. data/lib/para/page/model.rb +12 -0
  46. data/lib/para/page.rb +6 -0
  47. data/lib/para/routes.rb +13 -0
  48. data/lib/para/sti/root_model.rb +58 -0
  49. data/lib/para/sti.rb +6 -0
  50. data/lib/para/version.rb +1 -1
  51. data/lib/para.rb +3 -0
  52. data/lib/rails/relation_length_validator.rb +2 -2
  53. data/lib/rails/routing_mapper.rb +13 -1
  54. metadata +27 -4
  55. data/app/controllers/para/admin/settings_form_controller.rb +0 -21
  56. data/app/views/para/admin/crud_component/show.html.haml +0 -4
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 732caede63e764554d7a140b937d9b2c22ca9c85
4
- data.tar.gz: 2cf5c7b7351487eb7b6c73de119fe8e0b17a79af
3
+ metadata.gz: 855b5d4493847325b66af2955504dcb8524f9e2d
4
+ data.tar.gz: 32e9da832c3641f4993cdd3c65096782ef4ba14b
5
5
  SHA512:
6
- metadata.gz: abf828d53004049d831e19fb4125cc5ab54c254decc1f28a30a06bf8866f5bae76ca287d2e2b5664a28685c278106bd9ce269c51c1f6822be0984beab3a47148
7
- data.tar.gz: c271d48d9883fd0f5268efddddf48efa61a3b77cc8ca4309896aeb8ec3c18f17f60a59522d746e04b94b34fb84c7fc1683b6147bc24fec5780015197796a88b0
6
+ metadata.gz: b5f34e153a1bc38d5e07e37c96b7a9f181e0be8957d1c1d685d3606649fcfefd88a426e8fd201302289f81d99ba076919e98295c8ae8c720cf3aed61698846db
7
+ data.tar.gz: 790dffa7b7fa6d327548b23e3a1dec0aeabf115bea3ceb6aa4fd31588f4c5f0318f1b23ca4daf3da6167e2bbde207bdcd1cdc4a5358443d23fcdc686bba1d86c
@@ -17,7 +17,7 @@ class Para.NestedManyField
17
17
 
18
18
  @$fieldsList.on('sortupdate', $.proxy(@sortUpdate, this))
19
19
 
20
- sortUpdate: (e, ui) ->
20
+ sortUpdate: ->
21
21
  @$fieldsList.find('.form-fields').each (i, el) ->
22
22
  $(el).find('.resource-position-field').val(i)
23
23
 
@@ -31,6 +31,7 @@ class Para.NestedManyField
31
31
  if @orderable
32
32
  @$fieldsList.sortable('destroy')
33
33
  @initializeOrderable()
34
+ @sortUpdate()
34
35
 
35
36
  if ($redactor = $element.find('[data-redactor]')).length
36
37
  $redactor.simpleFormRedactor()
@@ -0,0 +1,9 @@
1
+ .page-actions
2
+ float: left
3
+ padding:
4
+ left: 10px
5
+ margin:
6
+ top: 15px
7
+ left: 10px
8
+ border:
9
+ left: 1px solid #ccc
@@ -13,6 +13,7 @@ body, html
13
13
  -moz-osx-font-smoothing: grayscale
14
14
 
15
15
  .body-full-height
16
+ height: 100%
16
17
  body
17
18
  height: 100%
18
19
 
@@ -95,7 +95,7 @@ module Para
95
95
  end
96
96
 
97
97
  def add_breadcrumbs
98
- add_breadcrumb(resource_title_for(resource)) if resource
98
+ add_breadcrumb(resource_title_for(resource), path_to_edit(resource)) if resource
99
99
  end
100
100
 
101
101
  def attach_resource_to_component
@@ -107,6 +107,12 @@ module Para
107
107
  return unless @component.namespaced?
108
108
  @component.remove_resource(resource)
109
109
  end
110
+
111
+ def path_to_edit(resource)
112
+ @component.relation_path(
113
+ resource, action: (resource.persisted? ? :edit : :new)
114
+ )
115
+ end
110
116
  end
111
117
  end
112
118
  end
@@ -4,6 +4,20 @@ module Para
4
4
  def show
5
5
  @settings = SettingsRails::Form.new
6
6
  end
7
+
8
+ def update
9
+ form = SettingsRails::Form.new
10
+ form.settings_attributes = settings_params[:settings_attributes]
11
+ form.save
12
+ flash_message(:success, form)
13
+ redirect_to admin_settings_path(@component)
14
+ end
15
+
16
+ private
17
+
18
+ def settings_params
19
+ params.require(:resource).permit(settings_attributes: [:key, :_type, :value])
20
+ end
7
21
  end
8
22
  end
9
23
  end
@@ -8,15 +8,19 @@ module Para
8
8
  find_path([:admin, self, :resources], options)
9
9
  end
10
10
 
11
- def relation_path(controller_or_resource, options = {})
11
+ def relation_path(controller_or_resource, *nested_resources, **options)
12
+ id_key = nested_resources.empty? ? :id : :resource_id
13
+
12
14
  if (id = extract_id_from(controller_or_resource))
13
- options[:id] = id
15
+ options[id_key] = id
14
16
  end
15
17
 
16
- route_key = route_key_for(options[:id], options)
18
+ route_key = route_key_for(options[id_key], options)
17
19
  options[:model] = model_singular_route_key
18
20
 
19
- polymorphic_path([:admin, self, route_key].compact, options)
21
+ data = [:admin, self, route_key].compact + nested_resources
22
+
23
+ polymorphic_path(data, options)
20
24
  end
21
25
 
22
26
  private
@@ -66,9 +66,9 @@ module Para
66
66
  key = "#{ flash_shared_key }.#{ params[:action] }.#{ type }"
67
67
 
68
68
  translation = if resource
69
- I18n.t(key, model: resource.class.model_name.human)
69
+ ::I18n.t(key, model: resource.class.model_name.human)
70
70
  else
71
- I18n.t(key)
71
+ ::I18n.t(key)
72
72
  end
73
73
 
74
74
  flash[type] = translation
@@ -89,7 +89,9 @@ module Para
89
89
  end
90
90
 
91
91
  def partial_exists?(relation, partial)
92
- lookup_context.find_all("admin/#{relation}/_#{ partial }").any?
92
+ partial_path = partial.to_s.split('/')
93
+ partial_path[-1] = "_#{ partial_path.last }"
94
+ lookup_context.find_all("admin/#{relation}/#{ partial_path.join('/') }").any?
93
95
  end
94
96
  end
95
97
  end
@@ -0,0 +1,32 @@
1
+ module Para
2
+ module Admin
3
+ module PageHelper
4
+ def page_top_bar(options = {})
5
+ content_tag(:div, class: 'page-title') do
6
+ content_tag(:h1, options[:title]) +
7
+
8
+ if (actions = actions_for(options[:type]))
9
+ content_tag(:div, class: 'page-actions') do
10
+ actions.map(&method(:build_action)).join('').html_safe
11
+ end
12
+ end
13
+ end
14
+ end
15
+
16
+ def build_action(action)
17
+ link_to(action[:url], class: 'btn btn-default') do
18
+ (
19
+ (fa_icon(action[:icon]) if action[:icon]) +
20
+ action[:label]
21
+ ).html_safe
22
+ end
23
+ end
24
+
25
+ def actions_for(type)
26
+ Para.config.page_actions_for(type).map do |action|
27
+ instance_eval(&action)
28
+ end
29
+ end
30
+ end
31
+ end
32
+ end
@@ -30,7 +30,7 @@ module Para
30
30
  component.relation_path(resource),
31
31
  method: :delete,
32
32
  data: {
33
- confirm: I18n.t('para.list.delete_confirmation')
33
+ confirm: ::I18n.t('para.list.delete_confirmation')
34
34
  },
35
35
  class: 'btn btn-danger'
36
36
  ) do
@@ -38,4 +38,4 @@ module Para
38
38
  end
39
39
  end
40
40
  end
41
- end
41
+ end
@@ -19,7 +19,7 @@ module Para
19
19
  scope :ordered, -> { order(position: :asc) }
20
20
 
21
21
  def name
22
- read_attribute(:name) || I18n.t(
22
+ read_attribute(:name) || ::I18n.t(
23
23
  "components.component.#{ identifier }",
24
24
  default: identifier.humanize
25
25
  )
@@ -9,7 +9,7 @@ module Para
9
9
  validates :identifier, presence: true
10
10
 
11
11
  def name
12
- read_attribute(:name) || I18n.t(
12
+ read_attribute(:name) || ::I18n.t(
13
13
  "components.section.#{ identifier }",
14
14
  default: identifier.humanize
15
15
  )
@@ -0,0 +1,21 @@
1
+ module Para
2
+ module Page
3
+ class Section < ActiveRecord::Base
4
+ self.table_name = 'para_page_sections'
5
+
6
+ include Para::Sti::RootModel
7
+
8
+ acts_as_orderable
9
+
10
+ belongs_to :page, polymorphic: true
11
+
12
+ def self.subclasses_namespace
13
+ 'PageSection'
14
+ end
15
+
16
+ def css_class
17
+ @css_class ||= self.class.name.demodulize.underscore.gsub(/_/, '-')
18
+ end
19
+ end
20
+ end
21
+ end
@@ -1,7 +1,7 @@
1
1
  !!!
2
- %html{ lang: 'en' }
2
+ %html.body-full-height{ lang: 'en' }
3
3
  %head
4
- %title= Para.config.admin_title || I18n.t('para.admin.title')
4
+ %title= Para.config.admin_title || ::I18n.t('para.admin.title')
5
5
 
6
6
  %meta{ charset: 'utf-8' }/
7
7
  %meta{ content: 'IE=edge', 'http-equiv' => 'X-UA-Compatible' }/
@@ -1,4 +1,3 @@
1
- .page-title
2
- %h1= @component.name
1
+ = page_top_bar(title: @component.name, type: 'crud/index')
3
2
 
4
3
  = listing_for(@resources)
@@ -1,5 +1,4 @@
1
- .page-title
2
- %h1= t('para.dashboard.title')
1
+ = page_top_bar(title: t('para.dashboard.title'), type: 'dashboard/show')
3
2
 
4
3
  .page-content-wrap
5
4
  - ordered_components.each_slice(3) do |components|
@@ -1,8 +1,8 @@
1
1
  = resources_table(model: model, component: component) do |table|
2
2
  = table.header do
3
3
  - attributes.each do |field|
4
- = table.header_for(field.name)
4
+ = table.header_for(field.name.to_sym)
5
5
 
6
6
  = table.rows(resources) do |resource|
7
7
  - attributes.each do |field|
8
- = table.data_for(resource, field.name)
8
+ = table.data_for(resource, field.name.to_sym)
@@ -2,15 +2,18 @@
2
2
  .node-row
3
3
  %span.handle
4
4
  %i.fa.fa-bars.fa-fw
5
- %span.node-name
5
+ %span.node-name
6
6
  = root.name
7
+
7
8
  .pull-right.btn-group
8
9
  = link_to @component.relation_path(root, action: :edit, return_to: request.fullpath), class: "btn btn-primary" do
9
10
  %i.fa.fa-pencil
10
- = link_to @component.relation_path(root), method: :delete, data: { confirm: I18n.t('para.list.delete_confirmation') }, class: 'btn btn-danger' do
11
+
12
+ = link_to @component.relation_path(root), method: :delete, data: { confirm: ::I18n.t('para.list.delete_confirmation') }, class: 'btn btn-danger' do
11
13
  %i.fa.fa-trash
12
- .clearfix
14
+
15
+ .clearfix
13
16
  %ul.tree
14
17
  %li.placeholder{ class: "#{ 'hidden' unless needs_placeholder?(root) }"}
15
18
  = render partial: find_partial_for(model, 'tree_item'), collection: root.children.ordered, as: :root, locals: { model: model }
16
-
19
+
@@ -1,6 +1,4 @@
1
- .page-title
2
- %h1
3
- = resource_title_for(resource)
1
+ = page_top_bar(title: resource_title_for(resource), type: 'crud/edit')
4
2
 
5
3
  .page-content-wrap
6
4
  = render find_partial_for(resource, :form)
@@ -1,6 +1,4 @@
1
- .page-title
2
- %h1
3
- = resource_title_for(resource)
1
+ = page_top_bar(title: resource_title_for(resource), type: 'crud/new')
4
2
 
5
3
  .page-content-wrap
6
4
  = render find_partial_for(resource, :form)
@@ -1,8 +1,7 @@
1
- .page-title
2
- %h1= @component.name
1
+ = page_top_bar(title: @component.name, type: 'settings/show')
3
2
 
4
3
  .page-content-wrap
5
- = para_form_for @settings, url: admin_settings_settings_form_path(@component) do |form|
4
+ = para_form_for @settings, url: admin_settings_path(@component) do |form|
6
5
  = form.fieldset do
7
6
  - @component.settings.each do |setting, type|
8
7
  = form.settings_input setting, type: type
@@ -1,5 +1,4 @@
1
- .page-title
2
- %h1= @component.name
1
+ = page_top_bar(title: @component.name, type: 'singleton_resource/show')
3
2
 
4
3
  .page-content-wrap
5
4
  = render find_partial_for(resource, :form)
@@ -1,8 +1,7 @@
1
1
  .nested-many-field{ class: ('orderable' if orderable) }
2
2
  .fields-list{ id: dom_identifier }
3
3
  = form.simple_fields_for attribute_name, resources, nested_attribute_name: attribute_name, orderable: orderable do |nested_form|
4
- = render partial: find_partial_for(model, 'nested_many/container', partial_dir: 'inputs'), locals: { form: nested_form, model: model, subclass: subclass, nested_locals: nested_locals }
5
-
4
+ = render partial: find_partial_for(model, 'nested_many/container', partial_dir: 'inputs'), locals: { form: nested_form, model: nested_form.object.class, subclass: subclass, nested_locals: nested_locals }
6
5
  -# Add button
7
6
  - if add_button
8
7
  - if subclass
@@ -16,6 +16,7 @@
16
16
  .panel-body.form-inputs.collapse{ id: form.nested_resource_dom_id }
17
17
  = render partial: find_partial_for(model, :fields), locals: { form: form }.merge(nested_locals)
18
18
 
19
- = form.hidden_field :type if form.object.class.column_names.include?(form.object.class.inheritance_column)
19
+ -# Add inheritance column field if needed
20
+ = form.hidden_field form.object.class.inheritance_column if form.object.class.column_names.include?(form.object.class.inheritance_column)
20
21
 
21
22
  .clearfix
@@ -0,0 +1,12 @@
1
+ class CreateParaPageSections < ActiveRecord::Migration
2
+ def change
3
+ create_table :para_page_sections do |t|
4
+ t.string :type
5
+ t.jsonb :data
6
+ t.integer :position, default: 0
7
+ t.references :page, index: true, polymorphic: true
8
+
9
+ t.timestamps null: false
10
+ end
11
+ end
12
+ end
@@ -1,2 +1 @@
1
- .page-title
2
- %h1= @component.name
1
+ = page_top_bar(title: @component.name, type: '<%= file_name %>/show')
@@ -9,7 +9,7 @@ Para.config do |config|
9
9
  # config.pagination_theme = 'twitter-bootstrap-3'
10
10
 
11
11
  # Configure the default admin HTML page <title>
12
- # config.admin_title = I18n.t('para.admin.title')
12
+ # config.admin_title = ::I18n.t('para.admin.title')
13
13
 
14
14
  # Configure the default max depth for trees
15
15
  # config.default_tree_max_depth = 3
@@ -20,4 +20,8 @@ Para.config do |config|
20
20
  # Default is [:name, :title]
21
21
  #
22
22
  # config.resource_name_methods += [:full_name]
23
+
24
+ # Para plugins to load
25
+ #
26
+ # config.plugins = []
23
27
  end
@@ -16,8 +16,8 @@ module Para
16
16
 
17
17
  def generate_fields_container
18
18
  template(
19
- "../../../../../app/views/para/inputs/_nested_many_container.html.haml",
20
- "app/views/admin/#{ plural_namespaced_path }/_nested_many_container.html.haml"
19
+ "../../../../../app/views/para/inputs/nested_many/_container.html.haml",
20
+ "app/views/admin/#{ plural_namespaced_path }/nested_many/_container.html.haml"
21
21
  ) if options[:container]
22
22
  end
23
23
  end
@@ -0,0 +1,28 @@
1
+ module Para
2
+ module Page
3
+ class SectionGenerator < Rails::Generators::NamedBase
4
+ include Para::Generators::NameHelpers
5
+
6
+ source_root File.expand_path("../templates", __FILE__)
7
+
8
+ argument :attributes, type: :array
9
+
10
+ def generate_form
11
+ template(
12
+ "section.rb.erb",
13
+ "app/models/page_section/#{ plural_namespaced_path }.rb"
14
+ )
15
+ end
16
+
17
+ private
18
+
19
+ def attributes_separated_with_commas
20
+ if attributes.empty?
21
+ ':title'
22
+ else
23
+ attributes.map { |attribute| ":#{ attribute.name }" }.join(', ')
24
+ end
25
+ end
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,6 @@
1
+ module PageSection
2
+ class <%= class_name %> < Para::Page::Section
3
+ # Your page section fields are declared here as store accessors
4
+ store_accessor :data, <%= attributes_separated_with_commas %>
5
+ end
6
+ end
@@ -6,7 +6,7 @@ module Para
6
6
  field_option :wrapper, :wrapper_name
7
7
 
8
8
  def value_for(instance)
9
- I18n.t("para.types.boolean.#{ (!!instance.send(name)).to_s }")
9
+ ::I18n.t("para.types.boolean.#{ (!!instance.send(name)).to_s }")
10
10
  end
11
11
 
12
12
  def wrapper_name
@@ -6,7 +6,7 @@ module Para
6
6
  def value_for(instance)
7
7
  if (raw_value = instance.send(name)) &&
8
8
  path = enum_path_for(instance, raw_value)
9
- translation = I18n.t("activerecord.#{ path }", default: false)
9
+ translation = ::I18n.t("activerecord.#{ path }", default: false)
10
10
 
11
11
  translation || raw_value
12
12
  end
@@ -11,7 +11,7 @@ module Para
11
11
 
12
12
  def title
13
13
  @title ||= if Symbol === identifier
14
- I18n.t("admin.breadcrumbs.#{ identifier }")
14
+ ::I18n.t("admin.breadcrumbs.#{ identifier }")
15
15
  else
16
16
  identifier
17
17
  end
data/lib/para/config.rb CHANGED
@@ -18,11 +18,18 @@ module Para
18
18
  mattr_accessor :resource_name_methods
19
19
  @@resource_name_methods = [:admin_name, :admin_title, :name, :title]
20
20
 
21
+ mattr_accessor :plugins
22
+ @@plugins = []
23
+
24
+ # Hidden from initializer on purpose.
25
+ #
26
+ # This is mainly here to be overriden from a gem, not the app dev
27
+ #
21
28
  mattr_accessor :ability_class_name
22
29
  @@ability_class_name = 'Para::Ability'
23
30
 
24
- mattr_accessor :plugins
25
- @@plugins = []
31
+ mattr_accessor :page_actions
32
+ @@page_actions = {}
26
33
 
27
34
  # Allows accessing plugins root module to configure them through a method
28
35
  # from the Para::Config class.
@@ -41,5 +48,17 @@ module Para
41
48
  super
42
49
  end
43
50
  end
51
+
52
+ def self.routes
53
+ Para::Routes
54
+ end
55
+
56
+ def self.page_actions_for(type)
57
+ page_actions[type] ||= []
58
+ end
59
+
60
+ def self.add_actions_for(type, &block)
61
+ page_actions_for(type) << block
62
+ end
44
63
  end
45
64
  end
data/lib/para/engine.rb CHANGED
@@ -48,6 +48,14 @@ module Para
48
48
  end
49
49
  end
50
50
 
51
+ initializer 'Extend simple form extension selectize input' do
52
+ ActiveSupport.on_load(:active_record) do
53
+ ::SimpleFormExtension::Inputs::SelectizeInput.send(
54
+ :include, Para::Ext::SimpleFormExtension::SelectizeInput
55
+ )
56
+ end
57
+ end
58
+
51
59
  initializer 'Build components tree' do |app|
52
60
  components_config_path = Rails.root.join('config', 'components.rb')
53
61
 
@@ -55,5 +63,9 @@ module Para
55
63
  require components_config_path if File.exist?(components_config_path)
56
64
  end
57
65
  end
66
+
67
+ initializer 'Load page sections' do |app|
68
+ Para::Page::Section.eager_load!
69
+ end
58
70
  end
59
71
  end
@@ -0,0 +1,21 @@
1
+ module Para
2
+ module Ext
3
+ module SimpleFormExtension
4
+ module SelectizeInput
5
+ extend ActiveSupport::Concern
6
+
7
+ included do
8
+ alias_method_chain :name_for, :admin_name
9
+ end
10
+
11
+ def name_for_with_admin_name(option)
12
+ Para.config.resource_name_methods.each do |method|
13
+ if (name = option.try(method))
14
+ return name
15
+ end
16
+ end
17
+ end
18
+ end
19
+ end
20
+ end
21
+ end
data/lib/para/ext.rb CHANGED
@@ -11,3 +11,4 @@ end
11
11
 
12
12
  require 'para/ext/cancan'
13
13
  require 'para/ext/paperclip'
14
+ require 'para/ext/simple_form_extension'
@@ -45,20 +45,20 @@ module Para
45
45
  end
46
46
 
47
47
  def para_submit_button(options = {})
48
- button(:submit, I18n.t('para.shared.save'), name: '_save', class: 'btn-success')
48
+ button(:submit, ::I18n.t('para.shared.save'), name: '_save', class: 'btn-success')
49
49
  end
50
50
 
51
51
  def para_submit_and_edit_button
52
- button(:submit, I18n.t('para.shared.save_and_edit'), name: '_save_and_edit', class: 'btn-primary')
52
+ button(:submit, ::I18n.t('para.shared.save_and_edit'), name: '_save_and_edit', class: 'btn-primary')
53
53
  end
54
54
 
55
55
  def para_submit_and_add_another_button
56
- button(:submit, I18n.t('para.shared.save_and_add_another_button'), name: '_save_and_add_another', class: 'btn-primary')
56
+ button(:submit, ::I18n.t('para.shared.save_and_add_another_button'), name: '_save_and_add_another', class: 'btn-primary')
57
57
  end
58
58
 
59
59
  def para_cancel_button
60
60
  template.link_to(
61
- I18n.t('para.shared.cancel'),
61
+ ::I18n.t('para.shared.cancel'),
62
62
  return_to_path,
63
63
  class: 'btn btn-danger'
64
64
  )
@@ -39,7 +39,7 @@ module Para
39
39
  self, wrapper_class: 'form-fields', class: 'btn btn-danger'
40
40
  ) do
41
41
  template.content_tag(:i, '', class: 'fa fa-trash') +
42
- I18n.t('para.form.nested.remove')
42
+ ::I18n.t('para.form.nested.remove')
43
43
  end
44
44
  end
45
45
  end
@@ -75,7 +75,7 @@ module Para
75
75
 
76
76
  def default_resource_name
77
77
  model_name = object.class.model_name.human
78
- id_or_new = (id = object.id) ? id : I18n.t('para.form.nested.new')
78
+ id_or_new = (id = object.id) ? id : ::I18n.t('para.form.nested.new')
79
79
 
80
80
  [model_name, id_or_new].join(' - ')
81
81
  end
@@ -41,7 +41,7 @@ module Para
41
41
 
42
42
  def title
43
43
  if Symbol === identifier
44
- I18n.t("forms.tabs.#{ object.class.model_name.i18n_key }.#{ identifier }")
44
+ ::I18n.t("forms.tabs.#{ object.class.model_name.i18n_key }.#{ identifier }")
45
45
  else
46
46
  identifier
47
47
  end
@@ -10,12 +10,19 @@ module Para
10
10
  end
11
11
  end
12
12
 
13
- def field_options_for(field)
14
- field_options = field.field_options
13
+ def field_options_for(field, options = {})
14
+ field_options = field.field_options.merge(options)
15
15
 
16
16
  options = field_options.each_with_object([]) do |(key, value), ary|
17
17
  if writable_value?(value)
18
- ary << "#{ key.inspect } => #{ value.inspect }"
18
+ if key.to_s.match(/^[\w\d]+/)
19
+ join_symbol = ': '
20
+ else
21
+ join_symbol = ' => '
22
+ key = key.inspect
23
+ end
24
+
25
+ ary << [key, join_symbol, value.inspect].join
19
26
  end
20
27
  end
21
28
 
@@ -1,6 +1,8 @@
1
1
  module Para
2
2
  module Inputs
3
3
  class NestedManyInput < SimpleForm::Inputs::Base
4
+ attr_reader :resource
5
+
4
6
  def input(wrapper_options = nil)
5
7
  input_html_options[:class] << "nested-many"
6
8
 
@@ -1,6 +1,9 @@
1
1
  module Para
2
2
  module Markup
3
3
  class ResourcesTable < Para::Markup::Component
4
+ class_attribute :default_actions
5
+ self.default_actions = [:edit, :clone, :delete]
6
+
4
7
  attr_reader :model, :component, :orderable, :actions
5
8
 
6
9
  def container(options = {}, &block)
@@ -11,7 +14,7 @@ module Para
11
14
  @orderable = model.orderable?
12
15
  end
13
16
 
14
- @actions = options.fetch(:actions, true)
17
+ @actions = build_actions(options.delete(:actions))
15
18
 
16
19
  merge_class!(options, 'table')
17
20
  merge_class!(options, 'para-component-relation-table')
@@ -41,7 +44,7 @@ module Para
41
44
  # Append cells
42
45
  cells << capture { block.call }
43
46
  # Append actions empty cell
44
- cells << content_tag(:th, '', class: 'actions') if actions
47
+ cells << content_tag(:th, '', class: 'actions', width: 1) if actions
45
48
 
46
49
  # Output full header
47
50
  content_tag(:thead) do
@@ -132,11 +135,9 @@ module Para
132
135
  def actions_cell(resource)
133
136
  content_tag(:td) do
134
137
  content_tag(:div, class: 'pull-right btn-group') do
135
- edit = edit_button(resource) if action?(:edit)
136
- clone = clone_button(resource) if action?(:clone)
137
- delete = delete_button(resource) if action?(:delete)
138
-
139
- edit + clone + delete
138
+ actions.map do |type|
139
+ send(:"#{ type }_button", resource)
140
+ end.compact.join.html_safe
140
141
  end
141
142
  end
142
143
  end
@@ -174,7 +175,7 @@ module Para
174
175
  options = {
175
176
  method: :delete,
176
177
  data: {
177
- confirm: I18n.t('para.list.delete_confirmation')
178
+ confirm: ::I18n.t('para.list.delete_confirmation')
178
179
  },
179
180
  class: 'btn btn-danger'
180
181
  }
@@ -194,8 +195,12 @@ module Para
194
195
  model.columns_hash.keys.include?(field_name.to_s)
195
196
  end
196
197
 
197
- def action?(type)
198
- actions == true || actions.include?(type)
198
+ def build_actions(actions)
199
+ if actions.in?([true, nil])
200
+ default_actions
201
+ else
202
+ actions
203
+ end
199
204
  end
200
205
  end
201
206
  end
@@ -4,6 +4,11 @@ module Para
4
4
  register :json, self
5
5
 
6
6
  def parse!
7
+ process_stored_attributes
8
+ process_remaining_json_fields
9
+ end
10
+
11
+ def process_stored_attributes
7
12
  model.stored_attributes.each do |store_key, field_names|
8
13
  fields_hash.delete(store_key)
9
14
 
@@ -15,8 +20,26 @@ module Para
15
20
  end
16
21
  end
17
22
 
23
+ # Duplicate fields to avoid updating the hash while iterating through it
24
+ # then remove remaining json fields from the hash
25
+ def process_remaining_json_fields
26
+ fields_hash.dup.each do |key, field|
27
+ fields_hash.delete(key) if json_field?(field)
28
+ end
29
+ end
30
+
18
31
  def applicable?
19
- !model.stored_attributes.empty?
32
+ !model.stored_attributes.empty? || model_includes_json_fields?
33
+ end
34
+
35
+ def model_includes_json_fields?
36
+ fields_hash.any? do |_, field|
37
+ json_field?(field)
38
+ end
39
+ end
40
+
41
+ def json_field?(field)
42
+ field.type.to_s.in?(%w(json jsonb))
20
43
  end
21
44
  end
22
45
  end
@@ -0,0 +1,12 @@
1
+ module Para
2
+ module Page
3
+ module Model
4
+ extend ActiveSupport::Concern
5
+
6
+ included do
7
+ has_many :sections, -> { ordered }, class_name: '::Para::Page::Section', as: :page
8
+ accepts_nested_attributes_for :sections, allow_destroy: true
9
+ end
10
+ end
11
+ end
12
+ end
data/lib/para/page.rb ADDED
@@ -0,0 +1,6 @@
1
+ module Para
2
+ module Page
3
+ end
4
+ end
5
+
6
+ require 'para/page/model'
data/lib/para/routes.rb CHANGED
@@ -1,5 +1,7 @@
1
1
  module Para
2
2
  class Routes
3
+ class_attribute :routes_extensions
4
+
3
5
  attr_reader :router
4
6
 
5
7
  def initialize(router)
@@ -15,6 +17,7 @@ module Para
15
17
 
16
18
  crud_component :crud, scope: ':model'
17
19
  singleton_resource_component :singleton, scope: ':model'
20
+ component :settings
18
21
  end
19
22
  end
20
23
 
@@ -22,5 +25,15 @@ module Para
22
25
  end
23
26
  end
24
27
  end
28
+
29
+ def self.extend_routes_for(component_type, &block)
30
+ extensions = routes_extensions_for(component_type)
31
+ extensions << block
32
+ end
33
+
34
+ def self.routes_extensions_for(component_type)
35
+ self.routes_extensions ||= {}
36
+ self.routes_extensions[component_type] ||= []
37
+ end
25
38
  end
26
39
  end
@@ -0,0 +1,58 @@
1
+ module Para
2
+ module Sti
3
+ module RootModel
4
+ extend ActiveSupport::Concern
5
+
6
+ included do
7
+ class << self
8
+ def descendants_with_eager_loaded_subclasses
9
+ eager_load!
10
+ descendants_without_eager_loaded_subclasses
11
+ end
12
+
13
+ alias_method_chain :descendants, :eager_loaded_subclasses
14
+ end
15
+ end
16
+
17
+ module ClassMethods
18
+ def eager_load!
19
+ return if @eager_loaded
20
+ @eager_loaded = true
21
+
22
+ models_dir = Rails.root.join('app', 'models')
23
+
24
+ Dir[models_dir.join(subclasses_dir, '*.rb')].each do |file_path|
25
+ file_name = File.basename(file_path, '.rb')
26
+
27
+ # Avoid Circular dependecy errors in development, when the first
28
+ # loaded class is not the base class. In this case, the base class
29
+ # loading is triggered by the child, so if we try to load that child
30
+ # again, Rails issues a CircularDependency error
31
+ file_load_path = File.join(File.dirname(file_path), file_name)
32
+ next if ActiveSupport::Dependencies.loading.include?(file_load_path)
33
+
34
+ # Autoload the subclass
35
+ require file_load_path
36
+ end
37
+ end
38
+
39
+ private
40
+
41
+ # Allows the including class to define `.subclasses_namespace` class
42
+ # method to override the namespace and directory used to eager load the
43
+ # subclasses.
44
+ #
45
+ # Note : No error is raised if target subclasses directory does not
46
+ # exist.
47
+ #
48
+ def subclasses_namespace
49
+ @subclasses_namespace ||= name.deconstantize
50
+ end
51
+
52
+ def subclasses_dir
53
+ @subclasses_dir ||= subclasses_namespace.underscore
54
+ end
55
+ end
56
+ end
57
+ end
58
+ end
data/lib/para/sti.rb ADDED
@@ -0,0 +1,6 @@
1
+ module Para
2
+ module Sti
3
+ end
4
+ end
5
+
6
+ require 'para/sti/root_model'
data/lib/para/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Para
2
- VERSION = "0.5.1"
2
+ VERSION = "0.5.3"
3
3
  end
data/lib/para.rb CHANGED
@@ -8,6 +8,7 @@ require 'truncate_html'
8
8
  require 'cocoon'
9
9
  require 'cancan'
10
10
  require 'request_store'
11
+ require 'roo'
11
12
 
12
13
  require 'sass-rails'
13
14
  require 'selectize-rails'
@@ -32,6 +33,8 @@ require 'para/engine'
32
33
  require 'para/components_configuration'
33
34
  require 'para/exporter'
34
35
  require 'para/importer'
36
+ require 'para/sti'
37
+ require 'para/page'
35
38
 
36
39
  module Para
37
40
  extend ActiveSupport::Autoload
@@ -27,7 +27,7 @@ class RelationLengthValidator < ActiveModel::EachValidator
27
27
 
28
28
  def smaller_error_message
29
29
  message = options[:message] && options[:message][:minimum]
30
- message || I18n.t(
30
+ message || ::I18n.t(
31
31
  "activerecord.errors.relation_length_is_smaller",
32
32
  minimum: minimum,
33
33
  default: "must have at least #{ minimum } elements"
@@ -36,7 +36,7 @@ class RelationLengthValidator < ActiveModel::EachValidator
36
36
 
37
37
  def greater_error_message
38
38
  message = options[:message] && options[:message][:maximum]
39
- message || I18n.t(
39
+ message || ::I18n.t(
40
40
  "activerecord.errors.relation_length_is_greater",
41
41
  maximum: maximum,
42
42
  default: "must have at most #{ maximum } elements"
@@ -20,7 +20,11 @@ module ActionDispatch
20
20
  )
21
21
 
22
22
  get endpoint => "#{ controller }#show", as: as
23
- scope(endpoint, as: component_name, &block) if block
23
+
24
+ scope(endpoint, as: component_name) do
25
+ instance_eval(&block) if block
26
+ add_extensions_for(:component)
27
+ end
24
28
  end
25
29
 
26
30
  def crud_component(component_name, options = {}, &block)
@@ -45,6 +49,7 @@ module ActionDispatch
45
49
  end
46
50
 
47
51
  instance_eval(&block) if block
52
+ add_extensions_for(:crud_component)
48
53
  end
49
54
  end
50
55
  end
@@ -59,6 +64,7 @@ module ActionDispatch
59
64
 
60
65
  scope endpoint, as: as do
61
66
  resource :resource, controller: controller, only: [:show, :create, :update]
67
+ add_extensions_for(:singleton_resource_component)
62
68
  end
63
69
  end
64
70
 
@@ -81,6 +87,12 @@ module ActionDispatch
81
87
 
82
88
  [as, controller, endpoint]
83
89
  end
90
+
91
+ def add_extensions_for(type)
92
+ Para.config.routes.routes_extensions_for(type).each do |extension|
93
+ instance_eval(&extension)
94
+ end
95
+ end
84
96
  end
85
97
  end
86
98
  end
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.5.1
4
+ version: 0.5.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Valentin Ballestrino
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2016-04-08 00:00:00.000000000 Z
11
+ date: 2016-05-11 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rails
@@ -192,6 +192,20 @@ dependencies:
192
192
  - - ">="
193
193
  - !ruby/object:Gem::Version
194
194
  version: '0'
195
+ - !ruby/object:Gem::Dependency
196
+ name: roo
197
+ requirement: !ruby/object:Gem::Requirement
198
+ requirements:
199
+ - - ">="
200
+ - !ruby/object:Gem::Version
201
+ version: '0'
202
+ type: :runtime
203
+ prerelease: false
204
+ version_requirements: !ruby/object:Gem::Requirement
205
+ requirements:
206
+ - - ">="
207
+ - !ruby/object:Gem::Version
208
+ version: '0'
195
209
  - !ruby/object:Gem::Dependency
196
210
  name: bootstrap-sass
197
211
  requirement: !ruby/object:Gem::Requirement
@@ -347,6 +361,7 @@ files:
347
361
  - app/assets/stylesheets/para/admin/src/fuelux.sass
348
362
  - app/assets/stylesheets/para/admin/src/jasny.bootstrap.sass
349
363
  - app/assets/stylesheets/para/admin/src/page-loading.sass
364
+ - app/assets/stylesheets/para/admin/src/page-top-bar.sass
350
365
  - app/assets/stylesheets/para/admin/src/redactor.sass
351
366
  - app/assets/stylesheets/para/admin/src/selectize.sass
352
367
  - app/assets/stylesheets/para/admin/src/slider.sass
@@ -379,7 +394,6 @@ files:
379
394
  - app/controllers/para/admin/main_controller.rb
380
395
  - app/controllers/para/admin/resources_controller.rb
381
396
  - app/controllers/para/admin/settings_component_controller.rb
382
- - app/controllers/para/admin/settings_form_controller.rb
383
397
  - app/controllers/para/admin/singleton_resources_controller.rb
384
398
  - app/controllers/para/application_controller.rb
385
399
  - app/decorators/para/component/base_decorator.rb
@@ -390,6 +404,7 @@ files:
390
404
  - app/helpers/para/admin/base_helper.rb
391
405
  - app/helpers/para/admin/component_groups_helper.rb
392
406
  - app/helpers/para/admin/components_helper.rb
407
+ - app/helpers/para/admin/page_helper.rb
393
408
  - app/helpers/para/admin/resources_helper.rb
394
409
  - app/helpers/para/application_helper.rb
395
410
  - app/helpers/para/exports_helper.rb
@@ -410,9 +425,9 @@ files:
410
425
  - app/models/para/component/singleton_resource.rb
411
426
  - app/models/para/component_resource.rb
412
427
  - app/models/para/component_section.rb
428
+ - app/models/para/page/section.rb
413
429
  - app/views/layouts/para/admin.html.haml
414
430
  - app/views/layouts/para/application.html.erb
415
- - app/views/para/admin/crud_component/show.html.haml
416
431
  - app/views/para/admin/crud_resources/index.html.haml
417
432
  - app/views/para/admin/dashboard.html.haml
418
433
  - app/views/para/admin/main/index.html.haml
@@ -451,6 +466,7 @@ files:
451
466
  - db/migrate/20150129170710_create_para_component_resources.rb
452
467
  - db/migrate/20150203173219_add_identifier_to_para_components.rb
453
468
  - db/migrate/20160304113055_add_json_equality_operator_patch_to_postgres.rb
469
+ - db/migrate/20160419145254_create_para_page_sections.rb
454
470
  - lib/generators/para/admin_user/admin_user_generator.rb
455
471
  - lib/generators/para/component/component_generator.rb
456
472
  - lib/generators/para/component/crud/crud_generator.rb
@@ -475,6 +491,8 @@ files:
475
491
  - lib/generators/para/nested_fields/templates/_nested_fields.html.haml
476
492
  - lib/generators/para/orderable/orderable_generator.rb
477
493
  - lib/generators/para/orderable/templates/orderable_migration.rb
494
+ - lib/generators/para/page/section/section_generator.rb
495
+ - lib/generators/para/page/section/templates/section.rb.erb
478
496
  - lib/generators/para/resource/resource_generator.rb
479
497
  - lib/generators/para/resource/templates/resource_controller.rb
480
498
  - lib/generators/para/table/table_generator.rb
@@ -515,6 +533,7 @@ files:
515
533
  - lib/para/ext.rb
516
534
  - lib/para/ext/cancan.rb
517
535
  - lib/para/ext/paperclip.rb
536
+ - lib/para/ext/simple_form_extension.rb
518
537
  - lib/para/form_builder.rb
519
538
  - lib/para/form_builder/containers.rb
520
539
  - lib/para/form_builder/field_mappings.rb
@@ -549,9 +568,13 @@ files:
549
568
  - lib/para/model_field_parsers/relations.rb
550
569
  - lib/para/model_field_parsers/store.rb
551
570
  - lib/para/orderable.rb
571
+ - lib/para/page.rb
572
+ - lib/para/page/model.rb
552
573
  - lib/para/plugins.rb
553
574
  - lib/para/plugins/routes.rb
554
575
  - lib/para/routes.rb
576
+ - lib/para/sti.rb
577
+ - lib/para/sti/root_model.rb
555
578
  - lib/para/version.rb
556
579
  - lib/rails/relation_length_validator.rb
557
580
  - lib/rails/routing_mapper.rb
@@ -1,21 +0,0 @@
1
- module Para
2
- module Admin
3
- class SettingsFormController < Para::Admin::BaseController
4
- load_and_authorize_component
5
-
6
- def update
7
- form = SettingsRails::Form.new
8
- form.settings_attributes = settings_params[:settings_attributes]
9
- form.save
10
- flash_message(:success, form)
11
- redirect_to admin_settings_path(@component)
12
- end
13
-
14
- private
15
-
16
- def settings_params
17
- params.require(:resource).permit(settings_attributes: [:key, :_type, :value])
18
- end
19
- end
20
- end
21
- end
@@ -1,4 +0,0 @@
1
- .page-title
2
- %h1= @component.name
3
-
4
- = listing_for(@resources)