upgrade matrice with files

This commit is contained in:
2026-03-19 16:16:41 +01:00
parent 245750f057
commit f043b43791
28 changed files with 4028 additions and 358 deletions
+252 -2
View File
@@ -268,6 +268,7 @@ if (!empty($_GET['ajax'])) {
// --- RECORD IN PRODUZIONE (2,7,8)
$sql = "SELECT
p.*,
m.id AS matrice_id,
m.nome AS matrice,
m.photo AS matrice_photo,
(
@@ -329,6 +330,7 @@ if (!empty($_GET['ajax'])) {
// --- RECORD IN STATO 6 ORDINATI PER PRIORITY
$sql2 = "SELECT
p.*,
m.id AS matrice_id,
m.nome AS matrice,
m.photo AS matrice_photo,
(
@@ -930,6 +932,10 @@ if (!empty($_GET['ajax'])) {
margin-left: auto;
/* la porta tutta a destra */
}
.show-matrice-files i {
font-size: 1.5rem;
}
</style>
</head>
@@ -1277,8 +1283,219 @@ if (!empty($_GET['ajax'])) {
loadRecords();
});
function escapeHtml(str) {
return String(str || '')
.replace(/&/g, '&amp;')
.replace(/</g, '&lt;')
.replace(/>/g, '&gt;')
.replace(/"/g, '&quot;')
.replace(/'/g, '&#039;');
}
function getFileExt(filename) {
const parts = String(filename || '').split('.');
return parts.length > 1 ? parts.pop().toLowerCase() : '';
}
function isImageExt(ext) {
return ['jpg', 'jpeg', 'png', 'gif', 'bmp', 'webp', 'heic', 'heif'].includes(ext);
}
function getFileIcon(ext) {
if (isImageExt(ext)) return '🖼️';
if (ext === 'pdf') return '📕';
if (['doc', 'docx'].includes(ext)) return '📘';
return '📎';
}
function getFileBadge(ext) {
if (isImageExt(ext)) return '<span style="background:#cff4fc;color:#055160;padding:3px 8px;border-radius:999px;font-size:0.78rem;font-weight:700;">Immagine</span>';
if (ext === 'pdf') return '<span style="background:#f8d7da;color:#842029;padding:3px 8px;border-radius:999px;font-size:0.78rem;font-weight:700;">PDF</span>';
if (['doc', 'docx'].includes(ext)) return '<span style="background:#cfe2ff;color:#084298;padding:3px 8px;border-radius:999px;font-size:0.78rem;font-weight:700;">DOC</span>';
return '<span style="background:#e2e3e5;color:#41464b;padding:3px 8px;border-radius:999px;font-size:0.78rem;font-weight:700;">File</span>';
}
function openFilePreview(filePath, fileName) {
const ext = getFileExt(fileName);
$("#filePreviewTitle").text(fileName || 'Anteprima file');
let html = '';
if (isImageExt(ext)) {
html = `
<div style="width:100%; height:100%; min-height:82vh; display:flex; justify-content:center; align-items:center;">
<img src="${escapeHtml(filePath)}"
alt="${escapeHtml(fileName)}"
style="max-width:100%; max-height:82vh; border-radius:10px;">
</div>
`;
} else if (ext === 'pdf') {
html = `
<iframe src="${escapeHtml(filePath)}#zoom=page-width"
style="display:block; width:100%; height:calc(92vh - 64px); border:none; background:#fff;">
</iframe>
`;
} else {
html = `
<div style="text-align:center; padding:40px 20px;">
<div style="font-size:3rem; margin-bottom:12px;">${getFileIcon(ext)}</div>
<div style="color:#475569; margin-bottom:16px;">Anteprima non disponibile per questo formato</div>
<a href="${escapeHtml(filePath)}" target="_blank"
style="display:inline-block; padding:10px 18px; border-radius:10px; text-decoration:none; background:#0d6efd; color:#fff; font-weight:600;">
Apri file
</a>
</div>
`;
}
$("#filePreviewContainer").html(html);
$("#filePreviewModal").addClass("active");
}
function loadMatriceAttachments(matriceId, matriceNome) {
$("#mf_matrice_name").text(matriceNome || '');
$("#matriceFilesList").html('<div style="color:#64748b;">Caricamento file...</div>');
$.getJSON("get_matrice_attachments.php", {
id: matriceId
}, function(r) {
if (!r.success) {
$("#matriceFilesList").html('<div style="color:#b91c1c;">Errore nel caricamento degli allegati.</div>');
return;
}
const files = r.attachments || [];
if (!files.length) {
$("#matriceFilesList").html('<div style="color:#64748b;">Nessun allegato disponibile per questa matrice.</div>');
return;
}
let html = '';
files.forEach(f => {
const fileName = f.file_name || '';
const filePath = f.file_url || f.file_path || '';
const desc = f.description || '';
const createdAt = f.created_at || '';
const ext = getFileExt(fileName);
const icon = getFileIcon(ext);
const badge = getFileBadge(ext);
let actionHtml = '';
if (isImageExt(ext) || ext === 'pdf') {
actionHtml = `
<button type="button"
class="open-matrice-file-preview"
data-file="${escapeHtml(filePath)}"
data-name="${escapeHtml(fileName)}"
style="padding:8px 14px; border-radius:10px; border:none; background:#0d6efd; color:#fff; font-weight:600; cursor:pointer;">
Apri
</button>
`;
} else {
actionHtml = `
<a href="${escapeHtml(filePath)}" target="_blank"
style="display:inline-block; padding:8px 14px; border-radius:10px; text-decoration:none; background:#0d6efd; color:#fff; font-weight:600;">
Apri
</a>
`;
}
let previewHtml = '';
if (isImageExt(ext)) {
previewHtml = `
<img src="${escapeHtml(filePath)}"
alt="${escapeHtml(fileName)}"
style="width:70px; height:70px; object-fit:cover; border-radius:10px; border:1px solid #dbe2ea;">
`;
} else {
previewHtml = `
<div style="width:70px; height:70px; border-radius:10px; background:#f1f5f9; display:flex; align-items:center; justify-content:center; font-size:1.8rem; border:1px solid #dbe2ea;">
${icon}
</div>
`;
}
html += `
<div style="border:1px solid #e2e8f0; border-radius:14px; padding:12px; background:#fff;">
<div style="display:flex; gap:14px; align-items:flex-start;">
<div>${previewHtml}</div>
<div style="flex:1;">
<div style="display:flex; justify-content:space-between; align-items:flex-start; gap:12px;">
<div>
<div style="font-weight:700; color:#1f2d3d;">${escapeHtml(fileName)}</div>
<div style="margin-top:4px;">${badge}</div>
${createdAt ? `<div style="margin-top:6px; color:#64748b; font-size:0.88rem;">${escapeHtml(createdAt)}</div>` : ''}
</div>
<div>${actionHtml}</div>
</div>
<div style="margin-top:10px; color:#475569; white-space:normal;">
${desc ? escapeHtml(desc) : '<em style="color:#94a3b8;">Nessuna descrizione</em>'}
</div>
</div>
</div>
</div>
`;
});
$("#matriceFilesList").html(html);
}).fail(function() {
$("#matriceFilesList").html('<div style="color:#b91c1c;">Errore di comunicazione col server.</div>');
});
}
$(document).on("click", ".show-matrice-files", function(e) {
e.stopPropagation();
const matriceId = $(this).data("matrice-id");
const matriceNome = $(this).data("matrice-nome") || "";
if (!matriceId) {
alert("Nessuna matrice associata a questo record.");
return;
}
loadMatriceAttachments(matriceId, matriceNome);
$("#matriceFilesModal").addClass("active");
});
$(document).on("click", "#closeMatriceFilesModal", function() {
$("#matriceFilesModal").removeClass("active");
});
$(document).on("click", "#matriceFilesModal", function(e) {
if ($(e.target).is("#matriceFilesModal")) {
$("#matriceFilesModal").removeClass("active");
}
});
$(document).on("click", ".open-matrice-file-preview", function(e) {
e.stopPropagation();
const file = $(this).data("file") || "";
const name = $(this).data("name") || "Anteprima file";
openFilePreview(file, name);
});
$(document).on("click", "#closeFilePreviewModal", function() {
$("#filePreviewModal").removeClass("active");
$("#filePreviewContainer").html("");
});
$(document).on("click", "#filePreviewModal", function(e) {
if ($(e.target).is("#filePreviewModal")) {
$("#filePreviewModal").removeClass("active");
$("#filePreviewContainer").html("");
}
});
$(document).on("click", "#filePreviewModal .modal-content", function(e) {
e.stopPropagation();
});
// --- CARICA RECORD ---
function loadRecords() {
@@ -1879,12 +2096,45 @@ if (!empty($_GET['ajax'])) {
});
</script>
<!-- MODALE ALLEGATI MATRICE (SOLO LETTURA) -->
<div id="matriceFilesModal" class="modal">
<div class="modal-content" style="width:95%; max-width:1100px; max-height:88vh; overflow:hidden; padding:0; border-radius:16px;">
</body>
<div style="background:#b9ebc7; padding:1rem 1.4rem; display:flex; justify-content:space-between; align-items:center;">
<div>
<h3 style="margin:0; color:#1f2d3d;">File correlati matrice</h3>
<div id="mf_matrice_name" style="font-size:0.95rem; color:#475569; margin-top:4px;"></div>
</div>
</html>
<button type="button" id="closeMatriceFilesModal"
style="font-size:1.9rem; line-height:1; background:none; border:none; cursor:pointer; color:#1f2d3d;">
&times;
</button>
</div>
<div style="padding:1.2rem 1.4rem; overflow-y:auto;">
<div id="matriceFilesList" style="display:flex; flex-direction:column; gap:12px;">
<div style="color:#64748b;">Caricamento file...</div>
</div>
</div>
</div>
</div>
<!-- MODALE PREVIEW FILE -->
<div id="filePreviewModal" class="modal">
<div class="modal-content" style="background:#fff; max-width:1400px; width:98%; height:92vh; padding:0; overflow:hidden; text-align:left;">
<div style="background:#b9ebc7; padding:0.9rem 1.2rem; display:flex; justify-content:space-between; align-items:center;">
<div id="filePreviewTitle" style="font-weight:700; color:#1f2d3d;">Anteprima file</div>
<button type="button" id="closeFilePreviewModal"
style="font-size:1.9rem; line-height:1; background:none; border:none; cursor:pointer; color:#1f2d3d;">
&times;
</button>
</div>
<div id="filePreviewContainer"
style="padding:0; background:#f8fafc; height:calc(92vh - 64px); overflow:hidden;">
</div>
</div>
</div>
</body>
</html>