403Webshell
Server IP : 188.114.96.3  /  Your IP : 216.73.216.143
Web Server : Apache
System : Linux sv058.home.net.pl 6.8.2 husak_dirty_pages_fix #1 SMP PREEMPT_DYNAMIC Tue Apr 2 22:06:51 CEST 2024 x86_64
User :  ( 3194769)
PHP Version : 8.5.12
Disable Function : NONE
MySQL : OFF  |  cURL : ON  |  WGET : ON  |  Perl : ON  |  Python : ON  |  Sudo : ON  |  Pkexec : OFF
Directory :  /polana/admin/

Upload File :
current_dir [ Writeable ] document_root [ Writeable ]

 

Command :


[ Back ]     

Current File : /polana/admin/import-editor.js
/* POLANA IMPORT R4 — ręczna korekta wierszy przed utworzeniem szkicu. */
(() => {
  'use strict';
  const mount = document.getElementById('polana-import-editor');
  const dataNode = document.getElementById('polana-import-editor-data');
  const form = document.getElementById('polana-import-confirm-form');
  const field = document.getElementById('polana-edited-rows');
  const submit = document.getElementById('polana-save-import-button');
  const status = document.getElementById('polana-review-save-state');
  if (!mount || !dataNode || !form || !field || !submit) return;

  let rows;
  try {
    rows = JSON.parse(dataNode.textContent);
    if (!Array.isArray(rows)) throw new Error('Niepoprawne dane podglądu.');
  } catch (err) {
    mount.textContent = 'Nie udało się uruchomić edytora. Odśwież stronę i wczytaj Worda ponownie.';
    return;
  }
  let nextKey = 1;
  rows = rows.map(row => ({
    id: nextKey++,
    kind: row.kind === 'category' ? 'category' : 'item',
    name: String(row.name ?? ''),
    price: String(row.price ?? ''),
    price_text: String(row.price_text ?? ''),
    description: String(row.description ?? '')
  }));
  let dirty = false;
  let submitting = false;
  const newRow = (kind, name = '') => ({id: nextKey++, kind, name, price:'', price_text:'', description:''});
  const h = (tag, className, text) => {
    const el = document.createElement(tag);
    if (className) el.className = className;
    if (text !== undefined) el.textContent = text;
    return el;
  };
  function groupStarts() {
    return rows.reduce((a, row, i) => {if(row.kind === 'category') a.push(i); return a;}, []);
  }
  function categoryAt(index) {
    for (let i=index;i>=0;i--) if (rows[i].kind === 'category') return i;
    return -1;
  }
  function refreshCounts() {
    const categories = rows.filter(r=>r.kind==='category').length;
    const items = rows.filter(r=>r.kind==='item').length;
    const missing = rows.filter(r=>r.kind==='item' && !r.price.trim() && !r.price_text.trim()).length;
    status.textContent = `${categories} kategorii, ${items} pozycji. ${missing ? 'Do uzupełnienia: ' + missing + ' cen. ' : ''}${dirty ? 'Zmiany jeszcze niezapisane.' : 'Przed zapisem sprawdź poprawność.'}`;
  }
  function changed() {dirty=true; refreshCounts();}
  function swapCategory(index, direction) {
    const starts = groupStarts();
    const p = starts.indexOf(index), other = p + direction;
    if (p < 0 || other < 0 || other >= starts.length) return;
    // Przesuwa kategorię RAZEM z jej daniami, a nie sam nagłówek.
    const segments = starts.map((start,j)=>rows.slice(start,starts[j+1] ?? rows.length));
    [segments[p],segments[other]] = [segments[other],segments[p]];
    rows=segments.flat();changed();render();
  }
  function shiftItem(index, direction) {
    const other=index+direction;
    if (other<0 || other>=rows.length || rows[other].kind !== 'item' || categoryAt(index)!==categoryAt(other)) return;
    [rows[index],rows[other]]=[rows[other],rows[index]];
    changed();render();
  }
  function moveToCategory(index, targetId) {
    const moving=rows[index];
    if (!moving || moving.kind!=='item') return;
    const targetRow=rows.find(r=>r.id===targetId && r.kind==='category');
    if (!targetRow) return;
    rows.splice(index,1);
    const catIndex=rows.indexOf(targetRow);
    let end=catIndex+1;
    while(end<rows.length && rows[end].kind!=='category') end++;
    rows.splice(end,0,moving);
    changed();render();
  }
  function setKind(index, kind) {
    if (!['category','item'].includes(kind) || rows[index].kind===kind) return;
    if (kind==='item' && rows[index].kind==='category') {
      if (!window.confirm('Zamienić nagłówek na danie? Pozycje pod nim przejdą do poprzedniej kategorii. Uzupełnij cenę dania.')) {render();return;}
      if (categoryAt(index-1)<0) { rows.unshift(newRow('category','Pozostałe')); index++; }
    }
    rows[index].kind=kind;
    changed();render();
  }
  function removeRow(index) {
    const row=rows[index];
    if (!window.confirm(`Usunąć ${row.kind==='category'?'kategorię':'pozycję'} „${row.name || '(bez nazwy)'}” z podglądu? Dane w bazie pozostaną bez zmian.`)) return;
    rows.splice(index,1);
    if (rows.length && rows[0].kind!=='category') rows.unshift(newRow('category','Pozostałe'));
    changed();render();
  }
  function addItemAfterCategory(catRow) {
    const catIndex=rows.indexOf(catRow);
    let end=catIndex+1;
    while(end<rows.length && rows[end].kind!=='category') end++;
    rows.splice(end,0,newRow('item',''));
    changed();render();
  }
  function miniButton(label, title, cb, disabled=false) {
    const btn=h('button','polana-mini',label);
    btn.type='button'; btn.title=title; btn.setAttribute('aria-label',title);
    btn.disabled=disabled;
    btn.addEventListener('click',cb);
    return btn;
  }
  function labelInput(caption, value, change, placeholder='') {
    const label=h('label','',caption), input=h('input');
    input.type='text'; input.value=value; input.placeholder=placeholder; input.autocomplete='off';
    input.addEventListener('input', e=>change(e.target.value));
    label.appendChild(input);return label;
  }
  function render() {
    mount.replaceChildren();
    const toolbar=h('div','polana-editor-toolbar');
    toolbar.appendChild(miniButton('+ Kategoria','Dodaj kategorię',()=>{rows.push(newRow('category','Nowa kategoria'));changed();render();}));
    toolbar.appendChild(miniButton('+ Danie / wino','Dodaj pozycję do ostatniej kategorii',()=>{
      if (!rows.some(r=>r.kind==='category')) rows.unshift(newRow('category','Pozostałe'));
      rows.push(newRow('item',''));changed();render();
    }));
    const instr=h('span','polana-edit-note','↑ ↓ zmieniają kolejność. „Kategoria / Danie” zmienia wygląd pozycji w menu i PDF.');
    toolbar.appendChild(instr); mount.appendChild(toolbar);
    rows.forEach((row,index)=>{
      const category=row.kind==='category';
      const section=h('article','polana-edit-row '+(category?'kind-category':'kind-item'));
      section.dataset.rowid=String(row.id);
      if (!category && !row.price.trim() && !row.price_text.trim()) section.classList.add('needs-price');
      const kindWrap=h('label','','Rodzaj wiersza');
      const kindSel=h('select');
      [['category','Kategoria (nagłówek)'],['item','Danie / napój / wino']].forEach(([v,name])=>{
        const opt=h('option','',name);opt.value=v;opt.selected=(v===row.kind);kindSel.appendChild(opt);
      });
      kindSel.addEventListener('change',e=>setKind(index,e.target.value));
      kindWrap.appendChild(kindSel);section.appendChild(kindWrap);
      section.appendChild(labelInput(category?'Nazwa kategorii':'Nazwa pozycji',row.name,v=>{row.name=v;changed();},'Wpisz pełną nazwę'));
      if (!category) {
        section.appendChild(labelInput('Cena w zł (np. 35)',row.price,v=>{
          row.price=v;changed();section.classList.toggle('needs-price', !v.trim()&&!row.price_text.trim());
        },'35 lub 35,50'));
        section.appendChild(labelInput('Cena opisowa / wina (opcjonalna)',row.price_text,v=>{
          row.price_text=v;changed();section.classList.toggle('needs-price', !v.trim()&&!row.price.trim());
        },'125 ml – 50 zł / 750 ml – 236 zł'));
      }
      const actions=h('div','polana-edit-actions');
      const cats=groupStarts();
      if(category) {
        const p=cats.indexOf(index);
        actions.appendChild(miniButton('↑','Przenieś kategorię z jej daniami wyżej',()=>swapCategory(index,-1),p===0));
        actions.appendChild(miniButton('↓','Przenieś kategorię z jej daniami niżej',()=>swapCategory(index,1),p===cats.length-1));
        actions.appendChild(miniButton('+ Danie','Dodaj pozycję w tej kategorii',()=>addItemAfterCategory(row)));
      } else {
        actions.appendChild(miniButton('↑','Przenieś pozycję wyżej',()=>shiftItem(index,-1),index<=0||rows[index-1].kind==='category'));
        actions.appendChild(miniButton('↓','Przenieś pozycję niżej',()=>shiftItem(index,1),index===rows.length-1||rows[index+1].kind==='category'));
        if (cats.length>1) {
          const choose=h('select');choose.setAttribute('aria-label','Przenieś do innej kategorii');
          const defaultOption=h('option','','Przenieś do…');defaultOption.value='';choose.appendChild(defaultOption);
          const own=categoryAt(index);
          cats.forEach(catIdx=>{
            if(catIdx===own) return;
            const opt=h('option','',rows[catIdx].name);opt.value=String(rows[catIdx].id);choose.appendChild(opt);
          });
          choose.addEventListener('change',e=>{if(e.target.value)moveToCategory(index,Number(e.target.value));});
          actions.appendChild(choose);
        }
      }
      actions.appendChild(miniButton('×','Usuń ten wiersz z podglądu',()=>removeRow(index)));
      section.appendChild(actions);mount.appendChild(section);
    });
    refreshCounts();
    submit.disabled=false;
  }
  function serialize() {
    return rows.map(({kind,name,price,price_text,description})=>({kind,name,price,price_text,description}));
  }
  form.addEventListener('submit',event=>{
    if (submitting) {event.preventDefault();return;}
    if (rows.length===0 || rows[0].kind!=='category') {
      event.preventDefault();window.alert('Najpierw dodaj kategorię u góry karty.');return;
    }
    const invalid=rows.findIndex(r=>!r.name.trim() || (r.kind==='item'&&!r.price.trim()&&!r.price_text.trim()));
    if (invalid>=0) {
      event.preventDefault();
      window.alert('Wiersz '+(invalid+1)+': wpisz nazwę oraz cenę dania (lub usuń pustą pozycję).');
      mount.querySelectorAll('.polana-edit-row')[invalid]?.scrollIntoView({block:'center',behavior:'smooth'});
      return;
    }
    if (!rows.some(r=>r.kind==='item')) {
      event.preventDefault();window.alert('Dodaj co najmniej jedną pozycję.');return;
    }
    field.value=JSON.stringify(serialize());
    if (field.value.length>350000) {event.preventDefault();window.alert('Karta jest za długa.');return;}
    submitting=true;
    submit.disabled=true;
  });
  window.addEventListener('beforeunload', event=>{
    if (dirty && !submitting) {event.preventDefault();event.returnValue='';}
  });
  render();
})();

Youez - 2016 - github.com/yon3zu
LinuXploit