diff --git a/db/migrations/20261019075739_add_is_strumento_is_ciclo_to_matrice_attachments.php b/db/migrations/20261019075739_add_is_strumento_is_ciclo_to_matrice_attachments.php
new file mode 100644
index 00000000..0c267d1b
--- /dev/null
+++ b/db/migrations/20261019075739_add_is_strumento_is_ciclo_to_matrice_attachments.php
@@ -0,0 +1,24 @@
+table('matrice_attachments')
+ ->addColumn('is_strumento', 'boolean', [
+ 'default' => false,
+ 'null' => false,
+ 'after' => 'is_disegno',
+ ])
+ ->addColumn('is_ciclo', 'boolean', [
+ 'default' => false,
+ 'null' => false,
+ 'after' => 'is_strumento',
+ ])
+ ->update();
+ }
+}
diff --git a/public/userarea/assets/js/worksheets-linked-modals.js b/public/userarea/assets/js/worksheets-linked-modals.js
index ab15de7b..88eab707 100644
--- a/public/userarea/assets/js/worksheets-linked-modals.js
+++ b/public/userarea/assets/js/worksheets-linked-modals.js
@@ -130,7 +130,40 @@
});
};
- let wsDisegniList = [];
+ // ================================================================
+ // Tab allegati della matrice: disegni tecnici, strumenti, cicli
+ // ================================================================
+ const WS_ATT_KINDS = {
+ disegni: {
+ flag: "is_disegno",
+ label: "Disegni tecnici",
+ icon: "π",
+ itemLabel: "Disegno",
+ empty:
+ "Nessun disegno tecnico per questo profilo. " +
+ "Si possono segnare dalla gestione matrici (graffetta β pulsante compasso).",
+ },
+ strumenti: {
+ flag: "is_strumento",
+ label: "Strumenti di lavoro",
+ icon: "π§",
+ itemLabel: "Strumento",
+ empty:
+ "Nessuno strumento di lavoro per questo profilo. " +
+ "Si possono segnare dalla gestione matrici (graffetta β pulsante chiave inglese).",
+ },
+ cicli: {
+ flag: "is_ciclo",
+ label: "Cicli di lavoro",
+ icon: "π",
+ itemLabel: "Ciclo",
+ empty:
+ "Nessun ciclo di lavoro per questo profilo. " +
+ "Si possono segnare dalla gestione matrici (graffetta β pulsante frecce).",
+ },
+ };
+
+ let wsAttLists = { disegni: [], strumenti: [], cicli: [] };
function wsFileExt(name) {
const p = String(name || "").split(".");
@@ -141,12 +174,15 @@
return ["jpg", "jpeg", "png", "gif", "bmp", "webp"].includes(ext);
}
- function showWorksheetDisegno(index) {
- const f = wsDisegniList[index];
+ function showWorksheetAttachment(kind, index) {
+ const list = wsAttLists[kind] || [];
+ const f = list[index];
if (!f) return;
- $(".ws-disegno-item").removeClass("active");
- $(`.ws-disegno-item[data-index="${index}"]`).addClass("active");
+ $(`.ws-disegno-item[data-kind="${kind}"]`).removeClass("active");
+ $(
+ `.ws-disegno-item[data-kind="${kind}"][data-index="${index}"]`,
+ ).addClass("active");
const name = f.file_name || "";
const path = f.file_url || f.file_path || "";
@@ -161,7 +197,7 @@
viewer = `
Anteprima non disponibile per questo formato: usa "Apri in nuova scheda"
`;
}
- $("#wsDisegnoToolbar").html(`
+ $(`#wsToolbar_${kind}`).html(`
${escapeHtml(name)}
${f.description ? `
${escapeHtml(f.description)}
` : ""}
@@ -170,18 +206,59 @@
Apri in nuova scheda
`);
- $("#wsDisegnoViewer").html(viewer);
+ $(`#wsViewer_${kind}`).html(viewer);
}
- function loadWorksheetDisegni(idmatrice) {
- wsDisegniList = [];
- const $c = $("#wsDisegniContainer");
+ function renderWorksheetAttachmentKind(kind) {
+ const cfg = WS_ATT_KINDS[kind];
+ const list = wsAttLists[kind];
+ const $c = $(`#wsContainer_${kind}`);
+
+ $(`#wsCount_${kind}`).text(list.length);
+
+ if (!list.length) {
+ $c.html(
+ `
${escapeHtml(cfg.empty)}
`,
+ );
+ return;
+ }
+
+ let listHtml = "";
+ if (list.length > 1) {
+ listHtml =
+ '
' +
+ list
+ .map(
+ (f, i) =>
+ ``,
+ )
+ .join("") +
+ "
";
+ }
+
+ $c.html(`
+ ${listHtml}
+
+
+ `);
+
+ // Se l'utente ha giΓ aperto il tab mentre caricava, mostro subito il primo
+ if ($(`.ws-tab[data-tab="${kind}"]`).hasClass("active")) {
+ showWorksheetAttachment(kind, 0);
+ }
+ }
+
+ function loadWorksheetAttachments(idmatrice) {
+ wsAttLists = { disegni: [], strumenti: [], cicli: [] };
+ const kinds = Object.keys(WS_ATT_KINDS);
if (!idmatrice) {
- $("#wsDisegniCount").text("0");
- $c.html(
- '
Nessun profilo collegato a questo foglio.
',
- );
+ kinds.forEach((k) => {
+ $(`#wsCount_${k}`).text("0");
+ $(`#wsContainer_${k}`).html(
+ '
Nessun profilo collegato a questo foglio.
',
+ );
+ });
return;
}
@@ -193,50 +270,25 @@
data.message || "Errore caricamento allegati",
);
- wsDisegniList = (data.attachments || []).filter(
- (a) => parseInt(a.is_disegno, 10) === 1,
- );
- $("#wsDisegniCount").text(wsDisegniList.length);
+ const all = data.attachments || [];
- if (!wsDisegniList.length) {
- $c.html(
- '
Nessun disegno tecnico per questo profilo. ' +
- "Si possono segnare dalla gestione matrici (graffetta β pulsante compasso).
",
+ kinds.forEach((k) => {
+ const flag = WS_ATT_KINDS[k].flag;
+ wsAttLists[k] = all.filter(
+ (a) => parseInt(a[flag], 10) === 1,
);
- return;
- }
-
- let listHtml = "";
- if (wsDisegniList.length > 1) {
- listHtml =
- '
' +
- wsDisegniList
- .map(
- (f, i) =>
- ``,
- )
- .join("") +
- "
";
- }
-
- $c.html(`
- ${listHtml}
-
-
- `);
-
- // Se l'utente ha giΓ aperto il tab mentre caricava, mostro subito il primo
- if ($('.ws-tab[data-tab="disegni"]').hasClass("active")) {
- showWorksheetDisegno(0);
- }
+ renderWorksheetAttachmentKind(k);
+ });
})
.catch((err) => {
- $("#wsDisegniCount").text("!");
- $c.html(
- '
Errore nel caricamento dei disegni: ' +
- escapeHtml(err.message || "") +
- "
",
- );
+ kinds.forEach((k) => {
+ $(`#wsCount_${k}`).text("!");
+ $(`#wsContainer_${k}`).html(
+ '
Errore nel caricamento degli allegati: ' +
+ escapeHtml(err.message || "") +
+ "
",
+ );
+ });
});
}
@@ -437,6 +489,28 @@
`;
+ const attTabsHtml = Object.keys(WS_ATT_KINDS)
+ .map((k) => {
+ const c = WS_ATT_KINDS[k];
+ return `
+ `;
+ })
+ .join("");
+
+ const attPanesHtml = Object.keys(WS_ATT_KINDS)
+ .map((k) => {
+ const c = WS_ATT_KINDS[k];
+ return `
+
+
+
Caricamento ${escapeHtml(c.label.toLowerCase())}...
+
+
`;
+ })
+ .join("");
+
const fullHtml = `
${headerHtml}
@@ -444,24 +518,18 @@
-
+ ${attTabsHtml}
${html}
-
-
-
Caricamento disegni tecnici...
-
-
+ ${attPanesHtml}
`;
$("#worksheetDetailContainer").html(fullHtml);
- loadWorksheetDisegni(ws.idmatrice);
+ loadWorksheetAttachments(ws.idmatrice);
})
.catch((err) => {
console.error("Catch loadMatriceWorksheets:", err);
@@ -495,18 +563,21 @@
$(".ws-tab-pane").removeClass("active");
$(`.ws-tab-pane[data-pane="${tab}"]`).addClass("active");
- // Carico il PDF solo la prima volta che si apre il tab
+ // Carico il file solo la prima volta che si apre il tab
if (
- tab === "disegni" &&
- wsDisegniList.length &&
- $("#wsDisegnoViewer").is(":empty")
+ WS_ATT_KINDS[tab] &&
+ (wsAttLists[tab] || []).length &&
+ $(`#wsViewer_${tab}`).is(":empty")
) {
- showWorksheetDisegno(0);
+ showWorksheetAttachment(tab, 0);
}
});
$(document).on("click", ".ws-disegno-item", function () {
- showWorksheetDisegno(parseInt($(this).data("index"), 10));
+ showWorksheetAttachment(
+ $(this).data("kind"),
+ parseInt($(this).data("index"), 10),
+ );
});
$(document).on("click", ".open-worksheet-detail", function () {
diff --git a/public/userarea/get_matrice_attachments.php b/public/userarea/get_matrice_attachments.php
index 1f21ddb0..0129440a 100644
--- a/public/userarea/get_matrice_attachments.php
+++ b/public/userarea/get_matrice_attachments.php
@@ -28,6 +28,8 @@ try {
description,
sort_order,
is_disegno,
+ is_strumento,
+ is_ciclo,
created_at,
updated_at
FROM matrice_attachments
@@ -52,6 +54,8 @@ try {
'description' => $row['description'] ?? '',
'sort_order' => (int)($row['sort_order'] ?? 0),
'is_disegno' => (int)($row['is_disegno'] ?? 0),
+ 'is_strumento' => (int)($row['is_strumento'] ?? 0),
+ 'is_ciclo' => (int)($row['is_ciclo'] ?? 0),
'created_at' => !empty($row['created_at']) ? date('d/m/Y H:i', strtotime($row['created_at'])) : '',
'updated_at' => !empty($row['updated_at']) ? date('d/m/Y H:i', strtotime($row['updated_at'])) : ''
];
diff --git a/public/userarea/include/worksheets-linked-modals.php b/public/userarea/include/worksheets-linked-modals.php
index 7718274b..792c58fd 100644
--- a/public/userarea/include/worksheets-linked-modals.php
+++ b/public/userarea/include/worksheets-linked-modals.php
@@ -27,6 +27,14 @@
background: #6f42c1;
}
+ .ws-tab[data-tab="strumenti"].active {
+ background: #fd7e14;
+ }
+
+ .ws-tab[data-tab="cicli"].active {
+ background: #0f9d77;
+ }
+
.ws-tab-count {
display: inline-block;
min-width: 24px;
@@ -67,6 +75,26 @@
color: #fff;
}
+ .ws-disegno-item[data-kind="strumenti"] {
+ border-color: #fd7e14;
+ color: #fd7e14;
+ }
+
+ .ws-disegno-item[data-kind="strumenti"].active {
+ background: #fd7e14;
+ color: #fff;
+ }
+
+ .ws-disegno-item[data-kind="cicli"] {
+ border-color: #0f9d77;
+ color: #0f9d77;
+ }
+
+ .ws-disegno-item[data-kind="cicli"].active {
+ background: #0f9d77;
+ color: #fff;
+ }
+
.ws-disegno-toolbar {
display: flex;
justify-content: space-between;
diff --git a/public/userarea/matrici.php b/public/userarea/matrici.php
index ec3776ef..ad6d9db4 100644
--- a/public/userarea/matrici.php
+++ b/public/userarea/matrici.php
@@ -577,6 +577,60 @@ function revisionLabel($rev)
background: #6f42c1;
color: #fff;
}
+
+ .attachments-existing-list .attachment-existing-row.is-ciclo:not(.is-disegno) {
+ border: 2px solid #0f9d77;
+ background: #effaf6;
+ }
+
+ .attachments-existing-list .attachment-existing-row.is-strumento:not(.is-disegno):not(.is-ciclo) {
+ border: 2px solid #fd7e14;
+ background: #fff6ee;
+ }
+
+ .badge-strumento,
+ .badge-ciclo {
+ display: inline-flex;
+ align-items: center;
+ gap: 5px;
+ color: #fff;
+ font-size: .78rem;
+ font-weight: 700;
+ padding: 4px 9px;
+ border-radius: 999px;
+ margin-left: 6px;
+ vertical-align: middle;
+ }
+
+ .badge-strumento {
+ background: #fd7e14;
+ }
+
+ .badge-ciclo {
+ background: #0f9d77;
+ }
+
+ .btn-toggle-strumento {
+ border-color: #fd7e14;
+ color: #fd7e14;
+ }
+
+ .btn-toggle-strumento:hover,
+ .btn-toggle-strumento.active {
+ background: #fd7e14;
+ color: #fff;
+ }
+
+ .btn-toggle-ciclo {
+ border-color: #0f9d77;
+ color: #0f9d77;
+ }
+
+ .btn-toggle-ciclo:hover,
+ .btn-toggle-ciclo.active {
+ background: #0f9d77;
+ color: #fff;
+ }
@@ -1175,9 +1229,11 @@ function revisionLabel($rev)
return;
}
- const list = (data.attachments || []).sort((a, b) =>
- (parseInt(b.is_disegno, 10) || 0) - (parseInt(a.is_disegno, 10) || 0)
- );
+ const flagScore = x =>
+ (parseInt(x.is_disegno, 10) || 0) * 4 +
+ (parseInt(x.is_ciclo, 10) || 0) * 2 +
+ (parseInt(x.is_strumento, 10) || 0);
+ const list = (data.attachments || []).sort((a, b) => flagScore(b) - flagScore(a));
const container = $("#existingAttachmentsList");
container.empty();
@@ -1196,6 +1252,8 @@ function revisionLabel($rev)
const createdAt = item.created_at || '';
const id = item.id || 0;
const isDisegno = (parseInt(item.is_disegno, 10) || 0) === 1;
+ const isStrumento = (parseInt(item.is_strumento, 10) || 0) === 1;
+ const isCiclo = (parseInt(item.is_ciclo, 10) || 0) === 1;
const previewHtml = isImageExt(ext) && filePath ?
`
` :
@@ -1221,7 +1279,7 @@ function revisionLabel($rev)
}
const html = `
-
+
${previewHtml}
@@ -1230,7 +1288,9 @@ function revisionLabel($rev)
${escapeHtml(fileName)}
- ${isDisegno ? ' Disegno tecnico' : ''}
+ ${isDisegno ? ' Disegno tecnico' : ''}
+ ${isStrumento ? ' Strumento di lavoro' : ''}
+ ${isCiclo ? ' Ciclo di lavoro' : ''}
${badge} ${createdAt ? ' β’ ' + escapeHtml(createdAt) : ''}
@@ -1241,9 +1301,25 @@ function revisionLabel($rev)
class="btn btn-sm btn-toggle-disegno toggle-disegno ${isDisegno ? 'active' : ''}"
data-id="${id}"
data-value="${isDisegno ? 1 : 0}"
- title="${isDisegno ? 'Togli da disegni tecnici' : 'Segna come disegno tecnico'}">
+ title="${isDisegno ? 'Togli da disegni tecnici' : 'Segna come disegno tecnico'}">
+
+
@@ -1820,6 +1896,55 @@ function revisionLabel($rev)
});
});
+ $(document).on("click", ".toggle-flag", function() {
+ const $btn = $(this);
+ const id = $btn.data("id");
+ const field = $btn.data("field");
+ const newValue = parseInt($btn.data("value"), 10) === 1 ? 0 : 1;
+ const idmatrice = $("#mf_idmatrice").val();
+
+ $btn.prop("disabled", true);
+
+ fetch("toggle_matrice_attachment_disegno.php", {
+ method: "POST",
+ headers: {
+ "Content-Type": "application/x-www-form-urlencoded"
+ },
+ body: "id=" + encodeURIComponent(id) +
+ "&field=" + encodeURIComponent(field) +
+ "&value=" + newValue
+ })
+ .then(r => r.json())
+ .then(data => {
+ if (!data.success) {
+ Swal.fire({
+ icon: "error",
+ title: "Errore",
+ text: data.message || ""
+ });
+ $btn.prop("disabled", false);
+ return;
+ }
+ Swal.fire({
+ toast: true,
+ position: "top-end",
+ icon: "success",
+ title: data.message,
+ showConfirmButton: false,
+ timer: 1500
+ });
+ loadExistingAttachments(idmatrice);
+ })
+ .catch(() => {
+ Swal.fire({
+ icon: "error",
+ title: "Errore",
+ text: "Errore di comunicazione con il server"
+ });
+ $btn.prop("disabled", false);
+ });
+ });
+
$(document).on("click", ".preview-existing-file", function() {
const file = $(this).data("file") || "";
const name = $(this).data("name") || "Anteprima file";
diff --git a/public/userarea/production_pause_reasons.php b/public/userarea/production_pause_reasons.php
index 598bf8fb..2de06a3d 100644
--- a/public/userarea/production_pause_reasons.php
+++ b/public/userarea/production_pause_reasons.php
@@ -241,7 +241,7 @@
-
+
-
@@ -298,11 +359,15 @@
-
+