Link the source code on GitHub from the footer
All checks were successful
Build and Deploy to Production / test (push) Successful in 19s
Build and Deploy to Production / build (push) Successful in 49s
Build and Deploy to Production / deploy (push) Successful in 35s

The site now lives in a public repo; point readers at it in all three
languages. Both pages had the same footer, so it becomes one partial
(absorbing the credits partial).

Assisted-by: Claude:opus-5
This commit is contained in:
Sergei Poljanski 2026-10-12 04:02:07 +04:00
commit 9336a8a7d2
Signed by: asxpi
GPG key ID: 4F8851660FA4121B
7 changed files with 21 additions and 12 deletions

1
app.rb
View file

@ -25,6 +25,7 @@ end
# Content is managed from asxp.io/admin/bingo (asxpio repo), which shares the # Content is managed from asxp.io/admin/bingo (asxpio repo), which shares the
# database and photo bucket. # database and photo bucket.
class BingoWeb < Sinatra::Base class BingoWeb < Sinatra::Base
SOURCE_URL = 'https://github.com/asxpi/datacenterbingo'.freeze
HOSTS = [ENV['BINGO_HOST'], ENV['BINGO_ALT_HOST']].compact.reject(&:empty?).freeze HOSTS = [ENV['BINGO_HOST'], ENV['BINGO_ALT_HOST']].compact.reject(&:empty?).freeze
configure do configure do

View file

@ -53,6 +53,7 @@ module Bingo
close: 'Закрыть', no_incidents: 'Инцидентов не зафиксировано.', close: 'Закрыть', no_incidents: 'Инцидентов не зафиксировано.',
credits_ai: 'Информация собрана и проверена с помощью Claude (Anthropic).', credits_ai: 'Информация собрана и проверена с помощью Claude (Anthropic).',
credits_hym: 'Спасибо %{link} (данные Cat Eyes OSINT) за часть списка: каждая запись перепроверена по сайтам операторов и прессе.', credits_hym: 'Спасибо %{link} (данные Cat Eyes OSINT) за часть списка: каждая запись перепроверена по сайтам операторов и прессе.',
source_code: 'Исходный код на GitHub',
footer: 'Данные из открытых источников (2025–2026). Клетка зачёркивается только по публичному источнику.', footer: 'Данные из открытых источников (2025–2026). Клетка зачёркивается только по публичному источнику.',
kinds: { 'strike' => 'Атака БПЛА', 'fire' => 'Пожар', 'outage' => 'Отключение', 'flood' => 'Затопление', 'cooling' => 'Перегрев', 'other' => 'Инцидент' }, kinds: { 'strike' => 'Атака БПЛА', 'fire' => 'Пожар', 'outage' => 'Отключение', 'flood' => 'Затопление', 'cooling' => 'Перегрев', 'other' => 'Инцидент' },
letters: %w[Б И Н Г О], letters: %w[Б И Н Г О],
@ -83,6 +84,7 @@ module Bingo
close: 'Close', no_incidents: 'No incidents recorded.', close: 'Close', no_incidents: 'No incidents recorded.',
credits_ai: 'Information collected and verified with the help of Claude (Anthropic).', credits_ai: 'Information collected and verified with the help of Claude (Anthropic).',
credits_hym: 'Thanks to %{link} (data by Cat Eyes OSINT) for part of the list; every entry was re-verified against operator sites and the press.', credits_hym: 'Thanks to %{link} (data by Cat Eyes OSINT) for part of the list; every entry was re-verified against operator sites and the press.',
source_code: 'Source code on GitHub',
footer: 'Open-source data (2025–2026). A cell is crossed out only with a public source.', footer: 'Open-source data (2025–2026). A cell is crossed out only with a public source.',
kinds: { 'strike' => 'Drone strike', 'fire' => 'Fire', 'outage' => 'Outage', 'flood' => 'Flood', 'cooling' => 'Overheating', 'other' => 'Incident' }, kinds: { 'strike' => 'Drone strike', 'fire' => 'Fire', 'outage' => 'Outage', 'flood' => 'Flood', 'cooling' => 'Overheating', 'other' => 'Incident' },
letters: %w[B I N G O], letters: %w[B I N G O],
@ -113,6 +115,7 @@ module Bingo
close: 'Закрити', no_incidents: 'Інцидентів не зафіксовано.', close: 'Закрити', no_incidents: 'Інцидентів не зафіксовано.',
credits_ai: 'Інформацію зібрано й перевірено за допомогою Claude (Anthropic).', credits_ai: 'Інформацію зібрано й перевірено за допомогою Claude (Anthropic).',
credits_hym: 'Дякуємо %{link} (дані Cat Eyes OSINT) за частину списку: кожен запис перевірено за сайтами операторів і пресою.', credits_hym: 'Дякуємо %{link} (дані Cat Eyes OSINT) за частину списку: кожен запис перевірено за сайтами операторів і пресою.',
source_code: 'Вихідний код на GitHub',
footer: 'Дані з відкритих джерел (2025–2026). Клітинка закреслюється лише за публічним джерелом.', footer: 'Дані з відкритих джерел (2025–2026). Клітинка закреслюється лише за публічним джерелом.',
kinds: { 'strike' => 'Атака БПЛА', 'fire' => 'Пожежа', 'outage' => 'Відключення', 'flood' => 'Затоплення', 'cooling' => 'Перегрів', 'other' => 'Інцидент' }, kinds: { 'strike' => 'Атака БПЛА', 'fire' => 'Пожежа', 'outage' => 'Відключення', 'flood' => 'Затоплення', 'cooling' => 'Перегрів', 'other' => 'Інцидент' },
letters: %w[Б І Н Г О], letters: %w[Б І Н Г О],

View file

@ -333,6 +333,15 @@ class BingoTest < Minitest::Test
refute_includes last_response.body, 'Second.' # no fallback across languages refute_includes last_response.body, 'Second.' # no fallback across languages
end end
def test_footer_links_to_source
{ 'ru' => 'Исходный код на GitHub', 'en' => 'Source code on GitHub', 'uk' => 'Вихідний код на GitHub' }.each do |l, text|
get "/#{l}"
assert_includes last_response.body, %(<a href="https://github.com/asxpi/datacenterbingo" rel="noopener">#{text}</a>)
end
get '/en/dc/dc-1'
assert_includes last_response.body, 'github.com/asxpi/datacenterbingo'
end
def test_static_files_not_served def test_static_files_not_served
get '/style.css' get '/style.css'
assert_equal 404, last_response.status assert_equal 404, last_response.status

View file

@ -1,2 +0,0 @@
<p class="credits"><%= t(:credits_ai) %>
<%== format(Rack::Utils.escape_html(t(:credits_hym)), link: '<a href="https://hackyourmom.com/en/karta-data-czentriv-na-rasii/" target="_blank" rel="noopener">hackyourmom</a>') %></p>

6
views/_footer.erb Normal file
View file

@ -0,0 +1,6 @@
<footer>
<p><%= t(:footer) %></p>
<p class="credits"><%= t(:credits_ai) %>
<%== format(Rack::Utils.escape_html(t(:credits_hym)), link: '<a href="https://hackyourmom.com/en/karta-data-czentriv-na-rasii/" target="_blank" rel="noopener">hackyourmom</a>') %></p>
<p>© <%= Date.today.year %> <a href="https://asxp.io">asxp.io</a> · <a href="<%= BingoWeb::SOURCE_URL %>" rel="noopener"><%= t(:source_code) %></a></p>
</footer>

View file

@ -27,9 +27,5 @@
</nav> </nav>
<p><a href="/<%= @locale %>"><%= t(:back) %></a></p> <p><a href="/<%= @locale %>"><%= t(:back) %></a></p>
<footer> <%== erb :_footer, layout: false %>
<p><%= t(:footer) %></p>
<%== erb :_credits, layout: false %>
<p>© <%= Date.today.year %> <a href="https://asxp.io">asxp.io</a></p>
</footer>
</main> </main>

View file

@ -84,11 +84,7 @@
</ul> </ul>
</section> </section>
<footer> <%== erb :_footer, layout: false %>
<p><%= t(:footer) %></p>
<%== erb :_credits, layout: false %>
<p>© <%= Date.today.year %> <a href="https://asxp.io">asxp.io</a></p>
</footer>
</main> </main>
<% b.cells.each do |dc| %> <% b.cells.each do |dc| %>