adjust delete log

This commit is contained in:
dbdbd9 2025-07-28 14:35:54 +07:00
parent 5c12dcf950
commit 063f96c19d
2 changed files with 125 additions and 230 deletions

View File

@ -94,20 +94,6 @@
</div> </div>
<div id="logSections"></div> <div id="logSections"></div>
<div id="logDeleteModal" class="modal hidden">
<div style="max-width: 30%" class="modal-content">
<div id="deleteLogText"></div>
<div class="modal-actions">
<button id="logCancelDeleteBtn" class="secondary-btn">
Cancel
</button>
<button id="logDeleteBtn" class="danger-btn">
Delete
</button>
</div>
</div>
</div>
<div id="deviceConfirmModal" class="modal hidden"> <div id="deviceConfirmModal" class="modal hidden">
<div style="max-width: 30%" class="modal-content"> <div style="max-width: 30%" class="modal-content">
<div id="deviceConfirmText"></div> <div id="deviceConfirmText"></div>
@ -298,6 +284,7 @@
versionList.addEventListener("change", () => { versionList.addEventListener("change", () => {
const pid = pidList.value; const pid = pidList.value;
const version = versionList.value; const version = versionList.value;
deletedLogs = [];
if (pid && version) { if (pid && version) {
// Set param pid, version to URL // Set param pid, version to URL
const currentParams = new URLSearchParams( const currentParams = new URLSearchParams(
@ -363,16 +350,20 @@
</div> </div>
</h3> </h3>
<div class="log-block ${ <div class="log-block ${
data[0].is_deleted ? "soft-deleted" : "" deletedLogs.some((item) => item.id === data[0].id)
? "soft-deleted"
: ""
}" id="log-${cmd}"> }" id="log-${cmd}">
${ ${
currentVerUser currentVerUser
? "" ? ""
: data[0].is_deleted : deletedLogs.some(
? `<button type="button" class="secondary-btn cancel-trash-btn" title="Cancel soft delete">✖️</button>` (item) => item.id === data[0].id,
: `<button type="button" class="danger-btn trash-btn" title="Soft delete">🗑</button>` )
? `<button type="button" class="secondary-btn cancel-trash-btn" title="Remove from delete list">✖️</button>`
: `<button type="button" class="danger-btn trash-btn" title="Add to delete list">🗑</button>`
} }
<b>${data[0].filename}</b>\n${data[0].output} <b>${data[0].filename}</b><br>${data[0].output}
</div> </div>
`; `;
@ -382,29 +373,7 @@
const updateDisplay = () => { const updateDisplay = () => {
const info = logsCache[`${pid}_${version}`][cmd]; const info = logsCache[`${pid}_${version}`][cmd];
const curr = info.logs[info.index]; const curr = info.logs[info.index];
updateDisplayActionDelete(curr, cmd, version);
const logBlock = document.getElementById(`log-${cmd}`);
logBlock.className = `log-block ${
curr.is_deleted ? "soft-deleted" : ""
}`;
const currentVerUser = versionsUser.find(
(verItem) => verItem.version === version,
);
if (!currentVerUser) {
if (curr.is_deleted) {
logBlock.innerHTML = `
<button type="button" class="secondary-btn cancel-trash-btn" title="Cancel soft delete">✖️</button>
<b>${curr.filename}</b>\n${curr.output}
`;
} else {
logBlock.innerHTML = `
<button type="button" class="danger-btn trash-btn" title="Soft delete">🗑</button>
<b>${curr.filename}</b>\n${curr.output}
`;
}
}
document.getElementById( document.getElementById(
`page-info-${cmd}`, `page-info-${cmd}`,
@ -437,6 +406,73 @@
loadPIDs(pidParam, versionParam); loadPIDs(pidParam, versionParam);
// Handle delete and cancel
document.addEventListener("click", async (e) => {
const pid = pidList.value;
const version = versionList.value;
if (!pid || !version) return;
// Find command section
const section = e.target.closest(".command-section");
if (!section) return;
const command = section.id.replace("section-", "");
const info = logsCache[`${pid}_${version}`][command];
const index = info.index;
const log = info.logs[index];
const isDeleted = deletedLogs.some(
(item) => item.id === log.id,
);
// Add to delete
if (e.target.classList.contains("trash-btn")) {
if (!isDeleted) {
deletedLogs.push({
id: log.id,
command: command,
});
updateDisplayActionDelete(log, command, version);
}
}
// Cancel add to delete
if (e.target.classList.contains("cancel-trash-btn")) {
deletedLogs = deletedLogs.filter(
(item) => item.id !== log.id,
);
updateDisplayActionDelete(log, command, version);
}
});
// Update UI delete and cancel button
const updateDisplayActionDelete = (log, command, version) => {
const logBlock = document.getElementById(`log-${command}`);
const isDeleted = deletedLogs.some(
(item) => item.id === log.id,
);
logBlock.className = `log-block ${
isDeleted ? "soft-deleted" : ""
}`;
const currentVerUser = versionsUser.find(
(verItem) => verItem.version === version,
);
if (!currentVerUser) {
logBlock.innerHTML = `
${
isDeleted
? `<button type="button" class="secondary-btn cancel-trash-btn" title="Remove from delete list">✖️</button>`
: `<button type="button" class="danger-btn trash-btn" title="Add to delete list">🗑</button>`
}
<b>${log.filename}</b>\n${log.output}
`;
}
};
const copyBtn = document.getElementById("copyBtn"); const copyBtn = document.getElementById("copyBtn");
const downloadBtn = document.getElementById("downloadBtn"); const downloadBtn = document.getElementById("downloadBtn");
@ -522,116 +558,6 @@ ${license}`.trim();
} }
</script> </script>
<!-- Handle soft delete log -->
<script>
let pendingDeleteLog = null;
const logDeleteModal = document.getElementById("logDeleteModal");
const logCancelDeleteBtn =
document.getElementById("logCancelDeleteBtn");
const logDeleteBtn = document.getElementById("logDeleteBtn");
document.addEventListener("click", async (e) => {
if (e.target.classList.contains("trash-btn")) {
const section = e.target.closest(".command-section");
const pid = pidList.value;
const version = versionList.value;
const command = section.id.replace("section-", "");
const index = logsCache[`${pid}_${version}`][command].index;
const log =
logsCache[`${pid}_${version}`][command].logs[index];
pendingDeleteLog = {
id: log.id,
command,
pid,
version,
is_deleted: true,
};
const text = `Are you sure you want to <strong>soft delete</strong> this log? <br /><code>${pid} - ${version} - ${command}</code> <br /> <div style="font-size: 12px; font-weight: 700" >${log.filename}</div>`;
document.getElementById("deleteLogText").innerHTML = text;
logDeleteBtn.innerHTML = "Delete";
showDeleteModal();
}
if (e.target.classList.contains("cancel-trash-btn")) {
const section = e.target.closest(".command-section");
const pid = pidList.value;
const version = versionList.value;
const command = section.id.replace("section-", "");
const index = logsCache[`${pid}_${version}`][command].index;
const log =
logsCache[`${pid}_${version}`][command].logs[index];
pendingDeleteLog = {
id: log.id,
command,
pid,
version,
is_deleted: false,
};
const text = `Are you sure you want to <strong>cancel soft delete</strong> this log? <br /><code>${pid} - ${version} - ${command}</code> <br /> <div style="font-size: 12px; font-weight: 700" >${log.filename}</div>`;
document.getElementById("deleteLogText").innerHTML = text;
logDeleteBtn.innerHTML = "Cancel Delete";
showDeleteModal();
}
});
function showDeleteModal() {
logDeleteModal.classList.remove("hidden");
}
function hideDeleteModal() {
logDeleteModal.classList.add("hidden");
pendingDeleteLog = null;
}
logCancelDeleteBtn.addEventListener("click", hideDeleteModal);
logDeleteBtn.addEventListener("click", async () => {
if (!pendingDeleteLog) return;
const token = localStorage.getItem("token");
try {
const res = await fetch("/api/soft-delete-log", {
method: "POST",
headers: {
"Content-Type": "application/json",
Authorization: `Bearer ${token}`,
},
body: JSON.stringify(pendingDeleteLog),
});
const data = await res.json();
if (data.success) {
alert(data.message || "Soft deleted successfully!");
location.reload();
} else {
alert(data.message || "Delete failed.");
}
} catch (err) {
console.error(err);
alert("Delete failed.");
} finally {
hideDeleteModal();
pendingDeleteLog = null;
}
});
function showToast(message = "Announce something") {
const toast = document.getElementById("logToast");
toast.textContent = message;
toast.classList.add("show");
toast.classList.remove("hidden");
setTimeout(() => {
toast.classList.remove("show");
toast.classList.add("hidden");
}, 2000);
}
</script>
<!-- Handle confirm device --> <!-- Handle confirm device -->
<script> <script>
const deviceConfirmBtn = const deviceConfirmBtn =
@ -646,6 +572,7 @@ ${license}`.trim();
document.getElementById("deviceConfirmText"); document.getElementById("deviceConfirmText");
let pendingDevice = null; let pendingDevice = null;
let deletedLogs = [];
deviceConfirmBtn.addEventListener("click", () => { deviceConfirmBtn.addEventListener("click", () => {
const pid = document.getElementById("pidList").value; const pid = document.getElementById("pidList").value;
@ -656,7 +583,7 @@ ${license}`.trim();
return; return;
} }
pendingDevice = { pid, version }; pendingDevice = { pid, version, deletedLogs };
deviceConfirmText.innerHTML = ` deviceConfirmText.innerHTML = `
Are you sure you want to <strong>save</strong> these changes?<br /> Are you sure you want to <strong>save</strong> these changes?<br />

View File

@ -226,54 +226,8 @@ app.get("/api/device/:pid/:version/:command", async (req, res) => {
res.json(logs); res.json(logs);
}); });
app.post("/api/soft-delete-log", authenticateToken, async (req, res) => {
const logId = req.body.id;
const logCommand = req.body.command;
const isDeleted = req.body.is_deleted;
try {
if (!logCommand || typeof logId !== "number") {
return res
.status(400)
.json({ success: false, message: "Invalid input." });
}
const [rows] = await db.query(
`SELECT id FROM \`${logCommand}_outputs\` WHERE id = ?`,
[logId],
);
if (rows.length === 0) {
return res.status(404).json({
success: false,
message: "Log not found.",
});
}
await db.query(
`UPDATE \`${logCommand}_outputs\` SET is_deleted = ? WHERE id = ?`,
[isDeleted, logId],
);
if (isDeleted) {
res.json({ success: true, message: "Soft deleted successfully!" });
} else {
res.json({
success: true,
message: "Cancel soft deleted successfully!",
});
}
} catch (error) {
console.error("Delete error:", error);
res.status(500).json({
success: false,
message: "Server error, please try again!",
});
}
});
app.post("/api/confirm-device", authenticateToken, async (req, res) => { app.post("/api/confirm-device", authenticateToken, async (req, res) => {
const { pid, version } = req.body; const { pid, version, deletedLogs } = req.body;
const updatedBy = req.user?.id; const updatedBy = req.user?.id;
if (!pid || !version) { if (!pid || !version) {
@ -297,7 +251,6 @@ app.post("/api/confirm-device", authenticateToken, async (req, res) => {
}); });
} }
const deviceId = rows[0].id;
if (rows[0].is_confirmed) { if (rows[0].is_confirmed) {
return res.status(400).json({ return res.status(400).json({
success: false, success: false,
@ -316,17 +269,32 @@ app.post("/api/confirm-device", authenticateToken, async (req, res) => {
); );
// Delete Log // Delete Log
const tables = [ for (const item of deletedLogs) {
"inventory_outputs", const { command, id } = item;
"version_outputs",
"license_outputs", if (!command || typeof id !== "number") continue;
"logging_outputs",
const allowedCommands = [
"inventory",
"version",
"license",
"logging",
]; ];
for (const table of tables) { if (!allowedCommands.includes(command)) continue;
await db.query(
`DELETE FROM ${table} WHERE device_id = ? AND is_deleted = TRUE`, const [rows] = await db.query(
[deviceId], `SELECT id FROM \`${command}_outputs\` WHERE id = ?`,
[id],
); );
if (rows.length === 0) {
continue;
}
// Delete log
await db.query(`DELETE FROM \`${command}_outputs\` WHERE id = ?`, [
id,
]);
} }
await db.query( await db.query(