dynamic_text 0.0.5 → 0.0.6
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Rakefile +6 -8
- data/app/assets/javascripts/dynamic_text/dynamic_text.js +7 -76
- data/app/assets/javascripts/dynamic_text/dynamic_text_preparer.js +62 -0
- data/app/assets/javascripts/dynamic_text/js.js +6 -0
- data/app/helpers/dynamic_text/view_helper.rb +6 -92
- data/app/views/dynamic_text/_dynamic_text.html.erb +4 -0
- data/app/views/dynamic_text/_editable_text.html.erb +20 -0
- data/lib/dynamic_text/configuration.rb +4 -4
- data/lib/dynamic_text/locals_setter.rb +70 -0
- data/lib/dynamic_text/version.rb +1 -1
- data/lib/dynamic_text/view_renderer.rb +39 -0
- data/lib/dynamic_text.rb +2 -0
- data/spec/dummy/Rakefile +6 -0
- data/spec/dummy/app/assets/config/manifest.js +4 -0
- data/spec/dummy/app/assets/javascripts/application.js +15 -0
- data/spec/dummy/app/assets/javascripts/cable.js +13 -0
- data/spec/dummy/app/assets/stylesheets/application.css +15 -0
- data/spec/dummy/app/channels/application_cable/channel.rb +4 -0
- data/spec/dummy/app/channels/application_cable/connection.rb +4 -0
- data/spec/dummy/app/controllers/application_controller.rb +2 -0
- data/spec/dummy/app/helpers/application_helper.rb +2 -0
- data/spec/dummy/app/jobs/application_job.rb +2 -0
- data/spec/dummy/app/mailers/application_mailer.rb +4 -0
- data/spec/dummy/app/models/application_record.rb +3 -0
- data/spec/dummy/app/views/layouts/application.html.erb +15 -0
- data/spec/dummy/app/views/layouts/mailer.html.erb +13 -0
- data/spec/dummy/app/views/layouts/mailer.text.erb +1 -0
- data/spec/dummy/bin/bundle +3 -0
- data/spec/dummy/bin/rails +4 -0
- data/spec/dummy/bin/rake +4 -0
- data/spec/dummy/bin/setup +36 -0
- data/spec/dummy/bin/update +31 -0
- data/spec/dummy/bin/yarn +11 -0
- data/spec/dummy/config/application.rb +18 -0
- data/spec/dummy/config/boot.rb +5 -0
- data/spec/dummy/config/cable.yml +10 -0
- data/spec/dummy/config/database.yml +26 -0
- data/spec/dummy/config/environment.rb +5 -0
- data/spec/dummy/config/environments/development.rb +61 -0
- data/spec/dummy/config/environments/production.rb +94 -0
- data/spec/dummy/config/environments/test.rb +46 -0
- data/spec/dummy/config/initializers/application_controller_renderer.rb +8 -0
- data/spec/dummy/config/initializers/assets.rb +14 -0
- data/spec/dummy/config/initializers/backtrace_silencers.rb +7 -0
- data/spec/dummy/config/initializers/content_security_policy.rb +25 -0
- data/spec/dummy/config/initializers/cookies_serializer.rb +5 -0
- data/spec/dummy/config/initializers/filter_parameter_logging.rb +4 -0
- data/spec/dummy/config/initializers/inflections.rb +16 -0
- data/spec/dummy/config/initializers/mime_types.rb +4 -0
- data/spec/dummy/config/initializers/wrap_parameters.rb +14 -0
- data/spec/dummy/config/locales/en.yml +33 -0
- data/spec/dummy/config/puma.rb +34 -0
- data/spec/dummy/config/routes.rb +3 -0
- data/spec/dummy/config/spring.rb +6 -0
- data/spec/dummy/config/storage.yml +34 -0
- data/spec/dummy/config.ru +5 -0
- data/spec/dummy/db/schema.rb +18 -0
- data/spec/dummy/log/development.log +38 -0
- data/spec/dummy/log/test.log +1646 -0
- data/spec/dummy/package.json +5 -0
- data/spec/dummy/public/404.html +67 -0
- data/spec/dummy/public/422.html +67 -0
- data/spec/dummy/public/500.html +66 -0
- data/spec/dummy/public/apple-touch-icon-precomposed.png +0 -0
- data/spec/dummy/public/apple-touch-icon.png +0 -0
- data/spec/dummy/public/favicon.ico +0 -0
- data/spec/helpers/view_helper_spec.rb +8 -0
- data/spec/integration/navigation_test.rb +7 -0
- data/spec/lib/locals_setter_spec.rb +114 -0
- data/spec/lib/view_renderer.rb +3 -0
- data/spec/rails_helper.rb +63 -0
- data/spec/spec_helper.rb +81 -0
- metadata +185 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: dc355787a78ea70e6728fb425360773d10a6a964478a551213a525a029153fa5
|
4
|
+
data.tar.gz: 400c9191e052f31835e86a1d3575cf82ff1c78bfd5240c7a3d46cf76502143e8
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 578a1f7541b9d99e46753eb26ee1e0a9f053629931ab30421a1d93ef9640058a963c56809f47ee4e0589c9f2d1f1a50f9355a948b6b5c2906f102e90e1562dfc
|
7
|
+
data.tar.gz: a38e4ea970e6808367e52c552b8b8b7a00014db566e2874cb156df239cfece7897808d4978d4b2563c0aa17c7fca8fe678c01c0d06bcc329e0565cbb8a4f099c
|
data/Rakefile
CHANGED
@@ -14,19 +14,17 @@ RDoc::Task.new(:rdoc) do |rdoc|
|
|
14
14
|
rdoc.rdoc_files.include('lib/**/*.rb')
|
15
15
|
end
|
16
16
|
|
17
|
-
APP_RAKEFILE = File.expand_path("
|
17
|
+
APP_RAKEFILE = File.expand_path("spec/dummy/Rakefile", __dir__)
|
18
18
|
load 'rails/tasks/engine.rake'
|
19
19
|
|
20
20
|
load 'rails/tasks/statistics.rake'
|
21
21
|
|
22
22
|
require 'bundler/gem_tasks'
|
23
23
|
|
24
|
-
require '
|
24
|
+
require 'rspec/core'
|
25
|
+
require 'rspec/core/rake_task'
|
25
26
|
|
26
|
-
|
27
|
-
|
28
|
-
t.pattern = 'test/**/*_test.rb'
|
29
|
-
t.verbose = false
|
30
|
-
end
|
27
|
+
# desc "Run all specs in spec directory (excluding plugin specs)"
|
28
|
+
RSpec::Core::RakeTask.new(:spec)
|
31
29
|
|
32
|
-
task default: :
|
30
|
+
task default: :spec
|
@@ -54,13 +54,13 @@ const DynamicText = {
|
|
54
54
|
this.ajaxResponses['default'] = func;
|
55
55
|
},
|
56
56
|
|
57
|
-
// Set response for specific
|
58
|
-
handleAjaxResponseFor(
|
59
|
-
this.ajaxResponses[
|
57
|
+
// Set response for specific js key
|
58
|
+
handleAjaxResponseFor(jsKey, func) {
|
59
|
+
this.ajaxResponses[jsKey] = func;
|
60
60
|
},
|
61
61
|
|
62
62
|
// Build ajax request for patch resource function.
|
63
|
-
sendPatchRequest(url, resourceType, attribute, updatedValue,
|
63
|
+
sendPatchRequest(url, resourceType, attribute, updatedValue, jsKey) {
|
64
64
|
const CSRF_TOKEN =
|
65
65
|
document.querySelector('meta[name="csrf-token"]')
|
66
66
|
.getAttribute('content');
|
@@ -78,7 +78,7 @@ const DynamicText = {
|
|
78
78
|
xhr.onload = () => {
|
79
79
|
if (xhr.status === 200) {
|
80
80
|
successCallback =
|
81
|
-
this.ajaxResponses[
|
81
|
+
this.ajaxResponses[jsKey] || this.ajaxResponses['default']
|
82
82
|
successCallback(JSON.parse(xhr.responseText), resourceType)
|
83
83
|
}
|
84
84
|
};
|
@@ -98,78 +98,9 @@ const DynamicText = {
|
|
98
98
|
const url = action.getAttribute('url');
|
99
99
|
const resourceType = action.getAttribute('resource-type');
|
100
100
|
const attribute = action.getAttribute('attribute');
|
101
|
-
const
|
101
|
+
const jsKey = action.getAttribute('js-key');
|
102
102
|
const updatedValue = editableText.innerText;
|
103
103
|
|
104
|
-
this.sendPatchRequest(url, resourceType, attribute, updatedValue,
|
104
|
+
this.sendPatchRequest(url, resourceType, attribute, updatedValue, jsKey)
|
105
105
|
}
|
106
106
|
}
|
107
|
-
|
108
|
-
const prepareDynamicText = () => {
|
109
|
-
document.querySelectorAll('.editable-text').forEach((editableText) => {
|
110
|
-
// Exit editable text editor mode (focus) on enter instead of adding a new line.
|
111
|
-
editableText.addEventListener('keydown', (e) => {
|
112
|
-
if (e.keyCode === 13) {
|
113
|
-
e.preventDefault();
|
114
|
-
e.currentTarget.blur();
|
115
|
-
}
|
116
|
-
});
|
117
|
-
|
118
|
-
// Properly paste text into editable text
|
119
|
-
editableText.addEventListener('paste', (e) => {
|
120
|
-
e.preventDefault();
|
121
|
-
DynamicText.handleContentEditablePaste(e)
|
122
|
-
});
|
123
|
-
|
124
|
-
// Disable dragging and dropping text/images into editable text.
|
125
|
-
["dragover", "drop"].forEach((evt) => {
|
126
|
-
editableText.addEventListener(evt, (e) => {
|
127
|
-
e.preventDefault();
|
128
|
-
return false;
|
129
|
-
});
|
130
|
-
});
|
131
|
-
|
132
|
-
// Store original value when focusing in on specific editable text (used to determine if text was changed and patch request should be sent on focusout.)
|
133
|
-
editableText.addEventListener('focus', (e) => {
|
134
|
-
const target = e.currentTarget;
|
135
|
-
target.setAttribute('data-original-value', target.innerText);
|
136
|
-
});
|
137
|
-
|
138
|
-
// Send patch request for resource if content was changed.
|
139
|
-
editableText.addEventListener('focusout', (e) => {
|
140
|
-
const target = e.currentTarget
|
141
|
-
|
142
|
-
// Empty all content of text if editable text is empty (otherwise certain browsers fill in a default <br> or <p> value.)
|
143
|
-
if (!target.innerText.trim().length) {
|
144
|
-
target.innerText = null;
|
145
|
-
}
|
146
|
-
|
147
|
-
// Send patch request if text was changed.
|
148
|
-
if (target.getAttribute('data-original-value') != target.innerText) {
|
149
|
-
DynamicText.patchResource(e);
|
150
|
-
}
|
151
|
-
|
152
|
-
target.removeAttribute('data-original-value')
|
153
|
-
});
|
154
|
-
|
155
|
-
// Update all other divs tagged with the same dynamic-tag as the current text being edited. (So if you have two elements on one page that display the same title property of a resource, both will be updated in real time when you edit the text of one.)
|
156
|
-
editableText.addEventListener('input', (e) => {
|
157
|
-
const target = e.currentTarget;
|
158
|
-
const newValue = target.innerText;
|
159
|
-
const dynamicTag = target.getAttribute('data-dynamic-tag');
|
160
|
-
|
161
|
-
document.querySelectorAll(`[data-dynamic-tag='${dynamicTag}']`)
|
162
|
-
.forEach((dynamicTextElement) => {
|
163
|
-
if(dynamicTextElement !== target) {
|
164
|
-
dynamicTextElement.innerText = newValue;
|
165
|
-
}
|
166
|
-
});
|
167
|
-
});
|
168
|
-
})
|
169
|
-
}
|
170
|
-
|
171
|
-
const events = ["turbolinks:load", "page:change"];
|
172
|
-
|
173
|
-
events.forEach((evt) => {
|
174
|
-
document.addEventListener(evt, prepareDynamicText)
|
175
|
-
});
|
@@ -0,0 +1,62 @@
|
|
1
|
+
const prepareDynamicText = () => {
|
2
|
+
document.querySelectorAll('.editable-text').forEach((editableText) => {
|
3
|
+
// Exit editable text editor mode (focus) on enter instead of adding a new line.
|
4
|
+
editableText.addEventListener('keydown', (e) => {
|
5
|
+
if (e.keyCode === 13) {
|
6
|
+
e.preventDefault();
|
7
|
+
e.currentTarget.blur();
|
8
|
+
}
|
9
|
+
});
|
10
|
+
|
11
|
+
// Properly paste text into editable text
|
12
|
+
editableText.addEventListener('paste', (e) => {
|
13
|
+
e.preventDefault();
|
14
|
+
DynamicText.handleContentEditablePaste(e)
|
15
|
+
});
|
16
|
+
|
17
|
+
// Disable dragging and dropping text/images into editable text.
|
18
|
+
["dragover", "drop"].forEach((evt) => {
|
19
|
+
editableText.addEventListener(evt, (e) => {
|
20
|
+
e.preventDefault();
|
21
|
+
return false;
|
22
|
+
});
|
23
|
+
});
|
24
|
+
|
25
|
+
// Store original value when focusing in on specific editable text (used to determine if text was changed and patch request should be sent on focusout.)
|
26
|
+
editableText.addEventListener('focus', (e) => {
|
27
|
+
const target = e.currentTarget;
|
28
|
+
target.setAttribute('data-original-value', target.innerText);
|
29
|
+
});
|
30
|
+
|
31
|
+
// Send patch request for resource if content was changed.
|
32
|
+
editableText.addEventListener('focusout', (e) => {
|
33
|
+
const target = e.currentTarget
|
34
|
+
|
35
|
+
// Empty all content of text if editable text is empty (otherwise certain browsers fill in a default <br> or <p> value.)
|
36
|
+
if (!target.innerText.trim().length) {
|
37
|
+
target.innerText = null;
|
38
|
+
}
|
39
|
+
|
40
|
+
// Send patch request if text was changed.
|
41
|
+
if (target.getAttribute('data-original-value') != target.innerText) {
|
42
|
+
DynamicText.patchResource(e);
|
43
|
+
}
|
44
|
+
|
45
|
+
target.removeAttribute('data-original-value')
|
46
|
+
});
|
47
|
+
|
48
|
+
// Update all other divs tagged with the same dynamic-tag as the current text being edited. (So if you have two elements on one page that display the same property of a resource, both will be updated in real time when you edit the text of one.)
|
49
|
+
editableText.addEventListener('input', (e) => {
|
50
|
+
const target = e.currentTarget;
|
51
|
+
const newValue = target.innerText;
|
52
|
+
const dynamicTag = target.getAttribute('data-dynamic-tag');
|
53
|
+
|
54
|
+
document.querySelectorAll(`[data-dynamic-tag='${dynamicTag}']`)
|
55
|
+
.forEach((dynamicTextElement) => {
|
56
|
+
if(dynamicTextElement !== target) {
|
57
|
+
dynamicTextElement.innerText = newValue;
|
58
|
+
}
|
59
|
+
});
|
60
|
+
});
|
61
|
+
})
|
62
|
+
}
|
@@ -1,99 +1,13 @@
|
|
1
1
|
module DynamicText
|
2
2
|
module ViewHelper
|
3
|
-
def
|
4
|
-
|
5
|
-
|
3
|
+
def dynamic_text_for(resource, attribute, opts={})
|
4
|
+
DynamicText::ViewRenderer.new(self)
|
5
|
+
.render_dynamic_text_for(resource, attribute, opts)
|
6
6
|
end
|
7
7
|
|
8
|
-
def
|
9
|
-
|
10
|
-
|
11
|
-
end
|
12
|
-
end
|
13
|
-
|
14
|
-
def dynamic_text_for(resource, attribute, options={})
|
15
|
-
options = dynamic_attributes(resource, attribute, options)
|
16
|
-
dynamic_text_tag(options)
|
17
|
-
end
|
18
|
-
|
19
|
-
def editable_text_for(resource, attribute, options = {})
|
20
|
-
options = editable_attributes(resource, attribute, options)
|
21
|
-
|
22
|
-
content_tag(:span, class: "editable-text-container") do
|
23
|
-
editable_text_tag(options) +
|
24
|
-
patch_request_tag(options)
|
25
|
-
end
|
26
|
-
end
|
27
|
-
|
28
|
-
private
|
29
|
-
|
30
|
-
def dynamic_attributes(resource, attribute, options={})
|
31
|
-
Hash.new.tap do |hash|
|
32
|
-
hash[:resource] = resource
|
33
|
-
hash[:attribute] = attribute
|
34
|
-
hash[:value] = resource.send(attribute)
|
35
|
-
hash[:placeholder] = options[:placeholder] || "Enter #{attribute}..."
|
36
|
-
hash[:resource_type] = expected_resource_type(resource)
|
37
|
-
hash[:dynamic_tag] =
|
38
|
-
default_dynamic_tag(hash[:resource_type], resource.id, attribute)
|
39
|
-
end
|
40
|
-
end
|
41
|
-
|
42
|
-
def editable_attributes(resource, attribute, options={})
|
43
|
-
dynamic_attributes(resource, attribute, options={}).tap do |hash|
|
44
|
-
hash[:url] =
|
45
|
-
options[:url] || send("#{DynamicText.configuration.path_prefix}#{hash[:resource_type]}_path", resource)
|
46
|
-
hash[:ajax_key] =
|
47
|
-
options[:ajax_key] || default_ajax_key(hash[:resource_type], attribute)
|
48
|
-
end
|
49
|
-
end
|
50
|
-
|
51
|
-
def dynamic_text_tag(attributes)
|
52
|
-
text = attributes[:value] || attributes[:placeholder]
|
53
|
-
dynamic_text_attributes = {
|
54
|
-
class: "dynamic-text",
|
55
|
-
data: {"dynamic-tag": attributes[:dynamic_tag]}
|
56
|
-
}
|
57
|
-
|
58
|
-
content_tag(:span, text, dynamic_text_attributes)
|
59
|
-
end
|
60
|
-
|
61
|
-
def editable_text_tag(attributes)
|
62
|
-
editable_text_attributes = {
|
63
|
-
class: "editable-text",
|
64
|
-
contenteditable: true,
|
65
|
-
placeholder: attributes[:placeholder],
|
66
|
-
data: {"dynamic-tag": attributes[:dynamic_tag]}
|
67
|
-
}
|
68
|
-
|
69
|
-
content_tag(:span, attributes[:value], editable_text_attributes)
|
70
|
-
end
|
71
|
-
|
72
|
-
def patch_request_tag(attributes)
|
73
|
-
patch_request_attributes = {
|
74
|
-
'url' => attributes[:url],
|
75
|
-
'attribute' => attributes[:attribute],
|
76
|
-
'resource-type' => attributes[:resource_type],
|
77
|
-
'ajax-key' => attributes[:ajax_key]
|
78
|
-
}
|
79
|
-
|
80
|
-
hidden_field_tag("_action", "patch", patch_request_attributes)
|
81
|
-
end
|
82
|
-
|
83
|
-
def expected_resource_type(resource)
|
84
|
-
resource.class.name.downcase
|
85
|
-
end
|
86
|
-
|
87
|
-
def expected_path(resource, resource_type=expected_type_for(resource))
|
88
|
-
send("#{resource_type}_path", resource)
|
89
|
-
end
|
90
|
-
|
91
|
-
def default_dynamic_tag(resource_type, resource_id, attribute)
|
92
|
-
"#{resource_type}:#{resource_id}:#{attribute}"
|
93
|
-
end
|
94
|
-
|
95
|
-
def default_ajax_key(resource_type, attribute)
|
96
|
-
"#{resource_type}:#{attribute}"
|
8
|
+
def editable_text_for(resource, attribute, opts={})
|
9
|
+
DynamicText::ViewRenderer.new(self)
|
10
|
+
.render_editable_text_for(resource, attribute, opts)
|
97
11
|
end
|
98
12
|
end
|
99
13
|
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
<span class='editable-text-container'>
|
2
|
+
<%= content_tag(:span,
|
3
|
+
class: 'editable-text',
|
4
|
+
contenteditable: true,
|
5
|
+
placeholder: placeholder,
|
6
|
+
data: { 'dynamic-tag': dynamic_tag }
|
7
|
+
) do -%>
|
8
|
+
<%= value -%>
|
9
|
+
<% end %>
|
10
|
+
|
11
|
+
<input id='_action'
|
12
|
+
type='hidden'
|
13
|
+
name='_action'
|
14
|
+
value='patch'
|
15
|
+
url='<%= url %>'
|
16
|
+
attribute='<%= attribute %>'
|
17
|
+
resource-type='<%= resource_type %>'
|
18
|
+
js-key='<%= js_key %>'
|
19
|
+
>
|
20
|
+
</span>
|
@@ -1,11 +1,11 @@
|
|
1
1
|
class DynamicText::Configuration
|
2
|
-
attr_reader :
|
2
|
+
attr_reader :resource_scope
|
3
3
|
|
4
4
|
def initialize
|
5
|
-
@
|
5
|
+
@resource_scope = nil
|
6
6
|
end
|
7
7
|
|
8
|
-
def
|
9
|
-
@
|
8
|
+
def resource_scope=(resource_scope)
|
9
|
+
@resource_scope = "/#{resource_scope}"
|
10
10
|
end
|
11
11
|
end
|
@@ -0,0 +1,70 @@
|
|
1
|
+
class DynamicText::LocalsSetter
|
2
|
+
def get_dynamic_locals(resource, attribute, opts={})
|
3
|
+
locals.merge!(opts).tap do |locals|
|
4
|
+
locals[:resource] = resource
|
5
|
+
locals[:attribute] = attribute
|
6
|
+
locals[:resource_id] = resource.id
|
7
|
+
locals[:value] = resource.send(attribute)
|
8
|
+
locals[:resource_scope] ||= default_resource_scope
|
9
|
+
locals[:placeholder] ||= default_placeholder
|
10
|
+
locals[:resource_type] ||= default_resource_type
|
11
|
+
locals[:resource_route] ||= default_resource_route
|
12
|
+
locals[:dynamic_tag] ||= default_dynamic_tag
|
13
|
+
end
|
14
|
+
end #PT
|
15
|
+
|
16
|
+
def get_editable_locals(resource, attribute, opts={})
|
17
|
+
get_dynamic_locals(resource, attribute, opts).tap do |locals|
|
18
|
+
locals[:url] ||= default_url
|
19
|
+
locals[:js_key] ||= default_js_key
|
20
|
+
end
|
21
|
+
end #PT
|
22
|
+
|
23
|
+
private
|
24
|
+
|
25
|
+
# Defaults
|
26
|
+
|
27
|
+
def default_resource_scope
|
28
|
+
DynamicText.configuration.resource_scope
|
29
|
+
end
|
30
|
+
|
31
|
+
def default_placeholder
|
32
|
+
"Enter #{get_local(:attribute)}..."
|
33
|
+
end
|
34
|
+
|
35
|
+
def default_resource_type
|
36
|
+
get_local(:resource).class.name.downcase
|
37
|
+
end
|
38
|
+
|
39
|
+
def default_resource_route
|
40
|
+
get_local(:resource_type).pluralize
|
41
|
+
end
|
42
|
+
|
43
|
+
def default_dynamic_tag
|
44
|
+
get_locals(:resource_type, :resource_id, :attribute).join(":")
|
45
|
+
end
|
46
|
+
|
47
|
+
def default_url
|
48
|
+
get_locals(:resource_scope, :resource_route, :resource_id).join("/")
|
49
|
+
end
|
50
|
+
|
51
|
+
def default_js_key
|
52
|
+
get_locals(:resource_type, :attribute).join(":")
|
53
|
+
end
|
54
|
+
|
55
|
+
# Helpers
|
56
|
+
|
57
|
+
def locals
|
58
|
+
@locals ||= {}
|
59
|
+
end
|
60
|
+
|
61
|
+
def get_local(local_name)
|
62
|
+
locals[local_name]
|
63
|
+
end
|
64
|
+
|
65
|
+
def get_locals(*local_names)
|
66
|
+
local_names.collect do |local_name|
|
67
|
+
get_local(local_name)
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
data/lib/dynamic_text/version.rb
CHANGED
@@ -0,0 +1,39 @@
|
|
1
|
+
class DynamicText::ViewRenderer < AbstractController::Base
|
2
|
+
def initialize(controller)
|
3
|
+
@controller = controller
|
4
|
+
end
|
5
|
+
|
6
|
+
def render_dynamic_text_for(resource, attribute, opts={})
|
7
|
+
render_dynamic_text dynamic_locals(resource, attribute, opts)
|
8
|
+
end
|
9
|
+
|
10
|
+
def render_editable_text_for(resource, attribute, opts={})
|
11
|
+
render_editable_text editable_locals(resource, attribute, opts)
|
12
|
+
end
|
13
|
+
|
14
|
+
private
|
15
|
+
|
16
|
+
def dynamic_locals(resource, attribute, opts={})
|
17
|
+
locals_setter.get_dynamic_locals(resource, attribute, opts)
|
18
|
+
end
|
19
|
+
|
20
|
+
def editable_locals(resource, attribute, opts={})
|
21
|
+
locals_setter.get_editable_locals(resource, attribute, opts)
|
22
|
+
end
|
23
|
+
|
24
|
+
def locals_setter
|
25
|
+
DynamicText::LocalsSetter.new
|
26
|
+
end
|
27
|
+
|
28
|
+
def render_editable_text(locals)
|
29
|
+
render_partial(:editable_text, **locals)
|
30
|
+
end
|
31
|
+
|
32
|
+
def render_dynamic_text(locals)
|
33
|
+
render_partial(:dynamic_text, **locals)
|
34
|
+
end
|
35
|
+
|
36
|
+
def render_partial(partial, **locals)
|
37
|
+
@controller.render partial: "dynamic_text/#{partial}", locals: locals
|
38
|
+
end
|
39
|
+
end
|
data/lib/dynamic_text.rb
CHANGED
data/spec/dummy/Rakefile
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
// This is a manifest file that'll be compiled into application.js, which will include all the files
|
2
|
+
// listed below.
|
3
|
+
//
|
4
|
+
// Any JavaScript/Coffee file within this directory, lib/assets/javascripts, vendor/assets/javascripts,
|
5
|
+
// or any plugin's vendor/assets/javascripts directory can be referenced here using a relative path.
|
6
|
+
//
|
7
|
+
// It's not advisable to add code directly here, but if you do, it'll appear at the bottom of the
|
8
|
+
// compiled file. JavaScript code in this file should be added after the last require_* statement.
|
9
|
+
//
|
10
|
+
// Read Sprockets README (https://github.com/rails/sprockets#sprockets-directives) for details
|
11
|
+
// about supported directives.
|
12
|
+
//
|
13
|
+
//= require rails-ujs
|
14
|
+
//= require activestorage
|
15
|
+
//= require_tree .
|
@@ -0,0 +1,13 @@
|
|
1
|
+
// Action Cable provides the framework to deal with WebSockets in Rails.
|
2
|
+
// You can generate new channels where WebSocket features live using the `rails generate channel` command.
|
3
|
+
//
|
4
|
+
//= require action_cable
|
5
|
+
//= require_self
|
6
|
+
//= require_tree ./channels
|
7
|
+
|
8
|
+
(function() {
|
9
|
+
this.App || (this.App = {});
|
10
|
+
|
11
|
+
App.cable = ActionCable.createConsumer();
|
12
|
+
|
13
|
+
}).call(this);
|
@@ -0,0 +1,15 @@
|
|
1
|
+
/*
|
2
|
+
* This is a manifest file that'll be compiled into application.css, which will include all the files
|
3
|
+
* listed below.
|
4
|
+
*
|
5
|
+
* Any CSS and SCSS file within this directory, lib/assets/stylesheets, vendor/assets/stylesheets,
|
6
|
+
* or any plugin's vendor/assets/stylesheets directory can be referenced here using a relative path.
|
7
|
+
*
|
8
|
+
* You're free to add application-wide styles to this file and they'll appear at the bottom of the
|
9
|
+
* compiled file so the styles you add here take precedence over styles defined in any other CSS/SCSS
|
10
|
+
* files in this directory. Styles in this file should be added after the last require_* statement.
|
11
|
+
* It is generally better to create a new file per style scope.
|
12
|
+
*
|
13
|
+
*= require_tree .
|
14
|
+
*= require_self
|
15
|
+
*/
|
@@ -0,0 +1,15 @@
|
|
1
|
+
<!DOCTYPE html>
|
2
|
+
<html>
|
3
|
+
<head>
|
4
|
+
<title>Dummy</title>
|
5
|
+
<%= csrf_meta_tags %>
|
6
|
+
<%= csp_meta_tag %>
|
7
|
+
|
8
|
+
<%= stylesheet_link_tag 'application', media: 'all' %>
|
9
|
+
<%= javascript_include_tag 'application' %>
|
10
|
+
</head>
|
11
|
+
|
12
|
+
<body>
|
13
|
+
<%= yield %>
|
14
|
+
</body>
|
15
|
+
</html>
|
@@ -0,0 +1 @@
|
|
1
|
+
<%= yield %>
|
data/spec/dummy/bin/rake
ADDED