설명 없음
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

mappa-dispositivi-setup-stampanti.js 10KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295
  1. 'use strict';
  2. (function () {
  3. const wizardEl = document.getElementById('wizard-md-stampanti');
  4. if (!wizardEl || typeof Stepper === 'undefined') {
  5. return;
  6. }
  7. const STEP_ENDPOINT = parseInt(wizardEl.dataset.stepEndpoint || '2', 10);
  8. const ENDPOINT_POLL_MS = 10000;
  9. const startStepDefault = parseInt(wizardEl.dataset.startStep || '0', 10);
  10. const stepper = new Stepper(wizardEl, { linear: false });
  11. let currentStepIndex = 0;
  12. let endpointPollInterval = null;
  13. let endpointAutoAdvanced = false;
  14. function waitForFestAgentApi(maxMs = 8000) {
  15. return new Promise((resolve) => {
  16. if (typeof window.fetchFestAgentStatus === 'function') {
  17. resolve();
  18. return;
  19. }
  20. const started = Date.now();
  21. const timer = setInterval(() => {
  22. if (typeof window.fetchFestAgentStatus === 'function' || Date.now() - started > maxMs) {
  23. clearInterval(timer);
  24. resolve();
  25. }
  26. }, 100);
  27. });
  28. }
  29. function stopEndpointPoll() {
  30. if (endpointPollInterval) {
  31. clearInterval(endpointPollInterval);
  32. endpointPollInterval = null;
  33. }
  34. }
  35. function renderSetupFestAgentStatus(status) {
  36. const el = document.getElementById('mdSetupFestAgentStatus');
  37. if (typeof window.renderFestAgentStatus === 'function') {
  38. window.renderFestAgentStatus(el, status);
  39. }
  40. }
  41. function checkFestAgentOnline() {
  42. if (typeof window.fetchFestAgentStatus !== 'function') {
  43. return Promise.resolve(false);
  44. }
  45. return window.fetchFestAgentStatus()
  46. .then((status) => {
  47. renderSetupFestAgentStatus(status);
  48. return status.online;
  49. })
  50. .catch(() => {
  51. renderSetupFestAgentStatus({ online: false, endpointId: null });
  52. return false;
  53. });
  54. }
  55. function advanceFromEndpointIfActive() {
  56. if (endpointAutoAdvanced || currentStepIndex !== STEP_ENDPOINT) {
  57. return;
  58. }
  59. endpointAutoAdvanced = true;
  60. stopEndpointPoll();
  61. stepper.next();
  62. if (typeof notyf !== 'undefined') {
  63. notyf.success('FestAgent attivo — vai al passo successivo');
  64. }
  65. }
  66. function pollEndpointFestAgentStatus() {
  67. checkFestAgentOnline().then((online) => {
  68. if (online) {
  69. advanceFromEndpointIfActive();
  70. }
  71. });
  72. }
  73. function startEndpointPoll() {
  74. stopEndpointPoll();
  75. endpointAutoAdvanced = false;
  76. waitForFestAgentApi().then(() => {
  77. pollEndpointFestAgentStatus();
  78. endpointPollInterval = setInterval(pollEndpointFestAgentStatus, ENDPOINT_POLL_MS);
  79. });
  80. }
  81. async function jumpToEndpointIfFestAgentActive() {
  82. if (currentStepIndex > STEP_ENDPOINT) {
  83. return;
  84. }
  85. const online = await checkFestAgentOnline();
  86. if (online && currentStepIndex < STEP_ENDPOINT) {
  87. stepper.to(STEP_ENDPOINT + 1);
  88. }
  89. }
  90. async function onSetupTabVisible() {
  91. await waitForFestAgentApi();
  92. await jumpToEndpointIfFestAgentActive();
  93. }
  94. const setupTabBtn = document.getElementById('md-tab-setup');
  95. const setupPane = document.getElementById('mdPaneSetup');
  96. setupTabBtn?.addEventListener('shown.bs.tab', onSetupTabVisible);
  97. waitForFestAgentApi().then(() => {
  98. if (setupPane?.classList.contains('active') || setupPane?.classList.contains('show')) {
  99. onSetupTabVisible();
  100. }
  101. });
  102. if (startStepDefault > 0) {
  103. stepper.to(startStepDefault + 1);
  104. }
  105. wizardEl.querySelectorAll('.btn-next').forEach((btn) => {
  106. btn.addEventListener('click', () => stepper.next());
  107. });
  108. wizardEl.querySelectorAll('.btn-prev').forEach((btn) => {
  109. btn.addEventListener('click', () => stepper.previous());
  110. });
  111. wizardEl.addEventListener('shown.bs-stepper', (event) => {
  112. const idx = event.detail.indexStep;
  113. currentStepIndex = idx;
  114. wizardEl.querySelectorAll('.btn-prev').forEach((btn) => {
  115. btn.disabled = idx === 0;
  116. });
  117. stopEndpointPoll();
  118. if (idx === STEP_ENDPOINT) {
  119. startEndpointPoll();
  120. }
  121. });
  122. const pcSiPanel = document.getElementById('mdSetupPcSiPanel');
  123. const pcNoPanel = document.getElementById('mdSetupPcNoPanel');
  124. function showPcChoice(choice) {
  125. pcSiPanel?.classList.toggle('d-none', choice !== 'si');
  126. pcNoPanel?.classList.toggle('d-none', choice !== 'no');
  127. }
  128. document.getElementById('mdSetupPcSi')?.addEventListener('click', () => showPcChoice('si'));
  129. document.getElementById('mdSetupPcNo')?.addEventListener('click', () => showPcChoice('no'));
  130. const quizAnswers = { rete: null, casse: null };
  131. const quizResultEl = document.getElementById('mdSetupQuizResult');
  132. function setQuizOption(btn) {
  133. const q = btn.dataset.q;
  134. const v = btn.dataset.v;
  135. if (!q || !v) return;
  136. quizAnswers[q] = v;
  137. document.querySelectorAll(`.md-setup-quiz-opt[data-q="${q}"]`).forEach((el) => {
  138. el.classList.remove('active', 'btn-primary');
  139. el.classList.add(el.dataset.v === 'ns' ? 'btn-outline-secondary' : 'btn-outline-primary');
  140. });
  141. btn.classList.add('active', 'btn-primary');
  142. btn.classList.remove('btn-outline-primary', 'btn-outline-secondary');
  143. updateSetupQuizResult();
  144. }
  145. function updateSetupQuizResult() {
  146. if (!quizResultEl) return;
  147. const { rete, casse } = quizAnswers;
  148. if (!rete || !casse) {
  149. quizResultEl.classList.add('d-none');
  150. return;
  151. }
  152. let html = '';
  153. if (rete === 'si' && casse === 'no') {
  154. html =
  155. '<p class="fw-semibold mb-1"><i class="bx bx-check-circle me-1 text-success"></i>Consiglio: <strong>un solo PC</strong></p>' +
  156. '<p class="mb-0">Metti tutte le stampanti su <strong>un computer</strong> e FestAgent solo lì. Con la rete che copre tutto, è la scelta più facile.</p>';
  157. quizResultEl.className = 'alert alert-success py-2 px-3 small mb-0';
  158. } else if (rete === 'si' && casse === 'si') {
  159. html =
  160. '<p class="fw-semibold mb-1"><i class="bx bx-info-circle me-1"></i>Consiglio: <strong>un PC per cassa</strong></p>' +
  161. '<p class="mb-0">Hai già PC e stampante per bancone: installa FestAgent <strong>su ogni PC-cassa</strong>, con le stampanti che usa lì.</p>';
  162. quizResultEl.className = 'alert alert-primary py-2 px-3 small mb-0';
  163. } else if (rete === 'no') {
  164. html =
  165. '<p class="fw-semibold mb-1"><i class="bx bx-info-circle me-1"></i>Consiglio: <strong>PC vicino alla stampante</strong></p>' +
  166. '<p class="mb-0">Rete debole? Meglio FestAgent sul PC <strong>accanto</strong> a ogni stampante (cavo USB o rete corta).</p>';
  167. quizResultEl.className = 'alert alert-primary py-2 px-3 small mb-0';
  168. } else {
  169. html =
  170. '<p class="fw-semibold mb-1"><i class="bx bx-help-circle me-1"></i>Non sei sicuro?</p>' +
  171. '<p class="mb-0">Chiedi a chi gestisce la rete. Oppure usa il PC <strong>accanto alla stampante</strong> — funziona sempre.</p>';
  172. quizResultEl.className = 'alert alert-secondary py-2 px-3 small mb-0';
  173. }
  174. quizResultEl.innerHTML = html;
  175. quizResultEl.classList.remove('d-none');
  176. }
  177. document.querySelectorAll('.md-setup-quiz-opt').forEach((btn) => {
  178. btn.addEventListener('click', () => setQuizOption(btn));
  179. });
  180. document.getElementById('mdSetupGoTree')?.addEventListener('click', () => {
  181. sessionStorage.setItem('fest.mappa_dispositivi.active_tab', '#mdPaneTree');
  182. const trigger = document.getElementById('md-tab-tree');
  183. if (trigger && typeof bootstrap !== 'undefined') {
  184. bootstrap.Tab.getOrCreateInstance(trigger).show();
  185. }
  186. });
  187. const modalEl = document.getElementById('mdSetupModal');
  188. const modalTitle = document.getElementById('mdSetupModalTitle');
  189. const modalBody = document.getElementById('mdSetupModalBody');
  190. const csrfToken = document.querySelector('meta[name="csrf-token"]')?.content;
  191. function openSetupModal(title, html) {
  192. if (!modalEl || !modalTitle || !modalBody || typeof bootstrap === 'undefined') {
  193. return;
  194. }
  195. modalTitle.innerHTML = title;
  196. modalBody.innerHTML = html;
  197. bootstrap.Modal.getOrCreateInstance(modalEl).show();
  198. }
  199. function loadSetupModal(title, url) {
  200. if (!modalEl || !modalTitle || !modalBody || typeof bootstrap === 'undefined') {
  201. return;
  202. }
  203. modalTitle.innerHTML = title;
  204. modalBody.innerHTML = '<div class="text-center py-4"><div class="spinner-border text-primary" role="status"></div></div>';
  205. bootstrap.Modal.getOrCreateInstance(modalEl).show();
  206. fetch(url, { headers: { 'X-Requested-With': 'XMLHttpRequest' } })
  207. .then((response) => response.text())
  208. .then((html) => { modalBody.innerHTML = html; })
  209. .catch(() => {
  210. modalBody.innerHTML = '<div class="alert alert-danger mb-0">Errore nel caricamento.</div>';
  211. });
  212. }
  213. document.getElementById('mdSetupIstruzioni')?.addEventListener('click', () => {
  214. loadSetupModal(
  215. '<i class="bx bx-help-circle me-1"></i> Aiuto FestAgent',
  216. wizardEl.dataset.urlIstruzioni || ''
  217. );
  218. });
  219. document.getElementById('mdSetupProductKey')?.addEventListener('click', () => {
  220. loadSetupModal('Codice manuale', wizardEl.dataset.urlProductKey || '');
  221. });
  222. document.getElementById('mdSetupCollegaPc')?.addEventListener('click', async () => {
  223. const btn = document.getElementById('mdSetupCollegaPc');
  224. if (!btn) return;
  225. btn.disabled = true;
  226. try {
  227. const response = await fetch(wizardEl.dataset.urlCollegaPc || '', {
  228. method: 'POST',
  229. headers: {
  230. Accept: 'application/json',
  231. 'X-CSRF-TOKEN': csrfToken,
  232. 'X-Requested-With': 'XMLHttpRequest',
  233. },
  234. });
  235. const payload = await response.json();
  236. if (!response.ok || !payload.url) {
  237. throw new Error(payload.message || 'Collegamento non riuscito');
  238. }
  239. window.open(payload.url, '_blank');
  240. openSetupModal(
  241. 'FestAgent si sta aprendo',
  242. '<div class="alert alert-info mb-2">Segui le istruzioni nel programma FestAgent:</div><ol class="mb-0 ps-3 small"><li>Dai un nome alla postazione</li><li>Scegli le stampanti</li><li>Clicca Registra stampanti e Avvia worker</li></ol><p class="small text-muted mt-3 mb-0">Appena FestAgent è attivo passeremo al passo successivo.</p>'
  243. );
  244. if (currentStepIndex === STEP_ENDPOINT) {
  245. startEndpointPoll();
  246. }
  247. } catch (error) {
  248. if (typeof notyf !== 'undefined') {
  249. notyf.error(error.message || 'Non sono riuscito a collegare il computer. Riprova.');
  250. } else {
  251. alert(error.message || 'Non sono riuscito a collegare il computer. Riprova.');
  252. }
  253. } finally {
  254. btn.disabled = false;
  255. }
  256. });
  257. })();