avo 3.0.0.pre18 → 3.0.0.pre19

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of avo might be problematic. Click here for more details.

Files changed (118) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +2 -2
  3. data/Gemfile.lock +23 -25
  4. data/Rakefile +2 -0
  5. data/{public/avo-assets/avo.css → app/assets/builds/avo.base.css} +587 -3848
  6. data/app/assets/builds/avo.base.js +124556 -0
  7. data/app/assets/builds/avo.base.js.map +7 -0
  8. data/app/assets/builds/avo.custom.js +6 -0
  9. data/app/assets/builds/avo.custom.js.map +7 -0
  10. data/app/assets/stylesheets/avo.base.css +1 -0
  11. data/app/assets/stylesheets/css/fields/tags.css +32 -0
  12. data/app/components/avo/actions_component.rb +1 -1
  13. data/app/components/avo/field_wrapper_component.html.erb +1 -1
  14. data/app/components/avo/field_wrapper_component.rb +1 -7
  15. data/app/components/avo/fields/boolean_field/index_component.html.erb +1 -1
  16. data/app/components/avo/fields/common/badge_viewer_component.html.erb +1 -24
  17. data/app/components/avo/fields/common/badge_viewer_component.rb +24 -0
  18. data/app/components/avo/fields/common/boolean_check_component.html.erb +1 -12
  19. data/app/components/avo/fields/common/boolean_check_component.rb +2 -1
  20. data/app/components/avo/fields/common/gravatar_viewer_component.html.erb +1 -1
  21. data/app/components/avo/fields/common/gravatar_viewer_component.rb +2 -2
  22. data/app/components/avo/fields/common/heading_component.html.erb +3 -8
  23. data/app/components/avo/fields/common/heading_component.rb +1 -3
  24. data/app/components/avo/fields/common/key_value_component.html.erb +2 -2
  25. data/app/components/avo/fields/common/key_value_component.rb +2 -2
  26. data/app/components/avo/fields/common/progress_bar_component.rb +3 -9
  27. data/app/components/avo/fields/common/status_viewer_component.html.erb +3 -0
  28. data/app/components/avo/fields/edit_component.rb +1 -1
  29. data/app/components/avo/fields/external_image_field/index_component.html.erb +1 -1
  30. data/app/components/avo/fields/file_field/index_component.html.erb +2 -2
  31. data/app/components/avo/fields/gravatar_field/index_component.html.erb +1 -1
  32. data/app/components/avo/fields/heading_field/edit_component.html.erb +1 -1
  33. data/app/components/avo/fields/heading_field/show_component.html.erb +1 -1
  34. data/app/components/avo/fields/id_field/index_component.html.erb +1 -1
  35. data/app/components/avo/fields/index_component.rb +1 -1
  36. data/app/components/avo/fields/show_component.rb +1 -1
  37. data/app/components/avo/fields/text_field/index_component.html.erb +1 -1
  38. data/app/components/avo/index/field_wrapper_component.rb +1 -1
  39. data/app/components/avo/index/resource_controls_component.rb +1 -1
  40. data/app/components/avo/index/resource_table_component.rb +3 -9
  41. data/app/components/avo/resource_component.rb +9 -4
  42. data/app/components/avo/sidebar_profile_component.html.erb +4 -4
  43. data/app/components/avo/tab_group_component.html.erb +1 -1
  44. data/app/components/avo/tab_switcher_component.rb +2 -2
  45. data/app/components/avo/views/resource_edit_component.html.erb +9 -20
  46. data/app/components/avo/views/resource_edit_component.rb +5 -5
  47. data/app/components/avo/views/resource_index_component.rb +1 -1
  48. data/app/components/avo/views/resource_show_component.html.erb +1 -1
  49. data/app/components/avo/views/resource_show_component.rb +1 -1
  50. data/app/controllers/avo/actions_controller.rb +9 -20
  51. data/app/controllers/avo/application_controller.rb +5 -5
  52. data/app/controllers/avo/base_controller.rb +39 -1
  53. data/app/controllers/avo/search_controller.rb +19 -2
  54. data/app/controllers/concerns/avo/initializes_avo.rb +1 -0
  55. data/app/helpers/avo/resources_helper.rb +1 -1
  56. data/app/helpers/avo/url_helpers.rb +1 -1
  57. data/app/views/avo/base/edit.html.erb +1 -1
  58. data/app/views/avo/base/index.html.erb +1 -1
  59. data/app/views/avo/base/new.html.erb +1 -1
  60. data/app/views/avo/base/show.html.erb +1 -1
  61. data/app/views/layouts/avo/application.html.erb +10 -2
  62. data/bin/dev +2 -0
  63. data/config/routes.rb +4 -3
  64. data/db/factories.rb +1 -1
  65. data/lib/avo/base_action.rb +21 -26
  66. data/lib/avo/base_resource.rb +13 -7
  67. data/lib/avo/concerns/filters_session_handler.rb +3 -3
  68. data/lib/avo/concerns/has_helpers.rb +18 -0
  69. data/lib/avo/concerns/has_items.rb +1 -5
  70. data/lib/avo/concerns/visible_in_different_views.rb +7 -1
  71. data/lib/avo/concerns/visible_items.rb +43 -0
  72. data/lib/avo/configuration.rb +28 -4
  73. data/lib/avo/current.rb +1 -6
  74. data/lib/avo/dsl/field_parser.rb +1 -1
  75. data/lib/avo/execution_context.rb +4 -1
  76. data/lib/avo/fields/badge_field.rb +1 -1
  77. data/lib/avo/fields/base_field.rb +21 -44
  78. data/lib/avo/fields/belongs_to_field.rb +1 -1
  79. data/lib/avo/fields/concerns/has_html_attributes.rb +2 -0
  80. data/lib/avo/fields/concerns/use_view_components.rb +45 -0
  81. data/lib/avo/fields/external_image_field.rb +2 -2
  82. data/lib/avo/fields/file_field.rb +2 -2
  83. data/lib/avo/fields/gravatar_field.rb +2 -2
  84. data/lib/avo/fields/has_base_field.rb +2 -2
  85. data/lib/avo/fields/heading_field.rb +5 -13
  86. data/lib/avo/fields/id_field.rb +2 -2
  87. data/lib/avo/fields/status_field.rb +3 -1
  88. data/lib/avo/fields/text_field.rb +2 -2
  89. data/lib/avo/filters/base_filter.rb +1 -1
  90. data/lib/avo/html/builder.rb +1 -1
  91. data/lib/avo/licensing/license_manager.rb +1 -1
  92. data/lib/avo/resources/items/holder.rb +0 -6
  93. data/lib/avo/resources/items/item_group.rb +2 -2
  94. data/lib/avo/resources/items/row.rb +3 -3
  95. data/lib/avo/resources/items/sidebar.rb +1 -1
  96. data/lib/avo/resources/items/tab.rb +2 -2
  97. data/lib/avo/resources/items/tab_group.rb +1 -1
  98. data/lib/avo/resources/resource_manager.rb +6 -1
  99. data/lib/avo/version.rb +1 -1
  100. data/lib/avo/view_inquirer.rb +36 -0
  101. data/lib/avo.rb +9 -0
  102. data/lib/generators/avo/concerns/parent_controller.rb +20 -0
  103. data/lib/generators/avo/controller_generator.rb +3 -0
  104. data/lib/generators/avo/eject_generator.rb +180 -15
  105. data/lib/generators/avo/field_generator.rb +49 -2
  106. data/lib/generators/avo/js/install_generator.rb +2 -2
  107. data/lib/generators/avo/resource_generator.rb +10 -7
  108. data/lib/generators/avo/tailwindcss/install_generator.rb +58 -12
  109. data/lib/generators/avo/templates/initializer/avo.tt +6 -1
  110. data/lib/generators/avo/templates/resource/controller.tt +1 -1
  111. data/lib/generators/avo/templates/tailwindcss/avo.tailwind.css +5 -3
  112. data/lib/generators/avo/templates/tailwindcss/tailwind.config.js +11 -0
  113. data/lib/tasks/avo_tasks.rake +33 -5
  114. data/public/avo-assets/avo.base.css +75 -4146
  115. metadata +14 -6
  116. data/config/master.key +0 -1
  117. data/public/avo-assets/avo.js +0 -513
  118. data/public/avo-assets/avo.js.map +0 -7
@@ -3,7 +3,30 @@ require_relative "base_generator"
3
3
  module Generators
4
4
  module Avo
5
5
  class EjectGenerator < BaseGenerator
6
- argument :filename, type: :string, required: true
6
+ class_option :partial,
7
+ desc: "The partial to eject. Example: ':logo', 'app/views/layouts/avo/application.html.erb'",
8
+ type: :string,
9
+ required: false
10
+
11
+ class_option :component,
12
+ desc: "The component to eject. Example: 'Avo::Index::TableRowComponent', 'avo/index/table_row_component'",
13
+ type: :string,
14
+ required: false
15
+
16
+ class_option :scope,
17
+ desc: "The scope of the component. Example: 'users', 'admins'",
18
+ type: :string,
19
+ required: false
20
+
21
+ class_option "field-components",
22
+ desc: "The field components to eject. Example: 'trix', 'text'",
23
+ type: :string,
24
+ required: false
25
+
26
+ class_option :view,
27
+ desc: "The view of the component to eject when using --field-component option. Example: 'index', 'show'",
28
+ type: :string,
29
+ required: false
7
30
 
8
31
  source_root ::Avo::Engine.root
9
32
 
@@ -21,19 +44,23 @@ module Generators
21
44
  }
22
45
 
23
46
  def handle
24
- if @filename.starts_with?(":")
25
- template_id = path_to_sym @filename
26
- template_path = TEMPLATES[template_id]
27
-
28
- if path_exists? template_path
29
- eject template_path
30
- else
31
- say("Failed to find the `#{template_id.to_sym}` template.", :yellow)
32
- end
33
- elsif path_exists? @filename
34
- eject @filename
47
+ if options[:partial].present?
48
+ eject_partial
49
+ elsif options[:component].present?
50
+ eject_component
51
+ elsif options["field-components"].present?
52
+ eject_field_components
35
53
  else
36
- say("Failed to find the `#{@filename}` template.", :yellow)
54
+ say "Please specify a partial or a component to eject.\n" \
55
+ "Examples: rails g avo:eject --partial :logo\n" \
56
+ " rails g avo:eject --partial app/views/layouts/avo/application.html.erb\n" \
57
+ " rails g avo:eject --component Avo::Index::TableRowComponent\n" \
58
+ " rails g avo:eject --component avo/index/table_row_component\n" \
59
+ " rails g avo:eject --field-components trix\n" \
60
+ " rails g avo:eject --field-components trix --scope users\n" \
61
+ " rails g avo:eject --field-components text --scope users --view edit\n" \
62
+ " rails g avo:eject --component Avo::Views::ResourceIndexComponent --scope users\n" \
63
+ " rails g avo:eject --component avo/views/resource_index_component --scope users", :yellow
37
64
  end
38
65
  end
39
66
 
@@ -48,8 +75,146 @@ module Generators
48
75
  path.present? && File.file?(::Avo::Engine.root.join(path))
49
76
  end
50
77
 
51
- def eject(path)
52
- copy_file ::Avo::Engine.root.join(path), ::Rails.root.join(path)
78
+ def dir_exists?(path)
79
+ path.present? && Dir.exist?(::Avo::Engine.root.join(path))
80
+ end
81
+
82
+ def eject(path, dest_path = nil, is_directory: false)
83
+ method = is_directory ? :directory : :copy_file
84
+
85
+ send method, ::Avo::Engine.root.join(path), ::Rails.root.join(dest_path || path)
86
+ end
87
+
88
+ def eject_partial
89
+ if options[:partial].starts_with?(":")
90
+ template_id = path_to_sym options[:partial]
91
+ template_path = TEMPLATES[template_id]
92
+
93
+ if path_exists? template_path
94
+ return unless confirm_ejection_on template_path
95
+ eject template_path
96
+ else
97
+ say("Failed to find the `#{template_id.to_sym}` template.", :yellow)
98
+ end
99
+ elsif path_exists? options[:partial]
100
+ return unless confirm_ejection_on template_path
101
+ eject options[:partial]
102
+ else
103
+ say("Failed to find the `#{options[:partial]}` template.", :yellow)
104
+ end
105
+ end
106
+
107
+ def eject_component(component_to_eject = options[:component], confirmation: true)
108
+ # Underscore the component name
109
+ # Example: Avo::Views::ResourceIndexComponent => avo/views/resource_index_component
110
+ component = component_to_eject.underscore
111
+
112
+ # Get the component path for both, the rb and erb files
113
+ rb, erb = ["app/components/#{component}.rb", "app/components/#{component}.html.erb"]
114
+
115
+ # Return if one of the components doesn't exist
116
+ if !path_exists?(rb) || !path_exists?(erb)
117
+ return say("Failed to find the `#{component_to_eject}` component.", :yellow)
118
+ end
119
+
120
+ # Add the scope to the component if it's possible
121
+ if add_scope? component
122
+ component = if component.starts_with?("avo/views/")
123
+ component.gsub("avo/views/", "avo/views/#{options[:scope].underscore}/")
124
+ elsif component.starts_with?("avo/fields/")
125
+ component.gsub("avo/fields/", "avo/fields/#{options[:scope].underscore}/")
126
+ end
127
+ added_scope = true
128
+ end
129
+
130
+ # Confirm the ejection
131
+ if confirmation
132
+ return if !confirm_ejection_on(component.camelize)
133
+ end
134
+
135
+ # Get the destination path for both, the rb and erb files
136
+ dest_rb = "#{::Avo.configuration.view_component_path}/#{component}.rb"
137
+ dest_erb = "#{::Avo.configuration.view_component_path}/#{component}.html.erb"
138
+
139
+ # Eject the component
140
+ eject rb, dest_rb
141
+ eject erb, dest_erb
142
+
143
+ # Remame the component class if scope was added
144
+ # Example: Avo::Views::ResourceIndexComponent => Avo::Views::Admins::ResourceIndexComponent
145
+ if added_scope
146
+ [dest_rb, dest_erb].each do |path|
147
+ if component.starts_with?("avo/views/")
148
+ modified_content = File.read(path).gsub("Avo::Views::", "Avo::Views::#{options[:scope].camelize}::")
149
+ elsif component.starts_with?("avo/fields/")
150
+ modified_content = File.read(path).gsub("#{options["field-components"].camelize}Field", "#{options[:scope].camelize}::#{options["field-components"].camelize}Field")
151
+ end
152
+
153
+ File.open(path, "w") do |file|
154
+ file.puts modified_content
155
+ end
156
+ end
157
+
158
+ if component.starts_with?("avo/views/")
159
+ say "You can now use this component on any resource by configuring the 'self.components' option.\n" \
160
+ " self.components = {\n" \
161
+ " #{component.split("/").last}: #{component.camelize}\n" \
162
+ " }", :green
163
+ elsif component.starts_with?("avo/fields/")
164
+ say "You can now use this component on any field by configuring the 'components' option.\n" \
165
+ " field :name, as: :#{options["field-components"]}, components: {\n" \
166
+ " #{component.split("/").last}: #{component.camelize}\n" \
167
+ " }", :green
168
+ end
169
+ end
170
+ end
171
+
172
+ def eject_field_components
173
+ # Check if the field exists
174
+ field_path = "lib/avo/fields/#{options["field-components"]}_field.rb"
175
+ return say("Failed to find the `#{options["field-components"]}` field.", :yellow) if !path_exists?(field_path)
176
+
177
+ # Eject single component if view is specified
178
+ if options[:view].present?
179
+ return eject_component "Avo::Fields::#{options["field-components"].camelize}Field::#{options[:view].camelize}Component"
180
+ end
181
+
182
+ # Check if the field components directory exist
183
+ components_path = "app/components/avo/fields/#{options["field-components"]}_field"
184
+ return say("Failed to find the `#{options["field-components"]}` field components.", :yellow) if !dir_exists?(components_path)
185
+
186
+ # Build the destination path for the components directory add the scope
187
+ destination_components_path = "#{::Avo.configuration.view_component_path}/#{components_path.gsub("app/components/", "")}"
188
+
189
+ if options[:scope].present?
190
+ destination_components_path = destination_components_path.gsub("avo/fields/", "avo/fields/#{options[:scope].underscore}/")
191
+ end
192
+
193
+ # Confirm the ejection
194
+ confirm_ejection_on destination_components_path, is_directory: true
195
+
196
+ # Eject the components directory
197
+ eject components_path, destination_components_path, is_directory: true
198
+
199
+ # Rename the component classes if scope was added
200
+ if options[:scope].present?
201
+ Dir.glob("#{destination_components_path}/*").each do |file|
202
+ modified_content = File.read(file).gsub("#{options["field-components"].camelize}Field", "#{options[:scope].camelize}::#{options["field-components"].camelize}Field")
203
+
204
+ File.open(file, "w") do |open_file|
205
+ open_file.puts modified_content
206
+ end
207
+ end
208
+ end
209
+ end
210
+
211
+ def confirm_ejection_on(path, is_directory: false)
212
+ say("By ejecting the '#{path}'#{" directory" if is_directory} \033[1myou'll take on the responsibility for maintain it.", :yellow)
213
+ yes?("Are you sure you want to eject the '#{path}'#{" directory" if is_directory}? [y/N]", :yellow)
214
+ end
215
+
216
+ def add_scope?(component)
217
+ (component.starts_with?("avo/views/") || component.starts_with?("avo/fields/")) && options[:scope].present?
53
218
  end
54
219
  end
55
220
  end
@@ -8,9 +8,56 @@ module Generators
8
8
  namespace "avo:field"
9
9
  desc "Add a custom Avo field to your project."
10
10
 
11
+ class_option "field-template", type: :string, required: false
12
+
11
13
  def handle
12
- directory "field/components", "#{::Avo.configuration.view_component_path}/avo/fields/#{singular_name}_field"
13
- template "field/%singular_name%_field.rb.tt", "app/avo/fields/#{singular_name}_field.rb"
14
+ return field_from_template if field_template.present?
15
+
16
+ directory "field/components", destination_components_path
17
+ template "field/%singular_name%_field.rb.tt", destination_field_path
18
+ end
19
+
20
+ no_tasks do
21
+ def field_from_template
22
+ if !File.file? ::Avo::Engine.root.join(template_field_path)
23
+ return say("Failed to find the `#{field_template}` template field.", :yellow)
24
+ end
25
+
26
+ if !Dir.exist? ::Avo::Engine.root.join(template_components_path)
27
+ return say("Failed to find the `#{field_template}` template field components.", :yellow)
28
+ end
29
+
30
+ directory ::Avo::Engine.root.join(template_components_path), destination_components_path
31
+ copy_file ::Avo::Engine.root.join(template_field_path), destination_field_path
32
+
33
+ Dir.glob("#{destination_components_path}/*").push(destination_field_path).each do |file|
34
+ modified_content = File.read(file).gsub("#{field_template.camelize}Field", "#{singular_name.camelize}Field")
35
+
36
+ File.open(file, "w") do |open_file|
37
+ open_file.puts modified_content
38
+ end
39
+ end
40
+ end
41
+
42
+ def field_template
43
+ options["field-template"]
44
+ end
45
+
46
+ def template_field_path
47
+ "lib/avo/fields/#{field_template}_field.rb"
48
+ end
49
+
50
+ def template_components_path
51
+ "app/components/avo/fields/#{field_template}_field"
52
+ end
53
+
54
+ def destination_components_path
55
+ "#{::Avo.configuration.view_component_path}/avo/fields/#{singular_name}_field"
56
+ end
57
+
58
+ def destination_field_path
59
+ "app/avo/fields/#{singular_name}_field.rb"
60
+ end
14
61
  end
15
62
  end
16
63
  end
@@ -31,7 +31,7 @@ module Generators
31
31
  end
32
32
 
33
33
  say "Ejecting the _head.html.erb partial"
34
- Rails::Generators.invoke("avo:eject", [":head", "--skip-avo-version"], {destination_root: Rails.root})
34
+ Rails::Generators.invoke("avo:eject", ["--partial", ":head", "--skip-avo-version"], {destination_root: Rails.root})
35
35
 
36
36
  say "Adding the JS asset to the partial"
37
37
  append_to_file Rails.root.join("app", "views", "avo", "partials", "_head.html.erb"), "<%= javascript_importmap_tags \"avo.custom\" %>"
@@ -48,7 +48,7 @@ module Generators
48
48
  end
49
49
 
50
50
  say "Ejecting the _head.html.erb partial"
51
- Rails::Generators.invoke("avo:eject", [":head", "--skip-avo-version"], {destination_root: Rails.root})
51
+ Rails::Generators.invoke("avo:eject", ["--partial", ":head", "--skip-avo-version"], {destination_root: Rails.root})
52
52
 
53
53
  say "Adding the JS asset to the partial"
54
54
  append_to_file Rails.root.join("app", "views", "avo", "partials", "_head.html.erb"), "<%= javascript_include_tag \"avo.custom\", \"data-turbo-track\": \"reload\", defer: true %>"
@@ -1,16 +1,19 @@
1
1
  require_relative "named_base_generator"
2
+ require_relative "concerns/parent_controller"
2
3
 
3
4
  module Generators
4
5
  module Avo
5
6
  class ResourceGenerator < NamedBaseGenerator
7
+ include Generators::Avo::Concerns::ParentController
8
+
6
9
  source_root File.expand_path("templates", __dir__)
7
10
 
8
11
  namespace "avo:resource"
9
12
 
10
13
  class_option "model-class",
14
+ desc: "The name of the model.",
11
15
  type: :string,
12
- required: false,
13
- desc: "The name of the model."
16
+ required: false
14
17
 
15
18
  def create
16
19
  template "resource/resource.tt", "app/avo/resources/#{resource_name}.rb"
@@ -18,7 +21,7 @@ module Generators
18
21
  end
19
22
 
20
23
  def resource_class
21
- "#{class_name.remove(":")}"
24
+ class_name.remove(":").to_s
22
25
  end
23
26
 
24
27
  def controller_class
@@ -26,7 +29,7 @@ module Generators
26
29
  end
27
30
 
28
31
  def resource_name
29
- "#{model_resource_name}"
32
+ model_resource_name.to_s
30
33
  end
31
34
 
32
35
  def controller_name
@@ -136,12 +139,12 @@ module Generators
136
139
 
137
140
  fields.each do |field_name, field_options|
138
141
  # if field_options are not available (likely a missing resource for an association), skip the field
139
- fields_string += "\n # Could not generate a field for #{field_name}" and next unless field_options
142
+ fields_string += "\n # Could not generate a field for #{field_name}" and next unless field_options
140
143
 
141
144
  options = ""
142
145
  field_options[:options].each { |k, v| options += ", #{k}: #{v}" } if field_options[:options].present?
143
146
 
144
- fields_string += "\n #{field_string field_name, field_options[:field], options}"
147
+ fields_string += "\n #{field_string field_name, field_options[:field], options}"
145
148
  end
146
149
 
147
150
  fields_string
@@ -163,7 +166,7 @@ module Generators
163
166
 
164
167
  def fields_from_model_rich_texts
165
168
  rich_texts.each do |name, _|
166
- fields[(name.delete_prefix("rich_text_"))] = {field: "trix"}
169
+ fields[name.delete_prefix("rich_text_")] = {field: "trix"}
167
170
  end
168
171
  end
169
172
 
@@ -11,17 +11,30 @@ module Generators
11
11
 
12
12
  def create_files
13
13
  unless tailwindcss_installed?
14
+ say "Installing Tailwindcss"
14
15
  system "./bin/bundle add tailwindcss-rails"
15
16
  system "./bin/rails tailwindcss:install"
16
17
  end
17
18
 
18
- unless Rails.root.join("app", "assets", "stylesheets", "avo.tailwind.css").exist?
19
- say "Add default app/assets/stylesheets/avo.tailwind.css"
20
- copy_file template_path("avo.tailwind.css"), "app/assets/stylesheets/avo.tailwind.css"
19
+ unless (path = Rails.root.join("config", "avo", "tailwind.config.js")).exist?
20
+ say "Generating the Avo config file."
21
+ copy_file template_path("tailwind.config.js"), path
22
+ end
23
+
24
+ unless (path = Rails.root.join("app", "assets", "stylesheets", "avo", "tailwindcss")).exist?
25
+ say "Generating the tailwindcss directory."
26
+ directory ::Avo::Engine.root.join("app", "assets", "stylesheets", "css", "tailwindcss"), path
27
+ end
28
+
29
+
30
+ unless (path = Rails.root.join("app", "assets", "stylesheets", "avo" ,"tailwind.css")).exist?
31
+ say "Add default tailwind.css"
32
+ copy_file template_path("avo.tailwind.css"), path
21
33
  end
22
34
 
23
35
  if Rails.root.join("Procfile.dev").exist?
24
- append_to_file "Procfile.dev", "avo_css: yarn avo:tailwindcss --watch\n"
36
+ say "Add #{cmd = "avo_css: yarn avo:tailwindcss --watch"} to Procfile.dev"
37
+ append_to_file "Procfile.dev", "#{cmd}\n"
25
38
  else
26
39
  say "Add default Procfile.dev"
27
40
  copy_file template_path("Procfile.dev"), "Procfile.dev"
@@ -30,17 +43,50 @@ module Generators
30
43
  run "gem install foreman"
31
44
  end
32
45
 
33
- # Ensure that the _pre_head.html.erb template is available
34
- unless Rails.root.join("app", "views", "avo", "partials", "_pre_head.html.erb").exist?
35
- say "Ejecting the _pre_head.html.erb partial"
36
- Rails::Generators.invoke("avo:eject", [":pre_head", "--skip-avo-version"], {destination_root: Rails.root})
46
+ script_name = "avo:tailwindcss"
47
+ script_command = "tailwindcss -i ./app/assets/stylesheets/avo/tailwind.css -o ./app/assets/builds/avo.tailwind.css -c ./config/avo/tailwind.config.js --minify"
48
+ pretty_script_command = "\"#{script_name}\": \"#{script_command}\""
49
+
50
+ if (path = Rails.root.join("package.json")).exist?
51
+ say "Add #{pretty_script_command} to package.json"
52
+ json_data = JSON.parse(File.read(path))
53
+ json_data["scripts"] ||= {}
54
+ json_data["scripts"][script_name] = script_command
55
+
56
+ File.open(path, 'w') do |file|
57
+ file.write(JSON.pretty_generate(json_data) + "\n")
58
+ end
59
+ else
60
+ say "package.json not found.", :yellow
61
+ say "Ensure you have the following script in your package.json file.", :yellow
62
+ say "\"scripts\": {\n" \
63
+ " #{pretty_script_command}\n" \
64
+ "}", :green
37
65
  end
38
66
 
39
- say "Adding the CSS asset to the partial"
40
- prepend_to_file Rails.root.join("app", "views", "avo", "partials", "_pre_head.html.erb"), "<%= stylesheet_link_tag \"avo.tailwind.css\", media: \"all\" %>"
67
+ rake_enhance = <<~RUBY
41
68
 
42
- say "Ensure you have the following script in your package.json file.", :yellow
43
- say %("scripts": { "avo:tailwindcss": "tailwindcss -i ./app/assets/stylesheets/avo.tailwind.css -o ./app/assets/builds/avo.tailwind.css --minify" }), :green
69
+ Rake::Task["assets:precompile"].enhance(["avo:sym_link"])
70
+ RUBY
71
+
72
+ if (path = Rails.root.join("Rakefile")).exist?
73
+ say "Add #{rake_enhance.strip} to Rakefile"
74
+ append_to_file path, rake_enhance
75
+ else
76
+ say "Rakefile not found.", :yellow
77
+ say "Ensure you have the following code in your Rakefile file.", :yellow
78
+ say rake_enhance, :green
79
+ end
80
+
81
+ say "Make sure you run \"bundle exec rake avo:sym_link\" before compiling the assets with the \"#{script_name}\" task.", :green
82
+ if (path = Rails.root.join("bin", "dev")).exist?
83
+ lines = File.read(path).lines
84
+
85
+ # Insert the task after the shebang line (the first line)
86
+ lines.insert(1, "bundle exec rake avo:sym_link")
87
+
88
+ File.write(path, lines.join)
89
+ end
44
90
  end
45
91
 
46
92
  no_tasks do
@@ -1,15 +1,19 @@
1
1
  # For more information regarding these settings check out our docs https://docs.avohq.io
2
+ # The values disaplayed here are the default ones. Uncomment and change them to fit your needs.
2
3
  Avo.configure do |config|
3
4
  ## == Routing ==
4
5
  config.root_path = '/<%= options[:path] %>'
5
6
  # used only when you have custom `map` configuration in your config.ru
6
7
  # config.prefix_path = "/internal"
7
8
 
9
+ # Sometimes you migth want to mount Avo's engines yourself.
10
+ # https://docs.avohq.io/3.0/routing.html
11
+ # config.mount_avo_engines = true
12
+
8
13
  # Where should the user be redirected when visting the `/<%= options[:path] %>` url
9
14
  # config.home_path = nil
10
15
 
11
16
  ## == Licensing ==
12
- config.license = 'community' # change this to 'pro' when you add the license key
13
17
  # config.license_key = ENV['AVO_LICENSE_KEY']
14
18
 
15
19
  ## == Set the context ==
@@ -66,6 +70,7 @@ Avo.configure do |config|
66
70
  # config.disabled_features = []
67
71
  # config.buttons_on_form_footers = true
68
72
  # config.field_wrapper_layout = true
73
+ # config.resource_parent_controller = "Avo::ResourcesController"
69
74
 
70
75
  ## == Branding ==
71
76
  # config.branding = {
@@ -1,4 +1,4 @@
1
1
  # This controller has been generated to enable Rails' resource routes.
2
2
  # More information on https://docs.avohq.io/2.0/controllers.html
3
- class <%= controller_class %> < Avo::ResourcesController
3
+ class <%= controller_class %> < <%= parent_controller %>
4
4
  end
@@ -1,6 +1,8 @@
1
- @tailwind base;
2
- @tailwind components;
3
- @tailwind utilities;
1
+ @import 'tailwindcss/base';
2
+ # Have all of Avo's custom and plugins styles available.
3
+ @import '../../../../tmp/avo/base.css';
4
+ @import 'tailwindcss/components';
5
+ @import 'tailwindcss/utilities';
4
6
 
5
7
  /*
6
8
 
@@ -0,0 +1,11 @@
1
+ const avoPreset = require('../../tmp/avo/tailwind.preset.js')
2
+
3
+ module.exports = {
4
+ presets: [avoPreset],
5
+ content: [
6
+ ...avoPreset.content,
7
+ './app/views/**/*.html.erb',
8
+ './app/helpers/**/*.rb',
9
+ './app/javascript/**/*.js',
10
+ ]
11
+ }
@@ -1,8 +1,3 @@
1
- # desc 'Explaining what the task does'
2
- # task :avo do
3
- # # Task goes here
4
- # end
5
-
6
1
  desc "Runs the update command for all Avo gems."
7
2
  task "avo:update" do
8
3
  system "bundle update avo avo-pro avo-advanced avo-dashboards avo_filters avo-menu avo_upgrade"
@@ -63,3 +58,36 @@ task "avo:gem_paths" do
63
58
  # avo:/Users/adrian/work/avocado/avo-3,avo_filters:/Users/adrian/work/avocado/advanced/avo_filters
64
59
  puts result
65
60
  end
61
+
62
+ desc "Symlinks all Avo gems to tmp/avo/packages"
63
+ task "avo:sym_link" do
64
+ base_path = Rails.root.join("tmp", "avo").to_s.gsub("/spec/dummy", "")
65
+ packages_path = "#{base_path}/packages"
66
+ if Dir.exist?(packages_path)
67
+ `rm -rf #{packages_path}/*`
68
+ else
69
+ `mkdir -p #{packages_path}`
70
+ `touch #{packages_path}/.keep`
71
+ end
72
+
73
+ ["avo", "avo-advanced", "avo-pro", "avo-dynamic_filters", "avo-dashboards", "avo-menu"].each do |gem|
74
+ path = `bundle show #{gem} 2> /dev/null`.chomp
75
+
76
+ unless path.empty?
77
+ puts "[Avo->] Linking #{gem} to #{path}"
78
+ `ln -s #{path} #{packages_path}/#{gem}`
79
+ end
80
+ end
81
+
82
+ base_css_path = Avo::Engine.root.join("app", "assets", "builds", "avo.base.css")
83
+ dest_css_path = "#{base_path}/base.css"
84
+ `rm #{dest_css_path}` if File.exist?("#{dest_css_path}")
85
+ puts "[Avo->] Linking avo.base.css to #{base_css_path}"
86
+ `ln -s #{base_css_path} #{dest_css_path}`
87
+
88
+ base_preset_path = Avo::Engine.root.join("tailwind.preset.js")
89
+ dest_preset_path = "#{base_path}/tailwind.preset.js"
90
+ `rm #{dest_preset_path}` if File.exist?("#{dest_preset_path}")
91
+ puts "[Avo->] Linking tailwind.preset.js to #{base_preset_path}"
92
+ `ln -s #{base_preset_path} #{dest_preset_path}`
93
+ end