super 0.0.5 → 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 (60) hide show
  1. checksums.yaml +4 -4
  2. data/.yardopts +2 -1
  3. data/README.md +55 -23
  4. data/app/assets/javascripts/super/application.js +1062 -261
  5. data/app/assets/stylesheets/super/application.css +72775 -50711
  6. data/app/controllers/super/application_controller.rb +39 -50
  7. data/app/helpers/super/application_helper.rb +24 -17
  8. data/app/views/layouts/super/application.html.erb +4 -0
  9. data/app/views/super/application/{_resources_header.html.erb → _collection_header.html.erb} +5 -6
  10. data/app/views/super/application/_flash.html.erb +13 -13
  11. data/app/views/super/application/_form_field_select.html.erb +1 -1
  12. data/app/views/super/application/_form_has_many.html.erb +1 -1
  13. data/app/views/super/application/{_resource_header.html.erb → _member_header.html.erb} +6 -6
  14. data/app/views/super/application/_super_layout.html.erb +7 -12
  15. data/app/views/super/application/_super_panel.html.erb +2 -6
  16. data/app/views/super/application/_super_schema_display_actions.html.erb +5 -0
  17. data/app/views/super/application/_super_schema_display_index.html.erb +39 -0
  18. data/app/views/super/application/_super_schema_display_show.html.erb +8 -0
  19. data/app/views/super/application/{_form.html.erb → _super_schema_form.html.erb} +2 -4
  20. data/app/views/super/application/edit.html.erb +2 -2
  21. data/app/views/super/application/index.html.erb +2 -2
  22. data/app/views/super/application/new.html.erb +2 -2
  23. data/app/views/super/application/show.html.erb +2 -2
  24. data/app/views/super/feather/{_chevron_down.svg → _chevron_down.html} +0 -0
  25. data/config/locales/en.yml +5 -0
  26. data/docs/cheat.md +41 -0
  27. data/docs/webpacker.md +1 -1
  28. data/frontend/super-frontend/dist/application.css +72775 -50711
  29. data/frontend/super-frontend/dist/application.js +1062 -261
  30. data/frontend/super-frontend/package.json +1 -1
  31. data/frontend/super-frontend/src/javascripts/super/apply_template_controller.ts +6 -8
  32. data/frontend/super-frontend/tailwind.config.js +7 -1
  33. data/frontend/super-frontend/yarn.lock +1103 -1195
  34. data/lib/generators/super/install/install_generator.rb +16 -0
  35. data/lib/super.rb +2 -2
  36. data/lib/super/action_inquirer.rb +2 -2
  37. data/lib/super/client_error.rb +43 -0
  38. data/lib/super/configuration.rb +1 -1
  39. data/lib/super/controls.rb +17 -101
  40. data/lib/super/controls/optional.rb +65 -0
  41. data/lib/super/controls/required.rb +41 -0
  42. data/lib/super/controls/steps.rb +115 -0
  43. data/lib/super/display/schema_types.rb +45 -2
  44. data/lib/super/error.rb +8 -9
  45. data/lib/super/form.rb +48 -0
  46. data/lib/super/form/schema_types.rb +8 -1
  47. data/lib/super/layout.rb +28 -0
  48. data/lib/super/link.rb +55 -32
  49. data/lib/super/panel.rb +13 -0
  50. data/lib/super/partial/resolving.rb +24 -0
  51. data/lib/super/schema.rb +19 -5
  52. data/lib/super/version.rb +1 -1
  53. data/lib/super/view_helper.rb +1 -1
  54. metadata +40 -15
  55. data/app/views/super/application/_index.html.erb +0 -45
  56. data/app/views/super/application/_show.html.erb +0 -10
  57. data/docs/controls.md +0 -39
  58. data/lib/super/display.rb +0 -9
  59. data/lib/super/step.rb +0 -36
  60. data/lib/tasks/super_tasks.rake +0 -4
@@ -1,82 +1,75 @@
1
1
  module Super
2
2
  # Provides a default implementation for each of the resourceful actions
3
3
  class ApplicationController < ActionController::Base
4
+ include ClientError::Handling
4
5
  include Pluggable.new(:super_application_controller)
5
6
 
6
7
  helper_method :action_inquirer
7
8
  helper_method :controls
8
9
 
9
- rescue_from Error::ClientError do |exception|
10
- code, default_message =
11
- case exception
12
- when Error::UnprocessableEntity
13
- [422, "Unprocessable entity"]
14
- when Error::NotFound
15
- [404, "Not found"]
16
- when Error::Forbidden
17
- [403, "Forbidden"]
18
- when Error::Unauthorized
19
- [401, "Unauthorized"]
20
- when Error::BadRequest, Error::ClientError
21
- [400, "Bad request"]
22
- end
23
-
24
- flash.now.alert =
25
- if exception.message == exception.class.name.to_s
26
- default_message
27
- else
28
- exception.message
29
- end
30
-
31
- render "nothing", status: code
32
- end
33
-
10
+ # Displays a list of records to the user
34
11
  def index
35
- @resources = Step.load_resources(controls, params, action_inquirer)
36
- @pagination = Step.initialize_pagination(@resources, request.GET)
37
- @resources = Step.paginate_resources(@resources, @pagination)
12
+ @records = controls.load_records(action: action_inquirer, params: params)
13
+ @pagination = controls.initialize_pagination(action: action_inquirer, records: @records, query_params: request.GET)
14
+ @records = controls.paginate_records(action: action_inquirer, records: @records, pagination: @pagination)
15
+ @display = controls.display_schema(action: action_inquirer)
38
16
  end
39
17
 
18
+ # Displays a specific record to the user
40
19
  def show
41
- @resource = Step.load_resource(controls, params, action_inquirer)
20
+ @record = controls.load_record(action: action_inquirer, params: params)
21
+ @display = controls.display_schema(action: action_inquirer)
42
22
  end
43
23
 
24
+ # Displays a form to allow the user to create a new record
44
25
  def new
45
- @resource = Step.build_resource(controls, action_inquirer)
26
+ @record = controls.build_record(action: action_inquirer)
27
+ @form = controls.form_schema(action: action_inquirer)
46
28
  end
47
29
 
30
+ # Creates a record, or shows the validation errors
48
31
  def create
49
- @resource = Step.build_resource_with_params(controls, action_inquirer, create_permitted_params)
32
+ @record = controls.build_record_with_params(action: action_inquirer, params: params)
50
33
 
51
- if @resource.save
52
- redirect_to polymorphic_path(Super.configuration.path_parts(@resource))
34
+ if controls.save_record(action: action_inquirer, record: @record, params: params)
35
+ redirect_to polymorphic_path(Super.configuration.path_parts(@record))
53
36
  else
37
+ @form = controls.form_schema(action: action_inquirer_for("new"))
54
38
  render :new, status: :bad_request
55
39
  end
56
40
  end
57
41
 
42
+ # Displays a form to allow the user to update an existing record
58
43
  def edit
59
- @resource = Step.load_resource(controls, params, action_inquirer)
44
+ @record = controls.load_record(action: action_inquirer, params: params)
45
+ @form = controls.form_schema(action: action_inquirer)
60
46
  end
61
47
 
48
+ # Updates a record, or shows validation errors
62
49
  def update
63
- @resource = Step.load_resource(controls, params, action_inquirer)
50
+ @record = controls.load_record(action: action_inquirer, params: params)
64
51
 
65
- if @resource.update(update_permitted_params)
66
- redirect_to polymorphic_path(Super.configuration.path_parts(@resource))
52
+ if controls.update_record(action: action_inquirer, record: @record, params: params)
53
+ redirect_to polymorphic_path(Super.configuration.path_parts(@record))
67
54
  else
55
+ @form = controls.form_schema(action: action_inquirer_for("edit"))
68
56
  render :edit, status: :bad_request
69
57
  end
70
58
  end
71
59
 
60
+ # Deletes a record, or shows validation errors
72
61
  def destroy
73
- @resource = Step.load_resource(controls, params, action_inquirer)
62
+ @record = controls.load_record(action: action_inquirer, params: params)
74
63
 
75
- if @resource.destroy
64
+ if controls.destroy_record(action: action_inquirer, record: @record, params: params)
76
65
  redirect_to polymorphic_path(Super.configuration.path_parts(controls.model))
77
66
  else
78
- redirect_to polymorphic_path(Super.configuration.path_parts(@resource))
67
+ flash.alert = "Couldn't delete record"
68
+ redirect_to polymorphic_path(Super.configuration.path_parts(@record))
79
69
  end
70
+ rescue ActiveRecord::InvalidForeignKey => e
71
+ flash.alert = "Couldn't delete record: #{e.class}"
72
+ redirect_to polymorphic_path(Super.configuration.path_parts(@record))
80
73
  end
81
74
 
82
75
  private
@@ -85,18 +78,14 @@ module Super
85
78
  Super::Controls.new(new_controls)
86
79
  end
87
80
 
88
- def create_permitted_params
89
- controls.permitted_params(params, action: action_inquirer)
90
- end
91
-
92
- def update_permitted_params
93
- controls.permitted_params(params, action: action_inquirer)
81
+ def action_inquirer
82
+ @action_inquirer ||= action_inquirer_for(params[:action])
94
83
  end
95
84
 
96
- def action_inquirer
97
- @action_inquirer ||= ActionInquirer.new(
98
- ActionInquirer.default_resources,
99
- params[:action]
85
+ def action_inquirer_for(action)
86
+ ActionInquirer.new(
87
+ ActionInquirer.default_for_resources,
88
+ action
100
89
  )
101
90
  end
102
91
  end
@@ -1,22 +1,6 @@
1
1
  module Super
2
+ # View helpers, available within views
2
3
  module ApplicationHelper
3
- def super_resolve_list_for_rendering(partials, block = -> {})
4
- block_result = block.call
5
- if block_result.present?
6
- partials = [block_result, *partials]
7
- end
8
-
9
- partials = partials.map do |partial|
10
- if partial.is_a?(Symbol)
11
- instance_variable_get(partial)
12
- else
13
- partial
14
- end
15
- end
16
-
17
- partials.compact
18
- end
19
-
20
4
  def super_render_partialish(partialish)
21
5
  if partialish.respond_to?(:to_partial_path)
22
6
  if partialish.is_a?(Super::Partial)
@@ -28,5 +12,28 @@ module Super
28
12
  partialish
29
13
  end
30
14
  end
15
+
16
+ def super_format_for_display(schema, record, column)
17
+ formatter = schema.fields[column]
18
+
19
+ formatted =
20
+ if formatter.real?
21
+ value = record.public_send(column)
22
+ formatter.present(value)
23
+ else
24
+ formatter.present
25
+ end
26
+
27
+ if formatted.respond_to?(:to_partial_path)
28
+ if formatted.respond_to?(:locals)
29
+ formatted.locals[:record] ||= record
30
+ render(formatted, formatted.locals)
31
+ else
32
+ render(formatted)
33
+ end
34
+ else
35
+ formatted
36
+ end
37
+ end
31
38
  end
32
39
  end
@@ -34,6 +34,10 @@
34
34
  <div class="pt-4"></div>
35
35
 
36
36
  <%= yield %>
37
+
38
+ <div class="pt-8 text-sm text-gray-800">
39
+ <%= t("super.layout.powered_by", env: Rails.env.capitalize, version: Super::VERSION) %>
40
+ </div>
37
41
  </div>
38
42
  </body>
39
43
  </html>
@@ -3,13 +3,12 @@
3
3
  <%= controls.title %>
4
4
  </h1>
5
5
  <div>
6
- <% controls.resources_actions(params: params, action: action_inquirer).each do |link| %>
7
- <%= link_to(
8
- link.text,
9
- link.href,
10
- link.options.reverse_merge(
6
+ <% controls.collection_actions(action: action_inquirer).each do |link| %>
7
+ <%= link.to_s(
8
+ default_options: {
11
9
  class: "super-button super-button--border-blue super-button-sm inline-block ml-2"
12
- )
10
+ },
11
+ params: params
13
12
  ) %>
14
13
  <% end %>
15
14
  </div>
@@ -1,17 +1,17 @@
1
- <%
2
- colors = {
1
+ <% if flash.any? %>
2
+ <% colors = {
3
3
  "notice" => { bg: "bg-blue-100", fg: "text-blue-400", border: "border-blue-600" },
4
4
  "alert" => { bg: "bg-red-100", fg: "text-red-400", border: "border-red-600" },
5
- }
6
- %>
5
+ } %>
7
6
 
8
- <div data-flash="anchor">
9
- <% flash.each do |level, messages| %>
10
- <% Array(messages).each do |message| %>
11
- <% color = colors[level.to_s] || colors["notice"] %>
12
- <div class="<%= "%<bg>s %<fg>s border-l-4 %<border>s p-4 mt-2" % color %>">
13
- <%= message %>
14
- </div>
7
+ <div class="mt-8">
8
+ <% flash.each do |level, messages| %>
9
+ <% Array(messages).each do |message| %>
10
+ <% color = colors[level.to_s] || colors["notice"] %>
11
+ <div class="<%= "%<bg>s %<fg>s border-l-4 %<border>s p-4 mt-2" % color %>">
12
+ <%= message %>
13
+ </div>
14
+ <% end %>
15
15
  <% end %>
16
- <% end %>
17
- </div>
16
+ </div>
17
+ <% end %>
@@ -13,7 +13,7 @@
13
13
  ) %>
14
14
  <div class="super-input-select-icon text-gray-700">
15
15
  <span class="h-4 w-4">
16
- <%= render "super/feather/chevron_down.svg" %>
16
+ <%= render "super/feather/chevron_down" %>
17
17
  </span>
18
18
  </div>
19
19
  </div>
@@ -10,7 +10,7 @@
10
10
  child_index: "TEMPLATEINDEX"
11
11
  ) do |ff|
12
12
  %>
13
- <template data-target="apply-template.template">
13
+ <template data-apply-template-target="template">
14
14
  <%= render "form_fieldset", form_fieldset: form_has_many, form: ff %>
15
15
  </template>
16
16
  <% end %>
@@ -3,13 +3,13 @@
3
3
  <%= controls.title %>
4
4
  </h1>
5
5
  <div>
6
- <% controls.resource_actions(@resource, params: params, action: action_inquirer).each do |link| %>
7
- <%= link_to(
8
- link.text,
9
- link.href,
10
- link.options.reverse_merge(
6
+ <% controls.member_actions(action: action_inquirer).each do |link| %>
7
+ <%= link.to_s(
8
+ default_options: {
11
9
  class: "super-button super-button--border-blue super-button-sm inline-block ml-2"
12
- )
10
+ },
11
+ record: @record,
12
+ params: params
13
13
  ) %>
14
14
  <% end %>
15
15
  </div>
@@ -1,34 +1,29 @@
1
- <%
2
- super_layout_headers = super_resolve_list_for_rendering(super_layout.headers)
3
- super_layout_asides = super_resolve_list_for_rendering(super_layout.asides)
4
- super_layout_mains = super_resolve_list_for_rendering(super_layout.mains)
5
- super_layout_footers = super_resolve_list_for_rendering(super_layout.footers)
6
- %>
1
+ <% super_layout.resolve(self) %>
7
2
 
8
- <% super_layout_headers.each do |partial| %>
3
+ <% super_layout.resolved_headers.each do |partial| %>
9
4
  <%= super_render_partialish(partial) %>
10
5
  <% end %>
11
6
 
12
- <% if super_layout_asides.empty? %>
13
- <% super_layout_mains.each do |partial| %>
7
+ <% if super_layout.resolved_asides.empty? %>
8
+ <% super_layout.resolved_mains.each do |partial| %>
14
9
  <%= super_render_partialish(partial) %>
15
10
  <% end %>
16
11
  <% else %>
17
12
  <div class="clearfix -mx-2">
18
13
  <div class="md:float-left md:w-9/12 px-2">
19
- <% super_layout_mains.each do |partial| %>
14
+ <% super_layout.resolved_mains.each do |partial| %>
20
15
  <%= super_render_partialish(partial) %>
21
16
  <% end %>
22
17
  </div>
23
18
 
24
19
  <div class="md:float-right md:w-3/12 px-2">
25
- <% super_layout_asides.each do |partial| %>
20
+ <% super_layout.resolved_asides.each do |partial| %>
26
21
  <%= super_render_partialish(partial) %>
27
22
  <% end %>
28
23
  </div>
29
24
  </div>
30
25
  <% end %>
31
26
 
32
- <% super_layout_footers.each do |partial| %>
27
+ <% super_layout.resolved_footers.each do |partial| %>
33
28
  <%= super_render_partialish(partial) %>
34
29
  <% end %>
@@ -1,10 +1,6 @@
1
- <%
2
- super_panel_parts = super_resolve_list_for_rendering(super_panel.parts, Proc.new)
3
- %>
4
-
5
- <% if super_panel_parts.any? %>
1
+ <% if super_panel.resolve(self, block_given? ? Proc.new : nil).resolved_parts.any? %>
6
2
  <div class="border rounded shadow border-gray-400 bg-white px-5 pt-4 pb-8 mt-6">
7
- <% super_panel_parts.each do |partial| %>
3
+ <% super_panel.resolved_parts.each do |partial| %>
8
4
  <%= super_render_partialish(partial) %>
9
5
  <% end %>
10
6
  </div>
@@ -0,0 +1,5 @@
1
+ <div>
2
+ <% controls.member_actions(action: action_inquirer).each do |link| %>
3
+ <span class="pr-2 last:pr-0"><%= link.to_s(record: record, params: params) %></span>
4
+ <% end %>
5
+ </div>
@@ -0,0 +1,39 @@
1
+ <div class="mt-4 overflow-x-auto">
2
+ <table class="w-full border-separate" cellspacing="0" cellpadding="0">
3
+ <thead>
4
+ <tr class="">
5
+ <% super_schema_display_index.field_keys.each do |column| %>
6
+ <th class="p-2 first:pl-6 border-b border-b-2 border-gray-400 text-gray-600 text-left text-sm font-normal"><%= column.to_s.humanize %></th>
7
+ <% end %>
8
+ </tr>
9
+ </thead>
10
+ <tbody class="">
11
+ <% @records.each.with_index do |record, row_index| %>
12
+ <tr id="record-pk-<%= record.id %>" class="group">
13
+ <% super_schema_display_index.field_keys.each do |column| %>
14
+ <td class="py-1 px-2 first:pl-5 border-transparent border-t border-b group-hover:bg-blue-200 first:border-l first:rounded-l-lg last:border-r last:rounded-r-lg <%= Super::ViewHelper.classes(["bg-gray-100", row_index.odd?]) %>">
15
+ <%= super_format_for_display(super_schema_display_index, record, column) %>
16
+ </td>
17
+ <% end %>
18
+ </tr>
19
+ <% end %>
20
+ </tbody>
21
+ </table>
22
+ </div>
23
+
24
+ <% if @pagination.necessary? %>
25
+ <div class="flex justify-end mr-2">
26
+ <div class="mt-4">
27
+ <% @pagination.each do |page_query_params, is_current_page, display| %>
28
+ <%= link_to(
29
+ display,
30
+ polymorphic_path(
31
+ Super.configuration.path_parts(controls.model),
32
+ page_query_params
33
+ ),
34
+ class: "inline-block ml-2 text-lg #{is_current_page ? " text-gray-900" : ""}"
35
+ ) %>
36
+ <% end %>
37
+ </div>
38
+ </div>
39
+ <% end %>
@@ -0,0 +1,8 @@
1
+ <table class="max-w-full leading-loose mt-4">
2
+ <% super_schema_display_show.field_keys.each do |column| %>
3
+ <tr>
4
+ <th class="text-right px-4"><%= column.to_s.humanize %></th>
5
+ <td><%= super_format_for_display(super_schema_display_show, @record, column) %></td>
6
+ </tr>
7
+ <% end %>
8
+ </table>
@@ -1,8 +1,6 @@
1
- <% schema = controls.form_schema(action: action_inquirer) %>
2
-
3
- <%= form_for(Super.configuration.path_parts(@resource)) do |f| %>
1
+ <%= form_for(Super.configuration.path_parts(@record), builder: Super::Form::Builder) do |f| %>
4
2
  <div class="max-w-3xl">
5
- <% schema.fields.each do |field, type| %>
3
+ <% super_schema_form.fields.each do |field, type| %>
6
4
  <%= render(
7
5
  type,
8
6
  form: f,
@@ -1,6 +1,6 @@
1
1
  <%= render(
2
2
  Super::Panel.new(
3
- Super::Partial.new("resource_header"),
4
- Super::Partial.new("form")
3
+ Super::Partial.new("member_header"),
4
+ @form
5
5
  )
6
6
  ) %>
@@ -1,6 +1,6 @@
1
1
  <%= render(
2
2
  Super::Panel.new(
3
- Super::Partial.new("resources_header"),
4
- Super::Partial.new("index")
3
+ Super::Partial.new("collection_header"),
4
+ @display
5
5
  )
6
6
  ) %>
@@ -1,6 +1,6 @@
1
1
  <%= render(
2
2
  Super::Panel.new(
3
- Super::Partial.new("resources_header"),
4
- Super::Partial.new("form")
3
+ Super::Partial.new("collection_header"),
4
+ @form
5
5
  )
6
6
  ) %>