Add Share to L2 buttons for media, recipes, and runs

- Updated cache detail button from "Publish to IPFS" to "Share to L2"
- Added Share to L2 button on recipe detail page
- Added Share to L2 button on run detail page
- Created /recipes/{id}/publish endpoint
- Created /runs/{id}/publish endpoint (publishes run output)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
gilesb
2026-01-11 18:21:14 +00:00
parent 088af1611b
commit 156014a1f3
5 changed files with 102 additions and 6 deletions

View File

@@ -396,3 +396,40 @@ async def ui_discard_recipe(
'<div class="text-green-400">Recipe deleted</div>'
'<script>setTimeout(() => window.location.href = "/recipes", 1500);</script>'
)
@router.post("/{recipe_id}/publish")
async def publish_recipe(
recipe_id: str,
request: Request,
ctx: UserContext = Depends(require_auth),
recipe_service: RecipeService = Depends(get_recipe_service),
):
"""Publish recipe to L2 and IPFS."""
from ..services.cache_service import CacheService
from ..dependencies import get_cache_manager
import database
# Verify recipe exists
recipe = await recipe_service.get_recipe(recipe_id)
if not recipe:
raise HTTPException(404, "Recipe not found")
# Use cache service to publish (recipes are stored in cache)
cache_service = CacheService(database, get_cache_manager())
ipfs_cid, error = await cache_service.publish_to_l2(
content_hash=recipe_id,
actor_id=ctx.actor_id,
l2_server=ctx.l2_server,
auth_token=request.cookies.get("auth_token"),
)
if error:
if wants_html(request):
return HTMLResponse(f'<span class="text-red-400">{error}</span>')
raise HTTPException(400, error)
if wants_html(request):
return HTMLResponse(f'<span class="text-green-400">Shared: {ipfs_cid[:16]}...</span>')
return {"ipfs_cid": ipfs_cid, "published": True}

View File

@@ -440,3 +440,47 @@ async def ui_discard_run(
'<div class="text-green-400">Run discarded</div>'
'<script>setTimeout(() => window.location.href = "/runs", 1500);</script>'
)
@router.post("/{run_id}/publish")
async def publish_run(
run_id: str,
request: Request,
ctx: UserContext = Depends(require_auth),
run_service: RunService = Depends(get_run_service),
):
"""Publish run output to L2 and IPFS."""
from ..services.cache_service import CacheService
from ..dependencies import get_cache_manager
import database
run = await run_service.get_run(run_id)
if not run:
raise HTTPException(404, "Run not found")
# Check if run has output
output_hash = run.get("output_hash")
if not output_hash:
error = "Run has no output to publish"
if wants_html(request):
return HTMLResponse(f'<span class="text-red-400">{error}</span>')
raise HTTPException(400, error)
# Use cache service to publish the output
cache_service = CacheService(database, get_cache_manager())
ipfs_cid, error = await cache_service.publish_to_l2(
content_hash=output_hash,
actor_id=ctx.actor_id,
l2_server=ctx.l2_server,
auth_token=request.cookies.get("auth_token"),
)
if error:
if wants_html(request):
return HTMLResponse(f'<span class="text-red-400">{error}</span>')
raise HTTPException(400, error)
if wants_html(request):
return HTMLResponse(f'<span class="text-green-400">Shared: {ipfs_cid[:16]}...</span>')
return {"ipfs_cid": ipfs_cid, "output_hash": output_hash, "published": True}

View File

@@ -97,14 +97,12 @@
class="bg-blue-600 hover:bg-blue-700 px-4 py-2 rounded font-medium">
Download
</a>
{% if not cache.ipfs_cid %}
<button hx-post="/cache/{{ cache.content_hash }}/publish"
hx-target="#publish-result"
class="bg-gray-700 hover:bg-gray-600 px-4 py-2 rounded font-medium">
Publish to IPFS
hx-target="#share-result"
class="bg-purple-600 hover:bg-purple-700 px-4 py-2 rounded font-medium">
Share to L2
</button>
<span id="publish-result"></span>
{% endif %}
<span id="share-result"></span>
</div>
</div>
{% endblock %}

View File

@@ -77,6 +77,16 @@
<div class="bg-gray-900 rounded-lg p-4 border border-gray-700">
<pre class="text-sm text-gray-300 overflow-x-auto whitespace-pre-wrap">{{ recipe.yaml }}</pre>
</div>
<!-- Actions -->
<div class="flex items-center space-x-4 mt-8">
<button hx-post="/recipes/{{ recipe.recipe_id }}/publish"
hx-target="#share-result"
class="bg-purple-600 hover:bg-purple-700 px-4 py-2 rounded font-medium">
Share to L2
</button>
<span id="share-result"></span>
</div>
</div>
<script>

View File

@@ -22,6 +22,13 @@
{% if run.cached %}
<span class="bg-purple-900 text-purple-300 px-3 py-1 rounded text-sm">Cached</span>
{% endif %}
<div class="flex-grow"></div>
<button hx-post="/runs/{{ run.run_id }}/publish"
hx-target="#share-result"
class="bg-purple-600 hover:bg-purple-700 px-3 py-1 rounded text-sm font-medium">
Share to L2
</button>
<span id="share-result"></span>
</div>
<!-- Info Grid -->