super 0.0.5 → 0.0.6

Sign up to get free protection for your applications and to get access to all the features.
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
  ) %>