Skip to content

Commit 8b2d496

Browse files
committed
Enable custom 404 pages for enhanced user experience
Site administrators can now select published entries as custom 404 pages, providing branded error handling that keeps users engaged instead of showing generic browser errors. This improves site cohesion and reduces bounce rates when visitors encounter broken links. REDMINE-21049
1 parent 69f34c2 commit 8b2d496

File tree

5 files changed

+130
-1
lines changed

5 files changed

+130
-1
lines changed

admins/pageflow/sites.rb

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,8 @@ module Pageflow
3030
:copyright_link_label,
3131
:privacy_link_url,
3232
:home_url,
33-
:cutoff_mode_name
33+
:cutoff_mode_name,
34+
:custom_404_entry_id
3435
] + permitted_admin_form_input_params
3536
end
3637

app/views/admin/sites/_fields.html.erb

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,12 @@
2323
<%= f.input :sitemap_enabled, hint: t('pageflow.admin.sites.sitemap_hint',
2424
site_host: @site&.persisted? ? @site.host : '<host>') %>
2525

26+
<%= f.input :custom_404_entry_id,
27+
as: :select,
28+
collection: @site&.persisted? ? @site.entries.published_without_password_protection.pluck(:title, :id) : [],
29+
include_blank: t('pageflow.admin.sites.custom_404_entry.none'),
30+
hint: t('pageflow.admin.sites.custom_404_entry.hint') %>
31+
2632
<% account_config.admin_form_inputs.find_all_for(:site).each do |form_input| %>
2733
<%= form_input.build(f) %>
2834
<% end %>
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
de:
2+
pageflow:
3+
admin:
4+
sites:
5+
custom_404_entry:
6+
none: "(Standard 404-Seite verwenden)"
7+
hint: "Wählen Sie einen Eintrag aus, der als benutzerdefinierte 404-Seite angezeigt werden soll. Nur veröffentlichte Einträge ohne Passwortschutz sind verfügbar."
8+
activerecord:
9+
attributes:
10+
pageflow/site:
11+
custom_404_entry_id: "Benutzerdefinierte 404-Seite"
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
en:
2+
pageflow:
3+
admin:
4+
sites:
5+
custom_404_entry:
6+
none: "(Use default 404 page)"
7+
hint: "Select an entry to display as the custom 404 page. Only published entries without password protection are available."
8+
activerecord:
9+
attributes:
10+
pageflow/site:
11+
custom_404_entry_id: "Custom 404 page"

spec/controllers/admin/sites_controller_spec.rb

Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -216,6 +216,15 @@ def self.name
216216

217217
expect(response.body).to have_select('Cutoff mode', options: ['(None)', 'Some Cutoff Mode'])
218218
end
219+
220+
it 'displays empty custom 404 entry select for new sites' do
221+
account = create(:account)
222+
223+
sign_in(create(:user, :admin), scope: :user)
224+
get(:new, params: {account_id: account})
225+
226+
expect(response.body).to have_select('Custom 404 page', options: ['(Use default 404 page)'])
227+
end
219228
end
220229

221230
describe '#edit' do
@@ -240,6 +249,28 @@ def self.name
240249

241250
expect(response.body).to have_selector('[name="site[custom_field]"]')
242251
end
252+
253+
it 'displays custom 404 entry select for existing sites' do
254+
site = create(:site)
255+
entry = create(:entry, :published, site: site)
256+
257+
sign_in(create(:user, :admin), scope: :user)
258+
get(:edit, params: {account_id: site.account, id: site})
259+
260+
expect(response.body).to have_select('Custom 404 page')
261+
end
262+
263+
it 'displays only published entries without password protection in custom 404 entry select' do
264+
site = create(:site)
265+
published_entry = create(:entry, :published, site: site, title: 'Published Entry')
266+
unpublished_entry = create(:entry, site: site, title: 'Unpublished Entry')
267+
password_protected_entry = create(:entry, :published_with_password, site: site, password: 'secret', title: 'Protected Entry')
268+
269+
sign_in(create(:user, :admin), scope: :user)
270+
get(:edit, params: {account_id: site.account, id: site})
271+
272+
expect(response.body).to have_select('Custom 404 page', options: ['(Use default 404 page)', 'Published Entry'])
273+
end
243274
end
244275

245276
describe '#create' do
@@ -342,6 +373,40 @@ def self.name
342373

343374
expect(account.sites.last.custom_field).to eq(nil)
344375
end
376+
377+
it 'sets custom_404_entry_id when provided' do
378+
site = create(:site)
379+
entry = create(:entry, :published, site: site)
380+
381+
sign_in(create(:user, :admin), scope: :user)
382+
patch(:update,
383+
params: {
384+
account_id: site.account,
385+
id: site,
386+
site: {
387+
custom_404_entry_id: entry.id
388+
}
389+
})
390+
391+
expect(site.reload.custom_404_entry_id).to eq(entry.id)
392+
end
393+
394+
it 'allows nil custom_404_entry_id' do
395+
account = create(:account)
396+
397+
sign_in(create(:user, :admin), scope: :user)
398+
post(:create,
399+
params: {
400+
account_id: account,
401+
site: {
402+
name: 'test site',
403+
custom_404_entry_id: ''
404+
}
405+
})
406+
407+
site = account.sites.last
408+
expect(site.custom_404_entry_id).to be_nil
409+
end
345410
end
346411

347412
describe '#update' do
@@ -438,6 +503,41 @@ def self.name
438503

439504
expect(site.reload.custom_field).to eq(nil)
440505
end
506+
507+
it 'updates custom_404_entry_id when provided' do
508+
site = create(:site)
509+
entry = create(:entry, :published, site: site)
510+
511+
sign_in(create(:user, :admin), scope: :user)
512+
patch(:update,
513+
params: {
514+
account_id: site.account,
515+
id: site,
516+
site: {
517+
custom_404_entry_id: entry.id
518+
}
519+
})
520+
521+
expect(site.reload.custom_404_entry_id).to eq(entry.id)
522+
end
523+
524+
it 'clears custom_404_entry_id when set to blank' do
525+
site = create(:site)
526+
entry = create(:entry, :published, site: site)
527+
site.update!(custom_404_entry: entry)
528+
529+
sign_in(create(:user, :admin), scope: :user)
530+
patch(:update,
531+
params: {
532+
account_id: site.account,
533+
id: site,
534+
site: {
535+
custom_404_entry_id: ''
536+
}
537+
})
538+
539+
expect(site.reload.custom_404_entry_id).to be_nil
540+
end
441541
end
442542
end
443543
end

0 commit comments

Comments
 (0)