coprl 3.0.0.beta.2 → 3.0.0.beta.3
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 +20 -0
- data/Gemfile +5 -0
- data/Gemfile.lock +31 -0
- data/app/demo/components/nav/menu.pom +0 -1
- data/app/demo/plugins/cacheable.pom +64 -0
- data/app/demo/plugins/google_maps.pom +24 -0
- data/app/demo/plugins/image_crop.pom +1 -1
- data/app/demo/plugins/nav/drawer.pom +1 -1
- data/app/demo/plugins/script.pom +17 -0
- data/app/demo/plugins/scroll_to.pom +22 -0
- data/app/demo/shared/context_list.pom +1 -1
- data/config.ru +15 -1
- data/lib/coprl/presenters/cli.rb +10 -0
- data/lib/coprl/presenters/dsl/components/event.rb +6 -1
- data/lib/coprl/presenters/generators/plugin.rb +20 -6
- data/lib/coprl/presenters/generators/templates/plugin/.github/workflows/semantic-release.yml +41 -0
- data/lib/coprl/presenters/generators/templates/plugin/.releaserc +15 -0
- data/lib/coprl/presenters/generators/templates/plugin/.ruby-version +1 -0
- data/lib/coprl/presenters/generators/templates/plugin/README.md.tt +34 -0
- data/lib/coprl/presenters/generators/templates/plugin/demo/plugin.pom.tt +15 -0
- data/lib/coprl/presenters/generators/templates/plugin/lib/coprl/presenters/plugins/components/actions/dsl.rb.tt +1 -1
- data/lib/coprl/presenters/generators/templates/plugin/lib/coprl/presenters/plugins/version.rb.tt +3 -0
- data/lib/coprl/presenters/generators/templates/plugin/presenter_plugin.gemspec.tt +8 -7
- data/lib/coprl/presenters/generators/templates/plugin/views/components/application/component.erb.tt +1 -1
- data/lib/coprl/presenters/settings.rb +1 -1
- data/lib/coprl/presenters/version.rb +1 -1
- data/rails-engine/app/controllers/coprl_controller.rb +18 -1
- data/rails-engine/config/initializers/session.rb +8 -0
- data/views/mdc/components/unordered_list/_list_item.erb +3 -3
- metadata +13 -7
- data/app/demo/components/google_maps.pom +0 -22
- data/lib/coprl/presenters/generators/templates/plugin/README.md +0 -253
- data/lib/coprl/presenters/plugins/google_maps.rb +0 -24
- data/lib/coprl/presenters/plugins/google_maps/google_map.erb +0 -10
- data/lib/coprl/presenters/plugins/google_maps/google_map.rb +0 -41
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 7d7518e53fa8334d12c57f9221559528d01368548e0806077042e232c47cf6d4
|
|
4
|
+
data.tar.gz: c7cbe113161ae098b0a789827edc1233d1a59299d6bdbc618a077c66b8cb85a0
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: f1b6b99fc482af03d45152745a7969cc190cf9948f116d8026a7623d8c4a11cd4fcfef7a66894b262e8110aa960f15bdec72c91913a4dc3ba0473ee4b640147e
|
|
7
|
+
data.tar.gz: a3d7dd1e766e3fc1e8f619f8abc658cf8dd0a887eee46068f9e147540768e6927e50cdb129346d79bc14402f960064d3df00608e15af8e3633e90d3347bb9ec4
|
data/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,23 @@
|
|
|
1
|
+
# [3.0.0-beta.3](https://github.com/rx/presenters/compare/v3.0.0-beta.2...v3.0.0-beta.3) (2021-06-07)
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
### Bug Fixes
|
|
5
|
+
|
|
6
|
+
* added cli --version ([4c5b10e](https://github.com/rx/presenters/commit/4c5b10e0707bcdeecfb29908eb3284b692cbcd41))
|
|
7
|
+
* added missing prepare context callbacks to Rails Engine ([bafa36d](https://github.com/rx/presenters/commit/bafa36d6e95ad9863eb93cb44cc894163c147c4f))
|
|
8
|
+
* added prepare context for Rails native views engine that sets the request and session automatically ([a09f3c6](https://github.com/rx/presenters/commit/a09f3c637102e640fe0b91894ae89b5a07288846))
|
|
9
|
+
* Added version.rb to plugin generator ([f1f2092](https://github.com/rx/presenters/commit/f1f20925dfd326fb5a47910952e21b34b762c31d))
|
|
10
|
+
* Added version.rb to plugin generator ([35187bf](https://github.com/rx/presenters/commit/35187bf188957e2ca93e2bf07963e958452f27fe))
|
|
11
|
+
* expanded plugin generator to include github semantic release, demo pom and sample README ([06de7a2](https://github.com/rx/presenters/commit/06de7a237f8a417a11776d1994915c32253a981d))
|
|
12
|
+
* fixed unordered list partial rendering error ([014f1d1](https://github.com/rx/presenters/commit/014f1d19926d7e9d39618fbe68c8068db316ac4b))
|
|
13
|
+
* generator not compatible with COPRL 3 Rails templating naming conventions ([f6d80f0](https://github.com/rx/presenters/commit/f6d80f0a44f6305b9339bc2bd6db8487eefc68cc))
|
|
14
|
+
* removed google_map built in plugin to its own plugin ([a34290d](https://github.com/rx/presenters/commit/a34290de890e2fdf7e6c2c7b1714854d454c82a4))
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
### Features
|
|
18
|
+
|
|
19
|
+
* Added singular alias for common actions: load, replace, post, create, and delete ([b57c305](https://github.com/rx/presenters/commit/b57c305bd4dbf95b8a9662ad747020683bf74c8d))
|
|
20
|
+
|
|
1
21
|
# [3.0.0-beta.2](https://github.com/rx/presenters/compare/v3.0.0-beta.1...v3.0.0-beta.2) (2021-06-03)
|
|
2
22
|
|
|
3
23
|
|
data/Gemfile
CHANGED
|
@@ -24,7 +24,12 @@ end
|
|
|
24
24
|
gem 'foo_presenter_plugin', github: 'coprl/foo_presenter_plugin', require: false
|
|
25
25
|
gem 'image_crop_presenter_plugin', github: 'coprl/image_crop_presenter_plugin', require: false
|
|
26
26
|
gem 'chart_presenter_plugin', github: 'coprl/chart_presenter_plugin', require: false
|
|
27
|
+
gem 'google_maps_presenter_plugin', github: 'coprl/google_maps_presenter_plugin', branch: :main, require: false
|
|
28
|
+
gem 'cacheable_presenter_plugin', github: 'coprl/cacheable_presenter_plugin', require: false
|
|
29
|
+
gem 'script_presenter_plugin', github: 'coprl/script_presenter_plugin', require: false
|
|
30
|
+
gem 'scroll_to_presenter_plugin', github: 'coprl/scroll_to_presenter_plugin', require: false
|
|
27
31
|
|
|
28
32
|
gem 'rack-cors'
|
|
29
33
|
gem 'honeybadger' if ENV.fetch('HONEYBADGER_API_KEY'){false}
|
|
30
34
|
gem 'puma'
|
|
35
|
+
gem 'dotenv'
|
data/Gemfile.lock
CHANGED
|
@@ -1,3 +1,9 @@
|
|
|
1
|
+
GIT
|
|
2
|
+
remote: https://github.com/coprl/cacheable_presenter_plugin.git
|
|
3
|
+
revision: 262ac076d70d94b111b9ccb692dfc9225c7cc6c6
|
|
4
|
+
specs:
|
|
5
|
+
cacheable_presenter_plugin (0.0.3)
|
|
6
|
+
|
|
1
7
|
GIT
|
|
2
8
|
remote: https://github.com/coprl/chart_presenter_plugin.git
|
|
3
9
|
revision: ae9a8bb805570dbf2c1156e3c81f07e3a24807e2
|
|
@@ -10,12 +16,31 @@ GIT
|
|
|
10
16
|
specs:
|
|
11
17
|
foo_presenter_plugin (0.0.2)
|
|
12
18
|
|
|
19
|
+
GIT
|
|
20
|
+
remote: https://github.com/coprl/google_maps_presenter_plugin.git
|
|
21
|
+
revision: 237d956ce36b6c9945080088e4d9e5a2f042ee5b
|
|
22
|
+
branch: main
|
|
23
|
+
specs:
|
|
24
|
+
google_maps_presenter_plugin (0.1.0)
|
|
25
|
+
|
|
13
26
|
GIT
|
|
14
27
|
remote: https://github.com/coprl/image_crop_presenter_plugin.git
|
|
15
28
|
revision: 33452c5d3b232e93a942280f8429be2707c992ab
|
|
16
29
|
specs:
|
|
17
30
|
image_crop_presenter_plugin (0.1.0)
|
|
18
31
|
|
|
32
|
+
GIT
|
|
33
|
+
remote: https://github.com/coprl/script_presenter_plugin.git
|
|
34
|
+
revision: c7cea03e73f4752a3df99e4b3ab0d4030f141f4d
|
|
35
|
+
specs:
|
|
36
|
+
script_presenter_plugin (0.0.2)
|
|
37
|
+
|
|
38
|
+
GIT
|
|
39
|
+
remote: https://github.com/coprl/scroll_to_presenter_plugin.git
|
|
40
|
+
revision: e1dd957723561117ee45743ac9e27a4fd91a4a97
|
|
41
|
+
specs:
|
|
42
|
+
scroll_to_presenter_plugin (0.0.2)
|
|
43
|
+
|
|
19
44
|
PATH
|
|
20
45
|
remote: .
|
|
21
46
|
specs:
|
|
@@ -40,6 +65,7 @@ GEM
|
|
|
40
65
|
concurrent-ruby (1.1.8)
|
|
41
66
|
diff-lcs (1.3)
|
|
42
67
|
docile (1.3.1)
|
|
68
|
+
dotenv (2.7.6)
|
|
43
69
|
dry-configurable (0.12.1)
|
|
44
70
|
concurrent-ruby (~> 1.0)
|
|
45
71
|
dry-core (~> 0.5, >= 0.5.0)
|
|
@@ -143,10 +169,13 @@ PLATFORMS
|
|
|
143
169
|
|
|
144
170
|
DEPENDENCIES
|
|
145
171
|
bundler (>= 1.13)
|
|
172
|
+
cacheable_presenter_plugin!
|
|
146
173
|
chart_presenter_plugin!
|
|
147
174
|
coprl!
|
|
175
|
+
dotenv
|
|
148
176
|
foo_presenter_plugin!
|
|
149
177
|
gem-release (~> 2.0)
|
|
178
|
+
google_maps_presenter_plugin!
|
|
150
179
|
image_crop_presenter_plugin!
|
|
151
180
|
pry
|
|
152
181
|
pry-byebug
|
|
@@ -158,6 +187,8 @@ DEPENDENCIES
|
|
|
158
187
|
rspec
|
|
159
188
|
rspec-html-matchers
|
|
160
189
|
rspec_junit_formatter
|
|
190
|
+
script_presenter_plugin!
|
|
191
|
+
scroll_to_presenter_plugin!
|
|
161
192
|
shotgun (~> 0.9)
|
|
162
193
|
simplecov
|
|
163
194
|
thor (~> 1.1.0)
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
require 'ostruct'
|
|
2
|
+
|
|
3
|
+
Coprl::Presenters.define(:cacheable, namespace: :plugins) do
|
|
4
|
+
helpers Demo::Helpers::IndentedGrid
|
|
5
|
+
attach :top_nav
|
|
6
|
+
attach :plugin_drawer
|
|
7
|
+
plugin :cacheable
|
|
8
|
+
|
|
9
|
+
page_title 'Cacheable'
|
|
10
|
+
|
|
11
|
+
helpers do
|
|
12
|
+
def cache_object
|
|
13
|
+
OpenStruct.new(cache_key: 'wild')
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def cache_objects
|
|
17
|
+
[
|
|
18
|
+
OpenStruct.new(cache_key: 'abc'),
|
|
19
|
+
OpenStruct.new(cache_key: '123'),
|
|
20
|
+
]
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
indented_grid do
|
|
25
|
+
body <<~DOC
|
|
26
|
+
The caching plugin provides russian doll caching support.
|
|
27
|
+
Declare the plugin in your pom, `plugin :cacheable`, or configure it globally:
|
|
28
|
+
|
|
29
|
+
```
|
|
30
|
+
Coprl::Presenters::Settings.configure do |config|
|
|
31
|
+
config.presenters.plugins.push(:cacheable)
|
|
32
|
+
end
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
For Rails it automatically uses the Rails::Cache. For other Rack apps you need to configure it with a block:
|
|
36
|
+
|
|
37
|
+
```
|
|
38
|
+
Coprl::Presenters::Plugins::Cacheable::Settings.configure do |config|
|
|
39
|
+
# A cache needs to respond to fetch(key, &block) and exist?(key) or has_key?(key)
|
|
40
|
+
config.cache=cache_store
|
|
41
|
+
end
|
|
42
|
+
```
|
|
43
|
+
Simply wrap your POM with the cache directive.
|
|
44
|
+
Complex keys are supported. If an object responds to `cache_key` then that will be used for it.
|
|
45
|
+
An object that responds to `map` will be expanded. As a last resort `to_s` is used.
|
|
46
|
+
|
|
47
|
+
Examples (refresh your browser to observe cached values):
|
|
48
|
+
DOC
|
|
49
|
+
title "Not cached at #{DateTime.now}"
|
|
50
|
+
cache :remember_me do
|
|
51
|
+
title "Simple Cache Key - cached at #{DateTime.now}"
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
cache [:title, cache_object, cache_objects] do
|
|
55
|
+
title "Complex Cache Key - cached at #{DateTime.now}"
|
|
56
|
+
end
|
|
57
|
+
blank
|
|
58
|
+
body <<~DOC
|
|
59
|
+
Note: Confusion alert ... if you are using shotgun for the demo, it **will not cache**, since the demo uses an in memory cache and shotgun reloads its entire process with each refresh.
|
|
60
|
+
DOC
|
|
61
|
+
|
|
62
|
+
end
|
|
63
|
+
attach :code, file: __FILE__
|
|
64
|
+
end
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
Coprl::Presenters.define(:google_maps, namespace: :plugins) do
|
|
2
|
+
helpers Demo::Helpers::IndentedGrid
|
|
3
|
+
attach :top_nav
|
|
4
|
+
attach :plugin_drawer
|
|
5
|
+
plugin :google_maps
|
|
6
|
+
page_title 'Maps'
|
|
7
|
+
|
|
8
|
+
indented_grid do
|
|
9
|
+
unless ENV['GOOGLE_API_KEY']
|
|
10
|
+
headline 'You must define the ENV variable GOOGLE_API_KEY for this to render a map'
|
|
11
|
+
subtitle 'Dev hint: Create an .env file with a `GOOGLE_API_KEY=yourkey` and restart. Goto [Google Using API Keys](https://developers.google.com/maps/documentation/javascript/get-api-key) to create a key.'
|
|
12
|
+
end
|
|
13
|
+
subheading 'Static Maps'
|
|
14
|
+
address = '125 Park Street, Traverse City, MI'
|
|
15
|
+
google_map address: address, height: "300px", width: "400px" do
|
|
16
|
+
event :click do
|
|
17
|
+
loads "https://www.google.com/maps/place/#{address}"
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
attach :code, file: __FILE__
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
end
|
|
@@ -7,7 +7,7 @@ Coprl::Presenters.define(:plugin_drawer, namespace: :plugins) do
|
|
|
7
7
|
loads :index
|
|
8
8
|
end
|
|
9
9
|
end
|
|
10
|
-
%i(image_crop chart).sort.each do |comp|
|
|
10
|
+
%i(image_crop chart google_maps cacheable script scroll_to).sort.each do |comp|
|
|
11
11
|
item titleize(comp) do
|
|
12
12
|
event :click do
|
|
13
13
|
loads comp
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
Coprl::Presenters.define(:script, namespace: :plugins) do
|
|
2
|
+
helpers Demo::Helpers::IndentedGrid
|
|
3
|
+
attach :top_nav
|
|
4
|
+
attach :plugin_drawer
|
|
5
|
+
plugin :script
|
|
6
|
+
page_title 'Script'
|
|
7
|
+
|
|
8
|
+
script inline: <<~JAVASCRIPT
|
|
9
|
+
alert( 'Hello, world!' );
|
|
10
|
+
JAVASCRIPT
|
|
11
|
+
indented_grid do
|
|
12
|
+
subheading 'You can write arbitrary javascript using the script component. For example, the alert you just dismissed.'
|
|
13
|
+
|
|
14
|
+
attach :code, file: __FILE__
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
end
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
Coprl::Presenters.define(:scroll_to, namespace: :plugins) do
|
|
2
|
+
helpers Demo::Helpers::IndentedGrid
|
|
3
|
+
attach :top_nav
|
|
4
|
+
attach :plugin_drawer
|
|
5
|
+
plugin :scroll_to
|
|
6
|
+
page_title 'Scroll to'
|
|
7
|
+
|
|
8
|
+
indented_grid do
|
|
9
|
+
subheading 'Sometimes you need to scroll to find content after some action. This is what the scroll to plugin is for.'
|
|
10
|
+
button :scroll do
|
|
11
|
+
event :click do
|
|
12
|
+
scroll_to :scroll_target #, smooth: true, offset: 100
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
(1..100).each do
|
|
16
|
+
body '.'
|
|
17
|
+
end
|
|
18
|
+
title 'Thanks for scrolling here', id: :scroll_target
|
|
19
|
+
|
|
20
|
+
attach :code, file: __FILE__
|
|
21
|
+
end
|
|
22
|
+
end
|
|
@@ -9,7 +9,7 @@ Coprl::Presenters.define(:context_list) do
|
|
|
9
9
|
end
|
|
10
10
|
|
|
11
11
|
def scrubbed_context
|
|
12
|
-
scrubbed_keys = context.fetch(:exclude) {%w{title file hide_time _presenter_ _namespace1_ session}}
|
|
12
|
+
scrubbed_keys = context.fetch(:exclude) {%w{title file hide_time _presenter_ _namespace1_ session request controller action presenter}}
|
|
13
13
|
context.select {|k, _| !scrubbed_keys.include?(k.to_s)}
|
|
14
14
|
end
|
|
15
15
|
end
|
data/config.ru
CHANGED
|
@@ -9,7 +9,7 @@ if ENV['VOOM_ENV'] == 'integration_testing'
|
|
|
9
9
|
end
|
|
10
10
|
|
|
11
11
|
ENV['VOOM_ROOT'] = File.expand_path(__dir__)
|
|
12
|
-
|
|
12
|
+
require 'dotenv/load'
|
|
13
13
|
require 'coprl'
|
|
14
14
|
|
|
15
15
|
require 'rack/cors'
|
|
@@ -27,6 +27,20 @@ Coprl::Presenters::Settings.configure do |config|
|
|
|
27
27
|
}
|
|
28
28
|
end
|
|
29
29
|
|
|
30
|
+
require 'pry'
|
|
31
|
+
require 'coprl/presenters/plugins/cacheable'
|
|
32
|
+
cache_store = Concurrent::Hash.new
|
|
33
|
+
# Quick and dirty demo always growing memory cache -- DONT DO THIS IN PRODUCTION!
|
|
34
|
+
def cache_store.fetch(key, options=nil, &block)
|
|
35
|
+
result = super(key, &block)
|
|
36
|
+
store(key, result) unless has_key?(key)
|
|
37
|
+
result
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
Coprl::Presenters::Plugins::Cacheable::Settings.configure do |config|
|
|
41
|
+
config.cache=cache_store
|
|
42
|
+
end
|
|
43
|
+
|
|
30
44
|
use Coprl::Presenters::Demo::Search
|
|
31
45
|
use Coprl::Presenters::Demo::Echo
|
|
32
46
|
use Coprl::Presenters::Demo::Slow
|
data/lib/coprl/presenters/cli.rb
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
require 'thor'
|
|
2
2
|
require_relative 'generators/plugin'
|
|
3
|
+
require_relative 'version'
|
|
3
4
|
|
|
4
5
|
module Coprl
|
|
5
6
|
module Presenters
|
|
@@ -20,6 +21,15 @@ module Coprl
|
|
|
20
21
|
end
|
|
21
22
|
end
|
|
22
23
|
class Cli < Thor
|
|
24
|
+
def self.exit_on_failure?
|
|
25
|
+
true
|
|
26
|
+
end
|
|
27
|
+
map %w[--version -v] => :__print_version
|
|
28
|
+
|
|
29
|
+
desc "--version, -v", "print the version"
|
|
30
|
+
def __print_version
|
|
31
|
+
puts Coprl::Presenters::Version::VERSION
|
|
32
|
+
end
|
|
23
33
|
desc "generate", "generate a plugin"
|
|
24
34
|
subcommand "generate", Generate
|
|
25
35
|
end
|
|
@@ -27,6 +27,7 @@ module Coprl
|
|
|
27
27
|
wait_for_download: wait_for_download,
|
|
28
28
|
params: params, &block)
|
|
29
29
|
end
|
|
30
|
+
alias load loads
|
|
30
31
|
|
|
31
32
|
def replaces(target, presenter, input_tag: nil, ignore_input_values: [], **params, &block)
|
|
32
33
|
self << Actions::Replaces.new(parent: self,
|
|
@@ -36,6 +37,7 @@ module Coprl
|
|
|
36
37
|
ignore_input_values: Array(ignore_input_values),
|
|
37
38
|
params: params, &block)
|
|
38
39
|
end
|
|
40
|
+
alias replace replaces
|
|
39
41
|
|
|
40
42
|
# Method can be one of :post, :put, :delete or :patch
|
|
41
43
|
def posts(path, input_tag: nil, headers: nil, **params, &block)
|
|
@@ -45,8 +47,10 @@ module Coprl
|
|
|
45
47
|
headers: headers,
|
|
46
48
|
params: params, &block)
|
|
47
49
|
end
|
|
48
|
-
|
|
50
|
+
alias post posts
|
|
49
51
|
alias creates posts
|
|
52
|
+
alias create posts
|
|
53
|
+
|
|
50
54
|
|
|
51
55
|
def updates(path, input_tag: nil, headers: nil, **params, &block)
|
|
52
56
|
self << Actions::Updates.new(parent: self,
|
|
@@ -63,6 +67,7 @@ module Coprl
|
|
|
63
67
|
headers: headers,
|
|
64
68
|
params: params, &block)
|
|
65
69
|
end
|
|
70
|
+
alias delete deletes
|
|
66
71
|
|
|
67
72
|
def dialog(dialog_id, **params, &block)
|
|
68
73
|
self << Actions::Dialog.new(parent: self,
|
|
@@ -32,13 +32,13 @@ module Coprl
|
|
|
32
32
|
|
|
33
33
|
def template_file(template, target_filename=template, source_path=nil, target_path=source_path)
|
|
34
34
|
source = join_path(TEMPLATES_ROOT, source_path, "#{template}.tt")
|
|
35
|
-
destination = join_path(
|
|
35
|
+
destination = join_path(plugin_name, target_path, target_filename)
|
|
36
36
|
template source, destination
|
|
37
37
|
end
|
|
38
38
|
|
|
39
39
|
def file(file, target_filename=file, source_path=nil, target_path=nil)
|
|
40
40
|
source = join_path(TEMPLATES_ROOT, source_path, file)
|
|
41
|
-
destination = join_path(
|
|
41
|
+
destination = join_path(plugin_name, target_path, target_filename)
|
|
42
42
|
|
|
43
43
|
copy_file source, destination
|
|
44
44
|
end
|
|
@@ -59,17 +59,27 @@ module Coprl
|
|
|
59
59
|
underscore(name)
|
|
60
60
|
end
|
|
61
61
|
|
|
62
|
-
def
|
|
62
|
+
def plugin_name
|
|
63
63
|
"#{underscored_name}_presenter_plugin"
|
|
64
64
|
end
|
|
65
65
|
end
|
|
66
66
|
|
|
67
|
+
def create_version
|
|
68
|
+
template_file('version.rb', "version.rb", LIB_ROOT, "lib/#{underscored_name}_presenter_plugin")
|
|
69
|
+
end
|
|
70
|
+
|
|
67
71
|
def create_root_files
|
|
68
72
|
file('.gitignore')
|
|
69
73
|
template_file('Gemfile')
|
|
70
74
|
template_file('LICENSE.txt')
|
|
71
75
|
template_file('presenter_plugin.gemspec', "#{underscored_name}_presenter_plugin.gemspec")
|
|
72
|
-
|
|
76
|
+
template_file 'README.md'
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
def create_semantic_release_github_action
|
|
80
|
+
file('.releaserc')
|
|
81
|
+
file('.ruby-version')
|
|
82
|
+
file('semantic-release.yml', 'semantic-release.yml', dir('.github', 'workflows'))
|
|
73
83
|
end
|
|
74
84
|
|
|
75
85
|
def create_plugin
|
|
@@ -90,9 +100,9 @@ module Coprl
|
|
|
90
100
|
dir('views', 'assets', 'css', 'components'))
|
|
91
101
|
template_file('component.js', "#{underscored_name}.js",
|
|
92
102
|
dir('views', 'assets', 'js', 'components'))
|
|
93
|
-
template_file('component.erb', "#{underscored_name}.erb",
|
|
103
|
+
template_file('component.erb', "_#{underscored_name}.erb",
|
|
94
104
|
dir('views', 'components', 'application'))
|
|
95
|
-
template_file('component_header.erb', "#{underscored_name}_header.erb",
|
|
105
|
+
template_file('component_header.erb', "_#{underscored_name}_header.erb",
|
|
96
106
|
dir('views', 'components', 'application'))
|
|
97
107
|
end
|
|
98
108
|
|
|
@@ -115,6 +125,10 @@ module Coprl
|
|
|
115
125
|
lib_dir('helpers'),
|
|
116
126
|
named_dir('helpers'))
|
|
117
127
|
end
|
|
128
|
+
|
|
129
|
+
def create_demo_pom
|
|
130
|
+
template_file('plugin.pom', "#{underscored_name}.pom", dir('demo'))
|
|
131
|
+
end
|
|
118
132
|
end
|
|
119
133
|
end
|
|
120
134
|
end
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
name: CI
|
|
2
|
+
|
|
3
|
+
# Controls when the action will run.
|
|
4
|
+
on:
|
|
5
|
+
# Triggers the workflow on push or pull request events but only for the master branch
|
|
6
|
+
push:
|
|
7
|
+
branches: [ master ]
|
|
8
|
+
pull_request:
|
|
9
|
+
branches: [ master ]
|
|
10
|
+
|
|
11
|
+
# Allows you to run this workflow manually from the Actions tab
|
|
12
|
+
workflow_dispatch:
|
|
13
|
+
|
|
14
|
+
# A workflow run is made up of one or more jobs that can run sequentially or in parallel
|
|
15
|
+
jobs:
|
|
16
|
+
# This workflow contains a single job called "build"
|
|
17
|
+
build:
|
|
18
|
+
# The type of runner that the job will run on
|
|
19
|
+
runs-on: ubuntu-latest
|
|
20
|
+
|
|
21
|
+
# Steps represent a sequence of tasks that will be executed as part of the job
|
|
22
|
+
steps:
|
|
23
|
+
- name: Checkout
|
|
24
|
+
uses: actions/checkout@v2
|
|
25
|
+
- name: Setup Ruby
|
|
26
|
+
uses: ruby/setup-ruby@v1
|
|
27
|
+
with:
|
|
28
|
+
bundler-cache: true # runs 'bundle install' and caches installed gems automatically
|
|
29
|
+
- name: Semantic Release
|
|
30
|
+
uses: cycjimmy/semantic-release-action@v2
|
|
31
|
+
with:
|
|
32
|
+
extra_plugins: |
|
|
33
|
+
@semantic-release/git
|
|
34
|
+
@semantic-release/changelog
|
|
35
|
+
@semantic-release/github
|
|
36
|
+
semantic-release-rubygem
|
|
37
|
+
dry_run: false
|
|
38
|
+
env:
|
|
39
|
+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
40
|
+
GEM_HOST_API_KEY: ${{ secrets.GEM_HOST_API_KEY }}
|
|
41
|
+
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
{
|
|
2
|
+
"branches": ['+([0-9])?(.{+([0-9]),x}).x', 'master', 'next', 'next-major', {name: 'beta', prerelease: true}, {name: 'alpha', prerelease: true}],
|
|
3
|
+
"plugins": [
|
|
4
|
+
"@semantic-release/commit-analyzer",
|
|
5
|
+
"@semantic-release/release-notes-generator",
|
|
6
|
+
"@semantic-release/changelog",
|
|
7
|
+
"@semantic-release/github",
|
|
8
|
+
["semantic-release-rubygem",
|
|
9
|
+
{
|
|
10
|
+
"gemPublish": false
|
|
11
|
+
}
|
|
12
|
+
],
|
|
13
|
+
"@semantic-release/git"
|
|
14
|
+
]
|
|
15
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
2.7.2
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
# <%= humanize(name) %> Presenter Plugin
|
|
2
|
+
|
|
3
|
+
A [COPRL](http://github.com/coprl/coprl) presenter plugin that <%= name %>
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
Add this line to your application's Gemfile:
|
|
8
|
+
|
|
9
|
+
```ruby
|
|
10
|
+
gem '<%= name %>_presenter_plugin', git: 'https://github.com/coprl/<%= name %>_presenter_plugin', require: false
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
And then execute:
|
|
14
|
+
|
|
15
|
+
$ bundle
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
## Usage in POMs
|
|
19
|
+
|
|
20
|
+
Declare the plugin in your pom, `plugin :<%= name %>`.
|
|
21
|
+
|
|
22
|
+
TODO: Add an example POM and describe your plugin here
|
|
23
|
+
|
|
24
|
+
## Contributing
|
|
25
|
+
|
|
26
|
+
Bug reports and pull requests are welcome on GitHub at https://github.com/coprl/<%= name %>_presenter_plugin.
|
|
27
|
+
|
|
28
|
+
## License
|
|
29
|
+
|
|
30
|
+
The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
|
|
31
|
+
|
|
32
|
+
## Code of Conduct
|
|
33
|
+
|
|
34
|
+
Everyone interacting in the COPRL project’s codebases, issue trackers, chat rooms and mailing lists is expected to follow the [code of conduct](https://github.com/coprl/coprl/blob/master/CODE-OF-CONDUCT.md).
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
Coprl::Presenters.define(:<%= name %>, namespace: :plugins) do
|
|
2
|
+
helpers Demo::Helpers::IndentedGrid
|
|
3
|
+
attach :top_nav
|
|
4
|
+
attach :plugin_drawer
|
|
5
|
+
plugin :<%= name %>
|
|
6
|
+
page_title '<%= humanize(name) %>'
|
|
7
|
+
|
|
8
|
+
<%= name %> # TODO Add your demo code here
|
|
9
|
+
|
|
10
|
+
indented_grid do
|
|
11
|
+
subheading 'TODO describe how to use your plugin'
|
|
12
|
+
|
|
13
|
+
attach :code, file: __FILE__
|
|
14
|
+
end
|
|
15
|
+
end
|
|
@@ -1,21 +1,22 @@
|
|
|
1
1
|
lib = File.expand_path("../lib", __FILE__)
|
|
2
2
|
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
|
3
|
+
require '<%= name %>_presenter_plugin/version'
|
|
3
4
|
|
|
4
5
|
Gem::Specification.new do |spec|
|
|
5
|
-
spec.name =
|
|
6
|
-
spec.version =
|
|
6
|
+
spec.name = '<%= name %>_presenter_plugin'
|
|
7
|
+
spec.version = <%= classify(name) %>PresenterPlugin::VERSION
|
|
7
8
|
spec.authors = ["<%= `git config user.name`.strip %>"]
|
|
8
9
|
spec.email = ["<%= `git config user.email`.strip %>"]
|
|
9
10
|
|
|
10
|
-
spec.summary = %q{<%= name %>
|
|
11
|
+
spec.summary = %q{A COPRL presenter plugin for <%= name %>}
|
|
11
12
|
spec.homepage = 'http://github.com/<%= `git config user.name`.strip %>/<%= name %>_presenters_plugin'
|
|
12
|
-
spec.license =
|
|
13
|
+
spec.license = 'MIT'
|
|
13
14
|
|
|
14
15
|
spec.files = `git ls-files -z`.split("\x0").reject do |f|
|
|
15
16
|
f.match(%r{^(test|spec|features)/})
|
|
16
17
|
end
|
|
17
|
-
spec.require_paths = [
|
|
18
|
+
spec.require_paths = ['lib']
|
|
18
19
|
|
|
19
|
-
spec.add_development_dependency
|
|
20
|
-
spec.add_development_dependency
|
|
20
|
+
spec.add_development_dependency 'bundler', "~> 2.0"
|
|
21
|
+
spec.add_development_dependency 'rake', "~> 10.0"
|
|
21
22
|
end
|
data/lib/coprl/presenters/generators/templates/plugin/views/components/application/component.erb.tt
CHANGED
|
@@ -11,4 +11,4 @@ Any additional data you want to pass to your component javascript should be setu
|
|
|
11
11
|
-->
|
|
12
12
|
<iframe id="random_fact" class='v-plugin v-input' data-plugin-callback='RandomFacts'
|
|
13
13
|
src="<%%= comp.random_fact %>" height=512
|
|
14
|
-
<%%=
|
|
14
|
+
<%%= partial "components/event", :locals => {comp: comp, events: comp.events, parent_id: comp.id} %>></iframe>
|
|
@@ -32,7 +32,7 @@ unless defined?(Coprl::Presenters::Settings)
|
|
|
32
32
|
setting :custom_css, '../public/presenters'
|
|
33
33
|
setting :protect_from_forgery, false
|
|
34
34
|
end
|
|
35
|
-
setting :plugins, [
|
|
35
|
+
setting :plugins, []
|
|
36
36
|
setting :components do
|
|
37
37
|
setting :defaults do
|
|
38
38
|
setting :datetime do
|
|
@@ -12,7 +12,7 @@ class CoprlController < ApplicationController
|
|
|
12
12
|
fq_presenter_name = [presenter_name, 'index'].compact.join(':')
|
|
13
13
|
presenter_name = fq_presenter_name if Coprl::Presenters::App.registered?(fq_presenter_name)
|
|
14
14
|
presenter = Coprl::Presenters::App[presenter_name].call
|
|
15
|
-
context = params
|
|
15
|
+
context = prepare_context(params)
|
|
16
16
|
router = Coprl::Presenters::WebClient::Router.new(base_url: request.base_url)
|
|
17
17
|
@pom = presenter.expand(router: router, context: context)
|
|
18
18
|
end
|
|
@@ -23,4 +23,21 @@ class CoprlController < ApplicationController
|
|
|
23
23
|
prepend_view_path path
|
|
24
24
|
end
|
|
25
25
|
end
|
|
26
|
+
|
|
27
|
+
def prepare_context(base_params = params)
|
|
28
|
+
prepare_context = Coprl::Presenters::Settings.config.presenters.web_client.prepare_context.dup
|
|
29
|
+
prepare_context.push(method(:scrub_context))
|
|
30
|
+
context = base_params.dup.to_unsafe_hash
|
|
31
|
+
prepare_context.reduce(context) do |params, context_proc|
|
|
32
|
+
context = context_proc.call(params, session, request.env)
|
|
33
|
+
end
|
|
34
|
+
context
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def scrub_context(params, _session, _env)
|
|
38
|
+
%i(grid_nesting input_tag).each do |key|
|
|
39
|
+
params.delete(key) {params.delete(key.to_s)}
|
|
40
|
+
end
|
|
41
|
+
params
|
|
42
|
+
end
|
|
26
43
|
end
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
<li class="<%= 'icon-li' if list_item.icon %>">
|
|
2
|
-
<%=
|
|
2
|
+
<%= partial "components/unordered_list/icon", :locals => {:list_item => list_item} %>
|
|
3
3
|
<%= expand_text(list_item.text&.text) %>
|
|
4
4
|
<% if list_item.unordered_list %>
|
|
5
|
-
<%=
|
|
5
|
+
<%= partial "components/unordered_list", :locals => {:comp => list_item.unordered_list} %>
|
|
6
6
|
<% end %>
|
|
7
|
-
</li>
|
|
7
|
+
</li>
|
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: coprl
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 3.0.0.beta.
|
|
4
|
+
version: 3.0.0.beta.3
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Russell Edens
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: exe
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2021-06-
|
|
11
|
+
date: 2021-06-07 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: ice_nine
|
|
@@ -340,7 +340,6 @@ files:
|
|
|
340
340
|
- app/demo/components/fabs.pom
|
|
341
341
|
- app/demo/components/file_inputs.pom
|
|
342
342
|
- app/demo/components/footers.pom
|
|
343
|
-
- app/demo/components/google_maps.pom
|
|
344
343
|
- app/demo/components/headers.pom
|
|
345
344
|
- app/demo/components/hidden_fields.pom
|
|
346
345
|
- app/demo/components/icons.pom
|
|
@@ -405,10 +404,14 @@ files:
|
|
|
405
404
|
- app/demo/patterns/drag_drop.pom
|
|
406
405
|
- app/demo/patterns/floating_card.pom
|
|
407
406
|
- app/demo/patterns/search_select.pom
|
|
407
|
+
- app/demo/plugins/cacheable.pom
|
|
408
408
|
- app/demo/plugins/chart.pom
|
|
409
|
+
- app/demo/plugins/google_maps.pom
|
|
409
410
|
- app/demo/plugins/image_crop.pom
|
|
410
411
|
- app/demo/plugins/index.pom
|
|
411
412
|
- app/demo/plugins/nav/drawer.pom
|
|
413
|
+
- app/demo/plugins/script.pom
|
|
414
|
+
- app/demo/plugins/scroll_to.pom
|
|
412
415
|
- app/demo/shared/code.pom
|
|
413
416
|
- app/demo/shared/context_list.pom
|
|
414
417
|
- app/demo/shared/debug.pom
|
|
@@ -558,16 +561,21 @@ files:
|
|
|
558
561
|
- lib/coprl/presenters/errors/unprocessable.rb
|
|
559
562
|
- lib/coprl/presenters/generators/inflectors.rb
|
|
560
563
|
- lib/coprl/presenters/generators/plugin.rb
|
|
564
|
+
- lib/coprl/presenters/generators/templates/plugin/.github/workflows/semantic-release.yml
|
|
561
565
|
- lib/coprl/presenters/generators/templates/plugin/.gitignore
|
|
566
|
+
- lib/coprl/presenters/generators/templates/plugin/.releaserc
|
|
567
|
+
- lib/coprl/presenters/generators/templates/plugin/.ruby-version
|
|
562
568
|
- lib/coprl/presenters/generators/templates/plugin/Gemfile.tt
|
|
563
569
|
- lib/coprl/presenters/generators/templates/plugin/LICENSE.txt.tt
|
|
564
|
-
- lib/coprl/presenters/generators/templates/plugin/README.md
|
|
570
|
+
- lib/coprl/presenters/generators/templates/plugin/README.md.tt
|
|
571
|
+
- lib/coprl/presenters/generators/templates/plugin/demo/plugin.pom.tt
|
|
565
572
|
- lib/coprl/presenters/generators/templates/plugin/lib/coprl/presenters/plugins/components/actions/action.rb.tt
|
|
566
573
|
- lib/coprl/presenters/generators/templates/plugin/lib/coprl/presenters/plugins/components/actions/dsl.rb.tt
|
|
567
574
|
- lib/coprl/presenters/generators/templates/plugin/lib/coprl/presenters/plugins/components/component.rb.tt
|
|
568
575
|
- lib/coprl/presenters/generators/templates/plugin/lib/coprl/presenters/plugins/components/dsl.rb.tt
|
|
569
576
|
- lib/coprl/presenters/generators/templates/plugin/lib/coprl/presenters/plugins/helpers/helper.rb.tt
|
|
570
577
|
- lib/coprl/presenters/generators/templates/plugin/lib/coprl/presenters/plugins/plugin.rb.tt
|
|
578
|
+
- lib/coprl/presenters/generators/templates/plugin/lib/coprl/presenters/plugins/version.rb.tt
|
|
571
579
|
- lib/coprl/presenters/generators/templates/plugin/lib/coprl/presenters/plugins/web_client/components/actions/data.rb.tt
|
|
572
580
|
- lib/coprl/presenters/generators/templates/plugin/lib/coprl/presenters/plugins/web_client/components/render.rb.tt
|
|
573
581
|
- lib/coprl/presenters/generators/templates/plugin/presenter_plugin.gemspec.tt
|
|
@@ -589,9 +597,6 @@ files:
|
|
|
589
597
|
- lib/coprl/presenters/namespace.rb
|
|
590
598
|
- lib/coprl/presenters/pluggable.rb
|
|
591
599
|
- lib/coprl/presenters/plugins.rb
|
|
592
|
-
- lib/coprl/presenters/plugins/google_maps.rb
|
|
593
|
-
- lib/coprl/presenters/plugins/google_maps/google_map.erb
|
|
594
|
-
- lib/coprl/presenters/plugins/google_maps/google_map.rb
|
|
595
600
|
- lib/coprl/presenters/rails/engine.rb
|
|
596
601
|
- lib/coprl/presenters/rails/railtie.rb
|
|
597
602
|
- lib/coprl/presenters/registry.rb
|
|
@@ -672,6 +677,7 @@ files:
|
|
|
672
677
|
- rails-engine/app/views/layouts/coprl.html.erb
|
|
673
678
|
- rails-engine/config.ru
|
|
674
679
|
- rails-engine/config/initializers/presenters.rb
|
|
680
|
+
- rails-engine/config/initializers/session.rb
|
|
675
681
|
- rails-engine/config/routes.rb
|
|
676
682
|
- scripts/build.sh
|
|
677
683
|
- views/mdc/.babelrc
|
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
require_relative '../helpers/indented_grid'
|
|
2
|
-
|
|
3
|
-
Coprl::Presenters.define(:maps) do
|
|
4
|
-
helpers Demo::Helpers::IndentedGrid
|
|
5
|
-
attach :top_nav
|
|
6
|
-
attach :component_drawer
|
|
7
|
-
page_title 'Maps'
|
|
8
|
-
|
|
9
|
-
indented_grid do
|
|
10
|
-
subheading 'Static Maps'
|
|
11
|
-
|
|
12
|
-
address = '125 Park Street, Traverse City, MI'
|
|
13
|
-
google_map address: address, height: 300, width: 400 do
|
|
14
|
-
event :click do
|
|
15
|
-
loads "https://www.google.com/maps/place/#{address}"
|
|
16
|
-
end
|
|
17
|
-
end
|
|
18
|
-
|
|
19
|
-
attach :code, file: __FILE__
|
|
20
|
-
end
|
|
21
|
-
|
|
22
|
-
end
|
|
@@ -1,253 +0,0 @@
|
|
|
1
|
-
# Presenter Plugins
|
|
2
|
-
|
|
3
|
-
Presenter plugins allows extension and modification of the DSL and WebClient.
|
|
4
|
-
It is powerfully designed for adding additional components to the system, or to change the behavior/look feel/capabilities of existing components.
|
|
5
|
-
|
|
6
|
-
## Global Plugins
|
|
7
|
-
|
|
8
|
-
Presenters have global plugins that are configured in the system. They are declared as a setting like so:
|
|
9
|
-
|
|
10
|
-
Coprl::Presenters::Settings.configure do |config|
|
|
11
|
-
config.presenters.plugins.push(:foo)
|
|
12
|
-
end
|
|
13
|
-
|
|
14
|
-
A global plugin is available to all presenters.
|
|
15
|
-
|
|
16
|
-
## Local Plugins
|
|
17
|
-
|
|
18
|
-
A presenters can define that it uses a plugin like so:
|
|
19
|
-
|
|
20
|
-
Coprl::Presenters.define(:index, namespace: :plugins) do
|
|
21
|
-
plugin :foo
|
|
22
|
-
end
|
|
23
|
-
|
|
24
|
-
A local plugin is available only to the presenter that it is defined in.
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
## Creating Plugins
|
|
28
|
-
|
|
29
|
-
The skeleton for a plugin starts with an empty module in a file stored in `coprl/presenters/plugins` somewhere in ruby's load path
|
|
30
|
-
(typically in a gemfile or in the lib directory of an framework app, like Rails):
|
|
31
|
-
|
|
32
|
-
module Coprl
|
|
33
|
-
module Presenters
|
|
34
|
-
module Plugins
|
|
35
|
-
module Foo
|
|
36
|
-
end
|
|
37
|
-
end
|
|
38
|
-
end
|
|
39
|
-
end
|
|
40
|
-
|
|
41
|
-
## Extending the presenter DSL and POM
|
|
42
|
-
|
|
43
|
-
### Components
|
|
44
|
-
If you want to add additional components to the presenters DSL, provide a `DSLComponents` module under the plugin module:
|
|
45
|
-
|
|
46
|
-
module DSLComponents
|
|
47
|
-
def foo(random_fact, **attributes, &block)
|
|
48
|
-
self << Foo::Component.new(random_fact, parent: self, **attributes, &block)
|
|
49
|
-
end
|
|
50
|
-
end
|
|
51
|
-
|
|
52
|
-
The above example will extend the dsl by adding the foo method that will add the Foo component to the
|
|
53
|
-
presenter object model tree.
|
|
54
|
-
|
|
55
|
-
A presenter component derives from `DSL::Components::Base` or if it needs to handle events `DSL::Components::EventBase`
|
|
56
|
-
|
|
57
|
-
require 'coprl/presenters/dsl/components/base'
|
|
58
|
-
|
|
59
|
-
module Coprl
|
|
60
|
-
module Presenters
|
|
61
|
-
module Plugins
|
|
62
|
-
module Foo
|
|
63
|
-
class Component < DSL::Components::Base
|
|
64
|
-
def initialize(**attribs_, &block)
|
|
65
|
-
super(type: :foo, **attribs_, &block)
|
|
66
|
-
end
|
|
67
|
-
end
|
|
68
|
-
end
|
|
69
|
-
end
|
|
70
|
-
end
|
|
71
|
-
end
|
|
72
|
-
|
|
73
|
-
### Helpers
|
|
74
|
-
|
|
75
|
-
To add helpers to the POM define the module `DSLHelpers`
|
|
76
|
-
|
|
77
|
-
module DSLHelpers
|
|
78
|
-
def random_fact
|
|
79
|
-
"http://en.wikipedia.org/wiki/Special:Randompage"
|
|
80
|
-
end
|
|
81
|
-
end
|
|
82
|
-
|
|
83
|
-
### Event Actions
|
|
84
|
-
A plugin can extend the set of event actions that are available.
|
|
85
|
-
When an event fires in the client, like mouse click, a set of actions are executed. A plugin can provide custom
|
|
86
|
-
actions. This examnple adds a actionJs actionJs that can be bound to an event.
|
|
87
|
-
|
|
88
|
-
module DSLEventActions
|
|
89
|
-
def actionJs(text, **attributes, &block)
|
|
90
|
-
self << Foo::Action.new(text: text, parent: self, **attributes, &block)
|
|
91
|
-
end
|
|
92
|
-
end
|
|
93
|
-
|
|
94
|
-
Example actionJs class:
|
|
95
|
-
|
|
96
|
-
require 'coprl/presenters/dsl/components/actions/base'
|
|
97
|
-
|
|
98
|
-
module Coprl
|
|
99
|
-
module Presenters
|
|
100
|
-
module Plugins
|
|
101
|
-
module Foo
|
|
102
|
-
class Action < DSL::Components::Actions::Base
|
|
103
|
-
def initialize(**attribs_, &block)
|
|
104
|
-
super(type: :actionJs, **attribs_, &block)
|
|
105
|
-
end
|
|
106
|
-
end
|
|
107
|
-
end
|
|
108
|
-
end
|
|
109
|
-
end
|
|
110
|
-
end
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
## Adding a WebClient implementation
|
|
114
|
-
|
|
115
|
-
A plugin that extends the DSL will give you a new custom POM (Presenter Object Model), but that alone won't get you very far.
|
|
116
|
-
The POM describes the user interface, a client must implement each of the components.
|
|
117
|
-
For the WebClient this means adding a template with HTML, CSS and Javascript.
|
|
118
|
-
|
|
119
|
-
### Component Templates
|
|
120
|
-
|
|
121
|
-
To render your component you need to add the following to your plugin:
|
|
122
|
-
|
|
123
|
-
module WebClientComponents
|
|
124
|
-
def render_foo(comp,
|
|
125
|
-
render:,
|
|
126
|
-
components:,
|
|
127
|
-
index:)
|
|
128
|
-
view_dir = File.join(__dir__, 'foo')
|
|
129
|
-
render.call :erb, :foo, views: view_dir,
|
|
130
|
-
locals: {comp: comp,
|
|
131
|
-
components: components, index: index}
|
|
132
|
-
end
|
|
133
|
-
end
|
|
134
|
-
|
|
135
|
-
From you ERB you can call any of the other built in WebClient erb's. You can even replace built in component templates.
|
|
136
|
-
The render object supports all the template types supported by Tilt/Sinatra (http://sinatrarb.com/intro.html)
|
|
137
|
-
|
|
138
|
-
Example template:
|
|
139
|
-
|
|
140
|
-
<iframe id="random_fact" src="<%= comp.random_fact %>" height=512 <%= erb :"components/event", :locals => {comp: comp, events: comp.events, parent_id: comp.id} %>></iframe>
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
### Event Action Data
|
|
144
|
-
|
|
145
|
-
An actionJs from the Presenter Object Model (POM) is sent to a ruby method during template expansion.
|
|
146
|
-
You are able to then setup any data that you want passed to your actionJs javascript method.
|
|
147
|
-
It expects you will return an array with a type that matches your event actionJs presenter type. The rest is up to you.
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
module WebClientActions
|
|
151
|
-
def action_data_bar(actionJs, _parent_id, *)
|
|
152
|
-
# Type, URL, Options, Params (passed into javascript event/actionJs classes)
|
|
153
|
-
[actionJs.type, actionJs.url, actionJs.options.to_h, actionJs.attributes.to_h]
|
|
154
|
-
end
|
|
155
|
-
end
|
|
156
|
-
|
|
157
|
-
Example Javascript method (typically rendered by a template triggered by the render_foo method above):
|
|
158
|
-
|
|
159
|
-
<script>
|
|
160
|
-
function actionJs(_options, params, _event) {
|
|
161
|
-
// Reload iFrame: https://stackoverflow.com/questions/86428/what-s-the-best-way-to-reload-refresh-an-iframe
|
|
162
|
-
document.getElementById('random_fact').src += '';
|
|
163
|
-
return {actionJs: 'actionJs', content: {data: params.text}, statusCode: 200};
|
|
164
|
-
}
|
|
165
|
-
</script>
|
|
166
|
-
|
|
167
|
-
Event actionJs WebClient methods must return a Javascript Object with the properties `actionJs`, `content` and `statusCode`.
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
## WebClient Javascript Interface
|
|
171
|
-
|
|
172
|
-
When developing a plugin for the WebClient you may want to have your data submitted as part of another component container.
|
|
173
|
-
The most familiar example is a Form. This requires that you bind your component to the DOM with a few methods.
|
|
174
|
-
Not all plugins need to do this.
|
|
175
|
-
It is only needed in the case of those components that add their data to an http post.
|
|
176
|
-
|
|
177
|
-
The following components are Containers that will collect data from nested DOM elements using this lifecycle protocol.
|
|
178
|
-
cards.js
|
|
179
|
-
content.js
|
|
180
|
-
dialogs.js
|
|
181
|
-
file-inputs.js
|
|
182
|
-
forms.js
|
|
183
|
-
grid.js
|
|
184
|
-
steppers.js
|
|
185
|
-
|
|
186
|
-
Lifecycle Protocol:
|
|
187
|
-
|
|
188
|
-
We call it it a protocol, because it defines a small number of DOM relationships to participate as an integrated component.
|
|
189
|
-
Many frameworks require a common base class, this approach is very light by design.
|
|
190
|
-
|
|
191
|
-
Container data in the WebClient is collected and submitted using the following sequence:
|
|
192
|
-
|
|
193
|
-
In your element markup include the `v-input` class on an DOM element.
|
|
194
|
-
|
|
195
|
-
You can see the container calling code here:
|
|
196
|
-
https://github.com/rx/presenters/blob/master/views/mdc/assets/js/components/base-container.js
|
|
197
|
-
|
|
198
|
-
If you add the v-plugin class to the DOM element along with a data-plugin-callback dataset that contains a string
|
|
199
|
-
with the class name to proxy the plugin events to.
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
Sample callback class:
|
|
203
|
-
|
|
204
|
-
// Optional Javascript callback class. You typically need to define this when you have data to submit, or special
|
|
205
|
-
// event handling to bind to.
|
|
206
|
-
// To hook this up you need to provide the `v-plugin` class and
|
|
207
|
-
// data-plugin-callback='RandomFacts' on the element.
|
|
208
|
-
class RandomFacts {
|
|
209
|
-
// passed the DOM element that has the .v-plugin class on it.
|
|
210
|
-
constructor(element) {
|
|
211
|
-
}
|
|
212
|
-
|
|
213
|
-
// optional.
|
|
214
|
-
// Called before the component is submitted via post/put. Allows the component to add its key/value pairs to the
|
|
215
|
-
// submitted data.
|
|
216
|
-
// If you provide this you need to add the v-input class to your DOM element to get called.
|
|
217
|
-
// Containers iterate their elements that have the v-input class defined on them and invoke the prepareSubmit
|
|
218
|
-
// function for each.
|
|
219
|
-
prepareSubmit(params) {
|
|
220
|
-
// params is a key,value pair. Add name/value like so:
|
|
221
|
-
// params.push(['some_name', 'some_value']);
|
|
222
|
-
}
|
|
223
|
-
|
|
224
|
-
// optional.
|
|
225
|
-
// Called whenever a container is about to be submitted, before prepareSubmit.
|
|
226
|
-
// returns true on success
|
|
227
|
-
// returns on failure return an error object that can be processed by VErrors:
|
|
228
|
-
// { email: ["email must be filled", "email must be from your domain"] }
|
|
229
|
-
// { page: ["must be filled"] }
|
|
230
|
-
// Returning an error stops the submission.
|
|
231
|
-
validate(formData) {
|
|
232
|
-
return true;
|
|
233
|
-
}
|
|
234
|
-
|
|
235
|
-
// optional.
|
|
236
|
-
// Clear's the control
|
|
237
|
-
clear() {
|
|
238
|
-
}
|
|
239
|
-
|
|
240
|
-
// called to add an event listener to the component
|
|
241
|
-
// this only needs to be defined if you need the event handler to be bound to the component
|
|
242
|
-
// in a different manner. Here is the default implementation you get if you don't define this method:
|
|
243
|
-
initEventListener(eventName, eventHandler) {
|
|
244
|
-
if (typeof this.eventsHandler === 'undefined') {
|
|
245
|
-
this.eventsHandler = {};
|
|
246
|
-
}
|
|
247
|
-
if (!this.eventsHandler[eventName]) {
|
|
248
|
-
// Delegate to the component if possible
|
|
249
|
-
this.eventsHandler[eventName] = eventHandler;
|
|
250
|
-
this.element.addEventListener(eventName, eventHandler);
|
|
251
|
-
}
|
|
252
|
-
}
|
|
253
|
-
}
|
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
module Coprl
|
|
2
|
-
module Presenters
|
|
3
|
-
module Plugins
|
|
4
|
-
module GoogleMaps
|
|
5
|
-
module DSLComponents
|
|
6
|
-
def google_map(**attributes, &block)
|
|
7
|
-
self << GoogleMap.new(parent: self, **attributes, &block)
|
|
8
|
-
end
|
|
9
|
-
end
|
|
10
|
-
module WebClientComponents
|
|
11
|
-
def render_google_map(comp,
|
|
12
|
-
render:,
|
|
13
|
-
components:,
|
|
14
|
-
index:)
|
|
15
|
-
view_dir = File.join(__dir__, 'google_maps')
|
|
16
|
-
render.call :erb, :google_map, views: view_dir,
|
|
17
|
-
locals: {comp: comp,
|
|
18
|
-
components: components, index: index}
|
|
19
|
-
end
|
|
20
|
-
end
|
|
21
|
-
end
|
|
22
|
-
end
|
|
23
|
-
end
|
|
24
|
-
end
|
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
<% if comp %>
|
|
2
|
-
<img id="<%= comp.id %>"
|
|
3
|
-
class="v-image v-google-map-image <%= comp.events ? 'v-actionable' : nil%>"
|
|
4
|
-
src="<%= comp.url %>"
|
|
5
|
-
border="0"
|
|
6
|
-
height="<%= comp.height %>"
|
|
7
|
-
width="<%= comp.width %>"
|
|
8
|
-
alt=""
|
|
9
|
-
<%= erb :"components/event", :locals => {comp: comp, events: comp.events, parent_id: comp.id} %>>
|
|
10
|
-
<% end %>
|
|
@@ -1,41 +0,0 @@
|
|
|
1
|
-
require 'uri'
|
|
2
|
-
|
|
3
|
-
module Coprl
|
|
4
|
-
module Presenters
|
|
5
|
-
module Plugins
|
|
6
|
-
module GoogleMaps
|
|
7
|
-
class GoogleMap < DSL::Components::EventBase
|
|
8
|
-
|
|
9
|
-
attr_reader :url, :google_api_key, :height, :width
|
|
10
|
-
|
|
11
|
-
def initialize(**attribs_, &block)
|
|
12
|
-
super(type: :google_map, **attribs_, &block)
|
|
13
|
-
@address = attribs.delete(:address)
|
|
14
|
-
@latitude = attribs.delete(:latitude)
|
|
15
|
-
@longitude = attribs.delete(:longitude)
|
|
16
|
-
@width = attribs.delete(:width) { 640 }
|
|
17
|
-
@height = attribs.delete(:height) { 640 }
|
|
18
|
-
@zoom = attribs.delete(:zoom) { 14 }
|
|
19
|
-
@scale = attribs.delete(:scale) { 1 }
|
|
20
|
-
@google_api_key = attribs.delete(:google_api_key) { ENV['GOOGLE_API_KEY'] }
|
|
21
|
-
@url = build_static_map_image_url
|
|
22
|
-
expand!
|
|
23
|
-
end
|
|
24
|
-
|
|
25
|
-
private
|
|
26
|
-
|
|
27
|
-
def build_static_map_image_url
|
|
28
|
-
return @img_url if locked?
|
|
29
|
-
@img_url = "https://maps.googleapis.com/maps/api/staticmap?center=#{query_string}&zoom=#{@zoom}&scale=#{@scale}&size=#{@width}x#{@height}&markers=|#{query_string}&key=#{@google_api_key}"
|
|
30
|
-
end
|
|
31
|
-
|
|
32
|
-
def query_string
|
|
33
|
-
return "#{@latitude},#{@longitude}" if @latitude && @longitude
|
|
34
|
-
URI.escape(@address)
|
|
35
|
-
end
|
|
36
|
-
|
|
37
|
-
end
|
|
38
|
-
end
|
|
39
|
-
end
|
|
40
|
-
end
|
|
41
|
-
end
|