feat(orders): tg notifications, ya metrika, meta tags
This commit is contained in:
324
module/oc_telegram_shop/upload/admin/view/template/extension/module/tgshop.twig
Executable file
324
module/oc_telegram_shop/upload/admin/view/template/extension/module/tgshop.twig
Executable file
@@ -0,0 +1,324 @@
|
||||
{{ header }}{{ column_left }}
|
||||
<div id="content">
|
||||
<div class="page-header">
|
||||
<div class="container-fluid">
|
||||
<div class="pull-right">
|
||||
<button type="submit" form="form-module" data-toggle="tooltip" title="{{ button_save }}"
|
||||
class="btn btn-primary"><i class="fa fa-save"></i></button>
|
||||
<a href="{{ cancel }}" data-toggle="tooltip" title="{{ button_cancel }}" class="btn btn-default"><i
|
||||
class="fa fa-reply"></i></a></div>
|
||||
<h1>{{ heading_title }}</h1>
|
||||
<ul class="breadcrumb">
|
||||
{% for breadcrumb in breadcrumbs %}
|
||||
<li><a href="{{ breadcrumb.href }}">{{ breadcrumb.text }}</a></li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
<div class="container-fluid">
|
||||
{% if error_warning %}
|
||||
<div class="alert alert-danger alert-dismissible"><i
|
||||
class="fa fa-exclamation-circle"></i> {{ error_warning }}
|
||||
<button type="button" class="close" data-dismiss="alert">×</button>
|
||||
</div>
|
||||
{% endif %}
|
||||
{% if success %}
|
||||
<div class="alert alert-success alert-dismissible"><i class="fa fa-check-circle"></i> {{ success }}
|
||||
<button type="button" class="close" data-dismiss="alert">×</button>
|
||||
</div>
|
||||
{% endif %}
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-heading">
|
||||
<h3 class="panel-title"><i class="fa fa-pencil"></i> {{ text_edit }}</h3>
|
||||
</div>
|
||||
<div class="panel-body">
|
||||
<form action="{{ action }}" method="post" enctype="multipart/form-data" id="form-module"
|
||||
class="form-horizontal">
|
||||
|
||||
<pre>
|
||||
* Проверка request от телеграм
|
||||
4. Выбор товаров, которые будут отображаться на главной странице
|
||||
1. Шаблон для уведомлений покупателя о заказе
|
||||
2. Требовать ввод email/phone
|
||||
3. Группа покупателей для заказов от ТГ
|
||||
</pre>
|
||||
|
||||
<ul class="nav nav-tabs">
|
||||
{% for tabKey, tabItems in settings %}
|
||||
<li{% if tabKey == 'general' %} class="active" {% endif %}>
|
||||
<a href="#{{ tabKey }}" data-toggle="tab">
|
||||
{% if attribute(_context, 'tab_' ~ tabKey) %}
|
||||
{{ attribute(_context, 'tab_' ~ tabKey) }}
|
||||
{% else %}
|
||||
{{ 'tab_' ~ tabKey }}
|
||||
{% endif %}
|
||||
|
||||
</a>
|
||||
</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
|
||||
<div class="tab-content">
|
||||
{% for tabKey, tabItems in settings %}
|
||||
<div class="tab-pane{%if tabKey == 'general' %} active{% endif %}" id="{{ tabKey }}">
|
||||
{% for settingKey, item in tabItems %}
|
||||
<div class="form-group{%if item['required'] %} required{% endif %}{% if item['hidden'] %} hidden{% endif %}">
|
||||
<label class="col-sm-2 control-label" for="{{ settingKey }}">
|
||||
{% if attribute(_context, 'lbl_' ~ settingKey) %}
|
||||
{{ attribute(_context, 'lbl_' ~ settingKey) }}
|
||||
{% else %}
|
||||
{{ 'lbl_' ~ settingKey }}
|
||||
{% endif %}
|
||||
</label>
|
||||
<div class="col-sm-10">
|
||||
{# Select #}
|
||||
{% if item['type'] == 'select' %}
|
||||
<select name="{{ settingKey }}" id="{{ settingKey }}" class="form-control">
|
||||
{% for key, value in item['options'] %}
|
||||
<option value="{{ key }}" {% if key == attribute(_context, settingKey) %}selected="selected"{% endif %}>
|
||||
{{ value }}
|
||||
</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
|
||||
{# Text Input #}
|
||||
{% elseif item['type'] == 'text' %}
|
||||
<input type="text"
|
||||
name="{{ settingKey }}"
|
||||
value="{{ attribute(_context, settingKey) }}"
|
||||
placeholder="{{ item['placeholder'] }}"
|
||||
id="{{ settingKey }}"
|
||||
class="form-control"
|
||||
/>
|
||||
|
||||
{# Image #}
|
||||
{% elseif item['type'] == 'image' %}
|
||||
<a href="" id="thumb-image" data-toggle="image" class="img-thumbnail">
|
||||
<img src="{{ attribute(_context, settingKey) }}"
|
||||
data-placeholder="{{ attribute(_context, settingKey) }}"
|
||||
/>
|
||||
</a>
|
||||
<input type="hidden"
|
||||
name="{{ settingKey }}"
|
||||
value="{{ attribute(_context, settingKey) }}"
|
||||
id="{{ settingKey }}"
|
||||
/>
|
||||
|
||||
{# Image #}
|
||||
{% elseif item['type'] == 'textarea' %}
|
||||
<textarea name="{{ settingKey }}"
|
||||
rows="{{ item['rows'] }}"
|
||||
placeholder="{{ item['placeholder'] }}"
|
||||
id="{{ settingKey }}"
|
||||
class="form-control"
|
||||
>{{ attribute(_context, settingKey) }}</textarea>
|
||||
|
||||
{# Products #}
|
||||
{% elseif item['type'] == 'products' %}
|
||||
<input type="text" value="" placeholder="Начните вводить название товара..." id="{{ settingKey }}-input" class="form-control"/>
|
||||
<div id="{{ settingKey }}-list" class="well well-sm" style="height: 150px; overflow: auto;">
|
||||
{% for product in attribute(_context, settingKey) %}
|
||||
<div id="{{ settingKey }}-{{ product.product_id }}">
|
||||
<i class="fa fa-minus-circle"></i> {{ product.name }}
|
||||
<input type="hidden" name="{{ settingKey }}[]" value="{{ product.product_id }}"/>
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
<script>
|
||||
$('#{{ settingKey }}-input').autocomplete({
|
||||
'source': function(request, response) {
|
||||
$.ajax({
|
||||
url: 'index.php?route=catalog/product/autocomplete&user_token={{ user_token }}&filter_name=' + encodeURIComponent(request),
|
||||
dataType: 'json',
|
||||
success: function(json) {
|
||||
response($.map(json, function(item) {
|
||||
return {
|
||||
label: item['name'],
|
||||
value: item['product_id']
|
||||
}
|
||||
}));
|
||||
}
|
||||
});
|
||||
},
|
||||
'select': function(item) {
|
||||
$('#{{ settingKey }}').val('');
|
||||
$('#{{ settingKey }}-' + item['value']).remove();
|
||||
$('#{{ settingKey }}-list').append('<div id="{{ settingKey }}-' + item['value'] + '"><i class="fa fa-minus-circle"></i> ' + item['label'] + '<input type="hidden" name="{{ settingKey }}[]" value="' + item['value'] + '" /></div>');
|
||||
}
|
||||
});
|
||||
|
||||
$('#{{ settingKey }}-list').delegate('.fa-minus-circle', 'click', function() {
|
||||
$(this).parent().remove();
|
||||
});
|
||||
</script>
|
||||
|
||||
{# ChatID #}
|
||||
{% elseif item['type'] == 'chatid' %}
|
||||
<div class="input-group">
|
||||
<span class="input-group-btn">
|
||||
<button id="{{ settingKey }}-btn" class="btn btn-primary" type="button">
|
||||
<i class="fa fa-refresh"></i> Получить Chat ID
|
||||
</button>
|
||||
</span>
|
||||
<input type="text"
|
||||
name="{{ settingKey }}"
|
||||
value="{{ attribute(_context, settingKey) }}"
|
||||
placeholder="{{ item['placeholder'] }}"
|
||||
id="{{ settingKey }}"
|
||||
class="form-control"
|
||||
/>
|
||||
<script>
|
||||
$('#{{ settingKey }}-btn').click(function () {
|
||||
const telegramToken = $('#module_tgshop_bot_token').val(); // fetch from input
|
||||
if (! telegramToken) {
|
||||
alert('Сначала введите Telegram Bot Token!');
|
||||
return;
|
||||
}
|
||||
|
||||
fetch(`https://api.telegram.org/bot${telegramToken}/getUpdates`)
|
||||
.then(res => res.json())
|
||||
.then(data => {
|
||||
if (!data.ok || !data.result.length) {
|
||||
alert('Не удалось получить обновления от бота. Убедитесь, что вы написали боту сообщение.');
|
||||
return;
|
||||
}
|
||||
|
||||
// Ищем последнее сообщение с chat_id
|
||||
const lastMessage = data.result.reverse().find(update => update.message && update.message.chat);
|
||||
if (!lastMessage) {
|
||||
alert('Не найдено сообщений с chat_id.');
|
||||
return;
|
||||
}
|
||||
|
||||
const chatId = lastMessage.message.chat.id;
|
||||
$('#{{ settingKey }}').val(chatId); // подставляем в поле
|
||||
})
|
||||
.catch(err => {
|
||||
console.error(err);
|
||||
alert('Ошибка при получении chat_id. Проверьте токен и соединение.');
|
||||
});
|
||||
});
|
||||
</script>
|
||||
</div>
|
||||
|
||||
<button class="btn btn-link btn-xs" type="button" data-toggle="collapse" data-target="#{{ settingKey }}-collapse" aria-expanded="false" aria-controls="collapseExample">
|
||||
Инструкция как получить ChatID.
|
||||
</button>
|
||||
<div class="collapse" id="{{ settingKey }}-collapse">
|
||||
<div class="well">
|
||||
<p class="text-primary">Как получить Chat ID</p>
|
||||
<ol>
|
||||
<li>Убедитесь, что вы ввели Telegram Bot Token выше.</li>
|
||||
<li>Откройте вашего бота в Telegram и отправьте ему любое сообщение.</li>
|
||||
<li>Вернитесь сюда и нажмите кнопку «Получить Chat ID» — мы автоматически подставим его в поле ниже.</li>
|
||||
</ol>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{% elseif item['type'] == 'tg_message_template' %}
|
||||
<div style="margin-bottom: 10px;">
|
||||
<textarea name="{{ settingKey }}"
|
||||
rows="{{ item['rows'] }}"
|
||||
placeholder="{{ item['placeholder'] }}"
|
||||
id="{{ settingKey }}"
|
||||
class="form-control"
|
||||
>{{ attribute(_context, settingKey) }}</textarea>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<button class="btn btn-link" type="button" data-toggle="collapse" data-target="#{{ settingKey }}-collapse">
|
||||
Документация
|
||||
</button>
|
||||
<button id="{{ settingKey }}-btn-test" type="button" class="btn btn-primary btn-sm">
|
||||
<i class="fa fa-envelope"></i>
|
||||
Отправить тестовое уведомление
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div class="collapse" id="{{ settingKey }}-collapse" style="margin-top: 15px">
|
||||
<div class="well">
|
||||
<p>Вы можете использовать переменные:</p>
|
||||
<ul>
|
||||
<li><code>{store_name}</code> — название магазина</li>
|
||||
<li><code>{order_id}</code> — номер заказа</li>
|
||||
<li><code>{customer}</code> — имя и фамилия покупателя</li>
|
||||
<li><code>{email}</code> — email покупателя</li>
|
||||
<li><code>{phone}</code> — телефон</li>
|
||||
<li><code>{comment}</code> — комментарий к заказу</li>
|
||||
<li><code>{address}</code> — адрес доставки</li>
|
||||
<li><code>{total}</code> — сумма заказа</li>
|
||||
<li><code>{ip}</code> — IP покупателя</li>
|
||||
<li><code>{created_at}</code> — дата и время создания заказа</li>
|
||||
</ul>
|
||||
<p>Форматирование: поддерживается <a href="https://core.telegram.org/bots/api#markdownv2-style" target="_blank">*MarkdownV2* <i class="fa fa-external-link"></i></a>.</p>
|
||||
<p>Символы, которые нужно экранировать в тексте:</p>
|
||||
<pre>_ * [ ] ( ) ~ ` > # + - = | { } . !</pre>
|
||||
<p>Каждый из них нужно экранировать обратным слэшем \, если он не используется для форматирования. Например вместо <code>Заказ #123</code> нужно писать <code>Заказ \#123</code>.</p>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<script>
|
||||
$('#{{ settingKey }}-btn-test').click(function () {
|
||||
const telegramToken = $('#module_tgshop_bot_token').val(); // fetch from input
|
||||
if (! telegramToken) {
|
||||
alert('Сначала введите Telegram Bot Token!');
|
||||
return;
|
||||
}
|
||||
|
||||
const chatId = $('#module_tgshop_chat_id').val(); // fetch from input
|
||||
if (! chatId) {
|
||||
alert('Сначала введите Chat ID!');
|
||||
return;
|
||||
}
|
||||
|
||||
const template = $('#{{ settingKey }}').val();
|
||||
if (! template) {
|
||||
alert('Сначала задайте шаблон!');
|
||||
return;
|
||||
}
|
||||
|
||||
fetch('/index.php?route=extension/tgshop/handle&api_action=testTgMessage', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
body: JSON.stringify({
|
||||
token: telegramToken,
|
||||
chat_id: chatId,
|
||||
template: template
|
||||
})
|
||||
})
|
||||
.then(res => res.json())
|
||||
.then(response => {
|
||||
alert(response.message || 'Уведомление успешно отправлено');
|
||||
})
|
||||
.catch(error => {
|
||||
console.error(error);
|
||||
alert('Ошибка при отправке тестового сообщения');
|
||||
});
|
||||
});
|
||||
</script>
|
||||
{% else %}
|
||||
Unsupported {{ item|json_encode }}
|
||||
{% endif %}
|
||||
|
||||
{% if attribute(_context, 'error_' ~ settingKey) %}
|
||||
<div class="text-danger">{{ attribute(_context, 'error_' ~ settingKey) }}</div>
|
||||
{% endif %}
|
||||
|
||||
{% if item['help'] %}
|
||||
<p class="help-block">{{ item['help'] }}</p>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{% endfor %}
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{{ footer }}
|
||||
@@ -0,0 +1,48 @@
|
||||
{{ header }}{{ column_left }}
|
||||
<div id="content">
|
||||
<div class="page-header">
|
||||
<div class="container-fluid">
|
||||
<div class="pull-right">
|
||||
<a href="{{ cancel }}" data-toggle="tooltip" title="{{ button_cancel }}" class="btn btn-default"><i
|
||||
class="fa fa-reply"></i></a></div>
|
||||
<h1>{{ heading_title }}</h1>
|
||||
<ul class="breadcrumb">
|
||||
{% for breadcrumb in breadcrumbs %}
|
||||
<li><a href="{{ breadcrumb.href }}">{{ breadcrumb.text }}</a></li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
<div class="container-fluid">
|
||||
{% if error_warning %}
|
||||
<div class="alert alert-danger alert-dismissible"><i
|
||||
class="fa fa-exclamation-circle"></i> {{ error_warning }}
|
||||
<button type="button" class="close" data-dismiss="alert">×</button>
|
||||
</div>
|
||||
{% endif %}
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-heading">
|
||||
<h3 class="panel-title"><i class="fa fa-pencil"></i> Инициализация модуля</h3>
|
||||
</div>
|
||||
<div class="panel-body">
|
||||
|
||||
<div class="col-md-push-4 col-md-4 text-center">
|
||||
<h2>Инициализация модуля</h2>
|
||||
<p>Модуль запускается первый раз, поэтому необходимо инициализировать настройки для его корректной работы.</p>
|
||||
<form action="{{ action }}" method="post" enctype="multipart/form-data" class="form-horizontal">
|
||||
<button type="submit"
|
||||
data-toggle="tooltip"
|
||||
title="Нажмите чтобы выполнить начальную инициализацию модуля"
|
||||
class="btn btn-primary"
|
||||
>
|
||||
Инициализация
|
||||
</button>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{{ footer }}
|
||||
Reference in New Issue
Block a user