Улучшенная регистрация пользователя

This commit is contained in:
Arsen Mirzaev Tatyano-Muradovich 2021-06-24 15:18:34 +10:00
parent cc1e7e7d66
commit c4035d8ad3
13 changed files with 360 additions and 64 deletions

View File

@ -11,6 +11,7 @@ use yii\filters\AccessControl;
use Throwable;
use Exception;
use yii\bootstrap\ActiveForm;
class AuthenticationController extends Controller
{
@ -35,15 +36,19 @@ class AuthenticationController extends Controller
public function actionIndex()
{
if (yii::$app->request->isAjax) {
// Инициализация
$model = new AccountForm(yii::$app->request->post('AccountForm'));
$type = yii::$app->request->post('type') ?? yii::$app->request->get('type');
$model->scenario = $model::SCENARIO_AUTHENTICATION;
if (yii::$app->request->isPost) {
// AJAX-POST-запрос
// Инициализация
$model = new AccountForm(yii::$app->request->post('AccountForm'));
$model->scenario = $model::SCENARIO_AUTHENTICATION;
yii::$app->response->format = Response::FORMAT_JSON;
// Валидация формы
if (!empty($errors = ActiveForm::validate($model))) return $errors;
if (!yii::$app->user->isGuest || $model->authentication()) {
// Аккаунт аутентифицирован

View File

@ -0,0 +1,15 @@
<?php
declare(strict_types=1);
namespace app\controllers;
use yii\web\Controller;
class PolicyController extends Controller
{
public function actionIndex()
{
return $this->render('/policy/index');
}
}

View File

@ -10,28 +10,15 @@ use yii\web\Controller;
use yii\web\Response;
use app\models\AccountForm;
use yii\bootstrap\ActiveForm;
class RegistrationController extends Controller
{
// public function behaviors()
// {
// return [
// 'access' => [
// 'class' => AccessControl::class,
// 'rules' => [
// [
// 'allow' => true,
// 'roles' => ['?'],
// ]
// ],
// ]
// ];
// }
public function actionIndex()
{
// Инициализация
$model = new AccountForm(yii::$app->request->post('AccountForm') ?? yii::$app->request->get('AccountForm'));
$type = yii::$app->request->post('type') ?? yii::$app->request->get('type');
$model->scenario = $model::SCENARIO_REGISTRATION;
if (yii::$app->request->isPost) {
@ -39,7 +26,10 @@ class RegistrationController extends Controller
yii::$app->response->format = Response::FORMAT_JSON;
if (!yii::$app->user->isGuest || $model->registration()) {
// Валидация формы
if (!empty($errors = ActiveForm::validate($model))) return $errors;
if ($type === 'registration' && (!yii::$app->user->isGuest || $model->registration())) {
// Данные прошли проверку и аккаунт был создан
// Аутентификация
@ -88,7 +78,7 @@ class RegistrationController extends Controller
yii::$app->response->statusCode = 400;
return [
'main' => $this->renderPartial('/account/index', compact('model')),
'main' => $this->renderPartial('/account/index', compact('model') + ['registration' => true]),
'redirect' => '/registration',
'_csrf' => yii::$app->request->getCsrfToken()
];
@ -98,7 +88,7 @@ class RegistrationController extends Controller
if (!yii::$app->user->isGuest) {
yii::$app->response->redirect('/');
} else {
return $this->render('/account/index', compact('model'));
return $this->render('/account/index', compact('model') + ['registration' => true]);
}
}
}

View File

@ -24,6 +24,8 @@ class AccountForm extends Model
public $mail;
public $pswd;
public $auto = false;
public $rept;
public $pols;
private $account = false;
@ -32,14 +34,63 @@ class AccountForm extends Model
{
return [
// Обязательные поля
[['mail', 'pswd'], 'required', 'message' => 'Заполните поле'],
[
[
'mail',
'pswd'
],
'required',
'message' => 'Заполните поле'
],
// Обязательные поля для регистрации
[
[
'rept',
'pols'
],
'required',
'message' => 'Заполните поле',
'on' => self::SCENARIO_REGISTRATION
],
// Повтор пароля
[
'rept',
'compare',
'compareAttribute' => 'pswd',
'message' => "Пароли не совпадают",
'on' => self::SCENARIO_REGISTRATION,
],
// Принятие политики конфидециальности
[
'pols',
'compare',
'compareValue' => 'on',
'message' => "Чтобы продолжить примите нашу политику конфидециальности",
'on' => self::SCENARIO_REGISTRATION,
],
// Функция "Запомнить меня"
['auto', 'boolean', 'on' => self::SCENARIO_AUTHENTICATION],
[
'auto',
'boolean',
'on' => self::SCENARIO_AUTHENTICATION
],
// Проверка почты,
['mail', 'email', 'message' => 'Проверьте почту'],
['mail', 'validateMail', 'on' => self::SCENARIO_REGISTRATION],
[
'mail',
'email',
'message' => 'Проверьте почту'
],
[
'mail',
'validateMail',
'on' => self::SCENARIO_REGISTRATION
],
// Проверка пароля
['pswd', 'validatePassword', 'on' => self::SCENARIO_AUTHENTICATION]
[
'pswd',
'validatePassword',
'on' => self::SCENARIO_AUTHENTICATION
]
];
}
@ -48,7 +99,8 @@ class AccountForm extends Model
return [
'mail' => 'Почта',
'pswd' => 'Пароль',
'auto' => '<i class="fas fa-lock"></i>'
'auto' => '<i class="fas fa-lock"></i>',
'pols' => 'Политика конфедециальности'
];
}
@ -59,6 +111,12 @@ class AccountForm extends Model
$account = $this->getAccount();
if (is_null($account)) {
// Не удалось проверить аккаунт
return;
}
if (!$account || $account->validateMail($this->mail)) {
// Проверка не пройдена
@ -74,6 +132,12 @@ class AccountForm extends Model
$account = $this->getAccount();
if (is_null($account)) {
// Не удалось проверить аккаунт
return;
}
if (!$account || !$account->validatePassword($this->pswd)) {
// Проверка не пройдена
@ -111,7 +175,7 @@ class AccountForm extends Model
// Инициализация нового аккаунта
$this->account = new Account();
if (isset($this->mail, $this->pswd) && $this->validate()) {
if ($this->validate()) {
// Проверка пройдена
// Запись параметров

View File

@ -16,34 +16,68 @@ use app\models\AccountForm;
<div class="row">
<div class="mx-auto">
<?php
// Инициализация идентификатора формы
$form_id = ($isPopupMenu ?? false) ? 'form_account_menu' : 'form_account';
$form = ActiveForm::begin([
'id' => 'form_account',
'id' => $form_id,
'action' => false,
'fieldConfig' => [
'template' => '{label}{input}{error}',
'options' => ['class' => '']
'options' => [
'class' => ''
]
],
'options' => [
'class' => '',
'class' => 'form_account',
'onsubmit' => 'return false;'
]
],
'enableClientValidation' => false,
'enableAjaxValidation' => true
]);
$model = $model ?? new AccountForm;
?>
<?= $form->field($model, 'mail', ['enableLabel' => false, 'options' => ['class' => 'mb-2']])->textInput(['autofocus' => true, 'placeholder' => $model->getAttributeLabel('mail')]) ?>
<?= $form->field($model, 'pswd', ['enableLabel' => false])->passwordInput(['placeholder' => $model->getAttributeLabel('pswd')]) ?>
<?php if ($registration ?? false) : ?>
<?php if ($isPopupMenu ?? false) : ?>
<h5 class="mb-4 text-center">Регистрация</h5>
<?php else : ?>
<h3 class="mb-4 text-center">Регистрация</h3>
<?php endif ?>
<?php else : ?>
<?php if ($isPopupMenu ?? false) : ?>
<h5 class="mb-4 text-center">Аутентификация</h5>
<?php else : ?>
<h3 class="mb-4 text-center">Аутентификация</h3>
<?php endif ?>
<?php endif ?>
<div class="d-flex mb-2 mt-3">
<?= $form->field($model, 'mail', ['enableLabel' => false, 'options' => ['class' => 'mb-2'], 'errorOptions' => ['class' => 'help-block help-block-error small']])->textInput(['autofocus' => true, 'placeholder' => $model->getAttributeLabel('mail')]) ?>
<?= $form->field($model, 'pswd', ['enableLabel' => false, 'errorOptions' => ['class' => 'help-block help-block-error small']])->passwordInput(['placeholder' => $model->getAttributeLabel('pswd')]) ?>
<div class="d-flex mb-2 mt-4">
<?= Html::submitButton('Войти', ['name' => 'submitAuthentication', 'onclick' => 'authentication(this.parentElement.parentElement);', 'class' => 'flex-grow-1 mr-2 btn btn-primary button_clean']) ?>
<?= $form->field($model, 'auto', ['checkboxTemplate' => '<div class="checkbox button_clean">{beginLabel}' .
Html::submitButton('{labelTitle}', ['name' => 'submit', 'data-toggle' => 'button', 'class' => 'w-100 btn btn-primary button_clean', 'aria-pressed' => 'false']) .
'{endLabel}</div>'])->checkbox()->label($model->getAttributeLabel('auto'), ['class' => 'w-100 m-0']) ?>
</div>
<?= Html::submitButton('Регистрация', ['name' => 'submitRegistration', 'onclick' => 'registration(this.parentElement);', 'class' => 'col-12 ml-auto btn btn-success btn-sm button_clean']) ?>
<?= Html::submitButton('Регистрация', ['name' => 'submitRegistration', 'onclick' => 'return registration_start(this.parentElement);', 'class' => 'col-12 ml-auto btn btn-success btn-sm button_clean']) ?>
<?php ActiveForm::end(); ?>
</div>
</div>
</div>
</div>
<?php if ($registration ?? false) : ?>
<script defer>
document.addEventListener('DOMContentLoaded', function() {
let form = document.getElementById('<?= $form_id ?>');
$(form).on('afterInit', function(e) {
registration_start(form);
});
}, false);
</script>
<?php endif ?>

View File

@ -4,19 +4,8 @@ declare(strict_types=1);
use yii;
if (!yii::$app->user->isGuest) {
// $popup = yii::$app->controller->renderPartial('/notification/panel');
// echo <<<HTML
// <a id="notification_button" class="text-dark d-flex h-100 mr-2" title="Уведомления" role="button" data-toggle="dropdown" data-offset="-100%p + 100%" onclick="return notification_stream();">
// <i class="fas fa-bell my-auto mx-2"></i>
// </a>
// <div id="notification_button_panel" class="dropdown-menu p-2" aria-labelledby="notification_button">
// $popup
// </div>
// HTML;
}
?>
<?=$notifications_button?>
<?=$notifications_panel?>
<a class="text-dark my-auto mr-2" title="Корзина" href="/cart" role="button" onclick="return page_cart();"><i class="fas fa-shopping-cart mx-2"></i></a>
@ -27,4 +16,4 @@ if (!yii::$app->user->isGuest) {
<div id="profile_button_panel" class="dropdown-menu dropdown-menu-right py-1" aria-labelledby="profile_button" onmouseout="$('#profile_button').dropdown('show')">
<a class="dropdown-item button_white text-dark" onclick="deauthentication()">Выход (<?= yii::$app->user->identity->mail ?>)</a>
</div>
</div>
</div>

View File

@ -5,14 +5,14 @@ declare(strict_types=1);
use yii;
?>
<a class="text-dark my-auto mr-2" title="Корзина" href="/cart" role="button" onclick="return page_cart();"><i class="fas fa-shopping-cart mx-2"></i></a>
<a class="text-dark my-auto mr-2" title="Заказы" href="/orders" role="button" onclick="return page_orders();"><i class="fas fa-list mx-2"></i></a>
<div class="btn-group my-auto">
<a class="btn m-0 px-0 text-dark button_clean" title="Личный кабинет" href="/profile" role="button" onclick="return page_profile();">Личный кабинет</a>
<button id="profile_button" class="btn pr-0 dropdown-toggle dropdown-toggle-split button_clean" type="button" data-toggle="dropdown" onmouseover="$('#profile_button').dropdown('show')"></button>
<div id="profile_button_panel" class="dropdown-menu dropdown-menu-long dropdown-menu-right p-3" aria-labelledby="profile_button" onmouseout="$('#profile_button').dropdown('show')">
<h5 class="mb-3 text-center">Аутентификация</h5>
<?= yii::$app->controller->renderPartial('/account/index', compact('model')) ?>
<?= yii::$app->controller->renderPartial('/account/index', compact('model') + ['isPopupMenu' => true]) ?>
<!-- <a class="dropdown-item-text text-center px-0 py-2" href="#"><small>Восстановление пароля</small></a> -->
</div>
</div>
</div>

View File

@ -2,8 +2,9 @@
declare(strict_types=1);
$this->title = 'SkillParts';
use yii;
$this->title = 'SkillParts';
?>
<link href="/css/ticker.css" rel="stylesheet">
@ -84,4 +85,4 @@ $this->title = 'SkillParts';
</section>
</div>
<script src="/js/ticker.js" defer></script>
<script src="/js/ticker.js" defer></script>

View File

@ -0,0 +1,53 @@
<link href="/css/pages/policy.css" rel="stylesheet">
<div id="page_policy" class="container mb-auto py-3">
<article class="p-5 rounded overflow-hidden">
<div class="row mb-5">
<div class="col">
<h3 class="mb-5 text-center"><b>Политика конфидециальности</b></h3>
В данной Политике обработки персональных данных (далее Политика) мы информируем Вас о порядке обработки Ваших персональных данных при использовании нашего веб-сайта https://skillparts.ru/ (далее - «Сайт») в целях исполнения заключенных договоров.
</br></br>
Мы обязуемся обеспечить конфиденциальность полученных от Вас с Вашего логина персональных данных физических лиц для целей, указанных в Политике, а также безопасность при их обработке в соответствии с требованиями Законодательства Российской Федерации.
</br></br>
При регистрации на Сайте и использовании Сайта Вы предоставляете нам персональные данные, не являющиеся специальными или биометрическими, бессрочно (вплоть до отзыва Вами либо физическим лицом субъектом персональных данных своего согласия на обработку персональных данных): имя, номер телефона, адрес электронной почты, а также иную информацию, относящуюся к Вам, физическому лицу субъекту персональных данных прямо или косвенно.
</br></br>
Настоящим Вы соглашаетесь с проведением нами онлайн-скоринга (оценки) таких Ваших персональных данных, как Ваше поведение на нашем Сайте, cookie, сведения о геопозиции, IP-адрес.
</br></br>
Настоящим Вы подтверждаете, что действуете свободно, своей волей и в своем интересе, а также подтверждаете свою дееспособность.
</br></br>
Настоящим Вы подтверждаете и несете ответственность за то, что физические лица субъекты персональных данных, полученных нами от Вас с Вашего логина, ознакомлены с настоящей Политикой и при передаче нам своих персональных данных действовали свободно, своей волей и в своем интересе, а также были дееспособны.
</br></br>
Предоставляя персональные данные, Вы соглашаетесь с тем, что предоставленные Вами персональные данные будут обрабатываться нами, а именно: ООО «СТАНДАРТМАШИНЕРИ», адрес (место нахождения): 680014, Хабаровский край, г. Хабаровск, ул. Промышленная 3, офис 105, ИНН 2724241607, ОГРН 1202700014626, как с использованием средств автоматизации, так и без использования таких средств.
</br></br>
В ходе обработки с Вашими персональными данными в целях исполнения заключенных договоров могут быть совершены следующие действия: сбор, запись, систематизация, накопление, хранение, уточнение (обновление, изменение), извлечение, использование, передача (распространение, предоставление, доступ), обезличивание, блокирование, удаление, уничтожение персональных данных.
</br></br>
Не считается нарушением обязательств передача информации в соответствии с обоснованными и применимыми требованиями законодательства Российской Федерации.
</br></br>
Мы используем предоставленные Вами персональные данные в целях: - исполнения заключенных с Вами договоров; - отправки Вам маркетинговых, рекламных и новостных рассылок, включая, но не ограничиваясь, новости о нас и наших партнерах; информацию о ценах на товары, наши предложения и предложения наших партнеров; - отправки Вам сообщений информационного характера и сервисных сообщений; - для осуществления деятельности по поставке и продвижению товаров и услуг; - оценки и анализа работы Сайта; - информирования Вас об акциях, скидках и специальных предложениях посредством электронных рассылок.
</br></br>
Настоящим Вы подтверждаете, что сообщили нам собственные (либо полученные и передаваемые нам законным путем в соответствии с ФЗ РФ «О персональных данных») и достоверные персональные данные.
</br></br>
Данное Вами согласие действительно с момента сообщения нам Вами персональных (регистрационных) данных.
</br></br>
Настоящим уведомляем Вас, что в том случае, если хотите внести уточнения в Ваши персональные данные, заблокировать или уничтожить их в случае, если персональные данные являются неполными, устаревшими, неточными, незаконно полученными или не являются необходимыми для заявленной цели обработки, либо в случае возникновения у Вас желания отозвать свое согласие на обработку персональных данных или устранить наши неправомерные действия в отношении Ваших персональных данных, то Вы должны направить нам официальный запрос одним из следующих способов:
</br> по Почте России по адресу: 680014, Хабаровский край, г. Хабаровск, ул. Промышленная 3, офис 105, в качестве получателя необходимо указывать: ООО «СТАНДАРТМАШИНЕРИ»;
</br> на адрес электронной почты (E-mail) Info@skillparts.ru
В случае направления нам официального запроса в тексте запроса необходимо указать Ваши:
</br> Фамилия, Имя, Отчество (если есть);
</br> Номер основного документа, удостоверяющего личность субъекта персональных данных или его представителя, сведения о дате выдачи указанного документа и выдавшем его органе;
</br> Сведения, подтверждающие Ваше участие в отношениях с нами либо сведения, иным способом подтверждающие факт обработки нами Ваших персональных данных;
</br> Подпись гражданина (или его законного представителя).
</br></br>
Если запрос отправляется в электронном виде, то он должен быть оформлен в виде электронного документа и подписан электронной подписью в соответствии с законодательством РФ.
</br>Мы обязуемся немедленно прекратить обработку Ваших персональных данных с момента получения от Вас письменного заявления (отзыва) и/или в случае достижения цели обработки и уничтожим их в срок и на условиях, установленных законом.
</br></br>
Вы можете отписаться от маркетинговых, рекламных и новостных рассылок путём направления нам соответствующего запроса на адрес электронной почты (E-mail) Info@skillparts.ru.
</br>Мы не несем ответственности за сведения, предоставленные Вами на Сайте в общедоступной форме.
</br>При обработке персональных данных мы принимаем необходимые и достаточные организационные и технические меры для защиты персональных данных от неправомерного доступа к ним, а также от иных неправомерных действий в отношении персональных данных.
</br></br>
Обращаем Ваше внимание, что данная Политика обработки персональных данных может обновляться в связи с возможными поправками в Законодательстве Российской Федерации, а также изменениями наших внутренних процессов и документов. Новая редакция Политики обработки персональных данных вступает в силу с момента ее размещения на Сайте.
</div>
</article>
</div>

View File

@ -178,6 +178,10 @@ main {
font-family: 'Gilroy';
}
.form_account .has-error > .checkbox {
color: #d90000
}
/* @media (max-width: 400px) {} */
/* Малые девайсы («ландшафтные телефоны», >= 576px) */
@ -194,4 +198,4 @@ main {
/* Экстрабольшие девайсы (большие десктопы, >= 1200px) */
/* @media (max-width: 1200px) {} */
/* @media (max-width: 1200px) {} */

View File

@ -0,0 +1,3 @@
#page_policy article {
background-color: #fff;
}

View File

@ -27,9 +27,14 @@ function authentication(form) {
'_csrf': yii.getCsrfToken()
};
} else {
form = $(form).serialize();
form = $(form).serializeArray();
}
form.push({
name: 'type',
value: 'authentication'
});
$.ajax({
url: '/authentication',
type: 'post',
@ -126,15 +131,146 @@ function deauthentication() {
});
};
function registration(form) {
function registration_start(form, type) {
// Инициализация постфикса
let postfix = '';
if (type === 'menu') {
postfix = '-menu';
}
// Удаление кнопок аутентификации
form.children[4].remove();
// Инициализация поля ввода пароля
let password = form.children[3];
// Изменение стиля
password.classList.add('mb-2');
// Инициализация кнопки регистрации
let registration = form.children[4];
// Изменение размера
registration.classList.remove('btn-sm');
registration.classList.add('btn');
// Изменение вызываемой функции
registration.setAttribute('onclick', 'return registration_end(this.parentElement);');
// Инициализация оболочки поля повтора пароля
let password_repeat_wrap = document.createElement('div');
password_repeat_wrap.setAttribute('class', 'mb-3 field-accountform-rept required');
// Инициализация поля повтора пароля
let password_repeat = document.createElement('input');
password_repeat.setAttribute('id', 'accountform-rept' + postfix);
password_repeat.classList.add('form-control');
password_repeat.setAttribute('type', 'password');
password_repeat.setAttribute('name', 'AccountForm[rept]');
password_repeat.setAttribute('placeholder', 'Повтор пароля');
password_repeat.setAttribute('aria-required', 'true');
password_repeat.setAttribute('aria-invalid', 'true');
// Инициализация элемента с текстом ошибок поля повтора пароля
let password_repeat_errors = document.createElement('p');
password_repeat_errors.setAttribute('class', 'help-block help-block-error small');
// Инициализация оболочки элемента с подтверждением политики персональных данных
let private_policy_wrap = document.createElement('div');
private_policy_wrap.setAttribute('class', 'mb-3 field-accountform-pols required');
// Инициализация оболочки для класса checkbox для элемента с подтверждением политики персональных данных
let private_policy_checkbox = document.createElement('div');
private_policy_checkbox.classList.add('checkbox');
private_policy_checkbox.classList.add('text-center');
// Инициализация оболочки для класса label для элемента с подтверждением политики персональных данных
let private_policy_label = document.createElement('label');
private_policy_label.setAttribute('for', 'accountform-pols');
// Инициализация скрытого элемента с подтверждением политики персональных данных
let private_policy_hidden = document.createElement('input');
private_policy_hidden.setAttribute('type', 'hidden');
private_policy_hidden.setAttribute('name', 'AccountForm[pols]');
private_policy_hidden.setAttribute('value', '0');
// Инициализация элемента с подтверждением политики персональных данных
let private_policy = document.createElement('input');
private_policy.setAttribute('id', 'accountform-pols' + postfix);
private_policy.setAttribute('type', 'checkbox');
private_policy.setAttribute('name', 'AccountForm[pols]');
private_policy.setAttribute('placeholder', 'Политика конфиденциальности');
// Инициализация оболочки элемента с текстом элемента с подтверждением политики персональных данных
let private_policy_text_wrap = document.createElement('small');
private_policy_text_wrap.setAttribute('class', 'ml-2');
// Инициализация элемента с текстом элемента с подтверждением политики персональных данных
let private_policy_text = document.createElement('a');
private_policy_text.setAttribute('href', '/policy');
private_policy_text.innerText = 'Политика';
// Запись в документ
form.insertBefore(password_repeat_wrap, registration);
password_repeat_wrap.appendChild(password_repeat);
password_repeat_wrap.appendChild(password_repeat_errors);
form.insertBefore(private_policy_wrap, registration);
private_policy_wrap.appendChild(private_policy_checkbox);
private_policy_checkbox.appendChild(private_policy_label);
private_policy_label.appendChild(private_policy);
private_policy_label.appendChild(private_policy_text_wrap);
private_policy_text_wrap.appendChild(private_policy_text);
private_policy_text_wrap.appendChild(document.createTextNode(' конфидециальности'));
// Инициализация заголовка
let title = form.children[1];
// Обновление заголовка
title.innerText = 'Регистрация';
// Подключение к ActiveForm
$(form).yiiActiveForm('add', {
id: 'accountform-rept',
name: 'rept',
container: '.field-accountform-rept',
input: '#accountform-rept',
error: '.help-block.help-block-error.small',
enableAjaxValidation: true
});
// Подключение к ActiveForm
$(form).yiiActiveForm('add', {
id: 'accountform-pols',
name: 'pols',
container: '.field-accountform-pols',
input: '#accountform-pols',
enableAjaxValidation: true
});
// Обновление валидатора
$(form).yiiActiveForm('data').settings.validationUrl = '/registration';
return false;
};
function registration_end(form) {
// Инициализация
$(form).yiiActiveForm('validate', true);
if (form == undefined) {
form = {
'_csrf': yii.getCsrfToken()
};
} else {
form = $(form).serialize();
form = $(form).serializeArray();
}
form.push({
name: 'type',
value: 'registration'
});
$.ajax({
url: '/registration',
type: 'post',
@ -184,6 +320,8 @@ function registration(form) {
}
}
});
return false;
};
document.addEventListener('DOMContentLoaded', identification(), true);
document.addEventListener('DOMContentLoaded', identification(), true);

View File

@ -8,7 +8,7 @@ function page_profile_panel_notification_create(form, html = 0) {
// Запись параметра типа уведомления (тест и html-код)
form.push({
name: "Notification[html]",
name: 'Notification[html]',
value: html
});
}
@ -48,4 +48,4 @@ function page_profile_panel_write (form) {
});
return false;
}
}