Skip to content

Commit 04fdfc1

Browse files
authored
feat: Improvements to the restart link user feedback (#511)
1 parent d4435e3 commit 04fdfc1

File tree

9 files changed

+97
-10
lines changed

9 files changed

+97
-10
lines changed

application/app/services/nav/nav_defaults.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,7 @@ def self.navigation_items
9292
{
9393
id: 'nav-restart',
9494
label: I18n.t('layouts.nav.navigation.link_restart_text'),
95-
url: "/nginx/stop?redir=#{routes.root_path}",
95+
url: routes.widgets_path('restart'),
9696
icon: 'bs://bi-bootstrap-reboot',
9797
position: 3
9898
},

application/app/views/widgets/_reset.html.erb

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,6 @@
88
<meta name="viewport" content="width=device-width, initial-scale=1">
99
<%= stylesheet_link_tag "application" %>
1010
<%= javascript_include_tag "application", defer: true %>
11-
12-
<!-- Meta refresh fallback -->
13-
<meta http-equiv="refresh" content="3;url=<%= root_path %>">
1411
</head>
1512
<body class="bg-light d-flex justify-content-center align-items-center vh-100">
1613
<div class="container">
@@ -25,9 +22,11 @@
2522
</div>
2623
<!-- Success redirect -->
2724
<script>
25+
<!-- FIRE AND FORGET -->
26+
fetch("<%= restart_url %>").catch(() => { })
2827
setTimeout(function() {
29-
window.location.href = "<%= restart_url %>";
30-
}, 3000);
28+
window.location.href = "<%= root_path %>";
29+
}, <%= ::Configuration.restart_delay %>);
3130
</script>
3231
<% else %>
3332
<div class="alert alert-danger border-2 rounded-3 shadow-sm text-center" role="alert">
@@ -39,7 +38,7 @@
3938
<script>
4039
setTimeout(function() {
4140
window.location.href = "<%= root_path %>";
42-
}, 3000);
41+
}, <%= ::Configuration.restart_delay %>);
4342
</script>
4443
<% end %>
4544
</div>
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
<!DOCTYPE html>
2+
<html>
3+
<head>
4+
<title><%= t('.page_title') %></title>
5+
<meta name="viewport" content="width=device-width, initial-scale=1">
6+
<%= stylesheet_link_tag "application" %>
7+
<%= javascript_include_tag "application", defer: true %>
8+
</head>
9+
<body class="bg-light d-flex justify-content-center align-items-center vh-100">
10+
<div class="container">
11+
<div class="row justify-content-center">
12+
<div class="col-md-8 col-lg-6">
13+
<div class="alert alert-success border-2 rounded-3 shadow-sm text-center" role="alert">
14+
<i class="bi bi-arrow-repeat fs-3 text-success mb-2"></i>
15+
<h4 class="alert-heading"><%= t('.content_title') %></h4>
16+
<%= t('.content_html', url: root_path) %>
17+
</div>
18+
<script>
19+
// Fire and forget restart trigger
20+
fetch("<%= restart_url %>").catch(() => { })
21+
setTimeout(function() {
22+
window.location.href = "<%= root_path %>";
23+
}, <%= ::Configuration.restart_delay %>);
24+
</script>
25+
</div>
26+
</div>
27+
</div>
28+
</body>
29+
</html>

application/config/configuration_singleton.rb

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ def property_configs
2121
::ConfigurationProperty.integer(:download_files_retention_period, default: 24 * 60 * 60),
2222
::ConfigurationProperty.integer(:upload_files_retention_period, default: 24 * 60 * 60),
2323
::ConfigurationProperty.integer(:ui_feedback_delay, default: 1500),
24+
::ConfigurationProperty.integer(:restart_delay, default: 3000),
2425
::ConfigurationProperty.integer(:detached_controller_interval, default: 10),
2526
::ConfigurationProperty.integer(:detached_process_status_interval, default: 10 * 1000), # 10s in MILLISECONDS
2627
::ConfigurationProperty.integer(:max_download_file_size, default: 10 * 1024 * 1024 * 1024), # 10 GIGABYTE

application/config/locales/views/en.yml

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -324,12 +324,22 @@ en:
324324
tab_project_label: "This Project Downloads"
325325
tab_global_label: "All Projects"
326326
empty_recent_text: "No recently used datasets found."
327+
restart:
328+
page_title: "Application Restarting"
329+
content_title: "Restart in Progress"
330+
content_html: >
331+
<p>Your personal <em>OnDemand Loop</em> instance is restarting.</p>
332+
<p>You will be redirected to the application <strong>shortly</strong>.</p>
333+
<hr>
334+
<p class="mb-0">
335+
If the page does not refresh automatically, <a href="%{url}">click here to continue</a>.
336+
</p>
327337
reset:
328338
success_page_title: "Reset Completed"
329339
success_content_title: "Reset Completed"
330340
success_content_html: >
331341
<p>Your personal <em>OnDemand Loop</em> instance has been successfully reset.</p>
332-
<p>The application will automatically restart in <strong>3 seconds</strong>.</p>
342+
<p>The application will automatically restart <strong>shortly</strong>.</p>
333343
<hr>
334344
<p class="mb-0">
335345
If the page does not refresh, <a href="%{url}">click here to continue</a>.

application/test/services/nav/nav_defaults_test.rb

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -157,7 +157,6 @@ class Nav::NavDefaultsTest < ActiveSupport::TestCase
157157
assert_equal 'bs://bi-bootstrap-reboot', restart_item.icon
158158
assert_equal 3, restart_item.position
159159
assert restart_item.link?
160-
assert_includes restart_item.url, '/nginx/stop?redir='
161160

162161
separator_item = menu_items_by_id['help-reset-separator']
163162
assert_equal '---', separator_item.label

application/test/views/widgets/reset_partial_test.rb

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,9 @@ def render_with(method: :post)
1919

2020
assert_includes html, 'Reset Completed'
2121
assert_includes html, 'successfully reset'
22-
assert_includes html, 'window.location.href = "/restart"'
22+
assert_includes html, 'window.location.href = "/"'
2323
assert_includes html, 'bi-check-circle-fill'
24+
assert_includes html, 'fetch("/restart")'
2425
end
2526

2627
test 'renders error when request is GET' do
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
# frozen_string_literal: true
2+
require 'test_helper'
3+
4+
class RestartPartialTest < ActionView::TestCase
5+
6+
def render_restart_partial
7+
view.stubs(:restart_url).returns('/restart')
8+
view.stubs(:root_path).returns('/')
9+
10+
render partial: 'widgets/restart'
11+
end
12+
13+
test 'renders restart content with correct elements' do
14+
html = render_restart_partial
15+
16+
assert_includes html, 'Application Restarting'
17+
assert_includes html, 'Restart in Progress'
18+
assert_includes html, 'restarting'
19+
assert_includes html, 'bi-arrow-repeat'
20+
assert_includes html, 'alert-success'
21+
end
22+
23+
test 'includes restart fetch call and redirect script' do
24+
html = render_restart_partial
25+
26+
assert_includes html, 'fetch("/restart")'
27+
assert_includes html, 'window.location.href = "/"'
28+
end
29+
30+
test 'uses Configuration.restart_delay for timeout' do
31+
html = render_restart_partial
32+
33+
# Should include the configuration value in the setTimeout
34+
assert_match /setTimeout\(function\(\)\s*\{.*\},\s*\d+\);/m, html
35+
end
36+
end

docs/guide/content/admin/configuration.md

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@ The following properties control various aspects of OnDemand Loop's behavior. Ea
6464
- [download_files_retention_period](#download_files_retention_period)
6565
- [upload_files_retention_period](#upload_files_retention_period)
6666
- [ui_feedback_delay](#ui_feedback_delay)
67+
- [restart_delay](#restart_delay)
6768
- [detached_controller_interval](#detached_controller_interval)
6869
- [detached_process_status_interval](#detached_process_status_interval)
6970
- [max_download_file_size](#max_download_file_size)
@@ -191,6 +192,15 @@ Defines the delay in milliseconds for feedback messages in the UI, such as tempo
191192

192193
---
193194

195+
<a id="restart_delay"></a>
196+
**`restart_delay`**
197+
Sets the delay in milliseconds before redirecting users after application restart or reset operations. This gives users time to read completion messages.
198+
199+
- **Default**: `3_000`
200+
- **Environment Variable**: `OOD_LOOP_RESTART_DELAY`
201+
202+
---
203+
194204
<a id="detached_controller_interval"></a>
195205
**`detached_controller_interval`**
196206
Controls how often (in seconds) the detached background process controller checks for updates or process state changes.
@@ -385,6 +395,7 @@ locale: ":es"
385395
download_files_retention_period: 172_800
386396
upload_files_retention_period: 172_800
387397
ui_feedback_delay: 2_000
398+
restart_delay: 3_000
388399
detached_controller_interval: 5
389400
detached_process_status_interval: 2_000
390401
max_download_file_size: 15_000_000_000
@@ -413,6 +424,7 @@ OOD_LOOP_LOCALE=:es
413424
OOD_LOOP_DOWNLOAD_FILES_RETENTION_PERIOD=172_800
414425
OOD_LOOP_UPLOAD_FILES_RETENTION_PERIOD=172_800
415426
OOD_LOOP_UI_FEEDBACK_DELAY=2_000
427+
OOD_LOOP_RESTART_DELAY=3_000
416428
OOD_LOOP_DETACHED_CONTROLLER_INTERVAL=5
417429
OOD_LOOP_DETACHED_PROCESS_STATUS_INTERVAL=2_000
418430
OOD_LOOP_MAX_DOWNLOAD_FILE_SIZE=15_000_000_000

0 commit comments

Comments
 (0)