mirror of
https://github.com/magicbug/Cloudlog
synced 2026-08-13 17:49:35 -04:00
Add HTMX modal upload and cert table refresh
Enable HTMX-driven certificate uploads and partial UI updates for LoTW. Updated Lotw controller to detect HTMX requests in do_cert_upload, return inline success/error alerts for modal uploads, and added cert_table_refresh endpoint to return the cert table partial. Extracted the certificate table into a new view (lotw_views/cert_table.php) and replaced the inline table in index.php with a container that loads that partial. Added a Bootstrap modal view (upload_cert_modal.php) with an HTMX multipart form, drag-and-drop file UI, JS handlers to manage upload state and refresh the certificate list, and modal reset behavior. Minor refactors to flash/success handling to support both full-page and HTMX flows.
This commit is contained in:
parent
7f7d2a6426
commit
88e95b0db9
4 changed files with 389 additions and 128 deletions
|
|
@ -93,6 +93,7 @@ class Lotw extends CI_Controller {
|
|||
|
|
||||
| do_cert_upload is called from cert_upload form submit and handles uploading
|
||||
| and processing of p12 files and storing the data into mysql
|
||||
| Now supports HTMX requests for modal-based uploads
|
||||
|
|
||||
*/
|
||||
public function do_cert_upload()
|
||||
|
|
@ -106,6 +107,9 @@ class Lotw extends CI_Controller {
|
|||
echo "You must install php OpenSSL for LoTW functions to work";
|
||||
}
|
||||
|
||||
// Check if this is an HTMX request
|
||||
$is_htmx = $this->input->get_request_header('HX-Request');
|
||||
|
||||
// create folder to store certs while processing
|
||||
if (!file_exists('./uploads/lotw/certs')) {
|
||||
mkdir('./uploads/lotw/certs', 0755, true);
|
||||
|
|
@ -119,17 +123,21 @@ class Lotw extends CI_Controller {
|
|||
if ( ! $this->upload->do_upload('userfile'))
|
||||
{
|
||||
// Upload of P12 Failed
|
||||
$error = array('error' => $this->upload->display_errors());
|
||||
$error = $this->upload->display_errors();
|
||||
|
||||
// Load DXCC Countrys List
|
||||
// If HTMX request, return just the error message
|
||||
if($is_htmx) {
|
||||
echo '<div class="alert alert-danger" role="alert">' . $error . '</div>';
|
||||
return;
|
||||
}
|
||||
|
||||
// Otherwise load the full form page
|
||||
$data = array('error' => $error);
|
||||
$data['dxcc_list'] = $this->dxcc->list();
|
||||
|
||||
// Set Page Title
|
||||
$data['page_title'] = "Logbook of the World";
|
||||
|
||||
// Load Views
|
||||
$this->load->view('interface_assets/header', $data);
|
||||
$this->load->view('lotw_views/upload_cert', $error);
|
||||
$this->load->view('lotw_views/upload_cert', $data);
|
||||
$this->load->view('interface_assets/footer');
|
||||
}
|
||||
else
|
||||
|
|
@ -152,20 +160,28 @@ class Lotw extends CI_Controller {
|
|||
$this->LotwCert->store_certificate($this->session->userdata('user_id'), $info['issued_callsign'], $info['dxcc-id'], $info['validFrom'], $info['validTo_Date'], $info['qso-first-date'], $info['qso-end-date'], $info['pem_key'], $info['general_cert']);
|
||||
|
||||
// Cert success flash message
|
||||
$this->session->set_flashdata('Success', $info['issued_callsign'].' Certificate Imported.');
|
||||
$success_msg = $info['issued_callsign'].' Certificate Imported.';
|
||||
} else {
|
||||
// Certificate is in the system time to update
|
||||
|
||||
$this->LotwCert->update_certificate($this->session->userdata('user_id'), $info['issued_callsign'], $info['dxcc-id'], $info['validFrom'], $info['validTo_Date'], $info['qso-first-date'], $info['qso-end-date'], $info['pem_key'], $info['general_cert']);
|
||||
|
||||
// Cert success flash message
|
||||
$this->session->set_flashdata('Success', $info['issued_callsign'].' Certificate Updated.');
|
||||
|
||||
$success_msg = $info['issued_callsign'].' Certificate Updated.';
|
||||
}
|
||||
|
||||
// p12 certificate processed time to delete the file
|
||||
unlink($data['upload_data']['full_path']);
|
||||
|
||||
// If HTMX request, return just the success message
|
||||
if($is_htmx) {
|
||||
echo '<div class="alert alert-success" role="alert">' . $success_msg . '</div>';
|
||||
return;
|
||||
}
|
||||
|
||||
// Otherwise load the full page
|
||||
$this->session->set_flashdata('Success', $success_msg);
|
||||
|
||||
// Get Array of the logged in users LoTW certs.
|
||||
$data['lotw_cert_results'] = $this->LotwCert->lotw_certs($this->session->userdata('user_id'));
|
||||
|
||||
|
|
@ -176,12 +192,31 @@ class Lotw extends CI_Controller {
|
|||
$this->load->view('interface_assets/header', $data);
|
||||
$this->load->view('lotw_views/index');
|
||||
$this->load->view('interface_assets/footer');
|
||||
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Function: cert_table_refresh
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Returns the certificate table for HTMX refresh after upload
|
||||
|
|
||||
*/
|
||||
public function cert_table_refresh() {
|
||||
$this->load->model('user_model');
|
||||
if(!$this->user_model->authorize(2)) { $this->session->set_flashdata('notice', 'You\'re not allowed to do that!'); redirect('dashboard'); }
|
||||
|
||||
// Load model
|
||||
$this->load->model('LotwCert');
|
||||
|
||||
// Get Array of the logged in users LoTW certs.
|
||||
$data['lotw_cert_results'] = $this->LotwCert->lotw_certs($this->session->userdata('user_id'));
|
||||
|
||||
// Load just the cert table partial
|
||||
$this->load->view('lotw_views/cert_table', $data);
|
||||
}
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Function: lotw_upload
|
||||
|
|
|
|||
112
application/views/lotw_views/cert_table.php
Normal file
112
application/views/lotw_views/cert_table.php
Normal file
|
|
@ -0,0 +1,112 @@
|
|||
<?php if(isset($error)) { ?>
|
||||
<div class="alert alert-danger" role="alert">
|
||||
<?php echo $error; ?>
|
||||
</div>
|
||||
<?php } ?>
|
||||
|
||||
<?php if(isset($_SESSION['Success'])) { ?>
|
||||
<div class="alert alert-success" role="alert">
|
||||
<?php echo $_SESSION['Success']; ?>
|
||||
</div>
|
||||
<?php unset($_SESSION['Success']); ?>
|
||||
<?php } ?>
|
||||
|
||||
<?php if ($lotw_cert_results->num_rows() > 0) { ?>
|
||||
|
||||
<div class="table-responsive">
|
||||
<table class="table table-hover">
|
||||
<thead class="thead-light">
|
||||
<tr>
|
||||
<th scope="col"><?php echo lang('gen_hamradio_callsign'); ?></th>
|
||||
<th scope="col"><?php echo lang('gen_hamradio_dxcc'); ?></th>
|
||||
<th scope="col"><?php echo lang('lotw_qso_start_date'); ?></th>
|
||||
<th scope="col"><?php echo lang('lotw_qso_end_date'); ?></th>
|
||||
<th scope="col"><?php echo lang('lotw_date_created'); ?></th>
|
||||
<th scope="col"><?php echo lang('lotw_date_expires'); ?></th>
|
||||
<th scope="col"><?php echo lang('lotw_status'); ?></th>
|
||||
<th scope="col"><?php echo lang('lotw_options'); ?></th>
|
||||
</tr>
|
||||
</thead>
|
||||
|
||||
<tbody>
|
||||
|
||||
<?php foreach ($lotw_cert_results->result() as $row) { ?>
|
||||
<tr>
|
||||
<td><?php echo $row->callsign; ?></td>
|
||||
<td><?php echo $row->cert_dxcc == '' ? '- NONE -' : ucfirst($row->cert_dxcc); if ($row->cert_dxcc_end != NULL) { echo ' <span class="badge text-bg-danger">'.lang('gen_hamradio_deleted_dxcc').'</span>'; } ?></td>
|
||||
<td><?php
|
||||
if (isset($row->qso_start_date)) {
|
||||
$valid_qso_start = strtotime( $row->qso_start_date );
|
||||
$new_valid_qso_start = date($this->config->item('qso_date_format'), $valid_qso_start );
|
||||
echo $new_valid_qso_start;
|
||||
} else {
|
||||
echo "n/a";
|
||||
} ?>
|
||||
</td>
|
||||
<td><?php
|
||||
if (isset($row->qso_end_date)) {
|
||||
$valid_qso_end = strtotime( $row->qso_end_date );
|
||||
$new_valid_qso_end = date($this->config->item('qso_date_format'), $valid_qso_end );
|
||||
echo $new_valid_qso_end;
|
||||
} else {
|
||||
echo "n/a";
|
||||
} ?>
|
||||
</td>
|
||||
<td><?php
|
||||
$valid_from = strtotime( $row->date_created );
|
||||
$new_valid_from = date($this->config->item('qso_date_format'), $valid_from );
|
||||
echo $new_valid_from; ?>
|
||||
</td>
|
||||
<td>
|
||||
<?php
|
||||
$valid_to = strtotime( $row->date_expires );
|
||||
$new_valid_to = date($this->config->item('qso_date_format'), $valid_to );
|
||||
echo $new_valid_to; ?>
|
||||
</td>
|
||||
<td>
|
||||
<?php $current_date = date('Y-m-d H:i:s'); ?>
|
||||
<?php $warning_date = date('Y-m-d H:i:s', strtotime($row->date_expires.'-30 days')); ?>
|
||||
|
||||
<?php if ($row->archived) { ?>
|
||||
<span class="badge text-bg-secondary"><?php echo 'Archived'; ?></span>
|
||||
<?php } else { ?>
|
||||
<?php if ($current_date > $row->date_expires) { ?>
|
||||
<span class="badge text-bg-danger"><?php echo lang('lotw_expired'); ?></span>
|
||||
<?php } else if ($current_date <= $row->date_expires && $current_date > $warning_date) { ?>
|
||||
<span class="badge text-bg-warning"><?php echo lang('lotw_expiring'); ?></span>
|
||||
<?php } else { ?>
|
||||
<span class="badge text-bg-success"><?php echo lang('lotw_valid'); ?></span>
|
||||
<?php } ?>
|
||||
<?php } ?>
|
||||
|
||||
<?php if ($row->last_upload) {
|
||||
$last_upload = date($this->config->item('qso_date_format').' H:i:s', strtotime( $row->last_upload )); ?>
|
||||
<span class="badge text-bg-success"><?php echo $last_upload; ?></span>
|
||||
<?php } else { ?>
|
||||
<span class="badge text-bg-warning"><?php echo lang('lotw_not_synced'); ?></span>
|
||||
<?php } ?>
|
||||
</td>
|
||||
<td>
|
||||
<?php if ($row->archived) { ?>
|
||||
<a class="btn btn-outline-info btn-sm me-1" href="<?php echo site_url('lotw/toggle_archive_cert/'.$row->lotw_cert_id); ?>" role="button">
|
||||
<i class="fas fa-box-open"></i> Unarchive
|
||||
</a>
|
||||
<?php } else { ?>
|
||||
<a class="btn btn-outline-secondary btn-sm me-1" href="<?php echo site_url('lotw/toggle_archive_cert/'.$row->lotw_cert_id); ?>" role="button">
|
||||
<i class="fas fa-archive"></i> Archive
|
||||
</a>
|
||||
<?php } ?>
|
||||
<a class="btn btn-outline-danger btn-sm" href="<?php echo site_url('lotw/delete_cert/'.$row->lotw_cert_id); ?>" role="button"><i class="far fa-trash-alt"></i> <?php echo lang('lotw_btn_delete'); ?></a>
|
||||
</td>
|
||||
</tr>
|
||||
<?php } ?>
|
||||
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<?php } else { ?>
|
||||
<div class="alert alert-info" role="alert">
|
||||
<?php echo lang('lotw_no_certs_uploaded'); ?>
|
||||
</div>
|
||||
<?php } ?>
|
||||
|
|
@ -6,129 +6,19 @@
|
|||
<!-- Card Starts -->
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<a class="btn btn-outline-success btn-sm float-end" href="<?php echo site_url('/lotw/cert_upload'); ?>" role="button"><i class="fas fa-cloud-upload-alt"></i> <?php echo lang('lotw_btn_upload_certificate'); ?></a><i class="fab fa-expeditedssl"></i> <?php echo lang('lotw_title_available_cert'); ?>
|
||||
<button class="btn btn-outline-success btn-sm float-end" data-bs-toggle="modal" data-bs-target="#uploadCertModal" role="button"><i class="fas fa-cloud-upload-alt"></i> <?php echo lang('lotw_btn_upload_certificate'); ?></button><i class="fab fa-expeditedssl"></i> <?php echo lang('lotw_title_available_cert'); ?>
|
||||
</div>
|
||||
|
||||
<div class="lotw-cert-list">
|
||||
<?php if(isset($error)) { ?>
|
||||
<div class="alert alert-danger" role="alert">
|
||||
<?php echo $error; ?>
|
||||
</div>
|
||||
<?php } ?>
|
||||
|
||||
<?php if(isset($_SESSION['Success'])) { ?>
|
||||
<div class="alert alert-success" role="alert">
|
||||
<?php echo $_SESSION['Success']; ?>
|
||||
</div>
|
||||
<?php } ?>
|
||||
|
||||
<?php if ($lotw_cert_results->num_rows() > 0) { ?>
|
||||
|
||||
<div class="table-responsive">
|
||||
<table class="table table-hover">
|
||||
<thead class="thead-light">
|
||||
<tr>
|
||||
<th scope="col"><?php echo lang('gen_hamradio_callsign'); ?></th>
|
||||
<th scope="col"><?php echo lang('gen_hamradio_dxcc'); ?></th>
|
||||
<th scope="col"><?php echo lang('lotw_qso_start_date'); ?></th>
|
||||
<th scope="col"><?php echo lang('lotw_qso_end_date'); ?></th>
|
||||
<th scope="col"><?php echo lang('lotw_date_created'); ?></th>
|
||||
<th scope="col"><?php echo lang('lotw_date_expires'); ?></th>
|
||||
<th scope="col"><?php echo lang('lotw_status'); ?></th>
|
||||
<th scope="col"><?php echo lang('lotw_options'); ?></th>
|
||||
</tr>
|
||||
</thead>
|
||||
|
||||
<tbody>
|
||||
|
||||
<?php foreach ($lotw_cert_results->result() as $row) { ?>
|
||||
<tr>
|
||||
<td><?php echo $row->callsign; ?></td>
|
||||
<td><?php echo $row->cert_dxcc == '' ? '- NONE -' : ucfirst($row->cert_dxcc); if ($row->cert_dxcc_end != NULL) { echo ' <span class="badge text-bg-danger">'.lang('gen_hamradio_deleted_dxcc').'</span>'; } ?></td>
|
||||
<td><?php
|
||||
if (isset($row->qso_start_date)) {
|
||||
$valid_qso_start = strtotime( $row->qso_start_date );
|
||||
$new_valid_qso_start = date($this->config->item('qso_date_format'), $valid_qso_start );
|
||||
echo $new_valid_qso_start;
|
||||
} else {
|
||||
echo "n/a";
|
||||
} ?>
|
||||
</td>
|
||||
<td><?php
|
||||
if (isset($row->qso_end_date)) {
|
||||
$valid_qso_end = strtotime( $row->qso_end_date );
|
||||
$new_valid_qso_end = date($this->config->item('qso_date_format'), $valid_qso_end );
|
||||
echo $new_valid_qso_end;
|
||||
} else {
|
||||
echo "n/a";
|
||||
} ?>
|
||||
</td>
|
||||
<td><?php
|
||||
$valid_from = strtotime( $row->date_created );
|
||||
$new_valid_from = date($this->config->item('qso_date_format'), $valid_from );
|
||||
echo $new_valid_from; ?>
|
||||
</td>
|
||||
<td>
|
||||
<?php
|
||||
$valid_to = strtotime( $row->date_expires );
|
||||
$new_valid_to = date($this->config->item('qso_date_format'), $valid_to );
|
||||
echo $new_valid_to; ?>
|
||||
</td>
|
||||
<td>
|
||||
<?php $current_date = date('Y-m-d H:i:s'); ?>
|
||||
<?php $warning_date = date('Y-m-d H:i:s', strtotime($row->date_expires.'-30 days')); ?>
|
||||
|
||||
<?php if ($row->archived) { ?>
|
||||
<span class="badge text-bg-secondary"><?php echo 'Archived'; ?></span>
|
||||
<?php } else { ?>
|
||||
<?php if ($current_date > $row->date_expires) { ?>
|
||||
<span class="badge text-bg-danger"><?php echo lang('lotw_expired'); ?></span>
|
||||
<?php } else if ($current_date <= $row->date_expires && $current_date > $warning_date) { ?>
|
||||
<span class="badge text-bg-warning"><?php echo lang('lotw_expiring'); ?></span>
|
||||
<?php } else { ?>
|
||||
<span class="badge text-bg-success"><?php echo lang('lotw_valid'); ?></span>
|
||||
<?php } ?>
|
||||
<?php } ?>
|
||||
|
||||
<?php if ($row->last_upload) {
|
||||
$last_upload = date($this->config->item('qso_date_format').' H:i:s', strtotime( $row->last_upload )); ?>
|
||||
<span class="badge text-bg-success"><?php echo $last_upload; ?></span>
|
||||
<?php } else { ?>
|
||||
<span class="badge text-bg-warning"><?php echo lang('lotw_not_synced'); ?></span>
|
||||
<?php } ?>
|
||||
</td>
|
||||
<td>
|
||||
<?php if ($row->archived) { ?>
|
||||
<a class="btn btn-outline-info btn-sm me-1" href="<?php echo site_url('lotw/toggle_archive_cert/'.$row->lotw_cert_id); ?>" role="button">
|
||||
<i class="fas fa-box-open"></i> Unarchive
|
||||
</a>
|
||||
<?php } else { ?>
|
||||
<a class="btn btn-outline-secondary btn-sm me-1" href="<?php echo site_url('lotw/toggle_archive_cert/'.$row->lotw_cert_id); ?>" role="button">
|
||||
<i class="fas fa-archive"></i> Archive
|
||||
</a>
|
||||
<?php } ?>
|
||||
<a class="btn btn-outline-danger btn-sm" href="<?php echo site_url('lotw/delete_cert/'.$row->lotw_cert_id); ?>" role="button"><i class="far fa-trash-alt"></i> <?php echo lang('lotw_btn_delete'); ?></a>
|
||||
</td>
|
||||
</tr>
|
||||
<?php } ?>
|
||||
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<?php } else { ?>
|
||||
<div class="alert alert-info" role="alert">
|
||||
<?php echo lang('lotw_no_certs_uploaded'); ?>
|
||||
</div>
|
||||
<?php } ?>
|
||||
|
||||
</div>
|
||||
<div class="lotw-cert-list" id="lotw-cert-list">
|
||||
<?php $this->load->view('lotw_views/cert_table', array('lotw_cert_results' => $lotw_cert_results)); ?>
|
||||
</div>
|
||||
</div>
|
||||
<!-- Card Ends -->
|
||||
|
||||
<br>
|
||||
|
||||
<!-- Card Starts -->
|
||||
<!-- Information Card - Only show if certificates exist -->
|
||||
<?php if ($lotw_cert_results->num_rows() > 0) { ?>
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<?php echo lang('lotw_title_information'); ?>
|
||||
|
|
@ -146,9 +36,13 @@
|
|||
<div id="lotw_manual_results"></div>
|
||||
</div>
|
||||
</div>
|
||||
<?php } ?>
|
||||
|
||||
</div>
|
||||
|
||||
<!-- Load Certificate Upload Modal -->
|
||||
<?php $this->load->view('lotw_views/upload_cert_modal'); ?>
|
||||
|
||||
<script>
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
const syncBtn = document.getElementById('manual-sync-btn');
|
||||
|
|
|
|||
220
application/views/lotw_views/upload_cert_modal.php
Normal file
220
application/views/lotw_views/upload_cert_modal.php
Normal file
|
|
@ -0,0 +1,220 @@
|
|||
<!-- LOTW Certificate Upload Modal -->
|
||||
<div class="modal fade" id="uploadCertModal" tabindex="-1" aria-labelledby="uploadCertModalLabel" aria-hidden="true">
|
||||
<div class="modal-dialog">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header border-bottom">
|
||||
<h5 class="modal-title" id="uploadCertModalLabel">
|
||||
<i class="fas fa-cloud-upload-alt me-2"></i><?php echo lang('lotw_btn_upload_certificate'); ?>
|
||||
</h5>
|
||||
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
|
||||
</div>
|
||||
|
||||
<div class="modal-body">
|
||||
<!-- Success/Error Messages -->
|
||||
<div id="cert-upload-messages" class="mb-3"></div>
|
||||
|
||||
<!-- Upload Container -->
|
||||
<div id="uploadContainer">
|
||||
<!-- Instructions Card -->
|
||||
<div class="alert alert-info" role="alert">
|
||||
<h6 class="alert-heading"><i class="fas fa-info-circle me-2"></i><?php echo lang('lotw_title_export_p12_file_instruction'); ?></h6>
|
||||
<ol class="mb-0 ps-3">
|
||||
<li><?php echo lang('lotw_p12_export_step_one'); ?></li>
|
||||
<li><?php echo lang('lotw_p12_export_step_two'); ?></li>
|
||||
<li><?php echo lang('lotw_p12_export_step_three'); ?></li>
|
||||
<li><?php echo lang('lotw_p12_export_step_four'); ?></li>
|
||||
</ol>
|
||||
</div>
|
||||
|
||||
<!-- Upload Form -->
|
||||
<form id="certUploadForm"
|
||||
hx-post="<?php echo site_url('lotw/do_cert_upload'); ?>"
|
||||
hx-encoding='multipart/form-data'
|
||||
hx-target="#cert-upload-messages"
|
||||
hx-swap="innerHTML">
|
||||
|
||||
<div class="mb-4">
|
||||
<label for="userfile" class="form-label fw-semibold"><?php echo lang('lotw_title_upload_p12_cert'); ?></label>
|
||||
|
||||
<!-- Drag & Drop Zone -->
|
||||
<div id="dropZone" class="border-2 border-dashed border-primary rounded p-4 text-center bg-light mb-3 cursor-pointer" style="border-width: 2px !important; transition: all 0.3s ease;">
|
||||
<i class="fas fa-file-import text-primary fa-2x mb-2 d-block"></i>
|
||||
<p class="mb-2 text-muted">Drag and drop your .p12 file here</p>
|
||||
<p class="mb-0 text-muted small">or click to browse</p>
|
||||
</div>
|
||||
|
||||
<input type="file" name="userfile" id="userfile" accept=".p12" required style="display: none; visibility: hidden; height: 0; width: 0; margin: 0; padding: 0; border: none;">
|
||||
<small class="form-text text-muted d-block mt-2"><i class="fas fa-file-certificate me-1"></i>Only .p12 certificate files are accepted</small>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="modal-footer border-top">
|
||||
<button type="submit" id="certUploadBtn" form="certUploadForm" class="btn btn-primary">
|
||||
<i class="fas fa-cloud-upload-alt me-2"></i><?php echo lang('lotw_btn_upload_file'); ?>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
// Handle upload start
|
||||
document.addEventListener('htmx:beforeRequest', function(evt) {
|
||||
if (evt.detail.target && evt.detail.target.id === 'certUploadForm') {
|
||||
const btn = document.getElementById('certUploadBtn');
|
||||
if (btn) {
|
||||
btn.disabled = true;
|
||||
btn.innerHTML = '<i class="fas fa-spinner fa-spin me-2"></i>Uploading...';
|
||||
}
|
||||
}
|
||||
}, true);
|
||||
|
||||
// Handle upload complete - using document-level delegation
|
||||
document.addEventListener('htmx:afterSwap', function(evt) {
|
||||
if (evt.detail.target && evt.detail.target.id === 'cert-upload-messages') {
|
||||
handleUploadSuccess();
|
||||
}
|
||||
}, true);
|
||||
|
||||
// Handle upload success
|
||||
function handleUploadSuccess() {
|
||||
const messagesDiv = document.getElementById('cert-upload-messages');
|
||||
const btn = document.getElementById('certUploadBtn');
|
||||
const uploadContainer = document.getElementById('uploadContainer');
|
||||
|
||||
// Reset button
|
||||
if (btn) {
|
||||
btn.disabled = false;
|
||||
btn.innerHTML = '<i class="fas fa-cloud-upload-alt me-2"></i><?php echo lang('lotw_btn_upload_file'); ?>';
|
||||
}
|
||||
|
||||
// Check for any alert message
|
||||
if (messagesDiv) {
|
||||
const hasDangerAlert = messagesDiv.querySelector('.alert-danger');
|
||||
const hasSuccessAlert = messagesDiv.querySelector('.alert-success');
|
||||
const hasInfoAlert = messagesDiv.querySelector('.alert-info');
|
||||
|
||||
// If there's a success or info alert (not error), hide the form
|
||||
if ((hasSuccessAlert || hasInfoAlert) && !hasDangerAlert) {
|
||||
// Refresh the certificate table
|
||||
htmx.ajax('GET', '<?php echo site_url('lotw/cert_table_refresh'); ?>', '#lotw-cert-list');
|
||||
|
||||
// Hide the upload container and button
|
||||
if (uploadContainer) {
|
||||
uploadContainer.style.display = 'none';
|
||||
}
|
||||
if (btn) {
|
||||
btn.style.display = 'none';
|
||||
}
|
||||
|
||||
// Add a completion message
|
||||
const completionMsg = document.createElement('div');
|
||||
completionMsg.className = 'alert alert-info alert-dismissible fade show mt-3';
|
||||
completionMsg.innerHTML = '<i class="fas fa-info-circle me-2"></i><strong>Certificate uploaded successfully!</strong> The certificate table has been updated. You can close this modal.';
|
||||
messagesDiv.appendChild(completionMsg);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Setup drag and drop - no DOMContentLoaded needed
|
||||
function setupDragDrop() {
|
||||
const dropZone = document.getElementById('dropZone');
|
||||
const fileInput = document.getElementById('userfile');
|
||||
|
||||
if (!dropZone || !fileInput) {
|
||||
setTimeout(setupDragDrop, 100);
|
||||
return;
|
||||
}
|
||||
|
||||
// Click to browse
|
||||
dropZone.addEventListener('click', () => fileInput.click(), { once: false });
|
||||
|
||||
// Drag over
|
||||
dropZone.addEventListener('dragover', (e) => {
|
||||
e.preventDefault();
|
||||
dropZone.style.opacity = '0.7';
|
||||
dropZone.style.backgroundColor = 'rgba(13, 110, 253, 0.1)';
|
||||
});
|
||||
|
||||
// Drag leave
|
||||
dropZone.addEventListener('dragleave', () => {
|
||||
dropZone.style.opacity = '1';
|
||||
dropZone.style.backgroundColor = '';
|
||||
});
|
||||
|
||||
// Drop
|
||||
dropZone.addEventListener('drop', (e) => {
|
||||
e.preventDefault();
|
||||
dropZone.style.opacity = '1';
|
||||
dropZone.style.backgroundColor = '';
|
||||
|
||||
if (e.dataTransfer.files.length > 0) {
|
||||
fileInput.files = e.dataTransfer.files;
|
||||
updateFileDisplay();
|
||||
}
|
||||
});
|
||||
|
||||
// File input change
|
||||
fileInput.addEventListener('change', updateFileDisplay);
|
||||
|
||||
// Update display when file selected
|
||||
function updateFileDisplay() {
|
||||
if (fileInput.files.length > 0) {
|
||||
const fileName = fileInput.files[0].name;
|
||||
dropZone.innerHTML = `<i class="fas fa-check-circle text-success fa-2x mb-2 d-block"></i><p class="mb-0 text-success fw-semibold">${fileName}</p>`;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Setup when modal is first shown
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
setupDragDrop();
|
||||
|
||||
// Also setup modal reset listener
|
||||
const modal = document.getElementById('uploadCertModal');
|
||||
if (modal) {
|
||||
modal.addEventListener('hidden.bs.modal', function() {
|
||||
const fileInput = document.getElementById('userfile');
|
||||
const dropZone = document.getElementById('dropZone');
|
||||
const uploadContainer = document.getElementById('uploadContainer');
|
||||
const certUploadBtn = document.getElementById('certUploadBtn');
|
||||
const messagesDiv = document.getElementById('cert-upload-messages');
|
||||
|
||||
if (fileInput) fileInput.value = '';
|
||||
if (dropZone) {
|
||||
dropZone.innerHTML = `<i class="fas fa-file-import text-primary fa-2x mb-2 d-block"></i><p class="mb-2 text-muted">Drag and drop your .p12 file here</p><p class="mb-0 text-muted small">or click to browse</p>`;
|
||||
}
|
||||
if (uploadContainer) uploadContainer.style.display = 'block';
|
||||
if (certUploadBtn) certUploadBtn.style.display = 'block';
|
||||
if (messagesDiv) messagesDiv.innerHTML = '';
|
||||
});
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
<style>
|
||||
#dropZone {
|
||||
cursor: pointer;
|
||||
transition: all 0.3s ease;
|
||||
}
|
||||
|
||||
#dropZone:hover {
|
||||
background-color: rgba(13, 110, 253, 0.05) !important;
|
||||
border-color: #0d6efd !important;
|
||||
}
|
||||
|
||||
#certUploadBtn {
|
||||
min-width: 140px;
|
||||
}
|
||||
|
||||
.fa-spin {
|
||||
animation: spin 1s linear infinite;
|
||||
}
|
||||
|
||||
@keyframes spin {
|
||||
0% { transform: rotate(0deg); }
|
||||
100% { transform: rotate(360deg); }
|
||||
}
|
||||
</style>
|
||||
Loading…
Add table
Add a link
Reference in a new issue