super 0.17.0 → 0.20.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (57) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +4 -4
  3. data/app/assets/javascripts/super/application.js +1260 -117
  4. data/app/assets/stylesheets/super/application.css +90711 -90034
  5. data/app/controllers/super/application_controller.rb +34 -4
  6. data/app/controllers/super/substructure_controller.rb +125 -29
  7. data/app/helpers/super/form_builder_helper.rb +4 -4
  8. data/app/views/layouts/super/application.html.erb +1 -1
  9. data/app/views/super/application/_batch_button.html.erb +12 -0
  10. data/app/views/super/application/_batch_checkbox.csv.erb +1 -0
  11. data/app/views/super/application/_batch_checkbox.html.erb +9 -0
  12. data/app/views/super/application/_batch_form.html.erb +3 -0
  13. data/app/views/super/application/_collection_header.html.erb +7 -6
  14. data/app/views/super/application/_csv_button.html.erb +25 -0
  15. data/app/views/super/application/_display_actions.html.erb +2 -2
  16. data/app/views/super/application/_form.html.erb +1 -1
  17. data/app/views/super/application/_layout.html.erb +13 -14
  18. data/app/views/super/application/_link.html.erb +8 -0
  19. data/app/views/super/application/_member_header.html.erb +7 -7
  20. data/app/views/super/application/_pagination.html.erb +2 -4
  21. data/app/views/super/application/_site_footer.html.erb +1 -1
  22. data/app/views/super/application/_site_header.html.erb +4 -4
  23. data/app/views/super/application/_view_chain.html.erb +5 -0
  24. data/app/views/super/application/index.csv.erb +14 -0
  25. data/config/locales/en.yml +15 -1
  26. data/frontend/super-frontend/dist/application.css +90711 -90034
  27. data/frontend/super-frontend/dist/application.js +6512 -5379
  28. data/frontend/super-frontend/dist/package.json +13 -0
  29. data/lib/generators/super/webpacker/USAGE +1 -7
  30. data/lib/generators/super/webpacker/templates/pack_super_application.js.tt +2 -0
  31. data/lib/generators/super/webpacker/webpacker_generator.rb +10 -6
  32. data/lib/super/action_inquirer.rb +3 -0
  33. data/lib/super/cheat.rb +1 -0
  34. data/lib/super/display/schema_types.rb +6 -0
  35. data/lib/super/display.rb +2 -1
  36. data/lib/super/engine.rb +5 -0
  37. data/lib/super/error.rb +11 -0
  38. data/lib/super/form/schema_types.rb +8 -36
  39. data/lib/super/form_builder/action_text_methods.rb +16 -0
  40. data/lib/super/form_builder/base_methods.rb +73 -0
  41. data/lib/super/form_builder/flatpickr_methods.rb +75 -0
  42. data/lib/super/form_builder/option_methods.rb +73 -0
  43. data/lib/super/form_builder.rb +143 -0
  44. data/lib/super/layout.rb +9 -33
  45. data/lib/super/link.rb +49 -70
  46. data/lib/super/link_builder.rb +24 -47
  47. data/lib/super/packaged_asset.rb +49 -0
  48. data/lib/super/pagination.rb +2 -1
  49. data/lib/super/reorderable_hash.rb +88 -0
  50. data/lib/super/reset.rb +20 -1
  51. data/lib/super/useful/i19.rb +35 -0
  52. data/lib/super/version.rb +1 -1
  53. data/lib/super/view_chain.rb +25 -0
  54. data/lib/super.rb +9 -1
  55. metadata +55 -10
  56. data/lib/generators/super/webpacker/templates/pack_super_application.js.erb.tt +0 -2
  57. data/lib/super/form/builder.rb +0 -289
data/lib/super/link.rb CHANGED
@@ -9,75 +9,43 @@ module Super
9
9
  end
10
10
 
11
11
  def self.find(link)
12
- if link.kind_of?(self)
13
- return link
14
- end
15
-
16
12
  if registry.key?(link)
17
- return registry[link]
13
+ found = registry[link]
14
+
15
+ if found.is_a?(LinkBuilder)
16
+ return found.dup
17
+ else
18
+ return found
19
+ end
18
20
  end
19
21
 
20
22
  raise Error::LinkNotRegistered, "Unknown link `#{link}`"
21
23
  end
22
24
 
23
25
  def self.registry
24
- @registry ||= {
25
- new: LinkBuilder.new(
26
- "New",
27
- -> (params:) {
28
- {
29
- controller: params[:controller],
30
- action: :new,
31
- only_path: true
32
- }
33
- }
34
- ),
35
- index: LinkBuilder.new(
36
- "Index",
37
- -> (params:) {
38
- {
39
- controller: params[:controller],
40
- action: :index,
41
- only_path: true
42
- }
43
- }
44
- ),
45
- show: LinkBuilder.new(
46
- "View",
47
- -> (record:, params:) {
48
- {
49
- controller: params[:controller],
50
- action: :show,
51
- id: record,
52
- only_path: true
53
- }
54
- }
55
- ),
56
- edit: LinkBuilder.new(
57
- "Edit",
58
- -> (record:, params:) {
59
- {
60
- controller: params[:controller],
61
- action: :edit,
62
- id: record,
63
- only_path: true
64
- }
65
- }
66
- ),
67
- destroy: LinkBuilder.new(
68
- "Delete",
69
- -> (record:, params:) {
70
- {
71
- controller: params[:controller],
72
- action: :destroy,
73
- id: record,
74
- only_path: true
75
- }
76
- },
77
- method: :delete,
78
- data: { confirm: "Really delete?" }
79
- ),
80
- }
26
+ @registry ||= {}.tap do |reg|
27
+ reg[:new] = LinkBuilder.new
28
+ .text { |params:| Super::Useful::I19.i18n_with_fallback("super", params[:controller].split("/"), "actions.new") }
29
+ .href { |params:| { controller: params[:controller], action: :new, only_path: true } }
30
+ .freeze
31
+ reg[:index] = LinkBuilder.new
32
+ .text { |params:| Super::Useful::I19.i18n_with_fallback("super", params[:controller].split("/"), "actions.index") }
33
+ .href { |params:| { controller: params[:controller], action: :index, only_path: true } }
34
+ .freeze
35
+ reg[:show] = LinkBuilder.new
36
+ .text { |params:, **| Super::Useful::I19.i18n_with_fallback("super", params[:controller].split("/"), "actions.show") }
37
+ .href { |params:, record:| { controller: params[:controller], action: :show, id: record, only_path: true } }
38
+ .freeze
39
+ reg[:edit] = LinkBuilder.new
40
+ .text { |params:, **| Super::Useful::I19.i18n_with_fallback("super", params[:controller].split("/"), "actions.edit") }
41
+ .href { |params:, record:| { controller: params[:controller], action: :edit, id: record, only_path: true } }
42
+ .freeze
43
+ reg[:destroy] = LinkBuilder.new
44
+ .text { |params:, **| Super::Useful::I19.i18n_with_fallback("super", params[:controller].split("/"), "actions.destroy") }
45
+ .href { |params:, record:| { controller: params[:controller], action: :destroy, id: record, only_path: true } }
46
+ .options { |**| { method: :delete, data: { confirm: "Really delete?" } } }
47
+ .freeze
48
+ end
81
49
  end
82
50
 
83
51
  def self.polymorphic_parts(*parts_tail)
@@ -85,15 +53,31 @@ module Super
85
53
  parts_head.map { |part| part.is_a?(String) ? part.to_sym : part } + parts_tail
86
54
  end
87
55
 
56
+ # The first argument should be the text of the link. If it's an array,
57
+ # it'll send it directly into `I18n.t`
88
58
  def initialize(text, href, **options)
89
59
  @text = text
90
60
  @href = href
91
61
  @options = options
92
62
  end
93
63
 
94
- attr_reader :text
95
64
  attr_reader :options
96
65
 
66
+ def text
67
+ if @text.is_a?(Array)
68
+ *head, tail = @text
69
+ if !tail.is_a?(Hash)
70
+ head.push(tail)
71
+ tail = {}
72
+ end
73
+
74
+ @text = I18n.t(*head, **tail)
75
+ return @text
76
+ end
77
+
78
+ @text
79
+ end
80
+
97
81
  def href
98
82
  if @href.is_a?(String)
99
83
  return @href
@@ -107,13 +91,8 @@ module Super
107
91
  @href = Super::Compatability.polymorphic_path_container.polymorphic_path(@href)
108
92
  end
109
93
 
110
- def to_s(default_options: nil, **)
111
- default_options ||= {}
112
- ActionController::Base.helpers.link_to(
113
- text,
114
- href,
115
- default_options.deep_merge(options)
116
- )
94
+ def to_partial_path
95
+ "link"
117
96
  end
118
97
 
119
98
  def ==(other)
@@ -2,57 +2,34 @@
2
2
 
3
3
  module Super
4
4
  class LinkBuilder
5
- def initialize(text, href, **options)
6
- @text = text
7
- @href = href
8
- @options = options
9
- @requirements = []
10
- @requirements += gather_requirements(text)
11
- @requirements += gather_requirements(href)
12
- @requirements += gather_requirements(options)
13
-
14
- unknown_arguments = @requirements - known_requirements
15
- if unknown_arguments.any?
16
- raise Error::ArgumentError, "Unknown arguments: #{unknown_arguments.join(", ")}"
17
- end
18
- end
19
-
20
- attr_reader :requirements
21
-
22
- def to_s(default_options: nil, **kwargs)
23
- resolve(**kwargs).to_s(default_options: default_options)
5
+ %i[text href options].each do |method_name|
6
+ class_eval(<<~RUBY, __FILE__, __LINE__ + 1)
7
+ def #{method_name}(&block)
8
+ @#{method_name} = block
9
+ self
10
+ end
11
+
12
+ def process_#{method_name}(&block)
13
+ @process_#{method_name} = block
14
+ self
15
+ end
16
+ RUBY
24
17
  end
25
18
 
26
19
  def resolve(**kwargs)
27
- Link.new(
28
- into_value(@text, kwargs),
29
- into_value(@href, kwargs),
30
- **into_value(@options, kwargs),
20
+ raise Super::Error::IncompleteBuilder, "LinkBuilder requires that #text is set" if @text.nil?
21
+ raise Super::Error::IncompleteBuilder, "LinkBuilder requires that #href is set" if @href.nil?
22
+
23
+ @options ||= -> (**) { {} }
24
+ @process_text ||= -> (t) { t }
25
+ @process_href ||= -> (h) { h }
26
+ @process_options ||= -> (o) { o }
27
+
28
+ Super::Link.new(
29
+ @process_text.call(@text.call(**kwargs)),
30
+ @process_href.call(@href.call(**kwargs)),
31
+ **@process_options.call(@options.call(**kwargs))
31
32
  )
32
33
  end
33
-
34
- private
35
-
36
- def known_requirements
37
- %i[params record].freeze
38
- end
39
-
40
- def gather_requirements(value_or_proc)
41
- return [] if !value_or_proc.is_a?(Proc)
42
-
43
- requirements =
44
- value_or_proc
45
- .parameters
46
- .select { |(kind, name)| kind = :keyreq }
47
- .map(&:last)
48
- end
49
-
50
- def into_value(value_or_proc, kwargs)
51
- if value_or_proc.kind_of?(Proc)
52
- value_or_proc.call(**kwargs)
53
- else
54
- value_or_proc
55
- end
56
- end
57
34
  end
58
35
  end
@@ -0,0 +1,49 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Super
4
+ class PackagedAsset
5
+ VERSION_BEGINNING = /\A\d+\.\d+.\d+/.freeze
6
+
7
+ class << self
8
+ attr_accessor :warning_message
9
+ end
10
+
11
+ def self.comparable_super_version
12
+ ::Super::VERSION[VERSION_BEGINNING]
13
+ end
14
+
15
+ def self.version_matches_gem?(package_json_path)
16
+ return true if ENV.key?("SUPER_IGNORE_PACKAGE_JSON_VERSION")
17
+
18
+ asset = new(package_json_path)
19
+
20
+ return true if !asset.comparable_version
21
+
22
+ asset.comparable_version == comparable_super_version
23
+ end
24
+
25
+ def initialize(package_json_path)
26
+ @package_json_path = package_json_path
27
+ end
28
+
29
+ def full_version
30
+ if instance_variable_defined?(:@full_version)
31
+ return @full_version
32
+ end
33
+
34
+ @full_version = JSON.parse(@package_json_path.read).dig("dependencies", "@superadministration/super")
35
+ rescue
36
+ @full_version = nil
37
+ end
38
+
39
+ def comparable_version
40
+ if instance_variable_defined?(:@asset_version)
41
+ return @asset_version
42
+ end
43
+
44
+ @asset_version = full_version[VERSION_BEGINNING]
45
+ rescue
46
+ @asset_version = nil
47
+ end
48
+ end
49
+ end
@@ -76,9 +76,10 @@ module Super
76
76
  module ControllerMethods
77
77
  def index
78
78
  super
79
+ return if !@records
79
80
  @pagination = initialize_pagination
80
81
  @records = paginate_records
81
- @view.mains.first.parts.push(:@pagination)
82
+ @view.main.insert(:pagination, @pagination, before: :main)
82
83
  end
83
84
  end
84
85
  end
@@ -0,0 +1,88 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Super
4
+ class ReorderableHash
5
+ include TSort
6
+ include Enumerable
7
+
8
+ UNDEFINED = BasicObject.new
9
+
10
+ def initialize(data = {})
11
+ @data = data
12
+ @ordering = {}
13
+ keys = @data.keys
14
+ dependencies = []
15
+ keys.each do |key|
16
+ @ordering[key] = dependencies.dup
17
+ dependencies.push(key)
18
+ end
19
+ end
20
+
21
+ def insert(key, value, before: UNDEFINED, after: UNDEFINED)
22
+ if @ordering.key?(key) || @data.key?(key)
23
+ raise Super::Error::ReorderableHash::DuplicateKey, "Duplicate key: #{key}"
24
+ end
25
+ @ordering[key] = []
26
+ @data[key] = value
27
+
28
+ order(key, before: before, after: after)
29
+
30
+ nil
31
+ end
32
+
33
+ def order(key, before: UNDEFINED, after: UNDEFINED)
34
+ if before != UNDEFINED
35
+ if !@ordering.key?(before)
36
+ raise KeyError, "Before key not found. Have: #{@data.keys} Requested: #{before}"
37
+ end
38
+ @ordering[before].push(key)
39
+ end
40
+
41
+ if after != UNDEFINED
42
+ if !@ordering.key?(after)
43
+ raise KeyError, "After key not found. Have: #{@data.keys} Requested: #{after}"
44
+ end
45
+ @ordering[key].push(after)
46
+ end
47
+ end
48
+
49
+ def tsort_each_node(&block)
50
+ @ordering.each_key(&block)
51
+ end
52
+
53
+ def tsort_each_child(node, &block)
54
+ dependencies = @ordering.fetch(node) { [] }
55
+ dependencies.each(&block)
56
+ end
57
+
58
+ def []=(key, where, value)
59
+ insert(key, value, **where)
60
+ end
61
+
62
+ def keys
63
+ tsort
64
+ end
65
+
66
+ def values
67
+ keys.each_with_object([]) do |key, array|
68
+ array.push(@data[key])
69
+ end
70
+ end
71
+
72
+ def to_h
73
+ keys.each_with_object({}) do |key, hash|
74
+ hash[key] = @data[key]
75
+ end
76
+ end
77
+
78
+ def each
79
+ if !block_given?
80
+ return enum_for(:each)
81
+ end
82
+
83
+ tsort_each do |key|
84
+ yield key, @data[key]
85
+ end
86
+ end
87
+ end
88
+ end
data/lib/super/reset.rb CHANGED
@@ -4,6 +4,20 @@ module Super
4
4
  module Reset
5
5
  extend ActiveSupport::Concern
6
6
 
7
+ KEEP = {
8
+ # Defined by Rails
9
+ _layout: true,
10
+ _generate_paths_by_default: true,
11
+
12
+ # Defined in Super::SubstructureController
13
+ navigation: true,
14
+ page_title: true,
15
+
16
+ # Defined in Super::ApplicationController
17
+ current_action: true,
18
+ with_current_action: true,
19
+ }
20
+
7
21
  included do
8
22
  undef_method :index
9
23
  undef_method :show
@@ -14,7 +28,12 @@ module Super
14
28
  undef_method :destroy
15
29
 
16
30
  Super::SubstructureController.private_instance_methods(false).each do |imethod|
17
- next if imethod == :navigation
31
+ next if KEEP.key?(imethod)
32
+ undef_method imethod
33
+ end
34
+
35
+ Super::ApplicationController.private_instance_methods(false).each do |imethod|
36
+ next if KEEP.key?(imethod)
18
37
  undef_method imethod
19
38
  end
20
39
  end
@@ -0,0 +1,35 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Super
4
+ module Useful
5
+ module I19
6
+ module_function
7
+
8
+ def build_chain(prefix, optional, suffix)
9
+ prefix = Array(prefix)
10
+ optional = Array(optional)
11
+ suffix = Array(suffix)
12
+
13
+ result = []
14
+
15
+ (optional.size + 1).times do
16
+ lookup = [prefix, optional, suffix].flatten.join(".").to_sym
17
+ result.push(lookup)
18
+ optional.pop
19
+ end
20
+
21
+ result
22
+ end
23
+
24
+ def chain_to_i18n(chain)
25
+ head, *tail = chain
26
+
27
+ [head, { default: tail }]
28
+ end
29
+
30
+ def i18n_with_fallback(prefix, optional, suffix)
31
+ chain_to_i18n(build_chain(prefix, optional, suffix))
32
+ end
33
+ end
34
+ end
35
+ end
data/lib/super/version.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Super
4
- VERSION = "0.17.0"
4
+ VERSION = "0.20.0"
5
5
  end
@@ -0,0 +1,25 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Super
4
+ class ViewChain
5
+ def initialize(chain)
6
+ @data = ReorderableHash.new(chain)
7
+ end
8
+
9
+ def chain
10
+ @chain ||= @data.values
11
+ end
12
+
13
+ def insert(*args, **kwargs)
14
+ if instance_variable_defined?(:@chain)
15
+ raise Error::ViewChain::ChainAlreadyStarted
16
+ end
17
+
18
+ @data.insert(*args, **kwargs)
19
+ end
20
+
21
+ def to_partial_path
22
+ "view_chain"
23
+ end
24
+ end
25
+ end
data/lib/super.rb CHANGED
@@ -7,6 +7,7 @@ require "rails/engine"
7
7
  require "super/schema/common"
8
8
  require "super/useful/builder"
9
9
  require "super/useful/enum"
10
+ require "super/useful/i19"
10
11
 
11
12
  require "super/action_inquirer"
12
13
  require "super/assets"
@@ -24,26 +25,33 @@ require "super/filter/guesser"
24
25
  require "super/filter/operator"
25
26
  require "super/filter/schema_types"
26
27
  require "super/form"
27
- require "super/form/builder"
28
28
  require "super/form/field_transcript"
29
29
  require "super/form/guesser"
30
30
  require "super/form/inline_errors"
31
31
  require "super/form/schema_types"
32
32
  require "super/form/strong_params"
33
+ require "super/form_builder"
34
+ require "super/form_builder/action_text_methods"
35
+ require "super/form_builder/base_methods"
36
+ require "super/form_builder/flatpickr_methods"
37
+ require "super/form_builder/option_methods"
33
38
  require "super/layout"
34
39
  require "super/link"
35
40
  require "super/link_builder"
36
41
  require "super/navigation"
42
+ require "super/packaged_asset"
37
43
  require "super/pagination"
38
44
  require "super/panel"
39
45
  require "super/partial"
40
46
  require "super/plugin"
41
47
  require "super/query/form_object"
48
+ require "super/reorderable_hash"
42
49
  require "super/reset"
43
50
  require "super/schema"
44
51
  require "super/schema/guesser"
45
52
  require "super/sort"
46
53
  require "super/version"
54
+ require "super/view_chain"
47
55
  require "super/view_helper"
48
56
 
49
57
  require "super/engine"