319 lines
15 KiB
PHP
319 lines
15 KiB
PHP
<?php
|
|
include('include/headscript.php');
|
|
|
|
// Binding preparati da import_insert.php (da risolvere + collegati in automatico).
|
|
$pending = $_SESSION['pending_bindings'] ?? null;
|
|
|
|
if (empty($pending) || (empty($pending['items']) && empty($pending['auto']) && empty($pending['saved']))) {
|
|
// Niente da mostrare: vado alla griglia.
|
|
$tid = $pending['template_id'] ?? ($_SESSION['template_id'] ?? null);
|
|
$ref = $pending['importref'] ?? '';
|
|
unset($_SESSION['pending_bindings']);
|
|
|
|
if ($tid) {
|
|
header("Location: imported.php?id=" . urlencode($tid) . "&importref=" . urlencode($ref));
|
|
} else {
|
|
header("Location: xlstemplates_grid.php");
|
|
}
|
|
exit;
|
|
}
|
|
|
|
$templateId = (int) $pending['template_id'];
|
|
$importRef = (string) $pending['importref'];
|
|
$items = $pending['items'] ?? [];
|
|
$autoItems = $pending['auto'] ?? [];
|
|
$savedItems = $pending['saved'] ?? [];
|
|
|
|
// Righe gia' risolte (modificabili): auto-collegate + binding gia' salvati.
|
|
$resolvedItems = [];
|
|
foreach ($autoItems as $a) {
|
|
$a['badge'] = 'auto';
|
|
$a['badge_class'] = 'bg-success';
|
|
$resolvedItems[] = $a;
|
|
}
|
|
foreach ($savedItems as $s) {
|
|
$s['badge'] = 'salvato';
|
|
$s['badge_class'] = 'bg-secondary';
|
|
$resolvedItems[] = $s;
|
|
}
|
|
|
|
$db = DBHandlerSelect::getInstance();
|
|
$pdo = $db->getConnection();
|
|
$stmt = $pdo->prepare("SELECT name FROM excel_templates WHERE id = ?");
|
|
$stmt->execute([$templateId]);
|
|
$templateName = $stmt->fetchColumn() ?: ('Template ' . $templateId);
|
|
?>
|
|
<!doctype html>
|
|
<html lang="en">
|
|
|
|
<head>
|
|
<meta charset="utf-8">
|
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
<link rel="icon" href="assets/images/favicon-32x32.png" type="image/png" />
|
|
<?php include('cssinclude.php'); ?>
|
|
<link href="https://cdn.jsdelivr.net/npm/select2@4.1.0-rc.0/dist/css/select2.min.css" rel="stylesheet">
|
|
<style>
|
|
.json-value {
|
|
font-family: Consolas, Monaco, monospace;
|
|
font-weight: 600;
|
|
}
|
|
|
|
.binding-status {
|
|
font-size: 12px;
|
|
}
|
|
|
|
td .select2-container {
|
|
min-width: 240px;
|
|
}
|
|
|
|
/* Allinea l'altezza di select2 a form-select/btn di Bootstrap */
|
|
.select2-container--default .select2-selection--single {
|
|
height: 38px;
|
|
border-color: #ced4da;
|
|
}
|
|
|
|
.select2-container--default .select2-selection--single .select2-selection__rendered {
|
|
line-height: 36px;
|
|
}
|
|
|
|
.select2-container--default .select2-selection--single .select2-selection__arrow {
|
|
height: 36px;
|
|
}
|
|
</style>
|
|
<title>Binding JSON -> LIMS - <?= htmlspecialchars($titlewebsite ?? '', ENT_QUOTES, 'UTF-8'); ?></title>
|
|
</head>
|
|
|
|
<body>
|
|
<div class="wrapper">
|
|
<?php include('include/navbar.php'); ?>
|
|
<?php include('include/topbar.php'); ?>
|
|
<div class="page-wrapper">
|
|
<div class="page-content">
|
|
|
|
<div class="card radius-10">
|
|
<div class="card-header">
|
|
<div class="d-flex align-items-center justify-content-between flex-wrap gap-2">
|
|
<div>
|
|
<h6 class="mb-0">Binding JSON -> LIMS</h6>
|
|
<small><?= htmlspecialchars($templateName) ?> - Template ID: <?= $templateId ?></small>
|
|
</div>
|
|
<a href="bindings_manage.php?template_id=<?= $templateId ?>" class="btn btn-sm btn-outline-secondary">
|
|
<i class="fas fa-cog"></i> Gestione binding
|
|
</a>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="card-body">
|
|
<?php if (!empty($items)): ?>
|
|
<div class="alert alert-info">
|
|
Alcuni valori importati dal JSON non hanno ancora una corrispondenza con i valori del LIMS.
|
|
Seleziona il valore LIMS corretto per ciascuno e conferma. I binding verranno salvati e
|
|
riutilizzati nelle importazioni successive.
|
|
</div>
|
|
<?php endif; ?>
|
|
<?php if (!empty($autoItems)): ?>
|
|
<div class="alert alert-success">
|
|
<?= count($autoItems) ?> valore/i collegato/i automaticamente (corrispondenza esatta con il LIMS).
|
|
</div>
|
|
<?php endif; ?>
|
|
|
|
<div id="bindingError" class="alert alert-danger" style="display:none;"></div>
|
|
|
|
<form id="bindingForm">
|
|
<div class="table-responsive">
|
|
<table class="table table-bordered align-middle">
|
|
<thead>
|
|
<tr>
|
|
<th>Campo (template_mapping)</th>
|
|
<th>Valore JSON</th>
|
|
<th>Valore LIMS</th>
|
|
<th style="width:210px;">Azioni</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
<?php foreach ($items as $idx => $item): ?>
|
|
<tr class="binding-row"
|
|
data-index="<?= $idx ?>"
|
|
data-mapping-id="<?= (int) $item['mapping_id'] ?>"
|
|
data-field-id="<?= (int) $item['field_id'] ?>"
|
|
data-json-value="<?= htmlspecialchars($item['json_value'], ENT_QUOTES) ?>"
|
|
data-datadb-ids="<?= htmlspecialchars(json_encode($item['datadb_ids']), ENT_QUOTES) ?>">
|
|
<td class="text-muted"><?= htmlspecialchars($item['field_label']) ?></td>
|
|
<td class="json-value"><?= htmlspecialchars($item['json_value']) ?></td>
|
|
<td>
|
|
<select class="form-select binding-select" data-field-id="<?= (int) $item['field_id'] ?>">
|
|
<option value="">Seleziona valore LIMS...</option>
|
|
</select>
|
|
</td>
|
|
<td>
|
|
<button type="button" class="btn btn-sm btn-outline-secondary skip-binding-btn">Nessuna corrispondenza</button>
|
|
<div class="binding-status text-muted mt-1">In attesa</div>
|
|
</td>
|
|
</tr>
|
|
<?php endforeach; ?>
|
|
|
|
<?php foreach ($resolvedItems as $res): ?>
|
|
<tr class="binding-row"
|
|
data-mapping-id="<?= (int) $res['mapping_id'] ?>"
|
|
data-field-id="<?= (int) $res['field_id'] ?>"
|
|
data-json-value="<?= htmlspecialchars($res['json_value'], ENT_QUOTES) ?>"
|
|
data-datadb-ids="<?= htmlspecialchars(json_encode($res['datadb_ids']), ENT_QUOTES) ?>">
|
|
<td class="text-muted"><?= htmlspecialchars($res['field_label']) ?></td>
|
|
<td class="json-value"><?= htmlspecialchars($res['json_value']) ?></td>
|
|
<td>
|
|
<select class="form-select binding-select" data-field-id="<?= (int) $res['field_id'] ?>">
|
|
<option value="<?= (int) $res['lims_value_id'] ?>" selected><?= htmlspecialchars($res['lims_value']) ?></option>
|
|
</select>
|
|
</td>
|
|
<td>
|
|
<button type="button" class="btn btn-sm btn-outline-secondary skip-binding-btn">Nessuna corrispondenza</button>
|
|
<div class="binding-status mt-1"><span class="badge <?= $res['badge_class'] ?>"><?= $res['badge'] ?></span></div>
|
|
</td>
|
|
</tr>
|
|
<?php endforeach; ?>
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
|
|
<div class="d-flex justify-content-end gap-2 mt-3">
|
|
<a href="imported.php?id=<?= $templateId ?>&importref=<?= urlencode($importRef) ?>"
|
|
class="btn btn-outline-secondary">Salta per ora</a>
|
|
<button type="submit" class="btn btn-primary" id="confirmBindingsBtn" disabled>
|
|
Conferma e prosegui
|
|
</button>
|
|
</div>
|
|
</form>
|
|
</div>
|
|
</div>
|
|
|
|
</div>
|
|
</div>
|
|
<div class="overlay toggle-icon"></div>
|
|
<a href="javaScript:;" class="back-to-top"><i class='bx bxs-up-arrow-alt'></i></a>
|
|
<?php include('include/footer.php'); ?>
|
|
</div>
|
|
|
|
<?php include('jsinclude.php'); ?>
|
|
<script src="https://cdn.jsdelivr.net/npm/select2@4.1.0-rc.0/dist/js/select2.min.js"></script>
|
|
|
|
<script>
|
|
$(function() {
|
|
const TEMPLATE_ID = <?= $templateId ?>;
|
|
const IMPORT_REF = <?= json_encode($importRef) ?>;
|
|
const CONTINUE_URL = 'imported.php?id=' + TEMPLATE_ID + '&importref=' + encodeURIComponent(IMPORT_REF);
|
|
|
|
const $form = $('#bindingForm');
|
|
const $btn = $('#confirmBindingsBtn');
|
|
const $error = $('#bindingError');
|
|
|
|
// Dropdown valori LIMS per riga (search_customfield_values.php).
|
|
$('.binding-select').each(function() {
|
|
const fieldId = $(this).data('field-id');
|
|
$(this).select2({
|
|
placeholder: 'Seleziona valore LIMS...',
|
|
width: '100%',
|
|
ajax: {
|
|
url: 'search_customfield_values.php',
|
|
dataType: 'json',
|
|
delay: 200,
|
|
data: params => ({
|
|
field_id: fieldId,
|
|
q: params.term || '',
|
|
limit: 50
|
|
}),
|
|
processResults: data => ({
|
|
results: data.results || []
|
|
})
|
|
},
|
|
minimumInputLength: 0
|
|
});
|
|
});
|
|
|
|
// Una riga e' pronta se ha un valore scelto oppure e' marcata "nessuna corrispondenza".
|
|
function refreshButton() {
|
|
const allReady = $('.binding-row').toArray().every(row => {
|
|
const $row = $(row);
|
|
return $row.hasClass('is-skipped') || $row.find('.binding-select').val();
|
|
});
|
|
$btn.prop('disabled', !allReady);
|
|
}
|
|
|
|
$('.binding-select').on('change', refreshButton);
|
|
refreshButton();
|
|
|
|
// "Nessuna corrispondenza": azzera il valore importato, nessun binding salvato.
|
|
$('.skip-binding-btn').on('click', function() {
|
|
const $row = $(this).closest('.binding-row');
|
|
const $select = $row.find('.binding-select');
|
|
const $status = $row.find('.binding-status');
|
|
const skipped = $row.toggleClass('is-skipped').hasClass('is-skipped');
|
|
|
|
$(this).toggleClass('btn-outline-secondary', !skipped).toggleClass('btn-secondary', skipped);
|
|
$select.val(null).trigger('change').prop('disabled', skipped);
|
|
$status.text(skipped ? 'Nessuna corrispondenza' : 'In attesa');
|
|
refreshButton();
|
|
});
|
|
|
|
$form.on('submit', function(e) {
|
|
e.preventDefault();
|
|
$error.hide();
|
|
$btn.prop('disabled', true).text('Salvataggio...');
|
|
|
|
const tasks = $('.binding-row').toArray().map(row => {
|
|
const $row = $(row);
|
|
const $status = $row.find('.binding-status');
|
|
const datadbIds = JSON.stringify($row.data('datadb-ids') || []);
|
|
const jsonValue = String($row.data('json-value'));
|
|
|
|
// Riga senza corrispondenza: azzera il valore, niente binding.
|
|
if ($row.hasClass('is-skipped')) {
|
|
return $.post('skip_binding.php', {
|
|
mapping_id: $row.data('mapping-id'),
|
|
json_value: jsonValue,
|
|
datadb_ids: datadbIds
|
|
}).then(resp => {
|
|
if (resp && resp.success) {
|
|
$status.text('Azzerato').removeClass('text-muted').addClass('text-success');
|
|
return true;
|
|
}
|
|
$status.text('Errore').addClass('text-danger');
|
|
throw new Error((resp && resp.error) || 'Errore azzeramento valore');
|
|
});
|
|
}
|
|
|
|
const $select = $row.find('.binding-select');
|
|
const selectedData = $select.select2('data')[0] || {};
|
|
|
|
return $.post('save_binding.php', {
|
|
mapping_id: $row.data('mapping-id'),
|
|
field_id: $row.data('field-id'),
|
|
template_id: TEMPLATE_ID,
|
|
json_value: jsonValue,
|
|
lims_value_id: $select.val(),
|
|
lims_value: selectedData.text || '',
|
|
datadb_ids: datadbIds
|
|
}).then(resp => {
|
|
if (resp && resp.success) {
|
|
$status.text('Salvato').removeClass('text-muted').addClass('text-success');
|
|
return true;
|
|
}
|
|
$status.text('Errore').addClass('text-danger');
|
|
throw new Error((resp && resp.error) || 'Errore salvataggio binding');
|
|
});
|
|
});
|
|
|
|
Promise.all(tasks)
|
|
.then(() => {
|
|
window.location.href = CONTINUE_URL;
|
|
})
|
|
.catch(err => {
|
|
$error.text(err.message || 'Errore durante il salvataggio dei binding.').show();
|
|
$btn.prop('disabled', false).text('Conferma e prosegui');
|
|
});
|
|
});
|
|
});
|
|
</script>
|
|
</body>
|
|
|
|
</html>
|