compony 0.7.0 → 0.8.0
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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +39 -0
- data/Gemfile.lock +1 -1
- data/README.md +49 -1591
- data/VERSION +1 -1
- data/compony.gemspec +4 -4
- data/doc/ComponentGenerator.html +1 -1
- data/doc/Components.html +1 -1
- data/doc/ComponentsGenerator.html +1 -1
- data/doc/Compony/Component.html +193 -457
- data/doc/Compony/ComponentMixins/Default/Labelling.html +1 -1
- data/doc/Compony/ComponentMixins/Default/Standalone/ResourcefulVerbDsl.html +1 -1
- data/doc/Compony/ComponentMixins/Default/Standalone/StandaloneDsl.html +3 -3
- data/doc/Compony/ComponentMixins/Default/Standalone/VerbDsl.html +1 -1
- data/doc/Compony/ComponentMixins/Default/Standalone.html +187 -1
- data/doc/Compony/ComponentMixins/Default.html +1 -1
- data/doc/Compony/ComponentMixins/Resourceful.html +2 -2
- data/doc/Compony/ComponentMixins.html +1 -1
- data/doc/Compony/Components/Button.html +2 -2
- data/doc/Compony/Components/Buttons/CssButton.html +282 -0
- data/doc/Compony/Components/Buttons/Link.html +252 -0
- data/doc/Compony/Components/Buttons.html +126 -0
- data/doc/Compony/Components/Destroy.html +11 -11
- data/doc/Compony/Components/Edit.html +14 -14
- data/doc/Compony/Components/Form.html +100 -100
- data/doc/Compony/Components/Index.html +2 -2
- data/doc/Compony/Components/List.html +3 -3
- data/doc/Compony/Components/New.html +2 -2
- data/doc/Compony/Components/Show.html +24 -24
- data/doc/Compony/Components/WithForm.html +3 -3
- data/doc/Compony/Components.html +5 -3
- data/doc/Compony/ControllerMixin.html +2 -2
- data/doc/Compony/Engine.html +1 -1
- data/doc/Compony/ExposedIntentsDsl.html +403 -0
- data/doc/Compony/Intent.html +1503 -0
- data/doc/Compony/MethodAccessibleHash.html +1 -1
- data/doc/Compony/ModelFields/Anchormodel.html +1 -1
- data/doc/Compony/ModelFields/Association.html +2 -2
- data/doc/Compony/ModelFields/Attachment.html +1 -1
- data/doc/Compony/ModelFields/Base.html +1 -1
- data/doc/Compony/ModelFields/Boolean.html +1 -1
- data/doc/Compony/ModelFields/Color.html +1 -1
- data/doc/Compony/ModelFields/Currency.html +1 -1
- data/doc/Compony/ModelFields/Date.html +1 -1
- data/doc/Compony/ModelFields/Datetime.html +1 -1
- data/doc/Compony/ModelFields/Decimal.html +1 -1
- data/doc/Compony/ModelFields/Email.html +1 -1
- data/doc/Compony/ModelFields/Float.html +1 -1
- data/doc/Compony/ModelFields/Integer.html +1 -1
- data/doc/Compony/ModelFields/Percentage.html +1 -1
- data/doc/Compony/ModelFields/Phone.html +1 -1
- data/doc/Compony/ModelFields/RichText.html +1 -1
- data/doc/Compony/ModelFields/String.html +1 -1
- data/doc/Compony/ModelFields/Text.html +1 -1
- data/doc/Compony/ModelFields/Time.html +1 -1
- data/doc/Compony/ModelFields/Url.html +1 -1
- data/doc/Compony/ModelFields.html +1 -1
- data/doc/Compony/ModelMixin.html +6 -1
- data/doc/Compony/NaturalOrdering.html +1 -1
- data/doc/Compony/RequestContext.html +177 -14
- data/doc/Compony/Version.html +1 -1
- data/doc/Compony/ViewHelpers.html +15 -272
- data/doc/Compony/VirtualModel.html +152 -0
- data/doc/Compony.html +303 -837
- data/doc/ComponyController.html +1 -1
- data/doc/_index.html +37 -2
- data/doc/class_list.html +1 -1
- data/doc/file.README.html +49 -1635
- data/doc/guide/basic_component.md +263 -0
- data/doc/guide/example.md +228 -0
- data/doc/guide/feasibility.md +40 -0
- data/doc/guide/generators.md +15 -0
- data/doc/guide/inheritance.md +64 -0
- data/doc/guide/installation.md +47 -0
- data/doc/guide/intents.md +167 -0
- data/doc/guide/internal_datastructures.md +47 -0
- data/doc/guide/model_fields.md +64 -0
- data/doc/guide/nesting.md +134 -0
- data/doc/guide/ownership.md +23 -0
- data/doc/guide/pre_built_components/destroy.md +25 -0
- data/doc/guide/pre_built_components/edit.md +27 -0
- data/doc/guide/pre_built_components/form.md +117 -0
- data/doc/guide/pre_built_components/index.md +6 -0
- data/doc/guide/pre_built_components/list.md +14 -0
- data/doc/guide/pre_built_components/new.md +27 -0
- data/doc/guide/pre_built_components/show.md +8 -0
- data/doc/guide/pre_built_components/with_form.md +18 -0
- data/doc/guide/pre_built_components.md +20 -0
- data/doc/guide/resourceful.md +103 -0
- data/doc/guide/standalone.md +144 -0
- data/doc/guide/virtual_models.md +31 -0
- data/doc/index.html +49 -1635
- data/doc/method_list.html +273 -161
- data/doc/top-level-namespace.html +1 -1
- data/lib/compony/component.rb +19 -48
- data/lib/compony/component_mixins/default/standalone/standalone_dsl.rb +2 -2
- data/lib/compony/component_mixins/default/standalone.rb +16 -0
- data/lib/compony/component_mixins/resourceful.rb +1 -1
- data/lib/compony/components/buttons/css_button.rb +32 -0
- data/lib/compony/components/buttons/link.rb +31 -0
- data/lib/compony/components/destroy.rb +9 -8
- data/lib/compony/components/edit.rb +5 -4
- data/lib/compony/components/form.rb +7 -1
- data/lib/compony/components/index.rb +2 -2
- data/lib/compony/components/list.rb +4 -4
- data/lib/compony/components/new.rb +1 -1
- data/lib/compony/components/show.rb +8 -11
- data/lib/compony/components/with_form.rb +1 -1
- data/lib/compony/exposed_intents_dsl.rb +29 -0
- data/lib/compony/intent.rb +145 -0
- data/lib/compony/model_fields/association.rb +1 -1
- data/lib/compony/request_context.rb +21 -0
- data/lib/compony/view_helpers.rb +5 -48
- data/lib/compony/virtual_model.rb +10 -0
- data/lib/compony.rb +67 -149
- metadata +36 -3
- data/lib/compony/components/button.rb +0 -61
data/lib/compony/view_helpers.rb
CHANGED
|
@@ -4,55 +4,12 @@ module Compony
|
|
|
4
4
|
# Rule of thumb: this holds methods that require a view context and results are rendered immediately.
|
|
5
5
|
# @see Compony Compony for standalone/pure helpers
|
|
6
6
|
module ViewHelpers
|
|
7
|
-
#
|
|
8
|
-
def compony_actions
|
|
9
|
-
return nil unless Compony.root_comp
|
|
10
|
-
Compony.root_comp.render_actions(self, wrapper_class: 'root-actions', action_class: 'root-action')
|
|
11
|
-
end
|
|
12
|
-
|
|
13
|
-
# Renders a link to a component given a comp and model or family. If authentication is configured
|
|
7
|
+
# Renders a button/link to a component given a comp and model or family. If authentication is configured
|
|
14
8
|
# and the current user has insufficient permissions to access the target object, the link is not displayed.
|
|
15
|
-
#
|
|
16
|
-
# @param
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
# @param link_args [Array] Positional arguments that will be passed to the Rails `link_to` helper
|
|
20
|
-
# @param label_opts [Hash] Options hash that will be passed to the label method (see {Compony::ComponentMixins::Default::Labelling#label})
|
|
21
|
-
# @param link_kwargs [Hash] Named arguments that will be passed to the Rails `link_to` helper
|
|
22
|
-
def compony_link(comp_name_or_cst_or_class,
|
|
23
|
-
model_or_family_name_or_cst = nil,
|
|
24
|
-
*link_args,
|
|
25
|
-
label: nil,
|
|
26
|
-
label_opts: {},
|
|
27
|
-
params: {},
|
|
28
|
-
feasibility_action: nil,
|
|
29
|
-
feasibility_target: nil,
|
|
30
|
-
standalone_name: nil,
|
|
31
|
-
**link_kwargs)
|
|
32
|
-
model = model_or_family_name_or_cst.respond_to?(:model_name) ? model_or_family_name_or_cst : nil
|
|
33
|
-
if comp_name_or_cst_or_class.is_a?(Class) && (comp_name_or_cst_or_class <= Compony::Component)
|
|
34
|
-
target_comp_instance = comp_name_or_cst_or_class.new(data: model)
|
|
35
|
-
else
|
|
36
|
-
target_comp_instance = Compony.comp_class_for!(comp_name_or_cst_or_class, model_or_family_name_or_cst).new(data: model)
|
|
37
|
-
end
|
|
38
|
-
return unless target_comp_instance.standalone_access_permitted_for?(self, standalone_name:)
|
|
39
|
-
feasibility_action ||= comp_name_or_cst_or_class.to_s.underscore.to_sym
|
|
40
|
-
feasibility_target ||= model
|
|
41
|
-
label ||= target_comp_instance.label(model, **label_opts)
|
|
42
|
-
path ||= Compony.path(target_comp_instance.comp_name, target_comp_instance.family_name, model, standalone_name:, **params)
|
|
43
|
-
if feasibility_target && !feasibility_target.feasible?(feasibility_action)
|
|
44
|
-
path = '#'
|
|
45
|
-
link_kwargs[:class] = link_kwargs[:class].is_a?(String) ? "#{link_kwargs[:class]} disabled" : 'disabled'
|
|
46
|
-
link_kwargs[:title] = feasibility_target.full_feasibility_messages(feasibility_action).presence
|
|
47
|
-
end
|
|
48
|
-
return helpers.link_to(label, path, *link_args, **link_kwargs)
|
|
49
|
-
end
|
|
50
|
-
|
|
51
|
-
# Given a component and a family/model, this instanciates and renders a button component.
|
|
52
|
-
# @see Compony#button Check Compony.button for accepted params
|
|
53
|
-
# @see Compony::Components::Button Compony::Components::Button: the default underlying implementation
|
|
54
|
-
def compony_button(...)
|
|
55
|
-
Compony.button(...).render(helpers.controller)
|
|
9
|
+
# When inside a request context (`content do...`), this is preceded by {RequestContext#render_intent}.
|
|
10
|
+
# @param button [Hash] Parameters that will be given to the button component initializer.
|
|
11
|
+
def render_intent(*, button: {}, **)
|
|
12
|
+
Compony.intent(*, **).render(self, **button)
|
|
56
13
|
end
|
|
57
14
|
end
|
|
58
15
|
end
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
module Compony
|
|
2
|
+
class VirtualModel < ActiveType::Object
|
|
3
|
+
# Use this as a base class whenever you would be inheriting from ActiveType::Object
|
|
4
|
+
# Note: this class is only available in applications that have `active_type` in their Gemfile
|
|
5
|
+
|
|
6
|
+
include Compony::ModelMixin
|
|
7
|
+
include Anchormodel::ModelMixin
|
|
8
|
+
include ActiveModel::Attributes
|
|
9
|
+
end
|
|
10
|
+
end
|
data/lib/compony.rb
CHANGED
|
@@ -3,17 +3,25 @@
|
|
|
3
3
|
# the setters, create an initializer `config/initializers/compony.rb` and call
|
|
4
4
|
# them from there.
|
|
5
5
|
# @see Compony::ViewHelpers Compony::ViewHelpers for helpers that require a view context and render results immediately
|
|
6
|
+
# @see Compony::RequestContext Compony::RequestContext for helpers that require a view context and render results immediately
|
|
6
7
|
module Compony
|
|
7
8
|
##########=====-------
|
|
8
9
|
# Configuration writers
|
|
9
10
|
##########=====-------
|
|
10
11
|
|
|
11
|
-
#
|
|
12
|
-
#
|
|
13
|
-
# button component
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
@
|
|
12
|
+
# Adds a button style that can be referred to when rendering an intent.
|
|
13
|
+
# @param name [Symbol] Name of the style. If it exists already, will override the style.
|
|
14
|
+
# @param button_component_class [String] String with the class name of the button component that will be instanciated to render the intent.
|
|
15
|
+
def self.register_button_style(name, button_component_class_name)
|
|
16
|
+
@button_component_class_names ||= {}
|
|
17
|
+
@button_component_class_names[name.to_sym] = button_component_class_name
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
# Setter for the default button style. Defaults to :css_button.
|
|
21
|
+
# @param default_button_style [Symbol] Name of the style that should be used as default.
|
|
22
|
+
# @see {Compony#default_button_style}
|
|
23
|
+
def self.default_button_style=(default_button_style)
|
|
24
|
+
@default_button_style = default_button_style
|
|
17
25
|
end
|
|
18
26
|
|
|
19
27
|
# Setter for the global field namespaces. This allows you to implement custom
|
|
@@ -58,12 +66,31 @@ module Compony
|
|
|
58
66
|
# Configuration readers
|
|
59
67
|
##########=====-------
|
|
60
68
|
|
|
61
|
-
# Getter for the
|
|
62
|
-
# @
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
69
|
+
# Getter for the button component class for a given style.
|
|
70
|
+
# @param style [Symbol] Style for which the matching button component class should be returned. Defaults to {Compony.default_button_style}.
|
|
71
|
+
# @see {Compony#register_button_style}
|
|
72
|
+
# @see {Compony#default_button_style}
|
|
73
|
+
def self.button_component_class(style = default_button_style)
|
|
74
|
+
# Lazy initialize
|
|
75
|
+
if @button_component_classes.nil?
|
|
76
|
+
@button_component_classes = {
|
|
77
|
+
css_button: Compony::Components::Buttons::CssButton,
|
|
78
|
+
link: Compony::Components::Buttons::Link
|
|
79
|
+
}.merge(@button_component_class_names&.transform_values(&:constantize) || {})
|
|
80
|
+
@button_component_classes.each_value do |button_component_class|
|
|
81
|
+
unless button_component_class.is_a?(Class) && button_component_class < Compony::Component
|
|
82
|
+
fail("Expected a button component class, got #{button_component_class.inspect}")
|
|
83
|
+
end
|
|
84
|
+
end
|
|
85
|
+
end
|
|
86
|
+
# Retrieval
|
|
87
|
+
return @button_component_classes[style&.to_sym] || fail("Unknown button style #{style.inspect}. Use one of: #{@button_component_classes.keys.inspect}")
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
# Getter for the default button style, defaults to `:css_button`.
|
|
91
|
+
# @see {Compony#default_button_style=}
|
|
92
|
+
def self.default_button_style
|
|
93
|
+
return @default_button_style || :css_button
|
|
67
94
|
end
|
|
68
95
|
|
|
69
96
|
# Getter for the global field namespaces.
|
|
@@ -94,123 +121,38 @@ module Compony
|
|
|
94
121
|
# Application-wide available pure helpers
|
|
95
122
|
##########=====-------
|
|
96
123
|
|
|
124
|
+
# Pure helper to create a Compony Intent. If given an intent, will return it unchanged. Otherwise, will give all params to the intent initializer.
|
|
125
|
+
def self.intent(intent_or_comp_args, ...)
|
|
126
|
+
if intent_or_comp_args.is_a?(Intent)
|
|
127
|
+
return intent_or_comp_args
|
|
128
|
+
else
|
|
129
|
+
return Intent.new(intent_or_comp_args, ...)
|
|
130
|
+
end
|
|
131
|
+
end
|
|
132
|
+
|
|
97
133
|
# Generates a Rails path to a component. Examples: `Compony.path(:index, :users)`, `Compony.path(:show, User.first)`
|
|
98
|
-
#
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
# or an instance implementing `model_name` from which the family name is auto-generated. Examples:
|
|
102
|
-
# `Users`, `'Users'`, `:users`, `User.first`
|
|
103
|
-
# @param standalone_name [Symbol,nil] Name of the standalone config to point to (defaults to nil the default standalone config).
|
|
104
|
-
# @param args_for_path_helper [Array] Positional arguments passed to the Rails helper
|
|
105
|
-
# @param kwargs_for_path_helper [Hash] Named arguments passed to the Rails helper. If a model is given to `model_or_family_name_or_cst`,
|
|
106
|
-
# the param `id` defaults to the passed model's ID.
|
|
107
|
-
def self.path(comp_name_or_cst_or_class, model_or_family_name_or_cst = nil, *args_for_path_helper, standalone_name: nil, **kwargs_for_path_helper)
|
|
108
|
-
# Extract model if any, to get the ID
|
|
109
|
-
model = model_or_family_name_or_cst.respond_to?(:model_name) ? model_or_family_name_or_cst : nil
|
|
110
|
-
comp_class = if comp_name_or_cst_or_class.is_a?(Class) && (comp_name_or_cst_or_class <= Compony::Component)
|
|
111
|
-
comp_name_or_cst_or_class
|
|
112
|
-
else
|
|
113
|
-
comp_class_for!(comp_name_or_cst_or_class, model_or_family_name_or_cst)
|
|
114
|
-
end
|
|
115
|
-
return comp_class.new.path(model, *args_for_path_helper, standalone_name:, **kwargs_for_path_helper)
|
|
134
|
+
# The first two arguments are given to create an {Intent} and all subsequend args and all kwargs are given to {Intent#path}
|
|
135
|
+
def self.path(comp_name_or_cst_or_class, model_or_family_name_or_cst = nil, ...)
|
|
136
|
+
intent(comp_name_or_cst_or_class, model_or_family_name_or_cst).path(...)
|
|
116
137
|
end
|
|
117
138
|
|
|
118
139
|
# Given a component and a family/model, this returns the matching component class if any, or nil if the component does not exist.
|
|
119
|
-
# @
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
family_cst_str = family_name_for(model_or_family_name_or_cst).camelize
|
|
125
|
-
comp_cst_str = comp_name_or_cst.to_s.camelize
|
|
126
|
-
return nil unless ::Components.const_defined?(family_cst_str)
|
|
127
|
-
family_constant = ::Components.const_get(family_cst_str)
|
|
128
|
-
return nil unless family_constant.const_defined?(comp_cst_str)
|
|
129
|
-
return family_constant.const_get(comp_cst_str)
|
|
140
|
+
# @see Intent for allowed parameters.
|
|
141
|
+
def self.comp_class_for(...)
|
|
142
|
+
return intent(...).comp_class
|
|
143
|
+
rescue NameError
|
|
144
|
+
return nil
|
|
130
145
|
end
|
|
131
146
|
|
|
132
147
|
# Same as Compony#comp_class_for but fails if none found
|
|
148
|
+
# @see Intent for allowed parameters.
|
|
133
149
|
# @see Compony#comp_class_for
|
|
134
|
-
def self.comp_class_for!(
|
|
135
|
-
comp_class_for(
|
|
150
|
+
def self.comp_class_for!(...)
|
|
151
|
+
comp_class_for(...) || fail(
|
|
136
152
|
"No component found for [#{comp_name_or_cst.inspect}, #{model_or_family_name_or_cst.inspect}]"
|
|
137
153
|
)
|
|
138
154
|
end
|
|
139
155
|
|
|
140
|
-
# Given a component and a family, this returns the name of the Rails URL helper returning the path to this component.<br>
|
|
141
|
-
# The parameters are the same as for {Compony#rails_action_name}.<br>
|
|
142
|
-
# Example usage: `send("#{path_helper_name(:index, :users)}_url)`
|
|
143
|
-
# @see Compony#path
|
|
144
|
-
# @see Compony#rails_action_name rails_action_name for the accepted params
|
|
145
|
-
def self.path_helper_name(...)
|
|
146
|
-
"#{rails_action_name(...)}_comp"
|
|
147
|
-
end
|
|
148
|
-
|
|
149
|
-
# Given a component and a family or a component class, this returns the name of the ComponyController action for this component.<br>
|
|
150
|
-
# Optionally can pass a name for extra standalone configs.
|
|
151
|
-
# @param comp_name_or_cst [String,Symbol] Name of the component the action points to.
|
|
152
|
-
# @param model_or_family_name_or_cst [String,Symbol] Name of the family the action points to.
|
|
153
|
-
# @param name [String,Symbol] If referring to an extra standalone entrypoint, specify its name using this param.
|
|
154
|
-
# @see Compony#path
|
|
155
|
-
def self.rails_action_name(comp_name_or_cst_or_class, model_or_family_name_or_cst, name = nil)
|
|
156
|
-
if comp_name_or_cst_or_class.is_a?(Class) && (comp_name_or_cst_or_class <= Compony::Component)
|
|
157
|
-
comp_class = comp_name_or_cst_or_class
|
|
158
|
-
comp_name_or_cst_or_class = comp_class.comp_name
|
|
159
|
-
model_or_family_name_or_cst = comp_class.family_name
|
|
160
|
-
end
|
|
161
|
-
[name.presence, comp_name_or_cst_or_class.to_s.underscore, family_name_for(model_or_family_name_or_cst)].compact.join('_')
|
|
162
|
-
end
|
|
163
|
-
|
|
164
|
-
# Given a component and a family/model, this instanciates and returns a button component.
|
|
165
|
-
# @param comp_name_or_cst_or_class [String,Symbol,Class] The component that should be loaded, for instance `ShowForAll`, `'ShowForAll'` or `:show_for_all`
|
|
166
|
-
# @param model_or_family_name_or_cst [String,Symbol,ApplicationRecord] Either the family that contains the requested component,
|
|
167
|
-
# or an instance implementing `model_name` from which the family name is auto-generated. Examples:
|
|
168
|
-
# `Users`, `'Users'`, `:users`, `User.first`
|
|
169
|
-
# @param label_opts [Hash] Options hash that will be passed to the label method (see {Compony::ComponentMixins::Default::Labelling#label})
|
|
170
|
-
# @param params [Hash] GET parameters to be inclued into the path this button points to. Special case: e.g. format: :pdf -> some.url/foo/bar.pdf
|
|
171
|
-
# @param feasibility_action [Symbol] Name of the feasibility action that should be checked for this button, defaults to the component name
|
|
172
|
-
# @param feasibility_target [Symbol] Name of the feasibility target (subject) that the feasibility should be checked on, defaults to the model if given
|
|
173
|
-
# @param standalone_name [Symbol,nil] Name of the standalone config to point to (defaults to nil the default standalone config).
|
|
174
|
-
# @param override_kwargs [Hash] Override button options, see options for {Compony::Components::Button}
|
|
175
|
-
# @see Compony::ViewHelpers#compony_button View helper providing a wrapper for this method that immediately renders a button.
|
|
176
|
-
# @see Compony::Components::Button Compony::Components::Button: the default underlying implementation
|
|
177
|
-
def self.button(comp_name_or_cst_or_class,
|
|
178
|
-
model_or_family_name_or_cst = nil,
|
|
179
|
-
label_opts: nil,
|
|
180
|
-
params: nil,
|
|
181
|
-
feasibility_action: nil,
|
|
182
|
-
feasibility_target: nil,
|
|
183
|
-
method: nil,
|
|
184
|
-
standalone_name: nil,
|
|
185
|
-
**override_kwargs)
|
|
186
|
-
label_opts ||= button_defaults[:label_opts] || {}
|
|
187
|
-
params ||= button_defaults[:params] || {}
|
|
188
|
-
model = model_or_family_name_or_cst.respond_to?(:model_name) ? model_or_family_name_or_cst : nil
|
|
189
|
-
if comp_name_or_cst_or_class.is_a?(Class) && (comp_name_or_cst_or_class <= Compony::Component)
|
|
190
|
-
target_comp_instance = comp_name_or_cst_or_class.new(data: model)
|
|
191
|
-
else
|
|
192
|
-
target_comp_instance = Compony.comp_class_for!(comp_name_or_cst_or_class, model_or_family_name_or_cst).new(data: model)
|
|
193
|
-
end
|
|
194
|
-
feasibility_action ||= button_defaults[:feasibility_action] || comp_name_or_cst_or_class.to_s.underscore.to_sym
|
|
195
|
-
feasibility_target ||= button_defaults[:feasibility_target] || model
|
|
196
|
-
options = {
|
|
197
|
-
label: target_comp_instance.label(model, **label_opts),
|
|
198
|
-
icon: target_comp_instance.icon,
|
|
199
|
-
color: target_comp_instance.color,
|
|
200
|
-
path: Compony.path(target_comp_instance.comp_name, target_comp_instance.family_name, model, standalone_name:, **params),
|
|
201
|
-
method:,
|
|
202
|
-
visible: ->(controller) { target_comp_instance.standalone_access_permitted_for?(controller, standalone_name:, verb: method) }
|
|
203
|
-
}
|
|
204
|
-
if feasibility_target
|
|
205
|
-
options.merge!({
|
|
206
|
-
enabled: feasibility_target.feasible?(feasibility_action),
|
|
207
|
-
title: feasibility_target.full_feasibility_messages(feasibility_action).presence
|
|
208
|
-
})
|
|
209
|
-
end
|
|
210
|
-
options.merge!(override_kwargs.symbolize_keys)
|
|
211
|
-
return Compony.button_component_class.new(**options.symbolize_keys)
|
|
212
|
-
end
|
|
213
|
-
|
|
214
156
|
# Returns the current root component, if any
|
|
215
157
|
def self.root_comp
|
|
216
158
|
RequestStore.store[:compony_root_comp]
|
|
@@ -228,37 +170,6 @@ module Compony
|
|
|
228
170
|
end
|
|
229
171
|
end
|
|
230
172
|
|
|
231
|
-
# Getter for current button defaults
|
|
232
|
-
# @todo document params
|
|
233
|
-
def self.button_defaults
|
|
234
|
-
RequestStore.store[:button_defaults] || {}
|
|
235
|
-
end
|
|
236
|
-
|
|
237
|
-
# Overwrites the keys of the current button defaults by the ones provided during the execution of a given block and restores them afterwords.
|
|
238
|
-
# This method is useful when the same set of options is to be given to a multitude of buttons.
|
|
239
|
-
# @param keys_to_overwrite [Hash] Options that should be given to the buttons within the block, with their values
|
|
240
|
-
# @param block [Block] Within this block, all omitted button options point to `keys_to_overwrite`
|
|
241
|
-
def self.with_button_defaults(**keys_to_overwrite, &block)
|
|
242
|
-
# Lazy initialize butto_defaults store if it hasn't been yet
|
|
243
|
-
RequestStore.store[:button_defaults] ||= {}
|
|
244
|
-
keys_to_overwrite.transform_keys!(&:to_sym)
|
|
245
|
-
old_values = {}
|
|
246
|
-
newly_defined_keys = keys_to_overwrite.keys - RequestStore.store[:button_defaults].keys
|
|
247
|
-
keys_to_overwrite.each do |key, new_value|
|
|
248
|
-
# Assign new value
|
|
249
|
-
old_values[key] = RequestStore.store[:button_defaults][key]
|
|
250
|
-
RequestStore.store[:button_defaults][key] = new_value
|
|
251
|
-
end
|
|
252
|
-
return_value = block.call
|
|
253
|
-
# Restore previous value
|
|
254
|
-
keys_to_overwrite.each_key do |key|
|
|
255
|
-
RequestStore.store[:button_defaults][key] = old_values[key]
|
|
256
|
-
end
|
|
257
|
-
# Undefine keys that were not there previously
|
|
258
|
-
newly_defined_keys.each { |key| RequestStore.store[:button_defaults].delete(key) }
|
|
259
|
-
return return_value
|
|
260
|
-
end
|
|
261
|
-
|
|
262
173
|
# Goes through model_field_namespaces and returns the first hit for the given constant
|
|
263
174
|
# @param constant [Constant] The constant that is searched, e.g. RichText -> would return e.g. Compony::ModelFields::RichText
|
|
264
175
|
def self.model_field_class_for(constant)
|
|
@@ -279,6 +190,7 @@ require 'request_store'
|
|
|
279
190
|
require 'schemacop'
|
|
280
191
|
require 'simple_form'
|
|
281
192
|
|
|
193
|
+
require 'compony/intent'
|
|
282
194
|
require 'compony/engine'
|
|
283
195
|
require 'compony/model_fields/base'
|
|
284
196
|
require 'compony/model_fields/anchormodel'
|
|
@@ -306,8 +218,10 @@ require 'compony/component_mixins/default/standalone/verb_dsl'
|
|
|
306
218
|
require 'compony/component_mixins/default/standalone/resourceful_verb_dsl'
|
|
307
219
|
require 'compony/component_mixins/default/labelling'
|
|
308
220
|
require 'compony/component_mixins/resourceful'
|
|
221
|
+
require 'compony/exposed_intents_dsl'
|
|
309
222
|
require 'compony/component'
|
|
310
|
-
require 'compony/components/
|
|
223
|
+
require 'compony/components/buttons/link'
|
|
224
|
+
require 'compony/components/buttons/css_button'
|
|
311
225
|
require 'compony/components/index'
|
|
312
226
|
require 'compony/components/list'
|
|
313
227
|
require 'compony/components/show'
|
|
@@ -323,3 +237,7 @@ require 'compony/request_context'
|
|
|
323
237
|
require 'compony/version'
|
|
324
238
|
require 'compony/view_helpers'
|
|
325
239
|
require 'compony/controller_mixin'
|
|
240
|
+
|
|
241
|
+
if defined?(ActiveType::Object)
|
|
242
|
+
require 'compony/virtual_model'
|
|
243
|
+
end
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: compony
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.8.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Sandro Kalbermatter
|
|
@@ -9,7 +9,7 @@ authors:
|
|
|
9
9
|
autorequire:
|
|
10
10
|
bindir: bin
|
|
11
11
|
cert_chain: []
|
|
12
|
-
date: 2025-11-
|
|
12
|
+
date: 2025-11-27 00:00:00.000000000 Z
|
|
13
13
|
dependencies:
|
|
14
14
|
- !ruby/object:Gem::Dependency
|
|
15
15
|
name: yard
|
|
@@ -203,6 +203,9 @@ files:
|
|
|
203
203
|
- doc/Compony/ComponentMixins/Resourceful.html
|
|
204
204
|
- doc/Compony/Components.html
|
|
205
205
|
- doc/Compony/Components/Button.html
|
|
206
|
+
- doc/Compony/Components/Buttons.html
|
|
207
|
+
- doc/Compony/Components/Buttons/CssButton.html
|
|
208
|
+
- doc/Compony/Components/Buttons/Link.html
|
|
206
209
|
- doc/Compony/Components/Destroy.html
|
|
207
210
|
- doc/Compony/Components/Edit.html
|
|
208
211
|
- doc/Compony/Components/Form.html
|
|
@@ -213,6 +216,8 @@ files:
|
|
|
213
216
|
- doc/Compony/Components/WithForm.html
|
|
214
217
|
- doc/Compony/ControllerMixin.html
|
|
215
218
|
- doc/Compony/Engine.html
|
|
219
|
+
- doc/Compony/ExposedIntentsDsl.html
|
|
220
|
+
- doc/Compony/Intent.html
|
|
216
221
|
- doc/Compony/MethodAccessibleHash.html
|
|
217
222
|
- doc/Compony/ModelFields.html
|
|
218
223
|
- doc/Compony/ModelFields/Anchormodel.html
|
|
@@ -240,6 +245,7 @@ files:
|
|
|
240
245
|
- doc/Compony/RequestContext.html
|
|
241
246
|
- doc/Compony/Version.html
|
|
242
247
|
- doc/Compony/ViewHelpers.html
|
|
248
|
+
- doc/Compony/VirtualModel.html
|
|
243
249
|
- doc/ComponyController.html
|
|
244
250
|
- doc/_index.html
|
|
245
251
|
- doc/class_list.html
|
|
@@ -249,6 +255,29 @@ files:
|
|
|
249
255
|
- doc/file.README.html
|
|
250
256
|
- doc/file_list.html
|
|
251
257
|
- doc/frames.html
|
|
258
|
+
- doc/guide/basic_component.md
|
|
259
|
+
- doc/guide/example.md
|
|
260
|
+
- doc/guide/feasibility.md
|
|
261
|
+
- doc/guide/generators.md
|
|
262
|
+
- doc/guide/inheritance.md
|
|
263
|
+
- doc/guide/installation.md
|
|
264
|
+
- doc/guide/intents.md
|
|
265
|
+
- doc/guide/internal_datastructures.md
|
|
266
|
+
- doc/guide/model_fields.md
|
|
267
|
+
- doc/guide/nesting.md
|
|
268
|
+
- doc/guide/ownership.md
|
|
269
|
+
- doc/guide/pre_built_components.md
|
|
270
|
+
- doc/guide/pre_built_components/destroy.md
|
|
271
|
+
- doc/guide/pre_built_components/edit.md
|
|
272
|
+
- doc/guide/pre_built_components/form.md
|
|
273
|
+
- doc/guide/pre_built_components/index.md
|
|
274
|
+
- doc/guide/pre_built_components/list.md
|
|
275
|
+
- doc/guide/pre_built_components/new.md
|
|
276
|
+
- doc/guide/pre_built_components/show.md
|
|
277
|
+
- doc/guide/pre_built_components/with_form.md
|
|
278
|
+
- doc/guide/resourceful.md
|
|
279
|
+
- doc/guide/standalone.md
|
|
280
|
+
- doc/guide/virtual_models.md
|
|
252
281
|
- doc/imgs/intro-example-destroy.png
|
|
253
282
|
- doc/imgs/intro-example-edit.png
|
|
254
283
|
- doc/imgs/intro-example-index.png
|
|
@@ -271,7 +300,8 @@ files:
|
|
|
271
300
|
- lib/compony/component_mixins/default/standalone/standalone_dsl.rb
|
|
272
301
|
- lib/compony/component_mixins/default/standalone/verb_dsl.rb
|
|
273
302
|
- lib/compony/component_mixins/resourceful.rb
|
|
274
|
-
- lib/compony/components/
|
|
303
|
+
- lib/compony/components/buttons/css_button.rb
|
|
304
|
+
- lib/compony/components/buttons/link.rb
|
|
275
305
|
- lib/compony/components/destroy.rb
|
|
276
306
|
- lib/compony/components/edit.rb
|
|
277
307
|
- lib/compony/components/form.rb
|
|
@@ -282,6 +312,8 @@ files:
|
|
|
282
312
|
- lib/compony/components/with_form.rb
|
|
283
313
|
- lib/compony/controller_mixin.rb
|
|
284
314
|
- lib/compony/engine.rb
|
|
315
|
+
- lib/compony/exposed_intents_dsl.rb
|
|
316
|
+
- lib/compony/intent.rb
|
|
285
317
|
- lib/compony/method_accessible_hash.rb
|
|
286
318
|
- lib/compony/model_fields/anchormodel.rb
|
|
287
319
|
- lib/compony/model_fields/association.rb
|
|
@@ -308,6 +340,7 @@ files:
|
|
|
308
340
|
- lib/compony/request_context.rb
|
|
309
341
|
- lib/compony/version.rb
|
|
310
342
|
- lib/compony/view_helpers.rb
|
|
343
|
+
- lib/compony/virtual_model.rb
|
|
311
344
|
- lib/generators/component/USAGE
|
|
312
345
|
- lib/generators/component/component_generator.rb
|
|
313
346
|
- lib/generators/component/templates/component.rb.erb
|
|
@@ -1,61 +0,0 @@
|
|
|
1
|
-
module Compony
|
|
2
|
-
module Components
|
|
3
|
-
# @api description
|
|
4
|
-
# This is the default button implementation, providing a minimal button
|
|
5
|
-
class Button < Compony::Component
|
|
6
|
-
SUPPORTED_TYPES = %i[button submit].freeze
|
|
7
|
-
|
|
8
|
-
# path: If given a block, it will be evaluated in the helpers context when rendering
|
|
9
|
-
# enabled: If given a block, it will be evaluated in the helpers context when rendering
|
|
10
|
-
def initialize(*, label: nil, path: nil, method: nil, type: nil, enabled: nil, visible: nil, title: nil, button_params: nil, value: nil, **, &)
|
|
11
|
-
@label = label || Compony.button_defaults[:label]
|
|
12
|
-
@type = type&.to_sym || Compony.button_defaults[:type] || :button
|
|
13
|
-
@path = path || Compony.button_defaults[:path] || 'javascript:void(0)'
|
|
14
|
-
@method = method || Compony.button_defaults[:method]
|
|
15
|
-
if @type != :button && !@method.nil?
|
|
16
|
-
fail("Param `method` is only allowed for :button type buttons, but got method #{@method.inspect} for type #{@type.inspect}")
|
|
17
|
-
end
|
|
18
|
-
@method ||= :get
|
|
19
|
-
@enabled = enabled
|
|
20
|
-
@enabled = Compony.button_defaults[:enabled] if @enabled.nil?
|
|
21
|
-
@enabled = true if @enabled.nil?
|
|
22
|
-
@visible = visible
|
|
23
|
-
@visible = Compony.button_defaults[:visible] if @visible.nil?
|
|
24
|
-
@visible = true if @visible.nil?
|
|
25
|
-
@title = title || Compony.button_defaults[:title]
|
|
26
|
-
@button_params = button_params
|
|
27
|
-
@value = value
|
|
28
|
-
|
|
29
|
-
fail "Unsupported button type #{@type}, use on of: #{SUPPORTED_TYPES.inspect}" unless SUPPORTED_TYPES.include?(@type)
|
|
30
|
-
|
|
31
|
-
super(*, **, &)
|
|
32
|
-
end
|
|
33
|
-
|
|
34
|
-
setup do
|
|
35
|
-
before_render do
|
|
36
|
-
if @path.respond_to?(:call)
|
|
37
|
-
@path = instance_exec(&@path)
|
|
38
|
-
end
|
|
39
|
-
if @enabled.respond_to?(:call)
|
|
40
|
-
@enabled = @enabled.call(controller)
|
|
41
|
-
end
|
|
42
|
-
if @visible.respond_to?(:call)
|
|
43
|
-
@visible = @visible.call(controller)
|
|
44
|
-
end
|
|
45
|
-
@path = 'javascript:void(0)' unless @enabled
|
|
46
|
-
end
|
|
47
|
-
|
|
48
|
-
content do
|
|
49
|
-
if @visible
|
|
50
|
-
case @type
|
|
51
|
-
when :button
|
|
52
|
-
concat button_to(@label, @path, method: @method, disabled: !@enabled, title: @title, params: @button_params)
|
|
53
|
-
when :submit
|
|
54
|
-
concat button_tag(@label, type: :submit, disabled: !@enabled, title: @title, value: @value)
|
|
55
|
-
end
|
|
56
|
-
end
|
|
57
|
-
end
|
|
58
|
-
end
|
|
59
|
-
end
|
|
60
|
-
end
|
|
61
|
-
end
|