2025-08-12 13:33:25 +03:00

523 lines
22 KiB
HTML

{% extends "base.html" %}
{% load static %}
{% block title %}API Endpoint Details - Integration{% endblock %}
{% block content %}
<!-- BEGIN breadcrumb -->
<ol class="breadcrumb float-xl-end">
<li class="breadcrumb-item"><a href="{% url 'core:dashboard' %}">Dashboard</a></li>
<li class="breadcrumb-item"><a href="{% url 'integration:dashboard' %}">Integration</a></li>
<li class="breadcrumb-item"><a href="{% url 'integration:api_endpoint_list' %}">API Endpoints</a></li>
<li class="breadcrumb-item active">{{ object.name }}</li>
</ol>
<!-- END breadcrumb -->
<!-- BEGIN page-header -->
<h1 class="page-header">
{{ object.name }}
<small>API Endpoint Details</small>
</h1>
<!-- END page-header -->
<div class="row">
<div class="col-xl-8">
<!-- BEGIN panel -->
<div class="panel panel-inverse">
<div class="panel-heading">
<h4 class="panel-title">Endpoint Information</h4>
<div class="panel-heading-btn">
<a href="{% url 'integration:api_endpoint_update' object.pk %}" class="btn btn-xs btn-primary me-2">
<i class="fa fa-edit"></i> Edit
</a>
<button class="btn btn-xs btn-success me-2" onclick="testEndpoint()">
<i class="fa fa-play"></i> Test
</button>
<a href="javascript:;" class="btn btn-xs btn-icon btn-default" data-toggle="panel-expand"><i class="fa fa-expand"></i></a>
</div>
</div>
<div class="panel-body">
<div class="row">
<div class="col-md-6">
<table class="table table-borderless">
<tr>
<td class="fw-bold" width="150">Name:</td>
<td>{{ object.name }}</td>
</tr>
<tr>
<td class="fw-bold">External System:</td>
<td>
<a href="{% url 'integration:external_system_detail' object.external_system.pk %}" class="text-decoration-none">
{{ object.external_system.name }}
</a>
</td>
</tr>
<tr>
<td class="fw-bold">URL:</td>
<td><code>{{ object.url }}</code></td>
</tr>
<tr>
<td class="fw-bold">Method:</td>
<td>
<span class="badge bg-{% if object.method == 'GET' %}primary{% elif object.method == 'POST' %}success{% elif object.method == 'PUT' %}warning{% elif object.method == 'DELETE' %}danger{% else %}secondary{% endif %}">
{{ object.method }}
</span>
</td>
</tr>
<tr>
<td class="fw-bold">Status:</td>
<td>
<span class="badge bg-{% if object.status == 'ACTIVE' %}success{% elif object.status == 'INACTIVE' %}secondary{% elif object.status == 'TESTING' %}warning{% else %}danger{% endif %}">
{{ object.get_status_display }}
</span>
</td>
</tr>
</table>
</div>
<div class="col-md-6">
<table class="table table-borderless">
<tr>
<td class="fw-bold" width="150">Health Status:</td>
<td>
{% if object.health_status %}
<span class="badge bg-{% if object.health_status == 'HEALTHY' %}success{% elif object.health_status == 'WARNING' %}warning{% else %}danger{% endif %}">
{{ object.health_status }}
</span>
{% else %}
<span class="text-muted">Not tested</span>
{% endif %}
</td>
</tr>
<tr>
<td class="fw-bold">Last Tested:</td>
<td>{{ object.last_tested|date:"M d, Y H:i"|default:"Never" }}</td>
</tr>
<tr>
<td class="fw-bold">Response Time:</td>
<td>{{ object.last_response_time|default:"--" }}ms</td>
</tr>
<tr>
<td class="fw-bold">Success Rate:</td>
<td>{{ object.success_rate|floatformat:1 }}%</td>
</tr>
<tr>
<td class="fw-bold">Created:</td>
<td>{{ object.created_at|date:"M d, Y H:i" }}</td>
</tr>
</table>
</div>
</div>
{% if object.description %}
<div class="mt-4">
<h6>Description</h6>
<div class="bg-light p-3 rounded">
{{ object.description|linebreaks }}
</div>
</div>
{% endif %}
</div>
</div>
<!-- END panel -->
<!-- BEGIN panel -->
<div class="panel panel-inverse">
<div class="panel-heading">
<h4 class="panel-title">Configuration</h4>
</div>
<div class="panel-body">
<div class="row">
<div class="col-md-6">
<h6>Request Configuration</h6>
<table class="table table-sm table-bordered">
<tr>
<td class="fw-bold" width="120">Timeout:</td>
<td>{{ object.timeout|default:"30" }} seconds</td>
</tr>
<tr>
<td class="fw-bold">Retry Count:</td>
<td>{{ object.retry_count|default:"3" }}</td>
</tr>
<tr>
<td class="fw-bold">Content Type:</td>
<td><code>{{ object.content_type|default:"application/json" }}</code></td>
</tr>
<tr>
<td class="fw-bold">Authentication:</td>
<td>{{ object.auth_type|default:"None" }}</td>
</tr>
</table>
</div>
<div class="col-md-6">
<h6>Response Configuration</h6>
<table class="table table-sm table-bordered">
<tr>
<td class="fw-bold" width="120">Expected Status:</td>
<td>{{ object.expected_status_code|default:"200" }}</td>
</tr>
<tr>
<td class="fw-bold">Response Format:</td>
<td>{{ object.response_format|default:"JSON" }}</td>
</tr>
<tr>
<td class="fw-bold">Validation:</td>
<td>{{ object.validate_response|yesno:"Enabled,Disabled" }}</td>
</tr>
<tr>
<td class="fw-bold">Logging:</td>
<td>{{ object.log_requests|yesno:"Enabled,Disabled" }}</td>
</tr>
</table>
</div>
</div>
{% if object.headers %}
<div class="mt-4">
<h6>Headers</h6>
<div class="table-responsive">
<table class="table table-sm table-striped">
<thead>
<tr>
<th>Header</th>
<th>Value</th>
</tr>
</thead>
<tbody>
{% for header, value in object.headers.items %}
<tr>
<td><code>{{ header }}</code></td>
<td><code>{{ value }}</code></td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
</div>
{% endif %}
{% if object.parameters %}
<div class="mt-4">
<h6>Parameters</h6>
<div class="table-responsive">
<table class="table table-sm table-striped">
<thead>
<tr>
<th>Parameter</th>
<th>Type</th>
<th>Required</th>
<th>Default Value</th>
</tr>
</thead>
<tbody>
{% for param in object.parameters %}
<tr>
<td><code>{{ param.name }}</code></td>
<td>{{ param.type }}</td>
<td>{{ param.required|yesno:"Yes,No" }}</td>
<td><code>{{ param.default_value|default:"--" }}</code></td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
</div>
{% endif %}
</div>
</div>
<!-- END panel -->
<!-- BEGIN panel -->
<div class="panel panel-inverse">
<div class="panel-heading">
<h4 class="panel-title">Recent Test Results</h4>
<div class="panel-heading-btn">
<button class="btn btn-xs btn-success" onclick="testEndpoint()">
<i class="fa fa-play"></i> Run Test
</button>
</div>
</div>
<div class="panel-body">
{% if recent_tests %}
<div class="table-responsive">
<table class="table table-striped">
<thead>
<tr>
<th>Test Date</th>
<th>Status</th>
<th>Response Time</th>
<th>Status Code</th>
<th>Result</th>
<th>Actions</th>
</tr>
</thead>
<tbody>
{% for test in recent_tests %}
<tr>
<td>{{ test.tested_at|date:"M d, Y H:i" }}</td>
<td>
<span class="badge bg-{% if test.success %}success{% else %}danger{% endif %}">
{{ test.success|yesno:"Success,Failed" }}
</span>
</td>
<td>{{ test.response_time }}ms</td>
<td>{{ test.status_code }}</td>
<td>
{% if test.error_message %}
<span class="text-danger">{{ test.error_message|truncatechars:50 }}</span>
{% else %}
<span class="text-success">OK</span>
{% endif %}
</td>
<td>
<button class="btn btn-sm btn-outline-primary" onclick="viewTestDetails({{ test.id }})">
<i class="fa fa-eye"></i>
</button>
</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
{% else %}
<div class="text-center text-muted py-3">
<i class="fa fa-flask fa-2x mb-2"></i>
<div>No test results available</div>
<button class="btn btn-primary mt-2" onclick="testEndpoint()">
<i class="fa fa-play me-2"></i>Run First Test
</button>
</div>
{% endif %}
</div>
</div>
<!-- END panel -->
</div>
<div class="col-xl-4">
<!-- BEGIN panel -->
<div class="panel panel-inverse">
<div class="panel-heading">
<h4 class="panel-title">Quick Actions</h4>
</div>
<div class="panel-body">
<div class="d-grid gap-2">
<button class="btn btn-success" onclick="testEndpoint()">
<i class="fa fa-play me-2"></i>Test Endpoint
</button>
<a href="{% url 'integration:api_endpoint_update' object.pk %}" class="btn btn-primary">
<i class="fa fa-edit me-2"></i>Edit Configuration
</a>
{% if object.status == 'INACTIVE' %}
<button class="btn btn-warning" onclick="activateEndpoint()">
<i class="fa fa-check me-2"></i>Activate Endpoint
</button>
{% else %}
<button class="btn btn-secondary" onclick="deactivateEndpoint()">
<i class="fa fa-pause me-2"></i>Deactivate Endpoint
</button>
{% endif %}
<button class="btn btn-info" onclick="duplicateEndpoint()">
<i class="fa fa-copy me-2"></i>Duplicate Endpoint
</button>
<button class="btn btn-outline-primary" onclick="exportConfiguration()">
<i class="fa fa-download me-2"></i>Export Config
</button>
<hr>
<a href="{% url 'integration:api_endpoint_delete' object.pk %}" class="btn btn-danger">
<i class="fa fa-trash me-2"></i>Delete Endpoint
</a>
</div>
</div>
</div>
<!-- END panel -->
<!-- BEGIN panel -->
<div class="panel panel-inverse">
<div class="panel-heading">
<h4 class="panel-title">Statistics</h4>
</div>
<div class="panel-body">
<div class="row text-center">
<div class="col-6">
<div class="fs-20px fw-bold text-primary">{{ object.total_calls }}</div>
<div class="small text-muted">Total Calls</div>
</div>
<div class="col-6">
<div class="fs-20px fw-bold text-success">{{ object.successful_calls }}</div>
<div class="small text-muted">Successful</div>
</div>
</div>
<hr>
<div class="row text-center">
<div class="col-6">
<div class="fs-20px fw-bold text-danger">{{ object.failed_calls }}</div>
<div class="small text-muted">Failed</div>
</div>
<div class="col-6">
<div class="fs-20px fw-bold text-info">{{ object.avg_response_time }}ms</div>
<div class="small text-muted">Avg Response</div>
</div>
</div>
<hr>
<div class="text-center">
<div class="fs-20px fw-bold text-warning">{{ object.success_rate|floatformat:1 }}%</div>
<div class="small text-muted">Success Rate</div>
</div>
</div>
</div>
<!-- END panel -->
<!-- BEGIN panel -->
<div class="panel panel-inverse">
<div class="panel-heading">
<h4 class="panel-title">External System</h4>
</div>
<div class="panel-body">
<div class="d-flex align-items-center mb-3">
<div class="flex-fill">
<div class="fw-bold">{{ object.external_system.name }}</div>
<div class="small text-muted">{{ object.external_system.system_type }}</div>
</div>
</div>
<table class="table table-borderless table-sm">
<tr>
<td class="fw-bold" width="80">Status:</td>
<td>
<span class="badge bg-{% if object.external_system.status == 'ACTIVE' %}success{% else %}secondary{% endif %}">
{{ object.external_system.get_status_display }}
</span>
</td>
</tr>
<tr>
<td class="fw-bold">Version:</td>
<td>{{ object.external_system.version|default:"Unknown" }}</td>
</tr>
<tr>
<td class="fw-bold">Base URL:</td>
<td><code class="small">{{ object.external_system.base_url }}</code></td>
</tr>
</table>
<div class="d-grid">
<a href="{% url 'integration:external_system_detail' object.external_system.pk %}" class="btn btn-outline-primary btn-sm">
<i class="fa fa-external-link-alt me-2"></i>View System Details
</a>
</div>
</div>
</div>
<!-- END panel -->
</div>
</div>
{% endblock %}
{% block js %}
<script>
function testEndpoint() {
$.ajax({
url: '{% url "integration:api_endpoint_test" object.pk %}',
method: 'POST',
data: {
'csrfmiddlewaretoken': '{{ csrf_token }}'
},
beforeSend: function() {
toastr.info('Testing endpoint...');
},
success: function(response) {
if (response.success) {
toastr.success('Endpoint test successful');
location.reload();
} else {
toastr.error('Endpoint test failed: ' + response.error);
}
},
error: function() {
toastr.error('Failed to test endpoint');
}
});
}
function activateEndpoint() {
$.ajax({
url: '{% url "integration:api_endpoint_activate" object.pk %}',
method: 'POST',
data: {
'csrfmiddlewaretoken': '{{ csrf_token }}'
},
success: function(response) {
if (response.success) {
toastr.success('Endpoint activated successfully');
location.reload();
} else {
toastr.error('Failed to activate endpoint');
}
},
error: function() {
toastr.error('An error occurred while activating the endpoint');
}
});
}
function deactivateEndpoint() {
if (confirm('Deactivate this endpoint?')) {
$.ajax({
url: '{% url "integration:api_endpoint_deactivate" object.pk %}',
method: 'POST',
data: {
'csrfmiddlewaretoken': '{{ csrf_token }}'
},
success: function(response) {
if (response.success) {
toastr.success('Endpoint deactivated successfully');
location.reload();
} else {
toastr.error('Failed to deactivate endpoint');
}
},
error: function() {
toastr.error('An error occurred while deactivating the endpoint');
}
});
}
}
function duplicateEndpoint() {
if (confirm('Create a copy of this endpoint?')) {
$.ajax({
url: '{% url "integration:api_endpoint_duplicate" object.pk %}',
method: 'POST',
data: {
'csrfmiddlewaretoken': '{{ csrf_token }}'
},
success: function(response) {
if (response.success) {
toastr.success('Endpoint duplicated successfully');
window.location.href = response.redirect_url;
} else {
toastr.error('Failed to duplicate endpoint');
}
},
error: function() {
toastr.error('An error occurred while duplicating the endpoint');
}
});
}
}
function exportConfiguration() {
window.open('{% url "integration:api_endpoint_export_config" object.pk %}');
}
function viewTestDetails(testId) {
// Open test details in modal or new page
window.open('{% url "integration:api_endpoint_test_detail" 0 %}'.replace('0', testId));
}
</script>
{% endblock %}