diff options
| author | erdgeist <erdgeist@erdgeist.org> | 2026-07-08 16:24:05 +0200 |
|---|---|---|
| committer | erdgeist <erdgeist@erdgeist.org> | 2026-07-08 16:24:05 +0200 |
| commit | 43e7743ebff1b1f41bbb5ae39bcc5bed7d8982e3 (patch) | |
| tree | d27f73cd3725b57cba22cac0692a178c500fd4f2 | |
| parent | c6bf63a82007c275d13e9e9e0857434b3b7890c0 (diff) | |
Autosave posts to its own endpoint surface lock loss immediately
Previously piggybacked on the main form's action and relied on a
.js.erb response to update #flash; now posts to the dedicated
autosave route with an explicit _method=put override, and reacts to
a 423 by stopping the timer and showing a persistent banner rather
than letting the next Save discover the conflict on its own.
| -rw-r--r-- | app/views/nodes/edit.html.erb | 2 | ||||
| -rw-r--r-- | public/javascripts/admin_interface.js | 38 | ||||
| -rw-r--r-- | public/stylesheets/admin.css | 5 |
3 files changed, 41 insertions, 4 deletions
diff --git a/app/views/nodes/edit.html.erb b/app/views/nodes/edit.html.erb index 4693569..1c6cc3a 100644 --- a/app/views/nodes/edit.html.erb +++ b/app/views/nodes/edit.html.erb | |||
| @@ -5,7 +5,7 @@ | |||
| 5 | <% end %> | 5 | <% end %> |
| 6 | 6 | ||
| 7 | <div id="page_editor"> | 7 | <div id="page_editor"> |
| 8 | <%= form_for(@node) do |f| %> | 8 | <%= form_for(@node, html: { data: { autosave_url: autosave_node_path(@node), show_url: node_path(@node) } }) do |f| %> |
| 9 | <% if @node.errors.any? %> | 9 | <% if @node.errors.any? %> |
| 10 | <div class="error_messages"> | 10 | <div class="error_messages"> |
| 11 | <ul><% @node.errors.full_messages.each do |msg| %><li><%= msg %></li><% end %></ul> | 11 | <ul><% @node.errors.full_messages.each do |msg| %><li><%= msg %></li><% end %></ul> |
diff --git a/public/javascripts/admin_interface.js b/public/javascripts/admin_interface.js index 41699a1..4107ce8 100644 --- a/public/javascripts/admin_interface.js +++ b/public/javascripts/admin_interface.js | |||
| @@ -159,13 +159,45 @@ cccms = { | |||
| 159 | page.cached_abstract = elements.abstract.val(); | 159 | page.cached_abstract = elements.abstract.val(); |
| 160 | page.cached_body = elements.body.html(); | 160 | page.cached_body = elements.body.html(); |
| 161 | 161 | ||
| 162 | $("#flash").append("<img src='/images/ajax-loader.gif' alt='' />"); | 162 | var data = this.serializeArray().filter(function(field) { |
| 163 | $.post(this.attr("action"), $(this).serialize(), null, "script"); | 163 | return field.name !== "_method"; |
| 164 | }); | ||
| 165 | data.push({ name: "_method", value: "put" }); | ||
| 166 | |||
| 167 | $.ajax({ | ||
| 168 | type: "POST", | ||
| 169 | url: this.attr("data-autosave-url"), | ||
| 170 | data: data, | ||
| 171 | error: function(xhr) { | ||
| 172 | if (xhr.status === 423) { | ||
| 173 | clearInterval(cccms.autosave_timer); | ||
| 174 | cccms.report_lock_lost($("#page_editor > form").attr("data-show-url")); | ||
| 175 | } | ||
| 176 | // any other failure: quietly retried on the next tick | ||
| 177 | } | ||
| 178 | }); | ||
| 164 | 179 | ||
| 165 | } | 180 | } |
| 166 | }; | 181 | }; |
| 167 | 182 | ||
| 168 | setInterval('$("#page_editor > form").submitWithAjax()', 7000); | 183 | cccms.autosave_timer = setInterval(function() { |
| 184 | $("#page_editor > form").submitWithAjax(); | ||
| 185 | }, 7000); | ||
| 186 | }, | ||
| 187 | |||
| 188 | report_lock_lost : function(show_url) { | ||
| 189 | var $flash = $("#flash"); | ||
| 190 | if ($flash.length === 0) { | ||
| 191 | $flash = $("<div>", { id: "flash" }).insertAfter(".admin_content_spacer"); | ||
| 192 | } | ||
| 193 | |||
| 194 | var $banner = $("<span>", { "class": "warning" }).text( | ||
| 195 | "This page is now locked by someone else — your changes here can no longer be saved. Copy anything you need, then " | ||
| 196 | ); | ||
| 197 | $banner.append($("<a>", { href: show_url }).text("return to the published page")); | ||
| 198 | $banner.append("."); | ||
| 199 | |||
| 200 | $flash.html($banner); | ||
| 169 | } | 201 | } |
| 170 | } | 202 | } |
| 171 | 203 | ||
diff --git a/public/stylesheets/admin.css b/public/stylesheets/admin.css index 0c0779f..7ae374c 100644 --- a/public/stylesheets/admin.css +++ b/public/stylesheets/admin.css | |||
| @@ -200,6 +200,11 @@ span#flash_error, span.warning { | |||
| 200 | padding-bottom: 1px; | 200 | padding-bottom: 1px; |
| 201 | } | 201 | } |
| 202 | 202 | ||
| 203 | span.warning a { | ||
| 204 | color: inherit; | ||
| 205 | text-decoration: underline; | ||
| 206 | } | ||
| 207 | |||
| 203 | /* ============================================================ | 208 | /* ============================================================ |
| 204 | Pagination | 209 | Pagination |
| 205 | ============================================================ */ | 210 | ============================================================ */ |
