...

Модуль Quick Chats

Тема в разделе "Примеры решений и дополнительных модулей", создана пользователем khodyrev, 28 мар 2022.

  1. khodyrev

    khodyrev Участник

    Представляем вашему вниманию модуль “Quick Chats”, реализованный на хакатоне февраля 2022.


    Для чего?

    Основное предназначение модуля - упростить коммуникации пользователей в ELMA365, при этом не нарушая привычный для них workflow. Модуль позволяет общаться в чатах и читать ленту, находясь на любой странице системы.


    Quick Chats - это удобное, сворачиваемое окно для общения в чатах ELMA365:


    [​IMG]


    Каждый пользователь может включить Quick Chats индивидуально для себя, в настройках профиля:

    [​IMG]


    Как и раздел “Сообщения” в меню, Quick Chats отображает счетчик непрочитанных сообщений:

    [​IMG]


    В свернутом состоянии, Quick Chats практически не заметен и не мешает работе в интерфейсе системы:


    [​IMG]


    Как это работает?
    Quick Chats это один виджет в корневой зоне расширения:

    [​IMG]

    Зона расширения root работает следующим образом. На основную страницу SPA-приложения добавляется виджет, который может содержать как скрипты, так и стили.

    Т.е. это расширение работает на всех страницах/формах/карточках. Возможности не ограничены - можно как переопределять системные стили, так и навешивать дополнительные обработчики на кнопки.

    Будьте внимательны при работе с данным расширением. Чтоб не влиять на производительность самой системы - не делайте никаких запросов на сервер, если это приходится делать - используйте localStorage, Namespace.cache или Namespace.storage.



    Внутри 3 виджета “Код”, со стилями, основным рендерером и периодическими рендерерами:

    [​IMG]


    Реализовано на CSS и JQuery, чаты встраиваются с помощью iframe.

    Спойлер: Style
    HTML:
    <style>
        @media screen and (min-width: 900px) {
            .chat-box-custom {
                max-height: 500px;
            }
        }
    
        @media screen and (min-width: 1560px) {
            .chat-box-custom {
                max-height: 800px;
            }
        }
    
        @media screen and (max-width: 1000px) {
            .chat-collapser {
                display: none !important;
            }
        }
    
        .chat-collapser {
            width: 40px;
            height: 40px;
            border-radius: 5px;
            font-size: 20px;
            background: transparent;
            cursor: pointer;
            transition: all 0.3s ease;
            position: relative;
            display: inline-block;
            box-shadow: 0 0 10px 5px rgba(221, 221, 221, 1);
            outline: none;
            position: fixed;
            right: 0;
            bottom: 0;
            margin-right: 35px;
            margin-bottom: 20px;
            z-index:1052;
        }
    
        .chat-collapser:hover {
            width: 40px;
            height: 40px;
            border-radius: 5px;
            font-size: 20px;
            background: #E8E8E8;
            cursor: pointer;
            transition: all 0.3s ease;
            position: relative;
            display: inline-block;
            box-shadow: 0 0 10px 5px rgba(221, 221, 221, 1);
            outline: none;
            position: fixed;
            right: 0;
            bottom: 0;
            margin-right: 35px;
            margin-bottom: 20px;
            z-index:1052;
        }
    
        .chat-box-custom {
            border-width: none;
            position: fixed;
            right: 0;
            bottom: 0;
            min-height: 120px;
            display: flex;
            flex-direction: column;
            box-shadow: 0 0 10px 5px rgba(221, 221, 221, 1);
            margin-right: 85px;
            margin-bottom: 20px;
            z-index:1052;
        }
    
        .frame_messages {
            width: 360px;
            height: 640px;
            border : 0px;
        }
    
        .counter-badge {
            position: absolute;
            right: calc(50% - 16px);
            top: 8px;
            border-radius: 2px;
            font-size: 10px;
            line-height: 20px;
            display: flex;
            align-items: center;
            justify-content: center;
            min-width: 14px;
            height: 14px;
            margin-left: 7px;
            padding: 2px 4px;
            background: #D4380D;
            color: #fff;
        }
    
        .qc-elma-icons {
        display: inline-block;
        font-family: elma365!important;
        font-style: normal;
        line-height: 1;
    }
    </style>

    Script onRender, создает в DOM дереве иконку чата, отвечает за сворачивание/разворачивание чата.

    Спойлер: Script onRender
    HTML:
    <script>
        if (!window.frameElement) {
            $(".app-wrap").append("<div class='chat-collapser' style='display: none'><i class='qc-elma-icons' style='margin: 10px 10px;'>system_message</i><span class='counter-badge' style='display: none'></span></div>");
    
            var localValue = localStorage.getItem('quick_chats');
            if (localValue == 'on') {
                $(".chat-collapser").show()
            }
    
            if($("a[href=messages] .badge").length > 0){
                var el = document.querySelector("a[href=messages] .badge");
                $(".counter-badge").text(el.outerText);
                $(".counter-badge").show()
            }
            else {
                $(".counter-badge").hide()
            }
    
            $( ".chat-collapser" ).click(function() {
                if ($(".chat-box-custom").length && $(".chat-box-custom").is(":visible")){
                    $(".chat-box-custom").hide()
                } else if ($(".chat-box-custom").is(":hidden")) {
                    $(".chat-box-custom").show()
                } else {
                    $(".app-wrap").append("<div class='chat-box-custom'><iframe class='frame_messages' src='/messages'></iframe></div>")
                }
            });
    
            function quickChatsControl() {
                if ($('#checkbox_chats').is(':checked')) {
                    localStorage.setItem('quick_chats', 'on');
                    $(".chat-collapser").show()
                } else {
                    localStorage.setItem('quick_chats', 'off');
                    $(".chat-collapser").hide();
                    $(".chat-box-custom").hide()
                }
            }
        }
    </script>

    Из интересного в этой части хочется отметить, что мы используем проверку на то, где выполняется данный код. Если это происходит внутри фрейма - наша кнопка отображаться не будет. Иначе мы бы ушли в рекурсию и наш виджет загружался бы бесконечно.

    Script setInterval, выполняет вспомогательные функции: добавляет настройку в профиль пользователя, скрывает виджет, если пользователь уже находится в разделе “Сообщения”, удаляет навигационную панель, и т.п.

    Спойлер: Script setInterval
    Код:
    
    <script>
        
    setInterval(()=>{
            if($(
    "#checkbox_chats").length == 0){
                $(
    "app-edit-profile elma-form.form-wrapper form.elma-form button.btn.btn-primary.ng-star-inserted").before("<elma-form-row class='elma-form-row ng-untouched ng-pristine ng-invalid ng-star-inserted'><elma-form-label class='elma-form-label ng-star-inserted'><span class='labelName'>Quick chats</span></elma-form-label><elma-form-control class='elma-form-control text-base'><input type='checkbox' id='checkbox_chats' onclick='quickChatsControl()' style='width: 2%'><label class='ng-star-inserted ui-chkbox-label ui-label-active'>Включить быстрые чаты</label></elma-form-control></elma-form-row>");
            }

            $( 
    ".frame_messages" ).contents().find("app-mobile-nav-manager").remove();
        
            var 
    localValue localStorage.getItem('quick_chats');
            if (
    localValue == 'on') {
                $(
    '#checkbox_chats').prop('checked'true);
                if(
    window.location.pathname.includes('/messages')){
                    $(
    ".chat-collapser").hide();
                    $(
    ".chat-box-custom").hide()
                } else {
                    $(
    ".chat-collapser").show()
                }
            } else {
                $(
    '#checkbox_chats').prop('checked'false);
                $(
    ".chat-collapser").hide()
            }

            if($(
    "a[href=messages] .badge").length 0){
                var 
    el document.querySelector("a[href=messages] .badge");
                $(
    ".counter-badge").text(el.outerText);
                $(
    ".counter-badge").show()
            }
            else {
                $(
    ".counter-badge").hide()
            }

            if(
    window.frameElement) {
                $(
    ".simple-notification-wrapper").hide()
            }
        }, 
    300);

    </script>

    Здесь прокомментирую такой момент. ELMA365 - это одностраничное приложение (SPA) и мы не можем отследить момент открытия определенного url или определенной карточки. Поэтому мы периодически (каждые 300ms) делаем проверку некоторых параметров - например, проверяем текущий url (window.location.pathname) на совпадение с нужным нам путем, чтобы не рисовать виджет, если пользователь уже находится в разделе "Сообщения".

    Скачать модуль можно здесь.
    Последнее редактирование: 28 мар 2022
  2. elma

    elma Участник

    Супер!)
  3. elma

    elma Участник

    Было бы удобно еще добавить возможность настройки отправки сообщений с клавиатуры типа через Enter или Ctrl+Enter
  4. elma

    elma Участник

    Заметил следующее, поставил модуль через админку, включил галочку - все заработало, отправил тестовому пользователю сообщение, перешел на его аккаунт, а там в настройках профиля нет галочки включения виджета. Перешел обратно в админку и там тоже пропало, но при этом сам модуль в режиме "включен", похоже что-то сбоит еще

    UPD: когда заходишь в админку - виджет не отображается, нажимаешь F5 для перезагрузки - начинает отображаться. Также у тестового пользователя. То есть до перезагрузки страницы после входа виджет невидим.
  5. khodyrev

    khodyrev Участник

    С отправкой есть ряд нюансов, которые пока не победили :) Но отправка по Enter работает, если использовать виджет в десктопном приложении.
  6. khodyrev

    khodyrev Участник

    Будем модуль дорабатывать, в будущих версиях исправим, спасибо за фидбэк!
  7. daniyar1997

    daniyar1997 Участник

    Здравствуйте, вопрос общий по модулям.
    Вы модули как храните? При импорте, например, пропадает возможность редактировать модуль. Используете виртуалку с исходным модулем?
  8. khodyrev

    khodyrev Участник

    Добрый день! Да, у нас есть компания в облаке с исходником
  9. Leni

    Leni Участник

    Добрый день. Спасибо за действительно полезный модуль)

    Просьба по возможности добавить:
    - Чтобы окно автоматически закрывалось при нажатии на область вне этого окна)
    - При нажатии на связанный элемент, чтобы он открывался в основном окне
    Последнее редактирование: 28 апр 2022
  10. khodyrev

    khodyrev Участник


    Добрый день, спасибо за обратную связь!

    - закрытие при нажатии на область вне окна умышленно не закладывали, есть кейсы, когда это будет больше мешать, чем помогать. Плюс ориентировались на аналогичную фичу у VK :)
    - связанный элемент - да, необходимая доработка
  11. Leni

    Leni Участник

    Можно чтобы пользователь сам выбирал, как закрывать окно)