import { qsThrowIfNotExists, getFlagsDataStorageKey, convertDataToSingleLine } from "../utils"; import * as bootstrap from "bootstrap"; export interface Flag { value: boolean; event?: string; vars?: string; } export function getFlagsByStorage(projectName: string) { const csv = getFlagsCSVByStorage(projectName); if (csv == null) return undefined; const rows = csv.split("\n"); return rows .map((row) => { const firstTab = row.indexOf("\t"); const secondTab = row.indexOf("\t", firstTab + 1); const thirdTab = row.indexOf("\t", secondTab + 1); return [ row.substring(0, firstTab), row.substring(firstTab + 1, secondTab), row.substring(secondTab + 1, thirdTab), row.substring(thirdTab + 1), ]; }) .map((row) => { return { value: row[1] === "TRUE", event: row[2] === "" ? undefined : row[2], vars: row[3] === "" ? undefined : row[3], } as Flag; }); } export function getFlagsCSVByStorage(projectName: string) { const savedData = localStorage.getItem(getFlagsDataStorageKey(projectName)); if (savedData == null) return undefined; return savedData; } export function initFlagEditor({ onFlagChanged }: { onFlagChanged?: () => void }) { const flagEditer = qsThrowIfNotExists(document, "#flagEditer"); const addRowButton = qsThrowIfNotExists(document, "#addRowButton"); const deleteRowsButton = qsThrowIfNotExists(document, "#deleteRowsButton"); const projectSelect = qsThrowIfNotExists(document, "#projectSelect"); const flagEditerModal = qsThrowIfNotExists(document, "#flagEditerModal"); const form = qsThrowIfNotExists(document, "#flagEditerForm"); const modal = new bootstrap.Modal(flagEditerModal); form.addEventListener("submit", (e) => { e.preventDefault(); }); const flagTableBody = qsThrowIfNotExists(document, "#flagTable tbody"); if (!flagTableBody) { console.error("Table body element not found"); return; } flagEditer.addEventListener("click", () => { const savedData = localStorage.getItem(getFlagsDataStorageKey(projectSelect.value)); flagTableBody.innerHTML = ""; if (savedData) { const rows = savedData.split("\n"); rows.forEach((rowData) => { const columns = rowData.split("\t"); const row = createTableRow(); const cells = row.getElementsByTagName("td"); for (let i = 0; i < 4; i++) { const cell = cells[i]; cell.textContent = columns[i]; } flagTableBody.appendChild(row); }); } modal.show(); }); function createTableRow(): HTMLTableRowElement { const row = document.createElement("tr"); for (let i = 0; i < 4; 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("#flagEditerModal button[type='submit']"); saveButton?.addEventListener("click", async (event) => { event.preventDefault(); await saveTableDataToLocalStorage(); modal.hide(); }); addRowButton.addEventListener("click", (event) => { event.preventDefault(); const table = qsThrowIfNotExists(document, "#flagTable 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} FALSE `; table.appendChild(newRow); }); deleteRowsButton.addEventListener("click", () => { const checkboxes = document.querySelectorAll(".row-checkbox:checked"); checkboxes.forEach((checkbox) => { const row = checkbox.closest("tr"); if (row) { // 行が削除される際それより後ろの行のIDをふり直し、連番の成立を維持させる const rows = flagTableBody.getElementsByTagName("tr"); const rowIndex = Array.from(rows).indexOf(row); for (let i = rowIndex + 1; i < rows.length; i++) { const cells = rows[i].getElementsByTagName("td"); if (cells.length > 0 && cells[0].textContent != null) { cells[0].textContent = String(parseInt(cells[0].textContent, 10) - 1); } } row.remove(); } }); }); function saveTableDataToLocalStorage() { const tableData: string[] = []; const rows = flagTableBody.getElementsByTagName("tr"); 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 < 4; j++) { const cell = cells[j]; const trimmedText = (cell.textContent ?? "").trim(); rowData.push(convertDataToSingleLine(trimmedText)); } tableData.push(rowData.join("\t")); } localStorage.setItem(getFlagsDataStorageKey(projectSelect.value), tableData.join("\n")); if (onFlagChanged) { onFlagChanged(); } } }