Forráskód Böngészése

feat: allDataExim import rework

Sv443 2 hónapja
szülő
commit
fc869f42fd
1 módosított fájl, 187 hozzáadás és 0 törlés
  1. 187 0
      src/dialogs/allDataExIm.ts

+ 187 - 0
src/dialogs/allDataExIm.ts

@@ -0,0 +1,187 @@
+import { consumeStringGen, type SerializedDataStore } from "@sv443-network/userutils";
+import { copyToClipboard, error, onInteraction, t } from "../utils/index.js";
+import { BytmDialog, createLongBtn, createRipple, showToast } from "../components/index.js";
+import { ExImDialog, type ExImDialogOpts } from "../components/ExImDialog.js";
+import { allSerializerStoresIds, downloadData, getStoreSerializer } from "../serializer.js";
+import "./autoLike.css";
+
+let allDataExImDialog: BytmDialog | undefined;
+
+/** Creates and/or returns the AllDataExIm dialog */
+export async function getAllDataExImDialog() {
+  if(!allDataExImDialog) {
+    const eximOpts: ExImDialogOpts = {
+      id: "all-data-exim",
+      width: 800,
+      height: 1000,
+      closeBtnEnabled: true,
+      closeOnBgClick: true,
+      closeOnEscPress: true,
+      destroyOnClose: true,
+      removeListenersOnDestroy: false,
+      small: true,
+      verticalAlign: "top",
+      title: () => t("all_data_exim_title"),
+      descExport: () => t("all_data_exim_export_desc"),
+      descImport: () => t("all_data_exim_import_desc"),
+      exportData: async () => await getStoreSerializer().serialize(),
+      onImport,
+    };
+
+    allDataExImDialog = new ExImDialog({
+      ...eximOpts,
+      renderBody: async () => await renderBody(eximOpts),
+    });
+  }
+  return allDataExImDialog;
+}
+
+/** Creates and/or returns the AutoLikeExIm dialog */
+async function onImport(data: string) {
+  try {
+    const serializer = getStoreSerializer();
+    await serializer.deserialize(data);
+
+    showToast(t("import_success"));
+  }
+  catch(err) {
+    error(err);
+    showToast(t("import_error"));
+  }
+}
+
+async function renderBody(opts: ExImDialogOpts): Promise<HTMLElement> {
+  const panesCont = document.createElement("div");
+  panesCont.classList.add("bytm-all-data-exim-dialog-panes-cont");
+
+  //#region export
+
+  const exportPane = document.createElement("div");
+  exportPane.classList.add("bytm-all-data-exim-dialog-pane", "export");
+
+  {
+    const descEl = document.createElement("p");
+    descEl.classList.add("bytm-all-data-exim-dialog-desc");
+    descEl.role = "note";
+    descEl.tabIndex = 0;
+    descEl.textContent = descEl.ariaLabel = await consumeStringGen(opts.descExport);
+
+    const exportPartsCont = document.createElement("div");
+    exportPartsCont.classList.add("bytm-all-data-exim-dialog-export-parts-cont");
+
+    const dataEl = document.createElement("textarea");
+    dataEl.classList.add("bytm-all-data-exim-dialog-data");
+    dataEl.readOnly = true;
+    dataEl.tabIndex = 0;
+    dataEl.value = t("click_to_reveal");
+
+    for(const id of allSerializerStoresIds) {
+      const rowEl = document.createElement("div");
+      rowEl.classList.add("bytm-all-data-exim-dialog-export-part-row");
+      rowEl.title = t(`data_stores.disable.${id}`);
+
+      const chkEl = document.createElement("input");
+      chkEl.type = "checkbox";
+      chkEl.id = `bytm-all-data-exim-dialog-export-part-${id}`;
+      chkEl.dataset.storeId = id;
+      chkEl.checked = true;
+      chkEl.title = t(`data_stores.disable.${id}`);
+
+      chkEl.addEventListener("change", async () => {
+        if(dataEl.classList.contains("revealed"))
+          dataEl.value = filter(await consumeStringGen(opts.exportData));
+      });
+
+      const lblEl = document.createElement("label");
+      lblEl.htmlFor = chkEl.id;
+      lblEl.textContent = t(`data_stores.disable.${id}`);
+
+      rowEl.append(chkEl, lblEl);
+      exportPartsCont.appendChild(rowEl);
+    }
+
+    const filter = (data: string) => {
+      const exportIds: string[] = [];
+
+      for(const chkEl of exportPartsCont.querySelectorAll<HTMLInputElement>("input[type=checkbox]"))
+        chkEl.checked && chkEl.dataset.storeId && exportIds.push(chkEl.dataset.storeId);
+
+      return JSON.stringify(
+        (JSON.parse(data) as SerializedDataStore[])
+          .filter(({ id }) => exportIds.includes(id))
+      );
+    };
+
+    onInteraction(dataEl, async () => {
+      dataEl.classList.add("revealed");
+      dataEl.value = filter(await consumeStringGen(opts.exportData));
+      dataEl.setSelectionRange(0, dataEl.value.length);
+    });
+
+    const exportCenterBtnCont = document.createElement("div");
+    exportCenterBtnCont.classList.add("bytm-all-data-exim-dialog-center-btn-cont");
+
+    const cpBtn = createRipple(await createLongBtn({
+      title: t("copy_to_clipboard"),
+      text: t("copy"),
+      resourceName: "icon-copy",
+      async onClick({ shiftKey }) {
+        const copyData = shiftKey && opts.exportDataSpecial ? opts.exportDataSpecial : opts.exportData;
+        copyToClipboard(filter(await consumeStringGen(copyData)));
+        await showToast({ message: t("copied_to_clipboard") });
+      },
+    }));
+
+    const dlBtn = createRipple(await createLongBtn({
+      title: t("download_file"),
+      text: t("download"),
+      resourceName: "icon-arrow_down",
+      async onClick({ shiftKey }) {
+        const dlData = shiftKey && opts.exportDataSpecial ? opts.exportDataSpecial : opts.exportData;
+        copyToClipboard(filter(await consumeStringGen(dlData)));
+        await downloadData();
+        await showToast({ message: t("downloaded_file_hint") });
+      },
+    }));
+
+    exportCenterBtnCont.append(cpBtn, dlBtn);
+    exportPane.append(descEl, dataEl, exportCenterBtnCont);
+  }
+
+  //#region import
+
+  const importPane = document.createElement("div");
+  importPane.classList.add("bytm-all-data-exim-dialog-pane", "import");
+
+  {
+    // TODO: file upload field
+    // TODO: select which stores to import
+
+    const descEl = document.createElement("p");
+    descEl.classList.add("bytm-all-data-exim-dialog-desc");
+    descEl.role = "note";
+    descEl.tabIndex = 0;
+    descEl.textContent = descEl.ariaLabel = await consumeStringGen(opts.descImport);
+
+    const dataEl = document.createElement("textarea");
+    dataEl.classList.add("bytm-all-data-exim-dialog-data");
+    dataEl.tabIndex = 0;
+
+    const importCenterBtnCont = document.createElement("div");
+    importCenterBtnCont.classList.add("bytm-all-data-exim-dialog-center-btn-cont");
+
+    const importBtn = createRipple(await createLongBtn({
+      title: t("start_import_tooltip"),
+      text: t("import"),
+      resourceName: "icon-upload",
+      onClick: () => opts.onImport(dataEl.value),
+    }));
+
+    importCenterBtnCont.appendChild(importBtn);
+    importPane.append(descEl, dataEl, importCenterBtnCont);
+  }
+
+  panesCont.append(exportPane, importPane);
+
+  return panesCont;
+}