UNPKG

@textback/notification-widget

Version:

TODO: Give a short introduction of your project. Let this section explain the objectives or the motivation behind this project.

570 lines (428 loc) 27.8 kB
# Установка виджета на сайт Для установки виджета подписки на сайт, сначала добавьте к вашей странице: ``` <script src="//cdn.jsdelivr.net/npm/@textback/notification-widget@latest/build/index.js"></script> ``` **Внимание** Виджет больше не требует подключения дополнительного скрипта с полифиллом. Для корректного отображение виджета на адаптивных сайтах на мобильных требуется добавить следующий мета-тег в секцию `<head>`: ```html <meta name="viewport" content="width=device-width, initial-scale=1.0> ``` Затем вы можете вставить один или несколько виджетов: ``` <tb-notification-widget widget-id="YOUR_WIDGET_ID"></tb-notification-widget> ``` с необходимыми widget-id. YOUR_WIDGET_ID указан в консоли администратора Textback. Если вы планируете использовать виджет в режиме "попап", то встраивайте виджет непосредственно внутри тега body, лучше сразу перед `</body>` шаблона страницы, на которую добавляется виджет. Если виджет будет использоваться в режиме "инлайн", то добавте виджет в том месте шаблона, в котором он должен отобразиться. Дополнительные параметры можно передать через data-атрибуты: ``` <tb-notification-widget widget-id="YOUR_WIDGET_ID" data-user-id="USER_ID" data-order-id="ORDER_ID"> </tb-notification-widget> ``` Чтобы передать secureContext, нужно использовать атрибут `secure-context-token`: ```html <tb-notification-widget widget-id="YOUR_WIDGET_ID" secure-context-token="YOUR_TOKEN" </tb-notification-widget> ``` ## Динамическая инициализация виджета Если вам необходимо динамически проинициализировать виджет, например во всплывающем окне или при разработке Single Page Application вы можете использовать класс, который доступен стразу после загрузки скрипта виджета ``` var widgetContainer = document.querySelector('tb-notification-widget'); var options = { widgetId: "YOUR_WIDGET_ID", element: widgetContainer, data: {userId: "USER_ID", orderId: "ORDER_ID"} }; new TextBack.NotificationWidget(options) ``` где widgetContainer - корневой HTML элемент, в котором необходимо отобразить виджет, data - дополнительные параметры. Чтобы изменить параметры после инициализации виджета повторно проинициализируйте виджет на элементе с новыми параметрами: ``` options.data.orderId = "NEW_ORDER_ID"; new TextBack.NotificationWidget(options) ``` ### Мгновенно отобразить popup-виджет По умолчанию при инициализации виджета используются параметры тайминга из настроек - через сколько секунд отобразить виджет, сколько раз за сессию и т.д. Если требуется отобразить виджет сразу, то можно воспользоваться разработанным для этого API. Сначала нужно добавить виджет на страницу, указав атрибут ```only-manual``` ```html <tb-notification-widget widget-id="YOUR_WIDGET_ID" only-manual></tb-notification-widget> ``` Добавленный таким образом виджет будет скрыт и не будет показан автоматически. Чтобы теперь отобразить виджет, нужно выполнить следующий код: ```javascript TextBack.NotificationWidget.getWidget('YOUR_WIDGET_ID').then(function(widget) { widget.show(); }); ``` Пример отображения виджета при нажатии на кнопку: ```javascript document.querySelector('#YOUR_BUTTON_ID').addEventListener('click', function() { TextBack.NotificationWidget.getWidget('YOUR_WIDGET_ID').then(function(widget) { widget.show(); }); }); ``` ### Предпросмотр виджета Релизован механизм, позволяющий задать JSON виджета динамически, не подгружая его по ID с нашего **API**. Для того, чтобы подписки работали в предпросомтре, необходимо, чтобы виджет был сохранен в БАЗУ и имел присвоенный ID. --- Этот механизм внедрян для добавления функционала пред-просмотра виджета в нашем редакторе, но ижет быть использован сторонними разработчикми, для динамической генерации сообщения приветствия, однака надо иметь в виду, что **ЭТО апи не финальное, и может изменится в любой момент**, используйте на свой страх и риск. --- Использование: ```javascript //получаем копию настроек виджета var data = angular.copy(notificationWidgetJSON); //override settings for preview purpose //переопределяем некторыесвойства, сохраненные на сервере //отображатся в виджете будет нвое значение. data.displayOptions.onLeave = null; data.displayOptions.timeoutDelay = 0; data.displayOptions.onTimeout = "yes"; //к примеру vkApiId привязан к домену, на котром отображается виджет data.vkApiId=TextBack.configuration.get('vkAppId'); //динамически создаем контейнер для виджета var widgetContainerJq = $('<div></div>'); $('body').append(widgetContainerJq); var widgetContainer = widgetContainerJq[0]; var options = { apiPath: 'https://api.textback.io/api', //необязатльный параметр element: widgetContainer, widgetConfig: data }; new TextBack.NotificationWidget(options) ``` # Локализация Все поддерживаемые языки находятся в переменной `TextBack.NotificationWidget.locales`. Перевод затрагивает только статичные элементы виджета, значения которых не задаются в настройках виджета. Чтобы применить нужный язык к виджету, передайте соответсвующий параметр `lang` в тег виджета: ``` <tb-notification-widget widget-id="YOUR_WIDGET_ID" lang="ru"> </tb-notification-widget> ``` или ``` var widgetContainer = document.querySelector('tb-notification-widget'); var options = { widgetId: "YOUR_WIDGET_ID", element: widgetContainer, lang: 'ru' }; new TextBack.NotificationWidget(options) ``` Чтобы изменить существующий перевод, передайте новое значение для нужной переменной в **TextBack.NotificationWidget.locales**: ``` <script>TextBack.NotificationWidget.locales.ru.whatsappb = 'Узнать больше'</script> ``` Вы можете создать новый перевод для всех элементов виджета (это касается как виджета подписок, так и WhatsApp Hunter): 1. В личном кабинете установите значение языка по умолчанию, чтобы аттрибут lang не передавался с нашего сервера; 2. В теге виджета на странице установите аттрибут lang со значением языка (это будет название новой локализации - locales); 3. Передайте значения для всех переменных в массиве после кода виджета. Для незаданных переменных будет использоваться язык по умолчанию - английский. **Важно!** И для виджета подписок, и для WhatsApp Hunter перевод берется из TextBack.NotificationWidget.locales. Если на странице используются оба виджета и обоим нужно задать полную кастомную локализацию в рамках одного locales, значения переменных нужно объявлять в одном массиве. Если объявить переменные по отдельности, то использоваться будет последняя переменная - неполная. Если для виджетов заданы разные lang, то объявите переменные для каждого виджета в отдельном массиве. **Пример перевода виджета подписок на французский** ``` <script> TextBack.NotificationWidget.locales.fr = { facebook: "Facebook", facebookExtended: "Abonnez-vous à Facebook", telegram: "Telegram", telegramExtended: "Abonnez-vous à Telegram", viber: "Viber", viberExtended: "Subscribe to Viber", vkontakte: "VK", vkontakteExtended: "Abonnez-vous à Viber", whatsapp: "WhatsApp", whatsappExtended: "Abonnez-vous à WhatsApp", whatsappb: "WhatsApp", whatsappbExtended: "Abonnez-vous à WhatsApp" } </script> ``` ### Список всех переменных Виджет подписок (пример для английского языка) ``` facebook: "Facebook", //для всех кнопок, кроме варианта показа "Прямоугольные кнопки" или "Всплывающее окно" facebookExtended: "Subscribe to Facebook", //если выбран вариант показа "Прямоугольные кнопки" или "Всплывающее окно" telegram: "Telegram", //для всех кнопок, кроме варианта показа "Прямоугольные кнопки" или "Всплывающее окно" telegramExtended: "Subscribe to Telegram", //если выбран вариант показа "Прямоугольные кнопки" или "Всплывающее окно" viber: "Viber", //для всех кнопок, кроме варианта показа "Прямоугольные кнопки" или "Всплывающее окно" viberExtended: "Subscribe to Viber", //если выбран вариант показа "Прямоугольные кнопки" или "Всплывающее окно" vkontakte: "VK", //для всех кнопок, кроме варианта показа "Прямоугольные кнопки" и "попап". vkontakteExtended: "Subscribe to VK", //если выбран лендинг ВК и вариант показа "Прямоугольные кнопки" или "Всплывающее окно" whatsapp: "WhatsApp", //для всех кнопок, кроме варианта показа "Прямоугольные кнопки" или "Всплывающее окно" whatsappExtended: "Subscribe to WhatsApp", //если выбран вариант показа "Прямоугольные кнопки" или "Всплывающее окно" whatsappb: "WhatsApp", //для всех кнопок, кроме варианта показа "Прямоугольные кнопки" или "Всплывающее окно" whatsappbExtended: "Subscribe to WhatsApp", //если выбран вариант показа "Прямоугольные кнопки" или "Всплывающее окно" //NB: если не использовать лендинг ВК, то при выборе прямоугольных кнопок или попапа используется нативная кнопка, перевод которой пока не реализован ``` WhatsApp Hunter (пример для английского языка) ``` getAnswer: "Get an answer in ", //согласие на получение сообщений enterNumber: "Enter your phone number", //placeholder в инпуте sendMessage: "We'll send a message in 3-2-1 sec", //В процессе отправки сообщения answerSuccessful: "We've answered you in WhatsApp. <br> Check your phone", //После успешной отправки numberNotFound: "There is no such user in WhatsApp. <br> Are you from Mars?🤔", //Ошибка, формат номера некорректный tryAgain: "Try another number", //Повтор ввода, если номер не найден somethingWentWrong: "Oops! Something went wrong", //на 500 при отправке сообщения (например, канал не подключен) errorTryAgain: "Try again", //Повтор ввода при ошибки 500 ``` # TextBack Widget SDK TextBack Widget SDK предоставляет набор функций для управления подпиской. SDK входит в состав виджета, но может быть подключен отдельно(см. ниже). **Преимущества SDK, в сравнении с виджетом подписок:** - SDK позволяет полностью настраивать внешний вид вашего UI, предоставляя только функции подписки пользователей. - Файл с SDK имеет меньший размер, чем файл с виджетом подписок. ## Как использовать SDK ### Подключение Добавить в код страницы ``` <script src="//cdn.jsdelivr.net/npm/@textback/notification-widget@latest/build/sdk.js"></script> ``` После этого на странице будет доступен объект ```TextBack.SDK``` ### Использование Приведенный ниже код будет подписывать пользователя в Telegram при клике на ссылку с `id="MY_TG_BUTTON"`: ```javascript var config = { widgetId: 'YOUR_WIDGET_ID' }; TextBack.SDK.initWidget(config).then( function(widget) { document.getElementById('MY_TG_BUTTON').addEventListener('click', function(event) { event.preventDefault(); widget.subscribe('tg'); }) } ); ``` **ВАЖНО!** Элемент с `id="MY_TG_BUTTON"` должен присутствовать на странице во время исполнения скрипта. Более подробное описание функции `initWidget()`, состава полей объекта конфигурации и других функций SDK смотрите ниже. ## SDK API **Примечание.** В документации по SDK под "виджетом" подразумевается не "виджет подписок", упоминавшийся ранее, а объект, который содержит настройки и методы виджета. Таким образом "**инициализация виджета**" - это не отрисовка виджета на странице, а **загрузка настроек с сервера и подготовка к работе**. Иными словами: "виджет" = "объект в приложении", "виджет подписок" = "объект в JavaScript" + "UI". ### Глобальное пространство имен SDK и виджет подписок доступны как свойства `SDK` и `NotificationWidget` глобального объекта `TextBack` соответственно. Для своей работы SDK использует полифиллы для метода `window.fetch()` и объекта ES6 `Promise`. Также, для работы с каналами VKontakte, используется VK JS API, представленное глобальным объектом VK. ### TextBack.SDK API Объект `TextBack.SDK` предоставляет API для инициализации виджетов и работы с ними. #### Метод `initWidget(config)` Инициализирует новый виджет по заданному объекту конфигурации. **Принимает** Объект `config` со следующими полями: - widgetId - (обязательный) идентификатор виджета. Если виджет с таким идентификатором уже есть, то виджет будет перезагружен; - secureContextToken - строка; - insecureContext - объект; - apiPath - адрес сервера; - overrideConfig - объект с настройками виджета. Если задан, то настройки виджета не будут загружаться с сервера, и для инициализации виджета будет использован данный объект; - customData - произвольные пользовательские данные. **Возвращает** Promise, который будет fulfilled объектом виджета. ##### Пример использования ```javascript var config = { widgetId: 'YOUR_WIDGET_ID', insecureContext: { data: 'data' } }; TextBack.SDK.initWidget(config).then( function(widget) { console.log('Widget has been initialized.'); } ); ``` #### Метод `getWidget(widgetId)` **Принимает** `widgetId` - идентификатор виджета. **Возвращает** Promise, возвращаемый функцией `initWidget()`, соответствующий переданному идентификатору. ##### Пример использования ```javascript TextBack.SDK.getWidget('YOUR_WIDGET_ID').then( function(widget) { console.log('Widget has id = ' + widget.id); } ) ``` #### Метод `on(eventName, callback)` Вешает обработчик `callback` на событие `eventName`. При наступлении события в `callback` первым аргументом будет передан объект события. Описание полей объекта события для различных событий см. ниже. **Поддерживаемые события** - 'widget.init' - успеная инициализация виджета. поля события: - widgetId - идентификатор виджета - 'subscribe.start' - вызвана функция подписки на канал. поля события: - widgetId - идентификатор виджета - channel - объект канала, на который осуществляется подписка **Возвращает** Функцию отписки обработчика `callback` от события. ##### Пример использования При инициализации первого виджета вывести в консоль сообщение. ```javascript const config = { widgetId: 'YOUR_WIDGET_ID' }; TextBack.SDK.initWidget(config); const off = TextBack.SDK.on('widget.init', function(event) { console.log('First widget with id = ' + event.widgetId + ' has been initilized'); off(); }) ``` #### Метод `deeplinkUpdater(String)` #### deeplinkUpdater :: String -> Promise -> Function Ф-ция getDeeplinkUpdater() принимает идентефикатор виджета и возвращает Promise, содержащий ф-цию, позволяющую обновлять данные в insecureContext с помощью PATCH запроса. ##### Пример использования Данный пример отправит в insecureContext данные на событие подписки. ```javascript TextBack.SDK.getDeeplinkUpdater('myWidgetId').then(f => { let data = { foo: 'foo', bar: 'bar' }; TextBack.SDK.on('subscribe.start', () => f(data)); }); ``` ### Widget API Объект Widget предоставляет функции для работы с конкретным виджетом. #### Метод `subscribe(channelType)` Инициализирует подписку пользователя на канал. **Принимает** channelType - тип канала, на который следует осуществить подписку. Поддерживаются следующие коды каналов: - `'facebook'` - Facebook - `'tg'` - Telegram - `'viber'` - Viber - `'vk'` - Vkontakte - `'whatsapp'` - WhatsApp - `'whatsappb'` - WhatsApp Business API - `'skype'` - Skype **Внимание!** - Мы **настоятельно рекомендуем** вызывать эту функцию непосредственно из обработчика клика на кнопку/ссылку, во избежание блокирования функции браузером. ##### Пример использования ```javascript var config = { widgetId: 'YOUR_WIDGET_ID' }; TextBack.SDK.initWidget(config).then( function(widget) { document.getElementById('MY_TG_BUTTON').addEventListener('click', function(event) { event.preventDefault(); widget.subscribe('tg'); }); document.getElementById('MY_VK_BUTTON').addEventListener('click', function(event) { event.preventDefault(); widget.subscribe('vk'); }) } ); ``` #### Метод `getConfig()` **Возвращает** загруженный с сервера объект конфигурации виджета #### Метод `getChannels()` **Возвращает** объекты каналов виджета(см. `Channel` ниже) #### Метод `getEnabledChannels()` **Возвращает** объекты каналов виджета, которые сейчас активны и инициализированны без ошибок. ##### Пример использования ```javascript var config = { widgetId: 'YOUR_WIDGET_ID' }; TextBack.SDK.initWidget(config).then( function(widget) { console.log('Total channels: ' + widget.getChannels().length); console.log('Enabled channels: ' + widget.getEnabledChannels().length); } ); ``` ### Channel API Объекты `Channel` предоставляют API конкретных каналов в виджете. Каждый канал реализует свою собственную функцию подписки пользователя. #### Свойство `hasError` Устанавливается в значение `true`, если при инициализации канала произошла ошибка (например, если не удалось загрузить внешнюю библиотеку для канала VKontakte). Информация об ошибке будет выведена в консоль. Каналы, для которых `hasError == true` не вовзращаются при вызове метода `getEnabledChannels()` у объекта виджета. #### Метод `subscribe()` Инициализирует процесс подписки пользователя на канал. ##### Пример использования ```javascript var config = { widgetId: 'YOUR_WIDGET_ID' }; TextBack.SDK.initWidget(config).then( function(widget) { document.getElementById('MY_BUTTON').addEventListener('click', function(event) { event.preventDefault(); const channels = widget.getEnabledChannels(); if (channels.length > 0) { channels[0].subscribe(); console.log('User has been subscribed on ' + channels[0].channel + ' channel'); } else { console.log('No channels available for subscription'); } }); } ); ``` ## Пример Страница с двумя ссылками, подписывающими в Telegram и Vkontakte. ```html <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>TextBack SDK Example</title> </head> <body> <h1>TextBack SDK</h1> <a href="" id="sign_tg">Telegram</a> <a href="" id="sign_vk">Vkontakte</a> <script src="//cdn.jsdelivr.net/npm/@textback/notification-widget@latest/build/sdk.js"></script> <script type="text/javascript"> var config = { widgetId: 'aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee', }; var off = TextBack.SDK.on('widget.init', function(event) { console.log('First widget has been initialized. ' + event.widgetId); off(); }); TextBack.SDK.initWidget(config).then(function(widget) { document.getElementById('sign_tg').addEventListener('click', function(event) { event.preventDefault(); widget.subscribe('tg'); }); document.getElementById('sign_vk').addEventListener('click', function(event) { event.preventDefault(); widget.subscribe('vk'); }); }); </script> </body> </html> ``` # Разработка В терминале перейдите в директорию исходного кода виджета и выполните команды, использую версию ноды v.12: ``` npm run dev PORT=8080 npm start ``` После этого тестовый стенд будет доступен локально по адресу http://localhost:8080/examples Если переменная PORT не указана, по умолчанию будет использован порт 3000 После любых изменений кода обновите страницу браузера Для проверки codestyle выполните ``` npm run test:lint ``` # Тестирование Для запуска тестов выполните ``` npm run build npm run test:all ``` Тесты будут запущенны во всех браузерах, установленных на локальной машине. Тестирование осуществляется с помощью https://github.com/DevExpress/testcafe Все тесты запускаются из директории `./tests`