import { qsThrowIfNotExists, convertDataToSingleLine } from "../utils"; import * as bootstrap from "bootstrap"; import { parse as parseCsv } from "csv-parse/browser/esm/sync"; export function getMessageStorageKey(project: string) { return `project${project}-messages`; } export type Messages = { [key: string]: string }; export function getMessagesByStorage(projectName: string) { const csv = getMessagesCSVByStorage(projectName); if (csv == null) return undefined; const messages: Messages = {}; ( parseCsv(csv, { encoding: "utf8", delimiter: "\t", }) as [string, string, string][] ).forEach((row, index) => { if (!row[1]) { console.warn(`${index + 1}行目のメッセージに値が無いためスキップします`); return; } if (messages[row[1]] != null) { console.error(`${row[1]} のメッセージが重複しています`); return; } messages[row[1]] = row[2]; }); return messages; } export function getMessagesCSVByStorage(projectName: string) { const messagesText = window.localStorage.getItem(getMessageStorageKey(projectName)); const messagesData: string[] = []; if (messagesText == null) return undefined; const messages = messagesText.split(", "); messages.map((message) => { const messagesString = message.split("\t"); const seri: string = messagesString[0]; const id: string = messagesString[1]; const messages: string = messagesString.slice(2).join(" ").replace(/"/g, `""`); const messagesStrings = [seri, id, `"${messages}"`].join("\t"); messagesData.push(messagesStrings); }); return messagesData.join("\n"); } export function initMessageEditor({ onMessageChanged }: { onMessageChanged?: () => void }) { const messageEditer = qsThrowIfNotExists(document, "#messageEditer"); const addRowButton = qsThrowIfNotExists(document, "#addMessageRowButton"); const deleteRowsButton = qsThrowIfNotExists(document, "#deleteMessageRowsButton"); const projectSelect = qsThrowIfNotExists(document, "#projectSelect"); const messageEditerModal = qsThrowIfNotExists(document, "#messageEditerModal"); const modal = new bootstrap.Modal(messageEditerModal); const messageTableBody = qsThrowIfNotExists(document, "#messageTable tbody"); if (!messageTableBody) { console.error("Table body element not found"); return; } messageEditer.addEventListener("click", () => { const projectName = projectSelect.options[projectSelect.selectedIndex].value; const savedData = localStorage.getItem(getMessageStorageKey(projectName)); messageTableBody.innerHTML = ""; if (savedData) { const rows = savedData.split(", "); rows.forEach((rowData) => { const columns = rowData.split("\t"); const row = createTableRow(); const cells = row.getElementsByTagName("td"); for (let i = 0; i < 3; i++) { const cell = cells[i]; cell.innerHTML = i === 2 ? columns.slice(2).join(" ") : columns[i]; } messageTableBody.appendChild(row); }); } modal.show(); }); function createTableRow(): HTMLTableRowElement { const row = document.createElement("tr"); for (let i = 0; i < 3; i++) { const cell = document.createElement("td"); cell.setAttribute("contenteditable", "plaintext-only"); row.appendChild(cell); } const checkboxCell = document.createElement("td"); const checkbox = document.createElement("input"); checkbox.type = "checkbox"; checkbox.classList.add("row-checkbox"); checkboxCell.appendChild(checkbox); row.appendChild(checkboxCell); return row; } const saveButton = document.querySelector("#messageEditerModal button[type='submit']"); saveButton?.addEventListener("click", async (event) => { event.preventDefault(); await saveTableDataToLocalStorage(); modal.hide(); }); addRowButton.addEventListener("click", (event) => { event.preventDefault(); const table = qsThrowIfNotExists(document, "#messageTable tbody"); const lastRow = table.rows[table.rows.length - 1]; const lastIdCell = lastRow ? lastRow.cells[0] : null; const lastId = lastIdCell ? parseInt(lastIdCell.textContent ?? "0") : 0; const newRow = document.createElement("tr"); newRow.innerHTML = ` ${lastId + 1} `; table.appendChild(newRow); }); deleteRowsButton.addEventListener("click", (event) => { event.preventDefault(); const checkboxes = document.querySelectorAll(".row-checkbox:checked"); checkboxes.forEach((checkbox) => { const row = checkbox.closest("tr"); if (row) { row.remove(); } }); }); function saveTableDataToLocalStorage() { const tableData: string[] = []; const rows = messageTableBody.getElementsByTagName("tr"); const projectName = projectSelect.options[projectSelect.selectedIndex].value; for (let i = 0; i < rows.length; i++) { const row = rows[i]; const cells = row.getElementsByTagName("td"); const rowData: string[] = []; for (let j = 0; j < 3; j++) { const cell = cells[j]; let cellContent = cell.textContent ?? ""; if (j !== 2) { cellContent = convertDataToSingleLine(cell.textContent ?? ""); } rowData.push(cellContent); } tableData.push(rowData.join("\t")); } localStorage.setItem(getMessageStorageKey(projectName), tableData.join(", ")); if (onMessageChanged) { onMessageChanged(); } } }