From ac7694f71661099e83e70db0c5110cd35bc9f0ca Mon Sep 17 00:00:00 2001 From: Arsen Mirzaev Tatyano-Muradovich Date: Mon, 21 Oct 2024 19:39:40 +0300 Subject: [PATCH] CATALOG TOTAL REBUILD + javascript masturbating + resolved #3 --- .../arming_bot/system/controllers/account.php | 2 + .../arming_bot/system/controllers/catalog.php | 261 +++- .../arming_bot/system/controllers/core.php | 2 + .../arming_bot/system/controllers/index.php | 2 + .../arming_bot/system/controllers/session.php | 2 + mirzaev/arming_bot/system/models/account.php | 5 +- mirzaev/arming_bot/system/models/core.php | 25 +- .../system/models/interfaces/collection.php | 29 + .../system/models/interfaces/document.php | 2 + mirzaev/arming_bot/system/models/product.php | 14 +- mirzaev/arming_bot/system/models/session.php | 47 +- .../system/models/traits/buffer.php | 71 ++ .../system/models/traits/document.php | 2 + .../arming_bot/system/models/traits/files.php | 2 + .../system/models/traits/status.php | 2 + .../system/models/traits/yandex/disk.php | 2 + .../arming_bot/system/public/js/account.js | 21 +- mirzaev/arming_bot/system/public/js/cart.js | 12 +- .../arming_bot/system/public/js/catalog.js | 1104 ++++++++++++----- .../arming_bot/system/public/js/connection.js | 13 +- mirzaev/arming_bot/system/public/js/core.js | 35 +- mirzaev/arming_bot/system/public/js/damper.js | 18 +- .../arming_bot/system/public/js/hotline.js | 6 +- mirzaev/arming_bot/system/public/js/loader.js | 265 ++++ .../arming_bot/system/public/js/session.js | 14 +- .../arming_bot/system/public/js/telegram.js | 14 +- .../public/themes/default/css/catalog.css | 149 +++ .../css/catalog/1row_with_description.css | 160 --- .../themes/default/css/catalog/2columns.css | 169 --- .../themes/default/css/catalog/3columns.css | 117 -- mirzaev/arming_bot/system/views/templater.php | 1 - .../system/views/themes/default/account.html | 2 +- .../themes/default/catalog/elements/cart.html | 3 - .../default/catalog/elements/categories.html | 9 +- .../default/catalog/elements/filters.html | 27 +- .../{products/2columns.html => products.html} | 18 +- .../products/1row_with_description.html | 13 - .../catalog/elements/products/3columns.html | 36 - .../default/catalog/elements/search.html | 11 +- .../views/themes/default/catalog/page.html | 8 +- .../views/themes/default/connection.html | 2 +- .../system/views/themes/default/head.html | 5 +- .../system/views/themes/default/js.html | 34 +- .../system/views/themes/default/menu.html | 2 +- 44 files changed, 1742 insertions(+), 996 deletions(-) create mode 100755 mirzaev/arming_bot/system/models/interfaces/collection.php create mode 100755 mirzaev/arming_bot/system/models/traits/buffer.php create mode 100755 mirzaev/arming_bot/system/public/js/loader.js create mode 100644 mirzaev/arming_bot/system/public/themes/default/css/catalog.css delete mode 100644 mirzaev/arming_bot/system/public/themes/default/css/catalog/1row_with_description.css delete mode 100644 mirzaev/arming_bot/system/public/themes/default/css/catalog/2columns.css delete mode 100644 mirzaev/arming_bot/system/public/themes/default/css/catalog/3columns.css delete mode 100755 mirzaev/arming_bot/system/views/themes/default/catalog/elements/cart.html rename mirzaev/arming_bot/system/views/themes/default/catalog/elements/{products/2columns.html => products.html} (78%) delete mode 100755 mirzaev/arming_bot/system/views/themes/default/catalog/elements/products/1row_with_description.html delete mode 100755 mirzaev/arming_bot/system/views/themes/default/catalog/elements/products/3columns.html diff --git a/mirzaev/arming_bot/system/controllers/account.php b/mirzaev/arming_bot/system/controllers/account.php index 9a3c160..f2049fa 100755 --- a/mirzaev/arming_bot/system/controllers/account.php +++ b/mirzaev/arming_bot/system/controllers/account.php @@ -16,6 +16,8 @@ use mirzaev\arangodb\document; * Controller of account * * @package mirzaev\arming_bot\controllers + * + * @license http://www.wtfpl.net/ Do What The Fuck You Want To Public License * @author Arsen Mirzaev Tatyano-Muradovich */ final class account extends core diff --git a/mirzaev/arming_bot/system/controllers/catalog.php b/mirzaev/arming_bot/system/controllers/catalog.php index 1c39118..eb1fda1 100755 --- a/mirzaev/arming_bot/system/controllers/catalog.php +++ b/mirzaev/arming_bot/system/controllers/catalog.php @@ -6,6 +6,7 @@ namespace mirzaev\arming_bot\controllers; // Files of the project use mirzaev\arming_bot\controllers\core, + mirzaev\arming_bot\models\enumerations\language, mirzaev\arming_bot\models\entry, mirzaev\arming_bot\models\category, mirzaev\arming_bot\models\product, @@ -18,6 +19,8 @@ use ArangoDBClient\Document as _document; * Controller of catalog * * @package mirzaev\arming_bot\controllers + * + * @license http://www.wtfpl.net/ Do What The Fuck You Want To Public License * @author Arsen Mirzaev Tatyano-Muradovich */ final class catalog extends core @@ -57,9 +60,10 @@ final class catalog extends core // Search for categories that are descendants of $category $entries = entry::search( document: $category, - amount: 30, + amount: 50, errors: $this->errors['catalog'] ); + /* var_dump($entries); die; */ // Initialize buffers of entries (in singular, by parameter from ArangoDB) $category = $product = []; @@ -72,10 +76,12 @@ final class catalog extends core } // Write to the buffer of global variables of view templater - $this->view->categories = $category; + $this->view->categories = $category ?? null; // Write to the buffer of global variables of view templater - $this->view->products = $product; + $this->view->products = $product ?? null; + + /* var_dump($this->view->products); die; */ // Delete buffers unset($category, $product); @@ -84,16 +90,15 @@ final class catalog extends core // Not received identifie of the category // Search for root ascendants categories - $this->view->categories = entry::ascendants(descendant: new category, errors: $this->errors['catalog']); + $this->view->categories = entry::ascendants(descendant: new category, errors: $this->errors['catalog']) ?? null; } - // Validating if (!empty($parameters['product']) && preg_match('/[\d]+/', $parameters['product'], $matches)) $product = (int) $matches[0]; if (isset($product)) { // Received and validated identifier of the product - // Search for product and write to the buffer of global variables of view templater + // Search for the product data and write to the buffer of global variables of view templater $this->view->product = product::read( filter: "d.identifier == @identifier && d.deleted != true && d.hidden != true", sort: 'd.created DESC', @@ -105,64 +110,196 @@ final class catalog extends core )[0]?->getAll() ?? null; } + // Intializing buffer of query parameters + $_parameters = []; + + // Initializing buffer of filters query (AQL) + $_filters = 'd.deleted != true && d.hidden != true'; + + // Search among products in the $category + if (isset($this->view->products) && count($this->view->products) > 0) { + // Amount of rendered products is more than 0 + + // Write to the buffer of filters query (AQL) + $_filters .= ' && POSITION(["' . implode('", "', array_map(fn(_document $document): string => $document->getId(), $this->view->products)) . '"], d._id)'; + } + // Validating - if (!empty($parameters['text']) && preg_match('/[\w\s]+/u', $parameters['text'], $matches)) $text = $matches[0]; + if (!empty($parameters['brand']) && preg_match('/[\w\s]+/u', urldecode($parameters['brand']), $matches)) $brand = $matches[0]; + + if (isset($brand)) { + // Received and validated filter by brand + + // Writing to the account buffer + $this->account?->write( + [ + 'catalog' => [ + 'filters' => [ + 'brand' => $brand + ] + ] + ] + ); + + // Writing to the session buffer + $this->session?->write( + [ + 'catalog' => [ + 'filters' => [ + 'brand' => $brand + ] + ] + ] + ); + + // Writing to the buffer of filters query (AQL) + $_filters .= ' && d.brand.@language == @brand'; + + // Writing to the buffer of query parameters + $_parameters['brand'] = $brand; + } else { + // Not received or not validated filter by brand + + // Writing to the account buffer + $this->account?->write( + [ + 'catalog' => [ + 'filters' => [ + 'brand' => null + ] + ] + ] + ); + + // Writing to the session buffer + $this->session?->write( + [ + 'catalog' => [ + 'filters' => [ + 'brand' => null + ] + ] + ] + ); + } + + // Initialize buffer of filters query (AQL) + $_sort = 'd.position ASC, d.name ASC, d.created DESC'; + + // Validating + if (!empty($parameters['sort']) && preg_match('/[\w\s]+/u', $parameters['sort'], $matches)) $sort = $matches[0]; + + if (isset($sort)) { + // Received and validated sort + + // Writing to the account buffer + $this->account?->write( + [ + 'catalog' => [ + 'sort' => $sort + ] + ] + ); + + // Writing to the session buffer + $this->session?->write( + [ + 'catalog' => [ + 'sort' => $sort + ] + ] + ); + + // Write to the buffer of sort query (AQL) + $_sort = "d.@sort DESC, $_sort"; + + // Write to the buffer of query parameters + $_parameters['sort'] = $sort; + } else { + // Not received or not validated filter by brand + + // Writing to the account buffer + $this->account?->write( + [ + 'catalog' => [ + 'sort' => null + ] + ] + ); + + // Writing to the session buffer + $this->session?->write( + [ + 'catalog' => [ + 'sort' => null + ] + ] + ); + } + + // Validating @todo add throwing errors + if (!empty($parameters['text']) && preg_match('/[\w\s]+/u', urldecode($parameters['text']), $matches) && mb_strlen($matches[0]) > 2) $text = $matches[0]; if (isset($text)) { - // Received and validated text for search + // Received and validated text - // Intialize buffer of query parameters - $_parameters = []; + // Writing to the account buffer + $this->account?->write( + [ + 'catalog' => [ + 'search' => [ + 'text' => $text + ] + ] + ] + ); - // Initialize buffer of filters query (AQL) - $_filters = 'd.deleted != true && d.hidden != true'; - - if (isset($this->view->products) && count($this->view->products) > 0) { - // Amount of rendered products is more than 0 - - // Write to the buffer of filters query (AQL) - $_filters .= ' && POSITION(["' . implode('", "', array_map(fn(_document $document): string => $document->getId(), $this->view->products)) . '"], d._id)'; - } - - // Validating - if (!empty($parameters['brand']) && preg_match('/[\w]+/', $parameters['brand'], $matches)) $brand = $matches[0]; - - if (isset($brand)) { - // Received and validated filter by brand - - // Write to the buffer of filters query (AQL) - $_filters .= ' && d.brand.@language == @brand'; - - // Write to the buffer of query parameters - $_parameters['brand'] = $brand; - } - - // Initialize buffer of filters query (AQL) - $_sort = 'd.position ASC, d.name ASC, d.created DESC'; - - // Validating - if (!empty($parameters['sort']) && preg_match('/[\w]+/', $parameters['sort'], $matches)) $sort = $matches[0]; - - if (isset($sort)) { - // Received and validated sort - - // Write to the buffer of sort query (AQL) - $_sort = "d.@sort DESC, $_sort"; - - // Write to the buffer of query parameters - $_parameters['sort'] = $sort; - } + // Writing to the session buffer + $this->session?->write( + [ + 'catalog' => [ + 'search' => [ + 'text' => $text + ] + ] + ] + ); // Search for products and write to the buffer of global variables of view templater $this->view->products = product::read( - search: $text, + search: $text ?? null, filter: $_filters, sort: $_sort, - amount: 30, + amount: 50, // @todo pagination language: $this->language, parameters: $_parameters, + return: 'DISTINCT MERGE(d, {name: d.name.@language, description: d.description.@language, compatibility: d.compatibility.@language})', errors: $this->errors['catalog'] ); + } else { + // Not received or not validated filter by brand + + // Writing to the account buffer + $this->account?->write( + [ + 'catalog' => [ + 'search' => [ + 'text' => null + ] + ] + ] + ); + + // Writing to the session buffer + $this->session?->write( + [ + 'catalog' => [ + 'search' => [ + 'text' => null + ] + ] + ] + ); } if (isset($this->view->products) && count($this->view->products) > 0) { @@ -198,6 +335,17 @@ final class catalog extends core if ($_SERVER['REQUEST_METHOD'] === 'GET') { // GET request + if (!empty($this->view->product)) { + // Initialized the product data + + // Writing javascript code that has been executed after core and damper has been loaded + $this->view->javascript = [<< core.catalog.product_system('$product'), 500); + } + javascript] + ($this->view->javascript ?? []); + } + // Exit (success) return $this->view->render('catalog/page.html'); } else if ($_SERVER['REQUEST_METHOD'] === 'POST') { @@ -205,36 +353,35 @@ final class catalog extends core // Initializing the buffer of response $response = [ - 'title' => $title ?? null + 'title' => $this->language === language::ru ? 'Каталог' : 'Catalog' // @see https://git.mirzaev.sexy/mirzaev/huesos/issues/1 ]; if (isset($this->view->categories)) { // Initialized categories // Render HTML-code of categories and write to the response buffer - $response['html'] ??= []; - $response['html']['categories'] = $this->view->render('catalog/elements/categories.html'); + $response['categories'] = $this->view->render('catalog/elements/categories.html'); } if (isset($this->view->product)) { // Initialized product + // Writing data of the product to the response buffer @todo GENERATE THIS ON THE SERVER + $response['product'] = $this->view->product; } if (isset($this->view->products)) { // Initialized products // Render HTML-code of products and write to the response buffer - $response['html'] ??= []; - $response['html']['products'] = $this->view->render('catalog/elements/products/2columns.html'); + $response['products'] = $this->view->render('catalog/elements/products.html'); } if (isset($this->view->filters)) { // Initialized filters // Render HTML-code of filters and write to the response buffer - $response['html'] ??= []; - $response['html']['filters'] = $this->view->render('catalog/elements/filters.html'); + $response['filters'] = $this->view->render('catalog/elements/filters.html'); } // Initializing a response headers diff --git a/mirzaev/arming_bot/system/controllers/core.php b/mirzaev/arming_bot/system/controllers/core.php index 5a10749..954599b 100755 --- a/mirzaev/arming_bot/system/controllers/core.php +++ b/mirzaev/arming_bot/system/controllers/core.php @@ -20,6 +20,8 @@ use mirzaev\minimal\controller; * Core of controllers * * @package mirzaev\arming_bot\controllers + * + * @license http://www.wtfpl.net/ Do What The Fuck You Want To Public License * @author Arsen Mirzaev Tatyano-Muradovich */ class core extends controller diff --git a/mirzaev/arming_bot/system/controllers/index.php b/mirzaev/arming_bot/system/controllers/index.php index ae1bf2b..50a65f0 100755 --- a/mirzaev/arming_bot/system/controllers/index.php +++ b/mirzaev/arming_bot/system/controllers/index.php @@ -12,6 +12,8 @@ use mirzaev\arming_bot\controllers\core, * Index controller * * @package mirzaev\arming_bot\controllers + * + * @license http://www.wtfpl.net/ Do What The Fuck You Want To Public License * @author Arsen Mirzaev Tatyano-Muradovich */ final class index extends core diff --git a/mirzaev/arming_bot/system/controllers/session.php b/mirzaev/arming_bot/system/controllers/session.php index 75c499f..3a6e8ce 100755 --- a/mirzaev/arming_bot/system/controllers/session.php +++ b/mirzaev/arming_bot/system/controllers/session.php @@ -16,6 +16,8 @@ use mirzaev\arangodb\document; * Controller of session * * @package mirzaev\arming_bot\controllers + * + * @license http://www.wtfpl.net/ Do What The Fuck You Want To Public License * @author Arsen Mirzaev Tatyano-Muradovich */ final class session extends core diff --git a/mirzaev/arming_bot/system/models/account.php b/mirzaev/arming_bot/system/models/account.php index 8c897c7..9b70c9f 100755 --- a/mirzaev/arming_bot/system/models/account.php +++ b/mirzaev/arming_bot/system/models/account.php @@ -8,6 +8,7 @@ namespace mirzaev\arming_bot\models; use mirzaev\arming_bot\models\core, mirzaev\arming_bot\models\traits\status, mirzaev\arming_bot\models\traits\document as arangodb_document_trait, + mirzaev\arming_bot\models\traits\buffer, mirzaev\arming_bot\models\interfaces\document as arangodb_document_interface, mirzaev\arming_bot\models\enumerations\language; @@ -34,7 +35,9 @@ use exception; */ final class account extends core implements arangodb_document_interface { - use status, arangodb_document_trait; + use status, arangodb_document_trait, buffer { + buffer::write as write; + } /** * Name of the collection in ArangoDB diff --git a/mirzaev/arming_bot/system/models/core.php b/mirzaev/arming_bot/system/models/core.php index fd003d0..cbf05ae 100755 --- a/mirzaev/arming_bot/system/models/core.php +++ b/mirzaev/arming_bot/system/models/core.php @@ -4,17 +4,19 @@ declare(strict_types=1); namespace mirzaev\arming_bot\models; +// Files of the project +use mirzaev\arming_bot\models\interfaces\collection as collection_interface; + // Framework for PHP use mirzaev\minimal\model; -// Framework for ArangoDB -use mirzaev\arangodb\connection as arangodb, - mirzaev\arangodb\collection, - mirzaev\arangodb\enumerations\collection\type; - // Library for ArangoDB use ArangoDBClient\Document as _document; +// Framework for ArangoDB +use mirzaev\arangodb\connection as arangodb, + mirzaev\arangodb\collection; + // Built-in libraries use exception; @@ -26,7 +28,7 @@ use exception; * @license http://www.wtfpl.net/ Do What The Fuck You Want To Public License * @author Arsen Mirzaev Tatyano-Muradovich */ -class core extends model +class core extends model implements collection_interface { /** * Postfix for name of models files @@ -45,16 +47,6 @@ class core extends model */ protected static arangodb $arangodb; - /** - * Name of the collection in ArangoDB - */ - public const string COLLECTION = 'THIS_COLLECTION_SHOULD_NOT_EXIST'; - - /** - * Type of the collection in ArangoDB - */ - public const type TYPE = type::document; - /** * Constructor of an instance * @@ -158,6 +150,7 @@ class core extends model return null; } + /** * Write * diff --git a/mirzaev/arming_bot/system/models/interfaces/collection.php b/mirzaev/arming_bot/system/models/interfaces/collection.php new file mode 100755 index 0000000..919988c --- /dev/null +++ b/mirzaev/arming_bot/system/models/interfaces/collection.php @@ -0,0 +1,29 @@ + + */ +interface collection +{ + /** + * Name of the collection in ArangoDB + */ + public const string COLLECTION = 'THIS_COLLECTION_SHOULD_NOT_EXIST'; + + /** + * Type of the collection in ArangoDB + */ + public const type TYPE = type::document; +} diff --git a/mirzaev/arming_bot/system/models/interfaces/document.php b/mirzaev/arming_bot/system/models/interfaces/document.php index 4015a49..3b3764a 100755 --- a/mirzaev/arming_bot/system/models/interfaces/document.php +++ b/mirzaev/arming_bot/system/models/interfaces/document.php @@ -13,6 +13,8 @@ use ArangoDBClient\Document as _document; * @param _document $document An instance of the ArangoDB document from ArangoDB (protected readonly) * * @package mirzaev\arming_bot\models\traits + * + * @license http://www.wtfpl.net/ Do What The Fuck You Want To Public License * @author Arsen Mirzaev Tatyano-Muradovich */ interface document diff --git a/mirzaev/arming_bot/system/models/product.php b/mirzaev/arming_bot/system/models/product.php index 7b3f921..020b22d 100755 --- a/mirzaev/arming_bot/system/models/product.php +++ b/mirzaev/arming_bot/system/models/product.php @@ -122,7 +122,7 @@ final class product extends core * @param array $parameters Binded parameters for placeholders ['placeholder' => parameter] * @param array &$errors Registry of errors * - * @return array Массив с найденными товарами (может быть пустым) + * @return array Found products (can be empty) */ public static function read( ?string $search = null, @@ -130,7 +130,7 @@ final class product extends core ?string $sort = 'd.position ASC, d.created DESC', int $page = 1, int $amount = 100, - ?string $return = 'd', + ?string $return = 'DISTINCT d', language $language = language::en, array $parameters = [], array &$errors = [] @@ -163,22 +163,22 @@ final class product extends core 1, false ) OR - levenshtein_match( + LEVENSHTEIN_MATCH( d.description.@language, - tokens(@search, @analyzer)[0], + TOKENS(@search, @analyzer)[0], 1, false ) OR - levenshtein_match( + LEVENSHTEIN_MATCH( d.compatibility.@language, - tokens(@search, @analyzer)[0], + TOKENS(@search, @analyzer)[0], 1, false ) AQL, empty($filter) ? '' : "FILTER $filter", empty($search) ? (empty($sort) ? '' : "SORT $sort") : (empty($sort) ? "SORT BM25(d) DESC" : "SORT BM25(d) DESC, $sort"), - empty($return) ? 'd' : $return + empty($return) ? 'DISTINCT d' : $return ), [ '@collection' => empty($search) ? static::COLLECTION : static::COLLECTION . 's_search', diff --git a/mirzaev/arming_bot/system/models/session.php b/mirzaev/arming_bot/system/models/session.php index 35e6fb2..f0423e4 100755 --- a/mirzaev/arming_bot/system/models/session.php +++ b/mirzaev/arming_bot/system/models/session.php @@ -10,6 +10,7 @@ use mirzaev\arming_bot\models\account, mirzaev\arming_bot\models\enumerations\session as verification, mirzaev\arming_bot\models\traits\status, mirzaev\arming_bot\models\traits\document as arangodb_document_trait, + mirzaev\arming_bot\models\traits\buffer, mirzaev\arming_bot\models\interfaces\document as arangodb_document_interface, mirzaev\arming_bot\models\enumerations\language; @@ -33,7 +34,9 @@ use exception; */ final class session extends core implements arangodb_document_interface { - use status, arangodb_document_trait; + use status, arangodb_document_trait, buffer { + buffer::write as write; + } /** * Name of the collection in ArangoDB @@ -43,7 +46,7 @@ final class session extends core implements arangodb_document_interface /** * Type of sessions verification */ - public const verification VERIFICATION = verification::hash_else_address; + final public const verification VERIFICATION = verification::hash_else_address; /** * Constructor of instance @@ -325,44 +328,4 @@ final class session extends core implements arangodb_document_interface // Exit (fail) return null; } - - /** - * Write to buffer of the session - * - * @param array $data Data for merging - * @param array &$errors Registry of errors - * - * @return bool Is data has written into the session document from ArangoDB? - */ - public function write(array $data, array &$errors = []): bool - { - try { - if (collection::initialize(static::COLLECTION, static::TYPE, errors: $errors)) { - // Initialized the collection - - // The instance of the session document from ArangoDB is initialized? - isset($this->document) || throw new exception('The instance of the sessoin document from ArangoDB is not initialized'); - - // Writing data into buffer of the instance of the session document from ArangoDB - $this->document->buffer = array_replace_recursive( - $this->document->buffer ?? [], - [$_SERVER['INTERFACE'] => array_replace_recursive($this->document->buffer[$_SERVER['INTERFACE']] ?? [], $data)] - ); - - // Writing to ArangoDB and exit (success) - return document::update($this->document, errors: $errors); - } else throw new exception('Failed to initialize ' . static::TYPE . ' collection: ' . static::COLLECTION); - } catch (exception $e) { - // Writing to the registry of errors - $errors[] = [ - 'text' => $e->getMessage(), - 'file' => $e->getFile(), - 'line' => $e->getLine(), - 'stack' => $e->getTrace() - ]; - } - - // Exit (fail) - return false; - } } diff --git a/mirzaev/arming_bot/system/models/traits/buffer.php b/mirzaev/arming_bot/system/models/traits/buffer.php new file mode 100755 index 0000000..c3d8976 --- /dev/null +++ b/mirzaev/arming_bot/system/models/traits/buffer.php @@ -0,0 +1,71 @@ + + */ +trait buffer +{ + /** + * Write to buffer of the session + * + * @param array $data Data for writing (merge) + * @param array &$errors Registry of errors + * + * @return bool Is data has written into the session document from ArangoDB? + */ + public function write(array $data, array &$errors = []): bool + { + try { + if (collection::initialize(static::COLLECTION, static::TYPE, errors: $errors)) { + // Initialized the collection + + // The instance of the session document from ArangoDB is initialized? + isset($this->document) || throw new exception('The instance of the sessoin document from ArangoDB is not initialized'); + + // Writing data into buffer of the instance of the session document from ArangoDB + $this->document->buffer = array_replace_recursive($this->document->buffer ?? [], $data); + + // Writing to ArangoDB and exit (success) + return document::update($this->document, errors: $errors); + } else throw new exception('Failed to initialize ' . static::TYPE . ' collection: ' . static::COLLECTION); + } catch (exception $e) { + // Writing to the registry of errors + $errors[] = [ + 'text' => $e->getMessage(), + 'file' => $e->getFile(), + 'line' => $e->getLine(), + 'stack' => $e->getTrace() + ]; + } + + // Exit (fail) + return false; + } +} diff --git a/mirzaev/arming_bot/system/models/traits/document.php b/mirzaev/arming_bot/system/models/traits/document.php index 26fe1c7..2af6a00 100755 --- a/mirzaev/arming_bot/system/models/traits/document.php +++ b/mirzaev/arming_bot/system/models/traits/document.php @@ -22,6 +22,8 @@ use exception; * @var protected readonly _document|null $document An instance of the ArangoDB document * * @package mirzaev\arming_bot\models\traits + * + * @license http://www.wtfpl.net/ Do What The Fuck You Want To Public License * @author Arsen Mirzaev Tatyano-Muradovich */ trait document diff --git a/mirzaev/arming_bot/system/models/traits/files.php b/mirzaev/arming_bot/system/models/traits/files.php index 1f341e0..badebb3 100755 --- a/mirzaev/arming_bot/system/models/traits/files.php +++ b/mirzaev/arming_bot/system/models/traits/files.php @@ -11,6 +11,8 @@ use exception; * Trait for initialization of files handlers * * @package mirzaev\arming_bot\models\traits + * + * @license http://www.wtfpl.net/ Do What The Fuck You Want To Public License * @author Arsen Mirzaev Tatyano-Muradovich */ trait files diff --git a/mirzaev/arming_bot/system/models/traits/status.php b/mirzaev/arming_bot/system/models/traits/status.php index 69f9c39..b4d4896 100755 --- a/mirzaev/arming_bot/system/models/traits/status.php +++ b/mirzaev/arming_bot/system/models/traits/status.php @@ -11,6 +11,8 @@ use exception; * Trait for initialization of a status * * @package mirzaev\arming_bot\models\traits + * + * @license http://www.wtfpl.net/ Do What The Fuck You Want To Public License * @author Arsen Mirzaev Tatyano-Muradovich */ trait status diff --git a/mirzaev/arming_bot/system/models/traits/yandex/disk.php b/mirzaev/arming_bot/system/models/traits/yandex/disk.php index b8431c9..40a0c5b 100755 --- a/mirzaev/arming_bot/system/models/traits/yandex/disk.php +++ b/mirzaev/arming_bot/system/models/traits/yandex/disk.php @@ -11,6 +11,8 @@ use exception; * Trait for "Yandex Disk" * * @package mirzaev\arming_bot\models\traits\yandex + * + * @license http://www.wtfpl.net/ Do What The Fuck You Want To Public License * @author Arsen Mirzaev Tatyano-Muradovich */ trait disk diff --git a/mirzaev/arming_bot/system/public/js/account.js b/mirzaev/arming_bot/system/public/js/account.js index 47fdc7a..a2f5e26 100755 --- a/mirzaev/arming_bot/system/public/js/account.js +++ b/mirzaev/arming_bot/system/public/js/account.js @@ -24,7 +24,17 @@ import("/js/core.js").then(() => if (typeof core.account === "undefined") { // Not initialized - // Write to the core + /** + * @name Account + * + * @description + * Implements actions with accounts + * + * @memberof core + * + * @license http://www.wtfpl.net/ Do What The Fuck You Want To Public License + * @author Arsen Mirzaev Tatyano-Muradovich + */ core.account = class account { // Wrap of indicator of the account static wrap = document.getElementById("account"); @@ -75,7 +85,7 @@ import("/js/core.js").then(() => core .request( "/session/connect/telegram", - core.telegram.api.initData + core.telegram.api.initData, ) .then((json) => { if ( @@ -94,8 +104,9 @@ import("/js/core.js").then(() => const a = core.status_account.getElementsByTagName("a")[0]; a.setAttribute("onclick", "core.account.profile()"); - a.innerText = - json.domain.length > 0 ? "@" + json.domain : "ERROR"; + a.innerText = json.domain.length > 0 + ? "@" + json.domain + : "ERROR"; } if ( @@ -132,7 +143,7 @@ import("/js/core.js").then(() => `${name}=${value}`, "POST", {}, - null + null, ); } } diff --git a/mirzaev/arming_bot/system/public/js/cart.js b/mirzaev/arming_bot/system/public/js/cart.js index 27104a4..9237584 100755 --- a/mirzaev/arming_bot/system/public/js/cart.js +++ b/mirzaev/arming_bot/system/public/js/cart.js @@ -22,7 +22,17 @@ import("/js/core.js").then(() => if (typeof core.cart === "undefined") { // Not initialized - // Write to the core + /** + * @name Cart + * + * @description + * Implements actions with cart + * + * @memberof core + * + * @license http://www.wtfpl.net/ Do What The Fuck You Want To Public License + * @author Arsen Mirzaev Tatyano-Muradovich + */ core.cart = class cart { /** * Products in cart ["product/148181", "product/148181", "product/148181"...] diff --git a/mirzaev/arming_bot/system/public/js/catalog.js b/mirzaev/arming_bot/system/public/js/catalog.js index fdee79b..41b4a12 100755 --- a/mirzaev/arming_bot/system/public/js/catalog.js +++ b/mirzaev/arming_bot/system/public/js/catalog.js @@ -2,327 +2,827 @@ // Import dependencies import("/js/core.js").then(() => - import("/js/damper.js").then(() => { - import("/js/telegram.js").then(() => { - import("/js/hotline.js").then(() => { - const dependencies = setInterval(() => { - if ( - typeof core === "function" && - typeof core.damper === "function" && - typeof core.telegram === "function" && - typeof core.hotline === "function" - ) { + import("/js/damper.js").then(() => + import("/js/loader.js").then(() => + import("/js/telegram.js").then(() => + import("/js/hotline.js").then(() => { + const dependencies = setInterval(() => { + if ( + typeof core === "function" && + typeof core.damper === "function" && + typeof core.telegram === "function" && + typeof core.hotline === "function" + ) { + clearInterval(dependencies); + clearTimeout(timeout); + initialization(); + } + }, 10); + const timeout = setTimeout(() => { clearInterval(dependencies); - clearTimeout(timeout); initialization(); - } - }, 10); - const timeout = setTimeout(() => { - clearInterval(dependencies); - initialization(); - }, 5000); + }, 5000); - function initialization() { - if (typeof core.catalog === "undefined") { - // Not initialized - - // Write to the core - core.catalog = class catalog { - /** - * Parameters of search - * - * Will be converted to the body of the GET request ("?name=value&name2=value2") - */ - static parameters = new Map([ - ["text", null], - ["category", null], - ["sort", null], - ["brand", null], - ]); + function initialization() { + if (typeof core.catalog === "undefined") { + // Not initialized /** - * Search (interface) + * @name Catalog * - * @param {Event} event Event (keyup) - * @param {HTMLElement} element Search bar - * @param {bool} force Ignore the damper? + * @description + * Implements actions with catalog * - * @return {void} + * @memberof core + * + * @license http://www.wtfpl.net/ Do What The Fuck You Want To Public License + * @author Arsen Mirzaev Tatyano-Muradovich */ - static search(event, element, force = false) { - if (typeof element === "undefined") { - element = document.getElementById("search"); - } + core.catalog = class catalog { + // Title + static element_title = core.main.getElementsByTagName("h2")[0]; - element.classList.remove("error"); + // Search search + static element_search = document.getElementById("search"); - if (element.value.length === 1) { - return; - } else { - if (typeof event === "undefined") { - // + // Search + static element_search_input = + this.element_search.getElementsByTagName("input")[0]; - this._search(element, true); - } else if (event.keyCode === 13) { - // Button: "enter" + // Categories
+ static element_categories = + document.getElementById("categories"); - element.setAttribute("disabled", true); + // Filters
+ static element_filters = document.getElementById("filters"); - this._search(element, force); - } else { - // Button: any + // Sorting
+ static element_sorting = document.getElementById("sorting"); - this._search(element, force); - } - } - } + // Products
+ static element_products = document.getElementById("products"); - /** - * Search (damper) - * - * @param {HTMLElement} element Search bar - * @param {bool} force Ignore the damper? - * - * @return {void} - */ - static _search = core.damper( - (...variables) => this.__search(...variables), - 1400, - 2, - ); + /** + * Parameters of search + * + * Will be converted to the body of the GET request ("?name=value&name2=value2") + */ + static parameters = new Map([ + [ + "text", + new URLSearchParams(document.location.search).get("text"), + ], + [ + "category", + new URLSearchParams(document.location.search).get( + "category" + ), + ], + [ + "sort", + new URLSearchParams(document.location.search).get("sort"), + ], + [ + "brand", + new URLSearchParams(document.location.search).get("brand"), + ], + ]); - /** - * Search (system) - * - * @param {HTMLElement} element Search bar - * - * @return {Promise} Request to the server - * - * @todo add animations of errors - */ - static __search(element) { - if (typeof element === "undefined") { - element = document.getElementById("search"); - } + /** + * Search (interface) + * + * Request search in the catalog and render in the core.main + * + * @param {Event} event Event (keyup) + * @param {bool} force Ignore the damper? (false) + * + * @return {bool} True if an error occurs to continue the event execution + */ + static search(event, force = false) { + if (this.element_search_input instanceof HTMLElement) { + // Found the search element - const urn = Array.from(this.parameters) - .filter(([k, v]) => - typeof v === "string" || typeof v === "number" - ) - .map(([k, v]) => `${k}=${v}`) - .join("&"); - - return core.request( - "/", - urn, - ) - .then((json) => { - element.removeAttribute("disabled"); - element.focus(); + // Removing errors animations + this.element_search_input.classList.remove("error"); if ( - json.errors !== null && - typeof json.errors === "object" && - json.errors.length > 0 + this.element_search_input.value.length < 3 && + this.element_search_input.value.lenght > 0 ) { - // Errors received + // Only 1-2 character entered (this is not a search reset and is not an adequate search) - element.classList.add("error"); + // Exit (fail) + return true; + } + } + + if (event instanceof Event) { + // Executed from event + + if (event.type === "keyup") { + // Executed by "keyup" event + + if (event.target === this.element_search_input) { + // Executed from search element + + if (event.keyCode === 13) { + // Executed by "enter" button + + // Execute + this.search_system(); + } else if (this.element_search_input.value.length < 3) { + // Less than 3 character entered (this is not a search reset and is not an adequate search) + + // Exit (fail) + return true; + } else { + // Executed by any else button + + // Execute under damper + this.search_damper(force); + } + } } else { - // Errors not received + // Executed not by "keyup" event - history.pushState( - {}, - urn, - urn, - ); + // Execute under damper + this.search_damper(force); + } - if ( - typeof json.title === "string" && - json.title.length > 0 - ) { - // Received the page title + // Exit (success) + return false; + } - // Initialize a link to the categories list - const title = core.main.getElementsByTagName("h2")[0]; + // Exit (fail) + return true; + } - // Write the title - title.innerText = json.title; - } + /** + * Search (damper) + * + * Request search in the catalog and render in the core.main + * + * @param {bool} force Ignore the damper? (false) + * + * @return {void} + */ + static search_damper = core.damper( + (...variables) => this.search_system(...variables), + 1400, + 1 + ); - // Deinitialization of the categories - const categories = core.main.querySelector( - 'section[data-catalog-type="categories"]', - ); - // if (categories instanceof HTMLElement) categories.remove(); + /** + * Search (system) + * + * Request search in the catalog and render in the core.main + * + * @return {Promise} Request to the server + * + * @todo add animations of errors + */ + static async search_system() { + // Blocking the search element + this.element_search_input.setAttribute("disabled", true); - if ( - typeof json.html.categories === "string" && - json.html.categories.length > 0 - ) { - // Received categories (reinitialization of the categories) + // @todo add timeout to unblock - const categories = core.main.querySelector( - 'section[data-catalog-type="categories"]', - ); + // Initialize the buffer of URN parameters + const parameters = new URLSearchParams( + window.location.search + ); - if (categories instanceof HTMLElement) { - // Found list of categories + // Iterate parameters + this.parameters.forEach((value, parameter) => { + if ( + (typeof value === "string" || + typeof value === "number") && + !( + (parameter === "text" && value === null) || + value.length < 3 + ) + ) { + // Validated value - categories.outerHTML = json.html.categories; - } else { - // Not found list of categories + // Write parameter to the buffer of URN parameters + parameters.set(parameter, value); + } else parameters.delete(parameter); + }); - const element = document.createElement("section"); + return await core.loader + .load("?" + parameters) + .then((json) => { + if (json) { + // Received response - const search = core.main.querySelector( - 'search[data-section="search"]', - ); + this.element_search_input.removeAttribute("disabled"); + // element.focus(); - if (search instanceof HTMLElement) { - core.main.insertBefore( - element, - search.nextSibling, - ); + /** + * Title

+ */ + if ( + typeof json.title === "string" && + json.title.length > 0 + ) { + // Received and validated text of the title

+ + if (this.element_title instanceof HTMLElement) { + // Found the title

element + + // Writing into the title

element + this.element_title.innerText = json.title; } else { - core.main.append(element); + // Not found the title

element + + // Initialize the title

element + this.element_title = document.createElement("h2"); + + if (core.main instanceof HTMLElement) { + // Found the
element + + // Inititalize the first element in the
element + const first = core.main.firstElementChild; + + if (first instanceof HTMLElement) { + // Initialized the first element in the
element + + // Writing the title

element before the first element in the
element + core.main.insertBefore( + this.element_title, + first + ); + } + } + + // Writing into the title

element + this.element_title.innerText = json.title; } - - element.outerHTML = json.html.categories; - } - } else { - // Not received categories (deinitialization of the categories) - - const categories = core.main.querySelector( - 'section[data-catalog-type="categories"', - ); - - if (categories instanceof HTMLElement) { - categories.remove(); - } - } - - if ( - typeof json.html.products === "string" && - json.html.products.length > 0 - ) { - // Received products (reinitialization of the products) - - const products = core.main.querySelector( - 'section[data-catalog-type="products"]', - ); - - if (products instanceof HTMLElement) { - // Found list of products - - products.outerHTML = json.html.products; } else { - // Not found list of products + // Not received or not validated text of the title

- const element = document.createElement("section"); + if (this.element_title instanceof HTMLElement) { + // Initialized the title

element - const categories = core.main.querySelector( - 'section[data-catalog-type="categories"', - ); + if (json.title === "") { + // Requested to delete the title

element - if (categories instanceof HTMLElement) { - // - - // - core.main.insertBefore( - element, - categories.nextSibling, - ); - - element.outerHTML = json.html.products; - } else { - // - - // - const search = core.main.querySelector( - 'search[data-section="search"]', - ); - - if (search instanceof HTMLElement) { - core.main.insertBefore( - element, - search.nextSibling, - ); - - element.outerHTML = json.html.products; + // Deleting the title

element + this.element_title.remove(); } } } - } else { - // Not received products (deinitialization of the products) - const products = core.main.querySelector( - 'section[data-catalog-type="products"]', - ); + /** + * Search search + */ + if ( + typeof json.search === "string" && + json.search.length > 0 + ) { + // Received and validated the searcn HTMl-code - if (products instanceof HTMLElement) { - products.remove(); + if (this.element_search instanceof HTMLElement) { + // Found the search element + + // Writing into the search element + this.element_search.outerHTML = json.search; + + // Reinitializing the parameter with the search element + this.element_search = + document.getElementById("search"); + } else { + // Not found the search element + + // Initialize the search element + this.element_search = + document.createElement("search"); + + if (core.main instanceof HTMLElement) { + // Found the
element + + if (this.element_title instanceof HTMLElement) { + // Initialized the title

elemment in the
element + + // Writing the search element after the title

element in the
element + core.main.insertBefore( + this.element_search, + this.element_title.nextSibling + ); + } else { + // Not initialized the title

element in the
element + + // Inititalize the first element in the
element + const first = core.main.firstElementChild; + + if (first instanceof HTMLElement) { + // Initialized the first element in the
element + + // Writing the search element before the first element in the
element + core.main.insertBefore( + this.element_search, + first + ); + } + } + + // Writing into the search element + this.element_search.outerHTML = json.search; + + // Reinitializing the parameter with the search element + this.element_search = + document.getElementById("search"); + + // Reinitializing the parameter with the search element + this.element_search_input = + this.element_search.getElementsByTagName( + "input" + )[0]; + } + } + } else { + // Not received or not validated the search HTML-code + + if (this.element_search instanceof HTMLElement) { + // Initialized the search element + + if (json.search === "") { + // Requested to delete the search element + + // Deleting the search element + this.element_search.remove(); + } + } + } + + /** + * Categories + */ + if ( + typeof json.categories === "string" && + json.categories.length > 0 + ) { + // Received and validated the categories HTMl-code + + if (this.element_categories instanceof HTMLElement) { + // Found the categories
element + + // Writing into the categories
element + this.element_categories.outerHTML = json.categories; + + // Reinitializing the parameter with the categories
element + this.element_categories = + document.getElementById("categories"); + } else { + // Not found the categories
element + + // Initialize the categories
element + this.element_categories = + document.createElement("section"); + + if (core.main instanceof HTMLElement) { + // Found the
element + + if (this.element_search instanceof HTMLElement) { + // Initialized the search element in the
element + + // Writing the categories
element after the search element in the
element + core.main.insertBefore( + this.element_categories, + this.element_search.nextSibling + ); + } else if ( + this.element_title instanceof HTMLElement + ) { + // Initialized the title

element in the
element + + // Writing the categories
element after the title

element in the
element + core.main.insertBefore( + this.element_categories, + this.element_title.nextSibling + ); + } else { + // Not initialized the title

element in the
element + + // Inititalize the first element in the
element + const first = core.main.firstElementChild; + + if (first instanceof HTMLElement) { + // Initialized the first element in the
element + + // Writing the categories
before the first element in the
element + core.main.insertBefore( + this.element_categories, + first + ); + } + } + + // Writing into the categories
element + this.element_categories.outerHTML = + json.categories; + + // Reinitializing the parameter with the categories
element + this.element_categories = + document.getElementById("categories"); + } + } + } else { + // Not received or not validated the categories HTML-code + + if (this.element_categories instanceof HTMLElement) { + // Initialized the categories
element + + // Deleting the categories
element + this.element_categories.remove(); + } + } + + /** + * Filters + */ + if ( + typeof json.filters === "string" && + json.filters.length > 0 + ) { + // Received and validated the filters HTMl-code + + if (this.element_filters instanceof HTMLElement) { + // Found the filters
element + + // Writing into the filters
element + this.element_filters.outerHTML = json.filters; + + // Reinitializing the parameter with the filters
element + this.element_filters = + document.getElementById("filters"); + } else { + // Not found the filters
element + + // Initialize the filters
element + this.element_filters = + document.createElement("section"); + + if (core.main instanceof HTMLElement) { + // Found the
element + + if ( + this.element_categories instanceof HTMLElement + ) { + // Initialized the categories
element in the
element + + // Writing the filters
element after the categories
element in the
element + core.main.insertBefore( + this.element_filters, + this.element_categories.nextSibling + ); + } else if ( + this.element_search instanceof HTMLElement + ) { + // Initialized the search element in the
element + + // Writing the filters
element after the search element in the
element + core.main.insertBefore( + this.element_filters, + this.element_search.nextSibling + ); + } else if ( + this.element_title instanceof HTMLElement + ) { + // Initialized the title

element in the
element + + // Writing the filters
element after the title

element in the
element + core.main.insertBefore( + this.element_filters, + this.element_title.nextSibling + ); + } else { + // Not initialized the title

element in the
element + + // Inititalize the first element in the
element + const first = core.main.firstElementChild; + + if (first instanceof HTMLElement) { + // Initialized the first element in the
element + + // Writing the filters
before the first element in the
element + core.main.insertBefore( + this.element_filters, + first + ); + } + } + + // Writing into the filters
element + this.element_filters.outerHTML = json.filters; + + // Reinitializing the parameter with the filters
element + this.element_filters = + document.getElementById("filters"); + } + } + } else { + // Not received or not validated the filters HTML-code + + if (this.element_filters instanceof HTMLElement) { + // Initialized the filters
element + + // Deleting the filters
element + this.element_filters.remove(); + } + } + + /** + * Sorting + */ + if ( + typeof json.sorting === "string" && + json.sorting.length > 0 + ) { + // Received and validated the sorting HTMl-code + + if (this.element_sorting instanceof HTMLElement) { + // Found the sorting
element + + // Writing into the sorting
element + this.element_sorting.outerHTML = json.sorting; + + // Reinitializing the parameter with the sorting
element + this.element_sorting = + document.getElementById("sorting"); + } else { + // Not found the sorting
element + + // Initialize the sorting
element + this.element_sorting = + document.createElement("section"); + + if (core.main instanceof HTMLElement) { + // Found the
element + + if (this.element_filters instanceof HTMLElement) { + // Initialized the filters
element in the
element + + // Writing the sorting
element after the filters
element in the
element + core.main.insertBefore( + this.element_sorting, + this.element_filters.nextSibling + ); + } else if ( + this.element_categories instanceof HTMLElement + ) { + // Initialized the categories
element in the
element + + // Writing the sorting
element after the categories
element in the
element + core.main.insertBefore( + this.element_sorting, + this.element_categories.nextSibling + ); + } else if ( + this.element_search instanceof HTMLElement + ) { + // Initialized the search element in the
element + + // Writing the sorting
element after the search element in the
element + core.main.insertBefore( + this.element_sorting, + this.element_search.nextSibling + ); + } else if ( + this.element_title instanceof HTMLElement + ) { + // Initialized the title

element in the
element + + // Writing the sorting
element after the title

element in the
element + core.main.insertBefore( + this.element_sorting, + this.element_title.nextSibling + ); + } else { + // Not initialized the title

element in the
element + + // Inititalize the first element in the
element + const first = core.main.firstElementChild; + + if (first instanceof HTMLElement) { + // Initialized the first element in the
element + + // Writing the sorting
before the first element in the
element + core.main.insertBefore( + this.element_sorting, + first + ); + } + } + + // Writing into the sorting
element + this.element_sorting.outerHTML = json.sorting; + + // Reinitializing the parameter with the sorting
element + this.element_sorting = + document.getElementById("sorting"); + } + } + } else { + // Not received or not validated the sorting HTML-code + + if (this.element_sorting instanceof HTMLElement) { + // Initialized the sorting
element + + // Deleting the sorting
element + this.element_sorting.remove(); + } + } + + /** + * Products + */ + if ( + typeof json.products === "string" && + json.products.length > 0 + ) { + // Received and validated the products HTMl-code + + if (this.element_products instanceof HTMLElement) { + // Found the products
element + + // Writing into the products
element + this.element_products.outerHTML = json.products; + + // Reinitializing the parameter with the products
element + this.element_products = + document.getElementById("products"); + } else { + // Not found the products
element element + + // Initialize the products
element + this.element_products = + document.createElement("section"); + + if (core.main instanceof HTMLElement) { + // Found the
element + + if (this.element_sorting instanceof HTMLElement) { + // Initialized the sorting
element in the
element + + // Writing the products
element after the sorting
element in the
element + core.main.insertBefore( + this.element_products, + this.element_sorting.nextSibling + ); + } else if ( + this.element_filters instanceof HTMLElement + ) { + // Initialized the filters
element in the
element + + // Writing the products
element after the filters
element in the
element + core.main.insertBefore( + this.element_products, + this.element_filters.nextSibling + ); + } else if ( + this.element_categories instanceof HTMLElement + ) { + // Initialized the categories
element in the
element + + // Writing the products
element after the categories
element in the
element + core.main.insertBefore( + this.element_products, + this.element_categories.nextSibling + ); + } else if ( + this.element_search instanceof HTMLElement + ) { + // Initialized the search element in the
element + + // Writing the products
element after the search element in the
element + core.main.insertBefore( + this.element_products, + this.element_search.nextSibling + ); + } else if ( + this.element_title instanceof HTMLElement + ) { + // Initialized the title

element in the
element + + // Writing the products
element after the title

element in the
element + core.main.insertBefore( + this.element_products, + this.element_title.nextSibling + ); + } else { + // Not initialized the title

element in the
element + + // Inititalize the first element in the
element + const first = core.main.firstElementChild; + + if (first instanceof HTMLElement) { + // Initialized the first element in the
element + + // Writing the products
before the first element in the
element + core.main.insertBefore( + this.element_products, + first + ); + } + } + + // Writing into the products
element + this.element_products.outerHTML = json.products; + + // Reinitializing the parameter with the products
element + this.element_products = + document.getElementById("products"); + } + } + } else { + // Not received or not validated the products HTML-code + + if (this.element_products instanceof HTMLElement) { + // Initialized the products
element + + // Deleting the products
element + this.element_products.remove(); + } } } - } - }); - } + }); + } - /** - * Open product card (interface) - * - * @param {HTMLElement} button Button of a product - * @param {bool} force Ignore the damper? - * - * @return {void} - */ - static product(button, force = false) { - // Initializing identifier of the category - const identifier = button.getAttribute( - "data-product-identifier", + /** + * Product card (interface) + * + * Request product data and render in core.window + * + * @param {HTMLElement} button Button of the product + * @param {bool} force Ignore the damper? (false) + * + * @return {bool} True if an error occurs to continue the event execution + */ + static product(button, force = false) { + // Initializing identifier of the category + const identifier = button.getAttribute( + "data-product-identifier" + ); + + // Execute under damper + this.product_damper(identifier, force); + + // Exit (success) + return false; + } + + /** + * Product card (damper) + * + * Request product data and render in core.window + * + * @param {string} identifier Identifier of the product + * @param {bool} force Ignore the damper? (false) + * + * @return {void} + */ + static product_damper = core.damper( + (...variables) => this.product_system(...variables), + 400, + 1 ); - this._product(identifier, force); - } + /** + * Product card (system) + * + * Request product data and render in core.window + * + * @param {string} identifier Identifier of the product + * + * @return {Promise} Request to the server + */ + static product_system(identifier) { + if (typeof identifier === "string") { + // Validated identifier - /** - * Open product card (damper) - * - * @param {string} identifier Identifier of a product - * @param {bool} force Ignore the damper? - * - * @return {void} - */ - static _product = core.damper( - (...variables) => this.__product(...variables), - 400, - 1, - ); + // Initialize the buffer of URN parameters @todo after opening window add to document.location.search + const parameters = new URLSearchParams(); - /** - * Open product card (system) - * - * @param {string} identifier Identifier of a product - * - * @return {Promise} Request to the server - */ - static __product(identifier) { - if (typeof identifier === "string") { - // + // Write parameter to the buffer of URN parameters + parameters.set("product", identifier); - // - const urn = `?product=${identifier}`; - - return core.request(urn) - .then((json) => { + return core.request("?" + parameters).then((json) => { if ( json.errors !== null && typeof json.errors === "object" && json.errors.length > 0 ) { - // Errors received + // Fail (received errors) } else { - // Errors not received + // Success (not received errors) + + if (core.window instanceof HTMLElement) { + // Initialized active window + + // Delete active window + core.window.remove(); + } if ( json.product !== null && @@ -362,7 +862,7 @@ import("/js/core.js").then(() => // блокировка закрытия изображений let images_from; - const _images_from = (event) => images_from = event; + const _images_from = (event) => (images_from = event); images.addEventListener("mousedown", _images_from); images.addEventListener("touchstart", _images_from); @@ -374,9 +874,11 @@ import("/js/core.js").then(() => { let x = event.pageX || event.touches[0].pageX; let y = event.pageY || event.touches[0].pageY; - let _x = images_from.pageX || + let _x = + images_from.pageX || images_from.touches[0].pageX; - let _y = images_from.pageY || + let _y = + images_from.pageY || images_from.touches[0].pageY; if ( @@ -408,10 +910,10 @@ import("/js/core.js").then(() => const _close = (event) => { let x = event.pageX || event.touches[0].pageX; let y = event.pageY || event.touches[0].pageY; - let _x = images_from.pageX || - images_from.touches[0].pageX; - let _y = images_from.pageY || - images_from.touches[0].pageY; + let _x = + images_from.pageX || images_from.touches[0].pageX; + let _y = + images_from.pageY || images_from.touches[0].pageY; if ( event.type === "touchstart" || @@ -435,7 +937,9 @@ import("/js/core.js").then(() => } images.classList.remove("extend"); - if (button) core.telegram.api.MainButton.show(); + if (button) { + core.telegram.api.MainButton.show(); + } images.removeEventListener("mouseup", _close); images.removeEventListener("touchend", _close); @@ -530,29 +1034,29 @@ import("/js/core.js").then(() => footer.append(cost); card.append(footer); wrap.append(card); - core.main.append(wrap); + document.body.append(wrap); + + // Reinitialize parameter + core.window = document.getElementById('window'); let width = 0; let buffer; - [...images.children].forEach((child) => - width += child.offsetWidth + (isNaN( - buffer = parseFloat( - getComputedStyle(child).marginRight, - ), - ) - ? 0 - : buffer) - ); - - history.pushState( - { identifier }, - json.product.name, - urn, + [...images.children].forEach( + (child) => + (width += + child.offsetWidth + + (isNaN( + (buffer = parseFloat( + getComputedStyle(child).marginRight + )) + ) + ? 0 + : buffer)) ); // блокировка закрытия карточки let from; - const _from = (event) => from = event.target; + const _from = (event) => (from = event.target); wrap.addEventListener("mousedown", _from); wrap.addEventListener("touchstart", _from); @@ -560,16 +1064,17 @@ import("/js/core.js").then(() => if ( typeof event === "undefined" || event.type !== "popstate" - ) history.back(); + ) + history.back(); wrap.remove(); images.removeEventListener( "mousedown", - _images_from, + _images_from ); images.removeEventListener( "touchstart", - _images_from, + _images_from ); wrap.removeEventListener("mousedown", _from); wrap.removeEventListener("touchstart", _from); @@ -585,9 +1090,11 @@ import("/js/core.js").then(() => from === wrap && !card.contains(event.target) && !!card && - !!(card.offsetWidth || + !!( + card.offsetWidth || card.offsetHeight || - card.getClientRects().length) + card.getClientRects().length + ) ) { remove(); } @@ -603,7 +1110,7 @@ import("/js/core.js").then(() => images.hotline = new core.hotline( json.product.identfier, - images, + images ); images.hotline.step = -0.3; images.hotline.wheel = true; @@ -615,12 +1122,13 @@ import("/js/core.js").then(() => } } }); + } } - } - }; + }; + } } - } - }); - }); - }) + }) + ) + ) + ) ); diff --git a/mirzaev/arming_bot/system/public/js/connection.js b/mirzaev/arming_bot/system/public/js/connection.js index 8596603..a15905e 100755 --- a/mirzaev/arming_bot/system/public/js/connection.js +++ b/mirzaev/arming_bot/system/public/js/connection.js @@ -22,7 +22,17 @@ import("/js/core.js").then(() => if (typeof core.connection === "undefined") { // Not initialized - // Write to the core + /** + * @name Connection + * + * @description + * Implements actions with websocket connection + * + * @memberof core + * + * @license http://www.wtfpl.net/ Do What The Fuck You Want To Public License + * @author Arsen Mirzaev Tatyano-Muradovich + */ core.connection = class connection { // Wrap of indicator of the connection static wrap = document.getElementById("connection"); @@ -205,7 +215,6 @@ import("/js/core.js").then(() => }; } - core.connection.connect( 3000, () => diff --git a/mirzaev/arming_bot/system/public/js/core.js b/mirzaev/arming_bot/system/public/js/core.js index 3ee7031..f66cbd5 100755 --- a/mirzaev/arming_bot/system/public/js/core.js +++ b/mirzaev/arming_bot/system/public/js/core.js @@ -1,6 +1,14 @@ "use strict"; -// Initialize of the class in global namespace +/** + * @name Core + * + * @description + * Core of the project + * + * @license http://www.wtfpl.net/ Do What The Fuck You Want To Public License + * @author Arsen Mirzaev Tatyano-Muradovich + */ const core = class core { // Domain static domain = window.location.hostname; @@ -8,31 +16,34 @@ const core = class core { // Language static language = "ru"; - // Label for the "loading" element + // Window + static window; + + // The "loading" element static status_loading = document.getElementById("loading"); - // Label for the "account" element + // The "account" element static status_account = document.getElementById("account"); - // Label for the
element + // The
element static header = document.body.getElementsByTagName("header")[0]; - // Label for the