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:
@@ -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}
|
||||
|
||||
@@ -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}
|
||||
|
||||
10
app/templates/cache/detail.html
vendored
10
app/templates/cache/detail.html
vendored
@@ -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 %}
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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 -->
|
||||
|
||||
Reference in New Issue
Block a user