PyRunner / templates /cpanel /scripts /create.html
Akoda35's picture
Upload 8 files
16a0ca6 verified
Raw
History Blame Contribute Delete
5.42 kB
{% extends "base.html" %}
{% block title %}Create Script - PyRunner{% endblock %}
{% block content %}
<div class="flex">
{% include "cpanel/_sidebar.html" %}
<div class="flex-1 p-8">
<!-- Header -->
<div class="mb-8">
<nav class="flex items-center space-x-2 text-sm text-code-muted mb-4">
<a href="{% url 'cpanel:script_list' %}" class="hover:text-code-accent">Scripts</a>
<svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 5l7 7-7 7"/>
</svg>
<span class="text-code-text">Create</span>
</nav>
<h1 class="text-2xl font-bold text-code-text">Create New Script</h1>
<p class="text-code-muted">Write and configure a new Python script</p>
</div>
<!-- Form with Two-Column Layout -->
<form method="post">
{% csrf_token %}
<div class="grid grid-cols-1 lg:grid-cols-12 gap-6">
<!-- Main Column: Name, Description, Code Editor -->
<div class="lg:col-span-7">
{% include "cpanel/scripts/_form_main.html" %}
</div>
<!-- Sidebar: Properties and Settings -->
<div class="lg:col-span-5">
{% include "cpanel/scripts/_form_sidebar.html" %}
</div>
</div>
</form>
</div>
</div>
{% endblock %}
{% block extra_scripts %}
<script src="https://cdn.jsdelivr.net/npm/monaco-editor@0.45.0/min/vs/loader.js"></script>
<script>
// Collapsible sections toggle
function toggleSection(sectionId) {
const content = document.getElementById(sectionId + '-content');
const chevron = document.getElementById(sectionId + '-chevron');
if (content && chevron) {
content.classList.toggle('hidden');
chevron.classList.toggle('rotate-180');
}
}
// Schedule options toggle
function toggleScheduleOptions(mode) {
const intervalOptions = document.getElementById('interval-options');
const dailyOptions = document.getElementById('daily-options');
if (intervalOptions) {
intervalOptions.classList.toggle('hidden', mode !== 'interval');
}
if (dailyOptions) {
dailyOptions.classList.toggle('hidden', mode !== 'daily');
}
// Update radio button styles
document.querySelectorAll('input[name="run_mode"]').forEach(radio => {
const label = radio.closest('label');
const dot = label.querySelector('span > span');
if (radio.checked) {
label.classList.add('border-code-accent', 'bg-code-accent/10');
label.classList.remove('border-code-border');
label.querySelector('span').classList.add('border-code-accent');
label.querySelector('span').classList.remove('border-code-border');
if (!dot) {
const indicator = label.querySelector('span.w-4');
indicator.innerHTML = '<span class="w-2 h-2 rounded-full bg-code-accent"></span>';
}
} else {
label.classList.remove('border-code-accent', 'bg-code-accent/10');
label.classList.add('border-code-border');
label.querySelector('span').classList.remove('border-code-accent');
label.querySelector('span').classList.add('border-code-border');
const indicator = label.querySelector('span.w-4');
indicator.innerHTML = '';
}
});
}
// Monaco Editor initialization
require.config({ paths: { vs: 'https://cdn.jsdelivr.net/npm/monaco-editor@0.45.0/min/vs' } });
require(['vs/editor/editor.main'], function () {
const textarea = document.getElementById('id_code');
const container = document.getElementById('code-editor-container');
if (!textarea || !container) {
console.error('Editor elements not found');
return;
}
textarea.style.display = 'none';
const editor = monaco.editor.create(container, {
value: textarea.value,
language: 'python',
theme: 'vs-dark',
fontSize: 14,
fontFamily: "'JetBrains Mono', 'Fira Code', 'Consolas', monospace",
minimap: { enabled: false },
scrollBeyondLastLine: false,
lineNumbers: 'on',
tabSize: 4,
insertSpaces: true,
automaticLayout: true
});
editor.onDidChangeModelContent(function () {
textarea.value = editor.getValue();
});
});
// Tag selection handling
document.querySelectorAll('.tag-label').forEach(label => {
label.addEventListener('click', function(e) {
if (e.target.tagName === 'INPUT') return;
e.preventDefault(); // Prevent browser's default toggle (input is inside label)
const checkbox = this.querySelector('input[type="checkbox"]');
checkbox.checked = !checkbox.checked;
updateTagStyle(this, checkbox.checked);
});
});
function updateTagStyle(label, isChecked) {
if (isChecked) {
label.classList.add('border-code-accent', 'bg-code-accent/20');
label.classList.remove('border-code-border', 'bg-code-bg');
} else {
label.classList.remove('border-code-accent', 'bg-code-accent/20');
label.classList.add('border-code-border', 'bg-code-bg');
}
}
</script>
{% endblock %}