coupdoeil 1.0.0.pre.beta.3 → 1.0.0.pre.rc1
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 +13 -0
- data/README.md +2 -1
- data/Rakefile +21 -0
- data/app/assets/javascripts/coupdoeil.js +17 -7
- data/app/assets/javascripts/coupdoeil.min.js +1 -1
- data/app/assets/javascripts/coupdoeil.min.js.map +1 -1
- data/app/controllers/coupdoeil/popovers_controller.rb +1 -1
- data/app/javascript/coupdoeil/elements/coupdoeil_element.js +2 -2
- data/app/javascript/coupdoeil/events/onclick.js +1 -1
- data/app/javascript/coupdoeil/events/onmouseover.js +2 -2
- data/app/javascript/coupdoeil/popover/opening.js +12 -2
- data/app/models/coupdoeil/params.rb +2 -2
- data/app/models/coupdoeil/popover/option/animation.rb +1 -1
- data/app/models/coupdoeil/popover/option/loading.rb +1 -1
- data/app/models/coupdoeil/popover/option/offset.rb +3 -3
- data/app/models/coupdoeil/popover/option/placement.rb +8 -8
- data/app/models/coupdoeil/popover/option/trigger.rb +1 -1
- data/app/models/coupdoeil/popover/option.rb +4 -4
- data/app/models/coupdoeil/popover/options_set.rb +1 -1
- data/app/models/coupdoeil/popover/registry.rb +3 -3
- data/app/models/coupdoeil/popover.rb +3 -3
- data/app/models/coupdoeil/tag.rb +1 -1
- data/config/routes.rb +2 -0
- data/lib/coupdoeil/engine.rb +17 -15
- data/lib/coupdoeil/version.rb +3 -1
- data/lib/coupdoeil.rb +2 -0
- data/lib/generators/coupdoeil/install/install_generator.rb +65 -61
- data/lib/generators/coupdoeil/popover/popover_generator.rb +20 -14
- data/lib/tasks/coupdoeil_tasks.rake +2 -0
- metadata +18 -18
@@ -6,7 +6,7 @@ module Coupdoeil
|
|
6
6
|
before_action :set_popover_class
|
7
7
|
before_action :set_popover_params
|
8
8
|
|
9
|
-
filters = _process_action_callbacks.map(&:filter) -
|
9
|
+
filters = _process_action_callbacks.map(&:filter) - [:set_action_and_resource_name, :set_popover_class, :set_popover_params]
|
10
10
|
skip_before_action(*filters, raise: false)
|
11
11
|
skip_after_action(*filters, raise: false)
|
12
12
|
skip_around_action(*filters, raise: false)
|
@@ -18,11 +18,11 @@ export default class extends HTMLElement {
|
|
18
18
|
}
|
19
19
|
|
20
20
|
openPopover(triggerElement = null, callbacks) {
|
21
|
-
if (this.openingPopover || this.popoverController.isOpen || this.disabled
|
21
|
+
if (this.openingPopover || this.popoverController.isOpen || this.disabled) return;
|
22
22
|
|
23
23
|
this.openingPopover = true
|
24
24
|
|
25
|
-
const parent = this.closest(POPOVER_SELECTOR)?.
|
25
|
+
const parent = this.closest(POPOVER_SELECTOR)?.popoverController
|
26
26
|
addToCurrents(this)
|
27
27
|
return openPopover(this.popoverController, { parent, ...callbacks })
|
28
28
|
}
|
@@ -53,7 +53,7 @@ function handleClickedCoupdoeilOutsidePopover(coupdoeilElement, clickedElement)
|
|
53
53
|
}
|
54
54
|
|
55
55
|
function handleClickOutsideCoupdoeilButWithinPopover(popoverElement, clickedElement) {
|
56
|
-
const popover = popoverElement.
|
56
|
+
const popover = popoverElement.popoverController;
|
57
57
|
|
58
58
|
if (isElementClosePopoverButton(clickedElement)) {
|
59
59
|
closeNow(popover)
|
@@ -30,7 +30,7 @@ export const onMouseOver = ({ target: hoveredElement }) => {
|
|
30
30
|
|
31
31
|
function handleMouseOverCoupdoeilWithinPopover(coupdoeilElement, popoverElement, hoveredElement) {
|
32
32
|
const childPopover = coupdoeilElement.popoverController
|
33
|
-
const parentPopover = popoverElement.
|
33
|
+
const parentPopover = popoverElement.popoverController
|
34
34
|
if(notTriggeredOnHover(childPopover))
|
35
35
|
return;
|
36
36
|
|
@@ -71,7 +71,7 @@ function handleOverOutsideCoupdoeilAndPopover() {
|
|
71
71
|
}
|
72
72
|
|
73
73
|
function handleOverOutsideCoupdoeilButWithinPopover(popoverElement) {
|
74
|
-
const popover = popoverElement.
|
74
|
+
const popover = popoverElement.popoverController
|
75
75
|
|
76
76
|
if (popover.closingRequest) {
|
77
77
|
// popover is still open but was requested to close, then it clears this closing request
|
@@ -76,6 +76,9 @@ async function display(controller, options, beforeDisplay) {
|
|
76
76
|
|
77
77
|
cancelCloseRequest(controller)
|
78
78
|
|
79
|
+
if (controller.card) {
|
80
|
+
controller.card.remove()
|
81
|
+
}
|
79
82
|
controller.card = buildPopoverElement(controller, options)
|
80
83
|
document.body.appendChild(controller.card)
|
81
84
|
|
@@ -85,6 +88,10 @@ async function display(controller, options, beforeDisplay) {
|
|
85
88
|
|
86
89
|
executeNextFrameIfStillOpening(controller, async () => {
|
87
90
|
await positionPopover(controller.coupdoeilElement, controller.card, options)
|
91
|
+
// popover can be closed while waiting for positioning promise to resolve
|
92
|
+
if (controller.card === null) {
|
93
|
+
return clearPopover(controller)
|
94
|
+
}
|
88
95
|
|
89
96
|
// see buildPopoverElement() about next 2 lines
|
90
97
|
controller.card.classList.add('hidden')
|
@@ -106,7 +113,7 @@ async function display(controller, options, beforeDisplay) {
|
|
106
113
|
|
107
114
|
function executeNextFrameIfStillOpening(controller, callback) {
|
108
115
|
requestAnimationFrame(() => {
|
109
|
-
if (controller.coupdoeilElement.openingPopover) {
|
116
|
+
if (controller.card && controller.coupdoeilElement.openingPopover && !controller.closingRequest) {
|
110
117
|
callback.call()
|
111
118
|
} else {
|
112
119
|
clearPopover(controller)
|
@@ -128,12 +135,15 @@ function buildPopoverElement(controller, options) {
|
|
128
135
|
el.classList.add(POPOVER_CLASS_NAME)
|
129
136
|
el.style.cssText = 'position: absolute; left: 0; top: 0;'
|
130
137
|
el.innerHTML = getPopoverContentHTML(controller)
|
131
|
-
el.
|
138
|
+
el.popoverController = controller
|
139
|
+
el.coupdoeilElement = controller.coupdoeilElement
|
140
|
+
el.close = function() { this.coupdoeilElement.closePopover() }
|
132
141
|
el.dataset.placement = options.placement
|
133
142
|
|
134
143
|
// Initial style is not .hidden (no display: none;) and visibility: 'hidden'; so the card is inserted
|
135
144
|
// in DOM the without being visible.
|
136
145
|
// This allows the browser to compute its actual size so the positioning is computed correctly.
|
137
146
|
el.style.visibility = 'hidden'
|
147
|
+
|
138
148
|
return el
|
139
149
|
}
|
@@ -12,7 +12,7 @@ module Coupdoeil
|
|
12
12
|
|
13
13
|
SerializationError = Class.new(StandardError)
|
14
14
|
|
15
|
-
def deserialize_global_id(hash) = GlobalID::Locator.locate
|
15
|
+
def deserialize_global_id(hash) = GlobalID::Locator.locate(hash[GLOBAL_ID_KEY])
|
16
16
|
def deserialize_hash(serialized_hash) = serialized_hash.transform_values { deserialize_param(_1) }
|
17
17
|
def serialized_global_id?(hash) = hash.size == 1 && hash.include?(GLOBAL_ID_KEY)
|
18
18
|
|
@@ -71,7 +71,7 @@ module Coupdoeil
|
|
71
71
|
param.map { |arg| deserialize_param(arg) }
|
72
72
|
when Hash
|
73
73
|
if serialized_global_id?(param)
|
74
|
-
deserialize_global_id
|
74
|
+
deserialize_global_id(param)
|
75
75
|
else
|
76
76
|
deserialize_hash(param)
|
77
77
|
end
|
@@ -6,7 +6,7 @@ module Coupdoeil
|
|
6
6
|
class Animation < Coupdoeil::Popover::Option
|
7
7
|
self.bit_size = 3
|
8
8
|
|
9
|
-
VALUES =
|
9
|
+
VALUES = [false, "slide-in", "fade-in", "slide-out", "custom"].freeze
|
10
10
|
INDEX_BY_VALUES = VALUES.each_with_index.to_h.with_indifferent_access.freeze
|
11
11
|
|
12
12
|
class << self
|
@@ -29,7 +29,7 @@ module Coupdoeil
|
|
29
29
|
def validate!
|
30
30
|
return ensure_no_overflow if (value in Float | Integer) || value.to_s.match?(/^-?\d+(\.\d{1,3})?(px|rem)?$/)
|
31
31
|
|
32
|
-
raise_invalid_option
|
32
|
+
raise_invalid_option("Value should be a signed float or integer, followed or not by 'rem' or 'px'.")
|
33
33
|
end
|
34
34
|
|
35
35
|
private
|
@@ -39,8 +39,8 @@ module Coupdoeil
|
|
39
39
|
integer, decimals = float_value.abs.to_s.split(".").map(&:to_i)
|
40
40
|
return if integer.in?(0..255) && decimals.in?(0..999)
|
41
41
|
|
42
|
-
raise_invalid_option
|
43
|
-
with a maximum of 3 decimal digits."
|
42
|
+
raise_invalid_option("Number should be comprised between -255.999 and 255.999, \
|
43
|
+
with a maximum of 3 decimal digits.")
|
44
44
|
end
|
45
45
|
end
|
46
46
|
end
|
@@ -6,13 +6,13 @@ module Coupdoeil
|
|
6
6
|
class Placement < Coupdoeil::Popover::Option
|
7
7
|
self.bit_size = 4 * 4
|
8
8
|
|
9
|
-
VALUES =
|
10
|
-
auto
|
11
|
-
top top-start top-end
|
12
|
-
right right-start right-end
|
13
|
-
bottom bottom-start bottom-end
|
14
|
-
left left-start left-end
|
15
|
-
].freeze
|
9
|
+
VALUES = [
|
10
|
+
"auto",
|
11
|
+
["top", "top-start", "top-end"],
|
12
|
+
["right", "right-start", "right-end"],
|
13
|
+
["bottom", "bottom-start", "bottom-end"],
|
14
|
+
["left", "left-start", "left-end"],
|
15
|
+
].flatten.freeze
|
16
16
|
INDEX_BY_VALUES = VALUES.each_with_index.to_h.with_indifferent_access.freeze
|
17
17
|
|
18
18
|
class << self
|
@@ -35,7 +35,7 @@ module Coupdoeil
|
|
35
35
|
next if placement_value.strip.in?(VALUES)
|
36
36
|
|
37
37
|
values_sentence = VALUES.to_sentence(last_word_connector: " or ")
|
38
|
-
raise_invalid_option
|
38
|
+
raise_invalid_option("Value must be one of: #{values_sentence}")
|
39
39
|
end
|
40
40
|
end
|
41
41
|
end
|
@@ -1,4 +1,5 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
|
+
|
2
3
|
module Coupdoeil
|
3
4
|
class Popover
|
4
5
|
class Option
|
@@ -20,7 +21,7 @@ module Coupdoeil
|
|
20
21
|
attr_reader :value
|
21
22
|
|
22
23
|
def initialize(value)
|
23
|
-
value = value.to_s if value.is_a?
|
24
|
+
value = value.to_s if value.is_a?(Symbol)
|
24
25
|
@value = value
|
25
26
|
end
|
26
27
|
|
@@ -29,8 +30,7 @@ module Coupdoeil
|
|
29
30
|
private
|
30
31
|
|
31
32
|
def raise_invalid_option(message)
|
32
|
-
raise InvalidOptionError,
|
33
|
-
"Invalid value '#{value}' (#{value.class.name}) for #{self.class.key} option. #{message}"
|
33
|
+
raise InvalidOptionError, "Invalid value '#{value}' (#{value.class.name}) for #{self.class.key} option. #{message}"
|
34
34
|
end
|
35
35
|
|
36
36
|
def validate_inclusion!
|
@@ -38,7 +38,7 @@ module Coupdoeil
|
|
38
38
|
return if value.in?(values)
|
39
39
|
|
40
40
|
values_sentence = values.to_sentence(two_words_connector: " or ", last_word_connector: " or ")
|
41
|
-
raise_invalid_option
|
41
|
+
raise_invalid_option("Value must be one of: #{values_sentence}")
|
42
42
|
end
|
43
43
|
end
|
44
44
|
end
|
@@ -7,12 +7,12 @@ module Coupdoeil
|
|
7
7
|
|
8
8
|
def initialize
|
9
9
|
@semaphore = Mutex.new
|
10
|
-
@registry =
|
10
|
+
@registry = {}
|
11
11
|
end
|
12
12
|
|
13
13
|
def register(type, klass) = @semaphore.synchronize { @registry[type] = klass }
|
14
|
-
def lookup(type) = @semaphore.synchronize {@registry.fetch(type) }
|
15
|
-
def safe_lookup(type) = @semaphore.synchronize {@registry[type] }
|
14
|
+
def lookup(type) = @semaphore.synchronize { @registry.fetch(type) }
|
15
|
+
def safe_lookup(type) = @semaphore.synchronize { @registry[type] }
|
16
16
|
|
17
17
|
def lookup_or_register(type)
|
18
18
|
safe_lookup(type) ||
|
@@ -35,7 +35,7 @@ module Coupdoeil
|
|
35
35
|
cache: true,
|
36
36
|
loading: :async,
|
37
37
|
trigger: "hover",
|
38
|
-
opening_delay: true
|
38
|
+
opening_delay: true,
|
39
39
|
)
|
40
40
|
|
41
41
|
DoubleRenderError = Class.new(::AbstractController::DoubleRenderError)
|
@@ -74,7 +74,7 @@ module Coupdoeil
|
|
74
74
|
define_singleton_method(action_name) { setup_class.new(self).with_type(action_name) }
|
75
75
|
end
|
76
76
|
public_send(method_name)
|
77
|
-
|
77
|
+
end
|
78
78
|
|
79
79
|
def respond_to_missing?(method, include_all = false)
|
80
80
|
action_methods.include?(method.name) || super
|
@@ -104,7 +104,7 @@ module Coupdoeil
|
|
104
104
|
|
105
105
|
def view_context
|
106
106
|
super.tap do |context|
|
107
|
-
context.extend
|
107
|
+
context.extend(ViewContextDelegation)
|
108
108
|
context.popover = self
|
109
109
|
context.__cp_view_context = @__cp_view_context
|
110
110
|
end
|
data/app/models/coupdoeil/tag.rb
CHANGED
data/config/routes.rb
CHANGED
data/lib/coupdoeil/engine.rb
CHANGED
@@ -1,16 +1,18 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Coupdoeil
|
2
4
|
class Engine < ::Rails::Engine
|
3
5
|
isolate_namespace Coupdoeil
|
4
6
|
config.eager_load_namespaces << Coupdoeil
|
5
7
|
config.coupdoeil = ActiveSupport::OrderedOptions.new
|
6
8
|
|
7
|
-
config.autoload_once_paths =
|
8
|
-
#{root}/app/controllers
|
9
|
-
#{root}/app/controllers/concerns
|
10
|
-
#{root}/app/helpers
|
11
|
-
#{root}/app/models
|
12
|
-
#{root}/app/models/concerns
|
13
|
-
|
9
|
+
config.autoload_once_paths = [
|
10
|
+
"#{root}/app/controllers",
|
11
|
+
"#{root}/app/controllers/concerns",
|
12
|
+
"#{root}/app/helpers",
|
13
|
+
"#{root}/app/models",
|
14
|
+
"#{root}/app/models/concerns",
|
15
|
+
]
|
14
16
|
|
15
17
|
# If you don't want to precompile Coupdoeil's assets (eg. because you're using webpack),
|
16
18
|
# you can do this in an intiailzer:
|
@@ -24,13 +26,13 @@ module Coupdoeil
|
|
24
26
|
# config.after_initialize do
|
25
27
|
# config.assets.precompile -= %w[coupdoeil/popover-arrow.css]
|
26
28
|
# end
|
27
|
-
PRECOMPILE_ASSETS =
|
28
|
-
coupdoeil.js
|
29
|
-
coupdoeil.min.js
|
30
|
-
coupdoeil.min.js.map
|
31
|
-
coupdoeil/popover.css
|
32
|
-
coupdoeil/popover-arrow.css
|
33
|
-
coupdoeil/popover-animation.css
|
29
|
+
PRECOMPILE_ASSETS = [
|
30
|
+
"coupdoeil.js",
|
31
|
+
"coupdoeil.min.js",
|
32
|
+
"coupdoeil.min.js.map",
|
33
|
+
"coupdoeil/popover.css",
|
34
|
+
"coupdoeil/popover-arrow.css",
|
35
|
+
"coupdoeil/popover-animation.css",
|
34
36
|
]
|
35
37
|
|
36
38
|
initializer "coupdoeil.assets" do
|
@@ -40,7 +42,7 @@ module Coupdoeil
|
|
40
42
|
end
|
41
43
|
|
42
44
|
initializer "coupdoeil.logger" do
|
43
|
-
stdout_logger = ActiveSupport::Logger.new(
|
45
|
+
stdout_logger = ActiveSupport::Logger.new($stdout)
|
44
46
|
stdout_logger.formatter = ::Logger::Formatter.new
|
45
47
|
tagged_stdout_logger = ActiveSupport::TaggedLogging.new(stdout_logger)
|
46
48
|
config.coupdoeil.logger = tagged_stdout_logger.tagged("Coupdoeil")
|
data/lib/coupdoeil/version.rb
CHANGED
data/lib/coupdoeil.rb
CHANGED
@@ -1,83 +1,87 @@
|
|
1
|
-
|
2
|
-
Coupdoeil::InstallGenerator.source_root Coupdoeil::Engine.root.join("lib/generators/coupdoeil/install/templates")
|
1
|
+
# frozen_string_literal: true
|
3
2
|
|
4
|
-
|
3
|
+
module Coupdoeil
|
4
|
+
class InstallGenerator < Rails::Generators::Base
|
5
|
+
Coupdoeil::InstallGenerator.source_root(Coupdoeil::Engine.root.join("lib/generators/coupdoeil/install/templates"))
|
5
6
|
|
6
|
-
|
7
|
-
create_file "app/popovers/application_popover.rb", <<~RUBY
|
8
|
-
class ApplicationPopover < Coupdoeil::Popover
|
9
|
-
end
|
10
|
-
RUBY
|
11
|
-
end
|
7
|
+
desc "Create base class for popovers and default layout."
|
12
8
|
|
13
|
-
|
14
|
-
|
15
|
-
|
9
|
+
def create_base_class
|
10
|
+
create_file("app/popovers/application_popover.rb", <<~RUBY)
|
11
|
+
class ApplicationPopover < Coupdoeil::Popover
|
12
|
+
end
|
13
|
+
RUBY
|
14
|
+
end
|
16
15
|
|
17
|
-
|
18
|
-
|
19
|
-
if Rails.root.join("config/importmap.rb").exist?
|
20
|
-
append_to_importmap
|
21
|
-
elsif Rails.root.join("package.json").exist?
|
22
|
-
add_with_node
|
23
|
-
else
|
24
|
-
puts "You must either be running with node (package.json) or importmap-rails (config/importmap.rb) to use this gem."
|
16
|
+
def insert_default_layout
|
17
|
+
template("layout.html.erb.tt", "app/popovers/layouts/popover.html.erb")
|
25
18
|
end
|
26
|
-
end
|
27
19
|
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
20
|
+
def install_javascripts
|
21
|
+
puts ""
|
22
|
+
if Rails.root.join("config/importmap.rb").exist?
|
23
|
+
append_to_importmap
|
24
|
+
elsif Rails.root.join("package.json").exist?
|
25
|
+
add_with_node
|
26
|
+
else
|
27
|
+
puts "You must either be running with node (package.json) or importmap-rails (config/importmap.rb) to use this gem."
|
28
|
+
end
|
29
|
+
end
|
33
30
|
|
34
|
-
|
31
|
+
def install_stylesheets
|
32
|
+
puts ""
|
33
|
+
import_stylesheet
|
34
|
+
hidden_class_requirement
|
35
|
+
end
|
35
36
|
|
36
|
-
|
37
|
-
puts "Using importmap"
|
38
|
-
puts "Pin Coupdoeil"
|
39
|
-
append_to_file "config/importmap.rb", %(pin "coupdoeil", to: "coupdoeil.min.js", preload: true\n)
|
37
|
+
private
|
40
38
|
|
41
|
-
|
42
|
-
|
43
|
-
|
39
|
+
def append_to_importmap
|
40
|
+
puts "Using importmap"
|
41
|
+
puts "Pin Coupdoeil"
|
42
|
+
append_to_file("config/importmap.rb", %(pin "coupdoeil", to: "coupdoeil.min.js", preload: true\n))
|
44
43
|
|
45
|
-
|
46
|
-
|
47
|
-
say "Import Coupdoeil"
|
48
|
-
append_to_file "app/javascript/application.js", %(import "coupdoeil"\n)
|
49
|
-
else
|
50
|
-
say "You must import coupdoeil in your JavaScript entrypoint file", :red
|
44
|
+
puts "Import Coupdoeil"
|
45
|
+
append_to_file("app/javascript/application.js", %(import "coupdoeil"\n))
|
51
46
|
end
|
52
47
|
|
53
|
-
|
54
|
-
|
55
|
-
|
48
|
+
def add_with_node
|
49
|
+
if Rails.root.join("app/javascript/application.js").exist?
|
50
|
+
say("Import Coupdoeil")
|
51
|
+
append_to_file("app/javascript/application.js", %(import "coupdoeil"\n))
|
52
|
+
else
|
53
|
+
say("You must import coupdoeil in your JavaScript entrypoint file", :red)
|
54
|
+
end
|
55
|
+
|
56
|
+
say("Install Coupdoeil")
|
57
|
+
run("yarn add coupdoeil")
|
58
|
+
end
|
56
59
|
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
60
|
+
def import_stylesheet
|
61
|
+
puts "To use Coupdoeil popover style, add to your layout's head:"
|
62
|
+
puts ""
|
63
|
+
puts <<-ERB
|
61
64
|
<%= stylesheet_link_tag "coupdoeil/popover" %>
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
65
|
+
ERB
|
66
|
+
puts ""
|
67
|
+
puts "Or one of two:"
|
68
|
+
puts ""
|
69
|
+
puts <<-ERB
|
67
70
|
<%= stylesheet_link_tag "coupdoeil/popover-arrow" %>
|
68
71
|
<%= stylesheet_link_tag "coupdoeil/popover-animation" %>
|
69
|
-
|
70
|
-
|
72
|
+
ERB
|
73
|
+
end
|
71
74
|
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
75
|
+
def hidden_class_requirement
|
76
|
+
puts ""
|
77
|
+
puts "Also make sure you have a CSS implementation of .hidden class:"
|
78
|
+
puts ""
|
79
|
+
puts <<-CSS
|
77
80
|
.hidden {
|
78
81
|
display: none;
|
79
82
|
}
|
80
|
-
|
81
|
-
|
83
|
+
CSS
|
84
|
+
puts ""
|
85
|
+
end
|
82
86
|
end
|
83
87
|
end
|
@@ -1,21 +1,27 @@
|
|
1
|
-
|
2
|
-
source_root File.expand_path("templates", __dir__)
|
1
|
+
# frozen_string_literal: true
|
3
2
|
|
4
|
-
|
3
|
+
module Coupdoeil
|
4
|
+
class PopoverGenerator < Rails::Generators::NamedBase
|
5
|
+
source_root File.expand_path("templates", __dir__)
|
5
6
|
|
6
|
-
|
7
|
+
check_class_collision suffix: "Popover"
|
7
8
|
|
8
|
-
|
9
|
+
class_option :skip_views, type: :boolean, desc: "Skip view files", default: false
|
9
10
|
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
11
|
+
argument :action_names, type: :array, default: []
|
12
|
+
|
13
|
+
def create_popover_file
|
14
|
+
template(
|
15
|
+
"popover.rb",
|
16
|
+
File.join("app/popovers", class_path, "#{file_name}_popover.rb"),
|
17
|
+
)
|
18
|
+
unless options.skip_views?
|
19
|
+
action_names.each do |action_name|
|
20
|
+
path = [*class_path, file_name].join("/")
|
21
|
+
create_file("app/popovers/#{path}_popover/#{action_name}.html.erb", <<~ERB)
|
22
|
+
<p>Hello from #{class_name}Popover##{action_name}</p>
|
23
|
+
ERB
|
24
|
+
end
|
19
25
|
end
|
20
26
|
end
|
21
27
|
end
|