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.
Files changed (43) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +78 -54
  3. data/app/components/dato/base_component.rb +9 -0
  4. data/app/components/dato/block.html.erb +18 -11
  5. data/app/components/dato/dast_node.rb +6 -0
  6. data/app/components/dato/image_block_record.html.erb +1 -0
  7. data/app/components/dato/image_block_record.rb +2 -0
  8. data/app/components/dato/inline_block.html.erb +20 -0
  9. data/app/components/dato/inline_block.rb +7 -0
  10. data/app/components/dato/inline_item.html.erb +39 -0
  11. data/app/components/dato/inline_item.rb +4 -0
  12. data/app/components/dato/item_link.html.erb +18 -0
  13. data/app/components/dato/item_link.rb +20 -0
  14. data/app/components/dato/link.rb +1 -7
  15. data/app/components/dato/live_stream.html.erb +26 -0
  16. data/app/components/dato/live_stream.rb +35 -0
  17. data/app/components/dato/node.rb +30 -2
  18. data/app/components/dato/paragraph.rb +1 -1
  19. data/app/components/dato/responsive_image.html.erb +1 -1
  20. data/app/components/dato/responsive_image.rb +3 -2
  21. data/app/components/dato/structured_text.rb +2 -0
  22. data/app/components/dato/unknown_block.html.erb +18 -17
  23. data/app/components/dato/unknown_node.html.erb +14 -14
  24. data/app/components/dato/wrapper.html.erb +32 -0
  25. data/app/components/dato/wrapper.rb +38 -0
  26. data/app/controllers/dato/live_controller.rb +1 -1
  27. data/app/controllers/dato/publish_controller.rb +1 -1
  28. data/app/views/dato/live/create.turbo_stream.erb +7 -0
  29. data/config/routes.rb +1 -1
  30. data/lib/dato/cache.rb +4 -0
  31. data/lib/dato/client.rb +11 -1
  32. data/lib/dato/config.rb +6 -3
  33. data/lib/dato/current_request.rb +5 -0
  34. data/lib/dato/engine.rb +21 -0
  35. data/lib/dato/fragments/meta_tags.rb +5 -0
  36. data/lib/dato/gql.rb +4 -3
  37. data/lib/dato/railties/controller_runtime.rb +33 -0
  38. data/lib/dato/version.rb +1 -1
  39. data/lib/tasks/dato/rails_tasks.rake +7 -4
  40. metadata +22 -11
  41. data/app/components/dato/live.html.erb +0 -22
  42. data/app/components/dato/live.rb +0 -40
  43. 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: 7d61ca3870d999b82aed6ff238182a3a6fd4b294f87c608b1b9c4ee9425d97ad
4
- data.tar.gz: 3032c72e0226946239830f8c5aaeb1a5f0640328aa349a269c1f156d9b40f6b8
3
+ metadata.gz: 1973ec82f04620deeaf8b94c8b8fe4816c60f5c00cf0ccfba93ab38e938af5fb
4
+ data.tar.gz: 1f83767d11f764f199b4bf394da6d216a237d22a37fee001542413f5f183ab61
5
5
  SHA512:
6
- metadata.gz: 7733a018553585d7f51a8d85920932dabe04944581772d84c6e9bea5d9c8ec6107e0269c6b0832da4028533128d95c0fa91e409b17a4a1d4acf429ae9c5e1591
7
- data.tar.gz: c705f72bf8f0ed731ff656459b0ef0e5adc4c0a351a79b250f4db55eb0835f6e17df8adb5e9e9a01f6420704c78c92972f894fc06935169795462b142b3a2a70
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
- To define a custom node, you can create a new `Dato::CustomNode` view component in your application and it will be automatically used.
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 both [preview](https://www.datocms.com/docs/pro-tips/how-to-manage-a-live-and-a-preview-site) and [live updates](https://www.datocms.com/docs/real-time-updates-api) features from Dato CMS.
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::Live` component like this:
119
+ you can now wrap everything in a `Dato::Wrapper` component like this:
130
120
 
131
121
  ```ruby
132
- render(Dato::Live.new(MyComponent, my_query, preview: true, live: true))
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
- As the file upload is asynchronous, you may need to implement some kind of polling to check if the upload is finished.
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.publish_key = ENV['DATO_PUBLISH_KEY'] # default: ENV['DATO_PUBLISH_KEY']
233
- config.build_trigger_id = ENV['DATO_BUILD_TRIGGER_ID'] # default: ENV['DATO_BUILD_TRIGGER_ID']
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::Live`, will be cached.
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::Live.new(MyComponent, my_query))
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 also be skipped.
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
- ### manually
265
+ ### manual
267
266
 
268
- executing `Rails.cache.clear(namespace: Dato::Config.cache_namespace)`
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
- * Mount the `dato-rails` engine in your Rails routes file.
274
- * Set the `DATO_PUBLISH_KEY` environment variable
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
+ ![docs/build_trigger_configuration.png](docs/build_trigger_configuration.png)
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
  [![Clone DatoCMS project](https://dashboard.datocms.com/clone/button.svg)](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, and contributors are expected to
309
- adhere to the [code of conduct](https://github.com/renuo/dato-rails/blob/master/CODE_OF_CONDUCT.md).
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).
@@ -0,0 +1,9 @@
1
+ module Dato
2
+ class BaseComponent < ViewComponent::Base
3
+ attr_reader :data
4
+
5
+ def initialize(data)
6
+ @data = data
7
+ end
8
+ end
9
+ end
@@ -1,13 +1,20 @@
1
- <% block = blocks.find { |b| b.id == @node.item } %>
2
- <% if block.__typename.nil? %>
3
- In order to render a block, 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
- blocks {
8
- __typename
9
- }
10
- </code>
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 %>
@@ -13,5 +13,11 @@ module Dato
13
13
  def generated_tag
14
14
  @type
15
15
  end
16
+
17
+ private
18
+
19
+ def extract_meta(type)
20
+ @node.meta&.find { |m| m.id == type }&.value
21
+ end
16
22
  end
17
23
  end
@@ -0,0 +1 @@
1
+ <%= render Dato::ResponsiveImage.new(@node.image.responsiveImage) %>
@@ -0,0 +1,2 @@
1
+ class Dato::ImageBlockRecord < Dato::Node
2
+ end
@@ -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,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ class Dato::InlineBlock < Dato::DastNode
4
+ def initialize(node, root)
5
+ super(node, "inlineBlock", root)
6
+ end
7
+ 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
+ &nbsp;'<%= 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,4 @@
1
+ # frozen_string_literal: true
2
+
3
+ class Dato::InlineItem < Dato::Node
4
+ 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
@@ -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
@@ -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 = (overrides[block.__typename] || Dato::Config.overrides[block.__typename])
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 = (overrides[node.type] || Dato::Config.overrides[node.type])
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
@@ -6,6 +6,6 @@ class Dato::Paragraph < Dato::DastNode
6
6
  end
7
7
 
8
8
  def generated_tag
9
- "p"
9
+ "div"
10
10
  end
11
11
  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
- <div style="border: 3px dotted limegreen; display: inline-block; padding: 5px;">
2
- <b>
3
- This is an unknown block. Here is the content:<br>
4
- <pre><%= JSON.pretty_generate(@node) %></pre>
5
- In order to render it, you need to define a ViewComponent named <code><%=class_by_type(@node.__typename) %></code>.<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::DastNode<br>
9
- ...<br>
10
- end<br>
11
- </code><br>
12
- If you don't want to render this block you can:
13
- * not return it in your GraphQL query
14
- * the component when rendering the root <code>Dato::StructuredText</code> node.<br>
15
- <code>Dato::StructuredText.new(content, overrides: { '<%=@node.__typename %>': Dato::NotRendered })</code>
16
- </b>
17
- </div>
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
- <div style="border: 3px dotted limegreen; display: inline-block; padding: 5px;">
2
- <b>
3
- This is an unknown node of type <code><%=@type %></code>.<br>
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::DastNode<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 <code>Dato::StructuredText</code> node.<br>
12
- <code>Dato::StructuredText.new(content, overrides: { link: Dato::NotRendered })</code>
13
- </b>
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
- </div>
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
@@ -1,6 +1,6 @@
1
1
  module Dato
2
2
  class LiveController < ActionController::Base
3
- def show
3
+ def create
4
4
  @data = Hashie::Mash.new(JSON.parse(params[:data], symbolize_names: true).dig(:response, :data))
5
5
  end
6
6
  end
@@ -7,7 +7,7 @@ module Dato
7
7
  before_action :check, only: :create
8
8
 
9
9
  def create
10
- Rails.cache.clear(namespace: Dato::Config.cache_namespace)
10
+ Dato::Cache.clear!
11
11
 
12
12
  notify_success
13
13
 
@@ -0,0 +1,7 @@
1
+ <turbo-stream target="<%= params[:frame_id] %>" action="replace" method="morph">
2
+ <template>
3
+ <div id=<%= params[:frame_id] %>>
4
+ <%= render params[:component].constantize.new(@data) %>
5
+ </div>
6
+ </template>
7
+ </turbo-stream>
data/config/routes.rb CHANGED
@@ -1,4 +1,4 @@
1
1
  Dato::Engine.routes.draw do
2
- get "live", to: "live#show"
2
+ post "live", to: "live#create"
3
3
  post "publish", to: "publish#create"
4
4
  end
data/lib/dato/cache.rb CHANGED
@@ -21,5 +21,9 @@ module Dato
21
21
  def self.namespace
22
22
  Dato::Config.cache_namespace
23
23
  end
24
+
25
+ def self.clear!
26
+ Rails.cache.clear(namespace: namespace)
27
+ end
24
28
  end
25
29
  end
data/lib/dato/client.rb CHANGED
@@ -1,6 +1,6 @@
1
1
  module Dato
2
2
  class Client
3
- delegate :live!, :execute!, :execute, to: :@gql
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["DATO_API_TOKEN"] }
10
- config_accessor(:publish_key) { ENV["DATO_PUBLISH_KEY"] }
11
- config_accessor(:build_trigger_id) { ENV["DATO_BUILD_TRIGGER_ID"] }
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
@@ -0,0 +1,5 @@
1
+ module Dato
2
+ class CurrentRequest < ActiveSupport::CurrentAttributes
3
+ attribute :dato_runtime
4
+ end
5
+ 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
@@ -0,0 +1,5 @@
1
+ Dato::Fragments::MetaTags = GQLi::DSL.fragment("metaTagsFragment", "Tag") {
2
+ attributes
3
+ content
4
+ tag
5
+ }
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
@@ -1,3 +1,3 @@
1
1
  module Dato
2
- VERSION = "0.7.5"
2
+ VERSION = "0.10.0"
3
3
  end
@@ -1,4 +1,7 @@
1
- # desc "Explaining what the task does"
2
- # task :dato_rails do
3
- # # Task goes here
4
- # end
1
+ namespace :dato do
2
+ namespace :cache do
3
+ task clear: :environment do
4
+ Dato::Cache.clear!
5
+ end
6
+ end
7
+ end
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.7.5
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: 2023-08-23 00:00:00.000000000 Z
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: '4'
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: '4'
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/live.html.erb
192
- - app/components/dato/live.rb
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/show.html.erb
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.3.26
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 %>
@@ -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
@@ -1,3 +0,0 @@
1
- <%= turbo_frame_tag params[:frame_id] do %>
2
- <%= render params[:component].constantize.new(@data) %>
3
- <% end %>