super 0.0.1 → 0.0.6

Sign up to get free protection for your applications and to get access to all the features.
Files changed (111) hide show
  1. checksums.yaml +4 -4
  2. data/.yardopts +11 -0
  3. data/README.md +64 -78
  4. data/Rakefile +3 -1
  5. data/app/assets/config/super_manifest.js +2 -1
  6. data/app/assets/javascripts/super/application.js +1252 -316
  7. data/app/assets/stylesheets/super/application.css +102704 -17321
  8. data/app/controllers/super/application_controller.rb +50 -42
  9. data/app/helpers/super/application_helper.rb +39 -0
  10. data/app/views/layouts/super/application.html.erb +11 -7
  11. data/app/views/super/application/_collection_header.html.erb +15 -0
  12. data/app/views/super/application/_flash.html.erb +17 -0
  13. data/app/views/super/application/_form_field__destroy.html.erb +9 -0
  14. data/app/views/super/application/_form_field_select.html.erb +23 -0
  15. data/app/views/super/application/_form_field_text.html.erb +13 -0
  16. data/app/views/super/application/_form_fieldset.html.erb +8 -0
  17. data/app/views/super/application/_form_has_many.html.erb +21 -0
  18. data/app/views/super/application/_form_has_one.html.erb +11 -0
  19. data/app/views/super/application/_form_inline_errors.html.erb +10 -0
  20. data/app/views/super/application/_member_header.html.erb +16 -0
  21. data/app/views/super/application/_super_layout.html.erb +29 -0
  22. data/app/views/super/application/_super_panel.html.erb +7 -0
  23. data/app/views/super/application/_super_schema_display_actions.html.erb +5 -0
  24. data/app/views/super/application/_super_schema_display_index.html.erb +39 -0
  25. data/app/views/super/application/_super_schema_display_show.html.erb +8 -0
  26. data/app/views/super/application/_super_schema_form.html.erb +15 -0
  27. data/app/views/super/application/edit.html.erb +4 -5
  28. data/app/views/super/application/index.html.erb +6 -1
  29. data/app/views/super/application/new.html.erb +4 -5
  30. data/app/views/super/application/nothing.html.erb +0 -0
  31. data/app/views/super/application/show.html.erb +6 -10
  32. data/app/views/super/feather/{_chevron_down.svg → _chevron_down.html} +0 -0
  33. data/config/locales/en.yml +5 -0
  34. data/docs/README.md +6 -0
  35. data/docs/cheat.md +41 -0
  36. data/docs/faq.md +44 -0
  37. data/docs/quick_start.md +45 -0
  38. data/docs/webpacker.md +17 -0
  39. data/docs/yard_customizations.rb +41 -0
  40. data/frontend/super-frontend/build.js +14 -12
  41. data/frontend/super-frontend/dist/application.css +102704 -17321
  42. data/frontend/super-frontend/dist/application.js +1252 -316
  43. data/frontend/super-frontend/package.json +11 -4
  44. data/frontend/super-frontend/postcss.config.js +4 -4
  45. data/frontend/super-frontend/src/javascripts/super/application.ts +18 -0
  46. data/frontend/super-frontend/src/javascripts/super/apply_template_controller.ts +19 -0
  47. data/frontend/super-frontend/src/javascripts/super/rails__ujs.d.ts +1 -0
  48. data/frontend/super-frontend/src/javascripts/super/toggle_pending_destruction_controller.ts +15 -0
  49. data/frontend/super-frontend/src/stylesheets/super/application.css +63 -0
  50. data/frontend/super-frontend/tailwind.config.js +12 -4
  51. data/frontend/super-frontend/tsconfig.json +13 -0
  52. data/frontend/super-frontend/yarn.lock +1891 -1798
  53. data/lib/generators/super/install/USAGE +4 -2
  54. data/lib/generators/super/install/install_generator.rb +18 -3
  55. data/lib/generators/super/resource/USAGE +1 -2
  56. data/lib/generators/super/resource/resource_generator.rb +0 -2
  57. data/lib/generators/super/resource/templates/resources_controller.rb.tt +38 -2
  58. data/lib/generators/super/webpacker/webpacker_generator.rb +8 -0
  59. data/lib/super.rb +10 -5
  60. data/lib/super/action_inquirer.rb +101 -0
  61. data/lib/super/assets.rb +1 -0
  62. data/lib/super/client_error.rb +43 -0
  63. data/lib/super/compatibility.rb +13 -0
  64. data/lib/super/configuration.rb +60 -45
  65. data/lib/super/controls.rb +26 -15
  66. data/lib/super/controls/optional.rb +65 -0
  67. data/lib/super/controls/required.rb +41 -0
  68. data/lib/super/controls/steps.rb +115 -0
  69. data/lib/super/display/schema_types.rb +60 -18
  70. data/lib/super/engine.rb +1 -0
  71. data/lib/super/error.rb +10 -1
  72. data/lib/super/form.rb +48 -0
  73. data/lib/super/form/schema_types.rb +96 -21
  74. data/lib/super/layout.rb +47 -0
  75. data/lib/super/link.rb +110 -0
  76. data/lib/super/navigation/automatic.rb +2 -0
  77. data/lib/super/pagination.rb +19 -8
  78. data/lib/super/panel.rb +30 -0
  79. data/lib/super/partial.rb +11 -0
  80. data/lib/super/partial/resolving.rb +24 -0
  81. data/lib/super/schema.rb +64 -1
  82. data/lib/super/version.rb +1 -1
  83. data/lib/super/view_helper.rb +43 -0
  84. metadata +145 -38
  85. data/app/views/super/application/_form.html.erb +0 -13
  86. data/app/views/super/application/_form_field.html.erb +0 -7
  87. data/app/views/super/application/_form_generic_select.html.erb +0 -19
  88. data/app/views/super/application/_form_generic_text.html.erb +0 -7
  89. data/app/views/super/application/_index.html.erb +0 -58
  90. data/frontend/super-frontend/src/javascripts/super/application.js +0 -11
  91. data/lib/generators/super/resource/templates/resource_dashboard.rb.tt +0 -65
  92. data/lib/super/display.rb +0 -9
  93. data/lib/super/inline_callback.rb +0 -82
  94. data/lib/super/test_support/fixtures/members.yml +0 -336
  95. data/lib/super/test_support/fixtures/ships.yml +0 -10
  96. data/lib/super/test_support/setup.rb +0 -79
  97. data/lib/super/test_support/starfleet_seeder.rb +0 -49
  98. data/lib/super/test_support/templates/20190216224956_create_members.rb +0 -11
  99. data/lib/super/test_support/templates/20190803143320_create_ships.rb +0 -11
  100. data/lib/super/test_support/templates/20190806014121_add_ship_to_members.rb +0 -5
  101. data/lib/super/test_support/templates/admin/members_controller.rb +0 -9
  102. data/lib/super/test_support/templates/admin/ships_controller.rb +0 -9
  103. data/lib/super/test_support/templates/admin_controller.rb +0 -2
  104. data/lib/super/test_support/templates/member.rb +0 -16
  105. data/lib/super/test_support/templates/member_dashboard.rb +0 -90
  106. data/lib/super/test_support/templates/routes.rb +0 -10
  107. data/lib/super/test_support/templates/seeds.rb +0 -2
  108. data/lib/super/test_support/templates/ship.rb +0 -3
  109. data/lib/super/test_support/templates/ship_dashboard.rb +0 -79
  110. data/lib/super/view.rb +0 -25
  111. data/lib/tasks/super_tasks.rake +0 -4
@@ -20,7 +20,8 @@ Example:
20
20
  config/initializers/super.rb
21
21
  app/controllers/admin_controller.rb
22
22
  app/controllers/admin/.keep
23
- app/super/.keep
23
+
24
+ This will also update your Sprockets manifest as necessary.
24
25
 
25
26
  Example:
26
27
  rails generate super:install --controller-namespace badminton
@@ -29,4 +30,5 @@ Example:
29
30
  config/initializers/super.rb
30
31
  app/controllers/badminton_controller.rb
31
32
  app/controllers/badminton/.keep
32
- app/super/.keep
33
+
34
+ This will also update your Sprockets manifest as necessary.
@@ -29,9 +29,24 @@ module Super
29
29
  create_file("app/controllers/#{controller_namespace}/.keep", "")
30
30
  end
31
31
 
32
- def create_directory_for_dashboards_slash_setup
33
- empty_directory("app/super")
34
- create_file("app/super/.keep", "")
32
+ def copy_cheatsheet
33
+ super_path = Pathname.new(Gem.loaded_specs["super"].full_gem_path).expand_path
34
+ super_cheat_path = super_path.join("docs", "cheat.md")
35
+
36
+ path =
37
+ if options["controller_namespace"].present?
38
+ "app/controllers/#{controller_namespace}/README.md"
39
+ else
40
+ "app/controllers/README.md"
41
+ end
42
+
43
+ create_file(path) do
44
+ super_cheat_path.read.sub(%r{<!--.*?-->}m, "").strip + "\n"
45
+ end
46
+ end
47
+
48
+ def setup_sprockets4_manifest
49
+ append_to_file "app/assets/config/manifest.js", "//= link super_manifest.js\n"
35
50
  end
36
51
 
37
52
  private
@@ -1,9 +1,8 @@
1
1
  Description:
2
- Creates a controller and its respective "control".
2
+ Creates a controller
3
3
 
4
4
  Example:
5
5
  rails generate super:resource Thing
6
6
 
7
7
  This will create:
8
8
  app/controllers/admin/things_controller.rb
9
- app/controls/thing_controls.rb
@@ -14,8 +14,6 @@ module Super
14
14
  "resources_controller.rb",
15
15
  "app/controllers/#{controller_subdir}#{file_path.pluralize}_controller.rb"
16
16
  )
17
-
18
- template("resource_dashboard.rb", "app/super/#{file_path}_dashboard.rb")
19
17
  end
20
18
 
21
19
  private
@@ -2,8 +2,44 @@
2
2
  class <%= class_name.pluralize %>Controller < <%= parent_controller_name %>
3
3
  private
4
4
 
5
- def dashboard
6
- <%= class_name %>Dashboard.new
5
+ def new_controls
6
+ Controls.new
7
+ end
8
+
9
+ class Controls
10
+ def title
11
+ <%= class_name %>.name.pluralize
12
+ end
13
+
14
+ def model
15
+ <%= class_name %>
16
+ end
17
+
18
+ def scope(action:)
19
+ if action.read?
20
+ <%= class_name %>.all
21
+ else
22
+ <%= class_name %>.all
23
+ end
24
+ end
25
+
26
+ def permitted_params(params, action:)
27
+ if action.create?
28
+ params.require(:<%= file_name %>).permit()
29
+ else
30
+ params.require(:<%= file_name %>).permit()
31
+ end
32
+ end
33
+
34
+ def display_schema(action:)
35
+ Super::Schema.new(Super::Display::SchemaTypes.new) do |fields, type|
36
+ end
37
+ end
38
+
39
+ def form_schema(action:)
40
+ Super::Schema.new(Super::Form::SchemaTypes.new) do |fields, type|
41
+ end
42
+ end
7
43
  end
8
44
  end
9
45
  <% end -%>
@@ -9,6 +9,14 @@ module Super
9
9
  )
10
10
  end
11
11
 
12
+ def set_asset_handler_to_webpacker
13
+ insert_into_file(
14
+ "config/initializers/super.rb",
15
+ " c.asset_handler = Super::Assets.webpacker\n",
16
+ before: /\bend\b/
17
+ )
18
+ end
19
+
12
20
  def remind_about_erb
13
21
  say "Make sure ERB is set up for Webpacker!", :bold
14
22
  say "Run if needed: rails webpacker:install:erb", :bold
@@ -1,18 +1,23 @@
1
- require "tsort"
2
1
  require "active_support/concern"
3
2
 
3
+ require "super/action_inquirer"
4
4
  require "super/assets"
5
+ require "super/client_error"
6
+ require "super/compatibility"
5
7
  require "super/configuration"
6
8
  require "super/controls"
9
+ require "super/display/schema_types"
7
10
  require "super/engine"
8
11
  require "super/error"
9
- require "super/display"
10
- require "super/display/schema_types"
12
+ require "super/form"
11
13
  require "super/form/schema_types"
12
- require "super/inline_callback"
14
+ require "super/layout"
15
+ require "super/link"
13
16
  require "super/navigation/automatic"
14
17
  require "super/pagination"
18
+ require "super/panel"
19
+ require "super/partial"
15
20
  require "super/plugin"
16
21
  require "super/schema"
17
22
  require "super/version"
18
- require "super/view"
23
+ require "super/view_helper"
@@ -0,0 +1,101 @@
1
+ module Super
2
+ # ```ruby
3
+ # action = Super::ActionInquirer.new(
4
+ # Super::ActionInquirer.default_for_resources,
5
+ # :index
6
+ # )
7
+ #
8
+ # action.read? # => true
9
+ # action.index? # => true
10
+ # action.show? # => false
11
+ # action.write? # => false
12
+ # ```
13
+ class ActionInquirer
14
+ attr_reader :action
15
+
16
+ # @return [Hash<Symbol, Array<Symbol>>] default settings for initialization
17
+ #
18
+ def self.default_for_resources
19
+ {
20
+ read: %i[index show new edit],
21
+ write: %i[create update destroy],
22
+ delete: %i[destroy]
23
+ }
24
+ end
25
+
26
+ def initialize(categories_and_their_actions, action)
27
+ @categories = categories_and_their_actions.keys.map(&:to_s)
28
+ @actions = categories_and_their_actions.values.flatten.uniq.map(&:to_s)
29
+ @actions_categories = {}
30
+
31
+ categories_and_their_actions.each do |c, actions|
32
+ c = c.to_s
33
+
34
+ actions.each do |a|
35
+ a = a.to_s
36
+ @actions_categories[a] ||= []
37
+ @actions_categories[a].push(c)
38
+ end
39
+ end
40
+
41
+ intersection = @categories & @actions
42
+ if intersection.any?
43
+ raise Error::ActionInquirerError,
44
+ "Found shared elements between categories and actions: #{intersection.join(", ")}"
45
+ end
46
+
47
+ self.action = action
48
+ end
49
+
50
+ def action=(new_action)
51
+ new_action = new_action.to_s
52
+ if !@actions.include?(new_action)
53
+ raise Error::ActionInquirerError, "Unknown action: #{new_action}"
54
+ end
55
+
56
+ @action = new_action
57
+ end
58
+
59
+ def respond_to_missing?(method_name, *)
60
+ inquiry = parse_inquiry(method_name)
61
+
62
+ return super if !inquiry
63
+
64
+ @actions.include?(inquiry) || @categories.include?(inquiry) || super
65
+ end
66
+
67
+ def method_missing(method_name, *)
68
+ inquiry = parse_inquiry(method_name)
69
+
70
+ return super if !inquiry
71
+
72
+ if @actions.include?(inquiry)
73
+ matches_action?(inquiry)
74
+ elsif @categories.include?(inquiry)
75
+ matches_category?(inquiry)
76
+ else
77
+ super
78
+ end
79
+ end
80
+
81
+ private
82
+
83
+ def parse_inquiry(method_name)
84
+ inquiry = method_name.to_s
85
+
86
+ if inquiry[-1] != "?"
87
+ return nil
88
+ end
89
+
90
+ inquiry.chomp("?")
91
+ end
92
+
93
+ def matches_action?(inquiry)
94
+ @action == inquiry
95
+ end
96
+
97
+ def matches_category?(inquiry)
98
+ @actions_categories[@action].include?(inquiry)
99
+ end
100
+ end
101
+ end
@@ -1,4 +1,5 @@
1
1
  module Super
2
+ # Utilities for determining whether to use Sprockets or Webpacker
2
3
  class Assets
3
4
  def self.sprockets_available?
4
5
  Gem::Dependency.new("sprockets").matching_specs.any?
@@ -0,0 +1,43 @@
1
+ module Super
2
+ # A container class for all user-facing (4xx) errors thrown by this library.
3
+ #
4
+ # See also `Super::Error`
5
+ class ClientError < StandardError
6
+ class BadRequest < ClientError; end
7
+ class Unauthorized < ClientError; end
8
+ class Forbidden < ClientError; end
9
+ class NotFound < ClientError; end
10
+ class UnprocessableEntity < ClientError; end
11
+
12
+ module Handling
13
+ extend ActiveSupport::Concern
14
+
15
+ included do
16
+ rescue_from ::Super::ClientError do |exception|
17
+ code, default_message =
18
+ case exception
19
+ when ClientError::UnprocessableEntity
20
+ [422, "Unprocessable entity"]
21
+ when ClientError::NotFound
22
+ [404, "Not found"]
23
+ when ClientError::Forbidden
24
+ [403, "Forbidden"]
25
+ when ClientError::Unauthorized
26
+ [401, "Unauthorized"]
27
+ when ClientError::BadRequest, ClientError
28
+ [400, "Bad request"]
29
+ end
30
+
31
+ flash.now.alert =
32
+ if exception.message == exception.class.name.to_s
33
+ default_message
34
+ else
35
+ exception.message
36
+ end
37
+
38
+ render "nothing", status: code
39
+ end
40
+ end
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,13 @@
1
+ module Super
2
+ module Compatability
3
+ module_function
4
+
5
+ def rails_50_errable_fields(field)
6
+ if Rails::VERSION::MAJOR == 5 && Rails::VERSION::MINOR == 0
7
+ [field.to_s, field.to_sym]
8
+ else
9
+ field
10
+ end
11
+ end
12
+ end
13
+ end
@@ -1,4 +1,6 @@
1
1
  module Super
2
+ # @yield [Configuration]
3
+ # @return [Configuration]
2
4
  def self.configuration
3
5
  @configuration ||= Configuration.new
4
6
 
@@ -9,78 +11,91 @@ module Super
9
11
  @configuration
10
12
  end
11
13
 
12
- module ConfigurationLogic
13
- def self.included(base)
14
- base.extend(ClassMethods)
15
- end
16
-
17
- def initialize
18
- self.class.defaults.each do |key, value|
19
- if value.respond_to?(:call)
20
- value = value.call
21
- end
22
-
23
- public_send("#{key}=", value)
14
+ # Allows setting global configuration
15
+ #
16
+ # ```ruby
17
+ # Super.configuration do |c|
18
+ # c.title = "My Admin Site"
19
+ # end
20
+ # ```
21
+ class Configuration
22
+ module ConfigurationLogic # @api private
23
+ def self.included(base)
24
+ base.extend(ClassMethods)
24
25
  end
25
- end
26
26
 
27
- def configured?(attr)
28
- instance_variable_defined?("@#{attr}")
29
- end
27
+ def initialize
28
+ self.class.defaults.each do |key, value|
29
+ if value.respond_to?(:call)
30
+ value = value.call
31
+ end
30
32
 
31
- module ClassMethods
32
- def defaults
33
- @defaults ||= {}
33
+ public_send("#{key}=", value)
34
+ end
34
35
  end
35
36
 
36
- def wraps
37
- @wraps ||= {}
37
+ def configured?(attr)
38
+ instance_variable_defined?("@#{attr}")
38
39
  end
39
40
 
40
- def configure(attr, wrap: nil, enum: nil, **kwargs)
41
- if kwargs.key?(:default)
42
- defaults[attr] = kwargs[:default]
41
+ module ClassMethods
42
+ def defaults
43
+ @defaults ||= {}
43
44
  end
44
45
 
45
- define_method(attr) do
46
- if !configured?(attr)
47
- raise Error::UnconfiguredConfiguration, "unconfigured: #{attr}"
46
+ def wraps
47
+ @wraps ||= {}
48
+ end
49
+
50
+ def configure(attr, wrap: nil, enum: nil, **kwargs)
51
+ if kwargs.key?(:default)
52
+ defaults[attr] = kwargs[:default]
48
53
  end
49
54
 
50
- result = instance_variable_get("@#{attr}")
55
+ define_method(attr) do
56
+ if !configured?(attr)
57
+ raise Error::UnconfiguredConfiguration, "unconfigured: #{attr}"
58
+ end
51
59
 
52
- if wrap.nil?
53
- result
54
- else
55
- wrap.call(result)
56
- end
57
- end
60
+ result = instance_variable_get("@#{attr}")
58
61
 
59
- define_method("#{attr}=") do |value|
60
- if enum.is_a?(Array)
61
- if !enum.include?(value)
62
- raise Error::InvalidConfiguration,
63
- "tried to set `#{attr}` to `#{value.inspect}`, " \
64
- "expected: #{enum.join(", ")}"
62
+ if wrap.nil?
63
+ result
64
+ else
65
+ wrap.call(result)
65
66
  end
66
67
  end
67
68
 
68
- instance_variable_set("@#{attr}", value)
69
- value
69
+ define_method("#{attr}=") do |value|
70
+ if enum.is_a?(Array)
71
+ if !enum.include?(value)
72
+ raise Error::InvalidConfiguration,
73
+ "tried to set `#{attr}` to `#{value.inspect}`, " \
74
+ "expected: #{enum.join(", ")}"
75
+ end
76
+ end
77
+
78
+ instance_variable_set("@#{attr}", value)
79
+ value
80
+ end
70
81
  end
71
82
  end
72
83
  end
73
- end
74
84
 
75
- class Configuration
76
85
  include ConfigurationLogic
77
86
 
87
+ # @!attribute [rw]
78
88
  configure :title
79
- configure :index_resources_per_page, default: 20
89
+ # @!attribute [rw]
90
+ configure :index_records_per_page, default: 20
91
+ # @!attribute [rw]
80
92
  configure :controller_namespace, default: "admin"
93
+ # @!attribute [rw]
81
94
  configure :route_namespace, default: :admin, wrap: -> (val) { [val].flatten }
95
+ # @!attribute [rw]
82
96
  configure :asset_handler, default: -> { Super::Assets.auto }
83
97
 
98
+ # @api private
84
99
  def path_parts(*parts)
85
100
  route_namespace + parts
86
101
  end