| {% extends "base.html" %} |
|
|
| {% block title %}Scripts - PyRunner{% endblock %} |
|
|
| {% block content %} |
| <div class="flex"> |
| {% include "cpanel/_sidebar.html" %} |
|
|
| <div class="flex-1 p-8"> |
| |
| <div class="flex items-center justify-between mb-8"> |
| <div> |
| <h1 class="text-2xl font-bold text-code-text">Scripts</h1> |
| <p class="text-code-muted">Manage your Python scripts</p> |
| </div> |
| <a href="{% url 'cpanel:script_create' %}" |
| class="px-4 py-2 bg-code-accent hover:bg-code-accent/90 text-white font-semibold rounded-lg transition-colors flex items-center space-x-2"> |
| <svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24"> |
| <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 4v16m8-8H4"/> |
| </svg> |
| <span>New Script</span> |
| </a> |
| </div> |
|
|
| |
| <div class="mb-6 flex items-center flex-wrap gap-4"> |
| <div class="flex items-center space-x-4"> |
| <span class="text-code-muted text-sm">Status:</span> |
| <a href="{% url 'cpanel:script_list' %}{% if selected_tag %}?tag={{ selected_tag.pk }}{% endif %}" |
| class="px-3 py-1 text-sm rounded-lg transition-colors {% if not status_filter %}bg-code-accent/20 text-code-accent{% else %}text-code-muted hover:text-code-text hover:bg-code-bg{% endif %}"> |
| All |
| </a> |
| <a href="{% url 'cpanel:script_list' %}?status=enabled{% if selected_tag %}&tag={{ selected_tag.pk }}{% endif %}" |
| class="px-3 py-1 text-sm rounded-lg transition-colors {% if status_filter == 'enabled' %}bg-code-green/20 text-code-green{% else %}text-code-muted hover:text-code-text hover:bg-code-bg{% endif %}"> |
| Enabled |
| </a> |
| <a href="{% url 'cpanel:script_list' %}?status=disabled{% if selected_tag %}&tag={{ selected_tag.pk }}{% endif %}" |
| class="px-3 py-1 text-sm rounded-lg transition-colors {% if status_filter == 'disabled' %}bg-code-yellow/20 text-code-yellow{% else %}text-code-muted hover:text-code-text hover:bg-code-bg{% endif %}"> |
| Disabled |
| </a> |
| <a href="{% url 'cpanel:script_list' %}?status=archived{% if selected_tag %}&tag={{ selected_tag.pk }}{% endif %}" |
| class="px-3 py-1 text-sm rounded-lg transition-colors {% if status_filter == 'archived' %}bg-code-red/20 text-code-red{% else %}text-code-muted hover:text-code-text hover:bg-code-bg{% endif %}"> |
| Archived |
| </a> |
| </div> |
|
|
| {% if all_tags %} |
| <div class="flex items-center space-x-2"> |
| <span class="text-code-muted text-sm">Tag:</span> |
| <select onchange="filterByTag(this.value)" |
| class="px-3 py-1 text-sm bg-code-bg border border-code-border rounded-lg text-code-text focus:outline-none focus:ring-2 focus:ring-code-accent/50"> |
| <option value="">All Tags</option> |
| {% for tag in all_tags %} |
| <option value="{{ tag.pk }}" {% if selected_tag.pk == tag.pk %}selected{% endif %}> |
| {{ tag.name }} |
| </option> |
| {% endfor %} |
| </select> |
| {% if selected_tag %} |
| <a href="{% url 'cpanel:script_list' %}{% if status_filter %}?status={{ status_filter }}{% endif %}" |
| class="text-code-muted hover:text-code-text text-sm"> |
| Clear |
| </a> |
| {% endif %} |
| </div> |
| {% endif %} |
| </div> |
|
|
| <script> |
| function filterByTag(tagId) { |
| const url = new URL(window.location.href); |
| if (tagId) { |
| url.searchParams.set('tag', tagId); |
| } else { |
| url.searchParams.delete('tag'); |
| } |
| window.location.href = url.toString(); |
| } |
| </script> |
|
|
| |
| {% if scripts %} |
| <div class="bg-code-surface border border-code-border rounded-xl overflow-hidden"> |
| <table class="w-full"> |
| <thead class="bg-code-bg border-b border-code-border"> |
| <tr> |
| <th class="px-6 py-4 text-left text-xs font-semibold text-code-muted uppercase tracking-wider">Name</th> |
| <th class="px-6 py-4 text-left text-xs font-semibold text-code-muted uppercase tracking-wider">Environment</th> |
| <th class="px-6 py-4 text-left text-xs font-semibold text-code-muted uppercase tracking-wider">Tags</th> |
| <th class="px-6 py-4 text-left text-xs font-semibold text-code-muted uppercase tracking-wider">Status</th> |
| <th class="px-6 py-4 text-left text-xs font-semibold text-code-muted uppercase tracking-wider">Runs</th> |
| <th class="px-6 py-4 text-left text-xs font-semibold text-code-muted uppercase tracking-wider">Success Rate</th> |
| <th class="px-6 py-4 text-left text-xs font-semibold text-code-muted uppercase tracking-wider">Updated</th> |
| </tr> |
| </thead> |
| <tbody class="divide-y divide-code-border"> |
| {% for script in scripts %} |
| <tr class="hover:bg-code-bg/50 transition-colors"> |
| <td class="px-6 py-4"> |
| <a href="{% url 'cpanel:script_detail' pk=script.pk %}" class="text-code-accent hover:underline font-medium"> |
| {{ script.name }} |
| </a> |
| {% if script.description %} |
| <p class="text-code-muted text-sm truncate max-w-xs">{{ script.description|truncatechars:50 }}</p> |
| {% endif %} |
| </td> |
| <td class="px-6 py-4 text-code-text"> |
| {{ script.environment.name }} |
| </td> |
| <td class="px-6 py-4"> |
| <div class="flex flex-wrap gap-1"> |
| {% for tag in script.tags.all %} |
| <a href="{% url 'cpanel:script_list' %}?tag={{ tag.pk }}{% if status_filter %}&status={{ status_filter }}{% endif %}" |
| class="inline-flex items-center px-2 py-0.5 text-xs rounded-full tag-{{ tag.color }} hover:opacity-80 transition-opacity"> |
| {{ tag.name }} |
| </a> |
| {% empty %} |
| <span class="text-code-muted text-sm">-</span> |
| {% endfor %} |
| </div> |
| </td> |
| <td class="px-6 py-4"> |
| {% if script.is_archived %} |
| <span class="px-2 py-1 text-xs rounded bg-code-red/20 text-code-red">Archived</span> |
| {% elif script.is_enabled %} |
| <span class="px-2 py-1 text-xs rounded bg-code-green/20 text-code-green">Enabled</span> |
| {% else %} |
| <span class="px-2 py-1 text-xs rounded bg-code-yellow/20 text-code-yellow">Disabled</span> |
| {% endif %} |
| </td> |
| <td class="px-6 py-4 text-code-text"> |
| {{ script.run_count }} |
| </td> |
| <td class="px-6 py-4"> |
| {% if script.run_count > 0 %} |
| <span class="{% if script.success_rate >= 80 %}text-code-green{% elif script.success_rate >= 50 %}text-code-yellow{% else %}text-code-red{% endif %}"> |
| {{ script.success_rate|floatformat:0 }}% |
| </span> |
| {% else %} |
| <span class="text-code-muted">-</span> |
| {% endif %} |
| </td> |
| <td class="px-6 py-4 text-code-muted text-sm"> |
| {{ script.updated_at|timesince }} ago |
| </td> |
| </tr> |
| {% endfor %} |
| </tbody> |
| </table> |
| </div> |
| {% else %} |
| <div class="bg-code-surface border border-code-border rounded-xl p-12 text-center"> |
| <div class="w-16 h-16 bg-code-accent/20 rounded-full flex items-center justify-center mx-auto mb-4"> |
| <svg class="w-8 h-8 text-code-accent" fill="none" stroke="currentColor" viewBox="0 0 24 24"> |
| <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M10 20l4-16m4 4l4 4-4 4M6 16l-4-4 4-4"/> |
| </svg> |
| </div> |
| <h3 class="text-lg font-semibold text-code-text mb-2">No scripts yet</h3> |
| <p class="text-code-muted mb-6">Create your first Python script to get started.</p> |
| <a href="{% url 'cpanel:script_create' %}" |
| class="inline-flex items-center px-4 py-2 bg-code-accent hover:bg-code-accent/90 text-white font-semibold rounded-lg transition-colors"> |
| <svg class="w-5 h-5 mr-2" fill="none" stroke="currentColor" viewBox="0 0 24 24"> |
| <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 4v16m8-8H4"/> |
| </svg> |
| Create Script |
| </a> |
| </div> |
| {% endif %} |
| </div> |
| </div> |
| {% endblock %} |
|
|