152 lines
8.6 KiB
HTML
152 lines
8.6 KiB
HTML
{% extends 'dashboard.html' %}
|
|
|
|
{% block page %}
|
|
<div class="max-w-5xl mx-auto px-4 sm:px-6 lg:px-8 py-8">
|
|
<!-- Back Link -->
|
|
<div class="mb-6">
|
|
<a href="#" hx-get="{{ url_for('community.index') }}" hx-target="#container" hx-push-url="true"
|
|
class="inline-flex items-center text-sm font-medium text-gray-500 hover:text-gray-700 dark:text-gray-400 dark:hover:text-gray-200 transition-colors">
|
|
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5"
|
|
stroke="currentColor" class="w-4 h-4 mr-1">
|
|
<path stroke-linecap="round" stroke-linejoin="round" d="M10.5 19.5 3 12m0 0 7.5-7.5M3 12h18" />
|
|
</svg>
|
|
Back to Community Library
|
|
</a>
|
|
</div>
|
|
|
|
<!-- Header Section -->
|
|
<div class="bg-white dark:bg-gray-800 rounded-xl shadow-sm border border-gray-200 dark:border-gray-700 p-6 mb-6">
|
|
<div class="flex flex-col md:flex-row md:items-start md:justify-between gap-4">
|
|
<div class="flex-1 min-w-0">
|
|
<div class="flex items-center gap-3 mb-2">
|
|
<h1 class="text-3xl font-bold text-gray-900 dark:text-white tracking-tight">{{ function.name }}</h1>
|
|
<span
|
|
class="inline-flex items-center px-2.5 py-0.5 rounded-full text-xs font-medium bg-blue-100 text-blue-800 dark:bg-blue-900 dark:text-blue-300 border border-blue-200 dark:border-blue-800 uppercase tracking-wide">
|
|
{{ function.runtime }}
|
|
</span>
|
|
</div>
|
|
|
|
<div class="flex flex-wrap items-center gap-4 text-sm text-gray-500 dark:text-gray-400">
|
|
<div class="flex items-center gap-1.5">
|
|
<div class="p-1 rounded-full bg-gray-100 dark:bg-gray-700">
|
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor"
|
|
class="w-4 h-4 text-gray-600 dark:text-gray-300">
|
|
<path fill-rule="evenodd"
|
|
d="M7.5 6a4.5 4.5 0 1 1 9 0 4.5 4.5 0 0 1-9 0ZM3.751 20.105a8.25 8.25 0 0 1 16.498 0 .75.75 0 0 1-.437.695A18.683 18.683 0 0 1 12 22.5c-2.786 0-5.433-.608-7.812-1.7a.75.75 0 0 1-.437-.695Z"
|
|
clip-rule="evenodd" />
|
|
</svg>
|
|
</div>
|
|
<span class="font-medium text-gray-700 dark:text-gray-300">{{ function.username }}</span>
|
|
</div>
|
|
<span class="hidden sm:inline text-gray-300 dark:text-gray-600">•</span>
|
|
<div class="flex items-center gap-1.5">
|
|
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5"
|
|
stroke="currentColor" class="w-4 h-4">
|
|
<path stroke-linecap="round" stroke-linejoin="round"
|
|
d="M6.75 3v2.25M17.25 3v2.25M3 18.75V7.5a2.25 2.25 0 0 1 2.25-2.25h13.5A2.25 2.25 0 0 1 21 7.5v11.25m-18 0h18M5.25 12h13.5h-13.5Zm0 3.75h13.5h-13.5Z" />
|
|
</svg>
|
|
<span>Published on {{ function.created_at.strftime('%B %d, %Y') }}</span>
|
|
</div>
|
|
</div>
|
|
|
|
{% if function.description %}
|
|
<div class="mt-4 prose prose-sm dark:prose-invert max-w-none text-gray-600 dark:text-gray-300">
|
|
<p class="whitespace-pre-wrap">{{ function.description }}</p>
|
|
</div>
|
|
{% endif %}
|
|
</div>
|
|
|
|
<div class="flex-shrink-0">
|
|
<button hx-post="{{ url_for('community.fork', function_id=function.id) }}" hx-target="#container"
|
|
class="inline-flex items-center justify-center px-5 py-2.5 text-sm font-medium text-white transition-all bg-green-600 border border-transparent rounded-lg shadow-sm hover:bg-green-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-green-500 dark:focus:ring-offset-gray-900">
|
|
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5"
|
|
stroke="currentColor" class="w-5 h-5 mr-2 -ml-1">
|
|
<path stroke-linecap="round" stroke-linejoin="round"
|
|
d="M15.75 17.25v3.375c0 .621-.504 1.125-1.125 1.125h-9.75a1.125 1.125 0 0 1-1.125-1.125V7.875c0-.621.504-1.125 1.125-1.125H6.75a9.06 9.06 0 0 1 1.5.124m7.5 10.376h3.375c.621 0 1.125-.504 1.125-1.125V11.25c0-4.46-3.243-8.161-7.5-8.876a9.06 9.06 0 0 0-1.5-.124H9.375c-.621 0-1.125.504-1.125 1.125v3.5m7.5 10.375H9.375a1.125 1.125 0 0 1-1.125-1.125v-9.25m12 6.625v-1.875a3.375 3.375 0 0 0-3.375-3.375h-1.5a1.125 1.125 0 0 1-1.125-1.125v-1.5a3.375 3.375 0 0 0-3.375-3.375H9.75" />
|
|
</svg>
|
|
Fork to My Library
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Tabs & Content -->
|
|
<div
|
|
class="bg-white dark:bg-gray-800 rounded-xl shadow-sm border border-gray-200 dark:border-gray-700 overflow-hidden">
|
|
<div class="border-b border-gray-200 dark:border-gray-700">
|
|
<nav class="flex -mb-px" aria-label="Tabs">
|
|
<button onclick="switchTab('code')" id="tab-code"
|
|
class="w-1/2 py-4 px-1 text-center border-b-2 font-medium text-sm focus:outline-none transition-colors border-blue-500 text-blue-600 dark:text-blue-400">
|
|
Function Code
|
|
</button>
|
|
<button onclick="switchTab('env')" id="tab-env"
|
|
class="w-1/2 py-4 px-1 text-center border-b-2 font-medium text-sm focus:outline-none transition-colors border-transparent text-gray-500 hover:text-gray-700 hover:border-gray-300 dark:text-gray-400 dark:hover:text-gray-300">
|
|
Environment Config
|
|
</button>
|
|
</nav>
|
|
</div>
|
|
|
|
<div class="p-0">
|
|
<div id="content-code" class="block">
|
|
<div id="code-editor" class="h-[500px] w-full"></div>
|
|
</div>
|
|
<div id="content-env" class="hidden">
|
|
<div id="env-editor" class="h-[500px] w-full"></div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<script>
|
|
// Tab Switching Logic
|
|
window.switchTab = function (tabName) {
|
|
// Update Tab Styles
|
|
const tabs = ['code', 'env'];
|
|
tabs.forEach(t => {
|
|
const btn = document.getElementById(`tab-${t}`);
|
|
const content = document.getElementById(`content-${t}`);
|
|
|
|
if (t === tabName) {
|
|
btn.classList.remove('border-transparent', 'text-gray-500', 'hover:text-gray-700', 'hover:border-gray-300', 'dark:text-gray-400', 'dark:hover:text-gray-300');
|
|
btn.classList.add('border-blue-500', 'text-blue-600', 'dark:text-blue-400');
|
|
content.classList.remove('hidden');
|
|
content.classList.add('block');
|
|
} else {
|
|
btn.classList.add('border-transparent', 'text-gray-500', 'hover:text-gray-700', 'hover:border-gray-300', 'dark:text-gray-400', 'dark:hover:text-gray-300');
|
|
btn.classList.remove('border-blue-500', 'text-blue-600', 'dark:text-blue-400');
|
|
content.classList.remove('block');
|
|
content.classList.add('hidden');
|
|
}
|
|
});
|
|
|
|
// Resize editors to ensure they render correctly after visibility change
|
|
if (tabName === 'code') codeEditor.resize();
|
|
if (tabName === 'env') envEditor.resize();
|
|
}
|
|
|
|
// Initialize Ace Editors
|
|
var codeEditor = ace.edit("code-editor");
|
|
codeEditor.setTheme("ace/theme/github_dark");
|
|
codeEditor.session.setMode("ace/mode/{{ 'python' if function.runtime == 'python' else 'javascript' }}");
|
|
codeEditor.setValue({{ function.script_content | tojson | safe }}, -1);
|
|
codeEditor.setReadOnly(true);
|
|
codeEditor.setOptions({
|
|
fontSize: "14px",
|
|
showPrintMargin: false,
|
|
highlightActiveLine: false,
|
|
highlightGutterLine: false
|
|
});
|
|
|
|
var envEditor = ace.edit("env-editor");
|
|
envEditor.setTheme("ace/theme/github_dark");
|
|
envEditor.session.setMode("ace/mode/json");
|
|
envEditor.setValue({{ function.environment_info | safe }}, -1);
|
|
envEditor.setReadOnly(true);
|
|
envEditor.setOptions({
|
|
fontSize: "14px",
|
|
showPrintMargin: false,
|
|
highlightActiveLine: false,
|
|
highlightGutterLine: false
|
|
});
|
|
</script>
|
|
{% endblock %} |