← back to depelo__bobine

Function bodies 262 total

All specs Real LLM only Function bodies
askDynamicPrompt function · javascript · L69-L135 (67 LOC)
bobine.js
function askDynamicPrompt(title, type, showScanner) {
  return new Promise((resolve, reject) => {
    const modal = document.getElementById('dynamicPromptModal');
    if (!modal) {
      reject('modal-missing');
      return;
    }
    const titleEl = document.getElementById('dpTitle');
    const input = document.getElementById('dpInput');
    const scanBtn = document.getElementById('dpScanBtn');
    if (titleEl) titleEl.textContent = title;
    if (!input || !scanBtn) {
      reject('input-missing');
      return;
    }

    input.type = type;
    input.value = '';
    scanBtn.style.display = showScanner ? '' : 'none';
    input.style.borderRadius = showScanner ? 'var(--radius) 0 0 var(--radius)' : 'var(--radius)';

    modal.classList.add('is-open');
    modal.setAttribute('aria-hidden', 'false');

    const confirmBtn = document.getElementById('dpConfirmBtn');
    const cancelBtn = document.getElementById('dpCancelBtn');
    if (!confirmBtn || !cancelBtn) {
      reject('buttons-mis
askMachinePrompt function · javascript · L137-L170 (34 LOC)
bobine.js
function askMachinePrompt() {
  return new Promise((resolve, reject) => {
    const modal = document.getElementById('machinePromptModal');
    const listEl = document.getElementById('mpMachineList');
    const cancelBtn = document.getElementById('mpCancelBtn');
    if (!modal || !listEl || !cancelBtn) {
      reject('modal-missing');
      return;
    }

    listEl.innerHTML = '';
    state.machines.forEach((m) => {
      const li = document.createElement('li');
      li.innerHTML = `<span>${m.name}</span>`;
      li.onclick = () => {
        document.activeElement?.blur();
        modal.classList.remove('is-open');
        modal.setAttribute('aria-hidden', 'true');
        resolve(m.id);
      };
      listEl.appendChild(li);
    });

    modal.classList.add('is-open');
    modal.setAttribute('aria-hidden', 'false');

    cancelBtn.onclick = () => {
      document.activeElement?.blur();
      modal.classList.remove('is-open');
      modal.setAttribute('aria-hidden', 'true');
      rej
askBobinaFinitaAsync function · javascript · L172-L205 (34 LOC)
bobine.js
function askBobinaFinitaAsync() {
  return new Promise((resolve, reject) => {
    const modal = document.getElementById('bobinaModal');
    const yesBtn = document.getElementById('bobinaBtnYes');
    const noBtn = document.getElementById('bobinaBtnNo');
    const cancelBtn = document.getElementById('bobinaBtnCancel');
    if (!modal || !yesBtn || !noBtn || !cancelBtn) {
      reject('modal-missing');
      return;
    }

    modal.classList.add('is-open');
    modal.setAttribute('aria-hidden', 'false');

    yesBtn.onclick = () => {
      document.activeElement?.blur();
      modal.classList.remove('is-open');
      modal.setAttribute('aria-hidden', 'true');
      resolve(true);
    };
    noBtn.onclick = () => {
      document.activeElement?.blur();
      modal.classList.remove('is-open');
      modal.setAttribute('aria-hidden', 'true');
      resolve(false);
    };
    cancelBtn.onclick = () => {
      document.activeElement?.blur();
      modal.classList.remove('is-open');
      mod
fetchData function · javascript · L207-L233 (27 LOC)
bobine.js
async function fetchData(endpoint) {
  const res = await fetch(`${API_URL}${endpoint}`, {
    credentials: 'include'
  });
  if (res.status === 401) {
    window.location.href = '/';
    throw new Error(`HTTP ${res.status}: autorizzazione richiesta`);
  }
  if (res.status === 403) {
    let data = null;
    try {
      data = await res.json();
    } catch {
      // ignore JSON parse errors
    }
    if (data && data.requiresPasswordChange) {
      // Reindirizza al nuovo modulo profilo standalone per la gestione del cambio password
      window.location.href = '/profile.html';
      throw new Error('HTTP 403: cambio password obbligatorio');
    }
    window.location.href = '/';
    const msg = data && data.message ? data.message : 'autorizzazione richiesta';
    throw new Error(`HTTP 403: ${msg}`);
  }
  if (!res.ok) throw new Error(`HTTP ${res.status}: ${res.statusText}`);
  return res.json();
}
loadInitialData function · javascript · L235-L259 (25 LOC)
bobine.js
async function loadInitialData() {
  try {
    const [operators, machines, logs] = await Promise.all([
      fetchData('/operators'),
      fetchData('/machines'),
      fetchData('/logs')
    ]);
    state.operators = operators;
    state.machines = machines;
    state.logs = logs;
  } catch (err) {
    console.error(err);
    alert('Impossibile caricare i dati. Verifica che il backend sia avviato su http://localhost:3000');
    state.operators = [];
    state.machines = [];
    state.logs = [];
  }
  populateMachineSelect();
  renderLogList(state.logs);
  renderOperatorList(state.operators);
  renderSimpleList(machineListEl, state.machines, pickMachineFromList);
  resetForm();
  applyPermissions();
  setScreen('log-edit');
}
updateCurrentOperatorUI function · javascript · L277-L304 (28 LOC)
bobine.js
function updateCurrentOperatorUI() {
  if (!currentOperatorDisplay) return;
  if (state.currentOperator) {
    const name =
      state.currentOperator.name ||
      'Operatore';
    const isAdmin =
      state.currentOperator.isAdmin === true ||
      state.currentOperator.isAdmin === 1;

    currentOperatorDisplay.textContent = name;

    if (isAdmin) {
      currentOperatorDisplay.style.backgroundColor = '#d4edda';
      currentOperatorDisplay.style.color = '#155724';
      currentOperatorDisplay.style.borderColor = '#c3e6cb';
    } else {
      currentOperatorDisplay.style.backgroundColor = '#e9ecef';
      currentOperatorDisplay.style.color = '#495057';
      currentOperatorDisplay.style.borderColor = '#ced4da';
    }
  } else {
    currentOperatorDisplay.textContent = 'Nessun operatore loggato';
    currentOperatorDisplay.style.backgroundColor = '#e9ecef';
    currentOperatorDisplay.style.color = 'var(--text-muted)';
    currentOperatorDisplay.style.borderColor = 'var(--border)';
toDateInputValue function · javascript · L308-L312 (5 LOC)
bobine.js
function toDateInputValue(dateString) {
  const datePart = dateString.split(' ')[0];
  const [day, month, year] = datePart.split('/');
  return `${year}-${month}-${day}`;
}
Same scanner, your repo: https://repobility.com — Repobility
updateDynamicRollId function · javascript · L315-L338 (24 LOC)
bobine.js
function updateDynamicRollId() {
  const rawCode = (form.rawCode && form.rawCode.value ? form.rawCode.value : '').trim();
  const lot = (form.lot && form.lot.value ? form.lot.value : '').trim();
  const rollInput = document.getElementById('rollId');
  if (!rollInput) return;

  if (!state.logs || state.logs.length === 0) {
    rollInput.value = '0';
    return;
  }

  const sorted = [...state.logs].sort((a, b) => new Date(b.date) - new Date(a.date));
  const lastLog = sorted[0];
  const lastCodart = (lastLog.rawCode != null ? String(lastLog.rawCode) : '').trim();
  const lastLot = (lastLog.lot != null ? String(lastLog.lot) : '').trim();

  if (rawCode === lastCodart && lot === lastLot) {
    const lastRoll = parseInt(lastLog.rollId, 10);
    const next = (Number.isNaN(lastRoll) ? 0 : lastRoll) + 1;
    rollInput.value = String(next);
  } else {
    rollInput.value = '0';
  }
}
displayDate function · javascript · L341-L347 (7 LOC)
bobine.js
function displayDate(dateStr) {
  if (dateStr == null || dateStr === '') return '-';
  const cleanDateStr = String(dateStr).replace('Z', '');
  const d = new Date(cleanDateStr);
  if (Number.isNaN(d.getTime())) return String(dateStr);
  return d.toLocaleDateString('it-IT') + ' ' + d.toLocaleTimeString('it-IT', { hour: '2-digit', minute: '2-digit' });
}
initCombobox function · javascript · L349-L421 (73 LOC)
bobine.js
function initCombobox(inputId, dropdownId, getItems, getValueFromItem, clearOptionLabel, onSelectItem, onClear) {
  const input = document.getElementById(inputId);
  const dropdown = document.getElementById(dropdownId);
  const wrap = input.closest('.combobox-wrap');

  function filterItems(query) {
    const q = (query || '').trim().toLowerCase();
    const items = getItems();
    if (!q) return items;
    return items.filter(
      (item) =>
        String(item.id).toLowerCase().includes(q) ||
        String(item.name).toLowerCase().includes(q)
    );
  }

  function renderDropdown() {
    const query = input.value.trim();
    const filtered = filterItems(query);
    dropdown.innerHTML = '';

    if (clearOptionLabel) {
      const clearOpt = document.createElement('div');
      clearOpt.setAttribute('role', 'option');
      clearOpt.className = 'combobox-clear';
      clearOpt.textContent = clearOptionLabel;
      clearOpt.addEventListener('click', () => {
        input.value = '';
filterItems function · javascript · L354-L363 (10 LOC)
bobine.js
  function filterItems(query) {
    const q = (query || '').trim().toLowerCase();
    const items = getItems();
    if (!q) return items;
    return items.filter(
      (item) =>
        String(item.id).toLowerCase().includes(q) ||
        String(item.name).toLowerCase().includes(q)
    );
  }
renderDropdown function · javascript · L365-L397 (33 LOC)
bobine.js
  function renderDropdown() {
    const query = input.value.trim();
    const filtered = filterItems(query);
    dropdown.innerHTML = '';

    if (clearOptionLabel) {
      const clearOpt = document.createElement('div');
      clearOpt.setAttribute('role', 'option');
      clearOpt.className = 'combobox-clear';
      clearOpt.textContent = clearOptionLabel;
      clearOpt.addEventListener('click', () => {
        input.value = '';
        if (typeof onClear === 'function') onClear();
        wrap.classList.remove('is-open');
        dropdown.setAttribute('aria-hidden', 'true');
      });
      dropdown.appendChild(clearOpt);
    }

    filtered.forEach((item) => {
      const opt = document.createElement('div');
      opt.setAttribute('role', 'option');
      opt.textContent = `${item.id} - ${item.name}`;
      opt.addEventListener('click', () => {
        input.value = getValueFromItem(item);
        if (typeof onSelectItem === 'function') onSelectItem(item);
        wrap.classList.re
openDropdown function · javascript · L399-L402 (4 LOC)
bobine.js
  function openDropdown() {
    wrap.classList.add('is-open');
    renderDropdown();
  }
closeDropdown function · javascript · L404-L407 (4 LOC)
bobine.js
  function closeDropdown() {
    wrap.classList.remove('is-open');
    dropdown.setAttribute('aria-hidden', 'true');
  }
populateSelect function · javascript · L423-L438 (16 LOC)
bobine.js
function populateSelect(select, items, placeholderLabel) {
  if (!select) return;
  select.innerHTML = '';

  const ph = document.createElement('option');
  ph.value = '';
  ph.textContent = placeholderLabel;
  select.appendChild(ph);

  items.forEach((item) => {
    const option = document.createElement('option');
    option.value = item.id != null ? String(item.id) : '';
    option.textContent = item.name;
    select.appendChild(option);
  });
}
Repobility analyzer · published findings · https://repobility.com
populateOperatorSelect function · javascript · L440-L442 (3 LOC)
bobine.js
function populateOperatorSelect() {
  // Se in futuro servirà un select per operatori, si potrà riutilizzare questa funzione.
}
populateMachineSelect function · javascript · L444-L447 (4 LOC)
bobine.js
function populateMachineSelect() {
  if (!machineSelect) return;
  populateSelect(machineSelect, state.machines, 'Seleziona macchina');
}
applyPermissions function · javascript · L451-L485 (35 LOC)
bobine.js
function applyPermissions() {
  const isAdmin = state.currentOperator?.isAdmin === true;
  const hasOperator = state.currentOperator != null;
  const isSuperuser = state.currentOperator?.isSuperuser === true;

  const lastLogByID = state.logs.length > 0
    ? state.logs.reduce((a, b) => (Number(a.uniqueRecordId) > Number(b.uniqueRecordId) ? a : b))
    : null;
  const isLastRecord = state.selectedLog && lastLogByID &&
    Number(state.selectedLog.uniqueRecordId) === Number(lastLogByID.uniqueRecordId);

  document.querySelectorAll('[data-action]').forEach((el) => {
    const action = el.dataset.action;
    if (ADMIN_ONLY_ACTIONS.includes(action)) {
      el.style.display = isAdmin ? '' : 'none';
      return;
    }
    if (action === 'edit-from-detail') {
      el.style.display = hasOperator ? '' : 'none';
      el.disabled = !hasOperator;
      return;
    }
    if (action === 'delete-log') {
      const canDelete = isAdmin || isLastRecord;
      el.style.display = canDelete ? '' : 'no
createActionButtons function · javascript · L487-L509 (23 LOC)
bobine.js
function createActionButtons(leftActions, rightActions) {
  actionsLeftEl.innerHTML = '';
  actionsRightEl.innerHTML = '';
  (leftActions || []).forEach((item) => {
    const btn = document.createElement('button');
    btn.className = 'action-btn';
    btn.type = 'button';
    btn.textContent = item.icon;
    btn.title = item.title;
    btn.dataset.action = item.action;
    actionsLeftEl.appendChild(btn);
  });
  (rightActions || []).forEach((item) => {
    const btn = document.createElement('button');
    btn.className = 'action-btn';
    btn.type = 'button';
    btn.textContent = item.icon;
    btn.title = item.title;
    btn.dataset.action = item.action;
    actionsRightEl.appendChild(btn);
  });
  applyPermissions();
}
setScreen function · javascript · L511-L526 (16 LOC)
bobine.js
function setScreen(name) {
  state.currentScreen = name;
  if (name !== 'log-detail') state.detailEditMode = false;

  screens.forEach((section) => {
    section.classList.toggle('is-visible', section.dataset.screen === name);
  });

  navButtons.forEach((btn) => {
    btn.classList.toggle('is-active', btn.dataset.screenTarget === name);
  });

  const meta = screenMeta[name] ?? { title: 'Registro', leftActions: [], rightActions: [] };
  titleEl.textContent = meta.title;
  createActionButtons(meta.leftActions, meta.rightActions);
}
fillForm function · javascript · L528-L542 (15 LOC)
bobine.js
function fillForm(record) {
  form.rawCode.value = record.rawCode ?? '';
  form.lot.value = record.lot ?? '';
  form.quantity.value = record.quantity ?? '';
  form.notes.value = record.notes ?? '';
  form.rollId.value = record.rollId ?? '';

  const idMach = record.IDMachine != null ? Number(record.IDMachine) : null;
  state.formDraft.IDMachine = idMach;

  const mach = state.machines.find((m) => Number(m.id) === idMach);

  if (machineSelect) machineSelect.value = idMach != null ? String(idMach) : '';
  applyPermissions();
}
formToPayload function · javascript · L544-L561 (18 LOC)
bobine.js
function formToPayload() {
  const opId = state.currentOperator && state.currentOperator.id != null ? Number(state.currentOperator.id) : null;
  const machId = machineSelect && machineSelect.value !== '' ? parseInt(machineSelect.value, 10) : null;

  state.formDraft.IDOperator = opId;
  state.formDraft.IDMachine = machId;

  return {
    date: new Date().toISOString(),
    rawCode: form.rawCode.value,
    lot: form.lot.value,
    quantity: form.quantity.value ? Number(form.quantity.value) : 0,
    notes: form.notes.value,
    rollId: form.rollId.value,
    IDOperator: opId,
    IDMachine: machId
  };
}
renderLogDetail function · javascript · L563-L604 (42 LOC)
bobine.js
function renderLogDetail(record) {
  detailGrid.innerHTML = '';

  const dateContainer = document.createElement('div');
  dateContainer.textContent = displayDate(record.date);

  if (state.currentOperator?.isAdmin && record.NumeroModifiche > 0) {
    const historyLink = document.createElement('span');
    historyLink.className = 'history-link';
    historyLink.textContent = `(modificato ${record.NumeroModifiche} volte)`;
    historyLink.onclick = () => openHistoryModal(record.uniqueRecordId);
    dateContainer.appendChild(historyLink);
  }

  const rows = [
    ['Data', dateContainer],
    ['Operatore', record.operator ?? '-'],
    ['Macchina', record.machine ?? '-'],
    ['Codice Articolo', record.rawCode ?? '-'],
    ['Lotto', record.lot ?? '-'],
    ['Quantità', record.quantity != null ? String(record.quantity) : '-'],
    ['Note', record.notes ?? '-'],
    ['ID Bobina', record.rollId ?? '-'],
    ['Bobina Finita', record.bobina_finita === true ? 'Sì' : record.bobina_finita === fals
Source: Repobility analyzer · https://repobility.com
renderLogDetailEditMode function · javascript · L606-L669 (64 LOC)
bobine.js
function renderLogDetailEditMode(record) {
  const staticRows = [
    ['Data', displayDate(record.date)],
    ['Operatore Originale', record.operator ?? '-'],
    ['ID Bobina', record.rollId ?? '-']
  ];

  detailGrid.innerHTML = '';
  staticRows.forEach(([k, v]) => {
    const key = document.createElement('p');
    key.className = 'k';
    key.textContent = k;
    const value = document.createElement('p');
    value.className = 'v';
    value.textContent = v;
    detailGrid.append(key, value);
  });

  const editableRows = [
    ['Quantità', 'quantity', 'number', record.quantity != null ? String(record.quantity) : ''],
    ['Codice Articolo', 'rawCode', 'text', record.rawCode ?? ''],
    ['Lotto', 'lot', 'text', record.lot ?? ''],
    ['Note', 'notes', 'textarea', record.notes ?? ''],
    ['Bobina Finita', 'bobinaFinita', 'select', record.bobina_finita == null ? '' : String(record.bobina_finita)]
  ];

  editableRows.forEach(([label, fieldId, type, val]) => {
    const key = document.
getDetailEditCurrentValues function · javascript · L671-L683 (13 LOC)
bobine.js
function getDetailEditCurrentValues() {
  const quantityEl = document.getElementById('detailEdit-quantity');
  const rawCodeEl = document.getElementById('detailEdit-rawCode');
  const lotEl = document.getElementById('detailEdit-lot');
  const notesEl = document.getElementById('detailEdit-notes');
  if (!quantityEl || !rawCodeEl || !lotEl || !notesEl) return null;
  return {
    quantity: quantityEl.value.trim(),
    rawCode: rawCodeEl.value.trim(),
    lot: lotEl.value.trim(),
    notes: notesEl.value.trim()
  };
}
hasDetailEditChanges function · javascript · L685-L706 (22 LOC)
bobine.js
function hasDetailEditChanges() {
  if (!state.detailEditInitial) {
    console.log('hasDetailEditChanges: stato iniziale mancante, permetto comunque il salvataggio.');
    return true;
  }
  const current = getDetailEditCurrentValues();
  if (!current) {
    console.log('hasDetailEditChanges: valori correnti non disponibili, permetto comunque il salvataggio.');
    return true;
  }
  const hasChanges =
    current.quantity !== state.detailEditInitial.quantity ||
    current.rawCode !== state.detailEditInitial.rawCode ||
    current.lot !== state.detailEditInitial.lot ||
    current.notes !== state.detailEditInitial.notes;
  console.log('hasDetailEditChanges:', {
    initial: state.detailEditInitial,
    current,
    hasChanges
  });
  return hasChanges;
}
setupDetailEditChangeTracking function · javascript · L708-L733 (26 LOC)
bobine.js
function setupDetailEditChangeTracking(record) {
  state.detailEditInitial = {
    quantity: record.quantity != null ? String(record.quantity) : '',
    rawCode: record.rawCode ?? '',
    lot: record.lot ?? '',
    notes: record.notes ?? ''
  };

  const saveBtn = document.querySelector('#topbarActionsRight [data-action="save-detail-edit"]');
  const updateSaveButtonState = () => {
    if (!saveBtn) return;
    const hasChanges = hasDetailEditChanges();
    console.log('updateSaveButtonState:', { hasChanges });
    saveBtn.disabled = !hasChanges;
    saveBtn.classList.toggle('is-disabled', !hasChanges);
  };

  ['detailEdit-quantity', 'detailEdit-rawCode', 'detailEdit-lot', 'detailEdit-notes'].forEach((id) => {
    const el = document.getElementById(id);
    if (!el) return;
    el.addEventListener('input', updateSaveButtonState);
    el.addEventListener('change', updateSaveButtonState);
  });

  updateSaveButtonState();
}
exitDetailEditMode function · javascript · L735-L744 (10 LOC)
bobine.js
function exitDetailEditMode() {
  state.detailEditMode = false;
  state.detailEditInitial = null;
  if (state.selectedLog) {
    renderLogDetail(state.selectedLog);
  }
  const meta = screenMeta['log-detail'] ?? { leftActions: [], rightActions: [] };
  createActionButtons(meta.leftActions, meta.rightActions);
  applyPermissions();
}
renderLogList function · javascript · L746-L799 (54 LOC)
bobine.js
function renderLogList(items) {
  logListEl.innerHTML = '';
  items.forEach((log) => {
    const li = document.createElement('li');

    // 1. Estrai solo la data (senza l'ora) dividendo la stringa
    const dateOnly = displayDate(log.date).split(' ')[0];

    // 2. Prepara le variabili con fallback se vuote
    const machineName = log.machine || '-';
    const code = log.rawCode || '-';
    const lot = log.lot || '-';
    const qty = log.quantity != null ? log.quantity : '-';

    // 3. Verifica le condizioni per colorare la riga in blu (Admin + Record modificato)
    const isAdmin = state.currentOperator?.isAdmin === true || state.currentOperator?.isAdmin === 1;
    if (isAdmin && log.NumeroModifiche > 0) {
      li.classList.add('is-modified-admin');
    }

    // 4. Costruisci il nuovo layout
    li.innerHTML = `
      <div class="log-card-content">
        <div class="log-card-row">
          <span class="log-date">${dateOnly}</span>
          <span class="log-machine">${machineNa
renderSimpleList function · javascript · L801-L808 (8 LOC)
bobine.js
function renderSimpleList(rootEl, items, onPick) {
  rootEl.innerHTML = '';
  items.forEach((item) => {
    const li = document.createElement('li');
    li.innerHTML = `<span>${item.name}</span>`;
    rootEl.appendChild(li);
  });
}
renderOperatorList function · javascript · L810-L843 (34 LOC)
bobine.js
function renderOperatorList(items) {
  operatorListEl.innerHTML = '';
  const sortedItems = items.slice().sort((a, b) => (a.name || '').localeCompare(b.name || '', 'it'));
  sortedItems.forEach((op) => {
    const li = document.createElement('li');
    li.style.display = 'flex';
    li.style.justifyContent = 'space-between';
    li.style.alignItems = 'center';
    li.style.padding = '12px';
    
    let alertIcon = op.resetRequested ? '<span style="display: inline-block; width: 10px; height: 10px; background-color: var(--danger); border-radius: 50%; margin-left: 8px; box-shadow: 0 0 5px rgba(220, 53, 69, 0.5);" title="Ha richiesto il reset della password"></span>' : '';
    let adminIcon = op.isAdmin ? '<span style="font-size: 0.8rem; background: var(--primary); color: white; padding: 2px 6px; border-radius: 12px; margin-left: 8px;">Admin</span>' : '';

    li.innerHTML = `
      <div style="font-weight: bold; color: var(--text);">
        ${op.name} ${alertIcon} ${adminIcon}
        <
Want this analysis on your repo? https://repobility.com/scan/
sortByName function · javascript · L847-L854 (8 LOC)
bobine.js
function sortByName(listKey) {
  const list = listKey === 'operators' ? state.operators : state.machines;
  list.sort((a, b) => {
    const result = (a.name || '').localeCompare(b.name || '', 'it');
    return state.sortAsc ? result : -result;
  });
  state.sortAsc = !state.sortAsc;
}
applySearch function · javascript · L856-L862 (7 LOC)
bobine.js
function applySearch(inputId, data, renderFn) {
  const el = document.getElementById(inputId);
  if (!el) return;
  const query = el.value.trim().toLowerCase();
  const filtered = data.filter((item) => JSON.stringify(item).toLowerCase().includes(query));
  renderFn(filtered);
}
resetForm function · javascript · L864-L872 (9 LOC)
bobine.js
function resetForm() {
  form.reset();
  state.formDraft = {};
  state.selectedLog = null;
  if (machineSelect) machineSelect.value = '';
  updateDynamicRollId();
  applyPermissions();
  updateCurrentOperatorUI();
}
handleTopbarAction function · javascript · L874-L1220 (347 LOC)
bobine.js
async function handleTopbarAction(action) {
  if (action === 'cancel-log') {
    if (state.selectedLog) {
      fillForm(state.selectedLog);
    } else {
      resetForm();
    }
    return;
  }

  if (action === 'new-log') {
    resetForm();
    setScreen('log-edit');
    return;
  }

  if (action === 'save-log') {
    // Step 1: Operator check
    if (!state.currentOperator) {
      openLoginModal();
      return;
    }

    // Step 2: Machine check
    if (!machineSelect || !machineSelect.value) {
      try {
        const machId = await askMachinePrompt();
        if (machineSelect) machineSelect.value = machId;
        state.formDraft.IDMachine = parseInt(machId, 10);
      } catch (e) {
        return;
      }
    }

    // Step 3: Data fields check
    if (!form.rawCode.value.trim()) {
      try {
        form.rawCode.value = await askDynamicPrompt('Inserisci Codice Materia', 'text', true);
        updateDynamicRollId();
      } catch (e) {
        return;
      }
    }

    if 
pickOperatorFromList function · javascript · L1222-L1224 (3 LOC)
bobine.js
function pickOperatorFromList(operator) {
  // Manteniamo per compatibilità futura; al momento il login è gestito via JWT.
}
pickMachineFromList function · javascript · L1226-L1230 (5 LOC)
bobine.js
function pickMachineFromList(machine) {
  state.formDraft.IDMachine = machine.id != null ? Number(machine.id) : machine.id;
  if (machineSelect) machineSelect.value = machine.id != null ? String(machine.id) : '';
  if (state.returnFromLookupTo === 'log-edit') setScreen('log-edit');
}
openMenuDrawer function · javascript · L1269-L1274 (6 LOC)
bobine.js
function openMenuDrawer() {
  document.getElementById('menuDrawer').classList.add('is-open');
  document.getElementById('menuDrawer').setAttribute('aria-hidden', 'false');
  document.getElementById('menuDrawerBackdrop').classList.add('is-open');
  document.getElementById('menuDrawerBackdrop').setAttribute('aria-hidden', 'false');
}
closeMenuDrawer function · javascript · L1276-L1290 (15 LOC)
bobine.js
function closeMenuDrawer() {
  const drawer = document.getElementById('menuDrawer');
  const backdrop = document.getElementById('menuDrawerBackdrop');
  if (document.activeElement && drawer && drawer.contains(document.activeElement)) {
    document.activeElement.blur();
  }
  if (drawer) {
    drawer.classList.remove('is-open');
    drawer.setAttribute('aria-hidden', 'true');
  }
  if (backdrop) {
    backdrop.classList.remove('is-open');
    backdrop.setAttribute('aria-hidden', 'true');
  }
}
Same scanner, your repo: https://repobility.com — Repobility
loginByBarcode function · javascript · L1346-L1369 (24 LOC)
bobine.js
function loginByBarcode(barcode, type = 'operator') {
  const code = String(barcode || '').trim();
  if (!code) return;

  if (type === 'machine') {
    const machine = state.machines.find((m) => String(m.barcode || '').trim() === code);
    if (!machine) {
      alert('Macchina non trovata per il barcode fornito.');
      return;
    }
    if (!machineSelect) return;

    let option = Array.from(machineSelect.options).find((opt) => opt.value === String(machine.id));
    if (!option) {
      option = document.createElement('option');
      option.value = machine.id != null ? String(machine.id) : '';
      option.textContent = `${machine.id} - ${machine.name}`;
      machineSelect.appendChild(option);
    }

    machineSelect.value = machine.id != null ? String(machine.id) : '';
    state.formDraft.IDMachine = machine.id != null ? Number(machine.id) : machine.id;
  }
}
playBarcodeBeep function · javascript · L1371-L1379 (9 LOC)
bobine.js
function playBarcodeBeep() {
  const audio = document.getElementById('barcodeBeepSound');
  if (!audio) return;

  audio.currentTime = 0;
  audio.play().catch((error) => {
    console.warn("Impossibile riprodurre il beep:", error);
  });
}
closeBarcodeScanner function · javascript · L1381-L1398 (18 LOC)
bobine.js
function closeBarcodeScanner() {
  const modal = document.getElementById('scannerModal');
  if (modal) {
    modal.classList.remove('is-open');
    modal.setAttribute('aria-hidden', 'true');
  }
  if (barcodeScannerInstance) {
    if (isScannerRunning) {
      try {
        barcodeScannerInstance.stop().catch(() => {});
      } catch (e) {}
    }
    barcodeScannerInstance = null;
    isScannerRunning = false;
  }
  const container = document.getElementById('scannerContainer');
  if (container) container.innerHTML = '';
}
openBarcodeScanner function · javascript · L1400-L1473 (74 LOC)
bobine.js
function openBarcodeScanner(targetFieldId) {
  const modal = document.getElementById('scannerModal');
  const container = document.getElementById('scannerContainer');
  if (!modal || !container) return;

  if (typeof Html5Qrcode === 'undefined') {
    alert('Libreria scanner non disponibile. Controlla la connessione.');
    return;
  }

  modal.classList.add('is-open');
  modal.setAttribute('aria-hidden', 'false');
  container.innerHTML = '';

  const onSuccess = (decodedText) => {
    playBarcodeBeep();
    if (targetFieldId === 'operator') {
      loginByBarcode(decodedText, 'operator');
      closeBarcodeScanner();
      return;
    }
    if (targetFieldId === 'machine') {
      loginByBarcode(decodedText, 'machine');
      closeBarcodeScanner();
      return;
    }

    if (targetFieldId === 'dynamicPrompt') {
      const dpInput = document.getElementById('dpInput');
      if (dpInput) dpInput.value = decodedText;
      closeBarcodeScanner();
      return;
    }

    if (targetFiel
openHistoryModal function · javascript · L1483-L1510 (28 LOC)
bobine.js
async function openHistoryModal(logId) {
  try {
    const historyData = await fetchData(`/logs/${logId}/history`);
    const tbody = document.querySelector('#historyTable tbody');
    tbody.innerHTML = '';

    historyData.forEach(row => {
      const tr = document.createElement('tr');
      const dataLabel = row.NumeroModifiche === 0 ? 'Creazione Originale' : displayDate(row.validFrom);

      tr.innerHTML = `
        <td>${dataLabel}</td>
        <td>${row.operatorName ?? '-'}</td>
        <td>${row.quantity ?? '-'}</td>
        <td>${row.rawCode ?? '-'}</td>
        <td>${row.lot ?? '-'}</td>
        <td>${row.notes ?? '-'}</td>
      `;
      tbody.appendChild(tr);
    });

    const modal = document.getElementById('historyModal');
    modal.classList.add('is-open');
    modal.setAttribute('aria-hidden', 'false');
  } catch (err) {
    alert('Errore caricamento storico: ' + err.message);
  }
}
closeHistoryModal function · javascript · L1512-L1518 (7 LOC)
bobine.js
function closeHistoryModal() {
  const modal = document.getElementById('historyModal');
  if (modal) {
    modal.classList.remove('is-open');
    modal.setAttribute('aria-hidden', 'true');
  }
}
showSuccessModal function · javascript · L1583-L1589 (7 LOC)
bobine.js
function showSuccessModal() {
  const modal = document.getElementById('successModal');
  if (modal) {
    modal.classList.add('is-open');
    modal.setAttribute('aria-hidden', 'false');
  }
}
openManageOperatorModal function · javascript · L1644-L1671 (28 LOC)
bobine.js
function openManageOperatorModal(op) {
  const idEl = document.getElementById('manageOpId');
  const nameEl = document.getElementById('manageOpName');
  const pwdEl = document.getElementById('manageOpNewPwd');
  const forceEl = document.getElementById('manageOpForcePwd');
  const pwdSection = document.getElementById('manageOpPwdSection');
  const modal = document.getElementById('manageOperatorModal');

  if (!idEl || !nameEl || !pwdEl || !forceEl || !pwdSection || !modal) return;

  idEl.value = op.id;
  nameEl.textContent = op.name;
  pwdEl.value = '';
  forceEl.checked = true;

  if (op.resetRequested) {
    // Mostra la sezione di reset SOLO se è stato richiesto dall'utente
    pwdSection.style.display = 'block';
    pwdSection.style.borderColor = 'var(--danger)';
    pwdSection.style.boxShadow = '0 0 8px rgba(220, 53, 69, 0.2)';
  } else {
    // Nasconde completamente la possibilità di resettare la password
    pwdSection.style.display = 'none';
  }

  modal.classList.add('is-open
Repobility analyzer · published findings · https://repobility.com
buildDynamicMenu function · javascript · L1773-L1801 (29 LOC)
bobine.js
function buildDynamicMenu() {
  const apps = window.SecurityData?.user?.authorizedApps;
  if (!Array.isArray(apps)) return;

  const container = document.getElementById('dynamicMenuApps');
  if (!container) return;

  container.innerHTML = '';

  apps.forEach((app) => {
    const aid = Number(app.id);
    if (aid === 1 || aid === 2) return;

    let url = '';
    if (aid === 3) url = '/ET.html';
    if (aid === 4) url = '/gb2.html';
    if (!url) return;

    const btn = document.createElement('button');
    btn.type = 'button';
    btn.className = 'menu-drawer-btn';
    btn.textContent = app.name || 'App';
    btn.addEventListener('click', () => {
      closeMenuDrawer();
      window.location.href = url;
    });
    container.appendChild(btn);
  });
}
bootstrapFromSecurity function · javascript · L1803-L1836 (34 LOC)
bobine.js
function bootstrapFromSecurity() {
  if (!window.SecurityData || !window.SecurityData.user) {
    return;
  }

  const user = window.SecurityData.user;

  const mappedUser = {
    id:
      user.id ??
      user.IDUser ??
      user.IDOperator ??
      null,
    name:
      user.username ??
      user.Nome ??
      user.name ??
      'Operatore',
    isAdmin: user.isAdmin === true || user.isAdmin === 1,
    isSuperuser: user.isSuperuser === true || user.isSuperuser === 1
  };

  state.currentOperator = {
    ...(state.currentOperator || {}),
    ...mappedUser
  };

  updateCurrentOperatorUI();
  buildDynamicMenu();
  applyPermissions();
  void loadInitialData().then(() => {
    setScreen('log-edit');
  });
}
getKey function · javascript · L11-L17 (7 LOC)
config/crypto.js
function getKey() {
    const hex = process.env.DB_ENCRYPTION_KEY;
    if (!hex || hex.length !== 64) {
        throw new Error('DB_ENCRYPTION_KEY mancante o invalida nel .env (servono 64 caratteri hex)');
    }
    return Buffer.from(hex, 'hex');
}
page 1 / 6next ›