Files
orchard/internal/api/static/index.html
Mondo Diaz 56f5fdb1d5 Initial commit: Orchard content-addressable storage system
- Go server with Gin framework
- PostgreSQL for metadata storage
- MinIO/S3 for artifact storage with SHA256 content addressing
- REST API for grove/tree/fruit operations
- Web UI for managing artifacts
- Docker Compose setup for local development

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-04 10:14:49 -06:00

184 lines
7.6 KiB
HTML

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Orchard - Content Addressable Storage</title>
<link rel="stylesheet" href="/static/style.css">
</head>
<body>
<nav class="navbar">
<div class="nav-brand">
<span class="logo">&#127822;</span> Orchard
</div>
<div class="nav-links">
<a href="#" class="nav-link active" data-view="groves">Groves</a>
<a href="#" class="nav-link" data-view="upload">Upload</a>
<a href="#" class="nav-link" data-view="search">Search</a>
</div>
</nav>
<main class="container">
<!-- Groves View -->
<div id="groves-view" class="view active">
<div class="view-header">
<h1>Groves</h1>
<button class="btn btn-primary" onclick="showCreateGroveModal()">+ New Grove</button>
</div>
<div id="groves-list" class="card-grid">
<div class="loading">Loading groves...</div>
</div>
</div>
<!-- Grove Detail View -->
<div id="grove-detail-view" class="view">
<div class="view-header">
<button class="btn btn-secondary" onclick="showView('groves')">&larr; Back</button>
<h1 id="grove-detail-title">Grove</h1>
</div>
<div class="grove-info" id="grove-info"></div>
<div class="section">
<div class="section-header">
<h2>Trees</h2>
<button class="btn btn-primary" onclick="showCreateTreeModal()">+ New Tree</button>
</div>
<div id="trees-list" class="card-grid"></div>
</div>
</div>
<!-- Tree Detail View -->
<div id="tree-detail-view" class="view">
<div class="view-header">
<button class="btn btn-secondary" onclick="backToGrove()">&larr; Back</button>
<h1 id="tree-detail-title">Tree</h1>
</div>
<div class="tree-info" id="tree-info"></div>
<div class="section">
<div class="section-header">
<h2>Versions (Grafts)</h2>
</div>
<div id="grafts-list" class="table-container"></div>
</div>
<div class="section">
<h2>Upload Artifact</h2>
<form id="tree-upload-form" class="upload-form" onsubmit="uploadToTree(event)">
<div class="form-group">
<label>File</label>
<input type="file" id="tree-upload-file" required>
</div>
<div class="form-group">
<label>Tag (optional)</label>
<input type="text" id="tree-upload-tag" placeholder="e.g., v1.0.0, latest">
</div>
<button type="submit" class="btn btn-primary">Upload</button>
</form>
</div>
</div>
<!-- Upload View -->
<div id="upload-view" class="view">
<h1>Upload Artifact</h1>
<form id="upload-form" class="upload-form card" onsubmit="uploadArtifact(event)">
<div class="form-row">
<div class="form-group">
<label>Grove</label>
<select id="upload-grove" required onchange="loadTreesForUpload()">
<option value="">Select grove...</option>
</select>
</div>
<div class="form-group">
<label>Tree</label>
<select id="upload-tree" required>
<option value="">Select tree...</option>
</select>
</div>
</div>
<div class="form-group">
<label>File</label>
<div class="file-drop" id="file-drop">
<input type="file" id="upload-file" required onchange="updateFileName()">
<p>Drop file here or click to browse</p>
<span id="file-name"></span>
</div>
</div>
<div class="form-group">
<label>Tag (optional)</label>
<input type="text" id="upload-tag" placeholder="e.g., v1.0.0, latest, stable">
</div>
<button type="submit" class="btn btn-primary btn-lg">Upload Artifact</button>
</form>
<div id="upload-result" class="result-card hidden"></div>
</div>
<!-- Search View -->
<div id="search-view" class="view">
<h1>Search Artifacts</h1>
<div class="search-box">
<input type="text" id="search-input" placeholder="Enter fruit ID (SHA256 hash)..." onkeyup="handleSearchKeyup(event)">
<button class="btn btn-primary" onclick="searchFruit()">Search</button>
</div>
<div id="search-result" class="result-card hidden"></div>
</div>
</main>
<!-- Create Grove Modal -->
<div id="create-grove-modal" class="modal hidden">
<div class="modal-content">
<div class="modal-header">
<h2>Create New Grove</h2>
<button class="modal-close" onclick="closeModals()">&times;</button>
</div>
<form onsubmit="createGrove(event)">
<div class="form-group">
<label>Name</label>
<input type="text" id="grove-name" required placeholder="e.g., blinx-core">
</div>
<div class="form-group">
<label>Description</label>
<textarea id="grove-description" placeholder="Optional description..."></textarea>
</div>
<div class="form-group checkbox">
<label>
<input type="checkbox" id="grove-public" checked>
Public grove
</label>
</div>
<div class="modal-actions">
<button type="button" class="btn btn-secondary" onclick="closeModals()">Cancel</button>
<button type="submit" class="btn btn-primary">Create Grove</button>
</div>
</form>
</div>
</div>
<!-- Create Tree Modal -->
<div id="create-tree-modal" class="modal hidden">
<div class="modal-content">
<div class="modal-header">
<h2>Create New Tree</h2>
<button class="modal-close" onclick="closeModals()">&times;</button>
</div>
<form onsubmit="createTree(event)">
<div class="form-group">
<label>Name</label>
<input type="text" id="tree-name" required placeholder="e.g., kernel">
</div>
<div class="form-group">
<label>Description</label>
<textarea id="tree-description" placeholder="Optional description..."></textarea>
</div>
<div class="modal-actions">
<button type="button" class="btn btn-secondary" onclick="closeModals()">Cancel</button>
<button type="submit" class="btn btn-primary">Create Tree</button>
</div>
</form>
</div>
</div>
<!-- Toast Notifications -->
<div id="toast-container"></div>
<script src="/static/app.js"></script>
</body>
</html>