Шаблоны в Поддержке

This commit is contained in:
n1rwana 2023-07-25 13:39:37 +03:00
parent a2384cc231
commit 541be355e3
14 changed files with 607 additions and 14 deletions

View file

@ -0,0 +1,40 @@
<?php declare(strict_types=1);
namespace openvk\Web\Models\Entities;
use openvk\Web\Models\Repositories\SupportTemplatesDirs;
use openvk\Web\Models\Repositories\Users;
use openvk\Web\Models\RowModel;
class SupportTemplate extends RowModel
{
protected $tableName = "support_templates";
function getId(): int
{
return $this->getRecord()->id;
}
function getOwner(): ?User
{
return (new Users)->get($this->getRecord()->owner);
}
function getDir(): ?SupportTemplateDir
{
return (new SupportTemplatesDirs)->get($this->getRecord()->dir);
}
function isPublic(): bool
{
return $this->getDir()->isPublic();
}
function getTitle(): string
{
return $this->getRecord()->title;
}
function getText(): string
{
return $this->getRecord()->text;
}
}

View file

@ -0,0 +1,40 @@
<?php declare(strict_types=1);
namespace openvk\Web\Models\Entities;
use openvk\Web\Models\Repositories\SupportTemplates;
use openvk\Web\Models\Repositories\Users;
use openvk\Web\Models\RowModel;
class SupportTemplateDir extends RowModel
{
protected $tableName = "support_templates_dirs";
function getId(): int
{
return $this->getRecord()->id;
}
function getOwner(): ?User
{
return (new Users)->get($this->getRecord()->owner);
}
function isPublic(): bool
{
return (bool) $this->getRecord()->is_public;
}
function getTitle(): string
{
return $this->getRecord()->title;
}
function getText(): string
{
return $this->getRecord()->text;
}
function getTemplates(): \Traversable
{
return (new SupportTemplates)->getListByDirId($this->getId());
}
}

View file

@ -0,0 +1,33 @@
<?php declare(strict_types=1);
namespace openvk\Web\Models\Repositories;
use Nette\Database\Table\ActiveRow;
use Chandler\Database\DatabaseConnection;
use openvk\Web\Models\Entities\{SupportTemplate, SupportAgent};
class SupportTemplates
{
private $context;
private $templates;
function __construct()
{
$this->context = DatabaseConnection::i()->getContext();
$this->templates = $this->context->table("support_templates");
}
private function toTemplate(?ActiveRow $ar): ?SupportTemplate
{
return is_null($ar) ? NULL : new SupportTemplate($ar);
}
function get(int $id): ?SupportTemplate
{
return $this->toTemplate($this->templates->get($id));
}
function getListByDirId(int $dir_id): \Traversable
{
foreach ($this->templates->where(["dir" => $dir_id, "deleted" => 0]) as $template)
yield new SupportTemplate($template);
}
}

View file

@ -0,0 +1,33 @@
<?php declare(strict_types=1);
namespace openvk\Web\Models\Repositories;
use Nette\Database\Table\ActiveRow;
use Chandler\Database\DatabaseConnection;
use openvk\Web\Models\Entities\{SupportTemplateDir};
class SupportTemplatesDirs
{
private $context;
private $dirs;
function __construct()
{
$this->context = DatabaseConnection::i()->getContext();
$this->dirs = $this->context->table("support_templates_dirs");
}
private function toDir(?ActiveRow $ar): ?SupportTemplateDir
{
return is_null($ar) ? NULL : new SupportTemplateDir($ar);
}
function get(int $id): ?SupportTemplateDir
{
return $this->toDir($this->dirs->get($id));
}
function getList(int $uid): \Traversable
{
foreach ($this->dirs->where("(owner=$uid OR is_public=1) AND deleted=0") as $dir)
yield new SupportTemplateDir($dir);
}
}

View file

@ -1,7 +1,12 @@
<?php declare(strict_types=1);
namespace openvk\Web\Presenters;
use openvk\Web\Models\Entities\{SupportAgent, Ticket, TicketComment};
use openvk\Web\Models\Repositories\{Tickets, Users, TicketComments, SupportAgents};
use openvk\Web\Models\Entities\{SupportAgent, SupportTemplate, SupportTemplateDir, Ticket, TicketComment};
use openvk\Web\Models\Repositories\{SupportTemplates,
SupportTemplatesDirs,
Tickets,
Users,
TicketComments,
SupportAgents};
use openvk\Web\Util\Telegram;
use Chandler\Session\Session;
use Chandler\Database\DatabaseConnection;
@ -210,7 +215,6 @@ final class SupportPresenter extends OpenVKPresenter
$this->template->ticket = $ticket;
$this->template->comments = $ticketComments;
$this->template->id = $id;
$this->template->fastAnswers = OPENVK_ROOT_CONF["openvk"]["preferences"]["support"]["fastAnswers"];
}
function renderAnswerTicketReply(int $id): void
@ -396,4 +400,233 @@ final class SupportPresenter extends OpenVKPresenter
$this->flashFail("succ", "Успех", "Профиль создан. Теперь пользователи видят Ваши псевдоним и аватарку вместо стандартных аватарки и номера.");
}
}
function renderGetTemplatesDirs(): void
{
$this->assertPermission("openvk\Web\Models\Entities\TicketReply", "write", 0);
$dirs = [];
foreach ((new SupportTemplatesDirs)->getList($this->user->identity->getId()) as $dir) {
$dirs[] = ["id" => $dir->getId(), "title" => $dir->getTitle()];
}
$this->returnJson(["success" => true, "dirs" => $dirs]);
}
function renderGetTemplatesInDir(int $dirId): void
{
$this->assertPermission("openvk\Web\Models\Entities\TicketReply", "write", 0);
$dir = (new SupportTemplatesDirs)->get($dirId);
if (!$dir || $dir->getOwner()->getId() !== $this->user->identity->getId() && !$dir->isPublic()) {
$this->returnJson(["success" => false, "error" => tr("forbidden")]);
}
$templates = [];
foreach ($dir->getTemplates() as $template) {
$templateData = [
"id" => $template->getId(),
"title" => $template->getTitle(),
"text" => $template->getText(),
];
if ($this->queryParam("tid")) {
$ticket = (new Tickets)->get((int) $this->queryParam("tid"));
$ticket_user = $ticket->getUser();
$replacements = [
"{user_name}" => $ticket_user->getFirstName(),
"{last_name}" => $ticket_user->getLastName(),
"{unban_time}" => $ticket_user->getUnbanTime(),
];
if ($ticket->getId()) {
foreach ($replacements as $search => $replace) {
$templateData["text"] = str_replace($search, $replace, $templateData["text"]);
}
}
}
$templates[] = $templateData;
}
$this->returnJson(["success" => true, "templates" => $templates]);
}
function renderCreateTemplatesDir(): void
{
$this->assertPermission("openvk\Web\Models\Entities\TicketReply", "write", 0);
$this->assertNoCSRF();
if ($_SERVER["REQUEST_METHOD"] === "POST") {
$dir = new SupportTemplateDir;
$dir->setTitle($this->postParam("title"));
$dir->setOwner($this->user->identity->getId());
$dir->setIs_Public(!empty($this->postParam("is_public")));
$dir->save();
$this->flashFail("succ", tr("changes_saved"));
}
}
function renderTemplates(): void
{
$this->assertPermission("openvk\Web\Models\Entities\TicketReply", "write", 0);
$mode = in_array($this->queryParam("act"), ["dirs", "list", "create_dir", "create_template", "edit_dir", "edit_template"]) ? $this->queryParam("act") : "dirs";
if ($_SERVER["REQUEST_METHOD"] === "POST") {
$this->assertNoCSRF();
if ($mode === "create_dir" || $mode === "edit_dir") {
$dirId = (int) $this->queryParam("dir");
$dir = ($mode === "create_dir") ? new SupportTemplateDir : (new SupportTemplatesDirs)->get($dirId);
if ($mode === "edit_dir" && (!$dir || $dir->isDeleted())) {
$this->notFound();
}
if ($mode === "edit_dir" && $dir->getOwner()->getId() !== $this->user->identity->getId()) {
$this->flashFail("err", tr("forbidden"));
}
$dir->setTitle($this->postParam("title"));
$dir->setOwner($this->user->identity->getId());
$dir->setIs_Public(!empty($this->postParam("is_public")));
$dir->save();
if ($mode === "create_dir") {
$this->redirect("/support/templates?act=list&dir=" . $dir->getId());
} else {
$this->flashFail("succ", tr("changes_saved"));
}
} else if ($mode === "create_template" || $mode === "edit_template") {
$templateId = (int) $this->queryParam("id");
$template = ($mode === "create_template") ? new SupportTemplate : (new SupportTemplates)->get($templateId);
if (!$template || $template->isDeleted()) {
$this->notFound();
}
if ($mode === "edit_template" && $template->getOwner()->getId() !== $this->user->identity->getId()) {
$this->flashFail("err", tr("forbidden"));
}
$dirId = ($mode === "create_template") ? (int) $this->queryParam("dir") : $template->getDir()->getId();
$dir = (new SupportTemplatesDirs)->get($dirId);
if ($mode === "create_template" && $dir->getOwner()->getId() !== $this->user->identity->getId()) {
$this->flashFail("err", tr("forbidden"));
}
if (!$dir || $dir->isDeleted()) {
$this->notFound();
}
if ($dir->getOwner()->getId() !== $this->user->identity->getId()) {
$this->flashFail("err", tr("forbidden"));
}
$template->setOwner($this->user->identity->getId());
$template->setDir($dir->getId());
$template->setTitle($this->postParam("title"));
$template->setText($this->postParam("text"));
$template->save();
if ($mode === "create_template") {
$this->redirect("/support/templates?act=list&dir=" . $dirId . "&id=" . $template->getId());
} else {
$this->flashFail("succ", tr("changes_saved"));
}
}
} else {
$this->template->mode = $mode;
if (!$this->queryParam("dir")) {
$dirs = (new SupportTemplatesDirs)->getList($this->user->identity->getId());
$this->template->dirs = $dirs;
$this->template->dirsCount = count($dirs);
if ($mode === "edit_template") {
$templateId = (int) $this->queryParam("id");
$template = (new SupportTemplates)->get($templateId);
if (!$template || $template->isDeleted()) {
$this->notFound();
}
if ($template->getOwner()->getId() !== $this->user->identity->getId()) {
$this->flashFail("err", tr("forbidden"));
}
$this->template->dir = $template->getDir();
$this->template->activeTemplate = $template;
}
} else {
$dirId = (int) $this->queryParam("dir");
$dir = (new SupportTemplatesDirs)->get($dirId);
if (!$dir || $dir->isDeleted()) {
$this->notFound();
}
if ($mode === "edit_dir" && $dir->getOwner()->getId() !== $this->user->identity->getId()) {
$this->flashFail("err", tr("forbidden"));
}
if ($mode === "create_template" && $dir->getOwner()->getId() !== $this->user->identity->getId()) {
$this->flashFail("err", tr("forbidden"));
}
$this->template->dir = $dir;
$templates = $dir->getTemplates();
$this->template->templates = $templates;
$this->template->templatesCount = count($templates);
$this->template->selectedTemplate = (int) $this->queryParam("id");
}
}
}
function renderDeleteDir(int $id): void
{
$this->assertPermission("openvk\Web\Models\Entities\TicketReply", "write", 0);
$dir = (new SupportTemplatesDirs)->get($id);
if (!$dir || $dir->isDeleted()) {
$this->notFound();
}
if ($dir->getOwner()->getId() !== $this->user->identity->getId()) {
$this->flashFail("err", tr("forbidden"));
}
$templates = $dir->getTemplates();
foreach ($templates as $template) {
$template->delete();
}
$dir->delete();
$this->redirect("/support/templates");
}
function renderDeleteTemplate(int $id): void
{
$this->assertPermission("openvk\Web\Models\Entities\TicketReply", "write", 0);
$template = (new SupportTemplates)->get($id);
if (!$template || $template->isDeleted()) {
$this->notFound();
}
if ($template->getOwner()->getId() !== $this->user->identity->getId()) {
$this->flashFail("err", tr("forbidden"));
}
$dir = $template->getDir()->getId();
$template->delete();
$this->redirect("/support/templates?act=list&dir=$dir");
}
}

View file

@ -33,8 +33,8 @@
<option value="0">{_support_status_0}</option>
</select>
</div>
<div n:if="!is_null($fastAnswers)" style="float: right;">
<a class="button" href="javascript:showSupportFastAnswerDialog(fastAnswers)">{_fast_answers}</a>
<div style="float: right;">
<a class="button" href="javascript:getTemplatesDirs({$ticket->getId()}, true)">{_fast_answers}</a>
</div>
<br />
</form>
@ -123,10 +123,9 @@
</table>
<script>
const fastAnswers = [
{foreach $fastAnswers as $answer}
{$answer},
{/foreach}
];
function toggleTemplateTextShow(id) {
const elem = document.getElementById('template-text-' + id);
elem.style.display = (elem.style.display === "none" ? "block" : "none");
}
</script>
{/block}

View file

@ -21,6 +21,9 @@
<div class="tab">
<a href="/support/agent{$thisUser->getId()}">Мой профиль</a>
</div>
<div class="tab">
<a href="/support/templates">{_support_my_templates}</a>
</div>
{/block}
{* BEGIN ELEMENTS DESCRIPTION *}

View file

@ -0,0 +1,93 @@
{extends "../@layout.xml"}
{block header}
<div n:if="$mode === 'dirs'">{_support_my_templates}</div>
<div n:if="$mode === 'list'"><a href="/support/templates">{_support_my_templates}</a> > {$dir->getTitle()}</div>
<div n:if="$mode === 'create_dir'"><a href="/support/templates">{_support_my_templates}</a> > {_support_create_templates_dir}</div>
<div n:if="$mode === 'create_template'">
<a href="/support/templates">{_support_my_templates}</a>
> <a href="/support/templates?act=list&dir={$dir->getId()}">{$dir->getTitle()}</a>
> {_support_create_template}
</div>
<div n:if="$mode === 'edit_dir'">
<a href="/support/templates">{_support_my_templates}</a>
> <a href="/support/templates?act=list&dir={$dir->getId()}">{$dir->getTitle()}</a>
> {_edit}
</div>
<div n:if="$mode === 'edit_template'">
<a href="/support/templates">{_support_my_templates}</a>
> <a href="/support/templates?act=list&dir={$dir->getId()}">{$dir->getTitle()}</a>
> <a href="/support/templates?act=list&dir={$dir->getId()}&id={$activeTemplate->getId()}">{$activeTemplate->getTitle()}</a>
> {_edit}
</div>
{/block}
{block content}
<div n:if="$mode === 'dirs'">
<div>
<a class="button" href="/support/templates?act=create_dir">{_support_create_templates_dir}</a>
</div>
<br/>
<div n:if="$dirsCount <= 0" style="padding: 32px">
<center>{_no_data_description}</center>
</div>
<div n:foreach="$dirs as $dir">
<a href="/support/templates?act=list&dir={$dir->getId()}">
<h4 style="padding: 8px;">
{$dir->getTitle()}
<a n:if="$dir->getOwner()->getId() === $thisUser->getId()" href="/support/templates?act=edit_dir&dir={$dir->getId()}">({_edit})</a>
</h4>
</a>
</div>
</div>
<div n:if="$mode === 'list'">
<div n:if="$dir->getOwner()->getId() === $thisUser->getId()">
<a class="button" href="/support/templates?act=create_template&dir={$dir->getId()}">{_support_create_template}</a>
<a class="button" href="/support/templates_dir{$dir->getId()}/delete">{_support_remove_templates_dir_1} <b>{_support_remove_templates_dir_2}</b></a>
</div>
<br/>
<div n:if="$templatesCount <= 0" style="padding: 32px">
<center>{_no_data_description}</center>
</div>
<div n:foreach="$templates as $template">
<h4 style="padding: 8px; cursor: pointer;" onclick="toggleTemplateTextShow({$template->getId()})">
{$template->getTitle()}
<a n:if="$template->getOwner()->getId() === $thisUser->getId()" href="/support/templates?act=edit_template&id={$template->getId()}">({_edit})</a>
</h4>
<div id="template-text-{$template->getId()}" style="display: none; padding: 8px; white-space: pre-wrap;">{$template->getText()}</div>
</div>
</div>
<div n:if="$mode === 'create_dir' || $mode === 'edit_dir'">
<form method="post">
<input type="text" placeholder="{_support_templates_dir_name}" name="title" n:attr="value => $mode === 'edit_dir' ? $dir->getTitle() : ''" />
<input type="checkbox" value="1" name="is_public" n:attr="checked => $mode === 'edit_dir' ? $dir->isPublic() : false"/> {_support_public_templates_dir}
<input type="hidden" value="{$csrfToken}" name="hash"/>
<input type="submit" n:attr="value => ($mode === 'create_dir' ? tr(create) : tr(save))" class="button" />
</form>
</div>
<div n:if="$mode === 'create_template' || $mode === 'edit_template'">
<form method="post">
<input n:attr="value => $mode === 'edit_template' ? $activeTemplate->getTitle() : ''" type="text" placeholder="{_support_template_name}" name="title"/>
<textarea style="resize: vertical;" name="text" placeholder="{_support_template_text}">{$mode === 'edit_template' ? $activeTemplate->getText() : ''}</textarea>
<ul>
<li><b>{="{user_name}"}</b> — {_support_template_replacement_user_name}</li>
<li><b>{="{last_name}"}</b> — {_support_template_replacement_last_name}</li>
<li><b>{="{unban_time}"}</b> — {_support_template_replacement_unban_time}</li>
</ul>
<input type="hidden" value="{$csrfToken}" name="hash"/>
<input type="submit" n:attr="value => ($mode === 'create_template' ? tr(create) : tr(save))" class="button" />
<a n:if="$mode === 'edit_template'" class="button" href="/support/template{$activeTemplate->getId()}/delete">{_delete}</a>
</form>
</div>
<script>
function toggleTemplateTextShow(id, scrollTo) {
if (!scrollTo) scrollTo = false;
const elem = document.getElementById('template-text-' + id);
elem.style.display = (elem.style.display === 'none' ? 'inherit' : 'none');
if (scrollTo) elem.scrollIntoView();
}
toggleTemplateTextShow({$selectedTemplate}, true)
</script>
{/block}

View file

@ -35,6 +35,18 @@ routes:
handler: "Support->agent"
- url: "/support/agent{num}/edit"
handler: "Support->editAgent"
- url: "/al_helpdesk/get_templates_dirs"
handler: "Support->getTemplatesDirs"
- url: "/al_helpdesk/td{num}/templates"
handler: "Support->getTemplatesInDir"
- url: "/al_helpdesk/create_templates_dir"
handler: "Support->createTemplatesDir"
- url: "/support/templates"
handler: "Support->templates"
- url: "/support/templates_dir{num}/delete"
handler: "Support->deleteDir"
- url: "/support/template{num}/delete"
handler: "Support->deleteTemplate"
- url: "/language"
handler: "About->language"
- url: "/language/{text}.js"

View file

@ -344,6 +344,57 @@ function supportFastAnswerDialogOnClick(answer) {
answerInput.focus();
}
function getTemplatesDirs(tid) {
$.ajax("/al_helpdesk/get_templates_dirs").done((response) => {
console.log(response, response.success);
if (response.success) {
const dirsHtml = response.dirs.length > 0 ? response.dirs.map((dir) => `
<li style="cursor: pointer;" onclick="getTemplatesInDir(${dir.id}, ${tid})">
<h4 style="padding: 8px;">${dir.title}</h4>
</li>
`).join("") : `<center>${tr("no_data_description")}</center>`;
const managementLink = `<a href="/support/templates" target="_blank" class="button">${tr("edit")}</a>`;
if (document.getElementsByClassName('ovk-diag-body').length === 0) {
MessageBox(tr("fast_answers"), `${managementLink}<ul style="padding-inline-start: 8px; overflow-y: auto; max-height: 70vh;">${dirsHtml}</ul>`, [tr("close")], [
Function.noop
]);
} else {
document.getElementsByClassName('ovk-diag-body')[0].innerHTML = `${managementLink}<ul style="padding-inline-start: 8px; overflow-y: auto; max-height: 70vh;">${dirsHtml}</ul>`;
}
}
});
}
function getTemplatesInDir(dir, ticket) {
$.ajax(`/al_helpdesk/td${dir}/templates?tid=${ticket}`).done((response) => {
console.log(response, response.success);
if (response.success) {
let html = "";
response.templates.forEach((template) => {
html += '\
<li onclick="toggleTemplateTextShow(' + template.id + ')" style="cursor: pointer;" onclick="toggleTemplateTextShow(' + template.id + ')">\
<h4 style="padding: 8px;">' + template.title + '</h4>\
<div id="template-text-' + template.id +'" style="color: #000; white-space: pre-wrap; display: none;">\
' + template.text + '\
<br/><br/><button class="button" onclick="document.getElementById(`answer_text`).value=`' + template.text.replaceAll("\"", "&quot;") + '`">' + tr("support_apply_template") + '</button>\
</div>\
</li>';
});
const templatesListHtml = response.templates.length > 0
? `<a href="javascript:getTemplatesDirs(${ticket}, false)">< ${tr("paginator_back")}</a><ul style="padding-inline-start: 8px; overflow-y: auto; max-height: 70vh;">${html}</ul>`
: `<center>${tr("no_data_description")}</center>`;
document.getElementsByClassName("ovk-diag-body")[0].innerHTML = templatesListHtml;
}
});
}
function ovk_proc_strtr(string, length = 0) {
const newString = string.substring(0, length);
return newString + (string !== newString ? "…" : "");

View file

@ -0,0 +1,33 @@
CREATE TABLE `support_templates_dirs`
(
`id` bigint(20) UNSIGNED NOT NULL,
`owner` bigint(20) UNSIGNED NOT NULL,
`is_public` tinyint(1) NOT NULL DEFAULT 0,
`title` tinytext COLLATE utf8mb4_unicode_ci NOT NULL,
`deleted` tinyint(1) NOT NULL DEFAULT 0
) ENGINE = InnoDB
DEFAULT CHARSET = utf8mb4;
ALTER TABLE `support_templates_dirs`
ADD PRIMARY KEY (`id`);
ALTER TABLE `support_templates_dirs`
MODIFY `id` bigint(20) UNSIGNED NOT NULL AUTO_INCREMENT;
COMMIT;
CREATE TABLE `support_templates`
(
`id` bigint(20) UNSIGNED NOT NULL,
`owner` bigint(20) UNSIGNED NOT NULL,
`dir` bigint(20) UNSIGNED NOT NULL,
`title` tinytext COLLATE utf8mb4_unicode_ci NOT NULL,
`text` longtext COLLATE utf8mb4_unicode_ci NOT NULL,
`deleted` tinyint(1) NOT NULL DEFAULT 0
) ENGINE = InnoDB
DEFAULT CHARSET = utf8mb4;
ALTER TABLE `support_templates`
ADD PRIMARY KEY (`id`);
ALTER TABLE `support_templates`
MODIFY `id` bigint(20) UNSIGNED NOT NULL AUTO_INCREMENT;

View file

@ -913,6 +913,20 @@
"banned_in_support_1" = "Sorry, <b>$1</b>, but now you can't create tickets.";
"banned_in_support_2" = "And the reason for this is simple: <b>$1</b>. Unfortunately, this time we had to take away this opportunity from you forever.";
"support_my_templates" = "My templates";
"support_create_templates_dir" = "Create folder";
"support_create_template" = "Create template";
"support_public_templates_dir" = "Other agents can use";
"support_remove_templates_dir_1" = "Delete folder";
"support_remove_templates_dir_2" = "with templates";
"support_templates_dir_name" = "Folder name";
"support_template_replacement_user_name" = "User's first name";
"support_template_replacement_last_name" = "User's last name";
"support_template_replacement_unban_time" = "User's unban time";
"support_template_text" = "Template Text";
"support_template_name" = "Template Name";
"support_apply_template" = "Use";
/* Invite */
"invite" = "Invite";

View file

@ -841,6 +841,19 @@
"ticket_changed_comment" = "Изменения вступят силу через несколько секунд.";
"banned_in_support_1" = "Извините, <b>$1</b>, но теперь вам нельзя создавать обращения.";
"banned_in_support_2" = "А причина этому проста: <b>$1</b>. К сожалению, на этот раз нам пришлось отобрать у вас эту возможность навсегда.";
"support_my_templates" = "Мои шаблоны";
"support_create_templates_dir" = "Создать папку";
"support_create_template" = "Создать шаблон";
"support_public_templates_dir" = "Видят другие агенты";
"support_remove_templates_dir_1" = "Удалить папку";
"support_remove_templates_dir_2" = "вместе с шаблонами";
"support_templates_dir_name" = "Название папки с шаблонами";
"support_template_replacement_user_name" = "Имя пользователя";
"support_template_replacement_last_name" = "Фамилия пользователя";
"support_template_replacement_unban_time" = "Время разблокировки";
"support_template_text" = "Текст шаблона";
"support_template_name" = "Название шаблона";
"support_apply_template" = "Применить";
/* Invite */

View file

@ -44,10 +44,6 @@ openvk:
support:
supportName: "Agent"
adminAccount: 1 # Change this ok
fastAnswers:
- "This is a list of quick answers to common questions for support. Post your responses here and agents can send it quickly with just 3 clicks"
- "There can be as many answers as you want, but it is best to have a maximum of 10.\n\nYou can also remove all answers from the list to disable this feature"
- "Good luck filling! If you are a regular support agent, inform the administrator that he forgot to fill the config"
messages:
strict: false
wall: