mirror of
https://github.com/System-End/hackatime.git
synced 2026-04-19 21:05:15 +00:00
Add maintenance page (#1030)
* Add maintenance page * Update the page a lil * Oops * Fixes!
This commit is contained in:
parent
483c723bc4
commit
d16c67d1e9
6 changed files with 233 additions and 0 deletions
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
class ErrorsController < ApplicationController
|
||||
skip_before_action :verify_authenticity_token
|
||||
before_action :render_maintenance_page, except: :not_found
|
||||
|
||||
def bad_request
|
||||
@status_code = 400
|
||||
|
|
@ -32,8 +33,21 @@ class ErrorsController < ApplicationController
|
|||
render_error
|
||||
end
|
||||
|
||||
def service_unavailable
|
||||
@status_code = 503
|
||||
@title = "Service Unavailable"
|
||||
@message = "The service is temporarily unavailable. Please try again later."
|
||||
render_error
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def render_maintenance_page
|
||||
return unless ENV["MAINTENANCE_MODE"].present?
|
||||
|
||||
render file: Rails.root.join("public", "maintenance.html"), layout: false, status: 503, content_type: "text/html"
|
||||
end
|
||||
|
||||
def render_error
|
||||
respond_to do |format|
|
||||
format.html { render "errors/show", status: @status_code, layout: error_layout }
|
||||
|
|
|
|||
7
app/controllers/maintenance_controller.rb
Normal file
7
app/controllers/maintenance_controller.rb
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
class MaintenanceController < ApplicationController
|
||||
skip_before_action :enforce_lockout
|
||||
|
||||
def show
|
||||
render file: Rails.root.join("public", "maintenance.html"), layout: false, content_type: "text/html"
|
||||
end
|
||||
end
|
||||
|
|
@ -57,6 +57,9 @@ module Harbor
|
|||
secure: Rails.env.production?,
|
||||
httponly: true
|
||||
|
||||
require_relative "../lib/maintenance_mode_middleware"
|
||||
config.middleware.insert_before 0, MaintenanceModeMiddleware
|
||||
|
||||
config.middleware.use Rack::Attack
|
||||
config.exceptions_app = routes
|
||||
end
|
||||
|
|
|
|||
|
|
@ -80,6 +80,9 @@ Rails.application.routes.draw do
|
|||
mount LetterOpenerWeb::Engine, at: "/letter_opener"
|
||||
end
|
||||
|
||||
# Maintenance page (always accessible for previewing)
|
||||
get "maintenance", to: "maintenance#show"
|
||||
|
||||
# Reveal health status on /up that returns 200 if the app boots with no exceptions, otherwise 500.
|
||||
# Can be used by load balancers and uptime monitors to verify that the app is live.
|
||||
get "up" => "rails/health#show", as: :rails_health_check
|
||||
|
|
@ -329,4 +332,5 @@ Rails.application.routes.draw do
|
|||
match "/404", to: "errors#not_found", via: :all
|
||||
match "/422", to: "errors#unprocessable_entity", via: :all
|
||||
match "/500", to: "errors#internal_server_error", via: :all
|
||||
match "/503", to: "errors#service_unavailable", via: :all
|
||||
end
|
||||
|
|
|
|||
17
lib/maintenance_mode_middleware.rb
Normal file
17
lib/maintenance_mode_middleware.rb
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
class MaintenanceModeMiddleware
|
||||
MAINTENANCE_PAGE = Rails.root.join("public", "maintenance.html").freeze
|
||||
SKIP_PATHS = %w[/up /maintenance].freeze
|
||||
|
||||
def initialize(app)
|
||||
@app = app
|
||||
end
|
||||
|
||||
def call(env)
|
||||
if ENV["MAINTENANCE_MODE"].present? && !SKIP_PATHS.include?(env["PATH_INFO"])
|
||||
content = File.read(MAINTENANCE_PAGE)
|
||||
[ 503, { "Content-Type" => "text/html", "Retry-After" => "1200" }, [ content ] ]
|
||||
else
|
||||
@app.call(env)
|
||||
end
|
||||
end
|
||||
end
|
||||
188
public/maintenance.html
Normal file
188
public/maintenance.html
Normal file
|
|
@ -0,0 +1,188 @@
|
|||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>Maintenance | Hackatime</title>
|
||||
<link rel="preconnect" href="https://fonts.googleapis.com" />
|
||||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
|
||||
<link
|
||||
href="https://fonts.googleapis.com/css2?family=Spline+Sans:wght@400;500;600;700&display=swap"
|
||||
rel="stylesheet"
|
||||
/>
|
||||
<style>
|
||||
:root {
|
||||
--bg: #121212;
|
||||
--text-main: #ffffff;
|
||||
--text-muted: #a1a1aa;
|
||||
--accent: #e4e4e7;
|
||||
--nav-link: #d4d4d8;
|
||||
}
|
||||
|
||||
body {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
background-color: var(--bg);
|
||||
color: var(--text-main);
|
||||
font-family: "Spline Sans", sans-serif;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
}
|
||||
|
||||
/* Top Banner */
|
||||
.top-bar {
|
||||
background-color: #1a1a1a;
|
||||
font-size: 12px;
|
||||
padding: 8px 0;
|
||||
text-align: center;
|
||||
color: var(--text-muted);
|
||||
border-bottom: 1px solid #27272a;
|
||||
}
|
||||
|
||||
/* Navigation */
|
||||
nav {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
padding: 2rem 5%;
|
||||
max-width: 1400px;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
.logo {
|
||||
font-weight: 700;
|
||||
font-size: 1.5rem;
|
||||
letter-spacing: -1px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 10px;
|
||||
}
|
||||
|
||||
.logo-icon {
|
||||
width: 32px;
|
||||
height: 32px;
|
||||
border: 2px solid white;
|
||||
border-radius: 50%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font-size: 18px;
|
||||
}
|
||||
|
||||
.nav-links {
|
||||
display: flex;
|
||||
gap: 2rem;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.nav-links a {
|
||||
color: var(--nav-link);
|
||||
text-decoration: none;
|
||||
font-size: 15px;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
/* Hero Section */
|
||||
.hero {
|
||||
padding: 80px 5% 40px;
|
||||
max-width: 1400px;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
h1 {
|
||||
font-family: "Spline Sans", sans-serif;
|
||||
font-size: clamp(3rem, 8vw, 6rem);
|
||||
line-height: 0.95;
|
||||
letter-spacing: -0.04em;
|
||||
font-weight: 800;
|
||||
margin: 0;
|
||||
max-width: 1000px;
|
||||
}
|
||||
|
||||
.cta-pill {
|
||||
display: inline-block;
|
||||
background: var(--accent);
|
||||
color: black;
|
||||
padding: 12px 24px;
|
||||
border-radius: 30px;
|
||||
font-weight: 600;
|
||||
text-decoration: none;
|
||||
margin-top: 40px;
|
||||
font-size: 16px;
|
||||
transition: opacity 0.2s;
|
||||
}
|
||||
|
||||
/* Content / FAQ Area */
|
||||
.content-grid {
|
||||
padding: 60px 5%;
|
||||
max-width: 1400px;
|
||||
margin: 0 auto;
|
||||
display: grid;
|
||||
grid-template-columns: 1fr 1fr;
|
||||
gap: 40px;
|
||||
border-top: 1px solid #27272a;
|
||||
}
|
||||
|
||||
.faq-title {
|
||||
font-family: "Spline Sans", sans-serif;
|
||||
font-size: 24px;
|
||||
font-weight: 700;
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
|
||||
.faq-text {
|
||||
color: var(--text-muted);
|
||||
line-height: 1.6;
|
||||
font-size: 18px;
|
||||
max-width: 500px;
|
||||
}
|
||||
|
||||
@media (max-width: 768px) {
|
||||
.nav-links,
|
||||
.top-bar {
|
||||
display: none;
|
||||
}
|
||||
.content-grid {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
h1 {
|
||||
font-size: 3.5rem;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="top-bar">An official service from Hack Club</div>
|
||||
|
||||
<nav>
|
||||
<div class="logo">
|
||||
<div class="logo-icon">H</div>
|
||||
Hackatime
|
||||
</div>
|
||||
<div class="nav-links">
|
||||
<a href="https://github.com/hackclub/hackatime">GitHub</a>
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
<main class="hero">
|
||||
<h1>Hackatime is down for maintenance.</h1>
|
||||
<span class="cta-pill">Est. time: 20 minutes</span>
|
||||
</main>
|
||||
|
||||
<section class="content-grid">
|
||||
<div>
|
||||
<div class="faq-title">Can I still work on my projects?</div>
|
||||
<p class="faq-text">
|
||||
Yes. Once Hackatime comes back up, your editor extensions will
|
||||
automatically reconnect to our servers and upload your tracked time.
|
||||
</p>
|
||||
</div>
|
||||
<div>
|
||||
<div class="faq-title">Why the maintenance?</div>
|
||||
<p class="faq-text">
|
||||
We are performing scheduled updates to improve infrastructure
|
||||
reliability. We appreciate your patience during this brief downtime.
|
||||
</p>
|
||||
</div>
|
||||
</section>
|
||||
</body>
|
||||
</html>
|
||||
Loading…
Add table
Reference in a new issue