super 0.0.2 → 0.0.7

Sign up to get free protection for your applications and to get access to all the features.
Files changed (110) hide show
  1. checksums.yaml +4 -4
  2. data/.yardopts +11 -0
  3. data/README.md +68 -76
  4. data/app/assets/javascripts/super/application.js +1252 -316
  5. data/app/assets/stylesheets/super/application.css +102704 -17321
  6. data/app/controllers/super/application_controller.rb +49 -71
  7. data/app/views/layouts/super/application.html.erb +10 -8
  8. data/app/views/super/application/_collection_header.html.erb +15 -0
  9. data/app/views/super/application/_filter.html.erb +14 -0
  10. data/app/views/super/application/_filter_type_select.html.erb +31 -0
  11. data/app/views/super/application/_filter_type_text.html.erb +22 -0
  12. data/app/views/super/application/_filter_type_timestamp.html.erb +35 -0
  13. data/app/views/super/application/_flash.html.erb +13 -13
  14. data/app/views/super/application/_form_field__destroy.html.erb +9 -0
  15. data/app/views/super/application/_form_field_select.html.erb +23 -0
  16. data/app/views/super/application/_form_field_text.html.erb +13 -0
  17. data/app/views/super/application/_form_fieldset.html.erb +8 -0
  18. data/app/views/super/application/_form_has_many.html.erb +21 -0
  19. data/app/views/super/application/_form_has_one.html.erb +11 -0
  20. data/app/views/super/application/_form_inline_errors.html.erb +10 -0
  21. data/app/views/super/application/_member_header.html.erb +16 -0
  22. data/app/views/super/application/_super_layout.html.erb +29 -0
  23. data/app/views/super/application/_super_pagination.html.erb +16 -0
  24. data/app/views/super/application/_super_panel.html.erb +7 -0
  25. data/app/views/super/application/_super_schema_display_actions.html.erb +5 -0
  26. data/app/views/super/application/_super_schema_display_index.html.erb +24 -0
  27. data/app/views/super/application/_super_schema_display_show.html.erb +8 -0
  28. data/app/views/super/application/_super_schema_form.html.erb +15 -0
  29. data/app/views/super/application/edit.html.erb +1 -6
  30. data/app/views/super/application/index.html.erb +1 -1
  31. data/app/views/super/application/new.html.erb +1 -6
  32. data/app/views/super/application/show.html.erb +1 -1
  33. data/app/views/super/feather/{_chevron_down.svg → _chevron_down.html} +0 -0
  34. data/config/locales/en.yml +5 -0
  35. data/docs/README.md +6 -0
  36. data/docs/cheat.md +41 -0
  37. data/docs/faq.md +44 -0
  38. data/docs/quick_start.md +45 -0
  39. data/docs/webpacker.md +17 -0
  40. data/docs/yard_customizations.rb +41 -0
  41. data/frontend/super-frontend/build.js +14 -12
  42. data/frontend/super-frontend/dist/application.css +102704 -17321
  43. data/frontend/super-frontend/dist/application.js +1252 -316
  44. data/frontend/super-frontend/package.json +11 -4
  45. data/frontend/super-frontend/postcss.config.js +4 -4
  46. data/frontend/super-frontend/src/javascripts/super/application.ts +18 -0
  47. data/frontend/super-frontend/src/javascripts/super/apply_template_controller.ts +19 -0
  48. data/frontend/super-frontend/src/javascripts/super/rails__ujs.d.ts +1 -0
  49. data/frontend/super-frontend/src/javascripts/super/toggle_pending_destruction_controller.ts +15 -0
  50. data/frontend/super-frontend/src/stylesheets/super/application.css +63 -0
  51. data/frontend/super-frontend/tailwind.config.js +12 -4
  52. data/frontend/super-frontend/tsconfig.json +13 -0
  53. data/frontend/super-frontend/yarn.lock +1891 -1798
  54. data/lib/generators/super/install/install_generator.rb +16 -0
  55. data/lib/generators/super/webpacker/webpacker_generator.rb +8 -0
  56. data/lib/super.rb +16 -6
  57. data/lib/super/action_inquirer.rb +14 -1
  58. data/lib/super/assets.rb +1 -0
  59. data/lib/super/client_error.rb +43 -0
  60. data/lib/super/compatibility.rb +25 -0
  61. data/lib/super/configuration.rb +66 -44
  62. data/lib/super/controls.rb +26 -15
  63. data/lib/super/controls/optional.rb +54 -0
  64. data/lib/super/controls/required.rb +41 -0
  65. data/lib/super/controls/steps.rb +128 -0
  66. data/lib/super/display/schema_types.rb +90 -18
  67. data/lib/super/engine.rb +7 -0
  68. data/lib/super/error.rb +9 -8
  69. data/lib/super/filter.rb +137 -0
  70. data/lib/super/filter/operator.rb +103 -0
  71. data/lib/super/filter/schema_types.rb +118 -0
  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 +80 -8
  78. data/lib/super/panel.rb +30 -0
  79. data/lib/super/partial.rb +23 -0
  80. data/lib/super/partial/resolving.rb +24 -0
  81. data/lib/super/plugin.rb +34 -63
  82. data/lib/super/schema.rb +65 -1
  83. data/lib/super/version.rb +1 -1
  84. data/lib/super/view_helper.rb +43 -0
  85. metadata +132 -33
  86. data/app/views/super/application/_form.html.erb +0 -15
  87. data/app/views/super/application/_form_field.html.erb +0 -7
  88. data/app/views/super/application/_form_generic_select.html.erb +0 -19
  89. data/app/views/super/application/_form_generic_text.html.erb +0 -7
  90. data/app/views/super/application/_index.html.erb +0 -60
  91. data/app/views/super/application/_show.html.erb +0 -12
  92. data/frontend/super-frontend/src/javascripts/super/application.js +0 -11
  93. data/lib/super/display.rb +0 -9
  94. data/lib/super/inline_callback.rb +0 -82
  95. data/lib/super/test_support/copy_app_templates/20190216224956_create_members.rb +0 -11
  96. data/lib/super/test_support/copy_app_templates/20190803143320_create_ships.rb +0 -11
  97. data/lib/super/test_support/copy_app_templates/20190806014121_add_ship_to_members.rb +0 -5
  98. data/lib/super/test_support/copy_app_templates/member.rb +0 -16
  99. data/lib/super/test_support/copy_app_templates/members_controller.rb +0 -52
  100. data/lib/super/test_support/copy_app_templates/routes.rb +0 -10
  101. data/lib/super/test_support/copy_app_templates/seeds.rb +0 -2
  102. data/lib/super/test_support/copy_app_templates/ship.rb +0 -3
  103. data/lib/super/test_support/copy_app_templates/ships_controller.rb +0 -47
  104. data/lib/super/test_support/fixtures/members.yml +0 -336
  105. data/lib/super/test_support/fixtures/ships.yml +0 -10
  106. data/lib/super/test_support/generate_copy_app.rb +0 -52
  107. data/lib/super/test_support/generate_dummy.rb +0 -94
  108. data/lib/super/test_support/starfleet_seeder.rb +0 -49
  109. data/lib/super/view.rb +0 -25
  110. data/lib/tasks/super_tasks.rake +0 -4
@@ -29,6 +29,22 @@ module Super
29
29
  create_file("app/controllers/#{controller_namespace}/.keep", "")
30
30
  end
31
31
 
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
+
32
48
  def setup_sprockets4_manifest
33
49
  append_to_file "app/assets/config/manifest.js", "//= link super_manifest.js\n"
34
50
  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,19 +1,29 @@
1
1
  require "tsort"
2
- require "active_support/concern"
2
+
3
+ require "rails/engine"
3
4
 
4
5
  require "super/action_inquirer"
5
6
  require "super/assets"
7
+ require "super/client_error"
8
+ require "super/compatibility"
6
9
  require "super/configuration"
7
10
  require "super/controls"
8
- require "super/engine"
9
- require "super/error"
10
- require "super/display"
11
11
  require "super/display/schema_types"
12
+ require "super/error"
13
+ require "super/filter"
14
+ require "super/filter/operator"
15
+ require "super/filter/schema_types"
16
+ require "super/form"
12
17
  require "super/form/schema_types"
13
- require "super/inline_callback"
18
+ require "super/layout"
19
+ require "super/link"
14
20
  require "super/navigation/automatic"
15
21
  require "super/pagination"
22
+ require "super/panel"
23
+ require "super/partial"
16
24
  require "super/plugin"
17
25
  require "super/schema"
18
26
  require "super/version"
19
- require "super/view"
27
+ require "super/view_helper"
28
+
29
+ require "super/engine"
@@ -1,8 +1,21 @@
1
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
+ # ```
2
13
  class ActionInquirer
3
14
  attr_reader :action
4
15
 
5
- def self.default_resources
16
+ # @return [Hash<Symbol, Array<Symbol>>] default settings for initialization
17
+ #
18
+ def self.default_for_resources
6
19
  {
7
20
  read: %i[index show new edit],
8
21
  write: %i[create update destroy],
@@ -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,25 @@
1
+ module Super
2
+ module Compatability
3
+ module_function
4
+
5
+ # Rails 5.1 and after lets you find field errors using either a string or a
6
+ # symbol.
7
+ def errable_fields(field)
8
+ if Rails::VERSION::MAJOR == 5 && Rails::VERSION::MINOR == 0
9
+ [field.to_s, field.to_sym]
10
+ else
11
+ field
12
+ end
13
+ end
14
+
15
+ def sanitize_sql_like(query)
16
+ if ActiveRecord::VERSION::MAJOR == 4
17
+ ActiveRecord::Base.send(:sanitize_sql_like, query)
18
+ elsif ActiveRecord::VERSION::MAJOR == 5 && ActiveRecord::VERSION::MINOR <= 1
19
+ ActiveRecord::Base.send(:sanitize_sql_like, query)
20
+ else
21
+ ActiveRecord::Base.sanitize_sql_like(query)
22
+ end
23
+ end
24
+ end
25
+ 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,98 @@ module Super
9
11
  @configuration
10
12
  end
11
13
 
12
- module ConfigurationLogic
13
- def self.included(base)
14
- base.extend(ClassMethods)
15
- end
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)
25
+ end
26
+
27
+ def initialize
28
+ self.class.defaults.each do |key, value|
29
+ if value.respond_to?(:call)
30
+ value = value.call
31
+ end
16
32
 
17
- def initialize
18
- self.class.defaults.each do |key, value|
19
- if value.respond_to?(:call)
20
- value = value.call
33
+ public_send("#{key}=", value)
21
34
  end
22
35
 
23
- public_send("#{key}=", value)
36
+ Plugin::Registry.controller.use(prepend: Super::Filter::ControllerMethods)
37
+ Plugin::Registry.controller.use(prepend: Super::Pagination::ControllerMethods)
24
38
  end
25
- end
26
-
27
- def configured?(attr)
28
- instance_variable_defined?("@#{attr}")
29
- end
30
39
 
31
- module ClassMethods
32
- def defaults
33
- @defaults ||= {}
40
+ def configured?(attr)
41
+ instance_variable_defined?("@#{attr}")
34
42
  end
35
43
 
36
- def wraps
37
- @wraps ||= {}
38
- end
44
+ module ClassMethods
45
+ def defaults
46
+ @defaults ||= {}
47
+ end
39
48
 
40
- def configure(attr, wrap: nil, enum: nil, **kwargs)
41
- if kwargs.key?(:default)
42
- defaults[attr] = kwargs[:default]
49
+ def wraps
50
+ @wraps ||= {}
43
51
  end
44
52
 
45
- define_method(attr) do
46
- if !configured?(attr)
47
- raise Error::UnconfiguredConfiguration, "unconfigured: #{attr}"
53
+ def configure(attr, wrap: nil, enum: nil, **kwargs)
54
+ if kwargs.key?(:default)
55
+ defaults[attr] = kwargs[:default]
48
56
  end
49
57
 
50
- result = instance_variable_get("@#{attr}")
58
+ define_method(attr) do
59
+ if !configured?(attr)
60
+ raise Error::UnconfiguredConfiguration, "unconfigured: #{attr}"
61
+ end
51
62
 
52
- if wrap.nil?
53
- result
54
- else
55
- wrap.call(result)
56
- end
57
- end
63
+ result = instance_variable_get("@#{attr}")
58
64
 
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(", ")}"
65
+ if wrap.nil?
66
+ result
67
+ else
68
+ wrap.call(result)
65
69
  end
66
70
  end
67
71
 
68
- instance_variable_set("@#{attr}", value)
69
- value
72
+ define_method("#{attr}=") do |value|
73
+ if enum.is_a?(Array)
74
+ if !enum.include?(value)
75
+ raise Error::InvalidConfiguration,
76
+ "tried to set `#{attr}` to `#{value.inspect}`, " \
77
+ "expected: #{enum.join(", ")}"
78
+ end
79
+ end
80
+
81
+ instance_variable_set("@#{attr}", value)
82
+ value
83
+ end
70
84
  end
71
85
  end
72
86
  end
73
- end
74
87
 
75
- class Configuration
76
88
  include ConfigurationLogic
77
89
 
90
+ # @!attribute [rw]
78
91
  configure :title
79
- configure :index_resources_per_page, default: 20
92
+ # @!attribute [rw]
93
+ configure :index_records_per_page, default: 20
94
+ # @!attribute [rw]
80
95
  configure :controller_namespace, default: "admin"
96
+ # @!attribute [rw]
81
97
  configure :route_namespace, default: :admin, wrap: -> (val) { [val].flatten }
98
+ # @!attribute [rw]
82
99
  configure :asset_handler, default: -> { Super::Assets.auto }
83
100
 
101
+ def controller_plugins
102
+ Plugin::Registry.controller
103
+ end
104
+
105
+ # @api private
84
106
  def path_parts(*parts)
85
107
  route_namespace + parts
86
108
  end
@@ -1,25 +1,36 @@
1
+ require "super/controls/optional"
2
+ require "super/controls/required"
3
+ require "super/controls/steps"
4
+
1
5
  module Super
6
+ # A wrapper around the per-controller Controls classes. This class often
7
+ # directly delegates to the per-controller classes, but it can also provide
8
+ # some default implementation.
2
9
  class Controls
3
- def initialize(dashboard)
4
- @dashboard = dashboard
10
+ include Required
11
+ include Optional
12
+ include Steps
13
+
14
+ def initialize(actual)
15
+ @actual = actual
5
16
  end
6
17
 
7
- attr_reader :dashboard
18
+ attr_reader :actual
8
19
 
9
- def method_missing(method_name, *args)
10
- if @dashboard.respond_to?(method_name)
11
- @dashboard.public_send(method_name, *args)
12
- else
13
- super
14
- end
15
- end
20
+ private
16
21
 
17
- def respond_to_missing?(method_name, _ = false)
18
- if @dashboard.respond_to?(method_name)
19
- true
20
- else
21
- super
22
+ def default_for(method_name, *args, **kwargs)
23
+ if @actual.respond_to?(method_name)
24
+ if args.empty? && kwargs.empty?
25
+ return @actual.public_send(method_name)
26
+ elsif args.empty?
27
+ return @actual.public_send(method_name, **kwargs)
28
+ else
29
+ return @actual.public_send(method_name, *args)
30
+ end
22
31
  end
32
+
33
+ yield
23
34
  end
24
35
  end
25
36
  end
@@ -0,0 +1,54 @@
1
+ module Super
2
+ class Controls
3
+ # Methods for `Controls` that have a sane default implementation
4
+ module Optional
5
+ # This is an optional method
6
+ #
7
+ # @return [String]
8
+ def title
9
+ default_for(:title) do
10
+ model.name.pluralize
11
+ end
12
+ end
13
+
14
+ # Configures what database records are visible on load. This is an optional
15
+ # method, it defaults to "`all`" methods
16
+ #
17
+ # @param action [ActionInquirer]
18
+ # @return [ActiveRecord::Relation]
19
+ def scope(action:)
20
+ default_for(:scope, action: action) do
21
+ model.all
22
+ end
23
+ end
24
+
25
+ # Configures the actions linked to on the index page. This is an optional
26
+ # method
27
+ #
28
+ # @param action [ActionInquirer]
29
+ # @return [Array<Link>]
30
+ def collection_actions(action:)
31
+ default_for(:collection_actions, action: action) do
32
+ Super::Link.find_all(:new)
33
+ end
34
+ end
35
+
36
+ # Configures the actions linked to on the show page as well as each row of
37
+ # the table on the index page. This is an optional method
38
+ #
39
+ # @param action [ActionInquirer]
40
+ # @return [Array<Link>]
41
+ def member_actions(action:)
42
+ default_for(:member_actions, action: action) do
43
+ if action.show?
44
+ Super::Link.find_all(:edit, :destroy)
45
+ elsif action.edit?
46
+ Super::Link.find_all(:show, :destroy)
47
+ else
48
+ Super::Link.find_all(:show, :edit, :destroy)
49
+ end
50
+ end
51
+ end
52
+ end
53
+ end
54
+ end
@@ -0,0 +1,41 @@
1
+ module Super
2
+ class Controls
3
+ # Methods for `Controls` that must be defined for Super to work properly
4
+ module Required
5
+ # Specifies the model. This is a required method
6
+ #
7
+ # @return [ActiveRecord::Base]
8
+ def model
9
+ @actual.model
10
+ end
11
+
12
+ # Configures which parameters could be written to the database. This is a
13
+ # required method
14
+ #
15
+ # @param params [ActionController::Parameters]
16
+ # @param action [ActionInquirer]
17
+ # @return [ActionController::Parameters]
18
+ def permitted_params(params, action:)
19
+ @actual.permitted_params(params, action: action)
20
+ end
21
+
22
+ # Configures the fields that are displayed on the index and show actions.
23
+ # This is a required method
24
+ #
25
+ # @param action [ActionInquirer]
26
+ # @return [Schema]
27
+ def display_schema(action:)
28
+ @actual.display_schema(action: action)
29
+ end
30
+
31
+ # Configures the editable fields on the new and edit actions. This is a
32
+ # required method
33
+ #
34
+ # @param action [ActionInquirer]
35
+ # @return [Schema]
36
+ def form_schema(action:)
37
+ @actual.form_schema(action: action)
38
+ end
39
+ end
40
+ end
41
+ end