mirror of
https://github.com/SrIzan10/hc-harbor.git
synced 2026-05-01 10:45:21 +00:00
256 lines
12 KiB
Plaintext
256 lines
12 KiB
Plaintext
<!DOCTYPE html>
|
|
<html class="<%= Rails.env == "production" ? "production" : "development" %>" data-theme="dark">
|
|
<head>
|
|
<title><%= @page_title || content_for(:title) || "Hackatime" %></title>
|
|
<meta name="viewport" content="width=device-width,initial-scale=1">
|
|
<meta name="apple-mobile-web-app-capable" content="yes">
|
|
<meta name="mobile-web-app-capable" content="yes">
|
|
<meta name="color-scheme" content="dark">
|
|
|
|
<!-- SEO Meta Tags -->
|
|
<meta name="description" content="<%= @meta_description || content_for(:meta_description) || 'Free and open-source coding time tracker built by Hack Club. Track your time across 75+ editors.' %>">
|
|
<meta name="keywords" content="<%= @meta_keywords || content_for(:meta_keywords) || 'coding time tracker, programming stats, wakatime alternative, free time tracking, code statistics, developer analytics, programming time, coding productivity' %>">
|
|
<meta name="author" content="Hack Club">
|
|
<meta name="robots" content="index, follow">
|
|
<link rel="canonical" href="<%= content_for(:canonical_url) || request.original_url %>">
|
|
|
|
<!-- Enhanced SEO -->
|
|
<meta name="theme-color" content="#ec3750">
|
|
<meta name="msapplication-TileColor" content="#ec3750">
|
|
|
|
<!-- Open Graph Tags -->
|
|
<meta property="og:title" content="<%= @og_title || content_for(:og_title) || @page_title || content_for(:title) || 'Hackatime - Free Coding Time Tracker' %>">
|
|
<meta property="og:description" content="<%= @og_description || content_for(:og_description) || @meta_description || content_for(:meta_description) || 'Free and open-source coding time tracker built by Hack Club. Track your time across 75+ editors.' %>">
|
|
<meta property="og:url" content="<%= content_for(:og_url) || request.original_url %>">
|
|
<meta property="og:type" content="<%= content_for(:og_type) || 'website' %>">
|
|
<meta property="og:image" content="<%= content_for(:og_image) || asset_path('favicon.png') %>">
|
|
<meta property="og:image:width" content="1200">
|
|
<meta property="og:image:height" content="630">
|
|
<meta property="og:site_name" content="Hackatime">
|
|
<meta property="og:locale" content="en_US">
|
|
|
|
<!-- Twitter Card Tags -->
|
|
<meta name="twitter:card" content="summary_large_image">
|
|
<meta name="twitter:site" content="@hackclub">
|
|
<meta name="twitter:creator" content="@hackclub">
|
|
<meta name="twitter:title" content="<%= @twitter_title || content_for(:twitter_title) || @page_title || content_for(:title) || 'Hackatime - Free Coding Time Tracker' %>">
|
|
<meta name="twitter:description" content="<%= @twitter_description || content_for(:twitter_description) || @meta_description || content_for(:meta_description) || 'Free and open-source coding time tracker built by Hack Club. Track your time across 75+ editors.' %>">
|
|
<meta name="twitter:image" content="<%= content_for(:twitter_image) || asset_path('favicon.png') %>">
|
|
|
|
<%= csrf_meta_tags %>
|
|
<%= csp_meta_tag %>
|
|
|
|
<% if current_user %>
|
|
<meta name="user-is-superadmin" content="<%= current_user.admin_level == "superadmin" %>">
|
|
<meta name="user-is-admin" content="<%= current_user.admin_level == "admin" %>">
|
|
<meta name="user-is-viewer" content="<%= current_user.admin_level == "viewer" %>">
|
|
<% end %>
|
|
|
|
<%= yield :head %>
|
|
|
|
<!-- JSON-LD Structured Data -->
|
|
<script type="application/ld+json">
|
|
{
|
|
"@context": "https://schema.org",
|
|
"@type": "SoftwareApplication",
|
|
"name": "Hackatime",
|
|
"alternateName": "Hack Club Hackatime",
|
|
"applicationCategory": "DeveloperApplication",
|
|
"operatingSystem": "Any",
|
|
"description": "Track your coding time easily with Hackatime. A free tool to see how much time you spend programming in different languages and editors.",
|
|
"url": "https://hackatime.hackclub.com",
|
|
"downloadUrl": "https://hackatime.hackclub.com",
|
|
"sameAs": [
|
|
"https://github.com/hackclub/hackatime",
|
|
"https://hackatime.hackclub.com/docs"
|
|
],
|
|
"offers": {
|
|
"@type": "Offer",
|
|
"price": "0",
|
|
"priceCurrency": "USD",
|
|
"availability": "https://schema.org/InStock"
|
|
},
|
|
"author": {
|
|
"@type": "Organization",
|
|
"name": "Hack Club",
|
|
"url": "https://hackclub.com"
|
|
},
|
|
"softwareVersion": "2.0",
|
|
"datePublished": "2025-01-01",
|
|
"license": "https://opensource.org/licenses/MIT",
|
|
"programmingLanguage": "Ruby",
|
|
"codeRepository": "https://github.com/hackclub/hackatime",
|
|
"supportingData": "Free coding time tracker",
|
|
"featureList": [
|
|
"Track coding time across 75+ editors",
|
|
"See which languages you use most",
|
|
"View daily coding statistics",
|
|
"Compare with other high schoolers",
|
|
"Free and open source"
|
|
]
|
|
}
|
|
</script>
|
|
|
|
<!-- Organization Schema -->
|
|
<script type="application/ld+json">
|
|
{
|
|
"@context": "https://schema.org",
|
|
"@type": "Organization",
|
|
"name": "Hack Club",
|
|
"url": "https://hackclub.com",
|
|
"logo": "https://hackclub.com/logo.png",
|
|
"sameAs": [
|
|
"https://twitter.com/hackclub",
|
|
"https://github.com/hackclub"
|
|
]
|
|
}
|
|
</script>
|
|
|
|
<!-- WebSite Schema -->
|
|
<script type="application/ld+json">
|
|
{
|
|
"@context": "https://schema.org",
|
|
"@type": "WebSite",
|
|
"name": "Hackatime",
|
|
"alternateName": "Hack Club Hackatime",
|
|
"url": "https://hackatime.hackclub.com"
|
|
}
|
|
</script>
|
|
|
|
<!-- FAQ Schema for Homepage -->
|
|
<% if request.path == "/" %>
|
|
<script type="application/ld+json">
|
|
{
|
|
"@context": "https://schema.org",
|
|
"@type": "FAQPage",
|
|
"mainEntity": [
|
|
{
|
|
"@type": "Question",
|
|
"name": "What is Hackatime?",
|
|
"acceptedAnswer": {
|
|
"@type": "Answer",
|
|
"text": "Hackatime is a free coding time tracker that helps you see how much time you spend programming. It tracks your coding time across different languages and editors."
|
|
}
|
|
},
|
|
{
|
|
"@type": "Question",
|
|
"name": "Is Hackatime free?",
|
|
"acceptedAnswer": {
|
|
"@type": "Answer",
|
|
"text": "Yes! Hackatime is completely free to use. There are no paid plans or hidden costs."
|
|
}
|
|
},
|
|
{
|
|
"@type": "Question",
|
|
"name": "How is Hackatime different from WakaTime?",
|
|
"acceptedAnswer": {
|
|
"@type": "Answer",
|
|
"text": "Hackatime is free and open source, while WakaTime has paid plans. Hackatime gives you all features for free and you can host it yourself."
|
|
}
|
|
},
|
|
{
|
|
"@type": "Question",
|
|
"name": "Is Hackatime the same as WakaTime?",
|
|
"acceptedAnswer": {
|
|
"@type": "Answer",
|
|
"text": "No. Hackatime is a separate, independent open-source project built by Hack Club. While both track coding time, Hackatime is completely free and designed for high school students in the Hack Club community."
|
|
}
|
|
}
|
|
]
|
|
}
|
|
</script>
|
|
<% end %>
|
|
|
|
<%# Enable PWA manifest for installable apps (make sure to enable in config/routes.rb too!) %>
|
|
<%#= tag.link rel: "manifest", href: pwa_manifest_path(format: :json) %>
|
|
|
|
<%= favicon_link_tag asset_path('favicon.png'), type: 'image/png' %>
|
|
|
|
<script defer data-domain="hackatime.hackclub.com" src="https://plausible.io/js/script.file-downloads.hash.js"></script>
|
|
|
|
<%# Includes all stylesheet files in app/assets/stylesheets %>
|
|
<%= stylesheet_link_tag :app %>
|
|
<%= javascript_importmap_tags %>
|
|
<%= stylesheet_link_tag "application", "data-turbo-track": "reload" %>
|
|
<%= stylesheet_link_tag "tailwind", "data-turbo-track": "reload" %>
|
|
<%= Sentry.get_trace_propagation_meta.html_safe %>
|
|
</head>
|
|
|
|
<body class="<%= content_for(:body_class) %> flex min-h-screen bg-darker" data-controller="nav">
|
|
<% unless content_for?(:hide_nav) %>
|
|
<button class="mobile-nav-button"
|
|
data-action="click->nav#toggle"
|
|
data-nav-target="button"
|
|
aria-label="Toggle navigation menu"
|
|
aria-expanded="false">
|
|
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor" aria-hidden="true">
|
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 6h16M4 12h16M4 18h16" />
|
|
</svg>
|
|
</button>
|
|
<div class="nav-overlay" data-nav-target="overlay" data-action="click->nav#close"></div>
|
|
<%= render "shared/nav" %>
|
|
<% end %>
|
|
|
|
<!-- 250px is defined in nav.css -->
|
|
<main class="flex-1 <%= 'lg:ml-[250px] lg:max-w-[calc(100%-250px)]' unless content_for?(:hide_nav) %> p-5 mb-[100px] pt-16 lg:pt-5 transition-all duration-300 ease-in-out">
|
|
<%= yield %>
|
|
<footer class="relative w-full mt-12 mb-5 p-2.5 text-center text-xs text-gray-600 hover:text-gray-300 transition-colors duration-200">
|
|
<div class="container">
|
|
<p>
|
|
Build <%= link_to Rails.application.config.git_version, Rails.application.config.commit_link, class: "text-inherit underline opacity-80 hover:opacity-100 transition-opacity duration-200" %>
|
|
from <%= time_ago_in_words(Rails.application.config.server_start_time) %> ago.
|
|
<%= pluralize(Heartbeat.recent_count, 'heartbeat') %>
|
|
(<%= Heartbeat.recent_imported_count %> imported)
|
|
in the past 24 hours.
|
|
(DB: <%= pluralize(QueryCount::Counter.counter, "query") %>, <%= QueryCount::Counter.counter_cache %> cached)
|
|
(CACHE: <%= cache_stats[:hits] %> hits, <%= cache_stats[:misses] %> misses)
|
|
(<%= requests_per_second %>)
|
|
</p>
|
|
<% if session[:impersonater_user_id] %>
|
|
<%= link_to "Stop impersonating", stop_impersonating_path, class: "text-primary font-bold hover:text-red-300 transition-colors duration-200", data: { turbo_prefetch: "false" } %>
|
|
<% end %>
|
|
</div>
|
|
<%= render "static_pages/active_users_graph", hours: active_users_graph_data %>
|
|
</footer>
|
|
</main>
|
|
|
|
<div class="fixed top-0 right-5 max-w-sm max-h-[80vh] bg-elevated border border-darkless rounded-b-xl shadow-lg z-[1000] overflow-hidden transform -translate-y-full transition-transform duration-300 ease-out hidden"
|
|
data-controller="currently-hacking"
|
|
data-currently-hacking-target="container"
|
|
data-currently-hacking-count-url-value="<%= currently_hacking_count_static_pages_path %>"
|
|
data-currently-hacking-full-url-value="<%= currently_hacking_static_pages_path %>"
|
|
data-currently-hacking-interval-value="60000">
|
|
<div class="currently-hacking p-3 bg-elevated cursor-pointer select-none bg-dark flex items-center justify-between">
|
|
<div class="text-white text-sm font-medium">
|
|
<div class="flex items-center">
|
|
<div class="w-2 h-2 rounded-full bg-green-500 animate-pulse mr-2"></div>
|
|
<span data-currently-hacking-target="count" class="text-lg"></span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div data-currently-hacking-target="content" style="display: none;">
|
|
</div>
|
|
</div>
|
|
<%= render "shared/modal",
|
|
modal_id: "logout-modal",
|
|
title: "Woah hold on a sec",
|
|
description: "You sure you want to sign out? You can sign back in later but that is a bit of a hassle...",
|
|
icon_svg: '<path fill="currentColor" d="M5 5h6c.55 0 1-.45 1-1s-.45-1-1-1H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h6c.55 0 1-.45 1-1s-.45-1-1-1H5z" /><path fill="currentColor" d="m20.65 11.65l-2.79-2.79a.501.501 0 0 0-.86.35V11h-7c-.55 0-1 .45-1 1s.45 1 1 1h7v1.79c0 .45.54.67.85.35l2.79-2.79c.2-.19.2-.51.01-.7" />',
|
|
icon_color: "text-primary",
|
|
buttons: [
|
|
{
|
|
text: "Go back",
|
|
class: "border border-gray-600 text-gray-300 hover:bg-darkless",
|
|
action: "click->modal#close"
|
|
},
|
|
{
|
|
text: "Log out now",
|
|
class: "bg-primary text-white hover:bg-red-600 font-medium",
|
|
form: true,
|
|
url: signout_path,
|
|
method: "delete"
|
|
}
|
|
] %>
|
|
</body>
|
|
</html>
|