286 lines
13 KiB
HTML
286 lines
13 KiB
HTML
{% extends 'base.html' %}
|
|
{% load i18n %}
|
|
|
|
{% block title %}
|
|
{{ source.name }} | {% trans "Source Details" %} | {% trans "Recruitment System" %}
|
|
{% endblock %}
|
|
|
|
{% block content %}
|
|
<div class="container-fluid py-4">
|
|
<!-- Page Header -->
|
|
<div class="row mb-4">
|
|
<div class="col-12">
|
|
<div class="d-flex justify-content-between align-items-center">
|
|
<div>
|
|
<h1 class="h3 mb-1">{{ source.name }}</h1>
|
|
<nav aria-label="breadcrumb">
|
|
<ol class="breadcrumb">
|
|
<li class="breadcrumb-item">
|
|
<a href="{% url 'source_list' %}">{% trans "Sources" %}</a>
|
|
</li>
|
|
<li class="breadcrumb-item active" aria-current="page">{{ source.name }}</li>
|
|
</ol>
|
|
</nav>
|
|
</div>
|
|
<div class="btn-group">
|
|
<a href="{% url 'source_update' source.pk %}" class="btn btn-primary">
|
|
<i class="fas fa-edit me-2"></i>
|
|
{% trans "Edit" %}
|
|
</a>
|
|
<a href="{% url 'source_delete' source.pk %}" class="btn btn-danger">
|
|
<i class="fas fa-trash me-2"></i>
|
|
{% trans "Delete" %}
|
|
</a>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Source Information Card -->
|
|
<div class="row mb-4">
|
|
<div class="col-12">
|
|
<div class="card shadow">
|
|
<div class="card-header py-3">
|
|
<h6 class="m-0 font-weight-bold text-primary">
|
|
<i class="fas fa-info-circle me-2"></i>
|
|
{% trans "Source Information" %}
|
|
</h6>
|
|
</div>
|
|
<div class="card-body">
|
|
<div class="row">
|
|
<div class="col-md-6">
|
|
<table class="table table-borderless">
|
|
<tr>
|
|
<th width="30%">{% trans "Name" %}</th>
|
|
<td>{{ source.name }}</td>
|
|
</tr>
|
|
<tr>
|
|
<th>{% trans "Type" %}</th>
|
|
<td>
|
|
<span class="badge bg-info">{{ source.source_type }}</span>
|
|
</td>
|
|
</tr>
|
|
<tr>
|
|
<th>{% trans "Status" %}</th>
|
|
<td>
|
|
{% if source.is_active %}
|
|
<span class="badge bg-success">
|
|
<i class="fas fa-check-circle me-1"></i>
|
|
{% trans "Active" %}
|
|
</span>
|
|
{% else %}
|
|
<span class="badge bg-danger">
|
|
<i class="fas fa-times-circle me-1"></i>
|
|
{% trans "Inactive" %}
|
|
</span>
|
|
{% endif %}
|
|
</td>
|
|
</tr>
|
|
</table>
|
|
</div>
|
|
<div class="col-md-6">
|
|
<table class="table table-borderless">
|
|
<tr>
|
|
<th width="30%">{% trans "Created By" %}</th>
|
|
<td>{{ source.created_by }}</td>
|
|
</tr>
|
|
<tr>
|
|
<th>{% trans "Created At" %}</th>
|
|
<td>{{ source.created_at|date:"M d, Y H:i" }}</td>
|
|
</tr>
|
|
<tr>
|
|
<th>{% trans "Updated At" %}</th>
|
|
<td>{{ source.updated_at|date:"M d, Y H:i" }}</td>
|
|
</tr>
|
|
</table>
|
|
</div>
|
|
</div>
|
|
<div class="row mt-3">
|
|
<div class="col-12">
|
|
<h6>{% trans "Description" %}</h6>
|
|
<p class="text-muted">{{ source.description|default:"-" }}</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="row">
|
|
<!-- Network Configuration -->
|
|
<div class="col-lg-6 mb-4">
|
|
<div class="card shadow">
|
|
<div class="card-header py-3">
|
|
<h6 class="m-0 font-weight-bold text-primary">
|
|
<i class="fas fa-network-wired me-2"></i>
|
|
{% trans "Network Configuration" %}
|
|
</h6>
|
|
</div>
|
|
<div class="card-body">
|
|
<div class="mb-3">
|
|
<strong>{% trans "IP Address" %}:</strong>
|
|
<code>{{ source.ip_address|default:"Not specified" }}</code>
|
|
</div>
|
|
<div class="mb-3">
|
|
<strong>{% trans "Trusted IPs" %}:</strong>
|
|
<div class="mt-2">
|
|
{% if source.trusted_ips %}
|
|
<div class="d-flex flex-wrap gap-2">
|
|
{% for ip in source.trusted_ips|split:"," %}
|
|
<span class="badge bg-secondary">{{ ip|strip }}</span>
|
|
{% endfor %}
|
|
</div>
|
|
{% else %}
|
|
<span class="text-muted">Not specified</span>
|
|
{% endif %}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- API Configuration -->
|
|
<div class="col-lg-6 mb-4">
|
|
<div class="card shadow">
|
|
<div class="card-header py-3">
|
|
<h6 class="m-0 font-weight-bold text-primary">
|
|
<i class="fas fa-key me-2"></i>
|
|
{% trans "API Configuration" %}
|
|
</h6>
|
|
</div>
|
|
<div class="card-body">
|
|
<div class="mb-3">
|
|
<strong>{% trans "Integration Version" %}:</strong>
|
|
<span class="badge bg-primary">{{ source.integration_version|default:"Not specified" }}</span>
|
|
</div>
|
|
<div class="mb-3">
|
|
<strong>{% trans "API Key" %}:</strong>
|
|
<div class="input-group mt-2">
|
|
<input type="text" class="form-control" id="apiKey" value="{{ masked_api_key }}" readonly>
|
|
<button class="btn btn-outline-secondary" type="button"
|
|
onclick="copyToClipboard('apiKey')">
|
|
<i class="fas fa-copy"></i>
|
|
</button>
|
|
</div>
|
|
</div>
|
|
<div class="mb-3">
|
|
<strong>{% trans "API Secret" %}:</strong>
|
|
<div class="input-group mt-2">
|
|
<input type="text" class="form-control" id="apiSecret" value="{{ masked_api_secret }}" readonly>
|
|
<button class="btn btn-outline-secondary" type="button"
|
|
onclick="copyToClipboard('apiSecret')">
|
|
<i class="fas fa-copy"></i>
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Integration Logs -->
|
|
<div class="row">
|
|
<div class="col-12">
|
|
<div class="card shadow">
|
|
<div class="card-header py-3 d-flex justify-content-between align-items-center">
|
|
<h6 class="m-0 font-weight-bold text-primary">
|
|
<i class="fas fa-history me-2"></i>
|
|
{% trans "Recent Integration Logs" %}
|
|
</h6>
|
|
<a href="{% url 'source_list' %}" class="btn btn-sm btn-secondary">
|
|
<i class="fas fa-arrow-left me-1"></i>
|
|
{% trans "Back to List" %}
|
|
</a>
|
|
</div>
|
|
<div class="card-body">
|
|
{% if recent_logs %}
|
|
<div class="table-responsive">
|
|
<table class="table table-bordered">
|
|
<thead>
|
|
<tr>
|
|
<th>{% trans "Time" %}</th>
|
|
<th>{% trans "Action" %}</th>
|
|
<th>{% trans "Endpoint" %}</th>
|
|
<th>{% trans "Method" %}</th>
|
|
<th>{% trans "Status" %}</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
{% for log in recent_logs %}
|
|
<tr>
|
|
<td>{{ log.created_at|date:"M d, Y H:i:s" }}</td>
|
|
<td>
|
|
<span class="badge bg-info">{{ log.get_action_display }}</span>
|
|
</td>
|
|
<td>
|
|
<code class="text-muted">{{ log.endpoint }}</code>
|
|
</td>
|
|
<td>
|
|
<span class="badge bg-secondary">{{ log.method }}</span>
|
|
</td>
|
|
<td>
|
|
{% if log.success %}
|
|
<span class="badge bg-success">Success</span>
|
|
{% else %}
|
|
<span class="badge bg-danger">Failed</span>
|
|
{% endif %}
|
|
</td>
|
|
</tr>
|
|
{% endfor %}
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
{% if recent_logs.has_previous %}
|
|
<div class="text-center mt-3">
|
|
<a href="?page={{ recent_logs.previous_page_number }}" class="btn btn-sm btn-secondary">
|
|
<i class="fas fa-chevron-left"></i> {% trans "Previous" %}
|
|
</a>
|
|
</div>
|
|
{% endif %}
|
|
{% else %}
|
|
<div class="text-center py-5">
|
|
<i class="fas fa-inbox fa-3x text-muted mb-3"></i>
|
|
<h5 class="text-muted">{% trans "No integration logs found" %}</h5>
|
|
<p class="text-muted">
|
|
{% trans "Integration logs will appear here when this source is used for external integrations." %}
|
|
</p>
|
|
</div>
|
|
{% endif %}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
{% endblock %}
|
|
|
|
{% block extra_js %}
|
|
<script>
|
|
// Make function available globally
|
|
window.copyToClipboard = function(elementId) {
|
|
const element = document.getElementById(elementId);
|
|
if (element) {
|
|
const text = element.value;
|
|
navigator.clipboard.writeText(text).then(function() {
|
|
// Show success message
|
|
const button = event.target.closest('button');
|
|
const originalContent = button.innerHTML;
|
|
button.innerHTML = '<i class="fas fa-check"></i>';
|
|
button.classList.add('btn-success');
|
|
button.classList.remove('btn-outline-secondary');
|
|
|
|
setTimeout(function() {
|
|
button.innerHTML = originalContent;
|
|
button.classList.remove('btn-success');
|
|
button.classList.add('btn-outline-secondary');
|
|
}, 2000);
|
|
}).catch(function(err) {
|
|
console.error('Failed to copy text: ', err);
|
|
alert('{% trans "Failed to copy to clipboard" %}');
|
|
});
|
|
} else {
|
|
console.error('Element not found:', elementId);
|
|
}
|
|
}
|
|
</script>
|
|
{% endblock %}
|