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
This commit is contained in:
183
internal/api/static/index.html
Normal file
183
internal/api/static/index.html
Normal file
@@ -0,0 +1,183 @@
|
||||
<!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">🍎</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')">← 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()">← 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()">×</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()">×</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>
|
||||
Reference in New Issue
Block a user