221 lines
9.4 KiB
JavaScript
221 lines
9.4 KiB
JavaScript
// ==UserScript==
|
||
// @name IDEAERP - Listy przewozowe
|
||
// @namespace http://tampermonkey.net/
|
||
// @version 1.0
|
||
// @description Kopiowanie elementów na stronach zamówień wysyłkowych - kliknij aby skopiować
|
||
// @match https://emma.ideaerp.pl/web*
|
||
// @icon https://emma.ideaerp.pl/web/image/res.company/1/favicon/
|
||
// @downloadURL https://n8n.emma.net.pl/webhook/order-shipping
|
||
// @updateURL https://n8n.emma.net.pl/webhook/order-shipping
|
||
// @grant GM_addStyle
|
||
// @grant GM_getValue
|
||
// @grant GM_setValue
|
||
// @grant GM_deleteValue
|
||
// @grant GM_registerMenuCommand
|
||
// ==/UserScript==
|
||
|
||
/* ========================OPIS==============================
|
||
WERSJA 1.0 - Kopiowanie elementów zamówień wysyłkowych
|
||
|
||
DZIAŁANIE SKRYPTU:
|
||
- Kopiowanie nazwy zamówienia - kliknij na nazwę zamówienia (h1) aby skopiować
|
||
- Kopiowanie numeru listu przewozowego - kliknij na element span[name="waybill"] aby skopiować
|
||
- Kopiowanie NIP faktury - kliknij na element span[name="invoice_vat"] aby skopiować
|
||
- Kopiowanie notatek - kliknij na element span[name="note"] aby skopiować
|
||
- Obsługa błędów w funkcjach kopiowania zgodnie z zasadami .rules
|
||
- Spójny styl wizualny ikon kopiowania (pomarańczowy kolor #ff9800)
|
||
|
||
AUTOMATYCZNE AKTUALIZACJE:
|
||
- Tampermonkey automatycznie sprawdza dostępność nowych wersji
|
||
- Jednoklikowa aktualizacja bez konieczności ręcznego pobierania
|
||
- Zachowanie ustawień użytkownika podczas aktualizacji
|
||
- Kompatybilność z systemem n8n do zarządzania wersjami
|
||
|
||
CHANGELOG:
|
||
v1.0 (2024) - PIERWSZA WERSJA SKRYPTU WYSYŁKOWEGO
|
||
- Utworzono dedykowany skrypt dla zamówień wysyłkowych (shipping.order)
|
||
- Dodano kopiowanie nazwy zamówienia (h1) z ikoną ⧉
|
||
- Dodano kopiowanie numeru listu przewozowego (span[name="waybill"]) z ikoną ⧉
|
||
- Dodano kopiowanie NIP faktury (span[name="invoice_vat"]) z ikoną ⧉
|
||
- Dodano kopiowanie notatek (span[name="note"]) z ikoną ⧉
|
||
- Dodano style CSS dla elementów span z ikonami kopiowania
|
||
- Dodano funkcję makeSpanCopyable() dla uniwersalnego kopiowania span
|
||
- Obsługa błędów w funkcjach kopiowania zgodnie z zasadami .rules
|
||
- Spójny styl wizualny ikon kopiowania (pomarańczowy kolor #ff9800)
|
||
- Podwyższenie numeru wersji do 1.0
|
||
|
||
AUTOR: Adam Grodecki
|
||
DATA: 2024
|
||
LICENCJA: Własność EMMA SPÓŁKA Z OGRANICZONĄ ODPOWIEDZIALNOŚCIĄ
|
||
================================================================ */
|
||
|
||
(function() {
|
||
'use strict';
|
||
|
||
// ——— Stałe ———
|
||
const STATE_KEY = 'tm_shipping_price_unit_visible';
|
||
const INIT_FLAG = 'tm_shipping_init_flag';
|
||
const COPY_MODE_KEY = 'tm_shipping_copy_mode';
|
||
const WIDTHS_KEY = 'tm_shipping_widths';
|
||
|
||
// ——— Style CSS ———
|
||
GM_addStyle(`
|
||
/* Kopiowanie nazwy zamówienia – ikona dla h1 */
|
||
h1.tm-copyable { cursor: copy; }
|
||
h1.tm-copyable::after {
|
||
content: '⧉'; /* symbol kopiowania */
|
||
display: inline-block; /* w tej samej linii co tekst */
|
||
margin-left: 8px; /* odstęp od tekstu */
|
||
font-size: 14px; /* większy rozmiar dla h1 */
|
||
line-height: 1;
|
||
color: #ff9800; /* pomarańczowy */
|
||
opacity: .75; /* widoczna także bez hovera */
|
||
vertical-align: baseline;
|
||
pointer-events: none;
|
||
transition: opacity .15s ease;
|
||
}
|
||
h1.tm-copyable:hover::after { opacity: 1; }
|
||
h1.tm-copyable.tm-copied {
|
||
outline: 2px solid #ff9800;
|
||
background-image: linear-gradient(90deg, rgba(255,152,0,.12), rgba(255,152,0,0));
|
||
}
|
||
|
||
/* Kopiowanie dla elementów span z określonymi name */
|
||
span.tm-copyable { cursor: copy; }
|
||
span.tm-copyable::after {
|
||
content: '⧉'; /* symbol kopiowania */
|
||
display: inline-block; /* w tej samej linii co tekst */
|
||
margin-left: 6px; /* odstęp od tekstu */
|
||
font-size: 12px; /* rozmiar jak dla komórek tabeli */
|
||
line-height: 1;
|
||
color: #ff9800; /* pomarańczowy */
|
||
opacity: .75; /* widoczna także bez hovera */
|
||
vertical-align: baseline;
|
||
pointer-events: none;
|
||
transition: opacity .15s ease;
|
||
}
|
||
span.tm-copyable:hover::after { opacity: 1; }
|
||
span.tm-copyable.tm-copied {
|
||
outline: 2px solid #ff9800;
|
||
background-image: linear-gradient(90deg, rgba(255,152,0,.12), rgba(255,152,0,0));
|
||
}
|
||
`);
|
||
|
||
// ——— Pomocnicze ———
|
||
function isShippingOrderForm() {
|
||
const params = new URLSearchParams((location.hash || '').replace(/^#/, ''));
|
||
const model = params.get('model');
|
||
const viewType = params.get('view_type');
|
||
return model === 'shipping.order' && viewType === 'form';
|
||
}
|
||
|
||
async function tmCopyToClipboard(text) {
|
||
try {
|
||
await navigator.clipboard.writeText(text);
|
||
}
|
||
catch {
|
||
const ta = document.createElement('textarea');
|
||
ta.value = text;
|
||
document.body.appendChild(ta);
|
||
ta.select();
|
||
document.execCommand('copy');
|
||
document.body.removeChild(ta);
|
||
}
|
||
}
|
||
|
||
// ——— Kopiowanie nazwy zamówienia ———
|
||
function makeOrderNameCopyable(h1Element) {
|
||
if (!h1Element || h1Element.dataset.tmOrderNameCopyable) return;
|
||
h1Element.dataset.tmOrderNameCopyable = '1';
|
||
h1Element.classList.add('tm-copyable');
|
||
h1Element.style.cursor = 'pointer';
|
||
h1Element.title = 'Kliknij aby skopiować nazwę zamówienia';
|
||
|
||
h1Element.addEventListener('click', async (e) => {
|
||
e.stopPropagation();
|
||
const orderName = (h1Element.textContent || '').trim();
|
||
if (!orderName) return;
|
||
|
||
try {
|
||
await tmCopyToClipboard(orderName);
|
||
const old = h1Element.title;
|
||
h1Element.title = `Skopiowano nazwę zamówienia: ${orderName}`;
|
||
h1Element.classList.add('tm-copied');
|
||
setTimeout(() => {
|
||
h1Element.title = old || 'Kliknij aby skopiować nazwę zamówienia';
|
||
h1Element.classList.remove('tm-copied');
|
||
}, 1200);
|
||
} catch (error) {
|
||
console.error('[Tampermonkey] Błąd podczas kopiowania nazwy zamówienia:', error);
|
||
h1Element.title = 'Błąd podczas kopiowania';
|
||
}
|
||
}, true); // capture=true
|
||
}
|
||
|
||
// ——— Kopiowanie elementów span z określonymi name ———
|
||
function makeSpanCopyable(spanElement, fieldName) {
|
||
if (!spanElement || spanElement.dataset.tmSpanCopyable) return;
|
||
spanElement.dataset.tmSpanCopyable = '1';
|
||
spanElement.classList.add('tm-copyable');
|
||
spanElement.style.cursor = 'pointer';
|
||
spanElement.title = `Kliknij aby skopiować ${fieldName}`;
|
||
|
||
spanElement.addEventListener('click', async (e) => {
|
||
e.stopPropagation();
|
||
const text = (spanElement.textContent || '').trim();
|
||
if (!text) return;
|
||
|
||
try {
|
||
await tmCopyToClipboard(text);
|
||
const old = spanElement.title;
|
||
spanElement.title = `Skopiowano ${fieldName}: ${text}`;
|
||
spanElement.classList.add('tm-copied');
|
||
setTimeout(() => {
|
||
spanElement.title = old || `Kliknij aby skopiować ${fieldName}`;
|
||
spanElement.classList.remove('tm-copied');
|
||
}, 1200);
|
||
} catch (error) {
|
||
console.error(`[Tampermonkey] Błąd podczas kopiowania ${fieldName}:`, error);
|
||
spanElement.title = 'Błąd podczas kopiowania';
|
||
}
|
||
}, true); // capture=true
|
||
}
|
||
|
||
// ——— Główna procedura ———
|
||
function processOnce() {
|
||
if (!isShippingOrderForm()) return;
|
||
if (!GM_getValue(INIT_FLAG)) { GM_setValue(INIT_FLAG, true); }
|
||
|
||
// Dodaj kopiowanie nazwy zamówienia
|
||
const orderNameSpan = document.querySelector('h1 span[name="name"]');
|
||
if (orderNameSpan) {
|
||
const orderNameH1 = orderNameSpan.closest('h1');
|
||
if (orderNameH1) {
|
||
makeOrderNameCopyable(orderNameH1);
|
||
}
|
||
}
|
||
|
||
// Dodaj kopiowanie dla elementów span z określonymi name
|
||
const waybillSpan = document.querySelector('span[name="waybill"]');
|
||
if (waybillSpan) {
|
||
makeSpanCopyable(waybillSpan, 'numer listu przewozowego');
|
||
}
|
||
|
||
const invoiceVatSpan = document.querySelector('span[name="invoice_vat"]');
|
||
if (invoiceVatSpan) {
|
||
makeSpanCopyable(invoiceVatSpan, 'NIP faktury');
|
||
}
|
||
|
||
const noteSpan = document.querySelector('span[name="note"]');
|
||
if (noteSpan) {
|
||
makeSpanCopyable(noteSpan, 'notatkę');
|
||
}
|
||
}
|
||
|
||
// ——— Start + reagowanie na zmiany ———
|
||
let deb = null; const debounce = (fn, ms = 150) => { clearTimeout(deb); deb = setTimeout(fn, ms); };
|
||
window.addEventListener('load', () => debounce(processOnce, 150));
|
||
window.addEventListener('hashchange', () => debounce(processOnce, 250));
|
||
new MutationObserver(() => debounce(processOnce, 150)).observe(document.documentElement, { childList: true, subtree: true });
|
||
})();
|