Создание корзины

This commit is contained in:
Arsen Mirzaev Tatyano-Muradovich 2021-03-07 20:29:19 +10:00
parent b8c1f7cef0
commit 53d7e2a048
34 changed files with 1248 additions and 396 deletions

View File

@ -0,0 +1,111 @@
<?php
declare(strict_types=1);
namespace app\controllers;
use app\models\AccountEdgeNotification;
use yii;
use yii\filters\AccessControl;
use yii\web\Controller;
use yii\web\Response;
use app\models\Order;
use app\models\AccountEdgeOrder;
use Exception;
class CartController extends Controller
{
public function behaviors()
{
return [
'access' => [
'class' => AccessControl::class,
'only' => ['index'],
'rules' => [
[
'allow' => true,
'roles' => ['@']
]
]
]
];
}
/**
* Страница: "Корзина"
*
* @see $this->behaviors Доступ только аутентифицированным
*/
public function actionIndex(): string|array|null
{
// Инициализация настроек страницы
$page = yii::$app->request->get('page') ?? 1;
// Инициализация корзина
$model = Order::search();
// Инициализация содержимого корзины
$supplies = $model->content(10, $page);
// Инициализация реестра дубликатов
$registry = [];
// Подсчёт и перестройка массива
foreach ($supplies as $key => &$supply) {
// Перебор поставок
if (in_array($supply->catn, $registry)) {
// Если данная поставка найдена в реестре
// Удаление
unset($supplies[$key]);
// Пропуск итерации
continue;
}
$amount = 0;
// Повторный перебор для поиска дубликатов
foreach ($supplies as &$supply4check) {
if ($supply == $supply4check) {
// Найден дубликат
// Постинкрементация счётчика
$amount++;
// Запись в реестр
$registry []= $supply4check->catn;
}
}
// Запись количества
$supply->amnt = $amount;
}
// Инициализация возврата по умолчанию
$return = [
'_csrf' => yii::$app->request->getCsrfToken()
];
if (yii::$app->request->isPost) {
// POST-запрос
yii::$app->response->format = Response::FORMAT_JSON;
$return = array_merge($return, [
'main' => $this->renderPartial('index', compact('model', 'supplies')),
'title' => 'Корзина',
'redirect' => '/cart'
]);
} else {
// GET-запрос (подразумевается)
return $this->render('index', compact('model', 'supplies'));
}
return $return;
}
}

View File

@ -30,6 +30,9 @@ class NotificationController extends Controller
];
}
/**
* @todo Перенести логику в модель
*/
public function actionIndex()
{
if (yii::$app->request->isPost) {
@ -84,12 +87,17 @@ class NotificationController extends Controller
/**
* Поиск рёбер: (УВЕДОМЛЕНИЕ)? -> ПОЛЬЗОВАТЕЛЬ
*
* @param bool $check Активация проверки получения
* @param bool $check Активация проверки на то, что уведомление не получено
*/
$search = function (bool $check = false) use ($model, $type, $let, $limit): array {
return $model::searchByAccount(
return $model::searchByEdge(
from: 'account',
to: 'notification',
params: $check ? $let->getBindVars() : [],
where: [
subquery_where: [
[
'account._id' => yii::$app->user->id
],
[
[
'notification.html' => null
@ -101,10 +109,10 @@ class NotificationController extends Controller
]
],
let: [
$model::collectionName() . '_edge_account',
'notification_edge_account',
'(' . (string) $let . ')'
],
post_where: $check ? [
where: $check ? [
'account_edge_notification[0]._to' => null
] : [],
limit: $limit,
@ -126,7 +134,7 @@ class NotificationController extends Controller
if (empty($notifications)) {
// Уведомления не найдены
yii::$app->response->statusCode = 404;
yii::$app->response->statusCode = 100;
goto end;
}

View File

@ -0,0 +1,94 @@
<?php
declare(strict_types=1);
namespace app\controllers;
use app\models\AccountEdgeNotification;
use yii;
use yii\filters\AccessControl;
use yii\web\Controller;
use yii\web\Response;
use app\models\Order;
use app\models\AccountEdgeOrder;
use Exception;
class OrderController extends Controller
{
public function behaviors()
{
return [
'access' => [
'class' => AccessControl::class,
'only' => ['index'],
'rules' => [
[
'allow' => true,
'roles' => ['@']
]
]
]
];
}
public function actionIndex()
{
}
public function actionWrite(): string|array|null {
if (yii::$app->request->isPost) {
// POST-запрос
// Инициализация входных данных
$account = yii::$app->user;
$supplies = yii::$app->request->post('supplies');
yii::$app->response->format = Response::FORMAT_JSON;
// Инициализация возврата по умолчанию
$return = [
'_csrf' => yii::$app->request->getCsrfToken()
];
if (is_null($supplies)) {
// 501 Not Implemented
yii::$app->response->statusCode = 501;
}
if (!is_null($supplies)) {
// Переданы поставки для записи
if (!$model = Order::search($account)) {
// Корзина не найдена (текущий заказ)
// Инициализация
$model = new Order();
$model->save() or throw new Exception('Не удалось инициализировать заказ');
// Запись в аккаунт
AccountEdgeOrder::write($account->id, $model->readId(), 'current') or $model->addError('errors', 'Не удалось инициализировать ребро: АККАУНТ -> ЗАКАЗ');
}
// Проверка входных данных
if (!is_array($supplies)) {
// Неверные входные данные
// Запись ошибки
$model->addError('errors', 'Переменная должна быть массивом');
}
// Если запись не удалась, то вернуть код: 500 Internal Server Error
$model->write($supplies) or yii::$app->response->statusCode = 500;
}
return $return;
}
yii::$app->response->statusCode = 500;
return null;
}
}

View File

@ -14,28 +14,28 @@ use app\models\Product;
class ProductController extends Controller
{
/**
* {@inheritdoc}
*/
public function behaviors()
{
return [
'access' => [
'class' => AccessControl::class,
'rules' => [
[
'allow' => true,
'actions' => ['index'],
'roles' => ['@']
],
[
'allow' => false,
'roles' => ['?']
],
]
]
];
}
// /**
// * {@inheritdoc}
// */
// public function behaviors()
// {
// return [
// 'access' => [
// 'class' => AccessControl::class,
// 'rules' => [
// [
// 'allow' => true,
// 'actions' => ['index'],
// 'roles' => ['@']
// ],
// [
// 'allow' => false,
// 'roles' => ['?']
// ],
// ]
// ]
// ];
// }
public function actionIndex(string $catn)
{

View File

@ -85,7 +85,7 @@ class ProfileController extends Controller
{
// Инициализация
$model = yii::$app->user->identity;
$attributes = Supply::searchByAccount(yii::$app->user->id);
$supplies = Supply::searchByAccount(select: 'supply.onec["ЗначенияСвойств"]');
if ($vars = yii::$app->request->post('Account') ?? yii::$app->request->get('Account')) {
// Обнаружены входные параметры
@ -116,13 +116,13 @@ class ProfileController extends Controller
yii::$app->response->format = Response::FORMAT_JSON;
return [
'main' => $this->renderPartial('index', compact('model', 'sidebar', 'attributes')),
'main' => $this->renderPartial('index', compact('model', 'sidebar', 'supplies')),
'redirect' => '/profile',
'_csrf' => yii::$app->request->getCsrfToken()
];
}
return $this->render('index', compact('model', 'sidebar', 'attributes'));
return $this->render('index', compact('model', 'sidebar', 'supplies'));
}
/**
@ -137,7 +137,7 @@ class ProfileController extends Controller
$sidebar = $this->renderPartial('sidebar');
if (yii::$app->request->isPost) {
// AJAX-POST-запрос
// POST-запрос
yii::$app->response->format = Response::FORMAT_JSON;

View File

@ -9,6 +9,7 @@ use yii\web\Controller;
use yii\web\Response;
use app\models\Product;
use app\models\Supply;
use app\models\Search;
class SearchController extends Controller
@ -18,6 +19,19 @@ class SearchController extends Controller
*/
public function actionIndex(): array|string
{
// Инициализация параметров
$auth_only = false;
if ($auth_only && yii::$app->user->isGuest) {
// Если активирован режим "Поиск только аутентифицированным" и запрос пришел не от аутентифицированного
// Запись кода ответа: 401 (необходима авторизация)
yii::$app->response->statusCode = 401;
// Переход к концу обработки
goto skip_search;
}
// Инициализация
$query = yii::$app->request->post('request') ?? yii::$app->request->get('q');
@ -30,7 +44,7 @@ class SearchController extends Controller
yii::$app->response->format = Response::FORMAT_JSON;
return [
'search_line_window' => $this->renderPartial('/search/panel', ['history' => true]),
'panel' => $this->renderPartial('/search/panel', ['history' => true]),
'_csrf' => yii::$app->request->getCsrfToken()
];
}
@ -46,7 +60,7 @@ class SearchController extends Controller
$timer = 0;
// Период пропуска запросов (в секундах)
$period = 3;
$period = 1;
$keep_connect = true;
$sanction = false;
$sanction_condition = ($session['last_request'] + $period - time()) < $period;
@ -68,39 +82,45 @@ class SearchController extends Controller
// Инициализация
$session['last_request'] = time();
// Пропуск проверок
goto first_request;
}
// Метка: "Повтор обработки поиска" (для создания непрерывного соединения)
keep_connect_wait:
// Запись времени последнего запроса и вычисление об истечении таймера
$timer = $session['last_request'] + $period - time();
if ($timer > 0) {
// Ожидание перед повторным запросом при условии что старых запросов нет
// Время блокировки не истекло
// Запись кода ответа: 202 (запрос не обработан)
yii::$app->response->statusCode = 202;
$return = [
'timer' => $timer,
'search_line_window' => $this->renderPartial('/loading'),
'panel' => $this->renderPartial('/search/loading'),
'_csrf' => yii::$app->request->getCsrfToken()
];
} else {
// Повторный запрос по истечению ожидания
// Запрос
// Очистка времени последнего запроса
unset($session['last_request']);
// Метка: "Первый запрос"
first_request:
if (strlen($query) < $query_min) {
// Выход за ограничения длины с недостатком
// Пропуск поиска
goto skip_query;
} else if (strlen($query) > $query_max) {
// Выход за ограничения длины с превышением
// Пропуск поиска
goto skip_query;
}
@ -109,12 +129,39 @@ class SearchController extends Controller
$limit = yii::$app->request->isPost ? 10 : 20;
if ($response = Product::searchByCatn($query, $limit, [])) {
if ($response = Product::searchByCatn($query, $limit, ['catn' => 'catn', '_key' => '_key'])) {
// Данные найдены по поиску в полях Каталожного номера
foreach ($response as &$row) {
// Перебор продуктов
// Поиск поставок привязанных к продуктам
$row['supplies'] = Supply::searchByEdge(
from: 'product',
to: 'supply',
edge: 'supply_edge_product',
limit: 11,
direction: 'OUTBOUND',
subquery_where: [
['product._key' => $row['_key']],
['supply.catn == product.catn'],
['supply_edge_product.type' => 'connect']
],
where: 'supply._id == supply_edge_product[0]._from',
select: 'supply_edge_product[0]'
);
if (count($row['supplies']) === 11) {
// Если в базе данных хранится много поставок
// Инициализация
$row['overload'] = true;
}
}
// Запись ответа
$return = [
'search_line_window' => $this->renderPartial('/search/panel', compact('response')),
'panel' => $this->renderPartial('/search/panel', compact('response')),
'_csrf' => yii::$app->request->getCsrfToken()
];
@ -123,16 +170,18 @@ class SearchController extends Controller
// Запись ответа
$return['main'] = $this->renderPartial('/search/index', compact('response'));
$return['search_line_window_hide'] = 1;
$return['hide'] = 1;
$return['redirect'] = '/search?type=product&q=' . $query;
}
} else {
// Данные не найдены
// Запись кода ответа: 404 (запрашиваемые данные не найдены)
yii::$app->response->statusCode = 404;
}
}
// Метка: "Пропуск запроса" (для пропуска самого поиска и возврата ответа)
skip_query:
if (yii::$app->request->isPost) {
@ -141,7 +190,7 @@ class SearchController extends Controller
yii::$app->response->format = Response::FORMAT_JSON;
return $return ?? [
'search_line_window' => $this->renderPartial('/search/panel'),
'panel' => $this->renderPartial('/search/panel'),
'_csrf' => yii::$app->request->getCsrfToken()
];
} else {
@ -153,6 +202,7 @@ class SearchController extends Controller
// Ожидание
sleep($timer);
// Повтор обработки
goto keep_connect_wait;
}
@ -160,9 +210,22 @@ class SearchController extends Controller
}
}
if (yii::$app->user->isGuest) {
return $this->render('/search/index', ['error_auth' => true]);
// Метка: "Пропуск обработки"
skip_search:
if (yii::$app->request->isPost) {
// POST-запрос
yii::$app->response->format = Response::FORMAT_JSON;
return [
'panel' => $this->renderPartial('/search/panel'),
'hide' => (int) $auth_only,
'_csrf' => yii::$app->request->getCsrfToken()
];
} else {
// GET-запрос
return $this->render('/search/index');
}
}

View File

@ -0,0 +1,16 @@
<?php
use mirzaev\yii2\arangodb\Migration;
class m210303_192326_create_order_collection extends Migration
{
public function up()
{
$this->createCollection('order', []);
}
public function down()
{
$this->dropCollection('order');
}
}

View File

@ -0,0 +1,16 @@
<?php
use mirzaev\yii2\arangodb\Migration;
class m210303_192451_create_order_edge_supply_collection extends Migration
{
public function up()
{
$this->createCollection('order_edge_supply', ['type' => 3]);
}
public function down()
{
$this->dropCollection('order_edge_supply');
}
}

View File

@ -0,0 +1,16 @@
<?php
use mirzaev\yii2\arangodb\Migration;
class m210307_000210_create_account_edge_order_collection extends Migration
{
public function up()
{
$this->createCollection('account_edge_order', ['type' => 3]);
}
public function down()
{
$this->dropCollection('account_edge_order');
}
}

View File

@ -0,0 +1,13 @@
<?php
declare(strict_types=1);
namespace app\models;
class AccountEdgeOrder extends Edge
{
public static function collectionName(): string
{
return 'account_edge_order';
}
}

View File

@ -113,7 +113,7 @@ abstract class Document extends ActiveRecord
/**
* Проверка на то, что в свойство передан массив
*/
protected function arrayValidator(string $attribute, array $params): bool
public function arrayValidator(string $attribute, array $params = null): bool
{
if (is_array($this->$attribute)) {
return true;

View File

@ -7,7 +7,9 @@ namespace app\models;
use yii;
use yii\web\IdentityInterface;
use app\models\traits\SearchByAccount;
use app\models\traits\SearchByEdge;
use Exception;
/**
* Поиск
@ -16,7 +18,7 @@ use app\models\traits\SearchByAccount;
*/
class Notification extends Document
{
use SearchByAccount;
use SearchByEdge;
/**
* Сценарий для доверенного пользователя с созданием уведомления
@ -116,9 +118,9 @@ class Notification extends Document
public function write(string $html = null, IdentityInterface|array|string $trgt = null, string $type = 'notice'): self|array|null
{
// Инициализация
isset($this->html) ? $html = $this->html : null;
isset($this->trgt) ? $trgt = $this->trgt : null;
isset($this->type) ? $type = $this->type : null;
$html ?? $html = $this->html ?? throw new Exception('Не удалось инициализировать содержимое');
$trgt ?? $trgt = yii::$app->user ?? throw new Exception('Не удалось инициализировать получателя');
$type ?? $trgt = $this->type ?? throw new Exception('Не удалось инициализировать тип');
// Инициализация уведомления
if (isset($html) && (bool) (int) $html) {
@ -193,15 +195,6 @@ class Notification extends Document
return AccountEdgeNotification::writeSafe($this->readId(), $target->readId(), $type) ? $this : null;
}
// "or" имеет приоритет ниже чем у "||" относительно "="
//
// if ($target = $buffer = Account::searchById($target) or
// $target = Account::searchById(Account::collectionName() . '/' . $buffer)
// ) {
//
// if (($target = Account::searchById($target)) ||
// ($target = Account::searchById(Account::collectionName() . '/' . $target))
// ) {
if ($target = Account::searchById(Account::collectionName() . '/' . $target)) {
// Аккаунт найден

View File

@ -0,0 +1,186 @@
<?php
declare(strict_types=1);
namespace app\models;
use yii;
use yii\web\User as Account;
use app\models\traits\SearchByEdge;
use Exception;
/**
* Заказ
*
* @see Account Заказчик
* @see Supply Поставки для заказа
*/
class Order extends Document
{
use SearchByEdge;
/**
* Поставки для записи
*/
public array $supplies;
/**
* Имя коллекции
*/
public static function collectionName(): string
{
return 'order';
}
/**
* Свойства
*/
public function attributes(): array
{
return array_merge(
parent::attributes(),
[]
);
}
/**
* Метки свойств
*/
public function attributeLabels(): array
{
return array_merge(
parent::attributeLabels(),
[]
);
}
/**
* Правила
*/
public function rules(): array
{
return array_merge(
parent::rules(),
[]
);
}
/**
* Запись
*
* $supply = [ Supply $supply, int $amount = 1 ]
*
* @param Supply|array $supply Поставка
* @param Account $trgt Заказчик
*
* @todo Создать параметр разделителя для администрации
*/
public function write(Supply|array $supply, Account $trgt = null): self|null
{
// Инициализация
$trgt ?? $trgt = yii::$app->user ?? throw new Exception('Не удалось инициализировать заказчика');
if ($supply instanceof Supply) {
// Передана инстанция класса поставки
// Унификация входных данных
$supply = [$supply, 1];
}
if (is_null($this->_key)) {
// Корзина не инициализирована
// Инициализация
if (!$this->save()) {
// Инициализация заказа не удалась
throw new Exception('Ошибка при записи заказа в базу данных');
}
// Инициализация ребра: АККАУНТ -> ЗАКАЗ
if (!AccountEdgeOrder::write($trgt->readId(), $this->readId(), 'create')) {
// Инициализация не удалась
throw new Exception('Ошибка при записи ребра от аккаунта до заказа в базу данных');
}
}
foreach ($supply as $supply_raw) {
// Перебор поставок
for ($i = 0; $i < $supply_raw[1]; $i++) {
// Создание рёбер соразмерно запросу (добавление нескольких продуктов в корзину)
// Инициализация ребра: ЗАКАЗ -> ПОСТАВКА
if (!$supply = Supply::searchByCatn($supply_raw[0]) or !OrderEdgeSupply::write($this->readId(), $supply->readId(), 'add')) {
// Поставка не найдена или инициализация ребра не удалась
continue;
}
}
}
// Отправка на сервер базы данных
return $this->save() ? $this : null;
}
/**
* Поиск заказа
*/
public static function search(Account $account = null, string $type = 'current', int $limit = 1): self|array
{
$account or $account = yii::$app->user ?? throw new Exception('Не удалось инициализировать пользователя');
$return = self::searchByEdge(
from: 'account',
to: 'order',
subquery_where: [
[
'account._id' => $account->id
],
[
'account_edge_order.type' => $type
]
],
limit: $limit,
sort: ['DESC'],
direction: 'INBOUND'
);
return $limit === 1 ? $return[0] : $return;
}
/**
* Поиск содержимого заказа
*
* @todo В будущем возможно заказ не только поставок реализовать
*/
public function content(int $limit = 1, int $page = 1): Supply|array
{
// Генерация сдвига по запрашиваемым данным (пагинация)
$offset = $limit * ($page - 1);
// Поиск рёбер: ЗАКАЗ -> ПОСТАВКА
$return = Supply::searchByEdge(
from: 'order',
to: 'supply',
edge: 'order_edge_supply',
subquery_where: [
[
'order._id' => $this->readId()
],
[
'order_edge_supply.type' => 'add'
]
],
foreach: ['edge' => 'order_edge_supply'],
where: 'edge._to == supply._id',
limit: $limit,
offset: $offset
);
return $limit === 1 ? $return[0] : $return;
}
}

View File

@ -0,0 +1,13 @@
<?php
declare(strict_types=1);
namespace app\models;
class OrderEdgeSupply extends Edge
{
public static function collectionName(): string
{
return 'order_edge_supply';
}
}

View File

@ -5,6 +5,7 @@ declare(strict_types=1);
namespace app\models;
use moonland\phpexcel\Excel;
use app\models\traits\SearchByEdge;
/**
* Продукт (в ассортименте магазина)
@ -15,6 +16,8 @@ use moonland\phpexcel\Excel;
*/
class Product extends Document
{
use SearchByEdge;
/**
* Сценарий импорта из .excel документа
*/
@ -52,13 +55,13 @@ class Product extends Document
parent::attributes(),
[
'name',
'desc',
'ocid',
'catn',
'imgs',
'oemn'
// 'data',
// 'cost',
// 'time'
'time',
'oemn',
'cost'
]
);
}
@ -71,14 +74,14 @@ class Product extends Document
return array_merge(
parent::attributeLabels(),
[
'name' => 'Название (name)',
'ocid' => 'Идентификатор 1C (ocid)',
'catn' => 'Каталожный номер (catn)',
'imgs' => 'Изображения (imgs)',
'oemn' => 'OEM номера (oemn)',
// 'data' => 'Данные товара (data)',
// 'cost' => 'Цены (cost)',
// 'time' => 'Сроки доставки (time)',
'name' => 'Название',
'desc' => 'Описание',
'ocid' => 'Идентификатор 1C',
'catn' => 'Каталожный номер',
'imgs' => 'Изображения',
'time' => 'Срок доставки',
'oemn' => 'OEM номера',
'cost' => 'Стоимость',
'file' => 'Документ',
'group' => 'Группа'
]
@ -284,7 +287,7 @@ class Product extends Document
*
* @todo Переделать нормально
*/
public static function searchByCatn(string $catn, int $limit = 1, array $select = ['catn' => 'catn']): static|array|null
public static function searchByCatn(string $catn, int $limit = 1, array $select = []): static|array|null
{
if ($limit <= 1) {
return static::findOne(['catn' => $catn]);

View File

@ -7,7 +7,7 @@ namespace app\models;
use yii;
use yii\web\IdentityInterface;
use app\models\traits\SearchByAccount;
use app\models\traits\SearchByEdge;
/**
* Поиск
@ -16,7 +16,7 @@ use app\models\traits\SearchByAccount;
*/
class Search extends Document
{
use SearchByAccount;
use SearchByEdge;
/**
* Имя коллекции

View File

@ -24,11 +24,15 @@ use exception;
*/
class Supply extends Product implements ProductInterface
{
/**
* Метод для конвертации XML в Array
*/
use Xml2Array;
/**
* Количество
*
* Используется при выводе в корзине
*/
public int $amnt = 0;
/**
* Имя коллекции
*/
@ -68,14 +72,14 @@ class Supply extends Product implements ProductInterface
*/
public function afterSave($data, $vars): void
{
if (AccountEdgeSupply::searchByVertex(Yii::$app->user->id, $this->readId())) {
if (AccountEdgeSupply::searchByVertex(yii::$app->user->id, $this->readId())) {
// Ребро уже существует
} else {
// Ребра не существует
// Запись ребра: АККАУНТ -> ПОСТАВКА
(new AccountEdgeSupply)->write(Yii::$app->user->id, $this->readId(), 'import');
(new AccountEdgeSupply)->write(yii::$app->user->id, $this->readId(), 'import');
}
}
@ -100,6 +104,39 @@ class Supply extends Product implements ProductInterface
return true;
}
/**
* Поиск через связь с аккаунтом
*
* @param string $id Идентификатор пользователя
* @param bool $select Запрашиваемые значения
*/
public static function searchByAccount(string $id = null, string|array $select = []): array
{
isset($id) ?: $id = yii::$app->user->id ?? throw new Exception('Не найден идентификатор');
return self::searchByEdge(
from: 'account',
to: 'supply',
subquery_where: [
[
'account._id' => $id
]
],
where: 'supply._id == account_edge_supply[0]._to AND supply.onec["ЗначенияСвойств"] != null',
select: $select,
// handle: function ($request) {
// $response = $request->createCommand()->execute()->getAll();
// foreach ($response as &$attribute) {
// // Приведение всех свойств в массив и очистка от лишних данных
// $attribute = $attribute->getAll();
// }
// return $response;
// }
);
}
/**
* Запись данных свойств по UUID 1C
@ -112,7 +149,7 @@ class Supply extends Product implements ProductInterface
public static function createProperties1c($properties): void
{
// Инициализация
$models = self::searchByAccount(Yii::$app->user->id, true);
$models = self::searchByAccount(select: 'supply.onec["ЗначенияСвойств"]');
$properties = self::xml2array($properties->xml);
// for ($i = 0; $i <= count($models); $i++)
@ -269,6 +306,14 @@ class Supply extends Product implements ProductInterface
foreach ($product as $product) {
// Перебор всех инициализированных продуктов
if ($this->catn !== $product->catn) {
// Каталожные номера не соответствуют друг другу
continue;
}
// Код ниже скорее всего устарел
if (SupplyEdgeProduct::searchByVertex($this->readId(), $product->readId())) {
// Ребро уже существует
@ -279,7 +324,7 @@ class Supply extends Product implements ProductInterface
$return = (new SupplyEdgeProduct)->write(
$this->readId(),
$product->readId(),
'sell',
'connect',
[
'onec' => self::xml2array($offer->xml)
]
@ -304,6 +349,7 @@ class Supply extends Product implements ProductInterface
// Настройка
$model->ocid = $id ?? null;
$model->catn = (string) $product->Артикул;
$model->desc = (string) $product->Описание;
$model->onec = self::xml2array($product->xml);
if (isset($model->onec['ЗначенияСвойств'])) {
@ -378,43 +424,12 @@ class Supply extends Product implements ProductInterface
}
/**
* Поиск через связь с аккаунтом
* Поиск по OEM-номерам
*
* @param string $id Идентификатор пользователя
* @param bool $full Возврат всех значений (иначе только свойства)
* @todo Реализовать с помощью LIKE
*/
public static function searchByAccount(string $id = null, bool $full = false): array
public static function searchByOemn(): array
{
if (!isset($id)) {
$id = yii::$app->user->id ?? throw new exception('Не найден идентификатор');
}
$subquery = static::find()
->for(['account', 'account_edge_supply'])
->traversal('supply')->in('account_edge_supply')
->where(['account._id' => $id])
->select('account_edge_supply')
->createCommand();
$query = static::find()
->params($subquery->getBindVars())
->let('account_edge_supply', '(' . (string) $subquery . ')')
->where('supply._id == account_edge_supply[0]._to')
->andWhere('supply.onec["ЗначенияСвойств"] != null');
if ($full) {
// Если указан полный поиск
return $query->select('supply')->all();
}
$query = $query->select('supply.onec["ЗначенияСвойств"]')->createCommand()->execute()->getAll();
foreach ($query as &$attribute) {
// Приведение всех свойств в массив и очистка от лишних данных
$attribute = $attribute->getAll();
}
return $query;
return [];
}
}

View File

@ -1,74 +0,0 @@
<?php
declare(strict_types=1);
namespace app\models\traits;
use yii;
use exception;
trait SearchByAccount
{
/**
* Поиск через связи рёбрами с аккаунтом
*
* @param string $id Идентификатор пользователя
* @param int $limit Количество
* @param int $offset Сдвиг
* @param string $sort Сортировка
*/
public static function searchByAccount(
string $id = null,
int $limit = 10,
int $offset = 0,
array $sort = ['ASC'],
string|array $where = [],
string|array $post_where = [],
string $direction = 'ANY',
array $let = [],
array $params = []
): ?array {
if (!isset($id)) {
$id = yii::$app->user->id ?? throw new exception('Не найден идентификатор');
}
$subquery = static::find()
->for(['account', 'account_edge_' . self::collectionName()])
->traversal(self::collectionName(), $direction)
->in('account_edge_' . self::collectionName())
->where(['account._id' => $id]);
if (!empty($where)) {
// Переданы дополнительные условия фильтрации
$subquery->where($where);
}
$subquery = $subquery->select('account_edge_' . self::collectionName())
->createCommand();
$query = static::find()
->params($params, $subquery->getBindVars())
->let('account_edge_' . self::collectionName(), '(' . (string) $subquery . ')')
->limit($limit)
->offset($offset)
->orderBy($sort);
if (!empty($let)) {
// Переданы дополнительные условия фильтрации
$query->let(...$let);
}
if (isset($post_where) && $post_where) {
// Если переданы дополнительные условия фильтрации
$query->where($post_where);
} else {
$query->where(self::collectionName() . '._id == account_edge_' . self::collectionName() . '[0]._to');
}
return $query->select(self::collectionName())->all();
}
}

View File

@ -0,0 +1,83 @@
<?php
declare(strict_types=1);
namespace app\models\traits;
use yii;
use exception;
trait SearchByEdge
{
/**
* Поиск через связи рёбрами с аккаунтом
*
* @param string $id Идентификатор пользователя
* @param int $limit Количество
* @param int $offset Сдвиг
* @param string $sort Сортировка
*/
public static function searchByEdge(
string $from,
string $to,
string $edge = null,
int $limit = 10,
int $offset = 0,
array $sort = ['ASC'],
string|array $subquery_where = [],
array $foreach = [],
string|array $where = [],
string $direction = 'ANY',
array $let = [],
string|array $select = null,
callable $handle = null,
array &$params = []
): ?array {
$subquery = static::find()
->for([$from, $edge ?? $from . '_edge_' . $to])
->traversal($to, $direction)
->in($edge ?? $from . '_edge_' . $to)
->where($subquery_where);
$subquery = $subquery->select($edge ?? $from . '_edge_' . $to)
->createCommand();
$query = static::find()
->params($params, $subquery->getBindVars())
->let($edge ?? $from . '_edge_' . $to, '(' . (string) $subquery . ')')
->limit($limit)
->offset($offset)
->orderBy($sort);
if (!empty($let)) {
// Переданы дополнительные условия фильтрации
$query->let(...$let);
}
// Запрос
$request = $query
->foreach($foreach)
->where($where)
->select($select ?? $to);
if (isset($handle)) {
// Передана функция для постобработки
return $handle($request);
} else if (isset($select)) {
$response = $request->createCommand()->execute()->getAll();
foreach ($response as &$attribute) {
// Приведение всех свойств в массив и очистка от лишних данных
$attribute = $attribute->getAll();
}
return $response;
} else {
return $request->all();
}
}
}

View File

@ -5,12 +5,12 @@ declare(strict_types=1);
use yii;
?>
<a class="text-dark my-auto mr-2" href="/cart"><i class="fas fa-shopping-cart mx-2"></i></a>
<a class="text-dark my-auto mr-2" href="/orders"><i class="fas fa-list mx-2"></i></a>
<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 class="dropdown-menu dropdown-menu-long dropdown-menu-right p-3" aria-labelledby="profile_button" onmouseout="$('#profile_button').dropdown('show')">
<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')) ?>
<!-- <a class="dropdown-item-text text-center px-0 py-2" href="#"><small>Восстановление пароля</small></a> -->

View File

@ -17,8 +17,8 @@ if (!yii::$app->user->isGuest) {
HTML;
}
?>
<a class="text-dark my-auto mr-2" href="/cart"><i class="fas fa-shopping-cart mx-2"></i></a>
<a class="text-dark my-auto mr-2" href="/orders"><i class="fas fa-list mx-2"></i></a>
<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>

View File

@ -0,0 +1,56 @@
<link href="/css/pages/cart.css" rel="stylesheet">
<div id="page_cart" class="container h-100">
<article class="my-3 p-3 h-100">
<h4 class="ml-4 mt-3 mb-4"><i class="fas fa-shopping-cart mr-2"></i>Корзина</h4>
<div class="col list">
<div class="row py-2">
<div class="col-1">
<input id="checkbox_cart_all" type="checkbox"/>
</div>
<div class="col">
<span>Артикул</span>
</div>
<div class="col">
<span>Описание</span>
</div>
<div class="col">
<span>Количество</span>
</div>
<div class="col">
<span>Доставка</span>
</div>
<div class="col">
<span>Стоимость </span>
</div>
</div>
<?php
foreach ($supplies as $supply) {
echo <<<HTML
<div class="row py-2">
<div class="col-1">
<input id="checkbox_cart_$supply->catn" type="checkbox"/>
</div>
<div class="col">
$supply->catn
</div>
<div class="col">
$supply->desc
</div>
<div class="col">
$supply->amnt
</div>
<div class="col">
$supply->time
</div>
<div class="col">
$supply->cost
</div>
</div>
HTML;
}
?>
</div>
</article>
</div>

View File

@ -69,22 +69,25 @@ AppAsset::register($this);
<label class="mb-0 px-3 px-md-4 py-1" for="catalog_search_panel_button_3">Третья кнопка</label> -->
<form class="d-flex catalog_search" onsubmit="return false;">
<div class="position-relative col-sm-8 col-lg-10 px-0">
<input id="search_line" type="text" class="form-control col-12 catalog_search_line button_clean" placeholder="Введите номер запчасти, например: 45223503481" oninput="$('#search_line').dropdown('hide'); product_search(this);" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false" autocomplete="off">
<input id="search_line" type="text" class="form-control col-12 catalog_search_line button_clean" placeholder="Введите номер запчасти, например: 45223503481" oninput="$('#search_line').dropdown('hide'); product_search(this.value);" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false" autocomplete="off">
<?php
if (!yii::$app->user->isGuest && $search_panel = $search_panel ?? yii::$app->controller->renderPartial('/search/panel', ['history' => true])) {
// Сделать системные настройки и по ним работать
$search_panel = yii::$app->controller->renderPartial('/search/panel', ['history' => true]);
// if (!yii::$app->user->isGuest && $search_panel = $search_panel ?? yii::$app->controller->renderPartial('/search/panel', ['history' => true])) {
echo <<<HTML
<div id="search_line_window" class="dropdown-menu w-100" aria-labelledby="search_line">
$search_panel
</div>
HTML;
} else {
echo <<<HTML
<div id="search_line_window" class="dropdown-menu w-100 d-none" aria-labelledby="search_line"></div>
HTML;
}
// } else {
// echo <<<HTML
// <div id="search_line_window" class="dropdown-menu w-100" style="display: none" aria-labelledby="search_line"></div>
// HTML;
// }
?>
</div>
<button type="submit" class="col btn button_clean catalog_search_button" onclick="product_search(this.parentElement.getElementsByTagName('input')[0], 1)">ПОИСК</button>
<button type="submit" class="col btn button_clean catalog_search_button" onclick="product_search(this.parentElement.getElementsByTagName('input')[0].value, 1)">ПОИСК</button>
</form>
</div>
</div>

View File

@ -9,7 +9,7 @@ use app\models\Product;
<link href="/css/pages/product.css" rel="stylesheet">
<div id="page_product" class="h-100">
<div class="container h-100">
<!-- <div class="container h-100"> -->
<div class="row h-100 py-3">
<article class="col-12">
<div class="h-100 p-3 d-flex flex-column rounded">
@ -126,5 +126,5 @@ use app\models\Product;
</div>
</article>
</div>
</div>
<!-- </div> -->
</div>

View File

@ -57,13 +57,14 @@ use app\models\Supply;
// Инициализация
isset($model) or $model = yii::$app->user->identity;
isset($attributes) or $attributes = Supply::searchByAccount(yii::$app->user->id);
isset($supplies) or $supplies = Supply::searchByAccount(select: 'supply.onec["ЗначенияСвойств"]');
$list = [];
// Перебор свойств поставок
foreach ($attributes as $attribute) {
foreach ($supplies as $supply) {
// Инициализация
$id = $attribute['ЗначенияСвойства']['Ид'];
$id = $supply['ЗначенияСвойства']['Ид'];
if (in_array($id, $list, true)) {
// Если встретился дубликат (вызывается очень часто)
@ -71,7 +72,7 @@ use app\models\Supply;
}
// Генерация
$list[$id] = $attribute['ЗначенияСвойства']['Наименование'];
$list[$id] = $supply['ЗначенияСвойства']['Наименование'];
}
// Инициализация текущего значения параметра в начале массива

View File

@ -2,13 +2,7 @@
<div id="page_search" class="container h-100">
<div class="row py-3">
<nav class="col-3">
<div class="p-3 rounded">
</div>
</nav>
<article class="col-9">
<div class="row mx-0 p-3 rounded">
<article class="col">
<?php
if (isset($timer) && $timer > 0) {
echo <<<HTML
@ -28,40 +22,100 @@
$amount = count($response);
foreach ($response as $row) {
$catn = $row['catn'];
$covr = $row['covr'] ?? '/img/covers/h150/product.png';
$amnt = $row['amnt'] ?? 1;
// $name = $row['name'];
// $catn = $row['catn'];
// Инициализация
extract($row);
isset($name) ?: $name = 'Без названия';
isset($catg) ?: $catg = 'Категория';
isset($covr) ?: $covr = '/img/covers/h150/product.png';
$supplies_html = '';
// <button class="button_clean_full d-flex p-0">
// <i class="fas fa-plus-square search_card_cart_icon my-auto"></i>
// </button>
foreach ($supplies as $supply) {
// Конкатенация HTML кода
echo <<<HTML
<div class="col-3 p-2 d-flex flex-column search_card rounded">
<div class="col">
<div class="row mb-2">
<img class="w-100 img-fluid rounded" src="$covr"/>
</div>
<div class="row mb-2">
<a class="mx-auto text-dark" href="/product/$catn"><h5 class="m-0">$catn</h5></a>
</div>
<div class="row px-2 mb-2">
<small class="mt-auto">{$amnt}шт</small>
<p class="mr-0">1000р</p>
</div>
<div class="row">
<button class="btn button_grey button_clean w-100 text-white">В корзину</button>
</div>
</div>
</div>
HTML;
// Инициализация артикула
$catn = $supply['catn'] ?? $supply['onec']['Артикул'];
if (++$i % 4 === 0 && $amount - $i !== 0) {
echo <<<HTML
<div class="dropdown-divider my-3 mx-4 w-100 "></div>
// Инициализация количества
$amount = $supply['amnt'] ?? $supply['onec']['Количество'];
if (empty($amount) || $amount < 1) {
$amount = 'Под заказ';
} else {
$amount .= ' шт';
}
// Инициализация цена
$price = $supply['prce'] ?? $supply['onec']['Цены']['Цена']['ЦенаЗаЕдиницу'] . ' ' . $supply['onec']['Цены']['Цена']['Валюта'];
$supplies_html .= <<<HTML
<div class="row my-auto m-0 h-100 text-right">
<small class="col-2 my-auto ml-auto">
$amount
</small>
<small class="col-2 my-auto ml-1">
Доставка
</small>
<b class="col-2 my-auto">
$price
</b>
<a class="col-1 h-100 text-dark d-flex" title="Добавить $catn в корзину" href="/cart" role="button" onclick="return cart_write('$catn');">
<i class="fas fa-cart-arrow-down my-auto"></i>
</a>
</div>
HTML;
}
echo <<<HTML
<div class="col pb-2">
<div class="row p-2 rounded">
<img class="ml-0 h-100 img-fluid rounded" src="$covr"/>
<div class="col-3 ml-3 p-0 d-flex flex-column">
<a class="my-auto text-dark" href="/product/$catn">
<h5 class="m-0">$name</h5>
<h6 class="m-0"><small>$catn</small></h6>
</a>
</div>
<div class="col-1 ml-2 p-0 d-flex flex-column">
<a class="my-auto text-dark" href="/product/$catn">
<small>$catg</small>
</a>
</div>
<div class="col ml-2 p-0 d-flex flex-column">
$supplies_html
</div>
</div>
</div>
HTML;
// echo <<<HTML
// <div class="col-3 p-2 d-flex flex-column search_card rounded">
// <div class="col">
// <div class="row mb-2">
// <img class="w-100 img-fluid rounded" src="$covr"/>
// </div>
// <div class="row mb-2">
// <a class="mx-auto text-dark" href="/product/$catn"><h5 class="m-0">$catn</h5></a>
// </div>
// <div class="row px-2 mb-2">
// <small class="mt-auto">{$amnt}шт</small>
// <p class="mr-0">1000р</p>
// </div>
// <div class="row">
// <button class="btn button_grey button_clean w-100 text-white">В корзину</button>
// </div>
// </div>
// </div>
// HTML;
// if (++$i % 4 === 0 && $amount - $i !== 0) {
// echo <<<HTML
// <div class="dropdown-divider my-3 mx-4 w-100 "></div>
// HTML;
// }
}
} else {
echo <<<HTML
@ -72,7 +126,8 @@
}
}
?>
</div>
</article>
</div>
</div>
<script src="/js/cart.js" defer></script>

View File

@ -7,7 +7,19 @@ use app\models\Search;
if (isset($history) && $history) {
// Отображение истории
if (!yii::$app->user->isGuest && $rows = Search::searchByAccount(sort: ['DESC'])) {
if (yii::$app->user->isGuest) {
// Не аутентифицирован
// В будущем выводить историю из cookie
echo <<<HTML
<p class="m-0 py-2 d-flex justify-content-center">Войдите для просмотра истории поиска</p>
HTML;
} else if ($rows = Search::searchByEdge(
from: 'account',
to: 'search',
sort: ['DESC']
)) {
// История поиска существует
foreach ($rows as $row) {

View File

@ -0,0 +1,11 @@
#page_cart article {
background-color: #fff;
}
#page_cart article .list .row:nth-child(2n+1) {
background-color: #f5f2fa;
}
#page_cart article .list .row:first-child {
background-color: #edeaf2;
}

View File

@ -1,7 +1,17 @@
#page_search nav > div, #page_search article > div {
#page_search nav>div,
#page_search article>div>div {
height : 65px;
background-color: #fff;
border-right : 0 solid #fff;
transition : 100ms ease-in;
}
/* #page_search nav > div, #page_search article > div:hover > div {
height: 68px;
border-right: 6px solid #e1e1ea;
border-radius: .25rem 0 0 .25rem !important;
} */
#page_search .search_card:hover {
background-color: #eaeaf0;
}

View File

@ -57,6 +57,13 @@ function authentication(form) {
// Обновление документа
$('meta[name=csrf-token]').prop("content", data._csrf);
}
// Реинициализация панели поиска
// Перенести в отдельный файл который подгружается в зависимости от настроек
// search_panel_show();
// Обновление панели поиска
product_search();
},
error: function (data, status) {
if (data.responseJSON.main !== undefined) {
@ -108,6 +115,13 @@ function deauthentication() {
// Обновление документа
$('meta[name=csrf-token]').prop("content", data._csrf);
}
// Реинициализация панели поиска
// Перенести в отдельный файл который подгружается в зависимости от настроек
// search_panel_hide();
// Обновление панели поиска
product_search();
}
});
};

View File

@ -0,0 +1,61 @@
function cart_write(catn, amount = 1) {
$.ajax({
url: '/order/write',
type: 'post',
dataType: 'json',
data: {
'_csrf': yii.getCsrfToken(),
'supplies': [
catn,
amount
]
},
success: cart_success,
error: cart_error
});
return false;
}
function cart_success(data, status) {
// Обработка ответов от удавшихся запросов
// Основной блок
if (data.main !== undefined) {
main = document.getElementsByTagName('main')[0];
// Обновление документа
main.innerHTML = data.main;
// Реинициализация
reinitialization(main);
}
// CSRF-токен
if (data._csrf !== undefined) {
// Обновление документа
$('meta[name=csrf-token]').prop("content", data._csrf);
}
}
function cart_error(data, status) {
// Обработка ответов от неудавшихся запросов
// Основной блок
if (data.responseJSON.main !== undefined) {
main = document.getElementsByTagName('main')[0];
// Обновление окна результатов поиска
main.innerHTML = data.main;
// Реинициализация
reinitialization(main);
}
// CSRF-токен
if (data.responseJSON._csrf !== undefined) {
// Обновление документа
$('meta[name=csrf-token]').prop("content", data.responseJSON._csrf);
}
}

View File

@ -7,51 +7,16 @@ function page_main() {
type: 'post',
dataType: 'json',
data: { '_csrf': yii.getCsrfToken() },
success: function (data, status) {
if (data.main !== undefined) {
main = document.getElementsByTagName('main')[0];
// Обновление документа
main.innerHTML = data.main;
// Реинициализация
reinitialization(main);
}
if (data.redirect !== undefined) {
// Перенаправление
history.pushState({}, document.title, data.redirect);
}
if (data._csrf !== undefined) {
// Обновление документа
$('meta[name=csrf-token]').prop("content", data._csrf);
}
},
error: function (data, status) {
if (data.responseJSON.main !== undefined) {
main = document.getElementsByTagName('main')[0];
// Обновление документа
main.innerHTML = data.responseJSON.main;
// Реинициализация
reinitialization(main);
}
if (data.responseJSON.redirect !== undefined) {
// Перенаправление
history.pushState({}, document.title, data.responseJSON.redirect);
}
if (data.responseJSON._csrf !== undefined) {
// Обновление документа
$('meta[name=csrf-token]').prop("content", data.responseJSON._csrf);
}
}
success: menu_success,
error: menu_error
});
}
return false;
};
}
function page_profile() {
if (document.getElementById('page_profile') === null) {
url = '/profile'
$.ajax({
@ -59,45 +24,27 @@ function page_profile() {
type: 'post',
dataType: 'json',
data: { '_csrf': yii.getCsrfToken() },
success: function (data, status) {
if (data.main !== undefined) {
main = document.getElementsByTagName('main')[0];
// Обновление документа
main.innerHTML = data.main;
// Реинициализация
reinitialization(main);
}
if (data.redirect !== undefined) {
// Перенаправление
history.pushState({}, document.title, data.redirect);
}
if (data._csrf !== undefined) {
// Обновление документа
$('meta[name=csrf-token]').prop("content", data._csrf);
}
},
error: function (data, status) {
if (data.responseJSON.main !== undefined) {
main = document.getElementsByTagName('main')[0];
// Обновление документа
main.innerHTML = data.responseJSON.main;
// Реинициализация
reinitialization(main);
}
if (data.responseJSON.redirect !== undefined) {
// Перенаправление
history.pushState({}, document.title, data.responseJSON.redirect);
}
if (data.responseJSON._csrf !== undefined) {
// Обновление документа
$('meta[name=csrf-token]').prop("content", data.responseJSON._csrf);
}
}
success: menu_success,
error: menu_error
});
}
return false;
}
function page_cart() {
if (document.getElementById('page_cart') === null) {
url = '/cart'
$.ajax({
url: url,
type: 'post',
dataType: 'json',
data: { '_csrf': yii.getCsrfToken() },
success: menu_success,
error: menu_error
});
}
return false;
};
@ -106,3 +53,75 @@ function notifications() {
return false;
}
function menu_success(data, status) {
// Обработка ответов от удавшихся запросов
// Основной блок
if (data.main !== undefined) {
// Инициализация
main = document.getElementsByTagName('main')[0];
// Обновление документа
main.innerHTML = data.main;
// Реинициализация
reinitialization(main);
}
// Заголовок
if (data.title !== undefined) {
// Запись
document.title = data.title;
}
// Перенаправление
if (data.redirect !== undefined) {
// Перенаправление
history.pushState({}, document.title, data.redirect);
}
// CSRF-токен
if (data._csrf !== undefined) {
// Обновление документа
$('meta[name=csrf-token]').prop("content", data._csrf);
}
}
function menu_error(data, status) {
// Обработка ответов от неудавшихся запросов
// Инициализация
data = data.responseJSON;
// Основной блок
if (data.main !== undefined) {
// Инициализация
main = document.getElementsByTagName('main')[0];
// Обновление окна результатов поиска
main.innerHTML = data.main;
// Реинициализация
reinitialization(main);
}
// Заголовок
if (data.title !== undefined) {
// Запись
document.title = data.title;
}
// Перенаправление
if (data.redirect !== undefined) {
// Перенаправление
history.pushState({}, document.title, data.redirect);
}
// CSRF-токен
if (data._csrf !== undefined) {
// Обновление документа
$('meta[name=csrf-token]').prop("content", data._csrf);
}
}

View File

@ -1,5 +1,5 @@
function product_search(line, advanced = 0) {
if (line.value.length > 1) {
function product_search(text = '', advanced = 0) {
if (text.length > 1) {
// Проверка на длину запроса пройдена
$.ajax({
@ -10,13 +10,13 @@ function product_search(line, advanced = 0) {
'_csrf': yii.getCsrfToken(),
'type': 'product',
'advanced': advanced,
'request': line.value
'request': text
},
success: function (data, status) {
search_panel_success(line, advanced, data, status);
search_panel_success(text, advanced, data, status);
},
error: function (data, status) {
search_panel_error(line, advanced, data, status);
search_panel_error(text, advanced, data, status);
},
statusCode: search_panel_statusCode()
});
@ -27,7 +27,7 @@ function product_search(line, advanced = 0) {
}
};
function product_search_history(line, advanced = 0) {
function product_search_history(text = '', advanced = 0) {
$.ajax({
url: '/search',
type: 'post',
@ -38,45 +38,39 @@ function product_search_history(line, advanced = 0) {
'history': true
},
success: function (data, status) {
search_panel_success(line, advanced, data, status);
search_panel_success(text, advanced, data, status);
},
error: function (data, status) {
search_panel_error(line, advanced, data, status);
search_panel_error(text, advanced, data, status);
},
statusCode: search_panel_statusCode()
});
}
function search_panel_success(line, advanced, data, status) {
if (data.search_line_window !== undefined) {
search_line_window = document.getElementById('search_line_window');
function search_panel_show(line = 'search_line', panel = 'search_line_window') {
// Показ панели поиска
// Обновление окна результатов поиска
search_line_window.innerHTML = data.search_line_window;
// Активация
document.getElementById(panel).style.display = '';
// Отображение окна (потом надо переделать)
$('#search_line').dropdown('show');
// Реинициализация
reinitialization(search_line_window);
// Открытие
$('#' + line).dropdown('show');
}
if (data.timer !== undefined) {
// Ожидание перед повторным запросом
if (getCookie('search') !== 'processing') {
// На данный момент нет других запросов поиска
function search_panel_hide(line = 'search_line', panel = 'search_line_window') {
// Сокрытие панели поиска
// Запись о существовании запроса
document.cookie = "search=processing; path=/";
// Закрытие
$('#' + line).dropdown('hide');
// Запрос
setTimeout(product_search, data.timer + '000', line, advanced);
}
}
if (data.search_line_window_hide === 1) {
// Скрытие окна (потом надо переделать)
$('#search_line').dropdown('hide');
// Деактивация
document.getElementById(panel).style.display = 'none';
}
function search_panel_success(text, advanced, data, status) {
// Обработка ответов от удавшихся запросов
// Основной блок
if (data.main !== undefined) {
main = document.getElementsByTagName('main')[0];
@ -86,29 +80,61 @@ function search_panel_success(line, advanced, data, status) {
// Реинициализация
reinitialization(main);
}
if (data.redirect !== undefined) {
// Перенаправление
history.pushState({}, document.title, data.redirect);
}
if (data._csrf !== undefined) {
// Обновление документа
$('meta[name=csrf-token]').prop("content", data._csrf);
}
};
function search_panel_error(line, advanced, data, status) {
if (data.responseJSON.search_line_window !== undefined) {
search_line_window = document.getElementById('search_line_window');
// Окно поиска
if (data.panel !== undefined) {
panel = document.getElementById('search_line_window');
// Обновление окна результатов поиска
search_line_window.innerHTML = data.responseJSON.search_line_window;
panel.innerHTML = data.panel;
// Отображение окна (потом надо переделать)
$('#search_line').dropdown('show');
// Реинициализация
reinitialization(search_line_window);
reinitialization(panel);
}
// Таймер для повтора запроса
if (data.timer !== undefined) {
// Ожидание перед повторным запросом
if (getCookie('search') !== 'processing') {
// На данный момент нет других запросов поиска
// Запись о существовании запроса
search_panel_statusCode_progress();
// Запрос
setTimeout(product_search, data.timer + '000', text, advanced);
}
}
// Перенаправление
if (data.redirect !== undefined) {
// Перенаправление
history.pushState({}, document.title, data.redirect);
}
if (data.responseJSON.hide === 1) {
}
// Сокрытие окна поиска
if (data.search_line_window_hide === 1) {
search_panel_hide();
}
// CSRF-токен
if (data._csrf !== undefined) {
// Обновление документа
$('meta[name=csrf-token]').prop("content", data._csrf);
}
}
function search_panel_error(text, advanced, data, status) {
// Обработка ответов от неудавшихся запросов
// Основной блок
if (data.responseJSON.main !== undefined) {
main = document.getElementsByTagName('main')[0];
@ -118,10 +144,28 @@ function search_panel_error(line, advanced, data, status) {
// Реинициализация
reinitialization(main);
}
// Окно поиска
if (data.responseJSON.panel !== undefined) {
panel = document.getElementById('search_line_window');
// Обновление окна результатов поиска
panel.innerHTML = data.responseJSON.panel;
// Отображение окна (потом надо переделать)
$('#search_line').dropdown('show');
// Реинициализация
reinitialization(panel);
}
// Перенаправление
if (data.responseJSON.redirect !== undefined) {
// Перенаправление
history.pushState({}, document.title, data.responseJSON.redirect);
}
// Таймер для повтора запроса
if (data.responseJSON.timer !== undefined) {
// Ожидание перед повторным запросом
@ -129,30 +173,40 @@ function search_panel_error(line, advanced, data, status) {
// На данный момент нет других запросов поиска
// Запись о существовании запроса
document.cookie = "search=processing; path=/";
search_panel_statusCode_progress();
// Запрос
setTimeout(product_search, data.responseJSON.timer + '000', line, advanced);
setTimeout(product_search, data.responseJSON.timer + '000', text, advanced);
}
}
if (data.responseJSON.search_line_window_hide === 1) {
// Скрытие окна (потом надо переделать)
$('#search_line').dropdown('hide');
// Сокрытие окна поиска
if (data.responseJSON.hide === 1) {
search_panel_hide();
}
// CSRF-токен
if (data.responseJSON._csrf !== undefined) {
// Обновление документа
$('meta[name=csrf-token]').prop("content", data.responseJSON._csrf);
}
};
}
function search_panel_statusCode() {
return {
200: search_panel_statusCode_waiting,
404: search_panel_statusCode_waiting,
};
};
}
function search_panel_statusCode_waiting() {
// Ожидание нового запроса
document.cookie = "search=waiting; path=/";
};
document.body.style.cursor = "unset";
}
function search_panel_statusCode_progress() {
// Выполнение запроса
document.cookie = "search=processing; path=/";
document.body.style.cursor = "progress";
}