<h2 dir="auto">Context</h2>
<p dir="auto">This PR is part of a conversation with <a class="user-mention notranslate" data-hovercard-type="user" data-hovercard-url="/users/gravitystorm/hovercard" data-octo-click="hovercard-link-click" data-octo-dimensions="link_type:self" href="https://github.com/gravitystorm">@gravitystorm</a> and <a class="user-mention notranslate" data-hovercard-type="user" data-hovercard-url="/users/tordans/hovercard" data-octo-click="hovercard-link-click" data-octo-dimensions="link_type:self" href="https://github.com/tordans">@tordans</a> on the recent OSM Hackweekend in Karlsruhe and following conversations. The goal is to show how to integrate Rails Trubo to the project and what a migration path would look like.</p>
<h2 dir="auto">Why are the changes necessary?</h2>
<p dir="auto">Navigating the OSM website should be smooth. <a href="https://github.com/rails/rails/tree/main/actionview/app/assets/javascripts">Rails UJS</a> and custom JavaScript enables users to manage their Messages in a SPA-like fashion without adding too much complexity to the codebase.</p>
<p dir="auto"><a href="https://turbo.hotwired.dev" rel="nofollow">Turbo</a> is the successor of Rails UJS. It provides SPA-like behaviour to Rails applications similar to Rails UJS but works a bit differently and allows to write even less JavaScript.</p>
<p dir="auto">With the latest changes to <a href="https://turbo.hotwired.dev" rel="nofollow">Turbo</a> (see <a href="https://github.com/hotwired/turbo/releases/tag/v8.0.0">v8.0.0</a> page refreshes with morphing) it has gotten even easier to manage front-end state without custom JavaScript.</p>
<h2 dir="auto">What has changed?</h2>
<ul dir="auto">
<li>Adds the <a href="https://www.npmjs.com/package/@hotwired/turbo" rel="nofollow"><code class="notranslate">@hotwired/turbo</code></a> npm-package which provides client-side capabilities for <a href="https://turbo.hotwired.dev/handbook/drive" rel="nofollow"><code class="notranslate">Turbo Drive</code></a> (which is used in this PR) and <a href="https://turbo.hotwired.dev/handbook/frames" rel="nofollow"><code class="notranslate">Turbo Frames</code></a> and <a href="https://turbo.hotwired.dev/handbook/streams" rel="nofollow"><code class="notranslate">Turbo Streams</code></a> which are not used in this PR</li>
<li>Adds the <a href="https://github.com/hotwired/turbo-rails"><code class="notranslate">turbo-rails</code></a>-gem which provides utility code to integrate Turbo Drive, Frames and Streams – the PR is only using the <code class="notranslate">turbo_refresh_method_tag</code>- and <code class="notranslate">turbo_refresh_scroll_tag</code>- helper methods. Most of the gem-code is not used, so theoretically it could be dropped but it is installed by default for all Rails 7+ applications (unless skipped)</li>
</ul>
<details>
<summary>
The UI/UX is mostly identical with 2 exceptions:
<ul dir="auto">
<li>Flash Messages are rendered.</li>
<li>The Messages front end state not just partially but fully updated.</li>
</ul>
</summary>
<h3 dir="auto">UI / UX Changes</h3>
<p dir="auto"><strong>TBD</strong>: The flash messages are now displayed (they were not displayed using UJS + custom JS). While the flash message is a bit disruptive, I am not sure if I want to suppress/hide them or keep them.</p>
<p dir="auto">The main difference between the Rails UJS and the Turbo version is that not just dedicated sections of the front-end state are managed, but the full page is managed.</p>
<p dir="auto">See e.g. what happens when all messages are deleted.</p>
<p dir="auto"><strong>Before</strong></p>
<p dir="auto"><a href="https://github.com/grekko/openstreetmap-website/assets/28648/7e88b66c-ac79-4f25-8f37-b1f6d2be14a9">delete-last-before.gif (view on web)</a></p>
<p dir="auto"><strong>After</strong></p>
<p dir="auto"><a href="https://github.com/grekko/openstreetmap-website/assets/28648/da5704ea-daa2-44dc-a28c-f67b3634746e">delete-last-after.gif (view on web)</a></p>
<h3 dir="auto">Demo</h3>
<p dir="auto">Besides the now-appearing flash messages the UX for managing messages should be identical.</p>
<ul dir="auto">
<li>The Message Counters are all updated</li>
<li>Deleted messages are faded out</li>
<li>The scroll position is preserved</li>
</ul>
<p dir="auto"><a href="https://github.com/grekko/openstreetmap-website/assets/28648/d63fe236-984f-4b69-ae43-4922ffc54ac7">2024-03-04.17.48.31.gif (view on web)</a></p>
</details>
<h2 dir="auto">Dev Notes</h2>
<ul dir="auto">
<li>Turbo and Rails UJS can co-exist
<ul dir="auto">
<li>Turbo (Drive) is therefore setup so that its behaviour must be enabled via opt-in data-attributes</li>
</ul>
</li>
<li>Turbo relies on the concept of <code class="notranslate">HTML over the Wire</code> (see <a href="https://hotwired.dev" rel="nofollow">https://hotwired.dev</a>). If there is still the need to send/receive JSON payloads, Rails UJS might be the right tool</li>
</ul>
<h2 dir="auto">Next steps</h2>
<p dir="auto">I'd like to get feedback on the state of the PR and would like to know if other developers are happy with the outcome or if they foresee any issues with gradually replacing Rails UJS with Turbo.</p>
<p dir="auto">Gradually replacing Rails UJS and integrating Turbo into other places of the OSM website application could be a good next EWG project.</p>
<hr>
<h4>You can view, comment on, or merge this pull request online at:</h4>
<p> <a href='https://github.com/openstreetmap/openstreetmap-website/pull/4562'>https://github.com/openstreetmap/openstreetmap-website/pull/4562</a></p>
<h4>Commit Summary</h4>
<ul>
<li><a href="https://github.com/openstreetmap/openstreetmap-website/pull/4562/commits/3a3f0c274a24eacac8b214ae426eaa60067adbcd" class="commit-link">3a3f0c2</a> Gemfile: Add turbo-rails</li>
<li><a href="https://github.com/openstreetmap/openstreetmap-website/pull/4562/commits/2f364ce51a59aa94c7b10f9ab6b53b088a8b35d1" class="commit-link">2f364ce</a> package.json: Add @hotwired/turbo-rails</li>
<li><a href="https://github.com/openstreetmap/openstreetmap-website/pull/4562/commits/e10550545d07ffd3a3a4236297beaf08c8778b2e" class="commit-link">e105505</a> Enable Turbo Drive with morphing for Messages#{destroy,mark}</li>
<li><a href="https://github.com/openstreetmap/openstreetmap-website/pull/4562/commits/80b5a3033d49af155f1dab5935e794609f381bfc" class="commit-link">80b5a30</a> application.js: Call updateHeader when turbo:render completed</li>
</ul>
<h4 style="display: inline-block">File Changes </h4> <p style="display: inline-block">(<a href="https://github.com/openstreetmap/openstreetmap-website/pull/4562/files">15 files</a>)</p>
<ul>
<li>
<strong>M</strong>
<a href="https://github.com/openstreetmap/openstreetmap-website/pull/4562/files#diff-d09ea66f8227784ff4393d88a19836f321c915ae10031d16c93d67e6283ab55f">Gemfile</a>
(1)
</li>
<li>
<strong>M</strong>
<a href="https://github.com/openstreetmap/openstreetmap-website/pull/4562/files#diff-89cade48462044ee1b672dc5f4c3ec250fbd29effcd8932096a23c1283c6731f">Gemfile.lock</a>
(5)
</li>
<li>
<strong>M</strong>
<a href="https://github.com/openstreetmap/openstreetmap-website/pull/4562/files#diff-0e145ba000e96b1a45d230275e350e4e8514efb4db7dbcfa228fe1003896c9b4">app/assets/javascripts/application.js</a>
(6)
</li>
<li>
<strong>M</strong>
<a href="https://github.com/openstreetmap/openstreetmap-website/pull/4562/files#diff-305c268f66d28c4cd669b9a69449100d2de05f2b61da1e58914295c1eea45e16">app/assets/javascripts/messages.js</a>
(43)
</li>
<li>
<strong>M</strong>
<a href="https://github.com/openstreetmap/openstreetmap-website/pull/4562/files#diff-9b58332ea76756301b1aafeacfb0659d1244ba014947602b0e0bf2d0f2921d26">app/controllers/messages_controller.rb</a>
(8)
</li>
<li>
<strong>M</strong>
<a href="https://github.com/openstreetmap/openstreetmap-website/pull/4562/files#diff-b3aa1d88647a55c139237705e584a32ca1962ba65e0e1b55b714fcc2b8e9c2fb">app/views/layouts/_meta.html.erb</a>
(2)
</li>
<li>
<strong>M</strong>
<a href="https://github.com/openstreetmap/openstreetmap-website/pull/4562/files#diff-dce312eee7c8db36eed14c39d7ef021c07c1772852becf919c71f74c8679866d">app/views/messages/_message_summary.html.erb</a>
(10)
</li>
<li>
<strong>M</strong>
<a href="https://github.com/openstreetmap/openstreetmap-website/pull/4562/files#diff-95d16dd14e4df274792fca31af9004e9017e2407a9181425f236c24ee0b0d309">app/views/messages/_messages_table.html.erb</a>
(2)
</li>
<li>
<strong>M</strong>
<a href="https://github.com/openstreetmap/openstreetmap-website/pull/4562/files#diff-9a422124885f02dd7f067069b46b678fac0a3bb7e41559adc1e49852dfb9936c">app/views/messages/_sent_message_summary.html.erb</a>
(2)
</li>
<li>
<strong>D</strong>
<a href="https://github.com/openstreetmap/openstreetmap-website/pull/4562/files#diff-d6f26b1992001b19726bac259d7236ab15d82af53ecc55b9e680e606b052398a">app/views/messages/destroy.json.jbuilder</a>
(4)
</li>
<li>
<strong>D</strong>
<a href="https://github.com/openstreetmap/openstreetmap-website/pull/4562/files#diff-588d73318290a46cc088f41a01f4f3bd61f2482fac02330854aa211f402ecec9">app/views/messages/mark.json.jbuilder</a>
(4)
</li>
<li>
<strong>M</strong>
<a href="https://github.com/openstreetmap/openstreetmap-website/pull/4562/files#diff-6b68c8e53bfd9ee0c6a0cb4d346af533a3587842ee3b37a486764a9315d80886">config/eslint.json</a>
(3)
</li>
<li>
<strong>M</strong>
<a href="https://github.com/openstreetmap/openstreetmap-website/pull/4562/files#diff-7ae45ad102eab3b6d7e7896acd08c427a9b25b346470d7bc6507b6481575d519">package.json</a>
(3)
</li>
<li>
<strong>M</strong>
<a href="https://github.com/openstreetmap/openstreetmap-website/pull/4562/files#diff-ddf5d19fd2916b2a385e2be7541e2229667490427938e04c2e1fdf1d1517385c">test/controllers/messages_controller_test.rb</a>
(10)
</li>
<li>
<strong>M</strong>
<a href="https://github.com/openstreetmap/openstreetmap-website/pull/4562/files#diff-89776ee82b60e12b97037696a30b3fc063b0ace4751fa6ff1485b8d2fe797fa2">test/system/messages_test.rb</a>
(3)
</li>
</ul>
<h4>Patch Links:</h4>
<ul>
<li><a href='https://github.com/openstreetmap/openstreetmap-website/pull/4562.patch'>https://github.com/openstreetmap/openstreetmap-website/pull/4562.patch</a></li>
<li><a href='https://github.com/openstreetmap/openstreetmap-website/pull/4562.diff'>https://github.com/openstreetmap/openstreetmap-website/pull/4562.diff</a></li>
</ul>
<p style="font-size:small;-webkit-text-size-adjust:none;color:#666;">—<br />Reply to this email directly, <a href="https://github.com/openstreetmap/openstreetmap-website/pull/4562">view it on GitHub</a>, or <a href="https://github.com/notifications/unsubscribe-auth/AAK2OLIW24RDFMCK4LYISUDYW3OEDAVCNFSM6AAAAABEIVPY5KVHI2DSMVQWIX3LMV43ASLTON2WKOZSGE3TCMBSHA2DGMA">unsubscribe</a>.<br />You are receiving this because you are subscribed to this thread.<img src="https://github.com/notifications/beacon/AAK2OLPBHWLKYQ4K6QYAEXTYW3OEDA5CNFSM6AAAAABEIVPY5KWGG33NNVSW45C7OR4XAZNFJFZXG5LFVJRW63LNMVXHIX3JMTHICZ2DZY.gif" height="1" width="1" alt="" /><span style="color: transparent; font-size: 0; display: none; visibility: hidden; overflow: hidden; opacity: 0; width: 0; height: 0; max-width: 0; max-height: 0; mso-hide: all">Message ID: <span><openstreetmap/openstreetmap-website/pull/4562</span><span>@</span><span>github</span><span>.</span><span>com></span></span></p>
<script type="application/ld+json">[
{
"@context": "http://schema.org",
"@type": "EmailMessage",
"potentialAction": {
"@type": "ViewAction",
"target": "https://github.com/openstreetmap/openstreetmap-website/pull/4562",
"url": "https://github.com/openstreetmap/openstreetmap-website/pull/4562",
"name": "View Pull Request"
},
"description": "View this Pull Request on GitHub",
"publisher": {
"@type": "Organization",
"name": "GitHub",
"url": "https://github.com"
}
}
]</script>