super 0.0.1 → 0.0.6

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 (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
@@ -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,65 @@
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
+
53
+ # Specifies how many records to show per page
54
+ #
55
+ # @param action [ActionInquirer]
56
+ # @param query_params [Hash]
57
+ # @return [ActiveRecord::Relation]
58
+ def records_per_page(action:, query_params:)
59
+ default_for(:records_per_page, action: action, query_params: query_params) do
60
+ Super.configuration.index_records_per_page
61
+ end
62
+ end
63
+ end
64
+ end
65
+ 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
@@ -0,0 +1,115 @@
1
+ module Super
2
+ class Controls
3
+ # Methods that are called by controller actions. All of these methods have
4
+ # a default implementation, but feel free to override as needed.
5
+ module Steps
6
+ # Tells the controller how to load records in the index action using
7
+ # `#scope`
8
+ #
9
+ # @param action [ActionInquirer]
10
+ # @param params [ActionController::Parameters]
11
+ # @return [ActiveRecord::Relation]
12
+ def load_records(action:, params:)
13
+ default_for(:load_records, action: action, params: params) do
14
+ scope(action: action)
15
+ end
16
+ end
17
+
18
+ # Sets up pagination
19
+ #
20
+ # @param action [ActionInquirer]
21
+ # @param records [ActiveRecord::Relation]
22
+ # @param query_params [Hash]
23
+ # @return [Pagination]
24
+ def initialize_pagination(action:, records:, query_params:)
25
+ default_for(:initialize_pagination, action: action, records: records, query_params: query_params) do
26
+ Pagination.new(
27
+ total_count: records.size,
28
+ limit: records_per_page(action: action, query_params: query_params),
29
+ query_params: query_params,
30
+ page_query_param: :page
31
+ )
32
+ end
33
+ end
34
+
35
+ # Paginates
36
+ #
37
+ # @param action [ActionInquirer]
38
+ # @param records [ActiveRecord::Relation]
39
+ # @param pagination [Pagination]
40
+ # @return [ActiveRecord::Relation]
41
+ def paginate_records(action:, records:, pagination:)
42
+ default_for(:paginate_records, action: action, records: records, pagination: pagination) do
43
+ records
44
+ .limit(pagination.limit)
45
+ .offset(pagination.offset)
46
+ end
47
+ end
48
+
49
+ # Loads a record using `#scope`
50
+ #
51
+ # @param action [ActionInquirer]
52
+ # @param params [ActionController::Parameters]
53
+ # @return [ActiveRecord::Base]
54
+ def load_record(action:, params:)
55
+ default_for(:load_record, action: action, params: params) do
56
+ scope(action: action).find(params[:id])
57
+ end
58
+ end
59
+
60
+ # Builds a record using `#scope`
61
+ #
62
+ # @param action [ActionInquirer]
63
+ # @return [ActiveRecord::Base]
64
+ def build_record(action:)
65
+ default_for(:build_record) do
66
+ scope(action: action).build
67
+ end
68
+ end
69
+
70
+ # Builds and populates a record using `#scope`
71
+ #
72
+ # @param action [ActionInquirer]
73
+ # @param params [ActionController::Parameters]
74
+ # @return [ActiveRecord::Base]
75
+ def build_record_with_params(action:, params:)
76
+ default_for(:build_record_with_params, action: action, params: params) do
77
+ scope(action: action).build(permitted_params(params, action: action))
78
+ end
79
+ end
80
+
81
+ # Saves a record
82
+ #
83
+ # @param action [ActionInquirer]
84
+ # @param params [ActionController::Parameters]
85
+ # @return [ActiveRecord::Base]
86
+ def save_record(action:, record:, params:)
87
+ default_for(:save_record, action: action, record: record, params: params) do
88
+ record.save
89
+ end
90
+ end
91
+
92
+ # Saves a record
93
+ #
94
+ # @param action [ActionInquirer]
95
+ # @param params [ActionController::Parameters]
96
+ # @return [ActiveRecord::Base]
97
+ def update_record(action:, record:, params:)
98
+ default_for(:update_record, action: action, record: record, params: params) do
99
+ record.update(permitted_params(params, action: action))
100
+ end
101
+ end
102
+
103
+ # Destroys a record
104
+ #
105
+ # @param action [ActionInquirer]
106
+ # @param params [ActionController::Parameters]
107
+ # @return [ActiveRecord::Base, false]
108
+ def destroy_record(action:, record:, params:)
109
+ default_for(:update_record, action: action, record: record, params: params) do
110
+ record.destroy
111
+ end
112
+ end
113
+ end
114
+ end
115
+ end
@@ -3,39 +3,81 @@ module Super
3
3
  # This schema type is meant to be used for +#index+ or +#show+ actions to
4
4
  # transform database fields into something that is human friendly.
5
5
  #
6
- # Note: The constants under "Defined Under Namespace" are considered
7
- # private.
6
+ # ```
7
+ # class MembersController::Controls
8
+ # # ...
8
9
  #
9
- # class MemberDashboard
10
- # # ...
11
- #
12
- # def show_schema
13
- # Super::Schema.new(Super::Display::SchemaTypes.new) do |fields, type|
14
- # fields[:name] = type.dynamic { |name| name }
15
- # fields[:rank] = type.dynamic { |rank| rank }
16
- # fields[:position] = type.dynamic { |position| position }
17
- # fields[:ship] = type.dynamic { |ship| "#{ship.name} (Ship ##{ship.id})" }
18
- # fields[:created_at] = type.dynamic { |created_at| created_at.iso8601 }
19
- # fields[:updated_at] = type.dynamic { |updated_at| updated_at.iso8601 }
20
- # end
10
+ # def show_schema
11
+ # Super::Schema.new(Super::Display::SchemaTypes.new) do |fields, type|
12
+ # fields[:name] = type.dynamic { |name| name }
13
+ # fields[:rank] = type.dynamic { |rank| rank }
14
+ # fields[:position] = type.dynamic { |position| position }
15
+ # fields[:ship] = type.dynamic { |ship| "#{ship.name} (Ship ##{ship.id})" }
16
+ # fields[:created_at] = type.dynamic { |created_at| created_at.iso8601 }
17
+ # fields[:updated_at] = type.dynamic { |updated_at| updated_at.iso8601 }
21
18
  # end
22
- #
23
- # # ...
24
19
  # end
20
+ #
21
+ # # ...
22
+ # end
23
+ # ```
25
24
  class SchemaTypes
26
25
  class Dynamic
27
26
  def initialize(transform_block)
28
27
  @transform_block = transform_block
29
28
  end
30
29
 
31
- def present(field)
32
- @transform_block.call(field)
30
+ def present(value)
31
+ @transform_block.call(value)
32
+ end
33
+
34
+ def real?
35
+ true
36
+ end
37
+ end
38
+
39
+ class Bypass
40
+ def initialize(partial:, real:)
41
+ @partial = partial
42
+ @real = real
43
+ end
44
+
45
+ def present
46
+ Partial.new(@partial)
47
+ end
48
+
49
+ def real?
50
+ @real
33
51
  end
34
52
  end
35
53
 
54
+ def initialize(action_inquirer)
55
+ @action_inquirer = action_inquirer
56
+ @actions_called = false
57
+ end
58
+
59
+ def before_yield(fields:)
60
+ @fields = fields
61
+ end
62
+
63
+ def after_yield
64
+ return if !@action_inquirer.index?
65
+ return if @actions_called
66
+ @fields[:actions] = actions
67
+ end
68
+
36
69
  def dynamic(&transform_block)
37
70
  Dynamic.new(transform_block)
38
71
  end
72
+
73
+ def actions
74
+ @actions_called = true
75
+ Bypass.new(partial: "super_schema_display_actions", real: false)
76
+ end
77
+
78
+ def to_partial_path
79
+ "super_schema_display_#{@action_inquirer.action}"
80
+ end
39
81
  end
40
82
  end
41
83
  end
@@ -1,4 +1,5 @@
1
1
  module Super
2
+ # Configures the host Rails app to work with Super
2
3
  class Engine < ::Rails::Engine
3
4
  initializer "super.assets.precompile" do |app|
4
5
  if Super::Assets.sprockets_available?
@@ -1,8 +1,17 @@
1
1
  module Super
2
+ # A container class for all internal errors thrown by this library
3
+ #
4
+ # See also `Super::ClientError`
2
5
  class Error < StandardError
6
+ # Error raised when some configuration is not set
3
7
  class UnconfiguredConfiguration < Error; end
8
+ # Error raised when a configuration is set to a invalid value
4
9
  class InvalidConfiguration < Error; end
5
- class InvalidStyle < Error; end
10
+ # Error raised on problematic plugins, see `Super::Plugin`
6
11
  class InvalidPluginArgument < Error; end
12
+ # Error raised on problematic ActionInquirer settings, see `Super::ActionInquirer`
13
+ class ActionInquirerError < Error; end
14
+ # Error raised when a `Super::Link` couldn't be found
15
+ class LinkNotRegistered < Error; end
7
16
  end
8
17
  end
@@ -0,0 +1,48 @@
1
+ module Super
2
+ class Form
3
+ module FieldErrorProc
4
+ def error_wrapping(html_tag)
5
+ if Thread.current[:super_form_builder]
6
+ return html_tag
7
+ end
8
+
9
+ super
10
+ end
11
+ end
12
+
13
+ class Builder < ActionView::Helpers::FormBuilder
14
+ # These methods were originally defined in the following files
15
+ #
16
+ # * actionview/lib/action_view/helpers/form_helper.rb
17
+ # * actionview/lib/action_view/helpers/form_options_helper.rb
18
+ # * actionview/lib/action_view/helpers/date_helper.rb
19
+ %w[
20
+ label text_field password_field hidden_field file_field text_area
21
+ check_box radio_button color_field search_field telephone_field
22
+ date_field time_field datetime_field month_field week_field url_field
23
+ email_field number_field range_field
24
+
25
+ select collection_select grouped_collection_select time_zone_select
26
+ collection_radio_buttons collection_check_boxes
27
+
28
+ time_select datetime_select date_select
29
+ ].each do |field_type_method|
30
+ class_eval(<<~RUBY, __FILE__, __LINE__ + 1)
31
+ def #{field_type_method}(*)
32
+ Thread.current[:super_form_builder] = true
33
+ super
34
+ ensure
35
+ Thread.current[:super_form_builder] = nil
36
+ end
37
+ RUBY
38
+ end
39
+
40
+ alias datetime_local_field datetime_field
41
+ alias phone_field telephone_field
42
+ end
43
+ end
44
+ end
45
+
46
+ ActionView::Helpers::Tags::Base.class_eval do
47
+ prepend Super::Form::FieldErrorProc
48
+ end