mockups/new_file.html
Rama main · réplica de lectura del repositorio original.
<!DOCTYPE html>
<html lang="en" class="dark">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>New file · mkappworks/cloudzilla — Cloudzilla</title>
<link rel="stylesheet" href="/assets/tailwind.css" />
<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=Geist+Mono:wght@400;500&family=Geist:wght@400;500;600&display=swap" rel="stylesheet" />
</head>
<body class="min-h-screen flex flex-col antialiased font-sans">
<a href="#main-content" class="skip-link">Skip to main content</a>
<div id="cz-header" data-repo-tab="code"></div>
<main id="main-content" tabindex="-1" class="max-w-[1400px] mx-auto px-6 pt-6 pb-20 flex-1 w-full">
<div class="space-y-6 max-w-3xl">
<section aria-labelledby="newfile-title">
<p class="font-mono text-[11px] text-muted-foreground uppercase tracking-wider mb-2">
<a href="repo.html" class="hover:underline">cloudzilla</a>
<span aria-hidden="true">·</span>
New file
</p>
<h1 id="newfile-title" class="text-xl tracking-tight font-medium">Add a file</h1>
<p class="text-[13px] text-muted-foreground mt-1">
Committing to
<span class="font-mono text-foreground">main</span>
</p>
</section>
<div id="nf-error" role="alert" hidden class="text-sm text-destructive bg-destructive/10 border border-destructive/40 rounded-md px-3 py-2">
<p id="nf-error-text"></p>
<p id="nf-error-upload" hidden class="mt-1">Choose <span class="font-mono"></span> again to upload it.</p>
</div>
<form id="newfile-form" class="space-y-5">
<div class="rounded-md border border-border bg-card p-5 space-y-4">
<div>
<label for="nf-path" class="block text-[12px] font-medium mb-1.5">File path</label>
<input id="nf-path" name="path" type="text" value="" placeholder="path/to/file.md" required class="w-full h-9 px-3 text-[13px] font-mono bg-background border border-border rounded-md placeholder:text-muted-foreground focus:outline-hidden focus:ring-2 focus:ring-ring" />
<p class="text-[11px] text-muted-foreground mt-1">Directories in the path are created automatically.</p>
</div>
<div>
<label for="nf-content" class="block text-[12px] font-medium mb-1.5">Contents</label>
<textarea id="nf-content" name="content" rows="16" placeholder="Type the file contents here…" class="w-full px-3 py-2 text-[13px] font-mono bg-background border border-border rounded-md placeholder:text-muted-foreground focus:outline-hidden focus:ring-2 focus:ring-ring resize-y"></textarea>
</div>
</div>
<div id="upload" class="rounded-md border border-border bg-card p-5">
<label for="nf-file" class="block text-[12px] font-medium mb-1.5">…or upload a file</label>
<input id="nf-file" name="file" type="file" class="block w-full text-[13px] text-muted-foreground file:mr-3 file:h-8 file:px-3 file:text-[13px] file:border file:border-border file:rounded-md file:bg-muted file:text-foreground file:hover:bg-accent" />
<p class="text-[11px] text-muted-foreground mt-1">An uploaded file replaces the typed contents. End the path with / to keep the uploaded file's name.</p>
</div>
<div class="rounded-md border border-border bg-card p-5">
<label for="nf-message" class="block text-[12px] font-medium mb-1.5">Commit message</label>
<input id="nf-message" name="message" type="text" placeholder="Add new file" class="w-full h-9 px-3 text-[13px] bg-background border border-border rounded-md placeholder:text-muted-foreground focus:outline-hidden focus:ring-2 focus:ring-ring" />
</div>
<div class="flex items-center justify-end gap-2">
<a href="repo.html" class="h-9 px-3 inline-flex items-center text-[13px] border border-border rounded-md hover:bg-accent">Cancel</a>
<button type="submit" class="h-9 px-4 inline-flex items-center text-[13px] bg-primary text-primary-foreground rounded-md hover:bg-primary/90 font-medium">Commit file</button>
</div>
</form>
</div>
</main>
<div id="cz-footer"></div>
<script src="shell.js"></script>
<script>
// The real handler re-renders the form with the typed path, contents and message; the mock keeps them in place.
function showError(msg, upload) {
document.getElementById('nf-error-text').textContent = msg;
var again = document.getElementById('nf-error-upload');
again.hidden = !upload;
again.querySelector('span').textContent = upload;
document.getElementById('nf-error').hidden = false;
}
document.getElementById('newfile-form').addEventListener('submit', async function (e) {
e.preventDefault();
if ((await new Response(new FormData(e.currentTarget)).blob()).size > 26 * 1024 * 1024) {
return showError('Files are limited to 25 MB. Reduce the form size and try again.', '');
}
var path = document.getElementById('nf-path').value.trim();
var file = document.getElementById('nf-file').files[0];
var upload = file ? file.name : '';
if (file && (path === '' || path.endsWith('/'))) path += file.name;
if (path === '') return showError('a file path is required', upload);
if (path.endsWith('/')) return showError('the path ends in /: add a file name or upload a file', upload);
if (/^\/?\.git(\/|$)/.test(path)) return showError('invalid file path: ".git" is reserved for Git\'s own data', upload);
window.czToast('File committed to main.');
setTimeout(function () { location.href = 'blob.html'; }, 700);
});
if (location.hash === '#error') {
document.getElementById('nf-path').value = '.git/hooks/post-checkout';
document.getElementById('nf-content').value = '#!/bin/sh\necho checked out\n';
document.getElementById('nf-message').value = 'Add a checkout hook';
showError('invalid file path: ".git" is reserved for Git\'s own data', '');
}
if (location.hash === '#upload') document.getElementById('upload').scrollIntoView();
</script>
</body>
</html>