...

Модуль отправки всплывающих уведомлений из клиентских сценариев

Тема в разделе "Примеры решений и дополнительных модулей", создана пользователем denis.g, 23 июл 2024.

  1. denis.g

    denis.g Новичок

    Модуль создаёт глобальную функцию sendNotification, которую можно вызывать как из виджета код, так и из клиентского сценария посредством обращения к window.sendNotification. На входе функция принимает:
    • notification_type - код уведомления из таблицы типов уведомления модуля;
    • text - текст уведомления;
    • details - детали уведомления. Будут отображены при клике на кнопку "Подробнее". Если на входе подавать пустую строку или undefined - кнопки "Подробнее" не будет;
    • time - время (в секундах), по истечению которого уведомление будет удалено со страницы. Если на входе подавать 0, то уведомление будет отображено, до тех пор пока пользователь сам его не закроет.

    upload_2024-7-23_16-41-8.png
    Подробнее о реализации
    В модуле реализован виджет в расширении корневой компонент. Корневой компонент позволяет создать виджет, код которого будет исполняться на всех страницах при загрузке системы. Это позволяет нам, единожды создав функцию, использовать её на всех виджетах и формах.

    Внутри корневого компонента добавляем 3 виджет кода на форму с следующим содержимым:

    1. CSS стили блоков - которые бесстыдно подсмотрены в стандартных уведомлениях ELMA365.
    Код:
    
    <style>
        
    #notify-container>*+*,
        #toast-container>*+* {
            
    margin-top7px;
        }

        .
    notify-div {
            
    width60%;
            
    max-width900px;
            
    positionrelative;
            
    overflowhidden;
            
    border-radius3px;
            
    box-shadow0 0 12px #999;
            
    margin0 auto;
            
    padding0;
            
    cursorpointer;
            
    font-size16px;
            
    line-height24px;
            
    pointer-eventsall;
        }

        .
    notify-div:hover {
            
    box-shadow0 0 12px #000;
        
    }

        .
    notify-row {
            
    displayflex;
            
    flex-wraprevert;
            
    padding3.5px;
            
    margin-left: -4px;
            
    margin-right: -4px;
            
    box-sizingborder-box;
        }

        .
    notify-icon {
            
    height20px;
            
    width20px;
            
    background-repeatno-repeat;
            
    margin-left16px;
        }

        .
    notify-text-div {
            
    flex1 0 75%;
            
    max-widthnone;
            
    displayflex;
            
    flex-directioncolumn;
            
    justify-contentcenter;
        }

        .
    notify-text {
            
    font-weight700;
            
    color#1f1f1f;
            
    displayflex;
        }

        
    a.details-button:hover {
            
    text-decorationnone;
        }

        .
    show-details .notify-details {
            
    displayblock !important;
        }
    </
    style>
    2. HTML разметка уведомлений.
    Подтягиваем из настроек модуля типы уведомлении и формируем для каждого из них шаблон, хранящийся на странице браузера, но скрытый от глаз пользователя.
    Код:
    
    <% const notify_types Context.data.notify_type; %>
    <% if (
    notify_types && notify_types.length 0) { %>
    <
    div id="notify-template" style="display: none;">
        <% for (
    let i 0notify_types.length; ++i) { %>
            <% const 
    notify_type notify_types[i]; %>
            <
    div class="notify-div <%- notify_type.code %>-div"
                
    style="display: block; border: 1px solid <%- notify_type.border_color %>; background-color: <%- notify_type.bg_color %>;">
                <
    div class="notify-row">
                    <
    div class="notify-icon">
                        <
    class="elma-icons md-18" style="color: <%- notify_type.border_color %>;"><%- notify_type.icon_code %></i>
                    </
    div>
                    <
    div class="col-9 notify-text-div">
                        <
    div class="notify-text">
                            <
    p style="margin: 0 3px 0 0;"></p>
                            <
    class="details-button" style="color: <%- notify_type.border_color %>;" onclick="show_details(this)">Подробнее... </a>
                        </
    div>
                    </
    div>
                    <
    div class="col-3 text-right" style="flex: 0 0 20px;">
                        <
    button class="md-18 btn btn-default btn-style-icon elma-icons" style="height: 20px; width: 20px; padding: 0;"
                        
    onclick="remove_notify(this)"system_close </button>
                    </
    div>
                </
    div>
                <
    textarea class="notify-details" readonly="" style="background: #ffffff; display: none;"></textarea>

            </
    div>
        <% } %>
    </
    div>
    <% } %>
    3. Скрипты
    Код:
    
    <div class="overlay-container" id="notify-overlay">
        <
    div id="notify-container" class="toast-top-center toast-container"></div>
    </
    div>

    <
    script>
        
    //Перемещаем в блок body контейнер для наших всплывающих уведомлений
        
    document.querySelector("body").appendChild(document.querySelector("#notify-overlay"));

        
    //Записываем в глобальную переменную sendNotification нашу функцию
        
    window.sendNotification = function ( notify_typetextdetailstime ) {
            
    // Ищем на странице шаблон поданного уведомления
            
    const template document.querySelector("#notify-template ." notify_type "-div");
            if (!
    template){
                return;
            }
          
            
    // Ищем на странице контейнер для всплывающего уведомления
            
    const target_container document.querySelector("#toast-container") ?? document.querySelector("#notify-container");
          
            
    // Копируем шаблон уведомления
            
    const notify template.cloneNode(true);       
            
    notify.querySelector(".notify-text p").innerText text ?? notify_type// Указываем заголовок уведомления

            
    if (details) {
                
    notify.querySelector(".notify-details").innerText details ?? ''// Указываем детали уведомления
            
    } else {
                
    notify.querySelector(".details-button").remove();
            }

            
    // Вставляем уведомление в контейнер для уведомления
            
    target_container.prepend(notify);

            
    // Автоудаление уведомления
            
    if (time 0) {
                
    setTimeout(() => {
                    
    notify.remove();
                }, 
    time 1000);
            }     
        }

        
    // Кнопка для удаления уведомления со страницы
        
    function remove_notifyelement ) {
            
    element.closest('.notify-div').remove();
        }   

        
    // Кнопка для отображения деталей уведомления
        
    function show_detailselement ) {
            
    notify element.closest('.notify-div');
            if (
    notify.classList.contains('show-details')){
                
    notify.classList.remove('show-details');
                
    element.innerText 'Подробнее...';
            } else {
                
    notify.classList.add('show-details');
                
    element.innerText 'Скрыть...';
            }
        }
    </script>
    </script>

    Использование:
    Теперь мы можем вызывать глобальную функцию напрямую из TypeScript, предварительно подключив window
    Код:
    
    declare const windowany;
    window.sendNotification('error''Текст ошибки''Подробности'0);
    Однако!
    Корневой компонент инициализируется при первой загрузке страницы. При перезагрузке страницы или например при открытие в новой вкладке, может возникнуть ситуация, что корневой компонент не успеет загрузиться, например если отправлять уведомления из функции onInit. Поэтому создадим функцию на TypeScript для ожидания загрузки корневого компонента.

    Код:
    
    declare const consoleany;
    declare const 
    windowany;

    /**
    * Отправляет всплывающее уведомления на форму
    * @param {string} notification_type Тип уведомления
    * @param {string} text Текст уведомления
    * @param {string | undefined} details Подробности
    * @param {Number} time Количество секунд до автоматического скрытия уведомления. Если передать 0, то уведомления не будет автоматически скрываться
    */
    async function sendNotification(notification_typestringtextstringdetailsstring undefined undefinedtimeNumber 0): Promise<void> {
        if (!
    window.sendNotification) {
            
    window.setTimeout(() => {
                try {
                    
    window.sendNotification(notification_typetextdetailstime);
                } catch {
                    
    // Глобальная функция sendNotification не найдена
                    
    console.error("Корневой компонент шаблоны уведомлений не найдет ")
                }
            }, 
    1000);
            return;
        }
        
    window.sendNotification(notification_typetextdetailstime);
    }

    async function onInit(): Promise<void> {
        
    // Отправляем уведомление на страницу
        
    sendNotification("success""Успех");  
        
    sendNotification("info""Информация"undefined5);
        
    sendNotification("warning""Предупреждение""Подробности предупреждения");
        
    sendNotification("error""Ошибка""Текст ошибки"0);
    }
    Файл модуля во вложении

    Вложения:

    Последнее редактирование: 24 июл 2024