diff --git a/app/assets/stylesheets/application.bootstrap.scss b/app/assets/stylesheets/application.bootstrap.scss index 03835146..3ab899d2 100644 --- a/app/assets/stylesheets/application.bootstrap.scss +++ b/app/assets/stylesheets/application.bootstrap.scss @@ -20,6 +20,7 @@ $bootstrap-icons-font-dir: '/fonts'; @import 'base'; @import 'components/navbar'; +@import 'components/footer'; @import 'components/sections'; @import 'components/cards'; @import 'components/stage-badge'; diff --git a/app/assets/stylesheets/components/_footer.scss b/app/assets/stylesheets/components/_footer.scss new file mode 100644 index 00000000..4e6a34a1 --- /dev/null +++ b/app/assets/stylesheets/components/_footer.scss @@ -0,0 +1,49 @@ +footer.site-footer { + background: $ink; + color: rgba(255, 255, 255, .78); + + h2, h3 { + color: #fff; + font-size: .875rem; + font-weight: 600; + letter-spacing: .04em; + text-transform: uppercase; + } + + a { + color: rgba(255, 255, 255, .78); + text-decoration: none; + + &:hover, &:focus { + color: #fff; + text-decoration: underline; + } + } + + ul { + list-style: none; + margin: 0; + padding: 0; + + li { + margin-bottom: .375rem; + } + } + + // Existing social icons are black SVGs — invert them on the dark footer. + .social-links img { + filter: invert(1); + opacity: .75; + transition: opacity .15s ease-out; + } + + .social-links a:hover img, + .social-links a:focus img { + opacity: 1; + } + + .footer-bottom { + border-top: 1px solid rgba(255, 255, 255, .08); + color: rgba(255, 255, 255, .55); + } +} diff --git a/app/assets/stylesheets/pages/_legacy.scss b/app/assets/stylesheets/pages/_legacy.scss index e9322e29..72d60368 100644 --- a/app/assets/stylesheets/pages/_legacy.scss +++ b/app/assets/stylesheets/pages/_legacy.scss @@ -1,39 +1,21 @@ -// Rules belonging to the pre-relaunch pages. They are kept intact, and separate, -// so the cutover that removes those pages can delete this file rather than pick -// rules out of the ones above. +// Rules belonging to the pre-relaunch pages. +// +// Two of the three that were here have gone with the pages they styled: the h2 +// title treatment, whose long selector only ever matched pages inside the +// .container wrapper, and the CSS territory gate on /introduction's partner +// wall -- which never matched anything anyway, since no logo on that page +// carried the `ru` class it selected on. PagesHelper#partner_logos does that +// job now, in Ruby, with a test. +// +// What remains is used by pages that are still here. -// Section headings inside a grid column. Fifteen existing pages rely on this -- -// our-team, our-channels, the calculators, majestic-endpoints and the rest -- -// so it cannot go until they do. The new pages do not use it: their headings -// take their colour from the body, not the brand. +// Section headings inside a grid column. Still used by our-team, +// majestic-endpoints, green-life, merchandise, the calculators and the rest. +// The relaunched pages do not use it: their headings take their colour from the +// body rather than the brand. .col > h3 { color: var(--bs-blue); font-size: 1.3rem; margin-bottom: 1rem; margin-top: 1.5rem; } - -// Territory-gating for the partner wall on /introduction, done in CSS because -// that page hardcodes every logo in the markup. The integrators in the .ru -// group serve Russia and are shown only to Russian-language visitors. -// -// The replacement is PagesHelper#partner_logos, which makes the same split in -// Ruby and can therefore be tested. Until /introduction goes, this rule is what -// enforces it -- deleting it early would show the Russian integrators to -// everyone, which is precisely what the maintainers asked not to happen. -html:not([lang="ru"]) article.introduction .col.logo.ru { - display: none; -} - -// Page titles on the pre-relaunch pages: brand-coloured and 700, as they have -// always been. _base.scss styles `article > header > h2` at 600 and inherits -// the body colour, which is the new design; this selector is longer, so it wins -// wherever it applies -- and it applies exactly to pages rendered inside the -// .container wrapper, which is every page that is not full-bleed. The two rules -// therefore split cleanly along the same line as the layout's fullwidth switch, -// and this one disappears when the pages it belongs to do. -body > main > .container > article > header > h2 { - color: var(--bs-blue); - font-weight: 700; - margin: 1rem 0 1.5rem; -} diff --git a/app/controllers/pages_controller.rb b/app/controllers/pages_controller.rb index 52897dbc..bc18bf58 100644 --- a/app/controllers/pages_controller.rb +++ b/app/controllers/pages_controller.rb @@ -4,11 +4,6 @@ class PagesController < ApplicationController def show end - def about - @page_title = t('pages.about_us.title') - render 'pages/our_channels' - end - def business @page_title = t('pages.business.title') render 'pages/business' @@ -69,11 +64,6 @@ def low_latency render 'pages/low_latency' end - def introduction - @page_title = t('pages.introduction.title') - render 'pages/introduction' - end - def majestic_endpoints @page_title = t('pages.majestic_endpoints.title') render 'pages/majestic_endpoints' @@ -84,21 +74,6 @@ def merchandise render 'pages/merchandise' end - def our_channels - @page_title = t('pages.our_channels.title') - render 'pages/our_channels' - end - - def our_software - @page_title = t('pages.our_software.title') - render 'pages/our_software' - end - - def our_projects - @page_title = t('pages.our_projects.title') - render 'pages/our_projects' - end - def our_team @page_title = t('pages.our_team.title') render 'pages/our_team' @@ -114,11 +89,6 @@ def stages_of_firmware_development render 'pages/stages_of_firmware_development' end - def support_open_source - @page_title = t('pages.support_open_source.title') - render 'pages/support_open_source' - end - def utilities @page_title = t('pages.utilities.title') render 'pages/utilities' diff --git a/app/models/snapshot.rb b/app/models/snapshot.rb index 819b4f48..cf5d849f 100644 --- a/app/models/snapshot.rb +++ b/app/models/snapshot.rb @@ -140,14 +140,19 @@ def purge_file_now file.attachment&.purge end + # dig, not credentials.mac.blacklisted. Without config/master.key -- which is + # what a fresh checkout and the test environment have -- credentials.mac is + # nil, and the reader raised NoMethodError on every upload rather than simply + # having nothing to blacklist. Production has the key, so this never showed + # there; it made the API impossible to exercise anywhere else. def blacklisted_mac - return unless mac_address.in?(Rails.application.credentials.mac.blacklisted) + return unless mac_address.in?(Rails.application.credentials.dig(:mac, :blacklisted) || []) errors.add :base, 'This IP address is blacklisted.' raise BlacklistedMac end def time_interval - return if ip_address.in?(Rails.application.credentials.ip.whitelisted) + return if ip_address.in?(Rails.application.credentials.dig(:ip, :whitelisted) || []) s = Snapshot.select(:created_at).where(mac_address: mac_address).order(:created_at).last if s && s.created_at > INTERVAL_LIMIT.ago + 2.minutes # hysteresis diff --git a/app/views/layouts/_footer.html.erb b/app/views/layouts/_footer.html.erb index 8708e1eb..6f88a264 100644 --- a/app/views/layouts/_footer.html.erb +++ b/app/views/layouts/_footer.html.erb @@ -1,27 +1,73 @@ <%# - Lifted out of application.html.erb unchanged, for the same reason as the - navbar. Every icon resolves through asset_path -- production runs with - config.assets.compile = false, so a literal /assets/... path is a 404, which - is what 2ec9baa fixed here and what any rewrite of this file has to preserve. + Four columns on dark, replacing the single copyright line. + + Two links from the draft of this footer are not here, both for reasons that + postdate it: + + /binaries answers 410 since 2cf8bc9. Linking a retired URL from every page + on the site would be a curious way to retire it. + + /majestic-endpoints left the menu in 3f0753c. The page is a pointer to the + camera's own WebUI now rather than somewhere to browse to; its URL stays for + inbound links, and the site does not advertise it. + + Every icon resolves through asset_path. Production runs with + config.assets.compile = false, so a literal /assets/... path is a 404 -- which + is exactly what 2ec9baa fixed in the footer this one replaces, and what the + draft would have reintroduced. %> -