- Created `schedule_list.html` to display scheduled actions with execution status, location, and timestamps. - Implemented buttons for executing and canceling schedules, along with a details view placeholder. - Created `unit_list.html` to show assigned units with their status, location, model, and session/file counts. - Added conditional rendering for active sessions and links to view unit and location details.
150 lines
7.0 KiB
HTML
150 lines
7.0 KiB
HTML
<!-- Scheduled Actions List -->
|
|
{% if schedules %}
|
|
<div class="space-y-4">
|
|
{% for item in schedules %}
|
|
<div class="border border-gray-200 dark:border-gray-700 rounded-lg p-4 hover:bg-gray-50 dark:hover:bg-gray-800/50 transition-colors">
|
|
<div class="flex items-start justify-between gap-3">
|
|
<div class="min-w-0 flex-1">
|
|
<div class="flex items-center gap-3 mb-2">
|
|
<h4 class="font-semibold text-gray-900 dark:text-white">
|
|
{{ item.schedule.action_type }}
|
|
</h4>
|
|
{% if item.schedule.execution_status == 'pending' %}
|
|
<span class="px-2 py-1 text-xs font-medium bg-yellow-100 text-yellow-800 dark:bg-yellow-900/30 dark:text-yellow-300 rounded-full">
|
|
Pending
|
|
</span>
|
|
{% elif item.schedule.execution_status == 'completed' %}
|
|
<span class="px-2 py-1 text-xs font-medium bg-green-100 text-green-800 dark:bg-green-900/30 dark:text-green-300 rounded-full">
|
|
Completed
|
|
</span>
|
|
{% elif item.schedule.execution_status == 'failed' %}
|
|
<span class="px-2 py-1 text-xs font-medium bg-red-100 text-red-800 dark:bg-red-900/30 dark:text-red-300 rounded-full">
|
|
Failed
|
|
</span>
|
|
{% elif item.schedule.execution_status == 'cancelled' %}
|
|
<span class="px-2 py-1 text-xs font-medium bg-gray-100 text-gray-800 dark:bg-gray-700 dark:text-gray-300 rounded-full">
|
|
Cancelled
|
|
</span>
|
|
{% endif %}
|
|
</div>
|
|
|
|
<div class="grid grid-cols-2 gap-3 text-sm text-gray-600 dark:text-gray-400">
|
|
{% if item.location %}
|
|
<div>
|
|
<span class="text-xs text-gray-500">Location:</span>
|
|
<a href="/projects/{{ project_id }}/nrl/{{ item.location.id }}"
|
|
class="text-seismo-orange hover:text-seismo-navy font-medium ml-1">
|
|
{{ item.location.name }}
|
|
</a>
|
|
</div>
|
|
{% endif %}
|
|
|
|
<div>
|
|
<span class="text-xs text-gray-500">Scheduled:</span>
|
|
<span class="ml-1">{{ item.schedule.scheduled_time.strftime('%Y-%m-%d %H:%M') if item.schedule.scheduled_time else 'N/A' }}</span>
|
|
</div>
|
|
|
|
{% if item.schedule.executed_at %}
|
|
<div>
|
|
<span class="text-xs text-gray-500">Executed:</span>
|
|
<span class="ml-1">{{ item.schedule.executed_at.strftime('%Y-%m-%d %H:%M') }}</span>
|
|
</div>
|
|
{% endif %}
|
|
|
|
{% if item.schedule.created_at %}
|
|
<div>
|
|
<span class="text-xs text-gray-500">Created:</span>
|
|
<span class="ml-1">{{ item.schedule.created_at.strftime('%Y-%m-%d %H:%M') }}</span>
|
|
</div>
|
|
{% endif %}
|
|
</div>
|
|
|
|
{% if item.schedule.description %}
|
|
<p class="text-xs text-gray-500 dark:text-gray-400 mt-2">
|
|
{{ item.schedule.description }}
|
|
</p>
|
|
{% endif %}
|
|
|
|
{% if item.schedule.result_message %}
|
|
<div class="mt-2 text-xs">
|
|
<span class="text-gray-500">Result:</span>
|
|
<span class="ml-1 text-gray-700 dark:text-gray-300">{{ item.schedule.result_message }}</span>
|
|
</div>
|
|
{% endif %}
|
|
</div>
|
|
|
|
<div class="flex items-center gap-2">
|
|
{% if item.schedule.execution_status == 'pending' %}
|
|
<button onclick="executeSchedule('{{ item.schedule.id }}')"
|
|
class="px-3 py-1 text-xs bg-seismo-orange text-white rounded-lg hover:bg-seismo-navy transition-colors">
|
|
Execute Now
|
|
</button>
|
|
<button onclick="cancelSchedule('{{ item.schedule.id }}')"
|
|
class="px-3 py-1 text-xs bg-red-100 text-red-700 dark:bg-red-900/30 dark:text-red-300 rounded-lg hover:bg-red-200 dark:hover:bg-red-900/50 transition-colors">
|
|
Cancel
|
|
</button>
|
|
{% endif %}
|
|
<button onclick="viewScheduleDetails('{{ item.schedule.id }}')"
|
|
class="px-3 py-1 text-xs bg-gray-100 text-gray-700 dark:bg-gray-700 dark:text-gray-300 rounded-lg hover:bg-gray-200 dark:hover:bg-gray-600 transition-colors">
|
|
Details
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
{% endfor %}
|
|
</div>
|
|
{% else %}
|
|
<div class="text-center py-12">
|
|
<svg class="w-16 h-16 mx-auto mb-4 text-gray-400" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M8 7V3m8 4V3m-9 8h10M5 21h14a2 2 0 002-2V7a2 2 0 00-2-2H5a2 2 0 00-2 2v12a2 2 0 002 2z"></path>
|
|
</svg>
|
|
<p class="text-gray-500 dark:text-gray-400 mb-2">No scheduled actions yet</p>
|
|
<p class="text-sm text-gray-400 dark:text-gray-500">Create schedules to automate tasks</p>
|
|
</div>
|
|
{% endif %}
|
|
|
|
<script>
|
|
function executeSchedule(scheduleId) {
|
|
if (!confirm('Execute this scheduled action now?')) return;
|
|
|
|
fetch(`/api/projects/{{ project_id }}/schedules/${scheduleId}/execute`, {
|
|
method: 'POST',
|
|
})
|
|
.then(response => response.json())
|
|
.then(data => {
|
|
if (data.success) {
|
|
htmx.trigger('#project-schedules', 'refresh');
|
|
} else {
|
|
alert('Error: ' + (data.message || 'Unknown error'));
|
|
}
|
|
})
|
|
.catch(error => {
|
|
alert('Error executing schedule: ' + error);
|
|
});
|
|
}
|
|
|
|
function cancelSchedule(scheduleId) {
|
|
if (!confirm('Cancel this scheduled action?')) return;
|
|
|
|
fetch(`/api/projects/{{ project_id }}/schedules/${scheduleId}/cancel`, {
|
|
method: 'POST',
|
|
})
|
|
.then(response => response.json())
|
|
.then(data => {
|
|
if (data.success) {
|
|
htmx.trigger('#project-schedules', 'refresh');
|
|
} else {
|
|
alert('Error: ' + (data.message || 'Unknown error'));
|
|
}
|
|
})
|
|
.catch(error => {
|
|
alert('Error cancelling schedule: ' + error);
|
|
});
|
|
}
|
|
|
|
function viewScheduleDetails(scheduleId) {
|
|
// TODO: Implement schedule details modal
|
|
alert('Schedule details coming soon: ' + scheduleId);
|
|
}
|
|
</script>
|