adjust delete log
This commit is contained in:
parent
5c12dcf950
commit
063f96c19d
|
|
@ -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(
|
||||||
|
|
@ -354,27 +341,31 @@
|
||||||
section.className = "command-section";
|
section.className = "command-section";
|
||||||
section.id = `section-${cmd}`;
|
section.id = `section-${cmd}`;
|
||||||
section.innerHTML = `
|
section.innerHTML = `
|
||||||
<h3>
|
<h3>
|
||||||
${"show " + cmd} (${data.length})
|
${"show " + cmd} (${data.length})
|
||||||
<div>
|
<div>
|
||||||
<button class="next-btn" id="btn-prev-${cmd}">Previous</button>
|
<button class="next-btn" id="btn-prev-${cmd}">Previous</button>
|
||||||
<span id="page-info-${cmd}">Output 1/${data.length}</span>
|
<span id="page-info-${cmd}">Output 1/${data.length}</span>
|
||||||
<button class="next-btn" id="btn-next-${cmd}">Next</button>
|
<button class="next-btn" id="btn-next-${cmd}">Next</button>
|
||||||
</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)
|
||||||
}" id="log-${cmd}">
|
? "soft-deleted"
|
||||||
${
|
: ""
|
||||||
currentVerUser
|
}" id="log-${cmd}">
|
||||||
? ""
|
${
|
||||||
: data[0].is_deleted
|
currentVerUser
|
||||||
? `<button type="button" class="secondary-btn cancel-trash-btn" title="Cancel soft delete">✖️</button>`
|
? ""
|
||||||
: `<button type="button" class="danger-btn trash-btn" title="Soft delete">🗑</button>`
|
: deletedLogs.some(
|
||||||
}
|
(item) => item.id === data[0].id,
|
||||||
<b>${data[0].filename}</b>\n${data[0].output}
|
)
|
||||||
</div>
|
? `<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><br>${data[0].output}
|
||||||
|
</div>
|
||||||
|
`;
|
||||||
|
|
||||||
logSections.appendChild(section);
|
logSections.appendChild(section);
|
||||||
|
|
||||||
|
|
@ -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,12 +583,12 @@ ${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 />
|
||||||
<strong>${pid} - ${version}</strong>
|
<strong>${pid} - ${version}</strong>
|
||||||
`;
|
`;
|
||||||
|
|
||||||
deviceConfirmModal.classList.remove("hidden");
|
deviceConfirmModal.classList.remove("hidden");
|
||||||
});
|
});
|
||||||
|
|
|
||||||
84
server.js
84
server.js
|
|
@ -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 = [
|
||||||
for (const table of tables) {
|
"inventory",
|
||||||
await db.query(
|
"version",
|
||||||
`DELETE FROM ${table} WHERE device_id = ? AND is_deleted = TRUE`,
|
"license",
|
||||||
[deviceId],
|
"logging",
|
||||||
|
];
|
||||||
|
if (!allowedCommands.includes(command)) continue;
|
||||||
|
|
||||||
|
const [rows] = await db.query(
|
||||||
|
`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(
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue