hackatime/app/views/users/wakatime_setup_step_3.html.erb
2026-01-27 03:05:59 -05:00

377 lines
19 KiB
Text

<div class="min-h-screen text-white">
<div class="max-w-6xl mx-auto p-4">
<div class="text-center mb-4">
<h1 class="text-4xl font-bold text-primary mb-2">Hackatime Setup</h1>
<div class="flex items-center justify-center gap-2 mb-4">
<div class="w-8 h-8 bg-green rounded-full flex items-center justify-center text-sm font-bold">
<svg class="w-5 h-5 text-white" fill="none" stroke="currentColor" stroke-width="3" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" d="M5 13l4 4L19 7" />
</svg>
</div>
<div class="w-16 h-1 bg-green"></div>
<div class="w-8 h-8 bg-green rounded-full flex items-center justify-center text-sm font-bold">
<svg class="w-5 h-5 text-white" fill="none" stroke="currentColor" stroke-width="3" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" d="M5 13l4 4L19 7" />
</svg>
</div>
<div class="w-16 h-1 bg-green"></div>
<div class="w-8 h-8 bg-primary rounded-full flex items-center justify-center text-sm font-bold">3</div>
<div class="w-16 h-1 bg-darkless"></div>
<div class="w-8 h-8 bg-darkless rounded-full flex items-center justify-center text-sm">4</div>
</div>
</div>
<% if params[:editor] == "vscode" %>
<div class="grid grid-cols-1 lg:grid-cols-3 gap-6">
<div class="lg:col-span-2">
<section class="bg-dark rounded-lg p-6">
<h3 class="text-2xl font-bold text-blue mb-4">💻 Install the VS Code Extension</h3>
<div class="space-y-4">
<p class="text-lg">Install the <a href="https://marketplace.visualstudio.com/items?itemName=WakaTime.vscode-wakatime" target="_blank" rel="noopener noreferrer" class="text-cyan hover:text-blue underline font-semibold">WakaTime extension from the marketplace</a>.</p>
<h4 class="font-bold mb-2">Step-by-step:</h4>
<ol class="list-decimal list-inside space-y-1">
<li>Open VS Code</li>
<li>Click the Extensions icon (squares) on the left sidebar</li>
<li>Search for "WakaTime"</li>
<li>Click <strong>Install</strong> on the WakaTime extension</li>
<li>Restart VS Code if prompted</li>
<li>Code for a few minutes to start tracking your time to make sure it's working</li>
</ol>
<details class="group">
<summary class="cursor-pointer text-secondary hover:text-white flex items-center gap-2">
<svg class="w-4 h-4 transition-transform group-open:rotate-90" fill="none" stroke="currentColor" stroke-width="2" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" d="M9 5l7 7-7 7" />
</svg>
How do I know it's working?
</summary>
<div class="mt-3 pl-6">
<p class="text-md mb-3">You'll see a clock icon in your status bar:</p>
<img src="https://hc-cdn.hel1.your-objectstorage.com/s/v3/95d2513ce4b0c1c147827d17ecb4c24540cd73cc_p.png" alt="WakaTime status bar in VS Code" class="max-w-full h-auto rounded-lg border border-darkless">
</div>
</details>
<details class="group">
<summary class="cursor-pointer text-secondary hover:text-white flex items-center gap-2">
<svg class="w-4 h-4 transition-transform group-open:rotate-90" fill="none" stroke="currentColor" stroke-width="2" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" d="M9 5l7 7-7 7" />
</svg>
Why is the extension called WakaTime?
</summary>
<div class="mt-3 pl-6">
<p class="text-md mb-3">WakaTime is a popular time tracking service for developers. Hackatime is compatible with WakaTime&rsquo;s API, so you can install WakaTime plugins or extensions in your editor or IDE and configure them to send their data to Hackatime instead of the WakaTime service.</p>
</div>
</details>
</div>
</section>
</div>
<div class="lg:col-span-1">
<div class="lg:sticky lg:top-4">
<section id="status-panel" class="bg-dark rounded-lg p-6 border-2 border-darkless">
<div id="waiting-state">
<div class="text-center mb-4">
<div class="w-16 h-16 mx-auto mb-3 rounded-full bg-blue/20 flex items-center justify-center">
<svg class="w-8 h-8 text-blue animate-pulse" fill="none" stroke="currentColor" stroke-width="2" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" d="M15 12a3 3 0 11-6 0 3 3 0 016 0z" />
<path stroke-linecap="round" stroke-linejoin="round" d="M2.458 12C3.732 7.943 7.523 5 12 5c4.478 0 8.268 2.943 9.542 7-1.274 4.057-5.064 7-9.542 7-4.477 0-8.268-2.943-9.542-7z" />
</svg>
</div>
<h4 class="text-xl font-bold text-white mb-2">Waiting for you to code...</h4>
<p class="text-secondary text-sm" id="status-message">Once you've installed the extension, open a file and start typing!</p>
</div>
<div class="bg-darkless rounded-lg p-3">
<div class="flex items-center justify-center gap-2 text-secondary">
<div class="spin"></div>
<span class="text-sm" id="poll-status">Checking for heartbeats...</span>
</div>
</div>
</div>
<div id="success-state" class="hidden">
<div class="text-center mb-4">
<div class="w-16 h-16 mx-auto mb-3 rounded-full bg-green/20 flex items-center justify-center">
<svg class="w-8 h-8 text-green" fill="none" stroke="currentColor" stroke-width="3" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" d="M5 13l4 4L19 7" />
</svg>
</div>
<h4 class="text-xl font-bold text-green mb-2">Heartbeat detected <span id="heartbeat-time-ago"></span>!</h4>
<p class="text-secondary text-sm" id="success-message">Hackatime is tracking your coding. Nice work!</p>
<p id="editor-mismatch-message" class="hidden text-cyan text-sm mt-2"></p>
</div>
<%= link_to my_wakatime_setup_step_4_path, class: "block w-full bg-primary hover:bg-red text-white text-center px-6 py-3 rounded-lg font-semibold transition-colors" do %>
Continue →
<% end %>
</div>
</section>
<p class="text-center text-secondary text-xs mt-3">Already set up? <a href="<%= my_wakatime_setup_step_4_path %>" class="text-cyan hover:underline">Skip to finish</a></p>
</div>
</div>
</div>
<% elsif params[:editor] == "vim" %>
<section id="vim" class="bg-dark rounded-lg p-6 mb-6">
<h3 class="text-2xl font-bold text-green mb-4">📟 Vim</h3>
<div class="space-y-6">
<p class="text-lg">Install the WakaTime plugin using your preferred plugin manager:</p>
<div class="space-y-4">
<div class="bg-green/10 border border-green/30 rounded-lg p-4">
<h4 class="font-bold mb-2">Using vim-plug:</h4>
<pre class="bg-darkless rounded p-3 text-cyan text-sm overflow-x-auto"><code>Plug 'wakatime/vim-wakatime'</code></pre>
<p class="text-sm mt-2">Then run <code class="bg-darkless px-1 rounded text-cyan">:PlugInstall</code></p>
</div>
<div class="bg-green/10 border border-green/30 rounded-lg p-4">
<h4 class="font-bold mb-2">Using Vundle:</h4>
<pre class="bg-darkless rounded p-3 text-cyan text-sm overflow-x-auto"><code>Plugin 'wakatime/vim-wakatime'</code></pre>
<p class="text-sm mt-2">Then run <code class="bg-darkless px-1 rounded text-cyan">:PluginInstall</code></p>
</div>
<div class="bg-green/10 border border-green/30 rounded-lg p-4">
<h4 class="font-bold mb-2">Manual installation:</h4>
<pre class="bg-darkless rounded p-3 text-cyan text-sm overflow-x-auto"><code>cd ~/.vim/bundle
git clone https://github.com/wakatime/vim-wakatime.git</code></pre>
</div>
</div>
</div>
</section>
<div class="flex gap-4 flex-wrap justify-center">
<%= link_to my_wakatime_setup_step_4_path, class: "bg-primary hover:bg-red text-white px-6 py-3 rounded-lg font-semibold transition-colors" do %>
Next Step
<% end %>
</div>
<% elsif params[:editor] == "neovim" %>
<section id="neovim" class="bg-dark rounded-lg p-6 mb-6">
<h3 class="text-2xl font-bold text-green mb-4">📟 Neovim</h3>
<div class="space-y-6">
<p class="text-lg">Install the WakaTime plugin using your preferred plugin manager:</p>
<div class="space-y-4">
<div class="bg-green/10 border border-green/30 rounded-lg p-4">
<h4 class="font-bold mb-2">Using lazy.nvim:</h4>
<pre class="bg-darkless rounded p-3 text-cyan text-sm overflow-x-auto"><code>{ "wakatime/vim-wakatime", lazy = false }</code></pre>
</div>
<div class="bg-green/10 border border-green/30 rounded-lg p-4">
<h4 class="font-bold mb-2">Using packer.nvim:</h4>
<pre class="bg-darkless rounded p-3 text-cyan text-sm overflow-x-auto"><code>use 'wakatime/vim-wakatime'</code></pre>
</div>
<div class="bg-green/10 border border-green/30 rounded-lg p-4">
<h4 class="font-bold mb-2">Using vim-plug:</h4>
<pre class="bg-darkless rounded p-3 text-cyan text-sm overflow-x-auto"><code>Plug 'wakatime/vim-wakatime'</code></pre>
<p class="text-sm mt-2">Then run <code class="bg-darkless px-1 rounded text-cyan">:PlugInstall</code></p>
</div>
</div>
</div>
</section>
<div class="flex gap-4 flex-wrap justify-center">
<%= link_to my_wakatime_setup_step_4_path, class: "bg-primary hover:bg-red text-white px-6 py-3 rounded-lg font-semibold transition-colors" do %>
Next Step
<% end %>
</div>
<% elsif params[:editor] == "emacs" %>
<section id="emacs" class="bg-dark rounded-lg p-6 mb-6">
<h3 class="text-2xl font-bold text-purple mb-4">🔮 Emacs</h3>
<div class="space-y-6">
<p class="text-lg">Install the WakaTime package using your preferred method:</p>
<div class="space-y-4">
<div class="bg-purple/10 border border-purple/30 rounded-lg p-4">
<h4 class="font-bold mb-2">Using MELPA:</h4>
<pre class="bg-darkless rounded p-3 text-cyan text-sm overflow-x-auto"><code>M-x package-install RET wakatime-mode RET</code></pre>
<p class="text-sm mt-2">Then add to your config: <code class="bg-darkless px-1 rounded text-cyan">(global-wakatime-mode)</code></p>
</div>
<div class="bg-purple/10 border border-purple/30 rounded-lg p-4">
<h4 class="font-bold mb-2">Using use-package:</h4>
<pre class="bg-darkless rounded p-3 text-cyan text-sm overflow-x-auto"><code>(use-package wakatime-mode
:ensure t
:config
(global-wakatime-mode))</code></pre>
</div>
</div>
</div>
</section>
<div class="flex gap-4 flex-wrap justify-center">
<%= link_to my_wakatime_setup_step_4_path, class: "bg-primary hover:bg-red text-white px-6 py-3 rounded-lg font-semibold transition-colors" do %>
Next Step
<% end %>
</div>
<% elsif params[:editor] == "godot" %>
<section id="godot" class="bg-dark rounded-lg p-6 mb-6">
<h3 class="text-2xl font-bold text-cyan mb-4">🎮 Godot</h3>
<div class="space-y-6">
<p class="text-lg">Follow our comprehensive <a href="/docs/editors/godot" class="text-cyan hover:text-blue underline">Godot & Hackatime Setup guide</a> with video tutorial!</p>
<div class="bg-cyan/10 border border-cyan/30 rounded-lg p-4">
<h4 class="font-bold mb-2">Quick steps:</h4>
<ol class="list-decimal list-inside space-y-1 text-sm">
<li>Open your Godot project</li>
<li>Go to the <strong>AssetLib</strong> tab</li>
<li>Search for <strong>"Godot Super Wakatime"</strong></li>
<li>Click <strong>Download</strong> and <strong>Install</strong></li>
<li>Enable in <strong>Project → Project Settings → Plugins</strong></li>
</ol>
<p class="text-sm mt-3 text-cyan">📺 <a href="https://www.youtube.com/watch?v=a938RgsBzNg&t=29s" target="_blank" class="underline">Watch the workshop recording</a> for a complete walkthrough!</p>
</div>
<div class="bg-yellow/10 border border-yellow/30 rounded-lg p-4">
<p class="text-yellow text-sm"><strong>Note:</strong> You need to install the plugin for each Godot project separately (it's a Godot limitation).</p>
</div>
</div>
</section>
<div class="flex gap-4 flex-wrap justify-center">
<%= link_to my_wakatime_setup_step_4_path, class: "bg-primary hover:bg-red text-white px-6 py-3 rounded-lg font-semibold transition-colors" do %>
Next Step
<% end %>
</div>
<% else %>
<section class="bg-dark rounded-lg p-6 mb-6">
<h3 class="text-2xl font-bold text-orange mb-4">🔧 Setup your Editor</h3>
<div class="bg-orange/10 border border-orange/30 rounded-lg p-4 mb-4">
<p class="mb-4"><strong>Hackatime works with any editor that supports WakaTime!</strong> This includes PyCharm, IntelliJ, Sublime Text, Atom, Neovim, Unity, Godot, and <a href="https://hackatime.hackclub.com/docs#supported-editors" class="text-cyan hover:text-blue underline">77+ more editors</a>.</p>
</div>
<div class="space-y-4">
<div>
<h4 class="font-bold mb-2 text-lg">Popular Editors:</h4>
<div class="grid grid-cols-1 md:grid-cols-2 gap-3">
<a href="/docs/editors/pycharm" class="flex items-center gap-3 bg-darkless rounded-lg p-3 hover:bg-primary/75 transition-colors">
<img src="/images/editor-icons/pycharm-128.png" alt="PyCharm" class="w-8 h-8">
<span>PyCharm</span>
</a>
<a href="/docs/editors/sublime-text" class="flex items-center gap-3 bg-darkless rounded-lg p-3 hover:bg-primary/75 transition-colors">
<img src="/images/editor-icons/sublime-text-128.png" alt="Sublime Text" class="w-8 h-8">
<span>Sublime Text</span>
</a>
<a href="/docs/editors/unity" class="flex items-center gap-3 bg-darkless rounded-lg p-3 hover:bg-primary/75 transition-colors">
<img src="/images/editor-icons/unity-128.png" alt="Unity" class="w-8 h-8">
<span>Unity</span>
</a>
<a href="/docs/editors/neovim" class="flex items-center gap-3 bg-darkless rounded-lg p-3 hover:bg-primary/75 transition-colors">
<img src="/images/editor-icons/neovim-128.png" alt="Neovim" class="w-8 h-8">
<span>Neovim</span>
</a>
</div>
</div>
<div class="bg-yellow/10 border border-yellow/30 rounded-lg p-4">
<p class="text-yellow font-bold mb-2">⚠️ Important:</p>
<p>When setting up WakaTime plugins, <strong>skip any steps that ask you to update ~/.wakatime.cfg</strong> or change the api_url. The setup script from Step 1 already configured this correctly!</p>
</div>
</div>
</section>
<div class="flex gap-4 flex-wrap justify-center">
<%= link_to my_wakatime_setup_step_4_path, class: "bg-primary hover:bg-red text-white px-6 py-3 rounded-lg font-semibold transition-colors" do %>
Next Step
<% end %>
</div>
<% end %>
</div>
</div>
<% if params[:editor] == "vscode" %>
<script>
document.addEventListener("turbo:load", function () {
const waitingState = document.getElementById("waiting-state");
const successState = document.getElementById("success-state");
const statusMessage = document.getElementById("status-message");
const pollStatus = document.getElementById("poll-status");
const statusPanel = document.getElementById("status-panel");
let checkCount = 0;
const maxChecks = 120; // 10m (5s)
const msg = ["Open any code file and start typing!", "Try editing some code in VS Code...", "Type a few characters in your editor!", "We're watching for your first keystroke...", "Make any edit in VS Code to continue!"];
function showSuccess(timeAgo, detectedEditor) {
waitingState.classList.add("hidden");
successState.classList.remove("hidden");
statusPanel.classList.remove("border-darkless");
statusPanel.classList.add("border-green");
document.getElementById("heartbeat-time-ago").textContent = timeAgo;
if (detectedEditor && detectedEditor.toLowerCase() !== "vscode" && detectedEditor.toLowerCase() !== "vs code") {
const mismatchMessage = document.getElementById("editor-mismatch-message");
mismatchMessage.textContent = `We detected a heartbeat from ${detectedEditor}. If this is intended, you're all set!`;
mismatchMessage.classList.remove("hidden");
}
}
function check() {
fetch(<%== api_v1_my_heartbeats_most_recent_path.to_json %>, {
headers: {
Authorization: "Bearer " + <%== @current_user_api_key.to_json %>,
},
})
.then((response) => response.json())
.then((data) => {
if (data.has_heartbeat) {
const heartbeatTime = new Date(data.heartbeat.created_at);
const now = new Date();
const secondsAgo = (now - heartbeatTime) / 1000;
const recentThreshold = 86400;
if (secondsAgo <= recentThreshold) {
showSuccess(data.time_ago, data.editor);
return;
}
}
throw new Error("No recent heartbeats");
})
.catch((error) => {
checkCount++;
if (checkCount % 3 === 0) {
const msgIndex = Math.floor(checkCount / 3) % msg.length;
statusMessage.textContent = msg[msgIndex];
}
pollStatus.textContent = `Checked ${checkCount} time${checkCount === 1 ? "" : "s"}...`;
if (checkCount >= maxChecks) {
pollStatus.textContent = "Still waiting... Make sure the extension is installed!";
return;
}
setTimeout(check, 5000);
});
}
check();
window.skipToNext = function () {
window.location.href = <%== my_wakatime_setup_step_4_path.to_json %>;
};
});
</script>
<style>
.spin {
width: 16px;
height: 16px;
border: 2px solid var(--color-darkless);
border-top: 2px solid var(--color-blue);
border-radius: 50%;
animation: spin 1s linear infinite;
}
@keyframes spin {
0% {
transform: rotate(0deg);
}
100% {
transform: rotate(360deg);
}
}
</style>
<% end %>