para 0.4.0 → 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (133) hide show
  1. checksums.yaml +4 -4
  2. data/app/assets/images/para/admin/loading-spinner.gif +0 -0
  3. data/app/assets/javascripts/para/admin/theme_actions.coffee +0 -1
  4. data/app/assets/javascripts/para/lib/turbolinks-forms.coffee +23 -0
  5. data/app/assets/javascripts/para/lib/turbolinks-loading.coffee +25 -0
  6. data/app/assets/stylesheets/para/{overrides → admin/src}/datetimepicker.sass +1 -3
  7. data/app/assets/stylesheets/para/{overrides → admin/src}/fuelux.sass +5 -8
  8. data/app/assets/stylesheets/para/{overrides → admin/src}/jasny.bootstrap.sass +1 -2
  9. data/app/assets/stylesheets/para/admin/src/page-loading.sass +24 -0
  10. data/app/assets/stylesheets/para/{overrides → admin/src}/redactor.sass +5 -7
  11. data/app/assets/stylesheets/para/{overrides → admin/src}/selectize.sass +4 -6
  12. data/app/assets/stylesheets/para/{overrides → admin/src}/slider.sass +0 -1
  13. data/app/assets/stylesheets/para/admin/theme/_base.sass +5 -3
  14. data/app/assets/stylesheets/para/admin/theme/_breadcrumb.sass +54 -16
  15. data/app/assets/stylesheets/para/admin/theme/_buttons.sass +0 -1
  16. data/app/assets/stylesheets/para/admin/theme/_checkable.sass +5 -6
  17. data/app/assets/stylesheets/para/admin/theme/_commonds.sass +10 -16
  18. data/app/assets/stylesheets/para/admin/theme/_dropdown.sass +1 -4
  19. data/app/assets/stylesheets/para/admin/theme/_form.sass +11 -3
  20. data/app/assets/stylesheets/para/admin/theme/_list.sass +5 -6
  21. data/app/assets/stylesheets/para/admin/theme/_navigation.sass +105 -109
  22. data/app/assets/stylesheets/para/admin/theme/_navtabs.sass +35 -15
  23. data/app/assets/stylesheets/para/admin/theme/_orderable.sass +2 -5
  24. data/app/assets/stylesheets/para/admin/theme/_panel.sass +20 -50
  25. data/app/assets/stylesheets/para/admin/theme/_sorting.sass +5 -7
  26. data/app/assets/stylesheets/para/admin/theme/_tree.sass +2 -4
  27. data/app/assets/stylesheets/para/admin.sass +1 -0
  28. data/app/assets/stylesheets/para/lib/_variables.scss +12 -12
  29. data/app/assets/stylesheets/para/overrides/responsive.sass +1 -2
  30. data/app/assets/stylesheets/para/overrides/theme.sass +10 -17
  31. data/app/controllers/para/admin/base_controller.rb +16 -5
  32. data/app/controllers/para/admin/crud_resources_controller.rb +43 -2
  33. data/app/controllers/para/admin/main_controller.rb +1 -1
  34. data/app/controllers/para/admin/resources_controller.rb +1 -1
  35. data/app/controllers/para/admin/settings_component_controller.rb +1 -3
  36. data/app/controllers/para/application_controller.rb +3 -3
  37. data/app/decorators/para/component/crud_decorator.rb +6 -2
  38. data/app/decorators/para/component/singleton_resource_decorator.rb +5 -1
  39. data/app/helpers/para/admin/base_helper.rb +9 -4
  40. data/app/helpers/para/admin/components_helper.rb +7 -0
  41. data/app/helpers/para/form_helper.rb +10 -2
  42. data/app/helpers/para/tag_helper.rb +12 -0
  43. data/app/models/para/ability.rb +12 -0
  44. data/app/models/para/component/base.rb +15 -7
  45. data/app/models/para/component/crud.rb +3 -1
  46. data/app/models/para/component/singleton_resource.rb +1 -1
  47. data/app/views/para/admin/crud_resources/index.html.haml +4 -0
  48. data/app/views/para/admin/dashboard.html.haml +10 -8
  49. data/app/views/para/admin/resources/_actions.html.haml +7 -0
  50. data/app/views/para/admin/resources/_add_button.html.haml +1 -0
  51. data/app/views/para/admin/resources/_filters.html.haml +1 -1
  52. data/app/views/para/admin/resources/_imports_menu.html.haml +22 -0
  53. data/app/views/para/admin/resources/_list.html.haml +8 -5
  54. data/app/views/para/admin/resources/_subclassable_add_button.html.haml +10 -0
  55. data/app/views/para/admin/resources/_tree.html.haml +1 -1
  56. data/app/views/para/admin/resources/_tree_item.html.haml +1 -1
  57. data/app/views/para/admin/resources/new.html.haml +1 -1
  58. data/app/views/para/admin/shared/_breadcrumbs.html.haml +8 -0
  59. data/app/views/para/admin/shared/_header.html.haml +26 -24
  60. data/app/views/para/admin/shared/_navigation.html.haml +5 -3
  61. data/app/views/para/form/_tabs.html.haml +13 -0
  62. data/app/views/para/inputs/_nested_many.html.haml +2 -2
  63. data/app/views/para/inputs/_nested_many_container.html.haml +1 -3
  64. data/config/locales/en.yml +10 -0
  65. data/config/locales/fr.yml +30 -15
  66. data/db/migrate/20160304113055_add_json_equality_operator_patch_to_postgres.rb +38 -0
  67. data/lib/generators/para/component/component_generator.rb +9 -29
  68. data/lib/generators/para/component/crud/crud_generator.rb +41 -0
  69. data/lib/generators/para/component/templates/component.rb +1 -1
  70. data/lib/generators/para/component/templates/decorator.rb +3 -0
  71. data/lib/generators/para/component/templates/resources_controller.rb +4 -0
  72. data/lib/generators/para/exporter/templates/base_exporter.rb +2 -0
  73. data/lib/generators/para/exporter/templates/csv_exporter.rb +2 -0
  74. data/lib/generators/para/filters/filters_generator.rb +16 -0
  75. data/lib/generators/para/filters/templates/_filters.html.haml +9 -0
  76. data/lib/generators/para/importer/importer_generator.rb +20 -0
  77. data/lib/generators/para/importer/templates/base_importer.rb +5 -0
  78. data/lib/generators/para/install/install_generator.rb +6 -25
  79. data/lib/generators/para/nested_fields/nested_fields_generator.rb +9 -0
  80. data/lib/para/attribute_field/base.rb +28 -0
  81. data/lib/para/attribute_field/belongs_to.rb +2 -0
  82. data/lib/para/attribute_field/boolean.rb +2 -0
  83. data/lib/para/attribute_field/datetime.rb +2 -0
  84. data/lib/para/attribute_field/enum.rb +22 -0
  85. data/lib/para/attribute_field/file.rb +2 -0
  86. data/lib/para/attribute_field/has_many.rb +2 -0
  87. data/lib/para/attribute_field/image.rb +2 -0
  88. data/lib/para/attribute_field/nested_many.rb +3 -0
  89. data/lib/para/attribute_field/nested_one.rb +6 -6
  90. data/lib/para/attribute_field/password.rb +2 -0
  91. data/lib/para/attribute_field/redactor.rb +2 -0
  92. data/lib/para/attribute_field/translation.rb +2 -0
  93. data/lib/para/attribute_field.rb +19 -0
  94. data/lib/para/attribute_field_mappings.rb +15 -29
  95. data/lib/para/breadcrumbs/breadcrumb.rb +43 -0
  96. data/lib/para/breadcrumbs/controller.rb +39 -0
  97. data/lib/para/breadcrumbs/manager.rb +19 -0
  98. data/lib/para/breadcrumbs.rb +9 -0
  99. data/lib/para/component/importable.rb +25 -0
  100. data/lib/para/component/subclassable.rb +27 -0
  101. data/lib/para/component.rb +5 -3
  102. data/lib/para/components_configuration.rb +18 -2
  103. data/lib/para/config.rb +25 -1
  104. data/lib/para/exporter/base.rb +13 -0
  105. data/lib/para/exporter/csv.rb +1 -1
  106. data/lib/para/form_builder/tabs.rb +56 -0
  107. data/lib/para/form_builder.rb +2 -0
  108. data/lib/para/generators/component_helpers.rb +57 -0
  109. data/lib/para/generators.rb +1 -0
  110. data/lib/para/importer/base.rb +23 -0
  111. data/lib/para/importer.rb +10 -0
  112. data/lib/para/inputs/nested_one_input.rb +13 -3
  113. data/lib/para/markup/resources_table.rb +48 -24
  114. data/lib/para/markup/resources_tree.rb +36 -0
  115. data/lib/para/model_field_parsers/store.rb +23 -0
  116. data/lib/para/model_field_parsers.rb +1 -0
  117. data/lib/para/orderable.rb +6 -3
  118. data/lib/para/plugins/routes.rb +25 -0
  119. data/lib/para/plugins.rb +11 -0
  120. data/lib/para/routes.rb +2 -25
  121. data/lib/para/version.rb +1 -1
  122. data/lib/para.rb +4 -2
  123. data/lib/rails/routing_mapper.rb +64 -5
  124. metadata +50 -64
  125. data/app/controllers/para/admin/crud_component_controller.rb +0 -17
  126. data/app/controllers/para/admin/singleton_resource_component_controller.rb +0 -14
  127. data/app/views/para/admin/component_sections/_form.html.haml +0 -10
  128. data/app/views/para/admin/component_sections/edit.html.haml +0 -5
  129. data/app/views/para/admin/component_sections/new.html.haml +0 -5
  130. data/app/views/para/admin/components/_form.html.haml +0 -15
  131. data/app/views/para/admin/components/new.html.haml +0 -4
  132. data/app/views/para/admin/shared/_breadcrumb.html.haml +0 -3
  133. /data/app/views/para/admin/{singleton_resource_component → singleton_resources}/show.html.haml +0 -0
@@ -12,5 +12,5 @@
12
12
  .clearfix
13
13
  %ul.tree
14
14
  %li.placeholder{ class: "#{ 'hidden' unless needs_placeholder?(root) }"}
15
- = render partial: 'para/admin/resources/tree_item', collection: root.children.ordered, as: :root
15
+ = render partial: find_partial_for(model, 'tree_item'), collection: root.children.ordered, as: :root, locals: { model: model }
16
16
 
@@ -1,6 +1,6 @@
1
1
  .page-title
2
2
  %h1
3
- = t('para.form.shared.new.title', model: resource.class.model_name.human)
3
+ = resource_title_for(resource)
4
4
 
5
5
  .page-content-wrap
6
6
  = render find_partial_for(resource, :form)
@@ -0,0 +1,8 @@
1
+ %ul.breadcrumb
2
+ - breadcrumbs.each do |breadcrumb|
3
+ - active = breadcrumb.active?(request)
4
+ %li{ class: ('active' if active) }
5
+ - if active
6
+ = breadcrumb.title
7
+ - else
8
+ = link_to breadcrumb.title, breadcrumb.path
@@ -1,27 +1,29 @@
1
- %ul.navigation-horizontal{ data: { header: true } }
2
- %li.brand-logo
3
- = link_to admin_path do
4
- .hidden-sm.hidden-xs
5
- = t('para.admin.title')
6
- .visible-sm.visible-xs
7
- %i.fa.fa-home
1
+ .navigation-horizontal{ data: { header: true } }
2
+ = render_breadcrumbs
3
+ %ul.list-unstyled.list-inline.ul-navbar
4
+ %li.brand-logo
5
+ = link_to admin_path do
6
+ .hidden-sm.hidden-xs
7
+ = t('para.admin.title')
8
+ .visible-sm.visible-xs
9
+ %i.fa.fa-home
8
10
 
9
- %li
10
- = link_to root_path do
11
- %i.fa.fa-long-arrow-left
12
- %span.text-hidden
13
- = t('para.admin.back_to_app')
11
+ %li.pull-right
12
+ %button.navbar-toggle.collapsed{ type: 'button', data: { toggle: 'collapse', target: '#menu-sidebar' } }
13
+ %span.sr-only
14
+ = t('para.admin.toggle_navigation')
15
+ %span.icon-bar
16
+ %span.icon-bar
17
+ %span.icon-bar
14
18
 
15
- %li.pull-right
16
- %button.navbar-toggle.collapsed{ type: 'button', data: { toggle: 'collapse', target: '#menu-sidebar' } }
17
- %span.sr-only
18
- = t('para.admin.toggle_navigation')
19
- %span.icon-bar
20
- %span.icon-bar
21
- %span.icon-bar
19
+ %li.pull-right
20
+ = link_to destroy_admin_user_session_path, method: :delete do
21
+ %i.fa.fa-power-off
22
+ %span.text-hidden
23
+ = t('para.admin.sign_out')
22
24
 
23
- %li.pull-right
24
- = link_to destroy_admin_user_session_path, method: :delete do
25
- %i.fa.fa-power-off
26
- %span.text-hidden
27
- = t('para.admin.sign_out')
25
+ %li.pull-right
26
+ = link_to root_path, target: "_blank" do
27
+ %i.fa.fa-home
28
+ %span.text-hidden
29
+ = t('para.admin.back_to_app')
@@ -5,15 +5,17 @@
5
5
 
6
6
  - if @component_sections.any?
7
7
  - @component_sections.each do |component_section|
8
+ - next unless component_section.components.any? { |component| can?(:manage, component) }
9
+
8
10
  %li.component-section-item
9
11
  = link_to "#", class: 'component-section-title' do
10
12
  = component_section.name
11
13
 
12
14
  %ul.component-section-list-items
13
15
  - component_section.components.each do |component|
14
- - active = request.fullpath.split('/')[3] == component.slug
15
- %li.component-item{ class: active && 'active' }
16
- = link_to component.name, component.path
16
+ - if can? :manage, component
17
+ %li.component-item{ class: (@component == component) && 'active' }
18
+ = link_to component.name, component.path
17
19
 
18
20
  - else
19
21
  %li.component-section-item
@@ -0,0 +1,13 @@
1
+ .form-tabs
2
+ %nav.navbar.navbar-inverse
3
+ %ul.nav.navbar-nav{ role: 'tablist' }
4
+ - tabs.each_with_index do |tab, index|
5
+ %li{ class: ('active' if index == 0), role: 'presentation' }
6
+ = link_to "##{ tab.dom_id }", role: 'tab', aria: { controls: 'settings' }, data: { toggle: 'tab' } do
7
+ %i.fa{ class: "fa-#{ tab.icon }" }
8
+ = tab.title
9
+
10
+ .tab-content
11
+ - tabs.each_with_index do |tab, index|
12
+ .tab-pane{ id: tab.dom_id, class: ('active' if index == 0), role: 'tabpanel' }
13
+ = tab.content
@@ -1,10 +1,10 @@
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: 'para/inputs/nested_many_container', locals: { form: nested_form, model: model }
4
+ = render partial: find_partial_for(model, :nested_many_container, partial_dir: 'inputs'), locals: { form: nested_form, model: model }
5
5
 
6
6
  -# Add button
7
7
  - if add_button
8
- = link_to_add_association form, attribute_name, partial: 'para/inputs/nested_many_container', form_name: 'form', class: 'btn btn-primary', data: { :'association-insertion-node' => "##{ dom_identifier }", :'association-insertion-method' => 'append' }, render_options: { nested_attribute_name: attribute_name, orderable: orderable, locals: { model: model } } do
8
+ = link_to_add_association form, attribute_name, partial: find_partial_for(model, :nested_many_container, partial_dir: 'inputs'), form_name: 'form', class: 'btn btn-primary', data: { :'association-insertion-node' => "##{ dom_identifier }", :'association-insertion-method' => 'append' }, render_options: { nested_attribute_name: attribute_name, orderable: orderable, locals: { model: model } } do
9
9
  %i.fa.fa-plus
10
10
  = t('para.form.nested.add')
@@ -7,9 +7,7 @@
7
7
  = form.nested_resource_name
8
8
  %span.caret
9
9
 
10
- %ul.panel-controls
11
- %li
12
- = form.remove_association_button
10
+ = form.remove_association_button
13
11
 
14
12
  .clearfix
15
13
 
@@ -50,6 +50,16 @@ en:
50
50
  no_results: "No results found, please try with other criterions"
51
51
  empty: "The list is empty"
52
52
 
53
+ export:
54
+ name: "Export %{name}"
55
+ as: "Exporter (.%{extension})"
56
+
57
+ import:
58
+ name: Import
59
+ select: "Select file"
60
+ change: "Change file"
61
+ placeholder: File format ( .csv .xlsx )
62
+
53
63
  shared:
54
64
  save: "Save"
55
65
  cancel: "Cancel"
@@ -14,11 +14,14 @@ fr:
14
14
  clone:
15
15
  success: "%{model} cloné(e)"
16
16
  error: "Impossible de cloner le(a) %{model}"
17
+ import:
18
+ success: "Import réussi"
19
+ error: "Merci de sélectionner un fichier à importer"
17
20
 
18
21
  admin:
19
22
  title: "Administration"
20
23
  toggle_navigation: "Open navigation"
21
- back_to_app: "Retour à l'application"
24
+ back_to_app: "Afficher le site"
22
25
  sign_out: "Se déconnecter"
23
26
 
24
27
  confirmation:
@@ -26,24 +29,17 @@ fr:
26
29
  destroy: 'Etes-vous sure de vouloir supprimer %{model} ?'
27
30
 
28
31
  component:
29
- create: "Créer un(e) Composant"
30
- add: "Ajouter un composant"
31
- none_created: "Aucune page pour le moment ..."
32
- crud:
33
- name: "Listing de ressources"
34
- singleton_resource:
35
- name: "Formulaire de ressource"
32
+ none_created: "Aucun composant pour le moment ..."
36
33
 
37
- component_section:
38
- add: "Ajouter une section"
39
- edit: 'Modifier la section'
40
- destroy: 'Supprimer la section'
41
- actions: "Actions"
34
+ dashboard:
35
+ title: "Tableau de bord"
42
36
 
43
37
  form:
44
38
  shared:
45
39
  new:
46
40
  title: "Créer un(e) %{model}"
41
+ edit:
42
+ title: "Modification d'un(e) %{model}"
47
43
  nested:
48
44
  name: "Nom"
49
45
  add: "Ajouter"
@@ -53,13 +49,19 @@ fr:
53
49
  list:
54
50
  search_title: "Recherche"
55
51
  delete_confirmation: "Êtes vous sûr de bien vouloir supprimer cette entrée ?"
56
- no_results: "Aucun résultat pour cette recherche, merci d'essayer avec d'autres critères"
57
- empty: "Aucune entrée créée pour le moment"
52
+ no_results: "Aucun résultat pour cette recherche, merci d'essayer avec d'autres critères ou de créer une nouvelle entrée avec le bouton suivant :"
53
+ empty: "Aucune entrée créée pour le moment. Créez une nouvelle entrée avec le bouton suivant :"
58
54
 
59
55
  export:
60
56
  name: "Export %{name}"
61
57
  as: "Exporter (.%{extension})"
62
58
 
59
+ import:
60
+ name: Importer
61
+ select: "Sélectionnez un fichier"
62
+ change: "Changer"
63
+ placeholder: Fichier au format ( .csv .xlsx )
64
+
63
65
  shared:
64
66
  save: "Enregistrer"
65
67
  cancel: "Annuler"
@@ -67,12 +69,17 @@ fr:
67
69
  search: "Rechercher"
68
70
  save_and_edit: "Enregistrer et éditer"
69
71
  save_and_add_another_button: "Enregistrer et créer un(e) autre"
72
+ destroy: "Supprimer"
70
73
 
71
74
  types:
72
75
  boolean:
73
76
  "true": "Oui"
74
77
  "false": "Non"
75
78
 
79
+ admin:
80
+ breadcrumbs:
81
+ home: "Tableau de bord"
82
+
76
83
  activerecord:
77
84
  errors:
78
85
  relation_length_is_smaller: "doit contenir au moins %{minimum} éléments"
@@ -99,3 +106,11 @@ fr:
99
106
  settings_rails/form:
100
107
  one: "Configuration"
101
108
  other: "Configuration"
109
+
110
+ date:
111
+ formats:
112
+ admin: '%d/%m/%Y'
113
+
114
+ time:
115
+ formats:
116
+ admin: '%d/%m/%Y %H:%M'
@@ -0,0 +1,38 @@
1
+ class AddJsonEqualityOperatorPatchToPostgres < ActiveRecord::Migration
2
+ def up
3
+ ActiveRecord::Base.connection.execute <<-SQL
4
+ -- This creates a function named hashjson that transforms the
5
+ -- json to texts and generates a hash
6
+ CREATE OR REPLACE FUNCTION hashjson(
7
+ json
8
+ ) RETURNS INTEGER LANGUAGE SQL STRICT IMMUTABLE AS $$
9
+ SELECT hashtext($1::text);
10
+ $$;
11
+
12
+ -- This creates a function named json_eq that checks equality (as text)
13
+ CREATE OR REPLACE FUNCTION json_eq(
14
+ json,
15
+ json
16
+ ) RETURNS BOOLEAN LANGUAGE SQL STRICT IMMUTABLE AS $$
17
+ SELECT bttextcmp($1::text, $2::text) = 0;
18
+ $$;
19
+
20
+ -- This creates an operator from the equality function
21
+ CREATE OPERATOR = (
22
+ LEFTARG = json,
23
+ RIGHTARG = json,
24
+ PROCEDURE = json_eq
25
+ );
26
+
27
+ -- Finaly, this defines a new default JSON operator family with the
28
+ -- operators and functions we just defined.
29
+ CREATE OPERATOR CLASS json_ops
30
+ DEFAULT FOR TYPE json USING hash AS
31
+ OPERATOR 1 =,
32
+ FUNCTION 1 hashjson(json);
33
+ SQL
34
+ end
35
+
36
+ def down
37
+ end
38
+ end
@@ -1,5 +1,7 @@
1
1
  module Para
2
2
  class ComponentGenerator < Rails::Generators::NamedBase
3
+ include Para::Generators::ComponentHelpers
4
+
3
5
  source_root File.expand_path('../templates', __FILE__)
4
6
 
5
7
  desc 'Para component generator'
@@ -12,48 +14,26 @@ module Para
12
14
  template 'component.rb', "app/components/#{ component_file_name }.rb"
13
15
  end
14
16
 
17
+ def copy_component_decorator
18
+ template 'decorator.rb', "app/decorators/#{ decorator_file_name }.rb"
19
+ end
20
+
15
21
  def copy_component_controller
16
22
  template 'component_controller.rb', "app/controllers/admin/#{ component_file_name }_controller.rb"
17
23
  end
18
24
 
19
- def add_require_to_application_controller
20
- prepend_to_file 'app/controllers/application_controller.rb' do
21
- "require '#{ component_file_name }'\n"
22
- end
23
- end
24
-
25
25
  def create_show_component_view
26
26
  template 'show.html.haml', "app/views/admin/#{ component_file_name }/show.html.haml"
27
27
  end
28
28
 
29
29
  def add_route
30
- route_file = File.read(Rails.root.join('config/routes.rb'))
31
-
32
- unless route_file.match /^\s+namespace :admin do/
33
- route "namespace :admin do\n end\n"
34
- end
35
-
36
- inject_into_file 'config/routes.rb', after: ' namespace :admin do' do
37
- "\n component :#{ file_name } do\n end"
38
- end
30
+ add_component_to_routes :component, file_name
39
31
  end
40
32
 
41
33
  private
42
34
 
43
- def component_name
44
- if class_name.match(/Component/i)
45
- class_name
46
- else
47
- "#{ class_name }Component"
48
- end
49
- end
50
-
51
- def component_file_name
52
- if file_name.match(/component/i)
53
- file_name
54
- else
55
- "#{ file_name }_component"
56
- end
35
+ def component_parent_name
36
+ 'Para::Component::Base'
57
37
  end
58
38
  end
59
39
  end
@@ -0,0 +1,41 @@
1
+ module Para
2
+ module Component
3
+ class CrudGenerator < Rails::Generators::NamedBase
4
+ include Para::Generators::ComponentHelpers
5
+
6
+ source_root File.expand_path('../../templates', __FILE__)
7
+
8
+ desc 'Para CRUD component generator'
9
+
10
+ def welcome
11
+ say 'Creating CRUD component...'
12
+ end
13
+
14
+ def copy_crud_component
15
+ template 'component.rb', "app/components/#{ component_file_name }.rb"
16
+ end
17
+
18
+ def copy_crud_component_decorator
19
+ template 'decorator.rb', "app/decorators/#{ decorator_file_name }.rb"
20
+ end
21
+
22
+ def copy_crud_resources_controller
23
+ template 'resources_controller.rb', "app/controllers/admin/#{ resources_controller_name }.rb"
24
+ end
25
+
26
+ def add_route
27
+ add_component_to_routes :crud_component, file_name
28
+ end
29
+
30
+ private
31
+
32
+ def component_parent_name
33
+ 'Para::Component::Crud'
34
+ end
35
+
36
+ def controller_parent_name
37
+ 'Para::Admin::CrudResourcesController'
38
+ end
39
+ end
40
+ end
41
+ end
@@ -1,3 +1,3 @@
1
- class <%= component_name %> < Para::Component::Base
1
+ class <%= component_name %> < <%= component_parent_name %>
2
2
  register :<%= file_name %>, self
3
3
  end
@@ -0,0 +1,3 @@
1
+ module <%= decorator_name %>
2
+ include <%= decorator_parent_name %>
3
+ end
@@ -0,0 +1,4 @@
1
+ module Admin
2
+ class <%= controller_name %> < <%= controller_parent_name %>
3
+ end
4
+ end
@@ -1,5 +1,7 @@
1
1
  module <%= format_module_name_for(@format) %>
2
2
  class <%= model_exporter_name %> < Para::Exporter::Base
3
+ exports '<%= class_name %>'
4
+
3
5
  def extension
4
6
  '<%= @format %>'
5
7
  end
@@ -1,5 +1,7 @@
1
1
  module <%= format_module_name_for(@format) %>
2
2
  class <%= model_exporter_name %> < Para::Exporter::Csv
3
+ exports '<%= class_name %>'
4
+
3
5
  def name
4
6
  'export'
5
7
  end
@@ -0,0 +1,16 @@
1
+ module Para
2
+ class FiltersGenerator < Para::Generators::NamedBase
3
+ include Para::SearchHelper
4
+ include Para::Admin::BaseHelper
5
+ include Para::Generators::FieldHelpers
6
+
7
+ source_root File.expand_path("../templates", __FILE__)
8
+
9
+ def generate_form
10
+ template(
11
+ "_filters.html.haml",
12
+ "app/views/admin/#{ plural_namespaced_path }/_filters.html.haml"
13
+ )
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,9 @@
1
+ = search_form_for @q, builder: SimpleForm::FormBuilder, url: @component.path do |form|
2
+ .input-group
3
+ %span.input-group-addon
4
+ %i.fa.fa-search
5
+
6
+ = form.input_field :<%= fulltext_search_param_for(attributes) %>, as: :string, placeholder: t('para.shared.search'), class: 'form-control'
7
+
8
+ %span.input-group-btn
9
+ = form.submit t('para.shared.search'), class: 'btn btn-default'
@@ -0,0 +1,20 @@
1
+ module Para
2
+ class ImporterGenerator < Rails::Generators::NamedBase
3
+ source_root File.expand_path('../templates', __FILE__)
4
+
5
+ desc 'Para importer generator'
6
+
7
+ def copy_resource_importer
8
+ template(
9
+ "base_importer.rb",
10
+ "app/importers/#{ plural_file_name }_importer.rb"
11
+ )
12
+ end
13
+
14
+ private
15
+
16
+ def model_importer_name
17
+ [class_name.to_s.pluralize, 'Importer'].join
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,5 @@
1
+ class <%= model_importer_name %> < Para::Importer::Base
2
+ def import_from_row(row)
3
+ # Add your import logic here
4
+ end
5
+ end
@@ -25,15 +25,14 @@ module Para
25
25
 
26
26
  [
27
27
  ['devise', '~> 3.0'],
28
+ # Allows for installing default wrappers and bootstrap adapters
29
+ # This should be avoided when add an initializer namespaced to the
30
+ # para environment
28
31
  ['simple_form'],
29
32
  ['simple_form_extension'],
30
33
  # Pull requests are pending, and I don't want to release the gem
31
34
  # under another name to be able to depend on it
32
35
  ['active_decorator', github: 'glyph-fr/active_decorator', branch: 'dev'],
33
- ['paperclip', '~> 4.2'],
34
- ['cancancan', '~> 1.9'],
35
- ['friendly_id', '~> 5.0'],
36
- ['rolify', '~> 3.4'],
37
36
  ['kaminari', '>= 0.16.1'],
38
37
  ['ransack', '>= 1.4.1'],
39
38
  ['bootstrap-kaminari-views', '>= 0.0.5']
@@ -50,38 +49,20 @@ module Para
50
49
  end
51
50
  end
52
51
 
53
- def friendly_id_install
54
- generate 'friendly_id'
55
- end
56
-
57
- def simple_form_install
58
- generate 'simple_form:install', '--bootstrap'
59
- generate 'simple_form_extension:install'
60
- end
61
-
62
- def cancan_install
63
- generate 'cancan:ability'
64
- end
65
-
66
52
  def devise_install
67
53
  generate 'devise:install'
68
54
  generate 'devise', 'AdminUser'
69
55
  end
70
56
 
71
- def rolify_install
72
- generate 'rolify Role AdminUser'
57
+ def simple_form_install
58
+ generate 'simple_form:install', '--bootstrap'
59
+ generate 'simple_form_extension:install'
73
60
  end
74
61
 
75
62
  def migrate
76
63
  rake 'db:migrate'
77
64
  end
78
65
 
79
- def add_admin_user_to_ability
80
- inject_into_file 'app/models/ability.rb', after: '# Define abilities for the passed in user here. For example:' do
81
- "\n\n if user.is_a?(AdminUser)\n can :manage, :all\n end\n"
82
- end
83
- end
84
-
85
66
  def create_default_admin
86
67
  generate 'para:admin_user'
87
68
  end
@@ -5,11 +5,20 @@ module Para
5
5
 
6
6
  source_root File.expand_path("../templates", __FILE__)
7
7
 
8
+ class_option :container, type: :boolean, default: false, :aliases => "-c"
9
+
8
10
  def generate_fields
9
11
  template(
10
12
  "_nested_fields.html.haml",
11
13
  "app/views/admin/#{ plural_namespaced_path }/_fields.html.haml"
12
14
  )
13
15
  end
16
+
17
+ def generate_fields_container
18
+ template(
19
+ "../../../../../app/views/para/inputs/_nested_many_container.html.haml",
20
+ "app/views/admin/#{ plural_namespaced_path }/_nested_many_container.html.haml"
21
+ ) if options[:container]
22
+ end
14
23
  end
15
24
  end
@@ -2,6 +2,7 @@ module Para
2
2
  module AttributeField
3
3
  class Base
4
4
  class_attribute :_field_options
5
+ cattr_accessor :_field_types
5
6
 
6
7
  attr_reader :model, :name, :type, :field_type, :field_method
7
8
 
@@ -15,6 +16,29 @@ module Para
15
16
  }]
16
17
  end
17
18
 
19
+ # Registers the class as the responder for a given field type
20
+ #
21
+ # Example :
22
+ #
23
+ # # This will allow looking :my_field or :myfield up and instantiate
24
+ # # self as the field
25
+ # class MyField < Para::AttributeField::Base
26
+ # register :my_field, :myfield, self
27
+ # end
28
+ #
29
+ #
30
+ def self.register(*args)
31
+ attribute_class = args.pop
32
+
33
+ args.each do |arg|
34
+ Base.field_types[arg] = attribute_class
35
+ end
36
+ end
37
+
38
+ def self.field_types
39
+ @_field_types ||= {}
40
+ end
41
+
18
42
  field_option :as, :field_type_name
19
43
 
20
44
  def initialize(model, options = {})
@@ -67,6 +91,10 @@ module Para
67
91
  [name]
68
92
  end
69
93
 
94
+ def type?(type)
95
+ self.type.to_s == type.to_s
96
+ end
97
+
70
98
  private
71
99
 
72
100
  def field_type_name
@@ -1,6 +1,8 @@
1
1
  module Para
2
2
  module AttributeField
3
3
  class BelongsToField < RelationField
4
+ register :belongs_to, self
5
+
4
6
  field_option :collection, :relation_options
5
7
 
6
8
  def field_name
@@ -1,6 +1,8 @@
1
1
  module Para
2
2
  module AttributeField
3
3
  class BooleanField < AttributeField::Base
4
+ register :boolean, :bool, self
5
+
4
6
  field_option :wrapper, :wrapper_name
5
7
 
6
8
  def value_for(instance)
@@ -1,6 +1,8 @@
1
1
  module Para
2
2
  module AttributeField
3
3
  class DatetimeField < AttributeField::Base
4
+ register :datetime, :date, self
5
+
4
6
  def value_for(instance)
5
7
  (value = instance.send(name)) && I18n.l(value)
6
8
  end