1/**************************** START Messages ****************************/ 2function openMessageDialog(content, className = 'info', timeoutRemove = undefined) { 3 const dialogTemplate = $('#new-message-dialog .robert-dialog'); 4 const newDialog = dialogTemplate.clone(); 5 newDialog.attr('x-data', `dialog(${timeoutRemove === undefined ? 'true' : 'false'}, ${timeoutRemove ? timeoutRemove : 4000}, true)`); 6 7 newDialog.addClass(className); 8 newDialog.find('p').html(content); 9 10 // If the dialog is not closable, we remove the close button 11 if (timeoutRemove !== undefined) { 12 newDialog.find('.robert-button').remove(); 13 } 14 15 // If theres more than 2 dialogs, we remove until we have only 2 16 const dialogs = document.querySelectorAll('.robert-dialog'); 17 const dialogArray = []; 18 for (let i = 0; i < dialogs.length; i++) { 19 if (dialogs[i].parentElement.id !== 'new-message-dialog') { 20 dialogArray.push(dialogs[i]); 21 } 22 } 23 24 if (dialogArray.length > 2) { 25 const event = new CustomEvent('disappear'); 26 dialogArray.slice(0, dialogArray.length - 2).forEach((dialog) => { 27 dialog.dispatchEvent(event); 28 }); 29 } 30 31 $('#message-dialog-wrapper').append(newDialog); 32} 33 34function closeMessageDialog(elem, jqueryElem = true) { 35 const event = new CustomEvent('disappear'); 36 if (!elem || !elem.length) { 37 return; 38 } 39 if (jqueryElem) { 40 elem[0].dispatchEvent(event); 41 } else { 42 elem.dispatchEvent(event); 43 } 44} 45 46// Display messages from the backend, htmx and axios 47 48function openMessagesDialog(messages) { 49 messages.forEach((message) => { 50 const tags = message.tags.split(' '); 51 // level is tag of value 'info', 'warning', 'error' or 'success' 52 const level = tags.find((tag) => ['info', 'warning', 'error', 'success'].includes(tag)); 53 54 const isClosable = tags.includes('closable'); 55 56 // Duration is found in this format duration.1000 57 // Base duration if not found is 4000ms 58 const duration = tags.find((tag) => tag.includes('duration')); 59 const durationValue = duration ? parseInt(duration.split('.')[1]) : 4000; 60 61 if (isClosable) { 62 openMessageDialog(message.message, level); 63 } else { 64 openMessageDialog(message.message, level, durationValue); 65 } 66 }); 67} 68 69htmx.on('messages', function (e) { 70 if (e.type == 'messages' && e?.detail?.value && e?.detail?.value?.length > 0) { 71 openMessagesDialog(e.detail.value); 72 } 73}); 74 75if (typeof axios !== 'undefined') { 76 axios.interceptors.response.use( 77 function (response) { 78 if (response.headers['x-messages']) { 79 const messages = JSON.parse(response.headers['x-messages']); 80 openMessagesDialog(messages); 81 } 82 return response; 83 }, 84 function (error) { 85 if (error.response && error.response.headers['x-messages']) { 86 const messages = JSON.parse(error.response.headers['x-messages']); 87 openMessagesDialog(messages); 88 } 89 return Promise.reject(error); 90 } 91 ); 92} 93 94/****************************** END Messages ******************************/
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.