dato-rails 0.7.5 → 0.10.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/README.md +78 -54
- data/app/components/dato/base_component.rb +9 -0
- data/app/components/dato/block.html.erb +18 -11
- data/app/components/dato/dast_node.rb +6 -0
- data/app/components/dato/image_block_record.html.erb +1 -0
- data/app/components/dato/image_block_record.rb +2 -0
- data/app/components/dato/inline_block.html.erb +20 -0
- data/app/components/dato/inline_block.rb +7 -0
- data/app/components/dato/inline_item.html.erb +39 -0
- data/app/components/dato/inline_item.rb +4 -0
- data/app/components/dato/item_link.html.erb +18 -0
- data/app/components/dato/item_link.rb +20 -0
- data/app/components/dato/link.rb +1 -7
- data/app/components/dato/live_stream.html.erb +26 -0
- data/app/components/dato/live_stream.rb +35 -0
- data/app/components/dato/node.rb +30 -2
- data/app/components/dato/paragraph.rb +1 -1
- data/app/components/dato/responsive_image.html.erb +1 -1
- data/app/components/dato/responsive_image.rb +3 -2
- data/app/components/dato/structured_text.rb +2 -0
- data/app/components/dato/unknown_block.html.erb +18 -17
- data/app/components/dato/unknown_node.html.erb +14 -14
- data/app/components/dato/wrapper.html.erb +32 -0
- data/app/components/dato/wrapper.rb +38 -0
- data/app/controllers/dato/live_controller.rb +1 -1
- data/app/controllers/dato/publish_controller.rb +1 -1
- data/app/views/dato/live/create.turbo_stream.erb +7 -0
- data/config/routes.rb +1 -1
- data/lib/dato/cache.rb +4 -0
- data/lib/dato/client.rb +11 -1
- data/lib/dato/config.rb +6 -3
- data/lib/dato/current_request.rb +5 -0
- data/lib/dato/engine.rb +21 -0
- data/lib/dato/fragments/meta_tags.rb +5 -0
- data/lib/dato/gql.rb +4 -3
- data/lib/dato/railties/controller_runtime.rb +33 -0
- data/lib/dato/version.rb +1 -1
- data/lib/tasks/dato/rails_tasks.rake +7 -4
- metadata +22 -11
- data/app/components/dato/live.html.erb +0 -22
- data/app/components/dato/live.rb +0 -40
- data/app/views/dato/live/show.html.erb +0 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 1973ec82f04620deeaf8b94c8b8fe4816c60f5c00cf0ccfba93ab38e938af5fb
|
4
|
+
data.tar.gz: 1f83767d11f764f199b4bf394da6d216a237d22a37fee001542413f5f183ab61
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 69b37b143b7e6f422c28f3b74677991d876a5bd181e3ebf97e9bc93d31165404bc39c32991cdbf3cd635c640fde730cc564a00c002ff4cf725870ec2703282c4
|
7
|
+
data.tar.gz: b9f95b4994a61b6801a781ba3369e679a1dbfc012d356a213de48b30bbab8a54ca2282d33a7754368c3b12b594b8b22ec265dc89b4776c083c0086707cf97dea
|
data/README.md
CHANGED
@@ -6,6 +6,8 @@ This gem allows you to fetch data using Dato GraphQL APIs and render the content
|
|
6
6
|
|
7
7
|
👉 See [this simple tutorial to get started on dev.to](https://dev.to/coorasse/datocms-with-ruby-on-rails-3ae5). 👈
|
8
8
|
|
9
|
+
👉 See also [this second tutorial to build a Blog](https://dev.to/coorasse/rails-blog-with-datocms-2h1e). 👈
|
10
|
+
|
9
11
|
## Installation
|
10
12
|
|
11
13
|
Add this line to your application's Gemfile:
|
@@ -31,7 +33,9 @@ queries to the GraphQL endpoint.
|
|
31
33
|
Look at GQLi documentation for more information about the syntax of queries.
|
32
34
|
You can also find some examples in specs of this library.
|
33
35
|
|
34
|
-
Set your api token as `DATO_API_TOKEN` environment variable
|
36
|
+
Set your api token as `DATO_API_TOKEN` environment variable or as
|
37
|
+
`Rails.application.credentials.dig(:dato, :api_token)`.
|
38
|
+
ENV variable will have precedence.
|
35
39
|
|
36
40
|
```ruby
|
37
41
|
client = Dato::Client.new # you can also pass the api token here.
|
@@ -57,7 +61,7 @@ GQLi::DSL.query {
|
|
57
61
|
__typename
|
58
62
|
id
|
59
63
|
image {
|
60
|
-
responsiveImage(imgixParams: {fm: __enum("png")}) {
|
64
|
+
responsiveImage(imgixParams: { fm: __enum("png") }) {
|
61
65
|
___ Dato::Fragments::ResponsiveImage
|
62
66
|
}
|
63
67
|
}
|
@@ -86,27 +90,13 @@ If you have a responsive image, you can render it with:
|
|
86
90
|
render Dato::ResponsiveImage.new(node.image.responsiveImage)
|
87
91
|
```
|
88
92
|
|
89
|
-
|
90
|
-
|
91
|
-
You can also customize how each node type is rendered by specifying the mapping on the single render:
|
92
|
-
|
93
|
-
```ruby
|
94
|
-
render Dato::StructuredText.new(response.data.homepage.content, overrides: { link: Dato::NotRendered })
|
95
|
-
```
|
96
|
-
|
97
|
-
or globally:
|
98
|
-
|
99
|
-
```
|
100
|
-
# config/initializers/dato.rb
|
101
|
-
|
102
|
-
Dato::Config.overrides = {
|
103
|
-
link: 'Dato::NotRendered'
|
104
|
-
}.with_indifferent_access
|
105
|
-
```
|
93
|
+
Read more about [StructuredText - Custom Nodes](docs/custom_nodes.md).
|
106
94
|
|
107
95
|
## Preview and live
|
108
96
|
|
109
|
-
The `Dato::Client` supports
|
97
|
+
The `Dato::Client` supports
|
98
|
+
both [preview](https://www.datocms.com/docs/pro-tips/how-to-manage-a-live-and-a-preview-site)
|
99
|
+
and [live updates](https://www.datocms.com/docs/real-time-updates-api) features from Dato CMS.
|
110
100
|
|
111
101
|
```ruby
|
112
102
|
Dato::Client.new(preview: true) # to fetch draft versions
|
@@ -123,13 +113,13 @@ you probably have the following:
|
|
123
113
|
|
124
114
|
```ruby
|
125
115
|
result = Dato::Client.new.execute!(my_query)
|
126
|
-
render(MyComponent.new(result))
|
116
|
+
render(MyComponent.new(result.data))
|
127
117
|
```
|
128
118
|
|
129
|
-
you can now wrap everything in a `Dato::
|
119
|
+
you can now wrap everything in a `Dato::Wrapper` component like this:
|
130
120
|
|
131
121
|
```ruby
|
132
|
-
render(Dato::
|
122
|
+
render(Dato::Wrapper.new(MyComponent, my_query, preview: true, live: true))
|
133
123
|
```
|
134
124
|
|
135
125
|
and your component will come to life with live updates 🎉 (requires turbo).
|
@@ -170,24 +160,26 @@ Dato::Client.new.items.destroy(item_id: '123')
|
|
170
160
|
|
171
161
|
## File upload
|
172
162
|
|
173
|
-
Dato Rails also supports file uploads.
|
174
|
-
These can be created either from a local file or from a url.
|
163
|
+
Dato Rails also supports file uploads.
|
164
|
+
These can be created either from a local file or from a url.
|
175
165
|
Basically all file types are supported, as long as they are valid in the CMS.
|
176
|
-
Be aware that dato jobs are not synchronous, so you may need to
|
166
|
+
Be aware that dato jobs are not synchronous, so you may need to
|
177
167
|
implement some kind of polling to check if the upload is finished.
|
178
168
|
The create method returns a job id, which can be used to retrieve the upload result.
|
179
169
|
|
180
|
-
> In addition to the binary file, also attributes and metadata can be uploaded.
|
181
|
-
Both metadata and attributes are optional.
|
170
|
+
> In addition to the binary file, also attributes and metadata can be uploaded.
|
171
|
+
> Both metadata and attributes are optional.
|
182
172
|
> Provide attributes according to the [docs](https://www.datocms.com/docs/content-management-api/resources/upload)
|
183
173
|
|
184
174
|
### Upload from Url
|
175
|
+
|
185
176
|
```ruby
|
186
177
|
Dato::Client.new.uploads.create_from_url('https://picsum.photos/seed/picsum/200/300')
|
187
178
|
Dato::Client.new.uploads.create_from_url('https://picsum.photos/seed/picsum/200/300', attributes:)
|
188
179
|
```
|
189
180
|
|
190
181
|
### Upload from Local File
|
182
|
+
|
191
183
|
```ruby
|
192
184
|
file = File.open('image.png')
|
193
185
|
|
@@ -203,20 +195,23 @@ attributes = { author: 'Dato Rails', default_field_metadata: meta }
|
|
203
195
|
```
|
204
196
|
|
205
197
|
### Optional: Filename
|
198
|
+
|
206
199
|
```ruby
|
207
200
|
Dato::Client.new.uploads.create_from_url('https://picsum.photos/seed/picsum/200/300', filename: 'test.png')
|
208
201
|
Dato::Client.new.uploads.create_from_file(file.path, filename: 'test.png')
|
209
202
|
```
|
210
203
|
|
211
|
-
|
212
204
|
### Getting the upload id
|
213
|
-
|
205
|
+
|
206
|
+
As the file upload is asynchronous, you may need to implement some kind of polling to check if the upload is finished.
|
214
207
|
With the retrieve_job_result method you can retrieve the upload id from the job result.
|
208
|
+
|
215
209
|
```ruby
|
216
210
|
job_id = client.uploads.create_from_file(file.path) # get back a job id
|
217
211
|
response = client.uploads.retrieve_job_result(job_id).parse # check the status
|
218
212
|
upload_id = response.dig('data', 'attributes', 'payload', 'data', 'id') # if nil, it's not done yet
|
219
213
|
```
|
214
|
+
|
220
215
|
## Configuration
|
221
216
|
|
222
217
|
The following options are available:
|
@@ -229,15 +224,18 @@ Dato::Config.configure do |config|
|
|
229
224
|
config.blocks = {} # default: {}
|
230
225
|
config.cache = false # default: false
|
231
226
|
config.cache_namespace = 'dato-rails' # default: 'dato-rails'
|
232
|
-
config.
|
233
|
-
config.
|
227
|
+
config.api_token = ENV['DATO_PUBLISH_KEY'] # default: ENV.fetch("DATO_API_TOKEN", Rails.application.credentials.dig(:dato, :api_token))
|
228
|
+
config.publish_key = ENV['DATO_PUBLISH_KEY'] # default: ENV.fetch("DATO_PUBLISH_KEY", Rails.application.credentials.dig(:dato, :publish_key))
|
229
|
+
config.build_trigger_id = ENV['DATO_BUILD_TRIGGER_ID'] # default: ENV.fetch("DATO_BUILD_TRIGGER_ID", Rails.application.credentials.dig(:dato, :build_trigger_id))
|
230
|
+
config.base_editing_url = ENV['DATO_BASE_EDITING_URL'] # default: ENV.fetch("DATO_BASE_EDITING_URL", Rails.application.credentials.dig(:dato, :base_editing_url))
|
231
|
+
config.mount_path = '/dato' # default: '/dato'
|
234
232
|
end
|
235
233
|
```
|
236
234
|
|
237
235
|
## Caching
|
238
236
|
|
239
237
|
The library supports caching of the rendered components.
|
240
|
-
If you enable caching, the components rendered using `Dato::
|
238
|
+
If you enable caching, the components rendered using `Dato::Wrapper`, will be cached.
|
241
239
|
|
242
240
|
To enable caching, you need to set the `cache` option in the configuration.
|
243
241
|
|
@@ -252,67 +250,93 @@ end
|
|
252
250
|
Now a call to
|
253
251
|
|
254
252
|
```ruby
|
255
|
-
render(Dato::
|
253
|
+
render(Dato::Wrapper.new(MyComponent, my_query))
|
256
254
|
```
|
257
255
|
|
258
|
-
will be cached for 1 day.
|
256
|
+
will be cached for 1 day.
|
259
257
|
|
260
|
-
This means that for the next 24 hours, the graphQL endpoint will not be invoked and the whole component rendering will
|
258
|
+
This means that for the next 24 hours, the graphQL endpoint will not be invoked and the whole component rendering will
|
259
|
+
also be skipped.
|
261
260
|
|
262
261
|
**We will cache the entire HTML result of the component, not only the graphQL response.**
|
263
262
|
|
264
263
|
If you want to expire the cache you have two options:
|
265
264
|
|
266
|
-
###
|
265
|
+
### manual
|
267
266
|
|
268
|
-
executing `
|
267
|
+
executing `Dato::Cache.clear!` or running `bin/rails dato:cache:clear`.
|
269
268
|
|
270
269
|
### publish endpoint
|
271
270
|
|
272
271
|
You can take advantage of the publish mechanism of Dato CMS to expire the cache.
|
273
|
-
|
274
|
-
*
|
272
|
+
|
273
|
+
* Generate a new secret key with `bin/rails secret` and set it as `DATO_PUBLISH_KEY` environment variable or in Rails Credentials as `dato.publish_key`.
|
275
274
|
* Create a build trigger with a custom webhook on your Dato CMS project setting.
|
276
275
|
* Define the Trigger URL as `https://yourapp.com/dato/publish`
|
277
276
|
* Set the `DATO_PUBLISH_KEY` as the Authorization header
|
278
277
|
* Copy the build trigger id and set it as `DATO_BUILD_TRIGGER_ID` environment variable.
|
279
278
|
|
279
|
+

|
280
|
+
|
281
|
+
### Caching of graphQL response / Controller helpers
|
282
|
+
|
283
|
+
If you are not using ViewComponents or you need to cache a single GraphQL query, you can still do it using the
|
284
|
+
`Dato::Cache` helper.
|
285
|
+
|
286
|
+
In your controllers you already have a helper method `execute_dato_query!`.
|
287
|
+
You can use it in your controller action and queries results will be automatically cached if:
|
288
|
+
|
289
|
+
* You have `Dato` cache enabled
|
290
|
+
* You have Rails cache enabled (check your environment configuration)
|
291
|
+
* you are not displaying a preview
|
292
|
+
|
293
|
+
```ruby
|
294
|
+
response = execute_dato_query!(blog_post_query(params[:slug]), preview: params[:preview])
|
295
|
+
@data = response.data
|
296
|
+
```
|
297
|
+
|
298
|
+
by using this helper, subsequent calls towards Dato will be cached.
|
280
299
|
|
300
|
+
## Logs instrumentation
|
301
|
+
|
302
|
+
In the logs you will see the time taken to fetch the data from Dato CMS.
|
303
|
+
For example:
|
304
|
+
|
305
|
+
```
|
306
|
+
Completed 200 OK in 365ms (Views: 109.5ms | ActiveRecord: 0.7ms (4 queries, 0 cached) | Dato: 254.3ms | GC: 0.0ms)`
|
307
|
+
```
|
308
|
+
|
309
|
+
this is useful to identify if the bottleneck is in the fetching of the data from Dato CMS.
|
281
310
|
|
282
311
|
## Development
|
283
312
|
|
284
|
-
After checking out the repo, run `bundle install` to install dependencies.
|
313
|
+
After checking out the repo, run `bundle install` to install dependencies.
|
285
314
|
|
286
315
|
You can now clone the dato-rails project
|
287
316
|
|
288
317
|
[](https://dashboard.datocms.com/clone?projectId=57262&name=dato-rails
|
289
318
|
)
|
290
319
|
|
291
|
-
|
292
320
|
You then need to set a `DATO_API_TOKEN=abcd123x` in the `.env` file on the root of your project
|
293
321
|
to consume data from your project. For testing purposes, set `TEST_MODEL_TYPE_ID=1234` in the `.env` file
|
294
322
|
with the id of the author model type in your project.
|
295
323
|
|
296
|
-
Then, run `bundle exec rspec` to run the tests.
|
324
|
+
Then, run `bundle exec rspec` to run the tests.
|
297
325
|
|
298
326
|
You can also run `rails console` for an interactive prompt that will allow you to experiment.
|
299
327
|
|
300
|
-
To install this gem onto your local machine, run `bundle exec rake install`.
|
301
|
-
To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`,
|
302
|
-
which will create a git tag for the version, push git commits and the created tag,
|
328
|
+
To install this gem onto your local machine, run `bundle exec rake install`.
|
329
|
+
To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`,
|
330
|
+
which will create a git tag for the version, push git commits and the created tag,
|
303
331
|
and push the `.gem` file to [rubygems.org](https://rubygems.org).
|
304
332
|
|
305
333
|
## Contributing
|
306
334
|
|
307
|
-
Bug reports and pull requests are welcome on GitHub at https://github.com/renuo/dato-rails.
|
308
|
-
This project is intended to be a safe, welcoming space for collaboration
|
309
|
-
|
335
|
+
Bug reports and pull requests are welcome on GitHub at https://github.com/renuo/dato-rails.
|
336
|
+
This project is intended to be a safe, welcoming space for collaboration.
|
337
|
+
|
338
|
+
Try to be a decent human being while interacting with other people.
|
310
339
|
|
311
340
|
## License
|
312
341
|
|
313
342
|
The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
|
314
|
-
|
315
|
-
## Code of Conduct
|
316
|
-
|
317
|
-
Everyone interacting in the Dato::Rails project's codebases, issue trackers, chat rooms and mailing lists is
|
318
|
-
expected to follow the [code of conduct](https://github.com/renuo/dato-rails/blob/master/CODE_OF_CONDUCT.md).
|
@@ -1,13 +1,20 @@
|
|
1
|
-
<% block = blocks
|
2
|
-
<% if block.
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
1
|
+
<% block = blocks&.find { |b| b.id == @node.item } %>
|
2
|
+
<% if block.nil? %>
|
3
|
+
<%= error_block do %>
|
4
|
+
There is a block with id <code><%= @node.item %></code> that has not been retrieved by the GraphQL Query.<br>
|
5
|
+
It's possible that your query is returning a structured text without blocks.
|
6
|
+
<% end %>
|
7
|
+
<% elsif block.__typename.nil? %>
|
8
|
+
<%= error_block do %>
|
9
|
+
In order to render a block, you need to return its <code>__typename</code>.<br>
|
10
|
+
In your GraphQL query, add <code>__typename</code> to the list of fields returned for the blocks.<br>
|
11
|
+
For example:<br><br>
|
12
|
+
<code>
|
13
|
+
blocks {
|
14
|
+
__typename
|
15
|
+
}
|
16
|
+
</code>
|
17
|
+
<% end %>
|
11
18
|
<% else %>
|
12
|
-
<%=render class_for_block(block).new(block, root) %>
|
19
|
+
<%= render class_for_block(block).new(block, root) %>
|
13
20
|
<% end %>
|
@@ -0,0 +1 @@
|
|
1
|
+
<%= render Dato::ResponsiveImage.new(@node.image.responsiveImage) %>
|
@@ -0,0 +1,20 @@
|
|
1
|
+
<% block = blocks&.find { |b| b.id == @node.item } %>
|
2
|
+
<% if block.nil? %>
|
3
|
+
<%= error_block do %>
|
4
|
+
There is an inline block with id <code><%= @node.item %></code> that has not been retrieved by the GraphQL Query.<br>
|
5
|
+
It's possible that your query is returning a structured text without blocks.
|
6
|
+
<% end %>
|
7
|
+
<% elsif block.__typename.nil? %>
|
8
|
+
<%= error_block do %>
|
9
|
+
In order to render an inline block, you need to return its <code>__typename</code>.<br>
|
10
|
+
In your GraphQL query, add <code>__typename</code> to the list of fields returned for the blocks.<br>
|
11
|
+
For example:<br><br>
|
12
|
+
<code>
|
13
|
+
blocks {
|
14
|
+
__typename
|
15
|
+
}
|
16
|
+
</code>
|
17
|
+
<% end %>
|
18
|
+
<% else %>
|
19
|
+
<%= render class_for_block(block).new(block, root) %>
|
20
|
+
<% end %>
|
@@ -0,0 +1,39 @@
|
|
1
|
+
<% inline_item = links.find { |b| b.id == @node.item } %>
|
2
|
+
|
3
|
+
<% if inline_item.present? %>
|
4
|
+
<% if class_for_inline_item(inline_item).present? %>
|
5
|
+
<%= render class_for_inline_item(inline_item).new(inline_item, root) %>
|
6
|
+
<% elsif path_for_inline_item(inline_item).present? %>
|
7
|
+
<%= link_to inline_item.title, path_for_inline_item(inline_item), class: "dato-cms-#{@node.type}" %>
|
8
|
+
<% else %>
|
9
|
+
<%= error_block do %>
|
10
|
+
This is an unknown InlineItem. Here is the content:<br>
|
11
|
+
<pre><%= JSON.pretty_generate(inline_item) %></pre>
|
12
|
+
This is a link, so you have some options:
|
13
|
+
<ul>
|
14
|
+
<li>Define the function to generate path for this item. For example:<br>
|
15
|
+
<code>
|
16
|
+
config.links_mapping = {<br>
|
17
|
+
'<%= inline_item.__typename %>' => ->(inline_item) { blog_post_path(inline_item.slug) }<br>
|
18
|
+
}<br>
|
19
|
+
</code>
|
20
|
+
This will use the default link renderer, and set the href attribute according to your definition.
|
21
|
+
</li>
|
22
|
+
<li>
|
23
|
+
Define a class in your <code>app/components/dato</code> folder. For example:<br>
|
24
|
+
<code>
|
25
|
+
class <%= class_by_type(inline_item.__typename) %> < Dato::Node<br>
|
26
|
+
...<br>
|
27
|
+
end<br>
|
28
|
+
</code><br>
|
29
|
+
</li>
|
30
|
+
<li>Not render it by excluding it from your GraphQL Query</li>
|
31
|
+
<li>Not render it by using the overrides: <code>{overrides: '<%= @node.__typename %>': Dato::NotRendered }</code></li>
|
32
|
+
</ul>
|
33
|
+
<% end %>
|
34
|
+
<% end %>
|
35
|
+
<% else %>
|
36
|
+
<%= error_block do %>
|
37
|
+
I don't know this inline item.
|
38
|
+
<% end %>
|
39
|
+
<% end %>
|
@@ -0,0 +1,18 @@
|
|
1
|
+
<% if inline_item.__typename.nil? %>
|
2
|
+
<%= error_block do %>
|
3
|
+
In order to render an item link, you need to return its <code>__typename</code>.<br>
|
4
|
+
In your GraphQL query, add <code>__typename</code> to the list of fields returned for the blocks.<br>
|
5
|
+
For example:<br><br>
|
6
|
+
<code>
|
7
|
+
links {
|
8
|
+
__typename
|
9
|
+
}
|
10
|
+
</code>
|
11
|
+
<% end %>
|
12
|
+
<% else %>
|
13
|
+
<%= tag.a(**link_attributes) do -%>
|
14
|
+
<% @node.children&.each do |node| -%>
|
15
|
+
<%= render_node(node) -%>
|
16
|
+
<% end -%>
|
17
|
+
<% end -%>
|
18
|
+
<% end %>
|
@@ -0,0 +1,20 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class Dato::ItemLink < Dato::DastNode
|
4
|
+
def initialize(node, root)
|
5
|
+
super(node, "itemLink", root)
|
6
|
+
end
|
7
|
+
|
8
|
+
def inline_item
|
9
|
+
links.find { |b| b.id == @node.item }
|
10
|
+
end
|
11
|
+
|
12
|
+
def link_attributes
|
13
|
+
attr = {
|
14
|
+
"href" => path_for_inline_item(inline_item),
|
15
|
+
"class" => "dato-cms-#{@node.type}"
|
16
|
+
}
|
17
|
+
%w[rel target].each { |type| attr[type] = extract_meta(type) }
|
18
|
+
attr
|
19
|
+
end
|
20
|
+
end
|
data/app/components/dato/link.rb
CHANGED
@@ -12,15 +12,9 @@ class Dato::Link < Dato::DastNode
|
|
12
12
|
def link_attributes
|
13
13
|
attr = {
|
14
14
|
"href" => @node.url,
|
15
|
-
"class" => "dato-cms-#{@node.type}"
|
15
|
+
"class" => "dato-cms-#{@node.type}"
|
16
16
|
}
|
17
17
|
%w[rel target].each { |type| attr[type] = extract_meta(type) }
|
18
18
|
attr
|
19
19
|
end
|
20
|
-
|
21
|
-
private
|
22
|
-
|
23
|
-
def extract_meta(type)
|
24
|
-
@node.meta&.find { |m| m.id == type }&.value
|
25
|
-
end
|
26
20
|
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
<script type="text/javascript">
|
2
|
+
const eventSourceUrl = '<%= data.url %>';
|
3
|
+
const componentKlass = '<%= component_klass %>';
|
4
|
+
const frameId = '<%= frame_id %>';
|
5
|
+
const path = '<%= Dato::Engine.routes.url_helpers.live_path %>';
|
6
|
+
const eventSource = new EventSource(eventSourceUrl);
|
7
|
+
const csrfToken = document.querySelector('meta[name="csrf-token"]').content
|
8
|
+
eventSource.addEventListener("update", (event) => {
|
9
|
+
fetch(path, {
|
10
|
+
method: "POST",
|
11
|
+
headers: {
|
12
|
+
'X-CSRF-Token': csrfToken,
|
13
|
+
'Content-Type': 'application/json',
|
14
|
+
"Accept": "text/vnd.turbo-stream.html"
|
15
|
+
},
|
16
|
+
body: JSON.stringify({
|
17
|
+
component: componentKlass,
|
18
|
+
data: event.data,
|
19
|
+
frame_id: frameId
|
20
|
+
})
|
21
|
+
}).then(response => response.text())
|
22
|
+
.then(html => Turbo.renderStreamMessage(html));
|
23
|
+
});
|
24
|
+
</script>
|
25
|
+
|
26
|
+
<div id=<%= frame_id %>></div>
|
@@ -0,0 +1,35 @@
|
|
1
|
+
# This component can bring to life your dato components allowing previews and live updates.
|
2
|
+
# Given that you have a ViewComponent "MyComponent" that renders your page, you can render your page with:
|
3
|
+
# render(MyComponent.new(data_result_from_dato_query))
|
4
|
+
# you can now use this wrapper component to do:
|
5
|
+
# render(Dato::LiveStream.new(MyComponent, query, preview: true)
|
6
|
+
module Dato
|
7
|
+
class LiveStream < ViewComponent::Base
|
8
|
+
delegate :turbo_frame_tag, to: :helpers
|
9
|
+
|
10
|
+
attr_reader :component_klass, :query, :preview
|
11
|
+
|
12
|
+
def initialize(component_klass, query, preview: false)
|
13
|
+
super()
|
14
|
+
@component_klass = component_klass
|
15
|
+
@query = query
|
16
|
+
@preview = preview
|
17
|
+
end
|
18
|
+
|
19
|
+
def data
|
20
|
+
@data ||= dato_fetch(query, preview: preview)
|
21
|
+
end
|
22
|
+
|
23
|
+
def frame_id
|
24
|
+
@frame_id ||= SecureRandom.hex(10)
|
25
|
+
end
|
26
|
+
|
27
|
+
private
|
28
|
+
|
29
|
+
def dato_fetch(query, preview: false)
|
30
|
+
client = Dato::Client.new(preview: preview, live: true)
|
31
|
+
response = client.live!(query)
|
32
|
+
response.data
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
data/app/components/dato/node.rb
CHANGED
@@ -17,6 +17,10 @@ module Dato
|
|
17
17
|
root.blocks
|
18
18
|
end
|
19
19
|
|
20
|
+
def links
|
21
|
+
root.links
|
22
|
+
end
|
23
|
+
|
20
24
|
def overrides
|
21
25
|
root.overrides
|
22
26
|
end
|
@@ -28,7 +32,7 @@ module Dato
|
|
28
32
|
private
|
29
33
|
|
30
34
|
def class_for_block(block)
|
31
|
-
class_name =
|
35
|
+
class_name = overrides[block.__typename] || Dato::Config.overrides[block.__typename]
|
32
36
|
if class_name.is_a?(String)
|
33
37
|
class_name = class_name.constantize
|
34
38
|
end
|
@@ -39,8 +43,27 @@ module Dato
|
|
39
43
|
end
|
40
44
|
end
|
41
45
|
|
46
|
+
def class_for_inline_item(inline_item)
|
47
|
+
class_name = overrides[inline_item.__typename] || Dato::Config.overrides[inline_item.__typename]
|
48
|
+
if class_name.is_a?(String)
|
49
|
+
class_name = class_name.constantize
|
50
|
+
end
|
51
|
+
begin
|
52
|
+
class_name || class_by_type(inline_item.__typename).constantize
|
53
|
+
rescue NameError
|
54
|
+
nil
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
def path_for_inline_item(inline_item)
|
59
|
+
lambda = Dato::Config.links_mapping[inline_item.__typename]
|
60
|
+
if lambda
|
61
|
+
instance_exec(inline_item, &lambda)
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
42
65
|
def class_for_node(node)
|
43
|
-
class_name =
|
66
|
+
class_name = overrides[node.type] || Dato::Config.overrides[node.type]
|
44
67
|
if class_name.is_a?(String)
|
45
68
|
class_name = class_name.constantize
|
46
69
|
end
|
@@ -54,5 +77,10 @@ module Dato
|
|
54
77
|
def class_by_type(type)
|
55
78
|
"Dato::#{type.classify}"
|
56
79
|
end
|
80
|
+
|
81
|
+
def error_block(&block)
|
82
|
+
content = capture(&block)
|
83
|
+
content_tag(:div, content, style: "border: 3px dotted limegreen; display: inline-block; padding: 5px;font-weight: bold")
|
84
|
+
end
|
57
85
|
end
|
58
86
|
end
|
@@ -4,7 +4,7 @@
|
|
4
4
|
<picture style="position: absolute; left: 0; top: 0; width: 100%">
|
5
5
|
<source srcset="<%= @node.webpSrcSet %>" type="image/webp">
|
6
6
|
<source srcset="<%= @node.srcSet %>">
|
7
|
-
<img src="<%= @node.src %>" alt="<%= @node.alt %>" title="<%= @node.title %>" loading="lazy" width="100%">
|
7
|
+
<img src="<%= @node.src %>" alt="<%= @node.alt %>" title="<%= @node.title %>" loading="lazy" width="100%" class="<%= @custom_img_css_classes %>">
|
8
8
|
</picture>
|
9
9
|
</div>
|
10
10
|
</div>
|
@@ -1,8 +1,9 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
class Dato::ResponsiveImage < Dato::Node
|
4
|
-
def initialize(node, root = nil, custom_css_classes: [])
|
4
|
+
def initialize(node, root = nil, custom_css_classes: [], custom_img_css_classes: [])
|
5
5
|
super(node, root)
|
6
|
-
@custom_css_classes = custom_css_classes
|
6
|
+
@custom_css_classes = custom_css_classes.is_a?(Array) ? custom_css_classes.join(" ") : custom_css_classes
|
7
|
+
@custom_img_css_classes = custom_img_css_classes.is_a?(Array) ? custom_img_css_classes.join(" ") : custom_img_css_classes
|
7
8
|
end
|
8
9
|
end
|
@@ -13,6 +13,7 @@ class Dato::StructuredText < Dato::Node
|
|
13
13
|
@overrides = overrides.with_indifferent_access
|
14
14
|
@structured_text_node = structured_text_node
|
15
15
|
@blocks = structured_text_node.blocks
|
16
|
+
@links = structured_text_node.links
|
16
17
|
end
|
17
18
|
|
18
19
|
def root
|
@@ -20,6 +21,7 @@ class Dato::StructuredText < Dato::Node
|
|
20
21
|
end
|
21
22
|
|
22
23
|
attr_reader :blocks
|
24
|
+
attr_reader :links
|
23
25
|
|
24
26
|
attr_reader :overrides
|
25
27
|
end
|
@@ -1,17 +1,18 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
<
|
16
|
-
|
17
|
-
</
|
1
|
+
<%= error_block do %>
|
2
|
+
This is an unknown block. Here is the content:<br>
|
3
|
+
<pre><%= JSON.pretty_generate(@node) %></pre>
|
4
|
+
In order to render it, you need to define a ViewComponent named <code><%= class_by_type(@node.__typename) %></code>.
|
5
|
+
<br>
|
6
|
+
You can define this class in your <code>app/components/dato</code> folder. For example:<br><br>
|
7
|
+
<code>
|
8
|
+
class <%= class_by_type(@node.__typename) %> < Dato::Node<br>
|
9
|
+
...<br>
|
10
|
+
end<br>
|
11
|
+
</code><br>
|
12
|
+
If you don't want to render this block you can:
|
13
|
+
<ul>
|
14
|
+
<li>not return it in your GraphQL query</li>
|
15
|
+
<li>override the component when rendering the root <code>Dato::StructuredText</code> node.<br>
|
16
|
+
<code>Dato::StructuredText.new(content, overrides: { '<%= @node.__typename %>': Dato::NotRendered })</code></li>
|
17
|
+
</ul>
|
18
|
+
<% end %>
|
@@ -1,15 +1,15 @@
|
|
1
|
-
|
2
|
-
<
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
</
|
1
|
+
<%= error_block do %>
|
2
|
+
This is an unknown node of type <code><%= @type %></code>. Here is the content:<br>
|
3
|
+
<pre><%= JSON.pretty_generate(@node) %></pre>
|
4
|
+
In order to render it, you need to define a ViewComponent named <code><%= class_by_type(@node.type) %></code>.<br>
|
5
|
+
You can define this class in your <code>app/components/dato</code> folder. For example:<br><br>
|
6
|
+
<code>
|
7
|
+
class <%= class_by_type(@node.type) %> < Dato::Node<br>
|
8
|
+
...<br>
|
9
|
+
end<br>
|
10
|
+
</code><br>
|
11
|
+
If you don't want to render this node, you can override the component when rendering the root
|
12
|
+
<code>Dato::StructuredText</code> node.<br>
|
13
|
+
<code>Dato::StructuredText.new(content, overrides: { link: Dato::NotRendered })</code>
|
14
14
|
<%= debug_node %>
|
15
|
-
|
15
|
+
<% end %>
|
@@ -0,0 +1,32 @@
|
|
1
|
+
<% if live? %>
|
2
|
+
<script type="text/javascript">
|
3
|
+
const eventSourceUrl = '<%= data.url %>';
|
4
|
+
const componentKlass = '<%= component_klass %>';
|
5
|
+
const frameId = '<%= frame_id %>';
|
6
|
+
const path = '<%= Dato::Engine.routes.url_helpers.live_path %>';
|
7
|
+
const eventSource = new EventSource(eventSourceUrl);
|
8
|
+
const csrfToken = document.querySelector('meta[name="csrf-token"]').content
|
9
|
+
eventSource.addEventListener("update", (event) => {
|
10
|
+
fetch(path, {
|
11
|
+
method: "POST",
|
12
|
+
headers: {
|
13
|
+
'X-CSRF-Token': csrfToken,
|
14
|
+
'Content-Type': 'application/json',
|
15
|
+
"Accept": "text/vnd.turbo-stream.html"
|
16
|
+
},
|
17
|
+
body: JSON.stringify({
|
18
|
+
component: componentKlass,
|
19
|
+
data: event.data,
|
20
|
+
frame_id: frameId
|
21
|
+
})
|
22
|
+
}).then(response => response.text())
|
23
|
+
.then(html => Turbo.renderStreamMessage(html));
|
24
|
+
});
|
25
|
+
</script>
|
26
|
+
|
27
|
+
<div id=<%= frame_id %>></div>
|
28
|
+
<% else %>
|
29
|
+
<%= Dato::Cache.fetch(cache_key) do %>
|
30
|
+
<% render(component_klass.new(data)) %>
|
31
|
+
<% end %>
|
32
|
+
<% end %>
|
@@ -0,0 +1,38 @@
|
|
1
|
+
module Dato
|
2
|
+
class Wrapper < ViewComponent::Base
|
3
|
+
attr_reader :component_klass, :query, :preview, :live
|
4
|
+
|
5
|
+
def initialize(component_klass, query, preview: false, live: false)
|
6
|
+
@component_klass = component_klass
|
7
|
+
@query = query
|
8
|
+
@preview = preview
|
9
|
+
@live = live
|
10
|
+
end
|
11
|
+
|
12
|
+
def live? = @live
|
13
|
+
|
14
|
+
def render_in(view_context)
|
15
|
+
if live?
|
16
|
+
LiveStream.new(component_klass, query, preview: preview).render_in(view_context)
|
17
|
+
else
|
18
|
+
super
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
def data
|
23
|
+
@data ||= dato_fetch(query, preview: preview)
|
24
|
+
end
|
25
|
+
|
26
|
+
def cache_key
|
27
|
+
@cache_key ||= Digest::MD5.hexdigest(query.to_gql)
|
28
|
+
end
|
29
|
+
|
30
|
+
private
|
31
|
+
|
32
|
+
def dato_fetch(query, preview: false)
|
33
|
+
client = Dato::Client.new(preview: preview)
|
34
|
+
response = client.execute!(query)
|
35
|
+
response.data
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
data/config/routes.rb
CHANGED
data/lib/dato/cache.rb
CHANGED
data/lib/dato/client.rb
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
module Dato
|
2
2
|
class Client
|
3
|
-
delegate :live!,
|
3
|
+
delegate :live!, to: :@gql
|
4
4
|
attr_reader :items, :uploads, :gql
|
5
5
|
|
6
6
|
def initialize(api_token = Dato::Config.api_token, validate_query: false, preview: false, live: false)
|
@@ -9,5 +9,15 @@ module Dato
|
|
9
9
|
@items = Dato::Items.new(api_token)
|
10
10
|
@uploads = Dato::Uploads.new(api_token)
|
11
11
|
end
|
12
|
+
|
13
|
+
def execute!(query)
|
14
|
+
ActiveSupport::Notifications.instrument("dato.query_execution") do
|
15
|
+
@gql.execute!(query)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
def execute(query)
|
20
|
+
@gql.execute(query)
|
21
|
+
end
|
12
22
|
end
|
13
23
|
end
|
data/lib/dato/config.rb
CHANGED
@@ -3,11 +3,14 @@ module Dato
|
|
3
3
|
include ActiveSupport::Configurable
|
4
4
|
|
5
5
|
config_accessor(:overrides) { {} }
|
6
|
+
config_accessor(:links_mapping) { {} }
|
6
7
|
config_accessor(:blocks) { {} }
|
7
8
|
config_accessor(:cache) { false }
|
8
9
|
config_accessor(:cache_namespace) { "dato-rails" }
|
9
|
-
config_accessor(:api_token) { ENV
|
10
|
-
config_accessor(:publish_key) { ENV
|
11
|
-
config_accessor(:build_trigger_id) { ENV
|
10
|
+
config_accessor(:api_token) { ENV.fetch("DATO_API_TOKEN", Rails.application.credentials.dig(:dato, :api_token)) }
|
11
|
+
config_accessor(:publish_key) { ENV.fetch("DATO_PUBLISH_KEY", Rails.application.credentials.dig(:dato, :publish_key)) }
|
12
|
+
config_accessor(:build_trigger_id) { ENV.fetch("DATO_BUILD_TRIGGER_ID", Rails.application.credentials.dig(:dato, :build_trigger_id)) }
|
13
|
+
config_accessor(:base_editing_url) { ENV.fetch("DATO_BASE_EDITING_URL", Rails.application.credentials.dig(:dato, :base_editing_url)) }
|
14
|
+
config_accessor(:mount_path) { "/dato" }
|
12
15
|
end
|
13
16
|
end
|
data/lib/dato/engine.rb
CHANGED
@@ -1,5 +1,26 @@
|
|
1
1
|
module Dato
|
2
|
+
class InvalidGraphqlQuery < StandardError; end
|
3
|
+
|
2
4
|
class Engine < ::Rails::Engine
|
3
5
|
isolate_namespace Dato
|
6
|
+
|
7
|
+
initializer "dato_rails.action_controller" do
|
8
|
+
ActiveSupport.on_load(:action_controller) do
|
9
|
+
include Dato::Railties::ControllerRuntime
|
10
|
+
end
|
11
|
+
|
12
|
+
ActiveSupport::Notifications.subscribe("dato.query_execution") do |_, start, finish, _, _payload|
|
13
|
+
Dato::CurrentRequest.dato_runtime ||= 0
|
14
|
+
Dato::CurrentRequest.dato_runtime += (finish - start) * 1000
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
initializer "dato_rails.configuration" do |app|
|
19
|
+
if Dato::Config.mount_path
|
20
|
+
app.routes.append do
|
21
|
+
mount Dato::Engine => Dato::Config.mount_path
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
4
25
|
end
|
5
26
|
end
|
data/lib/dato/gql.rb
CHANGED
@@ -2,11 +2,12 @@ module Dato
|
|
2
2
|
class Gql < GQLi::Client
|
3
3
|
def initialize(api_token, validate_query, preview, live)
|
4
4
|
@api_token = api_token
|
5
|
+
headers = {"Authorization" => @api_token}
|
6
|
+
headers["X-Base-Editing-Url"] = Dato::Config.base_editing_url if Dato::Config.base_editing_url.present?
|
7
|
+
|
5
8
|
super(
|
6
9
|
"https://graphql#{"-listen" if live}.datocms.com/#{"preview" if preview}",
|
7
|
-
headers:
|
8
|
-
"Authorization" => @api_token
|
9
|
-
},
|
10
|
+
headers: headers,
|
10
11
|
validate_query: validate_query && !live
|
11
12
|
)
|
12
13
|
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
module Dato
|
2
|
+
module Railties
|
3
|
+
module ControllerRuntime
|
4
|
+
extend ActiveSupport::Concern
|
5
|
+
|
6
|
+
def execute_dato_query(query, preview: false)
|
7
|
+
client = Dato::Client.new(preview: preview)
|
8
|
+
return client.execute!(query) if preview
|
9
|
+
|
10
|
+
key = "#{Digest::MD5.hexdigest(query.to_gql)}-query-#{preview}"
|
11
|
+
Dato::Cache.fetch(key) do
|
12
|
+
client.execute!(query)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
def execute_dato_query!(query, preview: false)
|
17
|
+
response = execute_dato_query(query, preview: preview)
|
18
|
+
raise(InvalidGraphqlQuery, response.errors.first.message) if response.errors&.any?
|
19
|
+
|
20
|
+
response
|
21
|
+
end
|
22
|
+
|
23
|
+
module ClassMethods # :nodoc:
|
24
|
+
def log_process_action(payload)
|
25
|
+
messages = super
|
26
|
+
Dato::CurrentRequest.dato_runtime ||= 0
|
27
|
+
messages << ("Dato: %.1fms" % Dato::CurrentRequest.dato_runtime)
|
28
|
+
messages
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
data/lib/dato/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: dato-rails
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.10.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Alessandro Rodi
|
8
|
-
autorequire:
|
9
8
|
bindir: bin
|
10
9
|
cert_chain: []
|
11
|
-
date:
|
10
|
+
date: 2025-02-27 00:00:00.000000000 Z
|
12
11
|
dependencies:
|
13
12
|
- !ruby/object:Gem::Dependency
|
14
13
|
name: rspec-rails
|
@@ -114,14 +113,14 @@ dependencies:
|
|
114
113
|
requirements:
|
115
114
|
- - ">="
|
116
115
|
- !ruby/object:Gem::Version
|
117
|
-
version: '
|
116
|
+
version: '6'
|
118
117
|
type: :runtime
|
119
118
|
prerelease: false
|
120
119
|
version_requirements: !ruby/object:Gem::Requirement
|
121
120
|
requirements:
|
122
121
|
- - ">="
|
123
122
|
- !ruby/object:Gem::Version
|
124
|
-
version: '
|
123
|
+
version: '6'
|
125
124
|
- !ruby/object:Gem::Dependency
|
126
125
|
name: turbo-rails
|
127
126
|
requirement: !ruby/object:Gem::Requirement
|
@@ -175,6 +174,7 @@ files:
|
|
175
174
|
- README.md
|
176
175
|
- Rakefile
|
177
176
|
- app/assets/config/dato_rails_manifest.js
|
177
|
+
- app/components/dato/base_component.rb
|
178
178
|
- app/components/dato/block.html.erb
|
179
179
|
- app/components/dato/block.rb
|
180
180
|
- app/components/dato/blockquote.html.erb
|
@@ -184,12 +184,20 @@ files:
|
|
184
184
|
- app/components/dato/dast_node.html.erb
|
185
185
|
- app/components/dato/dast_node.rb
|
186
186
|
- app/components/dato/heading.rb
|
187
|
+
- app/components/dato/image_block_record.html.erb
|
188
|
+
- app/components/dato/image_block_record.rb
|
189
|
+
- app/components/dato/inline_block.html.erb
|
190
|
+
- app/components/dato/inline_block.rb
|
191
|
+
- app/components/dato/inline_item.html.erb
|
192
|
+
- app/components/dato/inline_item.rb
|
193
|
+
- app/components/dato/item_link.html.erb
|
194
|
+
- app/components/dato/item_link.rb
|
187
195
|
- app/components/dato/link.html.erb
|
188
196
|
- app/components/dato/link.rb
|
189
197
|
- app/components/dato/list.rb
|
190
198
|
- app/components/dato/list_item.rb
|
191
|
-
- app/components/dato/
|
192
|
-
- app/components/dato/
|
199
|
+
- app/components/dato/live_stream.html.erb
|
200
|
+
- app/components/dato/live_stream.rb
|
193
201
|
- app/components/dato/node.rb
|
194
202
|
- app/components/dato/not_rendered.rb
|
195
203
|
- app/components/dato/paragraph.rb
|
@@ -204,18 +212,23 @@ files:
|
|
204
212
|
- app/components/dato/unknown_block.rb
|
205
213
|
- app/components/dato/unknown_node.html.erb
|
206
214
|
- app/components/dato/unknown_node.rb
|
215
|
+
- app/components/dato/wrapper.html.erb
|
216
|
+
- app/components/dato/wrapper.rb
|
207
217
|
- app/controllers/dato/live_controller.rb
|
208
218
|
- app/controllers/dato/publish_controller.rb
|
209
|
-
- app/views/dato/live/
|
219
|
+
- app/views/dato/live/create.turbo_stream.erb
|
210
220
|
- config/routes.rb
|
211
221
|
- lib/dato.rb
|
212
222
|
- lib/dato/cache.rb
|
213
223
|
- lib/dato/client.rb
|
214
224
|
- lib/dato/config.rb
|
225
|
+
- lib/dato/current_request.rb
|
215
226
|
- lib/dato/engine.rb
|
227
|
+
- lib/dato/fragments/meta_tags.rb
|
216
228
|
- lib/dato/fragments/responsive_image.rb
|
217
229
|
- lib/dato/gql.rb
|
218
230
|
- lib/dato/items.rb
|
231
|
+
- lib/dato/railties/controller_runtime.rb
|
219
232
|
- lib/dato/uploads.rb
|
220
233
|
- lib/dato/version.rb
|
221
234
|
- lib/tasks/dato/rails_tasks.rake
|
@@ -225,7 +238,6 @@ metadata:
|
|
225
238
|
homepage_uri: https://github.com/renuo/dato-rails
|
226
239
|
source_code_uri: https://github.com/renuo/dato-rails
|
227
240
|
changelog_uri: https://github.com/renuo/dato-rails/blob/main/CHANGELOG.md
|
228
|
-
post_install_message:
|
229
241
|
rdoc_options: []
|
230
242
|
require_paths:
|
231
243
|
- lib
|
@@ -240,8 +252,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
240
252
|
- !ruby/object:Gem::Version
|
241
253
|
version: '0'
|
242
254
|
requirements: []
|
243
|
-
rubygems_version: 3.
|
244
|
-
signing_key:
|
255
|
+
rubygems_version: 3.6.2
|
245
256
|
specification_version: 4
|
246
257
|
summary: Use Dato CMS in your Rails application.
|
247
258
|
test_files: []
|
@@ -1,22 +0,0 @@
|
|
1
|
-
<% if live %>
|
2
|
-
<script type="text/javascript">
|
3
|
-
const eventSourceUrl = '<%=data.url %>';
|
4
|
-
const componentKlass = '<%=component_klass%>';
|
5
|
-
const frameId = '<%=frame_id%>';
|
6
|
-
const eventSource = new EventSource(eventSourceUrl);
|
7
|
-
eventSource.addEventListener("update", (event) => {
|
8
|
-
const params = new URLSearchParams({
|
9
|
-
component: componentKlass,
|
10
|
-
data: event.data,
|
11
|
-
frame_id: frameId
|
12
|
-
});
|
13
|
-
document.getElementById(frameId).src = `/dato/live?${params.toString()}`;
|
14
|
-
});
|
15
|
-
</script>
|
16
|
-
|
17
|
-
<%= turbo_frame_tag frame_id %>
|
18
|
-
<% else %>
|
19
|
-
<%= Dato::Cache.fetch(cache_key) do %>
|
20
|
-
<% render(component_klass.new(data)) %>
|
21
|
-
<% end %>
|
22
|
-
<% end %>
|
data/app/components/dato/live.rb
DELETED
@@ -1,40 +0,0 @@
|
|
1
|
-
# This component can bring to life your dato components allowing peviews and live updates.
|
2
|
-
# Given that you have a component MyComponent that renders your page, you can would render your page with:
|
3
|
-
# render(MyComponent.new(@data_result_from_dato_query))
|
4
|
-
# you can now use this wrapper component to do:
|
5
|
-
# render(Dato::Live.new(MyComponent, query, preview: true, live: true)
|
6
|
-
module Dato
|
7
|
-
class Live < ViewComponent::Base
|
8
|
-
delegate :turbo_frame_tag, to: :helpers
|
9
|
-
|
10
|
-
attr_reader :component_klass, :query, :preview, :live
|
11
|
-
|
12
|
-
def initialize(component_klass, query, preview: false, live: false)
|
13
|
-
super()
|
14
|
-
@component_klass = component_klass
|
15
|
-
@query = query
|
16
|
-
@preview = preview
|
17
|
-
@live = live
|
18
|
-
end
|
19
|
-
|
20
|
-
def cache_key
|
21
|
-
@cache_key ||= Digest::MD5.hexdigest(query.to_gql)
|
22
|
-
end
|
23
|
-
|
24
|
-
def data
|
25
|
-
@data ||= dato_fetch(query, preview: preview, live: live)
|
26
|
-
end
|
27
|
-
|
28
|
-
def frame_id
|
29
|
-
@frame_id ||= SecureRandom.hex(10)
|
30
|
-
end
|
31
|
-
|
32
|
-
private
|
33
|
-
|
34
|
-
def dato_fetch(query, preview: false, live: false)
|
35
|
-
client = Dato::Client.new(preview: preview, live: live)
|
36
|
-
response = live ? client.live!(query) : client.execute!(query)
|
37
|
-
response.data
|
38
|
-
end
|
39
|
-
end
|
40
|
-
end
|