Welcome To Our Shell

Mister Spy & Souheyl Bypass Shell

Current Path : /home/cgabriel/

Linux ift1.ift-informatik.de 5.4.0-216-generic #236-Ubuntu SMP Fri Apr 11 19:53:21 UTC 2025 x86_64
Upload File :
Current File : //home/cgabriel/b2.html

<!DOCTYPE html>
<html lang="de">
<head>
<meta charset="utf-8">
<title>Buchhaltung</title>
<link href="https://unpkg.com/tabulator-tables@5.5.2/dist/css/tabulator.min.css" rel="stylesheet">
<script src="https://unpkg.com/tabulator-tables@5.5.2/dist/js/tabulator.min.js"></script>
<style>
body { font-family: monospace; margin: 0; }
#topbar { padding: 0.5rem; background: #eee; display: flex; align-items: center; gap: 1rem; }
#mandanten-buttons-container { display: flex; gap: 1rem; padding: 0.5rem; flex-wrap: wrap; }
.mandant-column { display: flex; flex-direction: column; }
.mandant-buttons { display: flex; flex-direction: column; gap: 0.25rem; }

.mandant-button-wrapper { position: relative; margin-bottom: 0.25rem; }
.mandant-button { width: 120px; height: 30px; position: relative; padding-right: 20px; box-sizing: border-box; cursor: pointer; }
.mandant-button.active { background-color: #007bff; color: white; }
.mandant-button .close-x { position: absolute; right: 4px; top: 50%; transform: translateY(-50%); background: transparent; border: none; color: inherit; font-weight: bold; cursor: pointer; padding: 0; }

select { max-width: 140px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

#mandanten-content-container { padding: 0.5rem; border-top: 1px solid #ccc; }
.meta { display: flex; gap: 0.5rem; margin-bottom: 0.5rem; }
.meta input { flex: 1; }
pre.baum { background: #fff; border: 1px solid #ccc; padding: 0.5rem; white-space: pre-wrap; margin-top: 0.5rem; }

#satellite { position:fixed; top:10%; left:20%; width:60%; height:70%; background:#fff; border:1px solid #000; display:none; padding:10px; overflow:auto; }

.cell-konto  { padding-left: 6px; padding-right: 6px; }

/* Durchgehende Linien */
.tabulator .tabulator-row { border-bottom: 1px solid #ccc; }
.tabulator .tabulator-tableHolder { border-bottom: none; }

/* Tabelle nimmt ganze Seitenbreite */
.tabulator { width: 100%; }

/* Alle Zellen 14px monospace */
.tabulator .tabulator-cell {
    font-family: monospace;
    font-size: 14px;
    line-height: normal;
}

/* Editor monospace gelb */
.tabulator input.tabulator-edit-input,
.tabulator textarea.tabulator-edit-input {
    background-color: #ffff00 !important;
    font-family: monospace !important;
    font-size: 14px !important;
    padding: 0 3px;
    box-sizing: border-box;
    line-height: normal;
}

/* Bearbeitete Zeilen hellgelb */
.tabulator .tabulator-row.modified { background-color: #fff9b0 !important; }

/* Flag-Spalte hellgrau */
.flag-cell {
  background-color: #e0e0e0;
  font-weight: bold;
  text-align: center;
}
#loginbar input { font-family: monospace; font-size: 14px; }
#login-msg { color: #b00000; font-weight: bold; }
</style>
</head>
<body>
<div id="topbar">
  <div id="loginbar" style="display:flex; gap:0.5rem; align-items:center;">
  <div style="display:flex; gap:0.5rem; align-items:center;">
    <label></label>
    <select id="mandant-select" onchange="addMandantInstance(this.value)" {% if not logged_in %}disabled{% endif %}>
      <option value="">Mandant wählen...</option>
      {% for m in mandanten %}
        <option value="{{ m }}">{{ m }}</option>
      {% endfor %}
    </select>
  </div>

    {% if logged_in %}
      <span>Login: <b>{{ username }}</b></span>
      <button onclick="doLogout()">Logout</button>
    {% else %}
      <input id="login-customer" placeholder="Customer" autocomplete="customer">
      <input id="login-user"     placeholder="Username" autocomplete="username">
      <input id="login-pass"     placeholder="Passwort" type="password" autocomplete="current-password">
      <button onclick="doLogin()">Login</button>
      <span id="login-msg"></span>
    {% endif %}
  </div>
</div>

<div id="mandanten-buttons-container"></div>
<div id="mandanten-content-container"></div>

<script>
const mandantInstances = [];
let activeInstance     = null;
let xid                = null;
let currentFile        = null;
let currentDir         = '';
let monthOffset        = 0;
let AnchorRow          = null;

window.copyBuffer = [];




/***************************************************************************/

async function doLogin(){
  const cus  = document.getElementById("login-customer").value.trim();
  const u    = document.getElementById("login-user").value.trim();
  const p    = document.getElementById("login-pass").value;
  const msg  = document.getElementById("login-msg");
  msg.textContent = "";
  try{
    const r = await fetch("/api/login", {
      method:"POST",
      headers:{"Content-Type":"application/json"},
      body: JSON.stringify({customer:cus, username:u, password:p})
    });
    if(!r.ok){
      msg.textContent = "Login fehlgeschlagen";
      return;
//    } else {
//        sessionStorage.setItem("cus",cus);
    }
    location.reload();
  }catch(e){
    msg.textContent = "Netzwerkfehler";
  }

}


/***************************************************************************/


async function doLogout(){
  try{
    await fetch("/api/logout", {method:"POST"});
  }catch(e){}
  location.reload();
}


/***************************************************************************/


// ------------------ Hilfsfunktionen ------------------
function measureText(text, font="14px monospace") {
  const canvas = measureText._canvas || (measureText._canvas = document.createElement("canvas"));
  const ctx = canvas.getContext("2d");
  ctx.font = font;
  return ctx.measureText(text).width;
}


/***************************************************************************/

// Berechnet Flag-Spalte 0/1
function computeFlag(row, needle){
  if(!needle) return "1";
  const terms = needle.toLowerCase().split(";").map(t=>t.trim()).filter(t=>t);
  for(const v of Object.values(row)){
    if(!v) continue;
    if(terms.some(t=>String(v).toLowerCase().includes(t))) return "1";
  }
  return "0";
}


/***************************************************************************/

// Update Flags & Sortierung
function updateFlags(){
  if(!activeInstance || !activeInstance.tabulator) return;

  const needle = document.querySelector(".trigger")?.value || "";

  activeInstance.tabulator.getRows().forEach(row=>{
    row.update({
      _flag: computeFlag(row.getData(), needle)
    });
  });

  // Sortiere absteigend nach _flag
  activeInstance.tabulator.setSort("_flag","desc");
}


/***************************************************************************/


// ------------------ Mandantenlogik ------------------
function addMandantInstance(baseId) {
  if (!baseId) return;
//  const cus = sessionStorage.getItem("cus")
  let instanceNo = 0;
  const used = mandantInstances.filter(i => i.baseId===baseId).map(i=>i.instanceNo);
  while(used.includes(instanceNo)) instanceNo++;
  const label = instanceNo===0 ? baseId : `${baseId} (${instanceNo})`;
  const instance = { baseId, instanceNo, label, context:{subdir:'',ktofile:'', data:null }, tabulator:null, tabulatorDiv:null };
  mandantInstances.push(instance);
  renderMandantButtons();
  setActiveInstance(instance);
  document.getElementById("mandant-select").value = '';
}


/***************************************************************************/

function renderMandantButtons() {
  const container = document.getElementById("mandanten-buttons-container");
  container.innerHTML = '';
  const grouped = {};
  mandantInstances.forEach(inst => {
    if (!grouped[inst.baseId]) grouped[inst.baseId] = [];
    grouped[inst.baseId].push(inst);
  });
  for (const [baseId, instances] of Object.entries(grouped)) {
    const col = document.createElement("div");
    col.className = "mandant-column";
    const buttonsDiv = document.createElement("div");
    buttonsDiv.className = "mandant-buttons";
    instances.forEach(inst => {
      const wrapper = document.createElement("div");
      wrapper.className = "mandant-button-wrapper";

      const btn = document.createElement('button');
      btn.textContent = inst.label;
      btn.className = "mandant-button";


      if (inst === activeInstance) btn.classList.add('active');
      btn.onclick = () => setActiveInstance(inst);

      const del = document.createElement('button');
      del.textContent = '×';
      del.className = 'close-x';
      del.onclick = (e) => { e.stopPropagation(); deleteMandantInstance(inst); };

      btn.appendChild(del);
      wrapper.appendChild(btn);
      buttonsDiv.appendChild(wrapper);
    });
    col.appendChild(buttonsDiv);
    container.appendChild(col);
  }
}


/***************************************************************************/

function deleteMandantInstance(inst) {
  const idx = mandantInstances.indexOf(inst);
  if (idx !== -1) mandantInstances.splice(idx,1);
  if (activeInstance === inst) {
    activeInstance = mandantInstances[0] || null;
    if (activeInstance) reloadContextInstance(activeInstance);
    else document.getElementById('mandanten-content-container').innerHTML = '';
  }
  renderMandantButtons();
}

/*function setActiveInstance(inst) {
  activeInstance = inst;
  renderMandantButtons();
  reloadContextInstance(inst);
}
*/


/***************************************************************************/

function setActiveInstance(inst) {

  if (activeInstance) {
    activeInstance.tabulatorDiv = document.getElementById(xid);
//    console.log("ACT",xid,activeInstance);
  }

  activeInstance  = inst;
  renderMandantButtons();

  const container = document.getElementById('mandanten-content-container');
  container.innerHTML = '';

  console.log(inst);
  if (inst.tabulatorDiv) {
    container.appendChild(inst.tabulatorDiv)
  } else {
    reloadContextInstance(inst);
  }
  xid = "tabs-"+inst.baseId+"-"+String(inst.instanceNo);

}

function reloadContextInstance(inst) {
  if (!inst) inst = activeInstance;
  fetch(`/api/context?mandant=${inst.baseId}&subdir=${inst.context.subdir}&kpattern=${inst.context.ktofile}`)
    .then(r => r.json())
    .then(data => {
      inst.context.data = data;
      renderActiveContent(inst);
    });
}

// ------------------ Tabelle rendern ------------------
function renderActiveContent(inst) {
  const ctx = inst.context.data;
  if (!ctx) return;
  const container = document.getElementById('mandanten-content-container');

  const triggerValue = ctx.active.trigger || "";

  if (ctx.active.buchungen) {
    ctx.active.buchungen = ctx.active.buchungen.map(b => {
      b.bemerkung = (b.bemerkung||"").trim().replace(/\n{2,}/g,"\n");
      return b;
    });
    
          
  }

  const ddd = ctx.files['.kto.html'] || [];
  const dd1 = ddd[0];

  container.innerHTML = `
    <div id="tabs-${inst.baseId}-${inst.instanceNo}">
    <select id="kto-select" class="kto-select" onchange="changeKtoFile(this.value, '', '${inst.baseId}')">
      <option>${dd1}</option>
      ${(ctx.files['.kto.html']||[])
        .map(f=>`<option ${f===ctx.active.kto?'selected':''}>${f}</option>`).join('')}
    </select>
    <select class="dir-select" onchange="onDirSelect(activeInstance, this, '${inst.baseId}')">
      <option value="" selected>DIR</option>
      ${(ctx.files['._d_']||[])
        .map(f=>`<option ${f===ctx.active.kto?'selected':''}>${f}</option>`).join('')}
    </select>
    <select class="file-select" onchange="openFileWindow(activeInstance, this)">  
      <option value="" selected>PDF</option>
      ${(ctx.files['.pdf']||[])
        .map(f=>`<option ${f===ctx.active.kto?'selected':''}>${f}</option>`).join('')}
    </select>
    <select class="file-select" onchange="openFileWindow(activeInstance, this)">  
      <option value="" selected>CSV</option>
      ${(ctx.files['.csv']||[])
        .map(f=>`<option ${f===ctx.active.kto?'selected':''}>${f}</option>`).join('')}
    </select>
    <select class="file-select" onchange="openFileWindow(activeInstance, this)">  
      <option value="" selected>MISC</option>
      ${(ctx.files['.xxx']||[])
        .map(f=>`<option ${f===ctx.active.kto?'selected':''}>${f}</option>`).join('')}
    </select>

<!--select id="dir-select" onchange="openDirectorySatellite(this.value)"></select>
<select id="pdf-select" onchange="openFileSatellite(this.value,'.pdf')"></select>
<select id="txt-select" onchange="openFileSatellite(this.value,'.txt')"></select-->
<input type="file" id="upload-input" />
<button id="uploadbutton" onclick="uploadFile()">Upload</button>
    ${inst.context.subdir}

<div id="satellite">
  <button onclick="downloadCurrent()">Download</button>
  <pre id="file-view"></pre>
  <button onclick="deleteCurrent()">Delete</button>
  <input id="rename-input" placeholder="new name" />	
  <button onclick="renameCurrent()">Save</button>
  <button onclick="closeSatellite()">Close</button>
</div>


    <div class="meta">
      <!--input class="konto" value="${ctx.active.konto||''}" placeholder="Konto">
      <input class="hash" value="${ctx.active.hash||''}" placeholder="Hash" disabled>
      <input class="saldo" value="${ctx.active.saldo||''}" placeholder="Saldo" disabled-->
      <!--input class="triggxx" value="${triggerValue}" placeholder="Triggerbegriff" onchange="updateFlags()"-->
    </div>

    <div id="tabulator-${inst.baseId}-${inst.instanceNo}" class="tabulator"></div>

    <div id="table-toolbar" style="display:flex; gap:0.5rem; margin-top:0.5rem;">
      <button onclick="activeInstance.tabulatorDiv='';reloadContextInstance(activeInstance)">Reload</button>
      <input class="konto" value="${ctx.active.konto||''}" placeholder="Konto">
      <input class="hash" value="${ctx.active.hash||''}" placeholder="Hash" disabled>
      <input class="saldo" value="${ctx.active.saldo||''}" placeholder="Saldo" disabled>
      <button onclick="sendToDB(activeInstance)">Speichern</button>
      <input class="rename" value="${triggerValue}" placeholder="Neuer Name" style="flex:1;">              
      <input class="trigger" value="${triggerValue}" placeholder="Filter" onchange="updateFlags()" style="flex:1;">
      <input class="search"  id="searchText"  placeholder="Suchen" style="flex:1;">
      <input class="replace" id="replaceText" placeholder="Ersetzen" style="flex:1;">
      <button onclick="replaceInTable(activeInstance)">Ersetzen</button>
    </div>
    <pre class="baum">${ctx.active.baum.join('\n')}</pre>
    </div>
  `;

  const tabDiv = document.getElementById(`tabulator-${inst.baseId}-${inst.instanceNo}`);
  const rowHeight = 35;
  
  document.getElementById("uploadbutton").disabled = true;  //  (ctx.wmode == "0");

  function markModified(cell){
    cell.getRow().getElement().classList.add("modified");
    cell.getRow().update({_flag: computeFlag(cell.getRow().getData(), document.querySelector(".trigger").value)});
    updateFlags();
  }

  const columnsDef = [

    {title:'', field:'lfdnr', visible: false },
    {title:"", field:"_flag", width:30, hozAlign:"center", frozen:true, cssClass:"flag-cell",
      formatter:function(cell){
        const val = computeFlag(cell.getRow().getData(), document.querySelector(".trigger").value);
        cell.getElement().style.backgroundColor = val === "1" ? "#d6ffd6" : "#ffd6d6";
        return val;
      }
    },
    {title:'Datum', field:'datum', editor:"input",
      editorParams:{elementAttributes:{style:"font-family:monospace;font-size:14px;background-color:#ffff00;width:100%;box-sizing:border-box;"}},
      cellEdited: markModified},
    {title:'Betrag', field:'betrag', width:110, editor:"input", hozAlign:'right',
      formatter:function(cell){
        const val = parseFloat(cell.getValue());
        cell.getElement().style.backgroundColor = (!isNaN(val) && val<0) ? "#ffd6d6" : "#e6ffe6";
        return cell.getValue();
      },
      editorParams:{elementAttributes:{style:"font-family:monospace;text-align:right;font-size:14px;background-color:#ffff00;width:100%;box-sizing:border-box;"}},
      cellEdited: markModified
    },
    {title:'Konto1', field:'konto1', editor:"input", cssClass:'cell-konto',
      editorParams:{elementAttributes:{style:"font-family:monospace;font-size:14px;background-color:#ffff00;width:100%;box-sizing:border-box;"}},
      cellEdited: markModified},
    {title:'Konto2', field:'konto2', editor:"input", cssClass:'cell-konto',
      editorParams:{elementAttributes:{style:"font-family:monospace;font-size:14px;background-color:#ffff00;width:100%;box-sizing:border-box;"}},
      cellEdited: markModified},
    {title:'Saldo', field:'saldo', width:120, editor:"input", hozAlign:'right',
      formatter:function(cell){
        const val = parseFloat(cell.getValue());
        cell.getElement().style.backgroundColor = (!isNaN(val) && val<0) ? "#ffd6d6" : "#e6f0ff";
        return cell.getValue();
      },
      editorParams:{elementAttributes:{style:"font-family:monospace;text-align:right;font-size:14px;background-color:#ffff00;width:100%;box-sizing:border-box;"}},
      cellEdited: markModified
    },
    {title:'Bemerkung', field:'bemerkung', editor:"input", widthGrow:100,
      editorParams:{elementAttributes:{style:"font-family:monospace;font-size:14px;background-color:#ffff00;width:100%;box-sizing:border-box;"}},
      cellEdited: markModified}
  ];

  inst.tabulator = new Tabulator(tabDiv, {
    height: Math.min((ctx.active.buchungen.length*rowHeight)+40,600),
    layout:"fitDataStretch",
    movableColumns:true,
    resizableColumns:true,
    selectable:true,
//    selectableRangeMode:"click",
//    selectableRange:false,
//    selectablePersistence:false,
    selectableRangeMode:"click",
    selectableRange:"true",
    selectableRangeColumns:"false",
    selectableRangeRows:"true",
//    rowClick:function(e,row){lastFocusedRow=row;},
//    cellClick:function(e,cell){lastFocusedRow=cell.getRow();},
//    cellFocused:function(cell){alert("OKI");console.log("OKKK");inst.lastFocusedRow=cell.getRow();},
    columns:columnsDef,
    data: ctx.active.buchungen || []
  });
  inst.lastFocusedRow=null;
//  inst.tabulator.on("cellFocused",function(cell){alert("OKK");inst.lastFocusedRow=cell.getRow();});
  inst.tabulator.on("rowMouseEnter",function(e,row){inst.lastFocusedRow=row;});



document.addEventListener("keydown", function(e){

  if(e.key == "Delete") {
    if(!activeInstance || !activeInstance.tabulator) return;

    const table    = activeInstance.tabulator;
    const focusRow = activeInstance.lastFocusedRow;
    const selected = table.getSelectedRows();

    if(!focusRow){
      table.deselectRow();
      return;
    }

    const inside = selected.includes(focusRow);

    if(inside){
      let aktNextRow = null;
      let z1         = 0;
      selected.forEach(r =>{z1=z1+1;aktNextRow=r.getNextRow();r.delete()});
      if (aktNextRow && (z1<2)) { 
        aktNextRow.select();
        activeInstance.lastFocusedRow = aktNextRow;
        setTimeout(()=>{
          const el = aktNextRow.getElement();
          if(el){
            el.dispatchEvent(new MouseEvent("click",{bubbles:true}));
          }
        },4);
      }
    }else{
      table.deselectRow();
    }
    return;
  }
  
  const table = activeInstance.tabulator;

  // ---------- COPY ----------
  if(e.ctrlKey && (e.key === "c" || e.key === "C")){
    e.preventDefault();
    copySelection(table);
    monthOffset = 0;
  }


  // ---------- PASTE ----------
  if(e.ctrlKey && (e.key === "v" || e.key === "V")){
    e.preventDefault();
    pasteSelection(table);
  }


  // ---------- +1 MONTH PASTE ----------
  if(e.ctrlKey && (e.key === "m" || e.key === "M")){
    e.preventDefault();
    monthOffset = monthOffset + 1;
    pasteSelection(table);
  }

});


  // Initial Flags berechnen und sortieren

    const ktoselect = document.getElementById("kto-select");
    if (ktoselect != null) { ktoselect.options[0].text = inst.context.ktofile || file;  }

  updateFlags();

}

/***************************************************************************/

function changeKtoFile(selectElem1, selectElem2, mandant) {
  const inst = activeInstance
  const ctx  = inst.context.data;
  const file = selectElem1;
  let   dir  = inst.context.subdir + selectElem2;
  if (selectElem2 !== "" ) { dir = dir + "/"; }
  if (selectElem2 == "..") { dir = inst.context.data.ppar; }
  fetch(`/api/context?mandant=${mandant}&subdir=${encodeURIComponent(dir)}&kpattern=${encodeURIComponent(file)}`)
    .then(r => r.json())
    .then(data => {
      const inst = activeInstance;
      inst.context.data    = data;
      inst.context.ktofile = file;
      inst.context.subdir  = dir;
      renderActiveContent(inst);
    });
    ctx.active.konto = file;
}

/***************************************************************************/

function openFileWindow(actInst, file){

  mandant = actInst.baseId;
  subdir  = actInst.context.subdir;
  wmode   = actInst.context.data.wmode;

  const w = 900;
  const h = 700;
  
  
  // Position des aktuellen Browserfensters
  const dualLeft = window.screenLeft !== undefined ? window.screenLeft : window.screenX;
  const dualTop  = window.screenTop  !== undefined ? window.screenTop  : window.screenY;

  // Größe des aktuellen Browserfensters
  const width  = window.innerWidth  || document.documentElement.clientWidth  || screen.width;
  const height = window.innerHeight || document.documentElement.clientHeight || screen.height;

  const left = dualLeft + (width  - w) / 2;
  const top  = dualTop  + (height - h) / 2;

  console.log("EEE",wmode);

  window.open(
    `/satellite?rw=${encodeURIComponent(wmode)}&mandant=${encodeURIComponent(mandant)}` +
                  `&subdir=${encodeURIComponent(subdir)}&file=${encodeURIComponent(file.value)}`,
          "_blank",
          `width=${w},height=${h},left=${left},top=${top},resizable=yes,scrollbars=yes`
  );
  const ctx = actInst.context.data;
  ctx.files[".kto.html"][0] = file;
//  file.blur();
//  file.selectedIndex = 0;
//  file.value=""
  
}

/***************************************************************************/

function openFileSatellite(name, ext){
  currentFile = name;
  fetch(`/api/file_view?rw=1?file=${encodeURIComponent(name)}?subdir=${encodeURIComponent(activeInstance.context.subdir)}?mandant=${encodeURIComponent(activeInstance.baseId)}`)
    .then(r=>r.text())
    .then(t=>{
      document.getElementById('file-view').textContent = t;
      document.getElementById('satellite').style.display='block';
    });
}

/***************************************************************************/

function openDirectorySatellite(dir){
  currentDir = dir;
  document.getElementById('satellite').style.display='block';
}

/***************************************************************************/

function closeSatellite(){
  document.getElementById('satellite').style.display='none';
}

/***************************************************************************/

function deleteCurrent(){
  fetch('/api/file_delete',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({file:currentFile})})
    .then(()=>closeSatellite());
}

/***************************************************************************/

function renameCurrent(){
  const newname = document.getElementById('rename-input').value;
  fetch('/api/file_rename',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({file:currentFile,newname})})
    .then(()=>closeSatellite());
}

/***************************************************************************/

function downloadCurrent(){
  window.location = `/api/file_download?file=${encodeURIComponent(currentFile)}`;
}


/***************************************************************************/

function uploadFile(){
  const f = document.getElementById('upload-input').files[0];
  const fd = new FormData();
  fd.append('file',f);
  fd.append('filename',f.name);
  fd.append('subdir',activeInstance.context.subdir);
  fd.append('mandant',activeInstance.baseId);
  console.log("uploadFileff");
  fetch('/api/file_upload',{method:'POST',body:fd});  //  .then(()=>location.reload());
  reloadContextInstance(activeInstance);
}

/***************************************************************************/

function onDirSelect(actInst, sel, mandant){
  const v = sel.value;

  // nur bei "." Satellite öffnen
  if(v === "."){
    openDirectoryWindow(actInst);   // oder openDirectoryWindow(...) falls du schon eins hast
    sel.selectedIndex = 0;       // wichtig: zurücksetzen, damit "." wieder auswählbar ist
    return;
  }

  // sonst: ganz normal Verzeichnis wechseln
  changeKtoFile("", v, mandant);

  // optional: zurücksetzen, damit man denselben Eintrag nochmal triggern kann
  // sel.selectedIndex = 0;
}

/***************************************************************************/

function openDirectoryWindow(actInst){

  const mandant = actInst.baseId;
  const subdir  = actInst.context.subdir;
  const wmode   = actInst.context.data.wmode;

  const w = 700;
  const h = 500;

  const dualLeft = window.screenLeft !== undefined ? window.screenLeft : window.screenX;
  const dualTop  = window.screenTop  !== undefined ? window.screenTop  : window.screenY;

  const width  = window.innerWidth  || document.documentElement.clientWidth  || screen.width;
  const height = window.innerHeight || document.documentElement.clientHeight || screen.height;

  const left = dualLeft + (width  - w) / 2;
  const top  = dualTop  + (height - h) / 2;

  window.open(
    `/satellite?mode=dir&rw=${encodeURIComponent(wmode)}&mandant=${encodeURIComponent(mandant)}&subdir=${encodeURIComponent(subdir)}`,
    "_blank",
    `width=${w},height=${h},left=${left},top=${top},resizable=yes,scrollbars=yes`
  );
}

/***************************************************************************/

function replaceInTable(actInst) {
    let search  = document.getElementById("searchText").value;
    let replace = document.getElementById("replaceText").value;

    let rows = actInst.tabulator.getRows();

    rows.forEach(row => {
        let data = row.getData();

        if (data.bemerkung && data.bemerkung.includes(search)) {
            data.bemerkung = data.bemerkung.replaceAll(search, replace);
            row.update(data);
        }
        if (data.konto1 && data.konto1.includes(search)) {
            data.konto1 = data.konto1.replaceAll(search, replace);
            row.update(data);
        }
        if (data.konto2 && data.konto2.includes(search)) {
            data.konto2 = data.konto2.replaceAll(search, replace);
            row.update(data);
        }
        if (data.datum && data.datum.includes(search)) {
            data.datum = data.datum.replaceAll(search, replace);
            row.update(data);
        }
        if (data.betrag && data.betrag.includes(search)) {
            data.betrag = data.betrag.replaceAll(search, replace);
            row.update(data);
        }
    });
}

/***************************************************************************/

function sendToDB(inst) {
  if (!inst) inst = activeInstance;
  fetch(`/api/context?mandant=${inst.baseId}&subdir=${inst.context.subdir}&kpattern=${inst.context.ktofile}`)
    .then(r => r.json())
    .then(data => {
      inst.context.data = data;
      renderActiveContent(inst);
    });
}

/***************************************************************************/

function addMonths(dateStr){

  if(!dateStr || dateStr.length !== 8) return dateStr;

  const y = parseInt(dateStr.substring(0,4));
  const m = parseInt(dateStr.substring(4,6)) - 1;
  const d = parseInt(dateStr.substring(6,8));

  const dt = new Date(y, m, d);

  if(isNaN(dt)) return dateStr;

  dt.setMonth(dt.getMonth() + monthOffset);

  const yy = dt.getFullYear();
  const mm = String(dt.getMonth()+1).padStart(2,"0");
  const dd = String(dt.getDate()).padStart(2,"0");

  return `${yy}${mm}${dd}`;
}

/***************************************************************************/

function copySelection(table){
  const rows = table.getSelectedData();
  if(!rows || rows.length === 0) return;

  window.copyBuffer = rows.map(r => ({...r}));
}

/***************************************************************************/

async function pasteSelection(table) {

  if(!window.copyBuffer || window.copyBuffer.length === 0) return;

  const selected = table.getSelectedRows();
  let insertAfter = selected.length ? selected[selected.length-1] : null;

  const insertedRows = [];

  for(let rowData of window.copyBuffer){

    let data = {...rowData};

    if(monthOffset > 0 && data.datum){
      data.datum = addMonths(data.datum);
    }

    let newRow;

    if(insertAfter){
      newRow = await table.addRow(data, false, insertAfter);
    }else{
      newRow = await table.addRow(data);
    }

    insertedRows.push(newRow);
    insertAfter = newRow;
  }

  // Selection nach Render setzen
//  setTimeout(()=>{
//    const el = (insertedRows[0]).getElement();
//    if(el){
//      el.dispatchEvent(new MouseEvent("click",{bubbles:true}));
//    }
//  },4);

  setTimeout(()=>{

    table.deselectRow();

    insertedRows.forEach(r=>{
      if(r) r.select();
    });

    // Cursor auf erste neue Zeile
    if(insertedRows.length){
      insertedRows[0].getElement().scrollIntoView({block:"nearest"});
    }
    


  }, 30);

}

</script>
</body>
</html>



bypass 1.0, Devloped By El Moujahidin (the source has been moved and devloped)
Email: contact@elmoujehidin.net bypass 1.0, Devloped By El Moujahidin (the source has been moved and devloped) Email: contact@elmoujehidin.net