bindDatasetEvents function domain

Last updated: 2026-03-04T23:21:38.430Z

Metrics

LOC: 254 Complexity: 39 Params: 0

Signature

bindDatasetEvents(): : void

Architecture violations

View all

  • [warning] max-cyclomatic-complexity: 'bindDatasetEvents' has cyclomatic complexity 39 (max 10)
  • [warning] max-lines: 'bindDatasetEvents' has 254 lines (max 80)

Source Code

function bindDatasetEvents(): void {
  // Filter
  document.getElementById("dataset-filter")?.addEventListener("input", (e) => {
    const val = (e.target as HTMLInputElement).value.trim();
    void loadDatasetList(val);
  });

  // Add entry
  document
    .getElementById("btn-add-dataset-entry")
    ?.addEventListener("click", async () => {
      const signals = (
        document.getElementById("dataset-signals") as HTMLInputElement
      ).value.trim();
      const type = (datasetTypeSelect?.getValue() ?? "") as FieldType;
      const difficulty = (
        document.getElementById("dataset-difficulty") as HTMLSelectElement
      ).value as "easy" | "medium" | "hard";

      if (!signals) {
        showToast(t("toastSignalsRequired"), "error");
        return;
      }

      const entry = (await chrome.runtime.sendMessage({
        type: "ADD_DATASET_ENTRY",
        payload: { signals, type, source: "manual", difficulty },
      })) as DatasetEntry | { error: string };

      if ("error" in entry) {
        showToast(entry.error, "error");
        return;
      }

      const existingIdx = _allDatasetEntries.findIndex(
        (e) => e.id === entry.id,
      );
      if (existingIdx >= 0) {
        _allDatasetEntries[existingIdx] = entry;
      } else {
        _allDatasetEntries.unshift(entry);
      }

      await loadDatasetList();
      (document.getElementById("dataset-signals") as HTMLInputElement).value =
        "";
      showToast(t("toastDatasetEntryAdded"));
    });

  // Seed built-in
  document
    .getElementById("btn-seed-dataset")
    ?.addEventListener("click", async () => {
      const btn = document.getElementById(
        "btn-seed-dataset",
      ) as HTMLButtonElement;
      btn.disabled = true;
      btn.textContent = t("importingText");
      try {
        const result = await seedBuiltinDataset();
        const fresh = (await chrome.runtime.sendMessage({
          type: "GET_DATASET",
        })) as DatasetEntry[];
        _allDatasetEntries = Array.isArray(fresh) ? fresh : [];
        await loadDatasetList();
        if (result.added > 0) {
          showToast(t("seedAdded", [String(result.added)]));
        } else {
          showToast(t("toastDatasetAlreadyFull"));
        }
      } finally {
        btn.disabled = false;
        btn.textContent = t("btnSeedDataset");
      }
    });

  // Export JSON
  document
    .getElementById("btn-export-dataset")
    ?.addEventListener("click", async () => {
      const entries = (await chrome.runtime.sendMessage({
        type: "EXPORT_DATASET",
      })) as DatasetEntry[];
      const json = JSON.stringify(entries, null, 2);
      const blob = new Blob([json], { type: "application/json" });
      const url = URL.createObjectURL(blob);
      const a = document.createElement("a");
      a.href = url;
      a.download = "fill-all-dataset.json";
      document.body.appendChild(a);
      a.click();
      document.body.removeChild(a);
      URL.revokeObjectURL(url);
      showToast(t("toastDatasetExported", [String(entries.length)]));
    });

  // Import JSON (file picker)
  document
    .getElementById("btn-import-dataset")
    ?.addEventListener("click", () => {
      document.getElementById("dataset-import-file")?.click();
    });

  document
    .getElementById("dataset-import-file")
    ?.addEventListener("change", async (e) => {
      const input = e.target as HTMLInputElement;
      const file = input.files?.[0];
      if (!file) return;

      try {
        const text = await file.text();
        const parsed = JSON.parse(text) as unknown;
        if (!Array.isArray(parsed))
          throw new Error("O arquivo deve ser um array JSON");

        const result = (await chrome.runtime.sendMessage({
          type: "IMPORT_DATASET",
          payload: parsed,
        })) as { success: boolean; added: number; error?: string };

        if (!result.success) throw new Error(result.error ?? "unknown error");

        const fresh = (await chrome.runtime.sendMessage({
          type: "GET_DATASET",
        })) as DatasetEntry[];
        _allDatasetEntries = Array.isArray(fresh) ? fresh : [];
        await loadDatasetList();
        showToast(t("toastDatasetImported", [String(result.added)]));
      } catch (err) {
        showToast(
          t("errorImportDataset", [
            err instanceof Error ? err.message : String(err),
          ]),
          "error",
        );
      }

      input.value = "";
    });

  // Clear dataset
  document
    .getElementById("btn-clear-dataset")
    ?.addEventListener("click", async () => {
      if (!confirm(t("confirmClearDataset"))) return;
      await chrome.runtime.sendMessage({ type: "CLEAR_DATASET" });
      _allDatasetEntries = [];
      await loadDatasetList();
      showToast(t("toastDatasetCleared"));
    });

  // Delete runtime model
  document
    .getElementById("btn-delete-model")
    ?.addEventListener("click", async () => {
      if (!confirm(t("confirmDeleteModel"))) return;
      await chrome.runtime.sendMessage({ type: "DELETE_RUNTIME_MODEL" });
      await loadModelStatus();
      showToast(t("toastModelRemoved"));
    });

  // Train model
  document
    .getElementById("btn-train-model")
    ?.addEventListener("click", async () => {
      const trainBtn = document.getElementById(
        "btn-train-model",
      ) as HTMLButtonElement;
      const progressBlock = document.getElementById("training-progress-block");
      const progressBar = document.getElementById("training-progress-bar");
      const progressLabel = document.getElementById("training-progress-label");
      const trainingLog = document.getElementById(
        "training-log",
      ) as HTMLPreElement | null;

      const entries = (await chrome.runtime.sendMessage({
        type: "GET_DATASET",
      })) as DatasetEntry[];
      if (!Array.isArray(entries) || entries.length < 10) {
        showToast(t("errorDatasetTooSmall", [String(entries.length)]), "error");
        return;
      }
      const distinctTypes = new Set(entries.map((e) => e.type)).size;
      if (distinctTypes < 2) {
        showToast(t("errorDatasetFewTypes", [String(distinctTypes)]), "error");
        return;
      }

      trainBtn.disabled = true;
      trainBtn.textContent = t("trainingText");
      if (progressBlock) progressBlock.style.display = "block";
      if (progressBar) progressBar.style.width = "0%";
      if (progressLabel) progressLabel.textContent = "Iniciando...";
      if (trainingLog)
        trainingLog.textContent = `Iniciando treinamento com ${entries.length} amostras...\n`;

      const onProgress = (p: TrainingProgress) => {
        const pct = Math.round((p.epoch / p.totalEpochs) * 100);
        if (progressBar) progressBar.style.width = `${pct}%`;
        if (progressLabel) {
          progressLabel.textContent = `Epoch ${p.epoch} / ${p.totalEpochs} — Loss: ${p.loss.toFixed(4)} — Accuracy: ${(p.accuracy * 100).toFixed(1)}%`;
        }
        if (trainingLog) {
          trainingLog.textContent += `Epoch ${String(p.epoch).padStart(3)} | loss: ${p.loss.toFixed(4)} | acc: ${(p.accuracy * 100).toFixed(2)}%\n`;
          trainingLog.scrollTop = trainingLog.scrollHeight;
        }
      };

      try {
        const result: TrainingResult = await trainModelFromDataset(
          entries,
          onProgress,
        );

        if (result.success) {
          if (progressBar) progressBar.style.width = "100%";
          if (progressLabel)
            progressLabel.textContent = "Treinamento concluído!";
          if (trainingLog) {
            trainingLog.textContent += `\n✅ Concluído em ${result.durationMs}ms\n`;
            trainingLog.textContent += `   Épocas: ${result.epochs} | Acurácia: ${(result.finalAccuracy * 100).toFixed(2)}% | Vocab: ${result.vocabSize}\n`;
            trainingLog.textContent += `   Modelo salvo no storage — ativo na próxima página preenchida.\n`;
          }
          const tabs = await chrome.tabs.query({});
          await Promise.allSettled(
            tabs.map((t) =>
              t.id
                ? chrome.tabs
                    .sendMessage(t.id, { type: "RELOAD_CLASSIFIER" })
                    .catch(() => {})
                : Promise.resolve(),
            ),
          );
          await loadModelStatus();
          showToast(
            t("toastModelTrained", [(result.finalAccuracy * 100).toFixed(1)]),
          );
        } else {
          if (trainingLog)
            trainingLog.textContent += `\n\u274C Error: ${result.error}\n`;
          showToast(t("toastTrainingError", [result.error ?? ""]), "error");
        }
      } catch (err) {
        const msg = err instanceof Error ? err.message : String(err);
        if (trainingLog)
          trainingLog.textContent += `\n\u274C Exception: ${msg}\n`;
        showToast(t("toastError", [msg]), "error");
      } finally {
        trainBtn.disabled = false;
        trainBtn.textContent = t("btnTrainModel");
      }
    });
}

Dependencies (Outgoing)

graph LR bindDatasetEvents["bindDatasetEvents"] loadDatasetList["loadDatasetList"] seedBuiltinDataset["seedBuiltinDataset"] loadModelStatus["loadModelStatus"] bindDatasetEvents -->|calls| loadDatasetList bindDatasetEvents -->|calls| seedBuiltinDataset bindDatasetEvents -->|calls| loadModelStatus style bindDatasetEvents fill:#dbeafe,stroke:#2563eb,stroke-width:2px click bindDatasetEvents "f0efa64bdb9c9631.html" click loadDatasetList "38bfd5021ccf26d2.html" click seedBuiltinDataset "a3f046b90d6a3d99.html" click loadModelStatus "2c3f5e65d67a73f9.html"
TargetType
loadDatasetList calls
seedBuiltinDataset calls
loadModelStatus calls
input dynamic_call
click dynamic_call
change dynamic_call

Impact (Incoming)

graph LR bindDatasetEvents["bindDatasetEvents"] initDatasetTab["initDatasetTab"] initDatasetTab -->|calls| bindDatasetEvents style bindDatasetEvents fill:#dbeafe,stroke:#2563eb,stroke-width:2px click bindDatasetEvents "f0efa64bdb9c9631.html" click initDatasetTab "a79227daf4a64033.html"
SourceType
initDatasetTab calls